From 974b0afca91844fed61c5fda9293bbcd88752c2f Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Sat, 29 Apr 2017 05:27:31 -0500 Subject: Remove last bit of chunk exists region file fix CraftBukkit removed their implementation that caused this issue, switching to Mojang's implementation which doesn't appear to share it. I already removed the important bit in the last upstream merge, this is just unused and unnecessary now. So we remove it. --- .../0047-Add-PlayerInitialSpawnEvent.patch | 36 + ...e-Region-File-s-when-checking-if-chunk-ex.patch | 37 - .../0048-Add-PlayerInitialSpawnEvent.patch | 36 - .../0048-Disable-chest-cat-detection.patch | 39 + .../0049-Disable-chest-cat-detection.patch | 39 - .../0049-Ensure-commands-are-not-ran-async.patch | 86 +++ ...-All-chunks-are-slime-spawn-chunks-toggle.patch | 37 + .../0050-Ensure-commands-are-not-ran-async.patch | 86 --- ...-All-chunks-are-slime-spawn-chunks-toggle.patch | 37 - .../0051-Optimize-Pathfinding.patch | 51 ++ ...oid-hopper-searches-if-there-are-no-items.patch | 99 +++ .../0052-Optimize-Pathfinding.patch | 51 -- ...oid-hopper-searches-if-there-are-no-items.patch | 99 --- .../0053-Expose-server-CommandMap.patch | 21 + ...t-more-informative-in-maxHealth-exception.patch | 25 + .../0054-Expose-server-CommandMap.patch | 21 - ...t-more-informative-in-maxHealth-exception.patch | 25 - .../0055-Player-Tab-List-and-Title-APIs.patch | 179 +++++ .../0056-Ensure-inv-drag-is-in-bounds.patch | 22 + .../0056-Player-Tab-List-and-Title-APIs.patch | 179 ----- ...mplementation-of-tile-entity-removal-list.patch | 88 +++ .../0057-Ensure-inv-drag-is-in-bounds.patch | 22 - ...058-Add-configurable-portal-search-radius.patch | 58 ++ ...mplementation-of-tile-entity-removal-list.patch | 88 --- ...059-Add-configurable-portal-search-radius.patch | 58 -- .../0059-Add-velocity-warnings.patch | 62 ++ .../0060-Add-velocity-warnings.patch | 62 -- ...60-Fix-inter-world-teleportation-glitches.patch | 43 ++ .../0061-Add-exception-reporting-event.patch | 376 ++++++++++ ...61-Fix-inter-world-teleportation-glitches.patch | 43 -- .../0062-Add-exception-reporting-event.patch | 376 ---------- ...if-we-don-t-need-to-when-cerealising-text.patch | 30 + ...le-Scoreboards-for-non-players-by-default.patch | 53 ++ ...if-we-don-t-need-to-when-cerealising-text.patch | 30 - ...-for-working-with-arrows-stuck-in-living-.patch | 47 ++ ...le-Scoreboards-for-non-players-by-default.patch | 53 -- ...-for-working-with-arrows-stuck-in-living-.patch | 47 -- .../0065-Complete-resource-pack-API.patch | 75 ++ .../0066-Chunk-save-queue-improvements.patch | 167 +++++ .../0066-Complete-resource-pack-API.patch | 75 -- .../0067-Chunk-Save-Reattempt.patch | 46 ++ .../0067-Chunk-save-queue-improvements.patch | 167 ----- .../0068-Chunk-Save-Reattempt.patch | 46 -- ...lt-loading-permissions.yml-before-plugins.patch | 55 ++ ...069-Allow-Reloading-of-Custom-Permissions.patch | 36 + ...lt-loading-permissions.yml-before-plugins.patch | 55 -- ...070-Allow-Reloading-of-Custom-Permissions.patch | 36 - .../0070-Remove-Metadata-on-reload.patch | 30 + .../0071-Remove-Metadata-on-reload.patch | 30 - .../0071-Undead-horse-leashing.patch | 37 + .../0072-Fix-Furnace-cook-time-bug.patch | 26 + .../0072-Undead-horse-leashing.patch | 37 - .../0073-Fix-Furnace-cook-time-bug.patch | 26 - .../0073-Handle-Item-Meta-Inconsistencies.patch | 293 ++++++++ ...onfigurable-Non-Player-Arrow-Despawn-Rate.patch | 41 ++ .../0074-Handle-Item-Meta-Inconsistencies.patch | 293 -------- .../0075-Add-World-Util-Methods.patch | 97 +++ ...onfigurable-Non-Player-Arrow-Despawn-Rate.patch | 41 -- .../0076-Add-World-Util-Methods.patch | 97 --- .../0076-Optimized-Light-Level-Comparisons.patch | 135 ++++ .../0077-Optimized-Light-Level-Comparisons.patch | 135 ---- .../0077-Pass-world-to-Village-creation.patch | 36 + .../0078-Custom-replacement-for-eaten-items.patch | 50 ++ .../0078-Pass-world-to-Village-creation.patch | 36 - .../0079-Custom-replacement-for-eaten-items.patch | 50 -- .../0079-Set-health-before-death-event.patch | 49 ++ .../0080-Set-health-before-death-event.patch | 49 -- ...-health-absorb-values-and-repair-bad-data.patch | 60 ++ ...081-Catch-Async-PlayerChunkMap-operations.patch | 26 + ...-health-absorb-values-and-repair-bad-data.patch | 60 -- ...082-Catch-Async-PlayerChunkMap-operations.patch | 26 - ...offline-mode-in-whitelist-command-as-well.patch | 93 +++ .../0083-Fix-SkullCache-case-bug.patch | 22 + ...offline-mode-in-whitelist-command-as-well.patch | 93 --- .../0084-Fix-SkullCache-case-bug.patch | 22 - .../0084-Waving-banner-workaround.patch | 38 + .../0085-Use-a-Shared-Random-for-Entities.patch | 31 + .../0085-Waving-banner-workaround.patch | 38 - .../0086-Don-t-teleport-dead-entities.patch | 24 + .../0086-Use-a-Shared-Random-for-Entities.patch | 31 - .../0087-Don-t-teleport-dead-entities.patch | 24 - .../0087-Optimize-Chunk-Access.patch | 46 ++ ...gurable-spawn-chances-for-skeleton-horses.patch | 36 + .../0088-Optimize-Chunk-Access.patch | 46 -- ...gurable-spawn-chances-for-skeleton-horses.patch | 36 - ...ValidLocation-getType-and-getBlockData-fo.patch | 259 +++++++ .../0090-Fix-cooked-fish-legacy-import.patch | 22 + ...ValidLocation-getType-and-getBlockData-fo.patch | 259 ------- .../0091-Access-items-by-EquipmentSlot.patch | 68 ++ .../0091-Fix-cooked-fish-legacy-import.patch | 22 - .../0092-Access-items-by-EquipmentSlot.patch | 68 -- ...092-Check-async-remove-unused-vars-GH-159.patch | 32 + ...093-Check-async-remove-unused-vars-GH-159.patch | 32 - ...to-disable-BlockPhysicsEvent-for-Redstone.patch | 71 ++ ...0094-Entity-AddTo-RemoveFrom-World-Events.patch | 29 + ...to-disable-BlockPhysicsEvent-for-Redstone.patch | 71 -- .../0095-Configurable-Chunk-Inhabited-Timer.patch | 40 ++ ...0095-Entity-AddTo-RemoveFrom-World-Events.patch | 29 - .../0096-Configurable-Chunk-Inhabited-Timer.patch | 40 -- .../0096-EntityPathfindEvent.patch | 39 + .../0097-EntityPathfindEvent.patch | 39 - ...erflow-BlockFromToEvent-from-loading-chun.patch | 52 ++ ...erflow-BlockFromToEvent-from-loading-chun.patch | 52 -- ...8-Reduce-IO-ops-opening-a-new-region-file.patch | 53 ++ ...9-Reduce-IO-ops-opening-a-new-region-file.patch | 53 -- ...ise-RegionFileCache-and-make-configurable.patch | 81 +++ ...ise-RegionFileCache-and-make-configurable.patch | 81 --- .../0100-Use-Optimized-Collections.patch | 51 ++ .../0101-Do-not-load-chunks-for-light-checks.patch | 23 + .../0101-Use-Optimized-Collections.patch | 51 -- .../0102-Add-PlayerUseUnknownEntityEvent.patch | 43 ++ .../0102-Do-not-load-chunks-for-light-checks.patch | 23 - .../0103-Add-PlayerUseUnknownEntityEvent.patch | 43 -- ...educedDebugInfo-not-initialized-on-client.patch | 21 + .../0104-Configurable-Grass-Spread-Tick-Rate.patch | 36 + ...educedDebugInfo-not-initialized-on-client.patch | 21 - .../0105-Configurable-Grass-Spread-Tick-Rate.patch | 36 - ...gurable-Keep-Spawn-Loaded-range-per-world.patch | 87 +++ ...gurable-Keep-Spawn-Loaded-range-per-world.patch | 87 --- ...elling-BlockPlaceEvent-triggering-physics.patch | 21 + ...-t-spam-reload-spawn-chunks-in-nether-end.patch | 33 + ...elling-BlockPlaceEvent-triggering-physics.patch | 21 - ...-t-spam-reload-spawn-chunks-in-nether-end.patch | 33 - .../0108-Remove-Debug-checks-from-DataBits.patch | 46 ++ ...se-vanilla-per-world-scoreboard-coloring-.patch | 55 ++ .../0109-Remove-Debug-checks-from-DataBits.patch | 46 -- ...se-vanilla-per-world-scoreboard-coloring-.patch | 55 -- ...karound-for-setting-passengers-on-players.patch | 32 + ...0111-Remove-unused-World-Tile-Entity-List.patch | 71 ++ ...karound-for-setting-passengers-on-players.patch | 32 - .../0112-Don-t-tick-Skulls-unused-code.patch | 22 + ...0112-Remove-unused-World-Tile-Entity-List.patch | 71 -- .../0113-Configurable-Player-Collision.patch | 136 ++++ .../0113-Don-t-tick-Skulls-unused-code.patch | 22 - ...ke-event-to-allow-plugins-to-handle-clien.patch | 49 ++ .../0114-Configurable-Player-Collision.patch | 136 ---- ...ke-event-to-allow-plugins-to-handle-clien.patch | 49 -- ...Water-mobs-should-only-spawn-in-the-water.patch | 30 + ...0116-Fix-Bugs-with-Spigot-Mob-Spawn-Logic.patch | 60 ++ ...Water-mobs-should-only-spawn-in-the-water.patch | 30 - .../0117-Configurable-RCON-IP-address.patch | 23 + ...0117-Fix-Bugs-with-Spigot-Mob-Spawn-Logic.patch | 60 -- .../0118-Configurable-RCON-IP-address.patch | 23 - .../0118-Prevent-Fire-from-loading-chunks.patch | 51 ++ .../0119-Implement-PlayerLocaleChangeEvent.patch | 54 ++ .../0119-Prevent-Fire-from-loading-chunks.patch | 51 -- ...0-EntityRegainHealthEvent-isFastRegen-API.patch | 45 ++ .../0120-Implement-PlayerLocaleChangeEvent.patch | 54 -- ...ility-to-configure-frosted_ice-properties.patch | 48 ++ ...1-EntityRegainHealthEvent-isFastRegen-API.patch | 45 -- ...ility-to-configure-frosted_ice-properties.patch | 48 -- .../0122-Vehicle-Event-Cancellation-Changes.patch | 45 ++ ...1-Fix-dispenser-dropper-furnace-placement.patch | 55 ++ .../0123-Vehicle-Event-Cancellation-Changes.patch | 45 -- ...0124-Improve-Minecraft-Hopper-Performance.patch | 90 +++ ...1-Fix-dispenser-dropper-furnace-placement.patch | 55 -- ...0125-Improve-Minecraft-Hopper-Performance.patch | 90 --- ...-null-possibility-for-getServer-singleton.patch | 39 + ...s-in-item-frames-performance-and-bug-fixe.patch | 149 ++++ ...-null-possibility-for-getServer-singleton.patch | 39 - ...s-in-item-frames-performance-and-bug-fixe.patch | 149 ---- ...Table-API-Replenishable-Lootables-Feature.patch | 786 +++++++++++++++++++++ .../0128-Do-not-load-chunks-for-pathfinding.patch | 22 + ...Table-API-Replenishable-Lootables-Feature.patch | 786 --------------------- .../0129-Do-not-load-chunks-for-pathfinding.patch | 22 - .../0129-Entity-Tracking-Improvements.patch | 103 +++ ...-empty-scoreboard-teams-to-scoreboard.dat.patch | 35 + .../0130-Entity-Tracking-Improvements.patch | 103 --- ...ark-chunks-as-active-for-neighbor-updates.patch | 48 ++ ...-empty-scoreboard-teams-to-scoreboard.dat.patch | 35 - ...ark-chunks-as-active-for-neighbor-updates.patch | 48 -- .../0132-Fix-Chunk-Unload-Queue-Issues.patch | 38 + .../0133-Fix-Chunk-Unload-Queue-Issues.patch | 38 - ...3-System-property-for-disabling-watchdoge.patch | 22 + Spigot-Server-Patches/0134-Optimize-EAR.patch | 69 ++ ...4-System-property-for-disabling-watchdoge.patch | 22 - Spigot-Server-Patches/0135-Optimize-EAR.patch | 69 -- .../0135-Optimize-UserCache-Thread-Safe.patch | 100 +++ ...void-blocking-on-Network-Manager-creation.patch | 47 ++ .../0136-Optimize-UserCache-Thread-Safe.patch | 100 --- ...void-blocking-on-Network-Manager-creation.patch | 47 -- .../0137-Optional-old-TNT-cannon-behaviors.patch | 393 +++++++++++ ...Faster-redstone-torch-rapid-clock-removal.patch | 43 ++ .../0138-Optional-old-TNT-cannon-behaviors.patch | 393 ----------- .../0139-Ensure-Chunks-never-ever-load-async.patch | 46 ++ ...Faster-redstone-torch-rapid-clock-removal.patch | 43 -- .../0140-Add-server-name-parameter.patch | 28 + .../0140-Ensure-Chunks-never-ever-load-async.patch | 46 -- .../0141-Add-server-name-parameter.patch | 28 - ...-Dragon-Wither-Death-sounds-to-same-world.patch | 48 ++ ...2-Fix-FallingBlocks-being-stuck-on-fences.patch | 106 +++ ...-Dragon-Wither-Death-sounds-to-same-world.patch | 48 -- ...3-Fix-FallingBlocks-being-stuck-on-fences.patch | 106 --- .../0143-Make-entities-look-for-hoppers.patch | 382 ++++++++++ ...ay-Chunk-Unloads-based-on-Player-Movement.patch | 144 ++++ .../0144-Make-entities-look-for-hoppers.patch | 382 ---------- ...ay-Chunk-Unloads-based-on-Player-Movement.patch | 144 ---- .../0145-Toggleable-Elytra-Wall-Damage.patch | 45 ++ .../0146-Fix-Double-World-Add-issues.patch | 37 + .../0146-Toggleable-Elytra-Wall-Damage.patch | 45 -- .../0147-Fix-Double-World-Add-issues.patch | 37 - .../0147-Fix-Old-Sign-Conversion.patch | 71 ++ ...p-game-profiles-that-have-no-UUID-and-no-.patch | 22 + .../0148-Fix-Old-Sign-Conversion.patch | 71 -- ...p-game-profiles-that-have-no-UUID-and-no-.patch | 22 - ...informative-vehicle-moved-wrongly-message.patch | 22 + ...informative-vehicle-moved-wrongly-message.patch | 22 - ...-players-that-dismount-from-other-players.patch | 27 + ...-Add-setting-for-proxy-online-mode-status.patch | 51 ++ ...-players-that-dismount-from-other-players.patch | 27 - ...-Add-setting-for-proxy-online-mode-status.patch | 51 -- ...timise-BlockStateEnum-hashCode-and-equals.patch | 62 ++ .../0153-Disable-ticking-of-snow-blocks.patch | 38 + ...timise-BlockStateEnum-hashCode-and-equals.patch | 62 -- .../0154-Disable-ticking-of-snow-blocks.patch | 38 - .../0154-Fix-AIOOBE-in-inventory-handling.patch | 22 + ...155-Configurable-packet-in-spam-threshold.patch | 48 ++ .../0155-Fix-AIOOBE-in-inventory-handling.patch | 22 - .../0156-Configurable-flying-kick-messages.patch | 47 ++ ...156-Configurable-packet-in-spam-threshold.patch | 48 -- .../0157-Auto-Save-Improvements.patch | 219 ++++++ .../0157-Configurable-flying-kick-messages.patch | 47 -- .../0158-Auto-Save-Improvements.patch | 219 ------ .../0158-Chunk-registration-fixes.patch | 25 + .../0159-Chunk-registration-fixes.patch | 25 - ...ingHook-reference-on-Craft-Entity-removal.patch | 30 + ...160-Auto-fix-bad-Y-levels-on-player-login.patch | 22 + ...ingHook-reference-on-Craft-Entity-removal.patch | 30 - ...161-Auto-fix-bad-Y-levels-on-player-login.patch | 22 - ...ise-string-limit-for-packet-serialization.patch | 27 + .../0162-Disable-Vanilla-Chunk-GC.patch | 33 + ...ise-string-limit-for-packet-serialization.patch | 27 - .../0163-Disable-Vanilla-Chunk-GC.patch | 33 - ...63-Option-to-remove-corrupt-tile-entities.patch | 45 ++ .../0164-Add-EntityZapEvent.patch | 71 ++ ...64-Option-to-remove-corrupt-tile-entities.patch | 45 -- .../0165-Add-EntityZapEvent.patch | 71 -- ...load-Chunks-from-Hoppers-and-other-things.patch | 36 + ...load-Chunks-from-Hoppers-and-other-things.patch | 36 - ...6-Prevent-Auto-Save-if-Save-Queue-is-full.patch | 68 ++ .../0167-Chunk-Save-Stats-Debug-Option.patch | 94 +++ ...7-Prevent-Auto-Save-if-Save-Queue-is-full.patch | 68 -- .../0168-Chunk-Save-Stats-Debug-Option.patch | 94 --- ...d-data-from-ArmorStand-and-SpawnEgg-items.patch | 65 ++ .../0169-Cache-user-authenticator-threads.patch | 67 ++ ...d-data-from-ArmorStand-and-SpawnEgg-items.patch | 65 -- .../0170-Cache-user-authenticator-threads.patch | 67 -- .../0170-Optimize-Network-Queue.patch | 22 + .../0171-Optimise-NetworkManager.patch | 125 ++++ .../0171-Optimize-Network-Queue.patch | 22 - .../0172-Optimise-NetworkManager.patch | 125 ---- .../0172-Optimise-removeQueue.patch | 65 ++ .../0173-Allow-Reloading-of-Command-Aliases.patch | 39 + .../0173-Optimise-removeQueue.patch | 65 -- .../0174-Add-source-to-PlayerExpChangeEvent.patch | 52 ++ .../0174-Allow-Reloading-of-Command-Aliases.patch | 39 - .../0175-Add-source-to-PlayerExpChangeEvent.patch | 52 -- ...5-Optimize-World.isLoaded-BlockPosition-Z.patch | 23 + ...6-Optimize-World.isLoaded-BlockPosition-Z.patch | 23 - .../0176-Speedup-BlockPos-by-fixing-inlining.patch | 181 +++++ .../0177-Don-t-let-fishinghooks-use-portals.patch | 39 + .../0177-Speedup-BlockPos-by-fixing-inlining.patch | 181 ----- .../0178-Add-ProjectileCollideEvent.patch | 111 +++ .../0178-Don-t-let-fishinghooks-use-portals.patch | 39 - .../0179-Add-ProjectileCollideEvent.patch | 111 --- .../0179-Vanished-players-don-t-have-rights.patch | 100 +++ ...0-Prevent-Pathfinding-out-of-World-Border.patch | 43 ++ .../0180-Vanished-players-don-t-have-rights.patch | 100 --- .../0181-Bound-Treasure-Maps-to-World-Border.patch | 52 ++ ...1-Prevent-Pathfinding-out-of-World-Border.patch | 43 -- .../0182-Bound-Treasure-Maps-to-World-Border.patch | 52 -- ...2-Configurable-Cartographer-Treasure-Maps.patch | 46 ++ ...3-Configurable-Cartographer-Treasure-Maps.patch | 46 -- .../0183-Optimize-ItemStack.isEmpty.patch | 31 + ...hods-to-control-if-armour-stands-can-move.patch | 54 ++ .../0184-Optimize-ItemStack.isEmpty.patch | 31 - ...hods-to-control-if-armour-stands-can-move.patch | 54 -- ...revent-armor-stands-from-doing-entity-loo.patch | 35 + ...6-Add-option-to-remove-invalid-statistics.patch | 57 ++ ...revent-armor-stands-from-doing-entity-loo.patch | 35 - ...7-Add-option-to-remove-invalid-statistics.patch | 57 -- .../0187-IllegalPacketEvent.patch | 71 ++ .../0188-IllegalPacketEvent.patch | 71 -- .../0188-Properly-fix-item-duplication-bug.patch | 35 + .../0189-Properly-fix-item-duplication-bug.patch | 35 - .../0189-String-based-Action-Bar-API.patch | 89 +++ .../0190-Activation-Range-Improvements.patch | 159 +++++ .../0190-String-based-Action-Bar-API.patch | 89 --- .../0191-Activation-Range-Improvements.patch | 159 ----- Spigot-Server-Patches/0191-Firework-API-s.patch | 133 ++++ ...e-Outdated-Build-Download-URL-to-Paper-CI.patch | 22 + Spigot-Server-Patches/0192-Firework-API-s.patch | 133 ---- ...e-Outdated-Build-Download-URL-to-Paper-CI.patch | 22 - .../0193-PlayerTeleportEndGatewayEvent.patch | 23 + ...9-Ignore-Improper-Anvil-Item-Name-Packets.patch | 28 + .../0194-PlayerTeleportEndGatewayEvent.patch | 23 - ...9-Ignore-Improper-Anvil-Item-Name-Packets.patch | 28 - ...017-Allow-31-instead-of-30-for-item-names.patch | 22 + ...017-Allow-31-instead-of-30-for-item-names.patch | 22 - .../0196-ShulkerBox-Dupe-Prevention.patch | 23 + ...197-Provide-E-TE-Chunk-count-stat-methods.patch | 45 ++ .../0197-ShulkerBox-Dupe-Prevention.patch | 23 - .../0198-Enforce-Sync-Player-Saves.patch | 31 + ...198-Provide-E-TE-Chunk-count-stat-methods.patch | 45 -- .../0199-Enforce-Sync-Chunk-Unloads.patch | 31 + .../0199-Enforce-Sync-Player-Saves.patch | 31 - ...n-t-allow-entities-to-ride-themselves-572.patch | 21 + .../0200-Enforce-Sync-Chunk-Unloads.patch | 31 - ...n-t-allow-entities-to-ride-themselves-572.patch | 21 - .../0201-Fix-block-break-desync.patch | 21 + ...02-Assign-the-World-in-WorldGenStronghold.patch | 21 + .../0202-Fix-block-break-desync.patch | 21 - ...03-Add-fromBottle-flag-to-Experience-Orbs.patch | 72 ++ ...03-Assign-the-World-in-WorldGenStronghold.patch | 21 - ...04-Add-fromBottle-flag-to-Experience-Orbs.patch | 72 -- .../0204-Remove-the-Vanilla-Method-Profiler.patch | 83 +++ .../0205-Cap-Entity-Collisions.patch | 60 ++ .../0205-Remove-the-Vanilla-Method-Profiler.patch | 83 --- .../0206-Cap-Entity-Collisions.patch | 60 -- ...ot-allow-a-zero-max-height-in-BiomeJungle.patch | 38 + ...ot-allow-a-zero-max-height-in-BiomeJungle.patch | 38 - ...Remove-CraftScheduler-Async-Task-Debugger.patch | 62 ++ ...Remove-CraftScheduler-Async-Task-Debugger.patch | 62 -- .../0208-Shame-on-you-Mojang.patch | 59 ++ ...Size-more-aggressive-in-the-chunk-unload-.patch | 22 + .../0209-Shame-on-you-Mojang.patch | 59 -- .../0210-Do-not-let-armorstands-drown.patch | 45 ++ ...Size-more-aggressive-in-the-chunk-unload-.patch | 22 - .../0211-Do-not-let-armorstands-drown.patch | 45 -- ...E-when-attempting-to-read-EMPTY-ItemStack.patch | 23 + ...E-when-attempting-to-read-EMPTY-ItemStack.patch | 23 - 331 files changed, 11130 insertions(+), 11167 deletions(-) create mode 100644 Spigot-Server-Patches/0047-Add-PlayerInitialSpawnEvent.patch delete mode 100644 Spigot-Server-Patches/0047-Don-t-create-Region-File-s-when-checking-if-chunk-ex.patch delete mode 100644 Spigot-Server-Patches/0048-Add-PlayerInitialSpawnEvent.patch create mode 100644 Spigot-Server-Patches/0048-Disable-chest-cat-detection.patch delete mode 100644 Spigot-Server-Patches/0049-Disable-chest-cat-detection.patch create mode 100644 Spigot-Server-Patches/0049-Ensure-commands-are-not-ran-async.patch create mode 100644 Spigot-Server-Patches/0050-All-chunks-are-slime-spawn-chunks-toggle.patch delete mode 100644 Spigot-Server-Patches/0050-Ensure-commands-are-not-ran-async.patch delete mode 100644 Spigot-Server-Patches/0051-All-chunks-are-slime-spawn-chunks-toggle.patch create mode 100644 Spigot-Server-Patches/0051-Optimize-Pathfinding.patch create mode 100644 Spigot-Server-Patches/0052-Avoid-hopper-searches-if-there-are-no-items.patch delete mode 100644 Spigot-Server-Patches/0052-Optimize-Pathfinding.patch delete mode 100644 Spigot-Server-Patches/0053-Avoid-hopper-searches-if-there-are-no-items.patch create mode 100644 Spigot-Server-Patches/0053-Expose-server-CommandMap.patch create mode 100644 Spigot-Server-Patches/0054-Be-a-bit-more-informative-in-maxHealth-exception.patch delete mode 100644 Spigot-Server-Patches/0054-Expose-server-CommandMap.patch delete mode 100644 Spigot-Server-Patches/0055-Be-a-bit-more-informative-in-maxHealth-exception.patch create mode 100644 Spigot-Server-Patches/0055-Player-Tab-List-and-Title-APIs.patch create mode 100644 Spigot-Server-Patches/0056-Ensure-inv-drag-is-in-bounds.patch delete mode 100644 Spigot-Server-Patches/0056-Player-Tab-List-and-Title-APIs.patch create mode 100644 Spigot-Server-Patches/0057-Change-implementation-of-tile-entity-removal-list.patch delete mode 100644 Spigot-Server-Patches/0057-Ensure-inv-drag-is-in-bounds.patch create mode 100644 Spigot-Server-Patches/0058-Add-configurable-portal-search-radius.patch delete mode 100644 Spigot-Server-Patches/0058-Change-implementation-of-tile-entity-removal-list.patch delete mode 100644 Spigot-Server-Patches/0059-Add-configurable-portal-search-radius.patch create mode 100644 Spigot-Server-Patches/0059-Add-velocity-warnings.patch delete mode 100644 Spigot-Server-Patches/0060-Add-velocity-warnings.patch create mode 100644 Spigot-Server-Patches/0060-Fix-inter-world-teleportation-glitches.patch create mode 100644 Spigot-Server-Patches/0061-Add-exception-reporting-event.patch delete mode 100644 Spigot-Server-Patches/0061-Fix-inter-world-teleportation-glitches.patch delete mode 100644 Spigot-Server-Patches/0062-Add-exception-reporting-event.patch create mode 100644 Spigot-Server-Patches/0062-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch create mode 100644 Spigot-Server-Patches/0063-Disable-Scoreboards-for-non-players-by-default.patch delete mode 100644 Spigot-Server-Patches/0063-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch create mode 100644 Spigot-Server-Patches/0064-Add-methods-for-working-with-arrows-stuck-in-living-.patch delete mode 100644 Spigot-Server-Patches/0064-Disable-Scoreboards-for-non-players-by-default.patch delete mode 100644 Spigot-Server-Patches/0065-Add-methods-for-working-with-arrows-stuck-in-living-.patch create mode 100644 Spigot-Server-Patches/0065-Complete-resource-pack-API.patch create mode 100644 Spigot-Server-Patches/0066-Chunk-save-queue-improvements.patch delete mode 100644 Spigot-Server-Patches/0066-Complete-resource-pack-API.patch create mode 100644 Spigot-Server-Patches/0067-Chunk-Save-Reattempt.patch delete mode 100644 Spigot-Server-Patches/0067-Chunk-save-queue-improvements.patch delete mode 100644 Spigot-Server-Patches/0068-Chunk-Save-Reattempt.patch create mode 100644 Spigot-Server-Patches/0068-Default-loading-permissions.yml-before-plugins.patch create mode 100644 Spigot-Server-Patches/0069-Allow-Reloading-of-Custom-Permissions.patch delete mode 100644 Spigot-Server-Patches/0069-Default-loading-permissions.yml-before-plugins.patch delete mode 100644 Spigot-Server-Patches/0070-Allow-Reloading-of-Custom-Permissions.patch create mode 100644 Spigot-Server-Patches/0070-Remove-Metadata-on-reload.patch delete mode 100644 Spigot-Server-Patches/0071-Remove-Metadata-on-reload.patch create mode 100644 Spigot-Server-Patches/0071-Undead-horse-leashing.patch create mode 100644 Spigot-Server-Patches/0072-Fix-Furnace-cook-time-bug.patch delete mode 100644 Spigot-Server-Patches/0072-Undead-horse-leashing.patch delete mode 100644 Spigot-Server-Patches/0073-Fix-Furnace-cook-time-bug.patch create mode 100644 Spigot-Server-Patches/0073-Handle-Item-Meta-Inconsistencies.patch create mode 100644 Spigot-Server-Patches/0074-Configurable-Non-Player-Arrow-Despawn-Rate.patch delete mode 100644 Spigot-Server-Patches/0074-Handle-Item-Meta-Inconsistencies.patch create mode 100644 Spigot-Server-Patches/0075-Add-World-Util-Methods.patch delete mode 100644 Spigot-Server-Patches/0075-Configurable-Non-Player-Arrow-Despawn-Rate.patch delete mode 100644 Spigot-Server-Patches/0076-Add-World-Util-Methods.patch create mode 100644 Spigot-Server-Patches/0076-Optimized-Light-Level-Comparisons.patch delete mode 100644 Spigot-Server-Patches/0077-Optimized-Light-Level-Comparisons.patch create mode 100644 Spigot-Server-Patches/0077-Pass-world-to-Village-creation.patch create mode 100644 Spigot-Server-Patches/0078-Custom-replacement-for-eaten-items.patch delete mode 100644 Spigot-Server-Patches/0078-Pass-world-to-Village-creation.patch delete mode 100644 Spigot-Server-Patches/0079-Custom-replacement-for-eaten-items.patch create mode 100644 Spigot-Server-Patches/0079-Set-health-before-death-event.patch delete mode 100644 Spigot-Server-Patches/0080-Set-health-before-death-event.patch create mode 100644 Spigot-Server-Patches/0080-handle-NaN-health-absorb-values-and-repair-bad-data.patch create mode 100644 Spigot-Server-Patches/0081-Catch-Async-PlayerChunkMap-operations.patch delete mode 100644 Spigot-Server-Patches/0081-handle-NaN-health-absorb-values-and-repair-bad-data.patch delete mode 100644 Spigot-Server-Patches/0082-Catch-Async-PlayerChunkMap-operations.patch create mode 100644 Spigot-Server-Patches/0082-Support-offline-mode-in-whitelist-command-as-well.patch create mode 100644 Spigot-Server-Patches/0083-Fix-SkullCache-case-bug.patch delete mode 100644 Spigot-Server-Patches/0083-Support-offline-mode-in-whitelist-command-as-well.patch delete mode 100644 Spigot-Server-Patches/0084-Fix-SkullCache-case-bug.patch create mode 100644 Spigot-Server-Patches/0084-Waving-banner-workaround.patch create mode 100644 Spigot-Server-Patches/0085-Use-a-Shared-Random-for-Entities.patch delete mode 100644 Spigot-Server-Patches/0085-Waving-banner-workaround.patch create mode 100644 Spigot-Server-Patches/0086-Don-t-teleport-dead-entities.patch delete mode 100644 Spigot-Server-Patches/0086-Use-a-Shared-Random-for-Entities.patch delete mode 100644 Spigot-Server-Patches/0087-Don-t-teleport-dead-entities.patch create mode 100644 Spigot-Server-Patches/0087-Optimize-Chunk-Access.patch create mode 100644 Spigot-Server-Patches/0088-Configurable-spawn-chances-for-skeleton-horses.patch delete mode 100644 Spigot-Server-Patches/0088-Optimize-Chunk-Access.patch delete mode 100644 Spigot-Server-Patches/0089-Configurable-spawn-chances-for-skeleton-horses.patch create mode 100644 Spigot-Server-Patches/0089-Optimize-isValidLocation-getType-and-getBlockData-fo.patch create mode 100644 Spigot-Server-Patches/0090-Fix-cooked-fish-legacy-import.patch delete mode 100644 Spigot-Server-Patches/0090-Optimize-isValidLocation-getType-and-getBlockData-fo.patch create mode 100644 Spigot-Server-Patches/0091-Access-items-by-EquipmentSlot.patch delete mode 100644 Spigot-Server-Patches/0091-Fix-cooked-fish-legacy-import.patch delete mode 100644 Spigot-Server-Patches/0092-Access-items-by-EquipmentSlot.patch create mode 100644 Spigot-Server-Patches/0092-Check-async-remove-unused-vars-GH-159.patch delete mode 100644 Spigot-Server-Patches/0093-Check-async-remove-unused-vars-GH-159.patch create mode 100644 Spigot-Server-Patches/0093-Option-to-disable-BlockPhysicsEvent-for-Redstone.patch create mode 100644 Spigot-Server-Patches/0094-Entity-AddTo-RemoveFrom-World-Events.patch delete mode 100644 Spigot-Server-Patches/0094-Option-to-disable-BlockPhysicsEvent-for-Redstone.patch create mode 100644 Spigot-Server-Patches/0095-Configurable-Chunk-Inhabited-Timer.patch delete mode 100644 Spigot-Server-Patches/0095-Entity-AddTo-RemoveFrom-World-Events.patch delete mode 100644 Spigot-Server-Patches/0096-Configurable-Chunk-Inhabited-Timer.patch create mode 100644 Spigot-Server-Patches/0096-EntityPathfindEvent.patch delete mode 100644 Spigot-Server-Patches/0097-EntityPathfindEvent.patch create mode 100644 Spigot-Server-Patches/0097-Prevent-Waterflow-BlockFromToEvent-from-loading-chun.patch delete mode 100644 Spigot-Server-Patches/0098-Prevent-Waterflow-BlockFromToEvent-from-loading-chun.patch create mode 100644 Spigot-Server-Patches/0098-Reduce-IO-ops-opening-a-new-region-file.patch delete mode 100644 Spigot-Server-Patches/0099-Reduce-IO-ops-opening-a-new-region-file.patch create mode 100644 Spigot-Server-Patches/0099-Sanitise-RegionFileCache-and-make-configurable.patch delete mode 100644 Spigot-Server-Patches/0100-Sanitise-RegionFileCache-and-make-configurable.patch create mode 100644 Spigot-Server-Patches/0100-Use-Optimized-Collections.patch create mode 100644 Spigot-Server-Patches/0101-Do-not-load-chunks-for-light-checks.patch delete mode 100644 Spigot-Server-Patches/0101-Use-Optimized-Collections.patch create mode 100644 Spigot-Server-Patches/0102-Add-PlayerUseUnknownEntityEvent.patch delete mode 100644 Spigot-Server-Patches/0102-Do-not-load-chunks-for-light-checks.patch delete mode 100644 Spigot-Server-Patches/0103-Add-PlayerUseUnknownEntityEvent.patch create mode 100644 Spigot-Server-Patches/0103-Fix-reducedDebugInfo-not-initialized-on-client.patch create mode 100644 Spigot-Server-Patches/0104-Configurable-Grass-Spread-Tick-Rate.patch delete mode 100644 Spigot-Server-Patches/0104-Fix-reducedDebugInfo-not-initialized-on-client.patch delete mode 100644 Spigot-Server-Patches/0105-Configurable-Grass-Spread-Tick-Rate.patch create mode 100644 Spigot-Server-Patches/0105-Configurable-Keep-Spawn-Loaded-range-per-world.patch delete mode 100644 Spigot-Server-Patches/0106-Configurable-Keep-Spawn-Loaded-range-per-world.patch create mode 100644 Spigot-Server-Patches/0106-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch create mode 100644 Spigot-Server-Patches/0107-Don-t-spam-reload-spawn-chunks-in-nether-end.patch delete mode 100644 Spigot-Server-Patches/0107-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch delete mode 100644 Spigot-Server-Patches/0108-Don-t-spam-reload-spawn-chunks-in-nether-end.patch create mode 100644 Spigot-Server-Patches/0108-Remove-Debug-checks-from-DataBits.patch create mode 100644 Spigot-Server-Patches/0109-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch delete mode 100644 Spigot-Server-Patches/0109-Remove-Debug-checks-from-DataBits.patch delete mode 100644 Spigot-Server-Patches/0110-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch create mode 100644 Spigot-Server-Patches/0110-Workaround-for-setting-passengers-on-players.patch create mode 100644 Spigot-Server-Patches/0111-Remove-unused-World-Tile-Entity-List.patch delete mode 100644 Spigot-Server-Patches/0111-Workaround-for-setting-passengers-on-players.patch create mode 100644 Spigot-Server-Patches/0112-Don-t-tick-Skulls-unused-code.patch delete mode 100644 Spigot-Server-Patches/0112-Remove-unused-World-Tile-Entity-List.patch create mode 100644 Spigot-Server-Patches/0113-Configurable-Player-Collision.patch delete mode 100644 Spigot-Server-Patches/0113-Don-t-tick-Skulls-unused-code.patch create mode 100644 Spigot-Server-Patches/0114-Add-handshake-event-to-allow-plugins-to-handle-clien.patch delete mode 100644 Spigot-Server-Patches/0114-Configurable-Player-Collision.patch delete mode 100644 Spigot-Server-Patches/0115-Add-handshake-event-to-allow-plugins-to-handle-clien.patch create mode 100644 Spigot-Server-Patches/0115-Water-mobs-should-only-spawn-in-the-water.patch create mode 100644 Spigot-Server-Patches/0116-Fix-Bugs-with-Spigot-Mob-Spawn-Logic.patch delete mode 100644 Spigot-Server-Patches/0116-Water-mobs-should-only-spawn-in-the-water.patch create mode 100644 Spigot-Server-Patches/0117-Configurable-RCON-IP-address.patch delete mode 100644 Spigot-Server-Patches/0117-Fix-Bugs-with-Spigot-Mob-Spawn-Logic.patch delete mode 100644 Spigot-Server-Patches/0118-Configurable-RCON-IP-address.patch create mode 100644 Spigot-Server-Patches/0118-Prevent-Fire-from-loading-chunks.patch create mode 100644 Spigot-Server-Patches/0119-Implement-PlayerLocaleChangeEvent.patch delete mode 100644 Spigot-Server-Patches/0119-Prevent-Fire-from-loading-chunks.patch create mode 100644 Spigot-Server-Patches/0120-EntityRegainHealthEvent-isFastRegen-API.patch delete mode 100644 Spigot-Server-Patches/0120-Implement-PlayerLocaleChangeEvent.patch create mode 100644 Spigot-Server-Patches/0121-Add-ability-to-configure-frosted_ice-properties.patch delete mode 100644 Spigot-Server-Patches/0121-EntityRegainHealthEvent-isFastRegen-API.patch delete mode 100644 Spigot-Server-Patches/0122-Add-ability-to-configure-frosted_ice-properties.patch create mode 100644 Spigot-Server-Patches/0122-Vehicle-Event-Cancellation-Changes.patch create mode 100644 Spigot-Server-Patches/0123-SPIGOT-1401-Fix-dispenser-dropper-furnace-placement.patch delete mode 100644 Spigot-Server-Patches/0123-Vehicle-Event-Cancellation-Changes.patch create mode 100644 Spigot-Server-Patches/0124-Improve-Minecraft-Hopper-Performance.patch delete mode 100644 Spigot-Server-Patches/0124-SPIGOT-1401-Fix-dispenser-dropper-furnace-placement.patch delete mode 100644 Spigot-Server-Patches/0125-Improve-Minecraft-Hopper-Performance.patch create mode 100644 Spigot-Server-Patches/0125-remove-null-possibility-for-getServer-singleton.patch create mode 100644 Spigot-Server-Patches/0126-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch delete mode 100644 Spigot-Server-Patches/0126-remove-null-possibility-for-getServer-singleton.patch delete mode 100644 Spigot-Server-Patches/0127-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch create mode 100644 Spigot-Server-Patches/0127-LootTable-API-Replenishable-Lootables-Feature.patch create mode 100644 Spigot-Server-Patches/0128-Do-not-load-chunks-for-pathfinding.patch delete mode 100644 Spigot-Server-Patches/0128-LootTable-API-Replenishable-Lootables-Feature.patch delete mode 100644 Spigot-Server-Patches/0129-Do-not-load-chunks-for-pathfinding.patch create mode 100644 Spigot-Server-Patches/0129-Entity-Tracking-Improvements.patch create mode 100644 Spigot-Server-Patches/0130-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch delete mode 100644 Spigot-Server-Patches/0130-Entity-Tracking-Improvements.patch create mode 100644 Spigot-Server-Patches/0131-Do-not-mark-chunks-as-active-for-neighbor-updates.patch delete mode 100644 Spigot-Server-Patches/0131-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch delete mode 100644 Spigot-Server-Patches/0132-Do-not-mark-chunks-as-active-for-neighbor-updates.patch create mode 100644 Spigot-Server-Patches/0132-Fix-Chunk-Unload-Queue-Issues.patch delete mode 100644 Spigot-Server-Patches/0133-Fix-Chunk-Unload-Queue-Issues.patch create mode 100644 Spigot-Server-Patches/0133-System-property-for-disabling-watchdoge.patch create mode 100644 Spigot-Server-Patches/0134-Optimize-EAR.patch delete mode 100644 Spigot-Server-Patches/0134-System-property-for-disabling-watchdoge.patch delete mode 100644 Spigot-Server-Patches/0135-Optimize-EAR.patch create mode 100644 Spigot-Server-Patches/0135-Optimize-UserCache-Thread-Safe.patch create mode 100644 Spigot-Server-Patches/0136-Avoid-blocking-on-Network-Manager-creation.patch delete mode 100644 Spigot-Server-Patches/0136-Optimize-UserCache-Thread-Safe.patch delete mode 100644 Spigot-Server-Patches/0137-Avoid-blocking-on-Network-Manager-creation.patch create mode 100644 Spigot-Server-Patches/0137-Optional-old-TNT-cannon-behaviors.patch create mode 100644 Spigot-Server-Patches/0138-Faster-redstone-torch-rapid-clock-removal.patch delete mode 100644 Spigot-Server-Patches/0138-Optional-old-TNT-cannon-behaviors.patch create mode 100644 Spigot-Server-Patches/0139-Ensure-Chunks-never-ever-load-async.patch delete mode 100644 Spigot-Server-Patches/0139-Faster-redstone-torch-rapid-clock-removal.patch create mode 100644 Spigot-Server-Patches/0140-Add-server-name-parameter.patch delete mode 100644 Spigot-Server-Patches/0140-Ensure-Chunks-never-ever-load-async.patch delete mode 100644 Spigot-Server-Patches/0141-Add-server-name-parameter.patch create mode 100644 Spigot-Server-Patches/0141-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch create mode 100644 Spigot-Server-Patches/0142-Fix-FallingBlocks-being-stuck-on-fences.patch delete mode 100644 Spigot-Server-Patches/0142-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch delete mode 100644 Spigot-Server-Patches/0143-Fix-FallingBlocks-being-stuck-on-fences.patch create mode 100644 Spigot-Server-Patches/0143-Make-entities-look-for-hoppers.patch create mode 100644 Spigot-Server-Patches/0144-Delay-Chunk-Unloads-based-on-Player-Movement.patch delete mode 100644 Spigot-Server-Patches/0144-Make-entities-look-for-hoppers.patch delete mode 100644 Spigot-Server-Patches/0145-Delay-Chunk-Unloads-based-on-Player-Movement.patch create mode 100644 Spigot-Server-Patches/0145-Toggleable-Elytra-Wall-Damage.patch create mode 100644 Spigot-Server-Patches/0146-Fix-Double-World-Add-issues.patch delete mode 100644 Spigot-Server-Patches/0146-Toggleable-Elytra-Wall-Damage.patch delete mode 100644 Spigot-Server-Patches/0147-Fix-Double-World-Add-issues.patch create mode 100644 Spigot-Server-Patches/0147-Fix-Old-Sign-Conversion.patch create mode 100644 Spigot-Server-Patches/0148-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch delete mode 100644 Spigot-Server-Patches/0148-Fix-Old-Sign-Conversion.patch delete mode 100644 Spigot-Server-Patches/0149-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch create mode 100644 Spigot-Server-Patches/0149-More-informative-vehicle-moved-wrongly-message.patch delete mode 100644 Spigot-Server-Patches/0150-More-informative-vehicle-moved-wrongly-message.patch create mode 100644 Spigot-Server-Patches/0150-Re-track-players-that-dismount-from-other-players.patch create mode 100644 Spigot-Server-Patches/0151-Add-setting-for-proxy-online-mode-status.patch delete mode 100644 Spigot-Server-Patches/0151-Re-track-players-that-dismount-from-other-players.patch delete mode 100644 Spigot-Server-Patches/0152-Add-setting-for-proxy-online-mode-status.patch create mode 100644 Spigot-Server-Patches/0152-Optimise-BlockStateEnum-hashCode-and-equals.patch create mode 100644 Spigot-Server-Patches/0153-Disable-ticking-of-snow-blocks.patch delete mode 100644 Spigot-Server-Patches/0153-Optimise-BlockStateEnum-hashCode-and-equals.patch delete mode 100644 Spigot-Server-Patches/0154-Disable-ticking-of-snow-blocks.patch create mode 100644 Spigot-Server-Patches/0154-Fix-AIOOBE-in-inventory-handling.patch create mode 100644 Spigot-Server-Patches/0155-Configurable-packet-in-spam-threshold.patch delete mode 100644 Spigot-Server-Patches/0155-Fix-AIOOBE-in-inventory-handling.patch create mode 100644 Spigot-Server-Patches/0156-Configurable-flying-kick-messages.patch delete mode 100644 Spigot-Server-Patches/0156-Configurable-packet-in-spam-threshold.patch create mode 100644 Spigot-Server-Patches/0157-Auto-Save-Improvements.patch delete mode 100644 Spigot-Server-Patches/0157-Configurable-flying-kick-messages.patch delete mode 100644 Spigot-Server-Patches/0158-Auto-Save-Improvements.patch create mode 100644 Spigot-Server-Patches/0158-Chunk-registration-fixes.patch delete mode 100644 Spigot-Server-Patches/0159-Chunk-registration-fixes.patch create mode 100644 Spigot-Server-Patches/0159-Remove-FishingHook-reference-on-Craft-Entity-removal.patch create mode 100644 Spigot-Server-Patches/0160-Auto-fix-bad-Y-levels-on-player-login.patch delete mode 100644 Spigot-Server-Patches/0160-Remove-FishingHook-reference-on-Craft-Entity-removal.patch delete mode 100644 Spigot-Server-Patches/0161-Auto-fix-bad-Y-levels-on-player-login.patch create mode 100644 Spigot-Server-Patches/0161-Raise-string-limit-for-packet-serialization.patch create mode 100644 Spigot-Server-Patches/0162-Disable-Vanilla-Chunk-GC.patch delete mode 100644 Spigot-Server-Patches/0162-Raise-string-limit-for-packet-serialization.patch delete mode 100644 Spigot-Server-Patches/0163-Disable-Vanilla-Chunk-GC.patch create mode 100644 Spigot-Server-Patches/0163-Option-to-remove-corrupt-tile-entities.patch create mode 100644 Spigot-Server-Patches/0164-Add-EntityZapEvent.patch delete mode 100644 Spigot-Server-Patches/0164-Option-to-remove-corrupt-tile-entities.patch delete mode 100644 Spigot-Server-Patches/0165-Add-EntityZapEvent.patch create mode 100644 Spigot-Server-Patches/0165-Don-t-load-Chunks-from-Hoppers-and-other-things.patch delete mode 100644 Spigot-Server-Patches/0166-Don-t-load-Chunks-from-Hoppers-and-other-things.patch create mode 100644 Spigot-Server-Patches/0166-Prevent-Auto-Save-if-Save-Queue-is-full.patch create mode 100644 Spigot-Server-Patches/0167-Chunk-Save-Stats-Debug-Option.patch delete mode 100644 Spigot-Server-Patches/0167-Prevent-Auto-Save-if-Save-Queue-is-full.patch delete mode 100644 Spigot-Server-Patches/0168-Chunk-Save-Stats-Debug-Option.patch create mode 100644 Spigot-Server-Patches/0168-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch create mode 100644 Spigot-Server-Patches/0169-Cache-user-authenticator-threads.patch delete mode 100644 Spigot-Server-Patches/0169-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch delete mode 100644 Spigot-Server-Patches/0170-Cache-user-authenticator-threads.patch create mode 100644 Spigot-Server-Patches/0170-Optimize-Network-Queue.patch create mode 100644 Spigot-Server-Patches/0171-Optimise-NetworkManager.patch delete mode 100644 Spigot-Server-Patches/0171-Optimize-Network-Queue.patch delete mode 100644 Spigot-Server-Patches/0172-Optimise-NetworkManager.patch create mode 100644 Spigot-Server-Patches/0172-Optimise-removeQueue.patch create mode 100644 Spigot-Server-Patches/0173-Allow-Reloading-of-Command-Aliases.patch delete mode 100644 Spigot-Server-Patches/0173-Optimise-removeQueue.patch create mode 100644 Spigot-Server-Patches/0174-Add-source-to-PlayerExpChangeEvent.patch delete mode 100644 Spigot-Server-Patches/0174-Allow-Reloading-of-Command-Aliases.patch delete mode 100644 Spigot-Server-Patches/0175-Add-source-to-PlayerExpChangeEvent.patch create mode 100644 Spigot-Server-Patches/0175-Optimize-World.isLoaded-BlockPosition-Z.patch delete mode 100644 Spigot-Server-Patches/0176-Optimize-World.isLoaded-BlockPosition-Z.patch create mode 100644 Spigot-Server-Patches/0176-Speedup-BlockPos-by-fixing-inlining.patch create mode 100644 Spigot-Server-Patches/0177-Don-t-let-fishinghooks-use-portals.patch delete mode 100644 Spigot-Server-Patches/0177-Speedup-BlockPos-by-fixing-inlining.patch create mode 100644 Spigot-Server-Patches/0178-Add-ProjectileCollideEvent.patch delete mode 100644 Spigot-Server-Patches/0178-Don-t-let-fishinghooks-use-portals.patch delete mode 100644 Spigot-Server-Patches/0179-Add-ProjectileCollideEvent.patch create mode 100644 Spigot-Server-Patches/0179-Vanished-players-don-t-have-rights.patch create mode 100644 Spigot-Server-Patches/0180-Prevent-Pathfinding-out-of-World-Border.patch delete mode 100644 Spigot-Server-Patches/0180-Vanished-players-don-t-have-rights.patch create mode 100644 Spigot-Server-Patches/0181-Bound-Treasure-Maps-to-World-Border.patch delete mode 100644 Spigot-Server-Patches/0181-Prevent-Pathfinding-out-of-World-Border.patch delete mode 100644 Spigot-Server-Patches/0182-Bound-Treasure-Maps-to-World-Border.patch create mode 100644 Spigot-Server-Patches/0182-Configurable-Cartographer-Treasure-Maps.patch delete mode 100644 Spigot-Server-Patches/0183-Configurable-Cartographer-Treasure-Maps.patch create mode 100644 Spigot-Server-Patches/0183-Optimize-ItemStack.isEmpty.patch create mode 100644 Spigot-Server-Patches/0184-Add-API-methods-to-control-if-armour-stands-can-move.patch delete mode 100644 Spigot-Server-Patches/0184-Optimize-ItemStack.isEmpty.patch delete mode 100644 Spigot-Server-Patches/0185-Add-API-methods-to-control-if-armour-stands-can-move.patch create mode 100644 Spigot-Server-Patches/0185-Option-to-prevent-armor-stands-from-doing-entity-loo.patch create mode 100644 Spigot-Server-Patches/0186-Add-option-to-remove-invalid-statistics.patch delete mode 100644 Spigot-Server-Patches/0186-Option-to-prevent-armor-stands-from-doing-entity-loo.patch delete mode 100644 Spigot-Server-Patches/0187-Add-option-to-remove-invalid-statistics.patch create mode 100644 Spigot-Server-Patches/0187-IllegalPacketEvent.patch delete mode 100644 Spigot-Server-Patches/0188-IllegalPacketEvent.patch create mode 100644 Spigot-Server-Patches/0188-Properly-fix-item-duplication-bug.patch delete mode 100644 Spigot-Server-Patches/0189-Properly-fix-item-duplication-bug.patch create mode 100644 Spigot-Server-Patches/0189-String-based-Action-Bar-API.patch create mode 100644 Spigot-Server-Patches/0190-Activation-Range-Improvements.patch delete mode 100644 Spigot-Server-Patches/0190-String-based-Action-Bar-API.patch delete mode 100644 Spigot-Server-Patches/0191-Activation-Range-Improvements.patch create mode 100644 Spigot-Server-Patches/0191-Firework-API-s.patch create mode 100644 Spigot-Server-Patches/0192-Change-Outdated-Build-Download-URL-to-Paper-CI.patch delete mode 100644 Spigot-Server-Patches/0192-Firework-API-s.patch delete mode 100644 Spigot-Server-Patches/0193-Change-Outdated-Build-Download-URL-to-Paper-CI.patch create mode 100644 Spigot-Server-Patches/0193-PlayerTeleportEndGatewayEvent.patch create mode 100644 Spigot-Server-Patches/0194-MC-111699-Ignore-Improper-Anvil-Item-Name-Packets.patch delete mode 100644 Spigot-Server-Patches/0194-PlayerTeleportEndGatewayEvent.patch delete mode 100644 Spigot-Server-Patches/0195-MC-111699-Ignore-Improper-Anvil-Item-Name-Packets.patch create mode 100644 Spigot-Server-Patches/0195-MC-112017-Allow-31-instead-of-30-for-item-names.patch delete mode 100644 Spigot-Server-Patches/0196-MC-112017-Allow-31-instead-of-30-for-item-names.patch create mode 100644 Spigot-Server-Patches/0196-ShulkerBox-Dupe-Prevention.patch create mode 100644 Spigot-Server-Patches/0197-Provide-E-TE-Chunk-count-stat-methods.patch delete mode 100644 Spigot-Server-Patches/0197-ShulkerBox-Dupe-Prevention.patch create mode 100644 Spigot-Server-Patches/0198-Enforce-Sync-Player-Saves.patch delete mode 100644 Spigot-Server-Patches/0198-Provide-E-TE-Chunk-count-stat-methods.patch create mode 100644 Spigot-Server-Patches/0199-Enforce-Sync-Chunk-Unloads.patch delete mode 100644 Spigot-Server-Patches/0199-Enforce-Sync-Player-Saves.patch create mode 100644 Spigot-Server-Patches/0200-Don-t-allow-entities-to-ride-themselves-572.patch delete mode 100644 Spigot-Server-Patches/0200-Enforce-Sync-Chunk-Unloads.patch delete mode 100644 Spigot-Server-Patches/0201-Don-t-allow-entities-to-ride-themselves-572.patch create mode 100644 Spigot-Server-Patches/0201-Fix-block-break-desync.patch create mode 100644 Spigot-Server-Patches/0202-Assign-the-World-in-WorldGenStronghold.patch delete mode 100644 Spigot-Server-Patches/0202-Fix-block-break-desync.patch create mode 100644 Spigot-Server-Patches/0203-Add-fromBottle-flag-to-Experience-Orbs.patch delete mode 100644 Spigot-Server-Patches/0203-Assign-the-World-in-WorldGenStronghold.patch delete mode 100644 Spigot-Server-Patches/0204-Add-fromBottle-flag-to-Experience-Orbs.patch create mode 100644 Spigot-Server-Patches/0204-Remove-the-Vanilla-Method-Profiler.patch create mode 100644 Spigot-Server-Patches/0205-Cap-Entity-Collisions.patch delete mode 100644 Spigot-Server-Patches/0205-Remove-the-Vanilla-Method-Profiler.patch delete mode 100644 Spigot-Server-Patches/0206-Cap-Entity-Collisions.patch create mode 100644 Spigot-Server-Patches/0206-Do-not-allow-a-zero-max-height-in-BiomeJungle.patch delete mode 100644 Spigot-Server-Patches/0207-Do-not-allow-a-zero-max-height-in-BiomeJungle.patch create mode 100644 Spigot-Server-Patches/0207-Remove-CraftScheduler-Async-Task-Debugger.patch delete mode 100644 Spigot-Server-Patches/0208-Remove-CraftScheduler-Async-Task-Debugger.patch create mode 100644 Spigot-Server-Patches/0208-Shame-on-you-Mojang.patch create mode 100644 Spigot-Server-Patches/0209-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch delete mode 100644 Spigot-Server-Patches/0209-Shame-on-you-Mojang.patch create mode 100644 Spigot-Server-Patches/0210-Do-not-let-armorstands-drown.patch delete mode 100644 Spigot-Server-Patches/0210-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch delete mode 100644 Spigot-Server-Patches/0211-Do-not-let-armorstands-drown.patch create mode 100644 Spigot-Server-Patches/0211-Fix-NFE-when-attempting-to-read-EMPTY-ItemStack.patch delete mode 100644 Spigot-Server-Patches/0212-Fix-NFE-when-attempting-to-read-EMPTY-ItemStack.patch diff --git a/Spigot-Server-Patches/0047-Add-PlayerInitialSpawnEvent.patch b/Spigot-Server-Patches/0047-Add-PlayerInitialSpawnEvent.patch new file mode 100644 index 0000000000..dd0cd845af --- /dev/null +++ b/Spigot-Server-Patches/0047-Add-PlayerInitialSpawnEvent.patch @@ -0,0 +1,36 @@ +From 5f5ff59c74f2094741e3cf0f5c615d34d2231005 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 + +diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java +index 80bf61164..59c7e78b8 100644 +--- a/src/main/java/net/minecraft/server/PlayerList.java ++++ b/src/main/java/net/minecraft/server/PlayerList.java +@@ -104,6 +104,21 @@ public abstract class PlayerList { + } + // CraftBukkit end + ++ // Paper start - support PlayerInitialSpawnEvent ++ Location originalLoc = new Location(entityplayer.world.getWorld(), entityplayer.locX, entityplayer.locY, entityplayer.locZ, entityplayer.yaw, entityplayer.pitch); ++ com.destroystokyo.paper.event.player.PlayerInitialSpawnEvent event = new com.destroystokyo.paper.event.player.PlayerInitialSpawnEvent(entityplayer.getBukkitEntity(), originalLoc); ++ this.server.server.getPluginManager().callEvent(event); ++ ++ Location newLoc = event.getSpawnLocation(); ++ entityplayer.world = ((CraftWorld) newLoc.getWorld()).getHandle(); ++ entityplayer.locX = newLoc.getX(); ++ entityplayer.locY = newLoc.getY(); ++ entityplayer.locZ = newLoc.getZ(); ++ entityplayer.yaw = newLoc.getYaw(); ++ entityplayer.pitch = newLoc.getPitch(); ++ entityplayer.dimension = ((CraftWorld) newLoc.getWorld()).getHandle().dimension; ++ // Paper end ++ + entityplayer.spawnIn(this.server.getWorldServer(entityplayer.dimension)); + entityplayer.playerInteractManager.a((WorldServer) entityplayer.world); + String s1 = "local"; +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0047-Don-t-create-Region-File-s-when-checking-if-chunk-ex.patch b/Spigot-Server-Patches/0047-Don-t-create-Region-File-s-when-checking-if-chunk-ex.patch deleted file mode 100644 index ad7e06eaf5..0000000000 --- a/Spigot-Server-Patches/0047-Don-t-create-Region-File-s-when-checking-if-chunk-ex.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 9d265dc548c5d1e3df9129a15865e70b1597451d Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 2 Mar 2016 23:51:51 -0600 -Subject: [PATCH] Don't create Region File's when checking if chunk exists - -Plugins like Dynmap can end up creating tons of emtpy Region Files -when using chunkExists. - -diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java -index 6ec72689c..0163a4e59 100644 ---- a/src/main/java/net/minecraft/server/RegionFileCache.java -+++ b/src/main/java/net/minecraft/server/RegionFileCache.java -@@ -12,7 +12,13 @@ public class RegionFileCache { - - public static final Map a = Maps.newHashMap(); // Spigot - private -> public - -+ // Paper start - public static synchronized RegionFile a(File file, int i, int j) { -+ return a(file, i, j, true); -+ } -+ -+ public static synchronized RegionFile a(File file, int i, int j, boolean create) { -+ // Paper end - File file1 = new File(file, "region"); - File file2 = new File(file1, "r." + (i >> 5) + "." + (j >> 5) + ".mca"); - RegionFile regionfile = (RegionFile) RegionFileCache.a.get(file2); -@@ -20,6 +26,7 @@ public class RegionFileCache { - if (regionfile != null) { - return regionfile; - } else { -+ if (!create && !file2.exists()) { return null; } // Paper - if (!file1.exists()) { - file1.mkdirs(); - } --- -2.12.2.windows.2 - diff --git a/Spigot-Server-Patches/0048-Add-PlayerInitialSpawnEvent.patch b/Spigot-Server-Patches/0048-Add-PlayerInitialSpawnEvent.patch deleted file mode 100644 index 5c38cea4f1..0000000000 --- a/Spigot-Server-Patches/0048-Add-PlayerInitialSpawnEvent.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 2e3b2f159778b82cd48210b44e1ce8dffeb91c78 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 - -diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java -index d778eafb3..d6a2bbc08 100644 ---- a/src/main/java/net/minecraft/server/PlayerList.java -+++ b/src/main/java/net/minecraft/server/PlayerList.java -@@ -104,6 +104,21 @@ public abstract class PlayerList { - } - // CraftBukkit end - -+ // Paper start - support PlayerInitialSpawnEvent -+ Location originalLoc = new Location(entityplayer.world.getWorld(), entityplayer.locX, entityplayer.locY, entityplayer.locZ, entityplayer.yaw, entityplayer.pitch); -+ com.destroystokyo.paper.event.player.PlayerInitialSpawnEvent event = new com.destroystokyo.paper.event.player.PlayerInitialSpawnEvent(entityplayer.getBukkitEntity(), originalLoc); -+ this.server.server.getPluginManager().callEvent(event); -+ -+ Location newLoc = event.getSpawnLocation(); -+ entityplayer.world = ((CraftWorld) newLoc.getWorld()).getHandle(); -+ entityplayer.locX = newLoc.getX(); -+ entityplayer.locY = newLoc.getY(); -+ entityplayer.locZ = newLoc.getZ(); -+ entityplayer.yaw = newLoc.getYaw(); -+ entityplayer.pitch = newLoc.getPitch(); -+ entityplayer.dimension = ((CraftWorld) newLoc.getWorld()).getHandle().dimension; -+ // Paper end -+ - entityplayer.spawnIn(this.server.getWorldServer(entityplayer.dimension)); - entityplayer.playerInteractManager.a((WorldServer) entityplayer.world); - String s1 = "local"; --- -2.12.2 - diff --git a/Spigot-Server-Patches/0048-Disable-chest-cat-detection.patch b/Spigot-Server-Patches/0048-Disable-chest-cat-detection.patch new file mode 100644 index 0000000000..7636e780aa --- /dev/null +++ b/Spigot-Server-Patches/0048-Disable-chest-cat-detection.patch @@ -0,0 +1,39 @@ +From d76321993eecd60cc0a0410ff8b45a0303134b81 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 3 Mar 2016 01:13:45 -0600 +Subject: [PATCH] Disable chest cat detection + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index e6aae7317..6ce62827a 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -224,4 +224,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/server/BlockChest.java b/src/main/java/net/minecraft/server/BlockChest.java +index c75ed8a36..9c4d1c938 100644 +--- a/src/main/java/net/minecraft/server/BlockChest.java ++++ b/src/main/java/net/minecraft/server/BlockChest.java +@@ -399,6 +399,11 @@ public class BlockChest extends BlockTileEntity { + } + + private boolean j(World world, BlockPosition blockposition) { ++ // Paper start - Option ti dsiable chest cat detection ++ if (world.paperConfig.disableChestCatDetection) { ++ return false; ++ } ++ // Paper end + Iterator iterator = world.a(EntityOcelot.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))).iterator(); + + EntityOcelot entityocelot; +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0049-Disable-chest-cat-detection.patch b/Spigot-Server-Patches/0049-Disable-chest-cat-detection.patch deleted file mode 100644 index 7082f8485f..0000000000 --- a/Spigot-Server-Patches/0049-Disable-chest-cat-detection.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 1c4b779cc2accfe5eae2d1435bdf0e1e2a74f319 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Mar 2016 01:13:45 -0600 -Subject: [PATCH] Disable chest cat detection - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index e6aae7317..6ce62827a 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -224,4 +224,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/server/BlockChest.java b/src/main/java/net/minecraft/server/BlockChest.java -index c75ed8a36..9c4d1c938 100644 ---- a/src/main/java/net/minecraft/server/BlockChest.java -+++ b/src/main/java/net/minecraft/server/BlockChest.java -@@ -399,6 +399,11 @@ public class BlockChest extends BlockTileEntity { - } - - private boolean j(World world, BlockPosition blockposition) { -+ // Paper start - Option ti dsiable chest cat detection -+ if (world.paperConfig.disableChestCatDetection) { -+ return false; -+ } -+ // Paper end - Iterator iterator = world.a(EntityOcelot.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))).iterator(); - - EntityOcelot entityocelot; --- -2.12.2 - diff --git a/Spigot-Server-Patches/0049-Ensure-commands-are-not-ran-async.patch b/Spigot-Server-Patches/0049-Ensure-commands-are-not-ran-async.patch new file mode 100644 index 0000000000..ed38f7e4b5 --- /dev/null +++ b/Spigot-Server-Patches/0049-Ensure-commands-are-not-ran-async.patch @@ -0,0 +1,86 @@ +From c121bda3726ac920a54e7d3462c86cc16e114a8c 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/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 27283efad..57879c76d 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -1268,6 +1268,29 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { + } + + if (!async && s.startsWith("/")) { ++ // Paper Start ++ if (org.spigotmc.AsyncCatcher.enabled && !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() == EntityHuman.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 0f77d0674..5302bb283 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -647,6 +647,29 @@ public final class CraftServer implements Server { + Validate.notNull(sender, "Sender cannot be null"); + Validate.notNull(commandLine, "CommandLine cannot be null"); + ++ // Paper Start ++ if (org.spigotmc.AsyncCatcher.enabled && !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; + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0050-All-chunks-are-slime-spawn-chunks-toggle.patch b/Spigot-Server-Patches/0050-All-chunks-are-slime-spawn-chunks-toggle.patch new file mode 100644 index 0000000000..1bb8773509 --- /dev/null +++ b/Spigot-Server-Patches/0050-All-chunks-are-slime-spawn-chunks-toggle.patch @@ -0,0 +1,37 @@ +From 6b81f8f28de16733bff9a2d833a2397f6af7fe9e 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 6ce62827a..ab7e81a0d 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -229,4 +229,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/server/EntitySlime.java b/src/main/java/net/minecraft/server/EntitySlime.java +index 8fb14d6b5..c68429fb1 100644 +--- a/src/main/java/net/minecraft/server/EntitySlime.java ++++ b/src/main/java/net/minecraft/server/EntitySlime.java +@@ -252,7 +252,8 @@ public class EntitySlime extends EntityInsentient implements IMonster { + return super.cM(); + } + +- if (this.random.nextInt(10) == 0 && chunk.a(world.spigotConfig.slimeSeed).nextInt(10) == 0 && this.locY < 40.0D) { // Spigot ++ boolean isSlimeChunk = world.paperConfig.allChunksAreSlimeChunks || chunk.a(world.spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot // Paper ++ if (this.random.nextInt(10) == 0 && isSlimeChunk && this.locY < 40.0D) { // Paper + return super.cM(); + } + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0050-Ensure-commands-are-not-ran-async.patch b/Spigot-Server-Patches/0050-Ensure-commands-are-not-ran-async.patch deleted file mode 100644 index 6e7cd59624..0000000000 --- a/Spigot-Server-Patches/0050-Ensure-commands-are-not-ran-async.patch +++ /dev/null @@ -1,86 +0,0 @@ -From acaa4a559a33fe2e2dae4fb4f59aaea68ff00490 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/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 27283efad..57879c76d 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -1268,6 +1268,29 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { - } - - if (!async && s.startsWith("/")) { -+ // Paper Start -+ if (org.spigotmc.AsyncCatcher.enabled && !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() == EntityHuman.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 0f77d0674..5302bb283 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -647,6 +647,29 @@ public final class CraftServer implements Server { - Validate.notNull(sender, "Sender cannot be null"); - Validate.notNull(commandLine, "CommandLine cannot be null"); - -+ // Paper Start -+ if (org.spigotmc.AsyncCatcher.enabled && !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; - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0051-All-chunks-are-slime-spawn-chunks-toggle.patch b/Spigot-Server-Patches/0051-All-chunks-are-slime-spawn-chunks-toggle.patch deleted file mode 100644 index d1347c3e67..0000000000 --- a/Spigot-Server-Patches/0051-All-chunks-are-slime-spawn-chunks-toggle.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 71575ec7e7c01c6ffae6465bb584e0bbb5d4e109 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 6ce62827a..ab7e81a0d 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -229,4 +229,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/server/EntitySlime.java b/src/main/java/net/minecraft/server/EntitySlime.java -index 8fb14d6b5..c68429fb1 100644 ---- a/src/main/java/net/minecraft/server/EntitySlime.java -+++ b/src/main/java/net/minecraft/server/EntitySlime.java -@@ -252,7 +252,8 @@ public class EntitySlime extends EntityInsentient implements IMonster { - return super.cM(); - } - -- if (this.random.nextInt(10) == 0 && chunk.a(world.spigotConfig.slimeSeed).nextInt(10) == 0 && this.locY < 40.0D) { // Spigot -+ boolean isSlimeChunk = world.paperConfig.allChunksAreSlimeChunks || chunk.a(world.spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot // Paper -+ if (this.random.nextInt(10) == 0 && isSlimeChunk && this.locY < 40.0D) { // Paper - return super.cM(); - } - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0051-Optimize-Pathfinding.patch b/Spigot-Server-Patches/0051-Optimize-Pathfinding.patch new file mode 100644 index 0000000000..ddcf2d546f --- /dev/null +++ b/Spigot-Server-Patches/0051-Optimize-Pathfinding.patch @@ -0,0 +1,51 @@ +From 3cca34b5a315231f82eaf848a700b684e4263560 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/server/NavigationAbstract.java b/src/main/java/net/minecraft/server/NavigationAbstract.java +index 4f28b8819..43b2be505 100644 +--- a/src/main/java/net/minecraft/server/NavigationAbstract.java ++++ b/src/main/java/net/minecraft/server/NavigationAbstract.java +@@ -118,10 +118,26 @@ public abstract class NavigationAbstract { + } + + public boolean a(Entity entity, double d0) { ++ // Paper start - Pathfinding optimizations ++ if (this.pathfindFailures > 10 && this.c == null && MinecraftServer.currentTick < this.lastFailure + 40) { ++ return false; ++ } ++ + PathEntity pathentity = this.a(entity); + +- return pathentity != null && this.a(pathentity, d0); ++ if (pathentity != null && this.a(pathentity, d0)) { ++ this.lastFailure = 0; ++ this.pathfindFailures = 0; ++ return true; ++ } else { ++ this.pathfindFailures++; ++ this.lastFailure = MinecraftServer.currentTick; ++ return false; ++ } + } ++ private int lastFailure = 0; ++ private int pathfindFailures = 0; ++ // Paper end + + public boolean a(@Nullable PathEntity pathentity, double d0) { + if (pathentity == null) { +@@ -255,6 +271,7 @@ public abstract class NavigationAbstract { + } + + public void o() { ++ this.pathfindFailures = 0; this.lastFailure = 0; // Paper - Pathfinding optimizations + this.c = null; + } + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0052-Avoid-hopper-searches-if-there-are-no-items.patch b/Spigot-Server-Patches/0052-Avoid-hopper-searches-if-there-are-no-items.patch new file mode 100644 index 0000000000..cfa611bb17 --- /dev/null +++ b/Spigot-Server-Patches/0052-Avoid-hopper-searches-if-there-are-no-items.patch @@ -0,0 +1,99 @@ +From 0c1ce95af25b8c95b34c255e9c0a440d64a100d7 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/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java +index b80f95159..e1fc4ea6c 100644 +--- a/src/main/java/net/minecraft/server/Chunk.java ++++ b/src/main/java/net/minecraft/server/Chunk.java +@@ -47,6 +47,13 @@ public class Chunk { + public boolean d; + protected gnu.trove.map.hash.TObjectIntHashMap entityCount = new gnu.trove.map.hash.TObjectIntHashMap(); // Spigot + ++ // Paper start ++ // 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 ++ + // CraftBukkit start - Neighbor loaded cache for chunk lighting and entity ticking + private int neighbors = 0x1 << 12; + public long chunkKey; +@@ -618,6 +625,13 @@ public class Chunk { + entity.ac = k; + entity.ad = this.locZ; + this.entitySlices[k].add(entity); ++ // Paper start - update count ++ if (entity instanceof EntityItem) { ++ itemCounts[k]++; ++ } else if (entity instanceof IInventory) { ++ inventoryEntityCounts[k]++; ++ } ++ // Paper end + // Spigot start - increment creature type count + // Keep this synced up with World.a(Class) + if (entity instanceof EntityInsentient) { +@@ -650,6 +664,13 @@ public class Chunk { + } + + this.entitySlices[i].remove(entity); ++ // Paper start - update counts ++ if (entity instanceof EntityItem) { ++ itemCounts[i]--; ++ } else if (entity instanceof IInventory) { ++ inventoryEntityCounts[i]--; ++ } ++ // Paper end + // Spigot start - decrement creature type count + // Keep this synced up with World.a(Class) + if (entity instanceof EntityInsentient) { +@@ -841,6 +862,15 @@ public class Chunk { + if (!this.entitySlices[k].isEmpty()) { + Iterator iterator = this.entitySlices[k].iterator(); + ++ // 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.c` ++ * ++ * Make sure the inventory selector stays in sync. ++ * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` ++ */ ++ if (predicate == IEntitySelector.c && inventoryEntityCounts[k] <= 0) continue; ++ // Paper end + while (iterator.hasNext()) { + Entity entity1 = (Entity) iterator.next(); + +@@ -877,7 +907,18 @@ public class Chunk { + 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 + + while (iterator.hasNext()) { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0052-Optimize-Pathfinding.patch b/Spigot-Server-Patches/0052-Optimize-Pathfinding.patch deleted file mode 100644 index b9d1e3766c..0000000000 --- a/Spigot-Server-Patches/0052-Optimize-Pathfinding.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0a119adb2127be5db1c6efba9c6cfeeecc3926d4 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/server/NavigationAbstract.java b/src/main/java/net/minecraft/server/NavigationAbstract.java -index 4f28b8819..43b2be505 100644 ---- a/src/main/java/net/minecraft/server/NavigationAbstract.java -+++ b/src/main/java/net/minecraft/server/NavigationAbstract.java -@@ -118,10 +118,26 @@ public abstract class NavigationAbstract { - } - - public boolean a(Entity entity, double d0) { -+ // Paper start - Pathfinding optimizations -+ if (this.pathfindFailures > 10 && this.c == null && MinecraftServer.currentTick < this.lastFailure + 40) { -+ return false; -+ } -+ - PathEntity pathentity = this.a(entity); - -- return pathentity != null && this.a(pathentity, d0); -+ if (pathentity != null && this.a(pathentity, d0)) { -+ this.lastFailure = 0; -+ this.pathfindFailures = 0; -+ return true; -+ } else { -+ this.pathfindFailures++; -+ this.lastFailure = MinecraftServer.currentTick; -+ return false; -+ } - } -+ private int lastFailure = 0; -+ private int pathfindFailures = 0; -+ // Paper end - - public boolean a(@Nullable PathEntity pathentity, double d0) { - if (pathentity == null) { -@@ -255,6 +271,7 @@ public abstract class NavigationAbstract { - } - - public void o() { -+ this.pathfindFailures = 0; this.lastFailure = 0; // Paper - Pathfinding optimizations - this.c = null; - } - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0053-Avoid-hopper-searches-if-there-are-no-items.patch b/Spigot-Server-Patches/0053-Avoid-hopper-searches-if-there-are-no-items.patch deleted file mode 100644 index f823900a13..0000000000 --- a/Spigot-Server-Patches/0053-Avoid-hopper-searches-if-there-are-no-items.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 082fa781df2dfffd7b1774cfe10089544daa70a9 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/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java -index b80f95159..e1fc4ea6c 100644 ---- a/src/main/java/net/minecraft/server/Chunk.java -+++ b/src/main/java/net/minecraft/server/Chunk.java -@@ -47,6 +47,13 @@ public class Chunk { - public boolean d; - protected gnu.trove.map.hash.TObjectIntHashMap entityCount = new gnu.trove.map.hash.TObjectIntHashMap(); // Spigot - -+ // Paper start -+ // 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 -+ - // CraftBukkit start - Neighbor loaded cache for chunk lighting and entity ticking - private int neighbors = 0x1 << 12; - public long chunkKey; -@@ -618,6 +625,13 @@ public class Chunk { - entity.ac = k; - entity.ad = this.locZ; - this.entitySlices[k].add(entity); -+ // Paper start - update count -+ if (entity instanceof EntityItem) { -+ itemCounts[k]++; -+ } else if (entity instanceof IInventory) { -+ inventoryEntityCounts[k]++; -+ } -+ // Paper end - // Spigot start - increment creature type count - // Keep this synced up with World.a(Class) - if (entity instanceof EntityInsentient) { -@@ -650,6 +664,13 @@ public class Chunk { - } - - this.entitySlices[i].remove(entity); -+ // Paper start - update counts -+ if (entity instanceof EntityItem) { -+ itemCounts[i]--; -+ } else if (entity instanceof IInventory) { -+ inventoryEntityCounts[i]--; -+ } -+ // Paper end - // Spigot start - decrement creature type count - // Keep this synced up with World.a(Class) - if (entity instanceof EntityInsentient) { -@@ -841,6 +862,15 @@ public class Chunk { - if (!this.entitySlices[k].isEmpty()) { - Iterator iterator = this.entitySlices[k].iterator(); - -+ // 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.c` -+ * -+ * Make sure the inventory selector stays in sync. -+ * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` -+ */ -+ if (predicate == IEntitySelector.c && inventoryEntityCounts[k] <= 0) continue; -+ // Paper end - while (iterator.hasNext()) { - Entity entity1 = (Entity) iterator.next(); - -@@ -877,7 +907,18 @@ public class Chunk { - 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 - - while (iterator.hasNext()) { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0053-Expose-server-CommandMap.patch b/Spigot-Server-Patches/0053-Expose-server-CommandMap.patch new file mode 100644 index 0000000000..d6b7155d96 --- /dev/null +++ b/Spigot-Server-Patches/0053-Expose-server-CommandMap.patch @@ -0,0 +1,21 @@ +From bf934f8ce2b8aed42e8412904cf5bd84f5163e3d 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 5302bb283..cab671d68 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1567,6 +1567,7 @@ public final class CraftServer implements Server { + return helpMap; + } + ++ @Override // Paper - add override + public SimpleCommandMap getCommandMap() { + return commandMap; + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0054-Be-a-bit-more-informative-in-maxHealth-exception.patch b/Spigot-Server-Patches/0054-Be-a-bit-more-informative-in-maxHealth-exception.patch new file mode 100644 index 0000000000..017b794085 --- /dev/null +++ b/Spigot-Server-Patches/0054-Be-a-bit-more-informative-in-maxHealth-exception.patch @@ -0,0 +1,25 @@ +From a95f24eee446165a8c8006583b0de0f793c168da 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 27cd0d43d..61032eb2f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -96,7 +96,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.maxHealth).b() ++ + (this instanceof CraftPlayer ? ", player: " + this.getName() + ')' : ')')); + } + + if (health == 0) { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0054-Expose-server-CommandMap.patch b/Spigot-Server-Patches/0054-Expose-server-CommandMap.patch deleted file mode 100644 index 5a7623c480..0000000000 --- a/Spigot-Server-Patches/0054-Expose-server-CommandMap.patch +++ /dev/null @@ -1,21 +0,0 @@ -From ccbbc6329f8ab2240eabdc1e2eb4bdc5e3e29834 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 5302bb283..cab671d68 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1567,6 +1567,7 @@ public final class CraftServer implements Server { - return helpMap; - } - -+ @Override // Paper - add override - public SimpleCommandMap getCommandMap() { - return commandMap; - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0055-Be-a-bit-more-informative-in-maxHealth-exception.patch b/Spigot-Server-Patches/0055-Be-a-bit-more-informative-in-maxHealth-exception.patch deleted file mode 100644 index 7f322e5017..0000000000 --- a/Spigot-Server-Patches/0055-Be-a-bit-more-informative-in-maxHealth-exception.patch +++ /dev/null @@ -1,25 +0,0 @@ -From ae0cf0afb053eb18ce36346f330d8940c9f8aeea 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 27cd0d43d..61032eb2f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -96,7 +96,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.maxHealth).b() -+ + (this instanceof CraftPlayer ? ", player: " + this.getName() + ')' : ')')); - } - - if (health == 0) { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0055-Player-Tab-List-and-Title-APIs.patch b/Spigot-Server-Patches/0055-Player-Tab-List-and-Title-APIs.patch new file mode 100644 index 0000000000..7f09037aba --- /dev/null +++ b/Spigot-Server-Patches/0055-Player-Tab-List-and-Title-APIs.patch @@ -0,0 +1,179 @@ +From 1de05f6089976c4332bb594dfcae72d598747e42 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/server/PacketPlayOutPlayerListHeaderFooter.java b/src/main/java/net/minecraft/server/PacketPlayOutPlayerListHeaderFooter.java +index 5f5b3825d..242efb0b9 100644 +--- a/src/main/java/net/minecraft/server/PacketPlayOutPlayerListHeaderFooter.java ++++ b/src/main/java/net/minecraft/server/PacketPlayOutPlayerListHeaderFooter.java +@@ -4,6 +4,8 @@ import java.io.IOException; + + public class PacketPlayOutPlayerListHeaderFooter implements Packet { + ++ public net.md_5.bungee.api.chat.BaseComponent[] header, footer; // Paper ++ + private IChatBaseComponent a; + private IChatBaseComponent b; + +@@ -19,8 +21,19 @@ public class PacketPlayOutPlayerListHeaderFooter implements Packet { + private int d; + private int e; + ++ // 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 ++ + public PacketPlayOutTitle() {} + + public PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction packetplayouttitle_enumtitleaction, IChatBaseComponent ichatbasecomponent) { +@@ -47,7 +59,13 @@ 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) { +- packetdataserializer.a(this.b); ++ // Paper start ++ if (this.components != null) { ++ packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); ++ } else { ++ packetdataserializer.a(this.b); ++ } ++ // Paper end + } + + if (this.a == PacketPlayOutTitle.EnumTitleAction.TIMES) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index c86a48070..0df01186f 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; + import com.google.common.io.BaseEncoding; +@@ -158,6 +159,85 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + } + ++ // Paper start ++ @Override ++ public void setPlayerListHeaderFooter(BaseComponent[] header, BaseComponent[] footer) { ++ PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter(); ++ packet.header = header; ++ packet.footer = footer; ++ getHandle().playerConnection.sendPacket(packet); ++ } ++ ++ @Override ++ public void setPlayerListHeaderFooter(BaseComponent header, BaseComponent footer) { ++ this.setPlayerListHeaderFooter(header == null ? null : new BaseComponent[]{header}, ++ footer == null ? null : new BaseComponent[]{footer}); ++ } ++ ++ ++ @Override ++ public void setTitleTimes(int fadeInTicks, int stayTicks, int fadeOutTicks) { ++ getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.TIMES, (BaseComponent[]) null, fadeInTicks, stayTicks, fadeOutTicks)); ++ } ++ ++ @Override ++ public void setSubtitle(BaseComponent[] subtitle) { ++ getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.SUBTITLE, subtitle, 0, 0, 0)); ++ } ++ ++ @Override ++ public void setSubtitle(BaseComponent subtitle) { ++ setSubtitle(new BaseComponent[]{subtitle}); ++ } ++ ++ @Override ++ public void showTitle(BaseComponent[] title) { ++ getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.TITLE, title, 0, 0, 0)); ++ } ++ ++ @Override ++ public void showTitle(BaseComponent title) { ++ showTitle(new BaseComponent[]{title}); ++ } ++ ++ @Override ++ public void showTitle(BaseComponent[] title, BaseComponent[] subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks) { ++ setTitleTimes(fadeInTicks, stayTicks, fadeOutTicks); ++ setSubtitle(subtitle); ++ showTitle(title); ++ } ++ ++ @Override ++ public void showTitle(BaseComponent title, BaseComponent subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks) { ++ setTitleTimes(fadeInTicks, stayTicks, fadeOutTicks); ++ setSubtitle(subtitle); ++ showTitle(title); ++ } ++ ++ @Override ++ public void sendTitle(Title title) { ++ Preconditions.checkNotNull(title, "Title is null"); ++ setTitleTimes(title.getFadeIn(), title.getStay(), title.getFadeOut()); ++ setSubtitle(title.getSubtitle() == null ? new BaseComponent[0] : title.getSubtitle()); ++ showTitle(title.getTitle()); ++ } ++ ++ @Override ++ public void updateTitle(Title title) { ++ Preconditions.checkNotNull(title, "Title is null"); ++ setTitleTimes(title.getFadeIn(), title.getStay(), title.getFadeOut()); ++ if (title.getSubtitle() != null) { ++ setSubtitle(title.getSubtitle()); ++ } ++ showTitle(title.getTitle()); ++ } ++ ++ @Override ++ public void hideTitle() { ++ getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.CLEAR, (BaseComponent[]) null, 0, 0, 0)); ++ } ++ // Paper end ++ + @Override + public String getDisplayName() { + return getHandle().displayName; +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0056-Ensure-inv-drag-is-in-bounds.patch b/Spigot-Server-Patches/0056-Ensure-inv-drag-is-in-bounds.patch new file mode 100644 index 0000000000..e62f60a9ec --- /dev/null +++ b/Spigot-Server-Patches/0056-Ensure-inv-drag-is-in-bounds.patch @@ -0,0 +1,22 @@ +From 3a9666f74e085cef316955a628fb5dbd7c63c214 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/server/Container.java b/src/main/java/net/minecraft/server/Container.java +index 686250ea8..b826089d1 100644 +--- a/src/main/java/net/minecraft/server/Container.java ++++ b/src/main/java/net/minecraft/server/Container.java +@@ -141,7 +141,7 @@ public abstract class Container { + this.d(); + } + } else if (this.g == 1) { +- Slot slot = (Slot) this.c.get(i); ++ Slot slot = i < this.c.size() ? this.c.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.h.size()) && this.b(slot)) { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0056-Player-Tab-List-and-Title-APIs.patch b/Spigot-Server-Patches/0056-Player-Tab-List-and-Title-APIs.patch deleted file mode 100644 index b2b8d90a39..0000000000 --- a/Spigot-Server-Patches/0056-Player-Tab-List-and-Title-APIs.patch +++ /dev/null @@ -1,179 +0,0 @@ -From ca1b52f9e3a17711934151e7ff7a2af41d700320 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/server/PacketPlayOutPlayerListHeaderFooter.java b/src/main/java/net/minecraft/server/PacketPlayOutPlayerListHeaderFooter.java -index 5f5b3825d..242efb0b9 100644 ---- a/src/main/java/net/minecraft/server/PacketPlayOutPlayerListHeaderFooter.java -+++ b/src/main/java/net/minecraft/server/PacketPlayOutPlayerListHeaderFooter.java -@@ -4,6 +4,8 @@ import java.io.IOException; - - public class PacketPlayOutPlayerListHeaderFooter implements Packet { - -+ public net.md_5.bungee.api.chat.BaseComponent[] header, footer; // Paper -+ - private IChatBaseComponent a; - private IChatBaseComponent b; - -@@ -19,8 +21,19 @@ public class PacketPlayOutPlayerListHeaderFooter implements Packet { - private int d; - private int e; - -+ // 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 -+ - public PacketPlayOutTitle() {} - - public PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction packetplayouttitle_enumtitleaction, IChatBaseComponent ichatbasecomponent) { -@@ -47,7 +59,13 @@ 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) { -- packetdataserializer.a(this.b); -+ // Paper start -+ if (this.components != null) { -+ packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); -+ } else { -+ packetdataserializer.a(this.b); -+ } -+ // Paper end - } - - if (this.a == PacketPlayOutTitle.EnumTitleAction.TIMES) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 16dcaba3f..0e7086da3 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; - import com.google.common.io.BaseEncoding; -@@ -158,6 +159,85 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - } - -+ // Paper start -+ @Override -+ public void setPlayerListHeaderFooter(BaseComponent[] header, BaseComponent[] footer) { -+ PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter(); -+ packet.header = header; -+ packet.footer = footer; -+ getHandle().playerConnection.sendPacket(packet); -+ } -+ -+ @Override -+ public void setPlayerListHeaderFooter(BaseComponent header, BaseComponent footer) { -+ this.setPlayerListHeaderFooter(header == null ? null : new BaseComponent[]{header}, -+ footer == null ? null : new BaseComponent[]{footer}); -+ } -+ -+ -+ @Override -+ public void setTitleTimes(int fadeInTicks, int stayTicks, int fadeOutTicks) { -+ getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.TIMES, (BaseComponent[]) null, fadeInTicks, stayTicks, fadeOutTicks)); -+ } -+ -+ @Override -+ public void setSubtitle(BaseComponent[] subtitle) { -+ getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.SUBTITLE, subtitle, 0, 0, 0)); -+ } -+ -+ @Override -+ public void setSubtitle(BaseComponent subtitle) { -+ setSubtitle(new BaseComponent[]{subtitle}); -+ } -+ -+ @Override -+ public void showTitle(BaseComponent[] title) { -+ getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.TITLE, title, 0, 0, 0)); -+ } -+ -+ @Override -+ public void showTitle(BaseComponent title) { -+ showTitle(new BaseComponent[]{title}); -+ } -+ -+ @Override -+ public void showTitle(BaseComponent[] title, BaseComponent[] subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks) { -+ setTitleTimes(fadeInTicks, stayTicks, fadeOutTicks); -+ setSubtitle(subtitle); -+ showTitle(title); -+ } -+ -+ @Override -+ public void showTitle(BaseComponent title, BaseComponent subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks) { -+ setTitleTimes(fadeInTicks, stayTicks, fadeOutTicks); -+ setSubtitle(subtitle); -+ showTitle(title); -+ } -+ -+ @Override -+ public void sendTitle(Title title) { -+ Preconditions.checkNotNull(title, "Title is null"); -+ setTitleTimes(title.getFadeIn(), title.getStay(), title.getFadeOut()); -+ setSubtitle(title.getSubtitle() == null ? new BaseComponent[0] : title.getSubtitle()); -+ showTitle(title.getTitle()); -+ } -+ -+ @Override -+ public void updateTitle(Title title) { -+ Preconditions.checkNotNull(title, "Title is null"); -+ setTitleTimes(title.getFadeIn(), title.getStay(), title.getFadeOut()); -+ if (title.getSubtitle() != null) { -+ setSubtitle(title.getSubtitle()); -+ } -+ showTitle(title.getTitle()); -+ } -+ -+ @Override -+ public void hideTitle() { -+ getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.CLEAR, (BaseComponent[]) null, 0, 0, 0)); -+ } -+ // Paper end -+ - @Override - public String getDisplayName() { - return getHandle().displayName; --- -2.12.2 - diff --git a/Spigot-Server-Patches/0057-Change-implementation-of-tile-entity-removal-list.patch b/Spigot-Server-Patches/0057-Change-implementation-of-tile-entity-removal-list.patch new file mode 100644 index 0000000000..414cc51e04 --- /dev/null +++ b/Spigot-Server-Patches/0057-Change-implementation-of-tile-entity-removal-list.patch @@ -0,0 +1,88 @@ +From 19528dbbeee2a72cb791ff414a47e84fd9e30efb 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 + + +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 7feed2995..5b5e0e73c 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -121,10 +121,10 @@ public abstract class Entity implements ICommandListener { + private static final DataWatcherObject aB = DataWatcher.a(Entity.class, DataWatcherRegistry.h); + private static final DataWatcherObject aC = DataWatcher.a(Entity.class, DataWatcherRegistry.h); + private static final DataWatcherObject aD = DataWatcher.a(Entity.class, DataWatcherRegistry.h); +- public boolean aa; +- public int ab; +- public int ac; +- public int ad; ++ public boolean aa; public boolean isAddedToChunk() { return aa; } // Paper - OBFHELPER ++ public int ab; public int getChunkX() { return ab; } // Paper - OBFHELPER ++ public int ac; public int getChunkY() { return ac; } // Paper - OBFHELPER ++ public int ad; public int getChunkZ() { return ad; } // Paper - OBFHELPER + public boolean ah; + public boolean impulse; + public int portalCooldown; +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index a1cdcd71b..354a7309b 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -30,6 +30,11 @@ import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; + import org.bukkit.generator.ChunkGenerator; + // CraftBukkit end + ++// Paper start ++import java.util.Set; ++import com.google.common.collect.Sets; ++// Paper end ++ + public abstract class World implements IBlockAccess { + + private int a = 63; +@@ -60,11 +65,11 @@ public abstract class World implements IBlockAccess { + } + }; + // Spigot end +- protected final List f = Lists.newArrayList(); ++ protected final Set f = Sets.newHashSet(); // Paper + public final List tileEntityList = Lists.newArrayList(); + public final List tileEntityListTick = Lists.newArrayList(); + private final List b = Lists.newArrayList(); +- private final List tileEntityListUnload = Lists.newArrayList(); ++ private final Set tileEntityListUnload = Sets.newHashSet(); // Paper + public final List players = Lists.newArrayList(); + public final List j = Lists.newArrayList(); + protected final IntHashMap entitiesById = new IntHashMap(); +@@ -1394,20 +1399,20 @@ public abstract class World implements IBlockAccess { + this.entityList.removeAll(this.f); + + int j; ++ // Paper start - Set based removal lists ++ for (Entity e : this.f) { ++ j = e.getChunkZ(); ++ int k = e.getChunkX(); + +- for (i = 0; i < this.f.size(); ++i) { +- entity = (Entity) this.f.get(i); +- int k = entity.ab; +- +- j = entity.ad; +- if (entity.aa && this.isChunkLoaded(k, j, true)) { +- this.getChunkAt(k, j).b(entity); ++ if (e.isAddedToChunk() && this.isChunkLoaded(k, j, true)) { ++ this.getChunkAt(k, j).b(e); + } + } + +- for (i = 0; i < this.f.size(); ++i) { +- this.c((Entity) this.f.get(i)); ++ for (Entity e : this.f) { ++ this.c(e); + } ++ // Paper end + + this.f.clear(); + this.l(); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0057-Ensure-inv-drag-is-in-bounds.patch b/Spigot-Server-Patches/0057-Ensure-inv-drag-is-in-bounds.patch deleted file mode 100644 index b7fa50f524..0000000000 --- a/Spigot-Server-Patches/0057-Ensure-inv-drag-is-in-bounds.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 20d8fcc6f23ec8125341558bdf29c7dc015258b1 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/server/Container.java b/src/main/java/net/minecraft/server/Container.java -index 686250ea8..b826089d1 100644 ---- a/src/main/java/net/minecraft/server/Container.java -+++ b/src/main/java/net/minecraft/server/Container.java -@@ -141,7 +141,7 @@ public abstract class Container { - this.d(); - } - } else if (this.g == 1) { -- Slot slot = (Slot) this.c.get(i); -+ Slot slot = i < this.c.size() ? this.c.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.h.size()) && this.b(slot)) { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0058-Add-configurable-portal-search-radius.patch b/Spigot-Server-Patches/0058-Add-configurable-portal-search-radius.patch new file mode 100644 index 0000000000..330c2f1327 --- /dev/null +++ b/Spigot-Server-Patches/0058-Add-configurable-portal-search-radius.patch @@ -0,0 +1,58 @@ +From c7880597e2dfa64fde32529848c07aff78bad349 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 ab7e81a0d..4cc74cd65 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -234,4 +234,9 @@ public class PaperWorldConfig { + private void allChunksAreSlimeChunks() { + allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); + } ++ ++ public int portalSearchRadius; ++ private void portalSearchRadius() { ++ portalSearchRadius = getInt("portal-search-radius", 128); ++ } + } +diff --git a/src/main/java/net/minecraft/server/PortalTravelAgent.java b/src/main/java/net/minecraft/server/PortalTravelAgent.java +index 4455c2c43..fbf7cff24 100644 +--- a/src/main/java/net/minecraft/server/PortalTravelAgent.java ++++ b/src/main/java/net/minecraft/server/PortalTravelAgent.java +@@ -12,7 +12,7 @@ import org.bukkit.util.Vector; + + public class PortalTravelAgent { + +- private final WorldServer world; ++ protected final WorldServer world; // Paper - private -> protected + private final Random b; + private final Long2ObjectMap c = new Long2ObjectOpenHashMap(4096); + +@@ -92,7 +92,7 @@ public class PortalTravelAgent { + + public boolean b(Entity entity, float f) { + // CraftBukkit start - Modularize portal search process and entity teleportation +- BlockPosition found = this.findPortal(entity.locX, entity.locY, entity.locZ, 128); ++ BlockPosition found = this.findPortal(entity.locX, entity.locY, entity.locZ, world.paperConfig.portalSearchRadius); // Paper - Configurable search radius + if (found == null) { + return false; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftTravelAgent.java b/src/main/java/org/bukkit/craftbukkit/CraftTravelAgent.java +index 1d5dce10e..7ca2617a8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftTravelAgent.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftTravelAgent.java +@@ -11,7 +11,7 @@ public class CraftTravelAgent extends PortalTravelAgent implements TravelAgent { + + public static TravelAgent DEFAULT = null; + +- private int searchRadius = 128; ++ private int searchRadius = world.paperConfig.portalSearchRadius; // Paper - Configurable search radius + private int creationRadius = 16; + private boolean canCreatePortal = true; + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0058-Change-implementation-of-tile-entity-removal-list.patch b/Spigot-Server-Patches/0058-Change-implementation-of-tile-entity-removal-list.patch deleted file mode 100644 index 4db00e534a..0000000000 --- a/Spigot-Server-Patches/0058-Change-implementation-of-tile-entity-removal-list.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 87607d3f2bf2e768f4e192bd97576dd95fe3efd5 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 - - -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 7feed2995..5b5e0e73c 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -121,10 +121,10 @@ public abstract class Entity implements ICommandListener { - private static final DataWatcherObject aB = DataWatcher.a(Entity.class, DataWatcherRegistry.h); - private static final DataWatcherObject aC = DataWatcher.a(Entity.class, DataWatcherRegistry.h); - private static final DataWatcherObject aD = DataWatcher.a(Entity.class, DataWatcherRegistry.h); -- public boolean aa; -- public int ab; -- public int ac; -- public int ad; -+ public boolean aa; public boolean isAddedToChunk() { return aa; } // Paper - OBFHELPER -+ public int ab; public int getChunkX() { return ab; } // Paper - OBFHELPER -+ public int ac; public int getChunkY() { return ac; } // Paper - OBFHELPER -+ public int ad; public int getChunkZ() { return ad; } // Paper - OBFHELPER - public boolean ah; - public boolean impulse; - public int portalCooldown; -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index a1cdcd71b..354a7309b 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -30,6 +30,11 @@ import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; - import org.bukkit.generator.ChunkGenerator; - // CraftBukkit end - -+// Paper start -+import java.util.Set; -+import com.google.common.collect.Sets; -+// Paper end -+ - public abstract class World implements IBlockAccess { - - private int a = 63; -@@ -60,11 +65,11 @@ public abstract class World implements IBlockAccess { - } - }; - // Spigot end -- protected final List f = Lists.newArrayList(); -+ protected final Set f = Sets.newHashSet(); // Paper - public final List tileEntityList = Lists.newArrayList(); - public final List tileEntityListTick = Lists.newArrayList(); - private final List b = Lists.newArrayList(); -- private final List tileEntityListUnload = Lists.newArrayList(); -+ private final Set tileEntityListUnload = Sets.newHashSet(); // Paper - public final List players = Lists.newArrayList(); - public final List j = Lists.newArrayList(); - protected final IntHashMap entitiesById = new IntHashMap(); -@@ -1394,20 +1399,20 @@ public abstract class World implements IBlockAccess { - this.entityList.removeAll(this.f); - - int j; -+ // Paper start - Set based removal lists -+ for (Entity e : this.f) { -+ j = e.getChunkZ(); -+ int k = e.getChunkX(); - -- for (i = 0; i < this.f.size(); ++i) { -- entity = (Entity) this.f.get(i); -- int k = entity.ab; -- -- j = entity.ad; -- if (entity.aa && this.isChunkLoaded(k, j, true)) { -- this.getChunkAt(k, j).b(entity); -+ if (e.isAddedToChunk() && this.isChunkLoaded(k, j, true)) { -+ this.getChunkAt(k, j).b(e); - } - } - -- for (i = 0; i < this.f.size(); ++i) { -- this.c((Entity) this.f.get(i)); -+ for (Entity e : this.f) { -+ this.c(e); - } -+ // Paper end - - this.f.clear(); - this.l(); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0059-Add-configurable-portal-search-radius.patch b/Spigot-Server-Patches/0059-Add-configurable-portal-search-radius.patch deleted file mode 100644 index a447ec9c55..0000000000 --- a/Spigot-Server-Patches/0059-Add-configurable-portal-search-radius.patch +++ /dev/null @@ -1,58 +0,0 @@ -From d04bed0a2739870f17f68f432a430319d515e2d9 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 ab7e81a0d..4cc74cd65 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -234,4 +234,9 @@ public class PaperWorldConfig { - private void allChunksAreSlimeChunks() { - allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); - } -+ -+ public int portalSearchRadius; -+ private void portalSearchRadius() { -+ portalSearchRadius = getInt("portal-search-radius", 128); -+ } - } -diff --git a/src/main/java/net/minecraft/server/PortalTravelAgent.java b/src/main/java/net/minecraft/server/PortalTravelAgent.java -index 4455c2c43..fbf7cff24 100644 ---- a/src/main/java/net/minecraft/server/PortalTravelAgent.java -+++ b/src/main/java/net/minecraft/server/PortalTravelAgent.java -@@ -12,7 +12,7 @@ import org.bukkit.util.Vector; - - public class PortalTravelAgent { - -- private final WorldServer world; -+ protected final WorldServer world; // Paper - private -> protected - private final Random b; - private final Long2ObjectMap c = new Long2ObjectOpenHashMap(4096); - -@@ -92,7 +92,7 @@ public class PortalTravelAgent { - - public boolean b(Entity entity, float f) { - // CraftBukkit start - Modularize portal search process and entity teleportation -- BlockPosition found = this.findPortal(entity.locX, entity.locY, entity.locZ, 128); -+ BlockPosition found = this.findPortal(entity.locX, entity.locY, entity.locZ, world.paperConfig.portalSearchRadius); // Paper - Configurable search radius - if (found == null) { - return false; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftTravelAgent.java b/src/main/java/org/bukkit/craftbukkit/CraftTravelAgent.java -index 1d5dce10e..7ca2617a8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftTravelAgent.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftTravelAgent.java -@@ -11,7 +11,7 @@ public class CraftTravelAgent extends PortalTravelAgent implements TravelAgent { - - public static TravelAgent DEFAULT = null; - -- private int searchRadius = 128; -+ private int searchRadius = world.paperConfig.portalSearchRadius; // Paper - Configurable search radius - private int creationRadius = 16; - private boolean canCreatePortal = true; - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0059-Add-velocity-warnings.patch b/Spigot-Server-Patches/0059-Add-velocity-warnings.patch new file mode 100644 index 0000000000..5020c623b2 --- /dev/null +++ b/Spigot-Server-Patches/0059-Add-velocity-warnings.patch @@ -0,0 +1,62 @@ +From c310ea8c337901ad0bfa65949f78a0716a7fd0e0 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 cab671d68..28da39cbd 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -173,6 +173,7 @@ public final class CraftServer implements Server { + private final UUID invalidUserUUID = UUID.nameUUIDFromBytes("InvalidUsername".getBytes(Charsets.UTF_8)); + private final List playerView; + public int reloadCount; ++ public static Exception excessiveVelEx; // Paper - Velocity warnings + + private final class BooleanWrapper { + private boolean value = true; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 6497905b9..463289199 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -229,6 +229,11 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + } + + public void setVelocity(Vector vel) { ++ // Paper start - Warn server owners when plugins try to set super high velocities ++ if (!(this instanceof org.bukkit.entity.Projectile) && (vel.getX() > 4 || vel.getX() < -4 || vel.getY() > 4 || vel.getY() < -4 || vel.getZ() > 4 || vel.getZ() < -4)) { ++ CraftServer.excessiveVelEx = new Exception("Excessive velocity set detected: tried to set velocity of entity #" + getEntityId() + " to (" + vel.getX() + "," + vel.getY() + "," + vel.getZ() + ")."); ++ } ++ // Paper end + entity.motX = vel.getX(); + entity.motY = vel.getY(); + entity.motZ = vel.getZ(); +diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java +index 3ed983cc0..6384d50e7 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -66,7 +66,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.server.World.blockLocation); + } +- // ++ // 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!):" ); + dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().primaryThread.getId(), Integer.MAX_VALUE ), log ); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0060-Add-velocity-warnings.patch b/Spigot-Server-Patches/0060-Add-velocity-warnings.patch deleted file mode 100644 index c1c50dc052..0000000000 --- a/Spigot-Server-Patches/0060-Add-velocity-warnings.patch +++ /dev/null @@ -1,62 +0,0 @@ -From e5d75fd43f1e772df59e499fced596ef2eefdb25 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 cab671d68..28da39cbd 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -173,6 +173,7 @@ public final class CraftServer implements Server { - private final UUID invalidUserUUID = UUID.nameUUIDFromBytes("InvalidUsername".getBytes(Charsets.UTF_8)); - private final List playerView; - public int reloadCount; -+ public static Exception excessiveVelEx; // Paper - Velocity warnings - - private final class BooleanWrapper { - private boolean value = true; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 6497905b9..463289199 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -229,6 +229,11 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - } - - public void setVelocity(Vector vel) { -+ // Paper start - Warn server owners when plugins try to set super high velocities -+ if (!(this instanceof org.bukkit.entity.Projectile) && (vel.getX() > 4 || vel.getX() < -4 || vel.getY() > 4 || vel.getY() < -4 || vel.getZ() > 4 || vel.getZ() < -4)) { -+ CraftServer.excessiveVelEx = new Exception("Excessive velocity set detected: tried to set velocity of entity #" + getEntityId() + " to (" + vel.getX() + "," + vel.getY() + "," + vel.getZ() + ")."); -+ } -+ // Paper end - entity.motX = vel.getX(); - entity.motY = vel.getY(); - entity.motZ = vel.getZ(); -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 3ed983cc0..6384d50e7 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -66,7 +66,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.server.World.blockLocation); - } -- // -+ // 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!):" ); - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().primaryThread.getId(), Integer.MAX_VALUE ), log ); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0060-Fix-inter-world-teleportation-glitches.patch b/Spigot-Server-Patches/0060-Fix-inter-world-teleportation-glitches.patch new file mode 100644 index 0000000000..c116a19892 --- /dev/null +++ b/Spigot-Server-Patches/0060-Fix-inter-world-teleportation-glitches.patch @@ -0,0 +1,43 @@ +From c91c1828836d0c7465029ed20177dcb79f267005 Mon Sep 17 00:00:00 2001 +From: Sudzzy +Date: Thu, 3 Mar 2016 02:50:31 -0600 +Subject: [PATCH] Fix inter-world teleportation glitches + +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 4cc74cd65..fa49397ea 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -239,4 +239,9 @@ public class PaperWorldConfig { + private void portalSearchRadius() { + portalSearchRadius = getInt("portal-search-radius", 128); + } ++ ++ 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 0df01186f..88fcadbfd 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -579,7 +579,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + if (fromWorld == toWorld) { + entity.playerConnection.teleport(to); + } else { +- server.getHandle().moveToWorld(entity, toWorld.dimension, true, to, true); ++ // Paper - Configurable suffocation check ++ server.getHandle().moveToWorld(entity, toWorld.dimension, true, to, !toWorld.paperConfig.disableTeleportationSuffocationCheck); + } + return true; + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0061-Add-exception-reporting-event.patch b/Spigot-Server-Patches/0061-Add-exception-reporting-event.patch new file mode 100644 index 0000000000..46f17774c3 --- /dev/null +++ b/Spigot-Server-Patches/0061-Add-exception-reporting-event.patch @@ -0,0 +1,376 @@ +From cbc43c201ce24ad2ba92a6720ec15fade9c971ef 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 000000000..93397188b +--- /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; ++ } ++} +\ No newline at end of file +diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java +index e1fc4ea6c..8f1a68d67 100644 +--- a/src/main/java/net/minecraft/server/Chunk.java ++++ b/src/main/java/net/minecraft/server/Chunk.java +@@ -1,5 +1,6 @@ + package net.minecraft.server; + ++import com.destroystokyo.paper.exception.ServerInternalException; + import com.google.common.base.Predicate; + import com.google.common.collect.Maps; + import com.google.common.collect.Queues; +@@ -16,6 +17,7 @@ import org.apache.logging.log4j.Logger; + + import com.google.common.collect.Lists; // CraftBukkit + import org.bukkit.Server; // CraftBukkit ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; // Paper + + public class Chunk { + +@@ -757,10 +759,15 @@ public class Chunk { + this.tileEntities.remove(blockposition); + // Paper end + } else { +- System.out.println("Attempted to place a tile entity (" + tileentity + ") at " + tileentity.position.getX() + "," + tileentity.position.getY() + "," + tileentity.position.getZ() +- + " (" + org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(getBlockData(blockposition).getBlock()) + ") where there was no entity tile!"); +- System.out.println("Chunk coordinates: " + (this.locX * 16) + "," + (this.locZ * 16)); +- new Exception().printStackTrace(); ++ // Paper start ++ ServerInternalException e = new ServerInternalException( ++ "Attempted to place a tile entity (" + tileentity + ") at " + tileentity.position.getX() + "," ++ + tileentity.position.getY() + "," + tileentity.position.getZ() ++ + " (" + CraftMagicNumbers.getMaterial(getBlockData(blockposition).getBlock()) + ") where there was no entity tile!\n" + ++ "Chunk coordinates: " + (this.locX * 16) + "," + (this.locZ * 16)); ++ e.printStackTrace(); ++ ServerInternalException.reportInternalException(e); ++ // Paper end + // CraftBukkit end + } + } +diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java +index fab36ec15..0ad57afba 100644 +--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java +@@ -12,6 +12,7 @@ import java.util.Iterator; + import java.util.List; + import java.util.Set; + import javax.annotation.Nullable; ++import com.destroystokyo.paper.exception.ServerInternalException; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + +@@ -189,7 +190,11 @@ public class ChunkProviderServer implements IChunkProvider { + + return chunk; + } catch (Exception exception) { +- ChunkProviderServer.a.error("Couldn\'t load chunk", exception); ++ // Paper start ++ String msg = "Couldn\'t load chunk"; ++ ChunkProviderServer.a.error(msg, exception); ++ ServerInternalException.reportInternalException(exception); ++ // Paper end + return null; + } + } +@@ -198,7 +203,11 @@ public class ChunkProviderServer implements IChunkProvider { + try (co.aikar.timings.Timing timed = world.timings.chunkSaveNop.startTiming()) { + this.chunkLoader.b(this.world, chunk); + } catch (Exception exception) { +- ChunkProviderServer.a.error("Couldn\'t save entities", exception); ++ // Paper start ++ String msg = "Couldn\'t save entities"; ++ ChunkProviderServer.a.error(msg, exception); ++ ServerInternalException.reportInternalException(exception); ++ // Paper end + } + + } +@@ -208,9 +217,14 @@ public class ChunkProviderServer implements IChunkProvider { + chunk.setLastSaved(this.world.getTime()); + this.chunkLoader.a(this.world, chunk); + } catch (IOException ioexception) { +- ChunkProviderServer.a.error("Couldn\'t save chunk", ioexception); ++ // Paper start ++ String msg = "Couldn\'t save chunk"; ++ ChunkProviderServer.a.error(msg, ioexception); ++ ServerInternalException.reportInternalException(ioexception); + } catch (ExceptionWorldConflict exceptionworldconflict) { +- ChunkProviderServer.a.error("Couldn\'t save chunk; already in use by another instance of Minecraft?", exceptionworldconflict); ++ String msg = "Couldn\'t save chunk; already in use by another instance of Minecraft?"; ++ ChunkProviderServer.a.error(msg, exceptionworldconflict); ++ ServerInternalException.reportInternalException(exceptionworldconflict); + } + + } +diff --git a/src/main/java/net/minecraft/server/NameReferencingFileConverter.java b/src/main/java/net/minecraft/server/NameReferencingFileConverter.java +index 016c64e82..2ff8a6da0 100644 +--- a/src/main/java/net/minecraft/server/NameReferencingFileConverter.java ++++ b/src/main/java/net/minecraft/server/NameReferencingFileConverter.java +@@ -1,5 +1,6 @@ + package net.minecraft.server; + ++import com.destroystokyo.paper.exception.ServerInternalException; + import com.google.common.base.Charsets; + import com.google.common.base.Predicate; + import com.google.common.collect.Iterators; +@@ -361,6 +362,7 @@ public class NameReferencingFileConverter { + root = NBTCompressedStreamTools.a(new java.io.FileInputStream(file1)); + } catch (Exception exception) { + exception.printStackTrace(); ++ ServerInternalException.reportInternalException(exception); // Paper + } + + if (root != null) { +@@ -374,6 +376,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/server/PersistentCollection.java b/src/main/java/net/minecraft/server/PersistentCollection.java +index 936d6c640..50056f49a 100644 +--- a/src/main/java/net/minecraft/server/PersistentCollection.java ++++ b/src/main/java/net/minecraft/server/PersistentCollection.java +@@ -1,5 +1,6 @@ + package net.minecraft.server; + ++import com.destroystokyo.paper.exception.ServerInternalException; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import java.io.DataInputStream; +@@ -53,6 +54,7 @@ public class PersistentCollection { + } + } catch (Exception exception1) { + exception1.printStackTrace(); ++ ServerInternalException.reportInternalException(exception1); // Paper + } + } + +@@ -102,6 +104,7 @@ public class PersistentCollection { + } + } catch (Exception exception) { + exception.printStackTrace(); ++ ServerInternalException.reportInternalException(exception); // Paper + } + + } +diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java +index 8d1b65885..5f9678aad 100644 +--- a/src/main/java/net/minecraft/server/RegionFile.java ++++ b/src/main/java/net/minecraft/server/RegionFile.java +@@ -1,5 +1,6 @@ + package net.minecraft.server; + ++import com.destroystokyo.paper.exception.ServerInternalException; + import com.google.common.collect.Lists; + import java.io.BufferedInputStream; + import java.io.BufferedOutputStream; +@@ -82,6 +83,7 @@ public class RegionFile { + } + } catch (IOException ioexception) { + ioexception.printStackTrace(); ++ ServerInternalException.reportInternalException(ioexception); // Paper + } + + } +@@ -209,6 +211,7 @@ public class RegionFile { + this.b(i, j, (int) (MinecraftServer.aw() / 1000L)); + } catch (IOException ioexception) { + ioexception.printStackTrace(); ++ ServerInternalException.reportInternalException(ioexception); // Paper + } + + } +diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java +index 6ec72689c..02b9bc8df 100644 +--- a/src/main/java/net/minecraft/server/RegionFileCache.java ++++ b/src/main/java/net/minecraft/server/RegionFileCache.java +@@ -1,5 +1,6 @@ + package net.minecraft.server; + ++import com.destroystokyo.paper.exception.ServerInternalException; + import com.google.common.collect.Maps; + import java.io.DataInputStream; + import java.io.DataOutputStream; +@@ -68,6 +69,7 @@ public class RegionFileCache { + } + } catch (IOException ioexception) { + ioexception.printStackTrace(); ++ ServerInternalException.reportInternalException(ioexception); // Paper + } + } + +diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java +index e42a0c776..c79fb7d57 100644 +--- a/src/main/java/net/minecraft/server/SpawnerCreature.java ++++ b/src/main/java/net/minecraft/server/SpawnerCreature.java +@@ -7,6 +7,7 @@ import java.util.Random; + import java.util.Set; + + // CraftBukkit start ++import com.destroystokyo.paper.exception.ServerInternalException; + import org.bukkit.craftbukkit.util.LongHash; + import org.bukkit.craftbukkit.util.LongHashSet; + import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; +@@ -177,6 +178,7 @@ public final class SpawnerCreature { + entityinsentient = (EntityInsentient) biomebase_biomemeta.b.getConstructor(new Class[] { World.class}).newInstance(new Object[] { worldserver}); + } catch (Exception exception) { + exception.printStackTrace(); ++ ServerInternalException.reportInternalException(exception); // Paper + return j1; + } + +@@ -288,6 +290,7 @@ public final class SpawnerCreature { + entityinsentient = (EntityInsentient) biomebase_biomemeta.b.getConstructor(new Class[] { World.class}).newInstance(new Object[] { world}); + } catch (Exception exception) { + exception.printStackTrace(); ++ ServerInternalException.reportInternalException(exception); // Paper + continue; + } + +diff --git a/src/main/java/net/minecraft/server/VillageSiege.java b/src/main/java/net/minecraft/server/VillageSiege.java +index 7af5b7dd7..2b498024c 100644 +--- a/src/main/java/net/minecraft/server/VillageSiege.java ++++ b/src/main/java/net/minecraft/server/VillageSiege.java +@@ -1,5 +1,7 @@ + package net.minecraft.server; + ++import com.destroystokyo.paper.exception.ServerInternalException; ++ + import java.util.Iterator; + import java.util.List; + import javax.annotation.Nullable; +@@ -136,6 +138,7 @@ public class VillageSiege { + entityzombie.prepare(this.a.D(new BlockPosition(entityzombie)), (GroupDataEntity) null); + } catch (Exception exception) { + exception.printStackTrace(); ++ ServerInternalException.reportInternalException(exception); // Paper + return false; + } + +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 354a7309b..cc7369e52 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -1,5 +1,7 @@ + package net.minecraft.server; + ++import com.destroystokyo.paper.event.server.ServerExceptionEvent; ++import com.destroystokyo.paper.exception.ServerInternalException; + import com.google.common.base.Function; + import com.google.common.base.Objects; + import com.google.common.base.Predicate; +@@ -1454,8 +1456,10 @@ public abstract class World implements IBlockAccess { + } catch (Throwable throwable1) { + entity.tickTimer.stopTiming(); + // 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); + throwable1.printStackTrace(); ++ getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable1))); + entity.dead = true; + continue; + // Paper end +@@ -1520,8 +1524,10 @@ public abstract class World implements IBlockAccess { + this.methodProfiler.b(); + } catch (Throwable throwable2) { + // 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.world.getWorld().getName() + ":" + tileentity.position.getX() + "," + tileentity.position.getY() + "," + tileentity.position.getZ(); ++ System.err.println(msg); + throwable2.printStackTrace(); ++ getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable2))); + tilesThisCycle--; + this.tileEntityListTick.remove(tileTickPosition--); + continue; +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index 9952b64be..e30cfb7b7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -15,6 +15,9 @@ import java.util.concurrent.atomic.AtomicReference; + import java.util.logging.Level; + + import co.aikar.timings.MinecraftTimings; // Paper ++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; +@@ -352,18 +355,24 @@ public class CraftScheduler implements BukkitScheduler { + try { + task.run(); + } catch (final Throwable throwable) { ++ // Paper start ++ String msg = String.format( ++ "Task #%s for %s generated an exception", ++ task.getTaskId(), ++ task.getOwner().getDescription().getFullName()); + task.getOwner().getLogger().log( + Level.WARNING, +- String.format( +- "Task #%s for %s generated an exception", +- task.getTaskId(), +- task.getOwner().getDescription().getFullName()), ++ msg, + throwable); ++ task.getOwner().getServer().getPluginManager().callEvent( ++ new ServerExceptionEvent(new ServerSchedulerException(msg, throwable, task)) ++ ); ++ // Paper end + } + 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) + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0061-Fix-inter-world-teleportation-glitches.patch b/Spigot-Server-Patches/0061-Fix-inter-world-teleportation-glitches.patch deleted file mode 100644 index b44d2936d1..0000000000 --- a/Spigot-Server-Patches/0061-Fix-inter-world-teleportation-glitches.patch +++ /dev/null @@ -1,43 +0,0 @@ -From fa4d2110a0ca3cc431097ca324b6e370212f8ac4 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Thu, 3 Mar 2016 02:50:31 -0600 -Subject: [PATCH] Fix inter-world teleportation glitches - -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 4cc74cd65..fa49397ea 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -239,4 +239,9 @@ public class PaperWorldConfig { - private void portalSearchRadius() { - portalSearchRadius = getInt("portal-search-radius", 128); - } -+ -+ 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 0e7086da3..d72ff0af2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -579,7 +579,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - if (fromWorld == toWorld) { - entity.playerConnection.teleport(to); - } else { -- server.getHandle().moveToWorld(entity, toWorld.dimension, true, to, true); -+ // Paper - Configurable suffocation check -+ server.getHandle().moveToWorld(entity, toWorld.dimension, true, to, !toWorld.paperConfig.disableTeleportationSuffocationCheck); - } - return true; - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0062-Add-exception-reporting-event.patch b/Spigot-Server-Patches/0062-Add-exception-reporting-event.patch deleted file mode 100644 index fd0948cde5..0000000000 --- a/Spigot-Server-Patches/0062-Add-exception-reporting-event.patch +++ /dev/null @@ -1,376 +0,0 @@ -From 810379dfd7052f869995fd68b8e139a640b10899 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 000000000..93397188b ---- /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; -+ } -+} -\ No newline at end of file -diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java -index e1fc4ea6c..8f1a68d67 100644 ---- a/src/main/java/net/minecraft/server/Chunk.java -+++ b/src/main/java/net/minecraft/server/Chunk.java -@@ -1,5 +1,6 @@ - package net.minecraft.server; - -+import com.destroystokyo.paper.exception.ServerInternalException; - import com.google.common.base.Predicate; - import com.google.common.collect.Maps; - import com.google.common.collect.Queues; -@@ -16,6 +17,7 @@ import org.apache.logging.log4j.Logger; - - import com.google.common.collect.Lists; // CraftBukkit - import org.bukkit.Server; // CraftBukkit -+import org.bukkit.craftbukkit.util.CraftMagicNumbers; // Paper - - public class Chunk { - -@@ -757,10 +759,15 @@ public class Chunk { - this.tileEntities.remove(blockposition); - // Paper end - } else { -- System.out.println("Attempted to place a tile entity (" + tileentity + ") at " + tileentity.position.getX() + "," + tileentity.position.getY() + "," + tileentity.position.getZ() -- + " (" + org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(getBlockData(blockposition).getBlock()) + ") where there was no entity tile!"); -- System.out.println("Chunk coordinates: " + (this.locX * 16) + "," + (this.locZ * 16)); -- new Exception().printStackTrace(); -+ // Paper start -+ ServerInternalException e = new ServerInternalException( -+ "Attempted to place a tile entity (" + tileentity + ") at " + tileentity.position.getX() + "," -+ + tileentity.position.getY() + "," + tileentity.position.getZ() -+ + " (" + CraftMagicNumbers.getMaterial(getBlockData(blockposition).getBlock()) + ") where there was no entity tile!\n" + -+ "Chunk coordinates: " + (this.locX * 16) + "," + (this.locZ * 16)); -+ e.printStackTrace(); -+ ServerInternalException.reportInternalException(e); -+ // Paper end - // CraftBukkit end - } - } -diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java -index fab36ec15..0ad57afba 100644 ---- a/src/main/java/net/minecraft/server/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java -@@ -12,6 +12,7 @@ import java.util.Iterator; - import java.util.List; - import java.util.Set; - import javax.annotation.Nullable; -+import com.destroystokyo.paper.exception.ServerInternalException; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - -@@ -189,7 +190,11 @@ public class ChunkProviderServer implements IChunkProvider { - - return chunk; - } catch (Exception exception) { -- ChunkProviderServer.a.error("Couldn\'t load chunk", exception); -+ // Paper start -+ String msg = "Couldn\'t load chunk"; -+ ChunkProviderServer.a.error(msg, exception); -+ ServerInternalException.reportInternalException(exception); -+ // Paper end - return null; - } - } -@@ -198,7 +203,11 @@ public class ChunkProviderServer implements IChunkProvider { - try (co.aikar.timings.Timing timed = world.timings.chunkSaveNop.startTiming()) { - this.chunkLoader.b(this.world, chunk); - } catch (Exception exception) { -- ChunkProviderServer.a.error("Couldn\'t save entities", exception); -+ // Paper start -+ String msg = "Couldn\'t save entities"; -+ ChunkProviderServer.a.error(msg, exception); -+ ServerInternalException.reportInternalException(exception); -+ // Paper end - } - - } -@@ -208,9 +217,14 @@ public class ChunkProviderServer implements IChunkProvider { - chunk.setLastSaved(this.world.getTime()); - this.chunkLoader.a(this.world, chunk); - } catch (IOException ioexception) { -- ChunkProviderServer.a.error("Couldn\'t save chunk", ioexception); -+ // Paper start -+ String msg = "Couldn\'t save chunk"; -+ ChunkProviderServer.a.error(msg, ioexception); -+ ServerInternalException.reportInternalException(ioexception); - } catch (ExceptionWorldConflict exceptionworldconflict) { -- ChunkProviderServer.a.error("Couldn\'t save chunk; already in use by another instance of Minecraft?", exceptionworldconflict); -+ String msg = "Couldn\'t save chunk; already in use by another instance of Minecraft?"; -+ ChunkProviderServer.a.error(msg, exceptionworldconflict); -+ ServerInternalException.reportInternalException(exceptionworldconflict); - } - - } -diff --git a/src/main/java/net/minecraft/server/NameReferencingFileConverter.java b/src/main/java/net/minecraft/server/NameReferencingFileConverter.java -index 016c64e82..2ff8a6da0 100644 ---- a/src/main/java/net/minecraft/server/NameReferencingFileConverter.java -+++ b/src/main/java/net/minecraft/server/NameReferencingFileConverter.java -@@ -1,5 +1,6 @@ - package net.minecraft.server; - -+import com.destroystokyo.paper.exception.ServerInternalException; - import com.google.common.base.Charsets; - import com.google.common.base.Predicate; - import com.google.common.collect.Iterators; -@@ -361,6 +362,7 @@ public class NameReferencingFileConverter { - root = NBTCompressedStreamTools.a(new java.io.FileInputStream(file1)); - } catch (Exception exception) { - exception.printStackTrace(); -+ ServerInternalException.reportInternalException(exception); // Paper - } - - if (root != null) { -@@ -374,6 +376,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/server/PersistentCollection.java b/src/main/java/net/minecraft/server/PersistentCollection.java -index 936d6c640..50056f49a 100644 ---- a/src/main/java/net/minecraft/server/PersistentCollection.java -+++ b/src/main/java/net/minecraft/server/PersistentCollection.java -@@ -1,5 +1,6 @@ - package net.minecraft.server; - -+import com.destroystokyo.paper.exception.ServerInternalException; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import java.io.DataInputStream; -@@ -53,6 +54,7 @@ public class PersistentCollection { - } - } catch (Exception exception1) { - exception1.printStackTrace(); -+ ServerInternalException.reportInternalException(exception1); // Paper - } - } - -@@ -102,6 +104,7 @@ public class PersistentCollection { - } - } catch (Exception exception) { - exception.printStackTrace(); -+ ServerInternalException.reportInternalException(exception); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java -index 8d1b65885..5f9678aad 100644 ---- a/src/main/java/net/minecraft/server/RegionFile.java -+++ b/src/main/java/net/minecraft/server/RegionFile.java -@@ -1,5 +1,6 @@ - package net.minecraft.server; - -+import com.destroystokyo.paper.exception.ServerInternalException; - import com.google.common.collect.Lists; - import java.io.BufferedInputStream; - import java.io.BufferedOutputStream; -@@ -82,6 +83,7 @@ public class RegionFile { - } - } catch (IOException ioexception) { - ioexception.printStackTrace(); -+ ServerInternalException.reportInternalException(ioexception); // Paper - } - - } -@@ -209,6 +211,7 @@ public class RegionFile { - this.b(i, j, (int) (MinecraftServer.aw() / 1000L)); - } catch (IOException ioexception) { - ioexception.printStackTrace(); -+ ServerInternalException.reportInternalException(ioexception); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java -index 0163a4e59..57d6443cd 100644 ---- a/src/main/java/net/minecraft/server/RegionFileCache.java -+++ b/src/main/java/net/minecraft/server/RegionFileCache.java -@@ -1,5 +1,6 @@ - package net.minecraft.server; - -+import com.destroystokyo.paper.exception.ServerInternalException; - import com.google.common.collect.Maps; - import java.io.DataInputStream; - import java.io.DataOutputStream; -@@ -75,6 +76,7 @@ public class RegionFileCache { - } - } catch (IOException ioexception) { - ioexception.printStackTrace(); -+ ServerInternalException.reportInternalException(ioexception); // Paper - } - } - -diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java -index e42a0c776..c79fb7d57 100644 ---- a/src/main/java/net/minecraft/server/SpawnerCreature.java -+++ b/src/main/java/net/minecraft/server/SpawnerCreature.java -@@ -7,6 +7,7 @@ import java.util.Random; - import java.util.Set; - - // CraftBukkit start -+import com.destroystokyo.paper.exception.ServerInternalException; - import org.bukkit.craftbukkit.util.LongHash; - import org.bukkit.craftbukkit.util.LongHashSet; - import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; -@@ -177,6 +178,7 @@ public final class SpawnerCreature { - entityinsentient = (EntityInsentient) biomebase_biomemeta.b.getConstructor(new Class[] { World.class}).newInstance(new Object[] { worldserver}); - } catch (Exception exception) { - exception.printStackTrace(); -+ ServerInternalException.reportInternalException(exception); // Paper - return j1; - } - -@@ -288,6 +290,7 @@ public final class SpawnerCreature { - entityinsentient = (EntityInsentient) biomebase_biomemeta.b.getConstructor(new Class[] { World.class}).newInstance(new Object[] { world}); - } catch (Exception exception) { - exception.printStackTrace(); -+ ServerInternalException.reportInternalException(exception); // Paper - continue; - } - -diff --git a/src/main/java/net/minecraft/server/VillageSiege.java b/src/main/java/net/minecraft/server/VillageSiege.java -index 7af5b7dd7..2b498024c 100644 ---- a/src/main/java/net/minecraft/server/VillageSiege.java -+++ b/src/main/java/net/minecraft/server/VillageSiege.java -@@ -1,5 +1,7 @@ - package net.minecraft.server; - -+import com.destroystokyo.paper.exception.ServerInternalException; -+ - import java.util.Iterator; - import java.util.List; - import javax.annotation.Nullable; -@@ -136,6 +138,7 @@ public class VillageSiege { - entityzombie.prepare(this.a.D(new BlockPosition(entityzombie)), (GroupDataEntity) null); - } catch (Exception exception) { - exception.printStackTrace(); -+ ServerInternalException.reportInternalException(exception); // Paper - return false; - } - -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 354a7309b..cc7369e52 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -1,5 +1,7 @@ - package net.minecraft.server; - -+import com.destroystokyo.paper.event.server.ServerExceptionEvent; -+import com.destroystokyo.paper.exception.ServerInternalException; - import com.google.common.base.Function; - import com.google.common.base.Objects; - import com.google.common.base.Predicate; -@@ -1454,8 +1456,10 @@ public abstract class World implements IBlockAccess { - } catch (Throwable throwable1) { - entity.tickTimer.stopTiming(); - // 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); - throwable1.printStackTrace(); -+ getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable1))); - entity.dead = true; - continue; - // Paper end -@@ -1520,8 +1524,10 @@ public abstract class World implements IBlockAccess { - this.methodProfiler.b(); - } catch (Throwable throwable2) { - // 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.world.getWorld().getName() + ":" + tileentity.position.getX() + "," + tileentity.position.getY() + "," + tileentity.position.getZ(); -+ System.err.println(msg); - throwable2.printStackTrace(); -+ getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable2))); - tilesThisCycle--; - this.tileEntityListTick.remove(tileTickPosition--); - continue; -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 9952b64be..e30cfb7b7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -15,6 +15,9 @@ import java.util.concurrent.atomic.AtomicReference; - import java.util.logging.Level; - - import co.aikar.timings.MinecraftTimings; // Paper -+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; -@@ -352,18 +355,24 @@ public class CraftScheduler implements BukkitScheduler { - try { - task.run(); - } catch (final Throwable throwable) { -+ // Paper start -+ String msg = String.format( -+ "Task #%s for %s generated an exception", -+ task.getTaskId(), -+ task.getOwner().getDescription().getFullName()); - task.getOwner().getLogger().log( - Level.WARNING, -- String.format( -- "Task #%s for %s generated an exception", -- task.getTaskId(), -- task.getOwner().getDescription().getFullName()), -+ msg, - throwable); -+ task.getOwner().getServer().getPluginManager().callEvent( -+ new ServerExceptionEvent(new ServerSchedulerException(msg, throwable, task)) -+ ); -+ // Paper end - } - 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) - } --- -2.12.2.windows.2 - diff --git a/Spigot-Server-Patches/0062-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch b/Spigot-Server-Patches/0062-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch new file mode 100644 index 0000000000..31cf9f47b7 --- /dev/null +++ b/Spigot-Server-Patches/0062-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch @@ -0,0 +1,30 @@ +From 517b94fca16325f04702e129596f9d9f1fa4a50a 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/server/PacketPlayOutChat.java b/src/main/java/net/minecraft/server/PacketPlayOutChat.java +index 9fc83c4a3..b3b13ba11 100644 +--- a/src/main/java/net/minecraft/server/PacketPlayOutChat.java ++++ b/src/main/java/net/minecraft/server/PacketPlayOutChat.java +@@ -27,7 +27,14 @@ public class PacketPlayOutChat implements Packet { + public void b(PacketDataSerializer packetdataserializer) throws IOException { + // 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); + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0063-Disable-Scoreboards-for-non-players-by-default.patch b/Spigot-Server-Patches/0063-Disable-Scoreboards-for-non-players-by-default.patch new file mode 100644 index 0000000000..4e8c04d389 --- /dev/null +++ b/Spigot-Server-Patches/0063-Disable-Scoreboards-for-non-players-by-default.patch @@ -0,0 +1,53 @@ +From 60f5daf8819357295a0fe9cbf2c9e6eaed5832d3 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 fa49397ea..9987a5c7a 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -244,4 +244,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/server/CommandScoreboard.java b/src/main/java/net/minecraft/server/CommandScoreboard.java +index 7af5d0aef..ab9aa132a 100644 +--- a/src/main/java/net/minecraft/server/CommandScoreboard.java ++++ b/src/main/java/net/minecraft/server/CommandScoreboard.java +@@ -492,6 +492,7 @@ public class CommandScoreboard extends CommandAbstract { + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); ++ if (!entity.world.paperConfig.nonPlayerEntitiesOnScoreboards && !(entity instanceof EntityHuman)) { continue; } // Paper + String s2 = e(minecraftserver, icommandlistener, entity.bf()); + + if (scoreboard.addPlayerToTeam(s2, s)) { +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 5b5e0e73c..be54c807b 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -2047,6 +2047,7 @@ public abstract class Entity implements ICommandListener { + + @Nullable + public ScoreboardTeamBase aQ() { ++ if (!this.world.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof EntityHuman)) { return null; } // Paper + return this.world.getScoreboard().getPlayerTeam(this.bf()); + } + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0063-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch b/Spigot-Server-Patches/0063-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch deleted file mode 100644 index 84291798bc..0000000000 --- a/Spigot-Server-Patches/0063-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 7c5e2edf7bd7a935b905f4ddd48137c861634f8d 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/server/PacketPlayOutChat.java b/src/main/java/net/minecraft/server/PacketPlayOutChat.java -index 9fc83c4a3..b3b13ba11 100644 ---- a/src/main/java/net/minecraft/server/PacketPlayOutChat.java -+++ b/src/main/java/net/minecraft/server/PacketPlayOutChat.java -@@ -27,7 +27,14 @@ public class PacketPlayOutChat implements Packet { - public void b(PacketDataSerializer packetdataserializer) throws IOException { - // 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); - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0064-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/Spigot-Server-Patches/0064-Add-methods-for-working-with-arrows-stuck-in-living-.patch new file mode 100644 index 0000000000..e570c71530 --- /dev/null +++ b/Spigot-Server-Patches/0064-Add-methods-for-working-with-arrows-stuck-in-living-.patch @@ -0,0 +1,47 @@ +From b8425c39d7e6296671d9ddc5862172ab9da70d57 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/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java +index e5fa1c3ba..247224117 100644 +--- a/src/main/java/net/minecraft/server/EntityLiving.java ++++ b/src/main/java/net/minecraft/server/EntityLiving.java +@@ -1380,10 +1380,12 @@ public abstract class EntityLiving extends Entity { + return (float) this.getAttributeInstance(GenericAttributes.maxHealth).getValue(); + } + ++ public final int getStuckArrows() { return this.cc(); } // Paper - OBFHELPER + public final int cc() { + return ((Integer) this.datawatcher.get(EntityLiving.bq)).intValue(); + } + ++ public final void setStuckArrows(int arrows) { this.f(arrows); } // Paper - OBFHELPER + public final void f(int i) { + this.datawatcher.set(EntityLiving.bq, Integer.valueOf(i)); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 61032eb2f..348a8c758 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -572,4 +572,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + public boolean isCollidable() { + return getHandle().collides; + } ++ ++ // Paper start ++ @Override ++ public int getArrowsStuck() { ++ return this.getHandle().getStuckArrows(); ++ } ++ ++ @Override ++ public void setArrowsStuck(int arrows) { ++ this.getHandle().setStuckArrows(arrows); ++ } ++ // Paper end + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0064-Disable-Scoreboards-for-non-players-by-default.patch b/Spigot-Server-Patches/0064-Disable-Scoreboards-for-non-players-by-default.patch deleted file mode 100644 index b52b4590f6..0000000000 --- a/Spigot-Server-Patches/0064-Disable-Scoreboards-for-non-players-by-default.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 94c3548d2ce0fa0ab60e04d21caf2c842eca3df3 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 fa49397ea..9987a5c7a 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -244,4 +244,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/server/CommandScoreboard.java b/src/main/java/net/minecraft/server/CommandScoreboard.java -index 7af5d0aef..ab9aa132a 100644 ---- a/src/main/java/net/minecraft/server/CommandScoreboard.java -+++ b/src/main/java/net/minecraft/server/CommandScoreboard.java -@@ -492,6 +492,7 @@ public class CommandScoreboard extends CommandAbstract { - - while (iterator.hasNext()) { - Entity entity = (Entity) iterator.next(); -+ if (!entity.world.paperConfig.nonPlayerEntitiesOnScoreboards && !(entity instanceof EntityHuman)) { continue; } // Paper - String s2 = e(minecraftserver, icommandlistener, entity.bf()); - - if (scoreboard.addPlayerToTeam(s2, s)) { -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 5b5e0e73c..be54c807b 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -2047,6 +2047,7 @@ public abstract class Entity implements ICommandListener { - - @Nullable - public ScoreboardTeamBase aQ() { -+ if (!this.world.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof EntityHuman)) { return null; } // Paper - return this.world.getScoreboard().getPlayerTeam(this.bf()); - } - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0065-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/Spigot-Server-Patches/0065-Add-methods-for-working-with-arrows-stuck-in-living-.patch deleted file mode 100644 index 34913fbf2a..0000000000 --- a/Spigot-Server-Patches/0065-Add-methods-for-working-with-arrows-stuck-in-living-.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 6d83a42776d8dcc58a966d6f8da8b5056c273026 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/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index e5fa1c3ba..247224117 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -1380,10 +1380,12 @@ public abstract class EntityLiving extends Entity { - return (float) this.getAttributeInstance(GenericAttributes.maxHealth).getValue(); - } - -+ public final int getStuckArrows() { return this.cc(); } // Paper - OBFHELPER - public final int cc() { - return ((Integer) this.datawatcher.get(EntityLiving.bq)).intValue(); - } - -+ public final void setStuckArrows(int arrows) { this.f(arrows); } // Paper - OBFHELPER - public final void f(int i) { - this.datawatcher.set(EntityLiving.bq, Integer.valueOf(i)); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 61032eb2f..348a8c758 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -572,4 +572,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public boolean isCollidable() { - return getHandle().collides; - } -+ -+ // Paper start -+ @Override -+ public int getArrowsStuck() { -+ return this.getHandle().getStuckArrows(); -+ } -+ -+ @Override -+ public void setArrowsStuck(int arrows) { -+ this.getHandle().setStuckArrows(arrows); -+ } -+ // Paper end - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0065-Complete-resource-pack-API.patch b/Spigot-Server-Patches/0065-Complete-resource-pack-API.patch new file mode 100644 index 0000000000..0c658d1092 --- /dev/null +++ b/Spigot-Server-Patches/0065-Complete-resource-pack-API.patch @@ -0,0 +1,75 @@ +From 258b0dd3501ba87edaadf75dc2bd065a29753105 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/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 57879c76d..b67837dd2 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -1029,7 +1029,12 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { + // CraftBukkit start + public void a(PacketPlayInResourcePackStatus packetplayinresourcepackstatus) { + PlayerConnectionUtils.ensureMainThread(packetplayinresourcepackstatus, this, this.player.x()); +- this.server.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.status.ordinal()])); ++ // Paper start ++ //this.server.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.status.ordinal()])); ++ final PlayerResourcePackStatusEvent.Status status = PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.status.ordinal()]; ++ this.getPlayer().setResourcePackStatus(status); ++ this.server.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), status)); ++ // 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 88fcadbfd..dd8380f71 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -74,6 +74,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); +@@ -1560,6 +1564,32 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + ((WorldServer) getHandle().world).getPlayerChunkMap().updateViewDistance(getHandle(), viewDistance); + } + ++ @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; ++ } ++ + // Spigot start + private final Player.Spigot spigot = new Player.Spigot() + { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0066-Chunk-save-queue-improvements.patch b/Spigot-Server-Patches/0066-Chunk-save-queue-improvements.patch new file mode 100644 index 0000000000..5c61c385c6 --- /dev/null +++ b/Spigot-Server-Patches/0066-Chunk-save-queue-improvements.patch @@ -0,0 +1,167 @@ +From 6faebb0cebf9a14b2b752145de89394a16604e53 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 4 Mar 2016 18:18:37 -0600 +Subject: [PATCH] Chunk save queue improvements + +For some unknown reason, Minecraft is sleeping 10ms between every single chunk being saved to disk. +Under high chunk load/unload activity (lots of movement / teleporting), this causes the chunk unload queue +to build up in size. + +This has multiple impacts: +1) Performance of the unload queue itself - The save thread is pretty ineffecient for how it accesses it + By letting the queue get larger, checking and popping work off the queue can get less performant. +2) Performance of chunk loading - As with #1, chunk loads also have to check this queue when loading + chunk data so that it doesn't load stale data if new data is pending write to disk. +3) Memory Usage - The entire chunk has been serialized to NBT, and now sits in this queue. This leads to + elevated memory usage, and then the objects used in the serialization sit around longer than needed, + resulting in promotion to Old Generation instead of dying young. + +To optimize this, we change the entire unload queue to be a proper queue. This improves the behavior of popping +the first queued chunk off, instead of abusing iterators like Mojang was doing. + +This also improves reliability of chunk saving, as the previous hack job had a race condition that could +fail to save some chunks. + +Then finally, Sleeping will by default be removed, but due to known issues with 1.9, a config option was added. +But if sleeps are to remain enabled, we at least lower the sleep interval so it doesn't have as much negative impact. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 9a6f87e59..873ffa77d 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -204,4 +204,10 @@ public class PaperConfig { + private static void chunkLoadThreads() { + minChunkLoadThreads = Math.min(6, getInt("settings.min-chunk-load-threads", 2)); // Keep people from doing stupid things with max of 6 + } ++ ++ public static boolean enableFileIOThreadSleep; ++ private static void enableFileIOThreadSleep() { ++ enableFileIOThreadSleep = getBoolean("settings.sleep-between-chunk-saves", false); ++ if (enableFileIOThreadSleep) Bukkit.getLogger().info("Enabled sleeping between chunk saves, beware of memory issues"); ++ } + } +diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java +index bee52d783..8e91be4a1 100644 +--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java ++++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java +@@ -12,14 +12,17 @@ import java.util.Map; + import java.util.Set; + import java.util.concurrent.ConcurrentHashMap; + import javax.annotation.Nullable; ++import java.util.concurrent.ConcurrentLinkedQueue; // Paper + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + + public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { + ++ private ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue<>(); // Paper - Chunk queue improvements ++ private final Object lock = new Object(); // Paper - Chunk queue improvements + private static final Logger a = LogManager.getLogger(); + private final Map b = new ConcurrentHashMap(); +- private final Set c = Collections.newSetFromMap(new ConcurrentHashMap()); ++ //private final Set c = Collections.newSetFromMap(new ConcurrentHashMap()); // Paper - Chunk queue improvements + private final File d; + private final DataConverterManager e; + private boolean f; +@@ -134,35 +137,32 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { + } + + protected void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) { +- if (!this.c.contains(chunkcoordintpair)) { ++ synchronized (lock) { // Paper - Chunk queue improvements + this.b.put(chunkcoordintpair, nbttagcompound); + } ++ queue.add(new QueuedChunk(chunkcoordintpair, nbttagcompound)); // Paper - Chunk queue improvements + + FileIOThread.a().a(this); + } + + public boolean c() { +- // CraftBukkit start +- Iterator> iter = this.b.entrySet().iterator(); +- if (!iter.hasNext()) { +- // CraftBukkit end ++ // Paper start - Chunk queue improvements ++ QueuedChunk chunk = queue.poll(); ++ if (chunk == null) { ++ // Paper - end + if (this.f) { + ChunkRegionLoader.a.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", new Object[] { this.d.getName()}); + } + + return false; + } else { +- // CraftBukkit start +- Map.Entry entry = iter.next(); +- iter.remove(); // Pop single entry +- ChunkCoordIntPair chunkcoordintpair = entry.getKey(); +- // CraftBukkit end ++ ChunkCoordIntPair chunkcoordintpair = chunk.coords; // Paper - Chunk queue improvements + + boolean flag; + + try { +- this.c.add(chunkcoordintpair); +- NBTTagCompound nbttagcompound = (NBTTagCompound) entry.getValue(); // CraftBukkit ++ //this.c.add(chunkcoordintpair); ++ NBTTagCompound nbttagcompound = chunk.compound; // Paper - Chunk queue improvements + + if (nbttagcompound != null) { + try { +@@ -171,10 +171,11 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { + ChunkRegionLoader.a.error("Failed to save chunk", exception); + } + } ++ synchronized (lock) { if (this.b.get(chunkcoordintpair) == nbttagcompound) { this.b.remove(chunkcoordintpair); } }// Paper - This will not equal if a newer version is still pending + + flag = true; + } finally { +- this.c.remove(chunkcoordintpair); ++ //this.c.remove(chunkcoordintpair); // Paper + } + + return flag; +@@ -539,4 +540,16 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { + return entity; + } + } ++ ++ // Paper start - Chunk queue improvements ++ private static class QueuedChunk { ++ public ChunkCoordIntPair coords; ++ public NBTTagCompound compound; ++ ++ public QueuedChunk(ChunkCoordIntPair coords, NBTTagCompound compound) { ++ this.coords = coords; ++ this.compound = compound; ++ } ++ } ++ // Paper end + } +diff --git a/src/main/java/net/minecraft/server/FileIOThread.java b/src/main/java/net/minecraft/server/FileIOThread.java +index acfdd52dc..fdbaf5fbd 100644 +--- a/src/main/java/net/minecraft/server/FileIOThread.java ++++ b/src/main/java/net/minecraft/server/FileIOThread.java +@@ -39,11 +39,15 @@ public class FileIOThread implements Runnable { + ++this.d; + } + +- try { +- Thread.sleep(this.e ? 0L : 10L); +- } catch (InterruptedException interruptedexception) { +- interruptedexception.printStackTrace(); ++ // Paper start - Add toggle ++ if (com.destroystokyo.paper.PaperConfig.enableFileIOThreadSleep) { ++ try { ++ Thread.sleep(this.e ? 0L : 2L); ++ } catch (InterruptedException interruptedexception) { ++ interruptedexception.printStackTrace(); ++ } + } ++ // Paper end + } + + if (this.b.isEmpty()) { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0066-Complete-resource-pack-API.patch b/Spigot-Server-Patches/0066-Complete-resource-pack-API.patch deleted file mode 100644 index b5f29fafea..0000000000 --- a/Spigot-Server-Patches/0066-Complete-resource-pack-API.patch +++ /dev/null @@ -1,75 +0,0 @@ -From db92fcc38686e0be97b3244eb5eae2e6da8966e1 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/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 57879c76d..b67837dd2 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -1029,7 +1029,12 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { - // CraftBukkit start - public void a(PacketPlayInResourcePackStatus packetplayinresourcepackstatus) { - PlayerConnectionUtils.ensureMainThread(packetplayinresourcepackstatus, this, this.player.x()); -- this.server.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.status.ordinal()])); -+ // Paper start -+ //this.server.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.status.ordinal()])); -+ final PlayerResourcePackStatusEvent.Status status = PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.status.ordinal()]; -+ this.getPlayer().setResourcePackStatus(status); -+ this.server.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), status)); -+ // 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 d72ff0af2..5fd5e39fa 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -74,6 +74,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); -@@ -1560,6 +1564,32 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - ((WorldServer) getHandle().world).getPlayerChunkMap().updateViewDistance(getHandle(), viewDistance); - } - -+ @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; -+ } -+ - // Spigot start - private final Player.Spigot spigot = new Player.Spigot() - { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0067-Chunk-Save-Reattempt.patch b/Spigot-Server-Patches/0067-Chunk-Save-Reattempt.patch new file mode 100644 index 0000000000..45e6b2bf57 --- /dev/null +++ b/Spigot-Server-Patches/0067-Chunk-Save-Reattempt.patch @@ -0,0 +1,46 @@ +From 215acca8d61ac2957f84dc40dfda8bdf6ed7b14a 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/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java +index 8e91be4a1..721a3cd81 100644 +--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java ++++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java +@@ -165,11 +165,16 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { + NBTTagCompound nbttagcompound = chunk.compound; // Paper - Chunk queue improvements + + if (nbttagcompound != null) { ++ int attempts = 0; Exception laste = null; while (attempts++ < 5) { // Paper + try { + this.b(chunkcoordintpair, nbttagcompound); ++ laste = null; break; // Paper + } catch (Exception exception) { +- ChunkRegionLoader.a.error("Failed to save chunk", exception); ++ //ChunkRegionLoader.a.error("Failed to save chunk", exception); // Paper ++ laste = exception; // Paper + } ++ try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();} } // Paper ++ if (laste != null) { com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(laste); MinecraftServer.LOGGER.error("Failed to save chunk", laste); } // Paper + } + synchronized (lock) { if (this.b.get(chunkcoordintpair) == nbttagcompound) { this.b.remove(chunkcoordintpair); } }// Paper - This will not equal if a newer version is still pending + +diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java +index 5f9678aad..ed840dbc9 100644 +--- a/src/main/java/net/minecraft/server/RegionFile.java ++++ b/src/main/java/net/minecraft/server/RegionFile.java +@@ -210,8 +210,7 @@ public class RegionFile { + + this.b(i, j, (int) (MinecraftServer.aw() / 1000L)); + } catch (IOException ioexception) { +- ioexception.printStackTrace(); +- ServerInternalException.reportInternalException(ioexception); // Paper ++ org.spigotmc.SneakyThrow.sneaky(ioexception); // Paper - we want the upper try/catch to retry this + } + + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0067-Chunk-save-queue-improvements.patch b/Spigot-Server-Patches/0067-Chunk-save-queue-improvements.patch deleted file mode 100644 index 1a6669e596..0000000000 --- a/Spigot-Server-Patches/0067-Chunk-save-queue-improvements.patch +++ /dev/null @@ -1,167 +0,0 @@ -From cfd598467afa046d6f71df7841c168df4758dca1 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 4 Mar 2016 18:18:37 -0600 -Subject: [PATCH] Chunk save queue improvements - -For some unknown reason, Minecraft is sleeping 10ms between every single chunk being saved to disk. -Under high chunk load/unload activity (lots of movement / teleporting), this causes the chunk unload queue -to build up in size. - -This has multiple impacts: -1) Performance of the unload queue itself - The save thread is pretty ineffecient for how it accesses it - By letting the queue get larger, checking and popping work off the queue can get less performant. -2) Performance of chunk loading - As with #1, chunk loads also have to check this queue when loading - chunk data so that it doesn't load stale data if new data is pending write to disk. -3) Memory Usage - The entire chunk has been serialized to NBT, and now sits in this queue. This leads to - elevated memory usage, and then the objects used in the serialization sit around longer than needed, - resulting in promotion to Old Generation instead of dying young. - -To optimize this, we change the entire unload queue to be a proper queue. This improves the behavior of popping -the first queued chunk off, instead of abusing iterators like Mojang was doing. - -This also improves reliability of chunk saving, as the previous hack job had a race condition that could -fail to save some chunks. - -Then finally, Sleeping will by default be removed, but due to known issues with 1.9, a config option was added. -But if sleeps are to remain enabled, we at least lower the sleep interval so it doesn't have as much negative impact. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 9a6f87e59..873ffa77d 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -204,4 +204,10 @@ public class PaperConfig { - private static void chunkLoadThreads() { - minChunkLoadThreads = Math.min(6, getInt("settings.min-chunk-load-threads", 2)); // Keep people from doing stupid things with max of 6 - } -+ -+ public static boolean enableFileIOThreadSleep; -+ private static void enableFileIOThreadSleep() { -+ enableFileIOThreadSleep = getBoolean("settings.sleep-between-chunk-saves", false); -+ if (enableFileIOThreadSleep) Bukkit.getLogger().info("Enabled sleeping between chunk saves, beware of memory issues"); -+ } - } -diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -index bee52d783..8e91be4a1 100644 ---- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -@@ -12,14 +12,17 @@ import java.util.Map; - import java.util.Set; - import java.util.concurrent.ConcurrentHashMap; - import javax.annotation.Nullable; -+import java.util.concurrent.ConcurrentLinkedQueue; // Paper - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - - public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { - -+ private ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue<>(); // Paper - Chunk queue improvements -+ private final Object lock = new Object(); // Paper - Chunk queue improvements - private static final Logger a = LogManager.getLogger(); - private final Map b = new ConcurrentHashMap(); -- private final Set c = Collections.newSetFromMap(new ConcurrentHashMap()); -+ //private final Set c = Collections.newSetFromMap(new ConcurrentHashMap()); // Paper - Chunk queue improvements - private final File d; - private final DataConverterManager e; - private boolean f; -@@ -134,35 +137,32 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { - } - - protected void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) { -- if (!this.c.contains(chunkcoordintpair)) { -+ synchronized (lock) { // Paper - Chunk queue improvements - this.b.put(chunkcoordintpair, nbttagcompound); - } -+ queue.add(new QueuedChunk(chunkcoordintpair, nbttagcompound)); // Paper - Chunk queue improvements - - FileIOThread.a().a(this); - } - - public boolean c() { -- // CraftBukkit start -- Iterator> iter = this.b.entrySet().iterator(); -- if (!iter.hasNext()) { -- // CraftBukkit end -+ // Paper start - Chunk queue improvements -+ QueuedChunk chunk = queue.poll(); -+ if (chunk == null) { -+ // Paper - end - if (this.f) { - ChunkRegionLoader.a.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", new Object[] { this.d.getName()}); - } - - return false; - } else { -- // CraftBukkit start -- Map.Entry entry = iter.next(); -- iter.remove(); // Pop single entry -- ChunkCoordIntPair chunkcoordintpair = entry.getKey(); -- // CraftBukkit end -+ ChunkCoordIntPair chunkcoordintpair = chunk.coords; // Paper - Chunk queue improvements - - boolean flag; - - try { -- this.c.add(chunkcoordintpair); -- NBTTagCompound nbttagcompound = (NBTTagCompound) entry.getValue(); // CraftBukkit -+ //this.c.add(chunkcoordintpair); -+ NBTTagCompound nbttagcompound = chunk.compound; // Paper - Chunk queue improvements - - if (nbttagcompound != null) { - try { -@@ -171,10 +171,11 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { - ChunkRegionLoader.a.error("Failed to save chunk", exception); - } - } -+ synchronized (lock) { if (this.b.get(chunkcoordintpair) == nbttagcompound) { this.b.remove(chunkcoordintpair); } }// Paper - This will not equal if a newer version is still pending - - flag = true; - } finally { -- this.c.remove(chunkcoordintpair); -+ //this.c.remove(chunkcoordintpair); // Paper - } - - return flag; -@@ -539,4 +540,16 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { - return entity; - } - } -+ -+ // Paper start - Chunk queue improvements -+ private static class QueuedChunk { -+ public ChunkCoordIntPair coords; -+ public NBTTagCompound compound; -+ -+ public QueuedChunk(ChunkCoordIntPair coords, NBTTagCompound compound) { -+ this.coords = coords; -+ this.compound = compound; -+ } -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/server/FileIOThread.java b/src/main/java/net/minecraft/server/FileIOThread.java -index acfdd52dc..fdbaf5fbd 100644 ---- a/src/main/java/net/minecraft/server/FileIOThread.java -+++ b/src/main/java/net/minecraft/server/FileIOThread.java -@@ -39,11 +39,15 @@ public class FileIOThread implements Runnable { - ++this.d; - } - -- try { -- Thread.sleep(this.e ? 0L : 10L); -- } catch (InterruptedException interruptedexception) { -- interruptedexception.printStackTrace(); -+ // Paper start - Add toggle -+ if (com.destroystokyo.paper.PaperConfig.enableFileIOThreadSleep) { -+ try { -+ Thread.sleep(this.e ? 0L : 2L); -+ } catch (InterruptedException interruptedexception) { -+ interruptedexception.printStackTrace(); -+ } - } -+ // Paper end - } - - if (this.b.isEmpty()) { --- -2.12.2.windows.2 - diff --git a/Spigot-Server-Patches/0068-Chunk-Save-Reattempt.patch b/Spigot-Server-Patches/0068-Chunk-Save-Reattempt.patch deleted file mode 100644 index 065b55e513..0000000000 --- a/Spigot-Server-Patches/0068-Chunk-Save-Reattempt.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 1a4ce4dfb31730e1359640c638688cbba006b68c 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/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -index 8e91be4a1..721a3cd81 100644 ---- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -@@ -165,11 +165,16 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { - NBTTagCompound nbttagcompound = chunk.compound; // Paper - Chunk queue improvements - - if (nbttagcompound != null) { -+ int attempts = 0; Exception laste = null; while (attempts++ < 5) { // Paper - try { - this.b(chunkcoordintpair, nbttagcompound); -+ laste = null; break; // Paper - } catch (Exception exception) { -- ChunkRegionLoader.a.error("Failed to save chunk", exception); -+ //ChunkRegionLoader.a.error("Failed to save chunk", exception); // Paper -+ laste = exception; // Paper - } -+ try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();} } // Paper -+ if (laste != null) { com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(laste); MinecraftServer.LOGGER.error("Failed to save chunk", laste); } // Paper - } - synchronized (lock) { if (this.b.get(chunkcoordintpair) == nbttagcompound) { this.b.remove(chunkcoordintpair); } }// Paper - This will not equal if a newer version is still pending - -diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java -index 5f9678aad..ed840dbc9 100644 ---- a/src/main/java/net/minecraft/server/RegionFile.java -+++ b/src/main/java/net/minecraft/server/RegionFile.java -@@ -210,8 +210,7 @@ public class RegionFile { - - this.b(i, j, (int) (MinecraftServer.aw() / 1000L)); - } catch (IOException ioexception) { -- ioexception.printStackTrace(); -- ServerInternalException.reportInternalException(ioexception); // Paper -+ org.spigotmc.SneakyThrow.sneaky(ioexception); // Paper - we want the upper try/catch to retry this - } - - } --- -2.12.2.windows.2 - diff --git a/Spigot-Server-Patches/0068-Default-loading-permissions.yml-before-plugins.patch b/Spigot-Server-Patches/0068-Default-loading-permissions.yml-before-plugins.patch new file mode 100644 index 0000000000..69ac736b4a --- /dev/null +++ b/Spigot-Server-Patches/0068-Default-loading-permissions.yml-before-plugins.patch @@ -0,0 +1,55 @@ +From 0c3c5d0949ca3e6635a5935f5e9cb162b6e28fa7 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 873ffa77d..b5ff26c71 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -210,4 +210,9 @@ public class PaperConfig { + enableFileIOThreadSleep = getBoolean("settings.sleep-between-chunk-saves", false); + if (enableFileIOThreadSleep) Bukkit.getLogger().info("Enabled sleeping between chunk saves, beware of memory issues"); + } ++ ++ 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 28da39cbd..9df6c0ebb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -318,6 +318,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(); +@@ -335,7 +336,7 @@ public final class CraftServer implements Server { + setVanillaCommands(false); + // Spigot end + commandMap.registerServerAliases(); +- loadCustomPermissions(); ++ if (!com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); // Paper + DefaultPermissions.registerCorePermissions(); + CraftDefaultPermissions.registerCorePermissions(); + helpMap.initializeCommands(); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0069-Allow-Reloading-of-Custom-Permissions.patch b/Spigot-Server-Patches/0069-Allow-Reloading-of-Custom-Permissions.patch new file mode 100644 index 0000000000..95e3241f43 --- /dev/null +++ b/Spigot-Server-Patches/0069-Allow-Reloading-of-Custom-Permissions.patch @@ -0,0 +1,36 @@ +From 1b592b3b573635540cf12d730926ede918b22e19 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 9df6c0ebb..e77307c35 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1827,4 +1827,21 @@ public final class CraftServer implements Server { + { + return spigot; + } ++ ++ // Paper start ++ @Override ++ public void reloadPermissions() { ++ ((SimplePluginManager) pluginManager).clearPermissions(); ++ loadCustomPermissions(); ++ for (Plugin plugin : pluginManager.getPlugins()) { ++ plugin.getDescription().getPermissions().forEach((perm) -> { ++ 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); ++ } ++ }); ++ } ++ } ++ // Paper end + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0069-Default-loading-permissions.yml-before-plugins.patch b/Spigot-Server-Patches/0069-Default-loading-permissions.yml-before-plugins.patch deleted file mode 100644 index f5737e3b20..0000000000 --- a/Spigot-Server-Patches/0069-Default-loading-permissions.yml-before-plugins.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 2cbb25a2774f83799823fe7362f067609bdffc0c 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 873ffa77d..b5ff26c71 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -210,4 +210,9 @@ public class PaperConfig { - enableFileIOThreadSleep = getBoolean("settings.sleep-between-chunk-saves", false); - if (enableFileIOThreadSleep) Bukkit.getLogger().info("Enabled sleeping between chunk saves, beware of memory issues"); - } -+ -+ 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 28da39cbd..9df6c0ebb 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -318,6 +318,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(); -@@ -335,7 +336,7 @@ public final class CraftServer implements Server { - setVanillaCommands(false); - // Spigot end - commandMap.registerServerAliases(); -- loadCustomPermissions(); -+ if (!com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); // Paper - DefaultPermissions.registerCorePermissions(); - CraftDefaultPermissions.registerCorePermissions(); - helpMap.initializeCommands(); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0070-Allow-Reloading-of-Custom-Permissions.patch b/Spigot-Server-Patches/0070-Allow-Reloading-of-Custom-Permissions.patch deleted file mode 100644 index c49e41e974..0000000000 --- a/Spigot-Server-Patches/0070-Allow-Reloading-of-Custom-Permissions.patch +++ /dev/null @@ -1,36 +0,0 @@ -From c17904b073dbf431afdc19c4dc09f444ad6ecb6c 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 9df6c0ebb..e77307c35 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1827,4 +1827,21 @@ public final class CraftServer implements Server { - { - return spigot; - } -+ -+ // Paper start -+ @Override -+ public void reloadPermissions() { -+ ((SimplePluginManager) pluginManager).clearPermissions(); -+ loadCustomPermissions(); -+ for (Plugin plugin : pluginManager.getPlugins()) { -+ plugin.getDescription().getPermissions().forEach((perm) -> { -+ 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); -+ } -+ }); -+ } -+ } -+ // Paper end - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0070-Remove-Metadata-on-reload.patch b/Spigot-Server-Patches/0070-Remove-Metadata-on-reload.patch new file mode 100644 index 0000000000..5e4a8d6408 --- /dev/null +++ b/Spigot-Server-Patches/0070-Remove-Metadata-on-reload.patch @@ -0,0 +1,30 @@ +From 6ad5adc9ed459e196fc415dba3914509def9b240 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 e77307c35..4d761d32a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -741,6 +741,14 @@ public final class CraftServer implements Server { + world.paperConfig.init(); // Paper + } + ++ // Paper start ++ for (Plugin plugin : pluginManager.getPlugins()) { ++ entityMetadata.removeAll(plugin); ++ worldMetadata.removeAll(plugin); ++ playerMetadata.removeAll(plugin); ++ } ++ // Paper end ++ + pluginManager.clearPlugins(); + commandMap.clearCommands(); + resetRecipes(); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0071-Remove-Metadata-on-reload.patch b/Spigot-Server-Patches/0071-Remove-Metadata-on-reload.patch deleted file mode 100644 index 27c349a80b..0000000000 --- a/Spigot-Server-Patches/0071-Remove-Metadata-on-reload.patch +++ /dev/null @@ -1,30 +0,0 @@ -From ef440adcb9e263901028407fe1ad0d2e02f2435c 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 e77307c35..4d761d32a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -741,6 +741,14 @@ public final class CraftServer implements Server { - world.paperConfig.init(); // Paper - } - -+ // Paper start -+ for (Plugin plugin : pluginManager.getPlugins()) { -+ entityMetadata.removeAll(plugin); -+ worldMetadata.removeAll(plugin); -+ playerMetadata.removeAll(plugin); -+ } -+ // Paper end -+ - pluginManager.clearPlugins(); - commandMap.clearCommands(); - resetRecipes(); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0071-Undead-horse-leashing.patch b/Spigot-Server-Patches/0071-Undead-horse-leashing.patch new file mode 100644 index 0000000000..aa718954ef --- /dev/null +++ b/Spigot-Server-Patches/0071-Undead-horse-leashing.patch @@ -0,0 +1,37 @@ +From 1e3c4136cd2e9eec214fb9b730c3a01e486d841c Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 18 Mar 2016 14:19:19 -0400 +Subject: [PATCH] Undead horse leashing + +default false to match vanilla, but option to allow undead horse types to be leashed. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 9987a5c7a..0873febb6 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -249,4 +249,9 @@ public class PaperWorldConfig { + private void nonPlayerEntitiesOnScoreboards() { + nonPlayerEntitiesOnScoreboards = getBoolean("allow-non-player-entities-on-scoreboards", false); + } ++ ++ public boolean allowLeashingUndeadHorse = false; ++ private void allowLeashingUndeadHorse() { ++ allowLeashingUndeadHorse = getBoolean("allow-leashing-undead-horse", false); ++ } + } +diff --git a/src/main/java/net/minecraft/server/EntityHorseAbstract.java b/src/main/java/net/minecraft/server/EntityHorseAbstract.java +index d74ccd68d..3416c7a7d 100644 +--- a/src/main/java/net/minecraft/server/EntityHorseAbstract.java ++++ b/src/main/java/net/minecraft/server/EntityHorseAbstract.java +@@ -115,7 +115,7 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven + } + + public boolean a(EntityHuman entityhuman) { +- return super.a(entityhuman) && this.getMonsterType() != EnumMonsterType.UNDEAD; ++ return world.paperConfig.allowLeashingUndeadHorse ? super.a(entityhuman) : super.a(entityhuman) && this.getMonsterType() != EnumMonsterType.UNDEAD; // Paper + } + + protected void q(float f) { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0072-Fix-Furnace-cook-time-bug.patch b/Spigot-Server-Patches/0072-Fix-Furnace-cook-time-bug.patch new file mode 100644 index 0000000000..36f1445198 --- /dev/null +++ b/Spigot-Server-Patches/0072-Fix-Furnace-cook-time-bug.patch @@ -0,0 +1,26 @@ +From 1f5e3b8cd3c4a90bd433b56172f9b84f11eb65ed Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 18 Mar 2016 14:24:53 -0400 +Subject: [PATCH] Fix Furnace cook time bug + +If the server lags out and skips multiple ticks, Furnace cooking behavior would not +cook in the expected amount of time as the cook time was not decremented correctly. + +This patch ensures that furnaces cook to the correct wall time expectation. + +diff --git a/src/main/java/net/minecraft/server/TileEntityFurnace.java b/src/main/java/net/minecraft/server/TileEntityFurnace.java +index 2f1f3edf5..e230d1608 100644 +--- a/src/main/java/net/minecraft/server/TileEntityFurnace.java ++++ b/src/main/java/net/minecraft/server/TileEntityFurnace.java +@@ -165,7 +165,7 @@ public class TileEntityFurnace extends TileEntityContainer implements ITickable, + if (this.isBurning() && this.canBurn()) { + this.cookTime += elapsedTicks; + if (this.cookTime >= this.cookTimeTotal) { +- this.cookTime = 0; ++ this.cookTime -= this.cookTimeTotal; // Paper + this.cookTimeTotal = this.a((ItemStack) this.items.get(0)); + this.burn(); + flag1 = true; +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0072-Undead-horse-leashing.patch b/Spigot-Server-Patches/0072-Undead-horse-leashing.patch deleted file mode 100644 index 5c4cd757ce..0000000000 --- a/Spigot-Server-Patches/0072-Undead-horse-leashing.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 2c430290f17c86c477c2c7a7d267fd23ddfbba3f Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Mar 2016 14:19:19 -0400 -Subject: [PATCH] Undead horse leashing - -default false to match vanilla, but option to allow undead horse types to be leashed. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 9987a5c7a..0873febb6 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -249,4 +249,9 @@ public class PaperWorldConfig { - private void nonPlayerEntitiesOnScoreboards() { - nonPlayerEntitiesOnScoreboards = getBoolean("allow-non-player-entities-on-scoreboards", false); - } -+ -+ public boolean allowLeashingUndeadHorse = false; -+ private void allowLeashingUndeadHorse() { -+ allowLeashingUndeadHorse = getBoolean("allow-leashing-undead-horse", false); -+ } - } -diff --git a/src/main/java/net/minecraft/server/EntityHorseAbstract.java b/src/main/java/net/minecraft/server/EntityHorseAbstract.java -index d74ccd68d..3416c7a7d 100644 ---- a/src/main/java/net/minecraft/server/EntityHorseAbstract.java -+++ b/src/main/java/net/minecraft/server/EntityHorseAbstract.java -@@ -115,7 +115,7 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven - } - - public boolean a(EntityHuman entityhuman) { -- return super.a(entityhuman) && this.getMonsterType() != EnumMonsterType.UNDEAD; -+ return world.paperConfig.allowLeashingUndeadHorse ? super.a(entityhuman) : super.a(entityhuman) && this.getMonsterType() != EnumMonsterType.UNDEAD; // Paper - } - - protected void q(float f) { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0073-Fix-Furnace-cook-time-bug.patch b/Spigot-Server-Patches/0073-Fix-Furnace-cook-time-bug.patch deleted file mode 100644 index cf4bac701f..0000000000 --- a/Spigot-Server-Patches/0073-Fix-Furnace-cook-time-bug.patch +++ /dev/null @@ -1,26 +0,0 @@ -From f9d6774c585cdc37c69b774d8afee693a95dda02 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Mar 2016 14:24:53 -0400 -Subject: [PATCH] Fix Furnace cook time bug - -If the server lags out and skips multiple ticks, Furnace cooking behavior would not -cook in the expected amount of time as the cook time was not decremented correctly. - -This patch ensures that furnaces cook to the correct wall time expectation. - -diff --git a/src/main/java/net/minecraft/server/TileEntityFurnace.java b/src/main/java/net/minecraft/server/TileEntityFurnace.java -index 2f1f3edf5..e230d1608 100644 ---- a/src/main/java/net/minecraft/server/TileEntityFurnace.java -+++ b/src/main/java/net/minecraft/server/TileEntityFurnace.java -@@ -165,7 +165,7 @@ public class TileEntityFurnace extends TileEntityContainer implements ITickable, - if (this.isBurning() && this.canBurn()) { - this.cookTime += elapsedTicks; - if (this.cookTime >= this.cookTimeTotal) { -- this.cookTime = 0; -+ this.cookTime -= this.cookTimeTotal; // Paper - this.cookTimeTotal = this.a((ItemStack) this.items.get(0)); - this.burn(); - flag1 = true; --- -2.12.2 - diff --git a/Spigot-Server-Patches/0073-Handle-Item-Meta-Inconsistencies.patch b/Spigot-Server-Patches/0073-Handle-Item-Meta-Inconsistencies.patch new file mode 100644 index 0000000000..53c1e6c930 --- /dev/null +++ b/Spigot-Server-Patches/0073-Handle-Item-Meta-Inconsistencies.patch @@ -0,0 +1,293 @@ +From 96ff410272199eb91bc1607e2b57ceaa9470b610 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/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +index a54bc7c42..81ec8f69e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +@@ -4,6 +4,7 @@ import static org.bukkit.craftbukkit.inventory.CraftMetaItem.ENCHANTMENTS; + import static org.bukkit.craftbukkit.inventory.CraftMetaItem.ENCHANTMENTS_ID; + import static org.bukkit.craftbukkit.inventory.CraftMetaItem.ENCHANTMENTS_LVL; + ++import java.util.Iterator; + import java.util.Map; + + import net.minecraft.server.EnchantmentManager; +@@ -183,28 +184,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); +- short id = tag.getShort(ENCHANTMENTS_ID.NBT); +- if (id == ench.getId()) { +- tag.setShort(ENCHANTMENTS_LVL.NBT, (short) level); +- return; +- } +- } +- NBTTagCompound tag = new NBTTagCompound(); +- tag.setShort(ENCHANTMENTS_ID.NBT, (short) ench.getId()); +- 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.server.ItemStack item) { +@@ -221,66 +205,34 @@ 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; // Pape - 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); +- int id = 0xffff & enchantment.getShort(ENCHANTMENTS_ID.NBT); +- if (id == ench.getId()) { +- 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); ++ // Paper start - replace entire method, maintain backwards compat of returning previous level. ++ final ItemMeta itemMeta = getItemMeta(); ++ final Iterator iterator = itemMeta.getEnchants().keySet().iterator(); ++ for (int i = 0; iterator.hasNext(); i++) { ++ if (iterator.next().equals(ench)) { ++ itemMeta.removeEnchant(ench); ++ setItemMeta(itemMeta); ++ return i; + } +- 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)); +- } +- } +- handle.getTag().set(ENCHANTMENTS.NBT, listCopy); +- +- return level; ++ // Paper end ++ return 0; + } + + @Override + public Map getEnchantments() { +- return getEnchantments(handle); ++ return hasItemMeta() ? getItemMeta().getEnchants() : ImmutableMap.of(); // Paper - use Item Meta + } + + static Map getEnchantments(net.minecraft.server.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 9d0c05cd0..ab50ee92e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +@@ -6,13 +6,8 @@ import java.lang.annotation.RetentionPolicy; + import java.lang.annotation.Target; + import java.lang.reflect.Constructor; + import java.lang.reflect.InvocationTargetException; +-import java.util.ArrayList; +-import java.util.Collection; +-import java.util.HashMap; +-import java.util.List; +-import java.util.Map; +-import java.util.NoSuchElementException; + ++import com.google.common.collect.ImmutableSortedMap; + import net.minecraft.server.NBTBase; + import net.minecraft.server.NBTTagCompound; + import net.minecraft.server.NBTTagList; +@@ -38,10 +33,18 @@ import com.google.common.collect.Sets; + import java.io.ByteArrayInputStream; + import java.io.ByteArrayOutputStream; + import java.io.IOException; ++import java.util.ArrayList; + import java.util.Arrays; ++import java.util.Collection; ++import java.util.Comparator; + import java.util.EnumSet; ++import java.util.HashMap; + import java.util.HashSet; ++import java.util.List; ++import java.util.Map; ++import java.util.NoSuchElementException; + import java.util.Set; ++import java.util.TreeMap; + import java.util.logging.Level; + import java.util.logging.Logger; + import net.minecraft.server.NBTCompressedStreamTools; +@@ -225,7 +228,7 @@ class CraftMetaItem implements ItemMeta, Repairable { + private String displayName; + private String locName; + private List lore; +- private Map enchantments; ++ private EnchantmentMap enchantments; // Paper + private int repairCost; + private int hideFlag; + private boolean unbreakable; +@@ -233,7 +236,7 @@ class CraftMetaItem implements ItemMeta, Repairable { + private static final Set HANDLED_TAGS = Sets.newHashSet(); + + private NBTTagCompound internalTag; +- private final Map unhandledTags = new HashMap(); ++ private final Map unhandledTags = new TreeMap<>(); // Paper + + CraftMetaItem(CraftMetaItem meta) { + if (meta == null) { +@@ -248,7 +251,7 @@ class CraftMetaItem implements ItemMeta, Repairable { + } + + if (meta.enchantments != null) { // Spigot +- this.enchantments = new HashMap(meta.enchantments); ++ this.enchantments = new EnchantmentMap(meta.enchantments); // Paper + } + + this.repairCost = meta.repairCost; +@@ -469,13 +472,13 @@ class CraftMetaItem implements ItemMeta, Repairable { + } + } + +- 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 HashMap(ench.size()); ++ EnchantmentMap enchantments = new EnchantmentMap(); // Paper + + for (int i = 0; i < ench.size(); i++) { + int id = 0xffff & ((NBTTagCompound) ench.get(i)).getShort(ENCHANTMENTS_ID.NBT); +@@ -545,13 +548,13 @@ class CraftMetaItem implements ItemMeta, Repairable { + void deserializeInternal(NBTTagCompound tag) { + } + +- 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 HashMap(ench.size()); ++ EnchantmentMap enchantments = new EnchantmentMap(); // Paper + for (Map.Entry entry : ench.entrySet()) { + Enchantment enchantment = Enchantment.getByName(entry.getKey().toString()); + +@@ -695,12 +698,12 @@ class CraftMetaItem implements ItemMeta, Repairable { + } + + public Map getEnchants() { +- return hasEnchants() ? ImmutableMap.copyOf(enchantments) : ImmutableMap.of(); ++ return hasEnchants() ? ImmutableSortedMap.copyOfSorted(enchantments) : ImmutableMap.of(); // Paper + } + + public boolean addEnchant(Enchantment ench, int level, boolean ignoreRestrictions) { + if (enchantments == null) { +- enchantments = new HashMap(4); ++ enchantments = new EnchantmentMap(); // Paper + } + + if (ignoreRestrictions || level >= ench.getStartLevel() && level <= ench.getMaxLevel()) { +@@ -870,7 +873,7 @@ class CraftMetaItem implements ItemMeta, Repairable { + clone.lore = new ArrayList(this.lore); + } + if (this.enchantments != null) { +- clone.enchantments = new HashMap(this.enchantments); ++ clone.enchantments = new EnchantmentMap(this.enchantments); // Paper + } + clone.hideFlag = this.hideFlag; + clone.unbreakable = this.unbreakable; +@@ -1027,6 +1030,23 @@ class CraftMetaItem implements ItemMeta, Repairable { + } + } + ++ // Paper start ++ private static class EnchantmentMap extends TreeMap { ++ private EnchantmentMap(Map enchantments) { ++ this(); ++ putAll(enchantments); ++ } ++ ++ private EnchantmentMap() { ++ super((o1, o2) -> ((Integer) o1.getId()).compareTo(o2.getId())); ++ } ++ ++ public EnchantmentMap clone() { ++ return (EnchantmentMap) super.clone(); ++ } ++ } ++ // Paper end ++ + // Spigot start + private final Spigot spigot = new Spigot() + { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0074-Configurable-Non-Player-Arrow-Despawn-Rate.patch b/Spigot-Server-Patches/0074-Configurable-Non-Player-Arrow-Despawn-Rate.patch new file mode 100644 index 0000000000..b631fdd608 --- /dev/null +++ b/Spigot-Server-Patches/0074-Configurable-Non-Player-Arrow-Despawn-Rate.patch @@ -0,0 +1,41 @@ +From f97a0149fe312629f4b29fce2ac49eacc0456754 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 0873febb6..b37b5901b 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -254,4 +254,13 @@ public class PaperWorldConfig { + private void allowLeashingUndeadHorse() { + allowLeashingUndeadHorse = getBoolean("allow-leashing-undead-horse", false); + } ++ ++ public int nonPlayerArrowDespawnRate = -1; ++ private void nonPlayerArrowDespawnRate() { ++ nonPlayerArrowDespawnRate = getInt("non-player-arrow-despawn-rate", -1); ++ if (nonPlayerArrowDespawnRate == -1) { ++ nonPlayerArrowDespawnRate = spigotConfig.arrowDespawnRate; ++ } ++ log("Non Player Arrow Despawn Rate: " + nonPlayerArrowDespawnRate); ++ } + } +diff --git a/src/main/java/net/minecraft/server/EntityArrow.java b/src/main/java/net/minecraft/server/EntityArrow.java +index 65689f26d..8cda47518 100644 +--- a/src/main/java/net/minecraft/server/EntityArrow.java ++++ b/src/main/java/net/minecraft/server/EntityArrow.java +@@ -157,7 +157,7 @@ public abstract class EntityArrow extends Entity implements IProjectile { + this.ay = 0; + } else { + ++this.ax; +- if (this.ax >= world.spigotConfig.arrowDespawnRate) { // Spigot - First int after shooter ++ if (this.ax >= (fromPlayer != PickupStatus.DISALLOWED ? world.spigotConfig.arrowDespawnRate : world.paperConfig.nonPlayerArrowDespawnRate)) { // Spigot - First int after shooter // Paper + this.die(); + } + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0074-Handle-Item-Meta-Inconsistencies.patch b/Spigot-Server-Patches/0074-Handle-Item-Meta-Inconsistencies.patch deleted file mode 100644 index b2ff8917df..0000000000 --- a/Spigot-Server-Patches/0074-Handle-Item-Meta-Inconsistencies.patch +++ /dev/null @@ -1,293 +0,0 @@ -From 3ebd0b6e30d5bb88cd31408f92c49f79e928d2a9 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/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index a54bc7c42..81ec8f69e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -4,6 +4,7 @@ import static org.bukkit.craftbukkit.inventory.CraftMetaItem.ENCHANTMENTS; - import static org.bukkit.craftbukkit.inventory.CraftMetaItem.ENCHANTMENTS_ID; - import static org.bukkit.craftbukkit.inventory.CraftMetaItem.ENCHANTMENTS_LVL; - -+import java.util.Iterator; - import java.util.Map; - - import net.minecraft.server.EnchantmentManager; -@@ -183,28 +184,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); -- short id = tag.getShort(ENCHANTMENTS_ID.NBT); -- if (id == ench.getId()) { -- tag.setShort(ENCHANTMENTS_LVL.NBT, (short) level); -- return; -- } -- } -- NBTTagCompound tag = new NBTTagCompound(); -- tag.setShort(ENCHANTMENTS_ID.NBT, (short) ench.getId()); -- 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.server.ItemStack item) { -@@ -221,66 +205,34 @@ 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; // Pape - 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); -- int id = 0xffff & enchantment.getShort(ENCHANTMENTS_ID.NBT); -- if (id == ench.getId()) { -- 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); -+ // Paper start - replace entire method, maintain backwards compat of returning previous level. -+ final ItemMeta itemMeta = getItemMeta(); -+ final Iterator iterator = itemMeta.getEnchants().keySet().iterator(); -+ for (int i = 0; iterator.hasNext(); i++) { -+ if (iterator.next().equals(ench)) { -+ itemMeta.removeEnchant(ench); -+ setItemMeta(itemMeta); -+ return i; - } -- 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)); -- } -- } -- handle.getTag().set(ENCHANTMENTS.NBT, listCopy); -- -- return level; -+ // Paper end -+ return 0; - } - - @Override - public Map getEnchantments() { -- return getEnchantments(handle); -+ return hasItemMeta() ? getItemMeta().getEnchants() : ImmutableMap.of(); // Paper - use Item Meta - } - - static Map getEnchantments(net.minecraft.server.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 9d0c05cd0..ab50ee92e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -6,13 +6,8 @@ import java.lang.annotation.RetentionPolicy; - import java.lang.annotation.Target; - import java.lang.reflect.Constructor; - import java.lang.reflect.InvocationTargetException; --import java.util.ArrayList; --import java.util.Collection; --import java.util.HashMap; --import java.util.List; --import java.util.Map; --import java.util.NoSuchElementException; - -+import com.google.common.collect.ImmutableSortedMap; - import net.minecraft.server.NBTBase; - import net.minecraft.server.NBTTagCompound; - import net.minecraft.server.NBTTagList; -@@ -38,10 +33,18 @@ import com.google.common.collect.Sets; - import java.io.ByteArrayInputStream; - import java.io.ByteArrayOutputStream; - import java.io.IOException; -+import java.util.ArrayList; - import java.util.Arrays; -+import java.util.Collection; -+import java.util.Comparator; - import java.util.EnumSet; -+import java.util.HashMap; - import java.util.HashSet; -+import java.util.List; -+import java.util.Map; -+import java.util.NoSuchElementException; - import java.util.Set; -+import java.util.TreeMap; - import java.util.logging.Level; - import java.util.logging.Logger; - import net.minecraft.server.NBTCompressedStreamTools; -@@ -225,7 +228,7 @@ class CraftMetaItem implements ItemMeta, Repairable { - private String displayName; - private String locName; - private List lore; -- private Map enchantments; -+ private EnchantmentMap enchantments; // Paper - private int repairCost; - private int hideFlag; - private boolean unbreakable; -@@ -233,7 +236,7 @@ class CraftMetaItem implements ItemMeta, Repairable { - private static final Set HANDLED_TAGS = Sets.newHashSet(); - - private NBTTagCompound internalTag; -- private final Map unhandledTags = new HashMap(); -+ private final Map unhandledTags = new TreeMap<>(); // Paper - - CraftMetaItem(CraftMetaItem meta) { - if (meta == null) { -@@ -248,7 +251,7 @@ class CraftMetaItem implements ItemMeta, Repairable { - } - - if (meta.enchantments != null) { // Spigot -- this.enchantments = new HashMap(meta.enchantments); -+ this.enchantments = new EnchantmentMap(meta.enchantments); // Paper - } - - this.repairCost = meta.repairCost; -@@ -469,13 +472,13 @@ class CraftMetaItem implements ItemMeta, Repairable { - } - } - -- 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 HashMap(ench.size()); -+ EnchantmentMap enchantments = new EnchantmentMap(); // Paper - - for (int i = 0; i < ench.size(); i++) { - int id = 0xffff & ((NBTTagCompound) ench.get(i)).getShort(ENCHANTMENTS_ID.NBT); -@@ -545,13 +548,13 @@ class CraftMetaItem implements ItemMeta, Repairable { - void deserializeInternal(NBTTagCompound tag) { - } - -- 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 HashMap(ench.size()); -+ EnchantmentMap enchantments = new EnchantmentMap(); // Paper - for (Map.Entry entry : ench.entrySet()) { - Enchantment enchantment = Enchantment.getByName(entry.getKey().toString()); - -@@ -695,12 +698,12 @@ class CraftMetaItem implements ItemMeta, Repairable { - } - - public Map getEnchants() { -- return hasEnchants() ? ImmutableMap.copyOf(enchantments) : ImmutableMap.of(); -+ return hasEnchants() ? ImmutableSortedMap.copyOfSorted(enchantments) : ImmutableMap.of(); // Paper - } - - public boolean addEnchant(Enchantment ench, int level, boolean ignoreRestrictions) { - if (enchantments == null) { -- enchantments = new HashMap(4); -+ enchantments = new EnchantmentMap(); // Paper - } - - if (ignoreRestrictions || level >= ench.getStartLevel() && level <= ench.getMaxLevel()) { -@@ -870,7 +873,7 @@ class CraftMetaItem implements ItemMeta, Repairable { - clone.lore = new ArrayList(this.lore); - } - if (this.enchantments != null) { -- clone.enchantments = new HashMap(this.enchantments); -+ clone.enchantments = new EnchantmentMap(this.enchantments); // Paper - } - clone.hideFlag = this.hideFlag; - clone.unbreakable = this.unbreakable; -@@ -1027,6 +1030,23 @@ class CraftMetaItem implements ItemMeta, Repairable { - } - } - -+ // Paper start -+ private static class EnchantmentMap extends TreeMap { -+ private EnchantmentMap(Map enchantments) { -+ this(); -+ putAll(enchantments); -+ } -+ -+ private EnchantmentMap() { -+ super((o1, o2) -> ((Integer) o1.getId()).compareTo(o2.getId())); -+ } -+ -+ public EnchantmentMap clone() { -+ return (EnchantmentMap) super.clone(); -+ } -+ } -+ // Paper end -+ - // Spigot start - private final Spigot spigot = new Spigot() - { --- -2.12.2.windows.2 - diff --git a/Spigot-Server-Patches/0075-Add-World-Util-Methods.patch b/Spigot-Server-Patches/0075-Add-World-Util-Methods.patch new file mode 100644 index 0000000000..47e7307023 --- /dev/null +++ b/Spigot-Server-Patches/0075-Add-World-Util-Methods.patch @@ -0,0 +1,97 @@ +From e6cab2b2737495bda0da7f5bea283749cf2d99be 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/World.java b/src/main/java/net/minecraft/server/World.java +index cc7369e52..1d2d174e8 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -152,6 +152,12 @@ public abstract class World implements IBlockAccess { + return (CraftServer) Bukkit.getServer(); + } + ++ // Paper start ++ public Chunk getChunkIfLoaded(BlockPosition blockposition) { ++ return this.chunkProvider.getLoadedChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ } ++ // Paper end ++ + public Chunk getChunkIfLoaded(int x, int z) { + return ((ChunkProviderServer) this.chunkProvider).getChunkIfLoaded(x, z); + } +@@ -682,6 +688,41 @@ public abstract class World implements IBlockAccess { + } + } + ++ // Paper start - test if meets light level, return faster ++ // logic copied from below ++ public boolean isLightLevel(BlockPosition blockposition, int level) { ++ if (isValidLocation(blockposition)) { ++ if (this.getType(blockposition).f()) { ++ if (this.c(blockposition.up(), false) >= level) { ++ return true; ++ } ++ if (this.c(blockposition.east(), false) >= level) { ++ return true; ++ } ++ if (this.c(blockposition.west(), false) >= level) { ++ return true; ++ } ++ if (this.c(blockposition.south(), false) >= level) { ++ return true; ++ } ++ if (this.c(blockposition.north(), false) >= level) { ++ return true; ++ } ++ return false; ++ } else { ++ if (blockposition.getY() >= 256) { ++ blockposition = new BlockPosition(blockposition.getX(), 255, blockposition.getZ()); ++ } ++ ++ Chunk chunk = this.getChunkAtWorldCoords(blockposition); ++ return chunk.a(blockposition, this.J) >= level; ++ } ++ } else { ++ return true; ++ } ++ } ++ // Paper end ++ + public int getLightLevel(BlockPosition blockposition) { + return this.c(blockposition, true); + } +@@ -801,6 +842,27 @@ public abstract class World implements IBlockAccess { + return this.worldProvider.o()[this.getLightLevel(blockposition)]; + } + ++ // Paper start - reduces need to do isLoaded before getType ++ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { ++ // CraftBukkit start - tree generation ++ if (captureTreeGeneration) { ++ Iterator it = capturedBlockStates.iterator(); ++ while (it.hasNext()) { ++ BlockState previous = it.next(); ++ if (previous.getX() == blockposition.getX() && previous.getY() == blockposition.getY() && previous.getZ() == blockposition.getZ()) { ++ return CraftMagicNumbers.getBlock(previous.getTypeId()).fromLegacyData(previous.getRawData()); ++ } ++ } ++ } ++ // CraftBukkit end ++ Chunk chunk = this.getChunkIfLoaded(blockposition); ++ if (chunk != null) { ++ return this.isValidLocation(blockposition) ? chunk.getBlockData(blockposition) : Blocks.AIR.getBlockData(); ++ } ++ return null; ++ } ++ // Paper end ++ + public IBlockData getType(BlockPosition blockposition) { + // CraftBukkit start - tree generation + if (captureTreeGeneration) { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0075-Configurable-Non-Player-Arrow-Despawn-Rate.patch b/Spigot-Server-Patches/0075-Configurable-Non-Player-Arrow-Despawn-Rate.patch deleted file mode 100644 index 3bafafd76f..0000000000 --- a/Spigot-Server-Patches/0075-Configurable-Non-Player-Arrow-Despawn-Rate.patch +++ /dev/null @@ -1,41 +0,0 @@ -From ccd2974a83c4fae5d48a01486ab8b8dffe414363 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 0873febb6..b37b5901b 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -254,4 +254,13 @@ public class PaperWorldConfig { - private void allowLeashingUndeadHorse() { - allowLeashingUndeadHorse = getBoolean("allow-leashing-undead-horse", false); - } -+ -+ public int nonPlayerArrowDespawnRate = -1; -+ private void nonPlayerArrowDespawnRate() { -+ nonPlayerArrowDespawnRate = getInt("non-player-arrow-despawn-rate", -1); -+ if (nonPlayerArrowDespawnRate == -1) { -+ nonPlayerArrowDespawnRate = spigotConfig.arrowDespawnRate; -+ } -+ log("Non Player Arrow Despawn Rate: " + nonPlayerArrowDespawnRate); -+ } - } -diff --git a/src/main/java/net/minecraft/server/EntityArrow.java b/src/main/java/net/minecraft/server/EntityArrow.java -index 65689f26d..8cda47518 100644 ---- a/src/main/java/net/minecraft/server/EntityArrow.java -+++ b/src/main/java/net/minecraft/server/EntityArrow.java -@@ -157,7 +157,7 @@ public abstract class EntityArrow extends Entity implements IProjectile { - this.ay = 0; - } else { - ++this.ax; -- if (this.ax >= world.spigotConfig.arrowDespawnRate) { // Spigot - First int after shooter -+ if (this.ax >= (fromPlayer != PickupStatus.DISALLOWED ? world.spigotConfig.arrowDespawnRate : world.paperConfig.nonPlayerArrowDespawnRate)) { // Spigot - First int after shooter // Paper - this.die(); - } - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0076-Add-World-Util-Methods.patch b/Spigot-Server-Patches/0076-Add-World-Util-Methods.patch deleted file mode 100644 index fa9710a215..0000000000 --- a/Spigot-Server-Patches/0076-Add-World-Util-Methods.patch +++ /dev/null @@ -1,97 +0,0 @@ -From cc98ddd19cc2afe5d8afcd704383ead8d44c36fd 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/World.java b/src/main/java/net/minecraft/server/World.java -index cc7369e52..1d2d174e8 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -152,6 +152,12 @@ public abstract class World implements IBlockAccess { - return (CraftServer) Bukkit.getServer(); - } - -+ // Paper start -+ public Chunk getChunkIfLoaded(BlockPosition blockposition) { -+ return this.chunkProvider.getLoadedChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ } -+ // Paper end -+ - public Chunk getChunkIfLoaded(int x, int z) { - return ((ChunkProviderServer) this.chunkProvider).getChunkIfLoaded(x, z); - } -@@ -682,6 +688,41 @@ public abstract class World implements IBlockAccess { - } - } - -+ // Paper start - test if meets light level, return faster -+ // logic copied from below -+ public boolean isLightLevel(BlockPosition blockposition, int level) { -+ if (isValidLocation(blockposition)) { -+ if (this.getType(blockposition).f()) { -+ if (this.c(blockposition.up(), false) >= level) { -+ return true; -+ } -+ if (this.c(blockposition.east(), false) >= level) { -+ return true; -+ } -+ if (this.c(blockposition.west(), false) >= level) { -+ return true; -+ } -+ if (this.c(blockposition.south(), false) >= level) { -+ return true; -+ } -+ if (this.c(blockposition.north(), false) >= level) { -+ return true; -+ } -+ return false; -+ } else { -+ if (blockposition.getY() >= 256) { -+ blockposition = new BlockPosition(blockposition.getX(), 255, blockposition.getZ()); -+ } -+ -+ Chunk chunk = this.getChunkAtWorldCoords(blockposition); -+ return chunk.a(blockposition, this.J) >= level; -+ } -+ } else { -+ return true; -+ } -+ } -+ // Paper end -+ - public int getLightLevel(BlockPosition blockposition) { - return this.c(blockposition, true); - } -@@ -801,6 +842,27 @@ public abstract class World implements IBlockAccess { - return this.worldProvider.o()[this.getLightLevel(blockposition)]; - } - -+ // Paper start - reduces need to do isLoaded before getType -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ // CraftBukkit start - tree generation -+ if (captureTreeGeneration) { -+ Iterator it = capturedBlockStates.iterator(); -+ while (it.hasNext()) { -+ BlockState previous = it.next(); -+ if (previous.getX() == blockposition.getX() && previous.getY() == blockposition.getY() && previous.getZ() == blockposition.getZ()) { -+ return CraftMagicNumbers.getBlock(previous.getTypeId()).fromLegacyData(previous.getRawData()); -+ } -+ } -+ } -+ // CraftBukkit end -+ Chunk chunk = this.getChunkIfLoaded(blockposition); -+ if (chunk != null) { -+ return this.isValidLocation(blockposition) ? chunk.getBlockData(blockposition) : Blocks.AIR.getBlockData(); -+ } -+ return null; -+ } -+ // Paper end -+ - public IBlockData getType(BlockPosition blockposition) { - // CraftBukkit start - tree generation - if (captureTreeGeneration) { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0076-Optimized-Light-Level-Comparisons.patch b/Spigot-Server-Patches/0076-Optimized-Light-Level-Comparisons.patch new file mode 100644 index 0000000000..c8eec49f6c --- /dev/null +++ b/Spigot-Server-Patches/0076-Optimized-Light-Level-Comparisons.patch @@ -0,0 +1,135 @@ +From ca1b25eea56895788212adb3ecb23dedc8ae132c Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 18 Mar 2016 21:22:56 -0400 +Subject: [PATCH] Optimized Light Level Comparisons + +Use an optimized method to test if a block position meets a desired light level. + +This method benefits from returning as soon as the desired light level matches. + +diff --git a/src/main/java/net/minecraft/server/BlockCrops.java b/src/main/java/net/minecraft/server/BlockCrops.java +index e9c5d1465..9015affc5 100644 +--- a/src/main/java/net/minecraft/server/BlockCrops.java ++++ b/src/main/java/net/minecraft/server/BlockCrops.java +@@ -48,7 +48,7 @@ public class BlockCrops extends BlockPlant implements IBlockFragilePlantElement + + public void b(World world, BlockPosition blockposition, IBlockData iblockdata, Random random) { + super.b(world, blockposition, iblockdata, random); +- if (world.getLightLevel(blockposition.up()) >= 9) { ++ if (world.isLightLevel(blockposition.up(), 9)) { // Paper + int i = this.z(iblockdata); + + if (i < this.g()) { +diff --git a/src/main/java/net/minecraft/server/BlockGrass.java b/src/main/java/net/minecraft/server/BlockGrass.java +index fb1bf80b8..8b43e6070 100644 +--- a/src/main/java/net/minecraft/server/BlockGrass.java ++++ b/src/main/java/net/minecraft/server/BlockGrass.java +@@ -29,7 +29,8 @@ public class BlockGrass extends Block implements IBlockFragilePlantElement { + + public void b(World world, BlockPosition blockposition, IBlockData iblockdata, Random random) { + if (!world.isClientSide) { +- if (world.getLightLevel(blockposition.up()) < 4 && world.getType(blockposition.up()).c() > 2) { ++ int lightLevel = -1; // Paper ++ if (world.getType(blockposition.up()).c() > 2 && (lightLevel = world.getLightLevel(blockposition.up())) < 4) { // Paper - move light check to end to avoid unneeded light lookups + // CraftBukkit start + // world.setTypeUpdate(blockposition, Blocks.DIRT.getBlockData()); + org.bukkit.World bworld = world.getWorld(); +@@ -44,18 +45,25 @@ public class BlockGrass extends Block implements IBlockFragilePlantElement { + } + // CraftBukkit end + } else { +- if (world.getLightLevel(blockposition.up()) >= 9) { ++ // Paper start ++ // If light was calculated above, reuse it, else grab it ++ if (lightLevel == -1) { ++ lightLevel = world.getLightLevel(blockposition.up()); ++ } ++ if (lightLevel >= 9) { ++ // Paper end + for (int i = 0; i < 4; ++i) { + BlockPosition blockposition1 = blockposition.a(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1); + +- if (blockposition1.getY() >= 0 && blockposition1.getY() < 256 && !world.isLoaded(blockposition1)) { ++ IBlockData iblockdata2 = world.getTypeIfLoaded(blockposition1); // Paper - moved up ++ if (iblockdata2 == null) { // Paper + return; + } + + IBlockData iblockdata1 = world.getType(blockposition1.up()); +- IBlockData iblockdata2 = world.getType(blockposition1); ++ //IBlockData iblockdata2 = world.getTypeIfLoaded(blockposition1); // Paper - moved up + +- if (iblockdata2.getBlock() == Blocks.DIRT && iblockdata2.get(BlockDirt.VARIANT) == BlockDirt.EnumDirtVariant.DIRT && world.getLightLevel(blockposition1.up()) >= 4 && iblockdata1.c() <= 2) { ++ if (iblockdata2.getBlock() == Blocks.DIRT && iblockdata2.get(BlockDirt.VARIANT) == BlockDirt.EnumDirtVariant.DIRT && iblockdata1.c() <= 2 && world.isLightLevel(blockposition1.up(), 4)) { // Paper - move last check before isLightLevel to avoid unneeded light checks + // CraftBukkit start + // world.setTypeUpdate(blockposition1, Blocks.GRASS.getBlockData()); + org.bukkit.World bworld = world.getWorld(); +diff --git a/src/main/java/net/minecraft/server/BlockSapling.java b/src/main/java/net/minecraft/server/BlockSapling.java +index f463b7113..89458cd77 100644 +--- a/src/main/java/net/minecraft/server/BlockSapling.java ++++ b/src/main/java/net/minecraft/server/BlockSapling.java +@@ -34,7 +34,7 @@ public class BlockSapling extends BlockPlant implements IBlockFragilePlantElemen + public void b(World world, BlockPosition blockposition, IBlockData iblockdata, Random random) { + if (!world.isClientSide) { + super.b(world, blockposition, iblockdata, random); +- if (world.getLightLevel(blockposition.up()) >= 9 && random.nextInt(Math.max(2, (int) (((100.0F / world.spigotConfig.saplingModifier) * 7) + 0.5F))) == 0) { // Spigot ++ if (world.isLightLevel(blockposition.up(), 9) && random.nextInt(Math.max(2, (int) (((100.0F / world.spigotConfig.saplingModifier) * 7) + 0.5F))) == 0) { // Spigot // Paper + // CraftBukkit start + world.captureTreeGeneration = true; + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/server/BlockStem.java b/src/main/java/net/minecraft/server/BlockStem.java +index c74b6284f..bb96e164e 100644 +--- a/src/main/java/net/minecraft/server/BlockStem.java ++++ b/src/main/java/net/minecraft/server/BlockStem.java +@@ -48,7 +48,7 @@ public class BlockStem extends BlockPlant implements IBlockFragilePlantElement { + + public void b(World world, BlockPosition blockposition, IBlockData iblockdata, Random random) { + super.b(world, blockposition, iblockdata, random); +- if (world.getLightLevel(blockposition.up()) >= 9) { ++ if (world.isLightLevel(blockposition.up(), 9)) { // Paper + float f = BlockCrops.a((Block) this, world, blockposition); + + if (random.nextInt((int) ((100.0F / (this == Blocks.PUMPKIN_STEM ? world.spigotConfig.pumpkinModifier : world.spigotConfig.melonModifier)) * (25.0F / f)) + 1) == 0) { // Spigot +diff --git a/src/main/java/net/minecraft/server/EntityMonster.java b/src/main/java/net/minecraft/server/EntityMonster.java +index 3ee52139c..59d8bb6e7 100644 +--- a/src/main/java/net/minecraft/server/EntityMonster.java ++++ b/src/main/java/net/minecraft/server/EntityMonster.java +@@ -118,17 +118,17 @@ public abstract class EntityMonster extends EntityCreature implements IMonster { + if (this.world.getBrightness(EnumSkyBlock.SKY, blockposition) > this.random.nextInt(32)) { + return false; + } else { +- int i = this.world.getLightLevel(blockposition); +- ++ //int i = this.world.getLightLevel(blockposition); // Paper ++ boolean passes; // Paper + if (this.world.V()) { + int j = this.world.af(); + + this.world.c(10); +- i = this.world.getLightLevel(blockposition); ++ passes = !world.isLightLevel(blockposition, this.random.nextInt(9)); // Paper + this.world.c(j); +- } ++ } else { passes = !world.isLightLevel(blockposition, this.random.nextInt(9)); } // Paper + +- return i <= this.random.nextInt(8); ++ return passes; // Paper + } + } + +diff --git a/src/main/java/net/minecraft/server/EntityZombie.java b/src/main/java/net/minecraft/server/EntityZombie.java +index 897882c97..970fabf71 100644 +--- a/src/main/java/net/minecraft/server/EntityZombie.java ++++ b/src/main/java/net/minecraft/server/EntityZombie.java +@@ -178,7 +178,7 @@ public class EntityZombie extends EntityMonster { + int j1 = j + MathHelper.nextInt(this.random, 7, 40) * MathHelper.nextInt(this.random, -1, 1); + int k1 = k + MathHelper.nextInt(this.random, 7, 40) * MathHelper.nextInt(this.random, -1, 1); + +- if (this.world.getType(new BlockPosition(i1, j1 - 1, k1)).r() && this.world.getLightLevel(new BlockPosition(i1, j1, k1)) < 10) { ++ if (this.world.getType(new BlockPosition(i1, j1 - 1, k1)).r() && !this.world.isLightLevel(new BlockPosition(i1, j1, k1), 10)) { // Paper + entityzombie.setPosition((double) i1, (double) j1, (double) k1); + if (!this.world.isPlayerNearby((double) i1, (double) j1, (double) k1, 7.0D) && this.world.a(entityzombie.getBoundingBox(), (Entity) entityzombie) && this.world.getCubes(entityzombie, entityzombie.getBoundingBox()).isEmpty() && !this.world.containsLiquid(entityzombie.getBoundingBox())) { + this.world.addEntity(entityzombie, CreatureSpawnEvent.SpawnReason.REINFORCEMENTS); // CraftBukkit +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0077-Optimized-Light-Level-Comparisons.patch b/Spigot-Server-Patches/0077-Optimized-Light-Level-Comparisons.patch deleted file mode 100644 index 0379be7100..0000000000 --- a/Spigot-Server-Patches/0077-Optimized-Light-Level-Comparisons.patch +++ /dev/null @@ -1,135 +0,0 @@ -From f9f7cf2e61b9417615c1eec1229bb54569db0d0d Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Mar 2016 21:22:56 -0400 -Subject: [PATCH] Optimized Light Level Comparisons - -Use an optimized method to test if a block position meets a desired light level. - -This method benefits from returning as soon as the desired light level matches. - -diff --git a/src/main/java/net/minecraft/server/BlockCrops.java b/src/main/java/net/minecraft/server/BlockCrops.java -index e9c5d1465..9015affc5 100644 ---- a/src/main/java/net/minecraft/server/BlockCrops.java -+++ b/src/main/java/net/minecraft/server/BlockCrops.java -@@ -48,7 +48,7 @@ public class BlockCrops extends BlockPlant implements IBlockFragilePlantElement - - public void b(World world, BlockPosition blockposition, IBlockData iblockdata, Random random) { - super.b(world, blockposition, iblockdata, random); -- if (world.getLightLevel(blockposition.up()) >= 9) { -+ if (world.isLightLevel(blockposition.up(), 9)) { // Paper - int i = this.z(iblockdata); - - if (i < this.g()) { -diff --git a/src/main/java/net/minecraft/server/BlockGrass.java b/src/main/java/net/minecraft/server/BlockGrass.java -index fb1bf80b8..8b43e6070 100644 ---- a/src/main/java/net/minecraft/server/BlockGrass.java -+++ b/src/main/java/net/minecraft/server/BlockGrass.java -@@ -29,7 +29,8 @@ public class BlockGrass extends Block implements IBlockFragilePlantElement { - - public void b(World world, BlockPosition blockposition, IBlockData iblockdata, Random random) { - if (!world.isClientSide) { -- if (world.getLightLevel(blockposition.up()) < 4 && world.getType(blockposition.up()).c() > 2) { -+ int lightLevel = -1; // Paper -+ if (world.getType(blockposition.up()).c() > 2 && (lightLevel = world.getLightLevel(blockposition.up())) < 4) { // Paper - move light check to end to avoid unneeded light lookups - // CraftBukkit start - // world.setTypeUpdate(blockposition, Blocks.DIRT.getBlockData()); - org.bukkit.World bworld = world.getWorld(); -@@ -44,18 +45,25 @@ public class BlockGrass extends Block implements IBlockFragilePlantElement { - } - // CraftBukkit end - } else { -- if (world.getLightLevel(blockposition.up()) >= 9) { -+ // Paper start -+ // If light was calculated above, reuse it, else grab it -+ if (lightLevel == -1) { -+ lightLevel = world.getLightLevel(blockposition.up()); -+ } -+ if (lightLevel >= 9) { -+ // Paper end - for (int i = 0; i < 4; ++i) { - BlockPosition blockposition1 = blockposition.a(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1); - -- if (blockposition1.getY() >= 0 && blockposition1.getY() < 256 && !world.isLoaded(blockposition1)) { -+ IBlockData iblockdata2 = world.getTypeIfLoaded(blockposition1); // Paper - moved up -+ if (iblockdata2 == null) { // Paper - return; - } - - IBlockData iblockdata1 = world.getType(blockposition1.up()); -- IBlockData iblockdata2 = world.getType(blockposition1); -+ //IBlockData iblockdata2 = world.getTypeIfLoaded(blockposition1); // Paper - moved up - -- if (iblockdata2.getBlock() == Blocks.DIRT && iblockdata2.get(BlockDirt.VARIANT) == BlockDirt.EnumDirtVariant.DIRT && world.getLightLevel(blockposition1.up()) >= 4 && iblockdata1.c() <= 2) { -+ if (iblockdata2.getBlock() == Blocks.DIRT && iblockdata2.get(BlockDirt.VARIANT) == BlockDirt.EnumDirtVariant.DIRT && iblockdata1.c() <= 2 && world.isLightLevel(blockposition1.up(), 4)) { // Paper - move last check before isLightLevel to avoid unneeded light checks - // CraftBukkit start - // world.setTypeUpdate(blockposition1, Blocks.GRASS.getBlockData()); - org.bukkit.World bworld = world.getWorld(); -diff --git a/src/main/java/net/minecraft/server/BlockSapling.java b/src/main/java/net/minecraft/server/BlockSapling.java -index f463b7113..89458cd77 100644 ---- a/src/main/java/net/minecraft/server/BlockSapling.java -+++ b/src/main/java/net/minecraft/server/BlockSapling.java -@@ -34,7 +34,7 @@ public class BlockSapling extends BlockPlant implements IBlockFragilePlantElemen - public void b(World world, BlockPosition blockposition, IBlockData iblockdata, Random random) { - if (!world.isClientSide) { - super.b(world, blockposition, iblockdata, random); -- if (world.getLightLevel(blockposition.up()) >= 9 && random.nextInt(Math.max(2, (int) (((100.0F / world.spigotConfig.saplingModifier) * 7) + 0.5F))) == 0) { // Spigot -+ if (world.isLightLevel(blockposition.up(), 9) && random.nextInt(Math.max(2, (int) (((100.0F / world.spigotConfig.saplingModifier) * 7) + 0.5F))) == 0) { // Spigot // Paper - // CraftBukkit start - world.captureTreeGeneration = true; - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/server/BlockStem.java b/src/main/java/net/minecraft/server/BlockStem.java -index c74b6284f..bb96e164e 100644 ---- a/src/main/java/net/minecraft/server/BlockStem.java -+++ b/src/main/java/net/minecraft/server/BlockStem.java -@@ -48,7 +48,7 @@ public class BlockStem extends BlockPlant implements IBlockFragilePlantElement { - - public void b(World world, BlockPosition blockposition, IBlockData iblockdata, Random random) { - super.b(world, blockposition, iblockdata, random); -- if (world.getLightLevel(blockposition.up()) >= 9) { -+ if (world.isLightLevel(blockposition.up(), 9)) { // Paper - float f = BlockCrops.a((Block) this, world, blockposition); - - if (random.nextInt((int) ((100.0F / (this == Blocks.PUMPKIN_STEM ? world.spigotConfig.pumpkinModifier : world.spigotConfig.melonModifier)) * (25.0F / f)) + 1) == 0) { // Spigot -diff --git a/src/main/java/net/minecraft/server/EntityMonster.java b/src/main/java/net/minecraft/server/EntityMonster.java -index 3ee52139c..59d8bb6e7 100644 ---- a/src/main/java/net/minecraft/server/EntityMonster.java -+++ b/src/main/java/net/minecraft/server/EntityMonster.java -@@ -118,17 +118,17 @@ public abstract class EntityMonster extends EntityCreature implements IMonster { - if (this.world.getBrightness(EnumSkyBlock.SKY, blockposition) > this.random.nextInt(32)) { - return false; - } else { -- int i = this.world.getLightLevel(blockposition); -- -+ //int i = this.world.getLightLevel(blockposition); // Paper -+ boolean passes; // Paper - if (this.world.V()) { - int j = this.world.af(); - - this.world.c(10); -- i = this.world.getLightLevel(blockposition); -+ passes = !world.isLightLevel(blockposition, this.random.nextInt(9)); // Paper - this.world.c(j); -- } -+ } else { passes = !world.isLightLevel(blockposition, this.random.nextInt(9)); } // Paper - -- return i <= this.random.nextInt(8); -+ return passes; // Paper - } - } - -diff --git a/src/main/java/net/minecraft/server/EntityZombie.java b/src/main/java/net/minecraft/server/EntityZombie.java -index 897882c97..970fabf71 100644 ---- a/src/main/java/net/minecraft/server/EntityZombie.java -+++ b/src/main/java/net/minecraft/server/EntityZombie.java -@@ -178,7 +178,7 @@ public class EntityZombie extends EntityMonster { - int j1 = j + MathHelper.nextInt(this.random, 7, 40) * MathHelper.nextInt(this.random, -1, 1); - int k1 = k + MathHelper.nextInt(this.random, 7, 40) * MathHelper.nextInt(this.random, -1, 1); - -- if (this.world.getType(new BlockPosition(i1, j1 - 1, k1)).r() && this.world.getLightLevel(new BlockPosition(i1, j1, k1)) < 10) { -+ if (this.world.getType(new BlockPosition(i1, j1 - 1, k1)).r() && !this.world.isLightLevel(new BlockPosition(i1, j1, k1), 10)) { // Paper - entityzombie.setPosition((double) i1, (double) j1, (double) k1); - if (!this.world.isPlayerNearby((double) i1, (double) j1, (double) k1, 7.0D) && this.world.a(entityzombie.getBoundingBox(), (Entity) entityzombie) && this.world.getCubes(entityzombie, entityzombie.getBoundingBox()).isEmpty() && !this.world.containsLiquid(entityzombie.getBoundingBox())) { - this.world.addEntity(entityzombie, CreatureSpawnEvent.SpawnReason.REINFORCEMENTS); // CraftBukkit --- -2.12.2 - diff --git a/Spigot-Server-Patches/0077-Pass-world-to-Village-creation.patch b/Spigot-Server-Patches/0077-Pass-world-to-Village-creation.patch new file mode 100644 index 0000000000..192e3aefce --- /dev/null +++ b/Spigot-Server-Patches/0077-Pass-world-to-Village-creation.patch @@ -0,0 +1,36 @@ +From 7cb360d7aec57c15e7ce8b669d28fd9de086ffc3 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 19 Mar 2016 15:16:54 -0400 +Subject: [PATCH] Pass world to Village creation + +fixes NPE bug #95 + +diff --git a/src/main/java/net/minecraft/server/PersistentVillage.java b/src/main/java/net/minecraft/server/PersistentVillage.java +index a5b79ecad..01f7cee38 100644 +--- a/src/main/java/net/minecraft/server/PersistentVillage.java ++++ b/src/main/java/net/minecraft/server/PersistentVillage.java +@@ -238,7 +238,7 @@ public class PersistentVillage extends PersistentBase { + + for (int i = 0; i < nbttaglist.size(); ++i) { + NBTTagCompound nbttagcompound1 = nbttaglist.get(i); +- Village village = new Village(); ++ Village village = new Village(world); // Paper + + village.a(nbttagcompound1); + this.villages.add(village); +diff --git a/src/main/java/net/minecraft/server/Village.java b/src/main/java/net/minecraft/server/Village.java +index 2ab381d50..817c836c3 100644 +--- a/src/main/java/net/minecraft/server/Village.java ++++ b/src/main/java/net/minecraft/server/Village.java +@@ -24,7 +24,7 @@ public class Village { + private final List k; + private int l; + +- public Village() { ++ private Village() { // Paper - Nothing should call this - world needs to be set. + this.c = BlockPosition.ZERO; + this.d = BlockPosition.ZERO; + this.j = Maps.newHashMap(); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0078-Custom-replacement-for-eaten-items.patch b/Spigot-Server-Patches/0078-Custom-replacement-for-eaten-items.patch new file mode 100644 index 0000000000..4893c0baf7 --- /dev/null +++ b/Spigot-Server-Patches/0078-Custom-replacement-for-eaten-items.patch @@ -0,0 +1,50 @@ +From c267a846efc3860d0dd8c2664eb5363fcf2c2f01 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/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java +index 247224117..9cb3b22fb 100644 +--- a/src/main/java/net/minecraft/server/EntityLiving.java ++++ b/src/main/java/net/minecraft/server/EntityLiving.java +@@ -2323,12 +2323,13 @@ public abstract class EntityLiving extends Entity { + + protected void v() { + if (!this.activeItem.isEmpty() && this.isHandRaised()) { ++ PlayerItemConsumeEvent event = null; // Paper + this.a(this.activeItem, 16); + // CraftBukkit start - fire PlayerItemConsumeEvent + ItemStack itemstack; + 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()) { +@@ -2343,9 +2344,21 @@ public abstract class EntityLiving extends Entity { + 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 ++ + this.a(this.cz(), itemstack); + // CraftBukkit end + this.cF(); ++ ++ // 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(); ++ } + } + + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0078-Pass-world-to-Village-creation.patch b/Spigot-Server-Patches/0078-Pass-world-to-Village-creation.patch deleted file mode 100644 index 0ccf26d36d..0000000000 --- a/Spigot-Server-Patches/0078-Pass-world-to-Village-creation.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 2914df909b71dac220c18c9b220de90f2fce300c Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 19 Mar 2016 15:16:54 -0400 -Subject: [PATCH] Pass world to Village creation - -fixes NPE bug #95 - -diff --git a/src/main/java/net/minecraft/server/PersistentVillage.java b/src/main/java/net/minecraft/server/PersistentVillage.java -index a5b79ecad..01f7cee38 100644 ---- a/src/main/java/net/minecraft/server/PersistentVillage.java -+++ b/src/main/java/net/minecraft/server/PersistentVillage.java -@@ -238,7 +238,7 @@ public class PersistentVillage extends PersistentBase { - - for (int i = 0; i < nbttaglist.size(); ++i) { - NBTTagCompound nbttagcompound1 = nbttaglist.get(i); -- Village village = new Village(); -+ Village village = new Village(world); // Paper - - village.a(nbttagcompound1); - this.villages.add(village); -diff --git a/src/main/java/net/minecraft/server/Village.java b/src/main/java/net/minecraft/server/Village.java -index 2ab381d50..817c836c3 100644 ---- a/src/main/java/net/minecraft/server/Village.java -+++ b/src/main/java/net/minecraft/server/Village.java -@@ -24,7 +24,7 @@ public class Village { - private final List k; - private int l; - -- public Village() { -+ private Village() { // Paper - Nothing should call this - world needs to be set. - this.c = BlockPosition.ZERO; - this.d = BlockPosition.ZERO; - this.j = Maps.newHashMap(); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0079-Custom-replacement-for-eaten-items.patch b/Spigot-Server-Patches/0079-Custom-replacement-for-eaten-items.patch deleted file mode 100644 index 70608f2819..0000000000 --- a/Spigot-Server-Patches/0079-Custom-replacement-for-eaten-items.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 37773c2d575050daa8addd625bf40b28ee74a5a0 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/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index 247224117..9cb3b22fb 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -2323,12 +2323,13 @@ public abstract class EntityLiving extends Entity { - - protected void v() { - if (!this.activeItem.isEmpty() && this.isHandRaised()) { -+ PlayerItemConsumeEvent event = null; // Paper - this.a(this.activeItem, 16); - // CraftBukkit start - fire PlayerItemConsumeEvent - ItemStack itemstack; - 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()) { -@@ -2343,9 +2344,21 @@ public abstract class EntityLiving extends Entity { - 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 -+ - this.a(this.cz(), itemstack); - // CraftBukkit end - this.cF(); -+ -+ // 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(); -+ } - } - - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0079-Set-health-before-death-event.patch b/Spigot-Server-Patches/0079-Set-health-before-death-event.patch new file mode 100644 index 0000000000..5efb3cfdc5 --- /dev/null +++ b/Spigot-Server-Patches/0079-Set-health-before-death-event.patch @@ -0,0 +1,49 @@ +From 4cea4a67fa45178c59807df4f21b86b09b88574e Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Sun, 19 Jul 2015 16:51:38 -0400 +Subject: [PATCH] Set health before death event + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index b5ff26c71..6907d4680 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -215,4 +215,9 @@ public class PaperConfig { + private static void loadPermsBeforePlugins() { + loadPermsBeforePlugins = getBoolean("settings.load-permissions-yml-before-plugins", true); + } ++ ++ public static boolean setHealthBeforeDeathEvent = false; ++ private static void healthDeath() { ++ setHealthBeforeDeathEvent = getBoolean("settings.set-health-before-death-event", false); ++ } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 348a8c758..c0103cb39 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -102,11 +102,20 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + + (this instanceof CraftPlayer ? ", player: " + this.getName() + ')' : ')')); + } + ++ // Paper start ++ if (com.destroystokyo.paper.PaperConfig.setHealthBeforeDeathEvent) { ++ this.getHandle().setHealth((float) health); ++ } ++ + if (health == 0) { + getHandle().die(DamageSource.GENERIC); + } + +- getHandle().setHealth((float) health); ++ // Paper start - wrap, see above ++ if (!com.destroystokyo.paper.PaperConfig.setHealthBeforeDeathEvent) { ++ getHandle().setHealth((float) health); ++ } ++ // Paper end + } + + public double getMaxHealth() { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0080-Set-health-before-death-event.patch b/Spigot-Server-Patches/0080-Set-health-before-death-event.patch deleted file mode 100644 index 295892b195..0000000000 --- a/Spigot-Server-Patches/0080-Set-health-before-death-event.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 376c4082cf93f2688de0d051a121f20b5c8ba326 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sun, 19 Jul 2015 16:51:38 -0400 -Subject: [PATCH] Set health before death event - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index b5ff26c71..6907d4680 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -215,4 +215,9 @@ public class PaperConfig { - private static void loadPermsBeforePlugins() { - loadPermsBeforePlugins = getBoolean("settings.load-permissions-yml-before-plugins", true); - } -+ -+ public static boolean setHealthBeforeDeathEvent = false; -+ private static void healthDeath() { -+ setHealthBeforeDeathEvent = getBoolean("settings.set-health-before-death-event", false); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 348a8c758..c0103cb39 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -102,11 +102,20 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - + (this instanceof CraftPlayer ? ", player: " + this.getName() + ')' : ')')); - } - -+ // Paper start -+ if (com.destroystokyo.paper.PaperConfig.setHealthBeforeDeathEvent) { -+ this.getHandle().setHealth((float) health); -+ } -+ - if (health == 0) { - getHandle().die(DamageSource.GENERIC); - } - -- getHandle().setHealth((float) health); -+ // Paper start - wrap, see above -+ if (!com.destroystokyo.paper.PaperConfig.setHealthBeforeDeathEvent) { -+ getHandle().setHealth((float) health); -+ } -+ // Paper end - } - - public double getMaxHealth() { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0080-handle-NaN-health-absorb-values-and-repair-bad-data.patch b/Spigot-Server-Patches/0080-handle-NaN-health-absorb-values-and-repair-bad-data.patch new file mode 100644 index 0000000000..4261b88323 --- /dev/null +++ b/Spigot-Server-Patches/0080-handle-NaN-health-absorb-values-and-repair-bad-data.patch @@ -0,0 +1,60 @@ +From 59332750bfa25c9dafc31afa9d52f2442ec5205f 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/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java +index 9cb3b22fb..c70f14a15 100644 +--- a/src/main/java/net/minecraft/server/EntityLiving.java ++++ b/src/main/java/net/minecraft/server/EntityLiving.java +@@ -481,7 +481,13 @@ public abstract class EntityLiving extends Entity { + } + + public void a(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) { + GenericAttributes.a(this.getAttributeMap(), nbttagcompound.getList("Attributes", 10)); + } +@@ -780,6 +786,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(); +@@ -2211,7 +2221,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 dd8380f71..0a9e8b9cd 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1398,6 +1398,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + + public void setRealHealth(double health) { ++ if (Double.isNaN(health)) {return;} // Paper + this.health = health; + } + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0081-Catch-Async-PlayerChunkMap-operations.patch b/Spigot-Server-Patches/0081-Catch-Async-PlayerChunkMap-operations.patch new file mode 100644 index 0000000000..e204f25dcb --- /dev/null +++ b/Spigot-Server-Patches/0081-Catch-Async-PlayerChunkMap-operations.patch @@ -0,0 +1,26 @@ +From 7a4c9cc8f43dd8cb13ceafc6b4360c58a40c5e7a Mon Sep 17 00:00:00 2001 +From: Daniel Ennis +Date: Sun, 20 Mar 2016 15:22:42 -0400 +Subject: [PATCH] Catch Async PlayerChunkMap operations + + +diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java +index 9012a63a0..5b27bd1c5 100644 +--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java +@@ -469,10 +469,12 @@ public class PlayerChunkMap { + } + + public void a(PlayerChunk playerchunk) { ++ org.spigotmc.AsyncCatcher.catchOp("Async Player Chunk Add"); // Paper + this.f.add(playerchunk); + } + + public void b(PlayerChunk playerchunk) { ++ org.spigotmc.AsyncCatcher.catchOp("Async Player Chunk Remove"); // Paper + ChunkCoordIntPair chunkcoordintpair = playerchunk.a(); + long i = d(chunkcoordintpair.x, chunkcoordintpair.z); + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0081-handle-NaN-health-absorb-values-and-repair-bad-data.patch b/Spigot-Server-Patches/0081-handle-NaN-health-absorb-values-and-repair-bad-data.patch deleted file mode 100644 index bb4e675b62..0000000000 --- a/Spigot-Server-Patches/0081-handle-NaN-health-absorb-values-and-repair-bad-data.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 04de121f6f8d6af28cb652b11cd17feec668ce9e 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/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index 9cb3b22fb..c70f14a15 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -481,7 +481,13 @@ public abstract class EntityLiving extends Entity { - } - - public void a(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) { - GenericAttributes.a(this.getAttributeMap(), nbttagcompound.getList("Attributes", 10)); - } -@@ -780,6 +786,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(); -@@ -2211,7 +2221,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 5fd5e39fa..80a6a0b41 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1398,6 +1398,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - public void setRealHealth(double health) { -+ if (Double.isNaN(health)) {return;} // Paper - this.health = health; - } - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0082-Catch-Async-PlayerChunkMap-operations.patch b/Spigot-Server-Patches/0082-Catch-Async-PlayerChunkMap-operations.patch deleted file mode 100644 index b4d23c424e..0000000000 --- a/Spigot-Server-Patches/0082-Catch-Async-PlayerChunkMap-operations.patch +++ /dev/null @@ -1,26 +0,0 @@ -From a5080daa55ef68c39c367086483795eb455cf451 Mon Sep 17 00:00:00 2001 -From: Daniel Ennis -Date: Sun, 20 Mar 2016 15:22:42 -0400 -Subject: [PATCH] Catch Async PlayerChunkMap operations - - -diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java -index 9012a63a0..5b27bd1c5 100644 ---- a/src/main/java/net/minecraft/server/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java -@@ -469,10 +469,12 @@ public class PlayerChunkMap { - } - - public void a(PlayerChunk playerchunk) { -+ org.spigotmc.AsyncCatcher.catchOp("Async Player Chunk Add"); // Paper - this.f.add(playerchunk); - } - - public void b(PlayerChunk playerchunk) { -+ org.spigotmc.AsyncCatcher.catchOp("Async Player Chunk Remove"); // Paper - ChunkCoordIntPair chunkcoordintpair = playerchunk.a(); - long i = d(chunkcoordintpair.x, chunkcoordintpair.z); - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0082-Support-offline-mode-in-whitelist-command-as-well.patch b/Spigot-Server-Patches/0082-Support-offline-mode-in-whitelist-command-as-well.patch new file mode 100644 index 0000000000..4db1720329 --- /dev/null +++ b/Spigot-Server-Patches/0082-Support-offline-mode-in-whitelist-command-as-well.patch @@ -0,0 +1,93 @@ +From 08efbaa590f1d22457b23dac04cc88535f84da74 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 21 Mar 2016 00:19:18 -0500 +Subject: [PATCH] Support offline mode in whitelist command as well + + +diff --git a/src/main/java/net/minecraft/server/CommandWhitelist.java b/src/main/java/net/minecraft/server/CommandWhitelist.java +index c74d1d2be..0f4237db1 100644 +--- a/src/main/java/net/minecraft/server/CommandWhitelist.java ++++ b/src/main/java/net/minecraft/server/CommandWhitelist.java +@@ -44,24 +44,35 @@ public class CommandWhitelist extends CommandAbstract { + throw new ExceptionUsage("commands.whitelist.add.usage", new Object[0]); + } + ++ // Paper start - Handle offline mode as well ++ /* + gameprofile = minecraftserver.getUserCache().getProfile(astring[1]); + if (gameprofile == null) { + throw new CommandException("commands.whitelist.add.failed", new Object[] { astring[1]}); + } + + minecraftserver.getPlayerList().addWhitelist(gameprofile); ++ */ ++ this.whitelist(minecraftserver, astring[1], true); ++ // Paper end + a(icommandlistener, (ICommand) this, "commands.whitelist.add.success", new Object[] { astring[1]}); + } else if ("remove".equals(astring[0])) { + if (astring.length < 2) { + throw new ExceptionUsage("commands.whitelist.remove.usage", new Object[0]); + } + ++ // Paper start - Handle offline mode as well ++ /* + gameprofile = minecraftserver.getPlayerList().getWhitelist().a(astring[1]); + if (gameprofile == null) { + throw new CommandException("commands.whitelist.remove.failed", new Object[] { astring[1]}); + } + + minecraftserver.getPlayerList().removeWhitelist(gameprofile); ++ ++ */ ++ this.whitelist(minecraftserver, astring[1], false); ++ // Paper end + a(icommandlistener, (ICommand) this, "commands.whitelist.remove.success", new Object[] { astring[1]}); + } else if ("reload".equals(astring[0])) { + minecraftserver.getPlayerList().reloadWhitelist(); +@@ -89,4 +100,43 @@ public class CommandWhitelist extends CommandAbstract { + return Collections.emptyList(); + } + } ++ ++ // Paper start ++ /** ++ * Adds or removes a player from the game whitelist ++ * ++ * @param mcserver running instance of MinecraftServer ++ * @param playerName the player we're going to be whitelisting ++ * @param add whether we're adding or removing from the whitelist ++ */ ++ private void whitelist(MinecraftServer mcserver, String playerName, boolean add) throws CommandException { ++ if (mcserver.getOnlineMode()) { ++ // The reason we essentially copy/pasta NMS code here is because the NMS online-only version ++ // is capable of providing feedback to the person running the command based on whether or ++ // not the player is a real online-mode account ++ GameProfile gameprofile = mcserver.getUserCache().getProfile(playerName); ++ if (gameprofile == null) { ++ if (add) { ++ throw new CommandException("commands.whitelist.add.failed", new Object[] { playerName}); ++ } else { ++ throw new CommandException("commands.whitelist.remove.failed", new Object[] { playerName}); ++ } ++ } ++ ++ if (add) { ++ mcserver.getPlayerList().addWhitelist(gameprofile); ++ } else { ++ mcserver.getPlayerList().removeWhitelist(gameprofile); ++ } ++ } else { ++ // versus our offline version, which will always report success all of the time ++ org.bukkit.OfflinePlayer offlinePlayer = org.bukkit.Bukkit.getOfflinePlayer(playerName); ++ if (add) { ++ offlinePlayer.setWhitelisted(true); ++ } else { ++ offlinePlayer.setWhitelisted(false); ++ } ++ } ++ } ++ // Paper end + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0083-Fix-SkullCache-case-bug.patch b/Spigot-Server-Patches/0083-Fix-SkullCache-case-bug.patch new file mode 100644 index 0000000000..9113bf809b --- /dev/null +++ b/Spigot-Server-Patches/0083-Fix-SkullCache-case-bug.patch @@ -0,0 +1,22 @@ +From b15951b4c90b25f3db552de1d9032a5daf99fc43 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 5 Jan 2016 21:48:24 -0500 +Subject: [PATCH] Fix SkullCache case bug + + +diff --git a/src/main/java/net/minecraft/server/TileEntitySkull.java b/src/main/java/net/minecraft/server/TileEntitySkull.java +index 91ca4a279..edd6fb69e 100644 +--- a/src/main/java/net/minecraft/server/TileEntitySkull.java ++++ b/src/main/java/net/minecraft/server/TileEntitySkull.java +@@ -191,7 +191,7 @@ public class TileEntitySkull extends TileEntity implements ITickable { + } else if (MinecraftServer.getServer() == null) { + callback.apply(gameprofile); + } else { +- GameProfile profile = skinCache.getIfPresent(gameprofile.getName()); ++ GameProfile profile = skinCache.getIfPresent(gameprofile.getName().toLowerCase()); // Paper + if (profile != null && Iterables.getFirst(profile.getProperties().get("textures"), (Object) null) != null) { + callback.apply(profile); + } else { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0083-Support-offline-mode-in-whitelist-command-as-well.patch b/Spigot-Server-Patches/0083-Support-offline-mode-in-whitelist-command-as-well.patch deleted file mode 100644 index ff4beb4abb..0000000000 --- a/Spigot-Server-Patches/0083-Support-offline-mode-in-whitelist-command-as-well.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 139e93117fa8452adb2be851e7dd957dd824d702 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 21 Mar 2016 00:19:18 -0500 -Subject: [PATCH] Support offline mode in whitelist command as well - - -diff --git a/src/main/java/net/minecraft/server/CommandWhitelist.java b/src/main/java/net/minecraft/server/CommandWhitelist.java -index c74d1d2be..0f4237db1 100644 ---- a/src/main/java/net/minecraft/server/CommandWhitelist.java -+++ b/src/main/java/net/minecraft/server/CommandWhitelist.java -@@ -44,24 +44,35 @@ public class CommandWhitelist extends CommandAbstract { - throw new ExceptionUsage("commands.whitelist.add.usage", new Object[0]); - } - -+ // Paper start - Handle offline mode as well -+ /* - gameprofile = minecraftserver.getUserCache().getProfile(astring[1]); - if (gameprofile == null) { - throw new CommandException("commands.whitelist.add.failed", new Object[] { astring[1]}); - } - - minecraftserver.getPlayerList().addWhitelist(gameprofile); -+ */ -+ this.whitelist(minecraftserver, astring[1], true); -+ // Paper end - a(icommandlistener, (ICommand) this, "commands.whitelist.add.success", new Object[] { astring[1]}); - } else if ("remove".equals(astring[0])) { - if (astring.length < 2) { - throw new ExceptionUsage("commands.whitelist.remove.usage", new Object[0]); - } - -+ // Paper start - Handle offline mode as well -+ /* - gameprofile = minecraftserver.getPlayerList().getWhitelist().a(astring[1]); - if (gameprofile == null) { - throw new CommandException("commands.whitelist.remove.failed", new Object[] { astring[1]}); - } - - minecraftserver.getPlayerList().removeWhitelist(gameprofile); -+ -+ */ -+ this.whitelist(minecraftserver, astring[1], false); -+ // Paper end - a(icommandlistener, (ICommand) this, "commands.whitelist.remove.success", new Object[] { astring[1]}); - } else if ("reload".equals(astring[0])) { - minecraftserver.getPlayerList().reloadWhitelist(); -@@ -89,4 +100,43 @@ public class CommandWhitelist extends CommandAbstract { - return Collections.emptyList(); - } - } -+ -+ // Paper start -+ /** -+ * Adds or removes a player from the game whitelist -+ * -+ * @param mcserver running instance of MinecraftServer -+ * @param playerName the player we're going to be whitelisting -+ * @param add whether we're adding or removing from the whitelist -+ */ -+ private void whitelist(MinecraftServer mcserver, String playerName, boolean add) throws CommandException { -+ if (mcserver.getOnlineMode()) { -+ // The reason we essentially copy/pasta NMS code here is because the NMS online-only version -+ // is capable of providing feedback to the person running the command based on whether or -+ // not the player is a real online-mode account -+ GameProfile gameprofile = mcserver.getUserCache().getProfile(playerName); -+ if (gameprofile == null) { -+ if (add) { -+ throw new CommandException("commands.whitelist.add.failed", new Object[] { playerName}); -+ } else { -+ throw new CommandException("commands.whitelist.remove.failed", new Object[] { playerName}); -+ } -+ } -+ -+ if (add) { -+ mcserver.getPlayerList().addWhitelist(gameprofile); -+ } else { -+ mcserver.getPlayerList().removeWhitelist(gameprofile); -+ } -+ } else { -+ // versus our offline version, which will always report success all of the time -+ org.bukkit.OfflinePlayer offlinePlayer = org.bukkit.Bukkit.getOfflinePlayer(playerName); -+ if (add) { -+ offlinePlayer.setWhitelisted(true); -+ } else { -+ offlinePlayer.setWhitelisted(false); -+ } -+ } -+ } -+ // Paper end - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0084-Fix-SkullCache-case-bug.patch b/Spigot-Server-Patches/0084-Fix-SkullCache-case-bug.patch deleted file mode 100644 index b3741f9043..0000000000 --- a/Spigot-Server-Patches/0084-Fix-SkullCache-case-bug.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 41e002267b87e75db128ca73dec84b7636afde2b Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 5 Jan 2016 21:48:24 -0500 -Subject: [PATCH] Fix SkullCache case bug - - -diff --git a/src/main/java/net/minecraft/server/TileEntitySkull.java b/src/main/java/net/minecraft/server/TileEntitySkull.java -index 91ca4a279..edd6fb69e 100644 ---- a/src/main/java/net/minecraft/server/TileEntitySkull.java -+++ b/src/main/java/net/minecraft/server/TileEntitySkull.java -@@ -191,7 +191,7 @@ public class TileEntitySkull extends TileEntity implements ITickable { - } else if (MinecraftServer.getServer() == null) { - callback.apply(gameprofile); - } else { -- GameProfile profile = skinCache.getIfPresent(gameprofile.getName()); -+ GameProfile profile = skinCache.getIfPresent(gameprofile.getName().toLowerCase()); // Paper - if (profile != null && Iterables.getFirst(profile.getProperties().get("textures"), (Object) null) != null) { - callback.apply(profile); - } else { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0084-Waving-banner-workaround.patch b/Spigot-Server-Patches/0084-Waving-banner-workaround.patch new file mode 100644 index 0000000000..c78b289980 --- /dev/null +++ b/Spigot-Server-Patches/0084-Waving-banner-workaround.patch @@ -0,0 +1,38 @@ +From 9db8303c4d0edf7f783e2f8656b2f8f68fae80cb Mon Sep 17 00:00:00 2001 +From: Gabscap +Date: Sat, 19 Mar 2016 22:25:11 +0100 +Subject: [PATCH] Waving banner workaround + +This patch is a workaround for MC-63720 + +diff --git a/src/main/java/net/minecraft/server/PacketPlayOutUpdateTime.java b/src/main/java/net/minecraft/server/PacketPlayOutUpdateTime.java +index c5c3f40ce..6413f76e7 100644 +--- a/src/main/java/net/minecraft/server/PacketPlayOutUpdateTime.java ++++ b/src/main/java/net/minecraft/server/PacketPlayOutUpdateTime.java +@@ -4,7 +4,13 @@ import java.io.IOException; + + public class PacketPlayOutUpdateTime implements Packet { + ++ // World Age in ticks ++ // Not changed by server commands ++ // World Age must not be negative + private long a; ++ // Time of Day in ticks ++ // If negative the sun will stop moving at the Math.abs of the time ++ // Displayed in the debug screen (F3) + private long b; + + public PacketPlayOutUpdateTime() {} +@@ -19,6 +25,9 @@ public class PacketPlayOutUpdateTime implements Packet { + } + } + ++ // Paper start ++ this.a = this.a % 192000; ++ // Paper end + } + + public void a(PacketDataSerializer packetdataserializer) throws IOException { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0085-Use-a-Shared-Random-for-Entities.patch b/Spigot-Server-Patches/0085-Use-a-Shared-Random-for-Entities.patch new file mode 100644 index 0000000000..e133a7e842 --- /dev/null +++ b/Spigot-Server-Patches/0085-Use-a-Shared-Random-for-Entities.patch @@ -0,0 +1,31 @@ +From ce002ce8991131c9acfba45b64c942a8b97b932d 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/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index be54c807b..42bd79b10 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -46,6 +46,7 @@ public abstract class Entity implements ICommandListener { + + // CraftBukkit start + private static final int CURRENT_LEVEL = 2; ++ public static Random SHARED_RANDOM = new Random(); // Paper + static boolean isLevelAtLeast(NBTTagCompound tag, int level) { + return tag.hasKey("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; + } +@@ -163,7 +164,7 @@ public abstract class Entity implements ICommandListener { + this.width = 0.6F; + this.length = 1.8F; + this.ax = 1; +- this.random = new Random(); ++ this.random = SHARED_RANDOM; // Paper + this.fireTicks = -this.getMaxFireTicks(); + this.justCreated = true; + this.uniqueID = MathHelper.a(this.random); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0085-Waving-banner-workaround.patch b/Spigot-Server-Patches/0085-Waving-banner-workaround.patch deleted file mode 100644 index 88f7957eb8..0000000000 --- a/Spigot-Server-Patches/0085-Waving-banner-workaround.patch +++ /dev/null @@ -1,38 +0,0 @@ -From ba98d3629b53c82bc96d097c0ee3086345af2300 Mon Sep 17 00:00:00 2001 -From: Gabscap -Date: Sat, 19 Mar 2016 22:25:11 +0100 -Subject: [PATCH] Waving banner workaround - -This patch is a workaround for MC-63720 - -diff --git a/src/main/java/net/minecraft/server/PacketPlayOutUpdateTime.java b/src/main/java/net/minecraft/server/PacketPlayOutUpdateTime.java -index c5c3f40ce..6413f76e7 100644 ---- a/src/main/java/net/minecraft/server/PacketPlayOutUpdateTime.java -+++ b/src/main/java/net/minecraft/server/PacketPlayOutUpdateTime.java -@@ -4,7 +4,13 @@ import java.io.IOException; - - public class PacketPlayOutUpdateTime implements Packet { - -+ // World Age in ticks -+ // Not changed by server commands -+ // World Age must not be negative - private long a; -+ // Time of Day in ticks -+ // If negative the sun will stop moving at the Math.abs of the time -+ // Displayed in the debug screen (F3) - private long b; - - public PacketPlayOutUpdateTime() {} -@@ -19,6 +25,9 @@ public class PacketPlayOutUpdateTime implements Packet { - } - } - -+ // Paper start -+ this.a = this.a % 192000; -+ // Paper end - } - - public void a(PacketDataSerializer packetdataserializer) throws IOException { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0086-Don-t-teleport-dead-entities.patch b/Spigot-Server-Patches/0086-Don-t-teleport-dead-entities.patch new file mode 100644 index 0000000000..c4fedec25a --- /dev/null +++ b/Spigot-Server-Patches/0086-Don-t-teleport-dead-entities.patch @@ -0,0 +1,24 @@ +From 3a9555ca894972a6e5c4e7bb7bf5d1e616235334 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 22 Mar 2016 00:55:23 -0400 +Subject: [PATCH] Don't teleport dead entities + +Had some issue with this in past, and this is the vanilla logic. +Potentially an old CB change that's no longer needed. + +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 42bd79b10..70a431a63 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -2317,7 +2317,7 @@ public abstract class Entity implements ICommandListener { + } + + public Entity teleportTo(Location exit, boolean portal) { +- if (true) { ++ if (!this.dead) { // Paper + WorldServer worldserver = ((CraftWorld) getBukkitEntity().getLocation().getWorld()).getHandle(); + WorldServer worldserver1 = ((CraftWorld) exit.getWorld()).getHandle(); + int i = worldserver1.dimension; +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0086-Use-a-Shared-Random-for-Entities.patch b/Spigot-Server-Patches/0086-Use-a-Shared-Random-for-Entities.patch deleted file mode 100644 index 6df31a9107..0000000000 --- a/Spigot-Server-Patches/0086-Use-a-Shared-Random-for-Entities.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 7db79cee3f3587bced0e3d249bb50aa4ee3b1fef 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/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index be54c807b..42bd79b10 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -46,6 +46,7 @@ public abstract class Entity implements ICommandListener { - - // CraftBukkit start - private static final int CURRENT_LEVEL = 2; -+ public static Random SHARED_RANDOM = new Random(); // Paper - static boolean isLevelAtLeast(NBTTagCompound tag, int level) { - return tag.hasKey("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; - } -@@ -163,7 +164,7 @@ public abstract class Entity implements ICommandListener { - this.width = 0.6F; - this.length = 1.8F; - this.ax = 1; -- this.random = new Random(); -+ this.random = SHARED_RANDOM; // Paper - this.fireTicks = -this.getMaxFireTicks(); - this.justCreated = true; - this.uniqueID = MathHelper.a(this.random); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0087-Don-t-teleport-dead-entities.patch b/Spigot-Server-Patches/0087-Don-t-teleport-dead-entities.patch deleted file mode 100644 index 9ba115e4cc..0000000000 --- a/Spigot-Server-Patches/0087-Don-t-teleport-dead-entities.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 978d5af9bceeb871be2b1cbfffb45f9de62b5636 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 22 Mar 2016 00:55:23 -0400 -Subject: [PATCH] Don't teleport dead entities - -Had some issue with this in past, and this is the vanilla logic. -Potentially an old CB change that's no longer needed. - -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 42bd79b10..70a431a63 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -2317,7 +2317,7 @@ public abstract class Entity implements ICommandListener { - } - - public Entity teleportTo(Location exit, boolean portal) { -- if (true) { -+ if (!this.dead) { // Paper - WorldServer worldserver = ((CraftWorld) getBukkitEntity().getLocation().getWorld()).getHandle(); - WorldServer worldserver1 = ((CraftWorld) exit.getWorld()).getHandle(); - int i = worldserver1.dimension; --- -2.12.2 - diff --git a/Spigot-Server-Patches/0087-Optimize-Chunk-Access.patch b/Spigot-Server-Patches/0087-Optimize-Chunk-Access.patch new file mode 100644 index 0000000000..d8e864fa8c --- /dev/null +++ b/Spigot-Server-Patches/0087-Optimize-Chunk-Access.patch @@ -0,0 +1,46 @@ +From 580a3c1e39db0c716b97f47e00d39ebd145d9d1c Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 27 Aug 2015 01:15:02 -0400 +Subject: [PATCH] Optimize Chunk Access + +getting a loaded chunk is one of the most hottest pieces of code in the game. +getChunkAt is called for the same chunk multiple times in a row, often from getType(); + +Optimize this look up by using a Last Access cache. + +diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java +index 0ad57afba..b49f4e292 100644 +--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java +@@ -27,7 +27,27 @@ public class ChunkProviderServer implements IChunkProvider { + public final Set unloadQueue = Sets.newHashSet(); + public final ChunkGenerator chunkGenerator; + private final IChunkLoader chunkLoader; +- public final Long2ObjectMap chunks = new Long2ObjectOpenHashMap(8192); ++ // Paper start ++ protected Chunk lastChunkByPos = null; ++ public Long2ObjectOpenHashMap chunks = new Long2ObjectOpenHashMap(8192) { ++ ++ @Override ++ public Chunk get(long key) { ++ if (lastChunkByPos != null && key == lastChunkByPos.chunkKey) { ++ return lastChunkByPos; ++ } ++ return lastChunkByPos = super.get(key); ++ } ++ ++ @Override ++ public Chunk remove(long key) { ++ if (lastChunkByPos != null && key == lastChunkByPos.chunkKey) { ++ lastChunkByPos = null; ++ } ++ return super.remove(key); ++ } ++ }; // CraftBukkit ++ // Paper end + public final WorldServer world; + + public ChunkProviderServer(WorldServer worldserver, IChunkLoader ichunkloader, ChunkGenerator chunkgenerator) { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0088-Configurable-spawn-chances-for-skeleton-horses.patch b/Spigot-Server-Patches/0088-Configurable-spawn-chances-for-skeleton-horses.patch new file mode 100644 index 0000000000..9913f36e53 --- /dev/null +++ b/Spigot-Server-Patches/0088-Configurable-spawn-chances-for-skeleton-horses.patch @@ -0,0 +1,36 @@ +From 76935253a4bfcc967fde6cc7d3e034f537c6160d 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 b37b5901b..adc810720 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -263,4 +263,9 @@ public class PaperWorldConfig { + } + log("Non Player Arrow Despawn Rate: " + nonPlayerArrowDespawnRate); + } ++ ++ public double skeleHorseSpawnChance; ++ private void skeleHorseSpawnChance() { ++ skeleHorseSpawnChance = getDouble("skeleton-horse-thunder-spawn-chance", 0.01D); // -1.0D represents a "vanilla" state ++ } + } +diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java +index ac8dc5f2f..39ed0d533 100644 +--- a/src/main/java/net/minecraft/server/WorldServer.java ++++ b/src/main/java/net/minecraft/server/WorldServer.java +@@ -436,7 +436,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { + if (this.isRainingAt(blockposition)) { + DifficultyDamageScaler difficultydamagescaler = this.D(blockposition); + +- if (this.getGameRules().getBoolean("doMobSpawning") && this.random.nextDouble() < (double) difficultydamagescaler.b() * 0.01D) { ++ if (this.getGameRules().getBoolean("doMobSpawning") && this.random.nextDouble() < (double) difficultydamagescaler.b() * paperConfig.skeleHorseSpawnChance) { + EntityHorseSkeleton entityhorseskeleton = new EntityHorseSkeleton(this); + + entityhorseskeleton.p(true); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0088-Optimize-Chunk-Access.patch b/Spigot-Server-Patches/0088-Optimize-Chunk-Access.patch deleted file mode 100644 index 86cd49fb74..0000000000 --- a/Spigot-Server-Patches/0088-Optimize-Chunk-Access.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 15890a007fe5797522d8b42f028835b2b2ff6d05 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 27 Aug 2015 01:15:02 -0400 -Subject: [PATCH] Optimize Chunk Access - -getting a loaded chunk is one of the most hottest pieces of code in the game. -getChunkAt is called for the same chunk multiple times in a row, often from getType(); - -Optimize this look up by using a Last Access cache. - -diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java -index b0a82e7ed..a7e8a3f7d 100644 ---- a/src/main/java/net/minecraft/server/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java -@@ -27,7 +27,27 @@ public class ChunkProviderServer implements IChunkProvider { - public final Set unloadQueue = Sets.newHashSet(); - public final ChunkGenerator chunkGenerator; - private final IChunkLoader chunkLoader; -- public final Long2ObjectMap chunks = new Long2ObjectOpenHashMap(8192); -+ // Paper start -+ protected Chunk lastChunkByPos = null; -+ public Long2ObjectOpenHashMap chunks = new Long2ObjectOpenHashMap(8192) { -+ -+ @Override -+ public Chunk get(long key) { -+ if (lastChunkByPos != null && key == lastChunkByPos.chunkKey) { -+ return lastChunkByPos; -+ } -+ return lastChunkByPos = super.get(key); -+ } -+ -+ @Override -+ public Chunk remove(long key) { -+ if (lastChunkByPos != null && key == lastChunkByPos.chunkKey) { -+ lastChunkByPos = null; -+ } -+ return super.remove(key); -+ } -+ }; // CraftBukkit -+ // Paper end - public final WorldServer world; - - public ChunkProviderServer(WorldServer worldserver, IChunkLoader ichunkloader, ChunkGenerator chunkgenerator) { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0089-Configurable-spawn-chances-for-skeleton-horses.patch b/Spigot-Server-Patches/0089-Configurable-spawn-chances-for-skeleton-horses.patch deleted file mode 100644 index 4149ebdd6b..0000000000 --- a/Spigot-Server-Patches/0089-Configurable-spawn-chances-for-skeleton-horses.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 4bc32176e261712428bd91475ec9a4da500a582d 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 b37b5901b..adc810720 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -263,4 +263,9 @@ public class PaperWorldConfig { - } - log("Non Player Arrow Despawn Rate: " + nonPlayerArrowDespawnRate); - } -+ -+ public double skeleHorseSpawnChance; -+ private void skeleHorseSpawnChance() { -+ skeleHorseSpawnChance = getDouble("skeleton-horse-thunder-spawn-chance", 0.01D); // -1.0D represents a "vanilla" state -+ } - } -diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index ac8dc5f2f..39ed0d533 100644 ---- a/src/main/java/net/minecraft/server/WorldServer.java -+++ b/src/main/java/net/minecraft/server/WorldServer.java -@@ -436,7 +436,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { - if (this.isRainingAt(blockposition)) { - DifficultyDamageScaler difficultydamagescaler = this.D(blockposition); - -- if (this.getGameRules().getBoolean("doMobSpawning") && this.random.nextDouble() < (double) difficultydamagescaler.b() * 0.01D) { -+ if (this.getGameRules().getBoolean("doMobSpawning") && this.random.nextDouble() < (double) difficultydamagescaler.b() * paperConfig.skeleHorseSpawnChance) { - EntityHorseSkeleton entityhorseskeleton = new EntityHorseSkeleton(this); - - entityhorseskeleton.p(true); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0089-Optimize-isValidLocation-getType-and-getBlockData-fo.patch b/Spigot-Server-Patches/0089-Optimize-isValidLocation-getType-and-getBlockData-fo.patch new file mode 100644 index 0000000000..d3b68513b2 --- /dev/null +++ b/Spigot-Server-Patches/0089-Optimize-isValidLocation-getType-and-getBlockData-fo.patch @@ -0,0 +1,259 @@ +From a76eee72a3134e780d7e75a0705c1db66c5e21e4 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 inling + +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/server/BaseBlockPosition.java b/src/main/java/net/minecraft/server/BaseBlockPosition.java +index d60e75502..f772c7cdf 100644 +--- a/src/main/java/net/minecraft/server/BaseBlockPosition.java ++++ b/src/main/java/net/minecraft/server/BaseBlockPosition.java +@@ -10,6 +10,14 @@ public class BaseBlockPosition implements Comparable { + private final int a; + private final int b; + private final int c; ++ // Paper start ++ public boolean isValidLocation() { ++ return a >= -30000000 && c >= -30000000 && a < 30000000 && c < 30000000 && b >= 0 && b < 256; ++ } ++ public boolean isInvalidYLocation() { ++ return b < 0 || b >= 256; ++ } ++ // Paper end + + public BaseBlockPosition(int i, int j, int k) { + this.a = i; +diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java +index 67b476b22..008ed206d 100644 +--- a/src/main/java/net/minecraft/server/BlockPosition.java ++++ b/src/main/java/net/minecraft/server/BlockPosition.java +@@ -339,6 +339,16 @@ public class BlockPosition extends BaseBlockPosition { + protected int b; + protected int c; + protected int d; ++ // Paper start ++ @Override ++ public boolean isValidLocation() { ++ return b >= -30000000 && d >= -30000000 && b < 30000000 && d < 30000000 && c >= 0 && c < 256; ++ } ++ @Override ++ public boolean isInvalidYLocation() { ++ return c < 0 || c >= 256; ++ } ++ // Paper end + + public MutableBlockPosition() { + this(0, 0, 0); +diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java +index 8f1a68d67..736fa1f62 100644 +--- a/src/main/java/net/minecraft/server/Chunk.java ++++ b/src/main/java/net/minecraft/server/Chunk.java +@@ -406,11 +406,26 @@ public class Chunk { + return this.a(i, j, k).c(); + } + +- public IBlockData getBlockData(BlockPosition blockposition) { +- return this.a(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ // Paper start - Optimize getBlockData to reduce instructions ++ public final IBlockData getBlockData(final BlockPosition pos) { ++ return getBlockData(pos.getX(), pos.getY(), pos.getZ()); ++ } ++ ++ 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) { ++ // Inlined ChunkSection.getType() and DataPaletteBlock.a(int,int,int) ++ return this.sections[i].blockIds.a((y & 15) << 8 | (z & 15) << 4 | x & 15); ++ } ++ return Blocks.AIR.getBlockData(); + } + + public IBlockData a(final int i, final int j, final int k) { ++ return getBlockData(i, j, k); ++ } ++ public IBlockData unused(final int i, final int j, final int k) { ++ // Paper end + if (this.world.L() == WorldType.DEBUG_ALL_BLOCK_STATES) { + IBlockData iblockdata = null; + +diff --git a/src/main/java/net/minecraft/server/ChunkSection.java b/src/main/java/net/minecraft/server/ChunkSection.java +index 3d784d0dc..afdc4a779 100644 +--- a/src/main/java/net/minecraft/server/ChunkSection.java ++++ b/src/main/java/net/minecraft/server/ChunkSection.java +@@ -5,7 +5,7 @@ public class ChunkSection { + private final int yPos; + private int nonEmptyBlockCount; + private int tickingBlockCount; +- private final DataPaletteBlock blockIds; ++ final DataPaletteBlock blockIds; // Paper - package + private NibbleArray emittedLight; + private NibbleArray skyLight; + +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 1d2d174e8..9427fc080 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -273,12 +273,12 @@ public abstract class World implements IBlockAccess { + return this.getType(blockposition1); + } + +- private boolean isValidLocation(BlockPosition blockposition) { +- return !this.E(blockposition) && blockposition.getX() >= -30000000 && blockposition.getZ() >= -30000000 && blockposition.getX() < 30000000 && blockposition.getZ() < 30000000; ++ private static boolean isValidLocation(BlockPosition blockposition) { // Paper - unused but incase reflection / future uses ++ return blockposition.isValidLocation(); // Paper + } + +- private boolean E(BlockPosition blockposition) { +- return blockposition.getY() < 0 || blockposition.getY() >= 256; ++ private static boolean E(BlockPosition blockposition) { // Paper - unused but incase reflection / future uses ++ return blockposition.isInvalidYLocation(); // Paper + } + + public boolean isEmpty(BlockPosition blockposition) { +@@ -374,7 +374,7 @@ public abstract class World implements IBlockAccess { + return true; + } + // CraftBukkit end +- if (this.E(blockposition)) { ++ if (blockposition.isInvalidYLocation()) { // Paper + return false; + } else if (!this.isClientSide && this.worldData.getType() == WorldType.DEBUG_ALL_BLOCK_STATES) { + return false; +@@ -691,7 +691,7 @@ public abstract class World implements IBlockAccess { + // Paper start - test if meets light level, return faster + // logic copied from below + public boolean isLightLevel(BlockPosition blockposition, int level) { +- if (isValidLocation(blockposition)) { ++ if (blockposition.isValidLocation()) { + if (this.getType(blockposition).f()) { + if (this.c(blockposition.up(), false) >= level) { + return true; +@@ -809,7 +809,7 @@ public abstract class World implements IBlockAccess { + blockposition = new BlockPosition(blockposition.getX(), 0, blockposition.getZ()); + } + +- if (!this.isValidLocation(blockposition)) { ++ if (!blockposition.isValidLocation()) { // Paper + return enumskyblock.c; + } else if (!this.isLoaded(blockposition)) { + return enumskyblock.c; +@@ -821,7 +821,7 @@ public abstract class World implements IBlockAccess { + } + + public void a(EnumSkyBlock enumskyblock, BlockPosition blockposition, int i) { +- if (this.isValidLocation(blockposition)) { ++ if (blockposition.isValidLocation()) { // Paper + if (this.isLoaded(blockposition)) { + Chunk chunk = this.getChunkAtWorldCoords(blockposition); + +@@ -845,19 +845,19 @@ public abstract class World implements IBlockAccess { + // Paper start - reduces need to do isLoaded before getType + public IBlockData getTypeIfLoaded(BlockPosition blockposition) { + // CraftBukkit start - tree generation ++ final int x = blockposition.getX(); ++ final int y = blockposition.getY(); ++ final int z = blockposition.getZ(); + if (captureTreeGeneration) { +- Iterator it = capturedBlockStates.iterator(); +- while (it.hasNext()) { +- BlockState previous = it.next(); +- if (previous.getX() == blockposition.getX() && previous.getY() == blockposition.getY() && previous.getZ() == blockposition.getZ()) { +- return CraftMagicNumbers.getBlock(previous.getTypeId()).fromLegacyData(previous.getRawData()); +- } ++ final IBlockData previous = getCapturedBlockType(x, y, z); ++ if (previous != null) { ++ return previous; + } + } + // CraftBukkit end +- Chunk chunk = this.getChunkIfLoaded(blockposition); ++ Chunk chunk = ((ChunkProviderServer) this.chunkProvider).getChunkIfLoaded(x >> 4, z >> 4); + if (chunk != null) { +- return this.isValidLocation(blockposition) ? chunk.getBlockData(blockposition) : Blocks.AIR.getBlockData(); ++ return chunk.getBlockData(x, y, z); + } + return null; + } +@@ -865,24 +865,33 @@ public abstract class World implements IBlockAccess { + + public IBlockData getType(BlockPosition blockposition) { + // CraftBukkit start - tree generation ++ // Paper start - optimize getType lookup to reduce instructions - getBlockData already enforces valid Y, move tree out ++ final int x = blockposition.getX(); ++ final int y = blockposition.getY(); ++ final int z = blockposition.getZ(); + if (captureTreeGeneration) { +- Iterator it = capturedBlockStates.iterator(); +- while (it.hasNext()) { +- BlockState previous = it.next(); +- if (previous.getX() == blockposition.getX() && previous.getY() == blockposition.getY() && previous.getZ() == blockposition.getZ()) { +- return CraftMagicNumbers.getBlock(previous.getTypeId()).fromLegacyData(previous.getRawData()); +- } ++ final IBlockData previous = getCapturedBlockType(x, y, z); ++ if (previous != null) { ++ return previous; + } + } + // CraftBukkit end +- if (this.E(blockposition)) { +- return Blocks.AIR.getBlockData(); +- } else { +- Chunk chunk = this.getChunkAtWorldCoords(blockposition); ++ return this.chunkProvider.getChunkAt(x >> 4, z >> 4).getBlockData(x, y, z); ++ // Paper end ++ } + +- return chunk.getBlockData(blockposition); ++ // Paper start ++ private IBlockData getCapturedBlockType(int x, int y, int z) { ++ Iterator it = capturedBlockStates.iterator(); ++ while (it.hasNext()) { ++ BlockState previous = it.next(); ++ if (previous.getX() == x && previous.getY() == y && previous.getZ() == z) { ++ return CraftMagicNumbers.getBlock(previous.getTypeId()).fromLegacyData(previous.getRawData()); ++ } + } ++ return null; + } ++ // Paper end + + public boolean B() { + return this.J < 4; +@@ -2017,7 +2026,7 @@ public abstract class World implements IBlockAccess { + public Map capturedTileEntities = Maps.newHashMap(); + @Nullable + public TileEntity getTileEntity(BlockPosition blockposition) { +- if (this.E(blockposition)) { ++ if (blockposition.isInvalidYLocation()) { // Paper + return null; + } else { + // CraftBukkit start +@@ -2058,7 +2067,7 @@ public abstract class World implements IBlockAccess { + } + + public void setTileEntity(BlockPosition blockposition, @Nullable TileEntity tileentity) { +- if (!this.E(blockposition)) { ++ if (!blockposition.isInvalidYLocation()) { + if (tileentity != null && !tileentity.y()) { + // CraftBukkit start + if (captureBlockStates) { +@@ -2121,7 +2130,7 @@ public abstract class World implements IBlockAccess { + } + + public boolean d(BlockPosition blockposition, boolean flag) { +- if (this.E(blockposition)) { ++ if (blockposition.isInvalidYLocation()) { // Paper + return false; + } else { + Chunk chunk = this.chunkProvider.getLoadedChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0090-Fix-cooked-fish-legacy-import.patch b/Spigot-Server-Patches/0090-Fix-cooked-fish-legacy-import.patch new file mode 100644 index 0000000000..c7e5591be4 --- /dev/null +++ b/Spigot-Server-Patches/0090-Fix-cooked-fish-legacy-import.patch @@ -0,0 +1,22 @@ +From 0dcc62d3626178628c8a2f9e1c55a7a1d6e97ab7 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Tue, 1 Mar 2016 04:32:08 -0500 +Subject: [PATCH] Fix cooked fish legacy import + + +diff --git a/src/main/java/net/minecraft/server/DataConverterMaterialId.java b/src/main/java/net/minecraft/server/DataConverterMaterialId.java +index 87b82eb35..a7c71f406 100644 +--- a/src/main/java/net/minecraft/server/DataConverterMaterialId.java ++++ b/src/main/java/net/minecraft/server/DataConverterMaterialId.java +@@ -261,7 +261,7 @@ public class DataConverterMaterialId implements IDataConverter { + DataConverterMaterialId.a[347] = "minecraft:clock"; + DataConverterMaterialId.a[348] = "minecraft:glowstone_dust"; + DataConverterMaterialId.a[349] = "minecraft:fish"; +- DataConverterMaterialId.a[350] = "minecraft:cooked_fished"; ++ DataConverterMaterialId.a[350] = "minecraft:cooked_fish"; // Paper - cooked_fished -> cooked_fish + DataConverterMaterialId.a[351] = "minecraft:dye"; + DataConverterMaterialId.a[352] = "minecraft:bone"; + DataConverterMaterialId.a[353] = "minecraft:sugar"; +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0090-Optimize-isValidLocation-getType-and-getBlockData-fo.patch b/Spigot-Server-Patches/0090-Optimize-isValidLocation-getType-and-getBlockData-fo.patch deleted file mode 100644 index 466555a9c6..0000000000 --- a/Spigot-Server-Patches/0090-Optimize-isValidLocation-getType-and-getBlockData-fo.patch +++ /dev/null @@ -1,259 +0,0 @@ -From 22e1661666d7e149b0fddf9a6f45cad52af4b917 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 inling - -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/server/BaseBlockPosition.java b/src/main/java/net/minecraft/server/BaseBlockPosition.java -index d60e75502..f772c7cdf 100644 ---- a/src/main/java/net/minecraft/server/BaseBlockPosition.java -+++ b/src/main/java/net/minecraft/server/BaseBlockPosition.java -@@ -10,6 +10,14 @@ public class BaseBlockPosition implements Comparable { - private final int a; - private final int b; - private final int c; -+ // Paper start -+ public boolean isValidLocation() { -+ return a >= -30000000 && c >= -30000000 && a < 30000000 && c < 30000000 && b >= 0 && b < 256; -+ } -+ public boolean isInvalidYLocation() { -+ return b < 0 || b >= 256; -+ } -+ // Paper end - - public BaseBlockPosition(int i, int j, int k) { - this.a = i; -diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java -index 67b476b22..008ed206d 100644 ---- a/src/main/java/net/minecraft/server/BlockPosition.java -+++ b/src/main/java/net/minecraft/server/BlockPosition.java -@@ -339,6 +339,16 @@ public class BlockPosition extends BaseBlockPosition { - protected int b; - protected int c; - protected int d; -+ // Paper start -+ @Override -+ public boolean isValidLocation() { -+ return b >= -30000000 && d >= -30000000 && b < 30000000 && d < 30000000 && c >= 0 && c < 256; -+ } -+ @Override -+ public boolean isInvalidYLocation() { -+ return c < 0 || c >= 256; -+ } -+ // Paper end - - public MutableBlockPosition() { - this(0, 0, 0); -diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java -index 8f1a68d67..736fa1f62 100644 ---- a/src/main/java/net/minecraft/server/Chunk.java -+++ b/src/main/java/net/minecraft/server/Chunk.java -@@ -406,11 +406,26 @@ public class Chunk { - return this.a(i, j, k).c(); - } - -- public IBlockData getBlockData(BlockPosition blockposition) { -- return this.a(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ // Paper start - Optimize getBlockData to reduce instructions -+ public final IBlockData getBlockData(final BlockPosition pos) { -+ return getBlockData(pos.getX(), pos.getY(), pos.getZ()); -+ } -+ -+ 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) { -+ // Inlined ChunkSection.getType() and DataPaletteBlock.a(int,int,int) -+ return this.sections[i].blockIds.a((y & 15) << 8 | (z & 15) << 4 | x & 15); -+ } -+ return Blocks.AIR.getBlockData(); - } - - public IBlockData a(final int i, final int j, final int k) { -+ return getBlockData(i, j, k); -+ } -+ public IBlockData unused(final int i, final int j, final int k) { -+ // Paper end - if (this.world.L() == WorldType.DEBUG_ALL_BLOCK_STATES) { - IBlockData iblockdata = null; - -diff --git a/src/main/java/net/minecraft/server/ChunkSection.java b/src/main/java/net/minecraft/server/ChunkSection.java -index 3d784d0dc..afdc4a779 100644 ---- a/src/main/java/net/minecraft/server/ChunkSection.java -+++ b/src/main/java/net/minecraft/server/ChunkSection.java -@@ -5,7 +5,7 @@ public class ChunkSection { - private final int yPos; - private int nonEmptyBlockCount; - private int tickingBlockCount; -- private final DataPaletteBlock blockIds; -+ final DataPaletteBlock blockIds; // Paper - package - private NibbleArray emittedLight; - private NibbleArray skyLight; - -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 1d2d174e8..9427fc080 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -273,12 +273,12 @@ public abstract class World implements IBlockAccess { - return this.getType(blockposition1); - } - -- private boolean isValidLocation(BlockPosition blockposition) { -- return !this.E(blockposition) && blockposition.getX() >= -30000000 && blockposition.getZ() >= -30000000 && blockposition.getX() < 30000000 && blockposition.getZ() < 30000000; -+ private static boolean isValidLocation(BlockPosition blockposition) { // Paper - unused but incase reflection / future uses -+ return blockposition.isValidLocation(); // Paper - } - -- private boolean E(BlockPosition blockposition) { -- return blockposition.getY() < 0 || blockposition.getY() >= 256; -+ private static boolean E(BlockPosition blockposition) { // Paper - unused but incase reflection / future uses -+ return blockposition.isInvalidYLocation(); // Paper - } - - public boolean isEmpty(BlockPosition blockposition) { -@@ -374,7 +374,7 @@ public abstract class World implements IBlockAccess { - return true; - } - // CraftBukkit end -- if (this.E(blockposition)) { -+ if (blockposition.isInvalidYLocation()) { // Paper - return false; - } else if (!this.isClientSide && this.worldData.getType() == WorldType.DEBUG_ALL_BLOCK_STATES) { - return false; -@@ -691,7 +691,7 @@ public abstract class World implements IBlockAccess { - // Paper start - test if meets light level, return faster - // logic copied from below - public boolean isLightLevel(BlockPosition blockposition, int level) { -- if (isValidLocation(blockposition)) { -+ if (blockposition.isValidLocation()) { - if (this.getType(blockposition).f()) { - if (this.c(blockposition.up(), false) >= level) { - return true; -@@ -809,7 +809,7 @@ public abstract class World implements IBlockAccess { - blockposition = new BlockPosition(blockposition.getX(), 0, blockposition.getZ()); - } - -- if (!this.isValidLocation(blockposition)) { -+ if (!blockposition.isValidLocation()) { // Paper - return enumskyblock.c; - } else if (!this.isLoaded(blockposition)) { - return enumskyblock.c; -@@ -821,7 +821,7 @@ public abstract class World implements IBlockAccess { - } - - public void a(EnumSkyBlock enumskyblock, BlockPosition blockposition, int i) { -- if (this.isValidLocation(blockposition)) { -+ if (blockposition.isValidLocation()) { // Paper - if (this.isLoaded(blockposition)) { - Chunk chunk = this.getChunkAtWorldCoords(blockposition); - -@@ -845,19 +845,19 @@ public abstract class World implements IBlockAccess { - // Paper start - reduces need to do isLoaded before getType - public IBlockData getTypeIfLoaded(BlockPosition blockposition) { - // CraftBukkit start - tree generation -+ final int x = blockposition.getX(); -+ final int y = blockposition.getY(); -+ final int z = blockposition.getZ(); - if (captureTreeGeneration) { -- Iterator it = capturedBlockStates.iterator(); -- while (it.hasNext()) { -- BlockState previous = it.next(); -- if (previous.getX() == blockposition.getX() && previous.getY() == blockposition.getY() && previous.getZ() == blockposition.getZ()) { -- return CraftMagicNumbers.getBlock(previous.getTypeId()).fromLegacyData(previous.getRawData()); -- } -+ final IBlockData previous = getCapturedBlockType(x, y, z); -+ if (previous != null) { -+ return previous; - } - } - // CraftBukkit end -- Chunk chunk = this.getChunkIfLoaded(blockposition); -+ Chunk chunk = ((ChunkProviderServer) this.chunkProvider).getChunkIfLoaded(x >> 4, z >> 4); - if (chunk != null) { -- return this.isValidLocation(blockposition) ? chunk.getBlockData(blockposition) : Blocks.AIR.getBlockData(); -+ return chunk.getBlockData(x, y, z); - } - return null; - } -@@ -865,24 +865,33 @@ public abstract class World implements IBlockAccess { - - public IBlockData getType(BlockPosition blockposition) { - // CraftBukkit start - tree generation -+ // Paper start - optimize getType lookup to reduce instructions - getBlockData already enforces valid Y, move tree out -+ final int x = blockposition.getX(); -+ final int y = blockposition.getY(); -+ final int z = blockposition.getZ(); - if (captureTreeGeneration) { -- Iterator it = capturedBlockStates.iterator(); -- while (it.hasNext()) { -- BlockState previous = it.next(); -- if (previous.getX() == blockposition.getX() && previous.getY() == blockposition.getY() && previous.getZ() == blockposition.getZ()) { -- return CraftMagicNumbers.getBlock(previous.getTypeId()).fromLegacyData(previous.getRawData()); -- } -+ final IBlockData previous = getCapturedBlockType(x, y, z); -+ if (previous != null) { -+ return previous; - } - } - // CraftBukkit end -- if (this.E(blockposition)) { -- return Blocks.AIR.getBlockData(); -- } else { -- Chunk chunk = this.getChunkAtWorldCoords(blockposition); -+ return this.chunkProvider.getChunkAt(x >> 4, z >> 4).getBlockData(x, y, z); -+ // Paper end -+ } - -- return chunk.getBlockData(blockposition); -+ // Paper start -+ private IBlockData getCapturedBlockType(int x, int y, int z) { -+ Iterator it = capturedBlockStates.iterator(); -+ while (it.hasNext()) { -+ BlockState previous = it.next(); -+ if (previous.getX() == x && previous.getY() == y && previous.getZ() == z) { -+ return CraftMagicNumbers.getBlock(previous.getTypeId()).fromLegacyData(previous.getRawData()); -+ } - } -+ return null; - } -+ // Paper end - - public boolean B() { - return this.J < 4; -@@ -2017,7 +2026,7 @@ public abstract class World implements IBlockAccess { - public Map capturedTileEntities = Maps.newHashMap(); - @Nullable - public TileEntity getTileEntity(BlockPosition blockposition) { -- if (this.E(blockposition)) { -+ if (blockposition.isInvalidYLocation()) { // Paper - return null; - } else { - // CraftBukkit start -@@ -2058,7 +2067,7 @@ public abstract class World implements IBlockAccess { - } - - public void setTileEntity(BlockPosition blockposition, @Nullable TileEntity tileentity) { -- if (!this.E(blockposition)) { -+ if (!blockposition.isInvalidYLocation()) { - if (tileentity != null && !tileentity.y()) { - // CraftBukkit start - if (captureBlockStates) { -@@ -2121,7 +2130,7 @@ public abstract class World implements IBlockAccess { - } - - public boolean d(BlockPosition blockposition, boolean flag) { -- if (this.E(blockposition)) { -+ if (blockposition.isInvalidYLocation()) { // Paper - return false; - } else { - Chunk chunk = this.chunkProvider.getLoadedChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0091-Access-items-by-EquipmentSlot.patch b/Spigot-Server-Patches/0091-Access-items-by-EquipmentSlot.patch new file mode 100644 index 0000000000..80d3336bab --- /dev/null +++ b/Spigot-Server-Patches/0091-Access-items-by-EquipmentSlot.patch @@ -0,0 +1,68 @@ +From 9a9ff76273935fe0116ddb2fd757452542354c51 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Sun, 20 Mar 2016 06:45:01 -0400 +Subject: [PATCH] Access items by EquipmentSlot + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java +index 67c54899d..3f58c34e0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java +@@ -267,4 +267,54 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i + public void setBootsDropChance(float chance) { + throw new UnsupportedOperationException(); + } ++ ++ // Paper start ++ @Override ++ public ItemStack getItem(org.bukkit.inventory.EquipmentSlot slot) { ++ Preconditions.checkNotNull(slot, "slot"); ++ switch (slot) { ++ case HAND: ++ return this.getItemInMainHand(); ++ case OFF_HAND: ++ return this.getItemInOffHand(); ++ case HEAD: ++ return this.getHelmet(); ++ case CHEST: ++ return this.getChestplate(); ++ case LEGS: ++ return this.getLeggings(); ++ case FEET: ++ return this.getBoots(); ++ } ++ ++ throw new UnsupportedOperationException(slot.name()); ++ } ++ ++ @Override ++ public void setItem(org.bukkit.inventory.EquipmentSlot slot, ItemStack stack) { ++ Preconditions.checkNotNull(slot, "slot"); ++ switch (slot) { ++ case HAND: ++ this.setItemInMainHand(stack); ++ return; ++ case OFF_HAND: ++ this.setItemInOffHand(stack); ++ return; ++ case HEAD: ++ this.setHelmet(stack); ++ return; ++ case CHEST: ++ this.setChestplate(stack); ++ return; ++ case LEGS: ++ this.setLeggings(stack); ++ return; ++ case FEET: ++ this.setBoots(stack); ++ return; ++ } ++ ++ throw new UnsupportedOperationException(slot.name()); ++ } ++ // Paper end + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0091-Fix-cooked-fish-legacy-import.patch b/Spigot-Server-Patches/0091-Fix-cooked-fish-legacy-import.patch deleted file mode 100644 index e0154dcc50..0000000000 --- a/Spigot-Server-Patches/0091-Fix-cooked-fish-legacy-import.patch +++ /dev/null @@ -1,22 +0,0 @@ -From c4390170763cc895adafa3fd63614c0423b6a761 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Tue, 1 Mar 2016 04:32:08 -0500 -Subject: [PATCH] Fix cooked fish legacy import - - -diff --git a/src/main/java/net/minecraft/server/DataConverterMaterialId.java b/src/main/java/net/minecraft/server/DataConverterMaterialId.java -index 87b82eb35..a7c71f406 100644 ---- a/src/main/java/net/minecraft/server/DataConverterMaterialId.java -+++ b/src/main/java/net/minecraft/server/DataConverterMaterialId.java -@@ -261,7 +261,7 @@ public class DataConverterMaterialId implements IDataConverter { - DataConverterMaterialId.a[347] = "minecraft:clock"; - DataConverterMaterialId.a[348] = "minecraft:glowstone_dust"; - DataConverterMaterialId.a[349] = "minecraft:fish"; -- DataConverterMaterialId.a[350] = "minecraft:cooked_fished"; -+ DataConverterMaterialId.a[350] = "minecraft:cooked_fish"; // Paper - cooked_fished -> cooked_fish - DataConverterMaterialId.a[351] = "minecraft:dye"; - DataConverterMaterialId.a[352] = "minecraft:bone"; - DataConverterMaterialId.a[353] = "minecraft:sugar"; --- -2.12.2 - diff --git a/Spigot-Server-Patches/0092-Access-items-by-EquipmentSlot.patch b/Spigot-Server-Patches/0092-Access-items-by-EquipmentSlot.patch deleted file mode 100644 index 4c55a3172f..0000000000 --- a/Spigot-Server-Patches/0092-Access-items-by-EquipmentSlot.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 52393541b308a635b69f891b01eb41c1776e8f07 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sun, 20 Mar 2016 06:45:01 -0400 -Subject: [PATCH] Access items by EquipmentSlot - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java -index 67c54899d..3f58c34e0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java -@@ -267,4 +267,54 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i - public void setBootsDropChance(float chance) { - throw new UnsupportedOperationException(); - } -+ -+ // Paper start -+ @Override -+ public ItemStack getItem(org.bukkit.inventory.EquipmentSlot slot) { -+ Preconditions.checkNotNull(slot, "slot"); -+ switch (slot) { -+ case HAND: -+ return this.getItemInMainHand(); -+ case OFF_HAND: -+ return this.getItemInOffHand(); -+ case HEAD: -+ return this.getHelmet(); -+ case CHEST: -+ return this.getChestplate(); -+ case LEGS: -+ return this.getLeggings(); -+ case FEET: -+ return this.getBoots(); -+ } -+ -+ throw new UnsupportedOperationException(slot.name()); -+ } -+ -+ @Override -+ public void setItem(org.bukkit.inventory.EquipmentSlot slot, ItemStack stack) { -+ Preconditions.checkNotNull(slot, "slot"); -+ switch (slot) { -+ case HAND: -+ this.setItemInMainHand(stack); -+ return; -+ case OFF_HAND: -+ this.setItemInOffHand(stack); -+ return; -+ case HEAD: -+ this.setHelmet(stack); -+ return; -+ case CHEST: -+ this.setChestplate(stack); -+ return; -+ case LEGS: -+ this.setLeggings(stack); -+ return; -+ case FEET: -+ this.setBoots(stack); -+ return; -+ } -+ -+ throw new UnsupportedOperationException(slot.name()); -+ } -+ // Paper end - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0092-Check-async-remove-unused-vars-GH-159.patch b/Spigot-Server-Patches/0092-Check-async-remove-unused-vars-GH-159.patch new file mode 100644 index 0000000000..fe5c7ccbb9 --- /dev/null +++ b/Spigot-Server-Patches/0092-Check-async-remove-unused-vars-GH-159.patch @@ -0,0 +1,32 @@ +From 5d65ae660c3bc6c62f38dc327121df456f8b9e32 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sun, 27 Mar 2016 20:24:05 -0500 +Subject: [PATCH] Check async, remove unused vars, GH-159 + + +diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java +index c79fb7d57..8749a1879 100644 +--- a/src/main/java/net/minecraft/server/SpawnerCreature.java ++++ b/src/main/java/net/minecraft/server/SpawnerCreature.java +@@ -40,6 +40,7 @@ public final class SpawnerCreature { + // Spigot end + + public int a(WorldServer worldserver, boolean flag, boolean flag1, boolean flag2) { ++ org.spigotmc.AsyncCatcher.catchOp("check for eligible spawn chunks"); // Paper - At least until we figure out what is calling this async + if (!flag && !flag1) { + return 0; + } else { +@@ -120,8 +121,10 @@ public final class SpawnerCreature { + // CraftBukkit end + + if ((!enumcreaturetype.d() || flag1) && (enumcreaturetype.d() || flag) && (!enumcreaturetype.e() || flag2)) { ++ /* Paper start - As far as I can tell neither of these are even used + k = worldserver.a(enumcreaturetype.a()); + int l1 = limit * i / a; // CraftBukkit - use per-world limits ++ */ // Paper end + + if ((mobcnt = getEntityCount(worldserver, enumcreaturetype.a())) <= limit * i / 256) { + BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0093-Check-async-remove-unused-vars-GH-159.patch b/Spigot-Server-Patches/0093-Check-async-remove-unused-vars-GH-159.patch deleted file mode 100644 index 16bff70638..0000000000 --- a/Spigot-Server-Patches/0093-Check-async-remove-unused-vars-GH-159.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 931dd1b6fbddd6576e436007a749078ceae64f1a Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sun, 27 Mar 2016 20:24:05 -0500 -Subject: [PATCH] Check async, remove unused vars, GH-159 - - -diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java -index c79fb7d57..8749a1879 100644 ---- a/src/main/java/net/minecraft/server/SpawnerCreature.java -+++ b/src/main/java/net/minecraft/server/SpawnerCreature.java -@@ -40,6 +40,7 @@ public final class SpawnerCreature { - // Spigot end - - public int a(WorldServer worldserver, boolean flag, boolean flag1, boolean flag2) { -+ org.spigotmc.AsyncCatcher.catchOp("check for eligible spawn chunks"); // Paper - At least until we figure out what is calling this async - if (!flag && !flag1) { - return 0; - } else { -@@ -120,8 +121,10 @@ public final class SpawnerCreature { - // CraftBukkit end - - if ((!enumcreaturetype.d() || flag1) && (enumcreaturetype.d() || flag) && (!enumcreaturetype.e() || flag2)) { -+ /* Paper start - As far as I can tell neither of these are even used - k = worldserver.a(enumcreaturetype.a()); - int l1 = limit * i / a; // CraftBukkit - use per-world limits -+ */ // Paper end - - if ((mobcnt = getEntityCount(worldserver, enumcreaturetype.a())) <= limit * i / 256) { - BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0093-Option-to-disable-BlockPhysicsEvent-for-Redstone.patch b/Spigot-Server-Patches/0093-Option-to-disable-BlockPhysicsEvent-for-Redstone.patch new file mode 100644 index 0000000000..e780e9b3b3 --- /dev/null +++ b/Spigot-Server-Patches/0093-Option-to-disable-BlockPhysicsEvent-for-Redstone.patch @@ -0,0 +1,71 @@ +From fb9b6e2de28107a733bfc5b55b4d446e115027fd Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 28 Mar 2016 19:55:45 -0400 +Subject: [PATCH] Option to disable BlockPhysicsEvent for Redstone + +Not sure of any reason a plugin would need to act on a Physics event +for redstone. There is a BlockRedstoneEvent that plugins can also use +for accessing redstone activity. + +Defaulting this to false will provide substantial performance improvement +by saving millions of event calls on redstone heavy servers. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index adc810720..e706efff5 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -268,4 +268,9 @@ public class PaperWorldConfig { + private void skeleHorseSpawnChance() { + skeleHorseSpawnChance = getDouble("skeleton-horse-thunder-spawn-chance", 0.01D); // -1.0D represents a "vanilla" state + } ++ ++ public boolean firePhysicsEventForRedstone = false; ++ private void firePhysicsEventForRedstone() { ++ firePhysicsEventForRedstone = getBoolean("fire-physics-event-for-redstone", firePhysicsEventForRedstone); ++ } + } +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 9427fc080..8cbdbda92 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -578,7 +578,7 @@ public abstract class World implements IBlockAccess { + try { + // CraftBukkit start + CraftWorld world = ((WorldServer) this).getWorld(); +- if (world != null) { ++ if (world != null && !((WorldServer)this).stopPhysicsEvent) { // Paper + BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftMagicNumbers.getId(block)); + this.getServer().getPluginManager().callEvent(event); + +diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java +index 39ed0d533..f969d2a72 100644 +--- a/src/main/java/net/minecraft/server/WorldServer.java ++++ b/src/main/java/net/minecraft/server/WorldServer.java +@@ -34,6 +34,7 @@ import org.bukkit.event.weather.LightningStrikeEvent; + public class WorldServer extends World implements IAsyncTaskHandler { + + private static final Logger a = LogManager.getLogger(); ++ boolean stopPhysicsEvent = false; // Paper + private final MinecraftServer server; + public EntityTracker tracker; + private final PlayerChunkMap manager; +@@ -727,6 +728,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { + + if (iblockdata.getMaterial() != Material.AIR && Block.a(iblockdata.getBlock(), nextticklistentry.a())) { + try { ++ stopPhysicsEvent = !paperConfig.firePhysicsEventForRedstone && (iblockdata.getBlock() instanceof BlockDiodeAbstract || iblockdata.getBlock() instanceof BlockRedstoneTorch); // Paper + iblockdata.getBlock().b((World) this, nextticklistentry.a, iblockdata, this.random); + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.a(throwable, "Exception while ticking a block"); +@@ -734,7 +736,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { + + CrashReportSystemDetails.a(crashreportsystemdetails, nextticklistentry.a, iblockdata); + throw new ReportedException(crashreport); +- } ++ } finally { stopPhysicsEvent = false; } // Paper + } + timing.stopTiming(); // Paper + } else { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0094-Entity-AddTo-RemoveFrom-World-Events.patch b/Spigot-Server-Patches/0094-Entity-AddTo-RemoveFrom-World-Events.patch new file mode 100644 index 0000000000..249699e62f --- /dev/null +++ b/Spigot-Server-Patches/0094-Entity-AddTo-RemoveFrom-World-Events.patch @@ -0,0 +1,29 @@ +From 92c341a06e29d044aae2b75fa6b940613ab4744f 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/World.java b/src/main/java/net/minecraft/server/World.java +index 8cbdbda92..f86c64cb2 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -1182,6 +1182,7 @@ public abstract class World implements IBlockAccess { + } + + entity.valid = true; // CraftBukkit ++ new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid + } + + protected void c(Entity entity) { +@@ -1189,6 +1190,7 @@ public abstract class World implements IBlockAccess { + ((IWorldAccess) this.u.get(i)).b(entity); + } + ++ new com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid + entity.valid = false; // CraftBukkit + } + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0094-Option-to-disable-BlockPhysicsEvent-for-Redstone.patch b/Spigot-Server-Patches/0094-Option-to-disable-BlockPhysicsEvent-for-Redstone.patch deleted file mode 100644 index 1e0fd7ebe4..0000000000 --- a/Spigot-Server-Patches/0094-Option-to-disable-BlockPhysicsEvent-for-Redstone.patch +++ /dev/null @@ -1,71 +0,0 @@ -From c80433172ca35367589f748c6ac3a0270f33b8f3 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 19:55:45 -0400 -Subject: [PATCH] Option to disable BlockPhysicsEvent for Redstone - -Not sure of any reason a plugin would need to act on a Physics event -for redstone. There is a BlockRedstoneEvent that plugins can also use -for accessing redstone activity. - -Defaulting this to false will provide substantial performance improvement -by saving millions of event calls on redstone heavy servers. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index adc810720..e706efff5 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -268,4 +268,9 @@ public class PaperWorldConfig { - private void skeleHorseSpawnChance() { - skeleHorseSpawnChance = getDouble("skeleton-horse-thunder-spawn-chance", 0.01D); // -1.0D represents a "vanilla" state - } -+ -+ public boolean firePhysicsEventForRedstone = false; -+ private void firePhysicsEventForRedstone() { -+ firePhysicsEventForRedstone = getBoolean("fire-physics-event-for-redstone", firePhysicsEventForRedstone); -+ } - } -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 9427fc080..8cbdbda92 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -578,7 +578,7 @@ public abstract class World implements IBlockAccess { - try { - // CraftBukkit start - CraftWorld world = ((WorldServer) this).getWorld(); -- if (world != null) { -+ if (world != null && !((WorldServer)this).stopPhysicsEvent) { // Paper - BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftMagicNumbers.getId(block)); - this.getServer().getPluginManager().callEvent(event); - -diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index 39ed0d533..f969d2a72 100644 ---- a/src/main/java/net/minecraft/server/WorldServer.java -+++ b/src/main/java/net/minecraft/server/WorldServer.java -@@ -34,6 +34,7 @@ import org.bukkit.event.weather.LightningStrikeEvent; - public class WorldServer extends World implements IAsyncTaskHandler { - - private static final Logger a = LogManager.getLogger(); -+ boolean stopPhysicsEvent = false; // Paper - private final MinecraftServer server; - public EntityTracker tracker; - private final PlayerChunkMap manager; -@@ -727,6 +728,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { - - if (iblockdata.getMaterial() != Material.AIR && Block.a(iblockdata.getBlock(), nextticklistentry.a())) { - try { -+ stopPhysicsEvent = !paperConfig.firePhysicsEventForRedstone && (iblockdata.getBlock() instanceof BlockDiodeAbstract || iblockdata.getBlock() instanceof BlockRedstoneTorch); // Paper - iblockdata.getBlock().b((World) this, nextticklistentry.a, iblockdata, this.random); - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.a(throwable, "Exception while ticking a block"); -@@ -734,7 +736,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { - - CrashReportSystemDetails.a(crashreportsystemdetails, nextticklistentry.a, iblockdata); - throw new ReportedException(crashreport); -- } -+ } finally { stopPhysicsEvent = false; } // Paper - } - timing.stopTiming(); // Paper - } else { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0095-Configurable-Chunk-Inhabited-Timer.patch b/Spigot-Server-Patches/0095-Configurable-Chunk-Inhabited-Timer.patch new file mode 100644 index 0000000000..df5d12d77f --- /dev/null +++ b/Spigot-Server-Patches/0095-Configurable-Chunk-Inhabited-Timer.patch @@ -0,0 +1,40 @@ +From 49abb603029c245c5d3946c3a941437ceeae0c3c Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 28 Mar 2016 20:46:14 -0400 +Subject: [PATCH] Configurable Chunk Inhabited Timer + +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 disable the timer. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index e706efff5..2c682ccf7 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -273,4 +273,9 @@ public class PaperWorldConfig { + private void firePhysicsEventForRedstone() { + firePhysicsEventForRedstone = getBoolean("fire-physics-event-for-redstone", firePhysicsEventForRedstone); + } ++ ++ public boolean useInhabitedTime = true; ++ private void useInhabitedTime() { ++ useInhabitedTime = getBoolean("use-chunk-inhabited-timer", true); ++ } + } +diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java +index 736fa1f62..61d34fc37 100644 +--- a/src/main/java/net/minecraft/server/Chunk.java ++++ b/src/main/java/net/minecraft/server/Chunk.java +@@ -1405,7 +1405,7 @@ public class Chunk { + } + + public long x() { +- return this.w; ++ return world.paperConfig.useInhabitedTime ? this.w : 0; // Paper + } + + public void c(long i) { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0095-Entity-AddTo-RemoveFrom-World-Events.patch b/Spigot-Server-Patches/0095-Entity-AddTo-RemoveFrom-World-Events.patch deleted file mode 100644 index 7690888efe..0000000000 --- a/Spigot-Server-Patches/0095-Entity-AddTo-RemoveFrom-World-Events.patch +++ /dev/null @@ -1,29 +0,0 @@ -From e87ca8c0409093b76e27c0077e2b3a86c26e045b 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/World.java b/src/main/java/net/minecraft/server/World.java -index 8cbdbda92..f86c64cb2 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -1182,6 +1182,7 @@ public abstract class World implements IBlockAccess { - } - - entity.valid = true; // CraftBukkit -+ new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid - } - - protected void c(Entity entity) { -@@ -1189,6 +1190,7 @@ public abstract class World implements IBlockAccess { - ((IWorldAccess) this.u.get(i)).b(entity); - } - -+ new com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid - entity.valid = false; // CraftBukkit - } - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0096-Configurable-Chunk-Inhabited-Timer.patch b/Spigot-Server-Patches/0096-Configurable-Chunk-Inhabited-Timer.patch deleted file mode 100644 index d8eaf22d1a..0000000000 --- a/Spigot-Server-Patches/0096-Configurable-Chunk-Inhabited-Timer.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 2f4d4c62f46ec42fef570d76224b5e12257eb95b Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 20:46:14 -0400 -Subject: [PATCH] Configurable Chunk Inhabited Timer - -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 disable the timer. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index e706efff5..2c682ccf7 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -273,4 +273,9 @@ public class PaperWorldConfig { - private void firePhysicsEventForRedstone() { - firePhysicsEventForRedstone = getBoolean("fire-physics-event-for-redstone", firePhysicsEventForRedstone); - } -+ -+ public boolean useInhabitedTime = true; -+ private void useInhabitedTime() { -+ useInhabitedTime = getBoolean("use-chunk-inhabited-timer", true); -+ } - } -diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java -index 736fa1f62..61d34fc37 100644 ---- a/src/main/java/net/minecraft/server/Chunk.java -+++ b/src/main/java/net/minecraft/server/Chunk.java -@@ -1405,7 +1405,7 @@ public class Chunk { - } - - public long x() { -- return this.w; -+ return world.paperConfig.useInhabitedTime ? this.w : 0; // Paper - } - - public void c(long i) { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0096-EntityPathfindEvent.patch b/Spigot-Server-Patches/0096-EntityPathfindEvent.patch new file mode 100644 index 0000000000..7d41201621 --- /dev/null +++ b/Spigot-Server-Patches/0096-EntityPathfindEvent.patch @@ -0,0 +1,39 @@ +From 8b31a83fcf313a58a3d2657eb4a618fe27452a35 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/server/NavigationAbstract.java b/src/main/java/net/minecraft/server/NavigationAbstract.java +index 43b2be505..c0ef2400b 100644 +--- a/src/main/java/net/minecraft/server/NavigationAbstract.java ++++ b/src/main/java/net/minecraft/server/NavigationAbstract.java +@@ -4,7 +4,7 @@ import javax.annotation.Nullable; + + public abstract class NavigationAbstract { + +- protected EntityInsentient a; ++ protected EntityInsentient a; public Entity getEntity() { return a; } // Paper - OBFHELPER + protected World b; + @Nullable + protected PathEntity c; +@@ -74,6 +74,7 @@ public abstract class NavigationAbstract { + } else if (this.c != null && !this.c.b() && blockposition.equals(this.q)) { + return this.c; + } else { ++ if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), MCUtil.toLocation(getEntity().world, blockposition), null).callEvent()) { return null; } // Paper + this.q = blockposition; + float f = this.h(); + +@@ -98,6 +99,7 @@ public abstract class NavigationAbstract { + if (this.c != null && !this.c.b() && blockposition.equals(this.q)) { + return this.c; + } else { ++ if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), MCUtil.toLocation(entity.world, blockposition), entity.getBukkitEntity()).callEvent()) { return null; } // Paper + this.q = blockposition; + float f = this.h(); + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0097-EntityPathfindEvent.patch b/Spigot-Server-Patches/0097-EntityPathfindEvent.patch deleted file mode 100644 index dc1e483d49..0000000000 --- a/Spigot-Server-Patches/0097-EntityPathfindEvent.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 45f66cc197d1dcd2090286f05210c9acef78ca40 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/server/NavigationAbstract.java b/src/main/java/net/minecraft/server/NavigationAbstract.java -index 43b2be505..c0ef2400b 100644 ---- a/src/main/java/net/minecraft/server/NavigationAbstract.java -+++ b/src/main/java/net/minecraft/server/NavigationAbstract.java -@@ -4,7 +4,7 @@ import javax.annotation.Nullable; - - public abstract class NavigationAbstract { - -- protected EntityInsentient a; -+ protected EntityInsentient a; public Entity getEntity() { return a; } // Paper - OBFHELPER - protected World b; - @Nullable - protected PathEntity c; -@@ -74,6 +74,7 @@ public abstract class NavigationAbstract { - } else if (this.c != null && !this.c.b() && blockposition.equals(this.q)) { - return this.c; - } else { -+ if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), MCUtil.toLocation(getEntity().world, blockposition), null).callEvent()) { return null; } // Paper - this.q = blockposition; - float f = this.h(); - -@@ -98,6 +99,7 @@ public abstract class NavigationAbstract { - if (this.c != null && !this.c.b() && blockposition.equals(this.q)) { - return this.c; - } else { -+ if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), MCUtil.toLocation(entity.world, blockposition), entity.getBukkitEntity()).callEvent()) { return null; } // Paper - this.q = blockposition; - float f = this.h(); - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0097-Prevent-Waterflow-BlockFromToEvent-from-loading-chun.patch b/Spigot-Server-Patches/0097-Prevent-Waterflow-BlockFromToEvent-from-loading-chun.patch new file mode 100644 index 0000000000..d0adde3580 --- /dev/null +++ b/Spigot-Server-Patches/0097-Prevent-Waterflow-BlockFromToEvent-from-loading-chun.patch @@ -0,0 +1,52 @@ +From 58e7452d99c66366f890d624f3ee8315fe87eb8c Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 28 Mar 2016 22:03:09 -0400 +Subject: [PATCH] Prevent Waterflow BlockFromToEvent from loading chunks + +Many protection plugins would unintentionally trigger chunk loads +by calling .getToBlock() on an unloaded chunk, killing performance. + +Simply skip the event call. as CraftBukkit blocks changing the block +of unloaded chunks anyways. + +This keeps behavior consistent, vs inconsistent flowing based on plugin triggered loads. + +diff --git a/src/main/java/net/minecraft/server/BlockFlowing.java b/src/main/java/net/minecraft/server/BlockFlowing.java +index 0a2823686..8eba70b01 100644 +--- a/src/main/java/net/minecraft/server/BlockFlowing.java ++++ b/src/main/java/net/minecraft/server/BlockFlowing.java +@@ -96,6 +96,7 @@ public class BlockFlowing extends BlockFluids { + + if (this.h(world, blockposition.down(), iblockdata2)) { + // CraftBukkit start ++ if (!canFlowTo(world, source, BlockFace.DOWN)) { return; } // Paper + BlockFromToEvent event = new BlockFromToEvent(source, BlockFace.DOWN); + world.getServer().getPluginManager().callEvent(event); + +@@ -136,6 +137,7 @@ public class BlockFlowing extends BlockFluids { + EnumDirection enumdirection1 = (EnumDirection) iterator1.next(); + + // CraftBukkit start ++ if (!canFlowTo(world, source, org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(enumdirection1))) { continue; } // Paper + BlockFromToEvent event = new BlockFromToEvent(source, org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(enumdirection1)); + world.getServer().getPluginManager().callEvent(event); + +@@ -148,8 +150,14 @@ public class BlockFlowing extends BlockFluids { + + } + ++ // Paper start ++ private boolean canFlowTo(World world, org.bukkit.block.Block source, BlockFace face) { ++ return source.getWorld().isChunkLoaded((source.getX() + face.getModX()) >> 4, (source.getZ() + face.getModZ()) >> 4); ++ } ++ // Paper end ++ + private void flow(World world, BlockPosition blockposition, IBlockData iblockdata, int i) { +- if (world.isLoaded(blockposition) && this.h(world, blockposition, iblockdata)) { // CraftBukkit - add isLoaded check ++ if (/*world.isLoaded(blockposition) &&*/ this.h(world, blockposition, iblockdata)) { // CraftBukkit - add isLoaded check // Paper - Already checked before we get here for isLoaded + if (iblockdata.getMaterial() != Material.AIR) { + if (this.material == Material.LAVA) { + this.fizz(world, blockposition); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0098-Prevent-Waterflow-BlockFromToEvent-from-loading-chun.patch b/Spigot-Server-Patches/0098-Prevent-Waterflow-BlockFromToEvent-from-loading-chun.patch deleted file mode 100644 index 928b555b1b..0000000000 --- a/Spigot-Server-Patches/0098-Prevent-Waterflow-BlockFromToEvent-from-loading-chun.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 063a6b2a26bfabac382e663575b0a98e517346d9 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 22:03:09 -0400 -Subject: [PATCH] Prevent Waterflow BlockFromToEvent from loading chunks - -Many protection plugins would unintentionally trigger chunk loads -by calling .getToBlock() on an unloaded chunk, killing performance. - -Simply skip the event call. as CraftBukkit blocks changing the block -of unloaded chunks anyways. - -This keeps behavior consistent, vs inconsistent flowing based on plugin triggered loads. - -diff --git a/src/main/java/net/minecraft/server/BlockFlowing.java b/src/main/java/net/minecraft/server/BlockFlowing.java -index 0a2823686..8eba70b01 100644 ---- a/src/main/java/net/minecraft/server/BlockFlowing.java -+++ b/src/main/java/net/minecraft/server/BlockFlowing.java -@@ -96,6 +96,7 @@ public class BlockFlowing extends BlockFluids { - - if (this.h(world, blockposition.down(), iblockdata2)) { - // CraftBukkit start -+ if (!canFlowTo(world, source, BlockFace.DOWN)) { return; } // Paper - BlockFromToEvent event = new BlockFromToEvent(source, BlockFace.DOWN); - world.getServer().getPluginManager().callEvent(event); - -@@ -136,6 +137,7 @@ public class BlockFlowing extends BlockFluids { - EnumDirection enumdirection1 = (EnumDirection) iterator1.next(); - - // CraftBukkit start -+ if (!canFlowTo(world, source, org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(enumdirection1))) { continue; } // Paper - BlockFromToEvent event = new BlockFromToEvent(source, org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(enumdirection1)); - world.getServer().getPluginManager().callEvent(event); - -@@ -148,8 +150,14 @@ public class BlockFlowing extends BlockFluids { - - } - -+ // Paper start -+ private boolean canFlowTo(World world, org.bukkit.block.Block source, BlockFace face) { -+ return source.getWorld().isChunkLoaded((source.getX() + face.getModX()) >> 4, (source.getZ() + face.getModZ()) >> 4); -+ } -+ // Paper end -+ - private void flow(World world, BlockPosition blockposition, IBlockData iblockdata, int i) { -- if (world.isLoaded(blockposition) && this.h(world, blockposition, iblockdata)) { // CraftBukkit - add isLoaded check -+ if (/*world.isLoaded(blockposition) &&*/ this.h(world, blockposition, iblockdata)) { // CraftBukkit - add isLoaded check // Paper - Already checked before we get here for isLoaded - if (iblockdata.getMaterial() != Material.AIR) { - if (this.material == Material.LAVA) { - this.fizz(world, blockposition); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0098-Reduce-IO-ops-opening-a-new-region-file.patch b/Spigot-Server-Patches/0098-Reduce-IO-ops-opening-a-new-region-file.patch new file mode 100644 index 0000000000..0e9e804207 --- /dev/null +++ b/Spigot-Server-Patches/0098-Reduce-IO-ops-opening-a-new-region-file.patch @@ -0,0 +1,53 @@ +From 4e9603ee0e06578012952c18fe907aff009b583c Mon Sep 17 00:00:00 2001 +From: Antony Riley +Date: Tue, 29 Mar 2016 06:56:23 +0300 +Subject: [PATCH] Reduce IO ops opening a new region file. + + +diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java +index ed840dbc9..4008a2143 100644 +--- a/src/main/java/net/minecraft/server/RegionFile.java ++++ b/src/main/java/net/minecraft/server/RegionFile.java +@@ -8,9 +8,12 @@ import java.io.ByteArrayInputStream; + import java.io.ByteArrayOutputStream; + import java.io.DataInputStream; + import java.io.DataOutputStream; ++import java.io.EOFException; + import java.io.File; + import java.io.IOException; + import java.io.RandomAccessFile; ++import java.nio.ByteBuffer; ++import java.nio.IntBuffer; + import java.util.List; + import java.util.zip.DeflaterOutputStream; + import java.util.zip.GZIPInputStream; +@@ -67,8 +70,16 @@ public class RegionFile { + + int k; + ++ // Paper Start ++ ByteBuffer header = ByteBuffer.allocate(8192); ++ while (header.hasRemaining()) { ++ if (this.c.getChannel().read(header) == -1) throw new EOFException(); ++ } ++ header.clear(); ++ IntBuffer headerAsInts = header.asIntBuffer(); ++ // Paper End + for (j = 0; j < 1024; ++j) { +- k = this.c.readInt(); ++ k = headerAsInts.get(); // Paper + this.d[j] = k; + if (k != 0 && (k >> 8) + (k & 255) <= this.f.size()) { + for (int l = 0; l < (k & 255); ++l) { +@@ -78,7 +89,7 @@ public class RegionFile { + } + + for (j = 0; j < 1024; ++j) { +- k = this.c.readInt(); ++ k = headerAsInts.get(); // Paper + this.e[j] = k; + } + } catch (IOException ioexception) { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0099-Reduce-IO-ops-opening-a-new-region-file.patch b/Spigot-Server-Patches/0099-Reduce-IO-ops-opening-a-new-region-file.patch deleted file mode 100644 index 18ee6f8d42..0000000000 --- a/Spigot-Server-Patches/0099-Reduce-IO-ops-opening-a-new-region-file.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 5fd361c508284348b1fe96835571b9d871da0ddc Mon Sep 17 00:00:00 2001 -From: Antony Riley -Date: Tue, 29 Mar 2016 06:56:23 +0300 -Subject: [PATCH] Reduce IO ops opening a new region file. - - -diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java -index 9cfc46bc2..637e5baaf 100644 ---- a/src/main/java/net/minecraft/server/RegionFile.java -+++ b/src/main/java/net/minecraft/server/RegionFile.java -@@ -8,9 +8,12 @@ import java.io.ByteArrayInputStream; - import java.io.ByteArrayOutputStream; - import java.io.DataInputStream; - import java.io.DataOutputStream; -+import java.io.EOFException; - import java.io.File; - import java.io.IOException; - import java.io.RandomAccessFile; -+import java.nio.ByteBuffer; -+import java.nio.IntBuffer; - import java.util.List; - import java.util.zip.DeflaterOutputStream; - import java.util.zip.GZIPInputStream; -@@ -67,8 +70,16 @@ public class RegionFile { - - int k; - -+ // Paper Start -+ ByteBuffer header = ByteBuffer.allocate(8192); -+ while (header.hasRemaining()) { -+ if (this.c.getChannel().read(header) == -1) throw new EOFException(); -+ } -+ header.clear(); -+ IntBuffer headerAsInts = header.asIntBuffer(); -+ // Paper End - for (j = 0; j < 1024; ++j) { -- k = this.c.readInt(); -+ k = headerAsInts.get(); // Paper - this.d[j] = k; - if (k != 0 && (k >> 8) + (k & 255) <= this.f.size()) { - for (int l = 0; l < (k & 255); ++l) { -@@ -78,7 +89,7 @@ public class RegionFile { - } - - for (j = 0; j < 1024; ++j) { -- k = this.c.readInt(); -+ k = headerAsInts.get(); // Paper - this.e[j] = k; - } - } catch (IOException ioexception) { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0099-Sanitise-RegionFileCache-and-make-configurable.patch b/Spigot-Server-Patches/0099-Sanitise-RegionFileCache-and-make-configurable.patch new file mode 100644 index 0000000000..05510d35eb --- /dev/null +++ b/Spigot-Server-Patches/0099-Sanitise-RegionFileCache-and-make-configurable.patch @@ -0,0 +1,81 @@ +From e9bec1384df97f7d694ebfa1dad07e0ae0e3faab 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 6907d4680..c3ff47e00 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -220,4 +220,9 @@ public class PaperConfig { + private static void healthDeath() { + setHealthBeforeDeathEvent = getBoolean("settings.set-health-before-death-event", false); + } ++ ++ public static int regionFileCacheSize = 256; ++ private static void regionFileCacheSize() { ++ regionFileCacheSize = getInt("settings.region-file-cache-size", 256); ++ } + } +diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java +index 02b9bc8df..91b55074e 100644 +--- a/src/main/java/net/minecraft/server/RegionFileCache.java ++++ b/src/main/java/net/minecraft/server/RegionFileCache.java +@@ -8,10 +8,12 @@ import java.io.File; + import java.io.IOException; + import java.util.Iterator; + import java.util.Map; ++import com.destroystokyo.paper.PaperConfig; // Paper ++import java.util.LinkedHashMap; // Paper + + public class RegionFileCache { + +- public static final Map a = Maps.newHashMap(); // Spigot - private -> public ++ public static final Map a = new LinkedHashMap(PaperConfig.regionFileCacheSize, 0.75f, true); // Spigot - private -> public, Paper - HashMap -> LinkedHashMap + + public static synchronized RegionFile a(File file, int i, int j) { + File file1 = new File(file, "region"); +@@ -25,8 +27,8 @@ public class RegionFileCache { + file1.mkdirs(); + } + +- if (RegionFileCache.a.size() >= 256) { +- a(); ++ if (RegionFileCache.a.size() >= PaperConfig.regionFileCacheSize) { // Paper ++ trimCache(); // Paper + } + + RegionFile regionfile1 = new RegionFile(file2); +@@ -57,6 +59,22 @@ public class RegionFileCache { + } + } + ++ // Paper Start ++ private static synchronized void trimCache() { ++ Iterator> itr = RegionFileCache.a.entrySet().iterator(); ++ int count = RegionFileCache.a.size() - PaperConfig.regionFileCacheSize; ++ while (count-- >= 0 && itr.hasNext()) { ++ try { ++ itr.next().getValue().c(); ++ } catch (IOException ioexception) { ++ ioexception.printStackTrace(); ++ ServerInternalException.reportInternalException(ioexception); ++ } ++ itr.remove(); ++ } ++ } ++ // Paper End ++ + public static synchronized void a() { + Iterator iterator = RegionFileCache.a.values().iterator(); + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0100-Sanitise-RegionFileCache-and-make-configurable.patch b/Spigot-Server-Patches/0100-Sanitise-RegionFileCache-and-make-configurable.patch deleted file mode 100644 index 61f928c687..0000000000 --- a/Spigot-Server-Patches/0100-Sanitise-RegionFileCache-and-make-configurable.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 61c14766f4cf6eb0ac45cfcd60aae9fdcba217e8 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 6907d4680..c3ff47e00 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -220,4 +220,9 @@ public class PaperConfig { - private static void healthDeath() { - setHealthBeforeDeathEvent = getBoolean("settings.set-health-before-death-event", false); - } -+ -+ public static int regionFileCacheSize = 256; -+ private static void regionFileCacheSize() { -+ regionFileCacheSize = getInt("settings.region-file-cache-size", 256); -+ } - } -diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java -index 19fbf9b4a..ad00c39ce 100644 ---- a/src/main/java/net/minecraft/server/RegionFileCache.java -+++ b/src/main/java/net/minecraft/server/RegionFileCache.java -@@ -8,10 +8,12 @@ import java.io.File; - import java.io.IOException; - import java.util.Iterator; - import java.util.Map; -+import com.destroystokyo.paper.PaperConfig; // Paper -+import java.util.LinkedHashMap; // Paper - - public class RegionFileCache { - -- public static final Map a = Maps.newHashMap(); // Spigot - private -> public -+ public static final Map a = new LinkedHashMap(PaperConfig.regionFileCacheSize, 0.75f, true); // Spigot - private -> public, Paper - HashMap -> LinkedHashMap - - // Paper start - public static synchronized RegionFile a(File file, int i, int j) { -@@ -32,8 +34,8 @@ public class RegionFileCache { - file1.mkdirs(); - } - -- if (RegionFileCache.a.size() >= 256) { -- a(); -+ if (RegionFileCache.a.size() >= PaperConfig.regionFileCacheSize) { // Paper -+ trimCache(); // Paper - } - - RegionFile regionfile1 = new RegionFile(file2); -@@ -64,6 +66,22 @@ public class RegionFileCache { - } - } - -+ // Paper Start -+ private static synchronized void trimCache() { -+ Iterator> itr = RegionFileCache.a.entrySet().iterator(); -+ int count = RegionFileCache.a.size() - PaperConfig.regionFileCacheSize; -+ while (count-- >= 0 && itr.hasNext()) { -+ try { -+ itr.next().getValue().c(); -+ } catch (IOException ioexception) { -+ ioexception.printStackTrace(); -+ ServerInternalException.reportInternalException(ioexception); -+ } -+ itr.remove(); -+ } -+ } -+ // Paper End -+ - public static synchronized void a() { - Iterator iterator = RegionFileCache.a.values().iterator(); - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0100-Use-Optimized-Collections.patch b/Spigot-Server-Patches/0100-Use-Optimized-Collections.patch new file mode 100644 index 0000000000..44fc35b3bb --- /dev/null +++ b/Spigot-Server-Patches/0100-Use-Optimized-Collections.patch @@ -0,0 +1,51 @@ +From bf55746ae8469ec426c19372f7fd267fc13b976e Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 30 Mar 2016 02:13:24 -0400 +Subject: [PATCH] Use Optimized Collections + +Swap out CraftBukkit LongObjectHashMap with Long2ObjectOpenHashMap +Swap out Integer key HashMap for a Int2ObjectOpenHashMap For ChunkProviderServer + +Amaranth, the creator of LongObjectHashMap, tested it vs fastutil and determined fastutil to be 3x faster +and could not create anything faster than fastutil. + +These collections are super fast as seen +http://java-performance.info/hashmap-overview-jdk-fastutil-goldman-sachs-hppc-koloboke-trove-january-2015/ + +diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java +index b49f4e292..dd37bec73 100644 +--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java +@@ -24,7 +24,7 @@ import org.bukkit.event.world.ChunkUnloadEvent; + public class ChunkProviderServer implements IChunkProvider { + + private static final Logger a = LogManager.getLogger(); +- public final Set unloadQueue = Sets.newHashSet(); ++ public final it.unimi.dsi.fastutil.longs.LongSet unloadQueue = new it.unimi.dsi.fastutil.longs.LongArraySet(); // PAIL: private -> public // Paper + public final ChunkGenerator chunkGenerator; + private final IChunkLoader chunkLoader; + // Paper start +diff --git a/src/main/java/net/minecraft/server/DataWatcher.java b/src/main/java/net/minecraft/server/DataWatcher.java +index 419add5db..820c15278 100644 +--- a/src/main/java/net/minecraft/server/DataWatcher.java ++++ b/src/main/java/net/minecraft/server/DataWatcher.java +@@ -12,6 +12,7 @@ import java.util.Map; + import java.util.concurrent.locks.ReadWriteLock; + import java.util.concurrent.locks.ReentrantReadWriteLock; + import javax.annotation.Nullable; ++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; +@@ -21,7 +22,7 @@ public class DataWatcher { + private static final Logger a = LogManager.getLogger(); + private static final Map, Integer> b = Maps.newHashMap(); + private final Entity c; +- private final Map> d = Maps.newHashMap(); ++ private final Map> d = new Int2ObjectOpenHashMap<>(); // Paper + private final ReadWriteLock e = new ReentrantReadWriteLock(); + private boolean f = true; + private boolean g; +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0101-Do-not-load-chunks-for-light-checks.patch b/Spigot-Server-Patches/0101-Do-not-load-chunks-for-light-checks.patch new file mode 100644 index 0000000000..0adcf8eaa8 --- /dev/null +++ b/Spigot-Server-Patches/0101-Do-not-load-chunks-for-light-checks.patch @@ -0,0 +1,23 @@ +From 0528c8e87adbb3e0ca9714a8c7cdada59d34319a 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 light checks + +Should only happen for blocks on the edge that uses neighbors light level +(certain blocks). In that case, there will be 3-4 other neighbors to get a light level from. + +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index f86c64cb2..7e6459654 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -759,6 +759,7 @@ public abstract class World implements IBlockAccess { + if (blockposition.getY() >= 256) { + blockposition = new BlockPosition(blockposition.getX(), 255, blockposition.getZ()); + } ++ if (!this.isLoaded(blockposition)) return 0; // Paper + + Chunk chunk = this.getChunkAtWorldCoords(blockposition); + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0101-Use-Optimized-Collections.patch b/Spigot-Server-Patches/0101-Use-Optimized-Collections.patch deleted file mode 100644 index 793086bf92..0000000000 --- a/Spigot-Server-Patches/0101-Use-Optimized-Collections.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0d5d2097b72aa92d7199dd4b84adc080cb9df775 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 30 Mar 2016 02:13:24 -0400 -Subject: [PATCH] Use Optimized Collections - -Swap out CraftBukkit LongObjectHashMap with Long2ObjectOpenHashMap -Swap out Integer key HashMap for a Int2ObjectOpenHashMap For ChunkProviderServer - -Amaranth, the creator of LongObjectHashMap, tested it vs fastutil and determined fastutil to be 3x faster -and could not create anything faster than fastutil. - -These collections are super fast as seen -http://java-performance.info/hashmap-overview-jdk-fastutil-goldman-sachs-hppc-koloboke-trove-january-2015/ - -diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java -index a7e8a3f7d..54b454fe3 100644 ---- a/src/main/java/net/minecraft/server/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java -@@ -24,7 +24,7 @@ import org.bukkit.event.world.ChunkUnloadEvent; - public class ChunkProviderServer implements IChunkProvider { - - private static final Logger a = LogManager.getLogger(); -- public final Set unloadQueue = Sets.newHashSet(); -+ public final it.unimi.dsi.fastutil.longs.LongSet unloadQueue = new it.unimi.dsi.fastutil.longs.LongArraySet(); // PAIL: private -> public // Paper - public final ChunkGenerator chunkGenerator; - private final IChunkLoader chunkLoader; - // Paper start -diff --git a/src/main/java/net/minecraft/server/DataWatcher.java b/src/main/java/net/minecraft/server/DataWatcher.java -index 419add5db..820c15278 100644 ---- a/src/main/java/net/minecraft/server/DataWatcher.java -+++ b/src/main/java/net/minecraft/server/DataWatcher.java -@@ -12,6 +12,7 @@ import java.util.Map; - import java.util.concurrent.locks.ReadWriteLock; - import java.util.concurrent.locks.ReentrantReadWriteLock; - import javax.annotation.Nullable; -+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; -@@ -21,7 +22,7 @@ public class DataWatcher { - private static final Logger a = LogManager.getLogger(); - private static final Map, Integer> b = Maps.newHashMap(); - private final Entity c; -- private final Map> d = Maps.newHashMap(); -+ private final Map> d = new Int2ObjectOpenHashMap<>(); // Paper - private final ReadWriteLock e = new ReentrantReadWriteLock(); - private boolean f = true; - private boolean g; --- -2.12.2 - diff --git a/Spigot-Server-Patches/0102-Add-PlayerUseUnknownEntityEvent.patch b/Spigot-Server-Patches/0102-Add-PlayerUseUnknownEntityEvent.patch new file mode 100644 index 0000000000..a126211f05 --- /dev/null +++ b/Spigot-Server-Patches/0102-Add-PlayerUseUnknownEntityEvent.patch @@ -0,0 +1,43 @@ +From ce229663241dcac2571047f5a1c9af02acd3c1c3 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/server/PacketPlayInUseEntity.java b/src/main/java/net/minecraft/server/PacketPlayInUseEntity.java +index c67cb54a3..521f46262 100644 +--- a/src/main/java/net/minecraft/server/PacketPlayInUseEntity.java ++++ b/src/main/java/net/minecraft/server/PacketPlayInUseEntity.java +@@ -5,7 +5,7 @@ import javax.annotation.Nullable; + + 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/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index b67837dd2..840448995 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -1614,6 +1614,16 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { + } + } + } ++ // Paper start - fire event ++ else { ++ this.server.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerUseUnknownEntityEvent( ++ this.getPlayer(), ++ packetplayinuseentity.getEntityId(), ++ packetplayinuseentity.a() == PacketPlayInUseEntity.EnumEntityUseAction.ATTACK, ++ packetplayinuseentity.b() == EnumHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND ++ )); ++ } ++ // Paper end + + } + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0102-Do-not-load-chunks-for-light-checks.patch b/Spigot-Server-Patches/0102-Do-not-load-chunks-for-light-checks.patch deleted file mode 100644 index c4db3b2789..0000000000 --- a/Spigot-Server-Patches/0102-Do-not-load-chunks-for-light-checks.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 22757113dc8d4014c7fe8ef4fb3d8a734fddf9fe 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 light checks - -Should only happen for blocks on the edge that uses neighbors light level -(certain blocks). In that case, there will be 3-4 other neighbors to get a light level from. - -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index f86c64cb2..7e6459654 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -759,6 +759,7 @@ public abstract class World implements IBlockAccess { - if (blockposition.getY() >= 256) { - blockposition = new BlockPosition(blockposition.getX(), 255, blockposition.getZ()); - } -+ if (!this.isLoaded(blockposition)) return 0; // Paper - - Chunk chunk = this.getChunkAtWorldCoords(blockposition); - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0103-Add-PlayerUseUnknownEntityEvent.patch b/Spigot-Server-Patches/0103-Add-PlayerUseUnknownEntityEvent.patch deleted file mode 100644 index 4813c52b9d..0000000000 --- a/Spigot-Server-Patches/0103-Add-PlayerUseUnknownEntityEvent.patch +++ /dev/null @@ -1,43 +0,0 @@ -From a143c953207c29ed4c31626f8a19e2aaa5ef72c0 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/server/PacketPlayInUseEntity.java b/src/main/java/net/minecraft/server/PacketPlayInUseEntity.java -index c67cb54a3..521f46262 100644 ---- a/src/main/java/net/minecraft/server/PacketPlayInUseEntity.java -+++ b/src/main/java/net/minecraft/server/PacketPlayInUseEntity.java -@@ -5,7 +5,7 @@ import javax.annotation.Nullable; - - 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/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index b67837dd2..840448995 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -1614,6 +1614,16 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { - } - } - } -+ // Paper start - fire event -+ else { -+ this.server.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerUseUnknownEntityEvent( -+ this.getPlayer(), -+ packetplayinuseentity.getEntityId(), -+ packetplayinuseentity.a() == PacketPlayInUseEntity.EnumEntityUseAction.ATTACK, -+ packetplayinuseentity.b() == EnumHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND -+ )); -+ } -+ // Paper end - - } - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0103-Fix-reducedDebugInfo-not-initialized-on-client.patch b/Spigot-Server-Patches/0103-Fix-reducedDebugInfo-not-initialized-on-client.patch new file mode 100644 index 0000000000..4c32cb1f8c --- /dev/null +++ b/Spigot-Server-Patches/0103-Fix-reducedDebugInfo-not-initialized-on-client.patch @@ -0,0 +1,21 @@ +From 797ffb13230f48f427a2a5e354dce5cc853ae481 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/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java +index 59c7e78b8..e303b45f0 100644 +--- a/src/main/java/net/minecraft/server/PlayerList.java ++++ b/src/main/java/net/minecraft/server/PlayerList.java +@@ -154,6 +154,7 @@ public abstract class PlayerList { + playerconnection.sendPacket(new PacketPlayOutServerDifficulty(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); + playerconnection.sendPacket(new PacketPlayOutAbilities(entityplayer.abilities)); + playerconnection.sendPacket(new PacketPlayOutHeldItemSlot(entityplayer.inventory.itemInHandIndex)); ++ playerconnection.sendPacket(new PacketPlayOutEntityStatus(entityplayer, (byte) (worldserver.getGameRules().getBoolean("reducedDebugInfo") ? 22 : 23))); // Paper - fix this rule not being initialized on the client + this.f(entityplayer); + entityplayer.getStatisticManager().d(); + entityplayer.getStatisticManager().updateStatistics(entityplayer); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0104-Configurable-Grass-Spread-Tick-Rate.patch b/Spigot-Server-Patches/0104-Configurable-Grass-Spread-Tick-Rate.patch new file mode 100644 index 0000000000..38541c1730 --- /dev/null +++ b/Spigot-Server-Patches/0104-Configurable-Grass-Spread-Tick-Rate.patch @@ -0,0 +1,36 @@ +From 408594ec2da3c56bb04e5789c7fb2ccaa85dd7c2 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 2c682ccf7..74a49a5fb 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -278,4 +278,10 @@ public class PaperWorldConfig { + private void useInhabitedTime() { + useInhabitedTime = getBoolean("use-chunk-inhabited-timer", true); + } ++ ++ 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/server/BlockGrass.java b/src/main/java/net/minecraft/server/BlockGrass.java +index 8b43e6070..5cbc95f7c 100644 +--- a/src/main/java/net/minecraft/server/BlockGrass.java ++++ b/src/main/java/net/minecraft/server/BlockGrass.java +@@ -28,6 +28,7 @@ public class BlockGrass extends Block implements IBlockFragilePlantElement { + } + + public void b(World world, BlockPosition blockposition, IBlockData iblockdata, Random random) { ++ if (world.paperConfig.grassUpdateRate != 1 && (world.paperConfig.grassUpdateRate < 1 || (MinecraftServer.currentTick + blockposition.hashCode()) % world.paperConfig.grassUpdateRate != 0)) { return; } // Paper + if (!world.isClientSide) { + int lightLevel = -1; // Paper + if (world.getType(blockposition.up()).c() > 2 && (lightLevel = world.getLightLevel(blockposition.up())) < 4) { // Paper - move light check to end to avoid unneeded light lookups +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0104-Fix-reducedDebugInfo-not-initialized-on-client.patch b/Spigot-Server-Patches/0104-Fix-reducedDebugInfo-not-initialized-on-client.patch deleted file mode 100644 index bf318a6fe6..0000000000 --- a/Spigot-Server-Patches/0104-Fix-reducedDebugInfo-not-initialized-on-client.patch +++ /dev/null @@ -1,21 +0,0 @@ -From a93413a68948fca1c6565e2998d21c76031a7f04 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/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java -index d6a2bbc08..b8d48b45c 100644 ---- a/src/main/java/net/minecraft/server/PlayerList.java -+++ b/src/main/java/net/minecraft/server/PlayerList.java -@@ -154,6 +154,7 @@ public abstract class PlayerList { - playerconnection.sendPacket(new PacketPlayOutServerDifficulty(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); - playerconnection.sendPacket(new PacketPlayOutAbilities(entityplayer.abilities)); - playerconnection.sendPacket(new PacketPlayOutHeldItemSlot(entityplayer.inventory.itemInHandIndex)); -+ playerconnection.sendPacket(new PacketPlayOutEntityStatus(entityplayer, (byte) (worldserver.getGameRules().getBoolean("reducedDebugInfo") ? 22 : 23))); // Paper - fix this rule not being initialized on the client - this.f(entityplayer); - entityplayer.getStatisticManager().d(); - entityplayer.getStatisticManager().updateStatistics(entityplayer); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0105-Configurable-Grass-Spread-Tick-Rate.patch b/Spigot-Server-Patches/0105-Configurable-Grass-Spread-Tick-Rate.patch deleted file mode 100644 index 2928d83bd5..0000000000 --- a/Spigot-Server-Patches/0105-Configurable-Grass-Spread-Tick-Rate.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 2239e93f9ca22ddb356ed4ee329aae51355d6a5d 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 2c682ccf7..74a49a5fb 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -278,4 +278,10 @@ public class PaperWorldConfig { - private void useInhabitedTime() { - useInhabitedTime = getBoolean("use-chunk-inhabited-timer", true); - } -+ -+ 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/server/BlockGrass.java b/src/main/java/net/minecraft/server/BlockGrass.java -index 8b43e6070..5cbc95f7c 100644 ---- a/src/main/java/net/minecraft/server/BlockGrass.java -+++ b/src/main/java/net/minecraft/server/BlockGrass.java -@@ -28,6 +28,7 @@ public class BlockGrass extends Block implements IBlockFragilePlantElement { - } - - public void b(World world, BlockPosition blockposition, IBlockData iblockdata, Random random) { -+ if (world.paperConfig.grassUpdateRate != 1 && (world.paperConfig.grassUpdateRate < 1 || (MinecraftServer.currentTick + blockposition.hashCode()) % world.paperConfig.grassUpdateRate != 0)) { return; } // Paper - if (!world.isClientSide) { - int lightLevel = -1; // Paper - if (world.getType(blockposition.up()).c() > 2 && (lightLevel = world.getLightLevel(blockposition.up())) < 4) { // Paper - move light check to end to avoid unneeded light lookups --- -2.12.2 - diff --git a/Spigot-Server-Patches/0105-Configurable-Keep-Spawn-Loaded-range-per-world.patch b/Spigot-Server-Patches/0105-Configurable-Keep-Spawn-Loaded-range-per-world.patch new file mode 100644 index 0000000000..bcb8bf2f4f --- /dev/null +++ b/Spigot-Server-Patches/0105-Configurable-Keep-Spawn-Loaded-range-per-world.patch @@ -0,0 +1,87 @@ +From f825c7818bd1558c1371f174a954545f6959d539 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 74a49a5fb..3a942c763 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -284,4 +284,10 @@ public class PaperWorldConfig { + grassUpdateRate = Math.max(0, getInt("grass-spread-tick-rate", grassUpdateRate)); + log("Grass Spread Tick Rate: " + grassUpdateRate); + } ++ ++ public short keepLoadedRange; ++ private void keepLoadedRange() { ++ keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 8)) * 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 e7c63a953..3aea41f76 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -356,8 +356,11 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs + long j = aw(); + i = 0; + +- for (int k = -192; k <= 192 && this.isRunning(); k += 16) { +- for (int l = -192; l <= 192 && this.isRunning(); l += 16) { ++ // Paper start ++ short radius = worldserver.paperConfig.keepLoadedRange; ++ for (int k = -radius; k <= radius && this.isRunning(); k += 16) { ++ for (int l = -radius; l <= radius && this.isRunning(); l += 16) { ++ // Paper end + long i1 = aw(); + + if (i1 - j > 1000L) { +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 7e6459654..dba3fb167 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -3194,8 +3194,9 @@ public abstract class World implements IBlockAccess { + int k = i * 16 + 8 - blockposition.getX(); + int l = j * 16 + 8 - blockposition.getZ(); + boolean flag = true; ++ short keepLoadedRange = paperConfig.keepLoadedRange; // Paper + +- return k >= -128 && k <= 128 && l >= -128 && l <= 128 && this.keepSpawnInMemory; // CraftBukkit - Added 'this.keepSpawnInMemory' ++ return k >= -keepLoadedRange && k <= keepLoadedRange && l >= -keepLoadedRange && l <= keepLoadedRange && this.keepSpawnInMemory; // CraftBukkit - Added 'this.keepSpawnInMemory' // Paper - Re-add range var + } + + public void a(Packet packet) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 4d761d32a..a958ce998 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -952,7 +952,7 @@ public final class CraftServer implements Server { + System.out.print("Preparing start region for level " + (console.worlds.size() - 1) + " (Seed: " + internal.getSeed() + ")"); + + if (internal.getWorld().getKeepSpawnInMemory()) { +- short short1 = 196; ++ short short1 = internal.paperConfig.keepLoadedRange; // Paper + long i = System.currentTimeMillis(); + for (int j = -short1; j <= short1; j += 16) { + for (int k = -short1; k <= short1; k += 16) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index f65611a6a..9965235ab 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1265,8 +1265,9 @@ public class CraftWorld implements World { + int chunkCoordX = chunkcoordinates.getX() >> 4; + int chunkCoordZ = chunkcoordinates.getZ() >> 4; + // Cycle through the 25x25 Chunks around it to load/unload the chunks. +- for (int x = -12; x <= 12; x++) { +- for (int z = -12; z <= 12; z++) { ++ int radius = world.paperConfig.keepLoadedRange / 16; // Paper ++ for (int x = -radius; x <= radius; x++) { // Paper ++ for (int z = -radius; z <= radius; z++) { // Paper + if (keepLoaded) { + loadChunk(chunkCoordX + x, chunkCoordZ + z); + } else { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0106-Configurable-Keep-Spawn-Loaded-range-per-world.patch b/Spigot-Server-Patches/0106-Configurable-Keep-Spawn-Loaded-range-per-world.patch deleted file mode 100644 index b323cea537..0000000000 --- a/Spigot-Server-Patches/0106-Configurable-Keep-Spawn-Loaded-range-per-world.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 02aceb5c58c3c99427fbc68765cf7ce5340d477d 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 74a49a5fb..3a942c763 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -284,4 +284,10 @@ public class PaperWorldConfig { - grassUpdateRate = Math.max(0, getInt("grass-spread-tick-rate", grassUpdateRate)); - log("Grass Spread Tick Rate: " + grassUpdateRate); - } -+ -+ public short keepLoadedRange; -+ private void keepLoadedRange() { -+ keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 8)) * 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 e7c63a953..3aea41f76 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -356,8 +356,11 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs - long j = aw(); - i = 0; - -- for (int k = -192; k <= 192 && this.isRunning(); k += 16) { -- for (int l = -192; l <= 192 && this.isRunning(); l += 16) { -+ // Paper start -+ short radius = worldserver.paperConfig.keepLoadedRange; -+ for (int k = -radius; k <= radius && this.isRunning(); k += 16) { -+ for (int l = -radius; l <= radius && this.isRunning(); l += 16) { -+ // Paper end - long i1 = aw(); - - if (i1 - j > 1000L) { -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 7e6459654..dba3fb167 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -3194,8 +3194,9 @@ public abstract class World implements IBlockAccess { - int k = i * 16 + 8 - blockposition.getX(); - int l = j * 16 + 8 - blockposition.getZ(); - boolean flag = true; -+ short keepLoadedRange = paperConfig.keepLoadedRange; // Paper - -- return k >= -128 && k <= 128 && l >= -128 && l <= 128 && this.keepSpawnInMemory; // CraftBukkit - Added 'this.keepSpawnInMemory' -+ return k >= -keepLoadedRange && k <= keepLoadedRange && l >= -keepLoadedRange && l <= keepLoadedRange && this.keepSpawnInMemory; // CraftBukkit - Added 'this.keepSpawnInMemory' // Paper - Re-add range var - } - - public void a(Packet packet) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 4d761d32a..a958ce998 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -952,7 +952,7 @@ public final class CraftServer implements Server { - System.out.print("Preparing start region for level " + (console.worlds.size() - 1) + " (Seed: " + internal.getSeed() + ")"); - - if (internal.getWorld().getKeepSpawnInMemory()) { -- short short1 = 196; -+ short short1 = internal.paperConfig.keepLoadedRange; // Paper - long i = System.currentTimeMillis(); - for (int j = -short1; j <= short1; j += 16) { - for (int k = -short1; k <= short1; k += 16) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index f65611a6a..9965235ab 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1265,8 +1265,9 @@ public class CraftWorld implements World { - int chunkCoordX = chunkcoordinates.getX() >> 4; - int chunkCoordZ = chunkcoordinates.getZ() >> 4; - // Cycle through the 25x25 Chunks around it to load/unload the chunks. -- for (int x = -12; x <= 12; x++) { -- for (int z = -12; z <= 12; z++) { -+ int radius = world.paperConfig.keepLoadedRange / 16; // Paper -+ for (int x = -radius; x <= radius; x++) { // Paper -+ for (int z = -radius; z <= radius; z++) { // Paper - if (keepLoaded) { - loadChunk(chunkCoordX + x, chunkCoordZ + z); - } else { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0106-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch b/Spigot-Server-Patches/0106-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch new file mode 100644 index 0000000000..87376f9ffe --- /dev/null +++ b/Spigot-Server-Patches/0106-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch @@ -0,0 +1,21 @@ +From a5d5dda4e43b4daafab005b8cf63e5eb148ebd56 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/server/World.java b/src/main/java/net/minecraft/server/World.java +index dba3fb167..44108ab9a 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -532,6 +532,7 @@ public abstract class World implements IBlockAccess { + } + + public void applyPhysics(BlockPosition blockposition, Block block, boolean flag) { ++ 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); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0107-Don-t-spam-reload-spawn-chunks-in-nether-end.patch b/Spigot-Server-Patches/0107-Don-t-spam-reload-spawn-chunks-in-nether-end.patch new file mode 100644 index 0000000000..be3cddf75c --- /dev/null +++ b/Spigot-Server-Patches/0107-Don-t-spam-reload-spawn-chunks-in-nether-end.patch @@ -0,0 +1,33 @@ +From 76d4bbc0f57b08ce52b6d3a4f3da9c7dc720c6e4 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 5 Apr 2016 19:42:22 -0400 +Subject: [PATCH] Don't spam reload spawn chunks in nether/end + + +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 44108ab9a..9bc8ce64c 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -3190,6 +3190,7 @@ public abstract class World implements IBlockAccess { + return this.N; + } + ++ public boolean shouldStayLoaded(int i, int j) { return e(i, j); } // Paper - OBFHELPER + public boolean e(int i, int j) { + BlockPosition blockposition = this.getSpawn(); + int k = i * 16 + 8 - blockposition.getX(); +diff --git a/src/main/java/net/minecraft/server/WorldProvider.java b/src/main/java/net/minecraft/server/WorldProvider.java +index a27512c0f..4691b3d8f 100644 +--- a/src/main/java/net/minecraft/server/WorldProvider.java ++++ b/src/main/java/net/minecraft/server/WorldProvider.java +@@ -138,6 +138,6 @@ public abstract class WorldProvider { + public void s() {} + + public boolean c(int i, int j) { +- return true; ++ return !this.b.shouldStayLoaded(i, j); // Paper - Use shouldStayLoaded check for all worlds + } + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0107-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch b/Spigot-Server-Patches/0107-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch deleted file mode 100644 index ffad2997ae..0000000000 --- a/Spigot-Server-Patches/0107-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch +++ /dev/null @@ -1,21 +0,0 @@ -From a22863594140aa2beb47672cc81f2eeca3a4424c 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/server/World.java b/src/main/java/net/minecraft/server/World.java -index dba3fb167..44108ab9a 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -532,6 +532,7 @@ public abstract class World implements IBlockAccess { - } - - public void applyPhysics(BlockPosition blockposition, Block block, boolean flag) { -+ 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); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0108-Don-t-spam-reload-spawn-chunks-in-nether-end.patch b/Spigot-Server-Patches/0108-Don-t-spam-reload-spawn-chunks-in-nether-end.patch deleted file mode 100644 index 65a3174398..0000000000 --- a/Spigot-Server-Patches/0108-Don-t-spam-reload-spawn-chunks-in-nether-end.patch +++ /dev/null @@ -1,33 +0,0 @@ -From b45bff5ab25d652697981a8e08b69d4d52edf888 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 5 Apr 2016 19:42:22 -0400 -Subject: [PATCH] Don't spam reload spawn chunks in nether/end - - -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 44108ab9a..9bc8ce64c 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -3190,6 +3190,7 @@ public abstract class World implements IBlockAccess { - return this.N; - } - -+ public boolean shouldStayLoaded(int i, int j) { return e(i, j); } // Paper - OBFHELPER - public boolean e(int i, int j) { - BlockPosition blockposition = this.getSpawn(); - int k = i * 16 + 8 - blockposition.getX(); -diff --git a/src/main/java/net/minecraft/server/WorldProvider.java b/src/main/java/net/minecraft/server/WorldProvider.java -index a27512c0f..4691b3d8f 100644 ---- a/src/main/java/net/minecraft/server/WorldProvider.java -+++ b/src/main/java/net/minecraft/server/WorldProvider.java -@@ -138,6 +138,6 @@ public abstract class WorldProvider { - public void s() {} - - public boolean c(int i, int j) { -- return true; -+ return !this.b.shouldStayLoaded(i, j); // Paper - Use shouldStayLoaded check for all worlds - } - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0108-Remove-Debug-checks-from-DataBits.patch b/Spigot-Server-Patches/0108-Remove-Debug-checks-from-DataBits.patch new file mode 100644 index 0000000000..6dad35ca53 --- /dev/null +++ b/Spigot-Server-Patches/0108-Remove-Debug-checks-from-DataBits.patch @@ -0,0 +1,46 @@ +From bc6666b8fea7c026847ea036395301569eae5fa2 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 5 Apr 2016 21:38:58 -0400 +Subject: [PATCH] Remove Debug checks from DataBits + +These are super hot and causing noticeable hits + +Before: http://i.imgur.com/nQsMzAE.png +After: http://i.imgur.com/nJ46crB.png + +diff --git a/src/main/java/net/minecraft/server/DataBits.java b/src/main/java/net/minecraft/server/DataBits.java +index f3a6799a8..fa0fd8a9c 100644 +--- a/src/main/java/net/minecraft/server/DataBits.java ++++ b/src/main/java/net/minecraft/server/DataBits.java +@@ -10,7 +10,7 @@ public class DataBits { + private final int d; + + public DataBits(int i, int j) { +- Validate.inclusiveBetween(1L, 32L, (long) i); ++ //Validate.inclusiveBetween(1L, 32L, (long) i); // Paper + this.d = j; + this.b = i; + this.c = (1L << i) - 1L; +@@ -18,8 +18,8 @@ public class DataBits { + } + + public void a(int i, int j) { +- Validate.inclusiveBetween(0L, (long) (this.d - 1), (long) i); +- Validate.inclusiveBetween(0L, this.c, (long) j); ++ //Validate.inclusiveBetween(0L, (long) (this.d - 1), (long) i); // Paper ++ //Validate.inclusiveBetween(0L, this.c, (long) j); // Paper + int k = i * this.b; + int l = k / 64; + int i1 = ((i + 1) * this.b - 1) / 64; +@@ -36,7 +36,7 @@ public class DataBits { + } + + public int a(int i) { +- Validate.inclusiveBetween(0L, (long) (this.d - 1), (long) i); ++ //Validate.inclusiveBetween(0L, (long) (this.d - 1), (long) i); // Paper + int j = i * this.b; + int k = j / 64; + int l = ((i + 1) * this.b - 1) / 64; +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0109-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch b/Spigot-Server-Patches/0109-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch new file mode 100644 index 0000000000..64619cd9e0 --- /dev/null +++ b/Spigot-Server-Patches/0109-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch @@ -0,0 +1,55 @@ +From c9d7dd9e35bd8ad3ec1b3ced918e0fdb1dae60b3 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 + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 3a942c763..3bd29650c 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -290,4 +290,9 @@ public class PaperWorldConfig { + keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 8)) * 16); + log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16)); + } ++ ++ public boolean useVanillaScoreboardColoring; ++ private void useVanillaScoreboardColoring() { ++ useVanillaScoreboardColoring = getBoolean("use-vanilla-world-scoreboard-name-coloring", false); ++ } + } +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 70a431a63..8908d8b8d 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -2046,6 +2046,7 @@ public abstract class Entity implements ICommandListener { + return this.getFlag(5); + } + ++ @Nullable public ScoreboardTeamBase getTeam() { return this.aQ(); } // Paper - OBFHELPER + @Nullable + public ScoreboardTeamBase aQ() { + if (!this.world.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof EntityHuman)) { return null; } // Paper +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 840448995..dfbae01f4 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -1347,7 +1347,14 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { + return; + } + +- s = String.format(event.getFormat(), event.getPlayer().getDisplayName(), event.getMessage()); ++ // Paper Start - (Meh) Support for vanilla world scoreboard name coloring ++ String displayName = event.getPlayer().getDisplayName(); ++ if (this.player.getWorld().paperConfig.useVanillaScoreboardColoring) { ++ displayName = ScoreboardTeam.getPlayerDisplayName(this.player.getTeam(), player.getDisplayName()); ++ } ++ ++ s = String.format(event.getFormat(), displayName, event.getMessage()); ++ // Paper end + minecraftServer.console.sendMessage(s); + if (((LazyPlayerSet) event.getRecipients()).isLazy()) { + for (Object recipient : minecraftServer.getPlayerList().players) { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0109-Remove-Debug-checks-from-DataBits.patch b/Spigot-Server-Patches/0109-Remove-Debug-checks-from-DataBits.patch deleted file mode 100644 index 25599d4a18..0000000000 --- a/Spigot-Server-Patches/0109-Remove-Debug-checks-from-DataBits.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 09e2228c9837b20fdc95318fbe4e2a2d8a396f57 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 5 Apr 2016 21:38:58 -0400 -Subject: [PATCH] Remove Debug checks from DataBits - -These are super hot and causing noticeable hits - -Before: http://i.imgur.com/nQsMzAE.png -After: http://i.imgur.com/nJ46crB.png - -diff --git a/src/main/java/net/minecraft/server/DataBits.java b/src/main/java/net/minecraft/server/DataBits.java -index f3a6799a8..fa0fd8a9c 100644 ---- a/src/main/java/net/minecraft/server/DataBits.java -+++ b/src/main/java/net/minecraft/server/DataBits.java -@@ -10,7 +10,7 @@ public class DataBits { - private final int d; - - public DataBits(int i, int j) { -- Validate.inclusiveBetween(1L, 32L, (long) i); -+ //Validate.inclusiveBetween(1L, 32L, (long) i); // Paper - this.d = j; - this.b = i; - this.c = (1L << i) - 1L; -@@ -18,8 +18,8 @@ public class DataBits { - } - - public void a(int i, int j) { -- Validate.inclusiveBetween(0L, (long) (this.d - 1), (long) i); -- Validate.inclusiveBetween(0L, this.c, (long) j); -+ //Validate.inclusiveBetween(0L, (long) (this.d - 1), (long) i); // Paper -+ //Validate.inclusiveBetween(0L, this.c, (long) j); // Paper - int k = i * this.b; - int l = k / 64; - int i1 = ((i + 1) * this.b - 1) / 64; -@@ -36,7 +36,7 @@ public class DataBits { - } - - public int a(int i) { -- Validate.inclusiveBetween(0L, (long) (this.d - 1), (long) i); -+ //Validate.inclusiveBetween(0L, (long) (this.d - 1), (long) i); // Paper - int j = i * this.b; - int k = j / 64; - int l = ((i + 1) * this.b - 1) / 64; --- -2.12.2 - diff --git a/Spigot-Server-Patches/0110-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch b/Spigot-Server-Patches/0110-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch deleted file mode 100644 index 201587187b..0000000000 --- a/Spigot-Server-Patches/0110-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 961fafdaceab970599d69a51dd78cb93a0d93a25 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 - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3a942c763..3bd29650c 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -290,4 +290,9 @@ public class PaperWorldConfig { - keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 8)) * 16); - log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16)); - } -+ -+ public boolean useVanillaScoreboardColoring; -+ private void useVanillaScoreboardColoring() { -+ useVanillaScoreboardColoring = getBoolean("use-vanilla-world-scoreboard-name-coloring", false); -+ } - } -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 70a431a63..8908d8b8d 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -2046,6 +2046,7 @@ public abstract class Entity implements ICommandListener { - return this.getFlag(5); - } - -+ @Nullable public ScoreboardTeamBase getTeam() { return this.aQ(); } // Paper - OBFHELPER - @Nullable - public ScoreboardTeamBase aQ() { - if (!this.world.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof EntityHuman)) { return null; } // Paper -diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 840448995..dfbae01f4 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -1347,7 +1347,14 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { - return; - } - -- s = String.format(event.getFormat(), event.getPlayer().getDisplayName(), event.getMessage()); -+ // Paper Start - (Meh) Support for vanilla world scoreboard name coloring -+ String displayName = event.getPlayer().getDisplayName(); -+ if (this.player.getWorld().paperConfig.useVanillaScoreboardColoring) { -+ displayName = ScoreboardTeam.getPlayerDisplayName(this.player.getTeam(), player.getDisplayName()); -+ } -+ -+ s = String.format(event.getFormat(), displayName, event.getMessage()); -+ // Paper end - minecraftServer.console.sendMessage(s); - if (((LazyPlayerSet) event.getRecipients()).isLazy()) { - for (Object recipient : minecraftServer.getPlayerList().players) { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0110-Workaround-for-setting-passengers-on-players.patch b/Spigot-Server-Patches/0110-Workaround-for-setting-passengers-on-players.patch new file mode 100644 index 0000000000..3296b0bd10 --- /dev/null +++ b/Spigot-Server-Patches/0110-Workaround-for-setting-passengers-on-players.patch @@ -0,0 +1,32 @@ +From e5988d5b1cd40ac1a8b4fa2868e5214516b99c73 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 0a9e8b9cd..8e06c2140 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -589,6 +589,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.server.PacketPlayOutMount(this.getHandle())); ++ } ++ return wasSet; ++ } ++ // Paper end ++ + @Override + public void setSneaking(boolean sneak) { + getHandle().setSneaking(sneak); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0111-Remove-unused-World-Tile-Entity-List.patch b/Spigot-Server-Patches/0111-Remove-unused-World-Tile-Entity-List.patch new file mode 100644 index 0000000000..308096a20f --- /dev/null +++ b/Spigot-Server-Patches/0111-Remove-unused-World-Tile-Entity-List.patch @@ -0,0 +1,71 @@ +From 0ee8a42416c06bb0ac9c29ab71474a8f97e0006f 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/World.java b/src/main/java/net/minecraft/server/World.java +index 9bc8ce64c..2f4728b0d 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -68,7 +68,7 @@ public abstract class World implements IBlockAccess { + }; + // Spigot end + protected final Set f = Sets.newHashSet(); // Paper +- public final List tileEntityList = Lists.newArrayList(); ++ //public final List tileEntityList = Lists.newArrayList(); // Paper - remove unused list + public final List tileEntityListTick = Lists.newArrayList(); + private final List b = Lists.newArrayList(); + private final Set tileEntityListUnload = Sets.newHashSet(); // Paper +@@ -1568,7 +1568,7 @@ public abstract class World implements IBlockAccess { + // CraftBukkit start - From below, clean up tile entities before ticking them + 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(); + } + // CraftBukkit end +@@ -1619,7 +1619,7 @@ public abstract class World implements IBlockAccess { + if (tileentity.y()) { + tilesThisCycle--; + this.tileEntityListTick.remove(tileTickPosition--); +- this.tileEntityList.remove(tileentity); ++ //this.tileEntityList.remove(tileentity); // Paper - remove unused list + if (this.isLoaded(tileentity.getPosition())) { + this.getChunkAtWorldCoords(tileentity.getPosition()).d(tileentity.getPosition()); + } +@@ -1657,7 +1657,7 @@ public abstract class World implements IBlockAccess { + 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 +@@ -1677,9 +1677,9 @@ public abstract class World implements IBlockAccess { + protected void l() {} + + public boolean a(TileEntity tileentity) { +- 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); + } + +@@ -2114,7 +2114,7 @@ public abstract class World implements IBlockAccess { + } else { + if (tileentity != null) { + this.b.remove(tileentity); +- this.tileEntityList.remove(tileentity); ++ //this.tileEntityList.remove(tileentity); // Paper - remove unused list + this.tileEntityListTick.remove(tileentity); + } + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0111-Workaround-for-setting-passengers-on-players.patch b/Spigot-Server-Patches/0111-Workaround-for-setting-passengers-on-players.patch deleted file mode 100644 index efbb98a3c9..0000000000 --- a/Spigot-Server-Patches/0111-Workaround-for-setting-passengers-on-players.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 5fa0344f756b199b838d8addb7e3f50efe5a4f91 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 80a6a0b41..5f6b182d6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -589,6 +589,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.server.PacketPlayOutMount(this.getHandle())); -+ } -+ return wasSet; -+ } -+ // Paper end -+ - @Override - public void setSneaking(boolean sneak) { - getHandle().setSneaking(sneak); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0112-Don-t-tick-Skulls-unused-code.patch b/Spigot-Server-Patches/0112-Don-t-tick-Skulls-unused-code.patch new file mode 100644 index 0000000000..8bfabdb113 --- /dev/null +++ b/Spigot-Server-Patches/0112-Don-t-tick-Skulls-unused-code.patch @@ -0,0 +1,22 @@ +From 6f8419e69afc9f0873ee2f8d073fa6aee9c9ff7b 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/server/TileEntitySkull.java b/src/main/java/net/minecraft/server/TileEntitySkull.java +index edd6fb69e..380373c0e 100644 +--- a/src/main/java/net/minecraft/server/TileEntitySkull.java ++++ b/src/main/java/net/minecraft/server/TileEntitySkull.java +@@ -21,7 +21,7 @@ import com.mojang.authlib.Agent; + import com.mojang.authlib.ProfileLookupCallback; + // Spigot end + +-public class TileEntitySkull extends TileEntity implements ITickable { ++public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Paper - remove tickable + + private int a; + public int rotation; +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0112-Remove-unused-World-Tile-Entity-List.patch b/Spigot-Server-Patches/0112-Remove-unused-World-Tile-Entity-List.patch deleted file mode 100644 index c3873355a9..0000000000 --- a/Spigot-Server-Patches/0112-Remove-unused-World-Tile-Entity-List.patch +++ /dev/null @@ -1,71 +0,0 @@ -From dcfc848c896f88a21c47d10b8e5914bdeeda4321 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/World.java b/src/main/java/net/minecraft/server/World.java -index 9bc8ce64c..2f4728b0d 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -68,7 +68,7 @@ public abstract class World implements IBlockAccess { - }; - // Spigot end - protected final Set f = Sets.newHashSet(); // Paper -- public final List tileEntityList = Lists.newArrayList(); -+ //public final List tileEntityList = Lists.newArrayList(); // Paper - remove unused list - public final List tileEntityListTick = Lists.newArrayList(); - private final List b = Lists.newArrayList(); - private final Set tileEntityListUnload = Sets.newHashSet(); // Paper -@@ -1568,7 +1568,7 @@ public abstract class World implements IBlockAccess { - // CraftBukkit start - From below, clean up tile entities before ticking them - 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(); - } - // CraftBukkit end -@@ -1619,7 +1619,7 @@ public abstract class World implements IBlockAccess { - if (tileentity.y()) { - tilesThisCycle--; - this.tileEntityListTick.remove(tileTickPosition--); -- this.tileEntityList.remove(tileentity); -+ //this.tileEntityList.remove(tileentity); // Paper - remove unused list - if (this.isLoaded(tileentity.getPosition())) { - this.getChunkAtWorldCoords(tileentity.getPosition()).d(tileentity.getPosition()); - } -@@ -1657,7 +1657,7 @@ public abstract class World implements IBlockAccess { - 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 -@@ -1677,9 +1677,9 @@ public abstract class World implements IBlockAccess { - protected void l() {} - - public boolean a(TileEntity tileentity) { -- 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); - } - -@@ -2114,7 +2114,7 @@ public abstract class World implements IBlockAccess { - } else { - if (tileentity != null) { - this.b.remove(tileentity); -- this.tileEntityList.remove(tileentity); -+ //this.tileEntityList.remove(tileentity); // Paper - remove unused list - this.tileEntityListTick.remove(tileentity); - } - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0113-Configurable-Player-Collision.patch b/Spigot-Server-Patches/0113-Configurable-Player-Collision.patch new file mode 100644 index 0000000000..f5eff894ca --- /dev/null +++ b/Spigot-Server-Patches/0113-Configurable-Player-Collision.patch @@ -0,0 +1,136 @@ +From 5c7d4a23609617b8822fa851a9550b15a8bcf6ee 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 c3ff47e00..710c432d8 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -225,4 +225,9 @@ public class PaperConfig { + private static void regionFileCacheSize() { + regionFileCacheSize = getInt("settings.region-file-cache-size", 256); + } ++ ++ public static boolean enablePlayerCollisions = true; ++ private static void enablePlayerCollisions() { ++ enablePlayerCollisions = getBoolean("settings.enable-player-collisions", true); ++ } + } +diff --git a/src/main/java/net/minecraft/server/CommandScoreboard.java b/src/main/java/net/minecraft/server/CommandScoreboard.java +index ab9aa132a..f9f59e559 100644 +--- a/src/main/java/net/minecraft/server/CommandScoreboard.java ++++ b/src/main/java/net/minecraft/server/CommandScoreboard.java +@@ -183,6 +183,13 @@ public class CommandScoreboard extends CommandAbstract { + throw new ExceptionUsage("commands.scoreboard.teams.option.usage", new Object[0]); + } + ++ // Paper start - Block setting options on our collideRule team as it is not persistent ++ if (astring[2].equals(MinecraftServer.getServer().getPlayerList().collideRuleTeamName)) { ++ icommandlistener.sendMessage(new ChatMessage("You cannot set team options on the collideRule team")); ++ return; ++ } ++ // Paper end ++ + this.c(icommandlistener, astring, 2, minecraftserver); + } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 3aea41f76..430168d21 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -331,6 +331,20 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs + this.v.setPlayerFileData(this.worldServer); + this.a(this.getDifficulty()); + this.l(); ++ ++ // Paper start - Handle collideRule team for player collision toggle ++ final Scoreboard scoreboard = this.getWorld().getScoreboard(); ++ final java.util.Collection 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_" + this.getWorld().random.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 + } + + protected void l() { +diff --git a/src/main/java/net/minecraft/server/PacketPlayOutScoreboardTeam.java b/src/main/java/net/minecraft/server/PacketPlayOutScoreboardTeam.java +index d8ec50455..eb45d3cf2 100644 +--- a/src/main/java/net/minecraft/server/PacketPlayOutScoreboardTeam.java ++++ b/src/main/java/net/minecraft/server/PacketPlayOutScoreboardTeam.java +@@ -96,7 +96,7 @@ public class PacketPlayOutScoreboardTeam implements Packet playersByName = new org.spigotmc.CaseInsensitiveMap(); ++ @Nullable String collideRuleTeamName; // Paper - Team name used for collideRule + + public PlayerList(MinecraftServer minecraftserver) { + this.cserver = minecraftserver.server = new CraftServer(minecraftserver, this); +@@ -228,6 +229,12 @@ public abstract class PlayerList { + } + + entityplayer.syncInventory(); ++ // Paper start - Add to collideRule team if needed ++ final Scoreboard scoreboard = this.getServer().getWorld().getScoreboard(); ++ if (this.collideRuleTeamName != null && scoreboard.getTeam(collideRuleTeamName) != null && entityplayer.getTeam() == null) { ++ scoreboard.addPlayerToTeam(entityplayer.getName(), collideRuleTeamName); ++ } ++ // Paper end + // CraftBukkit - Moved from above, added world + PlayerList.f.info(entityplayer.getName() + "[" + s1 + "] logged in with entity id " + entityplayer.getId() + " at ([" + entityplayer.world.worldData.getName() + "]" + entityplayer.locX + ", " + entityplayer.locY + ", " + entityplayer.locZ + ")"); + } +@@ -400,6 +407,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.getWorld().getScoreboard(); ++ final ScoreboardTeam team = scoreBoard.getTeam(this.collideRuleTeamName); ++ if (entityplayer.getTeam() == team && team != null) { ++ scoreBoard.removePlayerFromTeam(entityplayer.getName(), team); ++ } ++ } ++ // Paper end ++ + this.savePlayerFile(entityplayer); + if (entityplayer.isPassenger()) { + Entity entity = entityplayer.getVehicle(); +@@ -1314,7 +1331,13 @@ public abstract class PlayerList { + player.playerConnection.disconnect(this.server.server.getShutdownMessage()); // CraftBukkit - add custom shutdown message + } + // CraftBukkit end +- ++ // Paper start - Remove collideRule team if it exists ++ if (this.collideRuleTeamName != null) { ++ final Scoreboard scoreboard = this.getServer().getWorld().getScoreboard(); ++ final ScoreboardTeam team = scoreboard.getTeam(this.collideRuleTeamName); ++ if (team != null) scoreboard.removeTeam(team); ++ } ++ // Paper end + } + + // CraftBukkit start +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0113-Don-t-tick-Skulls-unused-code.patch b/Spigot-Server-Patches/0113-Don-t-tick-Skulls-unused-code.patch deleted file mode 100644 index c0064af2b3..0000000000 --- a/Spigot-Server-Patches/0113-Don-t-tick-Skulls-unused-code.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 421db0871b70be8fbcee14ef32188a132e5e12d2 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/server/TileEntitySkull.java b/src/main/java/net/minecraft/server/TileEntitySkull.java -index edd6fb69e..380373c0e 100644 ---- a/src/main/java/net/minecraft/server/TileEntitySkull.java -+++ b/src/main/java/net/minecraft/server/TileEntitySkull.java -@@ -21,7 +21,7 @@ import com.mojang.authlib.Agent; - import com.mojang.authlib.ProfileLookupCallback; - // Spigot end - --public class TileEntitySkull extends TileEntity implements ITickable { -+public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Paper - remove tickable - - private int a; - public int rotation; --- -2.12.2 - diff --git a/Spigot-Server-Patches/0114-Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/Spigot-Server-Patches/0114-Add-handshake-event-to-allow-plugins-to-handle-clien.patch new file mode 100644 index 0000000000..2d13371699 --- /dev/null +++ b/Spigot-Server-Patches/0114-Add-handshake-event-to-allow-plugins-to-handle-clien.patch @@ -0,0 +1,49 @@ +From 5b040a6ee5d97a584ea1875d45f251066eb51e79 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/HandshakeListener.java b/src/main/java/net/minecraft/server/HandshakeListener.java +index a46df4b7f..f02263c34 100644 +--- a/src/main/java/net/minecraft/server/HandshakeListener.java ++++ b/src/main/java/net/minecraft/server/HandshakeListener.java +@@ -72,8 +72,33 @@ public class HandshakeListener implements PacketHandshakingInListener { + this.b.close(chatcomponenttext); + } else { + this.b.setPacketListener(new LoginListener(this.a, this.b)); ++ // 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? ++ com.destroystokyo.paper.event.player.PlayerHandshakeEvent event = new com.destroystokyo.paper.event.player.PlayerHandshakeEvent(packethandshakinginsetprotocol.hostname, !proxyLogicEnabled); ++ if (event.callEvent()) { ++ // If we've failed somehow, let the client know so and go no further. ++ if (event.isFailed()) { ++ chatcomponenttext = new ChatComponentText(event.getFailMessage()); ++ this.b.sendPacket(new PacketLoginOutDisconnect(chatcomponenttext)); ++ this.b.close(chatcomponenttext); ++ return; ++ } ++ ++ packethandshakinginsetprotocol.hostname = event.getServerHostname(); ++ this.b.l = new java.net.InetSocketAddress(event.getSocketAddressHostname(), ((java.net.InetSocketAddress) this.b.getSocketAddress()).getPort()); ++ this.b.spoofedUUID = event.getUniqueId(); ++ this.b.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 ) { + packethandshakinginsetprotocol.hostname = split[0]; +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0114-Configurable-Player-Collision.patch b/Spigot-Server-Patches/0114-Configurable-Player-Collision.patch deleted file mode 100644 index c8b37aa397..0000000000 --- a/Spigot-Server-Patches/0114-Configurable-Player-Collision.patch +++ /dev/null @@ -1,136 +0,0 @@ -From 6e0a59b05544ff285c2775c54e01c0a5b08c8371 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 c3ff47e00..710c432d8 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -225,4 +225,9 @@ public class PaperConfig { - private static void regionFileCacheSize() { - regionFileCacheSize = getInt("settings.region-file-cache-size", 256); - } -+ -+ public static boolean enablePlayerCollisions = true; -+ private static void enablePlayerCollisions() { -+ enablePlayerCollisions = getBoolean("settings.enable-player-collisions", true); -+ } - } -diff --git a/src/main/java/net/minecraft/server/CommandScoreboard.java b/src/main/java/net/minecraft/server/CommandScoreboard.java -index ab9aa132a..f9f59e559 100644 ---- a/src/main/java/net/minecraft/server/CommandScoreboard.java -+++ b/src/main/java/net/minecraft/server/CommandScoreboard.java -@@ -183,6 +183,13 @@ public class CommandScoreboard extends CommandAbstract { - throw new ExceptionUsage("commands.scoreboard.teams.option.usage", new Object[0]); - } - -+ // Paper start - Block setting options on our collideRule team as it is not persistent -+ if (astring[2].equals(MinecraftServer.getServer().getPlayerList().collideRuleTeamName)) { -+ icommandlistener.sendMessage(new ChatMessage("You cannot set team options on the collideRule team")); -+ return; -+ } -+ // Paper end -+ - this.c(icommandlistener, astring, 2, minecraftserver); - } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 3aea41f76..430168d21 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -331,6 +331,20 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs - this.v.setPlayerFileData(this.worldServer); - this.a(this.getDifficulty()); - this.l(); -+ -+ // Paper start - Handle collideRule team for player collision toggle -+ final Scoreboard scoreboard = this.getWorld().getScoreboard(); -+ final java.util.Collection 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_" + this.getWorld().random.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 - } - - protected void l() { -diff --git a/src/main/java/net/minecraft/server/PacketPlayOutScoreboardTeam.java b/src/main/java/net/minecraft/server/PacketPlayOutScoreboardTeam.java -index d8ec50455..eb45d3cf2 100644 ---- a/src/main/java/net/minecraft/server/PacketPlayOutScoreboardTeam.java -+++ b/src/main/java/net/minecraft/server/PacketPlayOutScoreboardTeam.java -@@ -96,7 +96,7 @@ public class PacketPlayOutScoreboardTeam implements Packet playersByName = new org.spigotmc.CaseInsensitiveMap(); -+ @Nullable String collideRuleTeamName; // Paper - Team name used for collideRule - - public PlayerList(MinecraftServer minecraftserver) { - this.cserver = minecraftserver.server = new CraftServer(minecraftserver, this); -@@ -228,6 +229,12 @@ public abstract class PlayerList { - } - - entityplayer.syncInventory(); -+ // Paper start - Add to collideRule team if needed -+ final Scoreboard scoreboard = this.getServer().getWorld().getScoreboard(); -+ if (this.collideRuleTeamName != null && scoreboard.getTeam(collideRuleTeamName) != null && entityplayer.getTeam() == null) { -+ scoreboard.addPlayerToTeam(entityplayer.getName(), collideRuleTeamName); -+ } -+ // Paper end - // CraftBukkit - Moved from above, added world - PlayerList.f.info(entityplayer.getName() + "[" + s1 + "] logged in with entity id " + entityplayer.getId() + " at ([" + entityplayer.world.worldData.getName() + "]" + entityplayer.locX + ", " + entityplayer.locY + ", " + entityplayer.locZ + ")"); - } -@@ -400,6 +407,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.getWorld().getScoreboard(); -+ final ScoreboardTeam team = scoreBoard.getTeam(this.collideRuleTeamName); -+ if (entityplayer.getTeam() == team && team != null) { -+ scoreBoard.removePlayerFromTeam(entityplayer.getName(), team); -+ } -+ } -+ // Paper end -+ - this.savePlayerFile(entityplayer); - if (entityplayer.isPassenger()) { - Entity entity = entityplayer.getVehicle(); -@@ -1314,7 +1331,13 @@ public abstract class PlayerList { - player.playerConnection.disconnect(this.server.server.getShutdownMessage()); // CraftBukkit - add custom shutdown message - } - // CraftBukkit end -- -+ // Paper start - Remove collideRule team if it exists -+ if (this.collideRuleTeamName != null) { -+ final Scoreboard scoreboard = this.getServer().getWorld().getScoreboard(); -+ final ScoreboardTeam team = scoreboard.getTeam(this.collideRuleTeamName); -+ if (team != null) scoreboard.removeTeam(team); -+ } -+ // Paper end - } - - // CraftBukkit start --- -2.12.2.windows.2 - diff --git a/Spigot-Server-Patches/0115-Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/Spigot-Server-Patches/0115-Add-handshake-event-to-allow-plugins-to-handle-clien.patch deleted file mode 100644 index 9197eaab21..0000000000 --- a/Spigot-Server-Patches/0115-Add-handshake-event-to-allow-plugins-to-handle-clien.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 3112e052aea6a52a5959ddef046c307f09443bbd 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/HandshakeListener.java b/src/main/java/net/minecraft/server/HandshakeListener.java -index a46df4b7f..f02263c34 100644 ---- a/src/main/java/net/minecraft/server/HandshakeListener.java -+++ b/src/main/java/net/minecraft/server/HandshakeListener.java -@@ -72,8 +72,33 @@ public class HandshakeListener implements PacketHandshakingInListener { - this.b.close(chatcomponenttext); - } else { - this.b.setPacketListener(new LoginListener(this.a, this.b)); -+ // 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? -+ com.destroystokyo.paper.event.player.PlayerHandshakeEvent event = new com.destroystokyo.paper.event.player.PlayerHandshakeEvent(packethandshakinginsetprotocol.hostname, !proxyLogicEnabled); -+ if (event.callEvent()) { -+ // If we've failed somehow, let the client know so and go no further. -+ if (event.isFailed()) { -+ chatcomponenttext = new ChatComponentText(event.getFailMessage()); -+ this.b.sendPacket(new PacketLoginOutDisconnect(chatcomponenttext)); -+ this.b.close(chatcomponenttext); -+ return; -+ } -+ -+ packethandshakinginsetprotocol.hostname = event.getServerHostname(); -+ this.b.l = new java.net.InetSocketAddress(event.getSocketAddressHostname(), ((java.net.InetSocketAddress) this.b.getSocketAddress()).getPort()); -+ this.b.spoofedUUID = event.getUniqueId(); -+ this.b.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 ) { - packethandshakinginsetprotocol.hostname = split[0]; --- -2.12.2 - diff --git a/Spigot-Server-Patches/0115-Water-mobs-should-only-spawn-in-the-water.patch b/Spigot-Server-Patches/0115-Water-mobs-should-only-spawn-in-the-water.patch new file mode 100644 index 0000000000..8f48e60239 --- /dev/null +++ b/Spigot-Server-Patches/0115-Water-mobs-should-only-spawn-in-the-water.patch @@ -0,0 +1,30 @@ +From adfe939e1377279c32fe68488f5285302613c9ba Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Thu, 14 Apr 2016 17:48:56 -0500 +Subject: [PATCH] Water mobs should only spawn in the water + + +diff --git a/src/main/java/net/minecraft/server/EntityWaterAnimal.java b/src/main/java/net/minecraft/server/EntityWaterAnimal.java +index 90d33af95..251555713 100644 +--- a/src/main/java/net/minecraft/server/EntityWaterAnimal.java ++++ b/src/main/java/net/minecraft/server/EntityWaterAnimal.java +@@ -11,7 +11,15 @@ public abstract class EntityWaterAnimal extends EntityInsentient implements IAni + } + + public boolean cM() { +- return true; ++ // Paper start - Don't let water mobs spawn in non-water blocks ++ // Based around EntityAnimal's implementation ++ int i = MathHelper.floor(this.locX); ++ int j = MathHelper.floor(this.getBoundingBox().b); // minY of bounding box ++ int k = MathHelper.floor(this.locZ); ++ Block block = this.world.getType(new BlockPosition(i, j, k)).getBlock(); ++ ++ return block == Blocks.WATER || block == Blocks.FLOWING_WATER; ++ // Paper end + } + + public boolean canSpawn() { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0116-Fix-Bugs-with-Spigot-Mob-Spawn-Logic.patch b/Spigot-Server-Patches/0116-Fix-Bugs-with-Spigot-Mob-Spawn-Logic.patch new file mode 100644 index 0000000000..f97633e425 --- /dev/null +++ b/Spigot-Server-Patches/0116-Fix-Bugs-with-Spigot-Mob-Spawn-Logic.patch @@ -0,0 +1,60 @@ +From ce270a9774afd4425f09187b3dae122dab3a8943 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 14 Apr 2016 21:01:39 -0400 +Subject: [PATCH] Fix Bugs with Spigot Mob Spawn Logic + +Spigot drastically altered vanilla mob spawn logic and caused a few issues. +1) Used only spawnable chunks vs entire world for entity counting, resulting in ignoring +other entities in the world, and causing the world to go over its intended limit. + +Specially with servers using smaller mob spawn ranges than view distance, as well as affects spawning API + +2) Spigot was using 16x16 division instead of vanilla 17x17 division. + +This patch returns mob counting to use all loaded chunks, and 17x17 division. + +diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java +index 61d34fc37..a6cf1d83d 100644 +--- a/src/main/java/net/minecraft/server/Chunk.java ++++ b/src/main/java/net/minecraft/server/Chunk.java +@@ -680,7 +680,7 @@ public class Chunk { + i = this.entitySlices.length - 1; + } + +- this.entitySlices[i].remove(entity); ++ if (!this.entitySlices[i].remove(entity)) { return; } // Paper + // Paper start - update counts + if (entity instanceof EntityItem) { + itemCounts[i]--; +diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java +index 8749a1879..29d4c0866 100644 +--- a/src/main/java/net/minecraft/server/SpawnerCreature.java ++++ b/src/main/java/net/minecraft/server/SpawnerCreature.java +@@ -23,6 +23,15 @@ public final class SpawnerCreature { + // Spigot start - get entity count only from chunks being processed in b + private int getEntityCount(WorldServer server, Class oClass) + { ++ // Paper start - use entire world, not just active chunks. Spigot broke vanilla expectations. ++ if (true) { ++ return server ++ .getChunkProviderServer() ++ .chunks.values() ++ .stream() ++ .collect(java.util.stream.Collectors.summingInt(c -> c.entityCount.get(oClass))); ++ } ++ // Paper end + int i = 0; + Iterator it = this.b.iterator(); + while ( it.hasNext() ) +@@ -126,7 +135,7 @@ public final class SpawnerCreature { + int l1 = limit * i / a; // CraftBukkit - use per-world limits + */ // Paper end + +- if ((mobcnt = getEntityCount(worldserver, enumcreaturetype.a())) <= limit * i / 256) { ++ if ((mobcnt = getEntityCount(worldserver, enumcreaturetype.a())) <= limit * i / 289) { // Paper - use 17x17 like vanilla (a at top of file) + BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); + Iterator iterator1 = this.b.iterator(); + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0116-Water-mobs-should-only-spawn-in-the-water.patch b/Spigot-Server-Patches/0116-Water-mobs-should-only-spawn-in-the-water.patch deleted file mode 100644 index ba2f7fa0bc..0000000000 --- a/Spigot-Server-Patches/0116-Water-mobs-should-only-spawn-in-the-water.patch +++ /dev/null @@ -1,30 +0,0 @@ -From b5d0b73e9f5dc13affbd3c6fa857fe45deeaaa19 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Thu, 14 Apr 2016 17:48:56 -0500 -Subject: [PATCH] Water mobs should only spawn in the water - - -diff --git a/src/main/java/net/minecraft/server/EntityWaterAnimal.java b/src/main/java/net/minecraft/server/EntityWaterAnimal.java -index 90d33af95..251555713 100644 ---- a/src/main/java/net/minecraft/server/EntityWaterAnimal.java -+++ b/src/main/java/net/minecraft/server/EntityWaterAnimal.java -@@ -11,7 +11,15 @@ public abstract class EntityWaterAnimal extends EntityInsentient implements IAni - } - - public boolean cM() { -- return true; -+ // Paper start - Don't let water mobs spawn in non-water blocks -+ // Based around EntityAnimal's implementation -+ int i = MathHelper.floor(this.locX); -+ int j = MathHelper.floor(this.getBoundingBox().b); // minY of bounding box -+ int k = MathHelper.floor(this.locZ); -+ Block block = this.world.getType(new BlockPosition(i, j, k)).getBlock(); -+ -+ return block == Blocks.WATER || block == Blocks.FLOWING_WATER; -+ // Paper end - } - - public boolean canSpawn() { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0117-Configurable-RCON-IP-address.patch b/Spigot-Server-Patches/0117-Configurable-RCON-IP-address.patch new file mode 100644 index 0000000000..13d59c3dab --- /dev/null +++ b/Spigot-Server-Patches/0117-Configurable-RCON-IP-address.patch @@ -0,0 +1,23 @@ +From 82d1f04f8a674ab31b52e27e1987cd1785acf94d 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/RemoteControlListener.java b/src/main/java/net/minecraft/server/RemoteControlListener.java +index a6a0d5a29..efcafe77f 100644 +--- a/src/main/java/net/minecraft/server/RemoteControlListener.java ++++ b/src/main/java/net/minecraft/server/RemoteControlListener.java +@@ -24,7 +24,7 @@ public class RemoteControlListener extends RemoteConnectionThread { + super(iminecraftserver, "RCON Listener"); + this.h = iminecraftserver.a("rcon.port", 0); + this.l = iminecraftserver.a("rcon.password", ""); +- this.j = iminecraftserver.d_(); ++ this.j = iminecraftserver.a("rcon.ip", iminecraftserver.d_()); // Paper + this.i = iminecraftserver.e_(); + if (0 == this.h) { + this.h = this.i + 10; +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0117-Fix-Bugs-with-Spigot-Mob-Spawn-Logic.patch b/Spigot-Server-Patches/0117-Fix-Bugs-with-Spigot-Mob-Spawn-Logic.patch deleted file mode 100644 index 3edcec5827..0000000000 --- a/Spigot-Server-Patches/0117-Fix-Bugs-with-Spigot-Mob-Spawn-Logic.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0e4f44dde4037101a88ba017da160589dbf53b9e Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 14 Apr 2016 21:01:39 -0400 -Subject: [PATCH] Fix Bugs with Spigot Mob Spawn Logic - -Spigot drastically altered vanilla mob spawn logic and caused a few issues. -1) Used only spawnable chunks vs entire world for entity counting, resulting in ignoring -other entities in the world, and causing the world to go over its intended limit. - -Specially with servers using smaller mob spawn ranges than view distance, as well as affects spawning API - -2) Spigot was using 16x16 division instead of vanilla 17x17 division. - -This patch returns mob counting to use all loaded chunks, and 17x17 division. - -diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java -index 61d34fc37..a6cf1d83d 100644 ---- a/src/main/java/net/minecraft/server/Chunk.java -+++ b/src/main/java/net/minecraft/server/Chunk.java -@@ -680,7 +680,7 @@ public class Chunk { - i = this.entitySlices.length - 1; - } - -- this.entitySlices[i].remove(entity); -+ if (!this.entitySlices[i].remove(entity)) { return; } // Paper - // Paper start - update counts - if (entity instanceof EntityItem) { - itemCounts[i]--; -diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java -index 8749a1879..29d4c0866 100644 ---- a/src/main/java/net/minecraft/server/SpawnerCreature.java -+++ b/src/main/java/net/minecraft/server/SpawnerCreature.java -@@ -23,6 +23,15 @@ public final class SpawnerCreature { - // Spigot start - get entity count only from chunks being processed in b - private int getEntityCount(WorldServer server, Class oClass) - { -+ // Paper start - use entire world, not just active chunks. Spigot broke vanilla expectations. -+ if (true) { -+ return server -+ .getChunkProviderServer() -+ .chunks.values() -+ .stream() -+ .collect(java.util.stream.Collectors.summingInt(c -> c.entityCount.get(oClass))); -+ } -+ // Paper end - int i = 0; - Iterator it = this.b.iterator(); - while ( it.hasNext() ) -@@ -126,7 +135,7 @@ public final class SpawnerCreature { - int l1 = limit * i / a; // CraftBukkit - use per-world limits - */ // Paper end - -- if ((mobcnt = getEntityCount(worldserver, enumcreaturetype.a())) <= limit * i / 256) { -+ if ((mobcnt = getEntityCount(worldserver, enumcreaturetype.a())) <= limit * i / 289) { // Paper - use 17x17 like vanilla (a at top of file) - BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); - Iterator iterator1 = this.b.iterator(); - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0118-Configurable-RCON-IP-address.patch b/Spigot-Server-Patches/0118-Configurable-RCON-IP-address.patch deleted file mode 100644 index 527777a6f9..0000000000 --- a/Spigot-Server-Patches/0118-Configurable-RCON-IP-address.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 3cc6bf088a830f76ece5e6bb0c607c16278258cc 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/RemoteControlListener.java b/src/main/java/net/minecraft/server/RemoteControlListener.java -index a6a0d5a29..efcafe77f 100644 ---- a/src/main/java/net/minecraft/server/RemoteControlListener.java -+++ b/src/main/java/net/minecraft/server/RemoteControlListener.java -@@ -24,7 +24,7 @@ public class RemoteControlListener extends RemoteConnectionThread { - super(iminecraftserver, "RCON Listener"); - this.h = iminecraftserver.a("rcon.port", 0); - this.l = iminecraftserver.a("rcon.password", ""); -- this.j = iminecraftserver.d_(); -+ this.j = iminecraftserver.a("rcon.ip", iminecraftserver.d_()); // Paper - this.i = iminecraftserver.e_(); - if (0 == this.h) { - this.h = this.i + 10; --- -2.12.2 - diff --git a/Spigot-Server-Patches/0118-Prevent-Fire-from-loading-chunks.patch b/Spigot-Server-Patches/0118-Prevent-Fire-from-loading-chunks.patch new file mode 100644 index 0000000000..d34de7efb8 --- /dev/null +++ b/Spigot-Server-Patches/0118-Prevent-Fire-from-loading-chunks.patch @@ -0,0 +1,51 @@ +From 0cf6a91a4ecb498d0867e197dbffb42a5280a096 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 + +This causes the nether to spam unload/reload chunks, plus overall +bad behavior. + +diff --git a/src/main/java/net/minecraft/server/BlockFire.java b/src/main/java/net/minecraft/server/BlockFire.java +index 94cb9d462..dfc328850 100644 +--- a/src/main/java/net/minecraft/server/BlockFire.java ++++ b/src/main/java/net/minecraft/server/BlockFire.java +@@ -164,6 +164,7 @@ public class BlockFire extends Block { + } + + BlockPosition blockposition1 = blockposition.a(j, l, k); ++ if (!world.isLoaded(blockposition1)) continue; // Paper + int j1 = this.d(world, blockposition1); + + if (j1 > 0) { +@@ -232,10 +233,14 @@ public class BlockFire extends Block { + } + + private void a(World world, BlockPosition blockposition, int i, Random random, int j, BlockPosition sourceposition) { // CraftBukkit add sourceposition +- int k = this.c(world.getType(blockposition).getBlock()); ++ // Paper start ++ final IBlockData iblockdata = world.getTypeIfLoaded(blockposition); ++ if (iblockdata == null) return; ++ int k = this.c(iblockdata.getBlock()); ++ // 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()); +@@ -294,7 +299,9 @@ public class BlockFire extends Block { + for (int k = 0; k < j; ++k) { + EnumDirection enumdirection = aenumdirection[k]; + +- i = Math.max(this.d(world.getType(blockposition.shift(enumdirection)).getBlock()), i); ++ final IBlockData type = world.getTypeIfLoaded(blockposition.shift(enumdirection)); // Paper ++ if (type == null) continue; // Paper ++ i = Math.max(this.d(type.getBlock()), i); // Paper + } + + return i; +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0119-Implement-PlayerLocaleChangeEvent.patch b/Spigot-Server-Patches/0119-Implement-PlayerLocaleChangeEvent.patch new file mode 100644 index 0000000000..2afa48d599 --- /dev/null +++ b/Spigot-Server-Patches/0119-Implement-PlayerLocaleChangeEvent.patch @@ -0,0 +1,54 @@ +From facac094d3f1909ca5c2d0100b0f343591690b5c 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/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java +index bf3e46c35..ad1bb7bab 100644 +--- a/src/main/java/net/minecraft/server/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/EntityPlayer.java +@@ -31,7 +31,7 @@ import org.bukkit.inventory.MainHand; + public class EntityPlayer extends EntityHuman implements ICrafting { + + private static final Logger bR = LogManager.getLogger(); +- public String locale = "en_US"; // Spigot private -> public ++ public String locale = null; // Spigot private -> public // Paper - default to null + public PlayerConnection playerConnection; + public final MinecraftServer server; + public final PlayerInteractManager playerInteractManager; +@@ -1105,7 +1105,15 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + this.server.server.getPluginManager().callEvent(event); + } + // CraftBukkit end ++ ++ // Paper start - add PlayerLocaleChangeEvent ++ // Since the field is initialized to null, this event should always fire the first time the packet is received ++ String oldLocale = this.locale; + this.locale = packetplayinsettings.a(); ++ if (!this.locale.equals(oldLocale)) { ++ new com.destroystokyo.paper.event.player.PlayerLocaleChangeEvent(this.getBukkitEntity(), oldLocale, this.locale).callEvent(); ++ } ++ // Paper end + this.cg = packetplayinsettings.c(); + this.ch = packetplayinsettings.d(); + this.getDataWatcher().set(EntityPlayer.bq, Byte.valueOf((byte) packetplayinsettings.e())); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 8e06c2140..61c32223d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1691,7 +1691,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 + } + + @Override +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0119-Prevent-Fire-from-loading-chunks.patch b/Spigot-Server-Patches/0119-Prevent-Fire-from-loading-chunks.patch deleted file mode 100644 index a41984480c..0000000000 --- a/Spigot-Server-Patches/0119-Prevent-Fire-from-loading-chunks.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 73b1b9d098df385f6eaad2694a09d0ad1b967c06 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 - -This causes the nether to spam unload/reload chunks, plus overall -bad behavior. - -diff --git a/src/main/java/net/minecraft/server/BlockFire.java b/src/main/java/net/minecraft/server/BlockFire.java -index 94cb9d462..dfc328850 100644 ---- a/src/main/java/net/minecraft/server/BlockFire.java -+++ b/src/main/java/net/minecraft/server/BlockFire.java -@@ -164,6 +164,7 @@ public class BlockFire extends Block { - } - - BlockPosition blockposition1 = blockposition.a(j, l, k); -+ if (!world.isLoaded(blockposition1)) continue; // Paper - int j1 = this.d(world, blockposition1); - - if (j1 > 0) { -@@ -232,10 +233,14 @@ public class BlockFire extends Block { - } - - private void a(World world, BlockPosition blockposition, int i, Random random, int j, BlockPosition sourceposition) { // CraftBukkit add sourceposition -- int k = this.c(world.getType(blockposition).getBlock()); -+ // Paper start -+ final IBlockData iblockdata = world.getTypeIfLoaded(blockposition); -+ if (iblockdata == null) return; -+ int k = this.c(iblockdata.getBlock()); -+ // 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()); -@@ -294,7 +299,9 @@ public class BlockFire extends Block { - for (int k = 0; k < j; ++k) { - EnumDirection enumdirection = aenumdirection[k]; - -- i = Math.max(this.d(world.getType(blockposition.shift(enumdirection)).getBlock()), i); -+ final IBlockData type = world.getTypeIfLoaded(blockposition.shift(enumdirection)); // Paper -+ if (type == null) continue; // Paper -+ i = Math.max(this.d(type.getBlock()), i); // Paper - } - - return i; --- -2.12.2 - diff --git a/Spigot-Server-Patches/0120-EntityRegainHealthEvent-isFastRegen-API.patch b/Spigot-Server-Patches/0120-EntityRegainHealthEvent-isFastRegen-API.patch new file mode 100644 index 0000000000..7d44f74edf --- /dev/null +++ b/Spigot-Server-Patches/0120-EntityRegainHealthEvent-isFastRegen-API.patch @@ -0,0 +1,45 @@ +From 0be7d9227878e2d4b44885aa146bdbd64bda3fc5 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/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java +index c70f14a15..ec901150d 100644 +--- a/src/main/java/net/minecraft/server/EntityLiving.java ++++ b/src/main/java/net/minecraft/server/EntityLiving.java +@@ -762,10 +762,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 - Add isFastRegen + this.world.getServer().getPluginManager().callEvent(event); + + if (!event.isCancelled()) { +diff --git a/src/main/java/net/minecraft/server/FoodMetaData.java b/src/main/java/net/minecraft/server/FoodMetaData.java +index b6e978668..8d95d148f 100644 +--- a/src/main/java/net/minecraft/server/FoodMetaData.java ++++ b/src/main/java/net/minecraft/server/FoodMetaData.java +@@ -65,7 +65,7 @@ public class FoodMetaData { + if (this.foodTickTimer >= 10) { + 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); + this.foodTickTimer = 0; + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0120-Implement-PlayerLocaleChangeEvent.patch b/Spigot-Server-Patches/0120-Implement-PlayerLocaleChangeEvent.patch deleted file mode 100644 index 57d0b4d59c..0000000000 --- a/Spigot-Server-Patches/0120-Implement-PlayerLocaleChangeEvent.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 230b15e3cf0ecccba8688946cc029fd5d3a4a54d 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/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index bf3e46c35..ad1bb7bab 100644 ---- a/src/main/java/net/minecraft/server/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/EntityPlayer.java -@@ -31,7 +31,7 @@ import org.bukkit.inventory.MainHand; - public class EntityPlayer extends EntityHuman implements ICrafting { - - private static final Logger bR = LogManager.getLogger(); -- public String locale = "en_US"; // Spigot private -> public -+ public String locale = null; // Spigot private -> public // Paper - default to null - public PlayerConnection playerConnection; - public final MinecraftServer server; - public final PlayerInteractManager playerInteractManager; -@@ -1105,7 +1105,15 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.server.server.getPluginManager().callEvent(event); - } - // CraftBukkit end -+ -+ // Paper start - add PlayerLocaleChangeEvent -+ // Since the field is initialized to null, this event should always fire the first time the packet is received -+ String oldLocale = this.locale; - this.locale = packetplayinsettings.a(); -+ if (!this.locale.equals(oldLocale)) { -+ new com.destroystokyo.paper.event.player.PlayerLocaleChangeEvent(this.getBukkitEntity(), oldLocale, this.locale).callEvent(); -+ } -+ // Paper end - this.cg = packetplayinsettings.c(); - this.ch = packetplayinsettings.d(); - this.getDataWatcher().set(EntityPlayer.bq, Byte.valueOf((byte) packetplayinsettings.e())); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 8e06c2140..61c32223d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1691,7 +1691,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 - } - - @Override --- -2.12.2.windows.2 - diff --git a/Spigot-Server-Patches/0121-Add-ability-to-configure-frosted_ice-properties.patch b/Spigot-Server-Patches/0121-Add-ability-to-configure-frosted_ice-properties.patch new file mode 100644 index 0000000000..014762288f --- /dev/null +++ b/Spigot-Server-Patches/0121-Add-ability-to-configure-frosted_ice-properties.patch @@ -0,0 +1,48 @@ +From 6a3db8a7752bb7e49c4577771c3b92c763c0e159 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 3bd29650c..5cc55b794 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -295,4 +295,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/server/BlockIceFrost.java b/src/main/java/net/minecraft/server/BlockIceFrost.java +index 73855826e..f079c3389 100644 +--- a/src/main/java/net/minecraft/server/BlockIceFrost.java ++++ b/src/main/java/net/minecraft/server/BlockIceFrost.java +@@ -19,10 +19,14 @@ public class BlockIceFrost extends BlockIce { + } + + public void b(World world, BlockPosition blockposition, IBlockData iblockdata, Random random) { ++ if (!world.paperConfig.frostedIceEnabled) return; // Paper - add ability to disable frosted ice + if ((random.nextInt(3) == 0 || this.c(world, blockposition) < 4) && world.getLightLevel(blockposition) > 11 - ((Integer) iblockdata.get(BlockIceFrost.a)).intValue() - iblockdata.c()) { + this.a(world, blockposition, iblockdata, random, true); + } else { +- world.a(blockposition, (Block) this, MathHelper.nextInt(random, 20, 40)); ++ // Paper start - use configurable min/max delay ++ //world.a(blockposition, (Block) this, MathHelper.nextInt(random, 20, 40)); ++ world.a(blockposition, this, MathHelper.nextInt(random, world.paperConfig.frostedIceDelayMin, world.paperConfig.frostedIceDelayMax)); ++ // Paper end + } + + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0121-EntityRegainHealthEvent-isFastRegen-API.patch b/Spigot-Server-Patches/0121-EntityRegainHealthEvent-isFastRegen-API.patch deleted file mode 100644 index a9ea4cd806..0000000000 --- a/Spigot-Server-Patches/0121-EntityRegainHealthEvent-isFastRegen-API.patch +++ /dev/null @@ -1,45 +0,0 @@ -From aef8810f99eda6a4fd16bb1dfdb0b03100e36362 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/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index c70f14a15..ec901150d 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -762,10 +762,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 - Add isFastRegen - this.world.getServer().getPluginManager().callEvent(event); - - if (!event.isCancelled()) { -diff --git a/src/main/java/net/minecraft/server/FoodMetaData.java b/src/main/java/net/minecraft/server/FoodMetaData.java -index b6e978668..8d95d148f 100644 ---- a/src/main/java/net/minecraft/server/FoodMetaData.java -+++ b/src/main/java/net/minecraft/server/FoodMetaData.java -@@ -65,7 +65,7 @@ public class FoodMetaData { - if (this.foodTickTimer >= 10) { - 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); - this.foodTickTimer = 0; - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0122-Add-ability-to-configure-frosted_ice-properties.patch b/Spigot-Server-Patches/0122-Add-ability-to-configure-frosted_ice-properties.patch deleted file mode 100644 index 2276492ac2..0000000000 --- a/Spigot-Server-Patches/0122-Add-ability-to-configure-frosted_ice-properties.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 4166ec0c617ad78d508f015a1d4da5199641c20f 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 3bd29650c..5cc55b794 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -295,4 +295,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/server/BlockIceFrost.java b/src/main/java/net/minecraft/server/BlockIceFrost.java -index 73855826e..f079c3389 100644 ---- a/src/main/java/net/minecraft/server/BlockIceFrost.java -+++ b/src/main/java/net/minecraft/server/BlockIceFrost.java -@@ -19,10 +19,14 @@ public class BlockIceFrost extends BlockIce { - } - - public void b(World world, BlockPosition blockposition, IBlockData iblockdata, Random random) { -+ if (!world.paperConfig.frostedIceEnabled) return; // Paper - add ability to disable frosted ice - if ((random.nextInt(3) == 0 || this.c(world, blockposition) < 4) && world.getLightLevel(blockposition) > 11 - ((Integer) iblockdata.get(BlockIceFrost.a)).intValue() - iblockdata.c()) { - this.a(world, blockposition, iblockdata, random, true); - } else { -- world.a(blockposition, (Block) this, MathHelper.nextInt(random, 20, 40)); -+ // Paper start - use configurable min/max delay -+ //world.a(blockposition, (Block) this, MathHelper.nextInt(random, 20, 40)); -+ world.a(blockposition, this, MathHelper.nextInt(random, world.paperConfig.frostedIceDelayMin, world.paperConfig.frostedIceDelayMax)); -+ // Paper end - } - - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0122-Vehicle-Event-Cancellation-Changes.patch b/Spigot-Server-Patches/0122-Vehicle-Event-Cancellation-Changes.patch new file mode 100644 index 0000000000..15ad6b94d2 --- /dev/null +++ b/Spigot-Server-Patches/0122-Vehicle-Event-Cancellation-Changes.patch @@ -0,0 +1,45 @@ +From 293a7018d32c2e0e9aaf9eb4080530122a83d5fa Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Fri, 22 Apr 2016 18:20:05 -0500 +Subject: [PATCH] Vehicle Event Cancellation Changes + + +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 8908d8b8d..0f4a1b66b 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -70,7 +70,7 @@ public abstract class Entity implements ICommandListener { + public boolean i; + public final List passengers; + protected int j; +- private Entity au; ++ private Entity au;public void setVehicle(Entity entity) { this.au = entity; } // Paper // OBFHELPER + public boolean attachedToPlayer; + public World world; + public double lastX; +@@ -1928,6 +1928,7 @@ public abstract class Entity implements ICommandListener { + throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)"); + } else { + // CraftBukkit start ++ entity.setVehicle(this); // Paper - Set the vehicle back for the event + CraftEntity craft = (CraftEntity) entity.getBukkitEntity().getVehicle(); + Entity orig = craft == null ? null : craft.getHandle(); + if (getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) { +@@ -1943,7 +1944,13 @@ public abstract class Entity implements ICommandListener { + } + } + // CraftBukkit end +- Bukkit.getPluginManager().callEvent( new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity())); // Spigot ++ // Paper start - make EntityDismountEvent cancellable ++ if (!new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity()).callEvent()) { ++ return; ++ } ++ entity.setVehicle(null); ++ // Paper end ++ + this.passengers.remove(entity); + entity.j = 60; + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0123-SPIGOT-1401-Fix-dispenser-dropper-furnace-placement.patch b/Spigot-Server-Patches/0123-SPIGOT-1401-Fix-dispenser-dropper-furnace-placement.patch new file mode 100644 index 0000000000..6413e2f607 --- /dev/null +++ b/Spigot-Server-Patches/0123-SPIGOT-1401-Fix-dispenser-dropper-furnace-placement.patch @@ -0,0 +1,55 @@ +From 043c470686058669deac012958193f1bddfa2a10 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sun, 24 Apr 2016 19:49:33 -0500 +Subject: [PATCH] SPIGOT-1401: Fix dispenser, dropper, furnace placement + + +diff --git a/src/main/java/net/minecraft/server/BlockDispenser.java b/src/main/java/net/minecraft/server/BlockDispenser.java +index f8eaf2ac3..8e7884490 100644 +--- a/src/main/java/net/minecraft/server/BlockDispenser.java ++++ b/src/main/java/net/minecraft/server/BlockDispenser.java +@@ -20,6 +20,9 @@ public class BlockDispenser extends BlockTileEntity { + return 4; + } + ++ // Paper start - Removed override of onPlace that was reversing placement direction when ++ // adjacent to another block, which was not consistent with single player block placement ++ /* + public void onPlace(World world, BlockPosition blockposition, IBlockData iblockdata) { + super.onPlace(world, blockposition, iblockdata); + this.e(world, blockposition, iblockdata); +@@ -49,6 +52,8 @@ public class BlockDispenser extends BlockTileEntity { + world.setTypeAndData(blockposition, iblockdata.set(BlockDispenser.FACING, enumdirection).set(BlockDispenser.TRIGGERED, Boolean.valueOf(false)), 2); + } + } ++ */ ++ // Paper end + + public boolean interact(World world, BlockPosition blockposition, IBlockData iblockdata, EntityHuman entityhuman, EnumHand enumhand, EnumDirection enumdirection, float f, float f1, float f2) { + if (world.isClientSide) { +diff --git a/src/main/java/net/minecraft/server/BlockFurnace.java b/src/main/java/net/minecraft/server/BlockFurnace.java +index 528005446..b0d03e408 100644 +--- a/src/main/java/net/minecraft/server/BlockFurnace.java ++++ b/src/main/java/net/minecraft/server/BlockFurnace.java +@@ -18,6 +18,9 @@ public class BlockFurnace extends BlockTileEntity { + return Item.getItemOf(Blocks.FURNACE); + } + ++ // Paper start - Removed override of onPlace that was reversing placement direction when ++ // adjacent to another block, which was not consistent with single player block placement ++ /* + public void onPlace(World world, BlockPosition blockposition, IBlockData iblockdata) { + this.e(world, blockposition, iblockdata); + } +@@ -43,6 +46,8 @@ public class BlockFurnace extends BlockTileEntity { + world.setTypeAndData(blockposition, iblockdata.set(BlockFurnace.FACING, enumdirection), 2); + } + } ++ */ ++ // Paper end + + public boolean interact(World world, BlockPosition blockposition, IBlockData iblockdata, EntityHuman entityhuman, EnumHand enumhand, EnumDirection enumdirection, float f, float f1, float f2) { + if (world.isClientSide) { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0123-Vehicle-Event-Cancellation-Changes.patch b/Spigot-Server-Patches/0123-Vehicle-Event-Cancellation-Changes.patch deleted file mode 100644 index fe509deea6..0000000000 --- a/Spigot-Server-Patches/0123-Vehicle-Event-Cancellation-Changes.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 49d999a37165c4441c7479b021a7768a2f2d0c31 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Fri, 22 Apr 2016 18:20:05 -0500 -Subject: [PATCH] Vehicle Event Cancellation Changes - - -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 8908d8b8d..0f4a1b66b 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -70,7 +70,7 @@ public abstract class Entity implements ICommandListener { - public boolean i; - public final List passengers; - protected int j; -- private Entity au; -+ private Entity au;public void setVehicle(Entity entity) { this.au = entity; } // Paper // OBFHELPER - public boolean attachedToPlayer; - public World world; - public double lastX; -@@ -1928,6 +1928,7 @@ public abstract class Entity implements ICommandListener { - throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)"); - } else { - // CraftBukkit start -+ entity.setVehicle(this); // Paper - Set the vehicle back for the event - CraftEntity craft = (CraftEntity) entity.getBukkitEntity().getVehicle(); - Entity orig = craft == null ? null : craft.getHandle(); - if (getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) { -@@ -1943,7 +1944,13 @@ public abstract class Entity implements ICommandListener { - } - } - // CraftBukkit end -- Bukkit.getPluginManager().callEvent( new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity())); // Spigot -+ // Paper start - make EntityDismountEvent cancellable -+ if (!new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity()).callEvent()) { -+ return; -+ } -+ entity.setVehicle(null); -+ // Paper end -+ - this.passengers.remove(entity); - entity.j = 60; - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0124-Improve-Minecraft-Hopper-Performance.patch b/Spigot-Server-Patches/0124-Improve-Minecraft-Hopper-Performance.patch new file mode 100644 index 0000000000..38e4153791 --- /dev/null +++ b/Spigot-Server-Patches/0124-Improve-Minecraft-Hopper-Performance.patch @@ -0,0 +1,90 @@ +From bf25b8717b9a888b98fe9542ac860429350c61bb Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 27 Apr 2016 22:09:52 -0400 +Subject: [PATCH] Improve Minecraft Hopper Performance + +Removes unnecessary extra calls to .update() that are very expensive +Also reset cooldown each hopper tick that a hopper is full. +Also don't constantly clone ItemStacks without merit + +diff --git a/src/main/java/net/minecraft/server/TileEntity.java b/src/main/java/net/minecraft/server/TileEntity.java +index d0c0371fc..d2662ae14 100644 +--- a/src/main/java/net/minecraft/server/TileEntity.java ++++ b/src/main/java/net/minecraft/server/TileEntity.java +@@ -33,6 +33,7 @@ public abstract class TileEntity { + return (MinecraftKey) TileEntity.f.b(oclass); + } + ++ static boolean IGNORE_TILE_UPDATES = false; // Paper + public World getWorld() { + return this.world; + } +@@ -111,6 +112,7 @@ public abstract class TileEntity { + + public void update() { + if (this.world != null) { ++ if (IGNORE_TILE_UPDATES) return; // Paper + IBlockData iblockdata = this.world.getType(this.position); + + this.g = iblockdata.getBlock().toLegacyData(iblockdata); +diff --git a/src/main/java/net/minecraft/server/TileEntityHopper.java b/src/main/java/net/minecraft/server/TileEntityHopper.java +index 6acce15e7..44b6ecc5d 100644 +--- a/src/main/java/net/minecraft/server/TileEntityHopper.java ++++ b/src/main/java/net/minecraft/server/TileEntityHopper.java +@@ -220,11 +220,13 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + this.setCooldown(world.spigotConfig.hopperTransfer); // Spigot + return false; + } +- int origCount = event.getItem().getAmount(); // Spigot +- ItemStack itemstack1 = addItem(this, iinventory, CraftItemStack.asNMSCopy(event.getItem()), enumdirection); +- ++ // Paper start ++ org.bukkit.inventory.ItemStack eventStack = event.getItem(); ++ int origCount = eventStack.getAmount(); // Spigot ++ ItemStack itemstack1 = addItem(this, iinventory, CraftItemStack.asNMSCopy(eventStack), enumdirection); ++ // Paper end + if (itemstack1.isEmpty()) { +- if (event.getItem().equals(oitemstack)) { ++ if (eventStack.equals(oitemstack)) { // Paper + iinventory.update(); + } else { + this.setItem(i, itemstack); +@@ -377,11 +379,13 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + } + return false; + } +- int origCount = event.getItem().getAmount(); // Spigot +- ItemStack itemstack2 = addItem(iinventory, ihopper, CraftItemStack.asNMSCopy(event.getItem()), null); +- ++ // Paper start ++ org.bukkit.inventory.ItemStack eventStack = event.getItem(); ++ int origCount = eventStack.getAmount(); // Spigot ++ ItemStack itemstack2 = addItem(iinventory, ihopper, CraftItemStack.asNMSCopy(eventStack), null); ++ // Paper end + if (itemstack2.isEmpty()) { +- if (event.getItem().equals(oitemstack)) { ++ if (eventStack.equals(oitemstack)) { // Paper + iinventory.update(); + } else { + iinventory.setItem(i, itemstack1); +@@ -459,7 +463,9 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + boolean flag1 = iinventory1.w_(); + + if (itemstack1.isEmpty()) { ++ IGNORE_TILE_UPDATES = true; // Paper + iinventory1.setItem(i, itemstack); ++ IGNORE_TILE_UPDATES = false; // Paper + itemstack = ItemStack.a; + flag = true; + } else if (a(itemstack1, itemstack)) { +@@ -562,6 +568,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + this.f = i; + } + ++ boolean isCooledDown() { return J(); } // Paper - OBFHELPER + private boolean J() { + return this.f > 0; + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0124-SPIGOT-1401-Fix-dispenser-dropper-furnace-placement.patch b/Spigot-Server-Patches/0124-SPIGOT-1401-Fix-dispenser-dropper-furnace-placement.patch deleted file mode 100644 index 06e8b1b88a..0000000000 --- a/Spigot-Server-Patches/0124-SPIGOT-1401-Fix-dispenser-dropper-furnace-placement.patch +++ /dev/null @@ -1,55 +0,0 @@ -From fbebca9bf7a3e0aa8517e1009a3336ab8246e77c Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sun, 24 Apr 2016 19:49:33 -0500 -Subject: [PATCH] SPIGOT-1401: Fix dispenser, dropper, furnace placement - - -diff --git a/src/main/java/net/minecraft/server/BlockDispenser.java b/src/main/java/net/minecraft/server/BlockDispenser.java -index f8eaf2ac3..8e7884490 100644 ---- a/src/main/java/net/minecraft/server/BlockDispenser.java -+++ b/src/main/java/net/minecraft/server/BlockDispenser.java -@@ -20,6 +20,9 @@ public class BlockDispenser extends BlockTileEntity { - return 4; - } - -+ // Paper start - Removed override of onPlace that was reversing placement direction when -+ // adjacent to another block, which was not consistent with single player block placement -+ /* - public void onPlace(World world, BlockPosition blockposition, IBlockData iblockdata) { - super.onPlace(world, blockposition, iblockdata); - this.e(world, blockposition, iblockdata); -@@ -49,6 +52,8 @@ public class BlockDispenser extends BlockTileEntity { - world.setTypeAndData(blockposition, iblockdata.set(BlockDispenser.FACING, enumdirection).set(BlockDispenser.TRIGGERED, Boolean.valueOf(false)), 2); - } - } -+ */ -+ // Paper end - - public boolean interact(World world, BlockPosition blockposition, IBlockData iblockdata, EntityHuman entityhuman, EnumHand enumhand, EnumDirection enumdirection, float f, float f1, float f2) { - if (world.isClientSide) { -diff --git a/src/main/java/net/minecraft/server/BlockFurnace.java b/src/main/java/net/minecraft/server/BlockFurnace.java -index 528005446..b0d03e408 100644 ---- a/src/main/java/net/minecraft/server/BlockFurnace.java -+++ b/src/main/java/net/minecraft/server/BlockFurnace.java -@@ -18,6 +18,9 @@ public class BlockFurnace extends BlockTileEntity { - return Item.getItemOf(Blocks.FURNACE); - } - -+ // Paper start - Removed override of onPlace that was reversing placement direction when -+ // adjacent to another block, which was not consistent with single player block placement -+ /* - public void onPlace(World world, BlockPosition blockposition, IBlockData iblockdata) { - this.e(world, blockposition, iblockdata); - } -@@ -43,6 +46,8 @@ public class BlockFurnace extends BlockTileEntity { - world.setTypeAndData(blockposition, iblockdata.set(BlockFurnace.FACING, enumdirection), 2); - } - } -+ */ -+ // Paper end - - public boolean interact(World world, BlockPosition blockposition, IBlockData iblockdata, EntityHuman entityhuman, EnumHand enumhand, EnumDirection enumdirection, float f, float f1, float f2) { - if (world.isClientSide) { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0125-Improve-Minecraft-Hopper-Performance.patch b/Spigot-Server-Patches/0125-Improve-Minecraft-Hopper-Performance.patch deleted file mode 100644 index 178841c220..0000000000 --- a/Spigot-Server-Patches/0125-Improve-Minecraft-Hopper-Performance.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 3d13d3f46d166118a68be71adde74e57d7cb1d0f Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 27 Apr 2016 22:09:52 -0400 -Subject: [PATCH] Improve Minecraft Hopper Performance - -Removes unnecessary extra calls to .update() that are very expensive -Also reset cooldown each hopper tick that a hopper is full. -Also don't constantly clone ItemStacks without merit - -diff --git a/src/main/java/net/minecraft/server/TileEntity.java b/src/main/java/net/minecraft/server/TileEntity.java -index d0c0371fc..d2662ae14 100644 ---- a/src/main/java/net/minecraft/server/TileEntity.java -+++ b/src/main/java/net/minecraft/server/TileEntity.java -@@ -33,6 +33,7 @@ public abstract class TileEntity { - return (MinecraftKey) TileEntity.f.b(oclass); - } - -+ static boolean IGNORE_TILE_UPDATES = false; // Paper - public World getWorld() { - return this.world; - } -@@ -111,6 +112,7 @@ public abstract class TileEntity { - - public void update() { - if (this.world != null) { -+ if (IGNORE_TILE_UPDATES) return; // Paper - IBlockData iblockdata = this.world.getType(this.position); - - this.g = iblockdata.getBlock().toLegacyData(iblockdata); -diff --git a/src/main/java/net/minecraft/server/TileEntityHopper.java b/src/main/java/net/minecraft/server/TileEntityHopper.java -index 6acce15e7..44b6ecc5d 100644 ---- a/src/main/java/net/minecraft/server/TileEntityHopper.java -+++ b/src/main/java/net/minecraft/server/TileEntityHopper.java -@@ -220,11 +220,13 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - this.setCooldown(world.spigotConfig.hopperTransfer); // Spigot - return false; - } -- int origCount = event.getItem().getAmount(); // Spigot -- ItemStack itemstack1 = addItem(this, iinventory, CraftItemStack.asNMSCopy(event.getItem()), enumdirection); -- -+ // Paper start -+ org.bukkit.inventory.ItemStack eventStack = event.getItem(); -+ int origCount = eventStack.getAmount(); // Spigot -+ ItemStack itemstack1 = addItem(this, iinventory, CraftItemStack.asNMSCopy(eventStack), enumdirection); -+ // Paper end - if (itemstack1.isEmpty()) { -- if (event.getItem().equals(oitemstack)) { -+ if (eventStack.equals(oitemstack)) { // Paper - iinventory.update(); - } else { - this.setItem(i, itemstack); -@@ -377,11 +379,13 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - } - return false; - } -- int origCount = event.getItem().getAmount(); // Spigot -- ItemStack itemstack2 = addItem(iinventory, ihopper, CraftItemStack.asNMSCopy(event.getItem()), null); -- -+ // Paper start -+ org.bukkit.inventory.ItemStack eventStack = event.getItem(); -+ int origCount = eventStack.getAmount(); // Spigot -+ ItemStack itemstack2 = addItem(iinventory, ihopper, CraftItemStack.asNMSCopy(eventStack), null); -+ // Paper end - if (itemstack2.isEmpty()) { -- if (event.getItem().equals(oitemstack)) { -+ if (eventStack.equals(oitemstack)) { // Paper - iinventory.update(); - } else { - iinventory.setItem(i, itemstack1); -@@ -459,7 +463,9 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - boolean flag1 = iinventory1.w_(); - - if (itemstack1.isEmpty()) { -+ IGNORE_TILE_UPDATES = true; // Paper - iinventory1.setItem(i, itemstack); -+ IGNORE_TILE_UPDATES = false; // Paper - itemstack = ItemStack.a; - flag = true; - } else if (a(itemstack1, itemstack)) { -@@ -562,6 +568,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - this.f = i; - } - -+ boolean isCooledDown() { return J(); } // Paper - OBFHELPER - private boolean J() { - return this.f > 0; - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0125-remove-null-possibility-for-getServer-singleton.patch b/Spigot-Server-Patches/0125-remove-null-possibility-for-getServer-singleton.patch new file mode 100644 index 0000000000..f34b62446b --- /dev/null +++ b/Spigot-Server-Patches/0125-remove-null-possibility-for-getServer-singleton.patch @@ -0,0 +1,39 @@ +From 13ae7fd9680c4c26bfb24bc38f5372dab2c0f303 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 430168d21..83b62da55 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -52,6 +52,7 @@ import co.aikar.timings.MinecraftTimings; // Paper + + public abstract class MinecraftServer implements Runnable, ICommandListener, IAsyncTaskHandler, IMojangStatistics { + ++ private static MinecraftServer SERVER; // Paper + public static final Logger LOGGER = LogManager.getLogger(); + public static final File a = new File("usercache.json"); + public Convertable convertable; +@@ -123,6 +124,7 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs + // Spigot end + + public MinecraftServer(OptionSet options, Proxy proxy, DataConverterManager dataconvertermanager, YggdrasilAuthenticationService yggdrasilauthenticationservice, MinecraftSessionService minecraftsessionservice, GameProfileRepository gameprofilerepository, UserCache usercache) { ++ SERVER = this; // Paper - better singleton + io.netty.util.ResourceLeakDetector.setEnabled( false ); // Spigot - disable + this.e = proxy; + this.V = yggdrasilauthenticationservice; +@@ -1634,7 +1636,7 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs + // CraftBukkit start + @Deprecated + public static MinecraftServer getServer() { +- return (Bukkit.getServer() instanceof CraftServer) ? ((CraftServer) Bukkit.getServer()).getServer() : null; ++ return SERVER; + } + // CraftBukkit end + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0126-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch b/Spigot-Server-Patches/0126-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch new file mode 100644 index 0000000000..19c3943e2d --- /dev/null +++ b/Spigot-Server-Patches/0126-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch @@ -0,0 +1,149 @@ +From 7c6cdf790cf13759abac08cc78be4f7e82689711 Mon Sep 17 00:00:00 2001 +From: Aikar +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/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java +index 43e28d61c..af173a137 100644 +--- a/src/main/java/net/minecraft/server/EntityHuman.java ++++ b/src/main/java/net/minecraft/server/EntityHuman.java +@@ -597,6 +597,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 = Items.FILLED_MAP.getSavedMap(itemstack, this.world); ++ worldmap.updateSeenPlayers(this, itemstack); ++ } ++ // Paper stop + + ItemStack itemstack1 = this.a(entityitem); + +diff --git a/src/main/java/net/minecraft/server/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/EntityTrackerEntry.java +index f542bf491..fbda70a39 100644 +--- a/src/main/java/net/minecraft/server/EntityTrackerEntry.java ++++ b/src/main/java/net/minecraft/server/EntityTrackerEntry.java +@@ -90,11 +90,11 @@ public class EntityTrackerEntry { + } + + // PAIL : rename +- if (this.tracker instanceof EntityItemFrame /*&& this.a % 10 == 0*/) { // CraftBukkit - Moved below, should always enter this block ++ if (this.tracker instanceof EntityItemFrame && this.a % 20 == 0) { // Paper + EntityItemFrame entityitemframe = (EntityItemFrame) this.tracker; + ItemStack itemstack = entityitemframe.getItem(); + +- if (this.a % 10 == 0 && itemstack.getItem() instanceof ItemWorldMap) { // CraftBukkit - Moved this.a % 10 logic here so item frames do not enter the other blocks ++ if (itemstack != null && itemstack.getItem() instanceof ItemWorldMap) { // Paper - moved back up + WorldMap worldmap = Items.FILLED_MAP.getSavedMap(itemstack, this.tracker.world); + Iterator iterator = this.trackedPlayers.iterator(); // CraftBukkit + +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 2f4728b0d..7ed3a0677 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -1219,6 +1219,7 @@ public abstract class World implements IBlockAccess { + { + if ( iter.next().trackee == entity ) + { ++ map.decorations.remove(entity.getUniqueID()); // Paper + iter.remove(); + } + } +diff --git a/src/main/java/net/minecraft/server/WorldMap.java b/src/main/java/net/minecraft/server/WorldMap.java +index dd5412e69..dbe6a80f2 100644 +--- a/src/main/java/net/minecraft/server/WorldMap.java ++++ b/src/main/java/net/minecraft/server/WorldMap.java +@@ -28,6 +28,7 @@ public class WorldMap extends PersistentBase { + public List i = Lists.newArrayList(); + public final Map k = Maps.newHashMap(); // Spigot private -> public + public Map decorations = Maps.newLinkedHashMap(); // Spigot ++ private org.bukkit.craftbukkit.map.RenderData vanillaRender = new org.bukkit.craftbukkit.map.RenderData(); // Paper + + // CraftBukkit start + public final CraftMapView mapView; +@@ -40,6 +41,7 @@ public class WorldMap extends PersistentBase { + // CraftBukkit start + mapView = new CraftMapView(this); + server = (CraftServer) org.bukkit.Bukkit.getServer(); ++ vanillaRender.buffer = colors; // Paper + // CraftBukkit end + } + +@@ -114,6 +116,7 @@ public class WorldMap extends PersistentBase { + } + } + } ++ vanillaRender.buffer = colors; // Paper + + } + +@@ -149,6 +152,7 @@ public class WorldMap extends PersistentBase { + return nbttagcompound; + } + ++ public void updateSeenPlayers(EntityHuman entityhuman, ItemStack itemstack) { a(entityhuman, itemstack); } // Paper - OBFHELPER + public void a(EntityHuman entityhuman, ItemStack itemstack) { + if (!this.k.containsKey(entityhuman)) { + WorldMap.WorldMapHumanTracker worldmap_worldmaphumantracker = new WorldMap.WorldMapHumanTracker(entityhuman); +@@ -314,6 +318,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((uuid, mapIcon) -> { ++ // If this cursor is for a player check visibility with vanish system ++ org.bukkit.entity.Player other = org.bukkit.Bukkit.getPlayer(uuid); // 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 stop + public final EntityHuman trackee; + private boolean d = true; + private int e; +@@ -330,9 +349,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 256a13178..5768cd512 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() { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0126-remove-null-possibility-for-getServer-singleton.patch b/Spigot-Server-Patches/0126-remove-null-possibility-for-getServer-singleton.patch deleted file mode 100644 index c661ce95e5..0000000000 --- a/Spigot-Server-Patches/0126-remove-null-possibility-for-getServer-singleton.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 062ba076f982db42212697357f485aa5d920df0a 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 430168d21..83b62da55 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -52,6 +52,7 @@ import co.aikar.timings.MinecraftTimings; // Paper - - public abstract class MinecraftServer implements Runnable, ICommandListener, IAsyncTaskHandler, IMojangStatistics { - -+ private static MinecraftServer SERVER; // Paper - public static final Logger LOGGER = LogManager.getLogger(); - public static final File a = new File("usercache.json"); - public Convertable convertable; -@@ -123,6 +124,7 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs - // Spigot end - - public MinecraftServer(OptionSet options, Proxy proxy, DataConverterManager dataconvertermanager, YggdrasilAuthenticationService yggdrasilauthenticationservice, MinecraftSessionService minecraftsessionservice, GameProfileRepository gameprofilerepository, UserCache usercache) { -+ SERVER = this; // Paper - better singleton - io.netty.util.ResourceLeakDetector.setEnabled( false ); // Spigot - disable - this.e = proxy; - this.V = yggdrasilauthenticationservice; -@@ -1634,7 +1636,7 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs - // CraftBukkit start - @Deprecated - public static MinecraftServer getServer() { -- return (Bukkit.getServer() instanceof CraftServer) ? ((CraftServer) Bukkit.getServer()).getServer() : null; -+ return SERVER; - } - // CraftBukkit end - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0127-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch b/Spigot-Server-Patches/0127-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch deleted file mode 100644 index ed4b9fff2d..0000000000 --- a/Spigot-Server-Patches/0127-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 014e66039c805fb82717b0f6fe7c6b8d30f3699a Mon Sep 17 00:00:00 2001 -From: Aikar -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/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java -index 43e28d61c..af173a137 100644 ---- a/src/main/java/net/minecraft/server/EntityHuman.java -+++ b/src/main/java/net/minecraft/server/EntityHuman.java -@@ -597,6 +597,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 = Items.FILLED_MAP.getSavedMap(itemstack, this.world); -+ worldmap.updateSeenPlayers(this, itemstack); -+ } -+ // Paper stop - - ItemStack itemstack1 = this.a(entityitem); - -diff --git a/src/main/java/net/minecraft/server/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/EntityTrackerEntry.java -index f542bf491..fbda70a39 100644 ---- a/src/main/java/net/minecraft/server/EntityTrackerEntry.java -+++ b/src/main/java/net/minecraft/server/EntityTrackerEntry.java -@@ -90,11 +90,11 @@ public class EntityTrackerEntry { - } - - // PAIL : rename -- if (this.tracker instanceof EntityItemFrame /*&& this.a % 10 == 0*/) { // CraftBukkit - Moved below, should always enter this block -+ if (this.tracker instanceof EntityItemFrame && this.a % 20 == 0) { // Paper - EntityItemFrame entityitemframe = (EntityItemFrame) this.tracker; - ItemStack itemstack = entityitemframe.getItem(); - -- if (this.a % 10 == 0 && itemstack.getItem() instanceof ItemWorldMap) { // CraftBukkit - Moved this.a % 10 logic here so item frames do not enter the other blocks -+ if (itemstack != null && itemstack.getItem() instanceof ItemWorldMap) { // Paper - moved back up - WorldMap worldmap = Items.FILLED_MAP.getSavedMap(itemstack, this.tracker.world); - Iterator iterator = this.trackedPlayers.iterator(); // CraftBukkit - -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 2f4728b0d..7ed3a0677 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -1219,6 +1219,7 @@ public abstract class World implements IBlockAccess { - { - if ( iter.next().trackee == entity ) - { -+ map.decorations.remove(entity.getUniqueID()); // Paper - iter.remove(); - } - } -diff --git a/src/main/java/net/minecraft/server/WorldMap.java b/src/main/java/net/minecraft/server/WorldMap.java -index dd5412e69..dbe6a80f2 100644 ---- a/src/main/java/net/minecraft/server/WorldMap.java -+++ b/src/main/java/net/minecraft/server/WorldMap.java -@@ -28,6 +28,7 @@ public class WorldMap extends PersistentBase { - public List i = Lists.newArrayList(); - public final Map k = Maps.newHashMap(); // Spigot private -> public - public Map decorations = Maps.newLinkedHashMap(); // Spigot -+ private org.bukkit.craftbukkit.map.RenderData vanillaRender = new org.bukkit.craftbukkit.map.RenderData(); // Paper - - // CraftBukkit start - public final CraftMapView mapView; -@@ -40,6 +41,7 @@ public class WorldMap extends PersistentBase { - // CraftBukkit start - mapView = new CraftMapView(this); - server = (CraftServer) org.bukkit.Bukkit.getServer(); -+ vanillaRender.buffer = colors; // Paper - // CraftBukkit end - } - -@@ -114,6 +116,7 @@ public class WorldMap extends PersistentBase { - } - } - } -+ vanillaRender.buffer = colors; // Paper - - } - -@@ -149,6 +152,7 @@ public class WorldMap extends PersistentBase { - return nbttagcompound; - } - -+ public void updateSeenPlayers(EntityHuman entityhuman, ItemStack itemstack) { a(entityhuman, itemstack); } // Paper - OBFHELPER - public void a(EntityHuman entityhuman, ItemStack itemstack) { - if (!this.k.containsKey(entityhuman)) { - WorldMap.WorldMapHumanTracker worldmap_worldmaphumantracker = new WorldMap.WorldMapHumanTracker(entityhuman); -@@ -314,6 +318,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((uuid, mapIcon) -> { -+ // If this cursor is for a player check visibility with vanish system -+ org.bukkit.entity.Player other = org.bukkit.Bukkit.getPlayer(uuid); // 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 stop - public final EntityHuman trackee; - private boolean d = true; - private int e; -@@ -330,9 +349,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 256a13178..5768cd512 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() { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0127-LootTable-API-Replenishable-Lootables-Feature.patch b/Spigot-Server-Patches/0127-LootTable-API-Replenishable-Lootables-Feature.patch new file mode 100644 index 0000000000..24617487a0 --- /dev/null +++ b/Spigot-Server-Patches/0127-LootTable-API-Replenishable-Lootables-Feature.patch @@ -0,0 +1,786 @@ +From bfc069f2e9f925c0f10d95b9cdbdd33ea8a3f8f7 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 5cc55b794..fbe769eb3 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -305,4 +305,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/CraftLootable.java b/src/main/java/com/destroystokyo/paper/loottable/CraftLootable.java +new file mode 100644 +index 000000000..36c36d158 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootable.java +@@ -0,0 +1,12 @@ ++package com.destroystokyo.paper.loottable; ++ ++import net.minecraft.server.World; ++ ++interface CraftLootable extends Lootable { ++ ++ World getNMSWorld(); ++ ++ default org.bukkit.World getBukkitWorld() { ++ return getNMSWorld().getWorld(); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/CraftLootableBlockInventory.java b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableBlockInventory.java +new file mode 100644 +index 000000000..20d236c45 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableBlockInventory.java +@@ -0,0 +1,33 @@ ++package com.destroystokyo.paper.loottable; ++ ++import net.minecraft.server.BlockPosition; ++import net.minecraft.server.TileEntityLootable; ++import net.minecraft.server.World; ++import org.bukkit.Chunk; ++import org.bukkit.block.Block; ++ ++public interface CraftLootableBlockInventory extends LootableBlockInventory, CraftLootableInventory { ++ ++ 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 CraftLootableInventoryData getLootableData() { ++ return getTileEntity().getLootableData(); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/CraftLootableEntityInventory.java b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableEntityInventory.java +new file mode 100644 +index 000000000..1150dee01 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableEntityInventory.java +@@ -0,0 +1,31 @@ ++package com.destroystokyo.paper.loottable; ++ ++import net.minecraft.server.World; ++import org.bukkit.entity.Entity; ++ ++public interface CraftLootableEntityInventory extends LootableEntityInventory, CraftLootableInventory { ++ ++ net.minecraft.server.Entity getHandle(); ++ ++ @Override ++ default LootableInventory getAPILootableInventory() { ++ return this; ++ } ++ ++ default Entity getEntity() { ++ return getHandle().getBukkitEntity(); ++ } ++ ++ @Override ++ default World getNMSWorld() { ++ return getHandle().getWorld(); ++ } ++ ++ @Override ++ default CraftLootableInventoryData getLootableData() { ++ if (getHandle() instanceof CraftLootableInventory) { ++ return ((CraftLootableInventory) getHandle()).getLootableData(); ++ } ++ return null; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/CraftLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableInventory.java +new file mode 100644 +index 000000000..668097620 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableInventory.java +@@ -0,0 +1,88 @@ ++package com.destroystokyo.paper.loottable; ++ ++import org.apache.commons.lang.Validate; ++ ++import java.util.UUID; ++ ++public interface CraftLootableInventory extends CraftLootable, LootableInventory { ++ ++ CraftLootableInventoryData getLootableData(); ++ LootableInventory getAPILootableInventory(); ++ ++ @Override ++ default boolean isRefillEnabled() { ++ return getNMSWorld().paperConfig.autoReplenishLootables; ++ } ++ ++ @Override ++ default boolean hasBeenFilled() { ++ return getLastFilled() != -1; ++ } ++ ++ @Override ++ default String getLootTableName() { ++ return getLootableData().getLootable().getLootTableName(); ++ } ++ ++ @Override ++ default String setLootTable(String name, long seed) { ++ Validate.notNull(name); ++ ++ String prevLootTable = getLootTableName(); ++ getLootableData().getLootable().setLootTable(name, seed); ++ return prevLootTable; ++ } ++ ++ @Override ++ default long getLootTableSeed() { ++ return getLootableData().getLootable().getLootTableSeed(); ++ } ++ ++ @Override ++ default void clearLootTable() { ++ getLootableData().getLootable().clearLootTable(); ++ } ++ ++ @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/CraftLootableInventoryData.java b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableInventoryData.java +new file mode 100644 +index 000000000..01c2713d3 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableInventoryData.java +@@ -0,0 +1,182 @@ ++package com.destroystokyo.paper.loottable; ++ ++import com.destroystokyo.paper.PaperWorldConfig; ++import net.minecraft.server.*; ++import org.bukkit.entity.Player; ++ ++import javax.annotation.Nullable; ++import java.util.HashMap; ++import java.util.Map; ++import java.util.Random; ++import java.util.UUID; ++ ++public class CraftLootableInventoryData { ++ ++ private static final Random RANDOM = new Random(); ++ ++ private long lastFill = -1; ++ private long nextRefill = -1; ++ private int numRefills = 0; ++ private Map lootedPlayers; ++ private final CraftLootableInventory lootable; ++ ++ public CraftLootableInventoryData(CraftLootableInventory 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; ++ } ++ ++ CraftLootableInventory getLootable() { ++ return lootable; ++ } ++ ++ public boolean shouldReplenish(@Nullable EntityHuman player) { ++ String tableName = this.lootable.getLootTableName(); ++ ++ // No Loot Table associated ++ if (tableName == null) { ++ return false; ++ } ++ ++ // ALWAYS process the first fill ++ if (this.lastFill == -1) { ++ 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 * 1000; ++ int max = paperConfig.lootableRegenMax * 1000; ++ this.nextRefill = this.lastFill + min + RANDOM.nextInt(max - min + 1); ++ this.numRefills++; ++ if (paperConfig.changeLootTableSeedOnFill) { ++ this.lootable.setLootTableSeed(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.get(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/net/minecraft/server/EntityMinecartContainer.java b/src/main/java/net/minecraft/server/EntityMinecartContainer.java +index a79919696..965aa5c23 100644 +--- a/src/main/java/net/minecraft/server/EntityMinecartContainer.java ++++ b/src/main/java/net/minecraft/server/EntityMinecartContainer.java +@@ -6,17 +6,21 @@ import javax.annotation.Nullable; + // CraftBukkit start + import java.util.List; + import org.bukkit.Location; ++ ++import com.destroystokyo.paper.loottable.CraftLootableInventoryData; // Paper ++import com.destroystokyo.paper.loottable.CraftLootableInventory; // Paper ++import com.destroystokyo.paper.loottable.LootableInventory; // Paper + import org.bukkit.craftbukkit.entity.CraftHumanEntity; + import org.bukkit.entity.HumanEntity; + import org.bukkit.inventory.InventoryHolder; + // CraftBukkit end + +-public abstract class EntityMinecartContainer extends EntityMinecartAbstract implements ITileInventory, ILootable { ++public abstract class EntityMinecartContainer extends EntityMinecartAbstract implements ITileInventory, ILootable, CraftLootableInventory { // Paper + + private NonNullList items; + private boolean b; + private MinecraftKey c; +- private long d; ++ private long d;public long getLootTableSeed() { return d; } // Paper - OBFHELPER + + // CraftBukkit start + public List transaction = new java.util.ArrayList(); +@@ -164,12 +168,13 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp + + protected void b(NBTTagCompound nbttagcompound) { + super.b(nbttagcompound); ++ lootableData.saveNbt(nbttagcompound); // Paper + if (this.c != null) { + nbttagcompound.setString("LootTable", this.c.toString()); + if (this.d != 0L) { + nbttagcompound.setLong("LootTableSeed", this.d); + } +- } else { ++ } if (true) { // Paper - Always save the items, Table may stick around + ContainerUtil.a(nbttagcompound, this.items); + } + +@@ -181,7 +186,7 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp + if (nbttagcompound.hasKeyOfType("LootTable", 8)) { + this.c = new MinecraftKey(nbttagcompound.getString("LootTable")); + this.d = nbttagcompound.getLong("LootTableSeed"); +- } else { ++ } if (true) { // Paper - always load the items, table may still remain + ContainerUtil.b(nbttagcompound, this.items); + } + +@@ -230,10 +235,10 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp + } + + public void f(@Nullable EntityHuman entityhuman) { +- if (this.c != null) { ++ if (lootableData.shouldReplenish(entityhuman)) { // Paper + LootTable loottable = this.world.ak().a(this.c); + +- this.c = null; ++ lootableData.processRefill(entityhuman); // Paper + Random random; + + if (this.d == 0L) { +@@ -258,12 +263,52 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp + this.items.clear(); + } + ++ public void setLootTable(MinecraftKey key, long seed) { a(key, seed);} // Paper - OBFHELPER + public void a(MinecraftKey minecraftkey, long i) { + this.c = minecraftkey; + this.d = i; + } + ++ ++ public MinecraftKey getLootTableKey() { return b(); } // Paper - OBFHELPER + public MinecraftKey b() { + return this.c; + } ++ ++ // Paper start ++ private final CraftLootableInventoryData lootableData = new CraftLootableInventoryData(this); ++ ++ @Override ++ public CraftLootableInventoryData getLootableData() { ++ return lootableData; ++ } ++ ++ @Override ++ public LootableInventory getAPILootableInventory() { ++ return (LootableInventory) this.getBukkitEntity(); ++ } ++ ++ @Override ++ public World getNMSWorld() { ++ return this.world; ++ } ++ ++ public String getLootTableName() { ++ final MinecraftKey key = getLootTableKey(); ++ return key != null ? key.toString() : null; ++ } ++ ++ @Override ++ public String setLootTable(String name, long seed) { ++ String prev = getLootTableName(); ++ setLootTable(new MinecraftKey(name), seed); ++ return prev; ++ } ++ ++ @Override ++ public void clearLootTable() { ++ //noinspection RedundantCast ++ this.c = (MinecraftKey) null; ++ } ++ // Paper end + } +diff --git a/src/main/java/net/minecraft/server/TileEntityLootable.java b/src/main/java/net/minecraft/server/TileEntityLootable.java +index 5632f2e78..01d0d8071 100644 +--- a/src/main/java/net/minecraft/server/TileEntityLootable.java ++++ b/src/main/java/net/minecraft/server/TileEntityLootable.java +@@ -1,44 +1,50 @@ + package net.minecraft.server; + ++import com.destroystokyo.paper.loottable.CraftLootableInventoryData; // Paper ++import com.destroystokyo.paper.loottable.CraftLootableInventory; // Paper ++import com.destroystokyo.paper.loottable.LootableInventory; // Paper ++ + import java.util.Random; + import javax.annotation.Nullable; + +-public abstract class TileEntityLootable extends TileEntityContainer implements ILootable { ++public abstract class TileEntityLootable extends TileEntityContainer implements ILootable, CraftLootableInventory { // Paper + + protected MinecraftKey m; +- protected long n; ++ protected long n; public long getLootTableSeed() { return n; } // Paper - OBFHELPER + protected String o; + + public TileEntityLootable() {} + + protected boolean c(NBTTagCompound nbttagcompound) { ++ lootableData.loadNbt(nbttagcompound); // Paper + if (nbttagcompound.hasKeyOfType("LootTable", 8)) { + this.m = new MinecraftKey(nbttagcompound.getString("LootTable")); + this.n = nbttagcompound.getLong("LootTableSeed"); +- return true; ++ return false; // Paper - always load the items, table may still remain + } else { + return false; + } + } + + protected boolean d(NBTTagCompound nbttagcompound) { ++ lootableData.saveNbt(nbttagcompound); // Paper + if (this.m != null) { + nbttagcompound.setString("LootTable", this.m.toString()); + if (this.n != 0L) { + nbttagcompound.setLong("LootTableSeed", this.n); + } + +- return true; ++ return false; // Paper - always save the items, table may still remain + } else { + return false; + } + } + + public void d(@Nullable EntityHuman entityhuman) { +- if (this.m != null) { ++ if (lootableData.shouldReplenish(entityhuman)) { // Paper + LootTable loottable = this.world.ak().a(this.m); + +- this.m = null; ++ lootableData.processRefill(entityhuman); // Paper + Random random; + + if (this.n == 0L) { +@@ -58,10 +64,12 @@ public abstract class TileEntityLootable extends TileEntityContainer implements + + } + ++ public MinecraftKey getLootTableKey() { return b(); } // Paper - OBFHELPER + public MinecraftKey b() { + return this.m; + } + ++ public void setLootTable(MinecraftKey key, long seed) { a(key, seed);} // Paper - OBFHELPER + public void a(MinecraftKey minecraftkey, long i) { + this.m = minecraftkey; + this.n = i; +@@ -134,4 +142,42 @@ public abstract class TileEntityLootable extends TileEntityContainer implements + } + + protected abstract NonNullList q(); ++ ++ // Paper start - LootTable API ++ private final CraftLootableInventoryData lootableData = new CraftLootableInventoryData(this); ++ ++ @Override ++ public CraftLootableInventoryData getLootableData() { ++ return lootableData; ++ } ++ ++ @Override ++ public LootableInventory getAPILootableInventory() { ++ return (LootableInventory) getBukkitWorld().getBlockAt(MCUtil.toLocation(world, getPosition())).getState(); ++ } ++ ++ @Override ++ public World getNMSWorld() { ++ return world; ++ } ++ ++ public String getLootTableName() { ++ final MinecraftKey key = getLootTableKey(); ++ return key != null ? key.toString() : null; ++ } ++ ++ @Override ++ public String setLootTable(String name, long seed) { ++ String prev = getLootTableName(); ++ setLootTable(new MinecraftKey(name), seed); ++ return prev; ++ } ++ ++ @Override ++ public void clearLootTable() { ++ //noinspection RedundantCast ++ this.m = (MinecraftKey) null; ++ } ++ // Paper end ++ + } +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java +index 3de7e14d8..6cab545e5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java +@@ -1,5 +1,6 @@ + package org.bukkit.craftbukkit.block; + ++import com.destroystokyo.paper.loottable.CraftLootableBlockInventory; // Paper + import net.minecraft.server.BlockPosition; + import net.minecraft.server.TileEntityChest; + +@@ -11,7 +12,7 @@ import org.bukkit.craftbukkit.inventory.CraftInventory; + import org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest; + import org.bukkit.inventory.Inventory; + +-public class CraftChest extends CraftLootable implements Chest { ++public class CraftChest extends CraftLootable implements Chest, CraftLootableBlockInventory { // Paper + private final CraftWorld world; + private final TileEntityChest chest; + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java b/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java +index cc0d28f21..1b28e8ba2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java +@@ -1,5 +1,6 @@ + package org.bukkit.craftbukkit.block; + ++import com.destroystokyo.paper.loottable.CraftLootableBlockInventory; // Paper + import net.minecraft.server.BlockDispenser; + import net.minecraft.server.BlockPosition; + import net.minecraft.server.Blocks; +@@ -14,7 +15,7 @@ import org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource; + import org.bukkit.inventory.Inventory; + import org.bukkit.projectiles.BlockProjectileSource; + +-public class CraftDispenser extends CraftLootable implements Dispenser { ++public class CraftDispenser extends CraftLootable implements Dispenser, CraftLootableBlockInventory { // Paper + private final CraftWorld world; + private final TileEntityDispenser dispenser; + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java b/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java +index b7a04bd84..5d4a5519d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java +@@ -1,5 +1,6 @@ + package org.bukkit.craftbukkit.block; + ++import com.destroystokyo.paper.loottable.CraftLootableBlockInventory; // Paper + import net.minecraft.server.TileEntityHopper; + import org.bukkit.Material; + import org.bukkit.block.Block; +@@ -8,7 +9,7 @@ import org.bukkit.craftbukkit.CraftWorld; + import org.bukkit.craftbukkit.inventory.CraftInventory; + import org.bukkit.inventory.Inventory; + +-public class CraftHopper extends CraftLootable implements Hopper { ++public class CraftHopper extends CraftLootable implements Hopper, CraftLootableBlockInventory { // Paper + private final TileEntityHopper hopper; + + public CraftHopper(final Block block) { +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java b/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java +index 8a7ce92bf..02f56bc0d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java +@@ -1,5 +1,6 @@ + package org.bukkit.craftbukkit.block; + ++import com.destroystokyo.paper.loottable.CraftLootableBlockInventory; + import net.minecraft.server.BlockShulkerBox; + import net.minecraft.server.TileEntity; + import net.minecraft.server.TileEntityShulkerBox; +@@ -11,7 +12,7 @@ import org.bukkit.craftbukkit.CraftWorld; + import org.bukkit.craftbukkit.inventory.CraftInventory; + import org.bukkit.inventory.Inventory; + +-public class CraftShulkerBox extends CraftLootable implements ShulkerBox { ++public class CraftShulkerBox extends CraftLootable implements ShulkerBox, CraftLootableBlockInventory { // Paper + + private final CraftWorld world; + private final TileEntityShulkerBox box; +@@ -31,7 +32,7 @@ public class CraftShulkerBox extends CraftLootable implements ShulkerBox { + } + + @Override +- public TileEntity getTileEntity() { ++ public TileEntityShulkerBox getTileEntity() { // Paper + return box; + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java +index 69435c457..4291edf25 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java +@@ -1,5 +1,6 @@ + package org.bukkit.craftbukkit.entity; + ++import com.destroystokyo.paper.loottable.CraftLootableEntityInventory; // Paper + import net.minecraft.server.EntityMinecartChest; + + import org.bukkit.craftbukkit.CraftServer; +@@ -9,7 +10,7 @@ import org.bukkit.entity.minecart.StorageMinecart; + import org.bukkit.inventory.Inventory; + + @SuppressWarnings("deprecation") +-public class CraftMinecartChest extends CraftMinecart implements StorageMinecart { ++public class CraftMinecartChest extends CraftMinecart implements StorageMinecart, CraftLootableEntityInventory { // Paper + private final CraftInventory inventory; + + public CraftMinecartChest(CraftServer server, EntityMinecartChest entity) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java +index e9963e21c..acb4dee04 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java +@@ -1,5 +1,6 @@ + package org.bukkit.craftbukkit.entity; + ++import com.destroystokyo.paper.loottable.CraftLootableEntityInventory; // Paper + import net.minecraft.server.EntityMinecartHopper; + + import org.bukkit.craftbukkit.CraftServer; +@@ -8,7 +9,7 @@ import org.bukkit.entity.EntityType; + import org.bukkit.entity.minecart.HopperMinecart; + import org.bukkit.inventory.Inventory; + +-final class CraftMinecartHopper extends CraftMinecart implements HopperMinecart { ++final class CraftMinecartHopper extends CraftMinecart implements HopperMinecart, CraftLootableEntityInventory { // Paper + private final CraftInventory inventory; + + CraftMinecartHopper(CraftServer server, EntityMinecartHopper entity) { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0128-Do-not-load-chunks-for-pathfinding.patch b/Spigot-Server-Patches/0128-Do-not-load-chunks-for-pathfinding.patch new file mode 100644 index 0000000000..cebfc41856 --- /dev/null +++ b/Spigot-Server-Patches/0128-Do-not-load-chunks-for-pathfinding.patch @@ -0,0 +1,22 @@ +From 0e544cd8d1e8174c68a97013f8898d58741d0340 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 19 Jan 2016 00:13:19 -0500 +Subject: [PATCH] Do not load chunks for pathfinding + + +diff --git a/src/main/java/net/minecraft/server/ChunkCache.java b/src/main/java/net/minecraft/server/ChunkCache.java +index 08b986fd7..786d1dd22 100644 +--- a/src/main/java/net/minecraft/server/ChunkCache.java ++++ b/src/main/java/net/minecraft/server/ChunkCache.java +@@ -25,7 +25,7 @@ public class ChunkCache implements IBlockAccess { + + for (l = this.a; l <= j; ++l) { + for (i1 = this.b; i1 <= k; ++i1) { +- this.c[l - this.a][i1 - this.b] = world.getChunkAt(l, i1); ++ this.c[l - this.a][i1 - this.b] = world.getChunkIfLoaded(l, i1); // Paper + } + } + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0128-LootTable-API-Replenishable-Lootables-Feature.patch b/Spigot-Server-Patches/0128-LootTable-API-Replenishable-Lootables-Feature.patch deleted file mode 100644 index 711c5c35fc..0000000000 --- a/Spigot-Server-Patches/0128-LootTable-API-Replenishable-Lootables-Feature.patch +++ /dev/null @@ -1,786 +0,0 @@ -From 7d61f1ae6c1042b230ece85761341c36ce482e6d 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 5cc55b794..fbe769eb3 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -305,4 +305,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/CraftLootable.java b/src/main/java/com/destroystokyo/paper/loottable/CraftLootable.java -new file mode 100644 -index 000000000..36c36d158 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootable.java -@@ -0,0 +1,12 @@ -+package com.destroystokyo.paper.loottable; -+ -+import net.minecraft.server.World; -+ -+interface CraftLootable extends Lootable { -+ -+ World getNMSWorld(); -+ -+ default org.bukkit.World getBukkitWorld() { -+ return getNMSWorld().getWorld(); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/CraftLootableBlockInventory.java b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableBlockInventory.java -new file mode 100644 -index 000000000..20d236c45 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableBlockInventory.java -@@ -0,0 +1,33 @@ -+package com.destroystokyo.paper.loottable; -+ -+import net.minecraft.server.BlockPosition; -+import net.minecraft.server.TileEntityLootable; -+import net.minecraft.server.World; -+import org.bukkit.Chunk; -+import org.bukkit.block.Block; -+ -+public interface CraftLootableBlockInventory extends LootableBlockInventory, CraftLootableInventory { -+ -+ 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 CraftLootableInventoryData getLootableData() { -+ return getTileEntity().getLootableData(); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/CraftLootableEntityInventory.java b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableEntityInventory.java -new file mode 100644 -index 000000000..1150dee01 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableEntityInventory.java -@@ -0,0 +1,31 @@ -+package com.destroystokyo.paper.loottable; -+ -+import net.minecraft.server.World; -+import org.bukkit.entity.Entity; -+ -+public interface CraftLootableEntityInventory extends LootableEntityInventory, CraftLootableInventory { -+ -+ net.minecraft.server.Entity getHandle(); -+ -+ @Override -+ default LootableInventory getAPILootableInventory() { -+ return this; -+ } -+ -+ default Entity getEntity() { -+ return getHandle().getBukkitEntity(); -+ } -+ -+ @Override -+ default World getNMSWorld() { -+ return getHandle().getWorld(); -+ } -+ -+ @Override -+ default CraftLootableInventoryData getLootableData() { -+ if (getHandle() instanceof CraftLootableInventory) { -+ return ((CraftLootableInventory) getHandle()).getLootableData(); -+ } -+ return null; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/CraftLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableInventory.java -new file mode 100644 -index 000000000..668097620 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableInventory.java -@@ -0,0 +1,88 @@ -+package com.destroystokyo.paper.loottable; -+ -+import org.apache.commons.lang.Validate; -+ -+import java.util.UUID; -+ -+public interface CraftLootableInventory extends CraftLootable, LootableInventory { -+ -+ CraftLootableInventoryData getLootableData(); -+ LootableInventory getAPILootableInventory(); -+ -+ @Override -+ default boolean isRefillEnabled() { -+ return getNMSWorld().paperConfig.autoReplenishLootables; -+ } -+ -+ @Override -+ default boolean hasBeenFilled() { -+ return getLastFilled() != -1; -+ } -+ -+ @Override -+ default String getLootTableName() { -+ return getLootableData().getLootable().getLootTableName(); -+ } -+ -+ @Override -+ default String setLootTable(String name, long seed) { -+ Validate.notNull(name); -+ -+ String prevLootTable = getLootTableName(); -+ getLootableData().getLootable().setLootTable(name, seed); -+ return prevLootTable; -+ } -+ -+ @Override -+ default long getLootTableSeed() { -+ return getLootableData().getLootable().getLootTableSeed(); -+ } -+ -+ @Override -+ default void clearLootTable() { -+ getLootableData().getLootable().clearLootTable(); -+ } -+ -+ @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/CraftLootableInventoryData.java b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableInventoryData.java -new file mode 100644 -index 000000000..01c2713d3 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableInventoryData.java -@@ -0,0 +1,182 @@ -+package com.destroystokyo.paper.loottable; -+ -+import com.destroystokyo.paper.PaperWorldConfig; -+import net.minecraft.server.*; -+import org.bukkit.entity.Player; -+ -+import javax.annotation.Nullable; -+import java.util.HashMap; -+import java.util.Map; -+import java.util.Random; -+import java.util.UUID; -+ -+public class CraftLootableInventoryData { -+ -+ private static final Random RANDOM = new Random(); -+ -+ private long lastFill = -1; -+ private long nextRefill = -1; -+ private int numRefills = 0; -+ private Map lootedPlayers; -+ private final CraftLootableInventory lootable; -+ -+ public CraftLootableInventoryData(CraftLootableInventory 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; -+ } -+ -+ CraftLootableInventory getLootable() { -+ return lootable; -+ } -+ -+ public boolean shouldReplenish(@Nullable EntityHuman player) { -+ String tableName = this.lootable.getLootTableName(); -+ -+ // No Loot Table associated -+ if (tableName == null) { -+ return false; -+ } -+ -+ // ALWAYS process the first fill -+ if (this.lastFill == -1) { -+ 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 * 1000; -+ int max = paperConfig.lootableRegenMax * 1000; -+ this.nextRefill = this.lastFill + min + RANDOM.nextInt(max - min + 1); -+ this.numRefills++; -+ if (paperConfig.changeLootTableSeedOnFill) { -+ this.lootable.setLootTableSeed(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.get(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/net/minecraft/server/EntityMinecartContainer.java b/src/main/java/net/minecraft/server/EntityMinecartContainer.java -index a79919696..965aa5c23 100644 ---- a/src/main/java/net/minecraft/server/EntityMinecartContainer.java -+++ b/src/main/java/net/minecraft/server/EntityMinecartContainer.java -@@ -6,17 +6,21 @@ import javax.annotation.Nullable; - // CraftBukkit start - import java.util.List; - import org.bukkit.Location; -+ -+import com.destroystokyo.paper.loottable.CraftLootableInventoryData; // Paper -+import com.destroystokyo.paper.loottable.CraftLootableInventory; // Paper -+import com.destroystokyo.paper.loottable.LootableInventory; // Paper - import org.bukkit.craftbukkit.entity.CraftHumanEntity; - import org.bukkit.entity.HumanEntity; - import org.bukkit.inventory.InventoryHolder; - // CraftBukkit end - --public abstract class EntityMinecartContainer extends EntityMinecartAbstract implements ITileInventory, ILootable { -+public abstract class EntityMinecartContainer extends EntityMinecartAbstract implements ITileInventory, ILootable, CraftLootableInventory { // Paper - - private NonNullList items; - private boolean b; - private MinecraftKey c; -- private long d; -+ private long d;public long getLootTableSeed() { return d; } // Paper - OBFHELPER - - // CraftBukkit start - public List transaction = new java.util.ArrayList(); -@@ -164,12 +168,13 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp - - protected void b(NBTTagCompound nbttagcompound) { - super.b(nbttagcompound); -+ lootableData.saveNbt(nbttagcompound); // Paper - if (this.c != null) { - nbttagcompound.setString("LootTable", this.c.toString()); - if (this.d != 0L) { - nbttagcompound.setLong("LootTableSeed", this.d); - } -- } else { -+ } if (true) { // Paper - Always save the items, Table may stick around - ContainerUtil.a(nbttagcompound, this.items); - } - -@@ -181,7 +186,7 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp - if (nbttagcompound.hasKeyOfType("LootTable", 8)) { - this.c = new MinecraftKey(nbttagcompound.getString("LootTable")); - this.d = nbttagcompound.getLong("LootTableSeed"); -- } else { -+ } if (true) { // Paper - always load the items, table may still remain - ContainerUtil.b(nbttagcompound, this.items); - } - -@@ -230,10 +235,10 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp - } - - public void f(@Nullable EntityHuman entityhuman) { -- if (this.c != null) { -+ if (lootableData.shouldReplenish(entityhuman)) { // Paper - LootTable loottable = this.world.ak().a(this.c); - -- this.c = null; -+ lootableData.processRefill(entityhuman); // Paper - Random random; - - if (this.d == 0L) { -@@ -258,12 +263,52 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp - this.items.clear(); - } - -+ public void setLootTable(MinecraftKey key, long seed) { a(key, seed);} // Paper - OBFHELPER - public void a(MinecraftKey minecraftkey, long i) { - this.c = minecraftkey; - this.d = i; - } - -+ -+ public MinecraftKey getLootTableKey() { return b(); } // Paper - OBFHELPER - public MinecraftKey b() { - return this.c; - } -+ -+ // Paper start -+ private final CraftLootableInventoryData lootableData = new CraftLootableInventoryData(this); -+ -+ @Override -+ public CraftLootableInventoryData getLootableData() { -+ return lootableData; -+ } -+ -+ @Override -+ public LootableInventory getAPILootableInventory() { -+ return (LootableInventory) this.getBukkitEntity(); -+ } -+ -+ @Override -+ public World getNMSWorld() { -+ return this.world; -+ } -+ -+ public String getLootTableName() { -+ final MinecraftKey key = getLootTableKey(); -+ return key != null ? key.toString() : null; -+ } -+ -+ @Override -+ public String setLootTable(String name, long seed) { -+ String prev = getLootTableName(); -+ setLootTable(new MinecraftKey(name), seed); -+ return prev; -+ } -+ -+ @Override -+ public void clearLootTable() { -+ //noinspection RedundantCast -+ this.c = (MinecraftKey) null; -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/server/TileEntityLootable.java b/src/main/java/net/minecraft/server/TileEntityLootable.java -index 5632f2e78..01d0d8071 100644 ---- a/src/main/java/net/minecraft/server/TileEntityLootable.java -+++ b/src/main/java/net/minecraft/server/TileEntityLootable.java -@@ -1,44 +1,50 @@ - package net.minecraft.server; - -+import com.destroystokyo.paper.loottable.CraftLootableInventoryData; // Paper -+import com.destroystokyo.paper.loottable.CraftLootableInventory; // Paper -+import com.destroystokyo.paper.loottable.LootableInventory; // Paper -+ - import java.util.Random; - import javax.annotation.Nullable; - --public abstract class TileEntityLootable extends TileEntityContainer implements ILootable { -+public abstract class TileEntityLootable extends TileEntityContainer implements ILootable, CraftLootableInventory { // Paper - - protected MinecraftKey m; -- protected long n; -+ protected long n; public long getLootTableSeed() { return n; } // Paper - OBFHELPER - protected String o; - - public TileEntityLootable() {} - - protected boolean c(NBTTagCompound nbttagcompound) { -+ lootableData.loadNbt(nbttagcompound); // Paper - if (nbttagcompound.hasKeyOfType("LootTable", 8)) { - this.m = new MinecraftKey(nbttagcompound.getString("LootTable")); - this.n = nbttagcompound.getLong("LootTableSeed"); -- return true; -+ return false; // Paper - always load the items, table may still remain - } else { - return false; - } - } - - protected boolean d(NBTTagCompound nbttagcompound) { -+ lootableData.saveNbt(nbttagcompound); // Paper - if (this.m != null) { - nbttagcompound.setString("LootTable", this.m.toString()); - if (this.n != 0L) { - nbttagcompound.setLong("LootTableSeed", this.n); - } - -- return true; -+ return false; // Paper - always save the items, table may still remain - } else { - return false; - } - } - - public void d(@Nullable EntityHuman entityhuman) { -- if (this.m != null) { -+ if (lootableData.shouldReplenish(entityhuman)) { // Paper - LootTable loottable = this.world.ak().a(this.m); - -- this.m = null; -+ lootableData.processRefill(entityhuman); // Paper - Random random; - - if (this.n == 0L) { -@@ -58,10 +64,12 @@ public abstract class TileEntityLootable extends TileEntityContainer implements - - } - -+ public MinecraftKey getLootTableKey() { return b(); } // Paper - OBFHELPER - public MinecraftKey b() { - return this.m; - } - -+ public void setLootTable(MinecraftKey key, long seed) { a(key, seed);} // Paper - OBFHELPER - public void a(MinecraftKey minecraftkey, long i) { - this.m = minecraftkey; - this.n = i; -@@ -134,4 +142,42 @@ public abstract class TileEntityLootable extends TileEntityContainer implements - } - - protected abstract NonNullList q(); -+ -+ // Paper start - LootTable API -+ private final CraftLootableInventoryData lootableData = new CraftLootableInventoryData(this); -+ -+ @Override -+ public CraftLootableInventoryData getLootableData() { -+ return lootableData; -+ } -+ -+ @Override -+ public LootableInventory getAPILootableInventory() { -+ return (LootableInventory) getBukkitWorld().getBlockAt(MCUtil.toLocation(world, getPosition())).getState(); -+ } -+ -+ @Override -+ public World getNMSWorld() { -+ return world; -+ } -+ -+ public String getLootTableName() { -+ final MinecraftKey key = getLootTableKey(); -+ return key != null ? key.toString() : null; -+ } -+ -+ @Override -+ public String setLootTable(String name, long seed) { -+ String prev = getLootTableName(); -+ setLootTable(new MinecraftKey(name), seed); -+ return prev; -+ } -+ -+ @Override -+ public void clearLootTable() { -+ //noinspection RedundantCast -+ this.m = (MinecraftKey) null; -+ } -+ // Paper end -+ - } -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -index 3de7e14d8..6cab545e5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.block; - -+import com.destroystokyo.paper.loottable.CraftLootableBlockInventory; // Paper - import net.minecraft.server.BlockPosition; - import net.minecraft.server.TileEntityChest; - -@@ -11,7 +12,7 @@ import org.bukkit.craftbukkit.inventory.CraftInventory; - import org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest; - import org.bukkit.inventory.Inventory; - --public class CraftChest extends CraftLootable implements Chest { -+public class CraftChest extends CraftLootable implements Chest, CraftLootableBlockInventory { // Paper - private final CraftWorld world; - private final TileEntityChest chest; - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java b/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java -index cc0d28f21..1b28e8ba2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.block; - -+import com.destroystokyo.paper.loottable.CraftLootableBlockInventory; // Paper - import net.minecraft.server.BlockDispenser; - import net.minecraft.server.BlockPosition; - import net.minecraft.server.Blocks; -@@ -14,7 +15,7 @@ import org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource; - import org.bukkit.inventory.Inventory; - import org.bukkit.projectiles.BlockProjectileSource; - --public class CraftDispenser extends CraftLootable implements Dispenser { -+public class CraftDispenser extends CraftLootable implements Dispenser, CraftLootableBlockInventory { // Paper - private final CraftWorld world; - private final TileEntityDispenser dispenser; - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java b/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java -index b7a04bd84..5d4a5519d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.block; - -+import com.destroystokyo.paper.loottable.CraftLootableBlockInventory; // Paper - import net.minecraft.server.TileEntityHopper; - import org.bukkit.Material; - import org.bukkit.block.Block; -@@ -8,7 +9,7 @@ import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.inventory.CraftInventory; - import org.bukkit.inventory.Inventory; - --public class CraftHopper extends CraftLootable implements Hopper { -+public class CraftHopper extends CraftLootable implements Hopper, CraftLootableBlockInventory { // Paper - private final TileEntityHopper hopper; - - public CraftHopper(final Block block) { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java b/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java -index 8a7ce92bf..02f56bc0d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.block; - -+import com.destroystokyo.paper.loottable.CraftLootableBlockInventory; - import net.minecraft.server.BlockShulkerBox; - import net.minecraft.server.TileEntity; - import net.minecraft.server.TileEntityShulkerBox; -@@ -11,7 +12,7 @@ import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.inventory.CraftInventory; - import org.bukkit.inventory.Inventory; - --public class CraftShulkerBox extends CraftLootable implements ShulkerBox { -+public class CraftShulkerBox extends CraftLootable implements ShulkerBox, CraftLootableBlockInventory { // Paper - - private final CraftWorld world; - private final TileEntityShulkerBox box; -@@ -31,7 +32,7 @@ public class CraftShulkerBox extends CraftLootable implements ShulkerBox { - } - - @Override -- public TileEntity getTileEntity() { -+ public TileEntityShulkerBox getTileEntity() { // Paper - return box; - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java -index 69435c457..4291edf25 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.entity; - -+import com.destroystokyo.paper.loottable.CraftLootableEntityInventory; // Paper - import net.minecraft.server.EntityMinecartChest; - - import org.bukkit.craftbukkit.CraftServer; -@@ -9,7 +10,7 @@ import org.bukkit.entity.minecart.StorageMinecart; - import org.bukkit.inventory.Inventory; - - @SuppressWarnings("deprecation") --public class CraftMinecartChest extends CraftMinecart implements StorageMinecart { -+public class CraftMinecartChest extends CraftMinecart implements StorageMinecart, CraftLootableEntityInventory { // Paper - private final CraftInventory inventory; - - public CraftMinecartChest(CraftServer server, EntityMinecartChest entity) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java -index e9963e21c..acb4dee04 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.entity; - -+import com.destroystokyo.paper.loottable.CraftLootableEntityInventory; // Paper - import net.minecraft.server.EntityMinecartHopper; - - import org.bukkit.craftbukkit.CraftServer; -@@ -8,7 +9,7 @@ import org.bukkit.entity.EntityType; - import org.bukkit.entity.minecart.HopperMinecart; - import org.bukkit.inventory.Inventory; - --final class CraftMinecartHopper extends CraftMinecart implements HopperMinecart { -+final class CraftMinecartHopper extends CraftMinecart implements HopperMinecart, CraftLootableEntityInventory { // Paper - private final CraftInventory inventory; - - CraftMinecartHopper(CraftServer server, EntityMinecartHopper entity) { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0129-Do-not-load-chunks-for-pathfinding.patch b/Spigot-Server-Patches/0129-Do-not-load-chunks-for-pathfinding.patch deleted file mode 100644 index d9deb4a10f..0000000000 --- a/Spigot-Server-Patches/0129-Do-not-load-chunks-for-pathfinding.patch +++ /dev/null @@ -1,22 +0,0 @@ -From bd0317665aa18996d5e315cf993f1ee8c705efc8 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 19 Jan 2016 00:13:19 -0500 -Subject: [PATCH] Do not load chunks for pathfinding - - -diff --git a/src/main/java/net/minecraft/server/ChunkCache.java b/src/main/java/net/minecraft/server/ChunkCache.java -index 08b986fd7..786d1dd22 100644 ---- a/src/main/java/net/minecraft/server/ChunkCache.java -+++ b/src/main/java/net/minecraft/server/ChunkCache.java -@@ -25,7 +25,7 @@ public class ChunkCache implements IBlockAccess { - - for (l = this.a; l <= j; ++l) { - for (i1 = this.b; i1 <= k; ++i1) { -- this.c[l - this.a][i1 - this.b] = world.getChunkAt(l, i1); -+ this.c[l - this.a][i1 - this.b] = world.getChunkIfLoaded(l, i1); // Paper - } - } - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0129-Entity-Tracking-Improvements.patch b/Spigot-Server-Patches/0129-Entity-Tracking-Improvements.patch new file mode 100644 index 0000000000..349a9c13ad --- /dev/null +++ b/Spigot-Server-Patches/0129-Entity-Tracking-Improvements.patch @@ -0,0 +1,103 @@ +From d0d65d40d665bd4857968bce815a16b73fb71992 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 17 Jun 2013 01:24:00 -0400 +Subject: [PATCH] Entity Tracking Improvements + +If any part of a Vehicle/Passenger relationship is visible to a player, +send all passenger/vehicles to the player in the chain. + +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 0f4a1b66b..96b1e9a78 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -53,6 +53,7 @@ public abstract class Entity implements ICommandListener { + + protected CraftEntity bukkitEntity; + ++ EntityTrackerEntry tracker; // Paper + public CraftEntity getBukkitEntity() { + if (bukkitEntity == null) { + bukkitEntity = CraftEntity.getEntity(world.getServer(), this); +diff --git a/src/main/java/net/minecraft/server/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/EntityTrackerEntry.java +index fbda70a39..c28b4bd44 100644 +--- a/src/main/java/net/minecraft/server/EntityTrackerEntry.java ++++ b/src/main/java/net/minecraft/server/EntityTrackerEntry.java +@@ -49,6 +49,7 @@ public class EntityTrackerEntry { + // Paper end + + public EntityTrackerEntry(Entity entity, int i, int j, int k, boolean flag) { ++ entity.tracker = this; // Paper + this.tracker = entity; + this.e = i; + this.f = j; +@@ -446,17 +447,59 @@ public class EntityTrackerEntry { + + this.tracker.b(entityplayer); + entityplayer.d(this.tracker); ++ updatePassengers(entityplayer); // Paper + } + } else if (this.trackedPlayers.contains(entityplayer)) { + this.trackedPlayers.remove(entityplayer); + this.tracker.c(entityplayer); + entityplayer.c(this.tracker); ++ updatePassengers(entityplayer); // Paper + } + + } + } + + public boolean c(EntityPlayer entityplayer) { ++ // Paper start ++ if (tracker.isPassenger()) { ++ return isTrackedBy(tracker.getVehicle(), entityplayer); ++ } else if (hasPassengerInRange(tracker, entityplayer)) { ++ return true; ++ } ++ ++ return isInRangeOfPlayer(entityplayer); ++ } ++ private static boolean hasPassengerInRange(Entity entity, EntityPlayer entityplayer) { ++ if (!entity.isVehicle()) { ++ return false; ++ } ++ for (Entity passenger : entity.passengers) { ++ if (passenger.tracker != null && passenger.tracker.isInRangeOfPlayer(entityplayer)) { ++ return true; ++ } ++ if (passenger.isVehicle()) { ++ if (hasPassengerInRange(passenger, entityplayer)) { ++ return true; ++ } ++ } ++ } ++ return false; ++ } ++ private static boolean isTrackedBy(Entity entity, EntityPlayer entityplayer) { ++ return entity == entityplayer || entity.tracker != null && entity.tracker.trackedPlayers.contains(entityplayer); ++ } ++ private void updatePassengers(EntityPlayer player) { ++ if (tracker.isVehicle()) { ++ tracker.passengers.forEach((e) -> { ++ if (e.tracker != null) { ++ e.tracker.updatePlayer(player); ++ } ++ }); ++ player.playerConnection.sendPacket(new PacketPlayOutMount(this.tracker)); ++ } ++ } ++ private boolean isInRangeOfPlayer(EntityPlayer entityplayer) { ++ // Paper end + double d0 = entityplayer.locX - (double) this.xLoc / 4096.0D; + double d1 = entityplayer.locZ - (double) this.zLoc / 4096.0D; + int i = Math.min(this.e, this.f); +@@ -593,6 +636,7 @@ public class EntityTrackerEntry { + this.trackedPlayers.remove(entityplayer); + this.tracker.c(entityplayer); + entityplayer.c(this.tracker); ++ updatePassengers(entityplayer); // Paper + } + + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0130-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch b/Spigot-Server-Patches/0130-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch new file mode 100644 index 0000000000..5386a82010 --- /dev/null +++ b/Spigot-Server-Patches/0130-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch @@ -0,0 +1,35 @@ +From 0886e9d5e5edb0b883647a0ac6b83aa38b602b29 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 710c432d8..e009e5cf2 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -230,4 +230,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/server/PersistentScoreboard.java b/src/main/java/net/minecraft/server/PersistentScoreboard.java +index 230004b4a..62752f816 100644 +--- a/src/main/java/net/minecraft/server/PersistentScoreboard.java ++++ b/src/main/java/net/minecraft/server/PersistentScoreboard.java +@@ -184,6 +184,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()); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0130-Entity-Tracking-Improvements.patch b/Spigot-Server-Patches/0130-Entity-Tracking-Improvements.patch deleted file mode 100644 index 1389f2d469..0000000000 --- a/Spigot-Server-Patches/0130-Entity-Tracking-Improvements.patch +++ /dev/null @@ -1,103 +0,0 @@ -From dfc386797ff567e4f4c54a63e24ddb8240df07d7 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 17 Jun 2013 01:24:00 -0400 -Subject: [PATCH] Entity Tracking Improvements - -If any part of a Vehicle/Passenger relationship is visible to a player, -send all passenger/vehicles to the player in the chain. - -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 0f4a1b66b..96b1e9a78 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -53,6 +53,7 @@ public abstract class Entity implements ICommandListener { - - protected CraftEntity bukkitEntity; - -+ EntityTrackerEntry tracker; // Paper - public CraftEntity getBukkitEntity() { - if (bukkitEntity == null) { - bukkitEntity = CraftEntity.getEntity(world.getServer(), this); -diff --git a/src/main/java/net/minecraft/server/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/EntityTrackerEntry.java -index fbda70a39..c28b4bd44 100644 ---- a/src/main/java/net/minecraft/server/EntityTrackerEntry.java -+++ b/src/main/java/net/minecraft/server/EntityTrackerEntry.java -@@ -49,6 +49,7 @@ public class EntityTrackerEntry { - // Paper end - - public EntityTrackerEntry(Entity entity, int i, int j, int k, boolean flag) { -+ entity.tracker = this; // Paper - this.tracker = entity; - this.e = i; - this.f = j; -@@ -446,17 +447,59 @@ public class EntityTrackerEntry { - - this.tracker.b(entityplayer); - entityplayer.d(this.tracker); -+ updatePassengers(entityplayer); // Paper - } - } else if (this.trackedPlayers.contains(entityplayer)) { - this.trackedPlayers.remove(entityplayer); - this.tracker.c(entityplayer); - entityplayer.c(this.tracker); -+ updatePassengers(entityplayer); // Paper - } - - } - } - - public boolean c(EntityPlayer entityplayer) { -+ // Paper start -+ if (tracker.isPassenger()) { -+ return isTrackedBy(tracker.getVehicle(), entityplayer); -+ } else if (hasPassengerInRange(tracker, entityplayer)) { -+ return true; -+ } -+ -+ return isInRangeOfPlayer(entityplayer); -+ } -+ private static boolean hasPassengerInRange(Entity entity, EntityPlayer entityplayer) { -+ if (!entity.isVehicle()) { -+ return false; -+ } -+ for (Entity passenger : entity.passengers) { -+ if (passenger.tracker != null && passenger.tracker.isInRangeOfPlayer(entityplayer)) { -+ return true; -+ } -+ if (passenger.isVehicle()) { -+ if (hasPassengerInRange(passenger, entityplayer)) { -+ return true; -+ } -+ } -+ } -+ return false; -+ } -+ private static boolean isTrackedBy(Entity entity, EntityPlayer entityplayer) { -+ return entity == entityplayer || entity.tracker != null && entity.tracker.trackedPlayers.contains(entityplayer); -+ } -+ private void updatePassengers(EntityPlayer player) { -+ if (tracker.isVehicle()) { -+ tracker.passengers.forEach((e) -> { -+ if (e.tracker != null) { -+ e.tracker.updatePlayer(player); -+ } -+ }); -+ player.playerConnection.sendPacket(new PacketPlayOutMount(this.tracker)); -+ } -+ } -+ private boolean isInRangeOfPlayer(EntityPlayer entityplayer) { -+ // Paper end - double d0 = entityplayer.locX - (double) this.xLoc / 4096.0D; - double d1 = entityplayer.locZ - (double) this.zLoc / 4096.0D; - int i = Math.min(this.e, this.f); -@@ -593,6 +636,7 @@ public class EntityTrackerEntry { - this.trackedPlayers.remove(entityplayer); - this.tracker.c(entityplayer); - entityplayer.c(this.tracker); -+ updatePassengers(entityplayer); // Paper - } - - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0131-Do-not-mark-chunks-as-active-for-neighbor-updates.patch b/Spigot-Server-Patches/0131-Do-not-mark-chunks-as-active-for-neighbor-updates.patch new file mode 100644 index 0000000000..6d69b6cde3 --- /dev/null +++ b/Spigot-Server-Patches/0131-Do-not-mark-chunks-as-active-for-neighbor-updates.patch @@ -0,0 +1,48 @@ +From b45938c5752cc909b6cb49cef6768cda18a5788c Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 12 May 2016 01:55:17 -0400 +Subject: [PATCH] Do not mark chunks as active for neighbor updates + +Fixes chunk unload issues + +diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java +index a6cf1d83d..3db29161d 100644 +--- a/src/main/java/net/minecraft/server/Chunk.java ++++ b/src/main/java/net/minecraft/server/Chunk.java +@@ -1004,25 +1004,25 @@ public class Chunk { + // CraftBukkit end + world.timings.syncChunkLoadPostTimer.stopTiming(); // Paper + world.timings.syncChunkLoadPopulateNeighbors.startTiming(); // Paper +- Chunk chunk = ichunkprovider.getLoadedChunkAt(this.locX, this.locZ - 1); +- Chunk chunk1 = ichunkprovider.getLoadedChunkAt(this.locX + 1, this.locZ); +- Chunk chunk2 = ichunkprovider.getLoadedChunkAt(this.locX, this.locZ + 1); +- Chunk chunk3 = ichunkprovider.getLoadedChunkAt(this.locX - 1, this.locZ); ++ Chunk chunk = MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX, this.locZ - 1); // Paper ++ Chunk chunk1 = MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX + 1, this.locZ); // Paper ++ Chunk chunk2 = MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX, this.locZ + 1); // Paper ++ Chunk chunk3 = MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX - 1, this.locZ); // Paper + +- if (chunk1 != null && chunk2 != null && ichunkprovider.getLoadedChunkAt(this.locX + 1, this.locZ + 1) != null) { ++ if (chunk1 != null && chunk2 != null && MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX + 1, this.locZ + 1) != null) { // Paper + this.a(chunkgenerator); + } + +- if (chunk3 != null && chunk2 != null && ichunkprovider.getLoadedChunkAt(this.locX - 1, this.locZ + 1) != null) { ++ if (chunk3 != null && chunk2 != null && MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX - 1, this.locZ + 1) != null) { // Paper + chunk3.a(chunkgenerator); + } + +- if (chunk != null && chunk1 != null && ichunkprovider.getLoadedChunkAt(this.locX + 1, this.locZ - 1) != null) { ++ if (chunk != null && chunk1 != null && MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX + 1, this.locZ - 1) != null) { // Paper + chunk.a(chunkgenerator); + } + + if (chunk != null && chunk3 != null) { +- Chunk chunk4 = ichunkprovider.getLoadedChunkAt(this.locX - 1, this.locZ - 1); ++ Chunk chunk4 = MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX - 1, this.locZ - 1); // Paper + + if (chunk4 != null) { + chunk4.a(chunkgenerator); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0131-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch b/Spigot-Server-Patches/0131-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch deleted file mode 100644 index 91db886b86..0000000000 --- a/Spigot-Server-Patches/0131-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch +++ /dev/null @@ -1,35 +0,0 @@ -From c08c205ecb62164eb4e00f5356319ced19481ab3 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 710c432d8..e009e5cf2 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -230,4 +230,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/server/PersistentScoreboard.java b/src/main/java/net/minecraft/server/PersistentScoreboard.java -index 230004b4a..62752f816 100644 ---- a/src/main/java/net/minecraft/server/PersistentScoreboard.java -+++ b/src/main/java/net/minecraft/server/PersistentScoreboard.java -@@ -184,6 +184,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()); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0132-Do-not-mark-chunks-as-active-for-neighbor-updates.patch b/Spigot-Server-Patches/0132-Do-not-mark-chunks-as-active-for-neighbor-updates.patch deleted file mode 100644 index c1b64592a8..0000000000 --- a/Spigot-Server-Patches/0132-Do-not-mark-chunks-as-active-for-neighbor-updates.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 540962bdce2796a369838635bbb1f15eafeb414c Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 12 May 2016 01:55:17 -0400 -Subject: [PATCH] Do not mark chunks as active for neighbor updates - -Fixes chunk unload issues - -diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java -index a6cf1d83d..3db29161d 100644 ---- a/src/main/java/net/minecraft/server/Chunk.java -+++ b/src/main/java/net/minecraft/server/Chunk.java -@@ -1004,25 +1004,25 @@ public class Chunk { - // CraftBukkit end - world.timings.syncChunkLoadPostTimer.stopTiming(); // Paper - world.timings.syncChunkLoadPopulateNeighbors.startTiming(); // Paper -- Chunk chunk = ichunkprovider.getLoadedChunkAt(this.locX, this.locZ - 1); -- Chunk chunk1 = ichunkprovider.getLoadedChunkAt(this.locX + 1, this.locZ); -- Chunk chunk2 = ichunkprovider.getLoadedChunkAt(this.locX, this.locZ + 1); -- Chunk chunk3 = ichunkprovider.getLoadedChunkAt(this.locX - 1, this.locZ); -+ Chunk chunk = MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX, this.locZ - 1); // Paper -+ Chunk chunk1 = MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX + 1, this.locZ); // Paper -+ Chunk chunk2 = MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX, this.locZ + 1); // Paper -+ Chunk chunk3 = MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX - 1, this.locZ); // Paper - -- if (chunk1 != null && chunk2 != null && ichunkprovider.getLoadedChunkAt(this.locX + 1, this.locZ + 1) != null) { -+ if (chunk1 != null && chunk2 != null && MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX + 1, this.locZ + 1) != null) { // Paper - this.a(chunkgenerator); - } - -- if (chunk3 != null && chunk2 != null && ichunkprovider.getLoadedChunkAt(this.locX - 1, this.locZ + 1) != null) { -+ if (chunk3 != null && chunk2 != null && MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX - 1, this.locZ + 1) != null) { // Paper - chunk3.a(chunkgenerator); - } - -- if (chunk != null && chunk1 != null && ichunkprovider.getLoadedChunkAt(this.locX + 1, this.locZ - 1) != null) { -+ if (chunk != null && chunk1 != null && MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX + 1, this.locZ - 1) != null) { // Paper - chunk.a(chunkgenerator); - } - - if (chunk != null && chunk3 != null) { -- Chunk chunk4 = ichunkprovider.getLoadedChunkAt(this.locX - 1, this.locZ - 1); -+ Chunk chunk4 = MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX - 1, this.locZ - 1); // Paper - - if (chunk4 != null) { - chunk4.a(chunkgenerator); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0132-Fix-Chunk-Unload-Queue-Issues.patch b/Spigot-Server-Patches/0132-Fix-Chunk-Unload-Queue-Issues.patch new file mode 100644 index 0000000000..c67db5d1ac --- /dev/null +++ b/Spigot-Server-Patches/0132-Fix-Chunk-Unload-Queue-Issues.patch @@ -0,0 +1,38 @@ +From 2f0e1a92eb0215f3ea7481cc54eeaf6b8ba23cac Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 12 May 2016 02:03:56 -0400 +Subject: [PATCH] Fix Chunk Unload Queue Issues + +Vanilla implemented similar logic as Paper had pre 1.9.4, but Spigot +has not resolved all the bugs with the changes. + +This patch fixes known issues and really should be applied by Spigot team. + +diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java +index 3db29161d..98f2cff15 100644 +--- a/src/main/java/net/minecraft/server/Chunk.java ++++ b/src/main/java/net/minecraft/server/Chunk.java +@@ -46,7 +46,7 @@ public class Chunk { + private long w; + private int x; + private final ConcurrentLinkedQueue y; +- public boolean d; ++ public boolean d; public void setShouldUnload(boolean unload) { this.d = unload; } public boolean isUnloading() { return d; } // Paper - OBFHELPER + protected gnu.trove.map.hash.TObjectIntHashMap entityCount = new gnu.trove.map.hash.TObjectIntHashMap(); // Spigot + + // Paper start +diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java +index dd37bec73..eb3225ef2 100644 +--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java +@@ -299,6 +299,7 @@ public class ChunkProviderServer implements IChunkProvider { + + if (chunk != null && chunk.d) { + // CraftBukkit start - move unload logic to own method ++ chunk.setShouldUnload(false); // Paper + if (!unloadChunk(chunk, true)) { + continue; + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0133-Fix-Chunk-Unload-Queue-Issues.patch b/Spigot-Server-Patches/0133-Fix-Chunk-Unload-Queue-Issues.patch deleted file mode 100644 index e69374207b..0000000000 --- a/Spigot-Server-Patches/0133-Fix-Chunk-Unload-Queue-Issues.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 9e02e7677c27c8b05f69b00620f98b3f6a583e31 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 12 May 2016 02:03:56 -0400 -Subject: [PATCH] Fix Chunk Unload Queue Issues - -Vanilla implemented similar logic as Paper had pre 1.9.4, but Spigot -has not resolved all the bugs with the changes. - -This patch fixes known issues and really should be applied by Spigot team. - -diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java -index 3db29161d..98f2cff15 100644 ---- a/src/main/java/net/minecraft/server/Chunk.java -+++ b/src/main/java/net/minecraft/server/Chunk.java -@@ -46,7 +46,7 @@ public class Chunk { - private long w; - private int x; - private final ConcurrentLinkedQueue y; -- public boolean d; -+ public boolean d; public void setShouldUnload(boolean unload) { this.d = unload; } public boolean isUnloading() { return d; } // Paper - OBFHELPER - protected gnu.trove.map.hash.TObjectIntHashMap entityCount = new gnu.trove.map.hash.TObjectIntHashMap(); // Spigot - - // Paper start -diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java -index 54b454fe3..57ae50d2e 100644 ---- a/src/main/java/net/minecraft/server/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java -@@ -299,6 +299,7 @@ public class ChunkProviderServer implements IChunkProvider { - - if (chunk != null && chunk.d) { - // CraftBukkit start - move unload logic to own method -+ chunk.setShouldUnload(false); // Paper - if (!unloadChunk(chunk, true)) { - continue; - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0133-System-property-for-disabling-watchdoge.patch b/Spigot-Server-Patches/0133-System-property-for-disabling-watchdoge.patch new file mode 100644 index 0000000000..0b88f39dc8 --- /dev/null +++ b/Spigot-Server-Patches/0133-System-property-for-disabling-watchdoge.patch @@ -0,0 +1,22 @@ +From 16152841f16f55980d1d9ed723c60c33832f64c0 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 6384d50e7..cb1fcf0f4 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -52,7 +52,7 @@ public class WatchdogThread extends Thread + while ( !stopping ) + { + // +- if ( lastTick != 0 && System.currentTimeMillis() > lastTick + timeoutTime ) ++ if ( lastTick != 0 && System.currentTimeMillis() > lastTick + timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable + { + Logger log = Bukkit.getServer().getLogger(); + log.log( Level.SEVERE, "The server has stopped responding!" ); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0134-Optimize-EAR.patch b/Spigot-Server-Patches/0134-Optimize-EAR.patch new file mode 100644 index 0000000000..654afa58e1 --- /dev/null +++ b/Spigot-Server-Patches/0134-Optimize-EAR.patch @@ -0,0 +1,69 @@ +From a5d200f5f9ac0a6be1c90e383adeadc8b151e34a Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 13 May 2016 01:38:06 -0400 +Subject: [PATCH] Optimize EAR + + +diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java +index c411ce886..c8a6ff3d4 100644 +--- a/src/main/java/org/spigotmc/ActivationRange.java ++++ b/src/main/java/org/spigotmc/ActivationRange.java +@@ -2,6 +2,8 @@ package org.spigotmc; + + import java.util.List; + import java.util.Set; ++ ++import co.aikar.timings.MinecraftTimings; + import net.minecraft.server.AxisAlignedBB; + import net.minecraft.server.Chunk; + import net.minecraft.server.Entity; +@@ -13,7 +15,7 @@ import net.minecraft.server.EntityCreature; + import net.minecraft.server.EntityCreeper; + import net.minecraft.server.EntityEnderCrystal; + import net.minecraft.server.EntityEnderDragon; +-import net.minecraft.server.EntityFallingBlock; // Paper ++import net.minecraft.server.EntityFallingBlock; + import net.minecraft.server.EntityFireball; + import net.minecraft.server.EntityFireworks; + import net.minecraft.server.EntityHuman; +@@ -21,16 +23,15 @@ import net.minecraft.server.EntityLiving; + import net.minecraft.server.EntityMonster; + import net.minecraft.server.EntityProjectile; + import net.minecraft.server.EntitySheep; +-import net.minecraft.server.EntitySlice; + import net.minecraft.server.EntitySlime; + import net.minecraft.server.EntityTNTPrimed; + import net.minecraft.server.EntityVillager; + import net.minecraft.server.EntityWeather; + import net.minecraft.server.EntityWither; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MathHelper; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.World; +-import co.aikar.timings.MinecraftTimings; + + public class ActivationRange + { +@@ -108,6 +109,7 @@ public class ActivationRange + maxRange = Math.max( maxRange, miscActivationRange ); + maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); + ++ Chunk chunk; // Paper + for ( EntityHuman player : world.players ) + { + +@@ -126,9 +128,9 @@ public class ActivationRange + { + for ( int j1 = k; j1 <= l; ++j1 ) + { +- if ( world.getWorld().isChunkLoaded( i1, j1 ) ) ++ if ( (chunk = MCUtil.getLoadedChunkWithoutMarkingActive(world, i1, j1 )) != null ) // Paper + { +- activateChunkEntities( world.getChunkAt( i1, j1 ) ); ++ activateChunkEntities( chunk ); // Paper + } + } + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0134-System-property-for-disabling-watchdoge.patch b/Spigot-Server-Patches/0134-System-property-for-disabling-watchdoge.patch deleted file mode 100644 index ae5f115c6a..0000000000 --- a/Spigot-Server-Patches/0134-System-property-for-disabling-watchdoge.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 922d126f9e81684c5ca795fbbf67a7c38aaf1c18 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 6384d50e7..cb1fcf0f4 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -52,7 +52,7 @@ public class WatchdogThread extends Thread - while ( !stopping ) - { - // -- if ( lastTick != 0 && System.currentTimeMillis() > lastTick + timeoutTime ) -+ if ( lastTick != 0 && System.currentTimeMillis() > lastTick + timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable - { - Logger log = Bukkit.getServer().getLogger(); - log.log( Level.SEVERE, "The server has stopped responding!" ); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0135-Optimize-EAR.patch b/Spigot-Server-Patches/0135-Optimize-EAR.patch deleted file mode 100644 index e1e4c93b19..0000000000 --- a/Spigot-Server-Patches/0135-Optimize-EAR.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 1dc6b412b3e0bed7ef8c58885a37931bd3467f06 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 13 May 2016 01:38:06 -0400 -Subject: [PATCH] Optimize EAR - - -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index c411ce886..c8a6ff3d4 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -2,6 +2,8 @@ package org.spigotmc; - - import java.util.List; - import java.util.Set; -+ -+import co.aikar.timings.MinecraftTimings; - import net.minecraft.server.AxisAlignedBB; - import net.minecraft.server.Chunk; - import net.minecraft.server.Entity; -@@ -13,7 +15,7 @@ import net.minecraft.server.EntityCreature; - import net.minecraft.server.EntityCreeper; - import net.minecraft.server.EntityEnderCrystal; - import net.minecraft.server.EntityEnderDragon; --import net.minecraft.server.EntityFallingBlock; // Paper -+import net.minecraft.server.EntityFallingBlock; - import net.minecraft.server.EntityFireball; - import net.minecraft.server.EntityFireworks; - import net.minecraft.server.EntityHuman; -@@ -21,16 +23,15 @@ import net.minecraft.server.EntityLiving; - import net.minecraft.server.EntityMonster; - import net.minecraft.server.EntityProjectile; - import net.minecraft.server.EntitySheep; --import net.minecraft.server.EntitySlice; - import net.minecraft.server.EntitySlime; - import net.minecraft.server.EntityTNTPrimed; - import net.minecraft.server.EntityVillager; - import net.minecraft.server.EntityWeather; - import net.minecraft.server.EntityWither; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MathHelper; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.World; --import co.aikar.timings.MinecraftTimings; - - public class ActivationRange - { -@@ -108,6 +109,7 @@ public class ActivationRange - maxRange = Math.max( maxRange, miscActivationRange ); - maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); - -+ Chunk chunk; // Paper - for ( EntityHuman player : world.players ) - { - -@@ -126,9 +128,9 @@ public class ActivationRange - { - for ( int j1 = k; j1 <= l; ++j1 ) - { -- if ( world.getWorld().isChunkLoaded( i1, j1 ) ) -+ if ( (chunk = MCUtil.getLoadedChunkWithoutMarkingActive(world, i1, j1 )) != null ) // Paper - { -- activateChunkEntities( world.getChunkAt( i1, j1 ) ); -+ activateChunkEntities( chunk ); // Paper - } - } - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0135-Optimize-UserCache-Thread-Safe.patch b/Spigot-Server-Patches/0135-Optimize-UserCache-Thread-Safe.patch new file mode 100644 index 0000000000..9097c497ae --- /dev/null +++ b/Spigot-Server-Patches/0135-Optimize-UserCache-Thread-Safe.patch @@ -0,0 +1,100 @@ +From f8298bd0e0b7b50c1e71d97df928320f537323e6 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 83b62da55..2349c3ade 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -527,7 +527,7 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs + // Spigot start + if (org.spigotmc.SpigotConfig.saveUserCacheOnStopOnly) { + LOGGER.info("Saving usercache.json"); +- this.Y.c(); ++ this.Y.c(false); // Paper + } + // Spigot end + } +diff --git a/src/main/java/net/minecraft/server/UserCache.java b/src/main/java/net/minecraft/server/UserCache.java +index ccfc755d2..989758cdf 100644 +--- a/src/main/java/net/minecraft/server/UserCache.java ++++ b/src/main/java/net/minecraft/server/UserCache.java +@@ -108,7 +108,7 @@ public class UserCache { + this.a(gameprofile, (Date) null); + } + +- private void a(GameProfile gameprofile, Date date) { ++ private synchronized void a(GameProfile gameprofile, Date date) { // Paper - synchronize + UUID uuid = gameprofile.getId(); + + if (date == null) { +@@ -122,8 +122,9 @@ public class UserCache { + String s = gameprofile.getName().toLowerCase(Locale.ROOT); + UserCache.UserCacheEntry usercache_usercacheentry = new UserCache.UserCacheEntry(gameprofile, date, null); + +- if (this.e.containsKey(uuid)) { ++ //if (this.e.containsKey(uuid)) { // Paper + UserCache.UserCacheEntry usercache_usercacheentry1 = (UserCache.UserCacheEntry) this.e.get(uuid); ++ if (usercache_usercacheentry1 != null) { // Paper + + this.d.remove(usercache_usercacheentry1.a().getName().toLowerCase(Locale.ROOT)); + this.f.remove(gameprofile); +@@ -136,7 +137,7 @@ public class UserCache { + } + + @Nullable +- public GameProfile getProfile(String s) { ++ public synchronized GameProfile getProfile(String s) { // Paper - synchronize + String s1 = s.toLowerCase(Locale.ROOT); + UserCache.UserCacheEntry usercache_usercacheentry = (UserCache.UserCacheEntry) this.d.get(s1); + +@@ -165,7 +166,7 @@ public class UserCache { + return usercache_usercacheentry == null ? null : usercache_usercacheentry.a(); + } + +- public String[] a() { ++ public synchronized String[] a() { // Paper - synchronize + ArrayList arraylist = Lists.newArrayList(this.d.keySet()); + + return (String[]) arraylist.toArray(new String[arraylist.size()]); +@@ -227,8 +228,15 @@ public class UserCache { + + } + ++ // Paper start + public void c() { ++ c(true); ++ } ++ public void c(boolean asyncSave) { ++ // Paper end + String s = this.b.toJson(this.a(org.spigotmc.SpigotConfig.userCacheCap)); ++ Runnable save = () -> { ++ + BufferedWriter bufferedwriter = null; + + try { +@@ -242,6 +250,14 @@ public class UserCache { + } finally { + IOUtils.closeQuietly(bufferedwriter); + } ++ // Paper start ++ }; ++ if (asyncSave) { ++ MCUtil.scheduleAsyncTask(save); ++ } else { ++ save.run(); ++ } ++ // Paper end + + } + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0136-Avoid-blocking-on-Network-Manager-creation.patch b/Spigot-Server-Patches/0136-Avoid-blocking-on-Network-Manager-creation.patch new file mode 100644 index 0000000000..2318b30dd6 --- /dev/null +++ b/Spigot-Server-Patches/0136-Avoid-blocking-on-Network-Manager-creation.patch @@ -0,0 +1,47 @@ +From fe563a5eab9483cb69f2b7bfc2c750fafe263b50 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/ServerConnection.java b/src/main/java/net/minecraft/server/ServerConnection.java +index 6a71ebbd2..faf7b60af 100644 +--- a/src/main/java/net/minecraft/server/ServerConnection.java ++++ b/src/main/java/net/minecraft/server/ServerConnection.java +@@ -60,6 +60,15 @@ public class ServerConnection { + public volatile boolean d; + private final List g = Collections.synchronizedList(Lists.newArrayList()); + private final List h = Collections.synchronizedList(Lists.newArrayList()); ++ // Paper start - prevent blocking on adding a new network manager while the server is ticking ++ private final List pending = Collections.synchronizedList(Lists.newArrayList()); ++ private void addPending() { ++ synchronized (pending) { ++ this.h.addAll(pending); // Paper - OBFHELPER - List of network managers ++ pending.clear(); ++ } ++ } ++ // Paper end + + public ServerConnection(MinecraftServer minecraftserver) { + this.f = minecraftserver; +@@ -94,7 +103,7 @@ public class ServerConnection { + 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)); + NetworkManager networkmanager = new NetworkManager(EnumProtocolDirection.SERVERBOUND); + +- ServerConnection.this.h.add(networkmanager); ++ pending.add(networkmanager); // Paper + channel.pipeline().addLast("packet_handler", networkmanager); + networkmanager.setPacketListener(new HandshakeListener(ServerConnection.this.f, networkmanager)); + } +@@ -123,6 +132,7 @@ public class ServerConnection { + + synchronized (this.h) { + // Spigot Start ++ 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 ) + { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0136-Optimize-UserCache-Thread-Safe.patch b/Spigot-Server-Patches/0136-Optimize-UserCache-Thread-Safe.patch deleted file mode 100644 index df0e2f3bd8..0000000000 --- a/Spigot-Server-Patches/0136-Optimize-UserCache-Thread-Safe.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 9541bcf765a36a89596125b143980a9565b96454 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 83b62da55..2349c3ade 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -527,7 +527,7 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs - // Spigot start - if (org.spigotmc.SpigotConfig.saveUserCacheOnStopOnly) { - LOGGER.info("Saving usercache.json"); -- this.Y.c(); -+ this.Y.c(false); // Paper - } - // Spigot end - } -diff --git a/src/main/java/net/minecraft/server/UserCache.java b/src/main/java/net/minecraft/server/UserCache.java -index ccfc755d2..989758cdf 100644 ---- a/src/main/java/net/minecraft/server/UserCache.java -+++ b/src/main/java/net/minecraft/server/UserCache.java -@@ -108,7 +108,7 @@ public class UserCache { - this.a(gameprofile, (Date) null); - } - -- private void a(GameProfile gameprofile, Date date) { -+ private synchronized void a(GameProfile gameprofile, Date date) { // Paper - synchronize - UUID uuid = gameprofile.getId(); - - if (date == null) { -@@ -122,8 +122,9 @@ public class UserCache { - String s = gameprofile.getName().toLowerCase(Locale.ROOT); - UserCache.UserCacheEntry usercache_usercacheentry = new UserCache.UserCacheEntry(gameprofile, date, null); - -- if (this.e.containsKey(uuid)) { -+ //if (this.e.containsKey(uuid)) { // Paper - UserCache.UserCacheEntry usercache_usercacheentry1 = (UserCache.UserCacheEntry) this.e.get(uuid); -+ if (usercache_usercacheentry1 != null) { // Paper - - this.d.remove(usercache_usercacheentry1.a().getName().toLowerCase(Locale.ROOT)); - this.f.remove(gameprofile); -@@ -136,7 +137,7 @@ public class UserCache { - } - - @Nullable -- public GameProfile getProfile(String s) { -+ public synchronized GameProfile getProfile(String s) { // Paper - synchronize - String s1 = s.toLowerCase(Locale.ROOT); - UserCache.UserCacheEntry usercache_usercacheentry = (UserCache.UserCacheEntry) this.d.get(s1); - -@@ -165,7 +166,7 @@ public class UserCache { - return usercache_usercacheentry == null ? null : usercache_usercacheentry.a(); - } - -- public String[] a() { -+ public synchronized String[] a() { // Paper - synchronize - ArrayList arraylist = Lists.newArrayList(this.d.keySet()); - - return (String[]) arraylist.toArray(new String[arraylist.size()]); -@@ -227,8 +228,15 @@ public class UserCache { - - } - -+ // Paper start - public void c() { -+ c(true); -+ } -+ public void c(boolean asyncSave) { -+ // Paper end - String s = this.b.toJson(this.a(org.spigotmc.SpigotConfig.userCacheCap)); -+ Runnable save = () -> { -+ - BufferedWriter bufferedwriter = null; - - try { -@@ -242,6 +250,14 @@ public class UserCache { - } finally { - IOUtils.closeQuietly(bufferedwriter); - } -+ // Paper start -+ }; -+ if (asyncSave) { -+ MCUtil.scheduleAsyncTask(save); -+ } else { -+ save.run(); -+ } -+ // Paper end - - } - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0137-Avoid-blocking-on-Network-Manager-creation.patch b/Spigot-Server-Patches/0137-Avoid-blocking-on-Network-Manager-creation.patch deleted file mode 100644 index 07c5715db9..0000000000 --- a/Spigot-Server-Patches/0137-Avoid-blocking-on-Network-Manager-creation.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 65e18c08092da1309dc93d0853d3e80e10395ea8 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/ServerConnection.java b/src/main/java/net/minecraft/server/ServerConnection.java -index 6a71ebbd2..faf7b60af 100644 ---- a/src/main/java/net/minecraft/server/ServerConnection.java -+++ b/src/main/java/net/minecraft/server/ServerConnection.java -@@ -60,6 +60,15 @@ public class ServerConnection { - public volatile boolean d; - private final List g = Collections.synchronizedList(Lists.newArrayList()); - private final List h = Collections.synchronizedList(Lists.newArrayList()); -+ // Paper start - prevent blocking on adding a new network manager while the server is ticking -+ private final List pending = Collections.synchronizedList(Lists.newArrayList()); -+ private void addPending() { -+ synchronized (pending) { -+ this.h.addAll(pending); // Paper - OBFHELPER - List of network managers -+ pending.clear(); -+ } -+ } -+ // Paper end - - public ServerConnection(MinecraftServer minecraftserver) { - this.f = minecraftserver; -@@ -94,7 +103,7 @@ public class ServerConnection { - 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)); - NetworkManager networkmanager = new NetworkManager(EnumProtocolDirection.SERVERBOUND); - -- ServerConnection.this.h.add(networkmanager); -+ pending.add(networkmanager); // Paper - channel.pipeline().addLast("packet_handler", networkmanager); - networkmanager.setPacketListener(new HandshakeListener(ServerConnection.this.f, networkmanager)); - } -@@ -123,6 +132,7 @@ public class ServerConnection { - - synchronized (this.h) { - // Spigot Start -+ 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 ) - { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0137-Optional-old-TNT-cannon-behaviors.patch b/Spigot-Server-Patches/0137-Optional-old-TNT-cannon-behaviors.patch new file mode 100644 index 0000000000..1c9579533b --- /dev/null +++ b/Spigot-Server-Patches/0137-Optional-old-TNT-cannon-behaviors.patch @@ -0,0 +1,393 @@ +From 4570a07bfc85628581dfb4338637c0264f34df85 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sun, 22 May 2016 20:20:55 -0500 +Subject: [PATCH] Optional old TNT cannon behaviors + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index fbe769eb3..c4acb7597 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -327,4 +327,12 @@ public class PaperWorldConfig { + ); + } + } ++ ++ public boolean oldCannonBehaviors; ++ private void oldCannonBehaviors() { ++ oldCannonBehaviors = getBoolean("enable-old-tnt-cannon-behaviors", false); ++ if (oldCannonBehaviors) { ++ log("Old Cannon Behaviors: This feature may not be working entirely properly at the moment"); ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/server/BlockDiodeAbstract.java b/src/main/java/net/minecraft/server/BlockDiodeAbstract.java +index 59ee13de8..40c9f18bf 100644 +--- a/src/main/java/net/minecraft/server/BlockDiodeAbstract.java ++++ b/src/main/java/net/minecraft/server/BlockDiodeAbstract.java +@@ -76,6 +76,17 @@ public abstract class BlockDiodeAbstract extends BlockFacingHorizontal { + } else { + this.b(world, blockposition, iblockdata, 0); + world.setAir(blockposition); ++ // Paper start - Old TNT cannon behaviors ++ if (world.paperConfig.oldCannonBehaviors) { ++ world.applyPhysics(blockposition.shift(EnumDirection.EAST), this, false); ++ world.applyPhysics(blockposition.shift(EnumDirection.WEST), this, false); ++ world.applyPhysics(blockposition.shift(EnumDirection.SOUTH), this, false); ++ world.applyPhysics(blockposition.shift(EnumDirection.NORTH), this, false); ++ world.applyPhysics(blockposition.shift(EnumDirection.DOWN), this, false); ++ world.applyPhysics(blockposition.shift(EnumDirection.UP), this, false); ++ return; ++ } ++ // Paper end + EnumDirection[] aenumdirection = EnumDirection.values(); + int i = aenumdirection.length; + +@@ -173,6 +184,17 @@ public abstract class BlockDiodeAbstract extends BlockFacingHorizontal { + + public void postBreak(World world, BlockPosition blockposition, IBlockData iblockdata) { + if (this.d) { ++ // Paper start - Old TNT cannon behaviors ++ if (world.paperConfig.oldCannonBehaviors) { ++ world.applyPhysics(blockposition.shift(EnumDirection.EAST), this, false); ++ world.applyPhysics(blockposition.shift(EnumDirection.WEST), this, false); ++ world.applyPhysics(blockposition.shift(EnumDirection.NORTH), this, false); ++ world.applyPhysics(blockposition.shift(EnumDirection.SOUTH), this, false); ++ world.applyPhysics(blockposition.shift(EnumDirection.DOWN), this, false); ++ world.applyPhysics(blockposition.shift(EnumDirection.UP), this, false); ++ return; ++ } ++ // Paper end + EnumDirection[] aenumdirection = EnumDirection.values(); + int i = aenumdirection.length; + +diff --git a/src/main/java/net/minecraft/server/BlockRedstoneTorch.java b/src/main/java/net/minecraft/server/BlockRedstoneTorch.java +index c7e095a11..741236289 100644 +--- a/src/main/java/net/minecraft/server/BlockRedstoneTorch.java ++++ b/src/main/java/net/minecraft/server/BlockRedstoneTorch.java +@@ -52,6 +52,12 @@ public class BlockRedstoneTorch extends BlockTorch { + + public void onPlace(World world, BlockPosition blockposition, IBlockData iblockdata) { + if (this.isOn) { ++ // Paper start - Old TNT cannon behaviors ++ if (world.paperConfig.oldCannonBehaviors) { ++ this.shiftPositions(world, blockposition); ++ return; ++ } ++ // Paper end + EnumDirection[] aenumdirection = EnumDirection.values(); + int i = aenumdirection.length; + +@@ -66,6 +72,12 @@ public class BlockRedstoneTorch extends BlockTorch { + + public void remove(World world, BlockPosition blockposition, IBlockData iblockdata) { + if (this.isOn) { ++ // Paper start - Old TNT cannon behaviors ++ if (world.paperConfig.oldCannonBehaviors) { ++ this.shiftPositions(world, blockposition); ++ return; ++ } ++ // Paper end + EnumDirection[] aenumdirection = EnumDirection.values(); + int i = aenumdirection.length; + +@@ -78,6 +90,17 @@ public class BlockRedstoneTorch extends BlockTorch { + + } + ++ // Paper start - Old TNT cannon behaviors ++ private void shiftPositions(World world, BlockPosition blockposition) { ++ world.applyPhysics(blockposition.shift(EnumDirection.DOWN), this, false); ++ world.applyPhysics(blockposition.shift(EnumDirection.UP), this, false); ++ world.applyPhysics(blockposition.shift(EnumDirection.WEST), this, false); ++ world.applyPhysics(blockposition.shift(EnumDirection.EAST), this, false); ++ world.applyPhysics(blockposition.shift(EnumDirection.SOUTH), this, false); ++ world.applyPhysics(blockposition.shift(EnumDirection.NORTH), this, false); ++ } ++ // Paper end ++ + public int b(IBlockData iblockdata, IBlockAccess iblockaccess, BlockPosition blockposition, EnumDirection enumdirection) { + return this.isOn && iblockdata.get(BlockRedstoneTorch.FACING) != enumdirection ? 15 : 0; + } +diff --git a/src/main/java/net/minecraft/server/BlockRedstoneWire.java b/src/main/java/net/minecraft/server/BlockRedstoneWire.java +index 5a0f026b1..20b9465e7 100644 +--- a/src/main/java/net/minecraft/server/BlockRedstoneWire.java ++++ b/src/main/java/net/minecraft/server/BlockRedstoneWire.java +@@ -20,7 +20,7 @@ public class BlockRedstoneWire extends Block { + public static final BlockStateInteger POWER = BlockStateInteger.of("power", 0, 15); + protected static final AxisAlignedBB[] f = new AxisAlignedBB[] { new AxisAlignedBB(0.1875D, 0.0D, 0.1875D, 0.8125D, 0.0625D, 0.8125D), new AxisAlignedBB(0.1875D, 0.0D, 0.1875D, 0.8125D, 0.0625D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.1875D, 0.8125D, 0.0625D, 0.8125D), new AxisAlignedBB(0.0D, 0.0D, 0.1875D, 0.8125D, 0.0625D, 1.0D), new AxisAlignedBB(0.1875D, 0.0D, 0.0D, 0.8125D, 0.0625D, 0.8125D), new AxisAlignedBB(0.1875D, 0.0D, 0.0D, 0.8125D, 0.0625D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 0.8125D, 0.0625D, 0.8125D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 0.8125D, 0.0625D, 1.0D), new AxisAlignedBB(0.1875D, 0.0D, 0.1875D, 1.0D, 0.0625D, 0.8125D), new AxisAlignedBB(0.1875D, 0.0D, 0.1875D, 1.0D, 0.0625D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.1875D, 1.0D, 0.0625D, 0.8125D), new AxisAlignedBB(0.0D, 0.0D, 0.1875D, 1.0D, 0.0625D, 1.0D), new AxisAlignedBB(0.1875D, 0.0D, 0.0D, 1.0D, 0.0625D, 0.8125D), new AxisAlignedBB(0.1875D, 0.0D, 0.0D, 1.0D, 0.0625D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.0625D, 0.8125D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.0625D, 1.0D)}; + private boolean g = true; +- private final Set B = Sets.newHashSet(); ++ private final Set B = Sets.newHashSet(); private final Set blocksToUpdate = B; // Paper - OBFHELPER + + public BlockRedstoneWire() { + super(Material.ORIENTABLE); +@@ -186,6 +186,19 @@ public class BlockRedstoneWire extends Block { + } + + this.B.add(blockposition); ++ // Paper start - Old TNT cannon behaviors ++ if (world.paperConfig.oldCannonBehaviors) { ++ this.blocksToUpdate.add(blockposition.shift(EnumDirection.WEST)); ++ this.blocksToUpdate.add(blockposition.shift(EnumDirection.EAST)); ++ this.blocksToUpdate.add(blockposition.shift(EnumDirection.DOWN)); ++ this.blocksToUpdate.add(blockposition.shift(EnumDirection.UP)); ++ this.blocksToUpdate.add(blockposition.shift(EnumDirection.NORTH)); ++ this.blocksToUpdate.add(blockposition.shift(EnumDirection.SOUTH)); ++ return iblockdata; ++ } ++ // Paper end ++ ++ + EnumDirection[] aenumdirection = EnumDirection.values(); + int i1 = aenumdirection.length; + +@@ -202,6 +215,16 @@ public class BlockRedstoneWire extends Block { + private void b(World world, BlockPosition blockposition) { + if (world.getType(blockposition).getBlock() == this) { + world.applyPhysics(blockposition, this, false); ++ if (world.paperConfig.oldCannonBehaviors) { ++ world.applyPhysics(blockposition.shift(EnumDirection.WEST), this, false); ++ world.applyPhysics(blockposition.shift(EnumDirection.EAST), this, false); ++ world.applyPhysics(blockposition.shift(EnumDirection.NORTH), this, false); ++ world.applyPhysics(blockposition.shift(EnumDirection.SOUTH), this, false); ++ world.applyPhysics(blockposition.shift(EnumDirection.DOWN), this, false); ++ world.applyPhysics(blockposition.shift(EnumDirection.UP), this, false); ++ return; ++ } ++ // Paper end + EnumDirection[] aenumdirection = EnumDirection.values(); + int i = aenumdirection.length; + +diff --git a/src/main/java/net/minecraft/server/BlockTNT.java b/src/main/java/net/minecraft/server/BlockTNT.java +index 6b6aa892a..5cec4160c 100644 +--- a/src/main/java/net/minecraft/server/BlockTNT.java ++++ b/src/main/java/net/minecraft/server/BlockTNT.java +@@ -29,7 +29,11 @@ public class BlockTNT extends Block { + + public void wasExploded(World world, BlockPosition blockposition, Explosion explosion) { + if (!world.isClientSide) { +- EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(world, (double) ((float) blockposition.getX() + 0.5F), (double) blockposition.getY(), (double) ((float) blockposition.getZ() + 0.5F), explosion.getSource()); ++ // Paper start - Old TNT cannon behaviors ++ double y = blockposition.getY(); ++ if (!world.paperConfig.oldCannonBehaviors) y += 0.5; ++ EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(world, (double) ((float) blockposition.getX() + 0.5F), y, (double) ((float) blockposition.getZ() + 0.5F), explosion.getSource()); ++ // Paper end + + entitytntprimed.setFuseTicks((short) (world.random.nextInt(entitytntprimed.getFuseTicks() / 4) + entitytntprimed.getFuseTicks() / 8)); + world.addEntity(entitytntprimed); +@@ -43,7 +47,11 @@ public class BlockTNT extends Block { + public void a(World world, BlockPosition blockposition, IBlockData iblockdata, EntityLiving entityliving) { + if (!world.isClientSide) { + if (((Boolean) iblockdata.get(BlockTNT.EXPLODE)).booleanValue()) { +- EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(world, (double) ((float) blockposition.getX() + 0.5F), (double) blockposition.getY(), (double) ((float) blockposition.getZ() + 0.5F), entityliving); ++ // Paper start - Old TNT cannon behaviors ++ double y = blockposition.getY(); ++ if (!world.paperConfig.oldCannonBehaviors) y += 0.5; ++ EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(world, (double) ((float) blockposition.getX() + 0.5F), y, (double) ((float) blockposition.getZ() + 0.5F), entityliving); ++ // Paper end + + world.addEntity(entitytntprimed); + world.a((EntityHuman) null, entitytntprimed.locX, entitytntprimed.locY, entitytntprimed.locZ, SoundEffects.gV, SoundCategory.BLOCKS, 1.0F, 1.0F); +diff --git a/src/main/java/net/minecraft/server/DispenserRegistry.java b/src/main/java/net/minecraft/server/DispenserRegistry.java +index 6af9f206b..bec623c4d 100644 +--- a/src/main/java/net/minecraft/server/DispenserRegistry.java ++++ b/src/main/java/net/minecraft/server/DispenserRegistry.java +@@ -507,7 +507,11 @@ public class DispenserRegistry { + org.bukkit.block.Block block = world.getWorld().getBlockAt(isourceblock.getBlockPosition().getX(), isourceblock.getBlockPosition().getY(), isourceblock.getBlockPosition().getZ()); + CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + +- BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D)); ++ // Paper start - Old TNT cannon behaviors ++ double y = blockposition.getY(); ++ if (!world.paperConfig.oldCannonBehaviors) y += 0.5; ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockposition.getX() + 0.5D, y, (double) blockposition.getZ() + 0.5D)); ++ // Paper end + if (!BlockDispenser.eventFired) { + world.getServer().getPluginManager().callEvent(event); + } +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 96b1e9a78..0d1fdd3ee 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -1089,6 +1089,12 @@ public abstract class Entity implements ICommandListener { + } + + public boolean ak() { ++ // Paper start - OBFHELPER ++ return this.doWaterMovement(); ++ } ++ ++ public boolean doWaterMovement() { ++ // Paper end + if (this.bB() instanceof EntityBoat) { + this.inWater = false; + } else if (this.world.a(this.getBoundingBox().grow(0.0D, -0.4000000059604645D, 0.0D).shrink(0.001D), Material.WATER, this)) { +@@ -1292,6 +1298,12 @@ public abstract class Entity implements ICommandListener { + } + + public double e(double d0, double d1, double d2) { ++ // Paper start - OBFHELPER ++ return this.getDistance(d0, d1, d2); ++ } ++ ++ public double getDistance(double d0, double d1, double d2) { ++ // Paper end + double d3 = this.locX - d0; + double d4 = this.locY - d1; + double d5 = this.locZ - d2; +@@ -1346,6 +1358,11 @@ public abstract class Entity implements ICommandListener { + } + + public void f(double d0, double d1, double d2) { ++ // Paper start - OBFHELPER ++ this.addVelocity(d0, d1, d2); ++ } ++ ++ public void addVelocity(double d0, double d1, double d2) { + this.motX += d0; + this.motY += d1; + this.motZ += d2; +@@ -2505,6 +2522,12 @@ public abstract class Entity implements ICommandListener { + } + + public boolean bg() { ++ // Paper start - OBFHELPER ++ return this.pushedByWater(); ++ } ++ ++ public boolean pushedByWater() { ++ // Paper end + return true; + } + +diff --git a/src/main/java/net/minecraft/server/EntityFallingBlock.java b/src/main/java/net/minecraft/server/EntityFallingBlock.java +index 307a44c85..bb01929e8 100644 +--- a/src/main/java/net/minecraft/server/EntityFallingBlock.java ++++ b/src/main/java/net/minecraft/server/EntityFallingBlock.java +@@ -280,4 +280,19 @@ public class EntityFallingBlock extends Entity { + public boolean bu() { + return true; + } ++ ++ // Paper start - Old TNT cannon behaviors ++ @Override ++ public double getDistance(double d0, double d1, double d2) { ++ if (!world.paperConfig.oldCannonBehaviors) return super.getDistance(d0, d1, d2); ++ ++ double newX = this.locX - d0; ++ double newY = this.locY + this.getHeadHeight() - d1; ++ double newZ = this.locZ - d2; ++ ++ return (double) MathHelper.sqrt(newX * newX + newY * newY + newZ * newZ); ++ } ++ ++ ++ // Paper end + } +diff --git a/src/main/java/net/minecraft/server/EntityTNTPrimed.java b/src/main/java/net/minecraft/server/EntityTNTPrimed.java +index 25e471d37..e796ade87 100644 +--- a/src/main/java/net/minecraft/server/EntityTNTPrimed.java ++++ b/src/main/java/net/minecraft/server/EntityTNTPrimed.java +@@ -32,6 +32,7 @@ public class EntityTNTPrimed extends Entity { + this.lastY = d1; + this.lastZ = d2; + this.source = entityliving; ++ if (world.paperConfig.oldCannonBehaviors) this.motX = this.motZ = 0.0F; // Paper - Old TNT cannon behaviors + } + + protected void i() { +@@ -124,7 +125,7 @@ public class EntityTNTPrimed extends Entity { + } + + public float getHeadHeight() { +- return 0.0F; ++ return world.paperConfig.oldCannonBehaviors ? this.length / 16F : 0.0F; // Paper - Old TNT cannon behaviors + } + + public void setFuseTicks(int i) { +@@ -146,4 +147,58 @@ public class EntityTNTPrimed extends Entity { + public int getFuseTicks() { + return this.c; + } ++ ++ // Paper start - Old TNT cannon behaviors ++ @Override ++ public double getDistance(double d0, double d1, double d2) { ++ if (!world.paperConfig.oldCannonBehaviors) return super.getDistance(d0, d1, d2); ++ ++ double newX = this.locX - d0; ++ double newY = this.locY + this.getHeadHeight() - d1; ++ double newZ = this.locZ - d2; ++ ++ return (double) MathHelper.sqrt(newX * newX + newY * newY + newZ * newZ); ++ } ++ ++ @Override ++ public boolean pushedByWater() { ++ return !world.paperConfig.oldCannonBehaviors && super.pushedByWater(); ++ } ++ ++ /** ++ * Author: Jedediah Smith ++ */ ++ @Override ++ public boolean doWaterMovement() { ++ if (!world.paperConfig.oldCannonBehaviors) return super.doWaterMovement(); ++ ++ // Preserve velocity while calling the super method ++ double oldMotX = this.motX; ++ double oldMotY = this.motY; ++ double oldMotZ = this.motZ; ++ ++ super.doWaterMovement(); ++ ++ this.motX = oldMotX; ++ this.motY = oldMotY; ++ this.motZ = oldMotZ; ++ ++ if (this.inWater) { ++ // 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. ++ EntityTrackerEntry ete = ((WorldServer) this.getWorld()).getTracker().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); ++ }); ++ } ++ } ++ ++ return this.inWater; ++ } ++ // Paper end + } +diff --git a/src/main/java/net/minecraft/server/Explosion.java b/src/main/java/net/minecraft/server/Explosion.java +index d7bc6a0ed..f2785d86c 100644 +--- a/src/main/java/net/minecraft/server/Explosion.java ++++ b/src/main/java/net/minecraft/server/Explosion.java +@@ -149,9 +149,15 @@ public class Explosion { + d14 = entity instanceof EntityHuman && world.paperConfig.disableExplosionKnockback ? 0 : EnchantmentProtection.a((EntityLiving) entity, d13); // Paper - Disable explosion knockback + } + +- entity.motX += d8 * d14; +- entity.motY += d9 * d14; +- entity.motZ += d10 * d14; ++ // Paper start - Fix cannons ++ /* ++ entity.motX += d8 * d14; ++ entity.motY += d9 * d14; ++ entity.motZ += d10 * d14; ++ */ ++ // This impulse method sets the dirty flag, so clients will get an immediate velocity update ++ entity.addVelocity(d8 * d14, d9 * d14, d10 * d14); ++ // Paper end + if (entity instanceof EntityHuman) { + EntityHuman entityhuman = (EntityHuman) entity; + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0138-Faster-redstone-torch-rapid-clock-removal.patch b/Spigot-Server-Patches/0138-Faster-redstone-torch-rapid-clock-removal.patch new file mode 100644 index 0000000000..305a5a21cf --- /dev/null +++ b/Spigot-Server-Patches/0138-Faster-redstone-torch-rapid-clock-removal.patch @@ -0,0 +1,43 @@ +From ae790beb03eba954c38947720990f2f273b1d4e0 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/server/BlockRedstoneTorch.java b/src/main/java/net/minecraft/server/BlockRedstoneTorch.java +index 741236289..25a2a5d36 100644 +--- a/src/main/java/net/minecraft/server/BlockRedstoneTorch.java ++++ b/src/main/java/net/minecraft/server/BlockRedstoneTorch.java +@@ -117,9 +117,17 @@ public class BlockRedstoneTorch extends BlockTorch { + boolean flag = this.g(world, blockposition, iblockdata); + List list = (List) BlockRedstoneTorch.g.get(world); + +- while (list != null && !list.isEmpty() && world.getTime() - ((BlockRedstoneTorch.RedstoneUpdateInfo) list.get(0)).b > 60L) { +- list.remove(0); ++ // Paper start ++ if (list != null) { ++ int index = 0; ++ while (index < list.size() && world.getTime() - ((BlockRedstoneTorch.RedstoneUpdateInfo) list.get(index)).getTime() > 60L) { ++ index++; ++ } ++ if (index > 0) { ++ list.subList(0, index).clear(); ++ } + } ++ // Paper end + + // CraftBukkit start + org.bukkit.plugin.PluginManager manager = world.getServer().getPluginManager(); +@@ -202,7 +210,7 @@ public class BlockRedstoneTorch extends BlockTorch { + static class RedstoneUpdateInfo { + + BlockPosition a; +- long b; ++ long b; final long getTime() { return this.b; } // Paper - OBFHELPER + + public RedstoneUpdateInfo(BlockPosition blockposition, long i) { + this.a = blockposition; +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0138-Optional-old-TNT-cannon-behaviors.patch b/Spigot-Server-Patches/0138-Optional-old-TNT-cannon-behaviors.patch deleted file mode 100644 index 62440326fa..0000000000 --- a/Spigot-Server-Patches/0138-Optional-old-TNT-cannon-behaviors.patch +++ /dev/null @@ -1,393 +0,0 @@ -From 82e8f7a4a44e9c66dfc85f545c4ce71cf719c1b8 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sun, 22 May 2016 20:20:55 -0500 -Subject: [PATCH] Optional old TNT cannon behaviors - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index fbe769eb3..c4acb7597 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -327,4 +327,12 @@ public class PaperWorldConfig { - ); - } - } -+ -+ public boolean oldCannonBehaviors; -+ private void oldCannonBehaviors() { -+ oldCannonBehaviors = getBoolean("enable-old-tnt-cannon-behaviors", false); -+ if (oldCannonBehaviors) { -+ log("Old Cannon Behaviors: This feature may not be working entirely properly at the moment"); -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/server/BlockDiodeAbstract.java b/src/main/java/net/minecraft/server/BlockDiodeAbstract.java -index 59ee13de8..40c9f18bf 100644 ---- a/src/main/java/net/minecraft/server/BlockDiodeAbstract.java -+++ b/src/main/java/net/minecraft/server/BlockDiodeAbstract.java -@@ -76,6 +76,17 @@ public abstract class BlockDiodeAbstract extends BlockFacingHorizontal { - } else { - this.b(world, blockposition, iblockdata, 0); - world.setAir(blockposition); -+ // Paper start - Old TNT cannon behaviors -+ if (world.paperConfig.oldCannonBehaviors) { -+ world.applyPhysics(blockposition.shift(EnumDirection.EAST), this, false); -+ world.applyPhysics(blockposition.shift(EnumDirection.WEST), this, false); -+ world.applyPhysics(blockposition.shift(EnumDirection.SOUTH), this, false); -+ world.applyPhysics(blockposition.shift(EnumDirection.NORTH), this, false); -+ world.applyPhysics(blockposition.shift(EnumDirection.DOWN), this, false); -+ world.applyPhysics(blockposition.shift(EnumDirection.UP), this, false); -+ return; -+ } -+ // Paper end - EnumDirection[] aenumdirection = EnumDirection.values(); - int i = aenumdirection.length; - -@@ -173,6 +184,17 @@ public abstract class BlockDiodeAbstract extends BlockFacingHorizontal { - - public void postBreak(World world, BlockPosition blockposition, IBlockData iblockdata) { - if (this.d) { -+ // Paper start - Old TNT cannon behaviors -+ if (world.paperConfig.oldCannonBehaviors) { -+ world.applyPhysics(blockposition.shift(EnumDirection.EAST), this, false); -+ world.applyPhysics(blockposition.shift(EnumDirection.WEST), this, false); -+ world.applyPhysics(blockposition.shift(EnumDirection.NORTH), this, false); -+ world.applyPhysics(blockposition.shift(EnumDirection.SOUTH), this, false); -+ world.applyPhysics(blockposition.shift(EnumDirection.DOWN), this, false); -+ world.applyPhysics(blockposition.shift(EnumDirection.UP), this, false); -+ return; -+ } -+ // Paper end - EnumDirection[] aenumdirection = EnumDirection.values(); - int i = aenumdirection.length; - -diff --git a/src/main/java/net/minecraft/server/BlockRedstoneTorch.java b/src/main/java/net/minecraft/server/BlockRedstoneTorch.java -index c7e095a11..741236289 100644 ---- a/src/main/java/net/minecraft/server/BlockRedstoneTorch.java -+++ b/src/main/java/net/minecraft/server/BlockRedstoneTorch.java -@@ -52,6 +52,12 @@ public class BlockRedstoneTorch extends BlockTorch { - - public void onPlace(World world, BlockPosition blockposition, IBlockData iblockdata) { - if (this.isOn) { -+ // Paper start - Old TNT cannon behaviors -+ if (world.paperConfig.oldCannonBehaviors) { -+ this.shiftPositions(world, blockposition); -+ return; -+ } -+ // Paper end - EnumDirection[] aenumdirection = EnumDirection.values(); - int i = aenumdirection.length; - -@@ -66,6 +72,12 @@ public class BlockRedstoneTorch extends BlockTorch { - - public void remove(World world, BlockPosition blockposition, IBlockData iblockdata) { - if (this.isOn) { -+ // Paper start - Old TNT cannon behaviors -+ if (world.paperConfig.oldCannonBehaviors) { -+ this.shiftPositions(world, blockposition); -+ return; -+ } -+ // Paper end - EnumDirection[] aenumdirection = EnumDirection.values(); - int i = aenumdirection.length; - -@@ -78,6 +90,17 @@ public class BlockRedstoneTorch extends BlockTorch { - - } - -+ // Paper start - Old TNT cannon behaviors -+ private void shiftPositions(World world, BlockPosition blockposition) { -+ world.applyPhysics(blockposition.shift(EnumDirection.DOWN), this, false); -+ world.applyPhysics(blockposition.shift(EnumDirection.UP), this, false); -+ world.applyPhysics(blockposition.shift(EnumDirection.WEST), this, false); -+ world.applyPhysics(blockposition.shift(EnumDirection.EAST), this, false); -+ world.applyPhysics(blockposition.shift(EnumDirection.SOUTH), this, false); -+ world.applyPhysics(blockposition.shift(EnumDirection.NORTH), this, false); -+ } -+ // Paper end -+ - public int b(IBlockData iblockdata, IBlockAccess iblockaccess, BlockPosition blockposition, EnumDirection enumdirection) { - return this.isOn && iblockdata.get(BlockRedstoneTorch.FACING) != enumdirection ? 15 : 0; - } -diff --git a/src/main/java/net/minecraft/server/BlockRedstoneWire.java b/src/main/java/net/minecraft/server/BlockRedstoneWire.java -index 5a0f026b1..20b9465e7 100644 ---- a/src/main/java/net/minecraft/server/BlockRedstoneWire.java -+++ b/src/main/java/net/minecraft/server/BlockRedstoneWire.java -@@ -20,7 +20,7 @@ public class BlockRedstoneWire extends Block { - public static final BlockStateInteger POWER = BlockStateInteger.of("power", 0, 15); - protected static final AxisAlignedBB[] f = new AxisAlignedBB[] { new AxisAlignedBB(0.1875D, 0.0D, 0.1875D, 0.8125D, 0.0625D, 0.8125D), new AxisAlignedBB(0.1875D, 0.0D, 0.1875D, 0.8125D, 0.0625D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.1875D, 0.8125D, 0.0625D, 0.8125D), new AxisAlignedBB(0.0D, 0.0D, 0.1875D, 0.8125D, 0.0625D, 1.0D), new AxisAlignedBB(0.1875D, 0.0D, 0.0D, 0.8125D, 0.0625D, 0.8125D), new AxisAlignedBB(0.1875D, 0.0D, 0.0D, 0.8125D, 0.0625D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 0.8125D, 0.0625D, 0.8125D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 0.8125D, 0.0625D, 1.0D), new AxisAlignedBB(0.1875D, 0.0D, 0.1875D, 1.0D, 0.0625D, 0.8125D), new AxisAlignedBB(0.1875D, 0.0D, 0.1875D, 1.0D, 0.0625D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.1875D, 1.0D, 0.0625D, 0.8125D), new AxisAlignedBB(0.0D, 0.0D, 0.1875D, 1.0D, 0.0625D, 1.0D), new AxisAlignedBB(0.1875D, 0.0D, 0.0D, 1.0D, 0.0625D, 0.8125D), new AxisAlignedBB(0.1875D, 0.0D, 0.0D, 1.0D, 0.0625D, 1.0D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.0625D, 0.8125D), new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.0625D, 1.0D)}; - private boolean g = true; -- private final Set B = Sets.newHashSet(); -+ private final Set B = Sets.newHashSet(); private final Set blocksToUpdate = B; // Paper - OBFHELPER - - public BlockRedstoneWire() { - super(Material.ORIENTABLE); -@@ -186,6 +186,19 @@ public class BlockRedstoneWire extends Block { - } - - this.B.add(blockposition); -+ // Paper start - Old TNT cannon behaviors -+ if (world.paperConfig.oldCannonBehaviors) { -+ this.blocksToUpdate.add(blockposition.shift(EnumDirection.WEST)); -+ this.blocksToUpdate.add(blockposition.shift(EnumDirection.EAST)); -+ this.blocksToUpdate.add(blockposition.shift(EnumDirection.DOWN)); -+ this.blocksToUpdate.add(blockposition.shift(EnumDirection.UP)); -+ this.blocksToUpdate.add(blockposition.shift(EnumDirection.NORTH)); -+ this.blocksToUpdate.add(blockposition.shift(EnumDirection.SOUTH)); -+ return iblockdata; -+ } -+ // Paper end -+ -+ - EnumDirection[] aenumdirection = EnumDirection.values(); - int i1 = aenumdirection.length; - -@@ -202,6 +215,16 @@ public class BlockRedstoneWire extends Block { - private void b(World world, BlockPosition blockposition) { - if (world.getType(blockposition).getBlock() == this) { - world.applyPhysics(blockposition, this, false); -+ if (world.paperConfig.oldCannonBehaviors) { -+ world.applyPhysics(blockposition.shift(EnumDirection.WEST), this, false); -+ world.applyPhysics(blockposition.shift(EnumDirection.EAST), this, false); -+ world.applyPhysics(blockposition.shift(EnumDirection.NORTH), this, false); -+ world.applyPhysics(blockposition.shift(EnumDirection.SOUTH), this, false); -+ world.applyPhysics(blockposition.shift(EnumDirection.DOWN), this, false); -+ world.applyPhysics(blockposition.shift(EnumDirection.UP), this, false); -+ return; -+ } -+ // Paper end - EnumDirection[] aenumdirection = EnumDirection.values(); - int i = aenumdirection.length; - -diff --git a/src/main/java/net/minecraft/server/BlockTNT.java b/src/main/java/net/minecraft/server/BlockTNT.java -index 6b6aa892a..5cec4160c 100644 ---- a/src/main/java/net/minecraft/server/BlockTNT.java -+++ b/src/main/java/net/minecraft/server/BlockTNT.java -@@ -29,7 +29,11 @@ public class BlockTNT extends Block { - - public void wasExploded(World world, BlockPosition blockposition, Explosion explosion) { - if (!world.isClientSide) { -- EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(world, (double) ((float) blockposition.getX() + 0.5F), (double) blockposition.getY(), (double) ((float) blockposition.getZ() + 0.5F), explosion.getSource()); -+ // Paper start - Old TNT cannon behaviors -+ double y = blockposition.getY(); -+ if (!world.paperConfig.oldCannonBehaviors) y += 0.5; -+ EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(world, (double) ((float) blockposition.getX() + 0.5F), y, (double) ((float) blockposition.getZ() + 0.5F), explosion.getSource()); -+ // Paper end - - entitytntprimed.setFuseTicks((short) (world.random.nextInt(entitytntprimed.getFuseTicks() / 4) + entitytntprimed.getFuseTicks() / 8)); - world.addEntity(entitytntprimed); -@@ -43,7 +47,11 @@ public class BlockTNT extends Block { - public void a(World world, BlockPosition blockposition, IBlockData iblockdata, EntityLiving entityliving) { - if (!world.isClientSide) { - if (((Boolean) iblockdata.get(BlockTNT.EXPLODE)).booleanValue()) { -- EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(world, (double) ((float) blockposition.getX() + 0.5F), (double) blockposition.getY(), (double) ((float) blockposition.getZ() + 0.5F), entityliving); -+ // Paper start - Old TNT cannon behaviors -+ double y = blockposition.getY(); -+ if (!world.paperConfig.oldCannonBehaviors) y += 0.5; -+ EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(world, (double) ((float) blockposition.getX() + 0.5F), y, (double) ((float) blockposition.getZ() + 0.5F), entityliving); -+ // Paper end - - world.addEntity(entitytntprimed); - world.a((EntityHuman) null, entitytntprimed.locX, entitytntprimed.locY, entitytntprimed.locZ, SoundEffects.gV, SoundCategory.BLOCKS, 1.0F, 1.0F); -diff --git a/src/main/java/net/minecraft/server/DispenserRegistry.java b/src/main/java/net/minecraft/server/DispenserRegistry.java -index 6af9f206b..bec623c4d 100644 ---- a/src/main/java/net/minecraft/server/DispenserRegistry.java -+++ b/src/main/java/net/minecraft/server/DispenserRegistry.java -@@ -507,7 +507,11 @@ public class DispenserRegistry { - org.bukkit.block.Block block = world.getWorld().getBlockAt(isourceblock.getBlockPosition().getX(), isourceblock.getBlockPosition().getY(), isourceblock.getBlockPosition().getZ()); - CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); - -- BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D)); -+ // Paper start - Old TNT cannon behaviors -+ double y = blockposition.getY(); -+ if (!world.paperConfig.oldCannonBehaviors) y += 0.5; -+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockposition.getX() + 0.5D, y, (double) blockposition.getZ() + 0.5D)); -+ // Paper end - if (!BlockDispenser.eventFired) { - world.getServer().getPluginManager().callEvent(event); - } -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 96b1e9a78..0d1fdd3ee 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -1089,6 +1089,12 @@ public abstract class Entity implements ICommandListener { - } - - public boolean ak() { -+ // Paper start - OBFHELPER -+ return this.doWaterMovement(); -+ } -+ -+ public boolean doWaterMovement() { -+ // Paper end - if (this.bB() instanceof EntityBoat) { - this.inWater = false; - } else if (this.world.a(this.getBoundingBox().grow(0.0D, -0.4000000059604645D, 0.0D).shrink(0.001D), Material.WATER, this)) { -@@ -1292,6 +1298,12 @@ public abstract class Entity implements ICommandListener { - } - - public double e(double d0, double d1, double d2) { -+ // Paper start - OBFHELPER -+ return this.getDistance(d0, d1, d2); -+ } -+ -+ public double getDistance(double d0, double d1, double d2) { -+ // Paper end - double d3 = this.locX - d0; - double d4 = this.locY - d1; - double d5 = this.locZ - d2; -@@ -1346,6 +1358,11 @@ public abstract class Entity implements ICommandListener { - } - - public void f(double d0, double d1, double d2) { -+ // Paper start - OBFHELPER -+ this.addVelocity(d0, d1, d2); -+ } -+ -+ public void addVelocity(double d0, double d1, double d2) { - this.motX += d0; - this.motY += d1; - this.motZ += d2; -@@ -2505,6 +2522,12 @@ public abstract class Entity implements ICommandListener { - } - - public boolean bg() { -+ // Paper start - OBFHELPER -+ return this.pushedByWater(); -+ } -+ -+ public boolean pushedByWater() { -+ // Paper end - return true; - } - -diff --git a/src/main/java/net/minecraft/server/EntityFallingBlock.java b/src/main/java/net/minecraft/server/EntityFallingBlock.java -index 307a44c85..bb01929e8 100644 ---- a/src/main/java/net/minecraft/server/EntityFallingBlock.java -+++ b/src/main/java/net/minecraft/server/EntityFallingBlock.java -@@ -280,4 +280,19 @@ public class EntityFallingBlock extends Entity { - public boolean bu() { - return true; - } -+ -+ // Paper start - Old TNT cannon behaviors -+ @Override -+ public double getDistance(double d0, double d1, double d2) { -+ if (!world.paperConfig.oldCannonBehaviors) return super.getDistance(d0, d1, d2); -+ -+ double newX = this.locX - d0; -+ double newY = this.locY + this.getHeadHeight() - d1; -+ double newZ = this.locZ - d2; -+ -+ return (double) MathHelper.sqrt(newX * newX + newY * newY + newZ * newZ); -+ } -+ -+ -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/server/EntityTNTPrimed.java b/src/main/java/net/minecraft/server/EntityTNTPrimed.java -index 25e471d37..e796ade87 100644 ---- a/src/main/java/net/minecraft/server/EntityTNTPrimed.java -+++ b/src/main/java/net/minecraft/server/EntityTNTPrimed.java -@@ -32,6 +32,7 @@ public class EntityTNTPrimed extends Entity { - this.lastY = d1; - this.lastZ = d2; - this.source = entityliving; -+ if (world.paperConfig.oldCannonBehaviors) this.motX = this.motZ = 0.0F; // Paper - Old TNT cannon behaviors - } - - protected void i() { -@@ -124,7 +125,7 @@ public class EntityTNTPrimed extends Entity { - } - - public float getHeadHeight() { -- return 0.0F; -+ return world.paperConfig.oldCannonBehaviors ? this.length / 16F : 0.0F; // Paper - Old TNT cannon behaviors - } - - public void setFuseTicks(int i) { -@@ -146,4 +147,58 @@ public class EntityTNTPrimed extends Entity { - public int getFuseTicks() { - return this.c; - } -+ -+ // Paper start - Old TNT cannon behaviors -+ @Override -+ public double getDistance(double d0, double d1, double d2) { -+ if (!world.paperConfig.oldCannonBehaviors) return super.getDistance(d0, d1, d2); -+ -+ double newX = this.locX - d0; -+ double newY = this.locY + this.getHeadHeight() - d1; -+ double newZ = this.locZ - d2; -+ -+ return (double) MathHelper.sqrt(newX * newX + newY * newY + newZ * newZ); -+ } -+ -+ @Override -+ public boolean pushedByWater() { -+ return !world.paperConfig.oldCannonBehaviors && super.pushedByWater(); -+ } -+ -+ /** -+ * Author: Jedediah Smith -+ */ -+ @Override -+ public boolean doWaterMovement() { -+ if (!world.paperConfig.oldCannonBehaviors) return super.doWaterMovement(); -+ -+ // Preserve velocity while calling the super method -+ double oldMotX = this.motX; -+ double oldMotY = this.motY; -+ double oldMotZ = this.motZ; -+ -+ super.doWaterMovement(); -+ -+ this.motX = oldMotX; -+ this.motY = oldMotY; -+ this.motZ = oldMotZ; -+ -+ if (this.inWater) { -+ // 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. -+ EntityTrackerEntry ete = ((WorldServer) this.getWorld()).getTracker().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); -+ }); -+ } -+ } -+ -+ return this.inWater; -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/server/Explosion.java b/src/main/java/net/minecraft/server/Explosion.java -index d7bc6a0ed..f2785d86c 100644 ---- a/src/main/java/net/minecraft/server/Explosion.java -+++ b/src/main/java/net/minecraft/server/Explosion.java -@@ -149,9 +149,15 @@ public class Explosion { - d14 = entity instanceof EntityHuman && world.paperConfig.disableExplosionKnockback ? 0 : EnchantmentProtection.a((EntityLiving) entity, d13); // Paper - Disable explosion knockback - } - -- entity.motX += d8 * d14; -- entity.motY += d9 * d14; -- entity.motZ += d10 * d14; -+ // Paper start - Fix cannons -+ /* -+ entity.motX += d8 * d14; -+ entity.motY += d9 * d14; -+ entity.motZ += d10 * d14; -+ */ -+ // This impulse method sets the dirty flag, so clients will get an immediate velocity update -+ entity.addVelocity(d8 * d14, d9 * d14, d10 * d14); -+ // Paper end - if (entity instanceof EntityHuman) { - EntityHuman entityhuman = (EntityHuman) entity; - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0139-Ensure-Chunks-never-ever-load-async.patch b/Spigot-Server-Patches/0139-Ensure-Chunks-never-ever-load-async.patch new file mode 100644 index 0000000000..31e23a2f55 --- /dev/null +++ b/Spigot-Server-Patches/0139-Ensure-Chunks-never-ever-load-async.patch @@ -0,0 +1,46 @@ +From 7dacb06906b8a49f5fff6ac5d3e13f44e0921a4b Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 27 May 2016 21:41:26 -0400 +Subject: [PATCH] Ensure Chunks never ever load async + +Safely pushes the operation to main thread, then back to the posting thread + +diff --git a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOExecutor.java b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOExecutor.java +index 7b7a3d01b..9aaca21a7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOExecutor.java ++++ b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOExecutor.java +@@ -4,6 +4,7 @@ import com.destroystokyo.paper.PaperConfig; + import net.minecraft.server.Chunk; + import net.minecraft.server.ChunkProviderServer; + import net.minecraft.server.ChunkRegionLoader; ++import net.minecraft.server.MCUtil; // Paper + import net.minecraft.server.World; + import org.bukkit.craftbukkit.util.AsynchronousExecutor; + +@@ -14,7 +15,7 @@ public class ChunkIOExecutor { + private static final AsynchronousExecutor instance = new AsynchronousExecutor(new ChunkIOProvider(), BASE_THREADS); + + public static Chunk syncChunkLoad(World world, ChunkRegionLoader loader, ChunkProviderServer provider, int x, int z) { +- return instance.getSkipQueue(new QueuedChunk(x, z, loader, world, provider)); ++ return MCUtil.ensureMain("Async Chunk Load", () -> instance.getSkipQueue(new QueuedChunk(x, z, loader, world, provider))); // Paper + } + + public static void queueChunkLoad(World world, ChunkRegionLoader loader, ChunkProviderServer provider, int x, int z, Runnable runnable) { +diff --git a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java +index b5efb9c3f..ef9529add 100644 +--- a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java ++++ b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java +@@ -35,8 +35,8 @@ class ChunkIOProvider implements AsynchronousExecutor.CallBackProvider -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/server/BlockRedstoneTorch.java b/src/main/java/net/minecraft/server/BlockRedstoneTorch.java -index 741236289..25a2a5d36 100644 ---- a/src/main/java/net/minecraft/server/BlockRedstoneTorch.java -+++ b/src/main/java/net/minecraft/server/BlockRedstoneTorch.java -@@ -117,9 +117,17 @@ public class BlockRedstoneTorch extends BlockTorch { - boolean flag = this.g(world, blockposition, iblockdata); - List list = (List) BlockRedstoneTorch.g.get(world); - -- while (list != null && !list.isEmpty() && world.getTime() - ((BlockRedstoneTorch.RedstoneUpdateInfo) list.get(0)).b > 60L) { -- list.remove(0); -+ // Paper start -+ if (list != null) { -+ int index = 0; -+ while (index < list.size() && world.getTime() - ((BlockRedstoneTorch.RedstoneUpdateInfo) list.get(index)).getTime() > 60L) { -+ index++; -+ } -+ if (index > 0) { -+ list.subList(0, index).clear(); -+ } - } -+ // Paper end - - // CraftBukkit start - org.bukkit.plugin.PluginManager manager = world.getServer().getPluginManager(); -@@ -202,7 +210,7 @@ public class BlockRedstoneTorch extends BlockTorch { - static class RedstoneUpdateInfo { - - BlockPosition a; -- long b; -+ long b; final long getTime() { return this.b; } // Paper - OBFHELPER - - public RedstoneUpdateInfo(BlockPosition blockposition, long i) { - this.a = blockposition; --- -2.12.2 - diff --git a/Spigot-Server-Patches/0140-Add-server-name-parameter.patch b/Spigot-Server-Patches/0140-Add-server-name-parameter.patch new file mode 100644 index 0000000000..fcf79c9900 --- /dev/null +++ b/Spigot-Server-Patches/0140-Add-server-name-parameter.patch @@ -0,0 +1,28 @@ +From c325795fa35577349654d913c5be60aeddd6e6b4 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 4399faf69..59d4e2e6f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -134,6 +134,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 + } + }; + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0140-Ensure-Chunks-never-ever-load-async.patch b/Spigot-Server-Patches/0140-Ensure-Chunks-never-ever-load-async.patch deleted file mode 100644 index 00733f4564..0000000000 --- a/Spigot-Server-Patches/0140-Ensure-Chunks-never-ever-load-async.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0f1b139badcecfe47ada01bf5a643f6691154341 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 27 May 2016 21:41:26 -0400 -Subject: [PATCH] Ensure Chunks never ever load async - -Safely pushes the operation to main thread, then back to the posting thread - -diff --git a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOExecutor.java b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOExecutor.java -index 7b7a3d01b..9aaca21a7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOExecutor.java -+++ b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOExecutor.java -@@ -4,6 +4,7 @@ import com.destroystokyo.paper.PaperConfig; - import net.minecraft.server.Chunk; - import net.minecraft.server.ChunkProviderServer; - import net.minecraft.server.ChunkRegionLoader; -+import net.minecraft.server.MCUtil; // Paper - import net.minecraft.server.World; - import org.bukkit.craftbukkit.util.AsynchronousExecutor; - -@@ -14,7 +15,7 @@ public class ChunkIOExecutor { - private static final AsynchronousExecutor instance = new AsynchronousExecutor(new ChunkIOProvider(), BASE_THREADS); - - public static Chunk syncChunkLoad(World world, ChunkRegionLoader loader, ChunkProviderServer provider, int x, int z) { -- return instance.getSkipQueue(new QueuedChunk(x, z, loader, world, provider)); -+ return MCUtil.ensureMain("Async Chunk Load", () -> instance.getSkipQueue(new QueuedChunk(x, z, loader, world, provider))); // Paper - } - - public static void queueChunkLoad(World world, ChunkRegionLoader loader, ChunkProviderServer provider, int x, int z, Runnable runnable) { -diff --git a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java -index b5efb9c3f..ef9529add 100644 ---- a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java -+++ b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java -@@ -35,8 +35,8 @@ class ChunkIOProvider implements AsynchronousExecutor.CallBackProvider -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 4399faf69..59d4e2e6f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -134,6 +134,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 - } - }; - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0141-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch b/Spigot-Server-Patches/0141-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch new file mode 100644 index 0000000000..a646c2821f --- /dev/null +++ b/Spigot-Server-Patches/0141-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch @@ -0,0 +1,48 @@ +From 309f96980dba21738a6b1d9d802bc2c9f67301b4 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/server/EntityEnderDragon.java b/src/main/java/net/minecraft/server/EntityEnderDragon.java +index e24be3ccd..e93819fc1 100644 +--- a/src/main/java/net/minecraft/server/EntityEnderDragon.java ++++ b/src/main/java/net/minecraft/server/EntityEnderDragon.java +@@ -573,8 +573,12 @@ public class EntityEnderDragon extends EntityInsentient implements IComplex, IMo + if (this.bG == 1) { + // CraftBukkit start - Use relative location for far away sounds + // this.world.a(1028, new BlockPosition(this), 0); +- int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; +- for (EntityPlayer player : (List) MinecraftServer.getServer().getPlayerList().players) { ++ // Paper start ++ //int viewDistance = ((WorldServer) this.world).spigotConfig.viewDistance * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API ++ for (EntityHuman human : world.players) { ++ EntityPlayer player = (EntityPlayer) human; ++ int viewDistance = player.getViewDistance(); ++ // 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/server/EntityWither.java b/src/main/java/net/minecraft/server/EntityWither.java +index 9af34ba60..031507574 100644 +--- a/src/main/java/net/minecraft/server/EntityWither.java ++++ b/src/main/java/net/minecraft/server/EntityWither.java +@@ -211,8 +211,12 @@ public class EntityWither extends EntityMonster implements IRangedEntity { + + // CraftBukkit start - Use relative location for far away sounds + // this.world.a(1023, new BlockPosition(this), 0); +- int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; +- for (EntityPlayer player : (List) MinecraftServer.getServer().getPlayerList().players) { ++ // Paper start ++ //int viewDistance = ((WorldServer) this.world).spigotConfig.viewDistance * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API ++ for (EntityHuman human : world.players) { ++ EntityPlayer player = (EntityPlayer) human; ++ int viewDistance = player.getViewDistance(); ++ // Paper end + double deltaX = this.locX - player.locX; + double deltaZ = this.locZ - player.locZ; + double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0142-Fix-FallingBlocks-being-stuck-on-fences.patch b/Spigot-Server-Patches/0142-Fix-FallingBlocks-being-stuck-on-fences.patch new file mode 100644 index 0000000000..0d6f9e3dd3 --- /dev/null +++ b/Spigot-Server-Patches/0142-Fix-FallingBlocks-being-stuck-on-fences.patch @@ -0,0 +1,106 @@ +From a57b2a20bfc3edce691470ca6def1e166dc6cfa4 Mon Sep 17 00:00:00 2001 +From: Martin Panzer +Date: Fri, 3 Jun 2016 23:13:39 +0200 +Subject: [PATCH] Fix FallingBlocks being stuck on fences + +Fallingblocks would previously only check if directly beneath them a block exists. They also +hover on top of the 1.5 block tall hitbox of fences during these check. This +resulted in them always thinking they would be on air. + +We now first check, if if we are already on the ground. +if not, we check if the falling block is inside of the hitbox of the block at y - 1. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index c4acb7597..7bd745a27 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -335,4 +335,9 @@ public class PaperWorldConfig { + log("Old Cannon Behaviors: This feature may not be working entirely properly at the moment"); + } + } ++ ++ public boolean altFallingBlockOnGround; ++ private void altFallingBlockOnGround() { ++ altFallingBlockOnGround = getBoolean("use-alternate-fallingblock-onGround-detection", false); ++ } + } +diff --git a/src/main/java/net/minecraft/server/BlockFalling.java b/src/main/java/net/minecraft/server/BlockFalling.java +index dcdae998c..3c777418b 100644 +--- a/src/main/java/net/minecraft/server/BlockFalling.java ++++ b/src/main/java/net/minecraft/server/BlockFalling.java +@@ -71,6 +71,12 @@ public class BlockFalling extends Block { + return block == Blocks.FIRE || material == Material.AIR || material == Material.WATER || material == Material.LAVA; + } + ++ // Paper start - OBFHELPER ++ public static boolean canMoveThrough(IBlockData blockdata) { ++ return BlockFalling.i(blockdata); ++ } ++ // Paper end ++ + public void a_(World world, BlockPosition blockposition) {} + + public void b(World world, BlockPosition blockposition) {} +diff --git a/src/main/java/net/minecraft/server/EntityFallingBlock.java b/src/main/java/net/minecraft/server/EntityFallingBlock.java +index bb01929e8..8059e6dcd 100644 +--- a/src/main/java/net/minecraft/server/EntityFallingBlock.java ++++ b/src/main/java/net/minecraft/server/EntityFallingBlock.java +@@ -2,7 +2,9 @@ package net.minecraft.server; + + import com.google.common.collect.Lists; + import java.util.ArrayList; ++import java.util.Arrays; + import java.util.Iterator; ++import java.util.List; + import javax.annotation.Nullable; + + import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit +@@ -97,10 +99,9 @@ public class EntityFallingBlock extends Entity { + blockposition = new BlockPosition(this); + if (this.onGround) { + IBlockData iblockdata = this.world.getType(blockposition); +- +- if (BlockFalling.i(this.world.getType(new BlockPosition(this.locX, this.locY - 0.009999999776482582D, this.locZ)))) { ++ if (!isOnGround()) { + this.onGround = false; +- // return; // CraftBukkit ++ if (this.world.paperConfig.altFallingBlockOnGround) return; // Paper + } + + this.motX *= 0.699999988079071D; +@@ -159,6 +160,32 @@ public class EntityFallingBlock extends Entity { + } + } + ++ // Paper start ++ private boolean isOnGround() { ++ BlockPosition where = new BlockPosition(this.locX, this.locY - 0.009999999776482582D, this.locZ); ++ boolean cannotMoveThrough = !BlockFalling.canMoveThrough(this.world.getType(where)); ++ if (!this.world.paperConfig.altFallingBlockOnGround) return cannotMoveThrough; ++ ++ if (cannotMoveThrough) { ++ return true; ++ } ++ ++ IBlockData blockData = this.world.getType(where.down()); ++ if (BlockFalling.canMoveThrough(blockData)) { ++ return false; ++ } ++ ++ List list = new ArrayList<>(); ++ addCollisions(blockData, getWorld(), where, this.getBoundingBox(), list, this); ++ return list.size() > 0; ++ } ++ ++ // OBFHELPER ++ private void addCollisions(IBlockData blockData, World world, BlockPosition where, AxisAlignedBB collider, List list, Entity entity) { ++ blockData.a(world, where, collider, list, entity, false); ++ } ++ // Paper end ++ + public void e(float f, float f1) { + Block block = this.block.getBlock(); + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0142-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch b/Spigot-Server-Patches/0142-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch deleted file mode 100644 index efbfb96c24..0000000000 --- a/Spigot-Server-Patches/0142-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch +++ /dev/null @@ -1,48 +0,0 @@ -From c2807401573c8f0758a9ce02696466bc911439c2 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/server/EntityEnderDragon.java b/src/main/java/net/minecraft/server/EntityEnderDragon.java -index e24be3ccd..e93819fc1 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/server/EntityEnderDragon.java -@@ -573,8 +573,12 @@ public class EntityEnderDragon extends EntityInsentient implements IComplex, IMo - if (this.bG == 1) { - // CraftBukkit start - Use relative location for far away sounds - // this.world.a(1028, new BlockPosition(this), 0); -- int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; -- for (EntityPlayer player : (List) MinecraftServer.getServer().getPlayerList().players) { -+ // Paper start -+ //int viewDistance = ((WorldServer) this.world).spigotConfig.viewDistance * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ for (EntityHuman human : world.players) { -+ EntityPlayer player = (EntityPlayer) human; -+ int viewDistance = player.getViewDistance(); -+ // 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/server/EntityWither.java b/src/main/java/net/minecraft/server/EntityWither.java -index 9af34ba60..031507574 100644 ---- a/src/main/java/net/minecraft/server/EntityWither.java -+++ b/src/main/java/net/minecraft/server/EntityWither.java -@@ -211,8 +211,12 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - - // CraftBukkit start - Use relative location for far away sounds - // this.world.a(1023, new BlockPosition(this), 0); -- int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; -- for (EntityPlayer player : (List) MinecraftServer.getServer().getPlayerList().players) { -+ // Paper start -+ //int viewDistance = ((WorldServer) this.world).spigotConfig.viewDistance * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ for (EntityHuman human : world.players) { -+ EntityPlayer player = (EntityPlayer) human; -+ int viewDistance = player.getViewDistance(); -+ // Paper end - double deltaX = this.locX - player.locX; - double deltaZ = this.locZ - player.locZ; - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; --- -2.12.2 - diff --git a/Spigot-Server-Patches/0143-Fix-FallingBlocks-being-stuck-on-fences.patch b/Spigot-Server-Patches/0143-Fix-FallingBlocks-being-stuck-on-fences.patch deleted file mode 100644 index ae258a96df..0000000000 --- a/Spigot-Server-Patches/0143-Fix-FallingBlocks-being-stuck-on-fences.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 33ecb4b8cf5348bc04ebf70d86f3d0a82c06c00a Mon Sep 17 00:00:00 2001 -From: Martin Panzer -Date: Fri, 3 Jun 2016 23:13:39 +0200 -Subject: [PATCH] Fix FallingBlocks being stuck on fences - -Fallingblocks would previously only check if directly beneath them a block exists. They also -hover on top of the 1.5 block tall hitbox of fences during these check. This -resulted in them always thinking they would be on air. - -We now first check, if if we are already on the ground. -if not, we check if the falling block is inside of the hitbox of the block at y - 1. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index c4acb7597..7bd745a27 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -335,4 +335,9 @@ public class PaperWorldConfig { - log("Old Cannon Behaviors: This feature may not be working entirely properly at the moment"); - } - } -+ -+ public boolean altFallingBlockOnGround; -+ private void altFallingBlockOnGround() { -+ altFallingBlockOnGround = getBoolean("use-alternate-fallingblock-onGround-detection", false); -+ } - } -diff --git a/src/main/java/net/minecraft/server/BlockFalling.java b/src/main/java/net/minecraft/server/BlockFalling.java -index dcdae998c..3c777418b 100644 ---- a/src/main/java/net/minecraft/server/BlockFalling.java -+++ b/src/main/java/net/minecraft/server/BlockFalling.java -@@ -71,6 +71,12 @@ public class BlockFalling extends Block { - return block == Blocks.FIRE || material == Material.AIR || material == Material.WATER || material == Material.LAVA; - } - -+ // Paper start - OBFHELPER -+ public static boolean canMoveThrough(IBlockData blockdata) { -+ return BlockFalling.i(blockdata); -+ } -+ // Paper end -+ - public void a_(World world, BlockPosition blockposition) {} - - public void b(World world, BlockPosition blockposition) {} -diff --git a/src/main/java/net/minecraft/server/EntityFallingBlock.java b/src/main/java/net/minecraft/server/EntityFallingBlock.java -index bb01929e8..8059e6dcd 100644 ---- a/src/main/java/net/minecraft/server/EntityFallingBlock.java -+++ b/src/main/java/net/minecraft/server/EntityFallingBlock.java -@@ -2,7 +2,9 @@ package net.minecraft.server; - - import com.google.common.collect.Lists; - import java.util.ArrayList; -+import java.util.Arrays; - import java.util.Iterator; -+import java.util.List; - import javax.annotation.Nullable; - - import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit -@@ -97,10 +99,9 @@ public class EntityFallingBlock extends Entity { - blockposition = new BlockPosition(this); - if (this.onGround) { - IBlockData iblockdata = this.world.getType(blockposition); -- -- if (BlockFalling.i(this.world.getType(new BlockPosition(this.locX, this.locY - 0.009999999776482582D, this.locZ)))) { -+ if (!isOnGround()) { - this.onGround = false; -- // return; // CraftBukkit -+ if (this.world.paperConfig.altFallingBlockOnGround) return; // Paper - } - - this.motX *= 0.699999988079071D; -@@ -159,6 +160,32 @@ public class EntityFallingBlock extends Entity { - } - } - -+ // Paper start -+ private boolean isOnGround() { -+ BlockPosition where = new BlockPosition(this.locX, this.locY - 0.009999999776482582D, this.locZ); -+ boolean cannotMoveThrough = !BlockFalling.canMoveThrough(this.world.getType(where)); -+ if (!this.world.paperConfig.altFallingBlockOnGround) return cannotMoveThrough; -+ -+ if (cannotMoveThrough) { -+ return true; -+ } -+ -+ IBlockData blockData = this.world.getType(where.down()); -+ if (BlockFalling.canMoveThrough(blockData)) { -+ return false; -+ } -+ -+ List list = new ArrayList<>(); -+ addCollisions(blockData, getWorld(), where, this.getBoundingBox(), list, this); -+ return list.size() > 0; -+ } -+ -+ // OBFHELPER -+ private void addCollisions(IBlockData blockData, World world, BlockPosition where, AxisAlignedBB collider, List list, Entity entity) { -+ blockData.a(world, where, collider, list, entity, false); -+ } -+ // Paper end -+ - public void e(float f, float f1) { - Block block = this.block.getBlock(); - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0143-Make-entities-look-for-hoppers.patch b/Spigot-Server-Patches/0143-Make-entities-look-for-hoppers.patch new file mode 100644 index 0000000000..125875ed30 --- /dev/null +++ b/Spigot-Server-Patches/0143-Make-entities-look-for-hoppers.patch @@ -0,0 +1,382 @@ +From 5e24b91319bb930c470e28e5751d7f9b758fe063 Mon Sep 17 00:00:00 2001 +From: Techcable +Date: Sat, 18 Jun 2016 01:01:37 -0500 +Subject: [PATCH] Make entities look for hoppers + +Every tick hoppers try and find an block-inventory to extract from. +If no tile entity is above the hopper (which there often isn't) it will do a bounding box search for minecart chests and minecart hoppers. +If it can't find an inventory, it will then look for a dropped item, which is another bounding box search. +This patch eliminates that expensive check by having dropped items and minecart hoppers/chests look for hoppers instead. +Hoppers are tile entities meaning you can do a simple tile entity lookup to find the nearest hopper in range. +Pushing out of hoppers causes a bouding box lookup, which this patch replaces with a tile entity lookup. + +This patch may causes a decrease in the performance of dropped items, which is why it can be disabled in the configuration. + +diff --git a/src/main/java/com/destroystokyo/paper/HopperPusher.java b/src/main/java/com/destroystokyo/paper/HopperPusher.java +new file mode 100644 +index 000000000..aef7c2be9 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/HopperPusher.java +@@ -0,0 +1,59 @@ ++package com.destroystokyo.paper; ++ ++import net.minecraft.server.AxisAlignedBB; ++import net.minecraft.server.BlockPosition; ++import net.minecraft.server.MCUtil; ++import net.minecraft.server.TileEntityHopper; ++import net.minecraft.server.World; ++ ++public interface HopperPusher { ++ ++ default TileEntityHopper findHopper() { ++ BlockPosition pos = new BlockPosition(getX(), getY(), getZ()); ++ int startX = pos.getX() - 1; ++ int endX = pos.getX() + 1; ++ int startY = Math.max(0, pos.getY() - 1); ++ int endY = Math.min(255, pos.getY() + 1); ++ int startZ = pos.getZ() - 1; ++ int endZ = pos.getZ() + 1; ++ BlockPosition.PooledBlockPosition adjacentPos = BlockPosition.PooledBlockPosition.aquire(); ++ for (int x = startX; x <= endX; x++) { ++ for (int y = startY; y <= endY; y++) { ++ for (int z = startZ; z <= endZ; z++) { ++ adjacentPos.setValues(x, y, z); ++ TileEntityHopper hopper = MCUtil.getHopper(getWorld(), adjacentPos); ++ if (hopper == null) continue; // Avoid playing with the bounding boxes, if at all possible ++ AxisAlignedBB hopperBoundingBox = hopper.getHopperLookupBoundingBox(); ++ /* ++ * Check if the entity's bounding box intersects with the hopper's lookup box. ++ * This operation doesn't work both ways! ++ * Make sure you check if the entity's box intersects the hopper's box, not vice versa! ++ */ ++ if (this.getBoundingBox().intersects(hopperBoundingBox)) { ++ return hopper; ++ } ++ } ++ } ++ } ++ adjacentPos.free(); ++ return null; ++ } ++ ++ boolean acceptItem(TileEntityHopper hopper); ++ ++ default boolean tryPutInHopper() { ++ if (!getWorld().paperConfig.isHopperPushBased) return false; ++ TileEntityHopper hopper = findHopper(); ++ return hopper != null && hopper.canAcceptItems() && acceptItem(hopper); ++ } ++ ++ AxisAlignedBB getBoundingBox(); ++ ++ World getWorld(); ++ ++ double getX(); ++ ++ double getY(); ++ ++ double getZ(); ++} +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 7bd745a27..894d40662 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -340,4 +340,9 @@ public class PaperWorldConfig { + private void altFallingBlockOnGround() { + altFallingBlockOnGround = getBoolean("use-alternate-fallingblock-onGround-detection", false); + } ++ ++ public boolean isHopperPushBased; ++ private void isHopperPushBased() { ++ isHopperPushBased = getBoolean("hopper.push-based", false); ++ } + } +diff --git a/src/main/java/net/minecraft/server/AxisAlignedBB.java b/src/main/java/net/minecraft/server/AxisAlignedBB.java +index 1eb9c2da8..c88b76a79 100644 +--- a/src/main/java/net/minecraft/server/AxisAlignedBB.java ++++ b/src/main/java/net/minecraft/server/AxisAlignedBB.java +@@ -235,6 +235,7 @@ public class AxisAlignedBB { + } + } + ++ public final boolean intersects(AxisAlignedBB intersecting) { return this.c(intersecting); } // Paper - OBFHELPER + public boolean c(AxisAlignedBB axisalignedbb) { + return this.a(axisalignedbb.a, axisalignedbb.b, axisalignedbb.c, axisalignedbb.d, axisalignedbb.e, axisalignedbb.f); + } +diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java +index 008ed206d..b3c1f550c 100644 +--- a/src/main/java/net/minecraft/server/BlockPosition.java ++++ b/src/main/java/net/minecraft/server/BlockPosition.java +@@ -250,6 +250,7 @@ public class BlockPosition extends BaseBlockPosition { + super(i, j, k); + } + ++ public static BlockPosition.PooledBlockPosition aquire() { return s(); } // Paper - OBFHELPER + public static BlockPosition.PooledBlockPosition s() { + return e(0, 0, 0); + } +@@ -276,6 +277,7 @@ public class BlockPosition extends BaseBlockPosition { + return new BlockPosition.PooledBlockPosition(i, j, k); + } + ++ public void free() { t(); } // Paper - OBFHELPER + public void t() { + List list = BlockPosition.PooledBlockPosition.g; + +@@ -393,6 +395,7 @@ public class BlockPosition extends BaseBlockPosition { + return this.d; + } + ++ public void setValues(int x, int y, int z) { c(x, y, z); } // Paper - OBFHELPER + public BlockPosition.MutableBlockPosition c(int i, int j, int k) { + this.b = i; + this.c = j; +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 0d1fdd3ee..0479b7551 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -80,6 +80,19 @@ public abstract class Entity implements ICommandListener { + public double locX; + public double locY; + public double locZ; ++ // Paper start - getters to implement HopperPusher ++ public double getX() { ++ return locX; ++ } ++ ++ public double getY() { ++ return locY; ++ } ++ ++ public double getZ() { ++ return locZ; ++ } ++ // Paper end + public double motX; + public double motY; + public double motZ; +diff --git a/src/main/java/net/minecraft/server/EntityItem.java b/src/main/java/net/minecraft/server/EntityItem.java +index 9742afc65..95ca1b8e4 100644 +--- a/src/main/java/net/minecraft/server/EntityItem.java ++++ b/src/main/java/net/minecraft/server/EntityItem.java +@@ -5,8 +5,15 @@ import javax.annotation.Nullable; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + import org.bukkit.event.player.PlayerPickupItemEvent; // CraftBukkit ++import com.destroystokyo.paper.HopperPusher; // Paper + +-public class EntityItem extends Entity { ++// Paper start - implement HopperPusher ++public class EntityItem extends Entity implements HopperPusher { ++ @Override ++ public boolean acceptItem(TileEntityHopper hopper) { ++ return TileEntityHopper.putDropInInventory(null, hopper, this); ++ } ++// Paper end + + private static final Logger b = LogManager.getLogger(); + private static final DataWatcherObject c = DataWatcher.a(EntityItem.class, DataWatcherRegistry.f); +@@ -56,6 +63,7 @@ public class EntityItem extends Entity { + this.die(); + } else { + super.A_(); ++ if (tryPutInHopper()) return; // Paper + // CraftBukkit start - Use wall time for pickup and despawn timers + int elapsedTicks = MinecraftServer.currentTick - this.lastTick; + if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; +@@ -143,6 +151,7 @@ public class EntityItem extends Entity { + // Spigot start - copied from above + @Override + public void inactiveTick() { ++ if (tryPutInHopper()) return; // Paper + // CraftBukkit start - Use wall time for pickup and despawn timers + int elapsedTicks = MinecraftServer.currentTick - this.lastTick; + if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; +diff --git a/src/main/java/net/minecraft/server/EntityMinecartContainer.java b/src/main/java/net/minecraft/server/EntityMinecartContainer.java +index 965aa5c23..04256898b 100644 +--- a/src/main/java/net/minecraft/server/EntityMinecartContainer.java ++++ b/src/main/java/net/minecraft/server/EntityMinecartContainer.java +@@ -7,6 +7,7 @@ import javax.annotation.Nullable; + import java.util.List; + import org.bukkit.Location; + ++import com.destroystokyo.paper.HopperPusher; // Paper + import com.destroystokyo.paper.loottable.CraftLootableInventoryData; // Paper + import com.destroystokyo.paper.loottable.CraftLootableInventory; // Paper + import com.destroystokyo.paper.loottable.LootableInventory; // Paper +@@ -15,7 +16,25 @@ import org.bukkit.entity.HumanEntity; + import org.bukkit.inventory.InventoryHolder; + // CraftBukkit end + +-public abstract class EntityMinecartContainer extends EntityMinecartAbstract implements ITileInventory, ILootable, CraftLootableInventory { // Paper ++// Paper start - push into hoppers ++public abstract class EntityMinecartContainer extends EntityMinecartAbstract implements ITileInventory, ILootable, CraftLootableInventory, HopperPusher { // Paper - CraftLootableInventory ++ @Override ++ public boolean acceptItem(TileEntityHopper hopper) { ++ return TileEntityHopper.acceptItem(hopper, this); ++ } ++ ++ @Override ++ public void A_() { ++ super.A_(); ++ tryPutInHopper(); ++ } ++ ++ @Override ++ public void inactiveTick() { ++ super.inactiveTick(); ++ tryPutInHopper(); ++ } ++ // Paper end + + private NonNullList items; + private boolean b; +diff --git a/src/main/java/net/minecraft/server/IHopper.java b/src/main/java/net/minecraft/server/IHopper.java +index 804215a1c..e830d8390 100644 +--- a/src/main/java/net/minecraft/server/IHopper.java ++++ b/src/main/java/net/minecraft/server/IHopper.java +@@ -4,9 +4,9 @@ public interface IHopper extends IInventory { + + World getWorld(); + +- double E(); ++ double E(); default double getX() { return E(); } // Paper - OBFHELPER + +- double F(); ++ double F(); default double getY() { return F(); } // Paper - OBFHELPER + +- double G(); ++ double G(); default double getZ() { return G(); } // Paper - OBFHELPER + } +diff --git a/src/main/java/net/minecraft/server/TileEntityHopper.java b/src/main/java/net/minecraft/server/TileEntityHopper.java +index 44b6ecc5d..022e64520 100644 +--- a/src/main/java/net/minecraft/server/TileEntityHopper.java ++++ b/src/main/java/net/minecraft/server/TileEntityHopper.java +@@ -126,6 +126,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + } + + private boolean o() { ++ mayAcceptItems = false; // Paper - at the beginning of a tick, assume we can't accept items + if (this.world != null && !this.world.isClientSide) { + if (!this.J() && BlockHopper.f(this.v())) { + boolean flag = false; +@@ -135,6 +136,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + } + + if (!this.r()) { ++ mayAcceptItems = true; // Paper - flag this hopper to be able to accept items + flag = a((IHopper) this) || flag; + } + +@@ -150,6 +152,14 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + } + } + ++ // Paper start ++ private boolean mayAcceptItems = false; ++ ++ public boolean canAcceptItems() { ++ return mayAcceptItems; ++ } ++ // Paper end ++ + private boolean p() { + Iterator iterator = this.items.iterator(); + +@@ -302,8 +312,15 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + return true; + } + ++ // Paper start - split methods, and only do entity lookup if in pull mode + public static boolean a(IHopper ihopper) { +- IInventory iinventory = b(ihopper); ++ IInventory iinventory = getInventory(ihopper, !(ihopper instanceof TileEntityHopper) || !ihopper.getWorld().paperConfig.isHopperPushBased); ++ ++ return acceptItem(ihopper, iinventory); ++ } ++ ++ public static boolean acceptItem(IHopper ihopper, IInventory iinventory) { ++ // Paper end + + if (iinventory != null) { + EnumDirection enumdirection = EnumDirection.DOWN; +@@ -334,8 +351,8 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + } + } + } +- } else { +- Iterator iterator = a(ihopper.getWorld(), ihopper.E(), ihopper.F(), ihopper.G()).iterator(); ++ } else if (!ihopper.getWorld().paperConfig.isHopperPushBased || !(ihopper instanceof TileEntityHopper)) { // Paper - only search for entities in 'pull mode' ++ Iterator iterator = a(ihopper.getWorld(), ihopper.E(), ihopper.F(), ihopper.G()).iterator(); // Change getHopperLookupBoundingBox() if this ever changes + + while (iterator.hasNext()) { + EntityItem entityitem = (EntityItem) iterator.next(); +@@ -401,6 +418,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + return false; + } + ++ public static boolean putDropInInventory(IInventory iinventory, IInventory iinventory1, EntityItem entityitem) { return a(iinventory, iinventory1, entityitem); } // Paper - OBFHELPER + public static boolean a(IInventory iinventory, IInventory iinventory1, EntityItem entityitem) { + boolean flag = false; + +@@ -506,18 +524,44 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + private IInventory I() { + EnumDirection enumdirection = BlockHopper.e(this.v()); + +- return b(this.getWorld(), this.E() + (double) enumdirection.getAdjacentX(), this.F() + (double) enumdirection.getAdjacentY(), this.G() + (double) enumdirection.getAdjacentZ()); ++ // Paper start - don't search for entities in push mode ++ World world = getWorld(); ++ return getInventory(world, this.E() + (double) enumdirection.getAdjacentX(), this.F() + (double) enumdirection.getAdjacentY(), this.G() + (double) enumdirection.getAdjacentZ(), !world.paperConfig.isHopperPushBased); ++ // Paper end + } + +- public static IInventory b(IHopper ihopper) { +- return b(ihopper.getWorld(), ihopper.E(), ihopper.F() + 1.0D, ihopper.G()); ++ // Paper start - add option to search for entities ++ public static IInventory b(IHopper hopper) { ++ return getInventory(hopper, true); ++ } ++ ++ public static IInventory getInventory(IHopper ihopper, boolean searchForEntities) { ++ return getInventory(ihopper.getWorld(), ihopper.E(), ihopper.F() + 1.0D, ihopper.G(), searchForEntities); ++ // Paper end + } + + public static List a(World world, double d0, double d1, double d2) { +- return world.a(EntityItem.class, new AxisAlignedBB(d0 - 0.5D, d1, d2 - 0.5D, d0 + 0.5D, d1 + 1.5D, d2 + 0.5D), IEntitySelector.a); ++ return world.a(EntityItem.class, new AxisAlignedBB(d0 - 0.5D, d1, d2 - 0.5D, d0 + 0.5D, d1 + 1.5D, d2 + 0.5D), IEntitySelector.a); // Change getHopperLookupBoundingBox(double, double, double) if the bounding box calculation is ever changed ++ } ++ ++ // Paper start ++ public AxisAlignedBB getHopperLookupBoundingBox() { ++ return getHopperLookupBoundingBox(this.getX(), this.getY(), this.getZ()); + } + ++ private static AxisAlignedBB getHopperLookupBoundingBox(double d0, double d1, double d2) { ++ // Change this if a(World, double, double, double) above ever changes ++ return new AxisAlignedBB(d0 - 0.5D, d1, d2 - 0.5D, d0 + 0.5D, d1 + 1.5D, d2 + 0.5D); ++ } ++ // Paper end ++ ++ // Paper start - add option to searchForEntities + public static IInventory b(World world, double d0, double d1, double d2) { ++ return getInventory(world, d0, d1, d2, true); ++ } ++ ++ public static IInventory getInventory(World world, double d0, double d1, double d2, boolean searchForEntities) { ++ // Paper end + Object object = null; + int i = MathHelper.floor(d0); + int j = MathHelper.floor(d1); +@@ -537,7 +581,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + } + } + +- if (object == null) { ++ if (object == null && searchForEntities) { // Paper - only if searchForEntities + 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.c); + + if (!list.isEmpty()) { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0144-Delay-Chunk-Unloads-based-on-Player-Movement.patch b/Spigot-Server-Patches/0144-Delay-Chunk-Unloads-based-on-Player-Movement.patch new file mode 100644 index 0000000000..6faf012e78 --- /dev/null +++ b/Spigot-Server-Patches/0144-Delay-Chunk-Unloads-based-on-Player-Movement.patch @@ -0,0 +1,144 @@ +From 42eb9c7ff29419933afefaaa21c757752b817666 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 is maintained separately from ChunkGC. + +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 894d40662..04861f146 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -345,4 +345,13 @@ public class PaperWorldConfig { + private void isHopperPushBased() { + isHopperPushBased = getBoolean("hopper.push-based", false); + } ++ ++ 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 *= 1000; ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java +index 98f2cff15..88437d77a 100644 +--- a/src/main/java/net/minecraft/server/Chunk.java ++++ b/src/main/java/net/minecraft/server/Chunk.java +@@ -30,6 +30,7 @@ public class Chunk { + private boolean j; + public final World world; + public final int[] heightMap; ++ public Long scheduledForUnload; // Paper - delay chunk unloads + public final int locX; + public final int locZ; + private boolean m; +diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java +index eb3225ef2..81b9bb884 100644 +--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java +@@ -315,6 +315,19 @@ public class ChunkProviderServer implements IChunkProvider { + + activityAccountant.endActivity(); // Spigot + } ++ // Paper start - delayed chunk unloads ++ long now = System.currentTimeMillis(); ++ long unloadAfter = world.paperConfig.delayChunkUnloadsBy; ++ if (unloadAfter > 0) { ++ //noinspection Convert2streamapi ++ for (Chunk chunk : chunks.values()) { ++ if (chunk.scheduledForUnload != null && now - chunk.scheduledForUnload > unloadAfter) { ++ chunk.scheduledForUnload = null; ++ unload(chunk); ++ } ++ } ++ } ++ // Paper end + + this.chunkLoader.a(); + } +diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java +index dd40e98c8..f109e986d 100644 +--- a/src/main/java/net/minecraft/server/PlayerChunk.java ++++ b/src/main/java/net/minecraft/server/PlayerChunk.java +@@ -32,8 +32,16 @@ public class PlayerChunk { + public void run() { + loadInProgress = false; + PlayerChunk.this.chunk = PlayerChunk.this.playerChunkMap.getWorld().getChunkProviderServer().getOrLoadChunkAt(location.x, location.z); ++ markChunkUsed(); // Paper - delay chunk unloads + } + }; ++ // Paper start - delay chunk unloads ++ public final void markChunkUsed() { ++ if (chunk != null && chunk.scheduledForUnload != null) { ++ chunk.scheduledForUnload = null; ++ } ++ } ++ // Paper end + // CraftBukkit end + + public PlayerChunk(PlayerChunkMap playerchunkmap, int i, int j) { +@@ -42,6 +50,7 @@ public class PlayerChunk { + // CraftBukkit start + loadInProgress = true; + this.chunk = playerchunkmap.getWorld().getChunkProviderServer().getChunkAt(i, j, loadedRunnable, false); ++ markChunkUsed(); // Paper - delay chunk unloads + // CraftBukkit end + } + +@@ -110,6 +119,7 @@ public class PlayerChunk { + if (!loadInProgress) { + loadInProgress = true; + this.chunk = playerChunkMap.getWorld().getChunkProviderServer().getChunkAt(this.location.x, this.location.z, loadedRunnable, flag); ++ markChunkUsed(); // Paper - delay chunk unloads + } + // CraftBukkit end + +diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java +index 5b27bd1c5..b163346be 100644 +--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java +@@ -487,7 +487,13 @@ public class PlayerChunkMap { + Chunk chunk = playerchunk.f(); + + if (chunk != null) { +- this.getWorld().getChunkProviderServer().unload(chunk); ++ // Paper start - delay chunk unloads ++ if (world.paperConfig.delayChunkUnloadsBy <= 0) { ++ this.getWorld().getChunkProviderServer().unload(chunk); ++ } else { ++ chunk.scheduledForUnload = System.currentTimeMillis(); ++ } ++ // Paper end + } + + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 9965235ab..3f8859a1f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1558,7 +1558,7 @@ public class CraftWorld implements World { + ChunkProviderServer cps = world.getChunkProviderServer(); + for (net.minecraft.server.Chunk chunk : cps.chunks.values()) { + // If in use, skip it +- if (isChunkInUse(chunk.locX, chunk.locZ)) { ++ if (isChunkInUse(chunk.locX, chunk.locZ) || chunk.scheduledForUnload != null) { // Paper - delayed chunk unloads + continue; + } + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0144-Make-entities-look-for-hoppers.patch b/Spigot-Server-Patches/0144-Make-entities-look-for-hoppers.patch deleted file mode 100644 index 99d810654c..0000000000 --- a/Spigot-Server-Patches/0144-Make-entities-look-for-hoppers.patch +++ /dev/null @@ -1,382 +0,0 @@ -From 93a2af841f6352063d22593927b334434bae3383 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Sat, 18 Jun 2016 01:01:37 -0500 -Subject: [PATCH] Make entities look for hoppers - -Every tick hoppers try and find an block-inventory to extract from. -If no tile entity is above the hopper (which there often isn't) it will do a bounding box search for minecart chests and minecart hoppers. -If it can't find an inventory, it will then look for a dropped item, which is another bounding box search. -This patch eliminates that expensive check by having dropped items and minecart hoppers/chests look for hoppers instead. -Hoppers are tile entities meaning you can do a simple tile entity lookup to find the nearest hopper in range. -Pushing out of hoppers causes a bouding box lookup, which this patch replaces with a tile entity lookup. - -This patch may causes a decrease in the performance of dropped items, which is why it can be disabled in the configuration. - -diff --git a/src/main/java/com/destroystokyo/paper/HopperPusher.java b/src/main/java/com/destroystokyo/paper/HopperPusher.java -new file mode 100644 -index 000000000..aef7c2be9 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/HopperPusher.java -@@ -0,0 +1,59 @@ -+package com.destroystokyo.paper; -+ -+import net.minecraft.server.AxisAlignedBB; -+import net.minecraft.server.BlockPosition; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.TileEntityHopper; -+import net.minecraft.server.World; -+ -+public interface HopperPusher { -+ -+ default TileEntityHopper findHopper() { -+ BlockPosition pos = new BlockPosition(getX(), getY(), getZ()); -+ int startX = pos.getX() - 1; -+ int endX = pos.getX() + 1; -+ int startY = Math.max(0, pos.getY() - 1); -+ int endY = Math.min(255, pos.getY() + 1); -+ int startZ = pos.getZ() - 1; -+ int endZ = pos.getZ() + 1; -+ BlockPosition.PooledBlockPosition adjacentPos = BlockPosition.PooledBlockPosition.aquire(); -+ for (int x = startX; x <= endX; x++) { -+ for (int y = startY; y <= endY; y++) { -+ for (int z = startZ; z <= endZ; z++) { -+ adjacentPos.setValues(x, y, z); -+ TileEntityHopper hopper = MCUtil.getHopper(getWorld(), adjacentPos); -+ if (hopper == null) continue; // Avoid playing with the bounding boxes, if at all possible -+ AxisAlignedBB hopperBoundingBox = hopper.getHopperLookupBoundingBox(); -+ /* -+ * Check if the entity's bounding box intersects with the hopper's lookup box. -+ * This operation doesn't work both ways! -+ * Make sure you check if the entity's box intersects the hopper's box, not vice versa! -+ */ -+ if (this.getBoundingBox().intersects(hopperBoundingBox)) { -+ return hopper; -+ } -+ } -+ } -+ } -+ adjacentPos.free(); -+ return null; -+ } -+ -+ boolean acceptItem(TileEntityHopper hopper); -+ -+ default boolean tryPutInHopper() { -+ if (!getWorld().paperConfig.isHopperPushBased) return false; -+ TileEntityHopper hopper = findHopper(); -+ return hopper != null && hopper.canAcceptItems() && acceptItem(hopper); -+ } -+ -+ AxisAlignedBB getBoundingBox(); -+ -+ World getWorld(); -+ -+ double getX(); -+ -+ double getY(); -+ -+ double getZ(); -+} -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 7bd745a27..894d40662 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -340,4 +340,9 @@ public class PaperWorldConfig { - private void altFallingBlockOnGround() { - altFallingBlockOnGround = getBoolean("use-alternate-fallingblock-onGround-detection", false); - } -+ -+ public boolean isHopperPushBased; -+ private void isHopperPushBased() { -+ isHopperPushBased = getBoolean("hopper.push-based", false); -+ } - } -diff --git a/src/main/java/net/minecraft/server/AxisAlignedBB.java b/src/main/java/net/minecraft/server/AxisAlignedBB.java -index 1eb9c2da8..c88b76a79 100644 ---- a/src/main/java/net/minecraft/server/AxisAlignedBB.java -+++ b/src/main/java/net/minecraft/server/AxisAlignedBB.java -@@ -235,6 +235,7 @@ public class AxisAlignedBB { - } - } - -+ public final boolean intersects(AxisAlignedBB intersecting) { return this.c(intersecting); } // Paper - OBFHELPER - public boolean c(AxisAlignedBB axisalignedbb) { - return this.a(axisalignedbb.a, axisalignedbb.b, axisalignedbb.c, axisalignedbb.d, axisalignedbb.e, axisalignedbb.f); - } -diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java -index 008ed206d..b3c1f550c 100644 ---- a/src/main/java/net/minecraft/server/BlockPosition.java -+++ b/src/main/java/net/minecraft/server/BlockPosition.java -@@ -250,6 +250,7 @@ public class BlockPosition extends BaseBlockPosition { - super(i, j, k); - } - -+ public static BlockPosition.PooledBlockPosition aquire() { return s(); } // Paper - OBFHELPER - public static BlockPosition.PooledBlockPosition s() { - return e(0, 0, 0); - } -@@ -276,6 +277,7 @@ public class BlockPosition extends BaseBlockPosition { - return new BlockPosition.PooledBlockPosition(i, j, k); - } - -+ public void free() { t(); } // Paper - OBFHELPER - public void t() { - List list = BlockPosition.PooledBlockPosition.g; - -@@ -393,6 +395,7 @@ public class BlockPosition extends BaseBlockPosition { - return this.d; - } - -+ public void setValues(int x, int y, int z) { c(x, y, z); } // Paper - OBFHELPER - public BlockPosition.MutableBlockPosition c(int i, int j, int k) { - this.b = i; - this.c = j; -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 0d1fdd3ee..0479b7551 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -80,6 +80,19 @@ public abstract class Entity implements ICommandListener { - public double locX; - public double locY; - public double locZ; -+ // Paper start - getters to implement HopperPusher -+ public double getX() { -+ return locX; -+ } -+ -+ public double getY() { -+ return locY; -+ } -+ -+ public double getZ() { -+ return locZ; -+ } -+ // Paper end - public double motX; - public double motY; - public double motZ; -diff --git a/src/main/java/net/minecraft/server/EntityItem.java b/src/main/java/net/minecraft/server/EntityItem.java -index 9742afc65..95ca1b8e4 100644 ---- a/src/main/java/net/minecraft/server/EntityItem.java -+++ b/src/main/java/net/minecraft/server/EntityItem.java -@@ -5,8 +5,15 @@ import javax.annotation.Nullable; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - import org.bukkit.event.player.PlayerPickupItemEvent; // CraftBukkit -+import com.destroystokyo.paper.HopperPusher; // Paper - --public class EntityItem extends Entity { -+// Paper start - implement HopperPusher -+public class EntityItem extends Entity implements HopperPusher { -+ @Override -+ public boolean acceptItem(TileEntityHopper hopper) { -+ return TileEntityHopper.putDropInInventory(null, hopper, this); -+ } -+// Paper end - - private static final Logger b = LogManager.getLogger(); - private static final DataWatcherObject c = DataWatcher.a(EntityItem.class, DataWatcherRegistry.f); -@@ -56,6 +63,7 @@ public class EntityItem extends Entity { - this.die(); - } else { - super.A_(); -+ if (tryPutInHopper()) return; // Paper - // CraftBukkit start - Use wall time for pickup and despawn timers - int elapsedTicks = MinecraftServer.currentTick - this.lastTick; - if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; -@@ -143,6 +151,7 @@ public class EntityItem extends Entity { - // Spigot start - copied from above - @Override - public void inactiveTick() { -+ if (tryPutInHopper()) return; // Paper - // CraftBukkit start - Use wall time for pickup and despawn timers - int elapsedTicks = MinecraftServer.currentTick - this.lastTick; - if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; -diff --git a/src/main/java/net/minecraft/server/EntityMinecartContainer.java b/src/main/java/net/minecraft/server/EntityMinecartContainer.java -index 965aa5c23..04256898b 100644 ---- a/src/main/java/net/minecraft/server/EntityMinecartContainer.java -+++ b/src/main/java/net/minecraft/server/EntityMinecartContainer.java -@@ -7,6 +7,7 @@ import javax.annotation.Nullable; - import java.util.List; - import org.bukkit.Location; - -+import com.destroystokyo.paper.HopperPusher; // Paper - import com.destroystokyo.paper.loottable.CraftLootableInventoryData; // Paper - import com.destroystokyo.paper.loottable.CraftLootableInventory; // Paper - import com.destroystokyo.paper.loottable.LootableInventory; // Paper -@@ -15,7 +16,25 @@ import org.bukkit.entity.HumanEntity; - import org.bukkit.inventory.InventoryHolder; - // CraftBukkit end - --public abstract class EntityMinecartContainer extends EntityMinecartAbstract implements ITileInventory, ILootable, CraftLootableInventory { // Paper -+// Paper start - push into hoppers -+public abstract class EntityMinecartContainer extends EntityMinecartAbstract implements ITileInventory, ILootable, CraftLootableInventory, HopperPusher { // Paper - CraftLootableInventory -+ @Override -+ public boolean acceptItem(TileEntityHopper hopper) { -+ return TileEntityHopper.acceptItem(hopper, this); -+ } -+ -+ @Override -+ public void A_() { -+ super.A_(); -+ tryPutInHopper(); -+ } -+ -+ @Override -+ public void inactiveTick() { -+ super.inactiveTick(); -+ tryPutInHopper(); -+ } -+ // Paper end - - private NonNullList items; - private boolean b; -diff --git a/src/main/java/net/minecraft/server/IHopper.java b/src/main/java/net/minecraft/server/IHopper.java -index 804215a1c..e830d8390 100644 ---- a/src/main/java/net/minecraft/server/IHopper.java -+++ b/src/main/java/net/minecraft/server/IHopper.java -@@ -4,9 +4,9 @@ public interface IHopper extends IInventory { - - World getWorld(); - -- double E(); -+ double E(); default double getX() { return E(); } // Paper - OBFHELPER - -- double F(); -+ double F(); default double getY() { return F(); } // Paper - OBFHELPER - -- double G(); -+ double G(); default double getZ() { return G(); } // Paper - OBFHELPER - } -diff --git a/src/main/java/net/minecraft/server/TileEntityHopper.java b/src/main/java/net/minecraft/server/TileEntityHopper.java -index 44b6ecc5d..022e64520 100644 ---- a/src/main/java/net/minecraft/server/TileEntityHopper.java -+++ b/src/main/java/net/minecraft/server/TileEntityHopper.java -@@ -126,6 +126,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - } - - private boolean o() { -+ mayAcceptItems = false; // Paper - at the beginning of a tick, assume we can't accept items - if (this.world != null && !this.world.isClientSide) { - if (!this.J() && BlockHopper.f(this.v())) { - boolean flag = false; -@@ -135,6 +136,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - } - - if (!this.r()) { -+ mayAcceptItems = true; // Paper - flag this hopper to be able to accept items - flag = a((IHopper) this) || flag; - } - -@@ -150,6 +152,14 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - } - } - -+ // Paper start -+ private boolean mayAcceptItems = false; -+ -+ public boolean canAcceptItems() { -+ return mayAcceptItems; -+ } -+ // Paper end -+ - private boolean p() { - Iterator iterator = this.items.iterator(); - -@@ -302,8 +312,15 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - return true; - } - -+ // Paper start - split methods, and only do entity lookup if in pull mode - public static boolean a(IHopper ihopper) { -- IInventory iinventory = b(ihopper); -+ IInventory iinventory = getInventory(ihopper, !(ihopper instanceof TileEntityHopper) || !ihopper.getWorld().paperConfig.isHopperPushBased); -+ -+ return acceptItem(ihopper, iinventory); -+ } -+ -+ public static boolean acceptItem(IHopper ihopper, IInventory iinventory) { -+ // Paper end - - if (iinventory != null) { - EnumDirection enumdirection = EnumDirection.DOWN; -@@ -334,8 +351,8 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - } - } - } -- } else { -- Iterator iterator = a(ihopper.getWorld(), ihopper.E(), ihopper.F(), ihopper.G()).iterator(); -+ } else if (!ihopper.getWorld().paperConfig.isHopperPushBased || !(ihopper instanceof TileEntityHopper)) { // Paper - only search for entities in 'pull mode' -+ Iterator iterator = a(ihopper.getWorld(), ihopper.E(), ihopper.F(), ihopper.G()).iterator(); // Change getHopperLookupBoundingBox() if this ever changes - - while (iterator.hasNext()) { - EntityItem entityitem = (EntityItem) iterator.next(); -@@ -401,6 +418,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - return false; - } - -+ public static boolean putDropInInventory(IInventory iinventory, IInventory iinventory1, EntityItem entityitem) { return a(iinventory, iinventory1, entityitem); } // Paper - OBFHELPER - public static boolean a(IInventory iinventory, IInventory iinventory1, EntityItem entityitem) { - boolean flag = false; - -@@ -506,18 +524,44 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - private IInventory I() { - EnumDirection enumdirection = BlockHopper.e(this.v()); - -- return b(this.getWorld(), this.E() + (double) enumdirection.getAdjacentX(), this.F() + (double) enumdirection.getAdjacentY(), this.G() + (double) enumdirection.getAdjacentZ()); -+ // Paper start - don't search for entities in push mode -+ World world = getWorld(); -+ return getInventory(world, this.E() + (double) enumdirection.getAdjacentX(), this.F() + (double) enumdirection.getAdjacentY(), this.G() + (double) enumdirection.getAdjacentZ(), !world.paperConfig.isHopperPushBased); -+ // Paper end - } - -- public static IInventory b(IHopper ihopper) { -- return b(ihopper.getWorld(), ihopper.E(), ihopper.F() + 1.0D, ihopper.G()); -+ // Paper start - add option to search for entities -+ public static IInventory b(IHopper hopper) { -+ return getInventory(hopper, true); -+ } -+ -+ public static IInventory getInventory(IHopper ihopper, boolean searchForEntities) { -+ return getInventory(ihopper.getWorld(), ihopper.E(), ihopper.F() + 1.0D, ihopper.G(), searchForEntities); -+ // Paper end - } - - public static List a(World world, double d0, double d1, double d2) { -- return world.a(EntityItem.class, new AxisAlignedBB(d0 - 0.5D, d1, d2 - 0.5D, d0 + 0.5D, d1 + 1.5D, d2 + 0.5D), IEntitySelector.a); -+ return world.a(EntityItem.class, new AxisAlignedBB(d0 - 0.5D, d1, d2 - 0.5D, d0 + 0.5D, d1 + 1.5D, d2 + 0.5D), IEntitySelector.a); // Change getHopperLookupBoundingBox(double, double, double) if the bounding box calculation is ever changed -+ } -+ -+ // Paper start -+ public AxisAlignedBB getHopperLookupBoundingBox() { -+ return getHopperLookupBoundingBox(this.getX(), this.getY(), this.getZ()); - } - -+ private static AxisAlignedBB getHopperLookupBoundingBox(double d0, double d1, double d2) { -+ // Change this if a(World, double, double, double) above ever changes -+ return new AxisAlignedBB(d0 - 0.5D, d1, d2 - 0.5D, d0 + 0.5D, d1 + 1.5D, d2 + 0.5D); -+ } -+ // Paper end -+ -+ // Paper start - add option to searchForEntities - public static IInventory b(World world, double d0, double d1, double d2) { -+ return getInventory(world, d0, d1, d2, true); -+ } -+ -+ public static IInventory getInventory(World world, double d0, double d1, double d2, boolean searchForEntities) { -+ // Paper end - Object object = null; - int i = MathHelper.floor(d0); - int j = MathHelper.floor(d1); -@@ -537,7 +581,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - } - } - -- if (object == null) { -+ if (object == null && searchForEntities) { // Paper - only if searchForEntities - 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.c); - - if (!list.isEmpty()) { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0145-Delay-Chunk-Unloads-based-on-Player-Movement.patch b/Spigot-Server-Patches/0145-Delay-Chunk-Unloads-based-on-Player-Movement.patch deleted file mode 100644 index e5cf53bf95..0000000000 --- a/Spigot-Server-Patches/0145-Delay-Chunk-Unloads-based-on-Player-Movement.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 47bc97578256db7c8dc522c0810655ebc94b512a 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 is maintained separately from ChunkGC. - -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 894d40662..04861f146 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -345,4 +345,13 @@ public class PaperWorldConfig { - private void isHopperPushBased() { - isHopperPushBased = getBoolean("hopper.push-based", false); - } -+ -+ 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 *= 1000; -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java -index 98f2cff15..88437d77a 100644 ---- a/src/main/java/net/minecraft/server/Chunk.java -+++ b/src/main/java/net/minecraft/server/Chunk.java -@@ -30,6 +30,7 @@ public class Chunk { - private boolean j; - public final World world; - public final int[] heightMap; -+ public Long scheduledForUnload; // Paper - delay chunk unloads - public final int locX; - public final int locZ; - private boolean m; -diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java -index 57ae50d2e..0a8e09e5e 100644 ---- a/src/main/java/net/minecraft/server/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java -@@ -315,6 +315,19 @@ public class ChunkProviderServer implements IChunkProvider { - - activityAccountant.endActivity(); // Spigot - } -+ // Paper start - delayed chunk unloads -+ long now = System.currentTimeMillis(); -+ long unloadAfter = world.paperConfig.delayChunkUnloadsBy; -+ if (unloadAfter > 0) { -+ //noinspection Convert2streamapi -+ for (Chunk chunk : chunks.values()) { -+ if (chunk.scheduledForUnload != null && now - chunk.scheduledForUnload > unloadAfter) { -+ chunk.scheduledForUnload = null; -+ unload(chunk); -+ } -+ } -+ } -+ // Paper end - - this.chunkLoader.a(); - } -diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java -index dd40e98c8..f109e986d 100644 ---- a/src/main/java/net/minecraft/server/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/PlayerChunk.java -@@ -32,8 +32,16 @@ public class PlayerChunk { - public void run() { - loadInProgress = false; - PlayerChunk.this.chunk = PlayerChunk.this.playerChunkMap.getWorld().getChunkProviderServer().getOrLoadChunkAt(location.x, location.z); -+ markChunkUsed(); // Paper - delay chunk unloads - } - }; -+ // Paper start - delay chunk unloads -+ public final void markChunkUsed() { -+ if (chunk != null && chunk.scheduledForUnload != null) { -+ chunk.scheduledForUnload = null; -+ } -+ } -+ // Paper end - // CraftBukkit end - - public PlayerChunk(PlayerChunkMap playerchunkmap, int i, int j) { -@@ -42,6 +50,7 @@ public class PlayerChunk { - // CraftBukkit start - loadInProgress = true; - this.chunk = playerchunkmap.getWorld().getChunkProviderServer().getChunkAt(i, j, loadedRunnable, false); -+ markChunkUsed(); // Paper - delay chunk unloads - // CraftBukkit end - } - -@@ -110,6 +119,7 @@ public class PlayerChunk { - if (!loadInProgress) { - loadInProgress = true; - this.chunk = playerChunkMap.getWorld().getChunkProviderServer().getChunkAt(this.location.x, this.location.z, loadedRunnable, flag); -+ markChunkUsed(); // Paper - delay chunk unloads - } - // CraftBukkit end - -diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java -index 5b27bd1c5..b163346be 100644 ---- a/src/main/java/net/minecraft/server/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java -@@ -487,7 +487,13 @@ public class PlayerChunkMap { - Chunk chunk = playerchunk.f(); - - if (chunk != null) { -- this.getWorld().getChunkProviderServer().unload(chunk); -+ // Paper start - delay chunk unloads -+ if (world.paperConfig.delayChunkUnloadsBy <= 0) { -+ this.getWorld().getChunkProviderServer().unload(chunk); -+ } else { -+ chunk.scheduledForUnload = System.currentTimeMillis(); -+ } -+ // Paper end - } - - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 9965235ab..3f8859a1f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1558,7 +1558,7 @@ public class CraftWorld implements World { - ChunkProviderServer cps = world.getChunkProviderServer(); - for (net.minecraft.server.Chunk chunk : cps.chunks.values()) { - // If in use, skip it -- if (isChunkInUse(chunk.locX, chunk.locZ)) { -+ if (isChunkInUse(chunk.locX, chunk.locZ) || chunk.scheduledForUnload != null) { // Paper - delayed chunk unloads - continue; - } - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0145-Toggleable-Elytra-Wall-Damage.patch b/Spigot-Server-Patches/0145-Toggleable-Elytra-Wall-Damage.patch new file mode 100644 index 0000000000..ecdf42102c --- /dev/null +++ b/Spigot-Server-Patches/0145-Toggleable-Elytra-Wall-Damage.patch @@ -0,0 +1,45 @@ +From dcfa2ba7251ae9627d3dda488cbdf7e3cc31892e Mon Sep 17 00:00:00 2001 +From: Jadon Fowler +Date: Sat, 18 Jun 2016 23:13:59 -0700 +Subject: [PATCH] Toggleable Elytra Wall Damage + +Instead of calculating the damage taken from hitting a wall, you can +disable it in the config. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 04861f146..dc96bd7f4 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -354,4 +354,9 @@ public class PaperWorldConfig { + delayChunkUnloadsBy *= 1000; + } + } ++ ++ public boolean elytraHitWallDamage = true; ++ private void elytraHitWallDamage() { ++ elytraHitWallDamage = getBoolean("elytra-hit-wall-damage", true); ++ } + } +diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java +index ec901150d..b8ac99e5d 100644 +--- a/src/main/java/net/minecraft/server/EntityLiving.java ++++ b/src/main/java/net/minecraft/server/EntityLiving.java +@@ -1690,6 +1690,7 @@ public abstract class EntityLiving extends Entity { + this.motY = 0.30000001192092896D; + } + } else if (this.cH()) { ++ if (world.paperConfig.elytraHitWallDamage) { // Paper start - Toggleable Elytra Wall Damage + if (this.motY > -0.5D) { + this.fallDistance = 1.0F; + } +@@ -1739,6 +1740,7 @@ public abstract class EntityLiving extends Entity { + this.damageEntity(DamageSource.FLY_INTO_WALL, f7); + } + } ++ } // Paper end - Elyta Wall Damage if statement + + if (this.onGround && !this.world.isClientSide) { + if (getFlag(7) && !CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) // CraftBukkit +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0146-Fix-Double-World-Add-issues.patch b/Spigot-Server-Patches/0146-Fix-Double-World-Add-issues.patch new file mode 100644 index 0000000000..a77b14b155 --- /dev/null +++ b/Spigot-Server-Patches/0146-Fix-Double-World-Add-issues.patch @@ -0,0 +1,37 @@ +From 54c81de7d1b0aa3d7741b255d4fda4f562d20c8a 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/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java +index 721a3cd81..90d069539 100644 +--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java ++++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java +@@ -508,7 +508,7 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { + } + + public static void a(Entity entity, World world, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { +- if (world.addEntity(entity, reason) && entity.isVehicle()) { ++ if (!entity.valid && world.addEntity(entity, reason) && entity.isVehicle()) { // Paper + // CraftBukkit end + Iterator iterator = entity.bx().iterator(); + +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 7ed3a0677..7900fca57 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -1098,6 +1098,7 @@ public abstract class World implements IBlockAccess { + public boolean addEntity(Entity entity, SpawnReason spawnReason) { // Changed signature, added SpawnReason + org.spigotmc.AsyncCatcher.catchOp( "entity add"); // Spigot + if (entity == null) return false; ++ if (entity.valid) { MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); return true; } // Paper + // CraftBukkit end + int i = MathHelper.floor(entity.locX / 16.0D); + int j = MathHelper.floor(entity.locZ / 16.0D); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0146-Toggleable-Elytra-Wall-Damage.patch b/Spigot-Server-Patches/0146-Toggleable-Elytra-Wall-Damage.patch deleted file mode 100644 index be17bab921..0000000000 --- a/Spigot-Server-Patches/0146-Toggleable-Elytra-Wall-Damage.patch +++ /dev/null @@ -1,45 +0,0 @@ -From bc29002b6c5ff86ac128aee61f9e8d08c20eeeb5 Mon Sep 17 00:00:00 2001 -From: Jadon Fowler -Date: Sat, 18 Jun 2016 23:13:59 -0700 -Subject: [PATCH] Toggleable Elytra Wall Damage - -Instead of calculating the damage taken from hitting a wall, you can -disable it in the config. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 04861f146..dc96bd7f4 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -354,4 +354,9 @@ public class PaperWorldConfig { - delayChunkUnloadsBy *= 1000; - } - } -+ -+ public boolean elytraHitWallDamage = true; -+ private void elytraHitWallDamage() { -+ elytraHitWallDamage = getBoolean("elytra-hit-wall-damage", true); -+ } - } -diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index ec901150d..b8ac99e5d 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -1690,6 +1690,7 @@ public abstract class EntityLiving extends Entity { - this.motY = 0.30000001192092896D; - } - } else if (this.cH()) { -+ if (world.paperConfig.elytraHitWallDamage) { // Paper start - Toggleable Elytra Wall Damage - if (this.motY > -0.5D) { - this.fallDistance = 1.0F; - } -@@ -1739,6 +1740,7 @@ public abstract class EntityLiving extends Entity { - this.damageEntity(DamageSource.FLY_INTO_WALL, f7); - } - } -+ } // Paper end - Elyta Wall Damage if statement - - if (this.onGround && !this.world.isClientSide) { - if (getFlag(7) && !CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) // CraftBukkit --- -2.12.2 - diff --git a/Spigot-Server-Patches/0147-Fix-Double-World-Add-issues.patch b/Spigot-Server-Patches/0147-Fix-Double-World-Add-issues.patch deleted file mode 100644 index 5501f4edb3..0000000000 --- a/Spigot-Server-Patches/0147-Fix-Double-World-Add-issues.patch +++ /dev/null @@ -1,37 +0,0 @@ -From df9b45642a0350faf91c0100855ee2d22435f4ce 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/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -index 721a3cd81..90d069539 100644 ---- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -@@ -508,7 +508,7 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { - } - - public static void a(Entity entity, World world, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { -- if (world.addEntity(entity, reason) && entity.isVehicle()) { -+ if (!entity.valid && world.addEntity(entity, reason) && entity.isVehicle()) { // Paper - // CraftBukkit end - Iterator iterator = entity.bx().iterator(); - -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 7ed3a0677..7900fca57 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -1098,6 +1098,7 @@ public abstract class World implements IBlockAccess { - public boolean addEntity(Entity entity, SpawnReason spawnReason) { // Changed signature, added SpawnReason - org.spigotmc.AsyncCatcher.catchOp( "entity add"); // Spigot - if (entity == null) return false; -+ if (entity.valid) { MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); return true; } // Paper - // CraftBukkit end - int i = MathHelper.floor(entity.locX / 16.0D); - int j = MathHelper.floor(entity.locZ / 16.0D); --- -2.12.2.windows.2 - diff --git a/Spigot-Server-Patches/0147-Fix-Old-Sign-Conversion.patch b/Spigot-Server-Patches/0147-Fix-Old-Sign-Conversion.patch new file mode 100644 index 0000000000..e1c05a0160 --- /dev/null +++ b/Spigot-Server-Patches/0147-Fix-Old-Sign-Conversion.patch @@ -0,0 +1,71 @@ +From 0ae70ecc0b9df6e3dfedfaa196ff7d1484f59294 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/server/DefinedStructure.java b/src/main/java/net/minecraft/server/DefinedStructure.java +index a3dc6fe31..83646341b 100644 +--- a/src/main/java/net/minecraft/server/DefinedStructure.java ++++ b/src/main/java/net/minecraft/server/DefinedStructure.java +@@ -203,9 +203,11 @@ public class DefinedStructure { + definedstructure_blockinfo1.c.setInt("x", blockposition1.getX()); + definedstructure_blockinfo1.c.setInt("y", blockposition1.getY()); + definedstructure_blockinfo1.c.setInt("z", blockposition1.getZ()); ++ tileentity.isLoadingStructure = true; // Paper + tileentity.a(definedstructure_blockinfo1.c); + tileentity.a(definedstructureinfo.b()); + tileentity.a(definedstructureinfo.c()); ++ tileentity.isLoadingStructure = false; // Paper + } + } + } +@@ -600,7 +602,7 @@ public class DefinedStructure { + public IBlockData a(int i) { + IBlockData iblockdata = (IBlockData) this.b.fromId(i); + +- return iblockdata == null ? DefinedStructure.a.a : iblockdata; ++ return iblockdata == null ? a : iblockdata; // Paper - decompile error - Blocks.AIR.getBlockData() + } + + public Iterator iterator() { +diff --git a/src/main/java/net/minecraft/server/TileEntity.java b/src/main/java/net/minecraft/server/TileEntity.java +index d2662ae14..e6b79a571 100644 +--- a/src/main/java/net/minecraft/server/TileEntity.java ++++ b/src/main/java/net/minecraft/server/TileEntity.java +@@ -11,6 +11,7 @@ import org.bukkit.inventory.InventoryHolder; // CraftBukkit + public abstract class TileEntity { + + public Timing tickTimer = MinecraftTimings.getTileEntityTimings(this); // Paper ++ boolean isLoadingStructure = false; // Paper + private static final Logger a = LogManager.getLogger(); + private static final RegistryMaterials> f = new RegistryMaterials(); + protected World world; +diff --git a/src/main/java/net/minecraft/server/TileEntitySign.java b/src/main/java/net/minecraft/server/TileEntitySign.java +index 34ade146c..242552c36 100644 +--- a/src/main/java/net/minecraft/server/TileEntitySign.java ++++ b/src/main/java/net/minecraft/server/TileEntitySign.java +@@ -93,13 +93,14 @@ public class TileEntitySign extends TileEntity { + } + + try { +- IChatBaseComponent ichatbasecomponent = IChatBaseComponent.ChatSerializer.a(s); ++ //IChatBaseComponent ichatbasecomponent = IChatBaseComponent.ChatSerializer.a(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 ++ IChatBaseComponent ichatbasecomponent = IChatBaseComponent.ChatSerializer.a(s); // Paper - after old sign + + try { + this.lines[i] = ChatComponentUtils.filterForDisplay(icommandlistener, ichatbasecomponent, (Entity) null); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0148-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch b/Spigot-Server-Patches/0148-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch new file mode 100644 index 0000000000..6d6b6cb12a --- /dev/null +++ b/Spigot-Server-Patches/0148-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch @@ -0,0 +1,22 @@ +From 8596066290cfcde927c9d9f5b49898b3788e6f3e 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/UserCache.java b/src/main/java/net/minecraft/server/UserCache.java +index 989758cdf..1c619c596 100644 +--- a/src/main/java/net/minecraft/server/UserCache.java ++++ b/src/main/java/net/minecraft/server/UserCache.java +@@ -86,7 +86,7 @@ public class UserCache { + }; + + gameprofilerepository.findProfilesByNames(new String[] { s}, Agent.MINECRAFT, profilelookupcallback); +- if (!d() && agameprofile[0] == null) { ++ if (!d() && agameprofile[0] == 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 gameprofile = new GameProfile(uuid, s); + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0148-Fix-Old-Sign-Conversion.patch b/Spigot-Server-Patches/0148-Fix-Old-Sign-Conversion.patch deleted file mode 100644 index ac751f8a5f..0000000000 --- a/Spigot-Server-Patches/0148-Fix-Old-Sign-Conversion.patch +++ /dev/null @@ -1,71 +0,0 @@ -From b186fced2094d441de37e5b76a68e2b8dd8f0bda 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/server/DefinedStructure.java b/src/main/java/net/minecraft/server/DefinedStructure.java -index a3dc6fe31..83646341b 100644 ---- a/src/main/java/net/minecraft/server/DefinedStructure.java -+++ b/src/main/java/net/minecraft/server/DefinedStructure.java -@@ -203,9 +203,11 @@ public class DefinedStructure { - definedstructure_blockinfo1.c.setInt("x", blockposition1.getX()); - definedstructure_blockinfo1.c.setInt("y", blockposition1.getY()); - definedstructure_blockinfo1.c.setInt("z", blockposition1.getZ()); -+ tileentity.isLoadingStructure = true; // Paper - tileentity.a(definedstructure_blockinfo1.c); - tileentity.a(definedstructureinfo.b()); - tileentity.a(definedstructureinfo.c()); -+ tileentity.isLoadingStructure = false; // Paper - } - } - } -@@ -600,7 +602,7 @@ public class DefinedStructure { - public IBlockData a(int i) { - IBlockData iblockdata = (IBlockData) this.b.fromId(i); - -- return iblockdata == null ? DefinedStructure.a.a : iblockdata; -+ return iblockdata == null ? a : iblockdata; // Paper - decompile error - Blocks.AIR.getBlockData() - } - - public Iterator iterator() { -diff --git a/src/main/java/net/minecraft/server/TileEntity.java b/src/main/java/net/minecraft/server/TileEntity.java -index d2662ae14..e6b79a571 100644 ---- a/src/main/java/net/minecraft/server/TileEntity.java -+++ b/src/main/java/net/minecraft/server/TileEntity.java -@@ -11,6 +11,7 @@ import org.bukkit.inventory.InventoryHolder; // CraftBukkit - public abstract class TileEntity { - - public Timing tickTimer = MinecraftTimings.getTileEntityTimings(this); // Paper -+ boolean isLoadingStructure = false; // Paper - private static final Logger a = LogManager.getLogger(); - private static final RegistryMaterials> f = new RegistryMaterials(); - protected World world; -diff --git a/src/main/java/net/minecraft/server/TileEntitySign.java b/src/main/java/net/minecraft/server/TileEntitySign.java -index 34ade146c..242552c36 100644 ---- a/src/main/java/net/minecraft/server/TileEntitySign.java -+++ b/src/main/java/net/minecraft/server/TileEntitySign.java -@@ -93,13 +93,14 @@ public class TileEntitySign extends TileEntity { - } - - try { -- IChatBaseComponent ichatbasecomponent = IChatBaseComponent.ChatSerializer.a(s); -+ //IChatBaseComponent ichatbasecomponent = IChatBaseComponent.ChatSerializer.a(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 -+ IChatBaseComponent ichatbasecomponent = IChatBaseComponent.ChatSerializer.a(s); // Paper - after old sign - - try { - this.lines[i] = ChatComponentUtils.filterForDisplay(icommandlistener, ichatbasecomponent, (Entity) null); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0149-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch b/Spigot-Server-Patches/0149-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch deleted file mode 100644 index 650466cb0b..0000000000 --- a/Spigot-Server-Patches/0149-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 9c9779271b3982365fb2e2cd4c779dc8f918ab04 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/UserCache.java b/src/main/java/net/minecraft/server/UserCache.java -index 989758cdf..1c619c596 100644 ---- a/src/main/java/net/minecraft/server/UserCache.java -+++ b/src/main/java/net/minecraft/server/UserCache.java -@@ -86,7 +86,7 @@ public class UserCache { - }; - - gameprofilerepository.findProfilesByNames(new String[] { s}, Agent.MINECRAFT, profilelookupcallback); -- if (!d() && agameprofile[0] == null) { -+ if (!d() && agameprofile[0] == 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 gameprofile = new GameProfile(uuid, s); - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0149-More-informative-vehicle-moved-wrongly-message.patch b/Spigot-Server-Patches/0149-More-informative-vehicle-moved-wrongly-message.patch new file mode 100644 index 0000000000..eb3786568a --- /dev/null +++ b/Spigot-Server-Patches/0149-More-informative-vehicle-moved-wrongly-message.patch @@ -0,0 +1,22 @@ +From 6d446eaa300db8b349d0c5813e6bf2758beb8816 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Thu, 28 Jul 2016 17:58:53 -0500 +Subject: [PATCH] More informative vehicle moved wrongly message + + +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index dfbae01f4..4b79031f0 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -343,7 +343,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { + + if (d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot + flag1 = true; +- PlayerConnection.LOGGER.warn("{} moved wrongly!", new Object[] { entity.getName()}); ++ PlayerConnection.LOGGER.warn(entity.getName() + " (vehicle of " + this.player.getName() + ") moved wrongly!"); // Paper - More informative + } + + entity.setLocation(d3, d4, d5, f, f1); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0150-More-informative-vehicle-moved-wrongly-message.patch b/Spigot-Server-Patches/0150-More-informative-vehicle-moved-wrongly-message.patch deleted file mode 100644 index f720c1aea9..0000000000 --- a/Spigot-Server-Patches/0150-More-informative-vehicle-moved-wrongly-message.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 8fa14bdc0cab3b0e51f4255fb748ba1a5305cf13 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Thu, 28 Jul 2016 17:58:53 -0500 -Subject: [PATCH] More informative vehicle moved wrongly message - - -diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index dfbae01f4..4b79031f0 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -343,7 +343,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { - - if (d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot - flag1 = true; -- PlayerConnection.LOGGER.warn("{} moved wrongly!", new Object[] { entity.getName()}); -+ PlayerConnection.LOGGER.warn(entity.getName() + " (vehicle of " + this.player.getName() + ") moved wrongly!"); // Paper - More informative - } - - entity.setLocation(d3, d4, d5, f, f1); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0150-Re-track-players-that-dismount-from-other-players.patch b/Spigot-Server-Patches/0150-Re-track-players-that-dismount-from-other-players.patch new file mode 100644 index 0000000000..0cee8d1517 --- /dev/null +++ b/Spigot-Server-Patches/0150-Re-track-players-that-dismount-from-other-players.patch @@ -0,0 +1,27 @@ +From db3336329ce3d39657824be9a6af3f84b4123532 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sun, 31 Jul 2016 16:33:03 -0500 +Subject: [PATCH] Re-track players that dismount from other players + + +diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java +index ad1bb7bab..4e8efc549 100644 +--- a/src/main/java/net/minecraft/server/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/EntityPlayer.java +@@ -654,6 +654,13 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + if (entity1 != entity && this.playerConnection != null) { + this.playerConnection.a(this.locX, this.locY, this.locZ, this.yaw, this.pitch); + } ++ // Paper start - "Fixes" an issue in which the vehicle player would not be notified that the passenger dismounted ++ if (entity instanceof EntityPlayer) { ++ WorldServer worldServer = (WorldServer) entity.getWorld(); ++ worldServer.tracker.untrackEntity(this); ++ worldServer.tracker.track(this); ++ } ++ // Paper end + + } + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0151-Add-setting-for-proxy-online-mode-status.patch b/Spigot-Server-Patches/0151-Add-setting-for-proxy-online-mode-status.patch new file mode 100644 index 0000000000..ac0ecea9c3 --- /dev/null +++ b/Spigot-Server-Patches/0151-Add-setting-for-proxy-online-mode-status.patch @@ -0,0 +1,51 @@ +From a9a7d486128aa9801cbc4733db287bd1dadb961f 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 e009e5cf2..276185d9a 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -235,4 +235,9 @@ 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); ++ } + } +diff --git a/src/main/java/net/minecraft/server/NameReferencingFileConverter.java b/src/main/java/net/minecraft/server/NameReferencingFileConverter.java +index 2ff8a6da0..52e736080 100644 +--- a/src/main/java/net/minecraft/server/NameReferencingFileConverter.java ++++ b/src/main/java/net/minecraft/server/NameReferencingFileConverter.java +@@ -65,7 +65,8 @@ public class NameReferencingFileConverter { + } + }), String.class); + +- if (minecraftserver.getOnlineMode() || org.spigotmc.SpigotConfig.bungee) { // Spigot: bungee = online mode, for now. ++ if (minecraftserver.getOnlineMode() ++ || (org.spigotmc.SpigotConfig.bungee && com.destroystokyo.paper.PaperConfig.bungeeOnlineMode)) { // 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/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index a958ce998..8ade16865 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1336,7 +1336,8 @@ public final class CraftServer implements Server { + // Spigot Start + GameProfile profile = null; + // Only fetch an online UUID in online mode +- if ( MinecraftServer.getServer().getOnlineMode() || org.spigotmc.SpigotConfig.bungee ) ++ if ( MinecraftServer.getServer().getOnlineMode() ++ || (org.spigotmc.SpigotConfig.bungee && com.destroystokyo.paper.PaperConfig.bungeeOnlineMode)) // Paper - Handle via setting + { + profile = console.getUserCache().getProfile( name ); + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0151-Re-track-players-that-dismount-from-other-players.patch b/Spigot-Server-Patches/0151-Re-track-players-that-dismount-from-other-players.patch deleted file mode 100644 index ed5eb22756..0000000000 --- a/Spigot-Server-Patches/0151-Re-track-players-that-dismount-from-other-players.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 44ea66d13039d7c00b6fb87a41a187ba42690249 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sun, 31 Jul 2016 16:33:03 -0500 -Subject: [PATCH] Re-track players that dismount from other players - - -diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index ad1bb7bab..4e8efc549 100644 ---- a/src/main/java/net/minecraft/server/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/EntityPlayer.java -@@ -654,6 +654,13 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - if (entity1 != entity && this.playerConnection != null) { - this.playerConnection.a(this.locX, this.locY, this.locZ, this.yaw, this.pitch); - } -+ // Paper start - "Fixes" an issue in which the vehicle player would not be notified that the passenger dismounted -+ if (entity instanceof EntityPlayer) { -+ WorldServer worldServer = (WorldServer) entity.getWorld(); -+ worldServer.tracker.untrackEntity(this); -+ worldServer.tracker.track(this); -+ } -+ // Paper end - - } - --- -2.12.2.windows.2 - diff --git a/Spigot-Server-Patches/0152-Add-setting-for-proxy-online-mode-status.patch b/Spigot-Server-Patches/0152-Add-setting-for-proxy-online-mode-status.patch deleted file mode 100644 index 3a4bd2be25..0000000000 --- a/Spigot-Server-Patches/0152-Add-setting-for-proxy-online-mode-status.patch +++ /dev/null @@ -1,51 +0,0 @@ -From cdcf33ebe123e94c1e5a9882232d064285482ab0 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 e009e5cf2..276185d9a 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -235,4 +235,9 @@ 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); -+ } - } -diff --git a/src/main/java/net/minecraft/server/NameReferencingFileConverter.java b/src/main/java/net/minecraft/server/NameReferencingFileConverter.java -index 2ff8a6da0..52e736080 100644 ---- a/src/main/java/net/minecraft/server/NameReferencingFileConverter.java -+++ b/src/main/java/net/minecraft/server/NameReferencingFileConverter.java -@@ -65,7 +65,8 @@ public class NameReferencingFileConverter { - } - }), String.class); - -- if (minecraftserver.getOnlineMode() || org.spigotmc.SpigotConfig.bungee) { // Spigot: bungee = online mode, for now. -+ if (minecraftserver.getOnlineMode() -+ || (org.spigotmc.SpigotConfig.bungee && com.destroystokyo.paper.PaperConfig.bungeeOnlineMode)) { // 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/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index a958ce998..8ade16865 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1336,7 +1336,8 @@ public final class CraftServer implements Server { - // Spigot Start - GameProfile profile = null; - // Only fetch an online UUID in online mode -- if ( MinecraftServer.getServer().getOnlineMode() || org.spigotmc.SpigotConfig.bungee ) -+ if ( MinecraftServer.getServer().getOnlineMode() -+ || (org.spigotmc.SpigotConfig.bungee && com.destroystokyo.paper.PaperConfig.bungeeOnlineMode)) // Paper - Handle via setting - { - profile = console.getUserCache().getProfile( name ); - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0152-Optimise-BlockStateEnum-hashCode-and-equals.patch b/Spigot-Server-Patches/0152-Optimise-BlockStateEnum-hashCode-and-equals.patch new file mode 100644 index 0000000000..234464447e --- /dev/null +++ b/Spigot-Server-Patches/0152-Optimise-BlockStateEnum-hashCode-and-equals.patch @@ -0,0 +1,62 @@ +From 451df5c9f607c0f8f087b70c06ec5736521cf7b6 Mon Sep 17 00:00:00 2001 +From: Alfie Cleveland +Date: Fri, 19 Aug 2016 01:52:56 +0100 +Subject: [PATCH] Optimise BlockStateEnum hashCode and equals + + +diff --git a/src/main/java/net/minecraft/server/BlockStateEnum.java b/src/main/java/net/minecraft/server/BlockStateEnum.java +index 288c52c55..66c459d83 100644 +--- a/src/main/java/net/minecraft/server/BlockStateEnum.java ++++ b/src/main/java/net/minecraft/server/BlockStateEnum.java +@@ -16,6 +16,11 @@ public class BlockStateEnum & INamable> extends BlockState + private final ImmutableSet a; + private final Map b = Maps.newHashMap(); + ++ // Paper start - BlockStateEnum is a singleton, so we can use our own hashCode ++ private static int hashId = 0; ++ private int hashCode; ++ // Paper end ++ + protected BlockStateEnum(String s, Class oclass, Collection collection) { + super(s, oclass); + this.a = ImmutableSet.copyOf(collection); +@@ -32,6 +37,7 @@ public class BlockStateEnum & INamable> extends BlockState + this.b.put(s1, (T) oenum); + } + ++ this.hashCode = hashId++; // Paper + } + + public Collection c() { +@@ -46,24 +52,14 @@ public class BlockStateEnum & INamable> extends BlockState + return ((INamable) t0).getName(); + } + ++ @Override // Paper - override equals as BlockStateEnum is a singleton + public boolean equals(Object object) { +- if (this == object) { +- return true; +- } else if (object instanceof BlockStateEnum && super.equals(object)) { +- BlockStateEnum blockstateenum = (BlockStateEnum) object; +- +- return this.a.equals(blockstateenum.a) && this.b.equals(blockstateenum.b); +- } else { +- return false; +- } ++ return this == object; + } + ++ @Override // Paper - override hashCode as BlockStateEnum is a singleton + public int hashCode() { +- int i = super.hashCode(); +- +- i = 31 * i + this.a.hashCode(); +- i = 31 * i + this.b.hashCode(); +- return i; ++ return hashCode; + } + + public static & INamable> BlockStateEnum of(String s, Class oclass) { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0153-Disable-ticking-of-snow-blocks.patch b/Spigot-Server-Patches/0153-Disable-ticking-of-snow-blocks.patch new file mode 100644 index 0000000000..35bcecdf5f --- /dev/null +++ b/Spigot-Server-Patches/0153-Disable-ticking-of-snow-blocks.patch @@ -0,0 +1,38 @@ +From b1c66cf190817911beb2855fba6f91504dc805ef Mon Sep 17 00:00:00 2001 +From: killme +Date: Tue, 30 Aug 2016 16:39:48 +0200 +Subject: [PATCH] Disable ticking of snow blocks + + +diff --git a/src/main/java/net/minecraft/server/BlockSnowBlock.java b/src/main/java/net/minecraft/server/BlockSnowBlock.java +index 8123d7295..b6765e5bc 100644 +--- a/src/main/java/net/minecraft/server/BlockSnowBlock.java ++++ b/src/main/java/net/minecraft/server/BlockSnowBlock.java +@@ -6,7 +6,7 @@ public class BlockSnowBlock extends Block { + + protected BlockSnowBlock() { + super(Material.SNOW_BLOCK); +- this.a(true); ++ // this.a(true); // Paper - snow blocks don't need to tick + this.a(CreativeModeTab.b); + } + +@@ -18,6 +18,8 @@ public class BlockSnowBlock extends Block { + return 4; + } + ++ // Paper start - snow blocks don't need to tick ++ /* + public void b(World world, BlockPosition blockposition, IBlockData iblockdata, Random random) { + if (world.getBrightness(EnumSkyBlock.BLOCK, blockposition) > 11) { + // CraftBukkit start +@@ -30,4 +32,6 @@ public class BlockSnowBlock extends Block { + } + + } ++ */ ++ //Paper end + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0153-Optimise-BlockStateEnum-hashCode-and-equals.patch b/Spigot-Server-Patches/0153-Optimise-BlockStateEnum-hashCode-and-equals.patch deleted file mode 100644 index 80ac491d47..0000000000 --- a/Spigot-Server-Patches/0153-Optimise-BlockStateEnum-hashCode-and-equals.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 7293031a9dea2d01c59bc139f80b4a4f50b6c083 Mon Sep 17 00:00:00 2001 -From: Alfie Cleveland -Date: Fri, 19 Aug 2016 01:52:56 +0100 -Subject: [PATCH] Optimise BlockStateEnum hashCode and equals - - -diff --git a/src/main/java/net/minecraft/server/BlockStateEnum.java b/src/main/java/net/minecraft/server/BlockStateEnum.java -index 288c52c55..66c459d83 100644 ---- a/src/main/java/net/minecraft/server/BlockStateEnum.java -+++ b/src/main/java/net/minecraft/server/BlockStateEnum.java -@@ -16,6 +16,11 @@ public class BlockStateEnum & INamable> extends BlockState - private final ImmutableSet a; - private final Map b = Maps.newHashMap(); - -+ // Paper start - BlockStateEnum is a singleton, so we can use our own hashCode -+ private static int hashId = 0; -+ private int hashCode; -+ // Paper end -+ - protected BlockStateEnum(String s, Class oclass, Collection collection) { - super(s, oclass); - this.a = ImmutableSet.copyOf(collection); -@@ -32,6 +37,7 @@ public class BlockStateEnum & INamable> extends BlockState - this.b.put(s1, (T) oenum); - } - -+ this.hashCode = hashId++; // Paper - } - - public Collection c() { -@@ -46,24 +52,14 @@ public class BlockStateEnum & INamable> extends BlockState - return ((INamable) t0).getName(); - } - -+ @Override // Paper - override equals as BlockStateEnum is a singleton - public boolean equals(Object object) { -- if (this == object) { -- return true; -- } else if (object instanceof BlockStateEnum && super.equals(object)) { -- BlockStateEnum blockstateenum = (BlockStateEnum) object; -- -- return this.a.equals(blockstateenum.a) && this.b.equals(blockstateenum.b); -- } else { -- return false; -- } -+ return this == object; - } - -+ @Override // Paper - override hashCode as BlockStateEnum is a singleton - public int hashCode() { -- int i = super.hashCode(); -- -- i = 31 * i + this.a.hashCode(); -- i = 31 * i + this.b.hashCode(); -- return i; -+ return hashCode; - } - - public static & INamable> BlockStateEnum of(String s, Class oclass) { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0154-Disable-ticking-of-snow-blocks.patch b/Spigot-Server-Patches/0154-Disable-ticking-of-snow-blocks.patch deleted file mode 100644 index 1e93d97703..0000000000 --- a/Spigot-Server-Patches/0154-Disable-ticking-of-snow-blocks.patch +++ /dev/null @@ -1,38 +0,0 @@ -From a9215f422226e93bd492641c5ae02bb3b9fa0d10 Mon Sep 17 00:00:00 2001 -From: killme -Date: Tue, 30 Aug 2016 16:39:48 +0200 -Subject: [PATCH] Disable ticking of snow blocks - - -diff --git a/src/main/java/net/minecraft/server/BlockSnowBlock.java b/src/main/java/net/minecraft/server/BlockSnowBlock.java -index 8123d7295..b6765e5bc 100644 ---- a/src/main/java/net/minecraft/server/BlockSnowBlock.java -+++ b/src/main/java/net/minecraft/server/BlockSnowBlock.java -@@ -6,7 +6,7 @@ public class BlockSnowBlock extends Block { - - protected BlockSnowBlock() { - super(Material.SNOW_BLOCK); -- this.a(true); -+ // this.a(true); // Paper - snow blocks don't need to tick - this.a(CreativeModeTab.b); - } - -@@ -18,6 +18,8 @@ public class BlockSnowBlock extends Block { - return 4; - } - -+ // Paper start - snow blocks don't need to tick -+ /* - public void b(World world, BlockPosition blockposition, IBlockData iblockdata, Random random) { - if (world.getBrightness(EnumSkyBlock.BLOCK, blockposition) > 11) { - // CraftBukkit start -@@ -30,4 +32,6 @@ public class BlockSnowBlock extends Block { - } - - } -+ */ -+ //Paper end - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0154-Fix-AIOOBE-in-inventory-handling.patch b/Spigot-Server-Patches/0154-Fix-AIOOBE-in-inventory-handling.patch new file mode 100644 index 0000000000..f5b59c4d9b --- /dev/null +++ b/Spigot-Server-Patches/0154-Fix-AIOOBE-in-inventory-handling.patch @@ -0,0 +1,22 @@ +From aeab5af95f6f6914dab1a5752c42c8e387113e62 Mon Sep 17 00:00:00 2001 +From: Brokkonaut +Date: Sun, 4 Sep 2016 16:35:43 -0500 +Subject: [PATCH] Fix AIOOBE in inventory handling + + +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 4b79031f0..060434f32 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -1809,7 +1809,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { + case CLONE: + if (packetplayinwindowclick.c() == 2) { + click = ClickType.MIDDLE; +- if (packetplayinwindowclick.b() == -999) { ++ if (packetplayinwindowclick.b() < 0) { // Paper - GH-404 + action = InventoryAction.NOTHING; + } else { + Slot slot = this.player.activeContainer.getSlot(packetplayinwindowclick.b()); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0155-Configurable-packet-in-spam-threshold.patch b/Spigot-Server-Patches/0155-Configurable-packet-in-spam-threshold.patch new file mode 100644 index 0000000000..f8f6bad143 --- /dev/null +++ b/Spigot-Server-Patches/0155-Configurable-packet-in-spam-threshold.patch @@ -0,0 +1,48 @@ +From 866083bdb8aff3ba41f93b93486c5150d86bb6bf 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 276185d9a..bb4114b8d 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -240,4 +240,13 @@ public class PaperConfig { + private static void bungeeOnlineMode() { + bungeeOnlineMode = getBoolean("settings.bungee-online-mode", true); + } ++ ++ 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/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 060434f32..6281fe4d5 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -871,13 +871,14 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { + // 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; +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0155-Fix-AIOOBE-in-inventory-handling.patch b/Spigot-Server-Patches/0155-Fix-AIOOBE-in-inventory-handling.patch deleted file mode 100644 index 8325c597c4..0000000000 --- a/Spigot-Server-Patches/0155-Fix-AIOOBE-in-inventory-handling.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 7f2c080841b1462ac6e08fbd788aade8f8b4c23c Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Sun, 4 Sep 2016 16:35:43 -0500 -Subject: [PATCH] Fix AIOOBE in inventory handling - - -diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 4b79031f0..060434f32 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -1809,7 +1809,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { - case CLONE: - if (packetplayinwindowclick.c() == 2) { - click = ClickType.MIDDLE; -- if (packetplayinwindowclick.b() == -999) { -+ if (packetplayinwindowclick.b() < 0) { // Paper - GH-404 - action = InventoryAction.NOTHING; - } else { - Slot slot = this.player.activeContainer.getSlot(packetplayinwindowclick.b()); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0156-Configurable-flying-kick-messages.patch b/Spigot-Server-Patches/0156-Configurable-flying-kick-messages.patch new file mode 100644 index 0000000000..291f24eda7 --- /dev/null +++ b/Spigot-Server-Patches/0156-Configurable-flying-kick-messages.patch @@ -0,0 +1,47 @@ +From 9f4d0c83940ae2666504ab4a5625b894be1d162a 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 bb4114b8d..f86729724 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -249,4 +249,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/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 6281fe4d5..51d27351d 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -143,7 +143,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { + if (this.B) { + if (++this.C > 80) { + PlayerConnection.LOGGER.warn("{} was kicked for floating too long!", new Object[] { this.player.getName()}); +- this.disconnect("Flying is not enabled on this server"); ++ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage); // Paper - use configurable kick message + return; + } + } else { +@@ -162,7 +162,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { + if (this.D && this.player.getVehicle().bw() == this.player) { + if (++this.E > 80) { + PlayerConnection.LOGGER.warn("{} was kicked for floating a vehicle too long!", new Object[] { this.player.getName()}); +- this.disconnect("Flying is not enabled on this server"); ++ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage); // Paper - use configurable kick message + return; + } + } else { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0156-Configurable-packet-in-spam-threshold.patch b/Spigot-Server-Patches/0156-Configurable-packet-in-spam-threshold.patch deleted file mode 100644 index 036c8eb0f5..0000000000 --- a/Spigot-Server-Patches/0156-Configurable-packet-in-spam-threshold.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 00dd9ebe392fba212ccd1dcae0f5585f65e9249b 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 276185d9a..bb4114b8d 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -240,4 +240,13 @@ public class PaperConfig { - private static void bungeeOnlineMode() { - bungeeOnlineMode = getBoolean("settings.bungee-online-mode", true); - } -+ -+ 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/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 060434f32..6281fe4d5 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -871,13 +871,14 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { - // 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; --- -2.12.2 - diff --git a/Spigot-Server-Patches/0157-Auto-Save-Improvements.patch b/Spigot-Server-Patches/0157-Auto-Save-Improvements.patch new file mode 100644 index 0000000000..0c670e551c --- /dev/null +++ b/Spigot-Server-Patches/0157-Auto-Save-Improvements.patch @@ -0,0 +1,219 @@ +From f2eb7e545edd482486bfd002608f6b2b12d44d78 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 19 Sep 2016 23:16:39 -0400 +Subject: [PATCH] Auto Save Improvements + +Makes Auto Save Rate setting configurable per-world. If the auto save rate is left -1, the global bukkit.yml value will be used. + +Process auto save every tick instead of once per auto tick interval, so that chunk saves will distribute over many ticks instead of all at once. + +Re-introduce a cap per tick for auto save (Spigot disabled the vanilla cap) and make it configurable. + +Adds incremental player auto saving too + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index f86729724..009bf0c8b 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -256,4 +256,9 @@ public class PaperConfig { + flyingKickPlayerMessage = getString("messages.kick.flying-player", flyingKickPlayerMessage); + flyingKickVehicleMessage = getString("messages.kick.flying-vehicle", flyingKickVehicleMessage); + } ++ ++ public static int playerAutoSaveRate = -1; ++ private static void playerAutoSaveRate() { ++ playerAutoSaveRate = getInt("settings.player-auto-save-rate", -1); ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index dc96bd7f4..bcf24cb49 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 net.minecraft.server.MinecraftServer; + import org.bukkit.Bukkit; + import org.bukkit.configuration.file.YamlConfiguration; + import org.spigotmc.SpigotWorldConfig; +@@ -359,4 +360,19 @@ public class PaperWorldConfig { + private void elytraHitWallDamage() { + elytraHitWallDamage = getBoolean("elytra-hit-wall-damage", true); + } ++ ++ 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 = 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/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java +index 88437d77a..9f7f32dc2 100644 +--- a/src/main/java/net/minecraft/server/Chunk.java ++++ b/src/main/java/net/minecraft/server/Chunk.java +@@ -960,11 +960,9 @@ public class Chunk { + if (this.t && this.world.getTime() != this.lastSaved || this.s) { + return true; + } +- } else if (this.t && this.world.getTime() >= this.lastSaved + MinecraftServer.getServer().autosavePeriod * 4) { // Spigot - Only save if we've passed 2 auto save intervals without modification +- return true; + } +- +- return this.s; ++ // This !flag section should say if s(isModified) or t(hasEntities), then check auto save ++ return ((this.s || this.t) && this.world.getTime() >= this.lastSaved + world.paperConfig.autoSavePeriod); // Paper - Make world configurable and incremental + } + + public Random a(long i) { +diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java +index 81b9bb884..71df9e4aa 100644 +--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java +@@ -1,5 +1,6 @@ + package net.minecraft.server; + ++import com.destroystokyo.paper.PaperConfig; + import com.google.common.collect.Lists; + import com.google.common.collect.Sets; + import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +@@ -266,7 +267,7 @@ public class ChunkProviderServer implements IChunkProvider { + this.saveChunk(chunk); + chunk.f(false); + ++i; +- if (i == 24 && !flag && false) { // Spigot ++ if (!flag && i >= world.paperConfig.maxAutoSaveChunksPerTick) { // Spigot - // Paper - Incremental Auto Save - cap max per tick + return false; + } + } +diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java +index 4e8efc549..55c966811 100644 +--- a/src/main/java/net/minecraft/server/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/EntityPlayer.java +@@ -32,6 +32,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + + private static final Logger bR = LogManager.getLogger(); + public String locale = null; // Spigot private -> public // Paper - default to null ++ public long lastSave = MinecraftServer.currentTick; // Paper + public PlayerConnection playerConnection; + public final MinecraftServer server; + public final PlayerInteractManager playerInteractManager; +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 2349c3ade..8134501c7 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -118,6 +118,7 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs + public final Thread primaryThread; + public java.util.Queue processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); + public int autosavePeriod; ++ public boolean serverAutoSave = false; // Paper + // CraftBukkit end + // Spigot start + public final SlackActivityAccountant slackActivityAccountant = new SlackActivityAccountant(); +@@ -765,22 +766,30 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs + this.q.b().a(agameprofile); + } + +- if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit + this.methodProfiler.a("save"); +- this.v.savePlayers(); ++ ++ serverAutoSave = (autosavePeriod > 0 && this.ticks % autosavePeriod == 0); // Paper ++ int playerSaveInterval = com.destroystokyo.paper.PaperConfig.playerAutoSaveRate; ++ if (playerSaveInterval < 0) { ++ playerSaveInterval = autosavePeriod; ++ } ++ if (playerSaveInterval > 0) { // CraftBukkit // Paper ++ this.v.savePlayers(playerSaveInterval); + // Spigot Start ++ } // Paper - Incremental Auto Saving ++ + // We replace this with saving each individual world as this.saveChunks(...) is broken, + // and causes the main thread to sleep for random amounts of time depending on chunk activity + // Also pass flag to only save modified chunks + server.playerCommandState = true; + for (World world : worlds) { +- world.getWorld().save(false); ++ if (world.paperConfig.autoSavePeriod > 0) world.getWorld().save(false); // Paper - Incremental / Configurable Auto Saving + } + server.playerCommandState = false; + // this.saveChunks(true); + // Spigot End + this.methodProfiler.b(); +- } ++ //} // Paper - Incremental Auto Saving + + this.methodProfiler.a("tallying"); + // Spigot start +diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java +index 97322c5da..58f30fb1d 100644 +--- a/src/main/java/net/minecraft/server/PlayerList.java ++++ b/src/main/java/net/minecraft/server/PlayerList.java +@@ -330,6 +330,7 @@ public abstract class PlayerList { + } + + protected void savePlayerFile(EntityPlayer entityplayer) { ++ entityplayer.lastSave = MinecraftServer.currentTick; // Paper + this.playerFileData.save(entityplayer); + ServerStatisticManager serverstatisticmanager = (ServerStatisticManager) this.o.get(entityplayer.getUniqueID()); + +@@ -1207,13 +1208,23 @@ public abstract class PlayerList { + + } + ++ // Paper start + public void savePlayers() { ++ savePlayers(null); ++ } ++ ++ public void savePlayers(Integer interval) { ++ long now = MinecraftServer.currentTick; + MinecraftTimings.savePlayers.startTiming(); // Paper + 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); ++ } + } + MinecraftTimings.savePlayers.stopTiming(); // Paper + } ++ // Paper end + + public void addWhitelist(GameProfile gameprofile) { + this.whitelist.add(new WhiteListEntry(gameprofile)); +diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java +index f969d2a72..cc0e8d2c8 100644 +--- a/src/main/java/net/minecraft/server/WorldServer.java ++++ b/src/main/java/net/minecraft/server/WorldServer.java +@@ -1003,8 +1003,9 @@ public class WorldServer extends World implements IAsyncTaskHandler { + ChunkProviderServer chunkproviderserver = this.getChunkProviderServer(); + + if (chunkproviderserver.e()) { +- org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit ++ if (flag) org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit // Paper - Incremental Auto Saving - Only fire event on full save + timings.worldSave.startTiming(); // Paper ++ if (flag || server.serverAutoSave) { // Paper + if (iprogressupdate != null) { + iprogressupdate.a("Saving level"); + } +@@ -1013,6 +1014,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { + if (iprogressupdate != null) { + iprogressupdate.c("Saving chunks"); + } ++ } // Paper + + timings.worldSaveChunks.startTiming(); // Paper + chunkproviderserver.a(flag); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0157-Configurable-flying-kick-messages.patch b/Spigot-Server-Patches/0157-Configurable-flying-kick-messages.patch deleted file mode 100644 index 3b4170c613..0000000000 --- a/Spigot-Server-Patches/0157-Configurable-flying-kick-messages.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 88776c9c8191cc75cb70d2239b19bcd53ea8445f 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 bb4114b8d..f86729724 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -249,4 +249,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/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 6281fe4d5..51d27351d 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -143,7 +143,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { - if (this.B) { - if (++this.C > 80) { - PlayerConnection.LOGGER.warn("{} was kicked for floating too long!", new Object[] { this.player.getName()}); -- this.disconnect("Flying is not enabled on this server"); -+ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage); // Paper - use configurable kick message - return; - } - } else { -@@ -162,7 +162,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { - if (this.D && this.player.getVehicle().bw() == this.player) { - if (++this.E > 80) { - PlayerConnection.LOGGER.warn("{} was kicked for floating a vehicle too long!", new Object[] { this.player.getName()}); -- this.disconnect("Flying is not enabled on this server"); -+ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage); // Paper - use configurable kick message - return; - } - } else { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0158-Auto-Save-Improvements.patch b/Spigot-Server-Patches/0158-Auto-Save-Improvements.patch deleted file mode 100644 index 2e2fe6051c..0000000000 --- a/Spigot-Server-Patches/0158-Auto-Save-Improvements.patch +++ /dev/null @@ -1,219 +0,0 @@ -From 4978f444ee1bb732f34447349281f25b8f470a13 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 19 Sep 2016 23:16:39 -0400 -Subject: [PATCH] Auto Save Improvements - -Makes Auto Save Rate setting configurable per-world. If the auto save rate is left -1, the global bukkit.yml value will be used. - -Process auto save every tick instead of once per auto tick interval, so that chunk saves will distribute over many ticks instead of all at once. - -Re-introduce a cap per tick for auto save (Spigot disabled the vanilla cap) and make it configurable. - -Adds incremental player auto saving too - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index f86729724..009bf0c8b 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -256,4 +256,9 @@ public class PaperConfig { - flyingKickPlayerMessage = getString("messages.kick.flying-player", flyingKickPlayerMessage); - flyingKickVehicleMessage = getString("messages.kick.flying-vehicle", flyingKickVehicleMessage); - } -+ -+ public static int playerAutoSaveRate = -1; -+ private static void playerAutoSaveRate() { -+ playerAutoSaveRate = getInt("settings.player-auto-save-rate", -1); -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index dc96bd7f4..bcf24cb49 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 net.minecraft.server.MinecraftServer; - import org.bukkit.Bukkit; - import org.bukkit.configuration.file.YamlConfiguration; - import org.spigotmc.SpigotWorldConfig; -@@ -359,4 +360,19 @@ public class PaperWorldConfig { - private void elytraHitWallDamage() { - elytraHitWallDamage = getBoolean("elytra-hit-wall-damage", true); - } -+ -+ 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 = 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/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java -index 88437d77a..9f7f32dc2 100644 ---- a/src/main/java/net/minecraft/server/Chunk.java -+++ b/src/main/java/net/minecraft/server/Chunk.java -@@ -960,11 +960,9 @@ public class Chunk { - if (this.t && this.world.getTime() != this.lastSaved || this.s) { - return true; - } -- } else if (this.t && this.world.getTime() >= this.lastSaved + MinecraftServer.getServer().autosavePeriod * 4) { // Spigot - Only save if we've passed 2 auto save intervals without modification -- return true; - } -- -- return this.s; -+ // This !flag section should say if s(isModified) or t(hasEntities), then check auto save -+ return ((this.s || this.t) && this.world.getTime() >= this.lastSaved + world.paperConfig.autoSavePeriod); // Paper - Make world configurable and incremental - } - - public Random a(long i) { -diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java -index 81b9bb884..71df9e4aa 100644 ---- a/src/main/java/net/minecraft/server/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java -@@ -1,5 +1,6 @@ - package net.minecraft.server; - -+import com.destroystokyo.paper.PaperConfig; - import com.google.common.collect.Lists; - import com.google.common.collect.Sets; - import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -@@ -266,7 +267,7 @@ public class ChunkProviderServer implements IChunkProvider { - this.saveChunk(chunk); - chunk.f(false); - ++i; -- if (i == 24 && !flag && false) { // Spigot -+ if (!flag && i >= world.paperConfig.maxAutoSaveChunksPerTick) { // Spigot - // Paper - Incremental Auto Save - cap max per tick - return false; - } - } -diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index 4e8efc549..55c966811 100644 ---- a/src/main/java/net/minecraft/server/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/EntityPlayer.java -@@ -32,6 +32,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - private static final Logger bR = LogManager.getLogger(); - public String locale = null; // Spigot private -> public // Paper - default to null -+ public long lastSave = MinecraftServer.currentTick; // Paper - public PlayerConnection playerConnection; - public final MinecraftServer server; - public final PlayerInteractManager playerInteractManager; -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 2349c3ade..8134501c7 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -118,6 +118,7 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs - public final Thread primaryThread; - public java.util.Queue processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); - public int autosavePeriod; -+ public boolean serverAutoSave = false; // Paper - // CraftBukkit end - // Spigot start - public final SlackActivityAccountant slackActivityAccountant = new SlackActivityAccountant(); -@@ -765,22 +766,30 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs - this.q.b().a(agameprofile); - } - -- if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit - this.methodProfiler.a("save"); -- this.v.savePlayers(); -+ -+ serverAutoSave = (autosavePeriod > 0 && this.ticks % autosavePeriod == 0); // Paper -+ int playerSaveInterval = com.destroystokyo.paper.PaperConfig.playerAutoSaveRate; -+ if (playerSaveInterval < 0) { -+ playerSaveInterval = autosavePeriod; -+ } -+ if (playerSaveInterval > 0) { // CraftBukkit // Paper -+ this.v.savePlayers(playerSaveInterval); - // Spigot Start -+ } // Paper - Incremental Auto Saving -+ - // We replace this with saving each individual world as this.saveChunks(...) is broken, - // and causes the main thread to sleep for random amounts of time depending on chunk activity - // Also pass flag to only save modified chunks - server.playerCommandState = true; - for (World world : worlds) { -- world.getWorld().save(false); -+ if (world.paperConfig.autoSavePeriod > 0) world.getWorld().save(false); // Paper - Incremental / Configurable Auto Saving - } - server.playerCommandState = false; - // this.saveChunks(true); - // Spigot End - this.methodProfiler.b(); -- } -+ //} // Paper - Incremental Auto Saving - - this.methodProfiler.a("tallying"); - // Spigot start -diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java -index 97322c5da..58f30fb1d 100644 ---- a/src/main/java/net/minecraft/server/PlayerList.java -+++ b/src/main/java/net/minecraft/server/PlayerList.java -@@ -330,6 +330,7 @@ public abstract class PlayerList { - } - - protected void savePlayerFile(EntityPlayer entityplayer) { -+ entityplayer.lastSave = MinecraftServer.currentTick; // Paper - this.playerFileData.save(entityplayer); - ServerStatisticManager serverstatisticmanager = (ServerStatisticManager) this.o.get(entityplayer.getUniqueID()); - -@@ -1207,13 +1208,23 @@ public abstract class PlayerList { - - } - -+ // Paper start - public void savePlayers() { -+ savePlayers(null); -+ } -+ -+ public void savePlayers(Integer interval) { -+ long now = MinecraftServer.currentTick; - MinecraftTimings.savePlayers.startTiming(); // Paper - 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); -+ } - } - MinecraftTimings.savePlayers.stopTiming(); // Paper - } -+ // Paper end - - public void addWhitelist(GameProfile gameprofile) { - this.whitelist.add(new WhiteListEntry(gameprofile)); -diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index f969d2a72..cc0e8d2c8 100644 ---- a/src/main/java/net/minecraft/server/WorldServer.java -+++ b/src/main/java/net/minecraft/server/WorldServer.java -@@ -1003,8 +1003,9 @@ public class WorldServer extends World implements IAsyncTaskHandler { - ChunkProviderServer chunkproviderserver = this.getChunkProviderServer(); - - if (chunkproviderserver.e()) { -- org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit -+ if (flag) org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit // Paper - Incremental Auto Saving - Only fire event on full save - timings.worldSave.startTiming(); // Paper -+ if (flag || server.serverAutoSave) { // Paper - if (iprogressupdate != null) { - iprogressupdate.a("Saving level"); - } -@@ -1013,6 +1014,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { - if (iprogressupdate != null) { - iprogressupdate.c("Saving chunks"); - } -+ } // Paper - - timings.worldSaveChunks.startTiming(); // Paper - chunkproviderserver.a(flag); --- -2.12.2.windows.2 - diff --git a/Spigot-Server-Patches/0158-Chunk-registration-fixes.patch b/Spigot-Server-Patches/0158-Chunk-registration-fixes.patch new file mode 100644 index 0000000000..21c5628bcf --- /dev/null +++ b/Spigot-Server-Patches/0158-Chunk-registration-fixes.patch @@ -0,0 +1,25 @@ +From 08b118ed5d51e80df7a701c4e11e5ed101207af7 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/World.java b/src/main/java/net/minecraft/server/World.java +index 7900fca57..ec0a28cff 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -1763,7 +1763,7 @@ public abstract class World implements IBlockAccess { + } + + int k = MathHelper.floor(entity.locX / 16.0D); +- int l = MathHelper.floor(entity.locY / 16.0D); ++ int l = Math.min(15, Math.max(0, MathHelper.floor(entity.locY / 16.0D))); // Paper - stay consistent with chunk add/remove behavior + int i1 = MathHelper.floor(entity.locZ / 16.0D); + + if (!entity.aa || entity.ab != k || entity.ac != l || entity.ad != i1) { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0159-Chunk-registration-fixes.patch b/Spigot-Server-Patches/0159-Chunk-registration-fixes.patch deleted file mode 100644 index 764bbcfb34..0000000000 --- a/Spigot-Server-Patches/0159-Chunk-registration-fixes.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 65b94463de969e5f6657dd234d06e25f328a60c0 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/World.java b/src/main/java/net/minecraft/server/World.java -index 7900fca57..ec0a28cff 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -1763,7 +1763,7 @@ public abstract class World implements IBlockAccess { - } - - int k = MathHelper.floor(entity.locX / 16.0D); -- int l = MathHelper.floor(entity.locY / 16.0D); -+ int l = Math.min(15, Math.max(0, MathHelper.floor(entity.locY / 16.0D))); // Paper - stay consistent with chunk add/remove behavior - int i1 = MathHelper.floor(entity.locZ / 16.0D); - - if (!entity.aa || entity.ab != k || entity.ac != l || entity.ad != i1) { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0159-Remove-FishingHook-reference-on-Craft-Entity-removal.patch b/Spigot-Server-Patches/0159-Remove-FishingHook-reference-on-Craft-Entity-removal.patch new file mode 100644 index 0000000000..8d086b5d38 --- /dev/null +++ b/Spigot-Server-Patches/0159-Remove-FishingHook-reference-on-Craft-Entity-removal.patch @@ -0,0 +1,30 @@ +From 0277b11a48f2d4779dd56452aef42aa40783cc43 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/CraftFish.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java +index ecfc316bb..3f909c174 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java +@@ -64,6 +64,16 @@ public class CraftFish extends AbstractProjectile implements Fish { + this.biteChance = chance; + } + ++ // Paper start ++ @Override ++ public void remove() { ++ super.remove(); ++ if (getHandle().owner != null) { ++ getHandle().owner.hookedFish = null; ++ } ++ } ++ // Paper end ++ + @Deprecated + public LivingEntity _INVALID_getShooter() { + return (LivingEntity) getShooter(); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0160-Auto-fix-bad-Y-levels-on-player-login.patch b/Spigot-Server-Patches/0160-Auto-fix-bad-Y-levels-on-player-login.patch new file mode 100644 index 0000000000..e3ab9eed6a --- /dev/null +++ b/Spigot-Server-Patches/0160-Auto-fix-bad-Y-levels-on-player-login.patch @@ -0,0 +1,22 @@ +From e83fee4c7a5c51bb48c0ae699d12de348ae8589c 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/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java +index 55c966811..eca224bdb 100644 +--- a/src/main/java/net/minecraft/server/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/EntityPlayer.java +@@ -131,6 +131,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + } + } + ++ if (this.locY > 300) this.locY = 257; // Paper - bring down to a saner Y level if out of world + this.getBukkitEntity().readExtraData(nbttagcompound); // CraftBukkit + } + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0160-Remove-FishingHook-reference-on-Craft-Entity-removal.patch b/Spigot-Server-Patches/0160-Remove-FishingHook-reference-on-Craft-Entity-removal.patch deleted file mode 100644 index be1521f5df..0000000000 --- a/Spigot-Server-Patches/0160-Remove-FishingHook-reference-on-Craft-Entity-removal.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 7c28aed99b9afe7c37d5f9f0b70013dffb1c8a2b 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/CraftFish.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java -index ecfc316bb..3f909c174 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java -@@ -64,6 +64,16 @@ public class CraftFish extends AbstractProjectile implements Fish { - this.biteChance = chance; - } - -+ // Paper start -+ @Override -+ public void remove() { -+ super.remove(); -+ if (getHandle().owner != null) { -+ getHandle().owner.hookedFish = null; -+ } -+ } -+ // Paper end -+ - @Deprecated - public LivingEntity _INVALID_getShooter() { - return (LivingEntity) getShooter(); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0161-Auto-fix-bad-Y-levels-on-player-login.patch b/Spigot-Server-Patches/0161-Auto-fix-bad-Y-levels-on-player-login.patch deleted file mode 100644 index eaf3adca37..0000000000 --- a/Spigot-Server-Patches/0161-Auto-fix-bad-Y-levels-on-player-login.patch +++ /dev/null @@ -1,22 +0,0 @@ -From d90efd20600735e017db928e235bde3740181dab 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/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index 55c966811..eca224bdb 100644 ---- a/src/main/java/net/minecraft/server/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/EntityPlayer.java -@@ -131,6 +131,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - } - -+ if (this.locY > 300) this.locY = 257; // Paper - bring down to a saner Y level if out of world - this.getBukkitEntity().readExtraData(nbttagcompound); // CraftBukkit - } - --- -2.12.2.windows.2 - diff --git a/Spigot-Server-Patches/0161-Raise-string-limit-for-packet-serialization.patch b/Spigot-Server-Patches/0161-Raise-string-limit-for-packet-serialization.patch new file mode 100644 index 0000000000..39138523f5 --- /dev/null +++ b/Spigot-Server-Patches/0161-Raise-string-limit-for-packet-serialization.patch @@ -0,0 +1,27 @@ +From cfc4ef10920340b7a0d02dc201354ac16d37f0a2 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 21 Sep 2016 23:54:20 -0400 +Subject: [PATCH] Raise string limit for packet serialization + +The default limit is possible to hit with 50 page books with color codes, causing clients to disconnect. + +Bump the limit up a hair to above currently seen sizes. + +diff --git a/src/main/java/net/minecraft/server/PacketDataSerializer.java b/src/main/java/net/minecraft/server/PacketDataSerializer.java +index 7a6619595..68e8c4671 100644 +--- a/src/main/java/net/minecraft/server/PacketDataSerializer.java ++++ b/src/main/java/net/minecraft/server/PacketDataSerializer.java +@@ -297,8 +297,8 @@ public class PacketDataSerializer extends ByteBuf { + public PacketDataSerializer a(String s) { + byte[] abyte = s.getBytes(Charsets.UTF_8); + +- if (abyte.length > 32767) { +- throw new EncoderException("String too big (was " + abyte.length + " bytes encoded, max " + 32767 + ")"); ++ if (abyte.length > 44767) { // Paper - raise limit a bit more as normal means can trigger this ++ throw new EncoderException("String too big (was " + s.length() + " bytes encoded, max " + 44767 + ")"); // Paper + } else { + this.d(abyte.length); + this.writeBytes(abyte); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0162-Disable-Vanilla-Chunk-GC.patch b/Spigot-Server-Patches/0162-Disable-Vanilla-Chunk-GC.patch new file mode 100644 index 0000000000..d8ce8e3dd0 --- /dev/null +++ b/Spigot-Server-Patches/0162-Disable-Vanilla-Chunk-GC.patch @@ -0,0 +1,33 @@ +From 0a4cad3330e7c5b0b4b157b4a143a809b9cd4cca Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 26 Sep 2016 01:51:30 -0400 +Subject: [PATCH] Disable Vanilla Chunk GC + +Bukkit has its own system for this. + +diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java +index cc0e8d2c8..7a6d11f20 100644 +--- a/src/main/java/net/minecraft/server/WorldServer.java ++++ b/src/main/java/net/minecraft/server/WorldServer.java +@@ -1020,7 +1020,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { + chunkproviderserver.a(flag); + timings.worldSaveChunks.stopTiming(); // Paper + // CraftBukkit - ArrayList -> Collection +- Collection arraylist = chunkproviderserver.a(); ++ /* //Paper start Collection arraylist = chunkproviderserver.a(); + Iterator iterator = arraylist.iterator(); + + while (iterator.hasNext()) { +@@ -1029,7 +1029,8 @@ public class WorldServer extends World implements IAsyncTaskHandler { + if (chunk != null && !this.manager.a(chunk.locX, chunk.locZ)) { + chunkproviderserver.unload(chunk); + } +- } ++ }*/ ++ // Paper end + timings.worldSave.stopTiming(); // Paper + } + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0162-Raise-string-limit-for-packet-serialization.patch b/Spigot-Server-Patches/0162-Raise-string-limit-for-packet-serialization.patch deleted file mode 100644 index d630fa5c1f..0000000000 --- a/Spigot-Server-Patches/0162-Raise-string-limit-for-packet-serialization.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 392921840f177c1ab77c0ef174c08e1259ac174c Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 21 Sep 2016 23:54:20 -0400 -Subject: [PATCH] Raise string limit for packet serialization - -The default limit is possible to hit with 50 page books with color codes, causing clients to disconnect. - -Bump the limit up a hair to above currently seen sizes. - -diff --git a/src/main/java/net/minecraft/server/PacketDataSerializer.java b/src/main/java/net/minecraft/server/PacketDataSerializer.java -index 7a6619595..68e8c4671 100644 ---- a/src/main/java/net/minecraft/server/PacketDataSerializer.java -+++ b/src/main/java/net/minecraft/server/PacketDataSerializer.java -@@ -297,8 +297,8 @@ public class PacketDataSerializer extends ByteBuf { - public PacketDataSerializer a(String s) { - byte[] abyte = s.getBytes(Charsets.UTF_8); - -- if (abyte.length > 32767) { -- throw new EncoderException("String too big (was " + abyte.length + " bytes encoded, max " + 32767 + ")"); -+ if (abyte.length > 44767) { // Paper - raise limit a bit more as normal means can trigger this -+ throw new EncoderException("String too big (was " + s.length() + " bytes encoded, max " + 44767 + ")"); // Paper - } else { - this.d(abyte.length); - this.writeBytes(abyte); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0163-Disable-Vanilla-Chunk-GC.patch b/Spigot-Server-Patches/0163-Disable-Vanilla-Chunk-GC.patch deleted file mode 100644 index 00b91bfee5..0000000000 --- a/Spigot-Server-Patches/0163-Disable-Vanilla-Chunk-GC.patch +++ /dev/null @@ -1,33 +0,0 @@ -From e4a3829e997f8eed10c0d7be3796031c3789aef2 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 26 Sep 2016 01:51:30 -0400 -Subject: [PATCH] Disable Vanilla Chunk GC - -Bukkit has its own system for this. - -diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index cc0e8d2c8..7a6d11f20 100644 ---- a/src/main/java/net/minecraft/server/WorldServer.java -+++ b/src/main/java/net/minecraft/server/WorldServer.java -@@ -1020,7 +1020,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { - chunkproviderserver.a(flag); - timings.worldSaveChunks.stopTiming(); // Paper - // CraftBukkit - ArrayList -> Collection -- Collection arraylist = chunkproviderserver.a(); -+ /* //Paper start Collection arraylist = chunkproviderserver.a(); - Iterator iterator = arraylist.iterator(); - - while (iterator.hasNext()) { -@@ -1029,7 +1029,8 @@ public class WorldServer extends World implements IAsyncTaskHandler { - if (chunk != null && !this.manager.a(chunk.locX, chunk.locZ)) { - chunkproviderserver.unload(chunk); - } -- } -+ }*/ -+ // Paper end - timings.worldSave.stopTiming(); // Paper - } - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0163-Option-to-remove-corrupt-tile-entities.patch b/Spigot-Server-Patches/0163-Option-to-remove-corrupt-tile-entities.patch new file mode 100644 index 0000000000..41816497e2 --- /dev/null +++ b/Spigot-Server-Patches/0163-Option-to-remove-corrupt-tile-entities.patch @@ -0,0 +1,45 @@ +From c7e769e167626264f0fbc8a15080adcae1c4765e 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 bcf24cb49..220ecaf8d 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -375,4 +375,9 @@ public class PaperWorldConfig { + private void maxAutoSaveChunksPerTick() { + maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); + } ++ ++ public boolean removeCorruptTEs = false; ++ private void removeCorruptTEs() { ++ removeCorruptTEs = getBoolean("remove-corrupt-tile-entities", false); ++ } + } +diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java +index 9f7f32dc2..d850dbfc3 100644 +--- a/src/main/java/net/minecraft/server/Chunk.java ++++ b/src/main/java/net/minecraft/server/Chunk.java +@@ -783,11 +783,17 @@ public class Chunk { + "Chunk coordinates: " + (this.locX * 16) + "," + (this.locZ * 16)); + e.printStackTrace(); + ServerInternalException.reportInternalException(e); ++ ++ if (this.world.paperConfig.removeCorruptTEs) { ++ this.removeTileEntity(tileentity.getPosition()); ++ org.bukkit.Bukkit.getLogger().info("Removing corrupt tile entity"); ++ } + // Paper end + // CraftBukkit end + } + } + ++ public void removeTileEntity(BlockPosition blockposition) { this.d(blockposition); } // Paper - OBFHELPER + public void d(BlockPosition blockposition) { + if (this.j) { + TileEntity tileentity = (TileEntity) this.tileEntities.remove(blockposition); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0164-Add-EntityZapEvent.patch b/Spigot-Server-Patches/0164-Add-EntityZapEvent.patch new file mode 100644 index 0000000000..4c2297020c --- /dev/null +++ b/Spigot-Server-Patches/0164-Add-EntityZapEvent.patch @@ -0,0 +1,71 @@ +From dd9888bc9fafe9ec3bb38dc92d335f9f045ead78 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/server/EntityPig.java b/src/main/java/net/minecraft/server/EntityPig.java +index 88bd674ba..80ad25c1b 100644 +--- a/src/main/java/net/minecraft/server/EntityPig.java ++++ b/src/main/java/net/minecraft/server/EntityPig.java +@@ -159,6 +159,12 @@ public class EntityPig extends EntityAnimal { + if (!this.world.isClientSide && !this.dead) { + EntityPigZombie entitypigzombie = new EntityPigZombie(this.world); + ++ // 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/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java +index ee11691bf..4ad75468c 100644 +--- a/src/main/java/net/minecraft/server/EntityVillager.java ++++ b/src/main/java/net/minecraft/server/EntityVillager.java +@@ -616,6 +616,12 @@ public class EntityVillager extends EntityAgeable implements NPC, IMerchant { + if (!this.world.isClientSide && !this.dead) { + EntityWitch entitywitch = new EntityWitch(this.world); + ++ // 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(this.world.D(new BlockPosition(entitywitch)), (GroupDataEntity) null); + entitywitch.setAI(this.hasAI()); +@@ -624,7 +630,7 @@ public class EntityVillager extends EntityAgeable implements NPC, IMerchant { + entitywitch.setCustomNameVisible(this.getCustomNameVisible()); + } + +- this.world.addEntity(entitywitch); ++ this.world.addEntity(entitywitch, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); // Paper - Added lightning spawn reason for this entity + 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 95b12331e..4d252aa47 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -673,6 +673,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); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0164-Option-to-remove-corrupt-tile-entities.patch b/Spigot-Server-Patches/0164-Option-to-remove-corrupt-tile-entities.patch deleted file mode 100644 index 7707280fb1..0000000000 --- a/Spigot-Server-Patches/0164-Option-to-remove-corrupt-tile-entities.patch +++ /dev/null @@ -1,45 +0,0 @@ -From b51be29b2da1afbb7de35723ba0dad769edee720 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 bcf24cb49..220ecaf8d 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -375,4 +375,9 @@ public class PaperWorldConfig { - private void maxAutoSaveChunksPerTick() { - maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); - } -+ -+ public boolean removeCorruptTEs = false; -+ private void removeCorruptTEs() { -+ removeCorruptTEs = getBoolean("remove-corrupt-tile-entities", false); -+ } - } -diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java -index 9f7f32dc2..d850dbfc3 100644 ---- a/src/main/java/net/minecraft/server/Chunk.java -+++ b/src/main/java/net/minecraft/server/Chunk.java -@@ -783,11 +783,17 @@ public class Chunk { - "Chunk coordinates: " + (this.locX * 16) + "," + (this.locZ * 16)); - e.printStackTrace(); - ServerInternalException.reportInternalException(e); -+ -+ if (this.world.paperConfig.removeCorruptTEs) { -+ this.removeTileEntity(tileentity.getPosition()); -+ org.bukkit.Bukkit.getLogger().info("Removing corrupt tile entity"); -+ } - // Paper end - // CraftBukkit end - } - } - -+ public void removeTileEntity(BlockPosition blockposition) { this.d(blockposition); } // Paper - OBFHELPER - public void d(BlockPosition blockposition) { - if (this.j) { - TileEntity tileentity = (TileEntity) this.tileEntities.remove(blockposition); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0165-Add-EntityZapEvent.patch b/Spigot-Server-Patches/0165-Add-EntityZapEvent.patch deleted file mode 100644 index 8ba04db23f..0000000000 --- a/Spigot-Server-Patches/0165-Add-EntityZapEvent.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 1eeb3eb2836dad8e57a9c72fc70284fad2856e0e 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/server/EntityPig.java b/src/main/java/net/minecraft/server/EntityPig.java -index 88bd674ba..80ad25c1b 100644 ---- a/src/main/java/net/minecraft/server/EntityPig.java -+++ b/src/main/java/net/minecraft/server/EntityPig.java -@@ -159,6 +159,12 @@ public class EntityPig extends EntityAnimal { - if (!this.world.isClientSide && !this.dead) { - EntityPigZombie entitypigzombie = new EntityPigZombie(this.world); - -+ // 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/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java -index ee11691bf..4ad75468c 100644 ---- a/src/main/java/net/minecraft/server/EntityVillager.java -+++ b/src/main/java/net/minecraft/server/EntityVillager.java -@@ -616,6 +616,12 @@ public class EntityVillager extends EntityAgeable implements NPC, IMerchant { - if (!this.world.isClientSide && !this.dead) { - EntityWitch entitywitch = new EntityWitch(this.world); - -+ // 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(this.world.D(new BlockPosition(entitywitch)), (GroupDataEntity) null); - entitywitch.setAI(this.hasAI()); -@@ -624,7 +630,7 @@ public class EntityVillager extends EntityAgeable implements NPC, IMerchant { - entitywitch.setCustomNameVisible(this.getCustomNameVisible()); - } - -- this.world.addEntity(entitywitch); -+ this.world.addEntity(entitywitch, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); // Paper - Added lightning spawn reason for this entity - 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 95b12331e..4d252aa47 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -673,6 +673,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); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0165-Don-t-load-Chunks-from-Hoppers-and-other-things.patch b/Spigot-Server-Patches/0165-Don-t-load-Chunks-from-Hoppers-and-other-things.patch new file mode 100644 index 0000000000..a36549ef22 --- /dev/null +++ b/Spigot-Server-Patches/0165-Don-t-load-Chunks-from-Hoppers-and-other-things.patch @@ -0,0 +1,36 @@ +From d766004f07f7cb887283db77e0adc5ca4307c7b5 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/server/BlockChest.java b/src/main/java/net/minecraft/server/BlockChest.java +index 9c4d1c938..dd1c1a39b 100644 +--- a/src/main/java/net/minecraft/server/BlockChest.java ++++ b/src/main/java/net/minecraft/server/BlockChest.java +@@ -339,7 +339,13 @@ public class BlockChest extends BlockTileEntity { + while (iterator.hasNext()) { + EnumDirection enumdirection = (EnumDirection) iterator.next(); + BlockPosition blockposition1 = blockposition.shift(enumdirection); +- Block block = world.getType(blockposition1).getBlock(); ++ // Paper start - don't load chunks if the other side of the chest is in unloaded chunk ++ final IBlockData type = world.getTypeIfLoaded(blockposition1); // Paper ++ if (type == null) { ++ continue; ++ } ++ Block block = type.getBlock(); ++ // Paper end + + if (block == this) { + if (this.e(world, blockposition1)) { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0166-Don-t-load-Chunks-from-Hoppers-and-other-things.patch b/Spigot-Server-Patches/0166-Don-t-load-Chunks-from-Hoppers-and-other-things.patch deleted file mode 100644 index 313ea5d400..0000000000 --- a/Spigot-Server-Patches/0166-Don-t-load-Chunks-from-Hoppers-and-other-things.patch +++ /dev/null @@ -1,36 +0,0 @@ -From a8c1693f11909a132dbe93641df6029626f45b08 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/server/BlockChest.java b/src/main/java/net/minecraft/server/BlockChest.java -index 9c4d1c938..dd1c1a39b 100644 ---- a/src/main/java/net/minecraft/server/BlockChest.java -+++ b/src/main/java/net/minecraft/server/BlockChest.java -@@ -339,7 +339,13 @@ public class BlockChest extends BlockTileEntity { - while (iterator.hasNext()) { - EnumDirection enumdirection = (EnumDirection) iterator.next(); - BlockPosition blockposition1 = blockposition.shift(enumdirection); -- Block block = world.getType(blockposition1).getBlock(); -+ // Paper start - don't load chunks if the other side of the chest is in unloaded chunk -+ final IBlockData type = world.getTypeIfLoaded(blockposition1); // Paper -+ if (type == null) { -+ continue; -+ } -+ Block block = type.getBlock(); -+ // Paper end - - if (block == this) { - if (this.e(world, blockposition1)) { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0166-Prevent-Auto-Save-if-Save-Queue-is-full.patch b/Spigot-Server-Patches/0166-Prevent-Auto-Save-if-Save-Queue-is-full.patch new file mode 100644 index 0000000000..7bf4352f6e --- /dev/null +++ b/Spigot-Server-Patches/0166-Prevent-Auto-Save-if-Save-Queue-is-full.patch @@ -0,0 +1,68 @@ +From 76378e2f8f15b2354bbaeda957cd43eb6617d578 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 3 Nov 2016 21:52:22 -0400 +Subject: [PATCH] Prevent Auto Save if Save Queue is full + +If the save queue already has 50 (configurable) of chunks pending, +then avoid processing auto save (which would add more) + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 220ecaf8d..4ca44afa9 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -376,6 +376,11 @@ public class PaperWorldConfig { + maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); + } + ++ public int queueSizeAutoSaveThreshold = 50; ++ private void queueSizeAutoSaveThreshold() { ++ queueSizeAutoSaveThreshold = getInt("save-queue-limit-for-auto-save", 50); ++ } ++ + public boolean removeCorruptTEs = false; + private void removeCorruptTEs() { + removeCorruptTEs = getBoolean("remove-corrupt-tile-entities", false); +diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java +index 71df9e4aa..0fb1f8427 100644 +--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java +@@ -254,6 +254,14 @@ public class ChunkProviderServer implements IChunkProvider { + int i = 0; + + // CraftBukkit start ++ // Paper start ++ final ChunkRegionLoader chunkLoader = (ChunkRegionLoader) world.getChunkProviderServer().chunkLoader; ++ final int queueSize = chunkLoader.getQueueSize(); ++ if (queueSize > world.paperConfig.queueSizeAutoSaveThreshold){ ++ return false; ++ } ++ final int autoSaveLimit = world.paperConfig.maxAutoSaveChunksPerTick; ++ // Paper end + Iterator iterator = this.chunks.values().iterator(); + while (iterator.hasNext()) { + Chunk chunk = (Chunk) iterator.next(); +@@ -267,7 +275,7 @@ public class ChunkProviderServer implements IChunkProvider { + this.saveChunk(chunk); + chunk.f(false); + ++i; +- if (!flag && i >= world.paperConfig.maxAutoSaveChunksPerTick) { // Spigot - // Paper - Incremental Auto Save - cap max per tick ++ if (!flag && i >= autoSaveLimit) { // Spigot - // Paper - Incremental Auto Save - cap max per tick + return false; + } + } +diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java +index 90d069539..895882b2e 100644 +--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java ++++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java +@@ -32,6 +32,8 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { + this.e = dataconvertermanager; + } + ++ public int getQueueSize() { return queue.size(); } // Paper ++ + // CraftBukkit start - Add async variant, provide compatibility + @Nullable + public Chunk a(World world, int i, int j) throws IOException { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0167-Chunk-Save-Stats-Debug-Option.patch b/Spigot-Server-Patches/0167-Chunk-Save-Stats-Debug-Option.patch new file mode 100644 index 0000000000..bd9288df3c --- /dev/null +++ b/Spigot-Server-Patches/0167-Chunk-Save-Stats-Debug-Option.patch @@ -0,0 +1,94 @@ +From ebb2c9fa657f2f5ed42df82a3b7ef1a5461027f4 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 4 Nov 2016 02:12:10 -0400 +Subject: [PATCH] Chunk Save Stats Debug Option + +Adds a command line flag to enable stats on how chunk saves are processing. + +Stats on current queue, how many was processed and how many were queued. + +diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java +index 0fb1f8427..dabe4137f 100644 +--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java +@@ -28,6 +28,11 @@ public class ChunkProviderServer implements IChunkProvider { + public final it.unimi.dsi.fastutil.longs.LongSet unloadQueue = new it.unimi.dsi.fastutil.longs.LongArraySet(); // PAIL: private -> public // Paper + public final ChunkGenerator chunkGenerator; + private final IChunkLoader chunkLoader; ++ // Paper start - chunk save stats ++ private long lastQueuedSaves = 0L; // Paper ++ private long lastProcessedSaves = 0L; // Paper ++ private long lastSaveStatPrinted = System.currentTimeMillis(); ++ // Paper end + // Paper start + protected Chunk lastChunkByPos = null; + public Long2ObjectOpenHashMap chunks = new Long2ObjectOpenHashMap(8192) { +@@ -257,6 +262,30 @@ public class ChunkProviderServer implements IChunkProvider { + // Paper start + final ChunkRegionLoader chunkLoader = (ChunkRegionLoader) world.getChunkProviderServer().chunkLoader; + final int queueSize = chunkLoader.getQueueSize(); ++ ++ final long now = System.currentTimeMillis(); ++ final long timeSince = (now - lastSaveStatPrinted) / 1000; ++ final Integer printRateSecs = Integer.getInteger("printSaveStats"); ++ if (printRateSecs != null && timeSince >= printRateSecs) { ++ final String timeStr = "/" + timeSince +"s"; ++ final long queuedSaves = chunkLoader.getQueuedSaves(); ++ long queuedDiff = queuedSaves - lastQueuedSaves; ++ lastQueuedSaves = queuedSaves; ++ ++ final long processedSaves = chunkLoader.getProcessedSaves(); ++ long processedDiff = processedSaves - lastProcessedSaves; ++ lastProcessedSaves = processedSaves; ++ ++ lastSaveStatPrinted = now; ++ if (processedDiff > 0 || queueSize > 0 || queuedDiff > 0) { ++ System.out.println("[Chunk Save Stats] " + world.worldData.getName() + ++ " - Current: " + queueSize + ++ " - Queued: " + queuedDiff + timeStr + ++ " - Processed: " +processedDiff + timeStr ++ ); ++ } ++ } ++ + if (queueSize > world.paperConfig.queueSizeAutoSaveThreshold){ + return false; + } +diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java +index 895882b2e..a4c0b0c96 100644 +--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java ++++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java +@@ -32,7 +32,13 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { + this.e = dataconvertermanager; + } + +- public int getQueueSize() { return queue.size(); } // Paper ++ // Paper start ++ private long queuedSaves = 0; ++ private final java.util.concurrent.atomic.AtomicLong processedSaves = new java.util.concurrent.atomic.AtomicLong(0L); ++ public int getQueueSize() { return queue.size(); } ++ public long getQueuedSaves() { return queuedSaves; } ++ public long getProcessedSaves() { return processedSaves.longValue(); } ++ // Paper end + + // CraftBukkit start - Add async variant, provide compatibility + @Nullable +@@ -142,6 +148,7 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { + synchronized (lock) { // Paper - Chunk queue improvements + this.b.put(chunkcoordintpair, nbttagcompound); + } ++ queuedSaves++; // Paper + queue.add(new QueuedChunk(chunkcoordintpair, nbttagcompound)); // Paper - Chunk queue improvements + + FileIOThread.a().a(this); +@@ -159,6 +166,7 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { + return false; + } else { + ChunkCoordIntPair chunkcoordintpair = chunk.coords; // Paper - Chunk queue improvements ++ processedSaves.incrementAndGet(); // Paper + + boolean flag; + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0167-Prevent-Auto-Save-if-Save-Queue-is-full.patch b/Spigot-Server-Patches/0167-Prevent-Auto-Save-if-Save-Queue-is-full.patch deleted file mode 100644 index 698296a8f6..0000000000 --- a/Spigot-Server-Patches/0167-Prevent-Auto-Save-if-Save-Queue-is-full.patch +++ /dev/null @@ -1,68 +0,0 @@ -From f8e15ecff289a756ab1e2cdf81ea4fbc150e4bd2 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Nov 2016 21:52:22 -0400 -Subject: [PATCH] Prevent Auto Save if Save Queue is full - -If the save queue already has 50 (configurable) of chunks pending, -then avoid processing auto save (which would add more) - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 220ecaf8d..4ca44afa9 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -376,6 +376,11 @@ public class PaperWorldConfig { - maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); - } - -+ public int queueSizeAutoSaveThreshold = 50; -+ private void queueSizeAutoSaveThreshold() { -+ queueSizeAutoSaveThreshold = getInt("save-queue-limit-for-auto-save", 50); -+ } -+ - public boolean removeCorruptTEs = false; - private void removeCorruptTEs() { - removeCorruptTEs = getBoolean("remove-corrupt-tile-entities", false); -diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java -index 71df9e4aa..0fb1f8427 100644 ---- a/src/main/java/net/minecraft/server/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java -@@ -254,6 +254,14 @@ public class ChunkProviderServer implements IChunkProvider { - int i = 0; - - // CraftBukkit start -+ // Paper start -+ final ChunkRegionLoader chunkLoader = (ChunkRegionLoader) world.getChunkProviderServer().chunkLoader; -+ final int queueSize = chunkLoader.getQueueSize(); -+ if (queueSize > world.paperConfig.queueSizeAutoSaveThreshold){ -+ return false; -+ } -+ final int autoSaveLimit = world.paperConfig.maxAutoSaveChunksPerTick; -+ // Paper end - Iterator iterator = this.chunks.values().iterator(); - while (iterator.hasNext()) { - Chunk chunk = (Chunk) iterator.next(); -@@ -267,7 +275,7 @@ public class ChunkProviderServer implements IChunkProvider { - this.saveChunk(chunk); - chunk.f(false); - ++i; -- if (!flag && i >= world.paperConfig.maxAutoSaveChunksPerTick) { // Spigot - // Paper - Incremental Auto Save - cap max per tick -+ if (!flag && i >= autoSaveLimit) { // Spigot - // Paper - Incremental Auto Save - cap max per tick - return false; - } - } -diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -index 90d069539..895882b2e 100644 ---- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -@@ -32,6 +32,8 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { - this.e = dataconvertermanager; - } - -+ public int getQueueSize() { return queue.size(); } // Paper -+ - // CraftBukkit start - Add async variant, provide compatibility - @Nullable - public Chunk a(World world, int i, int j) throws IOException { --- -2.12.2.windows.2 - diff --git a/Spigot-Server-Patches/0168-Chunk-Save-Stats-Debug-Option.patch b/Spigot-Server-Patches/0168-Chunk-Save-Stats-Debug-Option.patch deleted file mode 100644 index ffbcd8fc10..0000000000 --- a/Spigot-Server-Patches/0168-Chunk-Save-Stats-Debug-Option.patch +++ /dev/null @@ -1,94 +0,0 @@ -From bdd1befe24e100ea6a31702f49dfbe8020bbf0cf Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 4 Nov 2016 02:12:10 -0400 -Subject: [PATCH] Chunk Save Stats Debug Option - -Adds a command line flag to enable stats on how chunk saves are processing. - -Stats on current queue, how many was processed and how many were queued. - -diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java -index 0fb1f8427..dabe4137f 100644 ---- a/src/main/java/net/minecraft/server/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java -@@ -28,6 +28,11 @@ public class ChunkProviderServer implements IChunkProvider { - public final it.unimi.dsi.fastutil.longs.LongSet unloadQueue = new it.unimi.dsi.fastutil.longs.LongArraySet(); // PAIL: private -> public // Paper - public final ChunkGenerator chunkGenerator; - private final IChunkLoader chunkLoader; -+ // Paper start - chunk save stats -+ private long lastQueuedSaves = 0L; // Paper -+ private long lastProcessedSaves = 0L; // Paper -+ private long lastSaveStatPrinted = System.currentTimeMillis(); -+ // Paper end - // Paper start - protected Chunk lastChunkByPos = null; - public Long2ObjectOpenHashMap chunks = new Long2ObjectOpenHashMap(8192) { -@@ -257,6 +262,30 @@ public class ChunkProviderServer implements IChunkProvider { - // Paper start - final ChunkRegionLoader chunkLoader = (ChunkRegionLoader) world.getChunkProviderServer().chunkLoader; - final int queueSize = chunkLoader.getQueueSize(); -+ -+ final long now = System.currentTimeMillis(); -+ final long timeSince = (now - lastSaveStatPrinted) / 1000; -+ final Integer printRateSecs = Integer.getInteger("printSaveStats"); -+ if (printRateSecs != null && timeSince >= printRateSecs) { -+ final String timeStr = "/" + timeSince +"s"; -+ final long queuedSaves = chunkLoader.getQueuedSaves(); -+ long queuedDiff = queuedSaves - lastQueuedSaves; -+ lastQueuedSaves = queuedSaves; -+ -+ final long processedSaves = chunkLoader.getProcessedSaves(); -+ long processedDiff = processedSaves - lastProcessedSaves; -+ lastProcessedSaves = processedSaves; -+ -+ lastSaveStatPrinted = now; -+ if (processedDiff > 0 || queueSize > 0 || queuedDiff > 0) { -+ System.out.println("[Chunk Save Stats] " + world.worldData.getName() + -+ " - Current: " + queueSize + -+ " - Queued: " + queuedDiff + timeStr + -+ " - Processed: " +processedDiff + timeStr -+ ); -+ } -+ } -+ - if (queueSize > world.paperConfig.queueSizeAutoSaveThreshold){ - return false; - } -diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -index 895882b2e..a4c0b0c96 100644 ---- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -@@ -32,7 +32,13 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { - this.e = dataconvertermanager; - } - -- public int getQueueSize() { return queue.size(); } // Paper -+ // Paper start -+ private long queuedSaves = 0; -+ private final java.util.concurrent.atomic.AtomicLong processedSaves = new java.util.concurrent.atomic.AtomicLong(0L); -+ public int getQueueSize() { return queue.size(); } -+ public long getQueuedSaves() { return queuedSaves; } -+ public long getProcessedSaves() { return processedSaves.longValue(); } -+ // Paper end - - // CraftBukkit start - Add async variant, provide compatibility - @Nullable -@@ -142,6 +148,7 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { - synchronized (lock) { // Paper - Chunk queue improvements - this.b.put(chunkcoordintpair, nbttagcompound); - } -+ queuedSaves++; // Paper - queue.add(new QueuedChunk(chunkcoordintpair, nbttagcompound)); // Paper - Chunk queue improvements - - FileIOThread.a().a(this); -@@ -159,6 +166,7 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { - return false; - } else { - ChunkCoordIntPair chunkcoordintpair = chunk.coords; // Paper - Chunk queue improvements -+ processedSaves.incrementAndGet(); // Paper - - boolean flag; - --- -2.12.2.windows.2 - diff --git a/Spigot-Server-Patches/0168-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch b/Spigot-Server-Patches/0168-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch new file mode 100644 index 0000000000..dec12bc5de --- /dev/null +++ b/Spigot-Server-Patches/0168-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch @@ -0,0 +1,65 @@ +From fbcfb4bcbf57547d045729d75dac619eacc7b088 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 4ca44afa9..dcf64efcc 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -385,4 +385,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/server/EntityFallingBlock.java b/src/main/java/net/minecraft/server/EntityFallingBlock.java +index 8059e6dcd..a4f465e38 100644 +--- a/src/main/java/net/minecraft/server/EntityFallingBlock.java ++++ b/src/main/java/net/minecraft/server/EntityFallingBlock.java +@@ -251,6 +251,14 @@ public class EntityFallingBlock extends Entity { + this.block = Block.getById(nbttagcompound.getByte("Tile") & 255).fromLegacyData(i); + } + ++ // 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.dc || b == Blocks.dd)) { ++ this.block = Blocks.STONE.getBlockData(); ++ } ++ // Paper end ++ + this.ticksLived = nbttagcompound.getInt("Time"); + Block block = this.block.getBlock(); + +diff --git a/src/main/java/net/minecraft/server/ItemMonsterEgg.java b/src/main/java/net/minecraft/server/ItemMonsterEgg.java +index 1a01a57d2..f914ad417 100644 +--- a/src/main/java/net/minecraft/server/ItemMonsterEgg.java ++++ b/src/main/java/net/minecraft/server/ItemMonsterEgg.java +@@ -102,7 +102,14 @@ public class ItemMonsterEgg extends Item { + NBTTagCompound nbttagcompound1 = entity.e(new NBTTagCompound()); + UUID uuid = entity.getUniqueID(); + +- nbttagcompound1.a(nbttagcompound.getCompound("EntityTag")); ++ // Paper start - Filter out position and motion information ++ final NBTTagCompound entityTag = nbttagcompound.getCompound("EntityTag"); ++ if (world.paperConfig.filterNBTFromSpawnEgg) { ++ entityTag.remove("Pos"); ++ entityTag.remove("Motion"); ++ } ++ nbttagcompound1.a(entityTag); ++ // Paper end + entity.a(uuid); + entity.f(nbttagcompound1); + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0169-Cache-user-authenticator-threads.patch b/Spigot-Server-Patches/0169-Cache-user-authenticator-threads.patch new file mode 100644 index 0000000000..e337a7739a --- /dev/null +++ b/Spigot-Server-Patches/0169-Cache-user-authenticator-threads.patch @@ -0,0 +1,67 @@ +From 08f57ad5059ec5d13942f6abd194ce96003c043a 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/LoginListener.java b/src/main/java/net/minecraft/server/LoginListener.java +index fe390feb9..350ec0323 100644 +--- a/src/main/java/net/minecraft/server/LoginListener.java ++++ b/src/main/java/net/minecraft/server/LoginListener.java +@@ -84,6 +84,12 @@ public class LoginListener implements PacketLoginInListener, ITickable { + + } + ++ // 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() + { +@@ -166,8 +172,8 @@ public class LoginListener implements PacketLoginInListener, ITickable { + this.networkManager.sendPacket(new PacketLoginOutEncryptionBegin("", this.server.O().getPublic(), 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 { +@@ -179,7 +185,8 @@ public class LoginListener implements PacketLoginInListener, ITickable { + server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + i.getName(), ex); + } + } +- }.start(); ++ }); ++ // Paper end + // Spigot end + } + +@@ -195,7 +202,8 @@ public class LoginListener implements PacketLoginInListener, ITickable { + this.loginKey = packetlogininencryptionbegin.a(privatekey); + this.g = LoginListener.EnumProtocolState.AUTHENTICATING; + this.networkManager.a(this.loginKey); +- (new Thread("User Authenticator #" + LoginListener.b.incrementAndGet()) { ++ // Paper start - Cache authenticator threads ++ authenticatorPool.execute(new Runnable() { + public void run() { + GameProfile gameprofile = LoginListener.this.i; + +@@ -242,7 +250,8 @@ public class LoginListener implements PacketLoginInListener, ITickable { + + return LoginListener.this.server.ac() && socketaddress instanceof InetSocketAddress ? ((InetSocketAddress) socketaddress).getAddress() : null; + } +- }).start(); ++ }); ++ // Paper end + } + } + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0169-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch b/Spigot-Server-Patches/0169-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch deleted file mode 100644 index e423936831..0000000000 --- a/Spigot-Server-Patches/0169-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch +++ /dev/null @@ -1,65 +0,0 @@ -From b277f7f16147d91a04ac1708888225076084af68 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 4ca44afa9..dcf64efcc 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -385,4 +385,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/server/EntityFallingBlock.java b/src/main/java/net/minecraft/server/EntityFallingBlock.java -index 8059e6dcd..a4f465e38 100644 ---- a/src/main/java/net/minecraft/server/EntityFallingBlock.java -+++ b/src/main/java/net/minecraft/server/EntityFallingBlock.java -@@ -251,6 +251,14 @@ public class EntityFallingBlock extends Entity { - this.block = Block.getById(nbttagcompound.getByte("Tile") & 255).fromLegacyData(i); - } - -+ // 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.dc || b == Blocks.dd)) { -+ this.block = Blocks.STONE.getBlockData(); -+ } -+ // Paper end -+ - this.ticksLived = nbttagcompound.getInt("Time"); - Block block = this.block.getBlock(); - -diff --git a/src/main/java/net/minecraft/server/ItemMonsterEgg.java b/src/main/java/net/minecraft/server/ItemMonsterEgg.java -index 1a01a57d2..f914ad417 100644 ---- a/src/main/java/net/minecraft/server/ItemMonsterEgg.java -+++ b/src/main/java/net/minecraft/server/ItemMonsterEgg.java -@@ -102,7 +102,14 @@ public class ItemMonsterEgg extends Item { - NBTTagCompound nbttagcompound1 = entity.e(new NBTTagCompound()); - UUID uuid = entity.getUniqueID(); - -- nbttagcompound1.a(nbttagcompound.getCompound("EntityTag")); -+ // Paper start - Filter out position and motion information -+ final NBTTagCompound entityTag = nbttagcompound.getCompound("EntityTag"); -+ if (world.paperConfig.filterNBTFromSpawnEgg) { -+ entityTag.remove("Pos"); -+ entityTag.remove("Motion"); -+ } -+ nbttagcompound1.a(entityTag); -+ // Paper end - entity.a(uuid); - entity.f(nbttagcompound1); - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0170-Cache-user-authenticator-threads.patch b/Spigot-Server-Patches/0170-Cache-user-authenticator-threads.patch deleted file mode 100644 index 3e91a6f9b5..0000000000 --- a/Spigot-Server-Patches/0170-Cache-user-authenticator-threads.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 1bc16bd4b171e1b4ab7c48ebbe5c336b4f1eeae0 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/LoginListener.java b/src/main/java/net/minecraft/server/LoginListener.java -index fe390feb9..350ec0323 100644 ---- a/src/main/java/net/minecraft/server/LoginListener.java -+++ b/src/main/java/net/minecraft/server/LoginListener.java -@@ -84,6 +84,12 @@ public class LoginListener implements PacketLoginInListener, ITickable { - - } - -+ // 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() - { -@@ -166,8 +172,8 @@ public class LoginListener implements PacketLoginInListener, ITickable { - this.networkManager.sendPacket(new PacketLoginOutEncryptionBegin("", this.server.O().getPublic(), 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 { -@@ -179,7 +185,8 @@ public class LoginListener implements PacketLoginInListener, ITickable { - server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + i.getName(), ex); - } - } -- }.start(); -+ }); -+ // Paper end - // Spigot end - } - -@@ -195,7 +202,8 @@ public class LoginListener implements PacketLoginInListener, ITickable { - this.loginKey = packetlogininencryptionbegin.a(privatekey); - this.g = LoginListener.EnumProtocolState.AUTHENTICATING; - this.networkManager.a(this.loginKey); -- (new Thread("User Authenticator #" + LoginListener.b.incrementAndGet()) { -+ // Paper start - Cache authenticator threads -+ authenticatorPool.execute(new Runnable() { - public void run() { - GameProfile gameprofile = LoginListener.this.i; - -@@ -242,7 +250,8 @@ public class LoginListener implements PacketLoginInListener, ITickable { - - return LoginListener.this.server.ac() && socketaddress instanceof InetSocketAddress ? ((InetSocketAddress) socketaddress).getAddress() : null; - } -- }).start(); -+ }); -+ // Paper end - } - } - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0170-Optimize-Network-Queue.patch b/Spigot-Server-Patches/0170-Optimize-Network-Queue.patch new file mode 100644 index 0000000000..c41e4677f0 --- /dev/null +++ b/Spigot-Server-Patches/0170-Optimize-Network-Queue.patch @@ -0,0 +1,22 @@ +From 50c7768c8c2458a09c65ab4034ee134336d33dc3 Mon Sep 17 00:00:00 2001 +From: vemacs +Date: Wed, 23 Nov 2016 12:54:56 -0500 +Subject: [PATCH] Optimize Network Queue + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 8134501c7..8df30e3d0 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -103,7 +103,7 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs + private final GameProfileRepository X; + private final UserCache Y; + private long Z; +- protected final Queue> j = new java.util.concurrent.ConcurrentLinkedQueue>(); // Spigot, PAIL: Rename ++ protected final Queue> j = new com.destroystokyo.paper.utils.CachedSizeConcurrentLinkedQueue<>(); // Spigot, PAIL: Rename // Paper - Make size() constant-time + private Thread serverThread; + private long ab = aw(); + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0171-Optimise-NetworkManager.patch b/Spigot-Server-Patches/0171-Optimise-NetworkManager.patch new file mode 100644 index 0000000000..05fc8a2868 --- /dev/null +++ b/Spigot-Server-Patches/0171-Optimise-NetworkManager.patch @@ -0,0 +1,125 @@ +From 863b08010dbfe4e4046e553ced31acb9c2d2fde1 Mon Sep 17 00:00:00 2001 +From: Alfie Cleveland +Date: Fri, 25 Nov 2016 20:35:05 +0000 +Subject: [PATCH] Optimise NetworkManager + + +diff --git a/src/main/java/net/minecraft/server/NetworkManager.java b/src/main/java/net/minecraft/server/NetworkManager.java +index 184ef32a8..be14c0b25 100644 +--- a/src/main/java/net/minecraft/server/NetworkManager.java ++++ b/src/main/java/net/minecraft/server/NetworkManager.java +@@ -62,8 +62,8 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + } + }; + private final EnumProtocolDirection h; +- private final Queue i = Queues.newConcurrentLinkedQueue(); +- private final ReentrantReadWriteLock j = new ReentrantReadWriteLock(); ++ // private final Queue i = Queues.newConcurrentLinkedQueue(); // Paper ++ // private final ReentrantReadWriteLock j = new ReentrantReadWriteLock(); // Paper + public Channel channel; + // Spigot Start // PAIL + public SocketAddress l; +@@ -141,32 +141,36 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + if (this.isConnected()) { + this.m(); + this.a(packet, (GenericFutureListener[]) null); +- } else { +- this.j.writeLock().lock(); +- +- try { +- this.i.add(new NetworkManager.QueuedPacket(packet, (GenericFutureListener[]) null)); +- } finally { +- this.j.writeLock().unlock(); +- } + } +- ++ // Paper start - Remove but force a conflict ++// else { ++// this.j.writeLock().lock(); ++// ++// try { ++// this.i.add(new NetworkManager.QueuedPacket(packet, (GenericFutureListener[]) null)); ++// } finally { ++// this.j.writeLock().unlock(); ++// } ++// } ++ // Paper end + } + + public void sendPacket(Packet packet, GenericFutureListener> genericfuturelistener, GenericFutureListener>... agenericfuturelistener) { + if (this.isConnected()) { + this.m(); + this.a(packet, (GenericFutureListener[]) ArrayUtils.add(agenericfuturelistener, 0, genericfuturelistener)); +- } else { +- this.j.writeLock().lock(); +- +- try { +- this.i.add(new NetworkManager.QueuedPacket(packet, (GenericFutureListener[]) ArrayUtils.add(agenericfuturelistener, 0, genericfuturelistener))); +- } finally { +- this.j.writeLock().unlock(); +- } + } +- ++ // Paper start - Remove but force a conflict ++// else { ++// this.j.writeLock().lock(); ++// ++// try { ++// this.i.add(new NetworkManager.QueuedPacket(packet, (GenericFutureListener[]) ArrayUtils.add(agenericfuturelistener, 0, genericfuturelistener))); ++// } finally { ++// this.j.writeLock().unlock(); ++// } ++// } ++ // Paper end + } + + private void a(final Packet packet, @Nullable final GenericFutureListener>[] agenericfuturelistener) { +@@ -211,20 +215,22 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + } + + private void m() { +- if (this.channel != null && this.channel.isOpen()) { +- this.j.readLock().lock(); +- +- try { +- while (!this.i.isEmpty()) { +- NetworkManager.QueuedPacket networkmanager_queuedpacket = (NetworkManager.QueuedPacket) this.i.poll(); +- +- this.a(networkmanager_queuedpacket.a, networkmanager_queuedpacket.b); +- } +- } finally { +- this.j.readLock().unlock(); +- } +- +- } ++ // Paper start - Remove but force a conflict ++// if (this.channel != null && this.channel.isOpen()) { ++// this.j.readLock().lock(); ++// ++// try { ++// while (!this.i.isEmpty()) { ++// NetworkManager.QueuedPacket networkmanager_queuedpacket = (NetworkManager.QueuedPacket) this.i.poll(); ++// ++// this.a(networkmanager_queuedpacket.a, networkmanager_queuedpacket.b); ++// } ++// } finally { ++// this.j.readLock().unlock(); ++// } ++// ++// } ++ // Paper end + } + + public void a() { +@@ -317,7 +323,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + } else if (this.i() != null) { + this.i().a(new ChatComponentText("Disconnected")); + } +- this.i.clear(); // Free up packet queue. ++ // this.i.clear(); // Free up packet queue. // Paper - remove unneeded packet queue + } + + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0171-Optimize-Network-Queue.patch b/Spigot-Server-Patches/0171-Optimize-Network-Queue.patch deleted file mode 100644 index ef5e41e97e..0000000000 --- a/Spigot-Server-Patches/0171-Optimize-Network-Queue.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 65234da12571d96b72b7d55fb939a1a4b4c807d9 Mon Sep 17 00:00:00 2001 -From: vemacs -Date: Wed, 23 Nov 2016 12:54:56 -0500 -Subject: [PATCH] Optimize Network Queue - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 8134501c7..8df30e3d0 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -103,7 +103,7 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs - private final GameProfileRepository X; - private final UserCache Y; - private long Z; -- protected final Queue> j = new java.util.concurrent.ConcurrentLinkedQueue>(); // Spigot, PAIL: Rename -+ protected final Queue> j = new com.destroystokyo.paper.utils.CachedSizeConcurrentLinkedQueue<>(); // Spigot, PAIL: Rename // Paper - Make size() constant-time - private Thread serverThread; - private long ab = aw(); - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0172-Optimise-NetworkManager.patch b/Spigot-Server-Patches/0172-Optimise-NetworkManager.patch deleted file mode 100644 index 2f80e680e1..0000000000 --- a/Spigot-Server-Patches/0172-Optimise-NetworkManager.patch +++ /dev/null @@ -1,125 +0,0 @@ -From a8811a6944cbbac091d661b2ca406b18929456bc Mon Sep 17 00:00:00 2001 -From: Alfie Cleveland -Date: Fri, 25 Nov 2016 20:35:05 +0000 -Subject: [PATCH] Optimise NetworkManager - - -diff --git a/src/main/java/net/minecraft/server/NetworkManager.java b/src/main/java/net/minecraft/server/NetworkManager.java -index 184ef32a8..be14c0b25 100644 ---- a/src/main/java/net/minecraft/server/NetworkManager.java -+++ b/src/main/java/net/minecraft/server/NetworkManager.java -@@ -62,8 +62,8 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - } - }; - private final EnumProtocolDirection h; -- private final Queue i = Queues.newConcurrentLinkedQueue(); -- private final ReentrantReadWriteLock j = new ReentrantReadWriteLock(); -+ // private final Queue i = Queues.newConcurrentLinkedQueue(); // Paper -+ // private final ReentrantReadWriteLock j = new ReentrantReadWriteLock(); // Paper - public Channel channel; - // Spigot Start // PAIL - public SocketAddress l; -@@ -141,32 +141,36 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - if (this.isConnected()) { - this.m(); - this.a(packet, (GenericFutureListener[]) null); -- } else { -- this.j.writeLock().lock(); -- -- try { -- this.i.add(new NetworkManager.QueuedPacket(packet, (GenericFutureListener[]) null)); -- } finally { -- this.j.writeLock().unlock(); -- } - } -- -+ // Paper start - Remove but force a conflict -+// else { -+// this.j.writeLock().lock(); -+// -+// try { -+// this.i.add(new NetworkManager.QueuedPacket(packet, (GenericFutureListener[]) null)); -+// } finally { -+// this.j.writeLock().unlock(); -+// } -+// } -+ // Paper end - } - - public void sendPacket(Packet packet, GenericFutureListener> genericfuturelistener, GenericFutureListener>... agenericfuturelistener) { - if (this.isConnected()) { - this.m(); - this.a(packet, (GenericFutureListener[]) ArrayUtils.add(agenericfuturelistener, 0, genericfuturelistener)); -- } else { -- this.j.writeLock().lock(); -- -- try { -- this.i.add(new NetworkManager.QueuedPacket(packet, (GenericFutureListener[]) ArrayUtils.add(agenericfuturelistener, 0, genericfuturelistener))); -- } finally { -- this.j.writeLock().unlock(); -- } - } -- -+ // Paper start - Remove but force a conflict -+// else { -+// this.j.writeLock().lock(); -+// -+// try { -+// this.i.add(new NetworkManager.QueuedPacket(packet, (GenericFutureListener[]) ArrayUtils.add(agenericfuturelistener, 0, genericfuturelistener))); -+// } finally { -+// this.j.writeLock().unlock(); -+// } -+// } -+ // Paper end - } - - private void a(final Packet packet, @Nullable final GenericFutureListener>[] agenericfuturelistener) { -@@ -211,20 +215,22 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - } - - private void m() { -- if (this.channel != null && this.channel.isOpen()) { -- this.j.readLock().lock(); -- -- try { -- while (!this.i.isEmpty()) { -- NetworkManager.QueuedPacket networkmanager_queuedpacket = (NetworkManager.QueuedPacket) this.i.poll(); -- -- this.a(networkmanager_queuedpacket.a, networkmanager_queuedpacket.b); -- } -- } finally { -- this.j.readLock().unlock(); -- } -- -- } -+ // Paper start - Remove but force a conflict -+// if (this.channel != null && this.channel.isOpen()) { -+// this.j.readLock().lock(); -+// -+// try { -+// while (!this.i.isEmpty()) { -+// NetworkManager.QueuedPacket networkmanager_queuedpacket = (NetworkManager.QueuedPacket) this.i.poll(); -+// -+// this.a(networkmanager_queuedpacket.a, networkmanager_queuedpacket.b); -+// } -+// } finally { -+// this.j.readLock().unlock(); -+// } -+// -+// } -+ // Paper end - } - - public void a() { -@@ -317,7 +323,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - } else if (this.i() != null) { - this.i().a(new ChatComponentText("Disconnected")); - } -- this.i.clear(); // Free up packet queue. -+ // this.i.clear(); // Free up packet queue. // Paper - remove unneeded packet queue - } - - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0172-Optimise-removeQueue.patch b/Spigot-Server-Patches/0172-Optimise-removeQueue.patch new file mode 100644 index 0000000000..fae4b557f1 --- /dev/null +++ b/Spigot-Server-Patches/0172-Optimise-removeQueue.patch @@ -0,0 +1,65 @@ +From e11ca040e04967c5991c13652e8d683f5d05d191 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/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java +index eca224bdb..58d40f994 100644 +--- a/src/main/java/net/minecraft/server/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/EntityPlayer.java +@@ -4,7 +4,9 @@ import com.google.common.collect.Lists; + import com.google.common.collect.Sets; + import com.mojang.authlib.GameProfile; + import io.netty.buffer.Unpooled; ++import java.util.ArrayDeque; // Paper + import java.util.Collection; ++import java.util.Deque; // Paper + import java.util.HashSet; + import java.util.Iterator; + import java.util.List; +@@ -38,7 +40,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + public final PlayerInteractManager playerInteractManager; + public double d; + public double e; +- public final List removeQueue = Lists.newLinkedList(); ++ public final Deque removeQueue = new ArrayDeque<>(); // Paper + private final ServerStatisticManager bU; + private float bV = Float.MIN_VALUE; + private int bW = Integer.MIN_VALUE; +@@ -251,10 +253,17 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + Iterator iterator = this.removeQueue.iterator(); + int j = 0; + +- while (iterator.hasNext() && j < i) { ++ // Paper start ++ /* while (iterator.hasNext() && j < i) { + aint[j++] = ((Integer) iterator.next()).intValue(); + iterator.remove(); ++ } */ ++ ++ Integer integer; ++ while (j < i && (integer = this.removeQueue.poll()) != null) { ++ aint[j++] = integer.intValue(); + } ++ // Paper end + + this.playerConnection.sendPacket(new PacketPlayOutEntityDestroy(aint)); + } +@@ -995,7 +1004,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + this.lastSentExp = -1; + this.lastHealthSent = -1.0F; + this.cc = -1; +- this.removeQueue.addAll(((EntityPlayer) entityhuman).removeQueue); ++ // this.removeQueue.addAll(((EntityPlayer) entityhuman).removeQueue); // Paper ++ // Paper start ++ if (this.removeQueue != ((EntityPlayer) entityhuman).removeQueue) { ++ this.removeQueue.addAll(((EntityPlayer) entityhuman).removeQueue); ++ } ++ // Paper end + } + + protected void a(MobEffect mobeffect) { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0173-Allow-Reloading-of-Command-Aliases.patch b/Spigot-Server-Patches/0173-Allow-Reloading-of-Command-Aliases.patch new file mode 100644 index 0000000000..4a2ea54a79 --- /dev/null +++ b/Spigot-Server-Patches/0173-Allow-Reloading-of-Command-Aliases.patch @@ -0,0 +1,39 @@ +From f54fafe71613988b003a239c2491d3f8c0f7e709 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 8ade16865..326196ce4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1852,5 +1852,24 @@ public final class CraftServer implements Server { + }); + } + } ++ ++ @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 + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0173-Optimise-removeQueue.patch b/Spigot-Server-Patches/0173-Optimise-removeQueue.patch deleted file mode 100644 index e16274e2ce..0000000000 --- a/Spigot-Server-Patches/0173-Optimise-removeQueue.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 8fe1d79d96efbc0d370340b62f9c9bbf85fa2bd4 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/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index eca224bdb..58d40f994 100644 ---- a/src/main/java/net/minecraft/server/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/EntityPlayer.java -@@ -4,7 +4,9 @@ import com.google.common.collect.Lists; - import com.google.common.collect.Sets; - import com.mojang.authlib.GameProfile; - import io.netty.buffer.Unpooled; -+import java.util.ArrayDeque; // Paper - import java.util.Collection; -+import java.util.Deque; // Paper - import java.util.HashSet; - import java.util.Iterator; - import java.util.List; -@@ -38,7 +40,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public final PlayerInteractManager playerInteractManager; - public double d; - public double e; -- public final List removeQueue = Lists.newLinkedList(); -+ public final Deque removeQueue = new ArrayDeque<>(); // Paper - private final ServerStatisticManager bU; - private float bV = Float.MIN_VALUE; - private int bW = Integer.MIN_VALUE; -@@ -251,10 +253,17 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - Iterator iterator = this.removeQueue.iterator(); - int j = 0; - -- while (iterator.hasNext() && j < i) { -+ // Paper start -+ /* while (iterator.hasNext() && j < i) { - aint[j++] = ((Integer) iterator.next()).intValue(); - iterator.remove(); -+ } */ -+ -+ Integer integer; -+ while (j < i && (integer = this.removeQueue.poll()) != null) { -+ aint[j++] = integer.intValue(); - } -+ // Paper end - - this.playerConnection.sendPacket(new PacketPlayOutEntityDestroy(aint)); - } -@@ -995,7 +1004,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.lastSentExp = -1; - this.lastHealthSent = -1.0F; - this.cc = -1; -- this.removeQueue.addAll(((EntityPlayer) entityhuman).removeQueue); -+ // this.removeQueue.addAll(((EntityPlayer) entityhuman).removeQueue); // Paper -+ // Paper start -+ if (this.removeQueue != ((EntityPlayer) entityhuman).removeQueue) { -+ this.removeQueue.addAll(((EntityPlayer) entityhuman).removeQueue); -+ } -+ // Paper end - } - - protected void a(MobEffect mobeffect) { --- -2.12.2.windows.2 - diff --git a/Spigot-Server-Patches/0174-Add-source-to-PlayerExpChangeEvent.patch b/Spigot-Server-Patches/0174-Add-source-to-PlayerExpChangeEvent.patch new file mode 100644 index 0000000000..ad7453f5b1 --- /dev/null +++ b/Spigot-Server-Patches/0174-Add-source-to-PlayerExpChangeEvent.patch @@ -0,0 +1,52 @@ +From 5423a90a37ac2a7ed6e5aef52861e2d0d41c204f 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/server/EntityExperienceOrb.java b/src/main/java/net/minecraft/server/EntityExperienceOrb.java +index 4b3816465..14431b8ad 100644 +--- a/src/main/java/net/minecraft/server/EntityExperienceOrb.java ++++ b/src/main/java/net/minecraft/server/EntityExperienceOrb.java +@@ -172,7 +172,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 4d252aa47..7e4982d93 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -45,6 +45,7 @@ import org.bukkit.entity.Player; + import org.bukkit.entity.Projectile; + import org.bukkit.entity.ThrownExpBottle; + import org.bukkit.entity.ThrownPotion; ++import org.bukkit.entity.ExperienceOrb; // Paper + import org.bukkit.event.Cancellable; + import org.bukkit.event.Event; + import org.bukkit.event.block.*; +@@ -645,6 +646,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, int x, int y, int z, net.minecraft.server.Block type, int data) { + Block block = world.getWorld().getBlockAt(x, y, z); + CraftBlockState state = (CraftBlockState) block.getState(); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0174-Allow-Reloading-of-Command-Aliases.patch b/Spigot-Server-Patches/0174-Allow-Reloading-of-Command-Aliases.patch deleted file mode 100644 index 0d7e053ef5..0000000000 --- a/Spigot-Server-Patches/0174-Allow-Reloading-of-Command-Aliases.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 786974fe4d33dfbcac920900a7b06e00b4ba6791 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 8ade16865..326196ce4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1852,5 +1852,24 @@ public final class CraftServer implements Server { - }); - } - } -+ -+ @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 - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0175-Add-source-to-PlayerExpChangeEvent.patch b/Spigot-Server-Patches/0175-Add-source-to-PlayerExpChangeEvent.patch deleted file mode 100644 index f21802ae52..0000000000 --- a/Spigot-Server-Patches/0175-Add-source-to-PlayerExpChangeEvent.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 5dcc1c79bdd70bdae5d82c71da0de1ffcacd504f 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/server/EntityExperienceOrb.java b/src/main/java/net/minecraft/server/EntityExperienceOrb.java -index 4b3816465..14431b8ad 100644 ---- a/src/main/java/net/minecraft/server/EntityExperienceOrb.java -+++ b/src/main/java/net/minecraft/server/EntityExperienceOrb.java -@@ -172,7 +172,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 4d252aa47..7e4982d93 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -45,6 +45,7 @@ import org.bukkit.entity.Player; - import org.bukkit.entity.Projectile; - import org.bukkit.entity.ThrownExpBottle; - import org.bukkit.entity.ThrownPotion; -+import org.bukkit.entity.ExperienceOrb; // Paper - import org.bukkit.event.Cancellable; - import org.bukkit.event.Event; - import org.bukkit.event.block.*; -@@ -645,6 +646,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, int x, int y, int z, net.minecraft.server.Block type, int data) { - Block block = world.getWorld().getBlockAt(x, y, z); - CraftBlockState state = (CraftBlockState) block.getState(); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0175-Optimize-World.isLoaded-BlockPosition-Z.patch b/Spigot-Server-Patches/0175-Optimize-World.isLoaded-BlockPosition-Z.patch new file mode 100644 index 0000000000..50313c9821 --- /dev/null +++ b/Spigot-Server-Patches/0175-Optimize-World.isLoaded-BlockPosition-Z.patch @@ -0,0 +1,23 @@ +From 4f91a4c59c79d3e9f13ab9061515227913e5b92b 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/server/World.java b/src/main/java/net/minecraft/server/World.java +index ec0a28cff..2fa63a27f 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -286,7 +286,7 @@ public abstract class World implements IBlockAccess { + } + + public boolean isLoaded(BlockPosition blockposition) { +- return this.a(blockposition, true); ++ return getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; // Paper + } + + public boolean a(BlockPosition blockposition, boolean flag) { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0176-Optimize-World.isLoaded-BlockPosition-Z.patch b/Spigot-Server-Patches/0176-Optimize-World.isLoaded-BlockPosition-Z.patch deleted file mode 100644 index 5812c5a3e8..0000000000 --- a/Spigot-Server-Patches/0176-Optimize-World.isLoaded-BlockPosition-Z.patch +++ /dev/null @@ -1,23 +0,0 @@ -From c277520b112c71aaacbe585cd1b6333b5ed6bf9e 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/server/World.java b/src/main/java/net/minecraft/server/World.java -index ec0a28cff..2fa63a27f 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -286,7 +286,7 @@ public abstract class World implements IBlockAccess { - } - - public boolean isLoaded(BlockPosition blockposition) { -- return this.a(blockposition, true); -+ return getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; // Paper - } - - public boolean a(BlockPosition blockposition, boolean flag) { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0176-Speedup-BlockPos-by-fixing-inlining.patch b/Spigot-Server-Patches/0176-Speedup-BlockPos-by-fixing-inlining.patch new file mode 100644 index 0000000000..899acc0466 --- /dev/null +++ b/Spigot-Server-Patches/0176-Speedup-BlockPos-by-fixing-inlining.patch @@ -0,0 +1,181 @@ +From a883117f5ebe4bf5f8179f3f2b6fb6b3e83ac45d Mon Sep 17 00:00:00 2001 +From: Techcable +Date: Wed, 30 Nov 2016 20:56:58 -0600 +Subject: [PATCH] Speedup BlockPos by fixing 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 mircorbenchmarks. +They had 'callq' (invoke) instead of 'mov' (get from memory) instructions. + +diff --git a/src/main/java/net/minecraft/server/BaseBlockPosition.java b/src/main/java/net/minecraft/server/BaseBlockPosition.java +index f772c7cdf..f5dc14493 100644 +--- a/src/main/java/net/minecraft/server/BaseBlockPosition.java ++++ b/src/main/java/net/minecraft/server/BaseBlockPosition.java +@@ -7,11 +7,12 @@ import javax.annotation.concurrent.Immutable; + public class BaseBlockPosition implements Comparable { + + public static final BaseBlockPosition ZERO = new BaseBlockPosition(0, 0, 0); +- private final int a; +- private final int b; +- private final int c; +- // Paper start +- public boolean isValidLocation() { ++ // Paper start - Make mutable and protected for MutableBlockPos and PooledBlockPos ++ protected int a; ++ protected int b; ++ protected int c; ++ ++ public final boolean isValidLocation() { + return a >= -30000000 && c >= -30000000 && a < 30000000 && c < 30000000 && b >= 0 && b < 256; + } + public boolean isInvalidYLocation() { +@@ -49,17 +50,19 @@ 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() { ++ // Paper start - Only allow a single implementation ++ public final int getX() { + return this.a; + } + +- public int getY() { ++ public final int getY() { + return this.b; + } + +- public int getZ() { ++ public final int getZ() { + return this.c; + } ++ // Paper end + + public BaseBlockPosition d(BaseBlockPosition baseblockposition) { + return new BaseBlockPosition(this.getY() * baseblockposition.getZ() - this.getZ() * baseblockposition.getY(), this.getZ() * baseblockposition.getX() - this.getX() * baseblockposition.getZ(), this.getX() * baseblockposition.getY() - this.getY() * baseblockposition.getX()); +diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java +index b3c1f550c..6a0b3a62d 100644 +--- a/src/main/java/net/minecraft/server/BlockPosition.java ++++ b/src/main/java/net/minecraft/server/BlockPosition.java +@@ -211,19 +211,21 @@ public class BlockPosition extends BaseBlockPosition { + if (this.b == null) { + this.b = new BlockPosition.MutableBlockPosition(i, j, k); + return this.b; +- } else if (this.b.b == l && this.b.c == i1 && this.b.d == j1) { ++ // Paper start - b, c, d, refer to x, y, z, and as such, a, b, c of BaseBlockPosition ++ } else if (((BaseBlockPosition)this.b).a == l && ((BaseBlockPosition)this.b).b == i1 && ((BaseBlockPosition)this.b).c == j1) { + return (BlockPosition.MutableBlockPosition) this.endOfData(); + } else { +- if (this.b.b < l) { +- ++this.b.b; +- } else if (this.b.c < i1) { +- this.b.b = i; +- ++this.b.c; +- } else if (this.b.d < j1) { +- this.b.b = i; +- this.b.c = j; +- ++this.b.d; ++ if (((BaseBlockPosition) this.b).a < l) { ++ ++((BaseBlockPosition) this.b).a; ++ } else if (((BaseBlockPosition) this.b).b < i1) { ++ ((BaseBlockPosition) this.b).a = i; ++ ++((BaseBlockPosition) this.b).b; ++ } else if (((BaseBlockPosition) this.b).c < j1) { ++ ((BaseBlockPosition) this.b).a = i; ++ ((BaseBlockPosition) this.b).b = j; ++ ++((BaseBlockPosition) this.b).c; + } ++ // Paper end + + return this.b; + } +@@ -338,6 +340,8 @@ public class BlockPosition extends BaseBlockPosition { + + public static class MutableBlockPosition extends BlockPosition { + ++ // Paper start - Remove variables ++ /* + protected int b; + protected int c; + protected int d; +@@ -350,6 +354,7 @@ public class BlockPosition extends BaseBlockPosition { + public boolean isInvalidYLocation() { + return c < 0 || c >= 256; + } ++ */ + // Paper end + + public MutableBlockPosition() { +@@ -362,9 +367,11 @@ public class BlockPosition extends BaseBlockPosition { + + public MutableBlockPosition(int i, int j, int k) { + super(0, 0, 0); +- this.b = i; +- this.c = j; +- this.d = k; ++ // Paper start - Modify base position variables ++ ((BaseBlockPosition) this).a = i; ++ ((BaseBlockPosition) this).b = j; ++ ((BaseBlockPosition) this).c = k; ++ // Paper end + } + + public BlockPosition a(double d0, double d1, double d2) { +@@ -383,6 +390,8 @@ public class BlockPosition extends BaseBlockPosition { + return super.a(enumblockrotation).h(); + } + ++ // Paper start - Use superclass methods ++ /* + public int getX() { + return this.b; + } +@@ -394,12 +403,16 @@ public class BlockPosition extends BaseBlockPosition { + public int getZ() { + return this.d; + } ++ */ ++ // Paper end + + public void setValues(int x, int y, int z) { c(x, y, z); } // Paper - OBFHELPER + public BlockPosition.MutableBlockPosition c(int i, int j, int k) { +- this.b = i; +- this.c = j; +- this.d = k; ++ // Paper start - Modify base position variables ++ ((BaseBlockPosition) this).a = i; ++ ((BaseBlockPosition) this).b = j; ++ ((BaseBlockPosition) this).c = k; ++ // Paper end + return this; + } + +@@ -416,11 +429,11 @@ public class BlockPosition extends BaseBlockPosition { + } + + public BlockPosition.MutableBlockPosition c(EnumDirection enumdirection, int i) { +- return this.c(this.b + enumdirection.getAdjacentX() * i, this.c + enumdirection.getAdjacentY() * i, this.d + enumdirection.getAdjacentZ() * i); ++ return this.c(this.getX() + enumdirection.getAdjacentX() * i, this.getY() + enumdirection.getAdjacentY() * i, this.getZ() + enumdirection.getAdjacentZ() * i); // Paper - USE THE BLEEPING GETTERS + } + + public void p(int i) { +- this.c = i; ++ ((BaseBlockPosition) this).b = i; // Paper - Modify base variable + } + + public BlockPosition h() { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0177-Don-t-let-fishinghooks-use-portals.patch b/Spigot-Server-Patches/0177-Don-t-let-fishinghooks-use-portals.patch new file mode 100644 index 0000000000..7fbe780ae5 --- /dev/null +++ b/Spigot-Server-Patches/0177-Don-t-let-fishinghooks-use-portals.patch @@ -0,0 +1,39 @@ +From f007be7ce27bdac76b9af0e066adcab134ce3f56 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/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 0479b7551..44fdf92ff 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -143,7 +143,7 @@ public abstract class Entity implements ICommandListener { + public boolean ah; + public boolean impulse; + public int portalCooldown; +- protected boolean ak; ++ protected boolean ak; public boolean inPortal() { return ak; } // Paper - OBFHELPER + protected int al; + public int dimension; + protected BlockPosition an; +diff --git a/src/main/java/net/minecraft/server/EntityFishingHook.java b/src/main/java/net/minecraft/server/EntityFishingHook.java +index 0c528c699..606160a17 100644 +--- a/src/main/java/net/minecraft/server/EntityFishingHook.java ++++ b/src/main/java/net/minecraft/server/EntityFishingHook.java +@@ -185,6 +185,12 @@ public class EntityFishingHook extends Entity { + this.motY *= 0.92D; + this.motZ *= 0.92D; + this.setPosition(this.locX, this.locY, this.locZ); ++ ++ // Paper start - These shouldn't be going through portals ++ if (this.inPortal()) { ++ this.die(); ++ } ++ // Paper end + } + } + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0177-Speedup-BlockPos-by-fixing-inlining.patch b/Spigot-Server-Patches/0177-Speedup-BlockPos-by-fixing-inlining.patch deleted file mode 100644 index e1cbab6b6f..0000000000 --- a/Spigot-Server-Patches/0177-Speedup-BlockPos-by-fixing-inlining.patch +++ /dev/null @@ -1,181 +0,0 @@ -From 5a54f793b0f84d651b28c65ee6fd45937eeb290b Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Wed, 30 Nov 2016 20:56:58 -0600 -Subject: [PATCH] Speedup BlockPos by fixing 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 mircorbenchmarks. -They had 'callq' (invoke) instead of 'mov' (get from memory) instructions. - -diff --git a/src/main/java/net/minecraft/server/BaseBlockPosition.java b/src/main/java/net/minecraft/server/BaseBlockPosition.java -index f772c7cdf..f5dc14493 100644 ---- a/src/main/java/net/minecraft/server/BaseBlockPosition.java -+++ b/src/main/java/net/minecraft/server/BaseBlockPosition.java -@@ -7,11 +7,12 @@ import javax.annotation.concurrent.Immutable; - public class BaseBlockPosition implements Comparable { - - public static final BaseBlockPosition ZERO = new BaseBlockPosition(0, 0, 0); -- private final int a; -- private final int b; -- private final int c; -- // Paper start -- public boolean isValidLocation() { -+ // Paper start - Make mutable and protected for MutableBlockPos and PooledBlockPos -+ protected int a; -+ protected int b; -+ protected int c; -+ -+ public final boolean isValidLocation() { - return a >= -30000000 && c >= -30000000 && a < 30000000 && c < 30000000 && b >= 0 && b < 256; - } - public boolean isInvalidYLocation() { -@@ -49,17 +50,19 @@ 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() { -+ // Paper start - Only allow a single implementation -+ public final int getX() { - return this.a; - } - -- public int getY() { -+ public final int getY() { - return this.b; - } - -- public int getZ() { -+ public final int getZ() { - return this.c; - } -+ // Paper end - - public BaseBlockPosition d(BaseBlockPosition baseblockposition) { - return new BaseBlockPosition(this.getY() * baseblockposition.getZ() - this.getZ() * baseblockposition.getY(), this.getZ() * baseblockposition.getX() - this.getX() * baseblockposition.getZ(), this.getX() * baseblockposition.getY() - this.getY() * baseblockposition.getX()); -diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java -index b3c1f550c..6a0b3a62d 100644 ---- a/src/main/java/net/minecraft/server/BlockPosition.java -+++ b/src/main/java/net/minecraft/server/BlockPosition.java -@@ -211,19 +211,21 @@ public class BlockPosition extends BaseBlockPosition { - if (this.b == null) { - this.b = new BlockPosition.MutableBlockPosition(i, j, k); - return this.b; -- } else if (this.b.b == l && this.b.c == i1 && this.b.d == j1) { -+ // Paper start - b, c, d, refer to x, y, z, and as such, a, b, c of BaseBlockPosition -+ } else if (((BaseBlockPosition)this.b).a == l && ((BaseBlockPosition)this.b).b == i1 && ((BaseBlockPosition)this.b).c == j1) { - return (BlockPosition.MutableBlockPosition) this.endOfData(); - } else { -- if (this.b.b < l) { -- ++this.b.b; -- } else if (this.b.c < i1) { -- this.b.b = i; -- ++this.b.c; -- } else if (this.b.d < j1) { -- this.b.b = i; -- this.b.c = j; -- ++this.b.d; -+ if (((BaseBlockPosition) this.b).a < l) { -+ ++((BaseBlockPosition) this.b).a; -+ } else if (((BaseBlockPosition) this.b).b < i1) { -+ ((BaseBlockPosition) this.b).a = i; -+ ++((BaseBlockPosition) this.b).b; -+ } else if (((BaseBlockPosition) this.b).c < j1) { -+ ((BaseBlockPosition) this.b).a = i; -+ ((BaseBlockPosition) this.b).b = j; -+ ++((BaseBlockPosition) this.b).c; - } -+ // Paper end - - return this.b; - } -@@ -338,6 +340,8 @@ public class BlockPosition extends BaseBlockPosition { - - public static class MutableBlockPosition extends BlockPosition { - -+ // Paper start - Remove variables -+ /* - protected int b; - protected int c; - protected int d; -@@ -350,6 +354,7 @@ public class BlockPosition extends BaseBlockPosition { - public boolean isInvalidYLocation() { - return c < 0 || c >= 256; - } -+ */ - // Paper end - - public MutableBlockPosition() { -@@ -362,9 +367,11 @@ public class BlockPosition extends BaseBlockPosition { - - public MutableBlockPosition(int i, int j, int k) { - super(0, 0, 0); -- this.b = i; -- this.c = j; -- this.d = k; -+ // Paper start - Modify base position variables -+ ((BaseBlockPosition) this).a = i; -+ ((BaseBlockPosition) this).b = j; -+ ((BaseBlockPosition) this).c = k; -+ // Paper end - } - - public BlockPosition a(double d0, double d1, double d2) { -@@ -383,6 +390,8 @@ public class BlockPosition extends BaseBlockPosition { - return super.a(enumblockrotation).h(); - } - -+ // Paper start - Use superclass methods -+ /* - public int getX() { - return this.b; - } -@@ -394,12 +403,16 @@ public class BlockPosition extends BaseBlockPosition { - public int getZ() { - return this.d; - } -+ */ -+ // Paper end - - public void setValues(int x, int y, int z) { c(x, y, z); } // Paper - OBFHELPER - public BlockPosition.MutableBlockPosition c(int i, int j, int k) { -- this.b = i; -- this.c = j; -- this.d = k; -+ // Paper start - Modify base position variables -+ ((BaseBlockPosition) this).a = i; -+ ((BaseBlockPosition) this).b = j; -+ ((BaseBlockPosition) this).c = k; -+ // Paper end - return this; - } - -@@ -416,11 +429,11 @@ public class BlockPosition extends BaseBlockPosition { - } - - public BlockPosition.MutableBlockPosition c(EnumDirection enumdirection, int i) { -- return this.c(this.b + enumdirection.getAdjacentX() * i, this.c + enumdirection.getAdjacentY() * i, this.d + enumdirection.getAdjacentZ() * i); -+ return this.c(this.getX() + enumdirection.getAdjacentX() * i, this.getY() + enumdirection.getAdjacentY() * i, this.getZ() + enumdirection.getAdjacentZ() * i); // Paper - USE THE BLEEPING GETTERS - } - - public void p(int i) { -- this.c = i; -+ ((BaseBlockPosition) this).b = i; // Paper - Modify base variable - } - - public BlockPosition h() { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0178-Add-ProjectileCollideEvent.patch b/Spigot-Server-Patches/0178-Add-ProjectileCollideEvent.patch new file mode 100644 index 0000000000..3b2e548ba1 --- /dev/null +++ b/Spigot-Server-Patches/0178-Add-ProjectileCollideEvent.patch @@ -0,0 +1,111 @@ +From 29af77dd9cc1266a6f29936bae339983f799055c 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/server/EntityArrow.java b/src/main/java/net/minecraft/server/EntityArrow.java +index 8cda47518..79ca071bc 100644 +--- a/src/main/java/net/minecraft/server/EntityArrow.java ++++ b/src/main/java/net/minecraft/server/EntityArrow.java +@@ -190,6 +190,15 @@ public abstract class EntityArrow extends Entity implements IProjectile { + } + } + ++ // Paper start - Call ProjectileCollideEvent ++ if (movingobjectposition != null && movingobjectposition.entity != null) { ++ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, movingobjectposition); ++ if (event.isCancelled()) { ++ movingobjectposition = null; ++ } ++ } ++ // Paper end ++ + if (movingobjectposition != null) { + this.a(movingobjectposition); + } +diff --git a/src/main/java/net/minecraft/server/EntityFireball.java b/src/main/java/net/minecraft/server/EntityFireball.java +index 789de85d1..d5c9d24cf 100644 +--- a/src/main/java/net/minecraft/server/EntityFireball.java ++++ b/src/main/java/net/minecraft/server/EntityFireball.java +@@ -70,6 +70,15 @@ public abstract class EntityFireball extends Entity { + ++this.f; + MovingObjectPosition movingobjectposition = ProjectileHelper.a(this, true, this.f >= 25, this.shooter); + ++ // Paper start - Call ProjectileCollideEvent ++ if (movingobjectposition != null && movingobjectposition.entity != null) { ++ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = CraftEventFactory.callProjectileCollideEvent(this, movingobjectposition); ++ if (event.isCancelled()) { ++ movingobjectposition = null; ++ } ++ } ++ // Paper end ++ + if (movingobjectposition != null) { + this.a(movingobjectposition); + +diff --git a/src/main/java/net/minecraft/server/EntityFishingHook.java b/src/main/java/net/minecraft/server/EntityFishingHook.java +index 606160a17..b78e0e49e 100644 +--- a/src/main/java/net/minecraft/server/EntityFishingHook.java ++++ b/src/main/java/net/minecraft/server/EntityFishingHook.java +@@ -240,6 +240,16 @@ public class EntityFishingHook extends Entity { + + vec3d = new Vec3D(this.locX, this.locY, this.locZ); + vec3d1 = new Vec3D(this.locX + this.motX, this.locY + this.motY, this.locZ + this.motZ); ++ ++ // Paper start - Call ProjectileCollideEvent ++ if (movingobjectposition != null && movingobjectposition.entity != null) { ++ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, movingobjectposition); ++ if (event.isCancelled()) { ++ movingobjectposition = null; ++ } ++ } ++ // Paper end ++ + if (movingobjectposition != null) { + vec3d1 = new Vec3D(movingobjectposition.pos.x, movingobjectposition.pos.y, movingobjectposition.pos.z); + } +diff --git a/src/main/java/net/minecraft/server/EntityProjectile.java b/src/main/java/net/minecraft/server/EntityProjectile.java +index 6fbc84559..a8b9d9263 100644 +--- a/src/main/java/net/minecraft/server/EntityProjectile.java ++++ b/src/main/java/net/minecraft/server/EntityProjectile.java +@@ -160,6 +160,15 @@ public abstract class EntityProjectile extends Entity implements IProjectile { + movingobjectposition = new MovingObjectPosition(entity); + } + ++ // Paper start - Call ProjectileCollideEvent ++ if (movingobjectposition != null && movingobjectposition.entity != null) { ++ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, movingobjectposition); ++ if (event.isCancelled()) { ++ movingobjectposition = null; ++ } ++ } ++ // Paper end ++ + if (movingobjectposition != null) { + if (movingobjectposition.type == MovingObjectPosition.EnumMovingObjectType.BLOCK && this.world.getType(movingobjectposition.a()).getBlock() == Blocks.PORTAL) { + this.e(movingobjectposition.a()); +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 7e4982d93..a850a9634 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -794,6 +794,16 @@ public class CraftEventFactory { + return CraftItemStack.asNMSCopy(bitem); + } + ++ // Paper start ++ public static com.destroystokyo.paper.event.entity.ProjectileCollideEvent callProjectileCollideEvent(Entity entity, MovingObjectPosition position) { ++ Projectile projectile = (Projectile) entity.getBukkitEntity(); ++ org.bukkit.entity.Entity collided = position.entity.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); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0178-Don-t-let-fishinghooks-use-portals.patch b/Spigot-Server-Patches/0178-Don-t-let-fishinghooks-use-portals.patch deleted file mode 100644 index 3120e1e3ad..0000000000 --- a/Spigot-Server-Patches/0178-Don-t-let-fishinghooks-use-portals.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 07f94f25a8a5c20683c36e3abfacc7f91892b779 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/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 0479b7551..44fdf92ff 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -143,7 +143,7 @@ public abstract class Entity implements ICommandListener { - public boolean ah; - public boolean impulse; - public int portalCooldown; -- protected boolean ak; -+ protected boolean ak; public boolean inPortal() { return ak; } // Paper - OBFHELPER - protected int al; - public int dimension; - protected BlockPosition an; -diff --git a/src/main/java/net/minecraft/server/EntityFishingHook.java b/src/main/java/net/minecraft/server/EntityFishingHook.java -index 0c528c699..606160a17 100644 ---- a/src/main/java/net/minecraft/server/EntityFishingHook.java -+++ b/src/main/java/net/minecraft/server/EntityFishingHook.java -@@ -185,6 +185,12 @@ public class EntityFishingHook extends Entity { - this.motY *= 0.92D; - this.motZ *= 0.92D; - this.setPosition(this.locX, this.locY, this.locZ); -+ -+ // Paper start - These shouldn't be going through portals -+ if (this.inPortal()) { -+ this.die(); -+ } -+ // Paper end - } - } - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0179-Add-ProjectileCollideEvent.patch b/Spigot-Server-Patches/0179-Add-ProjectileCollideEvent.patch deleted file mode 100644 index 04ccea1de1..0000000000 --- a/Spigot-Server-Patches/0179-Add-ProjectileCollideEvent.patch +++ /dev/null @@ -1,111 +0,0 @@ -From 3126a7e06fe1a789f090b648aeb41e4cd53006cb 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/server/EntityArrow.java b/src/main/java/net/minecraft/server/EntityArrow.java -index 8cda47518..79ca071bc 100644 ---- a/src/main/java/net/minecraft/server/EntityArrow.java -+++ b/src/main/java/net/minecraft/server/EntityArrow.java -@@ -190,6 +190,15 @@ public abstract class EntityArrow extends Entity implements IProjectile { - } - } - -+ // Paper start - Call ProjectileCollideEvent -+ if (movingobjectposition != null && movingobjectposition.entity != null) { -+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, movingobjectposition); -+ if (event.isCancelled()) { -+ movingobjectposition = null; -+ } -+ } -+ // Paper end -+ - if (movingobjectposition != null) { - this.a(movingobjectposition); - } -diff --git a/src/main/java/net/minecraft/server/EntityFireball.java b/src/main/java/net/minecraft/server/EntityFireball.java -index 789de85d1..d5c9d24cf 100644 ---- a/src/main/java/net/minecraft/server/EntityFireball.java -+++ b/src/main/java/net/minecraft/server/EntityFireball.java -@@ -70,6 +70,15 @@ public abstract class EntityFireball extends Entity { - ++this.f; - MovingObjectPosition movingobjectposition = ProjectileHelper.a(this, true, this.f >= 25, this.shooter); - -+ // Paper start - Call ProjectileCollideEvent -+ if (movingobjectposition != null && movingobjectposition.entity != null) { -+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = CraftEventFactory.callProjectileCollideEvent(this, movingobjectposition); -+ if (event.isCancelled()) { -+ movingobjectposition = null; -+ } -+ } -+ // Paper end -+ - if (movingobjectposition != null) { - this.a(movingobjectposition); - -diff --git a/src/main/java/net/minecraft/server/EntityFishingHook.java b/src/main/java/net/minecraft/server/EntityFishingHook.java -index 606160a17..b78e0e49e 100644 ---- a/src/main/java/net/minecraft/server/EntityFishingHook.java -+++ b/src/main/java/net/minecraft/server/EntityFishingHook.java -@@ -240,6 +240,16 @@ public class EntityFishingHook extends Entity { - - vec3d = new Vec3D(this.locX, this.locY, this.locZ); - vec3d1 = new Vec3D(this.locX + this.motX, this.locY + this.motY, this.locZ + this.motZ); -+ -+ // Paper start - Call ProjectileCollideEvent -+ if (movingobjectposition != null && movingobjectposition.entity != null) { -+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, movingobjectposition); -+ if (event.isCancelled()) { -+ movingobjectposition = null; -+ } -+ } -+ // Paper end -+ - if (movingobjectposition != null) { - vec3d1 = new Vec3D(movingobjectposition.pos.x, movingobjectposition.pos.y, movingobjectposition.pos.z); - } -diff --git a/src/main/java/net/minecraft/server/EntityProjectile.java b/src/main/java/net/minecraft/server/EntityProjectile.java -index 6fbc84559..a8b9d9263 100644 ---- a/src/main/java/net/minecraft/server/EntityProjectile.java -+++ b/src/main/java/net/minecraft/server/EntityProjectile.java -@@ -160,6 +160,15 @@ public abstract class EntityProjectile extends Entity implements IProjectile { - movingobjectposition = new MovingObjectPosition(entity); - } - -+ // Paper start - Call ProjectileCollideEvent -+ if (movingobjectposition != null && movingobjectposition.entity != null) { -+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, movingobjectposition); -+ if (event.isCancelled()) { -+ movingobjectposition = null; -+ } -+ } -+ // Paper end -+ - if (movingobjectposition != null) { - if (movingobjectposition.type == MovingObjectPosition.EnumMovingObjectType.BLOCK && this.world.getType(movingobjectposition.a()).getBlock() == Blocks.PORTAL) { - this.e(movingobjectposition.a()); -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 7e4982d93..a850a9634 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -794,6 +794,16 @@ public class CraftEventFactory { - return CraftItemStack.asNMSCopy(bitem); - } - -+ // Paper start -+ public static com.destroystokyo.paper.event.entity.ProjectileCollideEvent callProjectileCollideEvent(Entity entity, MovingObjectPosition position) { -+ Projectile projectile = (Projectile) entity.getBukkitEntity(); -+ org.bukkit.entity.Entity collided = position.entity.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); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0179-Vanished-players-don-t-have-rights.patch b/Spigot-Server-Patches/0179-Vanished-players-don-t-have-rights.patch new file mode 100644 index 0000000000..f66dca0030 --- /dev/null +++ b/Spigot-Server-Patches/0179-Vanished-players-don-t-have-rights.patch @@ -0,0 +1,100 @@ +From 5b717c8de16974c9eec0185c3b003fddd49dc26a Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Fri, 16 Dec 2016 22:10:35 -0600 +Subject: [PATCH] Vanished players don't have rights + + +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 44fdf92ff..1e295432e 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -68,7 +68,7 @@ public abstract class Entity implements ICommandListener { + private static double f = 1.0D; + private static int entityCount; + private int id; +- public boolean i; ++ public boolean i; public boolean blocksEntitySpawning() { return i; } // Paper - OBFHELPER + public final List passengers; + protected int j; + private Entity au;public void setVehicle(Entity entity) { this.au = entity; } // Paper // OBFHELPER +diff --git a/src/main/java/net/minecraft/server/ItemBlock.java b/src/main/java/net/minecraft/server/ItemBlock.java +index eb32871bd..a380e615b 100644 +--- a/src/main/java/net/minecraft/server/ItemBlock.java ++++ b/src/main/java/net/minecraft/server/ItemBlock.java +@@ -20,7 +20,7 @@ public class ItemBlock extends Item { + + ItemStack itemstack = entityhuman.b(enumhand); + +- if (!itemstack.isEmpty() && entityhuman.a(blockposition, enumdirection, itemstack) && world.a(this.a, blockposition, false, enumdirection, (Entity) null)) { ++ if (!itemstack.isEmpty() && entityhuman.a(blockposition, enumdirection, itemstack) && world.a(this.a, blockposition, false, enumdirection, entityhuman)) { // Paper - Pass entityhuman instead of null + int i = this.filterData(itemstack.getData()); + IBlockData iblockdata1 = this.a.getPlacedState(world, blockposition, enumdirection, f, f1, f2, i, entityhuman); + +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 2fa63a27f..7af76e14c 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -1799,6 +1799,33 @@ public abstract class World implements IBlockAccess { + return this.a(axisalignedbb, (Entity) null); + } + ++ // Paper start - Based on method below ++ /** ++ * @param axisalignedbb area to search within ++ * @param entity causing the action ex. block placer ++ * @return if there are no visible players colliding ++ */ ++ public boolean checkNoVisiblePlayerCollisions(AxisAlignedBB axisalignedbb, @Nullable Entity entity) { ++ List list = this.getEntities((Entity) null, axisalignedbb); ++ ++ for (int i = 0; i < list.size(); ++i) { ++ Entity entity1 = (Entity) list.get(i); ++ ++ if (entity instanceof EntityPlayer && entity1 instanceof EntityPlayer) { ++ if (!((EntityPlayer) entity).getBukkitEntity().canSee(((EntityPlayer) entity1).getBukkitEntity())) { ++ continue; ++ } ++ } ++ ++ if (!entity1.dead && entity1.blocksEntitySpawning()) { ++ return false; ++ } ++ } ++ ++ return true; ++ } ++ // Paper end ++ + public boolean a(AxisAlignedBB axisalignedbb, @Nullable Entity entity) { + List list = this.getEntities((Entity) null, axisalignedbb); + +@@ -2683,7 +2710,7 @@ public abstract class World implements IBlockAccess { + AxisAlignedBB axisalignedbb = flag ? null : block.getBlockData().c(this, blockposition); + + // CraftBukkit start - store default return +- boolean defaultReturn = axisalignedbb != Block.k && !this.a(axisalignedbb.a(blockposition), entity) ? false : (iblockdata.getMaterial() == Material.ORIENTABLE && block == Blocks.ANVIL ? true : iblockdata.getMaterial().isReplaceable() && block.canPlace(this, blockposition, enumdirection)); ++ boolean defaultReturn = axisalignedbb != Block.k && !this.checkNoVisiblePlayerCollisions(axisalignedbb.a(blockposition), entity) ? false : (iblockdata.getMaterial() == Material.ORIENTABLE && block == Blocks.ANVIL ? true : iblockdata.getMaterial().isReplaceable() && block.canPlace(this, blockposition, enumdirection)); // Paper - Use our entity search + BlockCanBuildEvent event = new BlockCanBuildEvent(this.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftMagicNumbers.getId(block), defaultReturn); + this.getServer().getPluginManager().callEvent(event); + +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index a850a9634..59942d9cb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -799,6 +799,13 @@ public class CraftEventFactory { + Projectile projectile = (Projectile) entity.getBukkitEntity(); + org.bukkit.entity.Entity collided = position.entity.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); ++ } ++ } ++ + Bukkit.getPluginManager().callEvent(event); + return event; + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0180-Prevent-Pathfinding-out-of-World-Border.patch b/Spigot-Server-Patches/0180-Prevent-Pathfinding-out-of-World-Border.patch new file mode 100644 index 0000000000..4667ab0441 --- /dev/null +++ b/Spigot-Server-Patches/0180-Prevent-Pathfinding-out-of-World-Border.patch @@ -0,0 +1,43 @@ +From 7292ba902909ac5284a165b4fc2c422bf503486a 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/server/NavigationAbstract.java b/src/main/java/net/minecraft/server/NavigationAbstract.java +index c0ef2400b..74d1fd6b2 100644 +--- a/src/main/java/net/minecraft/server/NavigationAbstract.java ++++ b/src/main/java/net/minecraft/server/NavigationAbstract.java +@@ -69,6 +69,7 @@ public abstract class NavigationAbstract { + + @Nullable + public PathEntity a(BlockPosition blockposition) { ++ if (!getEntity().getWorld().getWorldBorder().isInBounds(blockposition)) return null; // Paper - don't path out of world border + if (!this.b()) { + return null; + } else if (this.c != null && !this.c.b() && blockposition.equals(this.q)) { +@@ -95,6 +96,7 @@ public abstract class NavigationAbstract { + return null; + } else { + BlockPosition blockposition = new BlockPosition(entity); ++ if (!getEntity().getWorld().getWorldBorder().isInBounds(blockposition)) return null; // Paper - don't path out of world border + + if (this.c != null && !this.c.b() && blockposition.equals(this.q)) { + return this.c; +diff --git a/src/main/java/net/minecraft/server/WorldBorder.java b/src/main/java/net/minecraft/server/WorldBorder.java +index 9038d52eb..632eb1c9d 100644 +--- a/src/main/java/net/minecraft/server/WorldBorder.java ++++ b/src/main/java/net/minecraft/server/WorldBorder.java +@@ -29,7 +29,7 @@ public class WorldBorder { + this.l = 5; + } + +- public boolean a(BlockPosition blockposition) { ++ public boolean isInBounds(BlockPosition blockposition) { return a(blockposition); }public boolean a(BlockPosition blockposition) { // Paper - OBFHELPER + return (double) (blockposition.getX() + 1) > this.b() && (double) blockposition.getX() < this.d() && (double) (blockposition.getZ() + 1) > this.c() && (double) blockposition.getZ() < this.e(); + } + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0180-Vanished-players-don-t-have-rights.patch b/Spigot-Server-Patches/0180-Vanished-players-don-t-have-rights.patch deleted file mode 100644 index 958e1566f4..0000000000 --- a/Spigot-Server-Patches/0180-Vanished-players-don-t-have-rights.patch +++ /dev/null @@ -1,100 +0,0 @@ -From d0f789b689a9098e7010653e23a7cfcec0a2aa37 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Fri, 16 Dec 2016 22:10:35 -0600 -Subject: [PATCH] Vanished players don't have rights - - -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 44fdf92ff..1e295432e 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -68,7 +68,7 @@ public abstract class Entity implements ICommandListener { - private static double f = 1.0D; - private static int entityCount; - private int id; -- public boolean i; -+ public boolean i; public boolean blocksEntitySpawning() { return i; } // Paper - OBFHELPER - public final List passengers; - protected int j; - private Entity au;public void setVehicle(Entity entity) { this.au = entity; } // Paper // OBFHELPER -diff --git a/src/main/java/net/minecraft/server/ItemBlock.java b/src/main/java/net/minecraft/server/ItemBlock.java -index eb32871bd..a380e615b 100644 ---- a/src/main/java/net/minecraft/server/ItemBlock.java -+++ b/src/main/java/net/minecraft/server/ItemBlock.java -@@ -20,7 +20,7 @@ public class ItemBlock extends Item { - - ItemStack itemstack = entityhuman.b(enumhand); - -- if (!itemstack.isEmpty() && entityhuman.a(blockposition, enumdirection, itemstack) && world.a(this.a, blockposition, false, enumdirection, (Entity) null)) { -+ if (!itemstack.isEmpty() && entityhuman.a(blockposition, enumdirection, itemstack) && world.a(this.a, blockposition, false, enumdirection, entityhuman)) { // Paper - Pass entityhuman instead of null - int i = this.filterData(itemstack.getData()); - IBlockData iblockdata1 = this.a.getPlacedState(world, blockposition, enumdirection, f, f1, f2, i, entityhuman); - -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 2fa63a27f..7af76e14c 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -1799,6 +1799,33 @@ public abstract class World implements IBlockAccess { - return this.a(axisalignedbb, (Entity) null); - } - -+ // Paper start - Based on method below -+ /** -+ * @param axisalignedbb area to search within -+ * @param entity causing the action ex. block placer -+ * @return if there are no visible players colliding -+ */ -+ public boolean checkNoVisiblePlayerCollisions(AxisAlignedBB axisalignedbb, @Nullable Entity entity) { -+ List list = this.getEntities((Entity) null, axisalignedbb); -+ -+ for (int i = 0; i < list.size(); ++i) { -+ Entity entity1 = (Entity) list.get(i); -+ -+ if (entity instanceof EntityPlayer && entity1 instanceof EntityPlayer) { -+ if (!((EntityPlayer) entity).getBukkitEntity().canSee(((EntityPlayer) entity1).getBukkitEntity())) { -+ continue; -+ } -+ } -+ -+ if (!entity1.dead && entity1.blocksEntitySpawning()) { -+ return false; -+ } -+ } -+ -+ return true; -+ } -+ // Paper end -+ - public boolean a(AxisAlignedBB axisalignedbb, @Nullable Entity entity) { - List list = this.getEntities((Entity) null, axisalignedbb); - -@@ -2683,7 +2710,7 @@ public abstract class World implements IBlockAccess { - AxisAlignedBB axisalignedbb = flag ? null : block.getBlockData().c(this, blockposition); - - // CraftBukkit start - store default return -- boolean defaultReturn = axisalignedbb != Block.k && !this.a(axisalignedbb.a(blockposition), entity) ? false : (iblockdata.getMaterial() == Material.ORIENTABLE && block == Blocks.ANVIL ? true : iblockdata.getMaterial().isReplaceable() && block.canPlace(this, blockposition, enumdirection)); -+ boolean defaultReturn = axisalignedbb != Block.k && !this.checkNoVisiblePlayerCollisions(axisalignedbb.a(blockposition), entity) ? false : (iblockdata.getMaterial() == Material.ORIENTABLE && block == Blocks.ANVIL ? true : iblockdata.getMaterial().isReplaceable() && block.canPlace(this, blockposition, enumdirection)); // Paper - Use our entity search - BlockCanBuildEvent event = new BlockCanBuildEvent(this.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftMagicNumbers.getId(block), defaultReturn); - this.getServer().getPluginManager().callEvent(event); - -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index a850a9634..59942d9cb 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -799,6 +799,13 @@ public class CraftEventFactory { - Projectile projectile = (Projectile) entity.getBukkitEntity(); - org.bukkit.entity.Entity collided = position.entity.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); -+ } -+ } -+ - Bukkit.getPluginManager().callEvent(event); - return event; - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0181-Bound-Treasure-Maps-to-World-Border.patch b/Spigot-Server-Patches/0181-Bound-Treasure-Maps-to-World-Border.patch new file mode 100644 index 0000000000..93f820f634 --- /dev/null +++ b/Spigot-Server-Patches/0181-Bound-Treasure-Maps-to-World-Border.patch @@ -0,0 +1,52 @@ +From f9f30f2f2feec4b29dfe090139d5eef6fac615ec 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/server/StructureGenerator.java b/src/main/java/net/minecraft/server/StructureGenerator.java +index 9c1605b14..77236760f 100644 +--- a/src/main/java/net/minecraft/server/StructureGenerator.java ++++ b/src/main/java/net/minecraft/server/StructureGenerator.java +@@ -233,6 +233,9 @@ public abstract class StructureGenerator extends WorldGenBase { + + WorldGenBase.a(world.getSeed(), random, l2, i3); + random.nextInt(); ++ ++ if (!world.getWorldBorder().isChunkInBounds(l2, i3)) { continue; } // Paper ++ + if (structuregenerator.a(l2, i3)) { + if (!flag1 || !world.b(l2, i3)) { + return new BlockPosition((l2 << 4) + 8, 64, (i3 << 4) + 8); +diff --git a/src/main/java/net/minecraft/server/WorldBorder.java b/src/main/java/net/minecraft/server/WorldBorder.java +index 632eb1c9d..1bb172bbf 100644 +--- a/src/main/java/net/minecraft/server/WorldBorder.java ++++ b/src/main/java/net/minecraft/server/WorldBorder.java +@@ -33,6 +33,18 @@ public class WorldBorder { + return (double) (blockposition.getX() + 1) > this.b() && (double) blockposition.getX() < this.d() && (double) (blockposition.getZ() + 1) > this.c() && (double) blockposition.getZ() < this.e(); + } + ++ // Paper start ++ private final BlockPosition.MutableBlockPosition mutPos = new BlockPosition.MutableBlockPosition(); ++ public boolean isBlockInBounds(int chunkX, int chunkZ) { ++ mutPos.setValues(chunkX, 64, chunkZ); ++ return isInBounds(mutPos); ++ } ++ public boolean isChunkInBounds(int chunkX, int chunkZ) { ++ mutPos.setValues(((chunkX << 4) + 15), 64, (chunkZ << 4) + 15); ++ return isInBounds(mutPos); ++ } ++ // Paper end ++ + public boolean isInBounds(ChunkCoordIntPair chunkcoordintpair) { + return (double) chunkcoordintpair.e() > this.b() && (double) chunkcoordintpair.c() < this.d() && (double) chunkcoordintpair.f() > this.c() && (double) chunkcoordintpair.d() < this.e(); + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0181-Prevent-Pathfinding-out-of-World-Border.patch b/Spigot-Server-Patches/0181-Prevent-Pathfinding-out-of-World-Border.patch deleted file mode 100644 index b6e02658d8..0000000000 --- a/Spigot-Server-Patches/0181-Prevent-Pathfinding-out-of-World-Border.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 42ba792fd1872a43fa70dacebb308dd7482f951d 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/server/NavigationAbstract.java b/src/main/java/net/minecraft/server/NavigationAbstract.java -index c0ef2400b..74d1fd6b2 100644 ---- a/src/main/java/net/minecraft/server/NavigationAbstract.java -+++ b/src/main/java/net/minecraft/server/NavigationAbstract.java -@@ -69,6 +69,7 @@ public abstract class NavigationAbstract { - - @Nullable - public PathEntity a(BlockPosition blockposition) { -+ if (!getEntity().getWorld().getWorldBorder().isInBounds(blockposition)) return null; // Paper - don't path out of world border - if (!this.b()) { - return null; - } else if (this.c != null && !this.c.b() && blockposition.equals(this.q)) { -@@ -95,6 +96,7 @@ public abstract class NavigationAbstract { - return null; - } else { - BlockPosition blockposition = new BlockPosition(entity); -+ if (!getEntity().getWorld().getWorldBorder().isInBounds(blockposition)) return null; // Paper - don't path out of world border - - if (this.c != null && !this.c.b() && blockposition.equals(this.q)) { - return this.c; -diff --git a/src/main/java/net/minecraft/server/WorldBorder.java b/src/main/java/net/minecraft/server/WorldBorder.java -index 9038d52eb..632eb1c9d 100644 ---- a/src/main/java/net/minecraft/server/WorldBorder.java -+++ b/src/main/java/net/minecraft/server/WorldBorder.java -@@ -29,7 +29,7 @@ public class WorldBorder { - this.l = 5; - } - -- public boolean a(BlockPosition blockposition) { -+ public boolean isInBounds(BlockPosition blockposition) { return a(blockposition); }public boolean a(BlockPosition blockposition) { // Paper - OBFHELPER - return (double) (blockposition.getX() + 1) > this.b() && (double) blockposition.getX() < this.d() && (double) (blockposition.getZ() + 1) > this.c() && (double) blockposition.getZ() < this.e(); - } - --- -2.12.2 - diff --git a/Spigot-Server-Patches/0182-Bound-Treasure-Maps-to-World-Border.patch b/Spigot-Server-Patches/0182-Bound-Treasure-Maps-to-World-Border.patch deleted file mode 100644 index d59a0b0e1b..0000000000 --- a/Spigot-Server-Patches/0182-Bound-Treasure-Maps-to-World-Border.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 7318fd9b00548085fc7ed532a1541aa11916fd94 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/server/StructureGenerator.java b/src/main/java/net/minecraft/server/StructureGenerator.java -index 9c1605b1..77236760 100644 ---- a/src/main/java/net/minecraft/server/StructureGenerator.java -+++ b/src/main/java/net/minecraft/server/StructureGenerator.java -@@ -233,6 +233,9 @@ public abstract class StructureGenerator extends WorldGenBase { - - WorldGenBase.a(world.getSeed(), random, l2, i3); - random.nextInt(); -+ -+ if (!world.getWorldBorder().isChunkInBounds(l2, i3)) { continue; } // Paper -+ - if (structuregenerator.a(l2, i3)) { - if (!flag1 || !world.b(l2, i3)) { - return new BlockPosition((l2 << 4) + 8, 64, (i3 << 4) + 8); -diff --git a/src/main/java/net/minecraft/server/WorldBorder.java b/src/main/java/net/minecraft/server/WorldBorder.java -index 632eb1c9..1bb172bb 100644 ---- a/src/main/java/net/minecraft/server/WorldBorder.java -+++ b/src/main/java/net/minecraft/server/WorldBorder.java -@@ -33,6 +33,18 @@ public class WorldBorder { - return (double) (blockposition.getX() + 1) > this.b() && (double) blockposition.getX() < this.d() && (double) (blockposition.getZ() + 1) > this.c() && (double) blockposition.getZ() < this.e(); - } - -+ // Paper start -+ private final BlockPosition.MutableBlockPosition mutPos = new BlockPosition.MutableBlockPosition(); -+ public boolean isBlockInBounds(int chunkX, int chunkZ) { -+ mutPos.setValues(chunkX, 64, chunkZ); -+ return isInBounds(mutPos); -+ } -+ public boolean isChunkInBounds(int chunkX, int chunkZ) { -+ mutPos.setValues(((chunkX << 4) + 15), 64, (chunkZ << 4) + 15); -+ return isInBounds(mutPos); -+ } -+ // Paper end -+ - public boolean isInBounds(ChunkCoordIntPair chunkcoordintpair) { - return (double) chunkcoordintpair.e() > this.b() && (double) chunkcoordintpair.c() < this.d() && (double) chunkcoordintpair.f() > this.c() && (double) chunkcoordintpair.d() < this.e(); - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0182-Configurable-Cartographer-Treasure-Maps.patch b/Spigot-Server-Patches/0182-Configurable-Cartographer-Treasure-Maps.patch new file mode 100644 index 0000000000..029d29890b --- /dev/null +++ b/Spigot-Server-Patches/0182-Configurable-Cartographer-Treasure-Maps.patch @@ -0,0 +1,46 @@ +From 3f73beb3e92deb8c057e8c9051d26dd342dc184b 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 dcf64efcc..bf2916802 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -393,4 +393,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/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java +index 4ad75468c..ac6e2a9aa 100644 +--- a/src/main/java/net/minecraft/server/EntityVillager.java ++++ b/src/main/java/net/minecraft/server/EntityVillager.java +@@ -761,7 +761,8 @@ public class EntityVillager extends EntityAgeable implements NPC, IMerchant { + public void a(IMerchant imerchant, MerchantRecipeList merchantrecipelist, Random random) { + int i = this.a.a(random); + World world = imerchant.t_(); +- BlockPosition blockposition = world.a(this.b, imerchant.u_(), true); ++ if (!world.paperConfig.enableTreasureMaps) return; // Paper ++ BlockPosition blockposition = world.a(this.b, imerchant.u_(), !world.paperConfig.treasureMapsAlreadyDiscovered); // Paper - pass false to return first structure, regardless of if its been discovered. true returns only undiscovered. + + if (blockposition != null) { + ItemStack itemstack = ItemWorldMap.a(world, (double) blockposition.getX(), (double) blockposition.getZ(), (byte) 2, true, true); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0183-Configurable-Cartographer-Treasure-Maps.patch b/Spigot-Server-Patches/0183-Configurable-Cartographer-Treasure-Maps.patch deleted file mode 100644 index 35f1b75919..0000000000 --- a/Spigot-Server-Patches/0183-Configurable-Cartographer-Treasure-Maps.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 037a3547d5daa2d36dc0bd7f3dc1cf6958be8bed 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 dcf64efc..bf291680 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -393,4 +393,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/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java -index 4ad75468..ac6e2a9a 100644 ---- a/src/main/java/net/minecraft/server/EntityVillager.java -+++ b/src/main/java/net/minecraft/server/EntityVillager.java -@@ -761,7 +761,8 @@ public class EntityVillager extends EntityAgeable implements NPC, IMerchant { - public void a(IMerchant imerchant, MerchantRecipeList merchantrecipelist, Random random) { - int i = this.a.a(random); - World world = imerchant.t_(); -- BlockPosition blockposition = world.a(this.b, imerchant.u_(), true); -+ if (!world.paperConfig.enableTreasureMaps) return; // Paper -+ BlockPosition blockposition = world.a(this.b, imerchant.u_(), !world.paperConfig.treasureMapsAlreadyDiscovered); // Paper - pass false to return first structure, regardless of if its been discovered. true returns only undiscovered. - - if (blockposition != null) { - ItemStack itemstack = ItemWorldMap.a(world, (double) blockposition.getX(), (double) blockposition.getZ(), (byte) 2, true, true); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0183-Optimize-ItemStack.isEmpty.patch b/Spigot-Server-Patches/0183-Optimize-ItemStack.isEmpty.patch new file mode 100644 index 0000000000..46ad1e891d --- /dev/null +++ b/Spigot-Server-Patches/0183-Optimize-ItemStack.isEmpty.patch @@ -0,0 +1,31 @@ +From b44bf1c80442b336a199ef736c5e055c6aa9a763 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/server/ItemStack.java b/src/main/java/net/minecraft/server/ItemStack.java +index aca63be53..548da18e0 100644 +--- a/src/main/java/net/minecraft/server/ItemStack.java ++++ b/src/main/java/net/minecraft/server/ItemStack.java +@@ -120,9 +120,15 @@ public final class ItemStack { + this.F(); + } + ++ // Paper start - optimize isEmpty ++ private static Item airItem; + public boolean isEmpty() { +- return this == ItemStack.a ? true : (this.item != null && this.item != Item.getItemOf(Blocks.AIR) ? (this.count <= 0 ? true : this.damage < -32768 || this.damage > '\uffff') : true); ++ if (airItem == null) { ++ airItem = Item.REGISTRY.get(new MinecraftKey("air")); ++ } ++ return this == ItemStack.a || this.item == null || this.item == airItem || (this.count <= 0 || (this.damage < -32768 || this.damage > '\uffff')); + } ++ // Paper end + + public static void a(DataConverterManager dataconvertermanager) { + dataconvertermanager.a(DataConverterTypes.ITEM_INSTANCE, (DataInspector) (new DataInspectorBlockEntity())); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0184-Add-API-methods-to-control-if-armour-stands-can-move.patch b/Spigot-Server-Patches/0184-Add-API-methods-to-control-if-armour-stands-can-move.patch new file mode 100644 index 0000000000..14a84e3063 --- /dev/null +++ b/Spigot-Server-Patches/0184-Add-API-methods-to-control-if-armour-stands-can-move.patch @@ -0,0 +1,54 @@ +From 4b84f76c9cb64b655951120ee73e732bcb545d00 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/server/EntityArmorStand.java b/src/main/java/net/minecraft/server/EntityArmorStand.java +index 96bb11005..7738ca385 100644 +--- a/src/main/java/net/minecraft/server/EntityArmorStand.java ++++ b/src/main/java/net/minecraft/server/EntityArmorStand.java +@@ -50,6 +50,7 @@ public class EntityArmorStand extends EntityLiving { + public Vector3f rightArmPose; + public Vector3f leftLegPose; + public Vector3f rightLegPose; ++ public boolean canMove = true; // Paper + + public EntityArmorStand(World world) { + super(world); +@@ -763,4 +764,13 @@ public class EntityArmorStand extends EntityLiving { + public boolean cK() { + return false; + } ++ ++ // Paper start ++ @Override ++ public void move(EnumMoveType moveType, double x, double y, double z) { ++ if (this.canMove) { ++ super.move(moveType, x, y, z); ++ } ++ } ++ // 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 2b66a08ad..8a06cb165 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +@@ -211,4 +211,14 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { + public void setMarker(boolean marker) { + getHandle().setMarker(marker); + } ++ ++ @Override ++ public boolean canMove() { ++ return getHandle().canMove; ++ } ++ ++ @Override ++ public void setCanMove(boolean move) { ++ getHandle().canMove = move; ++ } + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0184-Optimize-ItemStack.isEmpty.patch b/Spigot-Server-Patches/0184-Optimize-ItemStack.isEmpty.patch deleted file mode 100644 index 466e443926..0000000000 --- a/Spigot-Server-Patches/0184-Optimize-ItemStack.isEmpty.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 2f31a8392b51b3118e251416709c02fd8251bc05 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/server/ItemStack.java b/src/main/java/net/minecraft/server/ItemStack.java -index 911bd879..45ebd3f6 100644 ---- a/src/main/java/net/minecraft/server/ItemStack.java -+++ b/src/main/java/net/minecraft/server/ItemStack.java -@@ -120,9 +120,15 @@ public final class ItemStack { - this.F(); - } - -+ // Paper start - optimize isEmpty -+ private static Item airItem; - public boolean isEmpty() { -- return this == ItemStack.a ? true : (this.item != null && this.item != Item.getItemOf(Blocks.AIR) ? (this.count <= 0 ? true : this.damage < -32768 || this.damage > '\uffff') : true); -+ if (airItem == null) { -+ airItem = Item.REGISTRY.get(new MinecraftKey("air")); -+ } -+ return this == ItemStack.a || this.item == null || this.item == airItem || (this.count <= 0 || (this.damage < -32768 || this.damage > '\uffff')); - } -+ // Paper end - - public static void a(DataConverterManager dataconvertermanager) { - dataconvertermanager.a(DataConverterTypes.ITEM_INSTANCE, (DataInspector) (new DataInspectorBlockEntity())); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0185-Add-API-methods-to-control-if-armour-stands-can-move.patch b/Spigot-Server-Patches/0185-Add-API-methods-to-control-if-armour-stands-can-move.patch deleted file mode 100644 index c596123575..0000000000 --- a/Spigot-Server-Patches/0185-Add-API-methods-to-control-if-armour-stands-can-move.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 97ba683a96e7d807faa7400a8acf3435bdd7f2a3 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/server/EntityArmorStand.java b/src/main/java/net/minecraft/server/EntityArmorStand.java -index 96bb1100..7738ca38 100644 ---- a/src/main/java/net/minecraft/server/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/server/EntityArmorStand.java -@@ -50,6 +50,7 @@ public class EntityArmorStand extends EntityLiving { - public Vector3f rightArmPose; - public Vector3f leftLegPose; - public Vector3f rightLegPose; -+ public boolean canMove = true; // Paper - - public EntityArmorStand(World world) { - super(world); -@@ -763,4 +764,13 @@ public class EntityArmorStand extends EntityLiving { - public boolean cK() { - return false; - } -+ -+ // Paper start -+ @Override -+ public void move(EnumMoveType moveType, double x, double y, double z) { -+ if (this.canMove) { -+ super.move(moveType, x, y, z); -+ } -+ } -+ // 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 2b66a08a..8a06cb16 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -@@ -211,4 +211,14 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { - public void setMarker(boolean marker) { - getHandle().setMarker(marker); - } -+ -+ @Override -+ public boolean canMove() { -+ return getHandle().canMove; -+ } -+ -+ @Override -+ public void setCanMove(boolean move) { -+ getHandle().canMove = move; -+ } - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0185-Option-to-prevent-armor-stands-from-doing-entity-loo.patch b/Spigot-Server-Patches/0185-Option-to-prevent-armor-stands-from-doing-entity-loo.patch new file mode 100644 index 0000000000..55a45627a9 --- /dev/null +++ b/Spigot-Server-Patches/0185-Option-to-prevent-armor-stands-from-doing-entity-loo.patch @@ -0,0 +1,35 @@ +From 7f5079d03bd22c1497fe715871a55339268944ec Mon Sep 17 00:00:00 2001 +From: kashike +Date: Wed, 21 Dec 2016 11:52:04 -0600 +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 bf2916802..61efcc479 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -403,4 +403,9 @@ public class PaperWorldConfig { + log("Treasure Maps will return already discovered locations"); + } + } ++ ++ public boolean armorStandEntityLookups = true; ++ private void armorStandEntityLookups() { ++ armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); ++ } + } +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 7af76e14c..2028cf81e 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -1331,6 +1331,7 @@ public abstract class World implements IBlockAccess { + + this.a(entity, axisalignedbb, false, arraylist); + if (entity != null) { ++ if (entity instanceof EntityArmorStand && !entity.world.paperConfig.armorStandEntityLookups) return arraylist; // Paper + List list = this.getEntities(entity, axisalignedbb.g(0.25D)); + + for (int i = 0; i < list.size(); ++i) { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0186-Add-option-to-remove-invalid-statistics.patch b/Spigot-Server-Patches/0186-Add-option-to-remove-invalid-statistics.patch new file mode 100644 index 0000000000..888518a87e --- /dev/null +++ b/Spigot-Server-Patches/0186-Add-option-to-remove-invalid-statistics.patch @@ -0,0 +1,57 @@ +From bde76955ebf689676626f9556eb9fdcfb14a4062 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 20 Dec 2016 23:09:21 -0600 +Subject: [PATCH] Add option to remove invalid statistics + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 009bf0c8b..a901cd85c 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -261,4 +261,13 @@ public class PaperConfig { + private static void playerAutoSaveRate() { + playerAutoSaveRate = getInt("settings.player-auto-save-rate", -1); + } ++ ++ public static boolean removeInvalidStatistics = false; ++ private static void removeInvalidStatistics() { ++ if (version < 12) { ++ boolean oldValue = getBoolean("remove-invalid-statistics", false); ++ set("settings.remove-invalid-statistics", oldValue); ++ } ++ removeInvalidStatistics = getBoolean("settings.remove-invalid-statistics", false); ++ } + } +diff --git a/src/main/java/net/minecraft/server/ServerStatisticManager.java b/src/main/java/net/minecraft/server/ServerStatisticManager.java +index 99466dbde..d1bee0257 100644 +--- a/src/main/java/net/minecraft/server/ServerStatisticManager.java ++++ b/src/main/java/net/minecraft/server/ServerStatisticManager.java +@@ -104,6 +104,7 @@ public class ServerStatisticManager extends StatisticManager { + JsonObject jsonobject = jsonelement.getAsJsonObject(); + HashMap hashmap = Maps.newHashMap(); + Iterator iterator = jsonobject.entrySet().iterator(); ++ java.util.List invalidStats = com.google.common.collect.Lists.newArrayList(); // Paper + + while (iterator.hasNext()) { + Entry entry = (Entry) iterator.next(); +@@ -137,9 +138,17 @@ public class ServerStatisticManager extends StatisticManager { + hashmap.put(statistic, statisticwrapper); + } else { + ServerStatisticManager.b.warn("Invalid statistic in {}: Don\'t know what {} is", new Object[] { this.d, entry.getKey()}); ++ if (com.destroystokyo.paper.PaperConfig.removeInvalidStatistics) invalidStats.add((String) entry.getKey()); // Paper + } + } + ++ // Paper start - Remove invalid statistics ++ for (String invalid : invalidStats) { ++ jsonobject.remove(invalid); ++ ServerStatisticManager.b.info("Removing invalid statistic: " + invalid); ++ } ++ // Paper end ++ + return hashmap; + } + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0186-Option-to-prevent-armor-stands-from-doing-entity-loo.patch b/Spigot-Server-Patches/0186-Option-to-prevent-armor-stands-from-doing-entity-loo.patch deleted file mode 100644 index adf1425488..0000000000 --- a/Spigot-Server-Patches/0186-Option-to-prevent-armor-stands-from-doing-entity-loo.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 153c50aca4dd903d388c955d0e94f48a9678dc55 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Wed, 21 Dec 2016 11:52:04 -0600 -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 bf291680..61efcc47 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -403,4 +403,9 @@ public class PaperWorldConfig { - log("Treasure Maps will return already discovered locations"); - } - } -+ -+ public boolean armorStandEntityLookups = true; -+ private void armorStandEntityLookups() { -+ armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); -+ } - } -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 7af76e14..2028cf81 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -1331,6 +1331,7 @@ public abstract class World implements IBlockAccess { - - this.a(entity, axisalignedbb, false, arraylist); - if (entity != null) { -+ if (entity instanceof EntityArmorStand && !entity.world.paperConfig.armorStandEntityLookups) return arraylist; // Paper - List list = this.getEntities(entity, axisalignedbb.g(0.25D)); - - for (int i = 0; i < list.size(); ++i) { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0187-Add-option-to-remove-invalid-statistics.patch b/Spigot-Server-Patches/0187-Add-option-to-remove-invalid-statistics.patch deleted file mode 100644 index 11ba7eca5c..0000000000 --- a/Spigot-Server-Patches/0187-Add-option-to-remove-invalid-statistics.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 1266f16b4aa8a1dc81aa3fcbbdabea44fc54ab1d Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 20 Dec 2016 23:09:21 -0600 -Subject: [PATCH] Add option to remove invalid statistics - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 009bf0c8..a901cd85 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -261,4 +261,13 @@ public class PaperConfig { - private static void playerAutoSaveRate() { - playerAutoSaveRate = getInt("settings.player-auto-save-rate", -1); - } -+ -+ public static boolean removeInvalidStatistics = false; -+ private static void removeInvalidStatistics() { -+ if (version < 12) { -+ boolean oldValue = getBoolean("remove-invalid-statistics", false); -+ set("settings.remove-invalid-statistics", oldValue); -+ } -+ removeInvalidStatistics = getBoolean("settings.remove-invalid-statistics", false); -+ } - } -diff --git a/src/main/java/net/minecraft/server/ServerStatisticManager.java b/src/main/java/net/minecraft/server/ServerStatisticManager.java -index 99466dbd..d1bee025 100644 ---- a/src/main/java/net/minecraft/server/ServerStatisticManager.java -+++ b/src/main/java/net/minecraft/server/ServerStatisticManager.java -@@ -104,6 +104,7 @@ public class ServerStatisticManager extends StatisticManager { - JsonObject jsonobject = jsonelement.getAsJsonObject(); - HashMap hashmap = Maps.newHashMap(); - Iterator iterator = jsonobject.entrySet().iterator(); -+ java.util.List invalidStats = com.google.common.collect.Lists.newArrayList(); // Paper - - while (iterator.hasNext()) { - Entry entry = (Entry) iterator.next(); -@@ -137,9 +138,17 @@ public class ServerStatisticManager extends StatisticManager { - hashmap.put(statistic, statisticwrapper); - } else { - ServerStatisticManager.b.warn("Invalid statistic in {}: Don\'t know what {} is", new Object[] { this.d, entry.getKey()}); -+ if (com.destroystokyo.paper.PaperConfig.removeInvalidStatistics) invalidStats.add((String) entry.getKey()); // Paper - } - } - -+ // Paper start - Remove invalid statistics -+ for (String invalid : invalidStats) { -+ jsonobject.remove(invalid); -+ ServerStatisticManager.b.info("Removing invalid statistic: " + invalid); -+ } -+ // Paper end -+ - return hashmap; - } - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0187-IllegalPacketEvent.patch b/Spigot-Server-Patches/0187-IllegalPacketEvent.patch new file mode 100644 index 0000000000..bfed8f8061 --- /dev/null +++ b/Spigot-Server-Patches/0187-IllegalPacketEvent.patch @@ -0,0 +1,71 @@ +From 4fc99496df25951ad23dbc3826251451b0b3648b Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 23 Jun 2016 23:33:57 -0400 +Subject: [PATCH] IllegalPacketEvent + +Fired for invalid data from players that represents hacking attempts + +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 51d27351d..437575003 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -56,6 +56,7 @@ import org.bukkit.inventory.CraftingInventory; + import org.bukkit.inventory.EquipmentSlot; + import org.bukkit.inventory.InventoryView; + import org.bukkit.util.NumberConversions; ++import com.destroystokyo.paper.event.player.IllegalPacketEvent; // Paper + import co.aikar.timings.MinecraftTimings; // Paper + // CraftBukkit end + +@@ -2236,8 +2237,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { + CraftEventFactory.handleEditBookEvent(player, itemstack1); // CraftBukkit + } + } catch (Exception exception) { +- PlayerConnection.LOGGER.error("Couldn\'t handle book info", exception); +- this.disconnect("Invalid book data!"); // CraftBukkit ++ IllegalPacketEvent.process(player.getBukkitEntity(), "InvalidBookEdit", "Invalid book data!", exception); // Paper + } + } else { + String s1; +@@ -2286,8 +2286,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { + CraftEventFactory.handleEditBookEvent(player, itemstack2); // CraftBukkit + } + } catch (Exception exception1) { +- PlayerConnection.LOGGER.error("Couldn\'t sign book", exception1); +- this.disconnect("Invalid book data!"); // CraftBukkit ++ IllegalPacketEvent.process(player.getBukkitEntity(), "InvalidBookSign", "Invalid book data!", exception1); // Paper + } + } else if ("MC|TrSel".equals(s)) { + try { +@@ -2298,8 +2297,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { + ((ContainerMerchant) container).d(j); + } + } catch (Exception exception2) { +- PlayerConnection.LOGGER.error("Couldn\'t select trade", exception2); +- this.disconnect("Invalid trade data!"); // CraftBukkit ++ IllegalPacketEvent.process(player.getBukkitEntity(), "InvalidTrade", "Invalid trade data!", exception2); // Paper + } + } else { + TileEntity tileentity; +@@ -2440,8 +2438,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { + iinventory.update(); + } + } catch (Exception exception5) { +- PlayerConnection.LOGGER.error("Couldn\'t set beacon", exception5); +- this.disconnect("Invalid beacon data!"); // CraftBukkit ++ IllegalPacketEvent.process(player.getBukkitEntity(), "InvalidBeacon", "Invalid beacon data!", exception5); // Paper + } + } + } else if ("MC|ItemName".equals(s)) { +@@ -2540,7 +2537,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { + this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(-2, k, this.player.inventory.getItem(k))); + this.player.playerConnection.sendPacket(new PacketPlayOutHeldItemSlot(this.player.inventory.itemInHandIndex)); + } catch (Exception exception7) { +- PlayerConnection.LOGGER.error("Couldn\'t pick item", exception7); ++ IllegalPacketEvent.process(player.getBukkitEntity(), "InvalidPickItem", "Invalid PickItem", exception7); // Paper + } + } + // CraftBukkit start +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0188-IllegalPacketEvent.patch b/Spigot-Server-Patches/0188-IllegalPacketEvent.patch deleted file mode 100644 index 9749502ab1..0000000000 --- a/Spigot-Server-Patches/0188-IllegalPacketEvent.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 296392390487981d5c0f092afa3b1cb69cd3e90c Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 23 Jun 2016 23:33:57 -0400 -Subject: [PATCH] IllegalPacketEvent - -Fired for invalid data from players that represents hacking attempts - -diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 51d27351..43757500 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -56,6 +56,7 @@ import org.bukkit.inventory.CraftingInventory; - import org.bukkit.inventory.EquipmentSlot; - import org.bukkit.inventory.InventoryView; - import org.bukkit.util.NumberConversions; -+import com.destroystokyo.paper.event.player.IllegalPacketEvent; // Paper - import co.aikar.timings.MinecraftTimings; // Paper - // CraftBukkit end - -@@ -2236,8 +2237,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { - CraftEventFactory.handleEditBookEvent(player, itemstack1); // CraftBukkit - } - } catch (Exception exception) { -- PlayerConnection.LOGGER.error("Couldn\'t handle book info", exception); -- this.disconnect("Invalid book data!"); // CraftBukkit -+ IllegalPacketEvent.process(player.getBukkitEntity(), "InvalidBookEdit", "Invalid book data!", exception); // Paper - } - } else { - String s1; -@@ -2286,8 +2286,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { - CraftEventFactory.handleEditBookEvent(player, itemstack2); // CraftBukkit - } - } catch (Exception exception1) { -- PlayerConnection.LOGGER.error("Couldn\'t sign book", exception1); -- this.disconnect("Invalid book data!"); // CraftBukkit -+ IllegalPacketEvent.process(player.getBukkitEntity(), "InvalidBookSign", "Invalid book data!", exception1); // Paper - } - } else if ("MC|TrSel".equals(s)) { - try { -@@ -2298,8 +2297,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { - ((ContainerMerchant) container).d(j); - } - } catch (Exception exception2) { -- PlayerConnection.LOGGER.error("Couldn\'t select trade", exception2); -- this.disconnect("Invalid trade data!"); // CraftBukkit -+ IllegalPacketEvent.process(player.getBukkitEntity(), "InvalidTrade", "Invalid trade data!", exception2); // Paper - } - } else { - TileEntity tileentity; -@@ -2440,8 +2438,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { - iinventory.update(); - } - } catch (Exception exception5) { -- PlayerConnection.LOGGER.error("Couldn\'t set beacon", exception5); -- this.disconnect("Invalid beacon data!"); // CraftBukkit -+ IllegalPacketEvent.process(player.getBukkitEntity(), "InvalidBeacon", "Invalid beacon data!", exception5); // Paper - } - } - } else if ("MC|ItemName".equals(s)) { -@@ -2540,7 +2537,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { - this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(-2, k, this.player.inventory.getItem(k))); - this.player.playerConnection.sendPacket(new PacketPlayOutHeldItemSlot(this.player.inventory.itemInHandIndex)); - } catch (Exception exception7) { -- PlayerConnection.LOGGER.error("Couldn\'t pick item", exception7); -+ IllegalPacketEvent.process(player.getBukkitEntity(), "InvalidPickItem", "Invalid PickItem", exception7); // Paper - } - } - // CraftBukkit start --- -2.12.2 - diff --git a/Spigot-Server-Patches/0188-Properly-fix-item-duplication-bug.patch b/Spigot-Server-Patches/0188-Properly-fix-item-duplication-bug.patch new file mode 100644 index 0000000000..594531a444 --- /dev/null +++ b/Spigot-Server-Patches/0188-Properly-fix-item-duplication-bug.patch @@ -0,0 +1,35 @@ +From 77f94e63e14562ee3fd6baee250aa08629d20294 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/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java +index 58d40f994..acb4469d2 100644 +--- a/src/main/java/net/minecraft/server/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/EntityPlayer.java +@@ -1346,7 +1346,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + + @Override + protected boolean isFrozen() { +- return super.isFrozen() || !getBukkitEntity().isOnline(); ++ return super.isFrozen() || (this.playerConnection != null && this.playerConnection.isDisconnected()); // Paper + } + + public void reset() { +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 437575003..7c2d43ac2 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -2565,6 +2565,6 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { + + // CraftBukkit start - Add "isDisconnected" method + public final boolean isDisconnected() { +- return !this.player.joining && !this.networkManager.isConnected(); ++ return (!this.player.joining && !this.networkManager.isConnected()) || this.processedDisconnect; // Paper + } + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0189-Properly-fix-item-duplication-bug.patch b/Spigot-Server-Patches/0189-Properly-fix-item-duplication-bug.patch deleted file mode 100644 index 8562067b09..0000000000 --- a/Spigot-Server-Patches/0189-Properly-fix-item-duplication-bug.patch +++ /dev/null @@ -1,35 +0,0 @@ -From bd8532227d23fe7a62d16e8d4695f237ad2fc408 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/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index 58d40f994..acb4469d2 100644 ---- a/src/main/java/net/minecraft/server/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/EntityPlayer.java -@@ -1346,7 +1346,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - @Override - protected boolean isFrozen() { -- return super.isFrozen() || !getBukkitEntity().isOnline(); -+ return super.isFrozen() || (this.playerConnection != null && this.playerConnection.isDisconnected()); // Paper - } - - public void reset() { -diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 437575003..7c2d43ac2 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -2565,6 +2565,6 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { - - // CraftBukkit start - Add "isDisconnected" method - public final boolean isDisconnected() { -- return !this.player.joining && !this.networkManager.isConnected(); -+ return (!this.player.joining && !this.networkManager.isConnected()) || this.processedDisconnect; // Paper - } - } --- -2.12.2.windows.2 - diff --git a/Spigot-Server-Patches/0189-String-based-Action-Bar-API.patch b/Spigot-Server-Patches/0189-String-based-Action-Bar-API.patch new file mode 100644 index 0000000000..29845d6170 --- /dev/null +++ b/Spigot-Server-Patches/0189-String-based-Action-Bar-API.patch @@ -0,0 +1,89 @@ +From e3751676733cbb710d6a2bb4bea2352b06268c0e 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/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index 1159eea1a..38359517c 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -1,10 +1,13 @@ + package net.minecraft.server; + + import com.google.common.util.concurrent.ThreadFactoryBuilder; ++import org.apache.commons.lang.exception.ExceptionUtils; + import org.bukkit.Location; ++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.concurrent.ExecutionException; + import java.util.concurrent.Executor; +@@ -17,6 +20,24 @@ public final class MCUtil { + + private MCUtil() {} + ++ /** ++ * 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)); ++ } + + /** + * Ensures the target code is running on the main thread +@@ -186,4 +207,13 @@ public final class MCUtil { + } + return null; + } ++ ++ @Nonnull ++ public static World getNMSWorld(@Nonnull org.bukkit.World world) { ++ return ((CraftWorld) world).getHandle(); ++ } ++ ++ public static World getNMSWorld(@Nonnull org.bukkit.entity.Entity entity) { ++ return getNMSWorld(entity.getWorld()); ++ } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 61c32223d..072b59125 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -165,6 +165,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + + // Paper start + @Override ++ public void sendActionBar(String message) { ++ if (getHandle().playerConnection == null || message == null || message.isEmpty()) return; ++ getHandle().playerConnection.sendPacket(new PacketPlayOutChat(new ChatComponentText(message), (byte) 2)); ++ } ++ ++ @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) { + PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter(); + packet.header = header; +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0190-Activation-Range-Improvements.patch b/Spigot-Server-Patches/0190-Activation-Range-Improvements.patch new file mode 100644 index 0000000000..8c6610ff72 --- /dev/null +++ b/Spigot-Server-Patches/0190-Activation-Range-Improvements.patch @@ -0,0 +1,159 @@ +From 2fdcf26f32ce8995e73577b04c3fa62daed47b0b Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 27 Dec 2016 22:38:06 -0500 +Subject: [PATCH] Activation Range Improvements + +Fixes and adds new Immunities to improve gameplay behavior + +diff --git a/src/main/java/net/minecraft/server/EntityCreature.java b/src/main/java/net/minecraft/server/EntityCreature.java +index fdfe5b9ed..ce3907438 100644 +--- a/src/main/java/net/minecraft/server/EntityCreature.java ++++ b/src/main/java/net/minecraft/server/EntityCreature.java +@@ -10,6 +10,7 @@ public abstract class EntityCreature extends EntityInsentient { + + public static final UUID bu = UUID.fromString("E199AD21-BA8A-4C53-8D13-6182D5C69D3A"); + public static final AttributeModifier bv = (new AttributeModifier(EntityCreature.bu, "Fleeing speed bonus", 2.0D, 2)).a(false); ++ public BlockPosition movingTarget = null; public BlockPosition getMovingTarget() { return movingTarget; } // Paper + private BlockPosition a; + private float b; + private float c; +diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java +index b8ac99e5d..7242da9cc 100644 +--- a/src/main/java/net/minecraft/server/EntityLiving.java ++++ b/src/main/java/net/minecraft/server/EntityLiving.java +@@ -73,7 +73,7 @@ public abstract class EntityLiving extends Entity { + public float aQ; + public float aR; + public EntityHuman killer; +- protected int lastDamageByPlayerTime; ++ public int lastDamageByPlayerTime; // Paper - public + protected boolean aU; + protected int ticksFarFromPlayer; + protected float aW; +diff --git a/src/main/java/net/minecraft/server/EntityLlama.java b/src/main/java/net/minecraft/server/EntityLlama.java +index 13ae7a030..7e3aa6ee6 100644 +--- a/src/main/java/net/minecraft/server/EntityLlama.java ++++ b/src/main/java/net/minecraft/server/EntityLlama.java +@@ -363,7 +363,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn + return this.bL != null; + } + +- public boolean dR() { ++ public boolean inCaravan() { return dR(); } public boolean dR() { // Paper - OBFHELPER + return this.bK != null; + } + +diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java +index ac6e2a9aa..e6c190d43 100644 +--- a/src/main/java/net/minecraft/server/EntityVillager.java ++++ b/src/main/java/net/minecraft/server/EntityVillager.java +@@ -20,7 +20,7 @@ public class EntityVillager extends EntityAgeable implements NPC, IMerchant { + private static final Logger bx = LogManager.getLogger(); + private static final DataWatcherObject by = DataWatcher.a(EntityVillager.class, DataWatcherRegistry.b); + private int profession; +- private boolean bA; ++ private boolean bA;public boolean isMating() { return bA; } // Paper - OBFHELPER + private boolean bB; + Village village; + private EntityHuman tradingPlayer; +diff --git a/src/main/java/net/minecraft/server/PathfinderGoal.java b/src/main/java/net/minecraft/server/PathfinderGoal.java +index 83d9c43f3..1cb6652c2 100644 +--- a/src/main/java/net/minecraft/server/PathfinderGoal.java ++++ b/src/main/java/net/minecraft/server/PathfinderGoal.java +@@ -18,7 +18,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/server/PathfinderGoalGotoTarget.java b/src/main/java/net/minecraft/server/PathfinderGoalGotoTarget.java +index e5b5e9887..e3781f3a8 100644 +--- a/src/main/java/net/minecraft/server/PathfinderGoalGotoTarget.java ++++ b/src/main/java/net/minecraft/server/PathfinderGoalGotoTarget.java +@@ -2,12 +2,21 @@ package net.minecraft.server; + + public abstract class PathfinderGoalGotoTarget extends PathfinderGoal { + +- private final EntityCreature c; ++ private final EntityCreature c; public EntityCreature getEntity() { return c; } // Paper - OBFHELPER + private final double d; + protected int a; + private int e; + private int f; +- protected BlockPosition b; ++ protected BlockPosition b; public BlockPosition getTarget() { return b; } public void setTarget(BlockPosition pos) { this.b = pos; getEntity().movingTarget = pos != BlockPosition.ZERO ? pos : null; } // Paper - OBFHELPER ++ ++ // Paper start ++ @Override ++ public void onTaskReset() { ++ super.onTaskReset(); ++ setTarget(BlockPosition.ZERO); ++ } ++ // Paper end ++ + private boolean g; + private final int h; + +@@ -69,7 +78,7 @@ public abstract class PathfinderGoalGotoTarget extends PathfinderGoal { + BlockPosition blockposition1 = blockposition.a(l, j - 1, i1); + + if (this.c.f(blockposition1) && this.a(this.c.world, blockposition1)) { +- this.b = blockposition1; ++ setTarget(blockposition1); // Paper + return true; + } + } +diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java +index c8a6ff3d4..428912cbc 100644 +--- a/src/main/java/org/spigotmc/ActivationRange.java ++++ b/src/main/java/org/spigotmc/ActivationRange.java +@@ -20,6 +20,7 @@ import net.minecraft.server.EntityFireball; + import net.minecraft.server.EntityFireworks; + import net.minecraft.server.EntityHuman; + import net.minecraft.server.EntityLiving; ++import net.minecraft.server.EntityLlama; + import net.minecraft.server.EntityMonster; + import net.minecraft.server.EntityProjectile; + import net.minecraft.server.EntitySheep; +@@ -210,18 +211,29 @@ public class ActivationRange + if ( entity instanceof EntityLiving ) + { + EntityLiving living = (EntityLiving) entity; +- if ( /*TODO: Missed mapping? living.attackTicks > 0 || */ living.hurtTicks > 0 || living.effects.size() > 0 ) ++ if ( living.lastDamageByPlayerTime > 0 || living.hurtTicks > 0 || living.effects.size() > 0 ) // Paper + { + return true; + } +- if ( entity instanceof EntityCreature && ( (EntityCreature) entity ).getGoalTarget() != null ) ++ if ( entity instanceof EntityCreature ) ++ { ++ // Paper start ++ EntityCreature creature = (EntityCreature) entity; ++ if (creature.getGoalTarget() != null || creature.getMovingTarget() != null) { ++ return true; ++ } ++ // Paper end ++ } ++ if ( entity instanceof EntityVillager && ( (EntityVillager) entity ).isMating() ) // Paper + { + return true; + } +- if ( entity instanceof EntityVillager && ( (EntityVillager) entity ).df()/* Getter for first boolean */ ) ++ // Paper start ++ if ( entity instanceof EntityLlama && ( (EntityLlama ) entity ).inCaravan() ) + { + return true; + } ++ // Paper end + if ( entity instanceof EntityAnimal ) + { + EntityAnimal animal = (EntityAnimal) entity; +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0190-String-based-Action-Bar-API.patch b/Spigot-Server-Patches/0190-String-based-Action-Bar-API.patch deleted file mode 100644 index cdea69da14..0000000000 --- a/Spigot-Server-Patches/0190-String-based-Action-Bar-API.patch +++ /dev/null @@ -1,89 +0,0 @@ -From cc90ff49f039ed8a4f6029ab012ebb54650af0e0 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/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 1159eea1..38359517 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -1,10 +1,13 @@ - package net.minecraft.server; - - import com.google.common.util.concurrent.ThreadFactoryBuilder; -+import org.apache.commons.lang.exception.ExceptionUtils; - import org.bukkit.Location; -+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.concurrent.ExecutionException; - import java.util.concurrent.Executor; -@@ -17,6 +20,24 @@ public final class MCUtil { - - private MCUtil() {} - -+ /** -+ * 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)); -+ } - - /** - * Ensures the target code is running on the main thread -@@ -186,4 +207,13 @@ public final class MCUtil { - } - return null; - } -+ -+ @Nonnull -+ public static World getNMSWorld(@Nonnull org.bukkit.World world) { -+ return ((CraftWorld) world).getHandle(); -+ } -+ -+ public static World getNMSWorld(@Nonnull org.bukkit.entity.Entity entity) { -+ return getNMSWorld(entity.getWorld()); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 233903b5..a5703447 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -165,6 +165,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - - // Paper start - @Override -+ public void sendActionBar(String message) { -+ if (getHandle().playerConnection == null || message == null || message.isEmpty()) return; -+ getHandle().playerConnection.sendPacket(new PacketPlayOutChat(new ChatComponentText(message), (byte) 2)); -+ } -+ -+ @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) { - PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter(); - packet.header = header; --- -2.12.2 - diff --git a/Spigot-Server-Patches/0191-Activation-Range-Improvements.patch b/Spigot-Server-Patches/0191-Activation-Range-Improvements.patch deleted file mode 100644 index a8c8770983..0000000000 --- a/Spigot-Server-Patches/0191-Activation-Range-Improvements.patch +++ /dev/null @@ -1,159 +0,0 @@ -From c392e42cebf61a9533e604a387aa1a7fd702c613 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 27 Dec 2016 22:38:06 -0500 -Subject: [PATCH] Activation Range Improvements - -Fixes and adds new Immunities to improve gameplay behavior - -diff --git a/src/main/java/net/minecraft/server/EntityCreature.java b/src/main/java/net/minecraft/server/EntityCreature.java -index fdfe5b9e..ce390743 100644 ---- a/src/main/java/net/minecraft/server/EntityCreature.java -+++ b/src/main/java/net/minecraft/server/EntityCreature.java -@@ -10,6 +10,7 @@ public abstract class EntityCreature extends EntityInsentient { - - public static final UUID bu = UUID.fromString("E199AD21-BA8A-4C53-8D13-6182D5C69D3A"); - public static final AttributeModifier bv = (new AttributeModifier(EntityCreature.bu, "Fleeing speed bonus", 2.0D, 2)).a(false); -+ public BlockPosition movingTarget = null; public BlockPosition getMovingTarget() { return movingTarget; } // Paper - private BlockPosition a; - private float b; - private float c; -diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index b8ac99e5..7242da9c 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -73,7 +73,7 @@ public abstract class EntityLiving extends Entity { - public float aQ; - public float aR; - public EntityHuman killer; -- protected int lastDamageByPlayerTime; -+ public int lastDamageByPlayerTime; // Paper - public - protected boolean aU; - protected int ticksFarFromPlayer; - protected float aW; -diff --git a/src/main/java/net/minecraft/server/EntityLlama.java b/src/main/java/net/minecraft/server/EntityLlama.java -index 13ae7a03..7e3aa6ee 100644 ---- a/src/main/java/net/minecraft/server/EntityLlama.java -+++ b/src/main/java/net/minecraft/server/EntityLlama.java -@@ -363,7 +363,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn - return this.bL != null; - } - -- public boolean dR() { -+ public boolean inCaravan() { return dR(); } public boolean dR() { // Paper - OBFHELPER - return this.bK != null; - } - -diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java -index ac6e2a9a..e6c190d4 100644 ---- a/src/main/java/net/minecraft/server/EntityVillager.java -+++ b/src/main/java/net/minecraft/server/EntityVillager.java -@@ -20,7 +20,7 @@ public class EntityVillager extends EntityAgeable implements NPC, IMerchant { - private static final Logger bx = LogManager.getLogger(); - private static final DataWatcherObject by = DataWatcher.a(EntityVillager.class, DataWatcherRegistry.b); - private int profession; -- private boolean bA; -+ private boolean bA;public boolean isMating() { return bA; } // Paper - OBFHELPER - private boolean bB; - Village village; - private EntityHuman tradingPlayer; -diff --git a/src/main/java/net/minecraft/server/PathfinderGoal.java b/src/main/java/net/minecraft/server/PathfinderGoal.java -index 83d9c43f..1cb6652c 100644 ---- a/src/main/java/net/minecraft/server/PathfinderGoal.java -+++ b/src/main/java/net/minecraft/server/PathfinderGoal.java -@@ -18,7 +18,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/server/PathfinderGoalGotoTarget.java b/src/main/java/net/minecraft/server/PathfinderGoalGotoTarget.java -index e5b5e988..e3781f3a 100644 ---- a/src/main/java/net/minecraft/server/PathfinderGoalGotoTarget.java -+++ b/src/main/java/net/minecraft/server/PathfinderGoalGotoTarget.java -@@ -2,12 +2,21 @@ package net.minecraft.server; - - public abstract class PathfinderGoalGotoTarget extends PathfinderGoal { - -- private final EntityCreature c; -+ private final EntityCreature c; public EntityCreature getEntity() { return c; } // Paper - OBFHELPER - private final double d; - protected int a; - private int e; - private int f; -- protected BlockPosition b; -+ protected BlockPosition b; public BlockPosition getTarget() { return b; } public void setTarget(BlockPosition pos) { this.b = pos; getEntity().movingTarget = pos != BlockPosition.ZERO ? pos : null; } // Paper - OBFHELPER -+ -+ // Paper start -+ @Override -+ public void onTaskReset() { -+ super.onTaskReset(); -+ setTarget(BlockPosition.ZERO); -+ } -+ // Paper end -+ - private boolean g; - private final int h; - -@@ -69,7 +78,7 @@ public abstract class PathfinderGoalGotoTarget extends PathfinderGoal { - BlockPosition blockposition1 = blockposition.a(l, j - 1, i1); - - if (this.c.f(blockposition1) && this.a(this.c.world, blockposition1)) { -- this.b = blockposition1; -+ setTarget(blockposition1); // Paper - return true; - } - } -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index c8a6ff3d..428912cb 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -20,6 +20,7 @@ import net.minecraft.server.EntityFireball; - import net.minecraft.server.EntityFireworks; - import net.minecraft.server.EntityHuman; - import net.minecraft.server.EntityLiving; -+import net.minecraft.server.EntityLlama; - import net.minecraft.server.EntityMonster; - import net.minecraft.server.EntityProjectile; - import net.minecraft.server.EntitySheep; -@@ -210,18 +211,29 @@ public class ActivationRange - if ( entity instanceof EntityLiving ) - { - EntityLiving living = (EntityLiving) entity; -- if ( /*TODO: Missed mapping? living.attackTicks > 0 || */ living.hurtTicks > 0 || living.effects.size() > 0 ) -+ if ( living.lastDamageByPlayerTime > 0 || living.hurtTicks > 0 || living.effects.size() > 0 ) // Paper - { - return true; - } -- if ( entity instanceof EntityCreature && ( (EntityCreature) entity ).getGoalTarget() != null ) -+ if ( entity instanceof EntityCreature ) -+ { -+ // Paper start -+ EntityCreature creature = (EntityCreature) entity; -+ if (creature.getGoalTarget() != null || creature.getMovingTarget() != null) { -+ return true; -+ } -+ // Paper end -+ } -+ if ( entity instanceof EntityVillager && ( (EntityVillager) entity ).isMating() ) // Paper - { - return true; - } -- if ( entity instanceof EntityVillager && ( (EntityVillager) entity ).df()/* Getter for first boolean */ ) -+ // Paper start -+ if ( entity instanceof EntityLlama && ( (EntityLlama ) entity ).inCaravan() ) - { - return true; - } -+ // Paper end - if ( entity instanceof EntityAnimal ) - { - EntityAnimal animal = (EntityAnimal) entity; --- -2.12.2 - diff --git a/Spigot-Server-Patches/0191-Firework-API-s.patch b/Spigot-Server-Patches/0191-Firework-API-s.patch new file mode 100644 index 0000000000..ca0d8523f0 --- /dev/null +++ b/Spigot-Server-Patches/0191-Firework-API-s.patch @@ -0,0 +1,133 @@ +From 77cab89358556aee79c19fc27856885bcc29174b Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 28 Dec 2016 01:18:33 -0500 +Subject: [PATCH] Firework API's + + +diff --git a/src/main/java/net/minecraft/server/EntityFireworks.java b/src/main/java/net/minecraft/server/EntityFireworks.java +index 572f4dead..f9cf382b2 100644 +--- a/src/main/java/net/minecraft/server/EntityFireworks.java ++++ b/src/main/java/net/minecraft/server/EntityFireworks.java +@@ -2,6 +2,8 @@ package net.minecraft.server; + + import java.util.Iterator; + import java.util.List; ++import java.util.UUID; ++ + import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class EntityFireworks extends Entity { +@@ -10,7 +12,8 @@ public class EntityFireworks extends Entity { + private static final DataWatcherObject b = DataWatcher.a(EntityFireworks.class, DataWatcherRegistry.b); + private int ticksFlown; + public int expectedLifespan; +- private EntityLiving e; ++ public UUID spawningEntity; // Paper ++ private EntityLiving e;public EntityLiving getBoostedEntity() { return e; } // Paper - OBFHELPER + + public EntityFireworks(World world) { + super(world); +@@ -203,6 +206,11 @@ public class EntityFireworks extends Entity { + if (!itemstack.isEmpty()) { + nbttagcompound.set("FireworksItem", itemstack.save(new NBTTagCompound())); + } ++ // Paper start ++ if (spawningEntity != null) { ++ nbttagcompound.setUUID("SpawningEntity", spawningEntity); ++ } ++ // Paper end + + } + +@@ -218,7 +226,11 @@ public class EntityFireworks extends Entity { + this.datawatcher.set(EntityFireworks.FIREWORK_ITEM, itemstack); + } + } +- ++ // Paper start ++ if (nbttagcompound.hasUUID("SpawningEntity")) { ++ spawningEntity = nbttagcompound.getUUID("SpawningEntity"); ++ } ++ // Paper end + } + + public boolean aV() { +diff --git a/src/main/java/net/minecraft/server/ItemFireworks.java b/src/main/java/net/minecraft/server/ItemFireworks.java +index 4fc36d243..5cd68bfaf 100644 +--- a/src/main/java/net/minecraft/server/ItemFireworks.java ++++ b/src/main/java/net/minecraft/server/ItemFireworks.java +@@ -9,6 +9,7 @@ public class ItemFireworks extends Item { + ItemStack itemstack = entityhuman.b(enumhand); + EntityFireworks entityfireworks = new EntityFireworks(world, (double) ((float) blockposition.getX() + f), (double) ((float) blockposition.getY() + f1), (double) ((float) blockposition.getZ() + f2), itemstack); + ++ entityfireworks.spawningEntity = entityhuman.getUniqueID(); // Paper + world.addEntity(entityfireworks); + if (!entityhuman.abilities.canInstantlyBuild) { + itemstack.subtract(1); +@@ -25,6 +26,7 @@ public class ItemFireworks extends Item { + if (!world.isClientSide) { + EntityFireworks entityfireworks = new EntityFireworks(world, itemstack, entityhuman); + ++ entityfireworks.spawningEntity = entityhuman.getUniqueID(); // Paper + world.addEntity(entityfireworks); + if (!entityhuman.abilities.canInstantlyBuild) { + itemstack.subtract(1); +diff --git a/src/main/java/net/minecraft/server/NBTTagCompound.java b/src/main/java/net/minecraft/server/NBTTagCompound.java +index 2a2f53c82..266741fcd 100644 +--- a/src/main/java/net/minecraft/server/NBTTagCompound.java ++++ b/src/main/java/net/minecraft/server/NBTTagCompound.java +@@ -103,7 +103,7 @@ public class NBTTagCompound extends NBTBase { + return new UUID(this.getLong(s + "Most"), this.getLong(s + "Least")); + } + +- public boolean b(String s) { ++ public boolean hasUUID(String s) { return b(s); } public boolean b(String s) { // Paper - OBFHELPER + return this.hasKeyOfType(s + "Most", 99) && this.hasKeyOfType(s + "Least", 99); + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java +index 99746b3c2..d4fbe31d6 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 net.minecraft.server.EntityFireworks; ++import net.minecraft.server.EntityLiving; + import net.minecraft.server.ItemStack; + import net.minecraft.server.Items; + +@@ -9,9 +10,11 @@ import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.inventory.CraftItemStack; + import org.bukkit.entity.EntityType; + import org.bukkit.entity.Firework; ++import org.bukkit.entity.LivingEntity; + import org.bukkit.inventory.meta.FireworkMeta; + + import java.util.Random; ++import java.util.UUID; + + public class CraftFirework extends CraftEntity implements Firework { + +@@ -70,4 +73,18 @@ public class CraftFirework extends CraftEntity implements Firework { + public void detonate() { + getHandle().expectedLifespan = 0; + } ++ ++ // Paper start ++ ++ @Override ++ public UUID getSpawningEntity() { ++ return getHandle().spawningEntity; ++ } ++ ++ @Override ++ public LivingEntity getBoostedEntity() { ++ EntityLiving boostedEntity = getHandle().getBoostedEntity(); ++ return boostedEntity != null ? (LivingEntity) boostedEntity.getBukkitEntity() : null; ++ } ++ // Paper end + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0192-Change-Outdated-Build-Download-URL-to-Paper-CI.patch b/Spigot-Server-Patches/0192-Change-Outdated-Build-Download-URL-to-Paper-CI.patch new file mode 100644 index 0000000000..0655c4c429 --- /dev/null +++ b/Spigot-Server-Patches/0192-Change-Outdated-Build-Download-URL-to-Paper-CI.patch @@ -0,0 +1,22 @@ +From 2c39eddf8fae574d0799de86543aee218c5de0c2 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 29 Dec 2016 00:56:51 -0500 +Subject: [PATCH] Change Outdated Build Download URL to Paper CI + + +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 59d4e2e6f..e4ec213e4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -200,7 +200,7 @@ public class Main { + deadline.add(Calendar.DAY_OF_YEAR, -14); + 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/ ***"); ++ System.err.println("*** Please download a new build as per instructions from https://paperci.emc.gs/ ***"); // Paper + System.err.println("*** Server will start in 15 seconds ***"); + Thread.sleep(TimeUnit.SECONDS.toMillis(15)); + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0192-Firework-API-s.patch b/Spigot-Server-Patches/0192-Firework-API-s.patch deleted file mode 100644 index c31386a122..0000000000 --- a/Spigot-Server-Patches/0192-Firework-API-s.patch +++ /dev/null @@ -1,133 +0,0 @@ -From efd9d25626205508f7eebb859fbbf11dd67f67d1 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 28 Dec 2016 01:18:33 -0500 -Subject: [PATCH] Firework API's - - -diff --git a/src/main/java/net/minecraft/server/EntityFireworks.java b/src/main/java/net/minecraft/server/EntityFireworks.java -index 572f4dea..f9cf382b 100644 ---- a/src/main/java/net/minecraft/server/EntityFireworks.java -+++ b/src/main/java/net/minecraft/server/EntityFireworks.java -@@ -2,6 +2,8 @@ package net.minecraft.server; - - import java.util.Iterator; - import java.util.List; -+import java.util.UUID; -+ - import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit - - public class EntityFireworks extends Entity { -@@ -10,7 +12,8 @@ public class EntityFireworks extends Entity { - private static final DataWatcherObject b = DataWatcher.a(EntityFireworks.class, DataWatcherRegistry.b); - private int ticksFlown; - public int expectedLifespan; -- private EntityLiving e; -+ public UUID spawningEntity; // Paper -+ private EntityLiving e;public EntityLiving getBoostedEntity() { return e; } // Paper - OBFHELPER - - public EntityFireworks(World world) { - super(world); -@@ -203,6 +206,11 @@ public class EntityFireworks extends Entity { - if (!itemstack.isEmpty()) { - nbttagcompound.set("FireworksItem", itemstack.save(new NBTTagCompound())); - } -+ // Paper start -+ if (spawningEntity != null) { -+ nbttagcompound.setUUID("SpawningEntity", spawningEntity); -+ } -+ // Paper end - - } - -@@ -218,7 +226,11 @@ public class EntityFireworks extends Entity { - this.datawatcher.set(EntityFireworks.FIREWORK_ITEM, itemstack); - } - } -- -+ // Paper start -+ if (nbttagcompound.hasUUID("SpawningEntity")) { -+ spawningEntity = nbttagcompound.getUUID("SpawningEntity"); -+ } -+ // Paper end - } - - public boolean aV() { -diff --git a/src/main/java/net/minecraft/server/ItemFireworks.java b/src/main/java/net/minecraft/server/ItemFireworks.java -index 4fc36d24..5cd68bfa 100644 ---- a/src/main/java/net/minecraft/server/ItemFireworks.java -+++ b/src/main/java/net/minecraft/server/ItemFireworks.java -@@ -9,6 +9,7 @@ public class ItemFireworks extends Item { - ItemStack itemstack = entityhuman.b(enumhand); - EntityFireworks entityfireworks = new EntityFireworks(world, (double) ((float) blockposition.getX() + f), (double) ((float) blockposition.getY() + f1), (double) ((float) blockposition.getZ() + f2), itemstack); - -+ entityfireworks.spawningEntity = entityhuman.getUniqueID(); // Paper - world.addEntity(entityfireworks); - if (!entityhuman.abilities.canInstantlyBuild) { - itemstack.subtract(1); -@@ -25,6 +26,7 @@ public class ItemFireworks extends Item { - if (!world.isClientSide) { - EntityFireworks entityfireworks = new EntityFireworks(world, itemstack, entityhuman); - -+ entityfireworks.spawningEntity = entityhuman.getUniqueID(); // Paper - world.addEntity(entityfireworks); - if (!entityhuman.abilities.canInstantlyBuild) { - itemstack.subtract(1); -diff --git a/src/main/java/net/minecraft/server/NBTTagCompound.java b/src/main/java/net/minecraft/server/NBTTagCompound.java -index 2a2f53c8..266741fc 100644 ---- a/src/main/java/net/minecraft/server/NBTTagCompound.java -+++ b/src/main/java/net/minecraft/server/NBTTagCompound.java -@@ -103,7 +103,7 @@ public class NBTTagCompound extends NBTBase { - return new UUID(this.getLong(s + "Most"), this.getLong(s + "Least")); - } - -- public boolean b(String s) { -+ public boolean hasUUID(String s) { return b(s); } public boolean b(String s) { // Paper - OBFHELPER - return this.hasKeyOfType(s + "Most", 99) && this.hasKeyOfType(s + "Least", 99); - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java -index 99746b3c..d4fbe31d 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 net.minecraft.server.EntityFireworks; -+import net.minecraft.server.EntityLiving; - import net.minecraft.server.ItemStack; - import net.minecraft.server.Items; - -@@ -9,9 +10,11 @@ import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.inventory.CraftItemStack; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.Firework; -+import org.bukkit.entity.LivingEntity; - import org.bukkit.inventory.meta.FireworkMeta; - - import java.util.Random; -+import java.util.UUID; - - public class CraftFirework extends CraftEntity implements Firework { - -@@ -70,4 +73,18 @@ public class CraftFirework extends CraftEntity implements Firework { - public void detonate() { - getHandle().expectedLifespan = 0; - } -+ -+ // Paper start -+ -+ @Override -+ public UUID getSpawningEntity() { -+ return getHandle().spawningEntity; -+ } -+ -+ @Override -+ public LivingEntity getBoostedEntity() { -+ EntityLiving boostedEntity = getHandle().getBoostedEntity(); -+ return boostedEntity != null ? (LivingEntity) boostedEntity.getBukkitEntity() : null; -+ } -+ // Paper end - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0193-Change-Outdated-Build-Download-URL-to-Paper-CI.patch b/Spigot-Server-Patches/0193-Change-Outdated-Build-Download-URL-to-Paper-CI.patch deleted file mode 100644 index 1efdc27ed9..0000000000 --- a/Spigot-Server-Patches/0193-Change-Outdated-Build-Download-URL-to-Paper-CI.patch +++ /dev/null @@ -1,22 +0,0 @@ -From aa61f3fe07ad74f26194edff03cd511a0ac490f1 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 29 Dec 2016 00:56:51 -0500 -Subject: [PATCH] Change Outdated Build Download URL to Paper CI - - -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 59d4e2e6..e4ec213e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -200,7 +200,7 @@ public class Main { - deadline.add(Calendar.DAY_OF_YEAR, -14); - 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/ ***"); -+ System.err.println("*** Please download a new build as per instructions from https://paperci.emc.gs/ ***"); // Paper - System.err.println("*** Server will start in 15 seconds ***"); - Thread.sleep(TimeUnit.SECONDS.toMillis(15)); - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0193-PlayerTeleportEndGatewayEvent.patch b/Spigot-Server-Patches/0193-PlayerTeleportEndGatewayEvent.patch new file mode 100644 index 0000000000..81f78a9811 --- /dev/null +++ b/Spigot-Server-Patches/0193-PlayerTeleportEndGatewayEvent.patch @@ -0,0 +1,23 @@ +From 2bdc6f5272c0edc55981f9be27551637da1cd57b 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/server/TileEntityEndGateway.java b/src/main/java/net/minecraft/server/TileEntityEndGateway.java +index 065d0bbfc..ea8992d72 100644 +--- a/src/main/java/net/minecraft/server/TileEntityEndGateway.java ++++ b/src/main/java/net/minecraft/server/TileEntityEndGateway.java +@@ -124,7 +124,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; +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0194-MC-111699-Ignore-Improper-Anvil-Item-Name-Packets.patch b/Spigot-Server-Patches/0194-MC-111699-Ignore-Improper-Anvil-Item-Name-Packets.patch new file mode 100644 index 0000000000..b477751f80 --- /dev/null +++ b/Spigot-Server-Patches/0194-MC-111699-Ignore-Improper-Anvil-Item-Name-Packets.patch @@ -0,0 +1,28 @@ +From c4db7822f7900b67d446e850eddc5c1072189c43 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 2 Jan 2017 02:07:24 -0500 +Subject: [PATCH] MC-111699: Ignore Improper Anvil Item Name Packets + +The client is improperly sending Item Name Packets to the server BEFORE +the click event. This causes the server to reset before the click event is processed + +This breaks the ability to rename more than 1 item at a time. + +See: https://bugs.mojang.com/browse/MC-111699 + +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 7c2d43ac2..cbe5d36d0 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -2449,7 +2449,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { + String s4 = SharedConstants.a(packetplayincustompayload.b().e(32767)); + + if (s4.length() <= 30) { +- containeranvil.a(s4); ++ if (!s4.isEmpty() || containeranvil.getSlot(2).getItem().isEmpty()) containeranvil.a(s4); // Paper - Hack Fix for MC-111699 + } + } else { + containeranvil.a(""); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0194-PlayerTeleportEndGatewayEvent.patch b/Spigot-Server-Patches/0194-PlayerTeleportEndGatewayEvent.patch deleted file mode 100644 index 87f797c189..0000000000 --- a/Spigot-Server-Patches/0194-PlayerTeleportEndGatewayEvent.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 9005f191ef06a9e704811f05166da220da96bc00 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/server/TileEntityEndGateway.java b/src/main/java/net/minecraft/server/TileEntityEndGateway.java -index 065d0bbf..ea8992d7 100644 ---- a/src/main/java/net/minecraft/server/TileEntityEndGateway.java -+++ b/src/main/java/net/minecraft/server/TileEntityEndGateway.java -@@ -124,7 +124,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; --- -2.12.2 - diff --git a/Spigot-Server-Patches/0195-MC-111699-Ignore-Improper-Anvil-Item-Name-Packets.patch b/Spigot-Server-Patches/0195-MC-111699-Ignore-Improper-Anvil-Item-Name-Packets.patch deleted file mode 100644 index b65a02a5d6..0000000000 --- a/Spigot-Server-Patches/0195-MC-111699-Ignore-Improper-Anvil-Item-Name-Packets.patch +++ /dev/null @@ -1,28 +0,0 @@ -From c36f506b1200efce56cc66a11e2930dcc4803de1 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 2 Jan 2017 02:07:24 -0500 -Subject: [PATCH] MC-111699: Ignore Improper Anvil Item Name Packets - -The client is improperly sending Item Name Packets to the server BEFORE -the click event. This causes the server to reset before the click event is processed - -This breaks the ability to rename more than 1 item at a time. - -See: https://bugs.mojang.com/browse/MC-111699 - -diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 7c2d43ac..cbe5d36d 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -2449,7 +2449,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { - String s4 = SharedConstants.a(packetplayincustompayload.b().e(32767)); - - if (s4.length() <= 30) { -- containeranvil.a(s4); -+ if (!s4.isEmpty() || containeranvil.getSlot(2).getItem().isEmpty()) containeranvil.a(s4); // Paper - Hack Fix for MC-111699 - } - } else { - containeranvil.a(""); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0195-MC-112017-Allow-31-instead-of-30-for-item-names.patch b/Spigot-Server-Patches/0195-MC-112017-Allow-31-instead-of-30-for-item-names.patch new file mode 100644 index 0000000000..298b6f374a --- /dev/null +++ b/Spigot-Server-Patches/0195-MC-112017-Allow-31-instead-of-30-for-item-names.patch @@ -0,0 +1,22 @@ +From 598f7eb64194ea079dd66291a32f825ed4e790e4 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 2 Jan 2017 02:43:22 -0500 +Subject: [PATCH] MC-112017: Allow 31 instead of 30 for item names + + +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index cbe5d36d0..70af4ebbb 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -2448,7 +2448,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { + if (packetplayincustompayload.b() != null && packetplayincustompayload.b().readableBytes() >= 1) { + String s4 = SharedConstants.a(packetplayincustompayload.b().e(32767)); + +- if (s4.length() <= 30) { ++ if (s4.length() <= 31) { // Paper - MC-112017 + if (!s4.isEmpty() || containeranvil.getSlot(2).getItem().isEmpty()) containeranvil.a(s4); // Paper - Hack Fix for MC-111699 + } + } else { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0196-MC-112017-Allow-31-instead-of-30-for-item-names.patch b/Spigot-Server-Patches/0196-MC-112017-Allow-31-instead-of-30-for-item-names.patch deleted file mode 100644 index 4e9bf31581..0000000000 --- a/Spigot-Server-Patches/0196-MC-112017-Allow-31-instead-of-30-for-item-names.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 8cbb563ef82d04f6723b7d3cfc4363da1d833249 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 2 Jan 2017 02:43:22 -0500 -Subject: [PATCH] MC-112017: Allow 31 instead of 30 for item names - - -diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index cbe5d36d..70af4ebb 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -2448,7 +2448,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { - if (packetplayincustompayload.b() != null && packetplayincustompayload.b().readableBytes() >= 1) { - String s4 = SharedConstants.a(packetplayincustompayload.b().e(32767)); - -- if (s4.length() <= 30) { -+ if (s4.length() <= 31) { // Paper - MC-112017 - if (!s4.isEmpty() || containeranvil.getSlot(2).getItem().isEmpty()) containeranvil.a(s4); // Paper - Hack Fix for MC-111699 - } - } else { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0196-ShulkerBox-Dupe-Prevention.patch b/Spigot-Server-Patches/0196-ShulkerBox-Dupe-Prevention.patch new file mode 100644 index 0000000000..de6d5c1b9c --- /dev/null +++ b/Spigot-Server-Patches/0196-ShulkerBox-Dupe-Prevention.patch @@ -0,0 +1,23 @@ +From b8d59828da1c0c02e2c8bbd465097280823dca75 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 2 Jan 2017 16:32:56 -0500 +Subject: [PATCH] ShulkerBox Dupe Prevention + +This ensures that Shulker Boxes can never drop their contents twice, and +that the inventory is cleared incase it some how also got saved to the world. + +diff --git a/src/main/java/net/minecraft/server/BlockShulkerBox.java b/src/main/java/net/minecraft/server/BlockShulkerBox.java +index fcb1a6c66..12fb81635 100644 +--- a/src/main/java/net/minecraft/server/BlockShulkerBox.java ++++ b/src/main/java/net/minecraft/server/BlockShulkerBox.java +@@ -109,6 +109,7 @@ public class BlockShulkerBox extends BlockTileEntity { + } + + a(world, blockposition, itemstack); ++ tileentityshulkerbox.clear(); // Paper - This was intended to be called in Vanilla (is checked in the if statement above if has been called) - Fixes dupe issues + } + + world.updateAdjacentComparators(blockposition, iblockdata.getBlock()); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0197-Provide-E-TE-Chunk-count-stat-methods.patch b/Spigot-Server-Patches/0197-Provide-E-TE-Chunk-count-stat-methods.patch new file mode 100644 index 0000000000..94854a7ecd --- /dev/null +++ b/Spigot-Server-Patches/0197-Provide-E-TE-Chunk-count-stat-methods.patch @@ -0,0 +1,45 @@ +From 02c793d3104d8e5020e4a3a52f84ff4dcedc7cb3 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 3f8859a1f..b42074706 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -78,6 +78,29 @@ public class CraftWorld implements World { + private int chunkLoadCount = 0; + private int chunkGCTickCount; + ++ // Paper start - Provide fast information methods ++ public int getEntityCount() { ++ return world.entityList.size(); ++ } ++ public int getTileEntityCount() { ++ // We don't use the full world tile entity list, so we must iterate chunks ++ int size = 0; ++ for (net.minecraft.server.Chunk chunk : ((ChunkProviderServer) world.getChunkProvider()).chunks.values()) { ++ size += chunk.tileEntities.size(); ++ } ++ return size; ++ } ++ public int getTickableTileEntityCount() { ++ return world.tileEntityListTick.size(); ++ } ++ public int getChunkCount() { ++ return world.getChunkProviderServer().chunks.size(); ++ } ++ public int getPlayerCount() { ++ return world.players.size(); ++ } ++ // Paper end ++ + private static final Random rand = new Random(); + + public CraftWorld(WorldServer world, ChunkGenerator gen, Environment env) { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0197-ShulkerBox-Dupe-Prevention.patch b/Spigot-Server-Patches/0197-ShulkerBox-Dupe-Prevention.patch deleted file mode 100644 index 851a3814b6..0000000000 --- a/Spigot-Server-Patches/0197-ShulkerBox-Dupe-Prevention.patch +++ /dev/null @@ -1,23 +0,0 @@ -From bbf93cd5704f8d700fcb1154b75085f7406c1a53 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 2 Jan 2017 16:32:56 -0500 -Subject: [PATCH] ShulkerBox Dupe Prevention - -This ensures that Shulker Boxes can never drop their contents twice, and -that the inventory is cleared incase it some how also got saved to the world. - -diff --git a/src/main/java/net/minecraft/server/BlockShulkerBox.java b/src/main/java/net/minecraft/server/BlockShulkerBox.java -index fcb1a6c6..12fb8163 100644 ---- a/src/main/java/net/minecraft/server/BlockShulkerBox.java -+++ b/src/main/java/net/minecraft/server/BlockShulkerBox.java -@@ -109,6 +109,7 @@ public class BlockShulkerBox extends BlockTileEntity { - } - - a(world, blockposition, itemstack); -+ tileentityshulkerbox.clear(); // Paper - This was intended to be called in Vanilla (is checked in the if statement above if has been called) - Fixes dupe issues - } - - world.updateAdjacentComparators(blockposition, iblockdata.getBlock()); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0198-Enforce-Sync-Player-Saves.patch b/Spigot-Server-Patches/0198-Enforce-Sync-Player-Saves.patch new file mode 100644 index 0000000000..ae74e6baa7 --- /dev/null +++ b/Spigot-Server-Patches/0198-Enforce-Sync-Player-Saves.patch @@ -0,0 +1,31 @@ +From 99d5619fef40baa566b55e9b3502d44a39ad3bf0 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/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java +index 58f30fb1d..034bdb7cf 100644 +--- a/src/main/java/net/minecraft/server/PlayerList.java ++++ b/src/main/java/net/minecraft/server/PlayerList.java +@@ -1214,6 +1214,7 @@ public abstract class PlayerList { + } + + public void savePlayers(Integer interval) { ++ MCUtil.ensureMain("Save Players", () -> { // Paper - ensure main + long now = MinecraftServer.currentTick; + MinecraftTimings.savePlayers.startTiming(); // Paper + for (int i = 0; i < this.players.size(); ++i) { +@@ -1223,6 +1224,7 @@ public abstract class PlayerList { + } + } + MinecraftTimings.savePlayers.stopTiming(); // Paper ++ return null; }); // Paper - ensure main + } + // Paper end + +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0198-Provide-E-TE-Chunk-count-stat-methods.patch b/Spigot-Server-Patches/0198-Provide-E-TE-Chunk-count-stat-methods.patch deleted file mode 100644 index 9508b74200..0000000000 --- a/Spigot-Server-Patches/0198-Provide-E-TE-Chunk-count-stat-methods.patch +++ /dev/null @@ -1,45 +0,0 @@ -From df856ad0cf3f52de980e71a1e0c7288beff54334 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 3f8859a1..b4207470 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -78,6 +78,29 @@ public class CraftWorld implements World { - private int chunkLoadCount = 0; - private int chunkGCTickCount; - -+ // Paper start - Provide fast information methods -+ public int getEntityCount() { -+ return world.entityList.size(); -+ } -+ public int getTileEntityCount() { -+ // We don't use the full world tile entity list, so we must iterate chunks -+ int size = 0; -+ for (net.minecraft.server.Chunk chunk : ((ChunkProviderServer) world.getChunkProvider()).chunks.values()) { -+ size += chunk.tileEntities.size(); -+ } -+ return size; -+ } -+ public int getTickableTileEntityCount() { -+ return world.tileEntityListTick.size(); -+ } -+ public int getChunkCount() { -+ return world.getChunkProviderServer().chunks.size(); -+ } -+ public int getPlayerCount() { -+ return world.players.size(); -+ } -+ // Paper end -+ - private static final Random rand = new Random(); - - public CraftWorld(WorldServer world, ChunkGenerator gen, Environment env) { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0199-Enforce-Sync-Chunk-Unloads.patch b/Spigot-Server-Patches/0199-Enforce-Sync-Chunk-Unloads.patch new file mode 100644 index 0000000000..5dd16ec3a0 --- /dev/null +++ b/Spigot-Server-Patches/0199-Enforce-Sync-Chunk-Unloads.patch @@ -0,0 +1,31 @@ +From 99af5e5c170122720f987589ca7d0102dda88197 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 7 Jan 2017 16:06:44 -0500 +Subject: [PATCH] Enforce Sync Chunk Unloads + +Unloading Chunks async is extremely dangerous. This will force it to main +the same way we handle async chunk loads. + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index b42074706..b837a921c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -238,6 +238,7 @@ public class CraftWorld implements World { + } + + private boolean unloadChunk0(int x, int z, boolean save) { ++ Boolean result = MCUtil.ensureMain("Unload Chunk", () -> { // Paper - Ensure never async + net.minecraft.server.Chunk chunk = world.getChunkProviderServer().getChunkIfLoaded(x, z); + if (chunk == null) { + return true; +@@ -245,6 +246,7 @@ public class CraftWorld implements World { + + // If chunk had previously been queued to save, must do save to avoid loss of that data + return world.getChunkProviderServer().unloadChunk(chunk, chunk.mustSave || save); ++ }); return result != null ? result : false; // Paper - Ensure never async + } + + public boolean regenerateChunk(int x, int z) { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0199-Enforce-Sync-Player-Saves.patch b/Spigot-Server-Patches/0199-Enforce-Sync-Player-Saves.patch deleted file mode 100644 index 31ff6fbbc0..0000000000 --- a/Spigot-Server-Patches/0199-Enforce-Sync-Player-Saves.patch +++ /dev/null @@ -1,31 +0,0 @@ -From ec9ab2991de89ca5c7c8c51bb4ab8abbee15d5d0 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/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java -index 58f30fb1d..034bdb7cf 100644 ---- a/src/main/java/net/minecraft/server/PlayerList.java -+++ b/src/main/java/net/minecraft/server/PlayerList.java -@@ -1214,6 +1214,7 @@ public abstract class PlayerList { - } - - public void savePlayers(Integer interval) { -+ MCUtil.ensureMain("Save Players", () -> { // Paper - ensure main - long now = MinecraftServer.currentTick; - MinecraftTimings.savePlayers.startTiming(); // Paper - for (int i = 0; i < this.players.size(); ++i) { -@@ -1223,6 +1224,7 @@ public abstract class PlayerList { - } - } - MinecraftTimings.savePlayers.stopTiming(); // Paper -+ return null; }); // Paper - ensure main - } - // Paper end - --- -2.12.2.windows.2 - diff --git a/Spigot-Server-Patches/0200-Don-t-allow-entities-to-ride-themselves-572.patch b/Spigot-Server-Patches/0200-Don-t-allow-entities-to-ride-themselves-572.patch new file mode 100644 index 0000000000..85a14cd9fe --- /dev/null +++ b/Spigot-Server-Patches/0200-Don-t-allow-entities-to-ride-themselves-572.patch @@ -0,0 +1,21 @@ +From 760288d1cb35ce28612916f1fe13f03a80ea8b73 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/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 1e295432e..6fcced926 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -1917,6 +1917,7 @@ public abstract class Entity implements ICommandListener { + } + + protected void o(Entity entity) { ++ if (entity == this) throw new IllegalArgumentException("Entities cannot become a passenger of themselves"); // Paper - issue 572 + if (entity.bB() != this) { + throw new IllegalStateException("Use x.startRiding(y), not y.addPassenger(x)"); + } else { +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0200-Enforce-Sync-Chunk-Unloads.patch b/Spigot-Server-Patches/0200-Enforce-Sync-Chunk-Unloads.patch deleted file mode 100644 index 62d8f26a3d..0000000000 --- a/Spigot-Server-Patches/0200-Enforce-Sync-Chunk-Unloads.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 2b343988be36223a17839d831ea5297856599981 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 7 Jan 2017 16:06:44 -0500 -Subject: [PATCH] Enforce Sync Chunk Unloads - -Unloading Chunks async is extremely dangerous. This will force it to main -the same way we handle async chunk loads. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index b4207470..b837a921 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -238,6 +238,7 @@ public class CraftWorld implements World { - } - - private boolean unloadChunk0(int x, int z, boolean save) { -+ Boolean result = MCUtil.ensureMain("Unload Chunk", () -> { // Paper - Ensure never async - net.minecraft.server.Chunk chunk = world.getChunkProviderServer().getChunkIfLoaded(x, z); - if (chunk == null) { - return true; -@@ -245,6 +246,7 @@ public class CraftWorld implements World { - - // If chunk had previously been queued to save, must do save to avoid loss of that data - return world.getChunkProviderServer().unloadChunk(chunk, chunk.mustSave || save); -+ }); return result != null ? result : false; // Paper - Ensure never async - } - - public boolean regenerateChunk(int x, int z) { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0201-Don-t-allow-entities-to-ride-themselves-572.patch b/Spigot-Server-Patches/0201-Don-t-allow-entities-to-ride-themselves-572.patch deleted file mode 100644 index 49ce781f7d..0000000000 --- a/Spigot-Server-Patches/0201-Don-t-allow-entities-to-ride-themselves-572.patch +++ /dev/null @@ -1,21 +0,0 @@ -From ae7ef20b19148e89f33b465fd8ff1dc210755dd6 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/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 1e295432..6fcced92 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -1917,6 +1917,7 @@ public abstract class Entity implements ICommandListener { - } - - protected void o(Entity entity) { -+ if (entity == this) throw new IllegalArgumentException("Entities cannot become a passenger of themselves"); // Paper - issue 572 - if (entity.bB() != this) { - throw new IllegalStateException("Use x.startRiding(y), not y.addPassenger(x)"); - } else { --- -2.12.2 - diff --git a/Spigot-Server-Patches/0201-Fix-block-break-desync.patch b/Spigot-Server-Patches/0201-Fix-block-break-desync.patch new file mode 100644 index 0000000000..2c441cefae --- /dev/null +++ b/Spigot-Server-Patches/0201-Fix-block-break-desync.patch @@ -0,0 +1,21 @@ +From b3d90b43866f0dbc59b6f35d3e0223776d228fb7 Mon Sep 17 00:00:00 2001 +From: Michael Himing +Date: Sun, 8 Jan 2017 18:50:35 +1100 +Subject: [PATCH] Fix block break desync + + +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 70af4ebbb..0e2f43b96 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -830,6 +830,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { + double d3 = d0 * d0 + d1 * d1 + d2 * d2; + + if (d3 > 36.0D) { ++ this.sendPacket(new PacketPlayOutBlockChange(worldserver, blockposition)); // Paper - Fix block break desync + return; + } else if (blockposition.getY() >= this.minecraftServer.getMaxBuildHeight()) { + return; +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0202-Assign-the-World-in-WorldGenStronghold.patch b/Spigot-Server-Patches/0202-Assign-the-World-in-WorldGenStronghold.patch new file mode 100644 index 0000000000..01d84ab7c8 --- /dev/null +++ b/Spigot-Server-Patches/0202-Assign-the-World-in-WorldGenStronghold.patch @@ -0,0 +1,21 @@ +From d87b02439ca632436aa045cadb984c0274c866c1 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 14 Jan 2017 01:22:07 -0600 +Subject: [PATCH] Assign the World in WorldGenStronghold + + +diff --git a/src/main/java/net/minecraft/server/WorldGenStronghold.java b/src/main/java/net/minecraft/server/WorldGenStronghold.java +index c93754704..a3b958e01 100644 +--- a/src/main/java/net/minecraft/server/WorldGenStronghold.java ++++ b/src/main/java/net/minecraft/server/WorldGenStronghold.java +@@ -56,6 +56,7 @@ public class WorldGenStronghold extends StructureGenerator { + } + + public BlockPosition getNearestGeneratedFeature(World world, BlockPosition blockposition, boolean flag) { ++ this.g = world; // Paper + if (!this.b) { + this.c(); + this.b = true; +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0202-Fix-block-break-desync.patch b/Spigot-Server-Patches/0202-Fix-block-break-desync.patch deleted file mode 100644 index a43a90eb20..0000000000 --- a/Spigot-Server-Patches/0202-Fix-block-break-desync.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 4455838df6bf9026d3ac21af134d2f7cf7d311a7 Mon Sep 17 00:00:00 2001 -From: Michael Himing -Date: Sun, 8 Jan 2017 18:50:35 +1100 -Subject: [PATCH] Fix block break desync - - -diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 70af4ebb..0e2f43b9 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -830,6 +830,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { - double d3 = d0 * d0 + d1 * d1 + d2 * d2; - - if (d3 > 36.0D) { -+ this.sendPacket(new PacketPlayOutBlockChange(worldserver, blockposition)); // Paper - Fix block break desync - return; - } else if (blockposition.getY() >= this.minecraftServer.getMaxBuildHeight()) { - return; --- -2.12.2 - diff --git a/Spigot-Server-Patches/0203-Add-fromBottle-flag-to-Experience-Orbs.patch b/Spigot-Server-Patches/0203-Add-fromBottle-flag-to-Experience-Orbs.patch new file mode 100644 index 0000000000..28c13b3003 --- /dev/null +++ b/Spigot-Server-Patches/0203-Add-fromBottle-flag-to-Experience-Orbs.patch @@ -0,0 +1,72 @@ +From a35b6a34e34c3e3ae1117ff6bef65b22385b8d5b Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 14 Jan 2017 16:15:26 -0600 +Subject: [PATCH] Add fromBottle flag to Experience Orbs + + +diff --git a/src/main/java/net/minecraft/server/EntityExperienceOrb.java b/src/main/java/net/minecraft/server/EntityExperienceOrb.java +index 14431b8ad..54c9200a9 100644 +--- a/src/main/java/net/minecraft/server/EntityExperienceOrb.java ++++ b/src/main/java/net/minecraft/server/EntityExperienceOrb.java +@@ -15,6 +15,14 @@ public class EntityExperienceOrb extends Entity { + public int value; + private EntityHuman targetPlayer; + private int targetTime; ++ // Paper start ++ private boolean fromBottle = false; ++ ++ public EntityExperienceOrb(World world, double d0, double d1, double d2, int i, boolean fromBottle) { ++ this(world, d0, d1, d2, i); ++ this.fromBottle = fromBottle; ++ } ++ // Paper end + + public EntityExperienceOrb(World world, double d0, double d1, double d2, int i) { + super(world); +@@ -27,6 +35,12 @@ public class EntityExperienceOrb extends Entity { + this.value = i; + } + ++ // Paper start ++ public boolean isFromBottle() { ++ return fromBottle; ++ } ++ // Paper end ++ + protected boolean playStepSound() { + return false; + } +diff --git a/src/main/java/net/minecraft/server/EntityThrownExpBottle.java b/src/main/java/net/minecraft/server/EntityThrownExpBottle.java +index 0255986fd..289312950 100644 +--- a/src/main/java/net/minecraft/server/EntityThrownExpBottle.java ++++ b/src/main/java/net/minecraft/server/EntityThrownExpBottle.java +@@ -40,7 +40,7 @@ public class EntityThrownExpBottle extends EntityProjectile { + 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, true)); // Paper - add fromBottle flag + } + + this.die(); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java +index 3a09cab3d..61e3c6c3e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java +@@ -18,6 +18,13 @@ public class CraftExperienceOrb extends CraftEntity implements ExperienceOrb { + getHandle().value = value; + } + ++ // Paper start ++ @Override ++ public boolean isFromBottle() { ++ return getHandle().isFromBottle(); ++ } ++ // Paper end ++ + @Override + public EntityExperienceOrb getHandle() { + return (EntityExperienceOrb) entity; +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0203-Assign-the-World-in-WorldGenStronghold.patch b/Spigot-Server-Patches/0203-Assign-the-World-in-WorldGenStronghold.patch deleted file mode 100644 index bbd74c79f5..0000000000 --- a/Spigot-Server-Patches/0203-Assign-the-World-in-WorldGenStronghold.patch +++ /dev/null @@ -1,21 +0,0 @@ -From ee446bce1a72c18ec83261e53a8536f72ffc2b5c Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 14 Jan 2017 01:22:07 -0600 -Subject: [PATCH] Assign the World in WorldGenStronghold - - -diff --git a/src/main/java/net/minecraft/server/WorldGenStronghold.java b/src/main/java/net/minecraft/server/WorldGenStronghold.java -index c9375470..a3b958e0 100644 ---- a/src/main/java/net/minecraft/server/WorldGenStronghold.java -+++ b/src/main/java/net/minecraft/server/WorldGenStronghold.java -@@ -56,6 +56,7 @@ public class WorldGenStronghold extends StructureGenerator { - } - - public BlockPosition getNearestGeneratedFeature(World world, BlockPosition blockposition, boolean flag) { -+ this.g = world; // Paper - if (!this.b) { - this.c(); - this.b = true; --- -2.12.2 - diff --git a/Spigot-Server-Patches/0204-Add-fromBottle-flag-to-Experience-Orbs.patch b/Spigot-Server-Patches/0204-Add-fromBottle-flag-to-Experience-Orbs.patch deleted file mode 100644 index 7d4b45fb22..0000000000 --- a/Spigot-Server-Patches/0204-Add-fromBottle-flag-to-Experience-Orbs.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 11f2e6a94b8554c5c3c40740b6931bcec25a59a4 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 14 Jan 2017 16:15:26 -0600 -Subject: [PATCH] Add fromBottle flag to Experience Orbs - - -diff --git a/src/main/java/net/minecraft/server/EntityExperienceOrb.java b/src/main/java/net/minecraft/server/EntityExperienceOrb.java -index 14431b8a..54c9200a 100644 ---- a/src/main/java/net/minecraft/server/EntityExperienceOrb.java -+++ b/src/main/java/net/minecraft/server/EntityExperienceOrb.java -@@ -15,6 +15,14 @@ public class EntityExperienceOrb extends Entity { - public int value; - private EntityHuman targetPlayer; - private int targetTime; -+ // Paper start -+ private boolean fromBottle = false; -+ -+ public EntityExperienceOrb(World world, double d0, double d1, double d2, int i, boolean fromBottle) { -+ this(world, d0, d1, d2, i); -+ this.fromBottle = fromBottle; -+ } -+ // Paper end - - public EntityExperienceOrb(World world, double d0, double d1, double d2, int i) { - super(world); -@@ -27,6 +35,12 @@ public class EntityExperienceOrb extends Entity { - this.value = i; - } - -+ // Paper start -+ public boolean isFromBottle() { -+ return fromBottle; -+ } -+ // Paper end -+ - protected boolean playStepSound() { - return false; - } -diff --git a/src/main/java/net/minecraft/server/EntityThrownExpBottle.java b/src/main/java/net/minecraft/server/EntityThrownExpBottle.java -index 0255986f..28931295 100644 ---- a/src/main/java/net/minecraft/server/EntityThrownExpBottle.java -+++ b/src/main/java/net/minecraft/server/EntityThrownExpBottle.java -@@ -40,7 +40,7 @@ public class EntityThrownExpBottle extends EntityProjectile { - 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, true)); // Paper - add fromBottle flag - } - - this.die(); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java -index 3a09cab3..61e3c6c3 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java -@@ -18,6 +18,13 @@ public class CraftExperienceOrb extends CraftEntity implements ExperienceOrb { - getHandle().value = value; - } - -+ // Paper start -+ @Override -+ public boolean isFromBottle() { -+ return getHandle().isFromBottle(); -+ } -+ // Paper end -+ - @Override - public EntityExperienceOrb getHandle() { - return (EntityExperienceOrb) entity; --- -2.12.2 - diff --git a/Spigot-Server-Patches/0204-Remove-the-Vanilla-Method-Profiler.patch b/Spigot-Server-Patches/0204-Remove-the-Vanilla-Method-Profiler.patch new file mode 100644 index 0000000000..1efc2bdca9 --- /dev/null +++ b/Spigot-Server-Patches/0204-Remove-the-Vanilla-Method-Profiler.patch @@ -0,0 +1,83 @@ +From c7306a084e0db72c5ecf0bae8d8463c69826e7f9 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 21 Jan 2017 02:00:33 -0500 +Subject: [PATCH] Remove the Vanilla Method Profiler + +Spigot rebrought this back after it was removed for years due to the performance hit. + +It is unknown if the JIT will optimize it out as effeciently with how it was +added, so we do not want any risk of performance degredation. + +Paper has a proper Timings system that makes the Vanilla Method profiler obsolete and inferior. + +diff --git a/src/main/java/net/minecraft/server/CommandDebug.java b/src/main/java/net/minecraft/server/CommandDebug.java +index fe58d428f..938f62f83 100644 +--- a/src/main/java/net/minecraft/server/CommandDebug.java ++++ b/src/main/java/net/minecraft/server/CommandDebug.java +@@ -33,12 +33,11 @@ public class CommandDebug extends CommandAbstract { + + public void execute(MinecraftServer minecraftserver, ICommandListener icommandlistener, String[] astring) throws CommandException { + // CraftBukkit start - only allow use when enabled (so that no blank profile results occur) +- if (!minecraftserver.methodProfiler.ENABLED) { +- icommandlistener.sendMessage(new ChatComponentText("Vanilla debug profiling is disabled.")); +- icommandlistener.sendMessage(new ChatComponentText("To enable, restart the server with `-DenableDebugMethodProfiler=true' before `-jar'.")); +- icommandlistener.sendMessage(new ChatComponentText("Use `/timings' for plugin timings.")); ++ if (true) { // Paper ++ icommandlistener.sendMessage(new ChatComponentText("Use `/timings report'")); // Paper + return; + } ++ /* + // CraftBukkit end + if (astring.length < 1) { + throw new ExceptionUsage("commands.debug.usage", new Object[0]); +@@ -144,7 +143,7 @@ public class CommandDebug extends CommandAbstract { + return astring[(int) (System.nanoTime() % (long) astring.length)]; + } catch (Throwable throwable) { + return "Witty comment unavailable :("; +- } ++ }*/ // Paper + } + + public List tabComplete(MinecraftServer minecraftserver, ICommandListener icommandlistener, String[] astring, @Nullable BlockPosition blockposition) { +diff --git a/src/main/java/net/minecraft/server/MethodProfiler.java b/src/main/java/net/minecraft/server/MethodProfiler.java +index 654652916..276983485 100644 +--- a/src/main/java/net/minecraft/server/MethodProfiler.java ++++ b/src/main/java/net/minecraft/server/MethodProfiler.java +@@ -9,8 +9,9 @@ import java.util.List; + import java.util.Map; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; +- +-public class MethodProfiler { ++// Paper - Remove this system - we have a more efficient Timings system ++/* ++class MethodProfiler { + + public static final boolean ENABLED = Boolean.getBoolean("enableDebugMethodProfiler"); // CraftBukkit - disable unless specified in JVM arguments + private static final Logger b = LogManager.getLogger(); +@@ -163,3 +164,22 @@ public class MethodProfiler { + } + } + } ++*/ ++ ++public class MethodProfiler { ++ public boolean a; ++ ++ MethodProfiler() {} ++ ++ public final void a() {} ++ ++ public final void a(String s) {} ++ ++ public final void b() {} ++ ++ public final void c(String s) {} ++ ++ public final String c() { ++ return null; ++ } ++} +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0205-Cap-Entity-Collisions.patch b/Spigot-Server-Patches/0205-Cap-Entity-Collisions.patch new file mode 100644 index 0000000000..f5d390b9c6 --- /dev/null +++ b/Spigot-Server-Patches/0205-Cap-Entity-Collisions.patch @@ -0,0 +1,60 @@ +From 3c00d6376d7fc8505bce90568180af8da00e2c13 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 61efcc479..4898e8bce 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -408,4 +408,10 @@ public class PaperWorldConfig { + private void armorStandEntityLookups() { + armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); + } ++ ++ 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/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 6fcced926..cfeff7c48 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -168,6 +168,7 @@ public abstract class Entity implements ICommandListener { + public final boolean defaultActivationState; + public long activatedTick = Integer.MIN_VALUE; + public boolean fromMobSpawner; ++ protected int numCollisions = 0; // Paper + public void inactiveTick() { } + // Spigot end + +diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java +index 7242da9cc..53486e205 100644 +--- a/src/main/java/net/minecraft/server/EntityLiving.java ++++ b/src/main/java/net/minecraft/server/EntityLiving.java +@@ -2132,8 +2132,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); + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0205-Remove-the-Vanilla-Method-Profiler.patch b/Spigot-Server-Patches/0205-Remove-the-Vanilla-Method-Profiler.patch deleted file mode 100644 index 24dcba73d0..0000000000 --- a/Spigot-Server-Patches/0205-Remove-the-Vanilla-Method-Profiler.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 6c4294e444a8a0bce3a404b84cd25388a2c3b25b Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 21 Jan 2017 02:00:33 -0500 -Subject: [PATCH] Remove the Vanilla Method Profiler - -Spigot rebrought this back after it was removed for years due to the performance hit. - -It is unknown if the JIT will optimize it out as effeciently with how it was -added, so we do not want any risk of performance degredation. - -Paper has a proper Timings system that makes the Vanilla Method profiler obsolete and inferior. - -diff --git a/src/main/java/net/minecraft/server/CommandDebug.java b/src/main/java/net/minecraft/server/CommandDebug.java -index fe58d428..938f62f8 100644 ---- a/src/main/java/net/minecraft/server/CommandDebug.java -+++ b/src/main/java/net/minecraft/server/CommandDebug.java -@@ -33,12 +33,11 @@ public class CommandDebug extends CommandAbstract { - - public void execute(MinecraftServer minecraftserver, ICommandListener icommandlistener, String[] astring) throws CommandException { - // CraftBukkit start - only allow use when enabled (so that no blank profile results occur) -- if (!minecraftserver.methodProfiler.ENABLED) { -- icommandlistener.sendMessage(new ChatComponentText("Vanilla debug profiling is disabled.")); -- icommandlistener.sendMessage(new ChatComponentText("To enable, restart the server with `-DenableDebugMethodProfiler=true' before `-jar'.")); -- icommandlistener.sendMessage(new ChatComponentText("Use `/timings' for plugin timings.")); -+ if (true) { // Paper -+ icommandlistener.sendMessage(new ChatComponentText("Use `/timings report'")); // Paper - return; - } -+ /* - // CraftBukkit end - if (astring.length < 1) { - throw new ExceptionUsage("commands.debug.usage", new Object[0]); -@@ -144,7 +143,7 @@ public class CommandDebug extends CommandAbstract { - return astring[(int) (System.nanoTime() % (long) astring.length)]; - } catch (Throwable throwable) { - return "Witty comment unavailable :("; -- } -+ }*/ // Paper - } - - public List tabComplete(MinecraftServer minecraftserver, ICommandListener icommandlistener, String[] astring, @Nullable BlockPosition blockposition) { -diff --git a/src/main/java/net/minecraft/server/MethodProfiler.java b/src/main/java/net/minecraft/server/MethodProfiler.java -index 65465291..27698348 100644 ---- a/src/main/java/net/minecraft/server/MethodProfiler.java -+++ b/src/main/java/net/minecraft/server/MethodProfiler.java -@@ -9,8 +9,9 @@ import java.util.List; - import java.util.Map; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -- --public class MethodProfiler { -+// Paper - Remove this system - we have a more efficient Timings system -+/* -+class MethodProfiler { - - public static final boolean ENABLED = Boolean.getBoolean("enableDebugMethodProfiler"); // CraftBukkit - disable unless specified in JVM arguments - private static final Logger b = LogManager.getLogger(); -@@ -163,3 +164,22 @@ public class MethodProfiler { - } - } - } -+*/ -+ -+public class MethodProfiler { -+ public boolean a; -+ -+ MethodProfiler() {} -+ -+ public final void a() {} -+ -+ public final void a(String s) {} -+ -+ public final void b() {} -+ -+ public final void c(String s) {} -+ -+ public final String c() { -+ return null; -+ } -+} --- -2.12.2 - diff --git a/Spigot-Server-Patches/0206-Cap-Entity-Collisions.patch b/Spigot-Server-Patches/0206-Cap-Entity-Collisions.patch deleted file mode 100644 index 03fbb17253..0000000000 --- a/Spigot-Server-Patches/0206-Cap-Entity-Collisions.patch +++ /dev/null @@ -1,60 +0,0 @@ -From f9ef38071405f1b311bf12dacd221d2b17fe298c 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 61efcc47..4898e8bc 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -408,4 +408,10 @@ public class PaperWorldConfig { - private void armorStandEntityLookups() { - armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); - } -+ -+ 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/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 6fcced92..cfeff7c4 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -168,6 +168,7 @@ public abstract class Entity implements ICommandListener { - public final boolean defaultActivationState; - public long activatedTick = Integer.MIN_VALUE; - public boolean fromMobSpawner; -+ protected int numCollisions = 0; // Paper - public void inactiveTick() { } - // Spigot end - -diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index 7242da9c..53486e20 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -2132,8 +2132,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); - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0206-Do-not-allow-a-zero-max-height-in-BiomeJungle.patch b/Spigot-Server-Patches/0206-Do-not-allow-a-zero-max-height-in-BiomeJungle.patch new file mode 100644 index 0000000000..d0447c4f8f --- /dev/null +++ b/Spigot-Server-Patches/0206-Do-not-allow-a-zero-max-height-in-BiomeJungle.patch @@ -0,0 +1,38 @@ +From 2ee2dc9a86f49234475babaaedbe77a8e738e1a5 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 23 Jan 2017 15:10:25 -0600 +Subject: [PATCH] Do not allow a zero max height in BiomeJungle + + +diff --git a/src/main/java/net/minecraft/server/BiomeJungle.java b/src/main/java/net/minecraft/server/BiomeJungle.java +index a4e5e4933..20c18cdbd 100644 +--- a/src/main/java/net/minecraft/server/BiomeJungle.java ++++ b/src/main/java/net/minecraft/server/BiomeJungle.java +@@ -39,7 +39,11 @@ public class BiomeJungle extends BiomeBase { + super.a(world, random, blockposition); + int i = random.nextInt(16) + 8; + int j = random.nextInt(16) + 8; +- int k = random.nextInt(world.getHighestBlockYAt(blockposition.a(i, 0, j)).getY() * 2); ++ // Paper start - Don't allow a 0 height ++ int height = world.getHighestBlockYAt(blockposition.add(i, 0, j)).getY() * 2; ++ if (height < 1) height = 1; ++ int k = random.nextInt(height); ++ // Paper end + + (new WorldGenMelon()).generate(world, random, blockposition.a(i, k, j)); + WorldGenVines worldgenvines = new WorldGenVines(); +diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java +index 6a0b3a62d..38a7af58c 100644 +--- a/src/main/java/net/minecraft/server/BlockPosition.java ++++ b/src/main/java/net/minecraft/server/BlockPosition.java +@@ -42,6 +42,7 @@ public class BlockPosition extends BaseBlockPosition { + this(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); + } + ++ public BlockPosition add(double x, double y, double z) { return this.a(x, y, z); } // Paper - OBFHELPER + public BlockPosition a(double d0, double d1, double d2) { + 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); + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0207-Do-not-allow-a-zero-max-height-in-BiomeJungle.patch b/Spigot-Server-Patches/0207-Do-not-allow-a-zero-max-height-in-BiomeJungle.patch deleted file mode 100644 index d3484f0d31..0000000000 --- a/Spigot-Server-Patches/0207-Do-not-allow-a-zero-max-height-in-BiomeJungle.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 058a0cb81978b5cf20cc32ab63e81de4b1a0f63c Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 23 Jan 2017 15:10:25 -0600 -Subject: [PATCH] Do not allow a zero max height in BiomeJungle - - -diff --git a/src/main/java/net/minecraft/server/BiomeJungle.java b/src/main/java/net/minecraft/server/BiomeJungle.java -index a4e5e493..20c18cdb 100644 ---- a/src/main/java/net/minecraft/server/BiomeJungle.java -+++ b/src/main/java/net/minecraft/server/BiomeJungle.java -@@ -39,7 +39,11 @@ public class BiomeJungle extends BiomeBase { - super.a(world, random, blockposition); - int i = random.nextInt(16) + 8; - int j = random.nextInt(16) + 8; -- int k = random.nextInt(world.getHighestBlockYAt(blockposition.a(i, 0, j)).getY() * 2); -+ // Paper start - Don't allow a 0 height -+ int height = world.getHighestBlockYAt(blockposition.add(i, 0, j)).getY() * 2; -+ if (height < 1) height = 1; -+ int k = random.nextInt(height); -+ // Paper end - - (new WorldGenMelon()).generate(world, random, blockposition.a(i, k, j)); - WorldGenVines worldgenvines = new WorldGenVines(); -diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java -index 6a0b3a62..38a7af58 100644 ---- a/src/main/java/net/minecraft/server/BlockPosition.java -+++ b/src/main/java/net/minecraft/server/BlockPosition.java -@@ -42,6 +42,7 @@ public class BlockPosition extends BaseBlockPosition { - this(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); - } - -+ public BlockPosition add(double x, double y, double z) { return this.a(x, y, z); } // Paper - OBFHELPER - public BlockPosition a(double d0, double d1, double d2) { - 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); - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0207-Remove-CraftScheduler-Async-Task-Debugger.patch b/Spigot-Server-Patches/0207-Remove-CraftScheduler-Async-Task-Debugger.patch new file mode 100644 index 0000000000..e4d9028f28 --- /dev/null +++ b/Spigot-Server-Patches/0207-Remove-CraftScheduler-Async-Task-Debugger.patch @@ -0,0 +1,62 @@ +From bc4620bc17988c0b738d7a19641dff1a42f38458 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 e30cfb7b7..448c27cc7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -80,8 +80,8 @@ public class CraftScheduler implements BukkitScheduler { + private final ConcurrentHashMap runners = new ConcurrentHashMap(); + private volatile int currentTick = -1; + private final Executor executor = Executors.newCachedThreadPool(new com.google.common.util.concurrent.ThreadFactoryBuilder().setNameFormat("Craft Scheduler Thread - %1$d").build()); // Spigot +- private CraftAsyncDebugger debugHead = new CraftAsyncDebugger(-1, null, null) {@Override StringBuilder debugTo(StringBuilder string) {return string;}}; +- private CraftAsyncDebugger debugTail = debugHead; ++ //private CraftAsyncDebugger debugHead = new CraftAsyncDebugger(-1, null, null) {@Override StringBuilder debugTo(StringBuilder string) {return string;}}; // Paper ++ //private CraftAsyncDebugger debugTail = debugHead; // Paper + private static final int RECENT_TICKS; + + static { +@@ -371,7 +371,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) +@@ -388,7 +388,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) { +@@ -447,10 +447,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 +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0208-Remove-CraftScheduler-Async-Task-Debugger.patch b/Spigot-Server-Patches/0208-Remove-CraftScheduler-Async-Task-Debugger.patch deleted file mode 100644 index a8990f0cd5..0000000000 --- a/Spigot-Server-Patches/0208-Remove-CraftScheduler-Async-Task-Debugger.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 3e17aa98688af91237bb7e386a5846e55d6a1aed 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 e30cfb7b..448c27cc 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -80,8 +80,8 @@ public class CraftScheduler implements BukkitScheduler { - private final ConcurrentHashMap runners = new ConcurrentHashMap(); - private volatile int currentTick = -1; - private final Executor executor = Executors.newCachedThreadPool(new com.google.common.util.concurrent.ThreadFactoryBuilder().setNameFormat("Craft Scheduler Thread - %1$d").build()); // Spigot -- private CraftAsyncDebugger debugHead = new CraftAsyncDebugger(-1, null, null) {@Override StringBuilder debugTo(StringBuilder string) {return string;}}; -- private CraftAsyncDebugger debugTail = debugHead; -+ //private CraftAsyncDebugger debugHead = new CraftAsyncDebugger(-1, null, null) {@Override StringBuilder debugTo(StringBuilder string) {return string;}}; // Paper -+ //private CraftAsyncDebugger debugTail = debugHead; // Paper - private static final int RECENT_TICKS; - - static { -@@ -371,7 +371,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) -@@ -388,7 +388,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) { -@@ -447,10 +447,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 --- -2.12.2 - diff --git a/Spigot-Server-Patches/0208-Shame-on-you-Mojang.patch b/Spigot-Server-Patches/0208-Shame-on-you-Mojang.patch new file mode 100644 index 0000000000..a4af73cbb9 --- /dev/null +++ b/Spigot-Server-Patches/0208-Shame-on-you-Mojang.patch @@ -0,0 +1,59 @@ +From 5659da37e2d30e64da7f749817355ad96899a4a8 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 5 Feb 2017 19:17:28 -0500 +Subject: [PATCH] Shame on you Mojang + +Someone wrote some horrible code that throws a world accessing task +onto the HTTP DOWNLOADER Thread Pool, for an activity that is not even +heavy enough to warrant async operation. + +This then triggers async chunk loads! + +What in the hell were you thinking? + +diff --git a/src/main/java/net/minecraft/server/BlockBeacon.java b/src/main/java/net/minecraft/server/BlockBeacon.java +index f44f05620..74c371179 100644 +--- a/src/main/java/net/minecraft/server/BlockBeacon.java ++++ b/src/main/java/net/minecraft/server/BlockBeacon.java +@@ -62,8 +62,8 @@ public class BlockBeacon extends BlockTileEntity { + } + + public static void c(final World world, final BlockPosition blockposition) { +- HttpUtilities.a.submit(new Runnable() { +- public void run() { ++ /*HttpUtilities.a.submit(new Runnable() { ++ public void run() {*/ // Paper + Chunk chunk = world.getChunkAtWorldCoords(blockposition); + + for (int i = blockposition.getY() - 1; i >= 0; --i) { +@@ -76,8 +76,8 @@ public class BlockBeacon extends BlockTileEntity { + IBlockData iblockdata = world.getType(blockposition1); + + if (iblockdata.getBlock() == Blocks.BEACON) { +- ((WorldServer) world).postToMainThread(new Runnable() { +- public void run() { ++ /*((WorldServer) world).postToMainThread(new Runnable() { ++ public void run() {*/ // Paper + TileEntity tileentity = world.getTileEntity(blockposition); + + if (tileentity instanceof TileEntityBeacon) { +@@ -85,12 +85,12 @@ public class BlockBeacon extends BlockTileEntity { + world.playBlockAction(blockposition, Blocks.BEACON, 1, 0); + } + +- } +- }); ++ /*} ++ });*/ // Paper + } + } + +- } +- }); ++ /*} ++ });*/ // Paper + } + } +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0209-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch b/Spigot-Server-Patches/0209-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch new file mode 100644 index 0000000000..66407fb849 --- /dev/null +++ b/Spigot-Server-Patches/0209-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch @@ -0,0 +1,22 @@ +From 4781c61848dc79486a9eb366c01b27c40c26a15b 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/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java +index dabe4137f..fb4f11958 100644 +--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java +@@ -325,7 +325,7 @@ public class ChunkProviderServer implements IChunkProvider { + // 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 + + Iterator iterator = this.unloadQueue.iterator(); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0209-Shame-on-you-Mojang.patch b/Spigot-Server-Patches/0209-Shame-on-you-Mojang.patch deleted file mode 100644 index bf7412685d..0000000000 --- a/Spigot-Server-Patches/0209-Shame-on-you-Mojang.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 6e834104fb58905edaea685fe77342ccc26bd5eb Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 5 Feb 2017 19:17:28 -0500 -Subject: [PATCH] Shame on you Mojang - -Someone wrote some horrible code that throws a world accessing task -onto the HTTP DOWNLOADER Thread Pool, for an activity that is not even -heavy enough to warrant async operation. - -This then triggers async chunk loads! - -What in the hell were you thinking? - -diff --git a/src/main/java/net/minecraft/server/BlockBeacon.java b/src/main/java/net/minecraft/server/BlockBeacon.java -index f44f0562..74c37117 100644 ---- a/src/main/java/net/minecraft/server/BlockBeacon.java -+++ b/src/main/java/net/minecraft/server/BlockBeacon.java -@@ -62,8 +62,8 @@ public class BlockBeacon extends BlockTileEntity { - } - - public static void c(final World world, final BlockPosition blockposition) { -- HttpUtilities.a.submit(new Runnable() { -- public void run() { -+ /*HttpUtilities.a.submit(new Runnable() { -+ public void run() {*/ // Paper - Chunk chunk = world.getChunkAtWorldCoords(blockposition); - - for (int i = blockposition.getY() - 1; i >= 0; --i) { -@@ -76,8 +76,8 @@ public class BlockBeacon extends BlockTileEntity { - IBlockData iblockdata = world.getType(blockposition1); - - if (iblockdata.getBlock() == Blocks.BEACON) { -- ((WorldServer) world).postToMainThread(new Runnable() { -- public void run() { -+ /*((WorldServer) world).postToMainThread(new Runnable() { -+ public void run() {*/ // Paper - TileEntity tileentity = world.getTileEntity(blockposition); - - if (tileentity instanceof TileEntityBeacon) { -@@ -85,12 +85,12 @@ public class BlockBeacon extends BlockTileEntity { - world.playBlockAction(blockposition, Blocks.BEACON, 1, 0); - } - -- } -- }); -+ /*} -+ });*/ // Paper - } - } - -- } -- }); -+ /*} -+ });*/ // Paper - } - } --- -2.12.2 - diff --git a/Spigot-Server-Patches/0210-Do-not-let-armorstands-drown.patch b/Spigot-Server-Patches/0210-Do-not-let-armorstands-drown.patch new file mode 100644 index 0000000000..535d0070da --- /dev/null +++ b/Spigot-Server-Patches/0210-Do-not-let-armorstands-drown.patch @@ -0,0 +1,45 @@ +From e3e92ddb40f19cb76fd012b57ad8388526bc5972 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/server/EntityArmorStand.java b/src/main/java/net/minecraft/server/EntityArmorStand.java +index 7738ca385..5818aa5e9 100644 +--- a/src/main/java/net/minecraft/server/EntityArmorStand.java ++++ b/src/main/java/net/minecraft/server/EntityArmorStand.java +@@ -772,5 +772,10 @@ public class EntityArmorStand extends EntityLiving { + super.move(moveType, x, y, z); + } + } ++ ++ @Override ++ public boolean canBreatheUnderwater() { // Skips a bit of damage handling code, probably a micro-optimization ++ return true; ++ } + // Paper end + } +diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java +index 53486e205..9b7159450 100644 +--- a/src/main/java/net/minecraft/server/EntityLiving.java ++++ b/src/main/java/net/minecraft/server/EntityLiving.java +@@ -188,6 +188,7 @@ public abstract class EntityLiving extends Entity { + super.a(d0, flag, iblockdata, blockposition); + } + ++ public boolean canBreatheUnderwater() { return this.bF(); } // Paper - OBFHELPER + public boolean bF() { + return false; + } +@@ -222,7 +223,7 @@ public abstract class EntityLiving extends Entity { + + if (this.isAlive()) { + if (this.a(Material.WATER)) { +- if (!this.bF() && !this.hasEffect(MobEffects.WATER_BREATHING) && !flag1) { ++ if (!this.canBreatheUnderwater() && !this.hasEffect(MobEffects.WATER_BREATHING) && !flag1) { // Paper - Use obfhelper + this.setAirTicks(this.d(this.getAirTicks())); + if (this.getAirTicks() == -20) { + this.setAirTicks(0); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0210-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch b/Spigot-Server-Patches/0210-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch deleted file mode 100644 index 9f403f809a..0000000000 --- a/Spigot-Server-Patches/0210-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch +++ /dev/null @@ -1,22 +0,0 @@ -From d9a36a3de6454128f14ae7c8f154e00b17cb3d89 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/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java -index 7006466b..c32fb3ef 100644 ---- a/src/main/java/net/minecraft/server/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java -@@ -325,7 +325,7 @@ public class ChunkProviderServer implements IChunkProvider { - // 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 - - Iterator iterator = this.unloadQueue.iterator(); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0211-Do-not-let-armorstands-drown.patch b/Spigot-Server-Patches/0211-Do-not-let-armorstands-drown.patch deleted file mode 100644 index 99630f47d9..0000000000 --- a/Spigot-Server-Patches/0211-Do-not-let-armorstands-drown.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 67b246c935f33eacd625d35e7d16d2f3dcf5f1dc 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/server/EntityArmorStand.java b/src/main/java/net/minecraft/server/EntityArmorStand.java -index 7738ca38..5818aa5e 100644 ---- a/src/main/java/net/minecraft/server/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/server/EntityArmorStand.java -@@ -772,5 +772,10 @@ public class EntityArmorStand extends EntityLiving { - super.move(moveType, x, y, z); - } - } -+ -+ @Override -+ public boolean canBreatheUnderwater() { // Skips a bit of damage handling code, probably a micro-optimization -+ return true; -+ } - // Paper end - } -diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index 53486e20..9b715945 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -188,6 +188,7 @@ public abstract class EntityLiving extends Entity { - super.a(d0, flag, iblockdata, blockposition); - } - -+ public boolean canBreatheUnderwater() { return this.bF(); } // Paper - OBFHELPER - public boolean bF() { - return false; - } -@@ -222,7 +223,7 @@ public abstract class EntityLiving extends Entity { - - if (this.isAlive()) { - if (this.a(Material.WATER)) { -- if (!this.bF() && !this.hasEffect(MobEffects.WATER_BREATHING) && !flag1) { -+ if (!this.canBreatheUnderwater() && !this.hasEffect(MobEffects.WATER_BREATHING) && !flag1) { // Paper - Use obfhelper - this.setAirTicks(this.d(this.getAirTicks())); - if (this.getAirTicks() == -20) { - this.setAirTicks(0); --- -2.12.2 - diff --git a/Spigot-Server-Patches/0211-Fix-NFE-when-attempting-to-read-EMPTY-ItemStack.patch b/Spigot-Server-Patches/0211-Fix-NFE-when-attempting-to-read-EMPTY-ItemStack.patch new file mode 100644 index 0000000000..1e1f885743 --- /dev/null +++ b/Spigot-Server-Patches/0211-Fix-NFE-when-attempting-to-read-EMPTY-ItemStack.patch @@ -0,0 +1,23 @@ +From 409d9321d3f2a0e641c01c82db43c5c0c719f3dc Mon Sep 17 00:00:00 2001 +From: kashike +Date: Sun, 9 Apr 2017 23:50:15 -0700 +Subject: [PATCH] Fix NFE when attempting to read EMPTY ItemStack + +Thanks @gabizou + +diff --git a/src/main/java/net/minecraft/server/ItemStack.java b/src/main/java/net/minecraft/server/ItemStack.java +index 548da18e0..29902769f 100644 +--- a/src/main/java/net/minecraft/server/ItemStack.java ++++ b/src/main/java/net/minecraft/server/ItemStack.java +@@ -97,7 +97,7 @@ public final class ItemStack { + + // CraftBukkit - break into own method + public void load(NBTTagCompound nbttagcompound) { +- this.item = Item.b(nbttagcompound.getString("id")); ++ this.item = nbttagcompound.hasKeyOfType("id", 8) ? Item.b(nbttagcompound.getString("id")) : Item.getItemOf(Blocks.AIR); // Paper - fix NumberFormatException caused by attempting to read an EMPTY ItemStack + this.count = nbttagcompound.getByte("Count"); + // CraftBukkit start - Route through setData for filtering + // this.damage = Math.max(0, nbttagcompound.getShort("Damage")); +-- +2.12.2.windows.2 + diff --git a/Spigot-Server-Patches/0212-Fix-NFE-when-attempting-to-read-EMPTY-ItemStack.patch b/Spigot-Server-Patches/0212-Fix-NFE-when-attempting-to-read-EMPTY-ItemStack.patch deleted file mode 100644 index 285b70e149..0000000000 --- a/Spigot-Server-Patches/0212-Fix-NFE-when-attempting-to-read-EMPTY-ItemStack.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 2f6bff5870596a421be90ada961ce01b515e9089 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Sun, 9 Apr 2017 23:50:15 -0700 -Subject: [PATCH] Fix NFE when attempting to read EMPTY ItemStack - -Thanks @gabizou - -diff --git a/src/main/java/net/minecraft/server/ItemStack.java b/src/main/java/net/minecraft/server/ItemStack.java -index 45ebd3f6..cf204f41 100644 ---- a/src/main/java/net/minecraft/server/ItemStack.java -+++ b/src/main/java/net/minecraft/server/ItemStack.java -@@ -97,7 +97,7 @@ public final class ItemStack { - - // CraftBukkit - break into own method - public void load(NBTTagCompound nbttagcompound) { -- this.item = Item.b(nbttagcompound.getString("id")); -+ this.item = nbttagcompound.hasKeyOfType("id", 8) ? Item.b(nbttagcompound.getString("id")) : Item.getItemOf(Blocks.AIR); // Paper - fix NumberFormatException caused by attempting to read an EMPTY ItemStack - this.count = nbttagcompound.getByte("Count"); - // CraftBukkit start - Route through setData for filtering - // this.damage = Math.max(0, nbttagcompound.getShort("Damage")); --- -2.12.2 - -- cgit v1.2.3