From e7f3ca4505d8bd36815a724acc5709edc71fead6 Mon Sep 17 00:00:00 2001 From: Zach Brown <1254957+zachbr@users.noreply.github.com> Date: Mon, 21 Jul 2014 15:46:54 -0500 Subject: [PATCH] Restructure PaperSpigot as a new set of modules Allows us much greater control over the Spigot portion of the code and makes us more "proper" Credit to @Dmck2b for originally passing the idea along a while back --- .gitignore | 2 + .gitmodules | 4 +- Bukkit | 2 +- Bukkit-Patches/0001-POM-Changes.patch | 64 + Bukkit-Patches/0002-Spigot-Timings.patch | 461 ++ .../0003-Add-PlayerItemDamageEvent.patch | 67 + Bukkit-Patches/0004-BungeeCord-Support.patch | 101 + Bukkit-Patches/0005-Add-Arrow-API.patch | 32 + Bukkit-Patches/0006-Add-Particle-API.patch | 362 ++ ...titySpawnEvent-and-SpawnerSpawnEvent.patch | 218 + ...008-Entity-Mount-and-Dismount-Events.patch | 110 + Bukkit-Patches/0009-Update-Depends.patch | 46 + ...entoryClickEvent-getClickedInventory.patch | 52 + ...lSessionData-to-the-Conversation-API.patch | 26 + .../0012-Catch-Conversation-API-Errors.patch | 32 + .../0013-Player-Collision-API.patch | 39 + .../0014-Expand-Boolean-Prompt-Values.patch | 26 + ...dd-Getter-for-Entity-Invulnerability.patch | 34 + Bukkit-Patches/0016-Add-respawn-API.patch | 26 + ...7-Fix-Plugin-Message-API-Disconnects.patch | 28 + ...Fix-Tab-Completion-for-Some-Commands.patch | 83 + Bukkit-Patches/0019-Add-Spigot-Links.patch | 27 + ...-Implement-Locale-Getter-for-Players.patch | 28 + ...-support-for-fetching-hidden-players.patch | 28 + .../0022-Silenceable-Lightning-API.patch | 68 + ...cation-on-some-player-lookup-methods.patch | 77 + ...-team-API-to-allow-arbitrary-strings.patch | 73 + .../0025-Add-Score.isScoreSet-Z-API.patch | 29 + .../0026-Add-PlayerSpawnLocationEvent.patch | 63 + ...ClassLoader-Deadlocks-Where-Possible.patch | 62 + CraftBukkit | 2 +- CraftBukkit-Patches/0001-POM-Changes.patch | 169 + .../0001-Rename-to-PaperSpigot.patch | 29 - CraftBukkit-Patches/0002-mc-dev-imports.patch | 3709 +++++++++++++++++ .../0003-Skeleton-API-Implementations.patch | 87 + .../0004-Obfuscation-Helpers.patch | 25 + .../0005-Spigot-Configuration.patch | 312 ++ .../0006-Better-Chunk-Tick-Selection.patch | 181 + .../0007-Crop-Growth-Rates.patch | 175 + ...0008-More-Efficient-Chunk-Save-Queue.patch | 99 + .../0009-Merge-tweaks-and-configuration.patch | 94 + .../0010-LongHash-Tweaks.patch | 223 + .../0011-Async-Operation-Catching.patch | 171 + CraftBukkit-Patches/0012-View-Distance.patch | 53 + CraftBukkit-Patches/0013-Spigot-Timings.patch | 863 ++++ ...b-Spawning-Relative-to-View-Distance.patch | 156 + .../0015-Handle-Null-Tile-Entities.patch | 25 + .../0016-Entity-Activation-Range.patch | 520 +++ CraftBukkit-Patches/0017-Metrics.patch | 690 +++ .../0018-PlayerItemDamageEvent.patch | 43 + .../0019-Faster-UUID-for-entities.patch | 21 + .../0020-Prevent-NPE-in-CraftSign.patch | 34 + .../0021-Entity-Tracking-Ranges.patch | 107 + .../0022-Limit-Custom-Map-Rendering.patch | 72 + .../0023-Thread-Naming-and-Tweaks.patch | 21 + .../0024-Close-Unloaded-Save-Files.patch | 64 + .../0025-Remove-o-Option.patch | 21 + .../0026-Recipe-Deconstruction.patch | 69 + .../0027-Implement-Arrow-API.patch | 29 + .../0028-Hopper-Customisations.patch | 131 + .../0029-Prevent-Shutdown-Hang.patch | 30 + .../0030-Implement-SpawnerSpawnEvent.patch | 100 + .../0031-Firework-Meta-Crash-Fix.patch | 29 + ...2-Allow-Disabling-of-Command-Logging.patch | 35 + ...low-Disabling-of-Command-TabComplete.patch | 51 + .../0034-Configurable-Messages.patch | 105 + ...Disabling-of-Random-Lighting-Updates.patch | 49 + .../0036-Properly-Close-Inventories.patch | 61 + .../0037-Disallow-Interaction-With-Self.patch | 25 + .../0038-Lower-Chunk-Compression.patch | 34 + ...039-Entity-Mount-and-Dismount-Events.patch | 49 + ...vent-Ghost-Players-Caused-by-Plugins.patch | 24 + .../0041-Plug-World-Unload-Memory-Leak.patch | 20 + .../0042-Player-Collision-API.patch | 83 + ...ly-Disable-Snooper-When-Not-Required.patch | 25 + ...dd-Getter-for-Entity-Invulnerability.patch | 23 + .../0045-Cap-Minimum-Player-Speed.patch | 29 + ...-and-Health-for-PlayerConsumeItemEve.patch | 22 + ...eBlockEvent-for-Fire-Arrows-hitting-.patch | 33 + ...-Disabling-of-1.6.3-Structure-Saving.patch | 48 + .../0049-Item-Despawn-Rate.patch | 36 + ...0050-Don-t-Special-Case-X-Move-Value.patch | 47 + .../0051-Implement-respawn-API.patch | 27 + ...x-BrewingStands-Removing-NBT-Potions.patch | 26 + .../0053-Arrow-Despawn-Rate.patch | 36 + .../0054-Fix-packed-ice-generation.patch | 36 + .../0055-Watchdog-Thread.patch | 303 ++ .../0056-Clear-Flower-Pot-on-Drop.patch | 19 + ...-chunks-not-being-sent-to-the-client.patch | 28 + .../0058-Fix-Broken-Async-Chat.patch | 38 + ...portation-of-Vehicles-and-Passengers.patch | 38 + ...Remove-OS-X-Special-Chars-from-Signs.patch | 19 + CraftBukkit-Patches/0061-Orebfuscator.patch | 429 ++ .../0062-Optimize-DataWatcher.patch | 132 + ...Fire-PreLogin-Events-in-Offline-Mode.patch | 157 + .../0064-BungeeCord-Support.patch | 213 + ...Disabling-Zombie-Villager-Aggression.patch | 46 + ...Configurable-Amount-of-Netty-Threads.patch | 55 + .../0067-Prevent-Mineshaft-Saving.patch | 20 + ...8-Log-Cause-of-Unexpected-Exceptions.patch | 24 + CraftBukkit-Patches/0069-Particle-API.patch | 173 + .../0070-Fix-Biome-Decoration-Crashes.patch | 109 + .../0071-Save-ticks-lived-to-nbttag.patch | 28 + .../0072-More-Efficient-GetCubes.patch | 66 + ...d-Option-to-Nerf-Mobs-from-Spawner-s.patch | 82 + ...-Warn-if-PermGen-may-be-insufficient.patch | 34 + ...ble-Connected-Check-on-setScoreboard.patch | 20 + .../0076-Add-Late-Bind-Option.patch | 59 + ...low-statistics-to-be-disabled-forced.patch | 91 + .../0078-Fix-anvil-collisions.patch | 27 + .../0079-Fix-ItemStack-Unbreakable-Code.patch | 26 + ...Try-and-Debug-Crash-Reports-Crashing.patch | 39 + .../0081-Replace-AutoSave-Mechanism.patch | 30 + ...ck-data-values-that-crash-the-client.patch | 59 + ...vanilla-s-direction-tag-on-fireballs.patch | 34 + .../0084-Support-non-prefixed-URLs.patch | 39 + ...ing-on-corrupted-map-data-NBT-arrays.patch | 31 + ...f-ZombiePigmen-spawning-in-portal-bl.patch | 36 + .../0087-Highly-Optimized-Tick-Loop.patch | 163 + .../0088-Add-Spigot-Links.patch | 77 + .../0089-Configurable-Ping-Sample-Size.patch | 41 + .../0090-Add-Optional-Tick-Shuffling.patch | 41 + ...-Allow-Configuring-Chunks-per-Packet.patch | 36 + ...-Implement-Locale-Getter-for-Players.patch | 37 + .../0093-Cap-Entity-Collisions.patch | 64 + ...one-meal-not-having-the-correct-data.patch | 20 + .../0095-Spam-Filter-Exclusions.patch | 58 + ...tion-to-Silence-CommandBlock-Console.patch | 35 + ...-support-for-fetching-hidden-players.patch | 30 + ...Allow-Disabling-Creative-Item-Filter.patch | 35 + .../0099-Cap-Channel-Registrations.patch | 19 + ...mmands-to-be-the-main-version-of-a-c.patch | 172 + ...-the-isDisconnected-method-by-bukkit.patch | 21 + ...-Implement-Silenceable-Lightning-API.patch | 103 + ...rmissibleBase-for-all-Command-Blocks.patch | 31 + ...-Prevent-hoppers-from-loading-chunks.patch | 19 + .../0105-Guard-Entity-List.patch | 77 + ...dificationException-while-being-idle.patch | 52 + ...ancellable-WitherSkull-potion-effect.patch | 34 + ...riptive-kick-reasons-instead-of-Nope.patch | 51 + ...ly-prefixed-commands-or-commands-tha.patch | 27 + ...-names-to-prevent-client-disconnects.patch | 19 + .../0111-Enable-Improved-Ping-Sending.patch | 63 + ...dragon-death-and-wither-spawn-sounds.patch | 52 + ...n-client-crashes-server-lists-and-Mo.patch | 21 + .../0114-Old-New-Version-Support.patch | 244 ++ .../0115-Treat-Bungee-as-Online-Mode.patch | 20 + ...ix-several-occurances-of-missed-diff.patch | 75 + ...ent-not-properly-cancelling.-Fixes-B.patch | 57 + CraftBukkit-Patches/0118-Update-Warning.patch | 55 + .../0119-Add-Conversion-Message.patch | 19 + ...cel-fishing-event.-Fixes-BUKKIT-5396.patch | 24 + ...121-Print-Stack-on-InternalException.patch | 19 + ...Offline-Player-Data-Once-if-Required.patch | 41 + ...ase-for-Non-Existent-Offline-Players.patch | 20 + ...-Check-for-blank-OfflinePlayer-Names.patch | 19 + .../0125-Fix-Player-Banning.patch | 47 + .../0126-Fix-ban-expire-dates.patch | 20 + .../0127-Correct-Ban-Expiration.patch | 20 + .../0128-Convert-Horses-owner-to-UUID.patch | 26 + ...-team-API-to-allow-arbitrary-strings.patch | 86 + .../0130-Add-Score.isScoreSet-Z-API.patch | 37 + .../0131-Log-null-TileEntity-Owner.patch | 27 + ...ial-case-invalid-usernames-for-UUIDs.patch | 23 + .../0133-Convert-player-skulls-async.patch | 123 + ...ssDefError-crash-and-notify-on-crash.patch | 48 + .../0135-Check-Skull-canPlace.patch | 24 + ...36-Don-t-let-trees-replace-any-block.patch | 25 + ...on-that-could-kill-connections-befor.patch | 61 + .../0138-Configurable-UserCache-cap.patch | 35 + ...9-Implement-PlayerSpawnLocationEvent.patch | 39 + .../0140-Cap-Objective-Score-Length.patch | 20 + ...tion-input-on-the-main-thread.-Fixes.patch | 39 + ...able-save-on-stop-only-for-UserCache.patch | 53 + ...43-Prevent-Unbounded-IntCache-Growth.patch | 60 + .../0144-Alternative-Hopper-Ticking.patch | 500 +++ ...ons-not-moving-invulnerable-entities.patch | 23 + ...6-Add-damager-to-the-unhandled-error.patch | 20 + ...d-Fireball-EntityDamageByEntityEvent.patch | 20 + ...148-Cross-World-Entity-Teleportation.patch | 28 + ...-block-placement-interaction-packets.patch | 54 + .../0150-Better-item-validation.patch | 113 + .../0151-Further-Seed-Customisation.patch | 52 + .../0152-Disable-ResourceLeakDetector.patch | 20 + ...e-Information-to-session.lock-Errors.patch | 36 + .../0154-Safer-JSON-Loading.patch | 45 + .../0155-Fix-Slow-Loading-Libraries.patch | 30 + .../0156-Add-CommandLine-EULA-Flag.patch | 32 + ...misnamed-function-from-1.7.10-update.patch | 20 + ...ng-table-wiping-meta-when-placing-st.patch | 25 + ...s-ocelots-when-plugins-spawn-ocelots.patch | 45 + ...Prevent-a-crash-involving-attributes.patch | 28 + CraftBukkit-Patches/0161-Fix-IP-banning.patch | 20 + .../Add-float-methods-to-configs.patch | 0 Spigot-API-Patches/POM-changes.patch | 36 + .../Ability-to-disable-asynccatcher.patch | 0 .../Add-1.8-recipes-for-stone-variants.patch | 0 ...-despawn-distances-for-living-entiti.patch | 0 .../Allow-for-toggling-of-spawn-chunks.patch | 0 .../Allow-nerfed-mobs-to-jump.patch | 0 ...low-undead-horse-types-to-be-leashed.patch | 0 .../Better-EULA-handling.patch | 0 ...onfigurable-AI-target-selector-delay.patch | 0 ...figurable-baby-zombie-movement-speed.patch | 0 ...ctus-and-reed-natural-growth-heights.patch | 0 ...e-damage-multiplier-for-PvP-blocking.patch | 0 .../Configurable-fishing-time-ranges.patch | 0 .../Configurable-nerf-for-TNT-cannons.patch | 0 .../Configurable-squid-spawn-ranges.patch | 0 ...Do-not-remove-player-in-world-change.patch | 0 .../Don-t-tick-chests.patch | 0 .../Fix-Null-Tile-Entity-Worlds.patch | 0 .../Fix-directional-TNT-bias.patch | 0 .../Fix-redstone-lag-issues.patch | 0 ...bie-sieges-and-their-spawn-mechanics.patch | 0 .../Inverted-Daylight-Detector-Toggle.patch | 0 .../Invisible-players-don-t-have-rights.patch | 0 ...e-destroyed-boats-drop-the-boat-item.patch | 0 Spigot-Server-Patches/POM-changes.patch | 59 + .../PaperSpigot-config-files.patch | 0 .../Player-Exhaustion-Multipliers.patch | 0 ...leport-passenger-vehicle-with-player.patch | 0 .../Toggle-for-player-interact-limiter.patch | 0 applyPatches.sh | 8 +- pom.xml | 14 +- rebuildPatches.sh | 2 + 226 files changed, 18045 insertions(+), 41 deletions(-) create mode 100644 Bukkit-Patches/0001-POM-Changes.patch create mode 100644 Bukkit-Patches/0002-Spigot-Timings.patch create mode 100644 Bukkit-Patches/0003-Add-PlayerItemDamageEvent.patch create mode 100644 Bukkit-Patches/0004-BungeeCord-Support.patch create mode 100644 Bukkit-Patches/0005-Add-Arrow-API.patch create mode 100644 Bukkit-Patches/0006-Add-Particle-API.patch create mode 100644 Bukkit-Patches/0007-Define-EntitySpawnEvent-and-SpawnerSpawnEvent.patch create mode 100644 Bukkit-Patches/0008-Entity-Mount-and-Dismount-Events.patch create mode 100644 Bukkit-Patches/0009-Update-Depends.patch create mode 100644 Bukkit-Patches/0010-InventoryClickEvent-getClickedInventory.patch create mode 100644 Bukkit-Patches/0011-Added-getAllSessionData-to-the-Conversation-API.patch create mode 100644 Bukkit-Patches/0012-Catch-Conversation-API-Errors.patch create mode 100644 Bukkit-Patches/0013-Player-Collision-API.patch create mode 100644 Bukkit-Patches/0014-Expand-Boolean-Prompt-Values.patch create mode 100644 Bukkit-Patches/0015-Add-Getter-for-Entity-Invulnerability.patch create mode 100644 Bukkit-Patches/0016-Add-respawn-API.patch create mode 100644 Bukkit-Patches/0017-Fix-Plugin-Message-API-Disconnects.patch create mode 100644 Bukkit-Patches/0018-Fix-Tab-Completion-for-Some-Commands.patch create mode 100644 Bukkit-Patches/0019-Add-Spigot-Links.patch create mode 100644 Bukkit-Patches/0020-Implement-Locale-Getter-for-Players.patch create mode 100644 Bukkit-Patches/0021-Add-support-for-fetching-hidden-players.patch create mode 100644 Bukkit-Patches/0022-Silenceable-Lightning-API.patch create mode 100644 Bukkit-Patches/0023-Remove-deprecation-on-some-player-lookup-methods.patch create mode 100644 Bukkit-Patches/0024-Expand-team-API-to-allow-arbitrary-strings.patch create mode 100644 Bukkit-Patches/0025-Add-Score.isScoreSet-Z-API.patch create mode 100644 Bukkit-Patches/0026-Add-PlayerSpawnLocationEvent.patch create mode 100644 Bukkit-Patches/0027-Ease-ClassLoader-Deadlocks-Where-Possible.patch create mode 100644 CraftBukkit-Patches/0001-POM-Changes.patch delete mode 100644 CraftBukkit-Patches/0001-Rename-to-PaperSpigot.patch create mode 100644 CraftBukkit-Patches/0002-mc-dev-imports.patch create mode 100644 CraftBukkit-Patches/0003-Skeleton-API-Implementations.patch create mode 100644 CraftBukkit-Patches/0004-Obfuscation-Helpers.patch create mode 100644 CraftBukkit-Patches/0005-Spigot-Configuration.patch create mode 100644 CraftBukkit-Patches/0006-Better-Chunk-Tick-Selection.patch create mode 100644 CraftBukkit-Patches/0007-Crop-Growth-Rates.patch create mode 100644 CraftBukkit-Patches/0008-More-Efficient-Chunk-Save-Queue.patch create mode 100644 CraftBukkit-Patches/0009-Merge-tweaks-and-configuration.patch create mode 100644 CraftBukkit-Patches/0010-LongHash-Tweaks.patch create mode 100644 CraftBukkit-Patches/0011-Async-Operation-Catching.patch create mode 100644 CraftBukkit-Patches/0012-View-Distance.patch create mode 100644 CraftBukkit-Patches/0013-Spigot-Timings.patch create mode 100644 CraftBukkit-Patches/0014-Fix-Mob-Spawning-Relative-to-View-Distance.patch create mode 100644 CraftBukkit-Patches/0015-Handle-Null-Tile-Entities.patch create mode 100644 CraftBukkit-Patches/0016-Entity-Activation-Range.patch create mode 100644 CraftBukkit-Patches/0017-Metrics.patch create mode 100644 CraftBukkit-Patches/0018-PlayerItemDamageEvent.patch create mode 100644 CraftBukkit-Patches/0019-Faster-UUID-for-entities.patch create mode 100644 CraftBukkit-Patches/0020-Prevent-NPE-in-CraftSign.patch create mode 100644 CraftBukkit-Patches/0021-Entity-Tracking-Ranges.patch create mode 100644 CraftBukkit-Patches/0022-Limit-Custom-Map-Rendering.patch create mode 100644 CraftBukkit-Patches/0023-Thread-Naming-and-Tweaks.patch create mode 100644 CraftBukkit-Patches/0024-Close-Unloaded-Save-Files.patch create mode 100644 CraftBukkit-Patches/0025-Remove-o-Option.patch create mode 100644 CraftBukkit-Patches/0026-Recipe-Deconstruction.patch create mode 100644 CraftBukkit-Patches/0027-Implement-Arrow-API.patch create mode 100644 CraftBukkit-Patches/0028-Hopper-Customisations.patch create mode 100644 CraftBukkit-Patches/0029-Prevent-Shutdown-Hang.patch create mode 100644 CraftBukkit-Patches/0030-Implement-SpawnerSpawnEvent.patch create mode 100644 CraftBukkit-Patches/0031-Firework-Meta-Crash-Fix.patch create mode 100644 CraftBukkit-Patches/0032-Allow-Disabling-of-Command-Logging.patch create mode 100644 CraftBukkit-Patches/0033-Allow-Disabling-of-Command-TabComplete.patch create mode 100644 CraftBukkit-Patches/0034-Configurable-Messages.patch create mode 100644 CraftBukkit-Patches/0035-Allow-Disabling-of-Random-Lighting-Updates.patch create mode 100644 CraftBukkit-Patches/0036-Properly-Close-Inventories.patch create mode 100644 CraftBukkit-Patches/0037-Disallow-Interaction-With-Self.patch create mode 100644 CraftBukkit-Patches/0038-Lower-Chunk-Compression.patch create mode 100644 CraftBukkit-Patches/0039-Entity-Mount-and-Dismount-Events.patch create mode 100644 CraftBukkit-Patches/0040-Prevent-Ghost-Players-Caused-by-Plugins.patch create mode 100644 CraftBukkit-Patches/0041-Plug-World-Unload-Memory-Leak.patch create mode 100644 CraftBukkit-Patches/0042-Player-Collision-API.patch create mode 100644 CraftBukkit-Patches/0043-Fully-Disable-Snooper-When-Not-Required.patch create mode 100644 CraftBukkit-Patches/0044-Add-Getter-for-Entity-Invulnerability.patch create mode 100644 CraftBukkit-Patches/0045-Cap-Minimum-Player-Speed.patch create mode 100644 CraftBukkit-Patches/0046-Update-Inventory-and-Health-for-PlayerConsumeItemEve.patch create mode 100644 CraftBukkit-Patches/0047-Call-EntityChangeBlockEvent-for-Fire-Arrows-hitting-.patch create mode 100644 CraftBukkit-Patches/0048-Allow-Disabling-of-1.6.3-Structure-Saving.patch create mode 100644 CraftBukkit-Patches/0049-Item-Despawn-Rate.patch create mode 100644 CraftBukkit-Patches/0050-Don-t-Special-Case-X-Move-Value.patch create mode 100644 CraftBukkit-Patches/0051-Implement-respawn-API.patch create mode 100644 CraftBukkit-Patches/0052-Fix-BrewingStands-Removing-NBT-Potions.patch create mode 100644 CraftBukkit-Patches/0053-Arrow-Despawn-Rate.patch create mode 100644 CraftBukkit-Patches/0054-Fix-packed-ice-generation.patch create mode 100644 CraftBukkit-Patches/0055-Watchdog-Thread.patch create mode 100644 CraftBukkit-Patches/0056-Clear-Flower-Pot-on-Drop.patch create mode 100644 CraftBukkit-Patches/0057-Fix-some-chunks-not-being-sent-to-the-client.patch create mode 100644 CraftBukkit-Patches/0058-Fix-Broken-Async-Chat.patch create mode 100644 CraftBukkit-Patches/0059-Allow-Teleportation-of-Vehicles-and-Passengers.patch create mode 100644 CraftBukkit-Patches/0060-Remove-OS-X-Special-Chars-from-Signs.patch create mode 100644 CraftBukkit-Patches/0061-Orebfuscator.patch create mode 100644 CraftBukkit-Patches/0062-Optimize-DataWatcher.patch create mode 100644 CraftBukkit-Patches/0063-Fire-PreLogin-Events-in-Offline-Mode.patch create mode 100644 CraftBukkit-Patches/0064-BungeeCord-Support.patch create mode 100644 CraftBukkit-Patches/0065-Allow-Disabling-Zombie-Villager-Aggression.patch create mode 100644 CraftBukkit-Patches/0066-Configurable-Amount-of-Netty-Threads.patch create mode 100644 CraftBukkit-Patches/0067-Prevent-Mineshaft-Saving.patch create mode 100644 CraftBukkit-Patches/0068-Log-Cause-of-Unexpected-Exceptions.patch create mode 100644 CraftBukkit-Patches/0069-Particle-API.patch create mode 100644 CraftBukkit-Patches/0070-Fix-Biome-Decoration-Crashes.patch create mode 100644 CraftBukkit-Patches/0071-Save-ticks-lived-to-nbttag.patch create mode 100644 CraftBukkit-Patches/0072-More-Efficient-GetCubes.patch create mode 100644 CraftBukkit-Patches/0073-Add-Option-to-Nerf-Mobs-from-Spawner-s.patch create mode 100644 CraftBukkit-Patches/0074-Warn-if-PermGen-may-be-insufficient.patch create mode 100644 CraftBukkit-Patches/0075-Disable-Connected-Check-on-setScoreboard.patch create mode 100644 CraftBukkit-Patches/0076-Add-Late-Bind-Option.patch create mode 100644 CraftBukkit-Patches/0077-Allow-statistics-to-be-disabled-forced.patch create mode 100644 CraftBukkit-Patches/0078-Fix-anvil-collisions.patch create mode 100644 CraftBukkit-Patches/0079-Fix-ItemStack-Unbreakable-Code.patch create mode 100644 CraftBukkit-Patches/0080-Try-and-Debug-Crash-Reports-Crashing.patch create mode 100644 CraftBukkit-Patches/0081-Replace-AutoSave-Mechanism.patch create mode 100644 CraftBukkit-Patches/0082-Block-data-values-that-crash-the-client.patch create mode 100644 CraftBukkit-Patches/0083-Support-vanilla-s-direction-tag-on-fireballs.patch create mode 100644 CraftBukkit-Patches/0084-Support-non-prefixed-URLs.patch create mode 100644 CraftBukkit-Patches/0085-Catch-stalling-on-corrupted-map-data-NBT-arrays.patch create mode 100644 CraftBukkit-Patches/0086-Allow-toggling-of-ZombiePigmen-spawning-in-portal-bl.patch create mode 100644 CraftBukkit-Patches/0087-Highly-Optimized-Tick-Loop.patch create mode 100644 CraftBukkit-Patches/0088-Add-Spigot-Links.patch create mode 100644 CraftBukkit-Patches/0089-Configurable-Ping-Sample-Size.patch create mode 100644 CraftBukkit-Patches/0090-Add-Optional-Tick-Shuffling.patch create mode 100644 CraftBukkit-Patches/0091-Allow-Configuring-Chunks-per-Packet.patch create mode 100644 CraftBukkit-Patches/0092-Implement-Locale-Getter-for-Players.patch create mode 100644 CraftBukkit-Patches/0093-Cap-Entity-Collisions.patch create mode 100644 CraftBukkit-Patches/0094-Fix-dispensing-bone-meal-not-having-the-correct-data.patch create mode 100644 CraftBukkit-Patches/0095-Spam-Filter-Exclusions.patch create mode 100644 CraftBukkit-Patches/0096-Add-Option-to-Silence-CommandBlock-Console.patch create mode 100644 CraftBukkit-Patches/0097-Add-support-for-fetching-hidden-players.patch create mode 100644 CraftBukkit-Patches/0098-Allow-Disabling-Creative-Item-Filter.patch create mode 100644 CraftBukkit-Patches/0099-Cap-Channel-Registrations.patch create mode 100644 CraftBukkit-Patches/0100-Allow-vanilla-commands-to-be-the-main-version-of-a-c.patch create mode 100644 CraftBukkit-Patches/0101-Unfinalize-the-isDisconnected-method-by-bukkit.patch create mode 100644 CraftBukkit-Patches/0102-Implement-Silenceable-Lightning-API.patch create mode 100644 CraftBukkit-Patches/0103-Use-one-PermissibleBase-for-all-Command-Blocks.patch create mode 100644 CraftBukkit-Patches/0104-Prevent-hoppers-from-loading-chunks.patch create mode 100644 CraftBukkit-Patches/0105-Guard-Entity-List.patch create mode 100644 CraftBukkit-Patches/0106-Fix-ConcurrentModificationException-while-being-idle.patch create mode 100644 CraftBukkit-Patches/0107-Cancellable-WitherSkull-potion-effect.patch create mode 100644 CraftBukkit-Patches/0108-Descriptive-kick-reasons-instead-of-Nope.patch create mode 100644 CraftBukkit-Patches/0109-Check-for-manually-prefixed-commands-or-commands-tha.patch create mode 100644 CraftBukkit-Patches/0110-Cap-window-names-to-prevent-client-disconnects.patch create mode 100644 CraftBukkit-Patches/0111-Enable-Improved-Ping-Sending.patch create mode 100644 CraftBukkit-Patches/0112-Configurable-dragon-death-and-wither-spawn-sounds.patch create mode 100644 CraftBukkit-Patches/0113-Display-Spigot-in-client-crashes-server-lists-and-Mo.patch create mode 100644 CraftBukkit-Patches/0114-Old-New-Version-Support.patch create mode 100644 CraftBukkit-Patches/0115-Treat-Bungee-as-Online-Mode.patch create mode 100644 CraftBukkit-Patches/0116-Fix-several-occurances-of-missed-diff.patch create mode 100644 CraftBukkit-Patches/0117-Fix-PlayerFishEvent-not-properly-cancelling.-Fixes-B.patch create mode 100644 CraftBukkit-Patches/0118-Update-Warning.patch create mode 100644 CraftBukkit-Patches/0119-Add-Conversion-Message.patch create mode 100644 CraftBukkit-Patches/0120-Properly-cancel-fishing-event.-Fixes-BUKKIT-5396.patch create mode 100644 CraftBukkit-Patches/0121-Print-Stack-on-InternalException.patch create mode 100644 CraftBukkit-Patches/0122-Use-Offline-Player-Data-Once-if-Required.patch create mode 100644 CraftBukkit-Patches/0123-Use-Provided-Case-for-Non-Existent-Offline-Players.patch create mode 100644 CraftBukkit-Patches/0124-Check-for-blank-OfflinePlayer-Names.patch create mode 100644 CraftBukkit-Patches/0125-Fix-Player-Banning.patch create mode 100644 CraftBukkit-Patches/0126-Fix-ban-expire-dates.patch create mode 100644 CraftBukkit-Patches/0127-Correct-Ban-Expiration.patch create mode 100644 CraftBukkit-Patches/0128-Convert-Horses-owner-to-UUID.patch create mode 100644 CraftBukkit-Patches/0129-Expand-team-API-to-allow-arbitrary-strings.patch create mode 100644 CraftBukkit-Patches/0130-Add-Score.isScoreSet-Z-API.patch create mode 100644 CraftBukkit-Patches/0131-Log-null-TileEntity-Owner.patch create mode 100644 CraftBukkit-Patches/0132-Don-t-special-case-invalid-usernames-for-UUIDs.patch create mode 100644 CraftBukkit-Patches/0133-Convert-player-skulls-async.patch create mode 100644 CraftBukkit-Patches/0134-Prevent-NoClassDefError-crash-and-notify-on-crash.patch create mode 100644 CraftBukkit-Patches/0135-Check-Skull-canPlace.patch create mode 100644 CraftBukkit-Patches/0136-Don-t-let-trees-replace-any-block.patch create mode 100644 CraftBukkit-Patches/0137-Fix-race-condition-that-could-kill-connections-befor.patch create mode 100644 CraftBukkit-Patches/0138-Configurable-UserCache-cap.patch create mode 100644 CraftBukkit-Patches/0139-Implement-PlayerSpawnLocationEvent.patch create mode 100644 CraftBukkit-Patches/0140-Cap-Objective-Score-Length.patch create mode 100644 CraftBukkit-Patches/0141-Process-conversation-input-on-the-main-thread.-Fixes.patch create mode 100644 CraftBukkit-Patches/0142-Configurable-save-on-stop-only-for-UserCache.patch create mode 100644 CraftBukkit-Patches/0143-Prevent-Unbounded-IntCache-Growth.patch create mode 100644 CraftBukkit-Patches/0144-Alternative-Hopper-Ticking.patch create mode 100644 CraftBukkit-Patches/0145-Fix-explosions-not-moving-invulnerable-entities.patch create mode 100644 CraftBukkit-Patches/0146-Add-damager-to-the-unhandled-error.patch create mode 100644 CraftBukkit-Patches/0147-Fix-ItemFrame-and-Fireball-EntityDamageByEntityEvent.patch create mode 100644 CraftBukkit-Patches/0148-Cross-World-Entity-Teleportation.patch create mode 100644 CraftBukkit-Patches/0149-Limit-block-placement-interaction-packets.patch create mode 100644 CraftBukkit-Patches/0150-Better-item-validation.patch create mode 100644 CraftBukkit-Patches/0151-Further-Seed-Customisation.patch create mode 100644 CraftBukkit-Patches/0152-Disable-ResourceLeakDetector.patch create mode 100644 CraftBukkit-Patches/0153-Add-More-Information-to-session.lock-Errors.patch create mode 100644 CraftBukkit-Patches/0154-Safer-JSON-Loading.patch create mode 100644 CraftBukkit-Patches/0155-Fix-Slow-Loading-Libraries.patch create mode 100644 CraftBukkit-Patches/0156-Add-CommandLine-EULA-Flag.patch create mode 100644 CraftBukkit-Patches/0157-Fix-misnamed-function-from-1.7.10-update.patch create mode 100644 CraftBukkit-Patches/0158-Fix-for-enchanting-table-wiping-meta-when-placing-st.patch create mode 100644 CraftBukkit-Patches/0159-Don-t-spawn-bonus-ocelots-when-plugins-spawn-ocelots.patch create mode 100644 CraftBukkit-Patches/0160-Prevent-a-crash-involving-attributes.patch create mode 100644 CraftBukkit-Patches/0161-Fix-IP-banning.patch rename Bukkit-Patches/0001-Add-float-methods-to-configs.patch => Spigot-API-Patches/Add-float-methods-to-configs.patch (100%) create mode 100644 Spigot-API-Patches/POM-changes.patch rename CraftBukkit-Patches/0013-Ability-to-disable-asynccatcher.patch => Spigot-Server-Patches/Ability-to-disable-asynccatcher.patch (100%) rename CraftBukkit-Patches/0012-Add-1.8-recipes-for-stone-variants.patch => Spigot-Server-Patches/Add-1.8-recipes-for-stone-variants.patch (100%) rename CraftBukkit-Patches/0022-Add-configurable-despawn-distances-for-living-entiti.patch => Spigot-Server-Patches/Add-configurable-despawn-distances-for-living-entiti.patch (100%) rename CraftBukkit-Patches/0023-Allow-for-toggling-of-spawn-chunks.patch => Spigot-Server-Patches/Allow-for-toggling-of-spawn-chunks.patch (100%) rename CraftBukkit-Patches/0019-Allow-nerfed-mobs-to-jump.patch => Spigot-Server-Patches/Allow-nerfed-mobs-to-jump.patch (100%) rename CraftBukkit-Patches/0003-Allow-undead-horse-types-to-be-leashed.patch => Spigot-Server-Patches/Allow-undead-horse-types-to-be-leashed.patch (100%) rename CraftBukkit-Patches/0025-Better-EULA-handling.patch => Spigot-Server-Patches/Better-EULA-handling.patch (100%) rename CraftBukkit-Patches/0028-Configurable-AI-target-selector-delay.patch => Spigot-Server-Patches/Configurable-AI-target-selector-delay.patch (100%) rename CraftBukkit-Patches/0009-Configurable-baby-zombie-movement-speed.patch => Spigot-Server-Patches/Configurable-baby-zombie-movement-speed.patch (100%) rename CraftBukkit-Patches/0008-Configurable-cactus-and-reed-natural-growth-heights.patch => Spigot-Server-Patches/Configurable-cactus-and-reed-natural-growth-heights.patch (100%) rename CraftBukkit-Patches/0007-Configurable-damage-multiplier-for-PvP-blocking.patch => Spigot-Server-Patches/Configurable-damage-multiplier-for-PvP-blocking.patch (100%) rename CraftBukkit-Patches/0018-Configurable-fishing-time-ranges.patch => Spigot-Server-Patches/Configurable-fishing-time-ranges.patch (100%) rename CraftBukkit-Patches/0026-Configurable-nerf-for-TNT-cannons.patch => Spigot-Server-Patches/Configurable-nerf-for-TNT-cannons.patch (100%) rename CraftBukkit-Patches/0006-Configurable-squid-spawn-ranges.patch => Spigot-Server-Patches/Configurable-squid-spawn-ranges.patch (100%) rename CraftBukkit-Patches/0015-Do-not-remove-player-in-world-change.patch => Spigot-Server-Patches/Do-not-remove-player-in-world-change.patch (100%) rename CraftBukkit-Patches/0027-Don-t-tick-chests.patch => Spigot-Server-Patches/Don-t-tick-chests.patch (100%) rename CraftBukkit-Patches/0024-Fix-Null-Tile-Entity-Worlds.patch => Spigot-Server-Patches/Fix-Null-Tile-Entity-Worlds.patch (100%) rename CraftBukkit-Patches/0016-Fix-directional-TNT-bias.patch => Spigot-Server-Patches/Fix-directional-TNT-bias.patch (100%) rename CraftBukkit-Patches/0014-Fix-redstone-lag-issues.patch => Spigot-Server-Patches/Fix-redstone-lag-issues.patch (100%) rename CraftBukkit-Patches/0017-Fix-zombie-sieges-and-their-spawn-mechanics.patch => Spigot-Server-Patches/Fix-zombie-sieges-and-their-spawn-mechanics.patch (100%) rename CraftBukkit-Patches/0011-Inverted-Daylight-Detector-Toggle.patch => Spigot-Server-Patches/Inverted-Daylight-Detector-Toggle.patch (100%) rename CraftBukkit-Patches/0005-Invisible-players-don-t-have-rights.patch => Spigot-Server-Patches/Invisible-players-don-t-have-rights.patch (100%) rename CraftBukkit-Patches/0010-Make-destroyed-boats-drop-the-boat-item.patch => Spigot-Server-Patches/Make-destroyed-boats-drop-the-boat-item.patch (100%) create mode 100644 Spigot-Server-Patches/POM-changes.patch rename CraftBukkit-Patches/0002-PaperSpigot-config-files.patch => Spigot-Server-Patches/PaperSpigot-config-files.patch (100%) rename CraftBukkit-Patches/0021-Player-Exhaustion-Multipliers.patch => Spigot-Server-Patches/Player-Exhaustion-Multipliers.patch (100%) rename CraftBukkit-Patches/0004-Teleport-passenger-vehicle-with-player.patch => Spigot-Server-Patches/Teleport-passenger-vehicle-with-player.patch (100%) rename CraftBukkit-Patches/0020-Toggle-for-player-interact-limiter.patch => Spigot-Server-Patches/Toggle-for-player-interact-limiter.patch (100%) diff --git a/.gitignore b/.gitignore index deab816f06..2b7c3a6f4a 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,5 @@ manifest.mf # other stuff Spigot-API Spigot-Server +PaperSpigot-Server +PaperSpigot-API diff --git a/.gitmodules b/.gitmodules index 11b24328b7..7c741aaf34 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "Bukkit"] path = Bukkit - url = https://github.com/SpigotMC/Spigot-API.git + url = https://github.com/Bukkit/Bukkit.git [submodule "CraftBukkit"] path = CraftBukkit - url = https://github.com/SpigotMC/Spigot-Server.git + url = https://github.com/Bukkit/CraftBukkit.git diff --git a/Bukkit b/Bukkit index 0cd44c54d0..d3ab9468c3 160000 --- a/Bukkit +++ b/Bukkit @@ -1 +1 @@ -Subproject commit 0cd44c54d033b283a256915d14b84fb7730127ba +Subproject commit d3ab9468c3aed2a06c280bf6c9cea5108c736dcc diff --git a/Bukkit-Patches/0001-POM-Changes.patch b/Bukkit-Patches/0001-POM-Changes.patch new file mode 100644 index 0000000000..ff670db3b2 --- /dev/null +++ b/Bukkit-Patches/0001-POM-Changes.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 2 Jun 2013 10:36:24 +1000 +Subject: [PATCH] POM Changes + + +diff --git a/pom.xml b/pom.xml +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -0,0 +0,0 @@ + + 4.0.0 +- org.bukkit +- bukkit ++ org.spigotmc ++ spigot-api + 1.7.10-R0.1-SNAPSHOT +- Bukkit +- http://www.bukkit.org ++ Spigot-API ++ http://www.spigotmc.org + + + UTF-8 + + +- +- scm:git:git@github.com:Bukkit/Bukkit.git +- scm:git:git://github.com/Bukkit/Bukkit.git +- https://github.com/Bukkit/Bukkit/tree/master/ +- +- +- +- jenkins +- http://ci.bukkit.org +- +- +- +- +- jd.bukkit.org +- file:///home/javadocs/public_html/ +- +- +- repobo-rel +- repo.bukkit.org Releases +- http://repo.bukkit.org/content/repositories/releases/ +- +- +- repobo-snap +- repo.bukkit.org Snapshots +- http://repo.bukkit.org/content/repositories/snapshots/ +- +- ++ ++ org.spigotmc ++ spigot-parent ++ dev-SNAPSHOT ++ ../pom.xml ++ + + + +-- \ No newline at end of file diff --git a/Bukkit-Patches/0002-Spigot-Timings.patch b/Bukkit-Patches/0002-Spigot-Timings.patch new file mode 100644 index 0000000000..8ebbc6f2d3 --- /dev/null +++ b/Bukkit-Patches/0002-Spigot-Timings.patch @@ -0,0 +1,461 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 2 Jun 2013 10:42:57 +1000 +Subject: [PATCH] Spigot Timings + +Adds performance tracking timings all around the Minecraft Server, and improves the usability of the /timings command + +Plugins can track their own timings with CustomTimingsHandler + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -0,0 +0,0 @@ public final class Bukkit { + */ + public static void reload() { + server.reload(); ++ org.spigotmc.CustomTimingsHandler.reload(); // Spigot + } + + /** +diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/command/Command.java ++++ b/src/main/java/org/bukkit/command/Command.java +@@ -0,0 +0,0 @@ public abstract class Command { + protected String usageMessage; + private String permission; + private String permissionMessage; ++ public org.spigotmc.CustomTimingsHandler timings; // Spigot + + protected Command(String name) { + this(name, "", "/" + name, new ArrayList()); +@@ -0,0 +0,0 @@ public abstract class Command { + this.usageMessage = usageMessage; + this.aliases = aliases; + this.activeAliases = new ArrayList(aliases); ++ this.timings = new org.spigotmc.CustomTimingsHandler("** Command: " + name); // Spigot + } + + /** +@@ -0,0 +0,0 @@ public abstract class Command { + public boolean setLabel(String name) { + this.nextLabel = name; + if (!isRegistered()) { ++ this.timings = new org.spigotmc.CustomTimingsHandler("** Command: " + name); // Spigot + this.label = name; + return true; + } +diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/command/SimpleCommandMap.java ++++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java +@@ -0,0 +0,0 @@ public class SimpleCommandMap implements CommandMap { + } + + try { ++ target.timings.startTiming(); // Spigot + // Note: we don't return the result of target.execute as thats success / failure, we return handled (true) or not handled (false) + target.execute(sender, sentCommandLabel, Arrays_copyOfRange(args, 1, args.length)); ++ target.timings.stopTiming(); // Spigot + } catch (CommandException ex) { ++ target.timings.stopTiming(); // Spigot + throw ex; + } catch (Throwable ex) { ++ target.timings.stopTiming(); // Spigot + throw new CommandException("Unhandled exception executing '" + commandLine + "' in " + target, ex); + } + +diff --git a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java ++++ b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java +@@ -0,0 +0,0 @@ import org.bukkit.util.StringUtil; + + import com.google.common.collect.ImmutableList; + ++// Spigot start ++import java.io.ByteArrayOutputStream; ++import java.io.OutputStream; ++import java.net.HttpURLConnection; ++import java.net.URL; ++import java.net.URLEncoder; ++import java.util.logging.Level; ++ ++import org.bukkit.command.RemoteConsoleCommandSender; ++import org.bukkit.plugin.SimplePluginManager; ++import org.spigotmc.CustomTimingsHandler; ++// Spigot end ++ + public class TimingsCommand extends BukkitCommand { +- private static final List TIMINGS_SUBCOMMANDS = ImmutableList.of("merged", "reset", "separate"); ++ private static final List TIMINGS_SUBCOMMANDS = ImmutableList.of("report", "reset", "on", "off", "paste"); // Spigot ++ public static long timingStart = 0; // Spigot + + public TimingsCommand(String name) { + super(name); +- this.description = "Records timings for all plugin events"; +- this.usageMessage = "/timings "; ++ this.description = "Manages Spigot Timings data to see performance of the server."; // Spigot ++ this.usageMessage = "/timings "; // Spigot + this.setPermission("bukkit.command.timings"); + } + ++ // Spigot start - redesigned Timings Command ++ public void executeSpigotTimings(CommandSender sender, String[] args) { ++ if ( "on".equals( args[0] ) ) ++ { ++ ( (SimplePluginManager) Bukkit.getPluginManager() ).useTimings( true ); ++ CustomTimingsHandler.reload(); ++ sender.sendMessage( "Enabled Timings & Reset" ); ++ return; ++ } else if ( "off".equals( args[0] ) ) ++ { ++ ( (SimplePluginManager) Bukkit.getPluginManager() ).useTimings( false ); ++ sender.sendMessage( "Disabled Timings" ); ++ return; ++ } ++ ++ if ( !Bukkit.getPluginManager().useTimings() ) ++ { ++ sender.sendMessage( "Please enable timings by typing /timings on" ); ++ return; ++ } ++ ++ boolean paste = "paste".equals( args[0] ); ++ if ("reset".equals(args[0])) { ++ CustomTimingsHandler.reload(); ++ sender.sendMessage("Timings reset"); ++ } else if ("merged".equals(args[0]) || "report".equals(args[0]) || paste) { ++ long sampleTime = System.nanoTime() - timingStart; ++ int index = 0; ++ File timingFolder = new File("timings"); ++ timingFolder.mkdirs(); ++ File timings = new File(timingFolder, "timings.txt"); ++ ByteArrayOutputStream bout = ( paste ) ? new ByteArrayOutputStream() : null; ++ while (timings.exists()) timings = new File(timingFolder, "timings" + (++index) + ".txt"); ++ PrintStream fileTimings = null; ++ try { ++ fileTimings = ( paste ) ? new PrintStream( bout ) : new PrintStream( timings ); ++ ++ CustomTimingsHandler.printTimings(fileTimings); ++ fileTimings.println( "Sample time " + sampleTime + " (" + sampleTime / 1E9 + "s)" ); ++ ++ if ( paste ) ++ { ++ new PasteThread( sender, bout ).start(); ++ return; ++ } ++ ++ sender.sendMessage("Timings written to " + timings.getPath()); ++ sender.sendMessage( "Paste contents of file into form at http://www.spigotmc.org/go/timings to read results." ); ++ ++ } catch (IOException e) { ++ } finally { ++ if (fileTimings != null) { ++ fileTimings.close(); ++ } ++ } ++ } ++ } ++ // Spigot end ++ + @Override + public boolean execute(CommandSender sender, String currentAlias, String[] args) { + if (!testPermission(sender)) return true; +- if (args.length != 1) { ++ if (args.length < 1) { // Spigot + sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); + return false; + } ++ if (true) { executeSpigotTimings(sender, args); return true; } // Spigot + if (!sender.getServer().getPluginManager().useTimings()) { + sender.sendMessage("Please enable timings by setting \"settings.plugin-profiling\" to true in bukkit.yml"); + return true; +@@ -0,0 +0,0 @@ public class TimingsCommand extends BukkitCommand { + } + return ImmutableList.of(); + } ++ ++ // Spigot start ++ private static class PasteThread extends Thread ++ { ++ ++ private final CommandSender sender; ++ private final ByteArrayOutputStream bout; ++ ++ public PasteThread(CommandSender sender, ByteArrayOutputStream bout) ++ { ++ super( "Timings paste thread" ); ++ this.sender = sender; ++ this.bout = bout; ++ } ++ ++ @Override ++ public synchronized void start() { ++ if (sender instanceof RemoteConsoleCommandSender) { ++ run(); ++ } else { ++ super.start(); ++ } ++ } ++ ++ @Override ++ public void run() ++ { ++ try ++ { ++ HttpURLConnection con = (HttpURLConnection) new URL( "http://paste.ubuntu.com/" ).openConnection(); ++ con.setDoOutput( true ); ++ con.setRequestMethod( "POST" ); ++ con.setInstanceFollowRedirects( false ); ++ ++ OutputStream out = con.getOutputStream(); ++ out.write( "poster=Spigot&syntax=text&content=".getBytes( "UTF-8" ) ); ++ out.write( URLEncoder.encode( bout.toString( "UTF-8" ), "UTF-8" ).getBytes( "UTF-8" ) ); ++ out.close(); ++ con.getInputStream().close(); ++ ++ String location = con.getHeaderField( "Location" ); ++ String pasteID = location.substring( "http://paste.ubuntu.com/".length(), location.length() - 1 ); ++ sender.sendMessage( ChatColor.GREEN + "View timings results can be viewed at http://www.spigotmc.org/go/timings?url=" + pasteID ); ++ } catch ( IOException ex ) ++ { ++ sender.sendMessage( ChatColor.RED + "Error pasting timings, check your console for more information" ); ++ Bukkit.getServer().getLogger().log( Level.WARNING, "Could not paste timings", ex ); ++ } ++ } ++ } ++ // Spigot end + } +diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java ++++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +@@ -0,0 +0,0 @@ public final class SimplePluginManager implements PluginManager { + } + } + ++ org.bukkit.command.defaults.TimingsCommand.timingStart = System.nanoTime(); // Spigot + return result.toArray(new Plugin[result.size()]); + } + +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +@@ -0,0 +0,0 @@ import org.bukkit.plugin.PluginLoader; + import org.bukkit.plugin.RegisteredListener; + import org.bukkit.plugin.TimedRegisteredListener; + import org.bukkit.plugin.UnknownDependencyException; ++import org.spigotmc.CustomTimingsHandler; // Spigot + import org.yaml.snakeyaml.error.YAMLException; + + /** +@@ -0,0 +0,0 @@ public final class JavaPluginLoader implements PluginLoader { + private final Pattern[] fileFilters = new Pattern[] { Pattern.compile("\\.jar$"), }; + private final Map> classes = new HashMap>(); + private final Map loaders = new LinkedHashMap(); ++ public static final CustomTimingsHandler pluginParentTimer = new CustomTimingsHandler("** Plugins"); // Spigot + + /** + * This class was not meant to be constructed explicitly +@@ -0,0 +0,0 @@ public final class JavaPluginLoader implements PluginLoader { + } + } + ++ final CustomTimingsHandler timings = new CustomTimingsHandler("Plugin: " + plugin.getDescription().getFullName() + " Event: " + listener.getClass().getName() + "::" + method.getName()+"("+eventClass.getSimpleName()+")", pluginParentTimer); // Spigot + EventExecutor executor = new EventExecutor() { + public void execute(Listener listener, Event event) throws EventException { + try { + if (!eventClass.isAssignableFrom(event.getClass())) { + return; + } ++ timings.startTiming(); // Spigot + method.invoke(listener, event); ++ timings.stopTiming(); // Spigot + } catch (InvocationTargetException ex) { + throw new EventException(ex.getCause()); + } catch (Throwable t) { +@@ -0,0 +0,0 @@ public final class JavaPluginLoader implements PluginLoader { + } + } + }; +- if (useTimings) { ++ if (false) { // Spigot - RL handles useTimings check now + eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled())); + } else { + eventSet.add(new RegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled())); +diff --git a/src/main/java/org/spigotmc/CustomTimingsHandler.java b/src/main/java/org/spigotmc/CustomTimingsHandler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/org/spigotmc/CustomTimingsHandler.java +@@ -0,0 +0,0 @@ ++package org.spigotmc; ++ ++import org.bukkit.command.defaults.TimingsCommand; ++import org.bukkit.event.HandlerList; ++import org.bukkit.plugin.Plugin; ++import org.bukkit.plugin.RegisteredListener; ++import org.bukkit.plugin.TimedRegisteredListener; ++import java.io.PrintStream; ++import java.util.Collection; ++import java.util.HashSet; ++import java.util.List; ++import java.util.Queue; ++import java.util.concurrent.ConcurrentLinkedQueue; ++ ++import org.bukkit.Bukkit; ++import org.bukkit.World; ++ ++/** ++ * Provides custom timing sections for /timings merged. ++ */ ++public class CustomTimingsHandler ++{ ++ ++ private static Queue HANDLERS = new ConcurrentLinkedQueue(); ++ /*========================================================================*/ ++ private final String name; ++ private final CustomTimingsHandler parent; ++ private long count = 0; ++ private long start = 0; ++ private long timingDepth = 0; ++ private long totalTime = 0; ++ private long curTickTotal = 0; ++ private long violations = 0; ++ ++ public CustomTimingsHandler(String name) ++ { ++ this( name, null ); ++ } ++ ++ public CustomTimingsHandler(String name, CustomTimingsHandler parent) ++ { ++ this.name = name; ++ this.parent = parent; ++ HANDLERS.add( this ); ++ } ++ ++ /** ++ * Prints the timings and extra data to the given stream. ++ * ++ * @param printStream ++ */ ++ public static void printTimings(PrintStream printStream) ++ { ++ printStream.println( "Minecraft" ); ++ for ( CustomTimingsHandler timings : HANDLERS ) ++ { ++ long time = timings.totalTime; ++ long count = timings.count; ++ if ( count == 0 ) ++ { ++ continue; ++ } ++ long avg = time / count; ++ ++ printStream.println( " " + timings.name + " Time: " + time + " Count: " + count + " Avg: " + avg + " Violations: " + timings.violations ); ++ } ++ printStream.println( "# Version " + Bukkit.getVersion() ); ++ int entities = 0; ++ int livingEntities = 0; ++ for ( World world : Bukkit.getWorlds() ) ++ { ++ entities += world.getEntities().size(); ++ livingEntities += world.getLivingEntities().size(); ++ } ++ printStream.println( "# Entities " + entities ); ++ printStream.println( "# LivingEntities " + livingEntities ); ++ } ++ ++ /** ++ * Resets all timings. ++ */ ++ public static void reload() ++ { ++ if ( Bukkit.getPluginManager().useTimings() ) ++ { ++ for ( CustomTimingsHandler timings : HANDLERS ) ++ { ++ timings.reset(); ++ } ++ } ++ TimingsCommand.timingStart = System.nanoTime(); ++ } ++ ++ /** ++ * Ticked every tick by CraftBukkit to count the number of times a timer ++ * caused TPS loss. ++ */ ++ public static void tick() ++ { ++ if ( Bukkit.getPluginManager().useTimings() ) ++ { ++ for ( CustomTimingsHandler timings : HANDLERS ) ++ { ++ if ( timings.curTickTotal > 50000000 ) ++ { ++ timings.violations += Math.ceil( timings.curTickTotal / 50000000 ); ++ } ++ timings.curTickTotal = 0; ++ timings.timingDepth = 0; // incase reset messes this up ++ } ++ } ++ } ++ ++ /** ++ * Starts timing to track a section of code. ++ */ ++ public void startTiming() ++ { ++ // If second condtion fails we are already timing ++ if ( Bukkit.getPluginManager().useTimings() && ++timingDepth == 1 ) ++ { ++ start = System.nanoTime(); ++ if ( parent != null && ++parent.timingDepth == 1 ) ++ { ++ parent.start = start; ++ } ++ } ++ } ++ ++ /** ++ * Stops timing a section of code. ++ */ ++ public void stopTiming() ++ { ++ if ( Bukkit.getPluginManager().useTimings() ) ++ { ++ if ( --timingDepth != 0 || start == 0 ) ++ { ++ return; ++ } ++ long diff = System.nanoTime() - start; ++ totalTime += diff; ++ curTickTotal += diff; ++ count++; ++ start = 0; ++ if ( parent != null ) ++ { ++ parent.stopTiming(); ++ } ++ } ++ } ++ ++ /** ++ * Reset this timer, setting all values to zero. ++ */ ++ public void reset() ++ { ++ count = 0; ++ violations = 0; ++ curTickTotal = 0; ++ totalTime = 0; ++ start = 0; ++ timingDepth = 0; ++ } ++} +-- \ No newline at end of file diff --git a/Bukkit-Patches/0003-Add-PlayerItemDamageEvent.patch b/Bukkit-Patches/0003-Add-PlayerItemDamageEvent.patch new file mode 100644 index 0000000000..adf4d7688e --- /dev/null +++ b/Bukkit-Patches/0003-Add-PlayerItemDamageEvent.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Mon, 4 Mar 2013 18:31:20 +1100 +Subject: [PATCH] Add PlayerItemDamageEvent + + +diff --git a/src/main/java/org/bukkit/event/player/PlayerItemDamageEvent.java b/src/main/java/org/bukkit/event/player/PlayerItemDamageEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/org/bukkit/event/player/PlayerItemDamageEvent.java +@@ -0,0 +0,0 @@ ++package org.bukkit.event.player; ++ ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.inventory.ItemStack; ++ ++public class PlayerItemDamageEvent extends PlayerEvent implements Cancellable { ++ ++ private static final HandlerList handlers = new HandlerList(); ++ private final ItemStack item; ++ private int damage; ++ private boolean cancelled = false; ++ ++ public PlayerItemDamageEvent(Player player, ItemStack what, int damage) { ++ super(player); ++ this.item = what; ++ this.damage = damage; ++ } ++ ++ public ItemStack getItem() { ++ return item; ++ } ++ ++ /** ++ * Gets the amount of durability damage this item will be taking. ++ * ++ * @return durability change ++ */ ++ public int getDamage() { ++ return damage; ++ } ++ ++ public void setDamage(int damage) { ++ this.damage = damage; ++ } ++ ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +-- \ No newline at end of file diff --git a/Bukkit-Patches/0004-BungeeCord-Support.patch b/Bukkit-Patches/0004-BungeeCord-Support.patch new file mode 100644 index 0000000000..205cc663f4 --- /dev/null +++ b/Bukkit-Patches/0004-BungeeCord-Support.patch @@ -0,0 +1,101 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 2 Jun 2013 15:20:49 +1000 +Subject: [PATCH] BungeeCord Support + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -0,0 +0,0 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline + * @see Player#setHealthScaled(boolean) + */ + public double getHealthScale(); ++ ++ // Spigot start ++ public class Spigot extends Entity.Spigot ++ { ++ ++ /** ++ * Gets the connection address of this player, regardless of whether it ++ * has been spoofed or not. ++ * ++ * @return the player's connection address ++ */ ++ public InetSocketAddress getRawAddress() ++ { ++ throw new UnsupportedOperationException( "Not supported yet." ); ++ } ++ } ++ ++ Spigot spigot(); ++ // Spigot end + } +diff --git a/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java b/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java +@@ -0,0 +0,0 @@ public class PlayerLoginEvent extends PlayerEvent { + private final String hostname; + private Result result = Result.ALLOWED; + private String message = ""; ++ private final InetAddress realAddress; // Spigot + + /** + * @deprecated Address should be provided in other constructor +@@ -0,0 +0,0 @@ public class PlayerLoginEvent extends PlayerEvent { + * @param address The address the player used to connect, provided for + * timing issues + */ +- public PlayerLoginEvent(final Player player, final String hostname, final InetAddress address) { ++ public PlayerLoginEvent(final Player player, final String hostname, final InetAddress address, final InetAddress realAddress) { // Spigot + super(player); + this.hostname = hostname; + this.address = address; ++ // Spigot start ++ this.realAddress = realAddress; ++ } ++ ++ public PlayerLoginEvent(final Player player, final String hostname, final InetAddress address) { ++ this(player, hostname, address, address); ++ // Spigot end + } + + /** +@@ -0,0 +0,0 @@ public class PlayerLoginEvent extends PlayerEvent { + */ + @Deprecated + public PlayerLoginEvent(final Player player, final Result result, final String message) { +- this(player, "", null, result, message); ++ this(player, "", null, result, message, null); // Spigot + } + + /** +@@ -0,0 +0,0 @@ public class PlayerLoginEvent extends PlayerEvent { + * @param result The result status for this event + * @param message The message to be displayed if result denies login + */ +- public PlayerLoginEvent(final Player player, String hostname, final InetAddress address, final Result result, final String message) { +- this(player, hostname, address); ++ public PlayerLoginEvent(final Player player, String hostname, final InetAddress address, final Result result, final String message, final InetAddress realAddress) { // Spigot ++ this(player, hostname, address, realAddress); // Spigot + this.result = result; + this.message = message; + } + ++ // Spigot start ++ /** ++ * Gets the connection address of this player, regardless of whether it has been spoofed or not. ++ * ++ * @return the player's connection address ++ */ ++ public InetAddress getRealAddress() { ++ return realAddress; ++ } ++ // Spigot end ++ + /** + * Gets the current result of the login, as an enum + * +-- \ No newline at end of file diff --git a/Bukkit-Patches/0005-Add-Arrow-API.patch b/Bukkit-Patches/0005-Add-Arrow-API.patch new file mode 100644 index 0000000000..50924773ac --- /dev/null +++ b/Bukkit-Patches/0005-Add-Arrow-API.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 2 Jun 2013 15:08:24 +1000 +Subject: [PATCH] Add Arrow API + + +diff --git a/src/main/java/org/bukkit/entity/Arrow.java b/src/main/java/org/bukkit/entity/Arrow.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/entity/Arrow.java ++++ b/src/main/java/org/bukkit/entity/Arrow.java +@@ -0,0 +0,0 @@ public interface Arrow extends Projectile { + * @param critical whether or not it should be critical + */ + public void setCritical(boolean critical); ++ ++ public class Spigot extends Entity.Spigot ++ { ++ ++ public double getDamage() ++ { ++ throw new UnsupportedOperationException( "Not supported yet." ); ++ } ++ ++ public void setDamage(double damage) ++ { ++ throw new UnsupportedOperationException( "Not supported yet." ); ++ } ++ } ++ ++ Spigot spigot(); + } +-- \ No newline at end of file diff --git a/Bukkit-Patches/0006-Add-Particle-API.patch b/Bukkit-Patches/0006-Add-Particle-API.patch new file mode 100644 index 0000000000..61158f9dfa --- /dev/null +++ b/Bukkit-Patches/0006-Add-Particle-API.patch @@ -0,0 +1,362 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 2 Jun 2013 15:57:09 +1000 +Subject: [PATCH] Add Particle API + + +diff --git a/src/main/java/org/bukkit/Effect.java b/src/main/java/org/bukkit/Effect.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/Effect.java ++++ b/src/main/java/org/bukkit/Effect.java +@@ -0,0 +0,0 @@ import java.util.Map; + import com.google.common.collect.Maps; + + import org.bukkit.block.BlockFace; ++import org.bukkit.material.MaterialData; + import org.bukkit.potion.Potion; + + /** +@@ -0,0 +0,0 @@ public enum Effect { + /** + * The flames seen on a mobspawner; a visual effect. + */ +- MOBSPAWNER_FLAMES(2004, Type.VISUAL); ++ MOBSPAWNER_FLAMES(2004, Type.VISUAL), ++ /** ++ * The spark that comes off a fireworks ++ */ ++ FIREWORKS_SPARK("fireworksSpark", Type.PARTICLE), ++ /** ++ * Critical hit particles ++ */ ++ CRIT("crit", Type.PARTICLE), ++ /** ++ * Blue critical hit particles ++ */ ++ MAGIC_CRIT("magicCrit", Type.PARTICLE), ++ /** ++ * Multicolored potion effect particles ++ */ ++ POTION_SWIRL("mobSpell", Type.PARTICLE), ++ /** ++ * Multicolored potion effect particles that are slightly transparent ++ */ ++ POTION_SWIRL_TRANSPARENT("mobSpellAmbient", Type.PARTICLE), ++ /** ++ * A puff of white potion swirls ++ */ ++ SPELL("spell", Type.PARTICLE), ++ /** ++ * A puff of white stars ++ */ ++ INSTANT_SPELL("instantSpell", Type.PARTICLE), ++ /** ++ * A puff of purple particles ++ */ ++ WITCH_MAGIC("witchMagic", Type.PARTICLE), ++ /** ++ * The note that appears above note blocks ++ */ ++ NOTE("note", Type.PARTICLE), ++ /** ++ * The particles shown at nether portals ++ */ ++ PORTAL("portal", Type.PARTICLE), ++ /** ++ * The symbols that fly towards the enchantment table ++ */ ++ FLYING_GLYPH("enchantmenttable", Type.PARTICLE), ++ /** ++ * Fire particles ++ */ ++ FLAME("flame", Type.PARTICLE), ++ /** ++ * The particles that pop out of lava ++ */ ++ LAVA_POP("lava", Type.PARTICLE), ++ /** ++ * A small gray square ++ */ ++ FOOTSTEP("footstep", Type.PARTICLE), ++ /** ++ * Water particles ++ */ ++ SPLASH("splash", Type.PARTICLE), ++ /** ++ * Smoke particles ++ */ ++ PARTICLE_SMOKE("smoke", Type.PARTICLE), ++ /** ++ * The biggest explosion particle effect ++ */ ++ EXPLOSION_HUGE("hugeexplosion", Type.PARTICLE), ++ /** ++ * A larger version of the explode particle ++ */ ++ EXPLOSION_LARGE("largeexplode", Type.PARTICLE), ++ /** ++ * Explosion particles ++ */ ++ EXPLOSION("explode", Type.PARTICLE), ++ /** ++ * Small gray particles ++ */ ++ VOID_FOG("depthsuspend", Type.PARTICLE), ++ /** ++ * Small gray particles ++ */ ++ SMALL_SMOKE("townaura", Type.PARTICLE), ++ /** ++ * A puff of white smoke ++ */ ++ CLOUD("cloud", Type.PARTICLE), ++ /** ++ * Multicolored dust particles ++ */ ++ COLOURED_DUST("reddust", Type.PARTICLE), ++ /** ++ * Snowball breaking ++ */ ++ SNOWBALL_BREAK("snowballpoof", Type.PARTICLE), ++ /** ++ * The water drip particle that appears on blocks under water ++ */ ++ WATERDRIP("dripWater", Type.PARTICLE), ++ /** ++ * The lava drip particle that appears on blocks under lava ++ */ ++ LAVADRIP("dripLava", Type.PARTICLE), ++ /** ++ * White particles ++ */ ++ SNOW_SHOVEL("snowshovel", Type.PARTICLE), ++ /** ++ * The particle shown when a slime jumps ++ */ ++ SLIME("slime", Type.PARTICLE), ++ /** ++ * The particle that appears when breading animals ++ */ ++ HEART("heart", Type.PARTICLE), ++ /** ++ * The particle that appears when hitting a villager ++ */ ++ VILLAGER_THUNDERCLOUD("angryVillager", Type.PARTICLE), ++ /** ++ * The particle that appears when trading with a villager ++ */ ++ HAPPY_VILLAGER("happyVillager", Type.PARTICLE), ++ /** ++ * The particles generated when a tool breaks. ++ * This particle requires a Material so that the client can select the correct texture. ++ */ ++ ITEM_BREAK("iconcrack", Type.PARTICLE, Material.class), ++ /** ++ * The particles generated while breaking a block. ++ * This particle requires a Material and data value so that the client can select the correct texture. ++ */ ++ TILE_BREAK("blockcrack", Type.PARTICLE, MaterialData.class), ++ /** ++ * The particles generated while sprinting a block ++ * This particle requires a Material and data value so that the client can select the correct texture. ++ */ ++ TILE_DUST("blockdust", Type.PARTICLE, MaterialData.class); + + private final int id; + private final Type type; + private final Class data; + private static final Map BY_ID = Maps.newHashMap(); ++ private static final Map BY_NAME = Maps.newHashMap(); ++ private final String particleName; + +- Effect(int id, Type type) { ++ private Effect(int id, Type type) { + this(id,type,null); + } + +- Effect(int id, Type type, Class data) { ++ private Effect(int id, Type type, Class data) { + this.id = id; + this.type = type; + this.data = data; ++ particleName = null; ++ } ++ ++ private Effect(String particleName, Type type, Class data) { ++ this.particleName = particleName; ++ this.type = type; ++ id = 0; ++ this.data = data; ++ } ++ ++ private Effect(String particleName, Type type) { ++ this.particleName = particleName; ++ this.type = type; ++ id = 0; ++ this.data = null; + } + + /** + * Gets the ID for this effect. + * +- * @return ID of this effect ++ * @return if this Effect isn't of type PARTICLE it returns ID of this effect + * @deprecated Magic value + */ + @Deprecated +@@ -0,0 +0,0 @@ public enum Effect { + } + + /** ++ * Returns the effect's name. This returns null if the effect is not a particle ++ * ++ * @return The effect's name ++ */ ++ public String getName() { ++ return particleName; ++ } ++ ++ /** + * @return The type of the effect. + */ + public Type getType() { +@@ -0,0 +0,0 @@ public enum Effect { + } + + /** +- * @return The class which represents data for this effect, or null if +- * none ++ * @return if this Effect isn't of type PARTICLE it returns the class which represents data for this effect, or null if none + */ + public Class getData() { + return this.data; +@@ -0,0 +0,0 @@ public enum Effect { + + static { + for (Effect effect : values()) { +- BY_ID.put(effect.id, effect); ++ if (effect.type != Type.PARTICLE) { ++ BY_ID.put(effect.id, effect); ++ } ++ } ++ } ++ ++ /** ++ * Gets the Effect associated with the given name. ++ * ++ * @param name name of the Effect to return ++ * @return Effect with the given name ++ */ ++ public static Effect getByName(String name) { ++ return BY_NAME.get(name); ++ } ++ ++ static { ++ for (Effect effect : values()) { ++ if (effect.type == Type.PARTICLE) { ++ BY_NAME.put(effect.particleName, effect); ++ } + } + } + + /** + * Represents the type of an effect. + */ +- public enum Type {SOUND, VISUAL} ++ public enum Type {SOUND, VISUAL, PARTICLE} + } +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -0,0 +0,0 @@ public interface World extends PluginMessageRecipient, Metadatable { + */ + public boolean isGameRule(String rule); + ++ // Spigot start ++ public class Spigot ++ { ++ ++ /** ++ * Plays an effect to all players within a default radius around a given ++ * location. ++ * ++ * @param location the {@link Location} around which players must be to ++ * see the effect ++ * @param effect the {@link Effect} ++ * @throws IllegalArgumentException if the location or effect is null. ++ * It also throws when the effect requires a material or a material data ++ */ ++ public void playEffect(Location location, Effect effect) ++ { ++ throw new UnsupportedOperationException( "Not supported yet." ); ++ } ++ ++ /** ++ * Plays an effect to all players within a default radius around a given ++ * location. The effect will use the provided material (and material ++ * data if required). The particle's position on the client will be the ++ * given location, adjusted on each axis by a normal distribution with ++ * mean 0 and standard deviation given in the offset parameters, each ++ * particle has independently calculated offsets. The effect will have ++ * the given speed and particle count if the effect is a particle. Some ++ * effect will create multiple particles. ++ * ++ * @param location the {@link Location} around which players must be to ++ * see the effect ++ * @param effect effect the {@link Effect} ++ * @param id the item/block/data id for the effect ++ * @param data the data value of the block/item for the effect ++ * @param offsetX the amount to be randomly offset by in the X axis ++ * @param offsetY the amount to be randomly offset by in the Y axis ++ * @param offsetZ the amount to be randomly offset by in the Z axis ++ * @param speed the speed of the particles ++ * @param particleCount the number of particles ++ * @param radius the radius around the location ++ */ ++ public void playEffect(Location location, Effect effect, int id, int data, float offsetX, float offsetY, float offsetZ, float speed, int particleCount, int radius) ++ { ++ throw new UnsupportedOperationException( "Not supported yet." ); ++ } ++ } ++ ++ Spigot spigot(); ++ // Spigot end ++ + /** + * Represents various map environment types that a world may be + */ +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -0,0 +0,0 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline + { + throw new UnsupportedOperationException( "Not supported yet." ); + } ++ ++ public void playEffect(Location location, Effect effect, int id, int data, float offsetX, float offsetY, float offsetZ, float speed, int particleCount, int radius) ++ { ++ throw new UnsupportedOperationException( "Not supported yet." ); ++ } + } + + Spigot spigot(); +diff --git a/src/test/java/org/bukkit/EffectTest.java b/src/test/java/org/bukkit/EffectTest.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/test/java/org/bukkit/EffectTest.java ++++ b/src/test/java/org/bukkit/EffectTest.java +@@ -0,0 +0,0 @@ public class EffectTest { + @Test + public void getById() { + for (Effect effect : Effect.values()) { +- assertThat(Effect.getById(effect.getId()), is(effect)); ++ if (effect.getType() != Effect.Type.PARTICLE) { ++ assertThat(Effect.getById(effect.getId()), is(effect)); ++ } else { ++ assertThat(Effect.getByName(effect.getName()), is(effect)); ++ } + } + } + } +-- \ No newline at end of file diff --git a/Bukkit-Patches/0007-Define-EntitySpawnEvent-and-SpawnerSpawnEvent.patch b/Bukkit-Patches/0007-Define-EntitySpawnEvent-and-SpawnerSpawnEvent.patch new file mode 100644 index 0000000000..801d762957 --- /dev/null +++ b/Bukkit-Patches/0007-Define-EntitySpawnEvent-and-SpawnerSpawnEvent.patch @@ -0,0 +1,218 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andy Shulman +Date: Mon, 15 Apr 2013 20:06:01 -0500 +Subject: [PATCH] Define EntitySpawnEvent and SpawnerSpawnEvent + +Defines EntitySpawnEvent and SpawnerSpawnEvent. Adds BUKKIT-267 and BUKKIT-1559 + +diff --git a/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java b/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java ++++ b/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java +@@ -0,0 +0,0 @@ import org.bukkit.Location; + import org.bukkit.entity.CreatureType; + import org.bukkit.entity.Entity; + import org.bukkit.entity.LivingEntity; +-import org.bukkit.event.Cancellable; +-import org.bukkit.event.HandlerList; + + /** + * Called when a creature is spawned into a world. + *

+ * If a Creature Spawn event is cancelled, the creature will not spawn. + */ +-public class CreatureSpawnEvent extends EntityEvent implements Cancellable { +- private static final HandlerList handlers = new HandlerList(); +- private boolean canceled; ++public class CreatureSpawnEvent extends EntitySpawnEvent { + private final SpawnReason spawnReason; + + public CreatureSpawnEvent(final LivingEntity spawnee, final SpawnReason spawnReason) { +@@ -0,0 +0,0 @@ public class CreatureSpawnEvent extends EntityEvent implements Cancellable { + spawnReason = reason; + } + +- public boolean isCancelled() { +- return canceled; +- } +- +- public void setCancelled(boolean cancel) { +- canceled = cancel; +- } +- + @Override + public LivingEntity getEntity() { + return (LivingEntity) entity; + } + + /** +- * Gets the location at which the creature is spawning. +- * +- * @return The location at which the creature is spawning +- */ +- public Location getLocation() { +- return getEntity().getLocation(); +- } +- +- /** + * Gets the type of creature being spawned. + * + * @return A CreatureType value detailing the type of creature being +@@ -0,0 +0,0 @@ public class CreatureSpawnEvent extends EntityEvent implements Cancellable { + return spawnReason; + } + +- @Override +- public HandlerList getHandlers() { +- return handlers; +- } +- +- public static HandlerList getHandlerList() { +- return handlers; +- } +- + /** + * An enum to specify the type of spawning + */ +diff --git a/src/main/java/org/bukkit/event/entity/EntitySpawnEvent.java b/src/main/java/org/bukkit/event/entity/EntitySpawnEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/org/bukkit/event/entity/EntitySpawnEvent.java +@@ -0,0 +0,0 @@ ++package org.bukkit.event.entity; ++ ++import org.bukkit.Location; ++import org.bukkit.entity.Entity; ++import org.bukkit.event.HandlerList; ++ ++/** ++ * Called when an entity is spawned into a world. ++ *

++ * If an Entity Spawn event is cancelled, the entity will not spawn. ++ */ ++public class EntitySpawnEvent extends EntityEvent implements org.bukkit.event.Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean canceled; ++ ++ public EntitySpawnEvent(final Entity spawnee) { ++ super(spawnee); ++ } ++ ++ public boolean isCancelled() { ++ return canceled; ++ } ++ ++ public void setCancelled(boolean cancel) { ++ canceled = cancel; ++ } ++ ++ /** ++ * Gets the location at which the entity is spawning. ++ * ++ * @return The location at which the entity is spawning ++ */ ++ public Location getLocation() { ++ return getEntity().getLocation(); ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +diff --git a/src/main/java/org/bukkit/event/entity/ItemSpawnEvent.java b/src/main/java/org/bukkit/event/entity/ItemSpawnEvent.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/event/entity/ItemSpawnEvent.java ++++ b/src/main/java/org/bukkit/event/entity/ItemSpawnEvent.java +@@ -0,0 +0,0 @@ + package org.bukkit.event.entity; + +-import org.bukkit.entity.Item; + import org.bukkit.Location; +-import org.bukkit.event.Cancellable; +-import org.bukkit.event.HandlerList; ++import org.bukkit.entity.Item; + + /** + * Called when an item is spawned into a world + */ +-public class ItemSpawnEvent extends EntityEvent implements Cancellable { +- private static final HandlerList handlers = new HandlerList(); +- private final Location location; +- private boolean canceled; +- +- public ItemSpawnEvent(final Item spawnee, final Location loc) { ++public class ItemSpawnEvent extends EntitySpawnEvent { ++ public ItemSpawnEvent(final Item spawnee) { + super(spawnee); +- this.location = loc; + } + +- public boolean isCancelled() { +- return canceled; +- } +- +- public void setCancelled(boolean cancel) { +- canceled = cancel; ++ @Deprecated ++ public ItemSpawnEvent(final Item spawnee, final Location loc) { ++ this(spawnee); + } + + @Override + public Item getEntity() { + return (Item) entity; + } +- +- /** +- * Gets the location at which the item is spawning. +- * +- * @return The location at which the item is spawning +- */ +- public Location getLocation() { +- return location; +- } +- +- @Override +- public HandlerList getHandlers() { +- return handlers; +- } +- +- public static HandlerList getHandlerList() { +- return handlers; +- } + } +diff --git a/src/main/java/org/bukkit/event/entity/SpawnerSpawnEvent.java b/src/main/java/org/bukkit/event/entity/SpawnerSpawnEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/org/bukkit/event/entity/SpawnerSpawnEvent.java +@@ -0,0 +0,0 @@ ++package org.bukkit.event.entity; ++ ++import org.bukkit.block.CreatureSpawner; ++import org.bukkit.entity.Entity; ++ ++/** ++ * Called when an entity is spawned into a world by a spawner. ++ *

++ * If a Spawner Spawn event is cancelled, the entity will not spawn. ++ */ ++public class SpawnerSpawnEvent extends EntitySpawnEvent { ++ private final CreatureSpawner spawner; ++ ++ public SpawnerSpawnEvent(final Entity spawnee, final CreatureSpawner spawner) { ++ super(spawnee); ++ this.spawner = spawner; ++ } ++ ++ public CreatureSpawner getSpawner() { ++ return spawner; ++ } ++} +-- \ No newline at end of file diff --git a/Bukkit-Patches/0008-Entity-Mount-and-Dismount-Events.patch b/Bukkit-Patches/0008-Entity-Mount-and-Dismount-Events.patch new file mode 100644 index 0000000000..7faf7592ca --- /dev/null +++ b/Bukkit-Patches/0008-Entity-Mount-and-Dismount-Events.patch @@ -0,0 +1,110 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Tue, 2 Jul 2013 20:32:53 +1000 +Subject: [PATCH] Entity Mount and Dismount Events + + +diff --git a/src/main/java/org/spigotmc/event/entity/EntityDismountEvent.java b/src/main/java/org/spigotmc/event/entity/EntityDismountEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/org/spigotmc/event/entity/EntityDismountEvent.java +@@ -0,0 +0,0 @@ ++package org.spigotmc.event.entity; ++ ++import org.bukkit.entity.Entity; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++ ++/** ++ * Called when an entity stops riding another entity. ++ * ++ */ ++public class EntityDismountEvent extends EntityEvent ++{ ++ ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean cancelled; ++ private final Entity dismounted; ++ ++ public EntityDismountEvent(Entity what, Entity dismounted) ++ { ++ super( what ); ++ this.dismounted = dismounted; ++ } ++ ++ public Entity getDismounted() ++ { ++ return dismounted; ++ } ++ ++ @Override ++ public HandlerList getHandlers() ++ { ++ return handlers; ++ } ++ ++ public static HandlerList getHandlerList() ++ { ++ return handlers; ++ } ++} +diff --git a/src/main/java/org/spigotmc/event/entity/EntityMountEvent.java b/src/main/java/org/spigotmc/event/entity/EntityMountEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/org/spigotmc/event/entity/EntityMountEvent.java +@@ -0,0 +0,0 @@ ++package org.spigotmc.event.entity; ++ ++import org.bukkit.entity.Entity; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++ ++/** ++ * Called when an entity attempts to ride another entity. ++ * ++ */ ++public class EntityMountEvent extends EntityEvent implements Cancellable ++{ ++ ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean cancelled; ++ private final Entity mount; ++ ++ public EntityMountEvent(Entity what, Entity mount) ++ { ++ super( what ); ++ this.mount = mount; ++ } ++ ++ public Entity getMount() ++ { ++ return mount; ++ } ++ ++ @Override ++ public boolean isCancelled() ++ { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) ++ { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public HandlerList getHandlers() ++ { ++ return handlers; ++ } ++ ++ public static HandlerList getHandlerList() ++ { ++ return handlers; ++ } ++} +-- \ No newline at end of file diff --git a/Bukkit-Patches/0009-Update-Depends.patch b/Bukkit-Patches/0009-Update-Depends.patch new file mode 100644 index 0000000000..ddfabd3f6b --- /dev/null +++ b/Bukkit-Patches/0009-Update-Depends.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Thu, 4 Jul 2013 20:05:19 +1000 +Subject: [PATCH] Update Depends + +- All of these changes have been reviewed to be binary compatible and in general contract compatible with previous versions of the libraries. + +diff --git a/pom.xml b/pom.xml +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -0,0 +0,0 @@ + + org.yaml + snakeyaml +- 1.9 ++ 1.12 + jar + compile + + + com.googlecode.json-simple + json-simple +- 1.1 ++ 1.1.1 + jar + compile + + + org.avaje + ebean +- 2.7.3 ++ 2.8.1 + jar + compile + +@@ -0,0 +0,0 @@ + + commons-lang + commons-lang +- 2.3 ++ 2.6 + + + +-- \ No newline at end of file diff --git a/Bukkit-Patches/0010-InventoryClickEvent-getClickedInventory.patch b/Bukkit-Patches/0010-InventoryClickEvent-getClickedInventory.patch new file mode 100644 index 0000000000..a268b860be --- /dev/null +++ b/Bukkit-Patches/0010-InventoryClickEvent-getClickedInventory.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 7 Jul 2013 10:32:05 -0400 +Subject: [PATCH] InventoryClickEvent getClickedInventory + +Add InventoryClickEvent.getClickedInventory. Adds BUKKIT-4495 +Plugins currently have to do the logic themselves on the raw slot ID +in order to determine the inventory clicked. This provides the logic for plugins to +readily identify which inventory was clicked. + +diff --git a/src/main/java/org/bukkit/event/inventory/InventoryClickEvent.java b/src/main/java/org/bukkit/event/inventory/InventoryClickEvent.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/event/inventory/InventoryClickEvent.java ++++ b/src/main/java/org/bukkit/event/inventory/InventoryClickEvent.java +@@ -0,0 +0,0 @@ public class InventoryClickEvent extends InventoryInteractEvent { + private static final HandlerList handlers = new HandlerList(); + private final ClickType click; + private final InventoryAction action; ++ private final Inventory clickedInventory; + private SlotType slot_type; + private int whichSlot; + private int rawSlot; +@@ -0,0 +0,0 @@ public class InventoryClickEvent extends InventoryInteractEvent { + super(view); + this.slot_type = type; + this.rawSlot = slot; ++ if (slot < 0) { ++ this.clickedInventory = null; ++ } else if (view.getTopInventory() != null && slot < view.getTopInventory().getSize()) { ++ this.clickedInventory = view.getTopInventory(); ++ } else { ++ this.clickedInventory = view.getBottomInventory(); ++ } + this.whichSlot = view.convertSlot(slot); + this.click = click; + this.action = action; +@@ -0,0 +0,0 @@ public class InventoryClickEvent extends InventoryInteractEvent { + } + + /** ++ * Gets the inventory that was clicked, or null if outside of window ++ * @return The clicked inventory ++ */ ++ public Inventory getClickedInventory() { ++ return clickedInventory; ++ } ++ ++ /** + * Gets the type of slot that was clicked. + * + * @return the slot type +-- \ No newline at end of file diff --git a/Bukkit-Patches/0011-Added-getAllSessionData-to-the-Conversation-API.patch b/Bukkit-Patches/0011-Added-getAllSessionData-to-the-Conversation-API.patch new file mode 100644 index 0000000000..4f84484293 --- /dev/null +++ b/Bukkit-Patches/0011-Added-getAllSessionData-to-the-Conversation-API.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alex Bennett +Date: Thu, 11 Jul 2013 15:31:32 -0500 +Subject: [PATCH] Added getAllSessionData() to the Conversation API. + + +diff --git a/src/main/java/org/bukkit/conversations/ConversationContext.java b/src/main/java/org/bukkit/conversations/ConversationContext.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/conversations/ConversationContext.java ++++ b/src/main/java/org/bukkit/conversations/ConversationContext.java +@@ -0,0 +0,0 @@ public class ConversationContext { + } + + /** ++ * Gets the entire sessionData map. ++ * @return The full sessionData map. ++ */ ++ public Map getAllSessionData() { ++ return sessionData; ++ } ++ ++ /** + * Gets session data shared between all {@link Prompt} invocations. Use + * this as a way to pass data through each Prompt as the conversation + * develops. +-- \ No newline at end of file diff --git a/Bukkit-Patches/0012-Catch-Conversation-API-Errors.patch b/Bukkit-Patches/0012-Catch-Conversation-API-Errors.patch new file mode 100644 index 0000000000..09acabbac9 --- /dev/null +++ b/Bukkit-Patches/0012-Catch-Conversation-API-Errors.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Mon, 22 Jul 2013 19:09:43 +1000 +Subject: [PATCH] Catch Conversation API Errors + + +diff --git a/src/main/java/org/bukkit/conversations/Conversation.java b/src/main/java/org/bukkit/conversations/Conversation.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/conversations/Conversation.java ++++ b/src/main/java/org/bukkit/conversations/Conversation.java +@@ -0,0 +0,0 @@ public class Conversation { + * @param input The user's chat text. + */ + public void acceptInput(String input) { ++ try { // Spigot + if (currentPrompt != null) { + + // Echo the user's input +@@ -0,0 +0,0 @@ public class Conversation { + currentPrompt = currentPrompt.acceptInput(context, input); + outputNextPrompt(); + } ++ // Spigot Start ++ } catch ( Throwable t ) ++ { ++ org.bukkit.Bukkit.getLogger().log( java.util.logging.Level.SEVERE, "Error handling conversation prompt", t ); ++ } ++ // Spigot End + } + + /** +-- \ No newline at end of file diff --git a/Bukkit-Patches/0013-Player-Collision-API.patch b/Bukkit-Patches/0013-Player-Collision-API.patch new file mode 100644 index 0000000000..c7975aeff1 --- /dev/null +++ b/Bukkit-Patches/0013-Player-Collision-API.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 3 Aug 2013 19:20:50 +1000 +Subject: [PATCH] Player Collision API + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -0,0 +0,0 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline + { + throw new UnsupportedOperationException( "Not supported yet." ); + } ++ ++ /** ++ * Gets whether the player collides with entities ++ * ++ * @return the player's collision toggle state ++ */ ++ public boolean getCollidesWithEntities() ++ { ++ throw new UnsupportedOperationException( "Not supported yet." ); ++ } ++ ++ /** ++ * Sets whether the player collides with entities ++ * ++ * @param collides whether the player should collide with entities or ++ * not. ++ */ ++ public void setCollidesWithEntities(boolean collides) ++ { ++ throw new UnsupportedOperationException( "Not supported yet." ); ++ } + } + + Spigot spigot(); +-- \ No newline at end of file diff --git a/Bukkit-Patches/0014-Expand-Boolean-Prompt-Values.patch b/Bukkit-Patches/0014-Expand-Boolean-Prompt-Values.patch new file mode 100644 index 0000000000..2bfe05c4e2 --- /dev/null +++ b/Bukkit-Patches/0014-Expand-Boolean-Prompt-Values.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 3 Aug 2013 19:42:16 +1000 +Subject: [PATCH] Expand Boolean Prompt Values + + +diff --git a/src/main/java/org/bukkit/conversations/BooleanPrompt.java b/src/main/java/org/bukkit/conversations/BooleanPrompt.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/conversations/BooleanPrompt.java ++++ b/src/main/java/org/bukkit/conversations/BooleanPrompt.java +@@ -0,0 +0,0 @@ public abstract class BooleanPrompt extends ValidatingPrompt{ + + @Override + protected boolean isInputValid(ConversationContext context, String input) { +- String[] accepted = {"true", "false", "on", "off", "yes", "no"}; ++ String[] accepted = {"true", "false", "on", "off", "yes", "no" /* Spigot: */, "y", "n", "1", "0", "right", "wrong", "correct", "incorrect", "valid", "invalid"}; // Spigot + return ArrayUtils.contains(accepted, input.toLowerCase()); + } + + @Override + protected Prompt acceptValidatedInput(ConversationContext context, String input) { ++ if (input.equalsIgnoreCase("y") || input.equals("1") || input.equalsIgnoreCase("right") || input.equalsIgnoreCase("correct") || input.equalsIgnoreCase("valid")) input = "true"; // Spigot + return acceptValidatedInput(context, BooleanUtils.toBoolean(input)); + } + +-- \ No newline at end of file diff --git a/Bukkit-Patches/0015-Add-Getter-for-Entity-Invulnerability.patch b/Bukkit-Patches/0015-Add-Getter-for-Entity-Invulnerability.patch new file mode 100644 index 0000000000..864bbf1866 --- /dev/null +++ b/Bukkit-Patches/0015-Add-Getter-for-Entity-Invulnerability.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 3 Aug 2013 19:49:36 +1000 +Subject: [PATCH] Add Getter for Entity Invulnerability + + +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -0,0 +0,0 @@ public interface Entity extends Metadatable { + * @return The current vehicle. + */ + public Entity getVehicle(); ++ ++ // Spigot Start ++ public class Spigot ++ { ++ ++ /** ++ * Returns whether this entity is invulnerable. ++ * ++ * @return True if the entity is invulnerable. ++ */ ++ public boolean isInvulnerable() ++ { ++ throw new UnsupportedOperationException( "Not supported yet." ); ++ } ++ } ++ ++ Spigot spigot(); ++ // Spigot End + } +-- \ No newline at end of file diff --git a/Bukkit-Patches/0016-Add-respawn-API.patch b/Bukkit-Patches/0016-Add-respawn-API.patch new file mode 100644 index 0000000000..a0f68511cc --- /dev/null +++ b/Bukkit-Patches/0016-Add-respawn-API.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ninja- +Date: Tue, 8 Oct 2013 14:35:58 +0200 +Subject: [PATCH] Add respawn API. + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -0,0 +0,0 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline + { + throw new UnsupportedOperationException( "Not supported yet." ); + } ++ ++ /** ++ * Respawns the player if dead. ++ */ ++ public void respawn() ++ { ++ throw new UnsupportedOperationException( "Not supported yet." ); ++ } + } + + Spigot spigot(); +-- \ No newline at end of file diff --git a/Bukkit-Patches/0017-Fix-Plugin-Message-API-Disconnects.patch b/Bukkit-Patches/0017-Fix-Plugin-Message-API-Disconnects.patch new file mode 100644 index 0000000000..9411f4ebec --- /dev/null +++ b/Bukkit-Patches/0017-Fix-Plugin-Message-API-Disconnects.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 19 Oct 2013 12:59:42 +1100 +Subject: [PATCH] Fix Plugin Message API Disconnects + + +diff --git a/src/main/java/org/bukkit/plugin/messaging/StandardMessenger.java b/src/main/java/org/bukkit/plugin/messaging/StandardMessenger.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/plugin/messaging/StandardMessenger.java ++++ b/src/main/java/org/bukkit/plugin/messaging/StandardMessenger.java +@@ -0,0 +0,0 @@ public class StandardMessenger implements Messenger { + Set registrations = getIncomingChannelRegistrations(channel); + + for (PluginMessageListenerRegistration registration : registrations) { +- registration.getListener().onPluginMessageReceived(channel, source, message); ++ // Spigot Start ++ try ++ { ++ registration.getListener().onPluginMessageReceived( channel, source, message ); ++ } catch ( Throwable t ) ++ { ++ org.bukkit.Bukkit.getLogger().log( java.util.logging.Level.WARNING, "Could not pass incoming plugin message to " + registration.getPlugin(), t ); ++ } ++ // Spigot End + } + } + +-- \ No newline at end of file diff --git a/Bukkit-Patches/0018-Fix-Tab-Completion-for-Some-Commands.patch b/Bukkit-Patches/0018-Fix-Tab-Completion-for-Some-Commands.patch new file mode 100644 index 0000000000..b10f77778f --- /dev/null +++ b/Bukkit-Patches/0018-Fix-Tab-Completion-for-Some-Commands.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Tue, 24 Dec 2013 10:14:25 +1100 +Subject: [PATCH] Fix Tab Completion for Some Commands + + +diff --git a/src/main/java/org/bukkit/command/defaults/PluginsCommand.java b/src/main/java/org/bukkit/command/defaults/PluginsCommand.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/command/defaults/PluginsCommand.java ++++ b/src/main/java/org/bukkit/command/defaults/PluginsCommand.java +@@ -0,0 +0,0 @@ public class PluginsCommand extends BukkitCommand { + + return "(" + plugins.length + "): " + pluginList.toString(); + } ++ ++ // Spigot Start ++ @Override ++ public java.util.List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException ++ { ++ return java.util.Collections.emptyList(); ++ } ++ // Spigot End + } +diff --git a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java ++++ b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java +@@ -0,0 +0,0 @@ public class ReloadCommand extends BukkitCommand { + + return true; + } ++ ++ // Spigot Start ++ @Override ++ public java.util.List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException ++ { ++ return java.util.Collections.emptyList(); ++ } ++ // Spigot End + } +diff --git a/src/main/java/org/bukkit/command/defaults/TellCommand.java b/src/main/java/org/bukkit/command/defaults/TellCommand.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/command/defaults/TellCommand.java ++++ b/src/main/java/org/bukkit/command/defaults/TellCommand.java +@@ -0,0 +0,0 @@ public class TellCommand extends VanillaCommand { + + return true; + } ++ ++ // Spigot Start ++ @Override ++ public java.util.List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException ++ { ++ if ( args.length == 0 ) ++ { ++ return super.tabComplete( sender, alias, args ); ++ } ++ return java.util.Collections.emptyList(); ++ } ++ // Spigot End + } +diff --git a/src/main/java/org/bukkit/command/defaults/TestForCommand.java b/src/main/java/org/bukkit/command/defaults/TestForCommand.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/command/defaults/TestForCommand.java ++++ b/src/main/java/org/bukkit/command/defaults/TestForCommand.java +@@ -0,0 +0,0 @@ public class TestForCommand extends VanillaCommand { + sender.sendMessage(ChatColor.RED + "/testfor is only usable by commandblocks with analog output."); + return true; + } ++ ++ // Spigot Start ++ @Override ++ public java.util.List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException ++ { ++ if ( args.length == 0 ) ++ { ++ return super.tabComplete( sender, alias, args ); ++ } ++ return java.util.Collections.emptyList(); ++ } ++ // Spigot End + } +-- \ No newline at end of file diff --git a/Bukkit-Patches/0019-Add-Spigot-Links.patch b/Bukkit-Patches/0019-Add-Spigot-Links.patch new file mode 100644 index 0000000000..f4b9a5b931 --- /dev/null +++ b/Bukkit-Patches/0019-Add-Spigot-Links.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Thu, 23 Jan 2014 13:17:38 +1100 +Subject: [PATCH] Add Spigot Links + + +diff --git a/README.md b/README.md +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/README.md ++++ b/README.md +@@ -0,0 +0,0 @@ +-Bukkit ++Spigot-API + ====== + + A Minecraft Server API. + +-Website: [http://bukkit.org](http://bukkit.org) +-Bugs/Suggestions: [http://leaky.bukkit.org](http://leaky.bukkit.org) +-Contributing Guidelines: [CONTRIBUTING.md](https://github.com/Bukkit/Bukkit/blob/master/CONTRIBUTING.md) ++Website: [http://spigotmc.org](http://spigotmc.org) ++Bugs/Suggestions: [http://www.spigotmc.org/forums/bugs-feature-requests.8/](http://www.spigotmc.org/forums/bugs-feature-requests.8/) ++Contributing Guidelines: [CONTRIBUTING.md](https://github.com/SpigotMC/Spigot-API/blob/master/CONTRIBUTING.md) + + Compilation + ----------- +-- \ No newline at end of file diff --git a/Bukkit-Patches/0020-Implement-Locale-Getter-for-Players.patch b/Bukkit-Patches/0020-Implement-Locale-Getter-for-Players.patch new file mode 100644 index 0000000000..63beb797b6 --- /dev/null +++ b/Bukkit-Patches/0020-Implement-Locale-Getter-for-Players.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Smove +Date: Sat, 1 Feb 2014 18:10:49 +1100 +Subject: [PATCH] Implement Locale Getter for Players + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -0,0 +0,0 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline + { + throw new UnsupportedOperationException( "Not supported yet." ); + } ++ ++ /** ++ * Gets player locale language. ++ * ++ * @return the player's client language settings ++ */ ++ public String getLocale() ++ { ++ throw new UnsupportedOperationException( "Not supported yet." ); ++ } + } + + Spigot spigot(); +-- \ No newline at end of file diff --git a/Bukkit-Patches/0021-Add-support-for-fetching-hidden-players.patch b/Bukkit-Patches/0021-Add-support-for-fetching-hidden-players.patch new file mode 100644 index 0000000000..ba76efb263 --- /dev/null +++ b/Bukkit-Patches/0021-Add-support-for-fetching-hidden-players.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tux +Date: Sun, 9 Feb 2014 14:02:11 -0500 +Subject: [PATCH] Add support for fetching hidden players + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -0,0 +0,0 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline + { + throw new UnsupportedOperationException( "Not supported yet." ); + } ++ ++ /** ++ * Gets all players hidden with {@link hidePlayer(org.bukkit.entity.Player)}. ++ * ++ * @return a Set with all hidden players ++ */ ++ public java.util.Set getHiddenPlayers() ++ { ++ throw new UnsupportedOperationException( "Not supported yet." ); ++ } + } + + Spigot spigot(); +-- \ No newline at end of file diff --git a/Bukkit-Patches/0022-Silenceable-Lightning-API.patch b/Bukkit-Patches/0022-Silenceable-Lightning-API.patch new file mode 100644 index 0000000000..afeebfd685 --- /dev/null +++ b/Bukkit-Patches/0022-Silenceable-Lightning-API.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: drXor +Date: Sun, 23 Feb 2014 16:16:29 -0400 +Subject: [PATCH] Silenceable Lightning API + + +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -0,0 +0,0 @@ public interface World extends PluginMessageRecipient, Metadatable { + { + throw new UnsupportedOperationException( "Not supported yet." ); + } ++ ++ /** ++ * Strikes lightning at the given {@link Location} and possibly without sound ++ * ++ * @param loc The location to strike lightning ++ * @param isSilent Whether this strike makes no sound ++ * @return The lightning entity. ++ */ ++ public LightningStrike strikeLightning(Location loc, boolean isSilent) ++ { ++ throw new UnsupportedOperationException( "Not supported yet." ); ++ } ++ ++ /** ++ * Strikes lightning at the given {@link Location} without doing damage and possibly without sound ++ * ++ * @param loc The location to strike lightning ++ * @param isSilent Whether this strike makes no sound ++ * @return The lightning entity. ++ */ ++ public LightningStrike strikeLightningEffect(Location loc, boolean isSilent) ++ { ++ throw new UnsupportedOperationException( "Not supported yet." ); ++ } + } + + Spigot spigot(); +diff --git a/src/main/java/org/bukkit/entity/LightningStrike.java b/src/main/java/org/bukkit/entity/LightningStrike.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/entity/LightningStrike.java ++++ b/src/main/java/org/bukkit/entity/LightningStrike.java +@@ -0,0 +0,0 @@ public interface LightningStrike extends Weather { + */ + public boolean isEffect(); + ++ ++ public class Spigot extends Entity.Spigot ++ { ++ ++ /* ++ * Returns whether the strike is silent. ++ * ++ * @return whether the strike is silent. ++ */ ++ public boolean isSilent() ++ { ++ throw new UnsupportedOperationException( "Not supported yet." ); ++ } ++ ++ } ++ ++ Spigot spigot(); + } +-- \ No newline at end of file diff --git a/Bukkit-Patches/0023-Remove-deprecation-on-some-player-lookup-methods.patch b/Bukkit-Patches/0023-Remove-deprecation-on-some-player-lookup-methods.patch new file mode 100644 index 0000000000..02263123d8 --- /dev/null +++ b/Bukkit-Patches/0023-Remove-deprecation-on-some-player-lookup-methods.patch @@ -0,0 +1,77 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 30 Mar 2014 15:58:22 +1100 +Subject: [PATCH] Remove deprecation on some player lookup methods + +Most of these methods still have plenty of use given that only one player with each name can exist at a time. Deprecating these methods renders even basic functionality such as /msg impossible without causing compiler warnings. We will maintain this API and it should be considered safe and appropriate for most use cases. + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -0,0 +0,0 @@ public final class Bukkit { + /** + * @see Server#getPlayer(String name) + */ +- @Deprecated + public static Player getPlayer(String name) { + return server.getPlayer(name); + } +@@ -0,0 +0,0 @@ public final class Bukkit { + /** + * @see Server#matchPlayer(String name) + */ +- @Deprecated + public static List matchPlayer(String name) { + return server.matchPlayer(name); + } +@@ -0,0 +0,0 @@ public final class Bukkit { + /** + * @see Server#getPlayerExact(String name) + */ +- @Deprecated + public static Player getPlayerExact(String name) { + return server.getPlayerExact(name); + } +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -0,0 +0,0 @@ public interface Server extends PluginMessageRecipient { + *

+ * This method may not return objects for offline players. + * +- * @deprecated Use {@link #getPlayer(UUID)} as player names are no longer +- * guaranteed to be unique + * @param name the name to look up + * @return a player if one was found, null otherwise + */ +- @Deprecated + public Player getPlayer(String name); + + /** + * Gets the player with the exact given name, case insensitive. + * +- * @deprecated Use {@link #getPlayer(UUID)} as player names are no longer +- * guaranteed to be unique + * @param name Exact name of the player to retrieve + * @return a player object if one was found, null otherwise + */ +- @Deprecated + public Player getPlayerExact(String name); + + /** +@@ -0,0 +0,0 @@ public interface Server extends PluginMessageRecipient { + * This list is not sorted in any particular order. If an exact match is + * found, the returned list will only contain a single result. + * +- * @deprecated Use {@link #getPlayer(UUID)} as player names are no longer +- * guaranteed to be unique + * @param name the (partial) name to match + * @return list of all possible players + */ +- @Deprecated + public List matchPlayer(String name); + + /** +-- \ No newline at end of file diff --git a/Bukkit-Patches/0024-Expand-team-API-to-allow-arbitrary-strings.patch b/Bukkit-Patches/0024-Expand-team-API-to-allow-arbitrary-strings.patch new file mode 100644 index 0000000000..6d1dad51f0 --- /dev/null +++ b/Bukkit-Patches/0024-Expand-team-API-to-allow-arbitrary-strings.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Thu, 17 Apr 2014 19:22:26 +1000 +Subject: [PATCH] Expand team API to allow arbitrary strings. + + +diff --git a/src/main/java/org/bukkit/scoreboard/Team.java b/src/main/java/org/bukkit/scoreboard/Team.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/scoreboard/Team.java ++++ b/src/main/java/org/bukkit/scoreboard/Team.java +@@ -0,0 +0,0 @@ public interface Team { + */ + Set getPlayers() throws IllegalStateException; + ++ // Spigot start ++ /** ++ * Same as the player method, but with an arbitrary string. ++ * ++ * @see #getPlayers() ++ */ ++ Set getEntries() throws IllegalStateException; ++ // Spigot End ++ + /** + * Gets the size of the team + * +@@ -0,0 +0,0 @@ public interface Team { + */ + void addPlayer(OfflinePlayer player) throws IllegalStateException, IllegalArgumentException; + ++ // Spigot start ++ /** ++ * Same as the player method, but with an arbitrary string. ++ * ++ * @see #addPlayer(org.bukkit.OfflinePlayer) ++ */ ++ void addEntry(String entry) throws IllegalStateException, IllegalArgumentException; ++ // Spigot end ++ + /** + * Removes the player from this team. + * +@@ -0,0 +0,0 @@ public interface Team { + */ + boolean removePlayer(OfflinePlayer player) throws IllegalStateException, IllegalArgumentException; + ++ // Spigot start ++ /** ++ * Same as the player method, but with an arbitrary string. ++ * ++ * @see #removePlayer(org.bukkit.OfflinePlayer) ++ */ ++ boolean removeEntry(String entry) throws IllegalStateException, IllegalArgumentException; ++ // Spigot end ++ + /** + * Unregisters this team from the Scoreboard + * +@@ -0,0 +0,0 @@ public interface Team { + * @throws IllegalStateException if this team has been unregistered + */ + boolean hasPlayer(OfflinePlayer player) throws IllegalArgumentException, IllegalStateException; ++ ++ // Spigot start ++ /** ++ * Same as the player method, but with an arbitrary string. ++ * ++ * @see #hasPlayer(org.bukkit.OfflinePlayer) ++ */ ++ boolean hasEntry(String entry) throws IllegalArgumentException,IllegalStateException; ++ // Spigot end + } +-- \ No newline at end of file diff --git a/Bukkit-Patches/0025-Add-Score.isScoreSet-Z-API.patch b/Bukkit-Patches/0025-Add-Score.isScoreSet-Z-API.patch new file mode 100644 index 0000000000..f554db46b0 --- /dev/null +++ b/Bukkit-Patches/0025-Add-Score.isScoreSet-Z-API.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Thu, 17 Apr 2014 19:35:13 +1000 +Subject: [PATCH] Add Score.isScoreSet()Z API. + + +diff --git a/src/main/java/org/bukkit/scoreboard/Score.java b/src/main/java/org/bukkit/scoreboard/Score.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/scoreboard/Score.java ++++ b/src/main/java/org/bukkit/scoreboard/Score.java +@@ -0,0 +0,0 @@ public interface Score { + */ + void setScore(int score) throws IllegalStateException; + ++ // Spigot start ++ /** ++ * Shows if this score has been set at any point in time. ++ * ++ * @return if this score has been set before ++ * @throws IllegalStateException if the associated objective has been ++ * unregistered ++ */ ++ boolean isScoreSet() throws IllegalStateException; ++ // Spigot end ++ + /** + * Gets the scoreboard for the associated objective. + * +-- \ No newline at end of file diff --git a/Bukkit-Patches/0026-Add-PlayerSpawnLocationEvent.patch b/Bukkit-Patches/0026-Add-PlayerSpawnLocationEvent.patch new file mode 100644 index 0000000000..ea18588b69 --- /dev/null +++ b/Bukkit-Patches/0026-Add-PlayerSpawnLocationEvent.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ninja +Date: Tue, 8 Apr 2014 14:01:32 +0200 +Subject: [PATCH] Add PlayerSpawnLocationEvent. + + +diff --git a/src/main/java/org/spigotmc/event/player/PlayerSpawnLocationEvent.java b/src/main/java/org/spigotmc/event/player/PlayerSpawnLocationEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/org/spigotmc/event/player/PlayerSpawnLocationEvent.java +@@ -0,0 +0,0 @@ ++package org.spigotmc.event.player; ++ ++import org.bukkit.Location; ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++ ++/** ++ * Called when player is about to spawn in a world after joining the server. ++ */ ++public class PlayerSpawnLocationEvent extends PlayerEvent { ++ private static final HandlerList handlers = new HandlerList(); ++ private Location spawnLocation; ++ ++ public PlayerSpawnLocationEvent(final Player who, Location spawnLocation) { ++ super(who); ++ this.spawnLocation = spawnLocation; ++ } ++ ++ ++ /** ++ * Gets player's spawn location. ++ * If the player {@link Player#hasPlayedBefore()}, it's going to default to the location inside player.dat file. ++ * For new players, the default spawn location is spawn of the main Bukkit world. ++ * ++ * @return the spawn location ++ */ ++ public Location getSpawnLocation() { ++ return spawnLocation; ++ } ++ ++ /** ++ * Sets player's spawn location. ++ * ++ * @param location the spawn location ++ */ ++ public void setSpawnLocation(Location location) { ++ this.spawnLocation = location; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +-- \ No newline at end of file diff --git a/Bukkit-Patches/0027-Ease-ClassLoader-Deadlocks-Where-Possible.patch b/Bukkit-Patches/0027-Ease-ClassLoader-Deadlocks-Where-Possible.patch new file mode 100644 index 0000000000..4cf0bd68d3 --- /dev/null +++ b/Bukkit-Patches/0027-Ease-ClassLoader-Deadlocks-Where-Possible.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Wed, 16 Jul 2014 17:24:21 +1000 +Subject: [PATCH] Ease ClassLoader Deadlocks Where Possible + +When on Java 7 we can register the classloader as parallel capable to prevent deadlocks caused by certain scenarios. Due to the nature of PluginClassLoader this isn't completely safe, but we can make it safer by switching to concurrency focused collections. Either way this is far better than crashing the server. + +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +@@ -0,0 +0,0 @@ import org.yaml.snakeyaml.error.YAMLException; + public final class JavaPluginLoader implements PluginLoader { + final Server server; + private final Pattern[] fileFilters = new Pattern[] { Pattern.compile("\\.jar$"), }; +- private final Map> classes = new HashMap>(); ++ private final Map> classes = new java.util.concurrent.ConcurrentHashMap>(); // Spigot + private final Map loaders = new LinkedHashMap(); + public static final CustomTimingsHandler pluginParentTimer = new CustomTimingsHandler("** Plugins"); // Spigot + +diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +@@ -0,0 +0,0 @@ import org.bukkit.plugin.PluginDescriptionFile; + */ + final class PluginClassLoader extends URLClassLoader { + private final JavaPluginLoader loader; +- private final Map> classes = new HashMap>(); ++ private final Map> classes = new java.util.concurrent.ConcurrentHashMap>(); // Spigot + private final PluginDescriptionFile description; + private final File dataFolder; + private final File file; +@@ -0,0 +0,0 @@ final class PluginClassLoader extends URLClassLoader { + private JavaPlugin pluginInit; + private IllegalStateException pluginState; + ++ // Spigot Start ++ static ++ { ++ try ++ { ++ java.lang.reflect.Method method = ClassLoader.class.getDeclaredMethod( "registerAsParallelCapable" ); ++ if ( method != null ) ++ { ++ boolean oldAccessible = method.isAccessible(); ++ method.setAccessible( true ); ++ method.invoke( null ); ++ method.setAccessible( oldAccessible ); ++ org.bukkit.Bukkit.getLogger().log( java.util.logging.Level.INFO, "Set PluginClassLoader as parallel capable" ); ++ } ++ } catch ( Exception ex ) ++ { ++ org.bukkit.Bukkit.getLogger().log( java.util.logging.Level.WARNING, "Error setting PluginClassLoader as parallel capable", ex ); ++ } ++ } ++ // Spigot End ++ + PluginClassLoader(final JavaPluginLoader loader, final ClassLoader parent, final PluginDescriptionFile description, final File dataFolder, final File file) throws InvalidPluginException, MalformedURLException { + super(new URL[] {file.toURI().toURL()}, parent); + Validate.notNull(loader, "Loader cannot be null"); +-- \ No newline at end of file diff --git a/CraftBukkit b/CraftBukkit index 6fb735eefe..37c7969161 160000 --- a/CraftBukkit +++ b/CraftBukkit @@ -1 +1 @@ -Subproject commit 6fb735eefe1b6401aff31aec28929f9bacf060cf +Subproject commit 37c79691615fbd28b49c7371a64700e4f5713eca diff --git a/CraftBukkit-Patches/0001-POM-Changes.patch b/CraftBukkit-Patches/0001-POM-Changes.patch new file mode 100644 index 0000000000..8e8d7b97fa --- /dev/null +++ b/CraftBukkit-Patches/0001-POM-Changes.patch @@ -0,0 +1,169 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Tue, 2 Jul 2013 13:07:39 +1000 +Subject: [PATCH] POM Changes + +Basic changes to the build system which mark the artifact as Spigot, and the necessary code changes to ensure proper functionality. Also disables the auto updater provided by CraftBukkit as it is useless to us. + +diff --git a/pom.xml b/pom.xml +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -0,0 +0,0 @@ + + 4.0.0 +- org.bukkit +- craftbukkit ++ org.spigotmc ++ spigot + jar + 1.7.10-R0.1-SNAPSHOT +- CraftBukkit +- http://www.bukkit.org ++ Spigot ++ http://www.spigotmc.org + + + UTF-8 +@@ -0,0 +0,0 @@ + + + +- +- scm:git:git://github.com/Bukkit/CraftBukkit.git +- scm:git:ssh://git@github.com/Bukkit/CraftBukkit.git +- https://github.com/Bukkit/CraftBukkit +- +- +- +- +- repobo-rel +- repo.bukkit.org Releases +- http://repo.bukkit.org/content/repositories/releases/ +- +- +- repobo-snap +- repo.bukkit.org Snapshots +- http://repo.bukkit.org/content/repositories/snapshots/ +- +- ++ ++ org.spigotmc ++ spigot-parent ++ dev-SNAPSHOT ++ ../pom.xml ++ + + + +@@ -0,0 +0,0 @@ + + + +- org.bukkit +- bukkit ++ org.spigotmc ++ spigot-api + ${project.version} + jar + compile + + +- org.bukkit ++ org.spigotmc + minecraft-server +- ${minecraft.version} ++ ${minecraft.version}-SNAPSHOT + jar + compile + +@@ -0,0 +0,0 @@ + gson + 2.1 + +- +- org.avaje +- ebean +- 2.7.3 +- jar +- provided +- +- +- org.yaml +- snakeyaml +- 1.9 +- jar +- provided +- +- +- com.google.guava +- guava +- 10.0 +- jar +- provided +- +- +- commons-lang +- commons-lang +- 2.3 +- provided +- + + + junit +@@ -0,0 +0,0 @@ + + + +- clean install ++ install + + + com.lukegb.mojo + gitdescribe-maven-plugin + 1.3 + +- ${buildtag.prefix} +- ${buildtag.suffix} ++ git-Spigot- ++ + + + +@@ -0,0 +0,0 @@ + + org.apache.maven.plugins + maven-shade-plugin +- 1.4 ++ 2.1 + + + package +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -0,0 +0,0 @@ public final class CraftServer implements Server { + loadIcon(); + + updater = new AutoUpdater(new BukkitDLUpdaterService(configuration.getString("auto-updater.host")), getLogger(), configuration.getString("auto-updater.preferred-channel")); +- updater.setEnabled(configuration.getBoolean("auto-updater.enabled")); ++ updater.setEnabled(false); // Spigot + updater.setSuggestChannels(configuration.getBoolean("auto-updater.suggest-channels")); + updater.getOnBroken().addAll(configuration.getStringList("auto-updater.on-broken")); + updater.getOnUpdate().addAll(configuration.getStringList("auto-updater.on-update")); +diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +@@ -0,0 +0,0 @@ public final class Versioning { + public static String getBukkitVersion() { + String result = "Unknown-Version"; + +- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/org.bukkit/bukkit/pom.properties"); ++ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/org.spigotmc/spigot-api/pom.properties"); + Properties properties = new Properties(); + + if (stream != null) { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0001-Rename-to-PaperSpigot.patch b/CraftBukkit-Patches/0001-Rename-to-PaperSpigot.patch deleted file mode 100644 index 781e536e32..0000000000 --- a/CraftBukkit-Patches/0001-Rename-to-PaperSpigot.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: gsand -Date: Tue, 15 Apr 2014 07:12:20 -0700 -Subject: [PATCH] Rename to PaperSpigot - - -diff --git a/pom.xml b/pom.xml -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -0,0 +0,0 @@ - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - 4.0.0 - org.spigotmc -- spigot -+ paperspigot - jar - 1.7.10-R0.1-SNAPSHOT - Spigot -@@ -0,0 +0,0 @@ - gitdescribe-maven-plugin - 1.3 - -- git-Spigot- -+ git-PaperSpigot- - - - --- \ No newline at end of file diff --git a/CraftBukkit-Patches/0002-mc-dev-imports.patch b/CraftBukkit-Patches/0002-mc-dev-imports.patch new file mode 100644 index 0000000000..4553c4f9dc --- /dev/null +++ b/CraftBukkit-Patches/0002-mc-dev-imports.patch @@ -0,0 +1,3709 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 1 Dec 2013 15:10:48 +1100 +Subject: [PATCH] mc-dev imports + +Imported files which are only modified by Spigot, not upstream. Files here should be completely unmodified aside from trivial changes such as adding throws statements to ensure proper compilation. You may need to add unrelated files in order to ensure a compilable result in the face of synthetic methods. + +diff --git a/src/main/java/net/minecraft/server/BanEntrySerializer.java b/src/main/java/net/minecraft/server/BanEntrySerializer.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/BanEntrySerializer.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.lang.reflect.Type; ++import java.text.ParseException; ++import java.util.Date; ++import java.util.UUID; ++ ++import net.minecraft.util.com.google.gson.JsonDeserializationContext; ++import net.minecraft.util.com.google.gson.JsonDeserializer; ++import net.minecraft.util.com.google.gson.JsonElement; ++import net.minecraft.util.com.google.gson.JsonObject; ++import net.minecraft.util.com.google.gson.JsonSerializationContext; ++import net.minecraft.util.com.google.gson.JsonSerializer; ++import net.minecraft.util.com.mojang.authlib.GameProfile; ++ ++class BanEntrySerializer implements JsonDeserializer, JsonSerializer { ++ ++ final UserCache a; ++ ++ private BanEntrySerializer(UserCache usercache) { ++ this.a = usercache; ++ } ++ ++ public JsonElement a(UserCacheEntry usercacheentry, Type type, JsonSerializationContext jsonserializationcontext) { ++ JsonObject jsonobject = new JsonObject(); ++ ++ jsonobject.addProperty("name", usercacheentry.a().getName()); ++ UUID uuid = usercacheentry.a().getId(); ++ ++ jsonobject.addProperty("uuid", uuid == null ? "" : uuid.toString()); ++ jsonobject.addProperty("expiresOn", UserCache.a.format(usercacheentry.b())); ++ return jsonobject; ++ } ++ ++ public UserCacheEntry a(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) { ++ if (jsonelement.isJsonObject()) { ++ JsonObject jsonobject = jsonelement.getAsJsonObject(); ++ JsonElement jsonelement1 = jsonobject.get("name"); ++ JsonElement jsonelement2 = jsonobject.get("uuid"); ++ JsonElement jsonelement3 = jsonobject.get("expiresOn"); ++ ++ if (jsonelement1 != null && jsonelement2 != null) { ++ String s = jsonelement2.getAsString(); ++ String s1 = jsonelement1.getAsString(); ++ Date date = null; ++ ++ if (jsonelement3 != null) { ++ try { ++ date = UserCache.a.parse(jsonelement3.getAsString()); ++ } catch (ParseException parseexception) { ++ date = null; ++ } ++ } ++ ++ if (s1 != null && s != null) { ++ UUID uuid; ++ ++ try { ++ uuid = UUID.fromString(s); ++ } catch (Throwable throwable) { ++ return null; ++ } ++ ++ UserCacheEntry usercacheentry = new UserCacheEntry(this.a, new GameProfile(uuid, s1), date, (GameProfileLookup) null); ++ ++ return usercacheentry; ++ } else { ++ return null; ++ } ++ } else { ++ return null; ++ } ++ } else { ++ return null; ++ } ++ } ++ ++ public JsonElement serialize(Object object, Type type, JsonSerializationContext jsonserializationcontext) { ++ return this.a((UserCacheEntry) object, type, jsonserializationcontext); ++ } ++ ++ public Object deserialize(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) { ++ return this.a(jsonelement, type, jsondeserializationcontext); ++ } ++ ++ BanEntrySerializer(UserCache usercache, GameProfileLookup gameprofilelookup) { ++ this(usercache); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/BiomeDecorator.java b/src/main/java/net/minecraft/server/BiomeDecorator.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/BiomeDecorator.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.util.Random; ++ ++public class BiomeDecorator { ++ ++ protected World a; ++ protected Random b; ++ protected int c; ++ protected int d; ++ protected WorldGenerator e = new WorldGenClay(4); ++ protected WorldGenerator f; ++ protected WorldGenerator g; ++ protected WorldGenerator h; ++ protected WorldGenerator i; ++ protected WorldGenerator j; ++ protected WorldGenerator k; ++ protected WorldGenerator l; ++ protected WorldGenerator m; ++ protected WorldGenerator n; ++ protected WorldGenerator o; ++ protected WorldGenFlowers p; ++ protected WorldGenerator q; ++ protected WorldGenerator r; ++ protected WorldGenerator s; ++ protected WorldGenerator t; ++ protected WorldGenerator u; ++ protected WorldGenerator v; ++ protected int w; ++ protected int x; ++ protected int y; ++ protected int z; ++ protected int A; ++ protected int B; ++ protected int C; ++ protected int D; ++ protected int E; ++ protected int F; ++ protected int G; ++ protected int H; ++ public boolean I; ++ ++ public BiomeDecorator() { ++ this.f = new WorldGenSand(Blocks.SAND, 7); ++ this.g = new WorldGenSand(Blocks.GRAVEL, 6); ++ this.h = new WorldGenMinable(Blocks.DIRT, 32); ++ this.i = new WorldGenMinable(Blocks.GRAVEL, 32); ++ this.j = new WorldGenMinable(Blocks.COAL_ORE, 16); ++ this.k = new WorldGenMinable(Blocks.IRON_ORE, 8); ++ this.l = new WorldGenMinable(Blocks.GOLD_ORE, 8); ++ this.m = new WorldGenMinable(Blocks.REDSTONE_ORE, 7); ++ this.n = new WorldGenMinable(Blocks.DIAMOND_ORE, 7); ++ this.o = new WorldGenMinable(Blocks.LAPIS_ORE, 6); ++ this.p = new WorldGenFlowers(Blocks.YELLOW_FLOWER); ++ this.q = new WorldGenFlowers(Blocks.BROWN_MUSHROOM); ++ this.r = new WorldGenFlowers(Blocks.RED_MUSHROOM); ++ this.s = new WorldGenHugeMushroom(); ++ this.t = new WorldGenReed(); ++ this.u = new WorldGenCactus(); ++ this.v = new WorldGenWaterLily(); ++ this.y = 2; ++ this.z = 1; ++ this.E = 1; ++ this.F = 3; ++ this.G = 1; ++ this.I = true; ++ } ++ ++ public void a(World world, Random random, BiomeBase biomebase, int i, int j) { ++ if (this.a != null) { ++ throw new RuntimeException("Already decorating!!"); ++ } else { ++ this.a = world; ++ this.b = random; ++ this.c = i; ++ this.d = j; ++ this.a(biomebase); ++ this.a = null; ++ this.b = null; ++ } ++ } ++ ++ protected void a(BiomeBase biomebase) { ++ this.a(); ++ ++ int i; ++ int j; ++ int k; ++ ++ for (i = 0; i < this.F; ++i) { ++ j = this.c + this.b.nextInt(16) + 8; ++ k = this.d + this.b.nextInt(16) + 8; ++ this.f.generate(this.a, this.b, j, this.a.i(j, k), k); ++ } ++ ++ for (i = 0; i < this.G; ++i) { ++ j = this.c + this.b.nextInt(16) + 8; ++ k = this.d + this.b.nextInt(16) + 8; ++ this.e.generate(this.a, this.b, j, this.a.i(j, k), k); ++ } ++ ++ for (i = 0; i < this.E; ++i) { ++ j = this.c + this.b.nextInt(16) + 8; ++ k = this.d + this.b.nextInt(16) + 8; ++ this.g.generate(this.a, this.b, j, this.a.i(j, k), k); ++ } ++ ++ i = this.x; ++ if (this.b.nextInt(10) == 0) { ++ ++i; ++ } ++ ++ int l; ++ int i1; ++ ++ for (j = 0; j < i; ++j) { ++ k = this.c + this.b.nextInt(16) + 8; ++ l = this.d + this.b.nextInt(16) + 8; ++ i1 = this.a.getHighestBlockYAt(k, l); ++ WorldGenTreeAbstract worldgentreeabstract = biomebase.a(this.b); ++ ++ worldgentreeabstract.a(1.0D, 1.0D, 1.0D); ++ if (worldgentreeabstract.generate(this.a, this.b, k, i1, l)) { ++ worldgentreeabstract.b(this.a, this.b, k, i1, l); ++ } ++ } ++ ++ for (j = 0; j < this.H; ++j) { ++ k = this.c + this.b.nextInt(16) + 8; ++ l = this.d + this.b.nextInt(16) + 8; ++ this.s.generate(this.a, this.b, k, this.a.getHighestBlockYAt(k, l), l); ++ } ++ ++ for (j = 0; j < this.y; ++j) { ++ k = this.c + this.b.nextInt(16) + 8; ++ l = this.d + this.b.nextInt(16) + 8; ++ i1 = this.b.nextInt(this.a.getHighestBlockYAt(k, l) + 32); ++ String s = biomebase.a(this.b, k, i1, l); ++ BlockFlowers blockflowers = BlockFlowers.e(s); ++ ++ if (blockflowers.getMaterial() != Material.AIR) { ++ this.p.a(blockflowers, BlockFlowers.f(s)); ++ this.p.generate(this.a, this.b, k, i1, l); ++ } ++ } ++ ++ for (j = 0; j < this.z; ++j) { ++ k = this.c + this.b.nextInt(16) + 8; ++ l = this.d + this.b.nextInt(16) + 8; ++ i1 = this.b.nextInt(this.a.getHighestBlockYAt(k, l) * 2); ++ WorldGenerator worldgenerator = biomebase.b(this.b); ++ ++ worldgenerator.generate(this.a, this.b, k, i1, l); ++ } ++ ++ for (j = 0; j < this.A; ++j) { ++ k = this.c + this.b.nextInt(16) + 8; ++ l = this.d + this.b.nextInt(16) + 8; ++ i1 = this.b.nextInt(this.a.getHighestBlockYAt(k, l) * 2); ++ (new WorldGenDeadBush(Blocks.DEAD_BUSH)).generate(this.a, this.b, k, i1, l); ++ } ++ ++ for (j = 0; j < this.w; ++j) { ++ k = this.c + this.b.nextInt(16) + 8; ++ l = this.d + this.b.nextInt(16) + 8; ++ ++ for (i1 = this.b.nextInt(this.a.getHighestBlockYAt(k, l) * 2); i1 > 0 && this.a.isEmpty(k, i1 - 1, l); --i1) { ++ ; ++ } ++ ++ this.v.generate(this.a, this.b, k, i1, l); ++ } ++ ++ for (j = 0; j < this.B; ++j) { ++ if (this.b.nextInt(4) == 0) { ++ k = this.c + this.b.nextInt(16) + 8; ++ l = this.d + this.b.nextInt(16) + 8; ++ i1 = this.a.getHighestBlockYAt(k, l); ++ this.q.generate(this.a, this.b, k, i1, l); ++ } ++ ++ if (this.b.nextInt(8) == 0) { ++ k = this.c + this.b.nextInt(16) + 8; ++ l = this.d + this.b.nextInt(16) + 8; ++ i1 = this.b.nextInt(this.a.getHighestBlockYAt(k, l) * 2); ++ this.r.generate(this.a, this.b, k, i1, l); ++ } ++ } ++ ++ if (this.b.nextInt(4) == 0) { ++ j = this.c + this.b.nextInt(16) + 8; ++ k = this.d + this.b.nextInt(16) + 8; ++ l = this.b.nextInt(this.a.getHighestBlockYAt(j, k) * 2); ++ this.q.generate(this.a, this.b, j, l, k); ++ } ++ ++ if (this.b.nextInt(8) == 0) { ++ j = this.c + this.b.nextInt(16) + 8; ++ k = this.d + this.b.nextInt(16) + 8; ++ l = this.b.nextInt(this.a.getHighestBlockYAt(j, k) * 2); ++ this.r.generate(this.a, this.b, j, l, k); ++ } ++ ++ for (j = 0; j < this.C; ++j) { ++ k = this.c + this.b.nextInt(16) + 8; ++ l = this.d + this.b.nextInt(16) + 8; ++ i1 = this.b.nextInt(this.a.getHighestBlockYAt(k, l) * 2); ++ this.t.generate(this.a, this.b, k, i1, l); ++ } ++ ++ for (j = 0; j < 10; ++j) { ++ k = this.c + this.b.nextInt(16) + 8; ++ l = this.d + this.b.nextInt(16) + 8; ++ i1 = this.b.nextInt(this.a.getHighestBlockYAt(k, l) * 2); ++ this.t.generate(this.a, this.b, k, i1, l); ++ } ++ ++ if (this.b.nextInt(32) == 0) { ++ j = this.c + this.b.nextInt(16) + 8; ++ k = this.d + this.b.nextInt(16) + 8; ++ l = this.b.nextInt(this.a.getHighestBlockYAt(j, k) * 2); ++ (new WorldGenPumpkin()).generate(this.a, this.b, j, l, k); ++ } ++ ++ for (j = 0; j < this.D; ++j) { ++ k = this.c + this.b.nextInt(16) + 8; ++ l = this.d + this.b.nextInt(16) + 8; ++ i1 = this.b.nextInt(this.a.getHighestBlockYAt(k, l) * 2); ++ this.u.generate(this.a, this.b, k, i1, l); ++ } ++ ++ if (this.I) { ++ for (j = 0; j < 50; ++j) { ++ k = this.c + this.b.nextInt(16) + 8; ++ l = this.b.nextInt(this.b.nextInt(248) + 8); ++ i1 = this.d + this.b.nextInt(16) + 8; ++ (new WorldGenLiquids(Blocks.WATER)).generate(this.a, this.b, k, l, i1); ++ } ++ ++ for (j = 0; j < 20; ++j) { ++ k = this.c + this.b.nextInt(16) + 8; ++ l = this.b.nextInt(this.b.nextInt(this.b.nextInt(240) + 8) + 8); ++ i1 = this.d + this.b.nextInt(16) + 8; ++ (new WorldGenLiquids(Blocks.LAVA)).generate(this.a, this.b, k, l, i1); ++ } ++ } ++ } ++ ++ protected void a(int i, WorldGenerator worldgenerator, int j, int k) { ++ for (int l = 0; l < i; ++l) { ++ int i1 = this.c + this.b.nextInt(16); ++ int j1 = this.b.nextInt(k - j) + j; ++ int k1 = this.d + this.b.nextInt(16); ++ ++ worldgenerator.generate(this.a, this.b, i1, j1, k1); ++ } ++ } ++ ++ protected void b(int i, WorldGenerator worldgenerator, int j, int k) { ++ for (int l = 0; l < i; ++l) { ++ int i1 = this.c + this.b.nextInt(16); ++ int j1 = this.b.nextInt(k) + this.b.nextInt(k) + (j - k); ++ int k1 = this.d + this.b.nextInt(16); ++ ++ worldgenerator.generate(this.a, this.b, i1, j1, k1); ++ } ++ } ++ ++ protected void a() { ++ this.a(20, this.h, 0, 256); ++ this.a(10, this.i, 0, 256); ++ this.a(20, this.j, 0, 128); ++ this.a(20, this.k, 0, 64); ++ this.a(2, this.l, 0, 32); ++ this.a(8, this.m, 0, 16); ++ this.a(1, this.n, 0, 16); ++ this.b(1, this.o, 16, 16); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/BlockAnvil.java b/src/main/java/net/minecraft/server/BlockAnvil.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/BlockAnvil.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++public class BlockAnvil extends BlockFalling { ++ ++ public static final String[] a = new String[] { "intact", "slightlyDamaged", "veryDamaged"}; ++ private static final String[] N = new String[] { "anvil_top_damaged_0", "anvil_top_damaged_1", "anvil_top_damaged_2"}; ++ ++ protected BlockAnvil() { ++ super(Material.HEAVY); ++ this.g(0); ++ this.a(CreativeModeTab.c); ++ } ++ ++ public boolean d() { ++ return false; ++ } ++ ++ public boolean c() { ++ return false; ++ } ++ ++ public void postPlace(World world, int i, int j, int k, EntityLiving entityliving, ItemStack itemstack) { ++ int l = MathHelper.floor((double) (entityliving.yaw * 4.0F / 360.0F) + 0.5D) & 3; ++ int i1 = world.getData(i, j, k) >> 2; ++ ++ ++l; ++ l %= 4; ++ if (l == 0) { ++ world.setData(i, j, k, 2 | i1 << 2, 2); ++ } ++ ++ if (l == 1) { ++ world.setData(i, j, k, 3 | i1 << 2, 2); ++ } ++ ++ if (l == 2) { ++ world.setData(i, j, k, 0 | i1 << 2, 2); ++ } ++ ++ if (l == 3) { ++ world.setData(i, j, k, 1 | i1 << 2, 2); ++ } ++ } ++ ++ public boolean interact(World world, int i, int j, int k, EntityHuman entityhuman, int l, float f, float f1, float f2) { ++ if (world.isStatic) { ++ return true; ++ } else { ++ entityhuman.openAnvil(i, j, k); ++ return true; ++ } ++ } ++ ++ public int b() { ++ return 35; ++ } ++ ++ public int getDropData(int i) { ++ return i >> 2; ++ } ++ ++ public void updateShape(IBlockAccess iblockaccess, int i, int j, int k) { ++ int l = iblockaccess.getData(i, j, k) & 3; ++ ++ if (l != 3 && l != 1) { ++ this.a(0.125F, 0.0F, 0.0F, 0.875F, 1.0F, 1.0F); ++ } else { ++ this.a(0.0F, 0.0F, 0.125F, 1.0F, 1.0F, 0.875F); ++ } ++ } ++ ++ protected void a(EntityFallingBlock entityfallingblock) { ++ entityfallingblock.a(true); ++ } ++ ++ public void a(World world, int i, int j, int k, int l) { ++ world.triggerEffect(1022, i, j, k, 0); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/BlockBrewingStand.java b/src/main/java/net/minecraft/server/BlockBrewingStand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/BlockBrewingStand.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.util.List; ++import java.util.Random; ++ ++public class BlockBrewingStand extends BlockContainer { ++ ++ private Random a = new Random(); ++ ++ public BlockBrewingStand() { ++ super(Material.ORE); ++ } ++ ++ public boolean c() { ++ return false; ++ } ++ ++ public int b() { ++ return 25; ++ } ++ ++ public TileEntity a(World world, int i) { ++ return new TileEntityBrewingStand(); ++ } ++ ++ public boolean d() { ++ return false; ++ } ++ ++ public void a(World world, int i, int j, int k, AxisAlignedBB axisalignedbb, List list, Entity entity) { ++ this.a(0.4375F, 0.0F, 0.4375F, 0.5625F, 0.875F, 0.5625F); ++ super.a(world, i, j, k, axisalignedbb, list, entity); ++ this.g(); ++ super.a(world, i, j, k, axisalignedbb, list, entity); ++ } ++ ++ public void g() { ++ this.a(0.0F, 0.0F, 0.0F, 1.0F, 0.125F, 1.0F); ++ } ++ ++ public boolean interact(World world, int i, int j, int k, EntityHuman entityhuman, int l, float f, float f1, float f2) { ++ if (world.isStatic) { ++ return true; ++ } else { ++ TileEntityBrewingStand tileentitybrewingstand = (TileEntityBrewingStand) world.getTileEntity(i, j, k); ++ ++ if (tileentitybrewingstand != null) { ++ entityhuman.openBrewingStand(tileentitybrewingstand); ++ } ++ ++ return true; ++ } ++ } ++ ++ public void postPlace(World world, int i, int j, int k, EntityLiving entityliving, ItemStack itemstack) { ++ if (itemstack.hasName()) { ++ ((TileEntityBrewingStand) world.getTileEntity(i, j, k)).a(itemstack.getName()); ++ } ++ } ++ ++ public void remove(World world, int i, int j, int k, Block block, int l) { ++ TileEntity tileentity = world.getTileEntity(i, j, k); ++ ++ if (tileentity instanceof TileEntityBrewingStand) { ++ TileEntityBrewingStand tileentitybrewingstand = (TileEntityBrewingStand) tileentity; ++ ++ for (int i1 = 0; i1 < tileentitybrewingstand.getSize(); ++i1) { ++ ItemStack itemstack = tileentitybrewingstand.getItem(i1); ++ ++ if (itemstack != null) { ++ float f = this.a.nextFloat() * 0.8F + 0.1F; ++ float f1 = this.a.nextFloat() * 0.8F + 0.1F; ++ float f2 = this.a.nextFloat() * 0.8F + 0.1F; ++ ++ while (itemstack.count > 0) { ++ int j1 = this.a.nextInt(21) + 10; ++ ++ if (j1 > itemstack.count) { ++ j1 = itemstack.count; ++ } ++ ++ itemstack.count -= j1; ++ EntityItem entityitem = new EntityItem(world, (double) ((float) i + f), (double) ((float) j + f1), (double) ((float) k + f2), new ItemStack(itemstack.getItem(), j1, itemstack.getData())); ++ float f3 = 0.05F; ++ ++ entityitem.motX = (double) ((float) this.a.nextGaussian() * f3); ++ entityitem.motY = (double) ((float) this.a.nextGaussian() * f3 + 0.2F); ++ entityitem.motZ = (double) ((float) this.a.nextGaussian() * f3); ++ world.addEntity(entityitem); ++ } ++ } ++ } ++ } ++ ++ super.remove(world, i, j, k, block, l); ++ } ++ ++ public Item getDropType(int i, Random random, int j) { ++ return Items.BREWING_STAND; ++ } ++ ++ public boolean isComplexRedstone() { ++ return true; ++ } ++ ++ public int g(World world, int i, int j, int k, int l) { ++ return Container.b((IInventory) world.getTileEntity(i, j, k)); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/BlockFlowerPot.java b/src/main/java/net/minecraft/server/BlockFlowerPot.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/BlockFlowerPot.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.util.Random; ++ ++public class BlockFlowerPot extends BlockContainer { ++ ++ public BlockFlowerPot() { ++ super(Material.ORIENTABLE); ++ this.g(); ++ } ++ ++ public void g() { ++ float f = 0.375F; ++ float f1 = f / 2.0F; ++ ++ this.a(0.5F - f1, 0.0F, 0.5F - f1, 0.5F + f1, f, 0.5F + f1); ++ } ++ ++ public boolean c() { ++ return false; ++ } ++ ++ public int b() { ++ return 33; ++ } ++ ++ public boolean d() { ++ return false; ++ } ++ ++ public boolean interact(World world, int i, int j, int k, EntityHuman entityhuman, int l, float f, float f1, float f2) { ++ ItemStack itemstack = entityhuman.inventory.getItemInHand(); ++ ++ if (itemstack != null && itemstack.getItem() instanceof ItemBlock) { ++ TileEntityFlowerPot tileentityflowerpot = this.e(world, i, j, k); ++ ++ if (tileentityflowerpot != null) { ++ if (tileentityflowerpot.a() != null) { ++ return false; ++ } else { ++ Block block = Block.a(itemstack.getItem()); ++ ++ if (!this.a(block, itemstack.getData())) { ++ return false; ++ } else { ++ tileentityflowerpot.a(itemstack.getItem(), itemstack.getData()); ++ tileentityflowerpot.update(); ++ if (!world.setData(i, j, k, itemstack.getData(), 2)) { ++ world.notify(i, j, k); ++ } ++ ++ if (!entityhuman.abilities.canInstantlyBuild && --itemstack.count <= 0) { ++ entityhuman.inventory.setItem(entityhuman.inventory.itemInHandIndex, (ItemStack) null); ++ } ++ ++ return true; ++ } ++ } ++ } else { ++ return false; ++ } ++ } else { ++ return false; ++ } ++ } ++ ++ private boolean a(Block block, int i) { ++ return block != Blocks.YELLOW_FLOWER && block != Blocks.RED_ROSE && block != Blocks.CACTUS && block != Blocks.BROWN_MUSHROOM && block != Blocks.RED_MUSHROOM && block != Blocks.SAPLING && block != Blocks.DEAD_BUSH ? block == Blocks.LONG_GRASS && i == 2 : true; ++ } ++ ++ public int getDropData(World world, int i, int j, int k) { ++ TileEntityFlowerPot tileentityflowerpot = this.e(world, i, j, k); ++ ++ return tileentityflowerpot != null && tileentityflowerpot.a() != null ? tileentityflowerpot.b() : 0; ++ } ++ ++ public boolean canPlace(World world, int i, int j, int k) { ++ return super.canPlace(world, i, j, k) && World.a((IBlockAccess) world, i, j - 1, k); ++ } ++ ++ public void doPhysics(World world, int i, int j, int k, Block block) { ++ if (!World.a((IBlockAccess) world, i, j - 1, k)) { ++ this.b(world, i, j, k, world.getData(i, j, k), 0); ++ world.setAir(i, j, k); ++ } ++ } ++ ++ public void remove(World world, int i, int j, int k, Block block, int l) { ++ TileEntityFlowerPot tileentityflowerpot = this.e(world, i, j, k); ++ ++ if (tileentityflowerpot != null && tileentityflowerpot.a() != null) { ++ this.a(world, i, j, k, new ItemStack(tileentityflowerpot.a(), 1, tileentityflowerpot.b())); ++ } ++ ++ super.remove(world, i, j, k, block, l); ++ } ++ ++ public void a(World world, int i, int j, int k, int l, EntityHuman entityhuman) { ++ super.a(world, i, j, k, l, entityhuman); ++ if (entityhuman.abilities.canInstantlyBuild) { ++ TileEntityFlowerPot tileentityflowerpot = this.e(world, i, j, k); ++ ++ if (tileentityflowerpot != null) { ++ tileentityflowerpot.a(Item.getById(0), 0); ++ } ++ } ++ } ++ ++ public Item getDropType(int i, Random random, int j) { ++ return Items.FLOWER_POT; ++ } ++ ++ private TileEntityFlowerPot e(World world, int i, int j, int k) { ++ TileEntity tileentity = world.getTileEntity(i, j, k); ++ ++ return tileentity != null && tileentity instanceof TileEntityFlowerPot ? (TileEntityFlowerPot) tileentity : null; ++ } ++ ++ public TileEntity a(World world, int i) { ++ Object object = null; ++ byte b0 = 0; ++ ++ switch (i) { ++ case 1: ++ object = Blocks.RED_ROSE; ++ b0 = 0; ++ break; ++ ++ case 2: ++ object = Blocks.YELLOW_FLOWER; ++ break; ++ ++ case 3: ++ object = Blocks.SAPLING; ++ b0 = 0; ++ break; ++ ++ case 4: ++ object = Blocks.SAPLING; ++ b0 = 1; ++ break; ++ ++ case 5: ++ object = Blocks.SAPLING; ++ b0 = 2; ++ break; ++ ++ case 6: ++ object = Blocks.SAPLING; ++ b0 = 3; ++ break; ++ ++ case 7: ++ object = Blocks.RED_MUSHROOM; ++ break; ++ ++ case 8: ++ object = Blocks.BROWN_MUSHROOM; ++ break; ++ ++ case 9: ++ object = Blocks.CACTUS; ++ break; ++ ++ case 10: ++ object = Blocks.DEAD_BUSH; ++ break; ++ ++ case 11: ++ object = Blocks.LONG_GRASS; ++ b0 = 2; ++ break; ++ ++ case 12: ++ object = Blocks.SAPLING; ++ b0 = 4; ++ break; ++ ++ case 13: ++ object = Blocks.SAPLING; ++ b0 = 5; ++ } ++ ++ return new TileEntityFlowerPot(Item.getItemOf((Block) object), b0); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/BlockTNT.java b/src/main/java/net/minecraft/server/BlockTNT.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/BlockTNT.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.util.Random; ++ ++public class BlockTNT extends Block { ++ ++ public BlockTNT() { ++ super(Material.TNT); ++ this.a(CreativeModeTab.d); ++ } ++ ++ public void onPlace(World world, int i, int j, int k) { ++ super.onPlace(world, i, j, k); ++ if (world.isBlockIndirectlyPowered(i, j, k)) { ++ this.postBreak(world, i, j, k, 1); ++ world.setAir(i, j, k); ++ } ++ } ++ ++ public void doPhysics(World world, int i, int j, int k, Block block) { ++ if (world.isBlockIndirectlyPowered(i, j, k)) { ++ this.postBreak(world, i, j, k, 1); ++ world.setAir(i, j, k); ++ } ++ } ++ ++ public int a(Random random) { ++ return 1; ++ } ++ ++ public void wasExploded(World world, int i, int j, int k, Explosion explosion) { ++ if (!world.isStatic) { ++ EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(world, (double) ((float) i + 0.5F), (double) ((float) j + 0.5F), (double) ((float) k + 0.5F), explosion.c()); ++ ++ entitytntprimed.fuseTicks = world.random.nextInt(entitytntprimed.fuseTicks / 4) + entitytntprimed.fuseTicks / 8; ++ world.addEntity(entitytntprimed); ++ } ++ } ++ ++ public void postBreak(World world, int i, int j, int k, int l) { ++ this.a(world, i, j, k, l, (EntityLiving) null); ++ } ++ ++ public void a(World world, int i, int j, int k, int l, EntityLiving entityliving) { ++ if (!world.isStatic) { ++ if ((l & 1) == 1) { ++ EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(world, (double) ((float) i + 0.5F), (double) ((float) j + 0.5F), (double) ((float) k + 0.5F), entityliving); ++ ++ world.addEntity(entitytntprimed); ++ world.makeSound(entitytntprimed, "game.tnt.primed", 1.0F, 1.0F); ++ } ++ } ++ } ++ ++ public boolean interact(World world, int i, int j, int k, EntityHuman entityhuman, int l, float f, float f1, float f2) { ++ if (entityhuman.bF() != null && entityhuman.bF().getItem() == Items.FLINT_AND_STEEL) { ++ this.a(world, i, j, k, 1, entityhuman); ++ world.setAir(i, j, k); ++ entityhuman.bF().damage(1, entityhuman); ++ return true; ++ } else { ++ return super.interact(world, i, j, k, entityhuman, l, f, f1, f2); ++ } ++ } ++ ++ public void a(World world, int i, int j, int k, Entity entity) { ++ if (entity instanceof EntityArrow && !world.isStatic) { ++ EntityArrow entityarrow = (EntityArrow) entity; ++ ++ if (entityarrow.isBurning()) { ++ this.a(world, i, j, k, 1, entityarrow.shooter instanceof EntityLiving ? (EntityLiving) entityarrow.shooter : null); ++ world.setAir(i, j, k); ++ } ++ } ++ } ++ ++ public boolean a(Explosion explosion) { ++ return false; ++ } ++} +diff --git a/src/main/java/net/minecraft/server/CommandDispatcher.java b/src/main/java/net/minecraft/server/CommandDispatcher.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/CommandDispatcher.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.util.Iterator; ++ ++public class CommandDispatcher extends CommandHandler implements ICommandDispatcher { ++ ++ public CommandDispatcher() { ++ this.a(new CommandTime()); ++ this.a(new CommandGamemode()); ++ this.a(new CommandDifficulty()); ++ this.a(new CommandGamemodeDefault()); ++ this.a(new CommandKill()); ++ this.a(new CommandToggleDownfall()); ++ this.a(new CommandWeather()); ++ this.a(new CommandXp()); ++ this.a(new CommandTp()); ++ this.a(new CommandGive()); ++ this.a(new CommandEffect()); ++ this.a(new CommandEnchant()); ++ this.a(new CommandMe()); ++ this.a(new CommandSeed()); ++ this.a(new CommandHelp()); ++ this.a(new CommandDebug()); ++ this.a(new CommandTell()); ++ this.a(new CommandSay()); ++ this.a(new CommandSpawnpoint()); ++ this.a(new CommandSetWorldSpawn()); ++ this.a(new CommandGamerule()); ++ this.a(new CommandClear()); ++ this.a(new CommandTestFor()); ++ this.a(new CommandSpreadPlayers()); ++ this.a(new CommandPlaySound()); ++ this.a(new CommandScoreboard()); ++ this.a(new CommandAchievement()); ++ this.a(new CommandSummon()); ++ this.a(new CommandSetBlock()); ++ this.a(new CommandTestForBlock()); ++ this.a(new CommandTellRaw()); ++ if (MinecraftServer.getServer().X()) { ++ this.a(new CommandOp()); ++ this.a(new CommandDeop()); ++ this.a(new CommandStop()); ++ this.a(new CommandSaveAll()); ++ this.a(new CommandSaveOff()); ++ this.a(new CommandSaveOn()); ++ this.a(new CommandBanIp()); ++ this.a(new CommandPardonIP()); ++ this.a(new CommandBan()); ++ this.a(new CommandBanList()); ++ this.a(new CommandPardon()); ++ this.a(new CommandKick()); ++ this.a(new CommandList()); ++ this.a(new CommandWhitelist()); ++ this.a(new CommandIdleTimeout()); ++ this.a(new CommandNetstat()); ++ } else { ++ this.a(new CommandPublish()); ++ } ++ ++ CommandAbstract.a((ICommandDispatcher) this); ++ } ++ ++ public void a(ICommandListener icommandlistener, ICommand icommand, int i, String s, Object... aobject) { ++ boolean flag = true; ++ ++ if (icommandlistener instanceof CommandBlockListenerAbstract && !MinecraftServer.getServer().worldServer[0].getGameRules().getBoolean("commandBlockOutput")) { ++ flag = false; ++ } ++ ++ ChatMessage chatmessage = new ChatMessage("chat.type.admin", new Object[] { icommandlistener.getName(), new ChatMessage(s, aobject)}); ++ ++ chatmessage.getChatModifier().setColor(EnumChatFormat.GRAY); ++ chatmessage.getChatModifier().setItalic(Boolean.valueOf(true)); ++ if (flag) { ++ Iterator iterator = MinecraftServer.getServer().getPlayerList().players.iterator(); ++ ++ while (iterator.hasNext()) { ++ EntityHuman entityhuman = (EntityHuman) iterator.next(); ++ ++ if (entityhuman != icommandlistener && MinecraftServer.getServer().getPlayerList().isOp(entityhuman.getProfile()) && icommand.canUse(entityhuman) && (!(icommandlistener instanceof RemoteControlCommandListener) || MinecraftServer.getServer().m())) { ++ entityhuman.sendMessage(chatmessage); ++ } ++ } ++ } ++ ++ if (icommandlistener != MinecraftServer.getServer()) { ++ MinecraftServer.getServer().sendMessage(chatmessage); ++ } ++ ++ if ((i & 1) != 1) { ++ icommandlistener.sendMessage(new ChatMessage(s, aobject)); ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/DataWatcher.java b/src/main/java/net/minecraft/server/DataWatcher.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/DataWatcher.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.util.ArrayList; ++import java.util.HashMap; ++import java.util.Iterator; ++import java.util.List; ++import java.util.Map; ++import java.util.concurrent.locks.ReadWriteLock; ++import java.util.concurrent.locks.ReentrantReadWriteLock; ++ ++import net.minecraft.util.org.apache.commons.lang3.ObjectUtils; ++ ++public class DataWatcher { ++ ++ private final Entity a; ++ private boolean b = true; ++ private static final HashMap c = new HashMap(); ++ private final Map d = new HashMap(); ++ private boolean e; ++ private ReadWriteLock f = new ReentrantReadWriteLock(); ++ ++ public DataWatcher(Entity entity) { ++ this.a = entity; ++ } ++ ++ public void a(int i, Object object) { ++ Integer integer = (Integer) c.get(object.getClass()); ++ ++ if (integer == null) { ++ throw new IllegalArgumentException("Unknown data type: " + object.getClass()); ++ } else if (i > 31) { ++ throw new IllegalArgumentException("Data value id is too big with " + i + "! (Max is " + 31 + ")"); ++ } else if (this.d.containsKey(Integer.valueOf(i))) { ++ throw new IllegalArgumentException("Duplicate id value for " + i + "!"); ++ } else { ++ WatchableObject watchableobject = new WatchableObject(integer.intValue(), i, object); ++ ++ this.f.writeLock().lock(); ++ this.d.put(Integer.valueOf(i), watchableobject); ++ this.f.writeLock().unlock(); ++ this.b = false; ++ } ++ } ++ ++ public void add(int i, int j) { ++ WatchableObject watchableobject = new WatchableObject(j, i, null); ++ ++ this.f.writeLock().lock(); ++ this.d.put(Integer.valueOf(i), watchableobject); ++ this.f.writeLock().unlock(); ++ this.b = false; ++ } ++ ++ public byte getByte(int i) { ++ return ((Byte) this.i(i).b()).byteValue(); ++ } ++ ++ public short getShort(int i) { ++ return ((Short) this.i(i).b()).shortValue(); ++ } ++ ++ public int getInt(int i) { ++ return ((Integer) this.i(i).b()).intValue(); ++ } ++ ++ public float getFloat(int i) { ++ return ((Float) this.i(i).b()).floatValue(); ++ } ++ ++ public String getString(int i) { ++ return (String) this.i(i).b(); ++ } ++ ++ public ItemStack getItemStack(int i) { ++ return (ItemStack) this.i(i).b(); ++ } ++ ++ private WatchableObject i(int i) { ++ this.f.readLock().lock(); ++ ++ WatchableObject watchableobject; ++ ++ try { ++ watchableobject = (WatchableObject) this.d.get(Integer.valueOf(i)); ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.a(throwable, "Getting synched entity data"); ++ CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Synched entity data"); ++ ++ crashreportsystemdetails.a("Data ID", Integer.valueOf(i)); ++ throw new ReportedException(crashreport); ++ } ++ ++ this.f.readLock().unlock(); ++ return watchableobject; ++ } ++ ++ public void watch(int i, Object object) { ++ WatchableObject watchableobject = this.i(i); ++ ++ if (ObjectUtils.notEqual(object, watchableobject.b())) { ++ watchableobject.a(object); ++ this.a.i(i); ++ watchableobject.a(true); ++ this.e = true; ++ } ++ } ++ ++ public void update(int i) { ++ WatchableObject.a(this.i(i), true); ++ this.e = true; ++ } ++ ++ public boolean a() { ++ return this.e; ++ } ++ ++ public static void a(List list, PacketDataSerializer packetdataserializer) { ++ if (list != null) { ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ WatchableObject watchableobject = (WatchableObject) iterator.next(); ++ ++ a(packetdataserializer, watchableobject); ++ } ++ } ++ ++ packetdataserializer.writeByte(127); ++ } ++ ++ public List b() { ++ ArrayList arraylist = null; ++ ++ if (this.e) { ++ this.f.readLock().lock(); ++ Iterator iterator = this.d.values().iterator(); ++ ++ while (iterator.hasNext()) { ++ WatchableObject watchableobject = (WatchableObject) iterator.next(); ++ ++ if (watchableobject.d()) { ++ watchableobject.a(false); ++ if (arraylist == null) { ++ arraylist = new ArrayList(); ++ } ++ ++ arraylist.add(watchableobject); ++ } ++ } ++ ++ this.f.readLock().unlock(); ++ } ++ ++ this.e = false; ++ return arraylist; ++ } ++ ++ public void a(PacketDataSerializer packetdataserializer) { ++ this.f.readLock().lock(); ++ Iterator iterator = this.d.values().iterator(); ++ ++ while (iterator.hasNext()) { ++ WatchableObject watchableobject = (WatchableObject) iterator.next(); ++ ++ a(packetdataserializer, watchableobject); ++ } ++ ++ this.f.readLock().unlock(); ++ packetdataserializer.writeByte(127); ++ } ++ ++ public List c() { ++ ArrayList arraylist = null; ++ ++ this.f.readLock().lock(); ++ ++ WatchableObject watchableobject; ++ ++ for (Iterator iterator = this.d.values().iterator(); iterator.hasNext(); arraylist.add(watchableobject)) { ++ watchableobject = (WatchableObject) iterator.next(); ++ if (arraylist == null) { ++ arraylist = new ArrayList(); ++ } ++ } ++ ++ this.f.readLock().unlock(); ++ return arraylist; ++ } ++ ++ private static void a(PacketDataSerializer packetdataserializer, WatchableObject watchableobject) { ++ int i = (watchableobject.c() << 5 | watchableobject.a() & 31) & 255; ++ ++ packetdataserializer.writeByte(i); ++ switch (watchableobject.c()) { ++ case 0: ++ packetdataserializer.writeByte(((Byte) watchableobject.b()).byteValue()); ++ break; ++ ++ case 1: ++ packetdataserializer.writeShort(((Short) watchableobject.b()).shortValue()); ++ break; ++ ++ case 2: ++ packetdataserializer.writeInt(((Integer) watchableobject.b()).intValue()); ++ break; ++ ++ case 3: ++ packetdataserializer.writeFloat(((Float) watchableobject.b()).floatValue()); ++ break; ++ ++ case 4: ++ try { ++ packetdataserializer.a((String) watchableobject.b()); ++ } catch (java.io.IOException ex) { ++ throw new RuntimeException(ex); ++ } ++ break; ++ ++ case 5: ++ ItemStack itemstack = (ItemStack) watchableobject.b(); ++ ++ packetdataserializer.a(itemstack); ++ break; ++ ++ case 6: ++ ChunkCoordinates chunkcoordinates = (ChunkCoordinates) watchableobject.b(); ++ ++ packetdataserializer.writeInt(chunkcoordinates.x); ++ packetdataserializer.writeInt(chunkcoordinates.y); ++ packetdataserializer.writeInt(chunkcoordinates.z); ++ } ++ } ++ ++ public static List b(PacketDataSerializer packetdataserializer) { ++ ArrayList arraylist = null; ++ ++ for (byte b0 = packetdataserializer.readByte(); b0 != 127; b0 = packetdataserializer.readByte()) { ++ if (arraylist == null) { ++ arraylist = new ArrayList(); ++ } ++ ++ int i = (b0 & 224) >> 5; ++ int j = b0 & 31; ++ WatchableObject watchableobject = null; ++ ++ switch (i) { ++ case 0: ++ watchableobject = new WatchableObject(i, j, Byte.valueOf(packetdataserializer.readByte())); ++ break; ++ ++ case 1: ++ watchableobject = new WatchableObject(i, j, Short.valueOf(packetdataserializer.readShort())); ++ break; ++ ++ case 2: ++ watchableobject = new WatchableObject(i, j, Integer.valueOf(packetdataserializer.readInt())); ++ break; ++ ++ case 3: ++ watchableobject = new WatchableObject(i, j, Float.valueOf(packetdataserializer.readFloat())); ++ break; ++ ++ case 4: ++ try { ++ watchableobject = new WatchableObject(i, j, packetdataserializer.c(32767)); ++ } catch (java.io.IOException ex) { ++ throw new RuntimeException(ex); ++ } ++ break; ++ ++ case 5: ++ watchableobject = new WatchableObject(i, j, packetdataserializer.c()); ++ break; ++ ++ case 6: ++ int k = packetdataserializer.readInt(); ++ int l = packetdataserializer.readInt(); ++ int i1 = packetdataserializer.readInt(); ++ ++ watchableobject = new WatchableObject(i, j, new ChunkCoordinates(k, l, i1)); ++ } ++ ++ arraylist.add(watchableobject); ++ } ++ ++ return arraylist; ++ } ++ ++ public boolean d() { ++ return this.b; ++ } ++ ++ public void e() { ++ this.e = false; ++ } ++ ++ static { ++ c.put(Byte.class, Integer.valueOf(0)); ++ c.put(Short.class, Integer.valueOf(1)); ++ c.put(Integer.class, Integer.valueOf(2)); ++ c.put(Float.class, Integer.valueOf(3)); ++ c.put(String.class, Integer.valueOf(4)); ++ c.put(ItemStack.class, Integer.valueOf(5)); ++ c.put(ChunkCoordinates.class, Integer.valueOf(6)); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/GameProfileBanEntry.java b/src/main/java/net/minecraft/server/GameProfileBanEntry.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/GameProfileBanEntry.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.util.Date; ++import java.util.UUID; ++ ++import net.minecraft.util.com.google.gson.JsonObject; ++import net.minecraft.util.com.mojang.authlib.GameProfile; ++ ++public class GameProfileBanEntry extends ExpirableListEntry { ++ ++ public GameProfileBanEntry(GameProfile gameprofile) { ++ this(gameprofile, (Date) null, (String) null, (Date) null, (String) null); ++ } ++ ++ public GameProfileBanEntry(GameProfile gameprofile, Date date, String s, Date date1, String s1) { ++ super(gameprofile, date1, s, date1, s1); ++ } ++ ++ public GameProfileBanEntry(JsonObject jsonobject) { ++ super(b(jsonobject), jsonobject); ++ } ++ ++ protected void a(JsonObject jsonobject) { ++ if (this.getKey() != null) { ++ jsonobject.addProperty("uuid", ((GameProfile) this.getKey()).getId() == null ? "" : ((GameProfile) this.getKey()).getId().toString()); ++ jsonobject.addProperty("name", ((GameProfile) this.getKey()).getName()); ++ super.a(jsonobject); ++ } ++ } ++ ++ private static GameProfile b(JsonObject jsonobject) { ++ if (jsonobject.has("uuid") && jsonobject.has("name")) { ++ String s = jsonobject.get("uuid").getAsString(); ++ ++ UUID uuid; ++ ++ try { ++ uuid = UUID.fromString(s); ++ } catch (Throwable throwable) { ++ return null; ++ } ++ ++ return new GameProfile(uuid, jsonobject.get("name").getAsString()); ++ } else { ++ return null; ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/IntCache.java b/src/main/java/net/minecraft/server/IntCache.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/IntCache.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.util.ArrayList; ++import java.util.List; ++ ++public class IntCache { ++ ++ private static int a = 256; ++ private static List b = new ArrayList(); ++ private static List c = new ArrayList(); ++ private static List d = new ArrayList(); ++ private static List e = new ArrayList(); ++ ++ public static synchronized int[] a(int i) { ++ int[] aint; ++ ++ if (i <= 256) { ++ if (b.isEmpty()) { ++ aint = new int[256]; ++ c.add(aint); ++ return aint; ++ } else { ++ aint = (int[]) b.remove(b.size() - 1); ++ c.add(aint); ++ return aint; ++ } ++ } else if (i > a) { ++ a = i; ++ d.clear(); ++ e.clear(); ++ aint = new int[a]; ++ e.add(aint); ++ return aint; ++ } else if (d.isEmpty()) { ++ aint = new int[a]; ++ e.add(aint); ++ return aint; ++ } else { ++ aint = (int[]) d.remove(d.size() - 1); ++ e.add(aint); ++ return aint; ++ } ++ } ++ ++ public static synchronized void a() { ++ if (!d.isEmpty()) { ++ d.remove(d.size() - 1); ++ } ++ ++ if (!b.isEmpty()) { ++ b.remove(b.size() - 1); ++ } ++ ++ d.addAll(e); ++ b.addAll(c); ++ e.clear(); ++ c.clear(); ++ } ++ ++ public static synchronized String b() { ++ return "cache: " + d.size() + ", tcache: " + b.size() + ", allocated: " + e.size() + ", tallocated: " + c.size(); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/ItemSkull.java b/src/main/java/net/minecraft/server/ItemSkull.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/ItemSkull.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.util.UUID; ++ ++import net.minecraft.util.com.mojang.authlib.GameProfile; ++ ++public class ItemSkull extends Item { ++ ++ private static final String[] b = new String[] { "skeleton", "wither", "zombie", "char", "creeper"}; ++ public static final String[] a = new String[] { "skeleton", "wither", "zombie", "steve", "creeper"}; ++ ++ public ItemSkull() { ++ this.a(CreativeModeTab.c); ++ this.setMaxDurability(0); ++ this.a(true); ++ } ++ ++ public boolean interactWith(ItemStack itemstack, EntityHuman entityhuman, World world, int i, int j, int k, int l, float f, float f1, float f2) { ++ if (l == 0) { ++ return false; ++ } else if (!world.getType(i, j, k).getMaterial().isBuildable()) { ++ return false; ++ } else { ++ if (l == 1) { ++ ++j; ++ } ++ ++ if (l == 2) { ++ --k; ++ } ++ ++ if (l == 3) { ++ ++k; ++ } ++ ++ if (l == 4) { ++ --i; ++ } ++ ++ if (l == 5) { ++ ++i; ++ } ++ ++ if (!world.isStatic) { ++ world.setTypeAndData(i, j, k, Blocks.SKULL, l, 2); ++ int i1 = 0; ++ ++ if (l == 1) { ++ i1 = MathHelper.floor((double) (entityhuman.yaw * 16.0F / 360.0F) + 0.5D) & 15; ++ } ++ ++ TileEntity tileentity = world.getTileEntity(i, j, k); ++ ++ if (tileentity != null && tileentity instanceof TileEntitySkull) { ++ if (itemstack.getData() == 3) { ++ GameProfile gameprofile = null; ++ ++ if (itemstack.hasTag()) { ++ NBTTagCompound nbttagcompound = itemstack.getTag(); ++ ++ if (nbttagcompound.hasKeyOfType("SkullOwner", 10)) { ++ gameprofile = GameProfileSerializer.deserialize(nbttagcompound.getCompound("SkullOwner")); ++ } else if (nbttagcompound.hasKeyOfType("SkullOwner", 8) && nbttagcompound.getString("SkullOwner").length() > 0) { ++ gameprofile = new GameProfile((UUID) null, nbttagcompound.getString("SkullOwner")); ++ } ++ } ++ ++ ((TileEntitySkull) tileentity).setGameProfile(gameprofile); ++ } else { ++ ((TileEntitySkull) tileentity).setSkullType(itemstack.getData()); ++ } ++ ++ ((TileEntitySkull) tileentity).setRotation(i1); ++ ((BlockSkull) Blocks.SKULL).a(world, i, j, k, (TileEntitySkull) tileentity); ++ } ++ ++ --itemstack.count; ++ } ++ ++ return true; ++ } ++ } ++ ++ public int filterData(int i) { ++ return i; ++ } ++ ++ public String a(ItemStack itemstack) { ++ int i = itemstack.getData(); ++ ++ if (i < 0 || i >= b.length) { ++ i = 0; ++ } ++ ++ return super.getName() + "." + b[i]; ++ } ++ ++ public String n(ItemStack itemstack) { ++ if (itemstack.getData() == 3 && itemstack.hasTag()) { ++ if (itemstack.getTag().hasKeyOfType("SkullOwner", 10)) { ++ return LocaleI18n.get("item.skull.player.name", new Object[] { GameProfileSerializer.deserialize(itemstack.getTag().getCompound("SkullOwner")).getName()}); ++ } ++ ++ if (itemstack.getTag().hasKeyOfType("SkullOwner", 8)) { ++ return LocaleI18n.get("item.skull.player.name", new Object[] { itemstack.getTag().getString("SkullOwner")}); ++ } ++ } ++ ++ return super.n(itemstack); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/NBTBase.java b/src/main/java/net/minecraft/server/NBTBase.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/NBTBase.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.io.DataInput; ++import java.io.DataOutput; ++import java.io.IOException; ++ ++public abstract class NBTBase { ++ ++ public static final String[] a = new String[] { "END", "BYTE", "SHORT", "INT", "LONG", "FLOAT", "DOUBLE", "BYTE[]", "STRING", "LIST", "COMPOUND", "INT[]"}; ++ ++ abstract void write(DataOutput dataoutput) throws IOException; ++ ++ abstract void load(DataInput datainput, int i, NBTReadLimiter nbtreadlimiter) throws IOException; ++ ++ public abstract String toString(); ++ ++ public abstract byte getTypeId(); ++ ++ protected NBTBase() {} ++ ++ protected static NBTBase createTag(byte b0) { ++ switch (b0) { ++ case 0: ++ return new NBTTagEnd(); ++ ++ case 1: ++ return new NBTTagByte(); ++ ++ case 2: ++ return new NBTTagShort(); ++ ++ case 3: ++ return new NBTTagInt(); ++ ++ case 4: ++ return new NBTTagLong(); ++ ++ case 5: ++ return new NBTTagFloat(); ++ ++ case 6: ++ return new NBTTagDouble(); ++ ++ case 7: ++ return new NBTTagByteArray(); ++ ++ case 8: ++ return new NBTTagString(); ++ ++ case 9: ++ return new NBTTagList(); ++ ++ case 10: ++ return new NBTTagCompound(); ++ ++ case 11: ++ return new NBTTagIntArray(); ++ ++ default: ++ return null; ++ } ++ } ++ ++ public abstract NBTBase clone(); ++ ++ public boolean equals(Object object) { ++ if (!(object instanceof NBTBase)) { ++ return false; ++ } else { ++ NBTBase nbtbase = (NBTBase) object; ++ ++ return this.getTypeId() == nbtbase.getTypeId(); ++ } ++ } ++ ++ public int hashCode() { ++ return this.getTypeId(); ++ } ++ ++ protected String a_() { ++ return this.toString(); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/NBTTagByteArray.java b/src/main/java/net/minecraft/server/NBTTagByteArray.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/NBTTagByteArray.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.io.DataInput; ++import java.io.DataOutput; ++import java.io.IOException; ++import java.util.Arrays; ++ ++public class NBTTagByteArray extends NBTBase { ++ ++ private byte[] data; ++ ++ NBTTagByteArray() {} ++ ++ public NBTTagByteArray(byte[] abyte) { ++ this.data = abyte; ++ } ++ ++ void write(DataOutput dataoutput) throws IOException { ++ dataoutput.writeInt(this.data.length); ++ dataoutput.write(this.data); ++ } ++ ++ void load(DataInput datainput, int i, NBTReadLimiter nbtreadlimiter) throws IOException { ++ int j = datainput.readInt(); ++ ++ nbtreadlimiter.a((long) (8 * j)); ++ this.data = new byte[j]; ++ datainput.readFully(this.data); ++ } ++ ++ public byte getTypeId() { ++ return (byte) 7; ++ } ++ ++ public String toString() { ++ return "[" + this.data.length + " bytes]"; ++ } ++ ++ public NBTBase clone() { ++ byte[] abyte = new byte[this.data.length]; ++ ++ System.arraycopy(this.data, 0, abyte, 0, this.data.length); ++ return new NBTTagByteArray(abyte); ++ } ++ ++ public boolean equals(Object object) { ++ return super.equals(object) ? Arrays.equals(this.data, ((NBTTagByteArray) object).data) : false; ++ } ++ ++ public int hashCode() { ++ return super.hashCode() ^ Arrays.hashCode(this.data); ++ } ++ ++ public byte[] c() { ++ return this.data; ++ } ++} +diff --git a/src/main/java/net/minecraft/server/NBTTagIntArray.java b/src/main/java/net/minecraft/server/NBTTagIntArray.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/NBTTagIntArray.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.io.DataInput; ++import java.io.DataOutput; ++import java.io.IOException; ++import java.util.Arrays; ++ ++public class NBTTagIntArray extends NBTBase { ++ ++ private int[] data; ++ ++ NBTTagIntArray() {} ++ ++ public NBTTagIntArray(int[] aint) { ++ this.data = aint; ++ } ++ ++ void write(DataOutput dataoutput) throws IOException { ++ dataoutput.writeInt(this.data.length); ++ ++ for (int i = 0; i < this.data.length; ++i) { ++ dataoutput.writeInt(this.data[i]); ++ } ++ } ++ ++ void load(DataInput datainput, int i, NBTReadLimiter nbtreadlimiter) throws IOException { ++ int j = datainput.readInt(); ++ ++ nbtreadlimiter.a((long) (32 * j)); ++ this.data = new int[j]; ++ ++ for (int k = 0; k < j; ++k) { ++ this.data[k] = datainput.readInt(); ++ } ++ } ++ ++ public byte getTypeId() { ++ return (byte) 11; ++ } ++ ++ public String toString() { ++ String s = "["; ++ int[] aint = this.data; ++ int i = aint.length; ++ ++ for (int j = 0; j < i; ++j) { ++ int k = aint[j]; ++ ++ s = s + k + ","; ++ } ++ ++ return s + "]"; ++ } ++ ++ public NBTBase clone() { ++ int[] aint = new int[this.data.length]; ++ ++ System.arraycopy(this.data, 0, aint, 0, this.data.length); ++ return new NBTTagIntArray(aint); ++ } ++ ++ public boolean equals(Object object) { ++ return super.equals(object) ? Arrays.equals(this.data, ((NBTTagIntArray) object).data) : false; ++ } ++ ++ public int hashCode() { ++ return super.hashCode() ^ Arrays.hashCode(this.data); ++ } ++ ++ public int[] c() { ++ return this.data; ++ } ++} +diff --git a/src/main/java/net/minecraft/server/NextTickListEntry.java b/src/main/java/net/minecraft/server/NextTickListEntry.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/NextTickListEntry.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++public class NextTickListEntry implements Comparable { ++ ++ private static long f; ++ private final Block g; ++ public int a; ++ public int b; ++ public int c; ++ public long d; ++ public int e; ++ private long h; ++ ++ public NextTickListEntry(int i, int j, int k, Block block) { ++ this.h = (long) (f++); ++ this.a = i; ++ this.b = j; ++ this.c = k; ++ this.g = block; ++ } ++ ++ public boolean equals(Object object) { ++ if (!(object instanceof NextTickListEntry)) { ++ return false; ++ } else { ++ NextTickListEntry nextticklistentry = (NextTickListEntry) object; ++ ++ return this.a == nextticklistentry.a && this.b == nextticklistentry.b && this.c == nextticklistentry.c && Block.a(this.g, nextticklistentry.g); ++ } ++ } ++ ++ public int hashCode() { ++ return (this.a * 1024 * 1024 + this.c * 1024 + this.b) * 256; ++ } ++ ++ public NextTickListEntry a(long i) { ++ this.d = i; ++ return this; ++ } ++ ++ public void a(int i) { ++ this.e = i; ++ } ++ ++ public int compareTo(NextTickListEntry nextticklistentry) { ++ return this.d < nextticklistentry.d ? -1 : (this.d > nextticklistentry.d ? 1 : (this.e != nextticklistentry.e ? this.e - nextticklistentry.e : (this.h < nextticklistentry.h ? -1 : (this.h > nextticklistentry.h ? 1 : 0)))); ++ } ++ ++ public String toString() { ++ return Block.getId(this.g) + ": (" + this.a + ", " + this.b + ", " + this.c + "), " + this.d + ", " + this.e + ", " + this.h; ++ } ++ ++ public Block a() { ++ return this.g; ++ } ++ ++ public int compareTo(Object object) { ++ return this.compareTo((NextTickListEntry) object); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/NibbleArray.java b/src/main/java/net/minecraft/server/NibbleArray.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/NibbleArray.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++public class NibbleArray { ++ ++ public final byte[] a; ++ private final int b; ++ private final int c; ++ ++ public NibbleArray(int i, int j) { ++ this.a = new byte[i >> 1]; ++ this.b = j; ++ this.c = j + 4; ++ } ++ ++ public NibbleArray(byte[] abyte, int i) { ++ this.a = abyte; ++ this.b = i; ++ this.c = i + 4; ++ } ++ ++ public int a(int i, int j, int k) { ++ int l = j << this.c | k << this.b | i; ++ int i1 = l >> 1; ++ int j1 = l & 1; ++ ++ return j1 == 0 ? this.a[i1] & 15 : this.a[i1] >> 4 & 15; ++ } ++ ++ public void a(int i, int j, int k, int l) { ++ int i1 = j << this.c | k << this.b | i; ++ int j1 = i1 >> 1; ++ int k1 = i1 & 1; ++ ++ if (k1 == 0) { ++ this.a[j1] = (byte) (this.a[j1] & 240 | l & 15); ++ } else { ++ this.a[j1] = (byte) (this.a[j1] & 15 | (l & 15) << 4); ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/OldChunkLoader.java b/src/main/java/net/minecraft/server/OldChunkLoader.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/OldChunkLoader.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++public class OldChunkLoader { ++ ++ public static OldChunk a(NBTTagCompound nbttagcompound) { ++ int i = nbttagcompound.getInt("xPos"); ++ int j = nbttagcompound.getInt("zPos"); ++ OldChunk oldchunk = new OldChunk(i, j); ++ ++ oldchunk.g = nbttagcompound.getByteArray("Blocks"); ++ oldchunk.f = new OldNibbleArray(nbttagcompound.getByteArray("Data"), 7); ++ oldchunk.e = new OldNibbleArray(nbttagcompound.getByteArray("SkyLight"), 7); ++ oldchunk.d = new OldNibbleArray(nbttagcompound.getByteArray("BlockLight"), 7); ++ oldchunk.c = nbttagcompound.getByteArray("HeightMap"); ++ oldchunk.b = nbttagcompound.getBoolean("TerrainPopulated"); ++ oldchunk.h = nbttagcompound.getList("Entities", 10); ++ oldchunk.i = nbttagcompound.getList("TileEntities", 10); ++ oldchunk.j = nbttagcompound.getList("TileTicks", 10); ++ ++ try { ++ oldchunk.a = nbttagcompound.getLong("LastUpdate"); ++ } catch (ClassCastException classcastexception) { ++ oldchunk.a = (long) nbttagcompound.getInt("LastUpdate"); ++ } ++ ++ return oldchunk; ++ } ++ ++ public static void a(OldChunk oldchunk, NBTTagCompound nbttagcompound, WorldChunkManager worldchunkmanager) { ++ nbttagcompound.setInt("xPos", oldchunk.k); ++ nbttagcompound.setInt("zPos", oldchunk.l); ++ nbttagcompound.setLong("LastUpdate", oldchunk.a); ++ int[] aint = new int[oldchunk.c.length]; ++ ++ for (int i = 0; i < oldchunk.c.length; ++i) { ++ aint[i] = oldchunk.c[i]; ++ } ++ ++ nbttagcompound.setIntArray("HeightMap", aint); ++ nbttagcompound.setBoolean("TerrainPopulated", oldchunk.b); ++ NBTTagList nbttaglist = new NBTTagList(); ++ ++ int j; ++ ++ for (int k = 0; k < 8; ++k) { ++ boolean flag = true; ++ ++ for (j = 0; j < 16 && flag; ++j) { ++ int l = 0; ++ ++ while (l < 16 && flag) { ++ int i1 = 0; ++ ++ while (true) { ++ if (i1 < 16) { ++ int j1 = j << 11 | i1 << 7 | l + (k << 4); ++ byte b0 = oldchunk.g[j1]; ++ ++ if (b0 == 0) { ++ ++i1; ++ continue; ++ } ++ ++ flag = false; ++ } ++ ++ ++l; ++ break; ++ } ++ } ++ } ++ ++ if (!flag) { ++ byte[] abyte = new byte[4096]; ++ NibbleArray nibblearray = new NibbleArray(abyte.length, 4); ++ NibbleArray nibblearray1 = new NibbleArray(abyte.length, 4); ++ NibbleArray nibblearray2 = new NibbleArray(abyte.length, 4); ++ ++ for (int k1 = 0; k1 < 16; ++k1) { ++ for (int l1 = 0; l1 < 16; ++l1) { ++ for (int i2 = 0; i2 < 16; ++i2) { ++ int j2 = k1 << 11 | i2 << 7 | l1 + (k << 4); ++ byte b1 = oldchunk.g[j2]; ++ ++ abyte[l1 << 8 | i2 << 4 | k1] = (byte) (b1 & 255); ++ nibblearray.a(k1, l1, i2, oldchunk.f.a(k1, l1 + (k << 4), i2)); ++ nibblearray1.a(k1, l1, i2, oldchunk.e.a(k1, l1 + (k << 4), i2)); ++ nibblearray2.a(k1, l1, i2, oldchunk.d.a(k1, l1 + (k << 4), i2)); ++ } ++ } ++ } ++ ++ NBTTagCompound nbttagcompound1 = new NBTTagCompound(); ++ ++ nbttagcompound1.setByte("Y", (byte) (k & 255)); ++ nbttagcompound1.setByteArray("Blocks", abyte); ++ nbttagcompound1.setByteArray("Data", nibblearray.a); ++ nbttagcompound1.setByteArray("SkyLight", nibblearray1.a); ++ nbttagcompound1.setByteArray("BlockLight", nibblearray2.a); ++ nbttaglist.add(nbttagcompound1); ++ } ++ } ++ ++ nbttagcompound.set("Sections", nbttaglist); ++ byte[] abyte1 = new byte[256]; ++ ++ for (int k2 = 0; k2 < 16; ++k2) { ++ for (j = 0; j < 16; ++j) { ++ abyte1[j << 4 | k2] = (byte) (worldchunkmanager.getBiome(oldchunk.k << 4 | k2, oldchunk.l << 4 | j).id & 255); ++ } ++ } ++ ++ nbttagcompound.setByteArray("Biomes", abyte1); ++ nbttagcompound.set("Entities", oldchunk.h); ++ nbttagcompound.set("TileEntities", oldchunk.i); ++ if (oldchunk.j != null) { ++ nbttagcompound.set("TileTicks", oldchunk.j); ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.io.IOException; ++import java.util.zip.DataFormatException; ++import java.util.zip.Deflater; ++import java.util.zip.Inflater; ++ ++public class PacketPlayOutMapChunk extends Packet { ++ ++ private int a; ++ private int b; ++ private int c; ++ private int d; ++ private byte[] e; ++ private byte[] f; ++ private boolean g; ++ private int h; ++ private static byte[] i = new byte[196864]; ++ ++ public PacketPlayOutMapChunk() {} ++ ++ public PacketPlayOutMapChunk(Chunk chunk, boolean flag, int i) { ++ this.a = chunk.locX; ++ this.b = chunk.locZ; ++ this.g = flag; ++ ChunkMap chunkmap = a(chunk, flag, i); ++ Deflater deflater = new Deflater(-1); ++ ++ this.d = chunkmap.c; ++ this.c = chunkmap.b; ++ ++ try { ++ this.f = chunkmap.a; ++ deflater.setInput(chunkmap.a, 0, chunkmap.a.length); ++ deflater.finish(); ++ this.e = new byte[chunkmap.a.length]; ++ this.h = deflater.deflate(this.e); ++ } finally { ++ deflater.end(); ++ } ++ } ++ ++ public static int c() { ++ return 196864; ++ } ++ ++ public void a(PacketDataSerializer packetdataserializer) throws IOException { ++ this.a = packetdataserializer.readInt(); ++ this.b = packetdataserializer.readInt(); ++ this.g = packetdataserializer.readBoolean(); ++ this.c = packetdataserializer.readShort(); ++ this.d = packetdataserializer.readShort(); ++ this.h = packetdataserializer.readInt(); ++ if (i.length < this.h) { ++ i = new byte[this.h]; ++ } ++ ++ packetdataserializer.readBytes(i, 0, this.h); ++ int i = 0; ++ ++ int j; ++ ++ for (j = 0; j < 16; ++j) { ++ i += this.c >> j & 1; ++ } ++ ++ j = 12288 * i; ++ if (this.g) { ++ j += 256; ++ } ++ ++ this.f = new byte[j]; ++ Inflater inflater = new Inflater(); ++ ++ inflater.setInput(PacketPlayOutMapChunk.i, 0, this.h); ++ ++ try { ++ inflater.inflate(this.f); ++ } catch (DataFormatException dataformatexception) { ++ throw new IOException("Bad compressed data format"); ++ } finally { ++ inflater.end(); ++ } ++ } ++ ++ public void b(PacketDataSerializer packetdataserializer) { ++ packetdataserializer.writeInt(this.a); ++ packetdataserializer.writeInt(this.b); ++ packetdataserializer.writeBoolean(this.g); ++ packetdataserializer.writeShort((short) (this.c & '\uffff')); ++ packetdataserializer.writeShort((short) (this.d & '\uffff')); ++ packetdataserializer.writeInt(this.h); ++ packetdataserializer.writeBytes(this.e, 0, this.h); ++ } ++ ++ public void a(PacketPlayOutListener packetplayoutlistener) { ++ packetplayoutlistener.a(this); ++ } ++ ++ public String b() { ++ return String.format("x=%d, z=%d, full=%b, sects=%d, add=%d, size=%d", new Object[] { Integer.valueOf(this.a), Integer.valueOf(this.b), Boolean.valueOf(this.g), Integer.valueOf(this.c), Integer.valueOf(this.d), Integer.valueOf(this.h)}); ++ } ++ ++ public static ChunkMap a(Chunk chunk, boolean flag, int i) { ++ int j = 0; ++ ChunkSection[] achunksection = chunk.getSections(); ++ int k = 0; ++ ChunkMap chunkmap = new ChunkMap(); ++ byte[] abyte = PacketPlayOutMapChunk.i; ++ ++ if (flag) { ++ chunk.q = true; ++ } ++ ++ int l; ++ ++ for (l = 0; l < achunksection.length; ++l) { ++ if (achunksection[l] != null && (!flag || !achunksection[l].isEmpty()) && (i & 1 << l) != 0) { ++ chunkmap.b |= 1 << l; ++ if (achunksection[l].getExtendedIdArray() != null) { ++ chunkmap.c |= 1 << l; ++ ++k; ++ } ++ } ++ } ++ ++ for (l = 0; l < achunksection.length; ++l) { ++ if (achunksection[l] != null && (!flag || !achunksection[l].isEmpty()) && (i & 1 << l) != 0) { ++ byte[] abyte1 = achunksection[l].getIdArray(); ++ ++ System.arraycopy(abyte1, 0, abyte, j, abyte1.length); ++ j += abyte1.length; ++ } ++ } ++ ++ NibbleArray nibblearray; ++ ++ for (l = 0; l < achunksection.length; ++l) { ++ if (achunksection[l] != null && (!flag || !achunksection[l].isEmpty()) && (i & 1 << l) != 0) { ++ nibblearray = achunksection[l].getDataArray(); ++ System.arraycopy(nibblearray.a, 0, abyte, j, nibblearray.a.length); ++ j += nibblearray.a.length; ++ } ++ } ++ ++ for (l = 0; l < achunksection.length; ++l) { ++ if (achunksection[l] != null && (!flag || !achunksection[l].isEmpty()) && (i & 1 << l) != 0) { ++ nibblearray = achunksection[l].getEmittedLightArray(); ++ System.arraycopy(nibblearray.a, 0, abyte, j, nibblearray.a.length); ++ j += nibblearray.a.length; ++ } ++ } ++ ++ if (!chunk.world.worldProvider.g) { ++ for (l = 0; l < achunksection.length; ++l) { ++ if (achunksection[l] != null && (!flag || !achunksection[l].isEmpty()) && (i & 1 << l) != 0) { ++ nibblearray = achunksection[l].getSkyLightArray(); ++ System.arraycopy(nibblearray.a, 0, abyte, j, nibblearray.a.length); ++ j += nibblearray.a.length; ++ } ++ } ++ } ++ ++ if (k > 0) { ++ for (l = 0; l < achunksection.length; ++l) { ++ if (achunksection[l] != null && (!flag || !achunksection[l].isEmpty()) && achunksection[l].getExtendedIdArray() != null && (i & 1 << l) != 0) { ++ nibblearray = achunksection[l].getExtendedIdArray(); ++ System.arraycopy(nibblearray.a, 0, abyte, j, nibblearray.a.length); ++ j += nibblearray.a.length; ++ } ++ } ++ } ++ ++ if (flag) { ++ byte[] abyte2 = chunk.m(); ++ ++ System.arraycopy(abyte2, 0, abyte, j, abyte2.length); ++ j += abyte2.length; ++ } ++ ++ chunkmap.a = new byte[j]; ++ System.arraycopy(abyte, 0, chunkmap.a, 0, j); ++ return chunkmap; ++ } ++ ++ public void handle(PacketListener packetlistener) { ++ this.a((PacketPlayOutListener) packetlistener); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/PacketPlayOutOpenWindow.java b/src/main/java/net/minecraft/server/PacketPlayOutOpenWindow.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/PacketPlayOutOpenWindow.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.io.IOException; ++ ++public class PacketPlayOutOpenWindow extends Packet { ++ ++ private int a; ++ private int b; ++ private String c; ++ private int d; ++ private boolean e; ++ private int f; ++ ++ public PacketPlayOutOpenWindow() {} ++ ++ public PacketPlayOutOpenWindow(int i, int j, String s, int k, boolean flag) { ++ this.a = i; ++ this.b = j; ++ this.c = s; ++ this.d = k; ++ this.e = flag; ++ } ++ ++ public PacketPlayOutOpenWindow(int i, int j, String s, int k, boolean flag, int l) { ++ this(i, j, s, k, flag); ++ this.f = l; ++ } ++ ++ public void a(PacketPlayOutListener packetplayoutlistener) { ++ packetplayoutlistener.a(this); ++ } ++ ++ public void a(PacketDataSerializer packetdataserializer) throws IOException { ++ this.a = packetdataserializer.readUnsignedByte(); ++ this.b = packetdataserializer.readUnsignedByte(); ++ this.c = packetdataserializer.c(32); ++ this.d = packetdataserializer.readUnsignedByte(); ++ this.e = packetdataserializer.readBoolean(); ++ if (this.b == 11) { ++ this.f = packetdataserializer.readInt(); ++ } ++ } ++ ++ public void b(PacketDataSerializer packetdataserializer) throws IOException { ++ packetdataserializer.writeByte(this.a); ++ packetdataserializer.writeByte(this.b); ++ packetdataserializer.a(this.c); ++ packetdataserializer.writeByte(this.d); ++ packetdataserializer.writeBoolean(this.e); ++ if (this.b == 11) { ++ packetdataserializer.writeInt(this.f); ++ } ++ } ++ ++ public void handle(PacketListener packetlistener) { ++ this.a((PacketPlayOutListener) packetlistener); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/RegionFileCache.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.io.DataInputStream; ++import java.io.DataOutputStream; ++import java.io.File; ++import java.io.IOException; ++import java.util.HashMap; ++import java.util.Iterator; ++import java.util.Map; ++ ++public class RegionFileCache { ++ ++ private static final Map a = new HashMap(); ++ ++ public static synchronized RegionFile a(File file1, int i, int j) { ++ File file2 = new File(file1, "region"); ++ File file3 = new File(file2, "r." + (i >> 5) + "." + (j >> 5) + ".mca"); ++ RegionFile regionfile = (RegionFile) a.get(file3); ++ ++ if (regionfile != null) { ++ return regionfile; ++ } else { ++ if (!file2.exists()) { ++ file2.mkdirs(); ++ } ++ ++ if (a.size() >= 256) { ++ a(); ++ } ++ ++ RegionFile regionfile1 = new RegionFile(file3); ++ ++ a.put(file3, regionfile1); ++ return regionfile1; ++ } ++ } ++ ++ public static synchronized void a() { ++ Iterator iterator = a.values().iterator(); ++ ++ while (iterator.hasNext()) { ++ RegionFile regionfile = (RegionFile) iterator.next(); ++ ++ try { ++ if (regionfile != null) { ++ regionfile.c(); ++ } ++ } catch (IOException ioexception) { ++ ioexception.printStackTrace(); ++ } ++ } ++ ++ a.clear(); ++ } ++ ++ public static DataInputStream c(File file1, int i, int j) { ++ RegionFile regionfile = a(file1, i, j); ++ ++ return regionfile.a(i & 31, j & 31); ++ } ++ ++ public static DataOutputStream d(File file1, int i, int j) { ++ RegionFile regionfile = a(file1, i, j); ++ ++ return regionfile.b(i & 31, j & 31); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/ServerConnection.java b/src/main/java/net/minecraft/server/ServerConnection.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/ServerConnection.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.net.InetAddress; ++import java.util.ArrayList; ++import java.util.Collections; ++import java.util.Iterator; ++import java.util.List; ++import java.util.concurrent.Callable; ++ ++import net.minecraft.util.com.google.common.util.concurrent.ThreadFactoryBuilder; ++import net.minecraft.util.io.netty.bootstrap.ServerBootstrap; ++import net.minecraft.util.io.netty.channel.ChannelFuture; ++import net.minecraft.util.io.netty.channel.nio.NioEventLoopGroup; ++import net.minecraft.util.io.netty.channel.socket.nio.NioServerSocketChannel; ++import net.minecraft.util.io.netty.util.concurrent.GenericFutureListener; ++import org.apache.logging.log4j.LogManager; ++import org.apache.logging.log4j.Logger; ++ ++public class ServerConnection { ++ ++ private static final Logger b = LogManager.getLogger(); ++ private static final NioEventLoopGroup c = new NioEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty IO #%d").setDaemon(true).build()); ++ private final MinecraftServer d; ++ public volatile boolean a; ++ private final List e = Collections.synchronizedList(new ArrayList()); ++ private final List f = Collections.synchronizedList(new ArrayList()); ++ ++ public ServerConnection(MinecraftServer minecraftserver) { ++ this.d = minecraftserver; ++ this.a = true; ++ } ++ ++ public void a(InetAddress inetaddress, int i) { ++ List list = this.e; ++ ++ synchronized (this.e) { ++ this.e.add(((ServerBootstrap) ((ServerBootstrap) (new ServerBootstrap()).channel(NioServerSocketChannel.class)).childHandler(new ServerConnectionChannel(this)).group(c).localAddress(inetaddress, i)).bind().syncUninterruptibly()); ++ } ++ } ++ ++ public void b() { ++ this.a = false; ++ Iterator iterator = this.e.iterator(); ++ ++ while (iterator.hasNext()) { ++ ChannelFuture channelfuture = (ChannelFuture) iterator.next(); ++ ++ channelfuture.channel().close().syncUninterruptibly(); ++ } ++ } ++ ++ public void c() { ++ List list = this.f; ++ ++ synchronized (this.f) { ++ Iterator iterator = this.f.iterator(); ++ ++ while (iterator.hasNext()) { ++ NetworkManager networkmanager = (NetworkManager) iterator.next(); ++ ++ if (!networkmanager.isConnected()) { ++ iterator.remove(); ++ if (networkmanager.f() != null) { ++ networkmanager.getPacketListener().a(networkmanager.f()); ++ } else if (networkmanager.getPacketListener() != null) { ++ networkmanager.getPacketListener().a(new ChatComponentText("Disconnected")); ++ } ++ } else { ++ try { ++ networkmanager.a(); ++ } catch (Exception exception) { ++ if (networkmanager.c()) { ++ CrashReport crashreport = CrashReport.a(exception, "Ticking memory connection"); ++ CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Ticking connection"); ++ ++ crashreportsystemdetails.a("Connection", (Callable) (new CrashReportServerConnection(this, networkmanager))); ++ throw new ReportedException(crashreport); ++ } ++ ++ b.warn("Failed to handle packet for " + networkmanager.getSocketAddress(), exception); ++ ChatComponentText chatcomponenttext = new ChatComponentText("Internal server error"); ++ ++ networkmanager.handle(new PacketPlayOutKickDisconnect(chatcomponenttext), new GenericFutureListener[] { new ServerConnectionFuture(this, networkmanager, chatcomponenttext)}); ++ networkmanager.g(); ++ } ++ } ++ } ++ } ++ } ++ ++ public MinecraftServer d() { ++ return this.d; ++ } ++ ++ static List a(ServerConnection serverconnection) { ++ return serverconnection.f; ++ } ++ ++ static MinecraftServer b(ServerConnection serverconnection) { ++ return serverconnection.d; ++ } ++} +diff --git a/src/main/java/net/minecraft/server/ServerConnectionChannel.java b/src/main/java/net/minecraft/server/ServerConnectionChannel.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/ServerConnectionChannel.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import net.minecraft.util.io.netty.channel.Channel; ++import net.minecraft.util.io.netty.channel.ChannelException; ++import net.minecraft.util.io.netty.channel.ChannelInitializer; ++import net.minecraft.util.io.netty.channel.ChannelOption; ++import net.minecraft.util.io.netty.handler.timeout.ReadTimeoutHandler; ++ ++class ServerConnectionChannel extends ChannelInitializer { ++ ++ final ServerConnection a; ++ ++ ServerConnectionChannel(ServerConnection serverconnection) { ++ this.a = serverconnection; ++ } ++ ++ protected void initChannel(Channel channel) { ++ try { ++ channel.config().setOption(ChannelOption.IP_TOS, Integer.valueOf(24)); ++ } catch (ChannelException channelexception) { ++ ; ++ } ++ ++ try { ++ channel.config().setOption(ChannelOption.TCP_NODELAY, Boolean.valueOf(false)); ++ } catch (ChannelException channelexception1) { ++ ; ++ } ++ ++ channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)).addLast("legacy_query", new LegacyPingHandler(this.a)).addLast("splitter", new PacketSplitter()).addLast("decoder", new PacketDecoder(NetworkManager.h)).addLast("prepender", new PacketPrepender()).addLast("encoder", new PacketEncoder(NetworkManager.h)); ++ NetworkManager networkmanager = new NetworkManager(false); ++ ++ ServerConnection.a(this.a).add(networkmanager); ++ channel.pipeline().addLast("packet_handler", networkmanager); ++ networkmanager.a((PacketListener) (new HandshakeListener(ServerConnection.b(this.a), networkmanager))); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/ServerStatisticManager.java b/src/main/java/net/minecraft/server/ServerStatisticManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/ServerStatisticManager.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.io.File; ++import java.io.IOException; ++import java.lang.reflect.Constructor; ++import java.util.HashMap; ++import java.util.HashSet; ++import java.util.Iterator; ++import java.util.Map; ++import java.util.Set; ++import java.util.Map.Entry; ++ ++import net.minecraft.util.com.google.common.collect.Maps; ++import net.minecraft.util.com.google.common.collect.Sets; ++import net.minecraft.util.com.google.gson.JsonElement; ++import net.minecraft.util.com.google.gson.JsonObject; ++import net.minecraft.util.com.google.gson.JsonParseException; ++import net.minecraft.util.com.google.gson.JsonParser; ++import net.minecraft.util.org.apache.commons.io.FileUtils; ++import org.apache.logging.log4j.LogManager; ++import org.apache.logging.log4j.Logger; ++ ++public class ServerStatisticManager extends StatisticManager { ++ ++ private static final Logger b = LogManager.getLogger(); ++ private final MinecraftServer c; ++ private final File d; ++ private final Set e = Sets.newHashSet(); ++ private int f = -300; ++ private boolean g = false; ++ ++ public ServerStatisticManager(MinecraftServer minecraftserver, File file1) { ++ this.c = minecraftserver; ++ this.d = file1; ++ } ++ ++ public void a() { ++ if (this.d.isFile()) { ++ try { ++ this.a.clear(); ++ this.a.putAll(this.a(FileUtils.readFileToString(this.d))); ++ } catch (IOException ioexception) { ++ b.error("Couldn\'t read statistics file " + this.d, ioexception); ++ } catch (JsonParseException jsonparseexception) { ++ b.error("Couldn\'t parse statistics file " + this.d, jsonparseexception); ++ } ++ } ++ } ++ ++ public void b() { ++ try { ++ FileUtils.writeStringToFile(this.d, a(this.a)); ++ } catch (IOException ioexception) { ++ b.error("Couldn\'t save stats", ioexception); ++ } ++ } ++ ++ public void setStatistic(EntityHuman entityhuman, Statistic statistic, int i) { ++ int j = statistic.d() ? this.getStatisticValue(statistic) : 0; ++ ++ super.setStatistic(entityhuman, statistic, i); ++ this.e.add(statistic); ++ if (statistic.d() && j == 0 && i > 0) { ++ this.g = true; ++ if (this.c.at()) { ++ this.c.getPlayerList().sendMessage(new ChatMessage("chat.type.achievement", new Object[] { entityhuman.getScoreboardDisplayName(), statistic.j()})); ++ } ++ } ++ } ++ ++ public Set c() { ++ HashSet hashset = Sets.newHashSet(this.e); ++ ++ this.e.clear(); ++ this.g = false; ++ return hashset; ++ } ++ ++ public Map a(String s) { ++ JsonElement jsonelement = (new JsonParser()).parse(s); ++ ++ if (!jsonelement.isJsonObject()) { ++ return Maps.newHashMap(); ++ } else { ++ JsonObject jsonobject = jsonelement.getAsJsonObject(); ++ HashMap hashmap = Maps.newHashMap(); ++ Iterator iterator = jsonobject.entrySet().iterator(); ++ ++ while (iterator.hasNext()) { ++ Entry entry = (Entry) iterator.next(); ++ Statistic statistic = StatisticList.getStatistic((String) entry.getKey()); ++ ++ if (statistic != null) { ++ StatisticWrapper statisticwrapper = new StatisticWrapper(); ++ ++ if (((JsonElement) entry.getValue()).isJsonPrimitive() && ((JsonElement) entry.getValue()).getAsJsonPrimitive().isNumber()) { ++ statisticwrapper.a(((JsonElement) entry.getValue()).getAsInt()); ++ } else if (((JsonElement) entry.getValue()).isJsonObject()) { ++ JsonObject jsonobject1 = ((JsonElement) entry.getValue()).getAsJsonObject(); ++ ++ if (jsonobject1.has("value") && jsonobject1.get("value").isJsonPrimitive() && jsonobject1.get("value").getAsJsonPrimitive().isNumber()) { ++ statisticwrapper.a(jsonobject1.getAsJsonPrimitive("value").getAsInt()); ++ } ++ ++ if (jsonobject1.has("progress") && statistic.l() != null) { ++ try { ++ Constructor constructor = statistic.l().getConstructor(new Class[0]); ++ IJsonStatistic ijsonstatistic = (IJsonStatistic) constructor.newInstance(new Object[0]); ++ ++ ijsonstatistic.a(jsonobject1.get("progress")); ++ statisticwrapper.a(ijsonstatistic); ++ } catch (Throwable throwable) { ++ b.warn("Invalid statistic progress in " + this.d, throwable); ++ } ++ } ++ } ++ ++ hashmap.put(statistic, statisticwrapper); ++ } else { ++ b.warn("Invalid statistic in " + this.d + ": Don\'t know what " + (String) entry.getKey() + " is"); ++ } ++ } ++ ++ return hashmap; ++ } ++ } ++ ++ public static String a(Map map) { ++ JsonObject jsonobject = new JsonObject(); ++ Iterator iterator = map.entrySet().iterator(); ++ ++ while (iterator.hasNext()) { ++ Entry entry = (Entry) iterator.next(); ++ ++ if (((StatisticWrapper) entry.getValue()).b() != null) { ++ JsonObject jsonobject1 = new JsonObject(); ++ ++ jsonobject1.addProperty("value", Integer.valueOf(((StatisticWrapper) entry.getValue()).a())); ++ ++ try { ++ jsonobject1.add("progress", ((StatisticWrapper) entry.getValue()).b().a()); ++ } catch (Throwable throwable) { ++ b.warn("Couldn\'t save statistic " + ((Statistic) entry.getKey()).e() + ": error serializing progress", throwable); ++ } ++ ++ jsonobject.add(((Statistic) entry.getKey()).name, jsonobject1); ++ } else { ++ jsonobject.addProperty(((Statistic) entry.getKey()).name, Integer.valueOf(((StatisticWrapper) entry.getValue()).a())); ++ } ++ } ++ ++ return jsonobject.toString(); ++ } ++ ++ public void d() { ++ Iterator iterator = this.a.keySet().iterator(); ++ ++ while (iterator.hasNext()) { ++ Statistic statistic = (Statistic) iterator.next(); ++ ++ this.e.add(statistic); ++ } ++ } ++ ++ public void a(EntityPlayer entityplayer) { ++ int i = this.c.al(); ++ HashMap hashmap = Maps.newHashMap(); ++ ++ if (this.g || i - this.f > 300) { ++ this.f = i; ++ Iterator iterator = this.c().iterator(); ++ ++ while (iterator.hasNext()) { ++ Statistic statistic = (Statistic) iterator.next(); ++ ++ hashmap.put(statistic, Integer.valueOf(this.getStatisticValue(statistic))); ++ } ++ } ++ ++ entityplayer.playerConnection.sendPacket(new PacketPlayOutStatistic(hashmap)); ++ } ++ ++ public void updateStatistics(EntityPlayer entityplayer) { ++ HashMap hashmap = Maps.newHashMap(); ++ Iterator iterator = AchievementList.e.iterator(); ++ ++ while (iterator.hasNext()) { ++ Achievement achievement = (Achievement) iterator.next(); ++ ++ if (this.hasAchievement(achievement)) { ++ hashmap.put(achievement, Integer.valueOf(this.getStatisticValue(achievement))); ++ this.e.remove(achievement); ++ } ++ } ++ ++ entityplayer.playerConnection.sendPacket(new PacketPlayOutStatistic(hashmap)); ++ } ++ ++ public boolean e() { ++ return this.g; ++ } ++} +diff --git a/src/main/java/net/minecraft/server/StructureGenerator.java b/src/main/java/net/minecraft/server/StructureGenerator.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/StructureGenerator.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.util.HashMap; ++import java.util.Iterator; ++import java.util.List; ++import java.util.Map; ++import java.util.Random; ++import java.util.concurrent.Callable; ++ ++public abstract class StructureGenerator extends WorldGenBase { ++ ++ private PersistentStructure e; ++ protected Map d = new HashMap(); ++ ++ public StructureGenerator() {} ++ ++ public abstract String a(); ++ ++ protected final void a(World world, int i, int j, int k, int l, Block[] ablock) { ++ this.a(world); ++ if (!this.d.containsKey(Long.valueOf(ChunkCoordIntPair.a(i, j)))) { ++ this.b.nextInt(); ++ ++ try { ++ if (this.a(i, j)) { ++ StructureStart structurestart = this.b(i, j); ++ ++ this.d.put(Long.valueOf(ChunkCoordIntPair.a(i, j)), structurestart); ++ this.a(i, j, structurestart); ++ } ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.a(throwable, "Exception preparing structure feature"); ++ CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Feature being prepared"); ++ ++ crashreportsystemdetails.a("Is feature chunk", (Callable) (new CrashReportIsFeatureChunk(this, i, j))); ++ crashreportsystemdetails.a("Chunk location", String.format("%d,%d", new Object[] { Integer.valueOf(i), Integer.valueOf(j)})); ++ crashreportsystemdetails.a("Chunk pos hash", (Callable) (new CrashReportChunkPosHash(this, i, j))); ++ crashreportsystemdetails.a("Structure type", (Callable) (new CrashReportStructureType(this))); ++ throw new ReportedException(crashreport); ++ } ++ } ++ } ++ ++ public boolean a(World world, Random random, int i, int j) { ++ this.a(world); ++ int k = (i << 4) + 8; ++ int l = (j << 4) + 8; ++ boolean flag = false; ++ Iterator iterator = this.d.values().iterator(); ++ ++ while (iterator.hasNext()) { ++ StructureStart structurestart = (StructureStart) iterator.next(); ++ ++ if (structurestart.d() && structurestart.a().a(k, l, k + 15, l + 15)) { ++ structurestart.a(world, random, new StructureBoundingBox(k, l, k + 15, l + 15)); ++ flag = true; ++ this.a(structurestart.e(), structurestart.f(), structurestart); ++ } ++ } ++ ++ return flag; ++ } ++ ++ public boolean b(int i, int j, int k) { ++ this.a(this.c); ++ return this.c(i, j, k) != null; ++ } ++ ++ protected StructureStart c(int i, int j, int k) { ++ Iterator iterator = this.d.values().iterator(); ++ ++ while (iterator.hasNext()) { ++ StructureStart structurestart = (StructureStart) iterator.next(); ++ ++ if (structurestart.d() && structurestart.a().a(i, k, i, k)) { ++ Iterator iterator1 = structurestart.b().iterator(); ++ ++ while (iterator1.hasNext()) { ++ StructurePiece structurepiece = (StructurePiece) iterator1.next(); ++ ++ if (structurepiece.c().b(i, j, k)) { ++ return structurestart; ++ } ++ } ++ } ++ } ++ ++ return null; ++ } ++ ++ public boolean d(int i, int j, int k) { ++ this.a(this.c); ++ Iterator iterator = this.d.values().iterator(); ++ ++ StructureStart structurestart; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return false; ++ } ++ ++ structurestart = (StructureStart) iterator.next(); ++ } while (!structurestart.d()); ++ ++ return structurestart.a().a(i, k, i, k); ++ } ++ ++ public ChunkPosition getNearestGeneratedFeature(World world, int i, int j, int k) { ++ this.c = world; ++ this.a(world); ++ this.b.setSeed(world.getSeed()); ++ long l = this.b.nextLong(); ++ long i1 = this.b.nextLong(); ++ long j1 = (long) (i >> 4) * l; ++ long k1 = (long) (k >> 4) * i1; ++ ++ this.b.setSeed(j1 ^ k1 ^ world.getSeed()); ++ this.a(world, i >> 4, k >> 4, 0, 0, (Block[]) null); ++ double d0 = Double.MAX_VALUE; ++ ChunkPosition chunkposition = null; ++ Iterator iterator = this.d.values().iterator(); ++ ++ ChunkPosition chunkposition1; ++ int l1; ++ int i2; ++ double d1; ++ int j2; ++ ++ while (iterator.hasNext()) { ++ StructureStart structurestart = (StructureStart) iterator.next(); ++ ++ if (structurestart.d()) { ++ StructurePiece structurepiece = (StructurePiece) structurestart.b().get(0); ++ ++ chunkposition1 = structurepiece.a(); ++ i2 = chunkposition1.x - i; ++ l1 = chunkposition1.y - j; ++ j2 = chunkposition1.z - k; ++ d1 = (double) (i2 * i2 + l1 * l1 + j2 * j2); ++ if (d1 < d0) { ++ d0 = d1; ++ chunkposition = chunkposition1; ++ } ++ } ++ } ++ ++ if (chunkposition != null) { ++ return chunkposition; ++ } else { ++ List list = this.o_(); ++ ++ if (list != null) { ++ ChunkPosition chunkposition2 = null; ++ Iterator iterator1 = list.iterator(); ++ ++ while (iterator1.hasNext()) { ++ chunkposition1 = (ChunkPosition) iterator1.next(); ++ i2 = chunkposition1.x - i; ++ l1 = chunkposition1.y - j; ++ j2 = chunkposition1.z - k; ++ d1 = (double) (i2 * i2 + l1 * l1 + j2 * j2); ++ if (d1 < d0) { ++ d0 = d1; ++ chunkposition2 = chunkposition1; ++ } ++ } ++ ++ return chunkposition2; ++ } else { ++ return null; ++ } ++ } ++ } ++ ++ protected List o_() { ++ return null; ++ } ++ ++ private void a(World world) { ++ if (this.e == null) { ++ this.e = (PersistentStructure) world.a(PersistentStructure.class, this.a()); ++ if (this.e == null) { ++ this.e = new PersistentStructure(this.a()); ++ world.a(this.a(), (PersistentBase) this.e); ++ } else { ++ NBTTagCompound nbttagcompound = this.e.a(); ++ Iterator iterator = nbttagcompound.c().iterator(); ++ ++ while (iterator.hasNext()) { ++ String s = (String) iterator.next(); ++ NBTBase nbtbase = nbttagcompound.get(s); ++ ++ if (nbtbase.getTypeId() == 10) { ++ NBTTagCompound nbttagcompound1 = (NBTTagCompound) nbtbase; ++ ++ if (nbttagcompound1.hasKey("ChunkX") && nbttagcompound1.hasKey("ChunkZ")) { ++ int i = nbttagcompound1.getInt("ChunkX"); ++ int j = nbttagcompound1.getInt("ChunkZ"); ++ StructureStart structurestart = WorldGenFactory.a(nbttagcompound1, world); ++ ++ if (structurestart != null) { ++ this.d.put(Long.valueOf(ChunkCoordIntPair.a(i, j)), structurestart); ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ private void a(int i, int j, StructureStart structurestart) { ++ this.e.a(structurestart.a(i, j), i, j); ++ this.e.c(); ++ } ++ ++ protected abstract boolean a(int i, int j); ++ ++ protected abstract StructureStart b(int i, int j); ++} +diff --git a/src/main/java/net/minecraft/server/UserCache.java b/src/main/java/net/minecraft/server/UserCache.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/UserCache.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.io.BufferedReader; ++import java.io.BufferedWriter; ++import java.io.File; ++import java.io.FileNotFoundException; ++import java.io.IOException; ++import java.lang.reflect.ParameterizedType; ++import java.text.SimpleDateFormat; ++import java.util.ArrayList; ++import java.util.Calendar; ++import java.util.Date; ++import java.util.Iterator; ++import java.util.LinkedList; ++import java.util.List; ++import java.util.Locale; ++import java.util.Map; ++import java.util.UUID; ++ ++import net.minecraft.util.com.google.common.base.Charsets; ++import net.minecraft.util.com.google.common.collect.Iterators; ++import net.minecraft.util.com.google.common.collect.Lists; ++import net.minecraft.util.com.google.common.collect.Maps; ++import net.minecraft.util.com.google.common.io.Files; ++import net.minecraft.util.com.google.gson.Gson; ++import net.minecraft.util.com.google.gson.GsonBuilder; ++import net.minecraft.util.com.mojang.authlib.Agent; ++import net.minecraft.util.com.mojang.authlib.GameProfile; ++import net.minecraft.util.org.apache.commons.io.IOUtils; ++ ++public class UserCache { ++ ++ public static final SimpleDateFormat a = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z"); ++ private final Map c = Maps.newHashMap(); ++ private final Map d = Maps.newHashMap(); ++ private final LinkedList e = Lists.newLinkedList(); ++ private final MinecraftServer f; ++ protected final Gson b; ++ private final File g; ++ private static final ParameterizedType h = new UserCacheEntryType(); ++ ++ public UserCache(MinecraftServer minecraftserver, File file1) { ++ this.f = minecraftserver; ++ this.g = file1; ++ GsonBuilder gsonbuilder = new GsonBuilder(); ++ ++ gsonbuilder.registerTypeHierarchyAdapter(UserCacheEntry.class, new BanEntrySerializer(this, (GameProfileLookup) null)); ++ this.b = gsonbuilder.create(); ++ this.b(); ++ } ++ ++ private static GameProfile a(MinecraftServer minecraftserver, String s) { ++ GameProfile[] agameprofile = new GameProfile[1]; ++ GameProfileLookup gameprofilelookup = new GameProfileLookup(agameprofile); ++ ++ minecraftserver.getGameProfileRepository().findProfilesByNames(new String[] { s}, Agent.MINECRAFT, gameprofilelookup); ++ if (!minecraftserver.getOnlineMode() && agameprofile[0] == null) { ++ UUID uuid = EntityHuman.a(new GameProfile((UUID) null, s)); ++ GameProfile gameprofile = new GameProfile(uuid, s); ++ ++ gameprofilelookup.onProfileLookupSucceeded(gameprofile); ++ } ++ ++ return agameprofile[0]; ++ } ++ ++ public void a(GameProfile gameprofile) { ++ this.a(gameprofile, (Date) null); ++ } ++ ++ private void a(GameProfile gameprofile, Date date) { ++ UUID uuid = gameprofile.getId(); ++ ++ if (date == null) { ++ Calendar calendar = Calendar.getInstance(); ++ ++ calendar.setTime(new Date()); ++ calendar.add(2, 1); ++ date = calendar.getTime(); ++ } ++ ++ String s = gameprofile.getName().toLowerCase(Locale.ROOT); ++ UserCacheEntry usercacheentry = new UserCacheEntry(this, gameprofile, date, (GameProfileLookup) null); ++ LinkedList linkedlist = this.e; ++ ++ synchronized (this.e) { ++ if (this.d.containsKey(uuid)) { ++ UserCacheEntry usercacheentry1 = (UserCacheEntry) this.d.get(uuid); ++ ++ this.c.remove(usercacheentry1.a().getName().toLowerCase(Locale.ROOT)); ++ this.c.put(gameprofile.getName().toLowerCase(Locale.ROOT), usercacheentry); ++ this.e.remove(gameprofile); ++ } else { ++ this.d.put(uuid, usercacheentry); ++ this.c.put(s, usercacheentry); ++ } ++ ++ this.e.addFirst(gameprofile); ++ } ++ } ++ ++ public GameProfile getProfile(String s) { ++ String s1 = s.toLowerCase(Locale.ROOT); ++ UserCacheEntry usercacheentry = (UserCacheEntry) this.c.get(s1); ++ ++ if (usercacheentry != null && (new Date()).getTime() >= UserCacheEntry.a(usercacheentry).getTime()) { ++ this.d.remove(usercacheentry.a().getId()); ++ this.c.remove(usercacheentry.a().getName().toLowerCase(Locale.ROOT)); ++ LinkedList linkedlist = this.e; ++ ++ synchronized (this.e) { ++ this.e.remove(usercacheentry.a()); ++ } ++ ++ usercacheentry = null; ++ } ++ ++ GameProfile gameprofile; ++ ++ if (usercacheentry != null) { ++ gameprofile = usercacheentry.a(); ++ LinkedList linkedlist1 = this.e; ++ ++ synchronized (this.e) { ++ this.e.remove(gameprofile); ++ this.e.addFirst(gameprofile); ++ } ++ } else { ++ gameprofile = a(this.f, s1); ++ if (gameprofile != null) { ++ this.a(gameprofile); ++ usercacheentry = (UserCacheEntry) this.c.get(s1); ++ } ++ } ++ ++ this.c(); ++ return usercacheentry == null ? null : usercacheentry.a(); ++ } ++ ++ public String[] a() { ++ ArrayList arraylist = Lists.newArrayList(this.c.keySet()); ++ ++ return (String[]) arraylist.toArray(new String[arraylist.size()]); ++ } ++ ++ public GameProfile a(UUID uuid) { ++ UserCacheEntry usercacheentry = (UserCacheEntry) this.d.get(uuid); ++ ++ return usercacheentry == null ? null : usercacheentry.a(); ++ } ++ ++ private UserCacheEntry b(UUID uuid) { ++ UserCacheEntry usercacheentry = (UserCacheEntry) this.d.get(uuid); ++ ++ if (usercacheentry != null) { ++ GameProfile gameprofile = usercacheentry.a(); ++ LinkedList linkedlist = this.e; ++ ++ synchronized (this.e) { ++ this.e.remove(gameprofile); ++ this.e.addFirst(gameprofile); ++ } ++ } ++ ++ return usercacheentry; ++ } ++ ++ public void b() { ++ List list = null; ++ BufferedReader bufferedreader = null; ++ ++ label81: { ++ try { ++ bufferedreader = Files.newReader(this.g, Charsets.UTF_8); ++ list = (List) this.b.fromJson(bufferedreader, h); ++ break label81; ++ } catch (FileNotFoundException filenotfoundexception) { ++ ; ++ } finally { ++ IOUtils.closeQuietly(bufferedreader); ++ } ++ ++ return; ++ } ++ ++ if (list != null) { ++ this.c.clear(); ++ this.d.clear(); ++ LinkedList linkedlist = this.e; ++ ++ synchronized (this.e) { ++ this.e.clear(); ++ } ++ ++ list = Lists.reverse(list); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ UserCacheEntry usercacheentry = (UserCacheEntry) iterator.next(); ++ ++ if (usercacheentry != null) { ++ this.a(usercacheentry.a(), usercacheentry.b()); ++ } ++ } ++ } ++ } ++ ++ public void c() { ++ String s = this.b.toJson(this.a(1000)); ++ BufferedWriter bufferedwriter = null; ++ ++ try { ++ bufferedwriter = Files.newWriter(this.g, Charsets.UTF_8); ++ bufferedwriter.write(s); ++ return; ++ } catch (FileNotFoundException filenotfoundexception) { ++ return; ++ } catch (IOException ioexception) { ++ ; ++ } finally { ++ IOUtils.closeQuietly(bufferedwriter); ++ } ++ } ++ ++ private List a(int i) { ++ ArrayList arraylist = Lists.newArrayList(); ++ LinkedList linkedlist = this.e; ++ ArrayList arraylist1; ++ ++ synchronized (this.e) { ++ arraylist1 = Lists.newArrayList(Iterators.limit(this.e.iterator(), i)); ++ } ++ ++ Iterator iterator = arraylist1.iterator(); ++ ++ while (iterator.hasNext()) { ++ GameProfile gameprofile = (GameProfile) iterator.next(); ++ UserCacheEntry usercacheentry = this.b(gameprofile.getId()); ++ ++ if (usercacheentry != null) { ++ arraylist.add(usercacheentry); ++ } ++ } ++ ++ return arraylist; ++ } ++} +diff --git a/src/main/java/net/minecraft/server/UserCacheEntry.java b/src/main/java/net/minecraft/server/UserCacheEntry.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/UserCacheEntry.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.util.Date; ++ ++import net.minecraft.util.com.mojang.authlib.GameProfile; ++ ++class UserCacheEntry { ++ ++ private final GameProfile b; ++ private final Date c; ++ final UserCache a; ++ ++ private UserCacheEntry(UserCache usercache, GameProfile gameprofile, Date date) { ++ this.a = usercache; ++ this.b = gameprofile; ++ this.c = date; ++ } ++ ++ public GameProfile a() { ++ return this.b; ++ } ++ ++ public Date b() { ++ return this.c; ++ } ++ ++ UserCacheEntry(UserCache usercache, GameProfile gameprofile, Date date, GameProfileLookup gameprofilelookup) { ++ this(usercache, gameprofile, date); ++ } ++ ++ static Date a(UserCacheEntry usercacheentry) { ++ return usercacheentry.c; ++ } ++} +diff --git a/src/main/java/net/minecraft/server/WatchableObject.java b/src/main/java/net/minecraft/server/WatchableObject.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/WatchableObject.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++public class WatchableObject { ++ ++ private final int a; ++ private final int b; ++ private Object c; ++ private boolean d; ++ ++ public WatchableObject(int i, int j, Object object) { ++ this.b = j; ++ this.c = object; ++ this.a = i; ++ this.d = true; ++ } ++ ++ public int a() { ++ return this.b; ++ } ++ ++ public void a(Object object) { ++ this.c = object; ++ } ++ ++ public Object b() { ++ return this.c; ++ } ++ ++ public int c() { ++ return this.a; ++ } ++ ++ public boolean d() { ++ return this.d; ++ } ++ ++ public void a(boolean flag) { ++ this.d = flag; ++ } ++ ++ static boolean a(WatchableObject watchableobject, boolean flag) { ++ return watchableobject.d = flag; ++ } ++} +diff --git a/src/main/java/net/minecraft/server/WorldGenForestTree.java b/src/main/java/net/minecraft/server/WorldGenForestTree.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/WorldGenForestTree.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.util.Random; ++ ++public class WorldGenForestTree extends WorldGenTreeAbstract { ++ ++ public WorldGenForestTree(boolean flag) { ++ super(flag); ++ } ++ ++ public boolean generate(World world, Random random, int i, int j, int k) { ++ int l = random.nextInt(3) + random.nextInt(2) + 6; ++ boolean flag = true; ++ ++ if (j >= 1 && j + l + 1 <= 256) { ++ int i1; ++ int j1; ++ ++ for (int k1 = j; k1 <= j + 1 + l; ++k1) { ++ byte b0 = 1; ++ ++ if (k1 == j) { ++ b0 = 0; ++ } ++ ++ if (k1 >= j + 1 + l - 2) { ++ b0 = 2; ++ } ++ ++ for (i1 = i - b0; i1 <= i + b0 && flag; ++i1) { ++ for (j1 = k - b0; j1 <= k + b0 && flag; ++j1) { ++ if (k1 >= 0 && k1 < 256) { ++ Block block = world.getType(i1, k1, j1); ++ ++ if (!this.a(block)) { ++ flag = false; ++ } ++ } else { ++ flag = false; ++ } ++ } ++ } ++ } ++ ++ if (!flag) { ++ return false; ++ } else { ++ Block block1 = world.getType(i, j - 1, k); ++ ++ if ((block1 == Blocks.GRASS || block1 == Blocks.DIRT) && j < 256 - l - 1) { ++ this.setType(world, i, j - 1, k, Blocks.DIRT); ++ this.setType(world, i + 1, j - 1, k, Blocks.DIRT); ++ this.setType(world, i + 1, j - 1, k + 1, Blocks.DIRT); ++ this.setType(world, i, j - 1, k + 1, Blocks.DIRT); ++ int l1 = random.nextInt(4); ++ ++ i1 = l - random.nextInt(4); ++ j1 = 2 - random.nextInt(3); ++ int i2 = i; ++ int j2 = k; ++ int k2 = 0; ++ ++ int l2; ++ int i3; ++ ++ for (l2 = 0; l2 < l; ++l2) { ++ i3 = j + l2; ++ if (l2 >= i1 && j1 > 0) { ++ i2 += Direction.a[l1]; ++ j2 += Direction.b[l1]; ++ --j1; ++ } ++ ++ Block block2 = world.getType(i2, i3, j2); ++ ++ if (block2.getMaterial() == Material.AIR || block2.getMaterial() == Material.LEAVES) { ++ this.setTypeAndData(world, i2, i3, j2, Blocks.LOG2, 1); ++ this.setTypeAndData(world, i2 + 1, i3, j2, Blocks.LOG2, 1); ++ this.setTypeAndData(world, i2, i3, j2 + 1, Blocks.LOG2, 1); ++ this.setTypeAndData(world, i2 + 1, i3, j2 + 1, Blocks.LOG2, 1); ++ k2 = i3; ++ } ++ } ++ ++ for (l2 = -2; l2 <= 0; ++l2) { ++ for (i3 = -2; i3 <= 0; ++i3) { ++ byte b1 = -1; ++ ++ this.a(world, i2 + l2, k2 + b1, j2 + i3); ++ this.a(world, 1 + i2 - l2, k2 + b1, j2 + i3); ++ this.a(world, i2 + l2, k2 + b1, 1 + j2 - i3); ++ this.a(world, 1 + i2 - l2, k2 + b1, 1 + j2 - i3); ++ if ((l2 > -2 || i3 > -1) && (l2 != -1 || i3 != -2)) { ++ byte b2 = 1; ++ ++ this.a(world, i2 + l2, k2 + b2, j2 + i3); ++ this.a(world, 1 + i2 - l2, k2 + b2, j2 + i3); ++ this.a(world, i2 + l2, k2 + b2, 1 + j2 - i3); ++ this.a(world, 1 + i2 - l2, k2 + b2, 1 + j2 - i3); ++ } ++ } ++ } ++ ++ if (random.nextBoolean()) { ++ this.a(world, i2, k2 + 2, j2); ++ this.a(world, i2 + 1, k2 + 2, j2); ++ this.a(world, i2 + 1, k2 + 2, j2 + 1); ++ this.a(world, i2, k2 + 2, j2 + 1); ++ } ++ ++ for (l2 = -3; l2 <= 4; ++l2) { ++ for (i3 = -3; i3 <= 4; ++i3) { ++ if ((l2 != -3 || i3 != -3) && (l2 != -3 || i3 != 4) && (l2 != 4 || i3 != -3) && (l2 != 4 || i3 != 4) && (Math.abs(l2) < 3 || Math.abs(i3) < 3)) { ++ this.a(world, i2 + l2, k2, j2 + i3); ++ } ++ } ++ } ++ ++ for (l2 = -1; l2 <= 2; ++l2) { ++ for (i3 = -1; i3 <= 2; ++i3) { ++ if ((l2 < 0 || l2 > 1 || i3 < 0 || i3 > 1) && random.nextInt(3) <= 0) { ++ int j3 = random.nextInt(3) + 2; ++ ++ int k3; ++ ++ for (k3 = 0; k3 < j3; ++k3) { ++ this.setTypeAndData(world, i + l2, k2 - k3 - 1, k + i3, Blocks.LOG2, 1); ++ } ++ ++ int l3; ++ ++ for (k3 = -1; k3 <= 1; ++k3) { ++ for (l3 = -1; l3 <= 1; ++l3) { ++ this.a(world, i2 + l2 + k3, k2 - 0, j2 + i3 + l3); ++ } ++ } ++ ++ for (k3 = -2; k3 <= 2; ++k3) { ++ for (l3 = -2; l3 <= 2; ++l3) { ++ if (Math.abs(k3) != 2 || Math.abs(l3) != 2) { ++ this.a(world, i2 + l2 + k3, k2 - 1, j2 + i3 + l3); ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ return true; ++ } else { ++ return false; ++ } ++ } ++ } else { ++ return false; ++ } ++ } ++ ++ private void a(World world, int i, int j, int k) { ++ Block block = world.getType(i, j, k); ++ ++ if (block.getMaterial() == Material.AIR) { ++ this.setTypeAndData(world, i, j, k, Blocks.LEAVES2, 1); ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/WorldGenLargeFeature.java b/src/main/java/net/minecraft/server/WorldGenLargeFeature.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/WorldGenLargeFeature.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.Iterator; ++import java.util.List; ++import java.util.Map; ++import java.util.Random; ++import java.util.Map.Entry; ++ ++public class WorldGenLargeFeature extends StructureGenerator { ++ ++ private static List e = Arrays.asList(new BiomeBase[] { BiomeBase.DESERT, BiomeBase.DESERT_HILLS, BiomeBase.JUNGLE, BiomeBase.JUNGLE_HILLS, BiomeBase.SWAMPLAND}); ++ private List f; ++ private int g; ++ private int h; ++ ++ public WorldGenLargeFeature() { ++ this.f = new ArrayList(); ++ this.g = 32; ++ this.h = 8; ++ this.f.add(new BiomeMeta(EntityWitch.class, 1, 1, 1)); ++ } ++ ++ public WorldGenLargeFeature(Map map) { ++ this(); ++ Iterator iterator = map.entrySet().iterator(); ++ ++ while (iterator.hasNext()) { ++ Entry entry = (Entry) iterator.next(); ++ ++ if (((String) entry.getKey()).equals("distance")) { ++ this.g = MathHelper.a((String) entry.getValue(), this.g, this.h + 1); ++ } ++ } ++ } ++ ++ public String a() { ++ return "Temple"; ++ } ++ ++ protected boolean a(int i, int j) { ++ int k = i; ++ int l = j; ++ ++ if (i < 0) { ++ i -= this.g - 1; ++ } ++ ++ if (j < 0) { ++ j -= this.g - 1; ++ } ++ ++ int i1 = i / this.g; ++ int j1 = j / this.g; ++ Random random = this.c.A(i1, j1, 14357617); ++ ++ i1 *= this.g; ++ j1 *= this.g; ++ i1 += random.nextInt(this.g - this.h); ++ j1 += random.nextInt(this.g - this.h); ++ if (k == i1 && l == j1) { ++ BiomeBase biomebase = this.c.getWorldChunkManager().getBiome(k * 16 + 8, l * 16 + 8); ++ Iterator iterator = e.iterator(); ++ ++ while (iterator.hasNext()) { ++ BiomeBase biomebase1 = (BiomeBase) iterator.next(); ++ ++ if (biomebase == biomebase1) { ++ return true; ++ } ++ } ++ } ++ ++ return false; ++ } ++ ++ protected StructureStart b(int i, int j) { ++ return new WorldGenLargeFeatureStart(this.c, this.b, i, j); ++ } ++ ++ public boolean a(int i, int j, int k) { ++ StructureStart structurestart = this.c(i, j, k); ++ ++ if (structurestart != null && structurestart instanceof WorldGenLargeFeatureStart && !structurestart.a.isEmpty()) { ++ StructurePiece structurepiece = (StructurePiece) structurestart.a.getFirst(); ++ ++ return structurepiece instanceof WorldGenWitchHut; ++ } else { ++ return false; ++ } ++ } ++ ++ public List b() { ++ return this.f; ++ } ++} +diff --git a/src/main/java/net/minecraft/server/WorldGenPackedIce2.java b/src/main/java/net/minecraft/server/WorldGenPackedIce2.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/WorldGenPackedIce2.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.util.Random; ++ ++public class WorldGenPackedIce2 extends WorldGenerator { ++ ++ public WorldGenPackedIce2() {} ++ ++ public boolean generate(World world, Random random, int i, int j, int k) { ++ while (world.isEmpty(i, j, k) && j > 2) { ++ --j; ++ } ++ ++ if (world.getType(i, j, k) != Blocks.SNOW_BLOCK) { ++ return false; ++ } else { ++ j += random.nextInt(4); ++ int l = random.nextInt(4) + 7; ++ int i1 = l / 4 + random.nextInt(2); ++ ++ if (i1 > 1 && random.nextInt(60) == 0) { ++ j += 10 + random.nextInt(30); ++ } ++ ++ int j1; ++ int k1; ++ int l1; ++ ++ for (j1 = 0; j1 < l; ++j1) { ++ float f = (1.0F - (float) j1 / (float) l) * (float) i1; ++ ++ k1 = MathHelper.f(f); ++ ++ for (l1 = -k1; l1 <= k1; ++l1) { ++ float f1 = (float) MathHelper.a(l1) - 0.25F; ++ ++ for (int i2 = -k1; i2 <= k1; ++i2) { ++ float f2 = (float) MathHelper.a(i2) - 0.25F; ++ ++ if ((l1 == 0 && i2 == 0 || f1 * f1 + f2 * f2 <= f * f) && (l1 != -k1 && l1 != k1 && i2 != -k1 && i2 != k1 || random.nextFloat() <= 0.75F)) { ++ Block block = world.getType(i + l1, j + j1, k + i2); ++ ++ if (block.getMaterial() == Material.AIR || block == Blocks.DIRT || block == Blocks.SNOW_BLOCK || block == Blocks.ICE) { ++ this.setType(world, i + l1, j + j1, k + i2, Blocks.PACKED_ICE); ++ } ++ ++ if (j1 != 0 && k1 > 1) { ++ block = world.getType(i + l1, j - j1, k + i2); ++ if (block.getMaterial() == Material.AIR || block == Blocks.DIRT || block == Blocks.SNOW_BLOCK || block == Blocks.ICE) { ++ this.setType(world, i + l1, j - j1, k + i2, Blocks.PACKED_ICE); ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ j1 = i1 - 1; ++ if (j1 < 0) { ++ j1 = 0; ++ } else if (j1 > 1) { ++ j1 = 1; ++ } ++ ++ for (int j2 = -j1; j2 <= j1; ++j2) { ++ k1 = -j1; ++ ++ while (k1 <= j1) { ++ l1 = j - 1; ++ int k2 = 50; ++ ++ if (Math.abs(j2) == 1 && Math.abs(k1) == 1) { ++ k2 = random.nextInt(5); ++ } ++ ++ while (true) { ++ if (l1 > 50) { ++ Block block1 = world.getType(i + j2, l1, k + k1); ++ ++ if (block1.getMaterial() == Material.AIR || block1 == Blocks.DIRT || block1 == Blocks.SNOW_BLOCK || block1 == Blocks.ICE || block1 == Blocks.PACKED_ICE) { ++ this.setType(world, i + j2, l1, k + k1, Blocks.PACKED_ICE); ++ --l1; ++ --k2; ++ if (k2 <= 0) { ++ l1 -= random.nextInt(5) + 1; ++ k2 = random.nextInt(5); ++ } ++ continue; ++ } ++ } ++ ++ ++k1; ++ break; ++ } ++ } ++ } ++ ++ return true; ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/WorldGenVillage.java b/src/main/java/net/minecraft/server/WorldGenVillage.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/WorldGenVillage.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.util.Arrays; ++import java.util.Iterator; ++import java.util.List; ++import java.util.Map; ++import java.util.Random; ++import java.util.Map.Entry; ++ ++public class WorldGenVillage extends StructureGenerator { ++ ++ public static final List e = Arrays.asList(new BiomeBase[] { BiomeBase.PLAINS, BiomeBase.DESERT, BiomeBase.SAVANNA}); ++ private int f; ++ private int g; ++ private int h; ++ ++ public WorldGenVillage() { ++ this.g = 32; ++ this.h = 8; ++ } ++ ++ public WorldGenVillage(Map map) { ++ this(); ++ Iterator iterator = map.entrySet().iterator(); ++ ++ while (iterator.hasNext()) { ++ Entry entry = (Entry) iterator.next(); ++ ++ if (((String) entry.getKey()).equals("size")) { ++ this.f = MathHelper.a((String) entry.getValue(), this.f, 0); ++ } else if (((String) entry.getKey()).equals("distance")) { ++ this.g = MathHelper.a((String) entry.getValue(), this.g, this.h + 1); ++ } ++ } ++ } ++ ++ public String a() { ++ return "Village"; ++ } ++ ++ protected boolean a(int i, int j) { ++ int k = i; ++ int l = j; ++ ++ if (i < 0) { ++ i -= this.g - 1; ++ } ++ ++ if (j < 0) { ++ j -= this.g - 1; ++ } ++ ++ int i1 = i / this.g; ++ int j1 = j / this.g; ++ Random random = this.c.A(i1, j1, 10387312); ++ ++ i1 *= this.g; ++ j1 *= this.g; ++ i1 += random.nextInt(this.g - this.h); ++ j1 += random.nextInt(this.g - this.h); ++ if (k == i1 && l == j1) { ++ boolean flag = this.c.getWorldChunkManager().a(k * 16 + 8, l * 16 + 8, 0, e); ++ ++ if (flag) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ protected StructureStart b(int i, int j) { ++ return new WorldGenVillageStart(this.c, this.b, i, j, this.f); ++ } ++} +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0003-Skeleton-API-Implementations.patch b/CraftBukkit-Patches/0003-Skeleton-API-Implementations.patch new file mode 100644 index 0000000000..56bb57478e --- /dev/null +++ b/CraftBukkit-Patches/0003-Skeleton-API-Implementations.patch @@ -0,0 +1,87 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 2 Jun 2013 15:10:56 +1000 +Subject: [PATCH] Skeleton API Implementations + +This contains the basic, empty implementations for some Spigot-API extensions. They are included early in the patching progress so that compilation will still succeed midway despite the APIs only being provided by subsequent patches. + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -0,0 +0,0 @@ public class CraftWorld implements World { + cps.queueUnload(chunk.locX, chunk.locZ); + } + } ++ // Spigot start ++ private final Spigot spigot = new Spigot() ++ { ++ }; ++ ++ public Spigot spigot() ++ { ++ return spigot; ++ } ++ // Spigot end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java +@@ -0,0 +0,0 @@ public class CraftArrow extends AbstractProjectile implements Arrow { + public void _INVALID_setShooter(LivingEntity shooter) { + getHandle().shooter = ((CraftLivingEntity) shooter).getHandle(); + } ++ ++ // Spigot start ++ private final Arrow.Spigot spigot = new Arrow.Spigot() ++ { ++ }; ++ ++ public Arrow.Spigot spigot() ++ { ++ return spigot; ++ } ++ // Spigot end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + + return getHandle().vehicle.getBukkitEntity(); + } ++ ++ // Spigot start ++ private final Spigot spigot = new Spigot() ++ { ++ }; ++ ++ public Spigot spigot() ++ { ++ return spigot; ++ } ++ // Spigot end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + collection.add(new AttributeModifiable(getHandle().getAttributeMap(), (new AttributeRanged("generic.maxHealth", scaledHealth ? healthScale : getMaxHealth(), 0.0D, Float.MAX_VALUE)).a("Max Health").a(true))); + } ++ ++ // Spigot start ++ private final Player.Spigot spigot = new Player.Spigot() ++ { ++ }; ++ ++ public Player.Spigot spigot() ++ { ++ return spigot; ++ } ++ // Spigot end + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0004-Obfuscation-Helpers.patch b/CraftBukkit-Patches/0004-Obfuscation-Helpers.patch new file mode 100644 index 0000000000..ebf3ce53de --- /dev/null +++ b/CraftBukkit-Patches/0004-Obfuscation-Helpers.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Mon, 14 Apr 2014 10:38:04 +1000 +Subject: [PATCH] Obfuscation Helpers + +Provides several friendly named methods which map to a obfuscated method. Obfuscated methods which are used frequently should be added to this file to ease with updates to new Minecraft versions. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + } + } + ++ // Spigot Start ++ public ServerConnection getServerConnection() ++ { ++ return this.p; ++ } ++ // Spigot End + public ServerConnection ai() { + return this.p; + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0005-Spigot-Configuration.patch b/CraftBukkit-Patches/0005-Spigot-Configuration.patch new file mode 100644 index 0000000000..8ee58e39e2 --- /dev/null +++ b/CraftBukkit-Patches/0005-Spigot-Configuration.patch @@ -0,0 +1,312 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 7 Jul 2013 09:32:53 +1000 +Subject: [PATCH] Spigot Configuration + +Provides the basic infrastructure to load and save the Spigot configuration file, spigot.yml + +diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/DedicatedServer.java +@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + if (this.L() < 0) { + this.setPort(this.propertyManager.getInt("server-port", 25565)); + } ++ // Spigot start ++ this.a((PlayerList) (new DedicatedPlayerList(this))); ++ org.spigotmc.SpigotConfig.init(); ++ org.spigotmc.SpigotConfig.registerCommands(); ++ // Spigot end + + i.info("Generating keypair"); + this.a(MinecraftEncryption.b()); +@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + return false; + } + +- this.a((PlayerList) (new DedicatedPlayerList(this))); // CraftBukkit ++ // Spigot Start - Move DedicatedPlayerList up and bring plugin loading from CraftServer to here ++ // this.a((PlayerList) (new DedicatedPlayerList(this))); // CraftBukkit ++ server.loadPlugins(); ++ server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.STARTUP); ++ // Spigot End + + if (!this.getOnlineMode()) { + i.warn("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!"); +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + public boolean pvpMode; + public boolean keepSpawnInMemory = true; + public ChunkGenerator generator; ++ public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot + + public CraftWorld getWorld() { + return this.world; +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + + // Changed signature - added gen and env + public World(IDataManager idatamanager, String s, WorldSettings worldsettings, WorldProvider worldprovider, MethodProfiler methodprofiler, ChunkGenerator gen, org.bukkit.World.Environment env) { ++ this.spigotConfig = new org.spigotmc.SpigotWorldConfig( s ); // Spigot + this.generator = gen; + this.world = new CraftWorld((WorldServer) this, gen, env); + this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -0,0 +0,0 @@ public final class CraftServer implements Server { + updater.getOnUpdate().addAll(configuration.getStringList("auto-updater.on-update")); + updater.check(serverVersion); + +- loadPlugins(); +- enablePlugins(PluginLoadOrder.STARTUP); ++ // Spigot Start - Moved to old location of new DedicatedPlayerList in DedicatedServer ++ // loadPlugins(); ++ // enablePlugins(PluginLoadOrder.STARTUP); ++ // Spigot End + } + + public boolean getCommandBlockOverride(String command) { +@@ -0,0 +0,0 @@ public final class CraftServer implements Server { + logger.log(Level.WARNING, "Failed to load banned-players.json, " + ex.getMessage()); + } + ++ org.spigotmc.SpigotConfig.init(); // Spigot + for (WorldServer world : console.worlds) { + world.difficulty = difficulty; + world.setSpawnFlags(monsters, animals); +@@ -0,0 +0,0 @@ public final class CraftServer implements Server { + } else { + world.ticksPerMonsterSpawns = this.getTicksPerMonsterSpawns(); + } ++ world.spigotConfig.init(); // Spigot + } + + pluginManager.clearPlugins(); + commandMap.clearCommands(); + resetRecipes(); ++ org.spigotmc.SpigotConfig.registerCommands(); // Spigot ++ + overrideAllCommandBlockCommands = commandsConfiguration.getStringList("command-block-overrides").contains("*"); + + int pollCount = 0; +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -0,0 +0,0 @@ ++package org.spigotmc; ++ ++import com.google.common.base.Throwables; ++import java.io.File; ++import java.io.IOException; ++import java.lang.reflect.InvocationTargetException; ++import java.lang.reflect.Method; ++import java.lang.reflect.Modifier; ++import java.util.HashMap; ++import java.util.List; ++import java.util.Map; ++import java.util.logging.Level; ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.Bukkit; ++import org.bukkit.command.Command; ++import org.bukkit.configuration.InvalidConfigurationException; ++import org.bukkit.configuration.file.YamlConfiguration; ++ ++public class SpigotConfig ++{ ++ ++ private static final File CONFIG_FILE = new File( "spigot.yml" ); ++ private static final String HEADER = "This is the main configuration file for Spigot.\n" ++ + "As you can see, there's tons to configure. Some options may impact gameplay, so use\n" ++ + "with caution, and make sure you know what each option does before configuring.\n" ++ + "For a reference for any variable inside this file, check out the Spigot wiki at\n" ++ + "http://www.spigotmc.org/wiki/spigot-configuration/\n" ++ + "\n" ++ + "If you need help with the configuration or have any questions related to Spigot,\n" ++ + "join us at the IRC or drop by our forums and leave a post.\n" ++ + "\n" ++ + "IRC: #spigot @ irc.esper.net ( http://webchat.esper.net/?channel=spigot )\n" ++ + "Forums: http://www.spigotmc.org/forum/\n"; ++ /*========================================================================*/ ++ static YamlConfiguration config; ++ static int version; ++ static Map commands; ++ /*========================================================================*/ ++ ++ public static void init() ++ { ++ config = new YamlConfiguration(); ++ try ++ { ++ config.load( CONFIG_FILE ); ++ } catch ( IOException ex ) ++ { ++ } catch ( InvalidConfigurationException ex ) ++ { ++ Bukkit.getLogger().log( Level.SEVERE, "Could not load spigot.yml, please correct your syntax errors", ex ); ++ throw Throwables.propagate( ex ); ++ } ++ ++ config.options().header( HEADER ); ++ config.options().copyDefaults( true ); ++ ++ commands = new HashMap(); ++ ++ version = getInt( "config-version", 6 ); ++ set( "config-version", 6 ); ++ readConfig( SpigotConfig.class, null ); ++ } ++ ++ public static void registerCommands() ++ { ++ for ( Map.Entry entry : commands.entrySet() ) ++ { ++ MinecraftServer.getServer().server.getCommandMap().register( entry.getKey(), "Spigot", entry.getValue() ); ++ } ++ } ++ ++ static void readConfig(Class clazz, Object instance) ++ { ++ for ( Method method : clazz.getDeclaredMethods() ) ++ { ++ if ( Modifier.isPrivate( method.getModifiers() ) ) ++ { ++ if ( method.getParameterTypes().length == 0 && method.getReturnType() == Void.TYPE ) ++ { ++ try ++ { ++ method.setAccessible( true ); ++ method.invoke( instance ); ++ } catch ( InvocationTargetException ex ) ++ { ++ throw Throwables.propagate( ex.getCause() ); ++ } catch ( Exception ex ) ++ { ++ Bukkit.getLogger().log( Level.SEVERE, "Error invoking " + method, ex ); ++ } ++ } ++ } ++ } ++ ++ try ++ { ++ config.save( CONFIG_FILE ); ++ } catch ( IOException ex ) ++ { ++ Bukkit.getLogger().log( Level.SEVERE, "Could not save " + CONFIG_FILE, ex ); ++ } ++ } ++ ++ private static void set(String path, Object val) ++ { ++ config.set( path, val ); ++ } ++ ++ private static boolean getBoolean(String path, boolean def) ++ { ++ config.addDefault( path, def ); ++ return config.getBoolean( path, config.getBoolean( path ) ); ++ } ++ ++ private static int getInt(String path, int def) ++ { ++ config.addDefault( path, def ); ++ return config.getInt( path, config.getInt( path ) ); ++ } ++ ++ private static List getList(String path, T def) ++ { ++ config.addDefault( path, def ); ++ return (List) config.getList( path, config.getList( path ) ); ++ } ++ ++ private static String getString(String path, String def) ++ { ++ config.addDefault( path, def ); ++ return config.getString( path, config.getString( path ) ); ++ } ++} +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -0,0 +0,0 @@ ++package org.spigotmc; ++ ++import java.util.List; ++import org.bukkit.Bukkit; ++import org.bukkit.configuration.file.YamlConfiguration; ++ ++public class SpigotWorldConfig ++{ ++ ++ private final String worldName; ++ private final YamlConfiguration config; ++ private boolean verbose; ++ ++ public SpigotWorldConfig(String worldName) ++ { ++ this.worldName = worldName; ++ this.config = SpigotConfig.config; ++ init(); ++ } ++ ++ public void init() ++ { ++ this.verbose = getBoolean( "verbose", true ); ++ ++ log( "-------- World Settings For [" + worldName + "] --------" ); ++ SpigotConfig.readConfig( SpigotWorldConfig.class, this ); ++ } ++ ++ private void log(String s) ++ { ++ if ( verbose ) ++ { ++ Bukkit.getLogger().info( s ); ++ } ++ } ++ ++ private void set(String path, Object val) ++ { ++ config.set( "world-settings.default." + path, val ); ++ } ++ ++ private boolean getBoolean(String path, boolean def) ++ { ++ config.addDefault( "world-settings.default." + path, def ); ++ return config.getBoolean( "world-settings." + worldName + "." + path, config.getBoolean( "world-settings.default." + path ) ); ++ } ++ ++ private double getDouble(String path, double def) ++ { ++ config.addDefault( "world-settings.default." + path, def ); ++ return config.getDouble( "world-settings." + worldName + "." + path, config.getDouble( "world-settings.default." + path ) ); ++ } ++ ++ private int getInt(String path, int def) ++ { ++ config.addDefault( "world-settings.default." + path, def ); ++ return config.getInt( "world-settings." + worldName + "." + path, config.getInt( "world-settings.default." + path ) ); ++ } ++ ++ private List getList(String path, T def) ++ { ++ config.addDefault( "world-settings.default." + path, def ); ++ return (List) config.getList( "world-settings." + worldName + "." + path, config.getList( "world-settings.default." + path ) ); ++ } ++ ++ private String getString(String path, String def) ++ { ++ config.addDefault( "world-settings.default." + path, def ); ++ return config.getString( "world-settings." + worldName + "." + path, config.getString( "world-settings.default." + path ) ); ++ } ++} +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0006-Better-Chunk-Tick-Selection.patch b/CraftBukkit-Patches/0006-Better-Chunk-Tick-Selection.patch new file mode 100644 index 0000000000..a4853a59c3 --- /dev/null +++ b/CraftBukkit-Patches/0006-Better-Chunk-Tick-Selection.patch @@ -0,0 +1,181 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Tue, 11 Jun 2013 12:56:02 +1000 +Subject: [PATCH] Better Chunk Tick Selection + +An optimized chunk ticking algorithm which better selects chunks around players which are active on the server. + +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + public Scoreboard scoreboard = new Scoreboard(); // CraftBukkit - protected -> public + public boolean isStatic; + // CraftBukkit start - public, longhashset +- protected LongHashSet chunkTickList = new LongHashSet(); ++ // protected LongHashSet chunkTickList = new LongHashSet(); // Spigot + private int K; + public boolean allowMonsters; + public boolean allowAnimals; +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + private boolean M; + int[] I; + ++ // Spigot start ++ protected final net.minecraft.util.gnu.trove.map.hash.TLongShortHashMap chunkTickList; ++ protected float growthOdds = 100; ++ protected float modifiedOdds = 100; ++ private final byte chunkTickRadius; ++ ++ public static long chunkToKey(int x, int z) ++ { ++ long k = ( ( ( (long) x ) & 0xFFFF0000L ) << 16 ) | ( ( ( (long) x ) & 0x0000FFFFL ) << 0 ); ++ k |= ( ( ( (long) z ) & 0xFFFF0000L ) << 32 ) | ( ( ( (long) z ) & 0x0000FFFFL ) << 16 ); ++ return k; ++ } ++ ++ public static int keyToX(long k) ++ { ++ return (int) ( ( ( k >> 16 ) & 0xFFFF0000 ) | ( k & 0x0000FFFF ) ); ++ } ++ ++ public static int keyToZ(long k) ++ { ++ return (int) ( ( ( k >> 32 ) & 0xFFFF0000L ) | ( ( k >> 16 ) & 0x0000FFFF ) ); ++ } ++ // Spigot end ++ + public BiomeBase getBiome(int i, int j) { + if (this.isLoaded(i, 0, j)) { + Chunk chunk = this.getChunkAtWorldCoords(i, j); +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit + this.ticksPerMonsterSpawns = this.getServer().getTicksPerMonsterSpawns(); // CraftBukkit + // CraftBukkit end ++ // Spigot start ++ this.chunkTickRadius = (byte) ( ( this.getServer().getViewDistance() < 7 ) ? this.getServer().getViewDistance() : 7 ); ++ this.chunkTickList = new net.minecraft.util.gnu.trove.map.hash.TLongShortHashMap( spigotConfig.chunksPerTick * 5, 0.7f, Long.MIN_VALUE, Short.MIN_VALUE ); ++ this.chunkTickList.setAutoCompactionFactor( 0 ); ++ // Spigot end + + this.K = this.random.nextInt(12000); + this.allowMonsters = true; +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + int k; + int l; + ++ // Spigot start ++ int optimalChunks = spigotConfig.chunksPerTick; ++ // Quick conditions to allow us to exist early ++ if ( optimalChunks <= 0 || players.isEmpty() ) ++ { ++ return; ++ } ++ // Keep chunks with growth inside of the optimal chunk range ++ int chunksPerPlayer = Math.min( 200, Math.max( 1, (int) ( ( ( optimalChunks - players.size() ) / (double) players.size() ) + 0.5 ) ) ); ++ int randRange = 3 + chunksPerPlayer / 30; ++ // Limit to normal tick radius - including view distance ++ randRange = ( randRange > chunkTickRadius ) ? chunkTickRadius : randRange; ++ // odds of growth happening vs growth happening in vanilla ++ this.growthOdds = this.modifiedOdds = Math.max( 35, Math.min( 100, ( ( chunksPerPlayer + 1 ) * 100F ) / 15F ) ); ++ // Spigot end + for (i = 0; i < this.players.size(); ++i) { + entityhuman = (EntityHuman) this.players.get(i); + j = MathHelper.floor(entityhuman.locX / 16.0D); + k = MathHelper.floor(entityhuman.locZ / 16.0D); + l = this.p(); + +- for (int i1 = -l; i1 <= l; ++i1) { +- for (int j1 = -l; j1 <= l; ++j1) { +- this.chunkTickList.add(org.bukkit.craftbukkit.util.LongHash.toLong(i1 + j, j1 + k)); // CraftBukkit ++ // Spigot start - Always update the chunk the player is on ++ long key = chunkToKey( j, k ); ++ int existingPlayers = Math.max( 0, chunkTickList.get( key ) ); // filter out -1 ++ chunkTickList.put(key, (short) (existingPlayers + 1)); ++ ++ // Check and see if we update the chunks surrounding the player this tick ++ for ( int chunk = 0; chunk < chunksPerPlayer; chunk++ ) ++ { ++ int dx = ( random.nextBoolean() ? 1 : -1 ) * random.nextInt( randRange ); ++ int dz = ( random.nextBoolean() ? 1 : -1 ) * random.nextInt( randRange ); ++ long hash = chunkToKey( dx + j, dz + k ); ++ if ( !chunkTickList.contains( hash ) && this.isChunkLoaded( dx + j, dz + k ) ) ++ { ++ chunkTickList.put( hash, (short) -1 ); // no players + } + } ++ // Spigot End + } + + this.methodProfiler.b(); +diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/WorldServer.java ++++ b/src/main/java/net/minecraft/server/WorldServer.java +@@ -0,0 +0,0 @@ public class WorldServer extends World { + // CraftBukkit start + // Iterator iterator = this.chunkTickList.iterator(); + +- for (long chunkCoord : this.chunkTickList.popAll()) { ++ // Spigot start ++ for (net.minecraft.util.gnu.trove.iterator.TLongShortIterator iter = chunkTickList.iterator(); iter.hasNext();) { ++ iter.advance(); ++ long chunkCoord = iter.key(); ++ int chunkX = World.keyToX(chunkCoord); ++ int chunkZ = World.keyToZ(chunkCoord); ++ // If unloaded, or in procedd of being unloaded, drop it ++ if ( ( !this.isChunkLoaded( chunkX, chunkZ ) ) || ( this.chunkProviderServer.unloadQueue.contains( chunkX, chunkZ ) ) ) ++ { ++ iter.remove(); ++ continue; ++ } ++ // Spigot end + // ChunkCoordIntPair chunkcoordintpair = (ChunkCoordIntPair) iterator.next(); +- int chunkX = LongHash.msw(chunkCoord); +- int chunkZ = LongHash.lsw(chunkCoord); + int k = chunkX * 16; + int l = chunkZ * 16; + +@@ -0,0 +0,0 @@ public class WorldServer extends World { + + if (block.isTicking()) { + ++i; ++ this.growthOdds = (iter.value() < 1) ? this.modifiedOdds : 100; // Spigot - grow fast if no players are in this chunk (value = player count) + block.a(this, k2 + k, i3 + chunksection.getYPosition(), l2 + l, this.random); + } + } +@@ -0,0 +0,0 @@ public class WorldServer extends World { + + this.methodProfiler.b(); + } ++ // Spigot Start ++ if ( spigotConfig.clearChunksOnTick ) ++ { ++ chunkTickList.clear(); ++ } ++ // Spigot End + } + + public boolean a(int i, int j, int k, Block block) { +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -0,0 +0,0 @@ public class SpigotWorldConfig + config.addDefault( "world-settings.default." + path, def ); + return config.getString( "world-settings." + worldName + "." + path, config.getString( "world-settings.default." + path ) ); + } ++ ++ public int chunksPerTick; ++ public boolean clearChunksOnTick; ++ private void chunksPerTick() ++ { ++ chunksPerTick = getInt( "chunks-per-tick", 650 ); ++ log( "Chunks to Grow per Tick: " + chunksPerTick ); ++ ++ clearChunksOnTick = getBoolean( "clear-tick-list", false ); ++ log( "Clear tick list: " + clearChunksOnTick ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0007-Crop-Growth-Rates.patch b/CraftBukkit-Patches/0007-Crop-Growth-Rates.patch new file mode 100644 index 0000000000..612e6a6f55 --- /dev/null +++ b/CraftBukkit-Patches/0007-Crop-Growth-Rates.patch @@ -0,0 +1,175 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Fri, 21 Jun 2013 17:17:20 +1000 +Subject: [PATCH] Crop Growth Rates + +Allows configuring the growth rates of crops as a percentage of their normal growth rate. + +diff --git a/src/main/java/net/minecraft/server/Block.java b/src/main/java/net/minecraft/server/Block.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Block.java ++++ b/src/main/java/net/minecraft/server/Block.java +@@ -0,0 +0,0 @@ public class Block { + return 0; + } + // CraftBukkit end ++ ++ // Spigot start ++ public static float range(float min, float value, float max) { ++ if (value < min) { ++ return min; ++ } ++ if (value > max) { ++ return max; ++ } ++ return value; ++ } ++ // Spigot end + } +diff --git a/src/main/java/net/minecraft/server/BlockCactus.java b/src/main/java/net/minecraft/server/BlockCactus.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/BlockCactus.java ++++ b/src/main/java/net/minecraft/server/BlockCactus.java +@@ -0,0 +0,0 @@ public class BlockCactus extends Block { + if (l < 3) { + int i1 = world.getData(i, j, k); + +- if (i1 == 15) { ++ if (i1 >= (byte) range(3, (world.growthOdds / world.spigotConfig.cactusModifier * 15) + 0.5F, 15)) { // Spigot + CraftEventFactory.handleBlockGrowEvent(world, i, j + 1, k, this, 0); // CraftBukkit + world.setData(i, j, k, 0, 4); + this.doPhysics(world, i, j + 1, k, this); +diff --git a/src/main/java/net/minecraft/server/BlockCrops.java b/src/main/java/net/minecraft/server/BlockCrops.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/BlockCrops.java ++++ b/src/main/java/net/minecraft/server/BlockCrops.java +@@ -0,0 +0,0 @@ public class BlockCrops extends BlockPlant implements IBlockFragilePlantElement + if (l < 7) { + float f = this.n(world, i, j, k); + +- if (random.nextInt((int) (25.0F / f) + 1) == 0) { ++ if (random.nextInt((int) (world.growthOdds / world.spigotConfig.wheatModifier * (25.0F / f)) + 1) == 0) { // Spigot + ++l; + CraftEventFactory.handleBlockGrowEvent(world, i, j, k, this, l); // CraftBukkit + } +diff --git a/src/main/java/net/minecraft/server/BlockGrass.java b/src/main/java/net/minecraft/server/BlockGrass.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/BlockGrass.java ++++ b/src/main/java/net/minecraft/server/BlockGrass.java +@@ -0,0 +0,0 @@ public class BlockGrass extends Block implements IBlockFragilePlantElement { + } + // CraftBukkit end + } else if (world.getLightLevel(i, j + 1, k) >= 9) { +- for (int l = 0; l < 4; ++l) { ++ int numGrowth = Math.min(4, Math.max(20, (int) (4 * 100F / world.growthOdds))); // Spigot ++ for (int l = 0; l < numGrowth; ++l) { // Spigot + int i1 = i + random.nextInt(3) - 1; + int j1 = j + random.nextInt(5) - 3; + int k1 = k + random.nextInt(3) - 1; +diff --git a/src/main/java/net/minecraft/server/BlockMushroom.java b/src/main/java/net/minecraft/server/BlockMushroom.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/BlockMushroom.java ++++ b/src/main/java/net/minecraft/server/BlockMushroom.java +@@ -0,0 +0,0 @@ public class BlockMushroom extends BlockPlant implements IBlockFragilePlantEleme + + public void a(World world, int i, int j, int k, Random random) { + final int sourceX = i, sourceY = j, sourceZ = k; // CraftBukkit +- if (random.nextInt(25) == 0) { ++ if (random.nextInt(Math.max(1, (int) world.growthOdds / world.spigotConfig.mushroomModifier * 25)) == 0) { // Spigot + byte b0 = 4; + int l = 5; + +diff --git a/src/main/java/net/minecraft/server/BlockMycel.java b/src/main/java/net/minecraft/server/BlockMycel.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/BlockMycel.java ++++ b/src/main/java/net/minecraft/server/BlockMycel.java +@@ -0,0 +0,0 @@ public class BlockMycel extends Block { + } + // CraftBukkit end + } else if (world.getLightLevel(i, j + 1, k) >= 9) { +- for (int l = 0; l < 4; ++l) { ++ int numGrowth = Math.min(4, Math.max(20, (int) (4 * 100F / world.growthOdds))); // Spigot ++ for (int l = 0; l < numGrowth; ++l) { // Spigot + int i1 = i + random.nextInt(3) - 1; + int j1 = j + random.nextInt(5) - 3; + int k1 = k + random.nextInt(3) - 1; +diff --git a/src/main/java/net/minecraft/server/BlockReed.java b/src/main/java/net/minecraft/server/BlockReed.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/BlockReed.java ++++ b/src/main/java/net/minecraft/server/BlockReed.java +@@ -0,0 +0,0 @@ public class BlockReed extends Block { + if (l < 3) { + int i1 = world.getData(i, j, k); + +- if (i1 == 15) { ++ if (i1 >= (byte) range(3, (world.growthOdds / world.spigotConfig.caneModifier * 15) + 0.5F, 15)) { // Spigot + org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(world, i, j + 1, k, this, 0); // CraftBukkit + world.setData(i, j, k, 0, 4); + } else { +diff --git a/src/main/java/net/minecraft/server/BlockSapling.java b/src/main/java/net/minecraft/server/BlockSapling.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/BlockSapling.java ++++ b/src/main/java/net/minecraft/server/BlockSapling.java +@@ -0,0 +0,0 @@ public class BlockSapling extends BlockPlant implements IBlockFragilePlantElemen + public void a(World world, int i, int j, int k, Random random) { + if (!world.isStatic) { + super.a(world, i, j, k, random); +- if (world.getLightLevel(i, j + 1, k) >= 9 && random.nextInt(7) == 0) { ++ if (world.getLightLevel(i, j + 1, k) >= 9 && (random.nextInt(Math.max(2, (int) ((world.growthOdds / world.spigotConfig.saplingModifier * 7) + 0.5F))) == 0)) { // Spigot + // 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/BlockStem.java ++++ b/src/main/java/net/minecraft/server/BlockStem.java +@@ -0,0 +0,0 @@ public class BlockStem extends BlockPlant implements IBlockFragilePlantElement { + if (world.getLightLevel(i, j + 1, k) >= 9) { + float f = this.n(world, i, j, k); + +- if (random.nextInt((int) (25.0F / f) + 1) == 0) { ++ if (random.nextInt((int) (world.growthOdds / (this == Blocks.PUMPKIN_STEM? world.spigotConfig.pumpkinModifier : world.spigotConfig.melonModifier) * (25.0F / f)) + 1) == 0) { // Spigot + int l = world.getData(i, j, k); + + if (l < 7) { +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -0,0 +0,0 @@ public class SpigotWorldConfig + clearChunksOnTick = getBoolean( "clear-tick-list", false ); + log( "Clear tick list: " + clearChunksOnTick ); + } ++ ++ // Crop growth rates ++ public int cactusModifier; ++ public int caneModifier; ++ public int melonModifier; ++ public int mushroomModifier; ++ public int pumpkinModifier; ++ public int saplingModifier; ++ public int wheatModifier; ++ private int getAndValidateGrowth(String crop) ++ { ++ int modifier = getInt( "growth." + crop.toLowerCase() + "-modifier", 100 ); ++ if ( modifier == 0 ) ++ { ++ log( "Cannot set " + crop + " growth to zero, defaulting to 100" ); ++ modifier = 100; ++ } ++ log( crop + " Growth Modifier: " + modifier + "%" ); ++ ++ return modifier; ++ } ++ private void growthModifiers() ++ { ++ cactusModifier = getAndValidateGrowth( "Cactus" ); ++ caneModifier = getAndValidateGrowth( "Cane" ); ++ melonModifier = getAndValidateGrowth( "Melon" ); ++ mushroomModifier = getAndValidateGrowth( "Mushroom" ); ++ pumpkinModifier = getAndValidateGrowth( "Pumpkin" ); ++ saplingModifier = getAndValidateGrowth( "Sapling" ); ++ wheatModifier = getAndValidateGrowth( "Wheat" ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0008-More-Efficient-Chunk-Save-Queue.patch b/CraftBukkit-Patches/0008-More-Efficient-Chunk-Save-Queue.patch new file mode 100644 index 0000000000..726e4c609e --- /dev/null +++ b/CraftBukkit-Patches/0008-More-Efficient-Chunk-Save-Queue.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Tue, 11 Jun 2013 12:09:45 +1000 +Subject: [PATCH] More Efficient Chunk Save Queue + +Optimizes the data structures behind the chunk save queue into ones more suitable for the type of data and access which they are used for. + +diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java ++++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java +@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger; + + public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { + ++ private java.util.LinkedHashMap pendingSaves = new java.util.LinkedHashMap(); // Spigot + private static final Logger a = LogManager.getLogger(); + private List b = new ArrayList(); + private Set c = new HashSet(); +@@ -0,0 +0,0 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { + ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(i, j); + + synchronized (this.d) { +- if (this.c.contains(chunkcoordintpair)) { +- for (int k = 0; k < this.b.size(); ++k) { +- if (((PendingChunkToSave) this.b.get(k)).a.equals(chunkcoordintpair)) { +- return true; +- } +- } +- } ++ // Spigot start ++ if (pendingSaves.containsKey(chunkcoordintpair)) { ++ return true; ++ } ++ // Spigot end + } + + return RegionFileCache.a(this.e, i, j).chunkExists(i & 31, j & 31); +@@ -0,0 +0,0 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { + Object object = this.d; + + synchronized (this.d) { +- if (this.c.contains(chunkcoordintpair)) { +- for (int k = 0; k < this.b.size(); ++k) { +- if (((PendingChunkToSave) this.b.get(k)).a.equals(chunkcoordintpair)) { +- nbttagcompound = ((PendingChunkToSave) this.b.get(k)).b; +- break; +- } +- } ++ // Spigot start ++ PendingChunkToSave pendingchunktosave = pendingSaves.get(chunkcoordintpair); ++ if (pendingchunktosave != null) { ++ nbttagcompound = pendingchunktosave.b; + } ++ // Spigot end + } + + if (nbttagcompound == null) { +@@ -0,0 +0,0 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { + Object object = this.d; + + synchronized (this.d) { +- if (this.c.contains(chunkcoordintpair)) { +- for (int i = 0; i < this.b.size(); ++i) { +- if (((PendingChunkToSave) this.b.get(i)).a.equals(chunkcoordintpair)) { +- this.b.set(i, new PendingChunkToSave(chunkcoordintpair, nbttagcompound)); +- return; +- } +- } ++ // Spigot start ++ if (this.pendingSaves.put(chunkcoordintpair, new PendingChunkToSave(chunkcoordintpair, nbttagcompound)) != null) { ++ return; + } +- +- this.b.add(new PendingChunkToSave(chunkcoordintpair, nbttagcompound)); +- this.c.add(chunkcoordintpair); ++ // Spigot end + FileIOThread.a.a(this); + } + } +@@ -0,0 +0,0 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { + Object object = this.d; + + synchronized (this.d) { +- if (this.b.isEmpty()) { ++ // Spigot start ++ if (this.pendingSaves.isEmpty()) { + return false; + } + +- pendingchunktosave = (PendingChunkToSave) this.b.remove(0); +- this.c.remove(pendingchunktosave.a); ++ pendingchunktosave = this.pendingSaves.values().iterator().next(); ++ this.pendingSaves.remove(pendingchunktosave.a); ++ // Spigot end + } + + if (pendingchunktosave != null) { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0009-Merge-tweaks-and-configuration.patch b/CraftBukkit-Patches/0009-Merge-tweaks-and-configuration.patch new file mode 100644 index 0000000000..409d18efc8 --- /dev/null +++ b/CraftBukkit-Patches/0009-Merge-tweaks-and-configuration.patch @@ -0,0 +1,94 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 23 Mar 2013 09:46:33 +1100 +Subject: [PATCH] Merge tweaks and configuration + +This allows the merging of Experience orbs, as well as the configuration of the merge radius of items. Additionally it refactors the merge algorithm to be a better experience for players. + +diff --git a/src/main/java/net/minecraft/server/EntityItem.java b/src/main/java/net/minecraft/server/EntityItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityItem.java ++++ b/src/main/java/net/minecraft/server/EntityItem.java +@@ -0,0 +0,0 @@ public class EntityItem extends Entity { + } + + private void k() { +- Iterator iterator = this.world.a(EntityItem.class, this.boundingBox.grow(0.5D, 0.0D, 0.5D)).iterator(); ++ // Spigot start ++ double radius = world.spigotConfig.itemMerge; ++ Iterator iterator = this.world.a(EntityItem.class, this.boundingBox.grow(radius, radius, radius)).iterator(); ++ // Spigot end + + while (iterator.hasNext()) { + EntityItem entityitem = (EntityItem) iterator.next(); +@@ -0,0 +0,0 @@ public class EntityItem extends Entity { + } else if (itemstack1.count + itemstack.count > itemstack1.getMaxStackSize()) { + return false; + } else { +- itemstack1.count += itemstack.count; +- entityitem.pickupDelay = Math.max(entityitem.pickupDelay, this.pickupDelay); +- entityitem.age = Math.min(entityitem.age, this.age); +- entityitem.setItemStack(itemstack1); +- this.die(); ++ // Spigot start ++ itemstack.count += itemstack1.count; ++ this.pickupDelay = Math.max(entityitem.pickupDelay, this.pickupDelay); ++ this.age = Math.min(entityitem.age, this.age); ++ this.setItemStack(itemstack); ++ entityitem.die(); ++ // Spigot end + return true; + } + } else { +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + // Not all projectiles extend EntityProjectile, so check for Bukkit interface instead + event = CraftEventFactory.callProjectileLaunchEvent(entity); + } ++ // Spigot start ++ else if (entity instanceof EntityExperienceOrb) { ++ EntityExperienceOrb xp = (EntityExperienceOrb) entity; ++ double radius = spigotConfig.expMerge; ++ if (radius > 0) { ++ List entities = this.getEntities(entity, entity.boundingBox.grow(radius, radius, radius)); ++ for (Entity e : entities) { ++ if (e instanceof EntityExperienceOrb) { ++ EntityExperienceOrb loopItem = (EntityExperienceOrb) e; ++ if (!loopItem.dead) { ++ xp.value += loopItem.value; ++ loopItem.die(); ++ } ++ } ++ } ++ } ++ } // Spigot end + + if (event != null && (event.isCancelled() || entity.dead)) { + entity.dead = true; +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -0,0 +0,0 @@ public class SpigotWorldConfig + saplingModifier = getAndValidateGrowth( "Sapling" ); + wheatModifier = getAndValidateGrowth( "Wheat" ); + } ++ ++ public double itemMerge; ++ private void itemMerge() ++ { ++ itemMerge = getDouble("merge-radius.item", 2.5 ); ++ log( "Item Merge Radius: " + itemMerge ); ++ } ++ ++ public double expMerge; ++ private void expMerge() ++ { ++ expMerge = getDouble("merge-radius.exp", 3.0 ); ++ log( "Experience Merge Radius: " + expMerge ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0010-LongHash-Tweaks.patch b/CraftBukkit-Patches/0010-LongHash-Tweaks.patch new file mode 100644 index 0000000000..75487b6803 --- /dev/null +++ b/CraftBukkit-Patches/0010-LongHash-Tweaks.patch @@ -0,0 +1,223 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Fri, 21 Jun 2013 17:13:47 +1000 +Subject: [PATCH] LongHash Tweaks + +Tweaks the LongHash algorithm and provides a large array based map to look up values centered around the origin, ie the access normally seen on a Minecraft server. + +diff --git a/src/main/java/org/bukkit/craftbukkit/util/LongHash.java b/src/main/java/org/bukkit/craftbukkit/util/LongHash.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/LongHash.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/LongHash.java +@@ -0,0 +0,0 @@ public class LongHash { + } + + public static int lsw(long l) { +- return (int) (l & 0xFFFFFFFF) + Integer.MIN_VALUE; ++ return (int) (l) + Integer.MIN_VALUE; // Spigot - remove redundant & + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/LongHashSet.java b/src/main/java/org/bukkit/craftbukkit/util/LongHashSet.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/LongHashSet.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/LongHashSet.java +@@ -0,0 +0,0 @@ public class LongHashSet { + private int elements; + private long[] values; + private int modCount; ++ private org.spigotmc.FlatMap flat = new org.spigotmc.FlatMap(); // Spigot + + public LongHashSet() { + this(INITIAL_SIZE); +@@ -0,0 +0,0 @@ public class LongHashSet { + } + + public boolean contains(int msw, int lsw) { ++ // Spigot start ++ if ( elements == 0 ) ++ { ++ return false; ++ } ++ if ( flat.contains( msw, lsw ) ) ++ { ++ return true; ++ } ++ // Spigot end + return contains(LongHash.toLong(msw, lsw)); + } + + public boolean contains(long value) { ++ // Spigot start ++ if ( elements == 0 ) ++ { ++ return false; ++ } ++ if ( flat.contains( value ) ) ++ { ++ return true; ++ } ++ // Spigot end + int hash = hash(value); + int index = (hash & 0x7FFFFFFF) % values.length; + int offset = 1; +@@ -0,0 +0,0 @@ public class LongHashSet { + } + + public boolean add(long value) { ++ flat.put( value, Boolean.TRUE ); // Spigot + int hash = hash(value); + int index = (hash & 0x7FFFFFFF) % values.length; + int offset = 1; +@@ -0,0 +0,0 @@ public class LongHashSet { + } + + public void remove(int msw, int lsw) { +- remove(LongHash.toLong(msw, lsw)); ++ // Spigot start ++ flat.remove(msw, lsw); ++ remove0(LongHash.toLong(msw, lsw)); + } + + public boolean remove(long value) { ++ flat.remove(value); ++ return remove0(value); ++ } ++ ++ private boolean remove0(long value) { ++ // Spigot end + int hash = hash(value); + int index = (hash & 0x7FFFFFFF) % values.length; + int offset = 1; +@@ -0,0 +0,0 @@ public class LongHashSet { + + freeEntries = values.length; + modCount++; ++ flat = new org.spigotmc.FlatMap(); + } + + public long[] toArray() { +diff --git a/src/main/java/org/bukkit/craftbukkit/util/LongObjectHashMap.java b/src/main/java/org/bukkit/craftbukkit/util/LongObjectHashMap.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/LongObjectHashMap.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/LongObjectHashMap.java +@@ -0,0 +0,0 @@ public class LongObjectHashMap implements Cloneable, Serializable { + private transient V[][] values; + private transient int modCount; + private transient int size; ++ private transient org.spigotmc.FlatMap flat = new org.spigotmc.FlatMap(); // Spigot + + public LongObjectHashMap() { + initialize(); +@@ -0,0 +0,0 @@ public class LongObjectHashMap implements Cloneable, Serializable { + } + + public V get(long key) { ++ // Spigot start ++ if ( size == 0 ) ++ { ++ return null; ++ } ++ V val = flat.get( key ); ++ if ( val != null ) ++ { ++ return val; ++ } ++ // Spigot end + int index = (int) (keyIndex(key) & (BUCKET_SIZE - 1)); + long[] inner = keys[index]; + if (inner == null) return null; +@@ -0,0 +0,0 @@ public class LongObjectHashMap implements Cloneable, Serializable { + } + + public V put(long key, V value) { ++ flat.put(key, value); // Spigot + int index = (int) (keyIndex(key) & (BUCKET_SIZE - 1)); + long[] innerKeys = keys[index]; + V[] innerValues = values[index]; +@@ -0,0 +0,0 @@ public class LongObjectHashMap implements Cloneable, Serializable { + } + + public V remove(long key) { ++ flat.remove(key); // Spigot + int index = (int) (keyIndex(key) & (BUCKET_SIZE - 1)); + long[] inner = keys[index]; + if (inner == null) { +@@ -0,0 +0,0 @@ public class LongObjectHashMap implements Cloneable, Serializable { + size = 0; + Arrays.fill(keys, null); + Arrays.fill(values, null); ++ flat = new org.spigotmc.FlatMap(); + } + + public Set keySet() { +diff --git a/src/main/java/org/spigotmc/FlatMap.java b/src/main/java/org/spigotmc/FlatMap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/org/spigotmc/FlatMap.java +@@ -0,0 +0,0 @@ ++package org.spigotmc; ++ ++import org.bukkit.craftbukkit.util.LongHash; ++ ++public class FlatMap ++{ ++ ++ private static final int FLAT_LOOKUP_SIZE = 512; ++ private final Object[][] flatLookup = new Object[ FLAT_LOOKUP_SIZE * 2 ][ FLAT_LOOKUP_SIZE * 2 ]; ++ ++ public void put(long msw, long lsw, V value) ++ { ++ long acx = Math.abs( msw ); ++ long acz = Math.abs( lsw ); ++ if ( acx < FLAT_LOOKUP_SIZE && acz < FLAT_LOOKUP_SIZE ) ++ { ++ flatLookup[(int) ( msw + FLAT_LOOKUP_SIZE )][(int) ( lsw + FLAT_LOOKUP_SIZE )] = value; ++ } ++ } ++ ++ public void put(long key, V value) ++ { ++ put( LongHash.msw( key ), LongHash.lsw( key ), value ); ++ ++ } ++ ++ public void remove(long key) ++ { ++ put( key, null ); ++ } ++ ++ public void remove(long msw, long lsw) ++ { ++ put( msw, lsw, null ); ++ } ++ ++ public boolean contains(long msw, long lsw) ++ { ++ return get( msw, lsw ) != null; ++ } ++ ++ public boolean contains(long key) ++ { ++ return get( key ) != null; ++ } ++ ++ public V get(long msw, long lsw) ++ { ++ long acx = Math.abs( msw ); ++ long acz = Math.abs( lsw ); ++ if ( acx < FLAT_LOOKUP_SIZE && acz < FLAT_LOOKUP_SIZE ) ++ { ++ return (V) flatLookup[(int) ( msw + FLAT_LOOKUP_SIZE )][(int) ( lsw + FLAT_LOOKUP_SIZE )]; ++ } else ++ { ++ return null; ++ } ++ } ++ ++ public V get(long key) ++ { ++ return get( LongHash.msw( key ), LongHash.lsw( key ) ); ++ } ++} +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0011-Async-Operation-Catching.patch b/CraftBukkit-Patches/0011-Async-Operation-Catching.patch new file mode 100644 index 0000000000..75c6efbbc6 --- /dev/null +++ b/CraftBukkit-Patches/0011-Async-Operation-Catching.patch @@ -0,0 +1,171 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Tue, 25 Mar 2014 16:10:01 +1100 +Subject: [PATCH] Async Operation Catching + +Catch and throw an exception when a potentially unsafe operation occurs on a thread other than the main server thread. + +diff --git a/src/main/java/net/minecraft/server/Block.java b/src/main/java/net/minecraft/server/Block.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Block.java ++++ b/src/main/java/net/minecraft/server/Block.java +@@ -0,0 +0,0 @@ public class Block { + return 10; + } + +- public void onPlace(World world, int i, int j, int k) {} ++ public void onPlace(World world, int i, int j, int k) { ++ org.spigotmc.AsyncCatcher.catchOp( "block onPlace"); // Spigot ++ } + +- public void remove(World world, int i, int j, int k, Block block, int l) {} ++ public void remove(World world, int i, int j, int k, Block block, int l) { ++ org.spigotmc.AsyncCatcher.catchOp( "block remove"); // Spigot ++ } + + public int a(Random random) { + return 1; +diff --git a/src/main/java/net/minecraft/server/EntityTracker.java b/src/main/java/net/minecraft/server/EntityTracker.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityTracker.java ++++ b/src/main/java/net/minecraft/server/EntityTracker.java +@@ -0,0 +0,0 @@ public class EntityTracker { + } + + public void addEntity(Entity entity, int i, int j, boolean flag) { ++ org.spigotmc.AsyncCatcher.catchOp( "entity track"); // Spigot + if (i > this.e) { + i = this.e; + } +@@ -0,0 +0,0 @@ public class EntityTracker { + } + + public void untrackEntity(Entity entity) { ++ org.spigotmc.AsyncCatcher.catchOp( "entity untrack"); // Spigot + if (entity instanceof EntityPlayer) { + EntityPlayer entityplayer = (EntityPlayer) entity; + Iterator iterator = this.c.iterator(); +diff --git a/src/main/java/net/minecraft/server/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/EntityTrackerEntry.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityTrackerEntry.java ++++ b/src/main/java/net/minecraft/server/EntityTrackerEntry.java +@@ -0,0 +0,0 @@ public class EntityTrackerEntry { + } + + public void updatePlayer(EntityPlayer entityplayer) { ++ org.spigotmc.AsyncCatcher.catchOp( "player tracker update"); // Spigot + if (entityplayer != this.tracker) { + double d0 = entityplayer.locX - (double) (this.xLoc / 32); + double d1 = entityplayer.locZ - (double) (this.zLoc / 32); +@@ -0,0 +0,0 @@ public class EntityTrackerEntry { + } + + public void clear(EntityPlayer entityplayer) { ++ org.spigotmc.AsyncCatcher.catchOp( "player tracker clear"); // Spigot + if (this.trackedPlayers.contains(entityplayer)) { + this.trackedPlayers.remove(entityplayer); + entityplayer.d(this.tracker); +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -0,0 +0,0 @@ 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; + // CraftBukkit end + +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + } + + public void removeEntity(Entity entity) { ++ org.spigotmc.AsyncCatcher.catchOp( "entity remove"); // Spigot + entity.die(); + if (entity instanceof EntityHuman) { + this.players.remove(entity); +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + } + + public void a(List list) { ++ org.spigotmc.AsyncCatcher.catchOp( "entity world add"); // Spigot + // CraftBukkit start + // this.entityList.addAll(list); + Entity entity = null; +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -0,0 +0,0 @@ public class CraftWorld implements World { + } + + public boolean unloadChunkRequest(int x, int z, boolean safe) { ++ org.spigotmc.AsyncCatcher.catchOp( "chunk unload"); // Spigot + if (safe && isChunkInUse(x, z)) { + return false; + } +@@ -0,0 +0,0 @@ public class CraftWorld implements World { + } + + public boolean unloadChunk(int x, int z, boolean save, boolean safe) { ++ org.spigotmc.AsyncCatcher.catchOp( "chunk unload"); // Spigot + if (safe && isChunkInUse(x, z)) { + return false; + } +@@ -0,0 +0,0 @@ public class CraftWorld implements World { + } + + public boolean loadChunk(int x, int z, boolean generate) { ++ org.spigotmc.AsyncCatcher.catchOp( "chunk load"); // Spigot + chunkLoadCount++; + if (generate) { + // Use the default variant of loadChunk when generate == true. +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + + @Override + public void kickPlayer(String message) { ++ org.spigotmc.AsyncCatcher.catchOp( "player kick"); // Spigot + if (getHandle().playerConnection == null) return; + + getHandle().playerConnection.disconnect(message == null ? "" : message); +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java +@@ -0,0 +0,0 @@ public final class CraftScoreboardManager implements ScoreboardManager { + } + + public CraftScoreboard getNewScoreboard() { ++ org.spigotmc.AsyncCatcher.catchOp( "scoreboard creation"); // Spigot + CraftScoreboard scoreboard = new CraftScoreboard(new ScoreboardServer(server)); + scoreboards.add(scoreboard); + return scoreboard; +diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/org/spigotmc/AsyncCatcher.java +@@ -0,0 +0,0 @@ ++package org.spigotmc; ++ ++import net.minecraft.server.MinecraftServer; ++ ++public class AsyncCatcher ++{ ++ ++ public static boolean enabled = true; ++ ++ public static void catchOp(String reason) ++ { ++ if ( enabled && Thread.currentThread() != MinecraftServer.getServer().primaryThread ) ++ { ++ throw new IllegalStateException( "Asynchronous " + reason + "!" ); ++ } ++ } ++} +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0012-View-Distance.patch b/CraftBukkit-Patches/0012-View-Distance.patch new file mode 100644 index 0000000000..1eb8acd57f --- /dev/null +++ b/CraftBukkit-Patches/0012-View-Distance.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 23 Mar 2013 09:52:41 +1100 +Subject: [PATCH] View Distance + +This commit allows the user to select per world view distances, and view distances below 3. Be wary of the issues selecting a view distance of 1 or 2 may cause! + +diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java +@@ -0,0 +0,0 @@ public class PlayerChunkMap { + private final int[][] i = new int[][] { { 1, 0}, { 0, 1}, { -1, 0}, { 0, -1}}; + private boolean wasNotEmpty; // CraftBukkit - add field + +- public PlayerChunkMap(WorldServer worldserver) { ++ public PlayerChunkMap(WorldServer worldserver, int viewDistance /* Spigot */) { + this.world = worldserver; +- this.a(worldserver.getMinecraftServer().getPlayerList().s()); ++ this.a(viewDistance); // Spigot + } + + public WorldServer a() { +diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/WorldServer.java ++++ b/src/main/java/net/minecraft/server/WorldServer.java +@@ -0,0 +0,0 @@ public class WorldServer extends World { + // CraftBukkit end + this.server = minecraftserver; + this.tracker = new EntityTracker(this); +- this.manager = new PlayerChunkMap(this); ++ this.manager = new PlayerChunkMap(this, spigotConfig.viewDistance); // Spigot + if (this.entitiesById == null) { + this.entitiesById = new IntHashMap(); + } +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -0,0 +0,0 @@ public class SpigotWorldConfig + expMerge = getDouble("merge-radius.exp", 3.0 ); + log( "Experience Merge Radius: " + expMerge ); + } ++ ++ public int viewDistance; ++ private void viewDistance() ++ { ++ viewDistance = getInt( "view-distance", Bukkit.getViewDistance() ); ++ log( "View Distance: " + viewDistance ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0013-Spigot-Timings.patch b/CraftBukkit-Patches/0013-Spigot-Timings.patch new file mode 100644 index 0000000000..f712b1275d --- /dev/null +++ b/CraftBukkit-Patches/0013-Spigot-Timings.patch @@ -0,0 +1,863 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 10 Jan 2013 00:18:11 -0500 +Subject: [PATCH] Spigot Timings + +Overhauls the Timings System adding performance tracking all around the Minecraft Server + +diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Chunk.java ++++ b/src/main/java/net/minecraft/server/Chunk.java +@@ -0,0 +0,0 @@ public class Chunk { + } + + public void loadNearby(IChunkProvider ichunkprovider, IChunkProvider ichunkprovider1, int i, int j) { ++ world.timings.syncChunkLoadPostTimer.startTiming(); // Spigot + if (!this.done && ichunkprovider.isChunkLoaded(i + 1, j + 1) && ichunkprovider.isChunkLoaded(i, j + 1) && ichunkprovider.isChunkLoaded(i + 1, j)) { + ichunkprovider.getChunkAt(ichunkprovider1, i, j); + } +@@ -0,0 +0,0 @@ public class Chunk { + if (ichunkprovider.isChunkLoaded(i - 1, j - 1) && !ichunkprovider.getOrCreateChunk(i - 1, j - 1).done && ichunkprovider.isChunkLoaded(i, j - 1) && ichunkprovider.isChunkLoaded(i - 1, j)) { + ichunkprovider.getChunkAt(ichunkprovider1, i - 1, j - 1); + } ++ world.timings.syncChunkLoadPostTimer.stopTiming(); // Spigot + } + + public int d(int i, int j) { +diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java +@@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider { + boolean newChunk = false; + + if (chunk == null) { ++ world.timings.syncChunkLoadTimer.startTiming(); // Spigot + chunk = this.loadChunk(i, j); + if (chunk == null) { + if (this.chunkProvider == null) { +@@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider { + } + // CraftBukkit end + chunk.loadNearby(this, this, i, j); ++ world.timings.syncChunkLoadTimer.stopTiming(); // Spigot + } + + return chunk; +@@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider { + if (chunk != null) { + chunk.lastSaved = this.world.getTime(); + if (this.chunkProvider != null) { ++ world.timings.syncChunkLoadStructuresTimer.startTiming(); // Spigot + this.chunkProvider.recreateStructures(i, j); ++ world.timings.syncChunkLoadStructuresTimer.stopTiming(); // Spigot + } + } + +diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java ++++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java +@@ -0,0 +0,0 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { + + // CraftBukkit start - Add async variant, provide compatibility + public Chunk a(World world, int i, int j) { ++ world.timings.syncChunkLoadDataTimer.startTiming(); // Spigot + Object[] data = this.loadChunk(world, i, j); ++ world.timings.syncChunkLoadDataTimer.stopTiming(); // Spigot + if (data != null) { + Chunk chunk = (Chunk) data[0]; + NBTTagCompound nbttagcompound = (NBTTagCompound) data[1]; +@@ -0,0 +0,0 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { + + public void loadEntities(Chunk chunk, NBTTagCompound nbttagcompound, World world) { + // CraftBukkit end ++ world.timings.syncChunkLoadEntitiesTimer.startTiming(); // Spigot + NBTTagList nbttaglist1 = nbttagcompound.getList("Entities", 10); + + if (nbttaglist1 != null) { +@@ -0,0 +0,0 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { + } + } + } +- ++ world.timings.syncChunkLoadEntitiesTimer.stopTiming(); // Spigot ++ world.timings.syncChunkLoadTileEntitiesTimer.startTiming(); // Spigot + NBTTagList nbttaglist2 = nbttagcompound.getList("TileEntities", 10); + + if (nbttaglist2 != null) { +@@ -0,0 +0,0 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { + } + } + } ++ world.timings.syncChunkLoadTileEntitiesTimer.stopTiming(); // Spigot ++ world.timings.syncChunkLoadTileTicksTimer.startTiming(); // Spigot + + if (nbttagcompound.hasKeyOfType("TileTicks", 9)) { + NBTTagList nbttaglist3 = nbttagcompound.getList("TileTicks", 10); +@@ -0,0 +0,0 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { + } + } + } ++ world.timings.syncChunkLoadTileTicksTimer.stopTiming(); // Spigot + + // return chunk; // CraftBukkit + } +diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/DedicatedServer.java +@@ -0,0 +0,0 @@ import java.io.PrintStream; + import org.apache.logging.log4j.Level; + + import org.bukkit.craftbukkit.LoggerOutputStream; ++import org.bukkit.craftbukkit.SpigotTimings; // Spigot + import org.bukkit.event.server.ServerCommandEvent; + // CraftBukkit end + +@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + } + + public void aB() { ++ SpigotTimings.serverCommandTimer.startTiming(); // Spigot + while (!this.j.isEmpty()) { + ServerCommand servercommand = (ServerCommand) this.j.remove(0); + +@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + this.server.dispatchServerCommand(this.console, servercommand); + // CraftBukkit end + } ++ SpigotTimings.serverCommandTimer.stopTiming(); // Spigot + } + + public boolean X() { +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -0,0 +0,0 @@ import org.bukkit.entity.Hanging; + import org.bukkit.entity.LivingEntity; + import org.bukkit.entity.Painting; + import org.bukkit.entity.Vehicle; ++import org.spigotmc.CustomTimingsHandler; // Spigot + import org.bukkit.event.entity.EntityCombustByEntityEvent; + import org.bukkit.event.hanging.HangingBreakByEntityEvent; + import org.bukkit.event.painting.PaintingBreakByEntityEvent; +@@ -0,0 +0,0 @@ public abstract class Entity { + public boolean valid; // CraftBukkit + public org.bukkit.projectiles.ProjectileSource projectileSource; // CraftBukkit - For projectiles only + ++ public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getEntityTimings(this); // Spigot ++ + public int getId() { + return this.id; + } +@@ -0,0 +0,0 @@ public abstract class Entity { + return; + } + // CraftBukkit end ++ org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.startTiming(); // Spigot + if (this.X) { + this.boundingBox.d(d0, d1, d2); + this.locX = (this.boundingBox.a + this.boundingBox.d) / 2.0D; +@@ -0,0 +0,0 @@ public abstract class Entity { + + this.world.methodProfiler.b(); + } ++ org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.stopTiming(); // Spigot + } + + protected String H() { +diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityLiving.java ++++ b/src/main/java/net/minecraft/server/EntityLiving.java +@@ -0,0 +0,0 @@ import org.bukkit.event.entity.EntityDamageEvent.DamageModifier; + import org.bukkit.event.entity.EntityRegainHealthEvent; + // CraftBukkit end + ++import org.bukkit.craftbukkit.SpigotTimings; // Spigot ++ + public abstract class EntityLiving extends Entity { + + private static final UUID b = UUID.fromString("662A6B8D-DA3E-4C1C-8813-96EA6097278D"); +@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { + } + + public void h() { ++ SpigotTimings.timerEntityBaseTick.startTiming(); // Spigot + super.h(); + if (!this.world.isStatic) { + int i = this.aZ(); +@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { + } + } + ++ SpigotTimings.timerEntityBaseTick.stopTiming(); // Spigot + this.e(); ++ SpigotTimings.timerEntityTickRest.startTiming(); // Spigot + double d0 = this.locX - this.lastX; + double d1 = this.locZ - this.lastZ; + float f = (float) (d0 * d0 + d1 * d1); +@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { + + this.world.methodProfiler.b(); + this.aX += f2; ++ SpigotTimings.timerEntityTickRest.stopTiming(); // Spigot + } + + protected float f(float f, float f1) { +@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { + } + + this.world.methodProfiler.a("ai"); ++ SpigotTimings.timerEntityAI.startTiming(); // Spigot + if (this.bh()) { + this.bc = false; + this.bd = 0.0F; +@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { + this.aO = this.yaw; + } + } ++ SpigotTimings.timerEntityAI.stopTiming(); // Spigot + + this.world.methodProfiler.b(); + this.world.methodProfiler.a("jump"); +@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { + this.bd *= 0.98F; + this.be *= 0.98F; + this.bf *= 0.9F; ++ SpigotTimings.timerEntityAIMove.startTiming(); // Spigot + this.e(this.bd, this.be); ++ SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot + this.world.methodProfiler.b(); + this.world.methodProfiler.a("push"); + if (!this.world.isStatic) { ++ SpigotTimings.timerEntityAICollision.startTiming(); // Spigot + this.bo(); ++ SpigotTimings.timerEntityAICollision.stopTiming(); // Spigot + } + + this.world.methodProfiler.b(); +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -0,0 +0,0 @@ import jline.console.ConsoleReader; + import joptsimple.OptionSet; + + import org.bukkit.World.Environment; ++import org.bukkit.craftbukkit.SpigotTimings; // Spigot + import org.bukkit.craftbukkit.util.Waitable; + import org.bukkit.event.server.RemoteServerCommandEvent; + import org.bukkit.event.world.WorldSaveEvent; +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + protected void t() {} + + protected void u() throws ExceptionWorldConflict { // CraftBukkit - added throws ++ SpigotTimings.serverTickTimer.startTiming(); // Spigot + long i = System.nanoTime(); + + ++this.ticks; +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + } + + if ((this.autosavePeriod > 0) && ((this.ticks % this.autosavePeriod) == 0)) { // CraftBukkit ++ SpigotTimings.worldSaveTimer.startTiming(); // Spigot + this.methodProfiler.a("save"); + this.u.savePlayers(); + this.saveChunks(true); + this.methodProfiler.b(); ++ SpigotTimings.worldSaveTimer.stopTiming(); // Spigot + } + + this.methodProfiler.a("tallying"); +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + public void v() { + this.methodProfiler.a("levels"); + ++ SpigotTimings.schedulerTimer.startTiming(); // Spigot + // CraftBukkit start + this.server.getScheduler().mainThreadHeartbeat(this.ticks); ++ SpigotTimings.schedulerTimer.stopTiming(); // Spigot + + // Run tasks that are waiting on processing ++ SpigotTimings.processQueueTimer.startTiming(); // Spigot + while (!processQueue.isEmpty()) { + processQueue.remove().run(); + } ++ SpigotTimings.processQueueTimer.stopTiming(); // Spigot + ++ SpigotTimings.chunkIOTickTimer.startTiming(); // Spigot + org.bukkit.craftbukkit.chunkio.ChunkIOExecutor.tick(); ++ SpigotTimings.chunkIOTickTimer.stopTiming(); // Spigot + ++ SpigotTimings.timeUpdateTimer.startTiming(); // Spigot + // Send time updates to everyone, it will get the right time from the world the player is in. + if (this.ticks % 20 == 0) { + for (int i = 0; i < this.getPlayerList().players.size(); ++i) { +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + entityplayer.playerConnection.sendPacket(new PacketPlayOutUpdateTime(entityplayer.world.getTime(), entityplayer.getPlayerTime(), entityplayer.world.getGameRules().getBoolean("doDaylightCycle"))); // Add support for per player time + } + } ++ SpigotTimings.timeUpdateTimer.stopTiming(); // Spigot + + int i; + +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + CrashReport crashreport; + + try { ++ worldserver.timings.doTick.startTiming(); // Spigot + worldserver.doTick(); ++ worldserver.timings.doTick.stopTiming(); // Spigot + } catch (Throwable throwable) { + crashreport = CrashReport.a(throwable, "Exception ticking world"); + worldserver.a(crashreport); +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + } + + try { ++ worldserver.timings.tickEntities.startTiming(); // Spigot + worldserver.tickEntities(); ++ worldserver.timings.tickEntities.stopTiming(); // Spigot + } catch (Throwable throwable1) { + crashreport = CrashReport.a(throwable1, "Exception ticking world entities"); + worldserver.a(crashreport); +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + + this.methodProfiler.b(); + this.methodProfiler.a("tracker"); ++ worldserver.timings.tracker.startTiming(); // Spigot + worldserver.getTracker().updatePlayers(); ++ worldserver.timings.tracker.stopTiming(); // Spigot + this.methodProfiler.b(); + this.methodProfiler.b(); + // } // CraftBukkit +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + } + + this.methodProfiler.c("connection"); ++ SpigotTimings.connectionTimer.startTiming(); // Spigot + this.ai().c(); ++ SpigotTimings.connectionTimer.stopTiming(); // Spigot + this.methodProfiler.c("players"); ++ SpigotTimings.playerListTimer.startTiming(); // Spigot + this.u.tick(); ++ SpigotTimings.playerListTimer.stopTiming(); // Spigot + this.methodProfiler.c("tickables"); + ++ SpigotTimings.tickablesTimer.startTiming(); // Spigot + for (i = 0; i < this.n.size(); ++i) { + ((IUpdatePlayerListBox) this.n.get(i)).a(); + } ++ SpigotTimings.tickablesTimer.stopTiming(); // Spigot + + this.methodProfiler.b(); ++ SpigotTimings.serverTickTimer.stopTiming(); // Spigot ++ org.spigotmc.CustomTimingsHandler.tick(); // Spigot + } + + public boolean getAllowNether() { +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketPlayInListener { + // CraftBukkit end + + private void handleCommand(String s) { ++ org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.startTiming(); // Spigot ++ + // CraftBukkit start - whole method + this.c.info(this.player.getName() + " issued server command: " + s); + +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketPlayInListener { + this.server.getPluginManager().callEvent(event); + + if (event.isCancelled()) { ++ org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot + return; + } + + try { + if (this.server.dispatchCommand(event.getPlayer(), event.getMessage().substring(1))) { ++ org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot + return; + } + } catch (org.bukkit.command.CommandException ex) { + player.sendMessage(org.bukkit.ChatColor.RED + "An internal error occurred while attempting to perform this command"); + java.util.logging.Logger.getLogger(PlayerConnection.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); ++ org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot + return; + } ++ org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot + //this.minecraftServer.getCommandHandler().a(this.player, s); + // CraftBukkit end + } +diff --git a/src/main/java/net/minecraft/server/TileEntity.java b/src/main/java/net/minecraft/server/TileEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/TileEntity.java ++++ b/src/main/java/net/minecraft/server/TileEntity.java +@@ -0,0 +0,0 @@ import java.util.concurrent.Callable; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + ++import org.spigotmc.CustomTimingsHandler; // Spigot + import org.bukkit.inventory.InventoryHolder; // CraftBukkit + + public class TileEntity { + ++ public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot + private static final Logger a = LogManager.getLogger(); + private static Map i = new HashMap(); + private static Map j = new HashMap(); +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -0,0 +0,0 @@ import org.bukkit.Bukkit; + import org.bukkit.block.BlockState; + import org.bukkit.craftbukkit.util.CraftMagicNumbers; + import org.bukkit.craftbukkit.util.LongHashSet; ++import org.bukkit.craftbukkit.SpigotTimings; // Spigot + import org.bukkit.generator.ChunkGenerator; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftWorld; +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + public ChunkGenerator generator; + public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot + ++ public final SpigotTimings.WorldTimingsHandler timings; // Spigot ++ + public CraftWorld getWorld() { + return this.world; + } +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + + this.worldProvider.a(this); + this.chunkProvider = this.j(); ++ timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings + if (!this.worldData.isInitialized()) { + try { + this.a(worldsettings); +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + this.f.clear(); + this.methodProfiler.c("regular"); + ++ timings.entityTick.startTiming(); // Spigot + // CraftBukkit start - Use field for loop variable + for (this.tickPosition = 0; this.tickPosition < this.entityList.size(); ++this.tickPosition) { + entity = (Entity) this.entityList.get(this.tickPosition); +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + this.methodProfiler.a("tick"); + if (!entity.dead) { + try { ++ SpigotTimings.tickEntityTimer.startTiming(); // Spigot + this.playerJoinedWorld(entity); ++ SpigotTimings.tickEntityTimer.stopTiming(); // Spigot + } catch (Throwable throwable1) { + crashreport = CrashReport.a(throwable1, "Ticking entity"); + crashreportsystemdetails = crashreport.a("Entity being ticked"); +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + this.methodProfiler.b(); + } + ++ timings.entityTick.stopTiming(); // Spigot + this.methodProfiler.c("blockEntities"); ++ timings.tileEntityTick.startTiming(); // Spigot + this.M = true; + // CraftBukkit start - From below, clean up tile entities before ticking them + if (!this.b.isEmpty()) { +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + + if (!tileentity.r() && tileentity.o() && this.isLoaded(tileentity.x, tileentity.y, tileentity.z)) { + try { ++ tileentity.tickTimer.startTiming(); // Spigot + tileentity.h(); ++ tileentity.tickTimer.stopTiming(); // Spigot + } catch (Throwable throwable2) { ++ tileentity.tickTimer.stopTiming(); // Spigot + crashreport = CrashReport.a(throwable2, "Ticking block entity"); + crashreportsystemdetails = crashreport.a("Block entity being ticked"); + tileentity.a(crashreportsystemdetails); +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + } + } + ++ timings.tileEntityTick.stopTiming(); // Spigot ++ timings.tileEntityPending.startTiming(); // Spigot + this.M = false; + /* CraftBukkit start - Moved up + if (!this.b.isEmpty()) { +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + this.a.clear(); + } + ++ timings.tileEntityPending.stopTiming(); // Spigot + this.methodProfiler.b(); + this.methodProfiler.b(); + } +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + // CraftBukkit start - Use neighbor cache instead of looking up + Chunk startingChunk = this.getChunkIfLoaded(i >> 4, j >> 4); + if (!flag || (startingChunk != null && startingChunk.areNeighborsLoaded(2)) /* this.b(i - b0, 0, j - b0, i + b0, 0, j + b0) */) { ++ entity.tickTimer.startTiming(); // Spigot + // CraftBukkit end + entity.S = entity.locX; + entity.T = entity.locY; +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + entity.passenger = null; + } + } ++ entity.tickTimer.stopTiming(); // Spigot + } + } + +diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/WorldServer.java ++++ b/src/main/java/net/minecraft/server/WorldServer.java +@@ -0,0 +0,0 @@ public class WorldServer extends World { + // CraftBukkit start - Only call spawner if we have players online and the world allows for mobs or animals + long time = this.worldData.getTime(); + if (this.getGameRules().getBoolean("doMobSpawning") && (this.allowMonsters || this.allowAnimals) && (this instanceof WorldServer && this.players.size() > 0)) { ++ timings.mobSpawn.startTiming(); // Spigot + this.R.spawnEntities(this, this.allowMonsters && (this.ticksPerMonsterSpawns != 0 && time % this.ticksPerMonsterSpawns == 0L), this.allowAnimals && (this.ticksPerAnimalSpawns != 0 && time % this.ticksPerAnimalSpawns == 0L), this.worldData.getTime() % 400L == 0L); ++ timings.mobSpawn.stopTiming(); // Spigot + // CraftBukkit end + } +- ++ // CraftBukkit end ++ timings.doChunkUnload.startTiming(); // Spigot + this.methodProfiler.c("chunkSource"); + this.chunkProvider.unloadChunks(); + int j = this.a(1.0F); +@@ -0,0 +0,0 @@ public class WorldServer extends World { + this.worldData.setDayTime(this.worldData.getDayTime() + 1L); + } + ++ timings.doChunkUnload.stopTiming(); // Spigot + this.methodProfiler.c("tickPending"); ++ timings.doTickPending.startTiming(); // Spigot + this.a(false); ++ timings.doTickPending.stopTiming(); // Spigot + this.methodProfiler.c("tickBlocks"); ++ timings.doTickTiles.startTiming(); // Spigot + this.g(); ++ timings.doTickTiles.stopTiming(); // Spigot + this.methodProfiler.c("chunkMap"); ++ timings.doChunkMap.startTiming(); // Spigot + this.manager.flush(); ++ timings.doChunkMap.stopTiming(); // Spigot + this.methodProfiler.c("village"); ++ timings.doVillages.startTiming(); // Spigot + this.villages.tick(); + this.siegeManager.a(); ++ timings.doVillages.stopTiming(); // Spigot + this.methodProfiler.c("portalForcer"); ++ timings.doPortalForcer.startTiming(); // Spigot + this.Q.a(this.getTime()); ++ timings.doPortalForcer.stopTiming(); // Spigot + this.methodProfiler.b(); ++ timings.doSounds.startTiming(); // Spigot + this.Z(); ++ timings.doSounds.stopTiming(); // Spigot + ++ timings.doChunkGC.startTiming(); // Spigot + this.getWorld().processChunkGC(); // CraftBukkit ++ timings.doChunkGC.stopTiming(); // Spigot + } + + public BiomeMeta a(EnumCreatureType enumcreaturetype, int i, int j, int k) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -0,0 +0,0 @@ public class CraftWorld implements World { + net.minecraft.server.Chunk chunk = world.chunkProviderServer.chunks.get(LongHash.toLong(x, z)); + + if (chunk == null) { ++ world.timings.syncChunkLoadTimer.startTiming(); // Spigot + chunk = world.chunkProviderServer.loadChunk(x, z); + + chunkLoadPostProcess(chunk, x, z); ++ world.timings.syncChunkLoadTimer.stopTiming(); // Spigot + } + return chunk != null; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java +@@ -0,0 +0,0 @@ ++package org.bukkit.craftbukkit; ++ ++import com.google.common.collect.Maps; ++import net.minecraft.server.*; ++import org.bukkit.plugin.java.JavaPluginLoader; ++import org.spigotmc.CustomTimingsHandler; ++import org.bukkit.scheduler.BukkitTask; ++ ++import java.util.HashMap; ++import java.util.Map; ++ ++import org.bukkit.craftbukkit.scheduler.CraftTask; ++ ++public class SpigotTimings { ++ ++ public static final CustomTimingsHandler serverTickTimer = new CustomTimingsHandler("** Full Server Tick"); ++ public static final CustomTimingsHandler playerListTimer = new CustomTimingsHandler("Player List"); ++ public static final CustomTimingsHandler connectionTimer = new CustomTimingsHandler("Connection Handler"); ++ public static final CustomTimingsHandler tickablesTimer = new CustomTimingsHandler("Tickables"); ++ public static final CustomTimingsHandler schedulerTimer = new CustomTimingsHandler("Scheduler"); ++ public static final CustomTimingsHandler chunkIOTickTimer = new CustomTimingsHandler("ChunkIOTick"); ++ public static final CustomTimingsHandler timeUpdateTimer = new CustomTimingsHandler("Time Update"); ++ public static final CustomTimingsHandler serverCommandTimer = new CustomTimingsHandler("Server Command"); ++ public static final CustomTimingsHandler worldSaveTimer = new CustomTimingsHandler("World Save"); ++ ++ public static final CustomTimingsHandler entityMoveTimer = new CustomTimingsHandler("** entityMove"); ++ public static final CustomTimingsHandler tickEntityTimer = new CustomTimingsHandler("** tickEntity"); ++ public static final CustomTimingsHandler activatedEntityTimer = new CustomTimingsHandler("** activatedTickEntity"); ++ public static final CustomTimingsHandler tickTileEntityTimer = new CustomTimingsHandler("** tickTileEntity"); ++ ++ public static final CustomTimingsHandler timerEntityBaseTick = new CustomTimingsHandler("** livingEntityBaseTick"); ++ public static final CustomTimingsHandler timerEntityAI = new CustomTimingsHandler("** livingEntityAI"); ++ public static final CustomTimingsHandler timerEntityAICollision = new CustomTimingsHandler("** livingEntityAICollision"); ++ public static final CustomTimingsHandler timerEntityAIMove = new CustomTimingsHandler("** livingEntityAIMove"); ++ public static final CustomTimingsHandler timerEntityTickRest = new CustomTimingsHandler("** livingEntityTickRest"); ++ ++ public static final CustomTimingsHandler processQueueTimer = new CustomTimingsHandler("processQueue"); ++ public static final CustomTimingsHandler schedulerSyncTimer = new CustomTimingsHandler("** Scheduler - Sync Tasks", JavaPluginLoader.pluginParentTimer); ++ ++ public static final CustomTimingsHandler playerCommandTimer = new CustomTimingsHandler("** playerCommand"); ++ ++ public static final HashMap entityTypeTimingMap = new HashMap(); ++ public static final HashMap tileEntityTypeTimingMap = new HashMap(); ++ public static final HashMap pluginTaskTimingMap = new HashMap(); ++ ++ /** ++ * Gets a timer associated with a plugins tasks. ++ * @param task ++ * @param period ++ * @return ++ */ ++ public static CustomTimingsHandler getPluginTaskTimings(BukkitTask task, long period) { ++ if (!task.isSync()) { ++ return null; ++ } ++ String plugin; ++ final CraftTask ctask = (CraftTask) task; ++ ++ if (task.getOwner() != null) { ++ plugin = task.getOwner().getDescription().getFullName(); ++ } else if (ctask.timingName != null) { ++ plugin = "CraftScheduler"; ++ } else { ++ plugin = "Unknown"; ++ } ++ String taskname = ctask.getTaskName(); ++ ++ String name = "Task: " + plugin + " Runnable: " + taskname; ++ if (period > 0) { ++ name += "(interval:" + period +")"; ++ } else { ++ name += "(Single)"; ++ } ++ CustomTimingsHandler result = pluginTaskTimingMap.get(name); ++ if (result == null) { ++ result = new CustomTimingsHandler(name, SpigotTimings.schedulerSyncTimer); ++ pluginTaskTimingMap.put(name, result); ++ } ++ return result; ++ } ++ ++ /** ++ * Get a named timer for the specified entity type to track type specific timings. ++ * @param entity ++ * @return ++ */ ++ public static CustomTimingsHandler getEntityTimings(Entity entity) { ++ String entityType = entity.getClass().getSimpleName(); ++ CustomTimingsHandler result = entityTypeTimingMap.get(entityType); ++ if (result == null) { ++ result = new CustomTimingsHandler("** tickEntity - " + entityType, activatedEntityTimer); ++ entityTypeTimingMap.put(entityType, result); ++ } ++ return result; ++ } ++ ++ /** ++ * Get a named timer for the specified tile entity type to track type specific timings. ++ * @param entity ++ * @return ++ */ ++ public static CustomTimingsHandler getTileEntityTimings(TileEntity entity) { ++ String entityType = entity.getClass().getSimpleName(); ++ CustomTimingsHandler result = tileEntityTypeTimingMap.get(entityType); ++ if (result == null) { ++ result = new CustomTimingsHandler("** tickTileEntity - " + entityType, tickTileEntityTimer); ++ tileEntityTypeTimingMap.put(entityType, result); ++ } ++ return result; ++ } ++ ++ /** ++ * Set of timers per world, to track world specific timings. ++ */ ++ public static class WorldTimingsHandler { ++ public final CustomTimingsHandler mobSpawn; ++ public final CustomTimingsHandler doChunkUnload; ++ public final CustomTimingsHandler doPortalForcer; ++ public final CustomTimingsHandler doTickPending; ++ public final CustomTimingsHandler doTickTiles; ++ public final CustomTimingsHandler doVillages; ++ public final CustomTimingsHandler doChunkMap; ++ public final CustomTimingsHandler doChunkGC; ++ public final CustomTimingsHandler doSounds; ++ public final CustomTimingsHandler entityTick; ++ public final CustomTimingsHandler tileEntityTick; ++ public final CustomTimingsHandler tileEntityPending; ++ public final CustomTimingsHandler tracker; ++ public final CustomTimingsHandler doTick; ++ public final CustomTimingsHandler tickEntities; ++ ++ public final CustomTimingsHandler syncChunkLoadTimer; ++ public final CustomTimingsHandler syncChunkLoadDataTimer; ++ public final CustomTimingsHandler syncChunkLoadStructuresTimer; ++ public final CustomTimingsHandler syncChunkLoadEntitiesTimer; ++ public final CustomTimingsHandler syncChunkLoadTileEntitiesTimer; ++ public final CustomTimingsHandler syncChunkLoadTileTicksTimer; ++ public final CustomTimingsHandler syncChunkLoadPostTimer; ++ ++ public WorldTimingsHandler(World server) { ++ String name = server.worldData.getName() +" - "; ++ ++ mobSpawn = new CustomTimingsHandler("** " + name + "mobSpawn"); ++ doChunkUnload = new CustomTimingsHandler("** " + name + "doChunkUnload"); ++ doTickPending = new CustomTimingsHandler("** " + name + "doTickPending"); ++ doTickTiles = new CustomTimingsHandler("** " + name + "doTickTiles"); ++ doVillages = new CustomTimingsHandler("** " + name + "doVillages"); ++ doChunkMap = new CustomTimingsHandler("** " + name + "doChunkMap"); ++ doSounds = new CustomTimingsHandler("** " + name + "doSounds"); ++ doChunkGC = new CustomTimingsHandler("** " + name + "doChunkGC"); ++ doPortalForcer = new CustomTimingsHandler("** " + name + "doPortalForcer"); ++ entityTick = new CustomTimingsHandler("** " + name + "entityTick"); ++ tileEntityTick = new CustomTimingsHandler("** " + name + "tileEntityTick"); ++ tileEntityPending = new CustomTimingsHandler("** " + name + "tileEntityPending"); ++ ++ syncChunkLoadTimer = new CustomTimingsHandler("** " + name + "syncChunkLoad"); ++ syncChunkLoadDataTimer = new CustomTimingsHandler("** " + name + "syncChunkLoad - Data"); ++ syncChunkLoadStructuresTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Structures"); ++ syncChunkLoadEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Entities"); ++ syncChunkLoadTileEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileEntities"); ++ syncChunkLoadTileTicksTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileTicks"); ++ syncChunkLoadPostTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Post"); ++ ++ ++ tracker = new CustomTimingsHandler(name + "tracker"); ++ doTick = new CustomTimingsHandler(name + "doTick"); ++ tickEntities = new CustomTimingsHandler(name + "tickEntities"); ++ } ++ } ++} +diff --git a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java ++++ b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java +@@ -0,0 +0,0 @@ class ChunkIOProvider implements AsynchronousExecutor.CallBackProvider +Date: Fri, 21 Jun 2013 17:29:54 +1000 +Subject: [PATCH] Fix Mob Spawning Relative to View Distance + +Changes the mob spawning algorithm to properly account for view distance and the range around players. + +Needs better documentation. + +diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Chunk.java ++++ b/src/main/java/net/minecraft/server/Chunk.java +@@ -0,0 +0,0 @@ public class Chunk { + public int r; + public long s; + private int x; ++ protected net.minecraft.util.gnu.trove.map.hash.TObjectIntHashMap entityCount = new net.minecraft.util.gnu.trove.map.hash.TObjectIntHashMap(); // Spigot + + // CraftBukkit start - Neighbor loaded cache for chunk lighting and entity ticking + private int neighbors = 0x1 << 12; +@@ -0,0 +0,0 @@ public class Chunk { + entity.ai = k; + entity.aj = this.locZ; + this.entitySlices[k].add(entity); ++ // Spigot start - increment creature type count ++ // Keep this synced up with World.a(Class) ++ if (entity instanceof EntityInsentient) { ++ EntityInsentient entityinsentient = (EntityInsentient) entity; ++ if (entityinsentient.isTypeNotPersistent() && entityinsentient.isPersistent()) { ++ return; ++ } ++ } ++ for ( EnumCreatureType creatureType : EnumCreatureType.values() ) ++ { ++ if ( creatureType.a().isAssignableFrom( entity.getClass() ) ) ++ { ++ this.entityCount.adjustOrPutValue( creatureType.a(), 1, 1 ); ++ } ++ } ++ // Spigot end + } + + public void b(Entity entity) { +@@ -0,0 +0,0 @@ public class Chunk { + } + + this.entitySlices[i].remove(entity); ++ // Spigot start - decrement creature type count ++ // Keep this synced up with World.a(Class) ++ if (entity instanceof EntityInsentient) { ++ EntityInsentient entityinsentient = (EntityInsentient) entity; ++ if (entityinsentient.isTypeNotPersistent() && entityinsentient.isPersistent()) { ++ return; ++ } ++ } ++ for ( EnumCreatureType creatureType : EnumCreatureType.values() ) ++ { ++ if ( creatureType.a().isAssignableFrom( entity.getClass() ) ) ++ { ++ this.entityCount.adjustValue( creatureType.a(), -1 ); ++ } ++ } ++ // Spigot end + } + + public boolean d(int i, int j, int k) { +diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/SpawnerCreature.java ++++ b/src/main/java/net/minecraft/server/SpawnerCreature.java +@@ -0,0 +0,0 @@ public final class SpawnerCreature { + return new ChunkPosition(k, i1, l); + } + ++ // Spigot start - get entity count only from chunks being processed in b ++ private int getEntityCount(WorldServer server, Class oClass) ++ { ++ int i = 0; ++ for ( Long coord : this.a.keySet() ) ++ { ++ int x = LongHash.msw( coord ); ++ int z = LongHash.lsw( coord ); ++ if ( !server.chunkProviderServer.unloadQueue.contains( coord ) && server.isChunkLoaded( x, z ) ) ++ { ++ i += server.getChunkAt( x, z ).entityCount.get( oClass ); ++ } ++ } ++ return i; ++ } ++ // Spigot end ++ + public int spawnEntities(WorldServer worldserver, boolean flag, boolean flag1, boolean flag2) { + if (!flag && !flag1) { + return 0; +@@ -0,0 +0,0 @@ public final class SpawnerCreature { + + j = MathHelper.floor(entityhuman.locZ / 16.0D); + byte b0 = 8; ++ // Spigot Start ++ b0 = worldserver.spigotConfig.mobSpawnRange; ++ b0 = ( b0 > worldserver.spigotConfig.viewDistance ) ? (byte) worldserver.spigotConfig.viewDistance : b0; ++ b0 = ( b0 > 8 ) ? 8 : b0; ++ // Spigot End + + for (int l = -b0; l <= b0; ++l) { + for (int i1 = -b0; i1 <= b0; ++i1) { +@@ -0,0 +0,0 @@ public final class SpawnerCreature { + if (limit == 0) { + continue; + } ++ int mobcnt = 0; + // CraftBukkit end + +- if ((!enumcreaturetype.d() || flag1) && (enumcreaturetype.d() || flag) && (!enumcreaturetype.e() || flag2) && worldserver.a(enumcreaturetype.a()) <= limit * this.a.size() / 256) { // CraftBukkit - use per-world limits ++ if ((!enumcreaturetype.d() || flag1) && (enumcreaturetype.d() || flag) && (!enumcreaturetype.e() || flag2) && (mobcnt = getEntityCount(worldserver, enumcreaturetype.a())) <= limit * this.a.size() / 256) { // Spigot - use per-world limits and use all loaded chunks + Iterator iterator = this.a.keySet().iterator(); + ++ int moblimit = (limit * this.a.size() / 256) - mobcnt + 1; // Spigot - up to 1 more than limit + label110: +- while (iterator.hasNext()) { ++ while (iterator.hasNext() && (moblimit > 0)) { // Spigot - while more allowed + // CraftBukkit start = use LongHash and LongObjectHashMap + long key = ((Long) iterator.next()).longValue(); + +@@ -0,0 +0,0 @@ public final class SpawnerCreature { + groupdataentity = entityinsentient.prepare(groupdataentity); + worldserver.addEntity(entityinsentient, SpawnReason.NATURAL); + // CraftBukkit end ++ // Spigot start ++ if ( --moblimit <= 0 ) ++ { ++ // If we're past limit, stop spawn ++ continue label110; ++ } ++ // Spigot end + if (j2 >= entityinsentient.bB()) { + continue label110; + } +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -0,0 +0,0 @@ public class SpigotWorldConfig + viewDistance = getInt( "view-distance", Bukkit.getViewDistance() ); + log( "View Distance: " + viewDistance ); + } ++ ++ public byte mobSpawnRange; ++ private void mobSpawnRange() ++ { ++ mobSpawnRange = (byte) getInt( "mob-spawn-range", 4 ); ++ log( "Mob Spawn Range: " + mobSpawnRange ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0015-Handle-Null-Tile-Entities.patch b/CraftBukkit-Patches/0015-Handle-Null-Tile-Entities.patch new file mode 100644 index 0000000000..037cd11b0d --- /dev/null +++ b/CraftBukkit-Patches/0015-Handle-Null-Tile-Entities.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 3 Feb 2013 09:20:19 +1100 +Subject: [PATCH] Handle Null Tile Entities + + +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + + while (iterator.hasNext()) { + TileEntity tileentity = (TileEntity) iterator.next(); ++ // Spigot start ++ if (tileentity == null) { ++ getServer().getLogger().severe("Spigot has detected a null entity and has removed it, preventing a crash"); ++ iterator.remove(); ++ continue; ++ } ++ // Spigot end + + if (!tileentity.r() && tileentity.o() && this.isLoaded(tileentity.x, tileentity.y, tileentity.z)) { + try { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0016-Entity-Activation-Range.patch b/CraftBukkit-Patches/0016-Entity-Activation-Range.patch new file mode 100644 index 0000000000..f456274d73 --- /dev/null +++ b/CraftBukkit-Patches/0016-Entity-Activation-Range.patch @@ -0,0 +1,520 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 3 Feb 2013 05:10:21 -0500 +Subject: [PATCH] Entity Activation Range + +This feature gives 3 new configurable ranges that if an entity of the matching type is outside of this radius of any player, will tick at 5% of its normal rate. + +This will drastically cut down on tick timings for entities that are not in range of a user to actually be "used". +This change can have dramatic impact on gameplay if configured too low. Balance according to your servers desired gameplay. + +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -0,0 +0,0 @@ public abstract class Entity { + public int ticksLived; + public int maxFireTicks; + public int fireTicks; // CraftBukkit - private -> public +- protected boolean inWater; ++ public boolean inWater; // Spigot - protected -> public + public int noDamageTicks; + private boolean justCreated; + protected boolean fireProof; +@@ -0,0 +0,0 @@ public abstract class Entity { + public boolean valid; // CraftBukkit + public org.bukkit.projectiles.ProjectileSource projectileSource; // CraftBukkit - For projectiles only + ++ // Spigot start + public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getEntityTimings(this); // Spigot ++ public final byte activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); ++ public final boolean defaultActivationState; ++ public long activatedTick = 0; ++ public void inactiveTick() { } ++ // Spigot end + + public int getId() { + return this.id; +@@ -0,0 +0,0 @@ public abstract class Entity { + this.setPosition(0.0D, 0.0D, 0.0D); + if (world != null) { + this.dimension = world.worldProvider.dimension; ++ // Spigot start ++ this.defaultActivationState = org.spigotmc.ActivationRange.initializeEntityActivationState(this, world.spigotConfig); ++ } else { ++ this.defaultActivationState = false; + } ++ // Spigot end + + this.datawatcher = new DataWatcher(this); + this.datawatcher.a(0, Byte.valueOf((byte) 0)); +diff --git a/src/main/java/net/minecraft/server/EntityAgeable.java b/src/main/java/net/minecraft/server/EntityAgeable.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityAgeable.java ++++ b/src/main/java/net/minecraft/server/EntityAgeable.java +@@ -0,0 +0,0 @@ public abstract class EntityAgeable extends EntityCreature { + private float bq; + public boolean ageLocked = false; // CraftBukkit + ++ // Spigot start ++ @Override ++ public void inactiveTick() ++ { ++ super.inactiveTick(); ++ if ( this.world.isStatic || this.ageLocked ) ++ { // CraftBukkit ++ this.a( this.isBaby() ); ++ } else ++ { ++ int i = this.getAge(); ++ ++ if ( i < 0 ) ++ { ++ ++i; ++ this.setAge( i ); ++ } else if ( i > 0 ) ++ { ++ --i; ++ this.setAge( i ); ++ } ++ } ++ } ++ // Spigot end ++ + public EntityAgeable(World world) { + super(world); + } +diff --git a/src/main/java/net/minecraft/server/EntityArrow.java b/src/main/java/net/minecraft/server/EntityArrow.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityArrow.java ++++ b/src/main/java/net/minecraft/server/EntityArrow.java +@@ -0,0 +0,0 @@ public class EntityArrow extends Entity implements IProjectile { + private int f = -1; + private Block g; + private int h; +- private boolean inGround; ++ public boolean inGround = false; // Spigot - private -> public + public int fromPlayer; + public int shake; + public Entity shooter; +@@ -0,0 +0,0 @@ public class EntityArrow extends Entity implements IProjectile { + private double damage = 2.0D; + public int knockbackStrength; // CraftBukkit - private -> public + ++ // Spigot Start ++ @Override ++ public void inactiveTick() ++ { ++ if ( this.inGround ) ++ { ++ this.at += 19; // Despawn counter. First int after shooter ++ } ++ super.inactiveTick(); ++ } ++ // Spigot End ++ + public EntityArrow(World world) { + super(world); + this.j = 10.0D; +diff --git a/src/main/java/net/minecraft/server/EntityFireworks.java b/src/main/java/net/minecraft/server/EntityFireworks.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityFireworks.java ++++ b/src/main/java/net/minecraft/server/EntityFireworks.java +@@ -0,0 +0,0 @@ public class EntityFireworks extends Entity { + private int ticksFlown; + public int expectedLifespan; // CraftBukkit - private -> public + ++ // Spigot Start ++ @Override ++ public void inactiveTick() ++ { ++ this.ticksFlown += 19; ++ super.inactiveTick(); ++ } ++ // Spigot End ++ + public EntityFireworks(World world) { + super(world); + this.a(0.25F, 0.25F); +diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityLiving.java ++++ b/src/main/java/net/minecraft/server/EntityLiving.java +@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { + public int maxAirTicks = 300; + ArrayList drops = null; + // CraftBukkit end ++ // Spigot start ++ public void inactiveTick() ++ { ++ super.inactiveTick(); ++ ++this.aU; // Above all the floats ++ } ++ // Spigot end + + public EntityLiving(World world) { + super(world); +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + this.f.clear(); + this.methodProfiler.c("regular"); + ++ org.spigotmc.ActivationRange.activateEntities(this); // Spigot + timings.entityTick.startTiming(); // Spigot + // CraftBukkit start - Use field for loop variable + for (this.tickPosition = 0; this.tickPosition < this.entityList.size(); ++this.tickPosition) { +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + int j = MathHelper.floor(entity.locZ); + byte b0 = 32; + +- // CraftBukkit start - Use neighbor cache instead of looking up +- Chunk startingChunk = this.getChunkIfLoaded(i >> 4, j >> 4); +- if (!flag || (startingChunk != null && startingChunk.areNeighborsLoaded(2)) /* this.b(i - b0, 0, j - b0, i + b0, 0, j + b0) */) { ++ // Spigot start ++ if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { ++ entity.ticksLived++; ++ entity.inactiveTick(); ++ } else { + entity.tickTimer.startTiming(); // Spigot + // CraftBukkit end + entity.S = entity.locX; +diff --git a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java ++++ b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java +@@ -0,0 +0,0 @@ public class SpigotTimings { + + public static final CustomTimingsHandler playerCommandTimer = new CustomTimingsHandler("** playerCommand"); + ++ public static final CustomTimingsHandler entityActivationCheckTimer = new CustomTimingsHandler("entityActivationCheck"); ++ public static final CustomTimingsHandler checkIfActiveTimer = new CustomTimingsHandler("** checkIfActive"); ++ + public static final HashMap entityTypeTimingMap = new HashMap(); + public static final HashMap tileEntityTypeTimingMap = new HashMap(); + public static final HashMap pluginTaskTimingMap = new HashMap(); +diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/org/spigotmc/ActivationRange.java +@@ -0,0 +0,0 @@ ++package org.spigotmc; ++ ++import java.util.ArrayList; ++import java.util.List; ++import net.minecraft.server.AxisAlignedBB; ++import net.minecraft.server.Chunk; ++import net.minecraft.server.Entity; ++import net.minecraft.server.EntityAmbient; ++import net.minecraft.server.EntityAnimal; ++import net.minecraft.server.EntityArrow; ++import net.minecraft.server.EntityComplexPart; ++import net.minecraft.server.EntityCreature; ++import net.minecraft.server.EntityEnderCrystal; ++import net.minecraft.server.EntityEnderDragon; ++import net.minecraft.server.EntityFireball; ++import net.minecraft.server.EntityFireworks; ++import net.minecraft.server.EntityHuman; ++import net.minecraft.server.EntityLiving; ++import net.minecraft.server.EntityMonster; ++import net.minecraft.server.EntityProjectile; ++import net.minecraft.server.EntitySheep; ++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.MathHelper; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.World; ++import org.bukkit.craftbukkit.SpigotTimings; ++ ++public class ActivationRange ++{ ++ ++ static AxisAlignedBB maxBB = AxisAlignedBB.a( 0, 0, 0, 0, 0, 0 ); ++ static AxisAlignedBB miscBB = AxisAlignedBB.a( 0, 0, 0, 0, 0, 0 ); ++ static AxisAlignedBB animalBB = AxisAlignedBB.a( 0, 0, 0, 0, 0, 0 ); ++ static AxisAlignedBB monsterBB = AxisAlignedBB.a( 0, 0, 0, 0, 0, 0 ); ++ ++ /** ++ * Initializes an entities type on construction to specify what group this ++ * entity is in for activation ranges. ++ * ++ * @param entity ++ * @return group id ++ */ ++ public static byte initializeEntityActivationType(Entity entity) ++ { ++ if ( entity instanceof EntityMonster || entity instanceof EntitySlime ) ++ { ++ return 1; // Monster ++ } else if ( entity instanceof EntityCreature || entity instanceof EntityAmbient ) ++ { ++ return 2; // Animal ++ } else ++ { ++ return 3; // Misc ++ } ++ } ++ ++ /** ++ * These entities are excluded from Activation range checks. ++ * ++ * @param entity ++ * @param world ++ * @return boolean If it should always tick. ++ */ ++ public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config) ++ { ++ if ( ( entity.activationType == 3 && config.miscActivationRange == 0 ) ++ || ( entity.activationType == 2 && config.animalActivationRange == 0 ) ++ || ( entity.activationType == 1 && config.monsterActivationRange == 0 ) ++ || entity instanceof EntityHuman ++ || entity instanceof EntityProjectile ++ || entity instanceof EntityEnderDragon ++ || entity instanceof EntityComplexPart ++ || entity instanceof EntityWither ++ || entity instanceof EntityFireball ++ || entity instanceof EntityWeather ++ || entity instanceof EntityTNTPrimed ++ || entity instanceof EntityEnderCrystal ++ || entity instanceof EntityFireworks ) ++ { ++ return true; ++ } ++ ++ return false; ++ } ++ ++ /** ++ * Utility method to grow an AABB without creating a new AABB or touching ++ * the pool, so we can re-use ones we have. ++ * ++ * @param target ++ * @param source ++ * @param x ++ * @param y ++ * @param z ++ */ ++ public static void growBB(AxisAlignedBB target, AxisAlignedBB source, int x, int y, int z) ++ { ++ target.a = source.a - x; ++ target.b = source.b - y; ++ target.c = source.c - z; ++ target.d = source.d + x; ++ target.e = source.e + y; ++ target.f = source.f + z; ++ } ++ ++ /** ++ * Find what entities are in range of the players in the world and set ++ * active if in range. ++ * ++ * @param world ++ */ ++ public static void activateEntities(World world) ++ { ++ SpigotTimings.entityActivationCheckTimer.startTiming(); ++ final int miscActivationRange = world.spigotConfig.miscActivationRange; ++ final int animalActivationRange = world.spigotConfig.animalActivationRange; ++ final int monsterActivationRange = world.spigotConfig.monsterActivationRange; ++ ++ int maxRange = Math.max( monsterActivationRange, animalActivationRange ); ++ maxRange = Math.max( maxRange, miscActivationRange ); ++ maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); ++ ++ for ( Entity player : new ArrayList( world.players ) ) ++ { ++ ++ player.activatedTick = MinecraftServer.currentTick; ++ growBB( maxBB, player.boundingBox, maxRange, 256, maxRange ); ++ growBB( miscBB, player.boundingBox, miscActivationRange, 256, miscActivationRange ); ++ growBB( animalBB, player.boundingBox, animalActivationRange, 256, animalActivationRange ); ++ growBB( monsterBB, player.boundingBox, monsterActivationRange, 256, monsterActivationRange ); ++ ++ int i = MathHelper.floor( maxBB.a / 16.0D ); ++ int j = MathHelper.floor( maxBB.d / 16.0D ); ++ int k = MathHelper.floor( maxBB.c / 16.0D ); ++ int l = MathHelper.floor( maxBB.f / 16.0D ); ++ ++ for ( int i1 = i; i1 <= j; ++i1 ) ++ { ++ for ( int j1 = k; j1 <= l; ++j1 ) ++ { ++ if ( world.getWorld().isChunkLoaded( i1, j1 ) ) ++ { ++ activateChunkEntities( world.getChunkAt( i1, j1 ) ); ++ } ++ } ++ } ++ } ++ SpigotTimings.entityActivationCheckTimer.stopTiming(); ++ } ++ ++ /** ++ * Checks for the activation state of all entities in this chunk. ++ * ++ * @param chunk ++ */ ++ private static void activateChunkEntities(Chunk chunk) ++ { ++ for ( List slice : chunk.entitySlices ) ++ { ++ for ( Entity entity : slice ) ++ { ++ if ( MinecraftServer.currentTick > entity.activatedTick ) ++ { ++ if ( entity.defaultActivationState ) ++ { ++ entity.activatedTick = MinecraftServer.currentTick; ++ continue; ++ } ++ switch ( entity.activationType ) ++ { ++ case 1: ++ if ( monsterBB.b( entity.boundingBox ) ) ++ { ++ entity.activatedTick = MinecraftServer.currentTick; ++ } ++ break; ++ case 2: ++ if ( animalBB.b( entity.boundingBox ) ) ++ { ++ entity.activatedTick = MinecraftServer.currentTick; ++ } ++ break; ++ case 3: ++ default: ++ if ( miscBB.b( entity.boundingBox ) ) ++ { ++ entity.activatedTick = MinecraftServer.currentTick; ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ /** ++ * If an entity is not in range, do some more checks to see if we should ++ * give it a shot. ++ * ++ * @param entity ++ * @return ++ */ ++ public static boolean checkEntityImmunities(Entity entity) ++ { ++ // quick checks. ++ if ( entity.inWater /* isInWater */ || entity.fireTicks > 0 ) ++ { ++ return true; ++ } ++ if ( !( entity instanceof EntityArrow ) ) ++ { ++ if ( !entity.onGround || entity.passenger != null ++ || entity.vehicle != null ) ++ { ++ return true; ++ } ++ } else if ( !( (EntityArrow) entity ).inGround ) ++ { ++ return true; ++ } ++ // special cases. ++ if ( entity instanceof EntityLiving ) ++ { ++ EntityLiving living = (EntityLiving) entity; ++ if ( living.attackTicks > 0 || living.hurtTicks > 0 || living.effects.size() > 0 ) ++ { ++ return true; ++ } ++ if ( entity instanceof EntityCreature && ( (EntityCreature) entity ).target != null ) ++ { ++ return true; ++ } ++ if ( entity instanceof EntityVillager && ( (EntityVillager) entity ).bY() /* Getter for first boolean */ ) ++ { ++ return true; ++ } ++ if ( entity instanceof EntityAnimal ) ++ { ++ EntityAnimal animal = (EntityAnimal) entity; ++ if ( animal.isBaby() || animal.ce() /*love*/ ) ++ { ++ return true; ++ } ++ if ( entity instanceof EntitySheep && ( (EntitySheep) entity ).isSheared() ) ++ { ++ return true; ++ } ++ } ++ } ++ return false; ++ } ++ ++ /** ++ * Checks if the entity is active for this tick. ++ * ++ * @param entity ++ * @return ++ */ ++ public static boolean checkIfActive(Entity entity) ++ { ++ SpigotTimings.checkIfActiveTimer.startTiming(); ++ boolean isActive = entity.activatedTick >= MinecraftServer.currentTick || entity.defaultActivationState; ++ ++ // Should this entity tick? ++ if ( !isActive ) ++ { ++ if ( ( MinecraftServer.currentTick - entity.activatedTick - 1 ) % 20 == 0 ) ++ { ++ // Check immunities every 20 ticks. ++ if ( checkEntityImmunities( entity ) ) ++ { ++ // Triggered some sort of immunity, give 20 full ticks before we check again. ++ entity.activatedTick = MinecraftServer.currentTick + 20; ++ } ++ isActive = true; ++ } ++ // Add a little performance juice to active entities. Skip 1/4 if not immune. ++ } else if ( !entity.defaultActivationState && entity.ticksLived % 4 == 0 && !checkEntityImmunities( entity ) ) ++ { ++ isActive = false; ++ } ++ int x = MathHelper.floor( entity.locX ); ++ int z = MathHelper.floor( entity.locZ ); ++ // Make sure not on edge of unloaded chunk ++ Chunk chunk = entity.world.getChunkIfLoaded( x >> 4, z >> 4 ); ++ if ( isActive && !( chunk != null && chunk.areNeighborsLoaded( 1 ) ) ) ++ { ++ isActive = false; ++ } ++ SpigotTimings.checkIfActiveTimer.stopTiming(); ++ return isActive; ++ } ++} +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -0,0 +0,0 @@ public class SpigotWorldConfig + mobSpawnRange = (byte) getInt( "mob-spawn-range", 4 ); + log( "Mob Spawn Range: " + mobSpawnRange ); + } ++ ++ public int animalActivationRange = 32; ++ public int monsterActivationRange = 32; ++ public int miscActivationRange = 16; ++ private void activationRange() ++ { ++ animalActivationRange = getInt( "entity-activation-range.animals", animalActivationRange ); ++ monsterActivationRange = getInt( "entity-activation-range.monsters", monsterActivationRange ); ++ miscActivationRange = getInt( "entity-activation-range.misc", miscActivationRange ); ++ log( "Entity Activation Range: An " + animalActivationRange + " / Mo " + monsterActivationRange + " / Mi " + miscActivationRange ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0017-Metrics.patch b/CraftBukkit-Patches/0017-Metrics.patch new file mode 100644 index 0000000000..caed577105 --- /dev/null +++ b/CraftBukkit-Patches/0017-Metrics.patch @@ -0,0 +1,690 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 23 Feb 2013 08:58:35 +1100 +Subject: [PATCH] Metrics + + +diff --git a/src/main/java/org/spigotmc/Metrics.java b/src/main/java/org/spigotmc/Metrics.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/org/spigotmc/Metrics.java +@@ -0,0 +0,0 @@ ++/* ++ * Copyright 2011-2013 Tyler Blair. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without modification, are ++ * permitted provided that the following conditions are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright notice, this list of ++ * conditions and the following disclaimer. ++ * ++ * 2. Redistributions in binary form must reproduce the above copyright notice, this list ++ * of conditions and the following disclaimer in the documentation and/or other materials ++ * provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ++ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR ++ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ++ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * The views and conclusions contained in the software and documentation are those of the ++ * authors and contributors and should not be interpreted as representing official policies, ++ * either expressed or implied, of anybody else. ++ */ ++package org.spigotmc; ++ ++import org.bukkit.Bukkit; ++import org.bukkit.configuration.file.YamlConfiguration; ++import org.bukkit.configuration.InvalidConfigurationException; ++import org.bukkit.plugin.Plugin; ++import org.bukkit.plugin.PluginDescriptionFile; ++import org.bukkit.scheduler.BukkitTask; ++ ++import java.io.BufferedReader; ++import java.io.File; ++import java.io.IOException; ++import java.io.InputStreamReader; ++import java.io.OutputStreamWriter; ++import java.io.UnsupportedEncodingException; ++import java.net.Proxy; ++import java.net.URL; ++import java.net.URLConnection; ++import java.net.URLEncoder; ++import java.util.Collections; ++import java.util.HashSet; ++import java.util.Iterator; ++import java.util.LinkedHashSet; ++import java.util.Set; ++import java.util.Timer; ++import java.util.TimerTask; ++import java.util.UUID; ++import java.util.concurrent.TimeUnit; ++import java.util.logging.Level; ++import net.minecraft.server.MinecraftServer; ++ ++/** ++ *

The metrics class obtains data about a plugin and submits statistics about it to the metrics backend.

++ * Public methods provided by this class:

++ * ++ * Graph createGraph(String name);
++ * void addCustomData(BukkitMetrics.Plotter plotter);
++ * void start();
++ *
++ */ ++public class Metrics { ++ ++ /** ++ * The current revision number ++ */ ++ private final static int REVISION = 6; ++ /** ++ * The base url of the metrics domain ++ */ ++ private static final String BASE_URL = "http://mcstats.org"; ++ /** ++ * The url used to report a server's status ++ */ ++ private static final String REPORT_URL = "/report/%s"; ++ /** ++ * The separator to use for custom data. This MUST NOT change unless you are hosting your own version of metrics and ++ * want to change it. ++ */ ++ private static final String CUSTOM_DATA_SEPARATOR = "~~"; ++ /** ++ * Interval of time to ping (in minutes) ++ */ ++ private static final int PING_INTERVAL = 10; ++ /** ++ * All of the custom graphs to submit to metrics ++ */ ++ private final Set graphs = Collections.synchronizedSet(new HashSet()); ++ /** ++ * The default graph, used for addCustomData when you don't want a specific graph ++ */ ++ private final Graph defaultGraph = new Graph("Default"); ++ /** ++ * The plugin configuration file ++ */ ++ private final YamlConfiguration configuration; ++ /** ++ * The plugin configuration file ++ */ ++ private final File configurationFile; ++ /** ++ * Unique server id ++ */ ++ private final String guid; ++ /** ++ * Debug mode ++ */ ++ private final boolean debug; ++ /** ++ * Lock for synchronization ++ */ ++ private final Object optOutLock = new Object(); ++ /** ++ * The scheduled task ++ */ ++ private volatile Timer task = null; ++ ++ public Metrics() throws IOException { ++ // load the config ++ configurationFile = getConfigFile(); ++ configuration = YamlConfiguration.loadConfiguration(configurationFile); ++ ++ // add some defaults ++ configuration.addDefault("opt-out", false); ++ configuration.addDefault("guid", UUID.randomUUID().toString()); ++ configuration.addDefault("debug", false); ++ ++ // Do we need to create the file? ++ if (configuration.get("guid", null) == null) { ++ configuration.options().header("http://mcstats.org").copyDefaults(true); ++ configuration.save(configurationFile); ++ } ++ ++ // Load the guid then ++ guid = configuration.getString("guid"); ++ debug = configuration.getBoolean("debug", false); ++ } ++ ++ /** ++ * Construct and create a Graph that can be used to separate specific plotters to their own graphs on the metrics ++ * website. Plotters can be added to the graph object returned. ++ * ++ * @param name The name of the graph ++ * @return Graph object created. Will never return NULL under normal circumstances unless bad parameters are given ++ */ ++ public Graph createGraph(final String name) { ++ if (name == null) { ++ throw new IllegalArgumentException("Graph name cannot be null"); ++ } ++ ++ // Construct the graph object ++ final Graph graph = new Graph(name); ++ ++ // Now we can add our graph ++ graphs.add(graph); ++ ++ // and return back ++ return graph; ++ } ++ ++ /** ++ * Add a Graph object to BukkitMetrics that represents data for the plugin that should be sent to the backend ++ * ++ * @param graph The name of the graph ++ */ ++ public void addGraph(final Graph graph) { ++ if (graph == null) { ++ throw new IllegalArgumentException("Graph cannot be null"); ++ } ++ ++ graphs.add(graph); ++ } ++ ++ /** ++ * Adds a custom data plotter to the default graph ++ * ++ * @param plotter The plotter to use to plot custom data ++ */ ++ public void addCustomData(final Plotter plotter) { ++ if (plotter == null) { ++ throw new IllegalArgumentException("Plotter cannot be null"); ++ } ++ ++ // Add the plotter to the graph o/ ++ defaultGraph.addPlotter(plotter); ++ ++ // Ensure the default graph is included in the submitted graphs ++ graphs.add(defaultGraph); ++ } ++ ++ /** ++ * Start measuring statistics. This will immediately create an async repeating task as the plugin and send the ++ * initial data to the metrics backend, and then after that it will post in increments of PING_INTERVAL * 1200 ++ * ticks. ++ * ++ * @return True if statistics measuring is running, otherwise false. ++ */ ++ public boolean start() { ++ synchronized (optOutLock) { ++ // Did we opt out? ++ if (isOptOut()) { ++ return false; ++ } ++ ++ // Is metrics already running? ++ if (task != null) { ++ return true; ++ } ++ ++ // Begin hitting the server with glorious data ++ task = new Timer("Spigot Metrics Thread", true); ++ ++ task.scheduleAtFixedRate(new TimerTask() { ++ private boolean firstPost = true; ++ ++ public void run() { ++ try { ++ // This has to be synchronized or it can collide with the disable method. ++ synchronized (optOutLock) { ++ // Disable Task, if it is running and the server owner decided to opt-out ++ if (isOptOut() && task != null) { ++ task.cancel(); ++ task = null; ++ // Tell all plotters to stop gathering information. ++ for (Graph graph : graphs) { ++ graph.onOptOut(); ++ } ++ } ++ } ++ ++ // We use the inverse of firstPost because if it is the first time we are posting, ++ // it is not a interval ping, so it evaluates to FALSE ++ // Each time thereafter it will evaluate to TRUE, i.e PING! ++ postPlugin(!firstPost); ++ ++ // After the first post we set firstPost to false ++ // Each post thereafter will be a ping ++ firstPost = false; ++ } catch (IOException e) { ++ if (debug) { ++ Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage()); ++ } ++ } ++ } ++ }, 0, TimeUnit.MINUTES.toMillis(PING_INTERVAL)); ++ ++ return true; ++ } ++ } ++ ++ /** ++ * Has the server owner denied plugin metrics? ++ * ++ * @return true if metrics should be opted out of it ++ */ ++ public boolean isOptOut() { ++ synchronized (optOutLock) { ++ try { ++ // Reload the metrics file ++ configuration.load(getConfigFile()); ++ } catch (IOException ex) { ++ if (debug) { ++ Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage()); ++ } ++ return true; ++ } catch (InvalidConfigurationException ex) { ++ if (debug) { ++ Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage()); ++ } ++ return true; ++ } ++ return configuration.getBoolean("opt-out", false); ++ } ++ } ++ ++ /** ++ * Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task. ++ * ++ * @throws java.io.IOException ++ */ ++ public void enable() throws IOException { ++ // This has to be synchronized or it can collide with the check in the task. ++ synchronized (optOutLock) { ++ // Check if the server owner has already set opt-out, if not, set it. ++ if (isOptOut()) { ++ configuration.set("opt-out", false); ++ configuration.save(configurationFile); ++ } ++ ++ // Enable Task, if it is not running ++ if (task == null) { ++ start(); ++ } ++ } ++ } ++ ++ /** ++ * Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task. ++ * ++ * @throws java.io.IOException ++ */ ++ public void disable() throws IOException { ++ // This has to be synchronized or it can collide with the check in the task. ++ synchronized (optOutLock) { ++ // Check if the server owner has already set opt-out, if not, set it. ++ if (!isOptOut()) { ++ configuration.set("opt-out", true); ++ configuration.save(configurationFile); ++ } ++ ++ // Disable Task, if it is running ++ if (task != null) { ++ task.cancel(); ++ task = null; ++ } ++ } ++ } ++ ++ /** ++ * Gets the File object of the config file that should be used to store data such as the GUID and opt-out status ++ * ++ * @return the File object for the config file ++ */ ++ public File getConfigFile() { ++ // I believe the easiest way to get the base folder (e.g craftbukkit set via -P) for plugins to use ++ // is to abuse the plugin object we already have ++ // plugin.getDataFolder() => base/plugins/PluginA/ ++ // pluginsFolder => base/plugins/ ++ // The base is not necessarily relative to the startup directory. ++ // File pluginsFolder = plugin.getDataFolder().getParentFile(); ++ ++ // return => base/plugins/PluginMetrics/config.yml ++ return new File(new File((File) MinecraftServer.getServer().options.valueOf("plugins"), "PluginMetrics"), "config.yml"); ++ } ++ ++ /** ++ * Generic method that posts a plugin to the metrics website ++ */ ++ private void postPlugin(final boolean isPing) throws IOException { ++ // Server software specific section ++ String pluginName = "Spigot"; ++ boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled ++ String pluginVersion = (Metrics.class.getPackage().getImplementationVersion() != null) ? Metrics.class.getPackage().getImplementationVersion() : "unknown"; ++ String serverVersion = Bukkit.getVersion(); ++ int playersOnline = Bukkit.getServer().getOnlinePlayers().size(); ++ ++ // END server software specific section -- all code below does not use any code outside of this class / Java ++ ++ // Construct the post data ++ final StringBuilder data = new StringBuilder(); ++ ++ // The plugin's description file containg all of the plugin data such as name, version, author, etc ++ data.append(encode("guid")).append('=').append(encode(guid)); ++ encodeDataPair(data, "version", pluginVersion); ++ encodeDataPair(data, "server", serverVersion); ++ encodeDataPair(data, "players", Integer.toString(playersOnline)); ++ encodeDataPair(data, "revision", String.valueOf(REVISION)); ++ ++ // New data as of R6 ++ String osname = System.getProperty("os.name"); ++ String osarch = System.getProperty("os.arch"); ++ String osversion = System.getProperty("os.version"); ++ String java_version = System.getProperty("java.version"); ++ int coreCount = Runtime.getRuntime().availableProcessors(); ++ ++ // normalize os arch .. amd64 -> x86_64 ++ if (osarch.equals("amd64")) { ++ osarch = "x86_64"; ++ } ++ ++ encodeDataPair(data, "osname", osname); ++ encodeDataPair(data, "osarch", osarch); ++ encodeDataPair(data, "osversion", osversion); ++ encodeDataPair(data, "cores", Integer.toString(coreCount)); ++ encodeDataPair(data, "online-mode", Boolean.toString(onlineMode)); ++ encodeDataPair(data, "java_version", java_version); ++ ++ // If we're pinging, append it ++ if (isPing) { ++ encodeDataPair(data, "ping", "true"); ++ } ++ ++ // Acquire a lock on the graphs, which lets us make the assumption we also lock everything ++ // inside of the graph (e.g plotters) ++ synchronized (graphs) { ++ final Iterator iter = graphs.iterator(); ++ ++ while (iter.hasNext()) { ++ final Graph graph = iter.next(); ++ ++ for (Plotter plotter : graph.getPlotters()) { ++ // The key name to send to the metrics server ++ // The format is C-GRAPHNAME-PLOTTERNAME where separator - is defined at the top ++ // Legacy (R4) submitters use the format Custom%s, or CustomPLOTTERNAME ++ final String key = String.format("C%s%s%s%s", CUSTOM_DATA_SEPARATOR, graph.getName(), CUSTOM_DATA_SEPARATOR, plotter.getColumnName()); ++ ++ // The value to send, which for the foreseeable future is just the string ++ // value of plotter.getValue() ++ final String value = Integer.toString(plotter.getValue()); ++ ++ // Add it to the http post data :) ++ encodeDataPair(data, key, value); ++ } ++ } ++ } ++ ++ // Create the url ++ URL url = new URL(BASE_URL + String.format(REPORT_URL, encode(pluginName))); ++ ++ // Connect to the website ++ URLConnection connection; ++ ++ // Mineshafter creates a socks proxy, so we can safely bypass it ++ // It does not reroute POST requests so we need to go around it ++ if (isMineshafterPresent()) { ++ connection = url.openConnection(Proxy.NO_PROXY); ++ } else { ++ connection = url.openConnection(); ++ } ++ ++ connection.setDoOutput(true); ++ ++ // Write the data ++ final OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream()); ++ writer.write(data.toString()); ++ writer.flush(); ++ ++ // Now read the response ++ final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); ++ final String response = reader.readLine(); ++ ++ // close resources ++ writer.close(); ++ reader.close(); ++ ++ if (response == null || response.startsWith("ERR")) { ++ throw new IOException(response); //Throw the exception ++ } else { ++ // Is this the first update this hour? ++ if (response.contains("OK This is your first update this hour")) { ++ synchronized (graphs) { ++ final Iterator iter = graphs.iterator(); ++ ++ while (iter.hasNext()) { ++ final Graph graph = iter.next(); ++ ++ for (Plotter plotter : graph.getPlotters()) { ++ plotter.reset(); ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ /** ++ * Check if mineshafter is present. If it is, we need to bypass it to send POST requests ++ * ++ * @return true if mineshafter is installed on the server ++ */ ++ private boolean isMineshafterPresent() { ++ try { ++ Class.forName("mineshafter.MineServer"); ++ return true; ++ } catch (Exception e) { ++ return false; ++ } ++ } ++ ++ /** ++ *

Encode a key/value data pair to be used in a HTTP post request. This INCLUDES a & so the first key/value pair ++ * MUST be included manually, e.g:

++ * ++ * StringBuffer data = new StringBuffer(); ++ * data.append(encode("guid")).append('=').append(encode(guid)); ++ * encodeDataPair(data, "version", description.getVersion()); ++ * ++ * ++ * @param buffer the stringbuilder to append the data pair onto ++ * @param key the key value ++ * @param value the value ++ */ ++ private static void encodeDataPair(final StringBuilder buffer, final String key, final String value) throws UnsupportedEncodingException { ++ buffer.append('&').append(encode(key)).append('=').append(encode(value)); ++ } ++ ++ /** ++ * Encode text as UTF-8 ++ * ++ * @param text the text to encode ++ * @return the encoded text, as UTF-8 ++ */ ++ private static String encode(final String text) throws UnsupportedEncodingException { ++ return URLEncoder.encode(text, "UTF-8"); ++ } ++ ++ /** ++ * Represents a custom graph on the website ++ */ ++ public static class Graph { ++ ++ /** ++ * The graph's name, alphanumeric and spaces only :) If it does not comply to the above when submitted, it is ++ * rejected ++ */ ++ private final String name; ++ /** ++ * The set of plotters that are contained within this graph ++ */ ++ private final Set plotters = new LinkedHashSet(); ++ ++ private Graph(final String name) { ++ this.name = name; ++ } ++ ++ /** ++ * Gets the graph's name ++ * ++ * @return the Graph's name ++ */ ++ public String getName() { ++ return name; ++ } ++ ++ /** ++ * Add a plotter to the graph, which will be used to plot entries ++ * ++ * @param plotter the plotter to add to the graph ++ */ ++ public void addPlotter(final Plotter plotter) { ++ plotters.add(plotter); ++ } ++ ++ /** ++ * Remove a plotter from the graph ++ * ++ * @param plotter the plotter to remove from the graph ++ */ ++ public void removePlotter(final Plotter plotter) { ++ plotters.remove(plotter); ++ } ++ ++ /** ++ * Gets an unmodifiable set of the plotter objects in the graph ++ * ++ * @return an unmodifiable {@link java.util.Set} of the plotter objects ++ */ ++ public Set getPlotters() { ++ return Collections.unmodifiableSet(plotters); ++ } ++ ++ @Override ++ public int hashCode() { ++ return name.hashCode(); ++ } ++ ++ @Override ++ public boolean equals(final Object object) { ++ if (!(object instanceof Graph)) { ++ return false; ++ } ++ ++ final Graph graph = (Graph) object; ++ return graph.name.equals(name); ++ } ++ ++ /** ++ * Called when the server owner decides to opt-out of BukkitMetrics while the server is running. ++ */ ++ protected void onOptOut() { ++ } ++ } ++ ++ /** ++ * Interface used to collect custom data for a plugin ++ */ ++ public static abstract class Plotter { ++ ++ /** ++ * The plot's name ++ */ ++ private final String name; ++ ++ /** ++ * Construct a plotter with the default plot name ++ */ ++ public Plotter() { ++ this("Default"); ++ } ++ ++ /** ++ * Construct a plotter with a specific plot name ++ * ++ * @param name the name of the plotter to use, which will show up on the website ++ */ ++ public Plotter(final String name) { ++ this.name = name; ++ } ++ ++ /** ++ * Get the current value for the plotted point. Since this function defers to an external function it may or may ++ * not return immediately thus cannot be guaranteed to be thread friendly or safe. This function can be called ++ * from any thread so care should be taken when accessing resources that need to be synchronized. ++ * ++ * @return the current value for the point to be plotted. ++ */ ++ public abstract int getValue(); ++ ++ /** ++ * Get the column name for the plotted point ++ * ++ * @return the plotted point's column name ++ */ ++ public String getColumnName() { ++ return name; ++ } ++ ++ /** ++ * Called after the website graphs have been updated ++ */ ++ public void reset() { ++ } ++ ++ @Override ++ public int hashCode() { ++ return getColumnName().hashCode(); ++ } ++ ++ @Override ++ public boolean equals(final Object object) { ++ if (!(object instanceof Plotter)) { ++ return false; ++ } ++ ++ final Plotter plotter = (Plotter) object; ++ return plotter.name.equals(name) && plotter.getValue() == getValue(); ++ } ++ } ++} +\ No newline at end of file +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -0,0 +0,0 @@ public class SpigotConfig + static int version; + static Map commands; + /*========================================================================*/ ++ private static Metrics metrics; + + public static void init() + { +@@ -0,0 +0,0 @@ public class SpigotConfig + { + MinecraftServer.getServer().server.getCommandMap().register( entry.getKey(), "Spigot", entry.getValue() ); + } ++ ++ if ( metrics == null ) ++ { ++ try ++ { ++ metrics = new Metrics(); ++ metrics.start(); ++ } catch ( IOException ex ) ++ { ++ Bukkit.getServer().getLogger().log( Level.SEVERE, "Could not start metrics service", ex ); ++ } ++ } + } + + static void readConfig(Class clazz, Object instance) +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0018-PlayerItemDamageEvent.patch b/CraftBukkit-Patches/0018-PlayerItemDamageEvent.patch new file mode 100644 index 0000000000..dcfd0b823c --- /dev/null +++ b/CraftBukkit-Patches/0018-PlayerItemDamageEvent.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Mon, 4 Mar 2013 18:45:52 +1100 +Subject: [PATCH] PlayerItemDamageEvent + + +diff --git a/src/main/java/net/minecraft/server/ItemStack.java b/src/main/java/net/minecraft/server/ItemStack.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/ItemStack.java ++++ b/src/main/java/net/minecraft/server/ItemStack.java +@@ -0,0 +0,0 @@ public final class ItemStack { + return this.item.getMaxDurability(); + } + ++ // Spigot start + public boolean isDamaged(int i, Random random) { ++ return isDamaged(i, random, null); ++ } ++ ++ public boolean isDamaged(int i, Random random, EntityLiving entityliving) { ++ // Spigot end + if (!this.g()) { + return false; + } else { +@@ -0,0 +0,0 @@ public final class ItemStack { + } + + i -= k; +- if (i <= 0) { ++ // Spigot start ++ if (entityliving instanceof EntityPlayer) { ++ org.bukkit.craftbukkit.inventory.CraftItemStack item = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(this); ++ org.bukkit.event.player.PlayerItemDamageEvent event = new org.bukkit.event.player.PlayerItemDamageEvent((org.bukkit.entity.Player) entityliving.getBukkitEntity(), item, i); ++ org.bukkit.Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) return false; ++ i = event.getDamage(); ++ } ++ // Spigot end ++ if (i <= 0 ) { + return false; + } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0019-Faster-UUID-for-entities.patch b/CraftBukkit-Patches/0019-Faster-UUID-for-entities.patch new file mode 100644 index 0000000000..dd5fbdb643 --- /dev/null +++ b/CraftBukkit-Patches/0019-Faster-UUID-for-entities.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 17 Mar 2013 19:02:50 +1100 +Subject: [PATCH] Faster UUID for entities + +It is overkill to create a new SecureRandom on each entity create and then use it to make a new Entity ID for every entity instance created. Instead we will just use a pseudo random UUID based off the random instance we already have. + +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -0,0 +0,0 @@ public abstract class Entity { + this.random = new Random(); + this.maxFireTicks = 1; + this.justCreated = true; +- this.uniqueID = UUID.randomUUID(); ++ this.uniqueID = new UUID(random.nextLong(), random.nextLong()); // Spigot + this.as = EnumEntitySize.SIZE_2; + this.world = world; + this.setPosition(0.0D, 0.0D, 0.0D); +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0020-Prevent-NPE-in-CraftSign.patch b/CraftBukkit-Patches/0020-Prevent-NPE-in-CraftSign.patch new file mode 100644 index 0000000000..2224c7b054 --- /dev/null +++ b/CraftBukkit-Patches/0020-Prevent-NPE-in-CraftSign.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Mon, 18 Mar 2013 20:01:44 +1100 +Subject: [PATCH] Prevent NPE in CraftSign + +This commit prevents the constructor of CraftSign throwing an NPE when it cannot get the sign tile entity. Instead it will fallback to a 4 empty lined sign, and not try to do anything to those lines on .update(). + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java +@@ -0,0 +0,0 @@ public class CraftSign extends CraftBlockState implements Sign { + + CraftWorld world = (CraftWorld) block.getWorld(); + sign = (TileEntitySign) world.getTileEntityAt(getX(), getY(), getZ()); ++ // Spigot start ++ if (sign == null) { ++ lines = new String[]{"", "", "", ""}; ++ return; ++ } ++ // Spigot end + lines = new String[sign.lines.length]; + System.arraycopy(sign.lines, 0, lines, 0, lines.length); + } +@@ -0,0 +0,0 @@ public class CraftSign extends CraftBlockState implements Sign { + public boolean update(boolean force, boolean applyPhysics) { + boolean result = super.update(force, applyPhysics); + +- if (result) { ++ if (result && sign != null) { // Spigot, add null check + sign.lines = sanitizeLines(lines); + sign.update(); + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0021-Entity-Tracking-Ranges.patch b/CraftBukkit-Patches/0021-Entity-Tracking-Ranges.patch new file mode 100644 index 0000000000..409ca0f9f5 --- /dev/null +++ b/CraftBukkit-Patches/0021-Entity-Tracking-Ranges.patch @@ -0,0 +1,107 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 20 Feb 2013 11:58:47 -0500 +Subject: [PATCH] Entity Tracking Ranges + +This will let you configure how far to track entities in range from players, so that the entity does not render on the client if out of this range. +This has multiple benefits: + +1) Less bandwidth. Not sending update packets for entities that are not even close to a player, or even close enough to clearly see. +2) Less lag by maps in item frames - Default range is 160 blocks... Many players can track that item frame and cause lag and not even see it. +3) Less lag in general - Less work for the server to do +4) Less client lag - Not trying to render distant item frames and paintings and entities will reduce entity count on the client, which is major for shop/town worlds which may use tons of item frames. + +diff --git a/src/main/java/net/minecraft/server/EntityTracker.java b/src/main/java/net/minecraft/server/EntityTracker.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityTracker.java ++++ b/src/main/java/net/minecraft/server/EntityTracker.java +@@ -0,0 +0,0 @@ public class EntityTracker { + + public void addEntity(Entity entity, int i, int j, boolean flag) { + org.spigotmc.AsyncCatcher.catchOp( "entity track"); // Spigot ++ i = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, i); // Spigot + if (i > this.e) { + i = this.e; + } +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -0,0 +0,0 @@ public class SpigotWorldConfig + miscActivationRange = getInt( "entity-activation-range.misc", miscActivationRange ); + log( "Entity Activation Range: An " + animalActivationRange + " / Mo " + monsterActivationRange + " / Mi " + miscActivationRange ); + } ++ ++ public int playerTrackingRange = 48; ++ public int animalTrackingRange = 48; ++ public int monsterTrackingRange = 48; ++ public int miscTrackingRange = 32; ++ public int otherTrackingRange = 64; ++ private void trackingRange() ++ { ++ playerTrackingRange = getInt( "entity-tracking-range.players", playerTrackingRange ); ++ animalTrackingRange = getInt( "entity-tracking-range.animals", animalTrackingRange ); ++ monsterTrackingRange = getInt( "entity-tracking-range.monsters", monsterTrackingRange ); ++ miscTrackingRange = getInt( "entity-tracking-range.misc", miscTrackingRange ); ++ otherTrackingRange = getInt( "entity-tracking-range.other", otherTrackingRange ); ++ log( "Entity Tracking Range: Pl " + playerTrackingRange + " / An " + animalTrackingRange + " / Mo " + monsterTrackingRange + " / Mi " + miscTrackingRange + " / Other " + otherTrackingRange ); ++ } + } +diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/org/spigotmc/TrackingRange.java +@@ -0,0 +0,0 @@ ++package org.spigotmc; ++ ++import net.minecraft.server.Entity; ++import net.minecraft.server.EntityExperienceOrb; ++import net.minecraft.server.EntityGhast; ++import net.minecraft.server.EntityItem; ++import net.minecraft.server.EntityItemFrame; ++import net.minecraft.server.EntityPainting; ++import net.minecraft.server.EntityPlayer; ++ ++public class TrackingRange ++{ ++ ++ /** ++ * Gets the range an entity should be 'tracked' by players and visible in ++ * the client. ++ * ++ * @param entity ++ * @param defaultRange Default range defined by Mojang ++ * @return ++ */ ++ public static int getEntityTrackingRange(Entity entity, int defaultRange) ++ { ++ SpigotWorldConfig config = entity.world.spigotConfig; ++ if ( entity instanceof EntityPlayer ) ++ { ++ return config.playerTrackingRange; ++ } else if ( entity.activationType == 1 ) ++ { ++ return config.monsterTrackingRange; ++ } else if ( entity instanceof EntityGhast ) ++ { ++ if ( config.monsterTrackingRange > config.monsterActivationRange ) ++ { ++ return config.monsterTrackingRange; ++ } else ++ { ++ return config.monsterActivationRange; ++ } ++ } else if ( entity.activationType == 2 ) ++ { ++ return config.animalTrackingRange; ++ } else if ( entity instanceof EntityItemFrame || entity instanceof EntityPainting || entity instanceof EntityItem || entity instanceof EntityExperienceOrb ) ++ { ++ return config.miscTrackingRange; ++ } else ++ { ++ return config.otherTrackingRange; ++ } ++ } ++} +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0022-Limit-Custom-Map-Rendering.patch b/CraftBukkit-Patches/0022-Limit-Custom-Map-Rendering.patch new file mode 100644 index 0000000000..e3e034aeee --- /dev/null +++ b/CraftBukkit-Patches/0022-Limit-Custom-Map-Rendering.patch @@ -0,0 +1,72 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 23 Mar 2013 19:08:41 +1100 +Subject: [PATCH] Limit Custom Map Rendering + +The default CraftBukkit render sequence for maps is ridiculously slow. By only using it when a custom renderer has been added (rarely in most cases), we can fallback to the Vanilla renderer for general usage. This leads to a much higher effiency overall, especially if no plugins are rendering such maps. + +diff --git a/src/main/java/net/minecraft/server/WorldMapHumanTracker.java b/src/main/java/net/minecraft/server/WorldMapHumanTracker.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/WorldMapHumanTracker.java ++++ b/src/main/java/net/minecraft/server/WorldMapHumanTracker.java +@@ -0,0 +0,0 @@ public class WorldMapHumanTracker { + int i; + int j; + +- org.bukkit.craftbukkit.map.RenderData render = this.worldMap.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) trackee.getBukkitEntity()); // CraftBukkit ++ // Spigot start ++ boolean custom = this.worldMap.mapView.renderers.size() > 1 || !(this.worldMap.mapView.renderers.get(0) instanceof org.bukkit.craftbukkit.map.CraftMapRenderer); ++ org.bukkit.craftbukkit.map.RenderData render = (custom) ? this.worldMap.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) trackee.getBukkitEntity()) : null; // CraftBukkit + + if (--this.g < 0) { + this.g = 4; +- abyte = new byte[render.cursors.size() * 3 + 1]; // CraftBukkit ++ abyte = new byte[((custom) ? render.cursors.size() : this.worldMap.decorations.size()) * 3 + 1]; // CraftBukkit + abyte[0] = 1; + i = 0; + + // CraftBukkit start +- for (i = 0; i < render.cursors.size(); ++i) { +- org.bukkit.map.MapCursor cursor = render.cursors.get(i); +- if (!cursor.isVisible()) continue; + +- abyte[i * 3 + 1] = (byte) (cursor.getRawType() << 4 | cursor.getDirection() & 15); +- abyte[i * 3 + 2] = (byte) cursor.getX(); +- abyte[i * 3 + 3] = (byte) cursor.getY(); ++ // Spigot start ++ for (Iterator iterator = ((custom) ? render.cursors.iterator() : this.worldMap.decorations.values().iterator()); iterator.hasNext(); ++i) { ++ org.bukkit.map.MapCursor cursor = (custom) ? (org.bukkit.map.MapCursor) iterator.next() : null; ++ if (cursor != null && !cursor.isVisible()) continue; ++ WorldMapDecoration deco = (custom) ? null : (WorldMapDecoration) iterator.next(); ++ ++ abyte[i * 3 + 1] = (byte) (((custom) ? cursor.getRawType() : deco.type) << 4 | ((custom) ? cursor.getDirection() : deco.rotation) & 15); ++ abyte[i * 3 + 2] = (byte) ((custom) ? cursor.getX() : deco.locX); ++ abyte[i * 3 + 3] = (byte) ((custom) ? cursor.getY() : deco.locY); + } ++ // Spigot end + // CraftBukkit end + + boolean flag = !itemstack.A(); +@@ -0,0 +0,0 @@ public class WorldMapHumanTracker { + abyte1[2] = (byte) j; + + for (int i1 = 0; i1 < abyte1.length - 3; ++i1) { +- abyte1[i1 + 3] = render.buffer[(i1 + j) * 128 + i]; // CraftBukkit ++ abyte1[i1 + 3] = ((custom) ? render.buffer : this.worldMap.colors)[(i1 + j) * 128 + i]; + } + + this.c[i] = -1; +diff --git a/src/main/java/org/bukkit/craftbukkit/map/CraftMapView.java b/src/main/java/org/bukkit/craftbukkit/map/CraftMapView.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/map/CraftMapView.java ++++ b/src/main/java/org/bukkit/craftbukkit/map/CraftMapView.java +@@ -0,0 +0,0 @@ import org.bukkit.map.MapView; + public final class CraftMapView implements MapView { + + private final Map renderCache = new HashMap(); +- private final List renderers = new ArrayList(); ++ public final List renderers = new ArrayList(); // Spigot + private final Map> canvases = new HashMap>(); + protected final WorldMap worldMap; + +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0023-Thread-Naming-and-Tweaks.patch b/CraftBukkit-Patches/0023-Thread-Naming-and-Tweaks.patch new file mode 100644 index 0000000000..70cf45e6cb --- /dev/null +++ b/CraftBukkit-Patches/0023-Thread-Naming-and-Tweaks.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Tue, 23 Apr 2013 11:50:27 +1000 +Subject: [PATCH] Thread Naming and Tweaks + +Removes the sleep forever thread and adds useful names for debugging to all staged thread files. + +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { + */ + private final ConcurrentHashMap runners = new ConcurrentHashMap(); + private volatile int currentTick = -1; +- private final Executor executor = Executors.newCachedThreadPool(); ++ 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 static final int RECENT_TICKS; +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0024-Close-Unloaded-Save-Files.patch b/CraftBukkit-Patches/0024-Close-Unloaded-Save-Files.patch new file mode 100644 index 0000000000..72f5fcff5b --- /dev/null +++ b/CraftBukkit-Patches/0024-Close-Unloaded-Save-Files.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Antony Riley +Date: Wed, 27 Mar 2013 01:41:54 +0200 +Subject: [PATCH] Close Unloaded Save Files + + +diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/RegionFileCache.java ++++ b/src/main/java/net/minecraft/server/RegionFileCache.java +@@ -0,0 +0,0 @@ import java.util.Map; + + public class RegionFileCache { + +- private static final Map a = new HashMap(); ++ public static final Map a = new HashMap(); // CraftBukkit - private -> public + + public static synchronized RegionFile a(File file1, int i, int j) { + File file2 = new File(file1, "region"); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -0,0 +0,0 @@ import net.minecraft.server.MinecraftServer; + import net.minecraft.server.MobEffectList; + import net.minecraft.server.PropertyManager; + import net.minecraft.server.ServerCommand; ++import net.minecraft.server.RegionFile; ++import net.minecraft.server.RegionFileCache; + import net.minecraft.server.ServerNBTManager; + import net.minecraft.server.WorldLoaderServer; + import net.minecraft.server.WorldManager; +@@ -0,0 +0,0 @@ public final class CraftServer implements Server { + worlds.remove(world.getName().toLowerCase()); + console.worlds.remove(console.worlds.indexOf(handle)); + ++ File parentFolder = world.getWorldFolder().getAbsoluteFile(); ++ ++ // Synchronized because access to RegionFileCache.a is guarded by this lock. ++ synchronized (RegionFileCache.class) { ++ // RegionFileCache.a should be RegionFileCache.cache ++ Iterator> i = RegionFileCache.a.entrySet().iterator(); ++ while(i.hasNext()) { ++ Map.Entry entry = i.next(); ++ File child = entry.getKey().getAbsoluteFile(); ++ while (child != null) { ++ if (child.equals(parentFolder)) { ++ i.remove(); ++ try { ++ entry.getValue().c(); // Should be RegionFile.close(); ++ } catch (IOException ex) { ++ getLogger().log(Level.SEVERE, null, ex); ++ } ++ break; ++ } ++ child = child.getParentFile(); ++ } ++ } ++ } ++ + return true; + } + +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0025-Remove-o-Option.patch b/CraftBukkit-Patches/0025-Remove-o-Option.patch new file mode 100644 index 0000000000..88691033e0 --- /dev/null +++ b/CraftBukkit-Patches/0025-Remove-o-Option.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 19 May 2013 18:29:48 +1000 +Subject: [PATCH] Remove -o Option + +Serves no purpose other than to confuse users. + +diff --git a/src/main/java/net/minecraft/server/PropertyManager.java b/src/main/java/net/minecraft/server/PropertyManager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PropertyManager.java ++++ b/src/main/java/net/minecraft/server/PropertyManager.java +@@ -0,0 +0,0 @@ public class PropertyManager { + } + + private T getOverride(String name, T value) { +- if ((this.options != null) && (this.options.has(name))) { ++ if ((this.options != null) && (this.options.has(name)) && !name.equals( "online-mode")) { // Spigot + return (T) this.options.valueOf(name); + } + +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0026-Recipe-Deconstruction.patch b/CraftBukkit-Patches/0026-Recipe-Deconstruction.patch new file mode 100644 index 0000000000..27f11d4517 --- /dev/null +++ b/CraftBukkit-Patches/0026-Recipe-Deconstruction.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 1 Jun 2013 16:34:38 +1000 +Subject: [PATCH] Recipe Deconstruction + +Some non API methods contributed by Asphodan to allow recipe deconstruction. + +diff --git a/src/main/java/net/minecraft/server/IRecipe.java b/src/main/java/net/minecraft/server/IRecipe.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/IRecipe.java ++++ b/src/main/java/net/minecraft/server/IRecipe.java +@@ -0,0 +0,0 @@ public interface IRecipe { + ItemStack b(); + + org.bukkit.inventory.Recipe toBukkitRecipe(); // CraftBukkit ++ ++ java.util.List getIngredients(); // Spigot + } +diff --git a/src/main/java/net/minecraft/server/ShapedRecipes.java b/src/main/java/net/minecraft/server/ShapedRecipes.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/ShapedRecipes.java ++++ b/src/main/java/net/minecraft/server/ShapedRecipes.java +@@ -0,0 +0,0 @@ public class ShapedRecipes implements IRecipe { + private int width; + private int height; + private ItemStack[] items; +- private ItemStack result; ++ public ItemStack result; // Spigot + private boolean e; + + public ShapedRecipes(int i, int j, ItemStack[] aitemstack, ItemStack itemstack) { +@@ -0,0 +0,0 @@ public class ShapedRecipes implements IRecipe { + this.e = true; + return this; + } ++ ++ // Spigot start ++ public java.util.List getIngredients() ++ { ++ return java.util.Arrays.asList( items ); ++ } ++ // Spigot end + } +diff --git a/src/main/java/net/minecraft/server/ShapelessRecipes.java b/src/main/java/net/minecraft/server/ShapelessRecipes.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/ShapelessRecipes.java ++++ b/src/main/java/net/minecraft/server/ShapelessRecipes.java +@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.inventory.CraftShapelessRecipe; + + public class ShapelessRecipes implements IRecipe { + +- private final ItemStack result; ++ public final ItemStack result; // Spigot + private final List ingredients; + + public ShapelessRecipes(ItemStack itemstack, List list) { +@@ -0,0 +0,0 @@ public class ShapelessRecipes implements IRecipe { + public int a() { + return this.ingredients.size(); + } ++ ++ // Spigot start ++ public java.util.List getIngredients() ++ { ++ return java.util.Collections.unmodifiableList( ingredients ); ++ } ++ // Spigot end + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0027-Implement-Arrow-API.patch b/CraftBukkit-Patches/0027-Implement-Arrow-API.patch new file mode 100644 index 0000000000..338f1c8484 --- /dev/null +++ b/CraftBukkit-Patches/0027-Implement-Arrow-API.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 2 Jun 2013 15:16:05 +1000 +Subject: [PATCH] Implement Arrow API + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java +@@ -0,0 +0,0 @@ public class CraftArrow extends AbstractProjectile implements Arrow { + // Spigot start + private final Arrow.Spigot spigot = new Arrow.Spigot() + { ++ @Override ++ public double getDamage() ++ { ++ return getHandle().e(); ++ } ++ ++ @Override ++ public void setDamage(double damage) ++ { ++ getHandle().b( damage ); ++ } + }; + + public Arrow.Spigot spigot() +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0028-Hopper-Customisations.patch b/CraftBukkit-Patches/0028-Hopper-Customisations.patch new file mode 100644 index 0000000000..c77306d9e6 --- /dev/null +++ b/CraftBukkit-Patches/0028-Hopper-Customisations.patch @@ -0,0 +1,131 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: erocs +Date: Sun, 8 Sep 2013 12:06:15 -0700 +Subject: [PATCH] Hopper Customisations + +Allows editing hopper cooldowns and amount transferred per tick. + +diff --git a/src/main/java/net/minecraft/server/TileEntityHopper.java b/src/main/java/net/minecraft/server/TileEntityHopper.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/TileEntityHopper.java ++++ b/src/main/java/net/minecraft/server/TileEntityHopper.java +@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntity implements IHopper { + } + + if (flag) { +- this.c(8); ++ this.c(world.spigotConfig.hopperTransfer); // Spigot + this.update(); + return true; + } + } + ++ // Spigot start ++ if ( !this.j() ) ++ { ++ this.c( world.spigotConfig.hopperCheck ); ++ } ++ // Spigot end + return false; + } else { + return false; +@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntity implements IHopper { + if (this.getItem(j) != null) { + ItemStack itemstack = this.getItem(j).cloneItemStack(); + // CraftBukkit start - Call event when pushing items into other inventories +- CraftItemStack oitemstack = CraftItemStack.asCraftMirror(this.splitStack(j, 1)); ++ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(this.splitStack(j, world.spigotConfig.hopperAmount)); // Spigot + + Inventory destinationInventory; + // Have to special case large chests as they work oddly +@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntity implements IHopper { + this.getWorld().getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + this.setItem(j, itemstack); +- this.c(8); // Delay hopper checks ++ this.c(world.spigotConfig.hopperTransfer); // Spigot + return false; + } ++ int origCount = event.getItem().getAmount(); // Spigot + ItemStack itemstack1 = addItem(iinventory, CraftItemStack.asNMSCopy(event.getItem()), i); +- + if (itemstack1 == null || itemstack1.count == 0) { + if (event.getItem().equals(oitemstack)) { + iinventory.update(); +@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntity implements IHopper { + // CraftBukkit end + return true; + } +- ++ itemstack.count -= origCount - itemstack1.count; // Spigot + this.setItem(j, itemstack); + } + } +@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntity implements IHopper { + if (itemstack != null && canTakeItemFromInventory(iinventory, itemstack, i, j)) { + ItemStack itemstack1 = itemstack.cloneItemStack(); + // CraftBukkit start - Call event on collection of items from inventories into the hopper +- CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.splitStack(i, 1)); ++ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.splitStack(i, ihopper.getWorld().spigotConfig.hopperAmount)); // Spigot + + Inventory sourceInventory; + // Have to special case large chests as they work oddly +@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntity implements IHopper { + iinventory.setItem(i, itemstack1); + + if (ihopper instanceof TileEntityHopper) { +- ((TileEntityHopper) ihopper).c(8); // Delay hopper checks ++ ((TileEntityHopper) ihopper).c(ihopper.getWorld().spigotConfig.hopperTransfer); // Spigot + } else if (ihopper instanceof EntityMinecartHopper) { +- ((EntityMinecartHopper) ihopper).l(4); // Delay hopper minecart checks ++ ((EntityMinecartHopper) ihopper).l(ihopper.getWorld().spigotConfig.hopperTransfer / 2); // Spigot + } + + return false; + } ++ int origCount = event.getItem().getAmount(); // Spigot + ItemStack itemstack2 = addItem(ihopper, CraftItemStack.asNMSCopy(event.getItem()), -1); + + if (itemstack2 == null || itemstack2.count == 0) { +@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntity implements IHopper { + + return true; + } ++ itemstack1.count -= origCount - itemstack2.count; // Spigot + + iinventory.setItem(i, itemstack1); + } +@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntity implements IHopper { + + if (flag) { + if (iinventory instanceof TileEntityHopper) { +- ((TileEntityHopper) iinventory).c(8); ++ ((TileEntityHopper) iinventory).c(((TileEntityHopper) iinventory).world.spigotConfig.hopperTransfer); // Spigot + iinventory.update(); + } + +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -0,0 +0,0 @@ public class SpigotWorldConfig + otherTrackingRange = getInt( "entity-tracking-range.other", otherTrackingRange ); + log( "Entity Tracking Range: Pl " + playerTrackingRange + " / An " + animalTrackingRange + " / Mo " + monsterTrackingRange + " / Mi " + miscTrackingRange + " / Other " + otherTrackingRange ); + } ++ ++ public int hopperTransfer; ++ public int hopperCheck; ++ public int hopperAmount; ++ private void hoppers() ++ { ++ // Set the tick delay between hopper item movements ++ hopperTransfer = getInt( "ticks-per.hopper-transfer", 8 ); ++ // Set the tick delay between checking for items after the associated ++ // container is empty. Default to the hopperTransfer value to prevent ++ // hopper sorting machines from becoming out of sync. ++ hopperCheck = getInt( "ticks-per.hopper-check", hopperTransfer ); ++ hopperAmount = getInt( "hopper-amount", 1 ); ++ log( "Hopper Transfer: " + hopperTransfer + " Hopper Check: " + hopperCheck + " Hopper Amount: " + hopperAmount ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0029-Prevent-Shutdown-Hang.patch b/CraftBukkit-Patches/0029-Prevent-Shutdown-Hang.patch new file mode 100644 index 0000000000..9c21a6d2f8 --- /dev/null +++ b/CraftBukkit-Patches/0029-Prevent-Shutdown-Hang.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Tue, 11 Jun 2013 11:54:32 +1000 +Subject: [PATCH] Prevent Shutdown Hang + +Prevents server hanging if players disconnect during the shutdown sequence. + +diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerList.java ++++ b/src/main/java/net/minecraft/server/PlayerList.java +@@ -0,0 +0,0 @@ public abstract class PlayerList { + } + + public void u() { +- for (int i = 0; i < this.players.size(); ++i) { +- ((EntityPlayer) this.players.get(i)).playerConnection.disconnect(this.server.server.getShutdownMessage()); // CraftBukkit - add custom shutdown message ++ while (!this.players.isEmpty()) { ++ // Spigot start ++ EntityPlayer p = (EntityPlayer) this.players.get( 0 ); ++ p.playerConnection.disconnect( this.server.server.getShutdownMessage() ); ++ if ( ( !this.players.isEmpty() ) && ( this.players.get( 0 ) == p ) ) ++ { ++ this.players.remove( 0 ); // Prevent shutdown hang if already disconnected ++ } ++ // Spigot end + } + } + +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0030-Implement-SpawnerSpawnEvent.patch b/CraftBukkit-Patches/0030-Implement-SpawnerSpawnEvent.patch new file mode 100644 index 0000000000..fd345fbc5e --- /dev/null +++ b/CraftBukkit-Patches/0030-Implement-SpawnerSpawnEvent.patch @@ -0,0 +1,100 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andy Shulman +Date: Mon, 15 Apr 2013 20:06:37 -0500 +Subject: [PATCH] Implement SpawnerSpawnEvent. + +Adds BUKKIT-267 + +diff --git a/src/main/java/net/minecraft/server/MobSpawnerAbstract.java b/src/main/java/net/minecraft/server/MobSpawnerAbstract.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/MobSpawnerAbstract.java ++++ b/src/main/java/net/minecraft/server/MobSpawnerAbstract.java +@@ -0,0 +0,0 @@ import java.util.Collection; + import java.util.Iterator; + import java.util.List; + +-import org.bukkit.event.entity.CreatureSpawnEvent; // CraftBukkit ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.SpawnerSpawnEvent; ++// CraftBukkit end + + public abstract class MobSpawnerAbstract { + +@@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { + + entity.f(nbttagcompound); + if (entity.world != null) { +- entity.world.addEntity(entity, CreatureSpawnEvent.SpawnReason.SPAWNER); // CraftBukkit ++ // CraftBukkit start - call SpawnerSpawnEvent, abort if cancelled ++ SpawnerSpawnEvent event = CraftEventFactory.callSpawnerSpawnEvent(entity, this.b(), this.c(), this.d()); ++ if (!event.isCancelled()) { ++ entity.world.addEntity(entity, CreatureSpawnEvent.SpawnReason.SPAWNER); // CraftBukkit ++ } ++ // CraftBukkit end + } + + NBTTagCompound nbttagcompound1; +@@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { + + entity2.f(nbttagcompound2); + entity2.setPositionRotation(entity1.locX, entity1.locY, entity1.locZ, entity1.yaw, entity1.pitch); ++ // CraftBukkit start - call SpawnerSpawnEvent, skip if cancelled ++ SpawnerSpawnEvent event = CraftEventFactory.callSpawnerSpawnEvent(entity2, this.b(), this.c(), this.d()); ++ if (event.isCancelled()) { ++ continue; ++ } + if (entity.world != null) { + entity.world.addEntity(entity2, CreatureSpawnEvent.SpawnReason.SPAWNER); // CraftBukkit + } +@@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { + } + } else if (entity instanceof EntityLiving && entity.world != null) { + ((EntityInsentient) entity).prepare((GroupDataEntity) null); +- this.a().addEntity(entity, CreatureSpawnEvent.SpawnReason.SPAWNER); // CraftBukkit ++ // Spigot start - call SpawnerSpawnEvent, abort if cancelled ++ SpawnerSpawnEvent event = CraftEventFactory.callSpawnerSpawnEvent(entity, this.b(), this.c(), this.d()); ++ if (!event.isCancelled()) { ++ this.a().addEntity(entity, CreatureSpawnEvent.SpawnReason.SPAWNER); // CraftBukkit ++ } ++ // Spigot end + } + + return entity; +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -0,0 +0,0 @@ import org.bukkit.Statistic.Type; + import org.bukkit.block.Block; + import org.bukkit.block.BlockFace; + import org.bukkit.block.BlockState; ++import org.bukkit.block.CreatureSpawner; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftStatistic; + import org.bukkit.craftbukkit.CraftWorld; +@@ -0,0 +0,0 @@ public class CraftEventFactory { + } + + /** ++ * Mob spawner event ++ */ ++ public static SpawnerSpawnEvent callSpawnerSpawnEvent(Entity spawnee, int spawnerX, int spawnerY, int spawnerZ) { ++ org.bukkit.craftbukkit.entity.CraftEntity entity = spawnee.getBukkitEntity(); ++ BlockState state = entity.getWorld().getBlockAt(spawnerX, spawnerY, spawnerZ).getState(); ++ ++ if (!(state instanceof CreatureSpawner)) { ++ state = null; ++ } ++ ++ SpawnerSpawnEvent event = new SpawnerSpawnEvent(entity, (CreatureSpawner) state); ++ entity.getServer().getPluginManager().callEvent(event); ++ return event; ++ } ++ ++ /** + * Bucket methods + */ + public static PlayerBucketEmptyEvent callPlayerBucketEmptyEvent(EntityHuman who, int clickedX, int clickedY, int clickedZ, int clickedFace, ItemStack itemInHand) { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0031-Firework-Meta-Crash-Fix.patch b/CraftBukkit-Patches/0031-Firework-Meta-Crash-Fix.patch new file mode 100644 index 0000000000..178ac6d603 --- /dev/null +++ b/CraftBukkit-Patches/0031-Firework-Meta-Crash-Fix.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 15 Jun 2013 21:34:48 +1000 +Subject: [PATCH] Firework Meta Crash Fix + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java +@@ -0,0 +0,0 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta { + case BURST: + return 4; + default: +- throw new AssertionError(type); ++ throw new IllegalStateException(type.toString()); // Spigot + } + } + +@@ -0,0 +0,0 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta { + case 4: + return Type.BURST; + default: +- throw new AssertionError(nbt); ++ throw new IllegalStateException(Integer.toString(nbt)); // Spigot + } + } + +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0032-Allow-Disabling-of-Command-Logging.patch b/CraftBukkit-Patches/0032-Allow-Disabling-of-Command-Logging.patch new file mode 100644 index 0000000000..4c24059c0c --- /dev/null +++ b/CraftBukkit-Patches/0032-Allow-Disabling-of-Command-Logging.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Fri, 21 Jun 2013 18:01:29 +1000 +Subject: [PATCH] Allow Disabling of Command Logging + + +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketPlayInListener { + org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.startTiming(); // Spigot + + // CraftBukkit start - whole method +- this.c.info(this.player.getName() + " issued server command: " + s); ++ if ( org.spigotmc.SpigotConfig.logCommands ) this.c.info(this.player.getName() + " issued server command: " + s); + + CraftPlayer player = this.getPlayer(); + +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -0,0 +0,0 @@ public class SpigotConfig + config.addDefault( path, def ); + return config.getString( path, config.getString( path ) ); + } ++ ++ public static boolean logCommands; ++ private static void logCommands() ++ { ++ logCommands = getBoolean( "commands.log", true ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0033-Allow-Disabling-of-Command-TabComplete.patch b/CraftBukkit-Patches/0033-Allow-Disabling-of-Command-TabComplete.patch new file mode 100644 index 0000000000..ab9879cdea --- /dev/null +++ b/CraftBukkit-Patches/0033-Allow-Disabling-of-Command-TabComplete.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Fri, 21 Jun 2013 18:05:54 +1000 +Subject: [PATCH] Allow Disabling of Command TabComplete + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -0,0 +0,0 @@ public final class CraftServer implements Server { + } + + public List tabCompleteCommand(Player player, String message) { ++ // Spigot Start ++ if ( (org.spigotmc.SpigotConfig.tabComplete < 0 || message.length() <= org.spigotmc.SpigotConfig.tabComplete) && !message.contains( " " ) ) ++ { ++ return ImmutableList.of(); ++ } ++ // Spigot End ++ + List completions = null; + try { + completions = getCommandMap().tabComplete(player, message.substring(1)); +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -0,0 +0,0 @@ public class SpigotConfig + { + logCommands = getBoolean( "commands.log", true ); + } ++ ++ public static int tabComplete; ++ private static void tabComplete() ++ { ++ if ( version < 6 ) ++ { ++ boolean oldValue = getBoolean( "commands.tab-complete", true ); ++ if ( oldValue ) ++ { ++ set( "commands.tab-complete", 0 ); ++ } else ++ { ++ set( "commands.tab-complete", -1 ); ++ } ++ } ++ tabComplete = getInt( "commands.tab-complete", 0 ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0034-Configurable-Messages.patch b/CraftBukkit-Patches/0034-Configurable-Messages.patch new file mode 100644 index 0000000000..66275bf179 --- /dev/null +++ b/CraftBukkit-Patches/0034-Configurable-Messages.patch @@ -0,0 +1,105 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Fri, 21 Jun 2013 19:21:58 +1000 +Subject: [PATCH] Configurable Messages + + +diff --git a/src/main/java/net/minecraft/server/HandshakeListener.java b/src/main/java/net/minecraft/server/HandshakeListener.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/HandshakeListener.java ++++ b/src/main/java/net/minecraft/server/HandshakeListener.java +@@ -0,0 +0,0 @@ public class HandshakeListener implements PacketHandshakingInListener { + // CraftBukkit end + + if (packethandshakinginsetprotocol.d() > 5) { +- chatcomponenttext = new ChatComponentText("Outdated server! I\'m still on 1.7.10"); ++ chatcomponenttext = new ChatComponentText( org.spigotmc.SpigotConfig.outdatedServerMessage ); // Spigot + this.b.handle(new PacketLoginOutDisconnect(chatcomponenttext), new GenericFutureListener[0]); + this.b.close(chatcomponenttext); + } else if (packethandshakinginsetprotocol.d() < 5) { +- chatcomponenttext = new ChatComponentText("Outdated client! Please use 1.7.10"); ++ chatcomponenttext = new ChatComponentText( org.spigotmc.SpigotConfig.outdatedClientMessage ); // Spigot + this.b.handle(new PacketLoginOutDisconnect(chatcomponenttext), new GenericFutureListener[0]); + this.b.close(chatcomponenttext); + } else { +diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerList.java ++++ b/src/main/java/net/minecraft/server/PlayerList.java +@@ -0,0 +0,0 @@ public abstract class PlayerList { + event.disallow(PlayerLoginEvent.Result.KICK_BANNED, s); + } else if (!this.isWhitelisted(gameprofile)) { + // return "You are not white-listed on this server!"; +- event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, "You are not white-listed on this server!"); ++ event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot + } else if (this.k.isBanned(socketaddress) && !this.k.get(gameprofile).hasExpired()) { + IpBanEntry ipbanentry = this.k.get(socketaddress); + +@@ -0,0 +0,0 @@ public abstract class PlayerList { + } else { + // return this.players.size() >= this.maxPlayers ? "The server is full!" : null; + if (this.players.size() >= this.maxPlayers) { +- event.disallow(PlayerLoginEvent.Result.KICK_FULL, "The server is full!"); ++ event.disallow(PlayerLoginEvent.Result.KICK_FULL, org.spigotmc.SpigotConfig.serverFullMessage); // Spigot + } + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -0,0 +0,0 @@ public final class CraftServer implements Server { + return true; + } + +- if (sender instanceof Player) { +- sender.sendMessage("Unknown command. Type \"/help\" for help."); +- } else { +- sender.sendMessage("Unknown command. Type \"help\" for help."); +- } ++ sender.sendMessage(org.spigotmc.SpigotConfig.unknownCommandMessage); + + return false; + } +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -0,0 +0,0 @@ import java.util.Map; + import java.util.logging.Level; + import net.minecraft.server.MinecraftServer; + import org.bukkit.Bukkit; ++import org.bukkit.ChatColor; + import org.bukkit.command.Command; + import org.bukkit.configuration.InvalidConfigurationException; + import org.bukkit.configuration.file.YamlConfiguration; +@@ -0,0 +0,0 @@ public class SpigotConfig + } + tabComplete = getInt( "commands.tab-complete", 0 ); + } ++ ++ public static String whitelistMessage; ++ public static String unknownCommandMessage; ++ public static String serverFullMessage; ++ public static String outdatedClientMessage = "Outdated client! Please use {}"; ++ public static String outdatedServerMessage = "Outdated server! I\'m still on {0}"; ++ private static String transform(String s) ++ { ++ return ChatColor.translateAlternateColorCodes( '&', s ).replaceAll( "\\n", "\n" ); ++ } ++ private static void messages() ++ { ++ if (version < 4) ++ { ++ set( "messages.outdated-client", outdatedClientMessage ); ++ set( "messages.outdated-server", outdatedServerMessage ); ++ } ++ ++ whitelistMessage = transform( getString( "messages.whitelist", "You are not whitelisted on this server!" ) ); ++ unknownCommandMessage = transform( getString( "messages.unknown-command", "Unknown command. Type \"/help\" for help." ) ); ++ serverFullMessage = transform( getString( "messages.server-full", "The server is full!" ) ); ++ outdatedClientMessage = transform( getString( "messages.outdated-client", outdatedClientMessage ) ); ++ outdatedServerMessage = transform( getString( "messages.outdated-server", outdatedServerMessage ) ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0035-Allow-Disabling-of-Random-Lighting-Updates.patch b/CraftBukkit-Patches/0035-Allow-Disabling-of-Random-Lighting-Updates.patch new file mode 100644 index 0000000000..817ae805e5 --- /dev/null +++ b/CraftBukkit-Patches/0035-Allow-Disabling-of-Random-Lighting-Updates.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 22 Jun 2013 16:12:02 +1000 +Subject: [PATCH] Allow Disabling of Random Lighting Updates + + +diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Chunk.java ++++ b/src/main/java/net/minecraft/server/Chunk.java +@@ -0,0 +0,0 @@ public class Chunk { + } + + this.m = true; +- if (!this.lit && this.done) { ++ if (!this.lit && this.done && this.world.spigotConfig.randomLightUpdates) { // Spigot - also use random light updates setting to determine if we should relight + this.p(); + } + } +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + } + + this.methodProfiler.a("playerCheckLight"); +- if (!this.players.isEmpty()) { ++ if (spigotConfig.randomLightUpdates && !this.players.isEmpty()) { // Spigot + i = this.random.nextInt(this.players.size()); + entityhuman = (EntityHuman) this.players.get(i); + j = MathHelper.floor(entityhuman.locX) + this.random.nextInt(11) - 5; +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -0,0 +0,0 @@ public class SpigotWorldConfig + hopperAmount = getInt( "hopper-amount", 1 ); + log( "Hopper Transfer: " + hopperTransfer + " Hopper Check: " + hopperCheck + " Hopper Amount: " + hopperAmount ); + } ++ ++ public boolean randomLightUpdates; ++ private void lightUpdates() ++ { ++ randomLightUpdates = getBoolean( "random-light-updates", false ); ++ log( "Random Lighting Updates: " + randomLightUpdates ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0036-Properly-Close-Inventories.patch b/CraftBukkit-Patches/0036-Properly-Close-Inventories.patch new file mode 100644 index 0000000000..b0144bdf33 --- /dev/null +++ b/CraftBukkit-Patches/0036-Properly-Close-Inventories.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Thu, 27 Jun 2013 17:26:09 +1000 +Subject: [PATCH] Properly Close Inventories + +Properly close inventories when unloading and switching worlds. + +diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Chunk.java ++++ b/src/main/java/net/minecraft/server/Chunk.java +@@ -0,0 +0,0 @@ public class Chunk { + + while (iterator.hasNext()) { + TileEntity tileentity = (TileEntity) iterator.next(); ++ // Spigot Start ++ if ( tileentity instanceof IInventory ) ++ { ++ for ( org.bukkit.craftbukkit.entity.CraftHumanEntity h : new ArrayList( (List) ( (IInventory) tileentity ).getViewers() ) ) ++ { ++ h.getHandle().closeInventory(); ++ } ++ } ++ // Spigot End + + this.world.a(tileentity); + } +@@ -0,0 +0,0 @@ public class Chunk { + java.util.Iterator iter = this.entitySlices[i].iterator(); + while (iter.hasNext()) { + Entity entity = (Entity) iter.next(); ++ // Spigot Start ++ if ( entity instanceof IInventory ) ++ { ++ for ( org.bukkit.craftbukkit.entity.CraftHumanEntity h : new ArrayList( (List) ( (IInventory) entity ).getViewers() ) ) ++ { ++ h.getHandle().closeInventory(); ++ } ++ } ++ // Spigot End + + // Do not pass along players, as doing so can get them stuck outside of time. + // (which for example disables inventory icon updates and prevents block breaking) +diff --git a/src/main/java/net/minecraft/server/EntityMinecartContainer.java b/src/main/java/net/minecraft/server/EntityMinecartContainer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityMinecartContainer.java ++++ b/src/main/java/net/minecraft/server/EntityMinecartContainer.java +@@ -0,0 +0,0 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp + } + + public void b(int i) { ++ // Spigot Start ++ for ( HumanEntity human : new java.util.ArrayList( transaction ) ) ++ { ++ human.closeInventory(); ++ } ++ // Spigot End + this.b = false; + super.b(i); + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0037-Disallow-Interaction-With-Self.patch b/CraftBukkit-Patches/0037-Disallow-Interaction-With-Self.patch new file mode 100644 index 0000000000..cd1d40070d --- /dev/null +++ b/CraftBukkit-Patches/0037-Disallow-Interaction-With-Self.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Fri, 28 Jun 2013 19:52:54 +1000 +Subject: [PATCH] Disallow Interaction With Self + + +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketPlayInListener { + if (this.player.dead) return; // CraftBukkit + WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension); + Entity entity = packetplayinuseentity.a((World) worldserver); ++ // Spigot Start ++ if ( entity == player ) ++ { ++ disconnect( "Cannot interact with self!" ); ++ return; ++ } ++ // Spigot End + + this.player.v(); + if (entity != null) { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0038-Lower-Chunk-Compression.patch b/CraftBukkit-Patches/0038-Lower-Chunk-Compression.patch new file mode 100644 index 0000000000..ba2faf7f01 --- /dev/null +++ b/CraftBukkit-Patches/0038-Lower-Chunk-Compression.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Tue, 2 Jul 2013 09:07:54 +1000 +Subject: [PATCH] Lower Chunk Compression + +Use a chunk compression level of 4 - this provides an optimal balance between speed and compression. + +diff --git a/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java ++++ b/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java +@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk extends Packet { + this.b = chunk.locZ; + this.g = flag; + ChunkMap chunkmap = a(chunk, flag, i); +- Deflater deflater = new Deflater(-1); ++ Deflater deflater = new Deflater(4); // Spigot + + this.d = chunkmap.c; + this.c = chunkmap.b; +diff --git a/src/main/java/net/minecraft/server/PacketPlayOutMapChunkBulk.java b/src/main/java/net/minecraft/server/PacketPlayOutMapChunkBulk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PacketPlayOutMapChunkBulk.java ++++ b/src/main/java/net/minecraft/server/PacketPlayOutMapChunkBulk.java +@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunkBulk extends Packet { + @Override + protected Deflater initialValue() { + // Don't use higher compression level, slows things down too much +- return new Deflater(6); ++ return new Deflater(4); // Spigot 6 -> 4 + } + }; + // CraftBukkit end +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0039-Entity-Mount-and-Dismount-Events.patch b/CraftBukkit-Patches/0039-Entity-Mount-and-Dismount-Events.patch new file mode 100644 index 0000000000..0ba8aa03d2 --- /dev/null +++ b/CraftBukkit-Patches/0039-Entity-Mount-and-Dismount-Events.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Tue, 2 Jul 2013 20:32:49 +1000 +Subject: [PATCH] Entity Mount and Dismount Events + + +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -0,0 +0,0 @@ public abstract class Entity { + } + } + // CraftBukkit end ++ pluginManager.callEvent( new org.spigotmc.event.entity.EntityDismountEvent( this.getBukkitEntity(), this.vehicle.getBukkitEntity() ) ); // Spigot + + this.setPositionRotation(this.vehicle.locX, this.vehicle.boundingBox.b + (double) this.vehicle.length, this.vehicle.locZ, this.yaw, this.pitch); + this.vehicle.passenger = null; +@@ -0,0 +0,0 @@ public abstract class Entity { + } + } + // CraftBukkit end ++ // Spigot Start ++ if ( entity.world.isChunkLoaded( (int) entity.locX >> 4, (int) entity.locZ >> 4 ) ) ++ { ++ org.spigotmc.event.entity.EntityMountEvent event = new org.spigotmc.event.entity.EntityMountEvent( this.getBukkitEntity(), entity.getBukkitEntity() ); ++ pluginManager.callEvent( event ); ++ if ( event.isCancelled() ) ++ { ++ return; ++ } ++ } ++ // Spigot End + + if (this.vehicle != null) { + this.vehicle.passenger = null; +diff --git a/src/main/java/net/minecraft/server/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityHuman.java ++++ b/src/main/java/net/minecraft/server/EntityHuman.java +@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving implements ICommandListen + public void setPassengerOf(Entity entity) { + // CraftBukkit end + if (this.vehicle != null && entity == null) { ++ world.getServer().getPluginManager().callEvent( new org.spigotmc.event.entity.EntityDismountEvent( this.getBukkitEntity(), this.vehicle.getBukkitEntity() ) ); // Spigot + // CraftBukkit start - use parent method instead to correctly fire VehicleExitEvent + Entity originalVehicle = this.vehicle; + // First statement moved down, second statement handled in parent method. +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0040-Prevent-Ghost-Players-Caused-by-Plugins.patch b/CraftBukkit-Patches/0040-Prevent-Ghost-Players-Caused-by-Plugins.patch new file mode 100644 index 0000000000..9debd42f25 --- /dev/null +++ b/CraftBukkit-Patches/0040-Prevent-Ghost-Players-Caused-by-Plugins.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alex Ciuba +Date: Tue, 11 Jun 2013 15:23:03 -0400 +Subject: [PATCH] Prevent Ghost Players Caused by Plugins + +Check if the player is still connected after firing event. Fixes BUKKIT-4327 + +diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerList.java ++++ b/src/main/java/net/minecraft/server/PlayerList.java +@@ -0,0 +0,0 @@ public abstract class PlayerList { + Player respawnPlayer = this.cserver.getPlayer(entityplayer1); + PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn); + this.cserver.getPluginManager().callEvent(respawnEvent); ++ // Spigot Start ++ if (entityplayer.playerConnection.isDisconnected()) { ++ return entityplayer; ++ } ++ // Spigot End + + location = respawnEvent.getRespawnLocation(); + entityplayer.reset(); +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0041-Plug-World-Unload-Memory-Leak.patch b/CraftBukkit-Patches/0041-Plug-World-Unload-Memory-Leak.patch new file mode 100644 index 0000000000..ac0ed6047f --- /dev/null +++ b/CraftBukkit-Patches/0041-Plug-World-Unload-Memory-Leak.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 3 Aug 2013 19:02:59 +1000 +Subject: [PATCH] Plug World Unload Memory Leak + + +diff --git a/src/main/java/net/minecraft/server/BlockRedstoneTorch.java b/src/main/java/net/minecraft/server/BlockRedstoneTorch.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/BlockRedstoneTorch.java ++++ b/src/main/java/net/minecraft/server/BlockRedstoneTorch.java +@@ -0,0 +0,0 @@ import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + public class BlockRedstoneTorch extends BlockTorch { + + private boolean isOn; +- private static Map b = new HashMap(); ++ private static Map b = new java.util.WeakHashMap(); // Spigot + + private boolean a(World world, int i, int j, int k, boolean flag) { + if (!b.containsKey(world)) { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0042-Player-Collision-API.patch b/CraftBukkit-Patches/0042-Player-Collision-API.patch new file mode 100644 index 0000000000..075c249b92 --- /dev/null +++ b/CraftBukkit-Patches/0042-Player-Collision-API.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 3 Aug 2013 19:27:07 +1000 +Subject: [PATCH] Player Collision API + + +diff --git a/src/main/java/net/minecraft/server/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityHuman.java ++++ b/src/main/java/net/minecraft/server/EntityHuman.java +@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving implements ICommandListen + + List list = this.world.getEntities(this, axisalignedbb); + +- if (list != null) { ++ if (list != null && this.S()) { // Spigot: Add this.S() condition (second !this.isDead near bottom of EntityLiving) + for (int i = 0; i < list.size(); ++i) { + Entity entity = (Entity) list.get(i); + +diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityLiving.java ++++ b/src/main/java/net/minecraft/server/EntityLiving.java +@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { + protected void bo() { + List list = this.world.getEntities(this, this.boundingBox.grow(0.20000000298023224D, 0.0D, 0.20000000298023224D)); + +- if (list != null && !list.isEmpty()) { ++ if (this.R() && list != null && !list.isEmpty()) { // Spigot: Add this.R() condition + for (int i = 0; i < list.size(); ++i) { + Entity entity = (Entity) list.get(i); + +diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/EntityPlayer.java +@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + public double maxHealthCache; + public boolean joining = true; + // CraftBukkit end ++ // Spigot start ++ public boolean collidesWithEntities = true; ++ ++ @Override ++ public boolean R() ++ { ++ return this.collidesWithEntities && super.R(); // (first !this.isDead near bottom of EntityLiving) ++ } ++ ++ @Override ++ public boolean S() ++ { ++ return this.collidesWithEntities && super.S(); // (second !this.isDead near bottom of EntityLiving) ++ } ++ // Spigot end + + public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) { + super(worldserver, gameprofile); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + // Spigot start + private final Player.Spigot spigot = new Player.Spigot() + { ++ ++ @Override ++ public boolean getCollidesWithEntities() ++ { ++ return getHandle().collidesWithEntities; ++ } ++ ++ @Override ++ public void setCollidesWithEntities(boolean collides) ++ { ++ getHandle().collidesWithEntities = collides; ++ getHandle().k = collides; // First boolean of Entity ++ } + }; + + public Player.Spigot spigot() +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0043-Fully-Disable-Snooper-When-Not-Required.patch b/CraftBukkit-Patches/0043-Fully-Disable-Snooper-When-Not-Required.patch new file mode 100644 index 0000000000..6be956369c --- /dev/null +++ b/CraftBukkit-Patches/0043-Fully-Disable-Snooper-When-Not-Required.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: agentk20 +Date: Sat, 3 Aug 2013 19:28:48 +1000 +Subject: [PATCH] Fully Disable Snooper When Not Required + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + this.g[this.ticks % 100] = System.nanoTime() - i; + this.methodProfiler.b(); + this.methodProfiler.a("snooper"); +- if (!this.l.d() && this.ticks > 100) { ++ if (getSnooperEnabled() && !this.l.d() && this.ticks > 100) { // Spigot + this.l.a(); + } + +- if (this.ticks % 6000 == 0) { ++ if (getSnooperEnabled() && this.ticks % 6000 == 0) { // Spigot + this.l.b(); + } + +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0044-Add-Getter-for-Entity-Invulnerability.patch b/CraftBukkit-Patches/0044-Add-Getter-for-Entity-Invulnerability.patch new file mode 100644 index 0000000000..d18d4b4db5 --- /dev/null +++ b/CraftBukkit-Patches/0044-Add-Getter-for-Entity-Invulnerability.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: DerFlash +Date: Sat, 3 Aug 2013 19:53:48 +1000 +Subject: [PATCH] Add Getter for Entity Invulnerability + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + // Spigot start + private final Spigot spigot = new Spigot() + { ++ @Override ++ public boolean isInvulnerable() ++ { ++ return getHandle().isInvulnerable(); ++ } + }; + + public Spigot spigot() +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0045-Cap-Minimum-Player-Speed.patch b/CraftBukkit-Patches/0045-Cap-Minimum-Player-Speed.patch new file mode 100644 index 0000000000..4cf6f19eae --- /dev/null +++ b/CraftBukkit-Patches/0045-Cap-Minimum-Player-Speed.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Mon, 5 Aug 2013 20:17:20 +1000 +Subject: [PATCH] Cap Minimum Player Speed + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + public void setFlySpeed(float value) { + validateSpeed(value); + EntityPlayer player = getHandle(); +- player.abilities.flySpeed = value / 2f; ++ player.abilities.flySpeed = Math.max( value, 0.0001f ) / 2f; // Spigot + player.updateAbilities(); + + } +@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + public void setWalkSpeed(float value) { + validateSpeed(value); + EntityPlayer player = getHandle(); +- player.abilities.walkSpeed = value / 2f; ++ player.abilities.walkSpeed = Math.max( value, 0.0001f ) / 2f; // Spigot + player.updateAbilities(); + } + +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0046-Update-Inventory-and-Health-for-PlayerConsumeItemEve.patch b/CraftBukkit-Patches/0046-Update-Inventory-and-Health-for-PlayerConsumeItemEve.patch new file mode 100644 index 0000000000..f8cda993ac --- /dev/null +++ b/CraftBukkit-Patches/0046-Update-Inventory-and-Health-for-PlayerConsumeItemEve.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 14 Sep 2013 10:16:38 +1000 +Subject: [PATCH] Update Inventory and Health for PlayerConsumeItemEvent + + +diff --git a/src/main/java/net/minecraft/server/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityHuman.java ++++ b/src/main/java/net/minecraft/server/EntityHuman.java +@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving implements ICommandListen + // Update client + if (this instanceof EntityPlayer) { + ((EntityPlayer) this).playerConnection.sendPacket(new PacketPlayOutSetSlot((byte) 0, activeContainer.getSlot((IInventory) this.inventory, this.inventory.itemInHandIndex).index, this.f)); ++ // Spigot Start ++ ((EntityPlayer) this).getBukkitEntity().updateInventory(); ++ ((EntityPlayer) this).getBukkitEntity().updateScaledHealth(); ++ // Spigot End + } + return; + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0047-Call-EntityChangeBlockEvent-for-Fire-Arrows-hitting-.patch b/CraftBukkit-Patches/0047-Call-EntityChangeBlockEvent-for-Fire-Arrows-hitting-.patch new file mode 100644 index 0000000000..f5e40fe411 --- /dev/null +++ b/CraftBukkit-Patches/0047-Call-EntityChangeBlockEvent-for-Fire-Arrows-hitting-.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BlackHole +Date: Tue, 16 Jul 2013 22:34:50 +0200 +Subject: [PATCH] Call EntityChangeBlockEvent for Fire Arrows hitting TNT + +Adds BUKKIT-4355 + +diff --git a/src/main/java/net/minecraft/server/BlockTNT.java b/src/main/java/net/minecraft/server/BlockTNT.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/BlockTNT.java ++++ b/src/main/java/net/minecraft/server/BlockTNT.java +@@ -0,0 +0,0 @@ public class BlockTNT extends Block { + + public boolean interact(World world, int i, int j, int k, EntityHuman entityhuman, int l, float f, float f1, float f2) { + if (entityhuman.bF() != null && entityhuman.bF().getItem() == Items.FLINT_AND_STEEL) { +- this.a(world, i, j, k, 1, entityhuman); ++ this.a(world, i, j, k, 1, (EntityLiving) entityhuman); // Spigot - Fix decompile error! + world.setAir(i, j, k); + entityhuman.bF().damage(1, entityhuman); + return true; +@@ -0,0 +0,0 @@ public class BlockTNT extends Block { + EntityArrow entityarrow = (EntityArrow) entity; + + if (entityarrow.isBurning()) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entityarrow, i, j, k, Blocks.AIR, 0).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + this.a(world, i, j, k, 1, entityarrow.shooter instanceof EntityLiving ? (EntityLiving) entityarrow.shooter : null); + world.setAir(i, j, k); + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0048-Allow-Disabling-of-1.6.3-Structure-Saving.patch b/CraftBukkit-Patches/0048-Allow-Disabling-of-1.6.3-Structure-Saving.patch new file mode 100644 index 0000000000..36036c6b8d --- /dev/null +++ b/CraftBukkit-Patches/0048-Allow-Disabling-of-1.6.3-Structure-Saving.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 21 Sep 2013 12:33:09 +1000 +Subject: [PATCH] Allow Disabling of 1.6.3 Structure Saving + + +diff --git a/src/main/java/net/minecraft/server/StructureGenerator.java b/src/main/java/net/minecraft/server/StructureGenerator.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/StructureGenerator.java ++++ b/src/main/java/net/minecraft/server/StructureGenerator.java +@@ -0,0 +0,0 @@ public abstract class StructureGenerator extends WorldGenBase { + + private void a(World world) { + if (this.e == null) { ++ // Spigot Start ++ if ( world.spigotConfig.saveStructureInfo ) ++ { + this.e = (PersistentStructure) world.a(PersistentStructure.class, this.a()); ++ } else ++ { ++ this.e = new PersistentStructure( this.a() ); ++ } ++ // Spigot End + if (this.e == null) { + this.e = new PersistentStructure(this.a()); + world.a(this.a(), (PersistentBase) this.e); +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -0,0 +0,0 @@ public class SpigotWorldConfig + randomLightUpdates = getBoolean( "random-light-updates", false ); + log( "Random Lighting Updates: " + randomLightUpdates ); + } ++ ++ public boolean saveStructureInfo; ++ private void structureInfo() ++ { ++ saveStructureInfo = getBoolean( "save-structure-info", true ); ++ log( "Structure Info Saving: " + saveStructureInfo ); ++ if ( !saveStructureInfo ) ++ { ++ log( "*** WARNING *** You have selected to NOT save structure info. This may cause structures such as fortresses to not spawn mobs when updating to 1.7!" ); ++ log( "*** WARNING *** Please use this option with caution, SpigotMC is not responsible for any issues this option may cause in the future!" ); ++ } ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0049-Item-Despawn-Rate.patch b/CraftBukkit-Patches/0049-Item-Despawn-Rate.patch new file mode 100644 index 0000000000..5d27fa2deb --- /dev/null +++ b/CraftBukkit-Patches/0049-Item-Despawn-Rate.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 22 Sep 2013 19:10:53 +1000 +Subject: [PATCH] Item Despawn Rate + + +diff --git a/src/main/java/net/minecraft/server/EntityItem.java b/src/main/java/net/minecraft/server/EntityItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityItem.java ++++ b/src/main/java/net/minecraft/server/EntityItem.java +@@ -0,0 +0,0 @@ public class EntityItem extends Entity { + } + + // ++this.age; // CraftBukkit - Moved up +- if (!this.world.isStatic && this.age >= 6000) { ++ if (!this.world.isStatic && this.age >= world.spigotConfig.itemDespawnRate) { // Spigot + // CraftBukkit start - fire ItemDespawnEvent + if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { + this.age = 0; +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -0,0 +0,0 @@ public class SpigotWorldConfig + log( "*** WARNING *** Please use this option with caution, SpigotMC is not responsible for any issues this option may cause in the future!" ); + } + } ++ ++ public int itemDespawnRate; ++ private void itemDespawnRate() ++ { ++ itemDespawnRate = getInt( "item-despawn-rate", 6000 ); ++ log( "Item Despawn Rate: " + itemDespawnRate ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0050-Don-t-Special-Case-X-Move-Value.patch b/CraftBukkit-Patches/0050-Don-t-Special-Case-X-Move-Value.patch new file mode 100644 index 0000000000..342a6e448b --- /dev/null +++ b/CraftBukkit-Patches/0050-Don-t-Special-Case-X-Move-Value.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 6 Oct 2013 17:36:28 +1100 +Subject: [PATCH] Don't Special Case X Move Value + + +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketPlayInListener { + private float lastPitch = Float.MAX_VALUE; + private float lastYaw = Float.MAX_VALUE; + private boolean justTeleported = false; ++ private boolean hasMoved; // Spigot + + // For the PacketPlayOutBlockPlace hack :( + Long lastPacket; +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketPlayInListener { + + // CraftBukkit start - fire PlayerMoveEvent + Player player = this.getPlayer(); ++ // Spigot Start ++ if ( !hasMoved ) ++ { ++ Location curPos = player.getLocation(); ++ lastPosX = curPos.getX(); ++ lastPosY = curPos.getY(); ++ lastPosZ = curPos.getZ(); ++ lastYaw = curPos.getYaw(); ++ lastPitch = curPos.getPitch(); ++ hasMoved = true; ++ } ++ // Spigot End + Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. + Location to = player.getLocation().clone(); // Start off the To location as the Players current location. + +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketPlayInListener { + this.lastPitch = to.getPitch(); + + // Skip the first time we do this +- if (from.getX() != Double.MAX_VALUE) { ++ if (true) { // Spigot - don't skip any move events + PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); + this.server.getPluginManager().callEvent(event); + +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0051-Implement-respawn-API.patch b/CraftBukkit-Patches/0051-Implement-respawn-API.patch new file mode 100644 index 0000000000..28876a3151 --- /dev/null +++ b/CraftBukkit-Patches/0051-Implement-respawn-API.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ninja- +Date: Tue, 8 Oct 2013 14:34:49 +0200 +Subject: [PATCH] Implement respawn API. + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + getHandle().collidesWithEntities = collides; + getHandle().k = collides; // First boolean of Entity + } ++ ++ @Override ++ public void respawn() ++ { ++ if ( getHealth() <= 0 && isOnline() ) ++ { ++ server.getServer().getPlayerList().moveToWorld( getHandle(), 0, false ); ++ } ++ } + }; + + public Player.Spigot spigot() +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0052-Fix-BrewingStands-Removing-NBT-Potions.patch b/CraftBukkit-Patches/0052-Fix-BrewingStands-Removing-NBT-Potions.patch new file mode 100644 index 0000000000..a84415d094 --- /dev/null +++ b/CraftBukkit-Patches/0052-Fix-BrewingStands-Removing-NBT-Potions.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Wed, 9 Oct 2013 18:20:05 +1100 +Subject: [PATCH] Fix BrewingStands Removing NBT / Potions + + +diff --git a/src/main/java/net/minecraft/server/BlockBrewingStand.java b/src/main/java/net/minecraft/server/BlockBrewingStand.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/BlockBrewingStand.java ++++ b/src/main/java/net/minecraft/server/BlockBrewingStand.java +@@ -0,0 +0,0 @@ public class BlockBrewingStand extends BlockContainer { + entityitem.motX = (double) ((float) this.a.nextGaussian() * f3); + entityitem.motY = (double) ((float) this.a.nextGaussian() * f3 + 0.2F); + entityitem.motZ = (double) ((float) this.a.nextGaussian() * f3); +- world.addEntity(entityitem); ++ // Spigot Start ++ if ( itemstack.hasTag() ) ++ { ++ entityitem.getItemStack().setTag( (NBTTagCompound) itemstack.getTag().clone() ); ++ } ++ // Spigot End ++ world.addEntity( entityitem ); + } + } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0053-Arrow-Despawn-Rate.patch b/CraftBukkit-Patches/0053-Arrow-Despawn-Rate.patch new file mode 100644 index 0000000000..6dc1d9b669 --- /dev/null +++ b/CraftBukkit-Patches/0053-Arrow-Despawn-Rate.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Mon, 14 Oct 2013 19:20:10 +1100 +Subject: [PATCH] Arrow Despawn Rate + + +diff --git a/src/main/java/net/minecraft/server/EntityArrow.java b/src/main/java/net/minecraft/server/EntityArrow.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityArrow.java ++++ b/src/main/java/net/minecraft/server/EntityArrow.java +@@ -0,0 +0,0 @@ public class EntityArrow extends Entity implements IProjectile { + + if (block == this.g && i == this.h) { + ++this.at; +- if (this.at == 1200) { ++ if (this.at >= world.spigotConfig.arrowDespawnRate) { // First int after shooter + this.die(); + } + } else { +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -0,0 +0,0 @@ public class SpigotWorldConfig + itemDespawnRate = getInt( "item-despawn-rate", 6000 ); + log( "Item Despawn Rate: " + itemDespawnRate ); + } ++ ++ public int arrowDespawnRate; ++ private void arrowDespawnRate() ++ { ++ arrowDespawnRate = getInt( "arrow-despawn-rate", 1200 ); ++ log( "Arrow Despawn Rate: " + arrowDespawnRate ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0054-Fix-packed-ice-generation.patch b/CraftBukkit-Patches/0054-Fix-packed-ice-generation.patch new file mode 100644 index 0000000000..1083007e04 --- /dev/null +++ b/CraftBukkit-Patches/0054-Fix-packed-ice-generation.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 1 Dec 2013 17:52:14 +1100 +Subject: [PATCH] Fix packed ice generation + + +diff --git a/src/main/java/net/minecraft/server/WorldGenPackedIce2.java b/src/main/java/net/minecraft/server/WorldGenPackedIce2.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/WorldGenPackedIce2.java ++++ b/src/main/java/net/minecraft/server/WorldGenPackedIce2.java +@@ -0,0 +0,0 @@ public class WorldGenPackedIce2 extends WorldGenerator { + Block block = world.getType(i + l1, j + j1, k + i2); + + if (block.getMaterial() == Material.AIR || block == Blocks.DIRT || block == Blocks.SNOW_BLOCK || block == Blocks.ICE) { +- this.setType(world, i + l1, j + j1, k + i2, Blocks.PACKED_ICE); ++ world.setTypeUpdate(i + l1, j + j1, k + i2, Blocks.PACKED_ICE); // Spigot + } + + if (j1 != 0 && k1 > 1) { + block = world.getType(i + l1, j - j1, k + i2); + if (block.getMaterial() == Material.AIR || block == Blocks.DIRT || block == Blocks.SNOW_BLOCK || block == Blocks.ICE) { +- this.setType(world, i + l1, j - j1, k + i2, Blocks.PACKED_ICE); ++ world.setTypeUpdate(i + l1, j - j1, k + i2, Blocks.PACKED_ICE); // Spigot + } + } + } +@@ -0,0 +0,0 @@ public class WorldGenPackedIce2 extends WorldGenerator { + Block block1 = world.getType(i + j2, l1, k + k1); + + if (block1.getMaterial() == Material.AIR || block1 == Blocks.DIRT || block1 == Blocks.SNOW_BLOCK || block1 == Blocks.ICE || block1 == Blocks.PACKED_ICE) { +- this.setType(world, i + j2, l1, k + k1, Blocks.PACKED_ICE); ++ world.setTypeUpdate(i + j2, l1, k + k1, Blocks.PACKED_ICE); // Spigot + --l1; + --k2; + if (k2 <= 0) { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0055-Watchdog-Thread.patch b/CraftBukkit-Patches/0055-Watchdog-Thread.patch new file mode 100644 index 0000000000..5ae3e5ab63 --- /dev/null +++ b/CraftBukkit-Patches/0055-Watchdog-Thread.patch @@ -0,0 +1,303 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 23 Feb 2013 12:33:20 +1100 +Subject: [PATCH] Watchdog Thread. + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + this.a(crashreport); + } finally { + try { ++ org.spigotmc.WatchdogThread.doStop(); + this.stop(); + this.isStopped = true; + } catch (Throwable throwable1) { +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + SpigotTimings.tickablesTimer.stopTiming(); // Spigot + + this.methodProfiler.b(); ++ org.spigotmc.WatchdogThread.tick(); // Spigot + SpigotTimings.serverTickTimer.stopTiming(); // Spigot + org.spigotmc.CustomTimingsHandler.tick(); // Spigot + } +diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/org/spigotmc/RestartCommand.java +@@ -0,0 +0,0 @@ ++package org.spigotmc; ++ ++import java.io.File; ++import java.util.List; ++import net.minecraft.server.EntityPlayer; ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++ ++public class RestartCommand extends Command ++{ ++ ++ public RestartCommand(String name) ++ { ++ super( name ); ++ this.description = "Restarts the server"; ++ this.usageMessage = "/restart"; ++ this.setPermission( "bukkit.command.restart" ); ++ } ++ ++ @Override ++ public boolean execute(CommandSender sender, String currentAlias, String[] args) ++ { ++ if ( testPermission( sender ) ) ++ { ++ MinecraftServer.getServer().processQueue.add( new Runnable() ++ { ++ @Override ++ public void run() ++ { ++ restart(); ++ } ++ } ); ++ } ++ return true; ++ } ++ ++ public static void restart() ++ { ++ restart( new File( SpigotConfig.restartScript ) ); ++ } ++ ++ public static void restart(final File script) ++ { ++ AsyncCatcher.enabled = false; // Disable async catcher incase it interferes with us ++ try ++ { ++ if ( script.isFile() ) ++ { ++ System.out.println( "Attempting to restart with " + SpigotConfig.restartScript ); ++ ++ // Disable Watchdog ++ WatchdogThread.doStop(); ++ ++ // Kick all players ++ for ( EntityPlayer p : (List< EntityPlayer>) MinecraftServer.getServer().getPlayerList().players ) ++ { ++ p.playerConnection.disconnect(SpigotConfig.restartMessage); ++ } ++ // Give the socket a chance to send the packets ++ try ++ { ++ Thread.sleep( 100 ); ++ } catch ( InterruptedException ex ) ++ { ++ } ++ // Close the socket so we can rebind with the new process ++ MinecraftServer.getServer().getServerConnection().b(); ++ ++ // Give time for it to kick in ++ try ++ { ++ Thread.sleep( 100 ); ++ } catch ( InterruptedException ex ) ++ { ++ } ++ ++ // Actually shutdown ++ try ++ { ++ MinecraftServer.getServer().stop(); ++ } catch ( Throwable t ) ++ { ++ } ++ ++ // This will be done AFTER the server has completely halted ++ Thread shutdownHook = new Thread() ++ { ++ @Override ++ public void run() ++ { ++ try ++ { ++ String os = System.getProperty( "os.name" ).toLowerCase(); ++ if ( os.contains( "win" ) ) ++ { ++ Runtime.getRuntime().exec( "cmd /c start " + script.getPath() ); ++ } else ++ { ++ Runtime.getRuntime().exec( new String[] ++ { ++ "sh", script.getPath() ++ } ); ++ } ++ } catch ( Exception e ) ++ { ++ e.printStackTrace(); ++ } ++ } ++ }; ++ ++ shutdownHook.setDaemon( true ); ++ Runtime.getRuntime().addShutdownHook( shutdownHook ); ++ } else ++ { ++ System.out.println( "Startup script '" + SpigotConfig.restartScript + "' does not exist! Stopping server." ); ++ } ++ System.exit( 0 ); ++ } catch ( Exception ex ) ++ { ++ ex.printStackTrace(); ++ } ++ } ++} +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -0,0 +0,0 @@ public class SpigotConfig + outdatedClientMessage = transform( getString( "messages.outdated-client", outdatedClientMessage ) ); + outdatedServerMessage = transform( getString( "messages.outdated-server", outdatedServerMessage ) ); + } ++ ++ public static int timeoutTime = 60; ++ public static boolean restartOnCrash = true; ++ public static String restartScript = "./start.sh"; ++ public static String restartMessage; ++ private static void watchdog() ++ { ++ timeoutTime = getInt( "settings.timeout-time", timeoutTime ); ++ restartOnCrash = getBoolean( "settings.restart-on-crash", restartOnCrash ); ++ restartScript = getString( "settings.restart-script", restartScript ); ++ restartMessage = transform( getString( "messages.restart", "Server is restarting" ) ); ++ commands.put( "restart", new RestartCommand( "restart" ) ); ++ WatchdogThread.doStart( timeoutTime, restartOnCrash ); ++ } + } +diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -0,0 +0,0 @@ ++package org.spigotmc; ++ ++import java.lang.management.ManagementFactory; ++import java.lang.management.MonitorInfo; ++import java.lang.management.ThreadInfo; ++import java.util.logging.Level; ++import java.util.logging.Logger; ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.Bukkit; ++ ++public class WatchdogThread extends Thread ++{ ++ ++ private static WatchdogThread instance; ++ private final long timeoutTime; ++ private final boolean restart; ++ private volatile long lastTick; ++ private volatile boolean stopping; ++ ++ private WatchdogThread(long timeoutTime, boolean restart) ++ { ++ super( "Spigot Watchdog Thread" ); ++ this.timeoutTime = timeoutTime; ++ this.restart = restart; ++ } ++ ++ public static void doStart(int timeoutTime, boolean restart) ++ { ++ if ( instance == null ) ++ { ++ instance = new WatchdogThread( timeoutTime * 1000L, restart ); ++ instance.start(); ++ } ++ } ++ ++ public static void tick() ++ { ++ instance.lastTick = System.currentTimeMillis(); ++ } ++ ++ public static void doStop() ++ { ++ if ( instance != null ) ++ { ++ instance.stopping = true; ++ } ++ } ++ ++ @Override ++ public void run() ++ { ++ while ( !stopping ) ++ { ++ // ++ if ( lastTick != 0 && System.currentTimeMillis() > lastTick + timeoutTime ) ++ { ++ Logger log = Bukkit.getServer().getLogger(); ++ log.log( Level.SEVERE, "The server has stopped responding!" ); ++ log.log( Level.SEVERE, "Please report this to http://www.spigotmc.org/" ); ++ log.log( Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports" ); ++ log.log( Level.SEVERE, "Spigot version: " + Bukkit.getServer().getVersion() ); ++ // ++ log.log( Level.SEVERE, "------------------------------" ); ++ log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Spigot!):" ); ++ dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().primaryThread.getId(), Integer.MAX_VALUE ), log ); ++ log.log( Level.SEVERE, "------------------------------" ); ++ // ++ log.log( Level.SEVERE, "Entire Thread Dump:" ); ++ ThreadInfo[] threads = ManagementFactory.getThreadMXBean().dumpAllThreads( true, true ); ++ for ( ThreadInfo thread : threads ) ++ { ++ dumpThread( thread, log ); ++ } ++ log.log( Level.SEVERE, "------------------------------" ); ++ ++ if ( restart ) ++ { ++ RestartCommand.restart(); ++ } ++ break; ++ } ++ ++ try ++ { ++ sleep( 10000 ); ++ } catch ( InterruptedException ex ) ++ { ++ interrupt(); ++ } ++ } ++ } ++ ++ private static void dumpThread(ThreadInfo thread, Logger log) ++ { ++ log.log( Level.SEVERE, "------------------------------" ); ++ // ++ log.log( Level.SEVERE, "Current Thread: " + thread.getThreadName() ); ++ log.log( Level.SEVERE, "\tPID: " + thread.getThreadId() ++ + " | Suspended: " + thread.isSuspended() ++ + " | Native: " + thread.isInNative() ++ + " | State: " + thread.getThreadState() ); ++ if ( thread.getLockedMonitors().length != 0 ) ++ { ++ log.log( Level.SEVERE, "\tThread is waiting on monitor(s):" ); ++ for ( MonitorInfo monitor : thread.getLockedMonitors() ) ++ { ++ log.log( Level.SEVERE, "\t\tLocked on:" + monitor.getLockedStackFrame() ); ++ } ++ } ++ log.log( Level.SEVERE, "\tStack:" ); ++ // ++ for ( StackTraceElement stack : thread.getStackTrace() ) ++ { ++ log.log( Level.SEVERE, "\t\t" + stack ); ++ } ++ } ++} +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0056-Clear-Flower-Pot-on-Drop.patch b/CraftBukkit-Patches/0056-Clear-Flower-Pot-on-Drop.patch new file mode 100644 index 0000000000..2a4e75b227 --- /dev/null +++ b/CraftBukkit-Patches/0056-Clear-Flower-Pot-on-Drop.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Tue, 3 Dec 2013 11:07:48 +1100 +Subject: [PATCH] Clear Flower Pot on Drop + + +diff --git a/src/main/java/net/minecraft/server/BlockFlowerPot.java b/src/main/java/net/minecraft/server/BlockFlowerPot.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/BlockFlowerPot.java ++++ b/src/main/java/net/minecraft/server/BlockFlowerPot.java +@@ -0,0 +0,0 @@ public class BlockFlowerPot extends BlockContainer { + + if (tileentityflowerpot != null && tileentityflowerpot.a() != null) { + this.a(world, i, j, k, new ItemStack(tileentityflowerpot.a(), 1, tileentityflowerpot.b())); ++ tileentityflowerpot.a( null, 0 ); // Spigot + } + + super.remove(world, i, j, k, block, l); +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0057-Fix-some-chunks-not-being-sent-to-the-client.patch b/CraftBukkit-Patches/0057-Fix-some-chunks-not-being-sent-to-the-client.patch new file mode 100644 index 0000000000..25e0ff9f62 --- /dev/null +++ b/CraftBukkit-Patches/0057-Fix-some-chunks-not-being-sent-to-the-client.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Mon, 2 Dec 2013 23:42:09 +0000 +Subject: [PATCH] Fix some chunks not being sent to the client + + +diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Chunk.java ++++ b/src/main/java/net/minecraft/server/Chunk.java +@@ -0,0 +0,0 @@ public class Chunk { + } + + public boolean isReady() { +- return this.m && this.done && this.lit; ++ // Spigot Start ++ /* ++ * As of 1.7, Mojang added a check to make sure that only chunks which have been lit are sent to the client. ++ * Unfortunately this interferes with our modified chunk ticking algorithm, which will only tick chunks distant from the player on a very infrequent basis. ++ * We cannot unfortunately do this lighting stage during chunk gen as it appears to put a lot more noticeable load on the server, than when it is done at play time. ++ * For now at least we will simply send all chunks, in accordance with pre 1.7 behaviour. ++ */ ++ return true; ++ // Spigot End + } + + public ChunkCoordIntPair l() { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0058-Fix-Broken-Async-Chat.patch b/CraftBukkit-Patches/0058-Fix-Broken-Async-Chat.patch new file mode 100644 index 0000000000..3fe8dff1b4 --- /dev/null +++ b/CraftBukkit-Patches/0058-Fix-Broken-Async-Chat.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Thu, 5 Dec 2013 13:55:53 +1100 +Subject: [PATCH] Fix Broken Async Chat + + +diff --git a/src/main/java/net/minecraft/server/PacketPlayInChat.java b/src/main/java/net/minecraft/server/PacketPlayInChat.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PacketPlayInChat.java ++++ b/src/main/java/net/minecraft/server/PacketPlayInChat.java +@@ -0,0 +0,0 @@ public class PacketPlayInChat extends Packet { + } + // CraftBukkit end + +- public void handle(PacketListener packetlistener) { ++ // Spigot Start ++ private static final java.util.concurrent.ExecutorService executors = java.util.concurrent.Executors.newCachedThreadPool( ++ new com.google.common.util.concurrent.ThreadFactoryBuilder().setDaemon( true ).setNameFormat( "Async Chat Thread - #%d" ).build() ); ++ public void handle(final PacketListener packetlistener) ++ { ++ if ( a() ) ++ { ++ executors.submit( new Runnable() ++ { ++ ++ @Override ++ public void run() ++ { ++ PacketPlayInChat.this.a( (PacketPlayInListener) packetlistener ); ++ } ++ } ); ++ return; ++ } ++ // Spigot End + this.a((PacketPlayInListener) packetlistener); + } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0059-Allow-Teleportation-of-Vehicles-and-Passengers.patch b/CraftBukkit-Patches/0059-Allow-Teleportation-of-Vehicles-and-Passengers.patch new file mode 100644 index 0000000000..cdf89386fc --- /dev/null +++ b/CraftBukkit-Patches/0059-Allow-Teleportation-of-Vehicles-and-Passengers.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ItsHarry +Date: Thu, 5 Dec 2013 21:58:11 +0100 +Subject: [PATCH] Allow Teleportation of Vehicles and Passengers + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + return false; + } + +- if (entity.vehicle != null || entity.passenger != null) { +- return false; +- } ++ // Spigot Start ++ // if (entity.vehicle != null || entity.passenger != null) { ++ // return false; ++ // } ++ // Spigot End + + // From = Players current Location + Location from = this.getLocation(); +@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + if (event.isCancelled()) { + return false; + } ++ ++ // Spigot Start ++ eject(); ++ leaveVehicle(); ++ // Spigot End + + // Update the From Location + from = event.getFrom(); +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0060-Remove-OS-X-Special-Chars-from-Signs.patch b/CraftBukkit-Patches/0060-Remove-OS-X-Special-Chars-from-Signs.patch new file mode 100644 index 0000000000..0bd0a7dacd --- /dev/null +++ b/CraftBukkit-Patches/0060-Remove-OS-X-Special-Chars-from-Signs.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 8 Dec 2013 16:52:42 +1100 +Subject: [PATCH] Remove OS X Special Chars from Signs + + +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketPlayInListener { + + for (j = 0; j < 4; ++j) { + boolean flag = true; ++ packetplayinupdatesign.f()[j] = packetplayinupdatesign.f()[j].replaceAll( "\uF700", "" ).replaceAll( "\uF701", "" ); // Spigot - Mac OSX sends weird chars + + if (packetplayinupdatesign.f()[j].length() > 15) { + flag = false; +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0061-Orebfuscator.patch b/CraftBukkit-Patches/0061-Orebfuscator.patch new file mode 100644 index 0000000000..5ac28d58b8 --- /dev/null +++ b/CraftBukkit-Patches/0061-Orebfuscator.patch @@ -0,0 +1,429 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Thu, 16 May 2013 18:51:05 +1000 +Subject: [PATCH] Orebfuscator + + +diff --git a/src/main/java/net/minecraft/server/EntityFallingBlock.java b/src/main/java/net/minecraft/server/EntityFallingBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityFallingBlock.java ++++ b/src/main/java/net/minecraft/server/EntityFallingBlock.java +@@ -0,0 +0,0 @@ public class EntityFallingBlock extends Entity { + } + + this.world.setAir(i, j, k); ++ world.spigotConfig.antiXrayInstance.updateNearbyBlocks(world, i, j, k); // Spigot + } + + if (this.onGround) { +@@ -0,0 +0,0 @@ public class EntityFallingBlock extends Entity { + } + this.world.setTypeAndData(i, j, k, this.id, this.data, 3); + // CraftBukkit end ++ world.spigotConfig.antiXrayInstance.updateNearbyBlocks(world, i, j, k); // Spigot + + if (this.id instanceof BlockFalling) { + ((BlockFalling) this.id).a(this.world, i, j, k, this.data); +diff --git a/src/main/java/net/minecraft/server/Explosion.java b/src/main/java/net/minecraft/server/Explosion.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Explosion.java ++++ b/src/main/java/net/minecraft/server/Explosion.java +@@ -0,0 +0,0 @@ public class Explosion { + j = chunkposition.y; + k = chunkposition.z; + block = this.world.getType(i, j, k); ++ world.spigotConfig.antiXrayInstance.updateNearbyBlocks(world, i, j, k); // Spigot + if (flag) { + double d0 = (double) ((float) i + this.world.random.nextFloat()); + double d1 = (double) ((float) j + this.world.random.nextFloat()); +diff --git a/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java ++++ b/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java +@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk extends Packet { + + this.d = chunkmap.c; + this.c = chunkmap.b; ++ chunk.world.spigotConfig.antiXrayInstance.obfuscateSync(chunk.locX, chunk.locZ, i, chunkmap.a, chunk.world); // Spigot + + try { + this.f = chunkmap.a; +diff --git a/src/main/java/net/minecraft/server/PacketPlayOutMapChunkBulk.java b/src/main/java/net/minecraft/server/PacketPlayOutMapChunkBulk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PacketPlayOutMapChunkBulk.java ++++ b/src/main/java/net/minecraft/server/PacketPlayOutMapChunkBulk.java +@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunkBulk extends Packet { + } + }; + // CraftBukkit end ++ private World world; // Spigot + + public PacketPlayOutMapChunkBulk() {} + +@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunkBulk extends Packet { + Chunk chunk = (Chunk) list.get(k); + ChunkMap chunkmap = PacketPlayOutMapChunk.a(chunk, true, '\uffff'); + ++ // Spigot start ++ world = chunk.world; ++ /* + if (buildBuffer.length < j + chunkmap.a.length) { + byte[] abyte = new byte[j + chunkmap.a.length]; + +@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunkBulk extends Packet { + } + + System.arraycopy(chunkmap.a, 0, buildBuffer, j, chunkmap.a.length); ++ */ ++ // Spigot end + j += chunkmap.a.length; + this.a[k] = chunk.locX; + this.b[k] = chunk.locZ; +@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunkBulk extends Packet { + if (this.buffer != null) { + return; + } ++ // Spigot start ++ int finalBufferSize = 0; ++ // Obfuscate all sections ++ for (int i = 0; i < a.length; i++) { ++ world.spigotConfig.antiXrayInstance.obfuscate(a[i], b[i], c[i], inflatedBuffers[i], world); ++ finalBufferSize += inflatedBuffers[i].length; ++ } ++ ++ // Now it's time to efficiently copy the chunk to the build buffer ++ buildBuffer = new byte[finalBufferSize]; ++ int bufferLocation = 0; ++ for (int i = 0; i < a.length; i++) { ++ System.arraycopy(inflatedBuffers[i], 0, buildBuffer, bufferLocation, inflatedBuffers[i].length); ++ bufferLocation += inflatedBuffers[i].length; ++ } ++ // Spigot end + + Deflater deflater = localDeflater.get(); + deflater.reset(); +diff --git a/src/main/java/net/minecraft/server/PlayerInteractManager.java b/src/main/java/net/minecraft/server/PlayerInteractManager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerInteractManager.java ++++ b/src/main/java/net/minecraft/server/PlayerInteractManager.java +@@ -0,0 +0,0 @@ public class PlayerInteractManager { + this.o = i1; + } + } ++ world.spigotConfig.antiXrayInstance.updateNearbyBlocks(world, i, j, k); // Spigot + } + } + +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + return this.getType(i, k, j); + } + +- public Block getType(int i, int j, int k) { ++ // Spigot start ++ public Block getType(int i, int j, int k) ++ { ++ return getType( i, j, k, true ); ++ } ++ ++ public Block getType(int i, int j, int k, boolean useCaptured) { + // CraftBukkit start - tree generation +- if (captureTreeGeneration) { ++ if (captureTreeGeneration && useCaptured) { ++ // Spigot end + Iterator it = capturedBlockStates.iterator(); + while (it.hasNext()) { + BlockState previous = it.next(); +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + this.e(i, j + 1, k, block); + this.e(i, j, k - 1, block); + this.e(i, j, k + 1, block); ++ spigotConfig.antiXrayInstance.updateNearbyBlocks(this, i, j, k); // Spigot + } + + public void b(int i, int j, int k, Block block, int l) { +diff --git a/src/main/java/org/spigotmc/AntiXray.java b/src/main/java/org/spigotmc/AntiXray.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/org/spigotmc/AntiXray.java +@@ -0,0 +0,0 @@ ++package org.spigotmc; ++ ++import net.minecraft.util.gnu.trove.set.TByteSet; ++import net.minecraft.util.gnu.trove.set.hash.TByteHashSet; ++import net.minecraft.server.Block; ++import net.minecraft.server.Blocks; ++import net.minecraft.server.World; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++ ++public class AntiXray ++{ ++ ++ private static final CustomTimingsHandler update = new CustomTimingsHandler( "xray - update" ); ++ private static final CustomTimingsHandler obfuscate = new CustomTimingsHandler( "xray - obfuscate" ); ++ /*========================================================================*/ ++ // Used to keep track of which blocks to obfuscate ++ private final boolean[] obfuscateBlocks = new boolean[ Short.MAX_VALUE ]; ++ // Used to select a random replacement ore ++ private final byte[] replacementOres; ++ ++ public AntiXray(SpigotWorldConfig config) ++ { ++ // Set all listed blocks as true to be obfuscated ++ for ( int id : ( config.engineMode == 1 ) ? config.hiddenBlocks : config.replaceBlocks ) ++ { ++ obfuscateBlocks[id] = true; ++ } ++ ++ // For every block ++ TByteSet blocks = new TByteHashSet(); ++ for ( Integer i : config.hiddenBlocks ) ++ { ++ Block block = Block.getById( i ); ++ // Check it exists and is not a tile entity ++ if ( block != null && !block.isTileEntity() ) ++ { ++ // Add it to the set of replacement blocks ++ blocks.add( (byte) (int) i ); ++ } ++ } ++ // Bake it to a flat array of replacements ++ replacementOres = blocks.toArray(); ++ } ++ ++ /** ++ * Starts the timings handler, then updates all blocks within the set radius ++ * of the given coordinate, revealing them if they are hidden ores. ++ */ ++ public void updateNearbyBlocks(World world, int x, int y, int z) ++ { ++ if ( world.spigotConfig.antiXray ) ++ { ++ update.startTiming(); ++ updateNearbyBlocks( world, x, y, z, 2, false ); // 2 is the radius, we shouldn't change it as that would make it exponentially slower ++ update.stopTiming(); ++ } ++ } ++ ++ /** ++ * Starts the timings handler, and then removes all non exposed ores from ++ * the chunk buffer. ++ */ ++ public void obfuscateSync(int chunkX, int chunkY, int bitmask, byte[] buffer, World world) ++ { ++ if ( world.spigotConfig.antiXray ) ++ { ++ obfuscate.startTiming(); ++ obfuscate( chunkX, chunkY, bitmask, buffer, world ); ++ obfuscate.stopTiming(); ++ } ++ } ++ ++ /** ++ * Removes all non exposed ores from the chunk buffer. ++ */ ++ public void obfuscate(int chunkX, int chunkY, int bitmask, byte[] buffer, World world) ++ { ++ // If the world is marked as obfuscated ++ if ( world.spigotConfig.antiXray ) ++ { ++ // Initial radius to search around for air ++ int initialRadius = 1; ++ // Which block in the buffer we are looking at, anywhere from 0 to 16^4 ++ int index = 0; ++ // The iterator marking which random ore we should use next ++ int randomOre = 0; ++ ++ // Chunk corner X and Z blocks ++ int startX = chunkX << 4; ++ int startZ = chunkY << 4; ++ ++ byte replaceWithTypeId; ++ switch ( world.getWorld().getEnvironment() ) ++ { ++ case NETHER: ++ replaceWithTypeId = (byte) CraftMagicNumbers.getId(Blocks.NETHERRACK); ++ break; ++ case THE_END: ++ replaceWithTypeId = (byte) CraftMagicNumbers.getId(Blocks.WHITESTONE); ++ break; ++ default: ++ replaceWithTypeId = (byte) CraftMagicNumbers.getId(Blocks.STONE); ++ break; ++ } ++ ++ // Chunks can have up to 16 sections ++ for ( int i = 0; i < 16; i++ ) ++ { ++ // If the bitmask indicates this chunk is sent... ++ if ( ( bitmask & 1 << i ) != 0 ) ++ { ++ // Work through all blocks in the chunk, y,z,x ++ for ( int y = 0; y < 16; y++ ) ++ { ++ for ( int z = 0; z < 16; z++ ) ++ { ++ for ( int x = 0; x < 16; x++ ) ++ { ++ // For some reason we can get too far ahead of ourselves (concurrent modification on bulk chunks?) so if we do, just abort and move on ++ if ( index >= buffer.length ) ++ { ++ index++; ++ continue; ++ } ++ // Grab the block ID in the buffer. ++ // TODO: extended IDs are not yet supported ++ int blockId = buffer[index] & 0xFF; ++ // Check if the block should be obfuscated ++ if ( obfuscateBlocks[blockId] ) ++ { ++ // The world isn't loaded, bail out ++ if ( !isLoaded( world, startX + x, ( i << 4 ) + y, startZ + z, initialRadius ) ) ++ { ++ index++; ++ continue; ++ } ++ // On the otherhand, if radius is 0, or the nearby blocks are all non air, we can obfuscate ++ if ( !hasTransparentBlockAdjacent( world, startX + x, ( i << 4 ) + y, startZ + z, initialRadius ) ) ++ { ++ switch ( world.spigotConfig.engineMode ) ++ { ++ case 1: ++ // Replace with replacement material ++ buffer[index] = replaceWithTypeId; ++ break; ++ case 2: ++ // Replace with random ore. ++ if ( randomOre >= replacementOres.length ) ++ { ++ randomOre = 0; ++ } ++ buffer[index] = replacementOres[randomOre++]; ++ break; ++ } ++ } ++ } ++ ++ index++; ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ private void updateNearbyBlocks(World world, int x, int y, int z, int radius, boolean updateSelf) ++ { ++ // If the block in question is loaded ++ if ( world.isLoaded( x, y, z ) ) ++ { ++ // Get block id ++ Block block = world.getType(x, y, z); ++ ++ // See if it needs update ++ if ( updateSelf && obfuscateBlocks[Block.getId( block )] ) ++ { ++ // Send the update ++ world.notify( x, y, z ); ++ } ++ ++ // Check other blocks for updates ++ if ( radius > 0 ) ++ { ++ updateNearbyBlocks( world, x + 1, y, z, radius - 1, true ); ++ updateNearbyBlocks( world, x - 1, y, z, radius - 1, true ); ++ updateNearbyBlocks( world, x, y + 1, z, radius - 1, true ); ++ updateNearbyBlocks( world, x, y - 1, z, radius - 1, true ); ++ updateNearbyBlocks( world, x, y, z + 1, radius - 1, true ); ++ updateNearbyBlocks( world, x, y, z - 1, radius - 1, true ); ++ } ++ } ++ } ++ ++ private static boolean isLoaded(World world, int x, int y, int z, int radius) ++ { ++ return world.isLoaded( x, y, z ) ++ && ( radius == 0 || ++ ( isLoaded( world, x + 1, y, z, radius - 1 ) ++ && isLoaded( world, x - 1, y, z, radius - 1 ) ++ && isLoaded( world, x, y + 1, z, radius - 1 ) ++ && isLoaded( world, x, y - 1, z, radius - 1 ) ++ && isLoaded( world, x, y, z + 1, radius - 1 ) ++ && isLoaded( world, x, y, z - 1, radius - 1 ) ) ); ++ } ++ ++ private static boolean hasTransparentBlockAdjacent(World world, int x, int y, int z, int radius) ++ { ++ return !isSolidBlock(world.getType(x, y, z, false)) /* isSolidBlock */ ++ || ( radius > 0 ++ && ( hasTransparentBlockAdjacent( world, x + 1, y, z, radius - 1 ) ++ || hasTransparentBlockAdjacent( world, x - 1, y, z, radius - 1 ) ++ || hasTransparentBlockAdjacent( world, x, y + 1, z, radius - 1 ) ++ || hasTransparentBlockAdjacent( world, x, y - 1, z, radius - 1 ) ++ || hasTransparentBlockAdjacent( world, x, y, z + 1, radius - 1 ) ++ || hasTransparentBlockAdjacent( world, x, y, z - 1, radius - 1 ) ) ); ++ } ++ ++ private static boolean isSolidBlock(Block block) { ++ // Mob spawners are treated as solid blocks as far as the ++ // game is concerned for lighting and other tasks but for ++ // rendering they can be seen through therefor we special ++ // case them so that the antixray doesn't show the fake ++ // blocks around them. ++ return block.r() && block != Blocks.MOB_SPAWNER; ++ } ++} +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -0,0 +0,0 @@ + package org.spigotmc; + ++import java.util.Arrays; + import java.util.List; + import org.bukkit.Bukkit; + import org.bukkit.configuration.file.YamlConfiguration; +@@ -0,0 +0,0 @@ public class SpigotWorldConfig + arrowDespawnRate = getInt( "arrow-despawn-rate", 1200 ); + log( "Arrow Despawn Rate: " + arrowDespawnRate ); + } ++ ++ public boolean antiXray; ++ public int engineMode; ++ public List hiddenBlocks; ++ public List replaceBlocks; ++ public AntiXray antiXrayInstance; ++ private void antiXray() ++ { ++ antiXray = getBoolean( "anti-xray.enabled", true ); ++ log( "Anti X-Ray: " + antiXray ); ++ ++ engineMode = getInt( "anti-xray.engine-mode", 1 ); ++ log( "\tEngine Mode: " + engineMode ); ++ ++ if ( SpigotConfig.version < 5 ) ++ { ++ set( "anti-xray.blocks", null ); ++ } ++ hiddenBlocks = getList( "anti-xray.hide-blocks", Arrays.asList( new Integer[] ++ { ++ 14, 15, 16, 21, 48, 49, 54, 56, 73, 74, 82, 129, 130 ++ } ) ); ++ log( "\tHidden Blocks: " + hiddenBlocks ); ++ ++ replaceBlocks = getList( "anti-xray.replace-blocks", Arrays.asList( new Integer[] ++ { ++ 1, 5 ++ } ) ); ++ log( "\tReplace Blocks: " + replaceBlocks ); ++ ++ antiXrayInstance = new AntiXray( this ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0062-Optimize-DataWatcher.patch b/CraftBukkit-Patches/0062-Optimize-DataWatcher.patch new file mode 100644 index 0000000000..3bb41a05ba --- /dev/null +++ b/CraftBukkit-Patches/0062-Optimize-DataWatcher.patch @@ -0,0 +1,132 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Fri, 13 Dec 2013 11:45:47 +1100 +Subject: [PATCH] Optimize DataWatcher + +Use primitive orientated collections, as well as more effective copies across collections. + +diff --git a/src/main/java/net/minecraft/server/DataWatcher.java b/src/main/java/net/minecraft/server/DataWatcher.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/DataWatcher.java ++++ b/src/main/java/net/minecraft/server/DataWatcher.java +@@ -0,0 +0,0 @@ public class DataWatcher { + + private final Entity a; + private boolean b = true; +- private static final HashMap c = new HashMap(); +- private final Map d = new HashMap(); ++ // Spigot Start ++ private static final net.minecraft.util.gnu.trove.map.TObjectIntMap classToId = new net.minecraft.util.gnu.trove.map.hash.TObjectIntHashMap( 10, 0.5f, -1 ); ++ private final net.minecraft.util.gnu.trove.map.TIntObjectMap dataValues = new net.minecraft.util.gnu.trove.map.hash.TIntObjectHashMap( 10, 0.5f, -1 ); ++ // These exist as an attempt at backwards compatability for (broken) NMS plugins ++ private static final Map c = net.minecraft.util.gnu.trove.TDecorators.wrap( classToId ); ++ private final Map d = net.minecraft.util.gnu.trove.TDecorators.wrap( dataValues ); ++ // Spigot End + private boolean e; + private ReadWriteLock f = new ReentrantReadWriteLock(); + +@@ -0,0 +0,0 @@ public class DataWatcher { + } + + public void a(int i, Object object) { +- Integer integer = (Integer) c.get(object.getClass()); ++ int integer = classToId.get(object.getClass()); // Spigot + +- if (integer == null) { ++ if (integer == -1) { // Spigot + throw new IllegalArgumentException("Unknown data type: " + object.getClass()); + } else if (i > 31) { + throw new IllegalArgumentException("Data value id is too big with " + i + "! (Max is " + 31 + ")"); +- } else if (this.d.containsKey(Integer.valueOf(i))) { ++ } else if (this.dataValues.containsKey(i)) { // Spigot + throw new IllegalArgumentException("Duplicate id value for " + i + "!"); + } else { +- WatchableObject watchableobject = new WatchableObject(integer.intValue(), i, object); ++ WatchableObject watchableobject = new WatchableObject(integer, i, object); // Spigot + + this.f.writeLock().lock(); +- this.d.put(Integer.valueOf(i), watchableobject); ++ this.dataValues.put(i, watchableobject); // Spigot + this.f.writeLock().unlock(); + this.b = false; + } +@@ -0,0 +0,0 @@ public class DataWatcher { + WatchableObject watchableobject = new WatchableObject(j, i, null); + + this.f.writeLock().lock(); +- this.d.put(Integer.valueOf(i), watchableobject); ++ this.dataValues.put(i, watchableobject); // Spigot + this.f.writeLock().unlock(); + this.b = false; + } +@@ -0,0 +0,0 @@ public class DataWatcher { + WatchableObject watchableobject; + + try { +- watchableobject = (WatchableObject) this.d.get(Integer.valueOf(i)); ++ watchableobject = (WatchableObject) this.dataValues.get(i); // Spigot + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.a(throwable, "Getting synched entity data"); + CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Synched entity data"); +@@ -0,0 +0,0 @@ public class DataWatcher { + + if (this.e) { + this.f.readLock().lock(); +- Iterator iterator = this.d.values().iterator(); ++ Iterator iterator = this.dataValues.valueCollection().iterator(); // Spigot + + while (iterator.hasNext()) { + WatchableObject watchableobject = (WatchableObject) iterator.next(); +@@ -0,0 +0,0 @@ public class DataWatcher { + + public void a(PacketDataSerializer packetdataserializer) { + this.f.readLock().lock(); +- Iterator iterator = this.d.values().iterator(); ++ Iterator iterator = this.dataValues.valueCollection().iterator(); // Spigot + + while (iterator.hasNext()) { + WatchableObject watchableobject = (WatchableObject) iterator.next(); +@@ -0,0 +0,0 @@ public class DataWatcher { + } + + public List c() { +- ArrayList arraylist = null; ++ ArrayList arraylist = new ArrayList(); // Spigot + + this.f.readLock().lock(); + +- WatchableObject watchableobject; +- +- for (Iterator iterator = this.d.values().iterator(); iterator.hasNext(); arraylist.add(watchableobject)) { +- watchableobject = (WatchableObject) iterator.next(); +- if (arraylist == null) { +- arraylist = new ArrayList(); +- } +- } ++ arraylist.addAll(this.dataValues.valueCollection()); // Spigot + + this.f.readLock().unlock(); + return arraylist; +@@ -0,0 +0,0 @@ public class DataWatcher { + } + + static { +- c.put(Byte.class, Integer.valueOf(0)); +- c.put(Short.class, Integer.valueOf(1)); +- c.put(Integer.class, Integer.valueOf(2)); +- c.put(Float.class, Integer.valueOf(3)); +- c.put(String.class, Integer.valueOf(4)); +- c.put(ItemStack.class, Integer.valueOf(5)); +- c.put(ChunkCoordinates.class, Integer.valueOf(6)); ++ // Spigot Start - remove valueOf ++ classToId.put(Byte.class, 0); ++ classToId.put(Short.class, 1); ++ classToId.put(Integer.class, 2); ++ classToId.put(Float.class, 3); ++ classToId.put(String.class, 4); ++ classToId.put(ItemStack.class, 5); ++ classToId.put(ChunkCoordinates.class, 6); ++ // Spigot End + } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0063-Fire-PreLogin-Events-in-Offline-Mode.patch b/CraftBukkit-Patches/0063-Fire-PreLogin-Events-in-Offline-Mode.patch new file mode 100644 index 0000000000..5da1919131 --- /dev/null +++ b/CraftBukkit-Patches/0063-Fire-PreLogin-Events-in-Offline-Mode.patch @@ -0,0 +1,157 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Wed, 18 Dec 2013 13:32:10 +1100 +Subject: [PATCH] Fire PreLogin Events in Offline Mode + + +diff --git a/src/main/java/net/minecraft/server/LoginListener.java b/src/main/java/net/minecraft/server/LoginListener.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/LoginListener.java ++++ b/src/main/java/net/minecraft/server/LoginListener.java +@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { + } + } + ++ // Spigot start ++ public void initUUID() ++ { ++ UUID uuid = UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + this.i.getName() ).getBytes( Charsets.UTF_8 ) ); ++ ++ this.i = new GameProfile( uuid, this.i.getName() ); ++ } ++ // Spigot end ++ + public void c() { ++ // Spigot start - Moved to initUUID ++ /* + if (!this.i.isComplete()) { + this.i = this.a(this.i); + } ++ */ ++ // Spigot end + + // CraftBukkit start - fire PlayerLoginEvent + EntityPlayer s = this.server.getPlayerList().attemptLogin(this, this.i, this.hostname); +@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { + this.g = EnumProtocolState.KEY; + this.networkManager.handle(new PacketLoginOutEncryptionBegin(this.j, this.server.K().getPublic(), this.e), new GenericFutureListener[0]); + } else { +- this.g = EnumProtocolState.READY_TO_ACCEPT; ++ (new ThreadPlayerLookupUUID(this, "User Authenticator #" + b.incrementAndGet())).start(); // Spigot + } + } + +diff --git a/src/main/java/net/minecraft/server/ThreadPlayerLookupUUID.java b/src/main/java/net/minecraft/server/ThreadPlayerLookupUUID.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/ThreadPlayerLookupUUID.java ++++ b/src/main/java/net/minecraft/server/ThreadPlayerLookupUUID.java +@@ -0,0 +0,0 @@ class ThreadPlayerLookupUUID extends Thread { + GameProfile gameprofile = LoginListener.a(this.a); + + try { ++ // Spigot Start ++ if ( !LoginListener.c( this.a ).getOnlineMode() ) ++ { ++ a.initUUID(); ++ fireLoginEvents(); ++ return; ++ } ++ // Spigot End + String s = (new BigInteger(MinecraftEncryption.a(LoginListener.b(this.a), LoginListener.c(this.a).K().getPublic(), LoginListener.d(this.a)))).toString(16); + + LoginListener.a(this.a, LoginListener.c(this.a).av().hasJoinedServer(new GameProfile((UUID) null, gameprofile.getName()), s)); + if (LoginListener.a(this.a) != null) { +- // CraftBukkit start - fire PlayerPreLoginEvent +- if (!this.a.networkManager.isConnected()) { +- return; +- } +- +- String playerName = LoginListener.a(this.a).getName(); +- java.net.InetAddress address = ((java.net.InetSocketAddress) a.networkManager.getSocketAddress()).getAddress(); +- java.util.UUID uniqueId = LoginListener.a(this.a).getId(); +- final org.bukkit.craftbukkit.CraftServer server = LoginListener.c(this.a).server; +- +- AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId); +- server.getPluginManager().callEvent(asyncEvent); +- +- if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { +- final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId); +- if (asyncEvent.getResult() != PlayerPreLoginEvent.Result.ALLOWED) { +- event.disallow(asyncEvent.getResult(), asyncEvent.getKickMessage()); +- } +- Waitable waitable = new Waitable() { +- @Override +- protected PlayerPreLoginEvent.Result evaluate() { +- server.getPluginManager().callEvent(event); +- return event.getResult(); +- }}; +- +- LoginListener.c(this.a).processQueue.add(waitable); +- if (waitable.get() != PlayerPreLoginEvent.Result.ALLOWED) { +- this.a.disconnect(event.getKickMessage()); +- return; +- } +- } else { +- if (asyncEvent.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) { +- this.a.disconnect(asyncEvent.getKickMessage()); +- return; +- } +- } +- // CraftBukkit end +- +- LoginListener.e().info("UUID of player " + LoginListener.a(this.a).getName() + " is " + LoginListener.a(this.a).getId()); +- LoginListener.a(this.a, EnumProtocolState.READY_TO_ACCEPT); ++ fireLoginEvents(); // Spigot + } else if (LoginListener.c(this.a).N()) { + LoginListener.e().warn("Failed to verify username but will let them in anyway!"); + LoginListener.a(this.a, this.a.a(gameprofile)); +@@ -0,0 +0,0 @@ class ThreadPlayerLookupUUID extends Thread { + // CraftBukkit end + } + } ++ ++ private void fireLoginEvents() throws Exception ++ { ++ // CraftBukkit start - fire PlayerPreLoginEvent ++ if (!this.a.networkManager.isConnected()) { ++ return; ++ } ++ ++ String playerName = LoginListener.a(this.a).getName(); ++ java.net.InetAddress address = ((java.net.InetSocketAddress) a.networkManager.getSocketAddress()).getAddress(); ++ java.util.UUID uniqueId = LoginListener.a(this.a).getId(); ++ final org.bukkit.craftbukkit.CraftServer server = LoginListener.c(this.a).server; ++ ++ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId); ++ server.getPluginManager().callEvent(asyncEvent); ++ ++ if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { ++ final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId); ++ if (asyncEvent.getResult() != PlayerPreLoginEvent.Result.ALLOWED) { ++ event.disallow(asyncEvent.getResult(), asyncEvent.getKickMessage()); ++ } ++ Waitable waitable = new Waitable() { ++ @Override ++ protected PlayerPreLoginEvent.Result evaluate() { ++ server.getPluginManager().callEvent(event); ++ return event.getResult(); ++ }}; ++ ++ LoginListener.c(this.a).processQueue.add(waitable); ++ if (waitable.get() != PlayerPreLoginEvent.Result.ALLOWED) { ++ this.a.disconnect(event.getKickMessage()); ++ return; ++ } ++ } else { ++ if (asyncEvent.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) { ++ this.a.disconnect(asyncEvent.getKickMessage()); ++ return; ++ } ++ } ++ // CraftBukkit end ++ ++ LoginListener.e().info("UUID of player " + LoginListener.a(this.a).getName() + " is " + LoginListener.a(this.a).getId()); ++ LoginListener.a(this.a, EnumProtocolState.READY_TO_ACCEPT); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0064-BungeeCord-Support.patch b/CraftBukkit-Patches/0064-BungeeCord-Support.patch new file mode 100644 index 0000000000..339eb3e315 --- /dev/null +++ b/CraftBukkit-Patches/0064-BungeeCord-Support.patch @@ -0,0 +1,213 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 1 Dec 2013 18:18:41 +1100 +Subject: [PATCH] BungeeCord Support + +Provides support for IP forwarding via BungeeCord. + +diff --git a/src/main/java/net/minecraft/server/HandshakeListener.java b/src/main/java/net/minecraft/server/HandshakeListener.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/HandshakeListener.java ++++ b/src/main/java/net/minecraft/server/HandshakeListener.java +@@ -0,0 +0,0 @@ + package net.minecraft.server; + ++import net.minecraft.util.com.mojang.authlib.properties.Property; // Spigot + import net.minecraft.util.io.netty.util.concurrent.GenericFutureListener; + + // CraftBukkit start + import java.net.InetAddress; + import java.util.HashMap; ++import net.minecraft.util.com.mojang.util.UUIDTypeAdapter; + // CraftBukkit end + + public class HandshakeListener implements PacketHandshakingInListener { + ++ private static final com.google.gson.Gson gson = new com.google.gson.Gson(); // Spigot + // CraftBukkit start - add fields + private static final HashMap throttleTracker = new HashMap(); + private static int throttleCounter = 0; +@@ -0,0 +0,0 @@ public class HandshakeListener implements PacketHandshakingInListener { + this.b.close(chatcomponenttext); + } else { + this.b.a((PacketListener) (new LoginListener(this.a, this.b))); ++ // Spigot Start ++ if (org.spigotmc.SpigotConfig.bungee) { ++ String[] split = packethandshakinginsetprotocol.b.split("\00"); ++ if ( split.length == 3 || split.length == 4 ) { ++ packethandshakinginsetprotocol.b = split[0]; ++ b.n = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) b.getSocketAddress()).getPort()); ++ b.spoofedUUID = UUIDTypeAdapter.fromString( split[2] ); ++ } else ++ { ++ chatcomponenttext = new ChatComponentText("If you wish to use IP forwarding, please enable it in your BungeeCord config as well!"); ++ this.b.handle(new PacketLoginOutDisconnect(chatcomponenttext), new GenericFutureListener[0]); ++ this.b.close(chatcomponenttext); ++ return; ++ } ++ if ( split.length == 4 ) ++ { ++ b.spoofedProfile = gson.fromJson(split[3], Property[].class); ++ } ++ } ++ // Spigot End + ((LoginListener) this.b.getPacketListener()).hostname = packethandshakinginsetprotocol.b + ":" + packethandshakinginsetprotocol.c; // CraftBukkit - set hostname + } + break; +diff --git a/src/main/java/net/minecraft/server/LoginListener.java b/src/main/java/net/minecraft/server/LoginListener.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/LoginListener.java ++++ b/src/main/java/net/minecraft/server/LoginListener.java +@@ -0,0 +0,0 @@ import javax.crypto.SecretKey; + + import net.minecraft.util.com.google.common.base.Charsets; + import net.minecraft.util.com.mojang.authlib.GameProfile; ++import net.minecraft.util.com.mojang.authlib.properties.Property; + import net.minecraft.util.io.netty.util.concurrent.GenericFutureListener; + import net.minecraft.util.org.apache.commons.lang3.Validate; + import org.apache.logging.log4j.LogManager; +@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { + // Spigot start + public void initUUID() + { +- UUID uuid = UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + this.i.getName() ).getBytes( Charsets.UTF_8 ) ); ++ UUID uuid; ++ if ( networkManager.spoofedUUID != null ) ++ { ++ uuid = networkManager.spoofedUUID; ++ } else ++ { ++ uuid = UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + this.i.getName() ).getBytes( Charsets.UTF_8 ) ); ++ } + + this.i = new GameProfile( uuid, this.i.getName() ); ++ ++ if (networkManager.spoofedProfile != null) ++ { ++ for ( Property property : networkManager.spoofedProfile ) ++ { ++ this.i.getProperties().put( property.getName(), property ); ++ } ++ } + } + // Spigot end + +diff --git a/src/main/java/net/minecraft/server/NetworkManager.java b/src/main/java/net/minecraft/server/NetworkManager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/NetworkManager.java ++++ b/src/main/java/net/minecraft/server/NetworkManager.java +@@ -0,0 +0,0 @@ import javax.crypto.SecretKey; + + import net.minecraft.util.com.google.common.collect.Queues; + import net.minecraft.util.com.google.common.util.concurrent.ThreadFactoryBuilder; ++import net.minecraft.util.com.mojang.authlib.properties.Property; + import net.minecraft.util.io.netty.channel.Channel; + import net.minecraft.util.io.netty.channel.ChannelFutureListener; + import net.minecraft.util.io.netty.channel.ChannelHandlerContext; +@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler { + private final Queue k = Queues.newConcurrentLinkedQueue(); + private final Queue l = Queues.newConcurrentLinkedQueue(); + private Channel m; +- private SocketAddress n; ++ // Spigot Start ++ public SocketAddress n; ++ public java.util.UUID spoofedUUID; ++ public Property[] spoofedProfile; ++ // Spigot End + private PacketListener o; + private EnumProtocol p; + private IChatBaseComponent q; +@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler { + static Channel a(NetworkManager networkmanager) { + return networkmanager.m; + } ++ ++ // Spigot Start ++ public SocketAddress getRawAddress() ++ { ++ return this.m.remoteAddress(); ++ } ++ // Spigot End + } +diff --git a/src/main/java/net/minecraft/server/PacketHandshakingInSetProtocol.java b/src/main/java/net/minecraft/server/PacketHandshakingInSetProtocol.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PacketHandshakingInSetProtocol.java ++++ b/src/main/java/net/minecraft/server/PacketHandshakingInSetProtocol.java +@@ -0,0 +0,0 @@ public class PacketHandshakingInSetProtocol extends Packet { + + public void a(PacketDataSerializer packetdataserializer) throws IOException { // CraftBukkit - added throws + this.a = packetdataserializer.a(); +- this.b = packetdataserializer.c(255); ++ this.b = packetdataserializer.c(Short.MAX_VALUE); // Spigot + this.c = packetdataserializer.readUnsignedShort(); + this.d = EnumProtocol.a(packetdataserializer.a()); + } +diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerList.java ++++ b/src/main/java/net/minecraft/server/PlayerList.java +@@ -0,0 +0,0 @@ public abstract class PlayerList { + + EntityPlayer entity = new EntityPlayer(this.server, this.server.getWorldServer(0), gameprofile, new PlayerInteractManager(this.server.getWorldServer(0))); + Player player = entity.getBukkitEntity(); +- PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress()); ++ PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.networkManager.getRawAddress()).getAddress()); + String s; + + if (this.j.isBanned(gameprofile) && !this.j.get(gameprofile).hasExpired()) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -0,0 +0,0 @@ public final class CraftServer implements Server { + + @Override + public long getConnectionThrottle() { +- return this.configuration.getInt("settings.connection-throttle"); ++ // Spigot Start - Automatically set connection throttle for bungee configurations ++ if (org.spigotmc.SpigotConfig.bungee) { ++ return -1; ++ } else { ++ return this.configuration.getInt("settings.connection-throttle"); ++ } ++ // Spigot End + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + { + + @Override ++ public InetSocketAddress getRawAddress() ++ { ++ return (InetSocketAddress) getHandle().playerConnection.networkManager.getRawAddress(); ++ } ++ ++ @Override + public boolean getCollidesWithEntities() + { + return getHandle().collidesWithEntities; +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -0,0 +0,0 @@ public class SpigotConfig + commands.put( "restart", new RestartCommand( "restart" ) ); + WatchdogThread.doStart( timeoutTime, restartOnCrash ); + } ++ ++ public static boolean bungee; ++ private static void bungee() { ++ if ( version < 4 ) ++ { ++ set( "settings.bungeecord", false ); ++ System.out.println( "Oudated config, disabling BungeeCord support!" ); ++ } ++ bungee = getBoolean( "settings.bungeecord", false ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0065-Allow-Disabling-Zombie-Villager-Aggression.patch b/CraftBukkit-Patches/0065-Allow-Disabling-Zombie-Villager-Aggression.patch new file mode 100644 index 0000000000..c3b16cff87 --- /dev/null +++ b/CraftBukkit-Patches/0065-Allow-Disabling-Zombie-Villager-Aggression.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dylan Xaldin +Date: Thu, 12 Dec 2013 18:05:03 -0600 +Subject: [PATCH] Allow Disabling Zombie Villager Aggression + +Ability to configure if Zombies will be aggressive towards Villagers. + +diff --git a/src/main/java/net/minecraft/server/EntityZombie.java b/src/main/java/net/minecraft/server/EntityZombie.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityZombie.java ++++ b/src/main/java/net/minecraft/server/EntityZombie.java +@@ -0,0 +0,0 @@ public class EntityZombie extends EntityMonster { + this.getNavigation().b(true); + this.goalSelector.a(0, new PathfinderGoalFloat(this)); + this.goalSelector.a(2, new PathfinderGoalMeleeAttack(this, EntityHuman.class, 1.0D, false)); +- this.goalSelector.a(4, new PathfinderGoalMeleeAttack(this, EntityVillager.class, 1.0D, true)); ++ if ( world.spigotConfig.zombieAggressiveTowardsVillager ) { this.goalSelector.a(4, new PathfinderGoalMeleeAttack(this, EntityVillager.class, 1.0D, true)); } // Spigot + this.goalSelector.a(5, new PathfinderGoalMoveTowardsRestriction(this, 1.0D)); + this.goalSelector.a(6, new PathfinderGoalMoveThroughVillage(this, 1.0D, false)); + this.goalSelector.a(7, new PathfinderGoalRandomStroll(this, 1.0D)); +@@ -0,0 +0,0 @@ public class EntityZombie extends EntityMonster { + this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this)); + this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, true)); + this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget(this, EntityHuman.class, 0, true)); +- this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget(this, EntityVillager.class, 0, false)); ++ if ( world.spigotConfig.zombieAggressiveTowardsVillager ) { this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget(this, EntityVillager.class, 0, false)); } // Spigot + this.a(0.6F, 1.8F); + } + +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -0,0 +0,0 @@ public class SpigotWorldConfig + + antiXrayInstance = new AntiXray( this ); + } ++ ++ public boolean zombieAggressiveTowardsVillager; ++ private void zombieAggressiveTowardsVillager() ++ { ++ zombieAggressiveTowardsVillager = getBoolean( "zombie-aggressive-towards-villager", true ); ++ log( "Zombie Aggressive Towards Villager: " + zombieAggressiveTowardsVillager ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0066-Configurable-Amount-of-Netty-Threads.patch b/CraftBukkit-Patches/0066-Configurable-Amount-of-Netty-Threads.patch new file mode 100644 index 0000000000..99bf5a9d5f --- /dev/null +++ b/CraftBukkit-Patches/0066-Configurable-Amount-of-Netty-Threads.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Fri, 13 Dec 2013 11:58:58 +1100 +Subject: [PATCH] Configurable Amount of Netty Threads + +This brings back the option that the Spigot version of netty saw. By default Netty will try and use cores*2 threads, however if running multiple servers on the same machine, this can be too many threads. Additionally some people have 16 core servers. If 32 Netty threads are allowed in this setup, then the lock contention, and thus blocking between threads becomes much greater, leading to decreased performance. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + private final List n = new ArrayList(); + private final ICommandHandler o; + public final MethodProfiler methodProfiler = new MethodProfiler(); +- private final ServerConnection p; ++ private ServerConnection p; // Spigot + private final ServerPing q = new ServerPing(); + private final Random r = new Random(); + private String serverIp; +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + j = this; + this.d = proxy; + // this.universe = file1; // CraftBukkit +- this.p = new ServerConnection(this); ++ // this.p = new ServerConnection(this); // Spigot + this.o = new CommandDispatcher(); + // this.convertable = new WorldLoaderServer(file1); // CraftBukkit - moved to DedicatedServer.init + this.T = new YggdrasilAuthenticationService(proxy, UUID.randomUUID().toString()); +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + } + // Spigot End + public ServerConnection ai() { +- return this.p; ++ return ( this.p ) == null ? this.p = new ServerConnection( this ) : this.p; // Spigot + } + + public boolean ak() { +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -0,0 +0,0 @@ public class SpigotConfig + } + bungee = getBoolean( "settings.bungeecord", false ); + } ++ ++ private static void nettyThreads() ++ { ++ int count = getInt( "settings.netty-threads", 4 ); ++ System.setProperty( "io.netty.eventLoopThreads", Integer.toString( count ) ); ++ Bukkit.getLogger().log( Level.INFO, "Using {0} threads for Netty based IO", count ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0067-Prevent-Mineshaft-Saving.patch b/CraftBukkit-Patches/0067-Prevent-Mineshaft-Saving.patch new file mode 100644 index 0000000000..fa69feed8e --- /dev/null +++ b/CraftBukkit-Patches/0067-Prevent-Mineshaft-Saving.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Fri, 13 Dec 2013 15:21:02 +1100 +Subject: [PATCH] Prevent Mineshaft Saving + + +diff --git a/src/main/java/net/minecraft/server/StructureGenerator.java b/src/main/java/net/minecraft/server/StructureGenerator.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/StructureGenerator.java ++++ b/src/main/java/net/minecraft/server/StructureGenerator.java +@@ -0,0 +0,0 @@ public abstract class StructureGenerator extends WorldGenBase { + private void a(World world) { + if (this.e == null) { + // Spigot Start +- if ( world.spigotConfig.saveStructureInfo ) ++ if ( world.spigotConfig.saveStructureInfo && !this.a().equals( "Mineshaft" ) ) + { + this.e = (PersistentStructure) world.a(PersistentStructure.class, this.a()); + } else +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0068-Log-Cause-of-Unexpected-Exceptions.patch b/CraftBukkit-Patches/0068-Log-Cause-of-Unexpected-Exceptions.patch new file mode 100644 index 0000000000..b636806913 --- /dev/null +++ b/CraftBukkit-Patches/0068-Log-Cause-of-Unexpected-Exceptions.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Wed, 18 Dec 2013 13:39:14 +1100 +Subject: [PATCH] Log Cause of Unexpected Exceptions + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + } + } catch (Throwable throwable) { + i.error("Encountered an unexpected exception", throwable); ++ // Spigot Start ++ if ( throwable.getCause() != null ) ++ { ++ i.error( "\tCause of unexpected exception was", throwable.getCause() ); ++ } ++ // Spigot End + CrashReport crashreport = null; + + if (throwable instanceof ReportedException) { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0069-Particle-API.patch b/CraftBukkit-Patches/0069-Particle-API.patch new file mode 100644 index 0000000000..d737e579dd --- /dev/null +++ b/CraftBukkit-Patches/0069-Particle-API.patch @@ -0,0 +1,173 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Fri, 20 Dec 2013 21:36:06 +0000 +Subject: [PATCH] Particle API + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftEffect.java b/src/main/java/org/bukkit/craftbukkit/CraftEffect.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftEffect.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftEffect.java +@@ -0,0 +0,0 @@ public class CraftEffect { + Validate.isTrue(((Material) data).isBlock(), "Material is not a block!"); + datavalue = ((Material) data).getId(); + break; ++ case ITEM_BREAK: ++ datavalue = ((Material) data).getId(); + default: + datavalue = 0; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -0,0 +0,0 @@ public class CraftWorld implements World { + Validate.isTrue(effect.getData() == null, "Wrong kind of data for this effect!"); + } + +- int datavalue = data == null ? 0 : CraftEffect.getDataValue(effect, data); +- playEffect(loc, effect, datavalue, radius); ++ if (data != null && data.getClass().equals( org.bukkit.material.MaterialData.class )) { ++ org.bukkit.material.MaterialData materialData = (org.bukkit.material.MaterialData) data; ++ Validate.isTrue( materialData.getItemType().isBlock(), "Material must be block" ); ++ spigot().playEffect( loc, effect, materialData.getItemType().getId(), materialData.getData(), 0, 0, 0, 1, 1, radius ); ++ } else { ++ int dataValue = data == null ? 0 : CraftEffect.getDataValue( effect, data ); ++ playEffect( loc, effect, dataValue, radius ); ++ } + } + + public void playEffect(Location location, Effect effect, int data, int radius) { +- Validate.notNull(location, "Location cannot be null"); +- Validate.notNull(effect, "Effect cannot be null"); +- Validate.notNull(location.getWorld(), "World cannot be null"); +- int packetData = effect.getId(); +- PacketPlayOutWorldEvent packet = new PacketPlayOutWorldEvent(packetData, location.getBlockX(), location.getBlockY(), location.getBlockZ(), data, false); +- int distance; +- radius *= radius; +- +- for (Player player : getPlayers()) { +- if (((CraftPlayer) player).getHandle().playerConnection == null) continue; +- if (!location.getWorld().equals(player.getWorld())) continue; +- +- distance = (int) player.getLocation().distanceSquared(location); +- if (distance <= radius) { +- ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); +- } +- } ++ spigot().playEffect( location, effect, data, 0, 0, 0, 0, 1, 1, radius ); + } + + public T spawn(Location location, Class clazz) throws IllegalArgumentException { +@@ -0,0 +0,0 @@ public class CraftWorld implements World { + // Spigot start + private final Spigot spigot = new Spigot() + { ++ @Override ++ public void playEffect( Location location, Effect effect, int id, int data, float offsetX, float offsetY, float offsetZ, float speed, int particleCount, int radius ) ++ { ++ Validate.notNull( location, "Location cannot be null" ); ++ Validate.notNull( effect, "Effect cannot be null" ); ++ Validate.notNull( location.getWorld(), "World cannot be null" ); ++ Packet packet; ++ if ( effect.getType() != Effect.Type.PARTICLE ) ++ { ++ int packetData = effect.getId(); ++ packet = new PacketPlayOutWorldEvent( packetData, location.getBlockX(), location.getBlockY(), location.getBlockZ(), id, false ); ++ } else ++ { ++ StringBuilder particleFullName = new StringBuilder(); ++ particleFullName.append( effect.getName() ); ++ if ( effect.getData() != null && ( effect.getData().equals( Material.class ) || effect.getData().equals( org.bukkit.material.MaterialData.class ) ) ) ++ { ++ particleFullName.append( '_' ).append( id ); ++ } ++ if ( effect.getData() != null && effect.getData().equals( org.bukkit.material.MaterialData.class ) ) ++ { ++ particleFullName.append( '_' ).append( data ); ++ } ++ packet = new PacketPlayOutWorldParticles( particleFullName.toString(), (float) location.getX(), (float) location.getY(), (float) location.getZ(), offsetX, offsetY, offsetZ, speed, particleCount ); ++ } ++ int distance; ++ radius *= radius; ++ for ( Player player : getPlayers() ) ++ { ++ if ( ( (CraftPlayer) player ).getHandle().playerConnection == null ) ++ { ++ continue; ++ } ++ if ( !location.getWorld().equals( player.getWorld() ) ) ++ { ++ continue; ++ } ++ distance = (int) player.getLocation().distanceSquared( location ); ++ if ( distance <= radius ) ++ { ++ ( (CraftPlayer) player ).getHandle().playerConnection.sendPacket( packet ); ++ } ++ } ++ } ++ ++ @Override ++ public void playEffect( Location location, Effect effect ) ++ { ++ CraftWorld.this.playEffect( location, effect, 0 ); ++ } + }; + + public Spigot spigot() +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + server.getServer().getPlayerList().moveToWorld( getHandle(), 0, false ); + } + } ++ ++ @Override ++ public void playEffect( Location location, Effect effect, int id, int data, float offsetX, float offsetY, float offsetZ, float speed, int particleCount, int radius ) ++ { ++ Validate.notNull( location, "Location cannot be null" ); ++ Validate.notNull( effect, "Effect cannot be null" ); ++ Validate.notNull( location.getWorld(), "World cannot be null" ); ++ Packet packet; ++ if ( effect.getType() != Effect.Type.PARTICLE ) ++ { ++ int packetData = effect.getId(); ++ packet = new PacketPlayOutWorldEvent( packetData, location.getBlockX(), location.getBlockY(), location.getBlockZ(), id, false ); ++ } else ++ { ++ StringBuilder particleFullName = new StringBuilder(); ++ particleFullName.append( effect.getName() ); ++ if ( effect.getData() != null && ( effect.getData().equals( Material.class ) || effect.getData().equals( org.bukkit.material.MaterialData.class ) ) ) ++ { ++ particleFullName.append( '_' ).append( id ); ++ } ++ if ( effect.getData() != null && effect.getData().equals( org.bukkit.material.MaterialData.class ) ) ++ { ++ particleFullName.append( '_' ).append( data ); ++ } ++ packet = new PacketPlayOutWorldParticles( particleFullName.toString(), (float) location.getX(), (float) location.getY(), (float) location.getZ(), offsetX, offsetY, offsetZ, speed, particleCount ); ++ } ++ int distance; ++ radius *= radius; ++ if ( getHandle().playerConnection == null ) ++ { ++ return; ++ } ++ if ( !location.getWorld().equals( getWorld() ) ) ++ { ++ return; ++ } ++ ++ distance = (int) getLocation().distanceSquared( location ); ++ if ( distance <= radius ) ++ { ++ getHandle().playerConnection.sendPacket( packet ); ++ } ++ } + }; + + public Player.Spigot spigot() +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0070-Fix-Biome-Decoration-Crashes.patch b/CraftBukkit-Patches/0070-Fix-Biome-Decoration-Crashes.patch new file mode 100644 index 0000000000..a7880bebf9 --- /dev/null +++ b/CraftBukkit-Patches/0070-Fix-Biome-Decoration-Crashes.patch @@ -0,0 +1,109 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 5 Jan 2014 09:35:01 +1100 +Subject: [PATCH] Fix Biome Decoration Crashes + +We don't really know what affect this will have on the terrain generation, but its better than crashing and not having terrain generate at all! + +diff --git a/src/main/java/net/minecraft/server/BiomeDecorator.java b/src/main/java/net/minecraft/server/BiomeDecorator.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/BiomeDecorator.java ++++ b/src/main/java/net/minecraft/server/BiomeDecorator.java +@@ -0,0 +0,0 @@ public class BiomeDecorator { + for (j = 0; j < this.z; ++j) { + k = this.c + this.b.nextInt(16) + 8; + l = this.d + this.b.nextInt(16) + 8; +- i1 = this.b.nextInt(this.a.getHighestBlockYAt(k, l) * 2); ++ i1 = this.b.nextInt(this.getHighestBlockYAt(k, l) * 2); // Spigot + WorldGenerator worldgenerator = biomebase.b(this.b); + + worldgenerator.generate(this.a, this.b, k, i1, l); +@@ -0,0 +0,0 @@ public class BiomeDecorator { + for (j = 0; j < this.A; ++j) { + k = this.c + this.b.nextInt(16) + 8; + l = this.d + this.b.nextInt(16) + 8; +- i1 = this.b.nextInt(this.a.getHighestBlockYAt(k, l) * 2); ++ i1 = this.b.nextInt(this.getHighestBlockYAt(k, l) * 2); // Spigot + (new WorldGenDeadBush(Blocks.DEAD_BUSH)).generate(this.a, this.b, k, i1, l); + } + +@@ -0,0 +0,0 @@ public class BiomeDecorator { + k = this.c + this.b.nextInt(16) + 8; + l = this.d + this.b.nextInt(16) + 8; + +- for (i1 = this.b.nextInt(this.a.getHighestBlockYAt(k, l) * 2); i1 > 0 && this.a.isEmpty(k, i1 - 1, l); --i1) { ++ for (i1 = this.b.nextInt(this.getHighestBlockYAt(k, l) * 2); i1 > 0 && this.a.isEmpty(k, i1 - 1, l); --i1) { // Spigot + ; + } + +@@ -0,0 +0,0 @@ public class BiomeDecorator { + if (this.b.nextInt(8) == 0) { + k = this.c + this.b.nextInt(16) + 8; + l = this.d + this.b.nextInt(16) + 8; +- i1 = this.b.nextInt(this.a.getHighestBlockYAt(k, l) * 2); ++ i1 = this.b.nextInt(this.getHighestBlockYAt(k, l) * 2); // Spigot + this.r.generate(this.a, this.b, k, i1, l); + } + } +@@ -0,0 +0,0 @@ public class BiomeDecorator { + if (this.b.nextInt(4) == 0) { + j = this.c + this.b.nextInt(16) + 8; + k = this.d + this.b.nextInt(16) + 8; +- l = this.b.nextInt(this.a.getHighestBlockYAt(j, k) * 2); ++ l = this.b.nextInt(this.getHighestBlockYAt(j, k) * 2); // Spigot + this.q.generate(this.a, this.b, j, l, k); + } + + if (this.b.nextInt(8) == 0) { + j = this.c + this.b.nextInt(16) + 8; + k = this.d + this.b.nextInt(16) + 8; +- l = this.b.nextInt(this.a.getHighestBlockYAt(j, k) * 2); ++ l = this.b.nextInt(this.getHighestBlockYAt(j, k) * 2); // Spigot + this.r.generate(this.a, this.b, j, l, k); + } + + for (j = 0; j < this.C; ++j) { + k = this.c + this.b.nextInt(16) + 8; + l = this.d + this.b.nextInt(16) + 8; +- i1 = this.b.nextInt(this.a.getHighestBlockYAt(k, l) * 2); ++ i1 = this.b.nextInt(this.getHighestBlockYAt(k, l) * 2); // Spigot + this.t.generate(this.a, this.b, k, i1, l); + } + + for (j = 0; j < 10; ++j) { + k = this.c + this.b.nextInt(16) + 8; + l = this.d + this.b.nextInt(16) + 8; +- i1 = this.b.nextInt(this.a.getHighestBlockYAt(k, l) * 2); ++ i1 = this.b.nextInt(this.getHighestBlockYAt(k, l) * 2); // Spigot + this.t.generate(this.a, this.b, k, i1, l); + } + + if (this.b.nextInt(32) == 0) { + j = this.c + this.b.nextInt(16) + 8; + k = this.d + this.b.nextInt(16) + 8; +- l = this.b.nextInt(this.a.getHighestBlockYAt(j, k) * 2); ++ l = this.b.nextInt(this.getHighestBlockYAt(j, k) * 2); // Spigot + (new WorldGenPumpkin()).generate(this.a, this.b, j, l, k); + } + + for (j = 0; j < this.D; ++j) { + k = this.c + this.b.nextInt(16) + 8; + l = this.d + this.b.nextInt(16) + 8; +- i1 = this.b.nextInt(this.a.getHighestBlockYAt(k, l) * 2); ++ i1 = this.b.nextInt(this.getHighestBlockYAt(k, l) * 2); // Spigot + this.u.generate(this.a, this.b, k, i1, l); + } + +@@ -0,0 +0,0 @@ public class BiomeDecorator { + this.a(1, this.n, 0, 16); + this.b(1, this.o, 16, 16); + } ++ ++ // Spigot Start ++ private int getHighestBlockYAt(int x, int z) ++ { ++ return Math.max( 1, this.a.getHighestBlockYAt( x, z ) ); ++ } ++ // Spigot End + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0071-Save-ticks-lived-to-nbttag.patch b/CraftBukkit-Patches/0071-Save-ticks-lived-to-nbttag.patch new file mode 100644 index 0000000000..01443e649f --- /dev/null +++ b/CraftBukkit-Patches/0071-Save-ticks-lived-to-nbttag.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: DerFlash +Date: Tue, 9 Jul 2013 00:11:12 +0200 +Subject: [PATCH] Save ticks lived to nbttag + + +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -0,0 +0,0 @@ public abstract class Entity { + nbttagcompound.setLong("WorldUUIDLeast", this.world.getDataManager().getUUID().getLeastSignificantBits()); + nbttagcompound.setLong("WorldUUIDMost", this.world.getDataManager().getUUID().getMostSignificantBits()); + nbttagcompound.setInt("Bukkit.updateLevel", CURRENT_LEVEL); ++ nbttagcompound.setInt("Spigot.ticksLived", this.ticksLived); + // CraftBukkit end + this.b(nbttagcompound); + if (this.vehicle != null) { +@@ -0,0 +0,0 @@ public abstract class Entity { + if (this instanceof EntityLiving) { + EntityLiving entity = (EntityLiving) this; + ++ this.ticksLived = nbttagcompound.getInt("Spigot.ticksLived"); ++ + // Reset the persistence for tamed animals + if (entity instanceof EntityTameableAnimal && !isLevelAtLeast(nbttagcompound, 2) && !nbttagcompound.getBoolean("PersistenceRequired")) { + EntityInsentient entityinsentient = (EntityInsentient) entity; +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0072-More-Efficient-GetCubes.patch b/CraftBukkit-Patches/0072-More-Efficient-GetCubes.patch new file mode 100644 index 0000000000..0a686e0d11 --- /dev/null +++ b/CraftBukkit-Patches/0072-More-Efficient-GetCubes.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Tue, 11 Jun 2013 12:17:37 +1000 +Subject: [PATCH] More Efficient GetCubes + + +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + int i1 = MathHelper.floor(axisalignedbb.c); + int j1 = MathHelper.floor(axisalignedbb.f + 1.0D); + +- for (int k1 = i; k1 < j; ++k1) { +- for (int l1 = i1; l1 < j1; ++l1) { +- if (this.isLoaded(k1, 64, l1)) { +- for (int i2 = k - 1; i2 < l; ++i2) { +- Block block; +- +- if (k1 >= -30000000 && k1 < 30000000 && l1 >= -30000000 && l1 < 30000000) { +- block = this.getType(k1, i2, l1); +- } else { +- block = Blocks.STONE; ++ // Spigot start ++ int ystart = ( ( k - 1 ) < 0 ) ? 0 : ( k - 1 ); ++ for ( int chunkx = ( i >> 4 ); chunkx <= ( ( j - 1 ) >> 4 ); chunkx++ ) ++ { ++ int cx = chunkx << 4; ++ for ( int chunkz = ( i1 >> 4 ); chunkz <= ( ( j1 - 1 ) >> 4 ); chunkz++ ) ++ { ++ if ( !this.isChunkLoaded( chunkx, chunkz ) ) ++ { ++ continue; ++ } ++ int cz = chunkz << 4; ++ Chunk chunk = this.getChunkAt( chunkx, chunkz ); ++ // Compute ranges within chunk ++ int xstart = ( i < cx ) ? cx : i; ++ int xend = ( j < ( cx + 16 ) ) ? j : ( cx + 16 ); ++ int zstart = ( i1 < cz ) ? cz : i1; ++ int zend = ( j1 < ( cz + 16 ) ) ? j1 : ( cz + 16 ); ++ // Loop through blocks within chunk ++ for ( int x = xstart; x < xend; x++ ) ++ { ++ for ( int z = zstart; z < zend; z++ ) ++ { ++ for ( int y = ystart; y < l; y++ ) ++ { ++ Block block = chunk.getType(x - cx, y, z - cz ); ++ if ( block != null ) ++ { ++ block.a( this, x, y, z, axisalignedbb, this.L, entity ); ++ } + } +- +- block.a(this, k1, i2, l1, axisalignedbb, this.L, entity); + } + } + } + } ++ // Spigot end + + double d0 = 0.25D; + List list = this.getEntities(entity, axisalignedbb.grow(d0, d0, d0)); +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0073-Add-Option-to-Nerf-Mobs-from-Spawner-s.patch b/CraftBukkit-Patches/0073-Add-Option-to-Nerf-Mobs-from-Spawner-s.patch new file mode 100644 index 0000000000..06ce4f52d7 --- /dev/null +++ b/CraftBukkit-Patches/0073-Add-Option-to-Nerf-Mobs-from-Spawner-s.patch @@ -0,0 +1,82 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 2 Feb 2014 16:55:46 +0000 +Subject: [PATCH] Add Option to Nerf Mobs from Spawner's + + +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -0,0 +0,0 @@ public abstract class Entity { + public final byte activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); + public final boolean defaultActivationState; + public long activatedTick = 0; ++ public boolean fromMobSpawner; + public void inactiveTick() { } + // Spigot end + +diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityInsentient.java ++++ b/src/main/java/net/minecraft/server/EntityInsentient.java +@@ -0,0 +0,0 @@ public abstract class EntityInsentient extends EntityLiving { + this.world.methodProfiler.a("checkDespawn"); + this.w(); + this.world.methodProfiler.b(); ++ // Spigot Start ++ if ( this.fromMobSpawner ) ++ { ++ return; ++ } ++ // Spigot End + this.world.methodProfiler.a("sensing"); + this.bq.a(); + this.world.methodProfiler.b(); +diff --git a/src/main/java/net/minecraft/server/MobSpawnerAbstract.java b/src/main/java/net/minecraft/server/MobSpawnerAbstract.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/MobSpawnerAbstract.java ++++ b/src/main/java/net/minecraft/server/MobSpawnerAbstract.java +@@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { + SpawnerSpawnEvent event = CraftEventFactory.callSpawnerSpawnEvent(entity, this.b(), this.c(), this.d()); + if (!event.isCancelled()) { + entity.world.addEntity(entity, CreatureSpawnEvent.SpawnReason.SPAWNER); // CraftBukkit ++ // Spigot Start ++ if ( entity.world.spigotConfig.nerfSpawnerMobs ) ++ { ++ entity.fromMobSpawner = true; ++ } ++ // Spigot End + } + // CraftBukkit end + } +@@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { + SpawnerSpawnEvent event = CraftEventFactory.callSpawnerSpawnEvent(entity, this.b(), this.c(), this.d()); + if (!event.isCancelled()) { + this.a().addEntity(entity, CreatureSpawnEvent.SpawnReason.SPAWNER); // CraftBukkit ++ // Spigot Start ++ if ( entity.world.spigotConfig.nerfSpawnerMobs ) ++ { ++ entity.fromMobSpawner = true; ++ } ++ // Spigot End + } + // Spigot end + } +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -0,0 +0,0 @@ public class SpigotWorldConfig + zombieAggressiveTowardsVillager = getBoolean( "zombie-aggressive-towards-villager", true ); + log( "Zombie Aggressive Towards Villager: " + zombieAggressiveTowardsVillager ); + } ++ ++ public boolean nerfSpawnerMobs; ++ private void nerfSpawnerMobs() ++ { ++ nerfSpawnerMobs = getBoolean( "nerf-spawner-mobs", false ); ++ log( "Nerfing mobs spawned from spawners: " + nerfSpawnerMobs ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0074-Warn-if-PermGen-may-be-insufficient.patch b/CraftBukkit-Patches/0074-Warn-if-PermGen-may-be-insufficient.patch new file mode 100644 index 0000000000..12d94f7282 --- /dev/null +++ b/CraftBukkit-Patches/0074-Warn-if-PermGen-may-be-insufficient.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Mon, 23 Dec 2013 14:07:41 +1100 +Subject: [PATCH] Warn if PermGen may be insufficient + + +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -0,0 +0,0 @@ public class Main { + useConsole = false; + } + ++ // Spigot Start ++ int maxPermGen = 0; // In kb ++ for ( String s : java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments() ) ++ { ++ if ( s.startsWith( "-XX:MaxPermSize" ) ) ++ { ++ maxPermGen = Integer.parseInt( s.replaceAll( "[^\\d]", "" ) ); ++ maxPermGen <<= 10 * ("kmg".indexOf( Character.toLowerCase( s.charAt( s.length() - 1 ) ) ) ); ++ } ++ } ++ if ( Float.parseFloat( System.getProperty( "java.class.version" ) ) < 52 && maxPermGen < ( 128 << 10 ) ) // 128mb ++ { ++ System.out.println( "Warning, your max perm gen size is not set or less than 128mb. It is recommended you restart Java with the following argument: -XX:MaxPermSize=128M" ); ++ System.out.println( "Please see http://www.spigotmc.org/wiki/changing-permgen-size/ for more details and more in-depth instructions." ); ++ } ++ // Spigot End + System.out.println("Loading libraries, please wait..."); + MinecraftServer.main(options); + } catch (Throwable t) { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0075-Disable-Connected-Check-on-setScoreboard.patch b/CraftBukkit-Patches/0075-Disable-Connected-Check-on-setScoreboard.patch new file mode 100644 index 0000000000..8a4de95f0f --- /dev/null +++ b/CraftBukkit-Patches/0075-Disable-Connected-Check-on-setScoreboard.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Mon, 23 Dec 2013 15:57:57 +1100 +Subject: [PATCH] Disable Connected Check on setScoreboard + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + throw new IllegalStateException("Cannot set scoreboard yet"); + } + if (playerConnection.isDisconnected()) { +- throw new IllegalStateException("Cannot set scoreboard for invalid CraftPlayer"); ++ // throw new IllegalStateException("Cannot set scoreboard for invalid CraftPlayer"); // Spigot - remove this as Mojang's semi asynchronous Netty implementation can lead to races + } + + this.server.getScoreboardManager().setPlayerBoard(this, scoreboard); +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0076-Add-Late-Bind-Option.patch b/CraftBukkit-Patches/0076-Add-Late-Bind-Option.patch new file mode 100644 index 0000000000..2a70b7fe44 --- /dev/null +++ b/CraftBukkit-Patches/0076-Add-Late-Bind-Option.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: slide23 +Date: Fri, 20 Dec 2013 20:15:33 -0600 +Subject: [PATCH] Add Late Bind Option + +Add late-bind config option to delay binding until loading is done. + +diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/DedicatedServer.java +@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + this.a(MinecraftEncryption.b()); + i.info("Starting Minecraft server on " + (this.getServerIp().length() == 0 ? "*" : this.getServerIp()) + ":" + this.L()); + ++ if (!org.spigotmc.SpigotConfig.lateBind) { + try { + this.ai().a(inetaddress, this.L()); + } catch (Throwable ioexception) { // CraftBukkit - IOException -> Throwable +@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + i.warn("Perhaps a server is already running on that port?"); + return false; + } ++ } + + // Spigot Start - Move DedicatedPlayerList up and bring plugin loading from CraftServer to here + // this.a((PlayerList) (new DedicatedPlayerList(this))); // CraftBukkit +@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + } + // CraftBukkit end + ++ if (org.spigotmc.SpigotConfig.lateBind) { ++ try { ++ this.ai().a(inetaddress, this.L()); ++ } catch (Throwable ioexception) { // CraftBukkit - IOException -> Throwable ++ i.warn("**** FAILED TO BIND TO PORT!"); ++ i.warn("The exception was: {}", new Object[] { ioexception.toString()}); ++ i.warn("Perhaps a server is already running on that port?"); ++ return false; ++ } ++ } + return true; + } + } +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -0,0 +0,0 @@ public class SpigotConfig + System.setProperty( "io.netty.eventLoopThreads", Integer.toString( count ) ); + Bukkit.getLogger().log( Level.INFO, "Using {0} threads for Netty based IO", count ); + } ++ ++ public static boolean lateBind; ++ private static void lateBind() { ++ lateBind = getBoolean( "settings.late-bind", false ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0077-Allow-statistics-to-be-disabled-forced.patch b/CraftBukkit-Patches/0077-Allow-statistics-to-be-disabled-forced.patch new file mode 100644 index 0000000000..e2570b9ee8 --- /dev/null +++ b/CraftBukkit-Patches/0077-Allow-statistics-to-be-disabled-forced.patch @@ -0,0 +1,91 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Tue, 7 Jan 2014 15:56:26 +0000 +Subject: [PATCH] Allow statistics to be disabled/forced + + +diff --git a/src/main/java/net/minecraft/server/ServerStatisticManager.java b/src/main/java/net/minecraft/server/ServerStatisticManager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/ServerStatisticManager.java ++++ b/src/main/java/net/minecraft/server/ServerStatisticManager.java +@@ -0,0 +0,0 @@ public class ServerStatisticManager extends StatisticManager { + public ServerStatisticManager(MinecraftServer minecraftserver, File file1) { + this.c = minecraftserver; + this.d = file1; ++ // Spigot start ++ for ( String name : org.spigotmc.SpigotConfig.forcedStats.keySet() ) ++ { ++ StatisticWrapper wrapper = new StatisticWrapper(); ++ wrapper.a( org.spigotmc.SpigotConfig.forcedStats.get( name ) ); ++ a.put( StatisticList.getStatistic( name ), wrapper ); ++ } ++ // Spigot end + } + + public void a() { +@@ -0,0 +0,0 @@ public class ServerStatisticManager extends StatisticManager { + } + + public void b() { ++ if ( org.spigotmc.SpigotConfig.disableStatSaving ) return; // Spigot + try { + FileUtils.writeStringToFile(this.d, a(this.a)); + } catch (IOException ioexception) { +@@ -0,0 +0,0 @@ public class ServerStatisticManager extends StatisticManager { + } + + public void setStatistic(EntityHuman entityhuman, Statistic statistic, int i) { ++ if ( org.spigotmc.SpigotConfig.disableStatSaving ) return; // Spigot + int j = statistic.d() ? this.getStatisticValue(statistic) : 0; + + super.setStatistic(entityhuman, statistic, i); +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -0,0 +0,0 @@ import java.util.HashMap; + import java.util.List; + import java.util.Map; + import java.util.logging.Level; ++import net.minecraft.util.gnu.trove.map.hash.TObjectIntHashMap; + import net.minecraft.server.MinecraftServer; + import org.bukkit.Bukkit; + import org.bukkit.ChatColor; + import org.bukkit.command.Command; ++import org.bukkit.configuration.ConfigurationSection; + import org.bukkit.configuration.InvalidConfigurationException; + import org.bukkit.configuration.file.YamlConfiguration; + +@@ -0,0 +0,0 @@ public class SpigotConfig + private static void lateBind() { + lateBind = getBoolean( "settings.late-bind", false ); + } ++ ++ public static boolean disableStatSaving; ++ public static TObjectIntHashMap forcedStats = new TObjectIntHashMap(); ++ private static void stats() ++ { ++ disableStatSaving = getBoolean( "stats.disable-saving", false ); ++ ++ if ( !config.contains( "stats.forced-stats" ) ) { ++ config.createSection( "stats.forced-stats" ); ++ } ++ ++ ConfigurationSection section = config.getConfigurationSection( "stats.forced-stats" ); ++ for ( String name : section.getKeys( true ) ) ++ { ++ if ( section.isInt( name ) ) ++ { ++ forcedStats.put( name, section.getInt( name ) ); ++ } ++ } ++ ++ if ( disableStatSaving && section.getInt( "achievement.openInventory", 0 ) < 1 ) ++ { ++ Bukkit.getLogger().warning( "*** WARNING *** stats.disable-saving is true but stats.forced-stats.achievement.openInventory" + ++ " isn't set to 1. Disabling stat saving without forcing the achievement may cause it to get stuck on the player's " + ++ "screen." ); ++ } ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0078-Fix-anvil-collisions.patch b/CraftBukkit-Patches/0078-Fix-anvil-collisions.patch new file mode 100644 index 0000000000..17cb949f92 --- /dev/null +++ b/CraftBukkit-Patches/0078-Fix-anvil-collisions.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Thu, 9 Jan 2014 14:19:12 +0000 +Subject: [PATCH] Fix anvil collisions + + +diff --git a/src/main/java/net/minecraft/server/BlockAnvil.java b/src/main/java/net/minecraft/server/BlockAnvil.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/BlockAnvil.java ++++ b/src/main/java/net/minecraft/server/BlockAnvil.java +@@ -0,0 +0,0 @@ public class BlockAnvil extends BlockFalling { + this.a(CreativeModeTab.c); + } + ++ // Spigot start ++ @Override ++ public AxisAlignedBB a( World world, int i, int j, int k ) ++ { ++ updateShape( world, i, j, k ); ++ return super.a( world, i, j, k ); ++ } ++ // Spigot end ++ + public boolean d() { + return false; + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0079-Fix-ItemStack-Unbreakable-Code.patch b/CraftBukkit-Patches/0079-Fix-ItemStack-Unbreakable-Code.patch new file mode 100644 index 0000000000..fffed616a0 --- /dev/null +++ b/CraftBukkit-Patches/0079-Fix-ItemStack-Unbreakable-Code.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Fri, 10 Jan 2014 15:15:50 +1100 +Subject: [PATCH] Fix ItemStack Unbreakable Code + + +diff --git a/src/main/java/net/minecraft/server/ItemStack.java b/src/main/java/net/minecraft/server/ItemStack.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/ItemStack.java ++++ b/src/main/java/net/minecraft/server/ItemStack.java +@@ -0,0 +0,0 @@ public final class ItemStack { + } + + public boolean g() { +- return this.item.getMaxDurability() <= 0 ? false : !this.hasTag() || !this.getTag().getBoolean("Unbreakable"); ++ // Spigot Start ++ if ( this.item.getMaxDurability() <= 0 ) ++ { ++ return false; ++ } ++ return ( !hasTag() ) || ( !getTag().getBoolean( "Unbreakable" ) ); ++ // Spigot End + } + + public boolean usesData() { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0080-Try-and-Debug-Crash-Reports-Crashing.patch b/CraftBukkit-Patches/0080-Try-and-Debug-Crash-Reports-Crashing.patch new file mode 100644 index 0000000000..2f6c9d7163 --- /dev/null +++ b/CraftBukkit-Patches/0080-Try-and-Debug-Crash-Reports-Crashing.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 12 Jan 2014 20:56:41 +1100 +Subject: [PATCH] Try and Debug Crash Reports Crashing + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + worldserver.doTick(); + worldserver.timings.doTick.stopTiming(); // Spigot + } catch (Throwable throwable) { ++ // Spigot Start ++ try { + crashreport = CrashReport.a(throwable, "Exception ticking world"); ++ } catch (Throwable t){ ++ throw new RuntimeException("Error generating crash report", t); ++ } ++ // Spigot End + worldserver.a(crashreport); + throw new ReportedException(crashreport); + } +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + worldserver.tickEntities(); + worldserver.timings.tickEntities.stopTiming(); // Spigot + } catch (Throwable throwable1) { ++ // Spigot Start ++ try { + crashreport = CrashReport.a(throwable1, "Exception ticking world entities"); ++ } catch (Throwable t){ ++ throw new RuntimeException("Error generating crash report", t); ++ } ++ // Spigot End + worldserver.a(crashreport); + throw new ReportedException(crashreport); + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0081-Replace-AutoSave-Mechanism.patch b/CraftBukkit-Patches/0081-Replace-AutoSave-Mechanism.patch new file mode 100644 index 0000000000..2c10b58c33 --- /dev/null +++ b/CraftBukkit-Patches/0081-Replace-AutoSave-Mechanism.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 12 Jan 2014 21:07:18 +1100 +Subject: [PATCH] Replace AutoSave Mechanism + +The problem here is that MinecraftServer.save(..), will attempt to sleep whilst all pending chunks are written to disk, however due to various and complicated bugs, it will wait for an incorrect amount of chunks, which may cause it to sleep for an overly long amount of time. Instead we will mimic the save-all command in its behaviour, which is both safe and performant. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + SpigotTimings.worldSaveTimer.startTiming(); // Spigot + this.methodProfiler.a("save"); + this.u.savePlayers(); +- this.saveChunks(true); ++ // Spigot Start ++ // 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 ++ server.playerCommandState = true; ++ for (World world : worlds) { ++ world.getWorld().save(); ++ } ++ server.playerCommandState = false; ++ // this.saveChunks(true); ++ // Spigot End + this.methodProfiler.b(); + SpigotTimings.worldSaveTimer.stopTiming(); // Spigot + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0082-Block-data-values-that-crash-the-client.patch b/CraftBukkit-Patches/0082-Block-data-values-that-crash-the-client.patch new file mode 100644 index 0000000000..96d857633e --- /dev/null +++ b/CraftBukkit-Patches/0082-Block-data-values-that-crash-the-client.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Wed, 15 Jan 2014 21:52:47 +0000 +Subject: [PATCH] Block data values that crash the client + + +diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Chunk.java ++++ b/src/main/java/net/minecraft/server/Chunk.java +@@ -0,0 +0,0 @@ public class Chunk { + } + + this.sections[l1].setTypeId(l, j1 & 15, i1, block); +- this.sections[l1].setData(l, j1 & 15, i1, abyte[k1]); ++ this.sections[l1].setData(l, j1 & 15, i1, checkData( block, abyte[k1] ) ); + } + } + } +@@ -0,0 +0,0 @@ public class Chunk { + } + } + ++ // Spigot start - prevent invalid data values ++ public static int checkData( Block block, int data ) ++ { ++ if (block == Blocks.DOUBLE_PLANT ) ++ { ++ return data < 6 || data >= 8 ? data : 0; ++ } ++ return data; ++ } ++ // Spigot end ++ + public boolean a(int i, int j, int k, Block block, int l) { + int i1 = k << 4 | i; + +@@ -0,0 +0,0 @@ public class Chunk { + if (chunksection.getTypeId(i, j & 15, k) != block) { + return false; + } else { +- chunksection.setData(i, j & 15, k, l); ++ chunksection.setData(i, j & 15, k, checkData( block, l ) ); + if (flag) { + this.initLighting(); + } else { +@@ -0,0 +0,0 @@ public class Chunk { + return false; + } else { + this.n = true; +- chunksection.setData(i, j & 15, k, l); +- if (chunksection.getTypeId(i, j & 15, k) instanceof IContainer) { ++ Block block = chunksection.getTypeId( i, j & 15, k ); ++ chunksection.setData(i, j & 15, k, checkData( block, l ) ); ++ if (block instanceof IContainer) { + TileEntity tileentity = this.e(i, j, k); + + if (tileentity != null) { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0083-Support-vanilla-s-direction-tag-on-fireballs.patch b/CraftBukkit-Patches/0083-Support-vanilla-s-direction-tag-on-fireballs.patch new file mode 100644 index 0000000000..5b8d2dffb4 --- /dev/null +++ b/CraftBukkit-Patches/0083-Support-vanilla-s-direction-tag-on-fireballs.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Sat, 18 Jan 2014 14:27:03 +0000 +Subject: [PATCH] Support vanilla's direction tag on fireballs + + +diff --git a/src/main/java/net/minecraft/server/EntityFireball.java b/src/main/java/net/minecraft/server/EntityFireball.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityFireball.java ++++ b/src/main/java/net/minecraft/server/EntityFireball.java +@@ -0,0 +0,0 @@ public abstract class EntityFireball extends Entity { + nbttagcompound.setByte("inGround", (byte) (this.i ? 1 : 0)); + // CraftBukkit - Fix direction being mismapped to invalid variables + nbttagcompound.set("power", this.a(new double[] { this.dirX, this.dirY, this.dirZ})); ++ // Spigot - Support vanilla's direction tag ++ nbttagcompound.set("direction", this.a(new double[] { this.motX, this.motY, this.motZ})); + } + + public void a(NBTTagCompound nbttagcompound) { +@@ -0,0 +0,0 @@ public abstract class EntityFireball extends Entity { + this.dirY = nbttaglist.d(1); + this.dirZ = nbttaglist.d(2); + // CraftBukkit end ++ } else if (nbttagcompound.hasKeyOfType("direction", 9)) { // Spigot - Support vanilla's direction tag ++ NBTTagList nbttaglist = nbttagcompound.getList("direction", 6); ++ ++ this.motX = nbttaglist.d(0); ++ this.motY = nbttaglist.d(1); ++ this.motZ = nbttaglist.d(2); ++ + } else { + this.die(); + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0084-Support-non-prefixed-URLs.patch b/CraftBukkit-Patches/0084-Support-non-prefixed-URLs.patch new file mode 100644 index 0000000000..e897a4a9f2 --- /dev/null +++ b/CraftBukkit-Patches/0084-Support-non-prefixed-URLs.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Sat, 18 Jan 2014 19:32:42 +0000 +Subject: [PATCH] Support non-prefixed URLs + + +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java +@@ -0,0 +0,0 @@ import com.google.common.collect.ImmutableMap.Builder; + public final class CraftChatMessage { + private static class StringMessage { + private static final Map formatMap; +- private static final Pattern INCREMENTAL_PATTERN = Pattern.compile("(" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + "[0-9a-fk-or])|(\\n)|(?:(https?://[^ ][^ ]*?)(?=[\\.\\?!,;:]?(?:[ \\n]|$)))", Pattern.CASE_INSENSITIVE); ++ private static final Pattern INCREMENTAL_PATTERN = Pattern.compile("(" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + "[0-9a-fk-or])|(\\n)|((?:(?:https?)://)?(?:[-\\w_\\.]{2,}\\.[a-z]{2,4}.*?(?=[\\.\\?!,;:]?(?:[" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + " \\n]|$))))", Pattern.CASE_INSENSITIVE); + + static { + Builder builder = ImmutableMap.builder(); +@@ -0,0 +0,0 @@ public final class CraftChatMessage { + currentChatComponent = null; + break; + case 3: ++ if ( !( match.startsWith( "http://" ) || match.startsWith( "https://" ) ) ) { ++ match = "http://" + match; ++ } + modifier.setChatClickable(new ChatClickable(EnumClickAction.OPEN_URL, match)); + appendNewComponent(matcher.end(groupId)); + modifier.setChatClickable((ChatClickable) null); +@@ -0,0 +0,0 @@ public final class CraftChatMessage { + appendNewComponent(message.length()); + } + +- output = list.toArray(new IChatBaseComponent[0]); ++ output = list.toArray(new IChatBaseComponent[list.size()]); + } + + private void appendNewComponent(int index) { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0085-Catch-stalling-on-corrupted-map-data-NBT-arrays.patch b/CraftBukkit-Patches/0085-Catch-stalling-on-corrupted-map-data-NBT-arrays.patch new file mode 100644 index 0000000000..46db27fc08 --- /dev/null +++ b/CraftBukkit-Patches/0085-Catch-stalling-on-corrupted-map-data-NBT-arrays.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Mon, 20 Jan 2014 13:44:07 +1100 +Subject: [PATCH] Catch stalling on corrupted map data / NBT arrays. + + +diff --git a/src/main/java/net/minecraft/server/NBTTagByteArray.java b/src/main/java/net/minecraft/server/NBTTagByteArray.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/NBTTagByteArray.java ++++ b/src/main/java/net/minecraft/server/NBTTagByteArray.java +@@ -0,0 +0,0 @@ public class NBTTagByteArray extends NBTBase { + + void load(DataInput datainput, int i, NBTReadLimiter nbtreadlimiter) throws IOException { + int j = datainput.readInt(); ++ com.google.common.base.Preconditions.checkArgument( j < 1 << 24); + + nbtreadlimiter.a((long) (8 * j)); + this.data = new byte[j]; +diff --git a/src/main/java/net/minecraft/server/NBTTagIntArray.java b/src/main/java/net/minecraft/server/NBTTagIntArray.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/NBTTagIntArray.java ++++ b/src/main/java/net/minecraft/server/NBTTagIntArray.java +@@ -0,0 +0,0 @@ public class NBTTagIntArray extends NBTBase { + + void load(DataInput datainput, int i, NBTReadLimiter nbtreadlimiter) throws IOException { + int j = datainput.readInt(); ++ com.google.common.base.Preconditions.checkArgument( j < 1 << 24); + + nbtreadlimiter.a((long) (32 * j)); + this.data = new int[j]; +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0086-Allow-toggling-of-ZombiePigmen-spawning-in-portal-bl.patch b/CraftBukkit-Patches/0086-Allow-toggling-of-ZombiePigmen-spawning-in-portal-bl.patch new file mode 100644 index 0000000000..00a1b916c4 --- /dev/null +++ b/CraftBukkit-Patches/0086-Allow-toggling-of-ZombiePigmen-spawning-in-portal-bl.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dmck2b +Date: Mon, 20 Jan 2014 20:18:23 +0000 +Subject: [PATCH] Allow toggling of ZombiePigmen spawning in portal blocks + + +diff --git a/src/main/java/net/minecraft/server/BlockPortal.java b/src/main/java/net/minecraft/server/BlockPortal.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/BlockPortal.java ++++ b/src/main/java/net/minecraft/server/BlockPortal.java +@@ -0,0 +0,0 @@ public class BlockPortal extends BlockHalfTransparent { + + public void a(World world, int i, int j, int k, Random random) { + super.a(world, i, j, k, random); +- if (world.worldProvider.d() && world.getGameRules().getBoolean("doMobSpawning") && random.nextInt(2000) < world.difficulty.a()) { ++ if (world.spigotConfig.enableZombiePigmenPortalSpawns && world.worldProvider.d() && world.getGameRules().getBoolean("doMobSpawning") && random.nextInt(2000) < world.difficulty.a()) { // Spigot + int l; + + for (l = j; !World.a((IBlockAccess) world, i, l, k) && l > 0; --l) { +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -0,0 +0,0 @@ public class SpigotWorldConfig + nerfSpawnerMobs = getBoolean( "nerf-spawner-mobs", false ); + log( "Nerfing mobs spawned from spawners: " + nerfSpawnerMobs ); + } ++ ++ public boolean enableZombiePigmenPortalSpawns; ++ private void enableZombiePigmenPortalSpawns() ++ { ++ enableZombiePigmenPortalSpawns = getBoolean( "enable-zombie-pigmen-portal-spawns", true ); ++ log( "Allow Zombie Pigmen to spawn from portal blocks: " + enableZombiePigmenPortalSpawns ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0087-Highly-Optimized-Tick-Loop.patch b/CraftBukkit-Patches/0087-Highly-Optimized-Tick-Loop.patch new file mode 100644 index 0000000000..009f94f5b3 --- /dev/null +++ b/CraftBukkit-Patches/0087-Highly-Optimized-Tick-Loop.patch @@ -0,0 +1,163 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 25 Jan 2014 14:08:35 +1100 +Subject: [PATCH] Highly Optimized Tick Loop + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + public java.util.Queue processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); + public int autosavePeriod; + // CraftBukkit end ++ // Spigot start ++ private static final int TPS = 20; ++ private static final int TICK_TIME = 1000000000 / TPS; ++ private static final int SAMPLE_INTERVAL = 100; ++ public final double[] recentTps = new double[ 3 ]; ++ // Spigot end + + public MinecraftServer(OptionSet options, Proxy proxy) { // CraftBukkit - signature file -> OptionSet + this.X = new UserCache(this, a); +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + this.isRunning = false; + } + ++ // Spigot Start ++ private static double calcTps(double avg, double exp, double tps) ++ { ++ return ( avg * exp ) + ( tps * ( 1 - exp ) ); ++ } ++ // Spigot End ++ + public void run() { + try { + if (this.init()) { +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + this.q.setServerInfo(new ServerPingServerData("1.7.10", 5)); + this.a(this.q); + ++ // Spigot start ++ Arrays.fill( recentTps, 20 ); ++ long lastTick = System.nanoTime(), catchupTime = 0, curTime, wait, tickSection = lastTick; + while (this.isRunning) { +- long k = ar(); +- long l = k - i; +- +- if (l > 2000L && i - this.P >= 15000L) { +- if (this.server.getWarnOnOverload()) // CraftBukkit - Added option to suppress warning messages +- MinecraftServer.i.warn("Can\'t keep up! Did the system time change, or is the server overloaded? Running {}ms behind, skipping {} tick(s)", new Object[] { Long.valueOf(l), Long.valueOf(l / 50L)}); +- l = 2000L; +- this.P = i; +- } +- +- if (l < 0L) { +- MinecraftServer.i.warn("Time ran backwards! Did the system time change?"); +- l = 0L; ++ curTime = System.nanoTime(); ++ wait = TICK_TIME - (curTime - lastTick) - catchupTime; ++ if (wait > 0) { ++ Thread.sleep(wait / 1000000); ++ catchupTime = 0; ++ continue; ++ } else { ++ catchupTime = Math.min(1000000000, Math.abs(wait)); + } + +- j += l; +- i = k; +- if (this.worlds.get(0).everyoneDeeplySleeping()) { // CraftBukkit +- this.u(); +- j = 0L; +- } else { +- while (j > 50L) { +- MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit +- j -= 50L; +- this.u(); +- } ++ if ( MinecraftServer.currentTick++ % SAMPLE_INTERVAL == 0 ) ++ { ++ double currentTps = 1E9 / ( curTime - tickSection ) * SAMPLE_INTERVAL; ++ recentTps[0] = calcTps( recentTps[0], 0.92, currentTps ); // 1/exp(5sec/1min) ++ recentTps[1] = calcTps( recentTps[1], 0.9835, currentTps ); // 1/exp(5sec/5min) ++ recentTps[2] = calcTps( recentTps[2], 0.9945, currentTps ); // 1/exp(5sec/15min) ++ tickSection = curTime; + } ++ lastTick = curTime; + +- Thread.sleep(Math.max(1L, 50L - j)); ++ this.u(); + this.O = true; + } ++ // Spigot end + } else { + this.a((CrashReport) null); + } +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -0,0 +0,0 @@ public class SpigotConfig + "screen." ); + } + } ++ ++ private static void tpsCommand() ++ { ++ commands.put( "tps", new TicksPerSecondCommand( "tps" ) ); ++ } + } +diff --git a/src/main/java/org/spigotmc/TicksPerSecondCommand.java b/src/main/java/org/spigotmc/TicksPerSecondCommand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/org/spigotmc/TicksPerSecondCommand.java +@@ -0,0 +0,0 @@ ++package org.spigotmc; ++ ++import com.google.common.base.Joiner; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.util.com.google.common.collect.Iterables; ++import org.bukkit.ChatColor; ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++ ++public class TicksPerSecondCommand extends Command ++{ ++ ++ public TicksPerSecondCommand(String name) ++ { ++ super( name ); ++ this.description = "Gets the current ticks per second for the server"; ++ this.usageMessage = "/tps"; ++ this.setPermission( "bukkit.command.tps" ); ++ } ++ ++ @Override ++ public boolean execute(CommandSender sender, String currentAlias, String[] args) ++ { ++ if ( !testPermission( sender ) ) ++ { ++ return true; ++ } ++ ++ StringBuilder sb = new StringBuilder( ChatColor.GOLD + "TPS from last 1m, 5m, 15m: " ); ++ for ( double tps : MinecraftServer.getServer().recentTps ) ++ { ++ sb.append( format( tps ) ); ++ sb.append( ", " ); ++ } ++ sender.sendMessage( sb.substring( 0, sb.length() - 2 ) ); ++ ++ return true; ++ } ++ ++ private String format(double tps) ++ { ++ return ( ( tps > 18.0 ) ? ChatColor.GREEN : ( tps > 16.0 ) ? ChatColor.YELLOW : ChatColor.RED ).toString() ++ + ( ( tps > 20.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); ++ } ++} +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0088-Add-Spigot-Links.patch b/CraftBukkit-Patches/0088-Add-Spigot-Links.patch new file mode 100644 index 0000000000..c591e99b20 --- /dev/null +++ b/CraftBukkit-Patches/0088-Add-Spigot-Links.patch @@ -0,0 +1,77 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Thu, 23 Jan 2014 13:17:35 +1100 +Subject: [PATCH] Add Spigot Links + + +diff --git a/README.md b/README.md +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/README.md ++++ b/README.md +@@ -0,0 +0,0 @@ +-CraftBukkit ++Spigot + =========== + +-A Bukkit (Minecraft Server API) implementation ++A Spigot-API and Bukkit implementation + +-Website: [http://bukkit.org](http://bukkit.org) +-Bugs/Suggestions: [http://leaky.bukkit.org](http://leaky.bukkit.org) +-Contributing Guidelines: [CONTRIBUTING.md](https://github.com/Bukkit/CraftBukkit/blob/master/CONTRIBUTING.md) ++Website: [http://spigotmc.org](http://spigotmc.org) ++Bugs/Suggestions: [http://www.spigotmc.org/forums/bugs-feature-requests.8/](http://www.spigotmc.org/forums/bugs-feature-requests.8/) ++Contributing Guidelines: [CONTRIBUTING.md](https://github.com/SpigotMC/Spigot-API/blob/master/CONTRIBUTING.md) + + Compilation + ----------- +@@ -0,0 +0,0 @@ Compilation + We use maven to handle our dependencies. + + * Install [Maven 3](http://maven.apache.org/download.html) +-* Check out and install [Bukkit](http://github.com/Bukkit/Bukkit) +- * *Note*: this is not needed as the repository we use has Bukkit too, but you might have a newer one (with your own changes :D) ++* Check out and install [Spigot-API](http://github.com/SpigotMC/Spigot) ++ * *Note*: this is not needed as the repository we use has Spigot-API too, but you might have a newer one (with your own changes :D) + * Check out this repo and: `mvn clean package` +diff --git a/src/main/resources/configurations/bukkit.yml b/src/main/resources/configurations/bukkit.yml +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/resources/configurations/bukkit.yml ++++ b/src/main/resources/configurations/bukkit.yml +@@ -0,0 +0,0 @@ + # If you need help on this file, feel free to join us on irc or leave a message + # on the forums asking for advice. + # +-# IRC: #bukkit @ esper.net +-# (If this means nothing to you, just go to http://webchat.esper.net/?channels=bukkit ) +-# Forums: http://forums.bukkit.org/forums/bukkit-help.6/ +-# Twitter: http://twitter.com/CraftBukkit +-# Bug tracker: http://leaky.bukkit.org/ ++# IRC: #spigot @ irc.spi.gt ++# (If this means nothing to you, just go to http://irc.spi.gt/iris/?nick=&channels=spigot ) ++# Forums: http://www.spigotmc.org/forums/help.40/ ++# Bug tracker: http://www.spigotmc.org/forums/bugs-feature-requests.8/ + + + settings: +diff --git a/src/main/resources/configurations/commands.yml b/src/main/resources/configurations/commands.yml +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/resources/configurations/commands.yml ++++ b/src/main/resources/configurations/commands.yml +@@ -0,0 +0,0 @@ + # If you need help on this file, feel free to join us on irc or leave a message + # on the forums asking for advice. + # +-# IRC: #bukkit @ esper.net +-# (If this means nothing to you, just go to http://webchat.esper.net/?channels=bukkit ) +-# Forums: http://forums.bukkit.org/forums/bukkit-help.6/ +-# Twitter: http://twitter.com/CraftBukkit +-# Bug tracker: http://leaky.bukkit.org/ ++# IRC: #spigot @ irc.spi.gt ++# (If this means nothing to you, just go to http://irc.spi.gt/iris/?nick=&channels=spigot ) ++# Forums: http://www.spigotmc.org/forums/help.40/ ++# Bug tracker: http://www.spigotmc.org/forums/bugs-feature-requests.8/ + + command-block-overrides: [] + aliases: +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0089-Configurable-Ping-Sample-Size.patch b/CraftBukkit-Patches/0089-Configurable-Ping-Sample-Size.patch new file mode 100644 index 0000000000..82a0d61ffd --- /dev/null +++ b/CraftBukkit-Patches/0089-Configurable-Ping-Sample-Size.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 26 Jan 2014 21:48:34 +1100 +Subject: [PATCH] Configurable Ping Sample Size + + +diff --git a/src/main/java/net/minecraft/server/PacketStatusListener.java b/src/main/java/net/minecraft/server/PacketStatusListener.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PacketStatusListener.java ++++ b/src/main/java/net/minecraft/server/PacketStatusListener.java +@@ -0,0 +0,0 @@ public class PacketStatusListener implements PacketStatusInListener { + } + + ServerPingPlayerSample playerSample = new ServerPingPlayerSample(event.getMaxPlayers(), profiles.size()); ++ // Spigot Start ++ if ( !profiles.isEmpty() ) ++ { ++ java.util.Collections.shuffle( profiles ); // This sucks, its inefficient but we have no simple way of doing it differently ++ profiles = profiles.subList( 0, Math.min( profiles.size(), org.spigotmc.SpigotConfig.playerSample ) ); // Cap the sample to n (or less) displayed players, ie: Vanilla behaviour ++ } ++ // Spigot End + playerSample.a(profiles.toArray(new GameProfile[profiles.size()])); + + ServerPing ping = new ServerPing(); +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -0,0 +0,0 @@ public class SpigotConfig + { + commands.put( "tps", new TicksPerSecondCommand( "tps" ) ); + } ++ ++ public static int playerSample; ++ private static void playerSample() ++ { ++ playerSample = getInt( "settings.sample-count", 12 ); ++ System.out.println( "Server Ping Player Sample Count: " + playerSample ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0090-Add-Optional-Tick-Shuffling.patch b/CraftBukkit-Patches/0090-Add-Optional-Tick-Shuffling.patch new file mode 100644 index 0000000000..80eb917323 --- /dev/null +++ b/CraftBukkit-Patches/0090-Add-Optional-Tick-Shuffling.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Mon, 27 Jan 2014 08:39:26 +1100 +Subject: [PATCH] Add Optional Tick Shuffling + +This prevents players from 'gaming' the server, and strategically relogging to increase their position in the tick order. + +diff --git a/src/main/java/net/minecraft/server/ServerConnection.java b/src/main/java/net/minecraft/server/ServerConnection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/ServerConnection.java ++++ b/src/main/java/net/minecraft/server/ServerConnection.java +@@ -0,0 +0,0 @@ public class ServerConnection { + List list = this.f; + + synchronized (this.f) { ++ // Spigot Start ++ // 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 ) ++ { ++ Collections.shuffle( this.f ); ++ } ++ // Spigot End + Iterator iterator = this.f.iterator(); + + while (iterator.hasNext()) { +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -0,0 +0,0 @@ public class SpigotConfig + playerSample = getInt( "settings.sample-count", 12 ); + System.out.println( "Server Ping Player Sample Count: " + playerSample ); + } ++ ++ public static int playerShuffle; ++ private static void playerShuffle() ++ { ++ playerShuffle = getInt( "settings.player-shuffle", 0 ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0091-Allow-Configuring-Chunks-per-Packet.patch b/CraftBukkit-Patches/0091-Allow-Configuring-Chunks-per-Packet.patch new file mode 100644 index 0000000000..99478e29c3 --- /dev/null +++ b/CraftBukkit-Patches/0091-Allow-Configuring-Chunks-per-Packet.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Tue, 28 Jan 2014 20:35:35 +1100 +Subject: [PATCH] Allow Configuring Chunks per Packet + + +diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/EntityPlayer.java +@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + + Chunk chunk; + +- while (iterator1.hasNext() && arraylist.size() < PacketPlayOutMapChunkBulk.c()) { ++ while (iterator1.hasNext() && arraylist.size() < this.world.spigotConfig.maxBulkChunk) { // Spigot + ChunkCoordIntPair chunkcoordintpair = (ChunkCoordIntPair) iterator1.next(); + + if (chunkcoordintpair != null) { +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -0,0 +0,0 @@ public class SpigotWorldConfig + enableZombiePigmenPortalSpawns = getBoolean( "enable-zombie-pigmen-portal-spawns", true ); + log( "Allow Zombie Pigmen to spawn from portal blocks: " + enableZombiePigmenPortalSpawns ); + } ++ ++ public int maxBulkChunk; ++ private void bulkChunkCount() ++ { ++ maxBulkChunk = getInt( "max-bulk-chunks", 5 ); ++ log( "Sending up to " + maxBulkChunk + " chunks per packet" ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0092-Implement-Locale-Getter-for-Players.patch b/CraftBukkit-Patches/0092-Implement-Locale-Getter-for-Players.patch new file mode 100644 index 0000000000..3d945169c4 --- /dev/null +++ b/CraftBukkit-Patches/0092-Implement-Locale-Getter-for-Players.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Smove +Date: Sat, 1 Feb 2014 18:12:16 +1100 +Subject: [PATCH] Implement Locale Getter for Players + + +diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/EntityPlayer.java +@@ -0,0 +0,0 @@ import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; + public class EntityPlayer extends EntityHuman implements ICrafting { + + private static final Logger bL = LogManager.getLogger(); +- private String locale = "en_US"; ++ public String locale = "en_US"; // Spigot + public PlayerConnection playerConnection; + public final MinecraftServer server; + public final PlayerInteractManager playerInteractManager; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + getHandle().playerConnection.sendPacket( packet ); + } + } ++ ++ @Override ++ public String getLocale() ++ { ++ return getHandle().locale; ++ } + }; + + public Player.Spigot spigot() +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0093-Cap-Entity-Collisions.patch b/CraftBukkit-Patches/0093-Cap-Entity-Collisions.patch new file mode 100644 index 0000000000..5ea44b01b2 --- /dev/null +++ b/CraftBukkit-Patches/0093-Cap-Entity-Collisions.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 31 Jan 2014 11:18:34 -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. + +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -0,0 +0,0 @@ public abstract class Entity { + + public void b_(EntityHuman entityhuman) {} + ++ int numCollisions = 0; // Spigot + public void collide(Entity entity) { + if (entity.passenger != this && entity.vehicle != this) { + double d0 = entity.locX - this.locX; +diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityLiving.java ++++ b/src/main/java/net/minecraft/server/EntityLiving.java +@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { + List list = this.world.getEntities(this, this.boundingBox.grow(0.20000000298023224D, 0.0D, 0.20000000298023224D)); + + if (this.R() && list != null && !list.isEmpty()) { // Spigot: Add this.R() condition ++ numCollisions -= world.spigotConfig.maxCollisionsPerEntity; // Spigot + for (int i = 0; i < list.size(); ++i) { ++ if (numCollisions > world.spigotConfig.maxCollisionsPerEntity) { break; } // Spigot + Entity entity = (Entity) list.get(i); + + // TODO better check now? +@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { + // CraftBukkit end + + if (entity.S()) { ++ entity.numCollisions++; // Spigot ++ numCollisions++; // Spigot + this.o(entity); + } + } ++ numCollisions = 0; // Spigot + } + } + +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -0,0 +0,0 @@ public class SpigotWorldConfig + maxBulkChunk = getInt( "max-bulk-chunks", 5 ); + log( "Sending up to " + maxBulkChunk + " chunks per packet" ); + } ++ ++ public int maxCollisionsPerEntity; ++ private void maxEntityCollision() ++ { ++ maxCollisionsPerEntity = getInt( "max-entity-collisions", 8 ); ++ log( "Max Entity Collisions: " + maxCollisionsPerEntity ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0094-Fix-dispensing-bone-meal-not-having-the-correct-data.patch b/CraftBukkit-Patches/0094-Fix-dispensing-bone-meal-not-having-the-correct-data.patch new file mode 100644 index 0000000000..d2f1ba9603 --- /dev/null +++ b/CraftBukkit-Patches/0094-Fix-dispensing-bone-meal-not-having-the-correct-data.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Thu, 6 Feb 2014 21:59:20 +0000 +Subject: [PATCH] Fix dispensing bone meal not having the correct data value + + +diff --git a/src/main/java/net/minecraft/server/DispenseBehaviorBonemeal.java b/src/main/java/net/minecraft/server/DispenseBehaviorBonemeal.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/DispenseBehaviorBonemeal.java ++++ b/src/main/java/net/minecraft/server/DispenseBehaviorBonemeal.java +@@ -0,0 +0,0 @@ final class DispenseBehaviorBonemeal extends DispenseBehaviorItem { + + // CraftBukkit start + org.bukkit.block.Block block = world.getWorld().getBlockAt(isourceblock.getBlockX(), isourceblock.getBlockY(), isourceblock.getBlockZ()); +- CraftItemStack craftItem = CraftItemStack.asNewCraftStack(itemstack.getItem()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); + + BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); + if (!BlockDispenser.eventFired) { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0095-Spam-Filter-Exclusions.patch b/CraftBukkit-Patches/0095-Spam-Filter-Exclusions.patch new file mode 100644 index 0000000000..044652b905 --- /dev/null +++ b/CraftBukkit-Patches/0095-Spam-Filter-Exclusions.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 8 Feb 2014 08:13:40 +0000 +Subject: [PATCH] Spam Filter Exclusions + + +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketPlayInListener { + this.minecraftServer.getPlayerList().sendMessage(chatmessage1, false); + } + ++ // Spigot - spam exclusions ++ boolean counted = true; ++ for ( String exclude : org.spigotmc.SpigotConfig.spamExclusions ) ++ { ++ if ( exclude != null && s.startsWith( exclude ) ) ++ { ++ counted = false; ++ break; ++ } ++ } + // CraftBukkit start - replaced with thread safe throttle + // this.chatThrottle += 20; +- if (chatSpamField.addAndGet(this, 20) > 200 && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { ++ if (counted && chatSpamField.addAndGet(this, 20) > 200 && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { + if (packetplayinchat.a()) { + Waitable waitable = new Waitable() { + @Override +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -0,0 +0,0 @@ import java.io.IOException; + import java.lang.reflect.InvocationTargetException; + import java.lang.reflect.Method; + import java.lang.reflect.Modifier; ++import java.util.Arrays; + import java.util.HashMap; + import java.util.List; + import java.util.Map; +@@ -0,0 +0,0 @@ public class SpigotConfig + { + playerShuffle = getInt( "settings.player-shuffle", 0 ); + } ++ ++ public static List spamExclusions; ++ private static void spamExclusions() ++ { ++ spamExclusions = getList( "commands.spam-exclusions", Arrays.asList( new String[] ++ { ++ "/skill" ++ } ) ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0096-Add-Option-to-Silence-CommandBlock-Console.patch b/CraftBukkit-Patches/0096-Add-Option-to-Silence-CommandBlock-Console.patch new file mode 100644 index 0000000000..9ad2d73ed8 --- /dev/null +++ b/CraftBukkit-Patches/0096-Add-Option-to-Silence-CommandBlock-Console.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 9 Feb 2014 14:39:01 +1100 +Subject: [PATCH] Add Option to Silence CommandBlock Console + + +diff --git a/src/main/java/net/minecraft/server/CommandDispatcher.java b/src/main/java/net/minecraft/server/CommandDispatcher.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/CommandDispatcher.java ++++ b/src/main/java/net/minecraft/server/CommandDispatcher.java +@@ -0,0 +0,0 @@ public class CommandDispatcher extends CommandHandler implements ICommandDispatc + } + } + +- if (icommandlistener != MinecraftServer.getServer()) { ++ if (icommandlistener != MinecraftServer.getServer() && !org.spigotmc.SpigotConfig.silentCommandBlocks) { // Spigot + MinecraftServer.getServer().sendMessage(chatmessage); + } + +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -0,0 +0,0 @@ public class SpigotConfig + "/skill" + } ) ); + } ++ ++ public static boolean silentCommandBlocks; ++ private static void silentCommandBlocks() ++ { ++ silentCommandBlocks = getBoolean( "commands.silent-commandblock-console", false ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0097-Add-support-for-fetching-hidden-players.patch b/CraftBukkit-Patches/0097-Add-support-for-fetching-hidden-players.patch new file mode 100644 index 0000000000..f877b0312e --- /dev/null +++ b/CraftBukkit-Patches/0097-Add-support-for-fetching-hidden-players.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tux +Date: Sun, 9 Feb 2014 14:03:03 -0500 +Subject: [PATCH] Add support for fetching hidden players + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + { + return getHandle().locale; + } ++ ++ @Override ++ public Set getHiddenPlayers() ++ { ++ Set ret = new HashSet(); ++ for ( UUID u : hiddenPlayers ) ++ { ++ ret.add( getServer().getPlayer( u ) ); ++ } ++ ++ return java.util.Collections.unmodifiableSet( ret ); ++ } + }; + + public Player.Spigot spigot() +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0098-Allow-Disabling-Creative-Item-Filter.patch b/CraftBukkit-Patches/0098-Allow-Disabling-Creative-Item-Filter.patch new file mode 100644 index 0000000000..dba2b728f3 --- /dev/null +++ b/CraftBukkit-Patches/0098-Allow-Disabling-Creative-Item-Filter.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Wed, 12 Feb 2014 18:18:01 +1100 +Subject: [PATCH] Allow Disabling Creative Item Filter + + +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketPlayInListener { + ItemStack itemstack = packetplayinsetcreativeslot.getItemStack(); + boolean flag1 = packetplayinsetcreativeslot.c() >= 1 && packetplayinsetcreativeslot.c() < 36 + PlayerInventory.getHotbarSize(); + // CraftBukkit - Add invalidItems check +- boolean flag2 = itemstack == null || itemstack.getItem() != null && !invalidItems.contains(Item.getId(itemstack.getItem())); ++ boolean flag2 = itemstack == null || itemstack.getItem() != null && (!invalidItems.contains(Item.getId(itemstack.getItem())) || !org.spigotmc.SpigotConfig.filterCreativeItems); // Spigot + boolean flag3 = itemstack == null || itemstack.getData() >= 0 && itemstack.count <= 64 && itemstack.count > 0; + + // CraftBukkit start - Call click event +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -0,0 +0,0 @@ public class SpigotConfig + { + silentCommandBlocks = getBoolean( "commands.silent-commandblock-console", false ); + } ++ ++ public static boolean filterCreativeItems; ++ private static void filterCreativeItems() ++ { ++ filterCreativeItems = getBoolean( "settings.filter-creative-items", true ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0099-Cap-Channel-Registrations.patch b/CraftBukkit-Patches/0099-Cap-Channel-Registrations.patch new file mode 100644 index 0000000000..7a4282e722 --- /dev/null +++ b/CraftBukkit-Patches/0099-Cap-Channel-Registrations.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Wed, 12 Feb 2014 20:02:58 +1100 +Subject: [PATCH] Cap Channel Registrations + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + + public void addChannel(String channel) { ++ com.google.common.base.Preconditions.checkState( channels.size() < 128, "Too many channels registered" ); // Spigot + if (channels.add(channel)) { + server.getPluginManager().callEvent(new PlayerRegisterChannelEvent(this, channel)); + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0100-Allow-vanilla-commands-to-be-the-main-version-of-a-c.patch b/CraftBukkit-Patches/0100-Allow-vanilla-commands-to-be-the-main-version-of-a-c.patch new file mode 100644 index 0000000000..7843428038 --- /dev/null +++ b/CraftBukkit-Patches/0100-Allow-vanilla-commands-to-be-the-main-version-of-a-c.patch @@ -0,0 +1,172 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Wed, 12 Feb 2014 20:44:14 +0000 +Subject: [PATCH] Allow vanilla commands to be the main version of a command + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -0,0 +0,0 @@ import org.bukkit.command.CommandSender; + import org.bukkit.command.ConsoleCommandSender; + import org.bukkit.command.PluginCommand; + import org.bukkit.command.SimpleCommandMap; ++import org.bukkit.command.defaults.VanillaCommand; + import org.bukkit.configuration.ConfigurationSection; + import org.bukkit.configuration.file.YamlConfiguration; + import org.bukkit.configuration.serialization.ConfigurationSerialization; +@@ -0,0 +0,0 @@ public final class CraftServer implements Server { + } + + if (type == PluginLoadOrder.POSTWORLD) { ++ // Spigot start - Allow vanilla commands to be forced to be the main command ++ setVanillaCommands(true); + commandMap.setFallbackCommands(); +- setVanillaCommands(); ++ setVanillaCommands(false); ++ // Spigot end + commandMap.registerServerAliases(); + loadCustomPermissions(); + DefaultPermissions.registerCorePermissions(); +@@ -0,0 +0,0 @@ public final class CraftServer implements Server { + pluginManager.disablePlugins(); + } + +- private void setVanillaCommands() { +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandAchievement(), "/achievement give [player]")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandBan(), "/ban [reason]")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandBanIp(), "/ban-ip ")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandBanList(), "/banlist [ips]")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandClear(), "/clear [item] [metadata]")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandGamemodeDefault(), "/defaultgamemode ")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandDeop(), "/deop ")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandDifficulty(), "/difficulty ")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandEffect(), "/effect [seconds] [amplifier]")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandEnchant(), "/enchant [enchantment level]")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandGamemode(), "/gamemode [player]")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandGamerule(), "/gamerule [true|false]")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandGive(), "/give [amount] [metadata] [dataTag]")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandHelp(), "/help [page|commandname]")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandIdleTimeout(), "/setidletimeout ")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandKick(), "/kick [reason]")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandKill(), "/kill [playername]")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandList(), "/list")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandMe(), "/me ")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandOp(), "/op ")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandPardon(), "/pardon ")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandPardonIP(), "/pardon-ip ")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandPlaySound(), "/playsound [x] [y] [z] [volume] [pitch] [minimumVolume]")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandSay(), "/say ")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandScoreboard(), "/scoreboard")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandSeed(), "/seed")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandSetBlock(), "/setblock [datavalue] [oldblockHandling] [dataTag]")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandSetWorldSpawn(), "/setworldspawn [x] [y] [z]")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandSpawnpoint(), "/spawnpoint [x] [y] [z]")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandSpreadPlayers(), "/spreadplayers [spreadDistance] [maxRange] [respectTeams] ")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandSummon(), "/summon [x] [y] [z] [dataTag]")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandTp(), "/tp [player] \n/tp [player] ")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandTell(), "/tell ")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandTellRaw(), "/tellraw ")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandTestFor(), "/testfor [dataTag]")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandTestForBlock(), "/testforblock [datavalue] [dataTag]")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandTime(), "/time set \n/time add ")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandToggleDownfall(), "/toggledownfall")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandWeather(), "/weather [duration in seconds]")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandWhitelist(), "/whitelist (add|remove) \n/whitelist (on|off|list|reload)")); +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandXp(), "/xp [player]\n/xp L [player]")); ++ // Spigot start ++ private void tryRegister(VanillaCommandWrapper commandWrapper, boolean first) { ++ if (org.spigotmc.SpigotConfig.replaceCommands.contains( commandWrapper.getName() ) ) { ++ if (first) { ++ commandMap.register( "minecraft", commandWrapper ); ++ } ++ } else if (!first) { ++ commandMap.register( "minecraft", commandWrapper ); ++ } ++ } ++ ++ private void setVanillaCommands(boolean first) ++ { ++ tryRegister( new VanillaCommandWrapper( new CommandAchievement(), "/achievement give [player]" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandBan(), "/ban [reason]" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandBanIp(), "/ban-ip " ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandBanList(), "/banlist [ips]" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandClear(), "/clear [item] [metadata]" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandGamemodeDefault(), "/defaultgamemode " ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandDeop(), "/deop " ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandDifficulty(), "/difficulty " ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandEffect(), "/effect [seconds] [amplifier]" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandEnchant(), "/enchant [enchantment level]" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandGamemode(), "/gamemode [player]" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandGamerule(), "/gamerule [true|false]" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandGive(), "/give [amount] [metadata] [dataTag]" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandHelp(), "/help [page|commandname]" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandIdleTimeout(), "/setidletimeout " ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandKick(), "/kick [reason]" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandKill(), "/kill [playername]" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandList(), "/list" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandMe(), "/me " ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandOp(), "/op " ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandPardon(), "/pardon " ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandPardonIP(), "/pardon-ip " ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandPlaySound(), "/playsound [x] [y] [z] [volume] [pitch] [minimumVolume]" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandSay(), "/say " ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandScoreboard(), "/scoreboard" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandSeed(), "/seed" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandSetBlock(), "/setblock [datavalue] [oldblockHandling] [dataTag]" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandSetWorldSpawn(), "/setworldspawn [x] [y] [z]" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandSpawnpoint(), "/spawnpoint [x] [y] [z]" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandSpreadPlayers(), "/spreadplayers [spreadDistance] [maxRange] [respectTeams] " ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandSummon(), "/summon [x] [y] [z] [dataTag]" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandTp(), "/tp [player] \n/tp [player] " ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandTell(), "/tell " ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandTellRaw(), "/tellraw " ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandTestFor(), "/testfor [dataTag]" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandTestForBlock(), "/testforblock [datavalue] [dataTag]" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandTime(), "/time set \n/time add " ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandToggleDownfall(), "/toggledownfall" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandWeather(), "/weather [duration in seconds]" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandWhitelist(), "/whitelist (add|remove) \n/whitelist (on|off|list|reload)" ), first ); ++ tryRegister( new VanillaCommandWrapper( new CommandXp(), "/xp [player]\n/xp L [player]" ), first ); + // This is what is in the lang file, I swear. +- commandMap.register("minecraft", new VanillaCommandWrapper(new CommandNetstat(), "/list")); ++ tryRegister( new VanillaCommandWrapper(new CommandNetstat(), "/list"), first ); + } ++ // Spigot end + + private void loadPlugin(Plugin plugin) { + try { +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -0,0 +0,0 @@ import java.lang.reflect.Method; + import java.lang.reflect.Modifier; + import java.util.Arrays; + import java.util.HashMap; ++import java.util.HashSet; + import java.util.List; + import java.util.Map; ++import java.util.Set; + import java.util.logging.Level; + import net.minecraft.util.gnu.trove.map.hash.TObjectIntHashMap; + import net.minecraft.server.MinecraftServer; +@@ -0,0 +0,0 @@ public class SpigotConfig + { + filterCreativeItems = getBoolean( "settings.filter-creative-items", true ); + } ++ ++ public static Set replaceCommands; ++ private static void replaceCommands() ++ { ++ if ( config.contains( "replace-commands" ) ) ++ { ++ set( "commands.replace-commands", config.getStringList( "replace-commands" ) ); ++ config.set( "replace-commands", null ); ++ } ++ replaceCommands = new HashSet( (List) getList( "commands.replace-commands", ++ Arrays.asList( "setblock", "summon", "testforblock", "tellraw" ) ) ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0101-Unfinalize-the-isDisconnected-method-by-bukkit.patch b/CraftBukkit-Patches/0101-Unfinalize-the-isDisconnected-method-by-bukkit.patch new file mode 100644 index 0000000000..76a98200ff --- /dev/null +++ b/CraftBukkit-Patches/0101-Unfinalize-the-isDisconnected-method-by-bukkit.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: hcherndon +Date: Sat, 15 Feb 2014 01:51:20 -0600 +Subject: [PATCH] Unfinalize the isDisconnected() method by bukkit. + +This would literally mean the world to me. You have no idea how much this method being final is fucking me over right now. (Working with NPC's and what not.) + +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketPlayInListener { + } + + // CraftBukkit start - Add "isDisconnected" method +- public final boolean isDisconnected() { ++ public boolean isDisconnected() { + return !this.player.joining && !NetworkManager.a(this.networkManager).config().isAutoRead(); + } + // CraftBukkit end +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0102-Implement-Silenceable-Lightning-API.patch b/CraftBukkit-Patches/0102-Implement-Silenceable-Lightning-API.patch new file mode 100644 index 0000000000..76ea806fb5 --- /dev/null +++ b/CraftBukkit-Patches/0102-Implement-Silenceable-Lightning-API.patch @@ -0,0 +1,103 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: drXor +Date: Sun, 23 Feb 2014 16:16:59 -0400 +Subject: [PATCH] Implement Silenceable Lightning API + + +diff --git a/src/main/java/net/minecraft/server/EntityLightning.java b/src/main/java/net/minecraft/server/EntityLightning.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityLightning.java ++++ b/src/main/java/net/minecraft/server/EntityLightning.java +@@ -0,0 +0,0 @@ public class EntityLightning extends EntityWeather { + // CraftBukkit start + public boolean isEffect = false; + ++ public boolean isSilent = false; // Spigot ++ + public EntityLightning(World world, double d0, double d1, double d2) { + this(world, d0, d1, d2, false); + } +@@ -0,0 +0,0 @@ public class EntityLightning extends EntityWeather { + } + } + ++ // Spigot start ++ public EntityLightning(World world, double d0, double d1, double d2, boolean isEffect, boolean isSilent) ++ { ++ this( world, d0, d1, d2, isEffect ); ++ this.isSilent = isSilent; ++ } ++ // Spigot end ++ + public void h() { + super.h(); +- if (this.lifeTicks == 2) { ++ if (!isSilent && this.lifeTicks == 2) { // Spigot + // CraftBukkit start - Use relative location for far away sounds + //this.world.makeSound(this.locX, this.locY, this.locZ, "ambient.weather.thunder", 10000.0F, 0.8F + this.random.nextFloat() * 0.2F); + float pitch = 0.8F + this.random.nextFloat() * 0.2F; +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -0,0 +0,0 @@ public class CraftWorld implements World { + { + CraftWorld.this.playEffect( location, effect, 0 ); + } ++ ++ @Override ++ public LightningStrike strikeLightning(Location loc, boolean isSilent) ++ { ++ EntityLightning lightning = new EntityLightning( world, loc.getX(), loc.getY(), loc.getZ(), false, isSilent ); ++ world.strikeLightning( lightning ); ++ return new CraftLightningStrike( server, lightning ); ++ } ++ ++ @Override ++ public LightningStrike strikeLightningEffect(Location loc, boolean isSilent) ++ { ++ EntityLightning lightning = new EntityLightning( world, loc.getX(), loc.getY(), loc.getZ(), true, isSilent ); ++ world.strikeLightning( lightning ); ++ return new CraftLightningStrike( server, lightning ); ++ } + }; + + public Spigot spigot() +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java +@@ -0,0 +0,0 @@ + package org.bukkit.craftbukkit.entity; + + import net.minecraft.server.EntityLightning; ++ + import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.entity.Arrow; + import org.bukkit.entity.EntityType; + import org.bukkit.entity.LightningStrike; + +@@ -0,0 +0,0 @@ public class CraftLightningStrike extends CraftEntity implements LightningStrike + public EntityType getType() { + return EntityType.LIGHTNING; + } ++ ++ // Spigot start ++ private final LightningStrike.Spigot spigot = new LightningStrike.Spigot() ++ { ++ ++ @Override ++ public boolean isSilent() ++ { ++ return getHandle().isSilent; ++ } ++ ++ }; ++ ++ public LightningStrike.Spigot spigot() ++ { ++ return this.spigot; ++ } ++ // Spigot end + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0103-Use-one-PermissibleBase-for-all-Command-Blocks.patch b/CraftBukkit-Patches/0103-Use-one-PermissibleBase-for-all-Command-Blocks.patch new file mode 100644 index 0000000000..c39c2546b6 --- /dev/null +++ b/CraftBukkit-Patches/0103-Use-one-PermissibleBase-for-all-Command-Blocks.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: FrozenBrain +Date: Sun, 2 Mar 2014 21:13:46 +0100 +Subject: [PATCH] Use one PermissibleBase for all Command Blocks + + +diff --git a/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java +@@ -0,0 +0,0 @@ import org.bukkit.plugin.Plugin; + import java.util.Set; + + public abstract class ServerCommandSender implements CommandSender { +- private final PermissibleBase perm = new PermissibleBase(this); ++ private static PermissibleBase blockPermInst; ++ private final PermissibleBase perm; + + public ServerCommandSender() { ++ if (this instanceof CraftBlockCommandSender) { ++ if (blockPermInst == null) { ++ blockPermInst = new PermissibleBase(this); ++ } ++ this.perm = blockPermInst; ++ } else { ++ this.perm = new PermissibleBase(this); ++ } + } + + public boolean isPermissionSet(String name) { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0104-Prevent-hoppers-from-loading-chunks.patch b/CraftBukkit-Patches/0104-Prevent-hoppers-from-loading-chunks.patch new file mode 100644 index 0000000000..71259fef32 --- /dev/null +++ b/CraftBukkit-Patches/0104-Prevent-hoppers-from-loading-chunks.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Wed, 5 Mar 2014 20:27:27 +0000 +Subject: [PATCH] Prevent hoppers from loading chunks + + +diff --git a/src/main/java/net/minecraft/server/TileEntityHopper.java b/src/main/java/net/minecraft/server/TileEntityHopper.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/TileEntityHopper.java ++++ b/src/main/java/net/minecraft/server/TileEntityHopper.java +@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntity implements IHopper { + int i = MathHelper.floor(d0); + int j = MathHelper.floor(d1); + int k = MathHelper.floor(d2); ++ if ( !world.isLoaded( i, j, k ) ) return null; // Spigot + TileEntity tileentity = world.getTileEntity(i, j, k); + + if (tileentity != null && tileentity instanceof IInventory) { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0105-Guard-Entity-List.patch b/CraftBukkit-Patches/0105-Guard-Entity-List.patch new file mode 100644 index 0000000000..56a54d5456 --- /dev/null +++ b/CraftBukkit-Patches/0105-Guard-Entity-List.patch @@ -0,0 +1,77 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Mon, 10 Mar 2014 09:03:28 +1100 +Subject: [PATCH] Guard Entity List + + +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -0,0 +0,0 @@ import org.bukkit.event.weather.ThunderChangeEvent; + public abstract class World implements IBlockAccess { + + public boolean d; +- public List entityList = new ArrayList(); ++ // Spigot start - guard entity list from removals ++ public List entityList = new ArrayList() ++ { ++ @Override ++ public Object remove(int index) ++ { ++ guard(); ++ return super.remove( index ); ++ } ++ ++ @Override ++ public boolean remove(Object o) ++ { ++ guard(); ++ return super.remove( o ); ++ } ++ ++ private void guard() ++ { ++ if ( guardEntityList ) ++ { ++ throw new java.util.ConcurrentModificationException(); ++ } ++ } ++ }; ++ // Spigot end + protected List f = new ArrayList(); + public Set tileEntityList = new HashSet(); // CraftBukkit - ArrayList -> HashSet + private List a = new ArrayList(); +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + int[] I; + + // Spigot start ++ private boolean guardEntityList; + protected final net.minecraft.util.gnu.trove.map.hash.TLongShortHashMap chunkTickList; + protected float growthOdds = 100; + protected float modifiedOdds = 100; +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + + org.spigotmc.ActivationRange.activateEntities(this); // Spigot + timings.entityTick.startTiming(); // Spigot ++ guardEntityList = true; // Spigot + // CraftBukkit start - Use field for loop variable + for (this.tickPosition = 0; this.tickPosition < this.entityList.size(); ++this.tickPosition) { + entity = (Entity) this.entityList.get(this.tickPosition); +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + this.getChunkAt(j, k).b(entity); + } + ++ guardEntityList = false; // Spigot + this.entityList.remove(this.tickPosition--); // CraftBukkit - Use field for loop variable ++ guardEntityList = true; // Spigot + this.b(entity); + } + + this.methodProfiler.b(); + } ++ guardEntityList = false; // Spigot + + timings.entityTick.stopTiming(); // Spigot + this.methodProfiler.c("blockEntities"); +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0106-Fix-ConcurrentModificationException-while-being-idle.patch b/CraftBukkit-Patches/0106-Fix-ConcurrentModificationException-while-being-idle.patch new file mode 100644 index 0000000000..60acabf9c1 --- /dev/null +++ b/CraftBukkit-Patches/0106-Fix-ConcurrentModificationException-while-being-idle.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Tue, 14 Jan 2014 20:11:25 +0000 +Subject: [PATCH] Fix ConcurrentModificationException while being idle kicked + in a vehicle + + +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + this.players.remove(entity); + this.everyoneSleeping(); + } +- +- int i = entity.ah; +- int j = entity.aj; +- +- if (entity.ag && this.isChunkLoaded(i, j)) { +- this.getChunkAt(i, j).b(entity); +- } +- +- // CraftBukkit start - Decrement loop variable field if we've already ticked this entity +- int index = this.entityList.indexOf(entity); +- if (index != -1) { +- if (index <= this.tickPosition) { +- this.tickPosition--; ++ // Spigot start ++ if (!guardEntityList) { // It will get removed after the tick if we are ticking ++ int i = entity.ah; ++ int j = entity.aj; ++ if (entity.ag && this.isChunkLoaded(i, j)) { ++ this.getChunkAt(i, j).b(entity); + } +- this.entityList.remove(index); ++ // CraftBukkit start - Decrement loop variable field if we've already ticked this entity ++ int index = this.entityList.indexOf(entity); ++ if (index != -1) { ++ if (index <= this.tickPosition) { ++ this.tickPosition--; ++ } ++ this.entityList.remove(index); ++ } ++ // CraftBukkit end + } +- // CraftBukkit end ++ // Spigot end + + this.b(entity); + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0107-Cancellable-WitherSkull-potion-effect.patch b/CraftBukkit-Patches/0107-Cancellable-WitherSkull-potion-effect.patch new file mode 100644 index 0000000000..da1c63aeed --- /dev/null +++ b/CraftBukkit-Patches/0107-Cancellable-WitherSkull-potion-effect.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: drXor +Date: Tue, 25 Feb 2014 15:15:26 -0400 +Subject: [PATCH] Cancellable WitherSkull potion effect + + +diff --git a/src/main/java/net/minecraft/server/EntityWitherSkull.java b/src/main/java/net/minecraft/server/EntityWitherSkull.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityWitherSkull.java ++++ b/src/main/java/net/minecraft/server/EntityWitherSkull.java +@@ -0,0 +0,0 @@ public class EntityWitherSkull extends EntityFireball { + protected void a(MovingObjectPosition movingobjectposition) { + if (!this.world.isStatic) { + if (movingobjectposition.entity != null) { ++ // Spigot start ++ boolean didDamage = false; + if (this.shooter != null) { +- if (movingobjectposition.entity.damageEntity(DamageSource.mobAttack(this.shooter), 8.0F) && !movingobjectposition.entity.isAlive()) { ++ didDamage = movingobjectposition.entity.damageEntity(DamageSource.mobAttack(this.shooter), 8.0F); ++ if (didDamage && !movingobjectposition.entity.isAlive()) { + this.shooter.heal(5.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.WITHER); // CraftBukkit + } + } else { +- movingobjectposition.entity.damageEntity(DamageSource.MAGIC, 5.0F); ++ didDamage = movingobjectposition.entity.damageEntity(DamageSource.MAGIC, 5.0F); + } + +- if (movingobjectposition.entity instanceof EntityLiving) { ++ if (didDamage && movingobjectposition.entity instanceof EntityLiving) { ++ // Spigot end + byte b0 = 0; + + if (this.world.difficulty == EnumDifficulty.NORMAL) { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0108-Descriptive-kick-reasons-instead-of-Nope.patch b/CraftBukkit-Patches/0108-Descriptive-kick-reasons-instead-of-Nope.patch new file mode 100644 index 0000000000..ab61acccd0 --- /dev/null +++ b/CraftBukkit-Patches/0108-Descriptive-kick-reasons-instead-of-Nope.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: drXor +Date: Sat, 15 Mar 2014 01:30:05 -0400 +Subject: [PATCH] Descriptive kick reasons instead of Nope! + + +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -0,0 +0,0 @@ public abstract class Entity { + if ((f == Float.POSITIVE_INFINITY) || (f == Float.NEGATIVE_INFINITY)) { + if (this instanceof EntityPlayer) { + this.world.getServer().getLogger().warning(((CraftPlayer) this.getBukkitEntity()).getName() + " was caught trying to crash the server with an invalid yaw"); +- ((CraftPlayer) this.getBukkitEntity()).kickPlayer("Nope"); ++ ((CraftPlayer) this.getBukkitEntity()).kickPlayer("Infinite yaw (Hacking?)"); //Spigot "Nope" -> Descriptive reason + } + f = 0; + } +@@ -0,0 +0,0 @@ public abstract class Entity { + if ((f1 == Float.POSITIVE_INFINITY) || (f1 == Float.NEGATIVE_INFINITY)) { + if (this instanceof EntityPlayer) { + this.world.getServer().getLogger().warning(((CraftPlayer) this.getBukkitEntity()).getName() + " was caught trying to crash the server with an invalid pitch"); +- ((CraftPlayer) this.getBukkitEntity()).kickPlayer("Nope"); ++ ((CraftPlayer) this.getBukkitEntity()).kickPlayer("Infinite pitch (Hacking?)"); //Spigot "Nope" -> Descriptive reason + } + f1 = 0; + } +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketPlayInListener { + // CraftBukkit start - Check for NaN + if (Double.isNaN(packetplayinflying.x) || Double.isNaN(packetplayinflying.y) || Double.isNaN(packetplayinflying.z) || Double.isNaN(packetplayinflying.stance)) { + c.warn(player.getName() + " was caught trying to crash the server with an invalid position."); +- getPlayer().kickPlayer("Nope!"); ++ getPlayer().kickPlayer("NaN in position (Hacking?)"); //Spigot "Nope" -> Descriptive reason + return; + } + // CraftBukkit end +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketPlayInListener { + this.player.v(); + } else { + c.warn(this.player.getName() + " tried to set an invalid carried item"); +- this.disconnect("Nope!"); // CraftBukkit ++ this.disconnect("Invalid hotbar selection (Hacking?)"); // CraftBukkit //Spigot "Nope" -> Descriptive reason + } + } + +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0109-Check-for-manually-prefixed-commands-or-commands-tha.patch b/CraftBukkit-Patches/0109-Check-for-manually-prefixed-commands-or-commands-tha.patch new file mode 100644 index 0000000000..af31ca3a36 --- /dev/null +++ b/CraftBukkit-Patches/0109-Check-for-manually-prefixed-commands-or-commands-tha.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Sun, 23 Mar 2014 01:12:10 +0000 +Subject: [PATCH] Check for manually prefixed commands or commands that don't + need a prefix for calling vanilla commands with command blocks + + +diff --git a/src/main/java/net/minecraft/server/CommandBlockListenerAbstract.java b/src/main/java/net/minecraft/server/CommandBlockListenerAbstract.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/CommandBlockListenerAbstract.java ++++ b/src/main/java/net/minecraft/server/CommandBlockListenerAbstract.java +@@ -0,0 +0,0 @@ public abstract class CommandBlockListenerAbstract implements ICommandListener { + } + } + ++ // Spigot start - check for manually prefixed command or commands that don't need a prefix ++ org.bukkit.command.Command commandBlockCommand = commandMap.getCommand(args[0]); ++ if (commandBlockCommand instanceof VanillaCommandWrapper) { ++ this.b = ((VanillaCommandWrapper) commandBlockCommand).dispatchVanillaCommandBlock(this, this.e); ++ return; ++ } ++ // Spigot end ++ + // Make sure this is a valid command + if (commandMap.getCommand(args[0]) == null) { + this.b = 0; +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0110-Cap-window-names-to-prevent-client-disconnects.patch b/CraftBukkit-Patches/0110-Cap-window-names-to-prevent-client-disconnects.patch new file mode 100644 index 0000000000..084c7cd063 --- /dev/null +++ b/CraftBukkit-Patches/0110-Cap-window-names-to-prevent-client-disconnects.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Sun, 23 Mar 2014 10:53:48 +0000 +Subject: [PATCH] Cap window names to prevent client disconnects + + +diff --git a/src/main/java/net/minecraft/server/PacketPlayOutOpenWindow.java b/src/main/java/net/minecraft/server/PacketPlayOutOpenWindow.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PacketPlayOutOpenWindow.java ++++ b/src/main/java/net/minecraft/server/PacketPlayOutOpenWindow.java +@@ -0,0 +0,0 @@ public class PacketPlayOutOpenWindow extends Packet { + public PacketPlayOutOpenWindow() {} + + public PacketPlayOutOpenWindow(int i, int j, String s, int k, boolean flag) { ++ if (s.length() > 32) s = s.substring( 0, 32 ); // Spigot - Cap window name to prevent client disconnects + this.a = i; + this.b = j; + this.c = s; +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0111-Enable-Improved-Ping-Sending.patch b/CraftBukkit-Patches/0111-Enable-Improved-Ping-Sending.patch new file mode 100644 index 0000000000..010a48decd --- /dev/null +++ b/CraftBukkit-Patches/0111-Enable-Improved-Ping-Sending.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 24 Feb 2013 20:45:20 +1100 +Subject: [PATCH] Enable Improved Ping Sending + + +diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/EntityPlayer.java +@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + public boolean keepLevel = false; + public double maxHealthCache; + public boolean joining = true; ++ public int lastPing = -1; // Spigot + // CraftBukkit end + // Spigot start + public boolean collidesWithEntities = true; +diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerList.java ++++ b/src/main/java/net/minecraft/server/PlayerList.java +@@ -0,0 +0,0 @@ public abstract class PlayerList { + // CraftBukkit end + } + ++ private int currentPing = 0; ++ + public void tick() { + if (++this.t > 600) { + this.t = 0; +@@ -0,0 +0,0 @@ public abstract class PlayerList { + this.sendAll(new PacketPlayOutPlayerInfo(entityplayer.getName(), true, entityplayer.ping)); + } + // CraftBukkit end */ ++ // Spigot start ++ try ++ { ++ if ( !players.isEmpty() ) ++ { ++ currentPing = ( currentPing + 1 ) % this.players.size(); ++ EntityPlayer player = (EntityPlayer) this.players.get( currentPing ); ++ if ( player.lastPing == -1 || Math.abs( player.ping - player.lastPing ) > 20 ) ++ { ++ Packet packet = new PacketPlayOutPlayerInfo( player.listName, true, player.ping ); ++ for ( EntityPlayer splayer : (List) this.players ) ++ { ++ if ( splayer.getBukkitEntity().canSee( player.getBukkitEntity() ) ) ++ { ++ splayer.playerConnection.sendPacket( packet ); ++ } ++ } ++ player.lastPing = player.ping; ++ } ++ } ++ } catch ( Exception e ) { ++ // Better safe than sorry :) ++ } ++ // Spigot end + } + + public void sendAll(Packet packet) { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0112-Configurable-dragon-death-and-wither-spawn-sounds.patch b/CraftBukkit-Patches/0112-Configurable-dragon-death-and-wither-spawn-sounds.patch new file mode 100644 index 0000000000..7b30949a63 --- /dev/null +++ b/CraftBukkit-Patches/0112-Configurable-dragon-death-and-wither-spawn-sounds.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: drXor +Date: Sat, 29 Mar 2014 13:44:25 -0400 +Subject: [PATCH] Configurable dragon death and wither spawn sounds + + +diff --git a/src/main/java/net/minecraft/server/EntityEnderDragon.java b/src/main/java/net/minecraft/server/EntityEnderDragon.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityEnderDragon.java ++++ b/src/main/java/net/minecraft/server/EntityEnderDragon.java +@@ -0,0 +0,0 @@ public class EntityEnderDragon extends EntityInsentient implements IComplex, IMo + double deltaX = this.locX - player.locX; + double deltaZ = this.locZ - player.locZ; + double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; ++ if ( world.spigotConfig.dragonDeathSoundRadius > 0 && distanceSquared > world.spigotConfig.dragonDeathSoundRadius * world.spigotConfig.dragonDeathSoundRadius ) continue; // Spigot + if (distanceSquared > viewDistance * viewDistance) { + double deltaLength = Math.sqrt(distanceSquared); + double relativeX = player.locX + (deltaX / deltaLength) * viewDistance; +diff --git a/src/main/java/net/minecraft/server/EntityWither.java b/src/main/java/net/minecraft/server/EntityWither.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityWither.java ++++ b/src/main/java/net/minecraft/server/EntityWither.java +@@ -0,0 +0,0 @@ public class EntityWither extends EntityMonster implements IRangedEntity { + double deltaX = this.locX - player.locX; + double deltaZ = this.locZ - player.locZ; + double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; ++ if ( world.spigotConfig.witherSpawnSoundRadius > 0 && distanceSquared > world.spigotConfig.witherSpawnSoundRadius * world.spigotConfig.witherSpawnSoundRadius ) continue; // Spigot + if (distanceSquared > viewDistance * viewDistance) { + double deltaLength = Math.sqrt(distanceSquared); + double relativeX = player.locX + (deltaX / deltaLength) * viewDistance; +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -0,0 +0,0 @@ public class SpigotWorldConfig + maxCollisionsPerEntity = getInt( "max-entity-collisions", 8 ); + log( "Max Entity Collisions: " + maxCollisionsPerEntity ); + } ++ ++ public int dragonDeathSoundRadius; ++ private void keepDragonDeathPerWorld() ++ { ++ dragonDeathSoundRadius = getInt( "dragon-death-sound-radius", 0 ); ++ } ++ ++ public int witherSpawnSoundRadius; ++ private void witherSpawnSoundRadius() ++ { ++ witherSpawnSoundRadius = getInt( "wither-spawn-sound-radius", 0 ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0113-Display-Spigot-in-client-crashes-server-lists-and-Mo.patch b/CraftBukkit-Patches/0113-Display-Spigot-in-client-crashes-server-lists-and-Mo.patch new file mode 100644 index 0000000000..763043e36a --- /dev/null +++ b/CraftBukkit-Patches/0113-Display-Spigot-in-client-crashes-server-lists-and-Mo.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Fri, 11 Apr 2014 11:16:34 +0100 +Subject: [PATCH] Display 'Spigot' in client crashes, server lists and Mojang + stats + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + } + + public String getServerModName() { +- return server.getName(); // CraftBukkit - cb > vanilla! ++ return "Spigot"; // Spigot - Spigot > // CraftBukkit - cb > vanilla! + } + + public CrashReport b(CrashReport crashreport) { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0114-Old-New-Version-Support.patch b/CraftBukkit-Patches/0114-Old-New-Version-Support.patch new file mode 100644 index 0000000000..0d48389a2c --- /dev/null +++ b/CraftBukkit-Patches/0114-Old-New-Version-Support.patch @@ -0,0 +1,244 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 12 Apr 2014 15:11:15 +1000 +Subject: [PATCH] Old / New Version Support. + +This adds support for newer / older Minecraft versions. +At present it supports protocol versions 4 and 5 (1.7.2-1.7.8). + +diff --git a/src/main/java/net/minecraft/server/HandshakeListener.java b/src/main/java/net/minecraft/server/HandshakeListener.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/HandshakeListener.java ++++ b/src/main/java/net/minecraft/server/HandshakeListener.java +@@ -0,0 +0,0 @@ public class HandshakeListener implements PacketHandshakingInListener { + } + + public void a(PacketHandshakingInSetProtocol packethandshakinginsetprotocol) { ++ // Spigot start ++ if ( NetworkManager.SUPPORTED_VERSIONS.contains( packethandshakinginsetprotocol.d() ) ) ++ { ++ NetworkManager.a( this.b ).attr( NetworkManager.protocolVersion ).set( packethandshakinginsetprotocol.d() ); ++ } ++ // Spigot end + switch (ProtocolOrdinalWrapper.a[packethandshakinginsetprotocol.c().ordinal()]) { + case 1: + this.b.a(EnumProtocol.LOGIN); +@@ -0,0 +0,0 @@ public class HandshakeListener implements PacketHandshakingInListener { + chatcomponenttext = new ChatComponentText( org.spigotmc.SpigotConfig.outdatedServerMessage ); // Spigot + this.b.handle(new PacketLoginOutDisconnect(chatcomponenttext), new GenericFutureListener[0]); + this.b.close(chatcomponenttext); +- } else if (packethandshakinginsetprotocol.d() < 5) { ++ } else if (packethandshakinginsetprotocol.d() < 4) { + chatcomponenttext = new ChatComponentText( org.spigotmc.SpigotConfig.outdatedClientMessage ); // Spigot + this.b.handle(new PacketLoginOutDisconnect(chatcomponenttext), new GenericFutureListener[0]); + this.b.close(chatcomponenttext); +diff --git a/src/main/java/net/minecraft/server/NetworkManager.java b/src/main/java/net/minecraft/server/NetworkManager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/NetworkManager.java ++++ b/src/main/java/net/minecraft/server/NetworkManager.java +@@ -0,0 +0,0 @@ import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + import org.apache.logging.log4j.Marker; + import org.apache.logging.log4j.MarkerManager; ++// Spigot start ++import com.google.common.collect.ImmutableSet; ++// Spigot end + + public class NetworkManager extends SimpleChannelInboundHandler { + +@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler { + private EnumProtocol p; + private IChatBaseComponent q; + private boolean r; ++ // Spigot Start ++ public static final AttributeKey protocolVersion = new AttributeKey("protocol_version"); ++ public static final ImmutableSet SUPPORTED_VERSIONS = ImmutableSet.of(4, 5); ++ public static final int CURRENT_VERSION = 5; ++ public static int getVersion(Channel attr) ++ { ++ Integer ver = attr.attr( protocolVersion ).get(); ++ return ( ver != null ) ? ver : CURRENT_VERSION; ++ } ++ public int getVersion() ++ { ++ return getVersion( this.m ); ++ } ++ // Spigot End + + public NetworkManager(boolean flag) { + this.j = flag; +diff --git a/src/main/java/net/minecraft/server/PacketDataSerializer.java b/src/main/java/net/minecraft/server/PacketDataSerializer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PacketDataSerializer.java ++++ b/src/main/java/net/minecraft/server/PacketDataSerializer.java +@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.inventory.CraftItemStack; // CraftBukkit + public class PacketDataSerializer extends ByteBuf { + + private final ByteBuf a; ++ // Spigot Start ++ public final int version; + +- public PacketDataSerializer(ByteBuf bytebuf) { ++ public PacketDataSerializer(ByteBuf bytebuf) ++ { ++ this( bytebuf, NetworkManager.CURRENT_VERSION ); ++ } ++ ++ public PacketDataSerializer(ByteBuf bytebuf, int version) { + this.a = bytebuf; ++ this.version = version; + } ++ // Spigot End + + public static int a(int i) { + return (i & -128) == 0 ? 1 : ((i & -16384) == 0 ? 2 : ((i & -2097152) == 0 ? 3 : ((i & -268435456) == 0 ? 4 : 5))); +diff --git a/src/main/java/net/minecraft/server/PacketEncoder.java b/src/main/java/net/minecraft/server/PacketEncoder.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/PacketEncoder.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.io.IOException; ++ ++import net.minecraft.util.com.google.common.collect.BiMap; ++import net.minecraft.util.io.netty.buffer.ByteBuf; ++import net.minecraft.util.io.netty.channel.ChannelHandlerContext; ++import net.minecraft.util.io.netty.handler.codec.MessageToByteEncoder; ++import org.apache.logging.log4j.LogManager; ++import org.apache.logging.log4j.Logger; ++import org.apache.logging.log4j.Marker; ++import org.apache.logging.log4j.MarkerManager; ++ ++public class PacketEncoder extends MessageToByteEncoder { ++ ++ private static final Logger a = LogManager.getLogger(); ++ private static final Marker b = MarkerManager.getMarker("PACKET_SENT", NetworkManager.b); ++ private final NetworkStatistics c; ++ ++ public PacketEncoder(NetworkStatistics networkstatistics) { ++ this.c = networkstatistics; ++ } ++ ++ protected void a(ChannelHandlerContext channelhandlercontext, Packet packet, ByteBuf bytebuf) throws IOException { ++ Integer integer = (Integer) ((BiMap) channelhandlercontext.channel().attr(NetworkManager.f).get()).inverse().get(packet.getClass()); ++ ++ if (a.isDebugEnabled()) { ++ a.debug(b, "OUT: [{}:{}] {}[{}]", new Object[] { channelhandlercontext.channel().attr(NetworkManager.d).get(), integer, packet.getClass().getName(), packet.b()}); ++ } ++ ++ if (integer == null) { ++ throw new IOException("Can\'t serialize unregistered packet"); ++ } else { ++ PacketDataSerializer packetdataserializer = new PacketDataSerializer(bytebuf, NetworkManager.getVersion(channelhandlercontext.channel())); // Spigot ++ ++ packetdataserializer.b(integer.intValue()); ++ packet.b(packetdataserializer); ++ this.c.b(integer.intValue(), (long) packetdataserializer.readableBytes()); ++ } ++ } ++ ++ protected void encode(ChannelHandlerContext channelhandlercontext, Object object, ByteBuf bytebuf) throws IOException { ++ this.a(channelhandlercontext, (Packet) object, bytebuf); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/PacketLoginOutSuccess.java b/src/main/java/net/minecraft/server/PacketLoginOutSuccess.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/PacketLoginOutSuccess.java +@@ -0,0 +0,0 @@ ++package net.minecraft.server; ++ ++import java.io.IOException; ++import java.util.UUID; ++ ++import net.minecraft.util.com.mojang.authlib.GameProfile; ++ ++public class PacketLoginOutSuccess extends Packet { ++ ++ private GameProfile a; ++ ++ public PacketLoginOutSuccess() {} ++ ++ public PacketLoginOutSuccess(GameProfile gameprofile) { ++ this.a = gameprofile; ++ } ++ ++ public void a(PacketDataSerializer packetdataserializer) throws IOException { ++ String s = packetdataserializer.c(36); ++ String s1 = packetdataserializer.c(16); ++ UUID uuid = UUID.fromString(s); ++ ++ this.a = new GameProfile(uuid, s1); ++ } ++ ++ public void b(PacketDataSerializer packetdataserializer) throws IOException { ++ UUID uuid = this.a.getId(); ++ ++ packetdataserializer.a(uuid == null ? "" : ( ( packetdataserializer.version >= 5 ) ? uuid.toString() : uuid.toString().replaceAll( "-", "" ) ) ); ++ packetdataserializer.a(this.a.getName()); ++ } ++ ++ public void a(PacketLoginOutListener packetloginoutlistener) { ++ packetloginoutlistener.a(this); ++ } ++ ++ public boolean a() { ++ return true; ++ } ++ ++ public void handle(PacketListener packetlistener) { ++ this.a((PacketLoginOutListener) packetlistener); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/PacketPlayOutNamedEntitySpawn.java b/src/main/java/net/minecraft/server/PacketPlayOutNamedEntitySpawn.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PacketPlayOutNamedEntitySpawn.java ++++ b/src/main/java/net/minecraft/server/PacketPlayOutNamedEntitySpawn.java +@@ -0,0 +0,0 @@ public class PacketPlayOutNamedEntitySpawn extends Packet { + packetdataserializer.b(this.a); + UUID uuid = this.b.getId(); + +- packetdataserializer.a(uuid == null ? "" : uuid.toString()); ++ packetdataserializer.a( uuid == null ? "" : ( ( packetdataserializer.version >= 5 ) ? uuid.toString() : uuid.toString().replaceAll( "-", "" ) ) ); // Spigot + packetdataserializer.a(this.b.getName().length() > 16 ? this.b.getName().substring(0, 16) : this.b.getName()); // CraftBukkit - Limit name length to 16 characters ++ if (packetdataserializer.version >= 5 ) { // Spigot + packetdataserializer.b(this.b.getProperties().size()); + Iterator iterator = this.b.getProperties().values().iterator(); + +@@ -0,0 +0,0 @@ public class PacketPlayOutNamedEntitySpawn extends Packet { + packetdataserializer.a(property.getValue()); + packetdataserializer.a(property.getSignature()); + } ++ } // Spigot + + packetdataserializer.writeInt(this.c); + packetdataserializer.writeInt(this.d); +diff --git a/src/main/java/net/minecraft/server/PacketStatusListener.java b/src/main/java/net/minecraft/server/PacketStatusListener.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PacketStatusListener.java ++++ b/src/main/java/net/minecraft/server/PacketStatusListener.java +@@ -0,0 +0,0 @@ public class PacketStatusListener implements PacketStatusInListener { + ping.setFavicon(event.icon.value); + ping.setMOTD(new ChatComponentText(event.getMotd())); + ping.setPlayerSample(playerSample); +- ping.setServerInfo(new ServerPingServerData(minecraftServer.getServerModName() + " " + minecraftServer.getVersion(), 5)); // TODO: Update when protocol changes ++ ping.setServerInfo(new ServerPingServerData(minecraftServer.getServerModName() + " " + minecraftServer.getVersion(), networkManager.getVersion())); // TODO: Update when protocol changes + + this.networkManager.handle(new PacketStatusOutServerInfo(ping), new GenericFutureListener[0]); + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/server/TileEntitySkull.java b/src/main/java/net/minecraft/server/TileEntitySkull.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/TileEntitySkull.java ++++ b/src/main/java/net/minecraft/server/TileEntitySkull.java +@@ -0,0 +0,0 @@ public class TileEntitySkull extends TileEntity { + + GameProfileSerializer.serialize(nbttagcompound1, this.j); + nbttagcompound.set("Owner", nbttagcompound1); ++ nbttagcompound.setString("ExtraType", nbttagcompound1.getString("Name")); // Spigot + } + } + +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0115-Treat-Bungee-as-Online-Mode.patch b/CraftBukkit-Patches/0115-Treat-Bungee-as-Online-Mode.patch new file mode 100644 index 0000000000..c90134d659 --- /dev/null +++ b/CraftBukkit-Patches/0115-Treat-Bungee-as-Online-Mode.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 12 Apr 2014 21:23:58 +1000 +Subject: [PATCH] Treat Bungee as Online Mode + + +diff --git a/src/main/java/net/minecraft/server/NameReferencingFileConverter.java b/src/main/java/net/minecraft/server/NameReferencingFileConverter.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/NameReferencingFileConverter.java ++++ b/src/main/java/net/minecraft/server/NameReferencingFileConverter.java +@@ -0,0 +0,0 @@ public class NameReferencingFileConverter { + private static void a(MinecraftServer minecraftserver, Collection collection, ProfileLookupCallback profilelookupcallback) { + String[] astring = (String[]) Iterators.toArray(Iterators.filter(collection.iterator(), new PredicateEmptyList()), String.class); + +- if (minecraftserver.getOnlineMode()) { ++ if (minecraftserver.getOnlineMode() || org.spigotmc.SpigotConfig.bungee) { // Spigot: bungee = online mode, for now. + minecraftserver.getGameProfileRepository().findProfilesByNames(astring, Agent.MINECRAFT, profilelookupcallback); + } else { + String[] astring1 = astring; +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0116-Fix-several-occurances-of-missed-diff.patch b/CraftBukkit-Patches/0116-Fix-several-occurances-of-missed-diff.patch new file mode 100644 index 0000000000..c7cd912a29 --- /dev/null +++ b/CraftBukkit-Patches/0116-Fix-several-occurances-of-missed-diff.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 12 Apr 2014 17:49:14 +1000 +Subject: [PATCH] Fix several occurances of missed diff. + + +diff --git a/src/main/java/net/minecraft/server/DispenseBehaviorFireball.java b/src/main/java/net/minecraft/server/DispenseBehaviorFireball.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/DispenseBehaviorFireball.java ++++ b/src/main/java/net/minecraft/server/DispenseBehaviorFireball.java +@@ -0,0 +0,0 @@ final class DispenseBehaviorFireball extends DispenseBehaviorItem { + EnumFacing enumfacing = BlockDispenser.b(isourceblock.h()); + IPosition iposition = BlockDispenser.a(isourceblock); + double d0 = iposition.getX() + (double) ((float) enumfacing.getAdjacentX() * 0.3F); +- double d1 = iposition.getY() + (double) ((float) enumfacing.getAdjacentY() * 0.3F); ++ double d1 = iposition.getY() + (double) ((float) enumfacing.getAdjacentX() * 0.3F); + double d2 = iposition.getZ() + (double) ((float) enumfacing.getAdjacentZ() * 0.3F); + World world = isourceblock.k(); + Random random = world.random; +diff --git a/src/main/java/net/minecraft/server/EntityBoat.java b/src/main/java/net/minecraft/server/EntityBoat.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityBoat.java ++++ b/src/main/java/net/minecraft/server/EntityBoat.java +@@ -0,0 +0,0 @@ public class EntityBoat extends Entity { + return !this.dead; + } + +- public void h() { ++ public void h() { + // CraftBukkit start + double prevX = this.locX; + double prevY = this.locY; +diff --git a/src/main/java/net/minecraft/server/EntityItem.java b/src/main/java/net/minecraft/server/EntityItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityItem.java ++++ b/src/main/java/net/minecraft/server/EntityItem.java +@@ -0,0 +0,0 @@ public class EntityItem extends Entity { + public ItemStack getItemStack() { + ItemStack itemstack = this.getDataWatcher().getItemStack(10); + +- return itemstack == null ? new ItemStack(Blocks.STONE) : itemstack; ++ return itemstack == null ? new ItemStack(Blocks.STONE) : itemstack; + } + + public void setItemStack(ItemStack itemstack) { +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketPlayInListener { + } + + if (itemstack.getItem() == Items.WRITTEN_BOOK && itemstack1.getItem() == Items.BOOK_AND_QUILL) { +- CraftEventFactory.handleEditBookEvent(player, itemstack); // CraftBukkit ++ CraftEventFactory.handleEditBookEvent(player, itemstack); // CraftBukkit + } + + return; +diff --git a/src/main/java/net/minecraft/server/PlayerSelector.java b/src/main/java/net/minecraft/server/PlayerSelector.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerSelector.java ++++ b/src/main/java/net/minecraft/server/PlayerSelector.java +@@ -0,0 +0,0 @@ + package net.minecraft.server; + +-import java.util.*; ++import java.util.Collections; ++import java.util.HashMap; ++import java.util.Iterator; ++import java.util.List; ++import java.util.Map; + import java.util.regex.Matcher; + import java.util.regex.Pattern; + +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0117-Fix-PlayerFishEvent-not-properly-cancelling.-Fixes-B.patch b/CraftBukkit-Patches/0117-Fix-PlayerFishEvent-not-properly-cancelling.-Fixes-B.patch new file mode 100644 index 0000000000..c0b3194e51 --- /dev/null +++ b/CraftBukkit-Patches/0117-Fix-PlayerFishEvent-not-properly-cancelling.-Fixes-B.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: myiume +Date: Wed, 19 Feb 2014 15:40:37 +0200 +Subject: [PATCH] Fix PlayerFishEvent not properly cancelling. Fixes + BUKKIT-5245,BUKKIT-5396 + +PlayerFishEvent event states are not properly being cancelled, +the FishingHookEntity being deleted when the event is cancelled, +thus making the event happen. The event states of CAUGHT_ENTITY, +CAUGHT_FISH, FAILED_ATTEMPT, IN_GROUND must keep the +EntityFishingHook alive in order to cancel the event. +Removed the entity despawn lines when event is cancelled +and added a cancelled action for FAILED_ATTEMPT state. + +diff --git a/src/main/java/net/minecraft/server/EntityFishingHook.java b/src/main/java/net/minecraft/server/EntityFishingHook.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityFishingHook.java ++++ b/src/main/java/net/minecraft/server/EntityFishingHook.java +@@ -0,0 +0,0 @@ public class EntityFishingHook extends Entity { + this.world.getServer().getPluginManager().callEvent(playerFishEvent); + + if (playerFishEvent.isCancelled()) { +- this.die(); +- this.owner.hookedFish = null; + return 0; + } + // CraftBukkit end +@@ -0,0 +0,0 @@ public class EntityFishingHook extends Entity { + this.world.getServer().getPluginManager().callEvent(playerFishEvent); + + if (playerFishEvent.isCancelled()) { +- this.die(); +- this.owner.hookedFish = null; + return 0; + } + // CraftBukkit end +@@ -0,0 +0,0 @@ public class EntityFishingHook extends Entity { + this.world.getServer().getPluginManager().callEvent(playerFishEvent); + + if (playerFishEvent.isCancelled()) { +- this.die(); +- this.owner.hookedFish = null; + return 0; + } + // CraftBukkit end +@@ -0,0 +0,0 @@ public class EntityFishingHook extends Entity { + if (b0 == 0) { + PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) this.owner.getBukkitEntity(), null, (Fish) this.getBukkitEntity(), PlayerFishEvent.State.FAILED_ATTEMPT); + this.world.getServer().getPluginManager().callEvent(playerFishEvent); ++ ++ if (playerFishEvent.isCancelled()) { ++ return 0; ++ } + } + // CraftBukkit end + +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0118-Update-Warning.patch b/CraftBukkit-Patches/0118-Update-Warning.patch new file mode 100644 index 0000000000..6bed755c55 --- /dev/null +++ b/CraftBukkit-Patches/0118-Update-Warning.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 12 Apr 2014 21:37:12 +1000 +Subject: [PATCH] Update Warning + + +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -0,0 +0,0 @@ + package org.bukkit.craftbukkit; + ++import java.io.BufferedReader; + import java.io.File; + import java.io.IOException; ++import java.io.InputStreamReader; + import java.text.SimpleDateFormat; + import java.util.Arrays; + import java.util.List; ++import java.util.concurrent.TimeUnit; + import java.util.logging.Level; + import java.util.logging.Logger; + import joptsimple.OptionParser; +@@ -0,0 +0,0 @@ public class Main { + public static boolean useJline = true; + public static boolean useConsole = true; + +- public static void main(String[] args) { ++ public static void main(String[] args) throws IOException { ++ // Spigot Start ++ File lock = new File( ".update-lock" ); ++ if ( !new File( "update-lock" ).exists() && !lock.exists() && System.getProperty( "IReallyKnowWhatIAmDoingThisUpdate" ) == null ) ++ { ++ System.err.println( "WARNING: This Minecraft update alters the way in which saved data is stored." ); ++ System.err.println( "Please ensure your server is in the correct online/offline mode state, as the changes made are PERMANENT" ); ++ System.err.println( "If you are running in offline mode, but your BungeeCord is in online mode, it is imperative that BungeeCord support is enabled in spigot.yml and BungeeCord's config.yml" ); ++ System.err.println( "By typing `yes` you acknowledge that you have taken the necessary backups and are aware of this conversion" ); ++ System.err.println( "Please type yes to continue starting the server. You have been warned :)" ); ++ System.err.println( "See http://www.spigotmc.org/wiki/uuid-conversion/ if you have any questions and remember BACKUP BACKUP BACKUP" ); ++ System.err.println( "=================================================================================" ); ++ System.err.println( "Starting server in 10 seconds" ); ++ lock.createNewFile(); ++ try ++ { ++ Thread.sleep( TimeUnit.SECONDS.toMillis( 10 ) ); ++ } catch ( InterruptedException ex ) ++ { ++ } ++ } ++ // Spigot End + // Todo: Installation script + OptionParser parser = new OptionParser() { + { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0119-Add-Conversion-Message.patch b/CraftBukkit-Patches/0119-Add-Conversion-Message.patch new file mode 100644 index 0000000000..22aa800723 --- /dev/null +++ b/CraftBukkit-Patches/0119-Add-Conversion-Message.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sat, 12 Apr 2014 23:30:44 +1000 +Subject: [PATCH] Add Conversion Message + + +diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/DedicatedServer.java +@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + } + + protected boolean aE() { ++ server.getLogger().info( "**** Beginning UUID conversion, this may take A LONG time ****"); // Spigot, let the user know whats up! + boolean flag = false; + + int i; +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0120-Properly-cancel-fishing-event.-Fixes-BUKKIT-5396.patch b/CraftBukkit-Patches/0120-Properly-cancel-fishing-event.-Fixes-BUKKIT-5396.patch new file mode 100644 index 0000000000..5020baf998 --- /dev/null +++ b/CraftBukkit-Patches/0120-Properly-cancel-fishing-event.-Fixes-BUKKIT-5396.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "gjmcferrin@gmail.com" +Date: Mon, 10 Feb 2014 10:05:11 -0500 +Subject: [PATCH] Properly cancel fishing event. Fixes BUKKIT-5396 + +Previously, when cancelling a PlayerFishEvent with State.FISHING, the next +fishing attempt would automatically result in a new PlayerFishEvent with +State.FAILED_ATTEMPT because the player's hooked entity was not properly +cleared. This ensures that the player's hooked entity value is set to null so +that the next attempt will result in the proper state being called. + +diff --git a/src/main/java/net/minecraft/server/ItemFishingRod.java b/src/main/java/net/minecraft/server/ItemFishingRod.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/ItemFishingRod.java ++++ b/src/main/java/net/minecraft/server/ItemFishingRod.java +@@ -0,0 +0,0 @@ public class ItemFishingRod extends Item { + world.getServer().getPluginManager().callEvent(playerFishEvent); + + if (playerFishEvent.isCancelled()) { ++ entityhuman.hookedFish = null; + return itemstack; + } + // CraftBukkit end +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0121-Print-Stack-on-InternalException.patch b/CraftBukkit-Patches/0121-Print-Stack-on-InternalException.patch new file mode 100644 index 0000000000..16e71b0fc6 --- /dev/null +++ b/CraftBukkit-Patches/0121-Print-Stack-on-InternalException.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 13 Apr 2014 09:00:59 +1000 +Subject: [PATCH] Print Stack on InternalException + + +diff --git a/src/main/java/net/minecraft/server/NetworkManager.java b/src/main/java/net/minecraft/server/NetworkManager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/NetworkManager.java ++++ b/src/main/java/net/minecraft/server/NetworkManager.java +@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler { + } + + this.close(chatmessage); ++ if (MinecraftServer.getServer().isDebugging()) throwable.printStackTrace(); // Spigot + } + + protected void a(ChannelHandlerContext channelhandlercontext, Packet packet) { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0122-Use-Offline-Player-Data-Once-if-Required.patch b/CraftBukkit-Patches/0122-Use-Offline-Player-Data-Once-if-Required.patch new file mode 100644 index 0000000000..4d9a21effe --- /dev/null +++ b/CraftBukkit-Patches/0122-Use-Offline-Player-Data-Once-if-Required.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 13 Apr 2014 14:41:23 +1000 +Subject: [PATCH] Use Offline Player Data Once if Required. + +If we are online mode and the only copy of player data we can find is the player's offline mode data, we will attempt a once off conversion by reading this data and then renaming the file so it won't be used again. + +diff --git a/src/main/java/net/minecraft/server/WorldNBTStorage.java b/src/main/java/net/minecraft/server/WorldNBTStorage.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/WorldNBTStorage.java ++++ b/src/main/java/net/minecraft/server/WorldNBTStorage.java +@@ -0,0 +0,0 @@ public class WorldNBTStorage implements IDataManager, IPlayerFileData { + + try { + File file1 = new File(this.playerDir, entityhuman.getUniqueID().toString() + ".dat"); ++ // Spigot Start ++ boolean usingWrongFile = false; ++ if ( !file1.exists() ) ++ { ++ file1 = new File( this.playerDir, UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + entityhuman.getName() ).getBytes( "UTF-8" ) ).toString() + ".dat"); ++ if ( file1.exists() ) ++ { ++ usingWrongFile = true; ++ org.bukkit.Bukkit.getServer().getLogger().warning( "Using offline mode UUID file for player " + entityhuman.getName() + " as it is the only copy we can find." ); ++ } ++ } ++ // Spigot End + + if (file1.exists() && file1.isFile()) { + nbttagcompound = NBTCompressedStreamTools.a((InputStream) (new FileInputStream(file1))); + } ++ // Spigot Start ++ if ( usingWrongFile ) ++ { ++ file1.renameTo( new File( file1.getPath() + ".offline-read" ) ); ++ } ++ // Spigot End + } catch (Exception exception) { + a.warn("Failed to load player data for " + entityhuman.getName()); + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0123-Use-Provided-Case-for-Non-Existent-Offline-Players.patch b/CraftBukkit-Patches/0123-Use-Provided-Case-for-Non-Existent-Offline-Players.patch new file mode 100644 index 0000000000..4bd3d4c8f8 --- /dev/null +++ b/CraftBukkit-Patches/0123-Use-Provided-Case-for-Non-Existent-Offline-Players.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Mon, 14 Apr 2014 09:46:20 +1000 +Subject: [PATCH] Use Provided Case for Non Existent Offline Players + + +diff --git a/src/main/java/net/minecraft/server/UserCache.java b/src/main/java/net/minecraft/server/UserCache.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/UserCache.java ++++ b/src/main/java/net/minecraft/server/UserCache.java +@@ -0,0 +0,0 @@ public class UserCache { + this.e.addFirst(gameprofile); + } + } else { +- gameprofile = a(this.f, s1); ++ gameprofile = a(this.f, s); // Spigot - use correct case for offline players + if (gameprofile != null) { + this.a(gameprofile); + usercacheentry = (UserCacheEntry) this.c.get(s1); +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0124-Check-for-blank-OfflinePlayer-Names.patch b/CraftBukkit-Patches/0124-Check-for-blank-OfflinePlayer-Names.patch new file mode 100644 index 0000000000..9b48f8fa8c --- /dev/null +++ b/CraftBukkit-Patches/0124-Check-for-blank-OfflinePlayer-Names.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Mon, 14 Apr 2014 17:21:24 +1000 +Subject: [PATCH] Check for blank OfflinePlayer Names + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -0,0 +0,0 @@ public final class CraftServer implements Server { + @Deprecated + public OfflinePlayer getOfflinePlayer(String name) { + Validate.notNull(name, "Name cannot be null"); ++ com.google.common.base.Preconditions.checkArgument( !org.apache.commons.lang.StringUtils.isBlank( name ), "Name cannot be blank" ); // Spigot + + // If the name given cannot ever be a valid username give a dummy return, for scoreboard plugins + if (!validUserPattern.matcher(name).matches()) { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0125-Fix-Player-Banning.patch b/CraftBukkit-Patches/0125-Fix-Player-Banning.patch new file mode 100644 index 0000000000..c9d9c8921e --- /dev/null +++ b/CraftBukkit-Patches/0125-Fix-Player-Banning.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Tue, 15 Apr 2014 10:32:48 +1000 +Subject: [PATCH] Fix Player Banning + +This issue stems from the fact that Bukkit's API only allows a UUID to be banned, but Minecraft requires both a UUID and name. To fix this we modify the code to require a UUID or a name, or both. The correct fix would be expanding the API to be able to provide a name, however this would require plugin changes. + +diff --git a/src/main/java/net/minecraft/server/GameProfileBanEntry.java b/src/main/java/net/minecraft/server/GameProfileBanEntry.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/GameProfileBanEntry.java ++++ b/src/main/java/net/minecraft/server/GameProfileBanEntry.java +@@ -0,0 +0,0 @@ public class GameProfileBanEntry extends ExpirableListEntry { + } + + private static GameProfile b(JsonObject jsonobject) { +- if (jsonobject.has("uuid") && jsonobject.has("name")) { ++ // Spigot start ++ // this whole method has to be reworked to account for the fact Bukkit only accepts UUID bans and gives no way for usernames to be stored! ++ UUID uuid = null; ++ String name = null; ++ if (jsonobject.has("uuid")) { + String s = jsonobject.get("uuid").getAsString(); + +- UUID uuid; +- + try { + uuid = UUID.fromString(s); + } catch (Throwable throwable) { +- return null; + } + +- return new GameProfile(uuid, jsonobject.get("name").getAsString()); ++ } ++ if ( jsonobject.has("name")) ++ { ++ name = jsonobject.get("name").getAsString(); ++ } ++ if ( uuid != null || name != null ) ++ { ++ return new GameProfile( uuid, name ); + } else { + return null; + } ++ // Spigot End + } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0126-Fix-ban-expire-dates.patch b/CraftBukkit-Patches/0126-Fix-ban-expire-dates.patch new file mode 100644 index 0000000000..2f87f738bc --- /dev/null +++ b/CraftBukkit-Patches/0126-Fix-ban-expire-dates.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Wed, 16 Apr 2014 10:09:56 +1000 +Subject: [PATCH] Fix ban expire dates. + + +diff --git a/src/main/java/net/minecraft/server/GameProfileBanEntry.java b/src/main/java/net/minecraft/server/GameProfileBanEntry.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/GameProfileBanEntry.java ++++ b/src/main/java/net/minecraft/server/GameProfileBanEntry.java +@@ -0,0 +0,0 @@ public class GameProfileBanEntry extends ExpirableListEntry { + } + + public GameProfileBanEntry(GameProfile gameprofile, Date date, String s, Date date1, String s1) { +- super(gameprofile, date1, s, date1, s1); ++ super(gameprofile, date, s, date1, s1); // Spigot + } + + public GameProfileBanEntry(JsonObject jsonobject) { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0127-Correct-Ban-Expiration.patch b/CraftBukkit-Patches/0127-Correct-Ban-Expiration.patch new file mode 100644 index 0000000000..2c55ba2e2e --- /dev/null +++ b/CraftBukkit-Patches/0127-Correct-Ban-Expiration.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Wed, 16 Apr 2014 11:14:38 +1000 +Subject: [PATCH] Correct Ban Expiration + + +diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerList.java ++++ b/src/main/java/net/minecraft/server/PlayerList.java +@@ -0,0 +0,0 @@ public abstract class PlayerList { + } + + // return s; +- event.disallow(PlayerLoginEvent.Result.KICK_BANNED, s); ++ if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, s); // Spigot + } else if (!this.isWhitelisted(gameprofile)) { + // return "You are not white-listed on this server!"; + event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0128-Convert-Horses-owner-to-UUID.patch b/CraftBukkit-Patches/0128-Convert-Horses-owner-to-UUID.patch new file mode 100644 index 0000000000..a2f0a7bfe1 --- /dev/null +++ b/CraftBukkit-Patches/0128-Convert-Horses-owner-to-UUID.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 16 Apr 2014 01:40:30 -0400 +Subject: [PATCH] Convert Horses owner to UUID + + +diff --git a/src/main/java/net/minecraft/server/EntityHorse.java b/src/main/java/net/minecraft/server/EntityHorse.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityHorse.java ++++ b/src/main/java/net/minecraft/server/EntityHorse.java +@@ -0,0 +0,0 @@ public class EntityHorse extends EntityAnimal implements IInventoryListener { + if (nbttagcompound.hasKeyOfType("OwnerUUID", 8)) { + this.setOwnerUUID(nbttagcompound.getString("OwnerUUID")); + } ++ // Spigot start ++ else if (nbttagcompound.hasKey("OwnerName")) { ++ String owner = nbttagcompound.getString("OwnerName"); ++ if (owner != null && !owner.isEmpty()) { ++ this.setOwnerUUID(NameReferencingFileConverter.a(owner)); ++ } ++ } ++ // Spigot end + // CraftBukkit start + if (nbttagcompound.hasKey("Bukkit.MaxDomestication")) { + this.maxDomestication = nbttagcompound.getInt("Bukkit.MaxDomestication"); +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0129-Expand-team-API-to-allow-arbitrary-strings.patch b/CraftBukkit-Patches/0129-Expand-team-API-to-allow-arbitrary-strings.patch new file mode 100644 index 0000000000..0f99d60aa9 --- /dev/null +++ b/CraftBukkit-Patches/0129-Expand-team-API-to-allow-arbitrary-strings.patch @@ -0,0 +1,86 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Thu, 17 Apr 2014 19:22:22 +1000 +Subject: [PATCH] Expand team API to allow arbitrary strings. + + +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java +@@ -0,0 +0,0 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { + return players.build(); + } + ++ // Spigot start ++ @Override ++ public Set getEntries() throws IllegalStateException { ++ CraftScoreboard scoreboard = checkState(); ++ ++ ImmutableSet.Builder entries = ImmutableSet.builder(); ++ for (Object o : team.getPlayerNameSet()){ ++ entries.add(o.toString()); ++ } ++ return entries.build(); ++ } ++ // Spigot end ++ + public int getSize() throws IllegalStateException { + CraftScoreboard scoreboard = checkState(); + +@@ -0,0 +0,0 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { + + public void addPlayer(OfflinePlayer player) throws IllegalStateException, IllegalArgumentException { + Validate.notNull(player, "OfflinePlayer cannot be null"); ++ // Spigot Start ++ addEntry(player.getName()); ++ } ++ ++ public void addEntry(String entry) throws IllegalStateException, IllegalArgumentException { ++ Validate.notNull(entry, "Entry cannot be null"); + CraftScoreboard scoreboard = checkState(); + +- scoreboard.board.addPlayerToTeam(player.getName(), team.getName()); ++ scoreboard.board.addPlayerToTeam(entry, team.getName()); ++ // Spigot end + } + + public boolean removePlayer(OfflinePlayer player) throws IllegalStateException, IllegalArgumentException { + Validate.notNull(player, "OfflinePlayer cannot be null"); ++ // Spigot start ++ return removeEntry(player.getName()); ++ } ++ ++ public boolean removeEntry(String entry) throws IllegalStateException, IllegalArgumentException { ++ Validate.notNull(entry, "Entry cannot be null"); + CraftScoreboard scoreboard = checkState(); + +- if (!team.getPlayerNameSet().contains(player.getName())) { ++ if (!team.getPlayerNameSet().contains(entry)) { + return false; + } + +- scoreboard.board.removePlayerFromTeam(player.getName(), team); ++ scoreboard.board.removePlayerFromTeam(entry, team); ++ // Spigot end + return true; + } + + public boolean hasPlayer(OfflinePlayer player) throws IllegalArgumentException, IllegalStateException { + Validate.notNull(player, "OfflinePlayer cannot be null"); ++ // Spigot start ++ return hasEntry(player.getName()); ++ } ++ ++ public boolean hasEntry(String entry) throws IllegalArgumentException, IllegalStateException { ++ Validate.notNull("Entry cannot be null"); ++ + CraftScoreboard scoreboard = checkState(); + +- return team.getPlayerNameSet().contains(player.getName()); ++ return team.getPlayerNameSet().contains(entry); ++ // Spigot end + } + + @Override +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0130-Add-Score.isScoreSet-Z-API.patch b/CraftBukkit-Patches/0130-Add-Score.isScoreSet-Z-API.patch new file mode 100644 index 0000000000..3a5accadb5 --- /dev/null +++ b/CraftBukkit-Patches/0130-Add-Score.isScoreSet-Z-API.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Thu, 17 Apr 2014 19:35:53 +1000 +Subject: [PATCH] Add Score.isScoreSet()Z API. + +Also fix generics on CraftScore.getScore()I. + +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScore.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScore.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScore.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScore.java +@@ -0,0 +0,0 @@ final class CraftScore implements Score { + Scoreboard board = objective.checkState().board; + + if (board.getPlayers().contains(entry)) { // Lazy +- Map scores = board.getPlayerObjectives(entry); ++ Map scores = board.getPlayerObjectives(entry); // Spigot + ScoreboardScore score = scores.get(objective.getHandle()); + if (score != null) { // Lazy + return score.getScore(); +@@ -0,0 +0,0 @@ final class CraftScore implements Score { + objective.checkState().board.getPlayerScoreForObjective(entry, objective.getHandle()).setScore(score); + } + ++ // Spigot start ++ @Override ++ public boolean isScoreSet() throws IllegalStateException { ++ Scoreboard board = objective.checkState().board; ++ ++ return board.getPlayers().contains(entry) && board.getPlayerObjectives(entry).containsKey(objective.getHandle()); ++ } ++ // Spigot end ++ + public CraftScoreboard getScoreboard() { + return objective.getScoreboard(); + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0131-Log-null-TileEntity-Owner.patch b/CraftBukkit-Patches/0131-Log-null-TileEntity-Owner.patch new file mode 100644 index 0000000000..3734eaa798 --- /dev/null +++ b/CraftBukkit-Patches/0131-Log-null-TileEntity-Owner.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 20 Apr 2014 11:16:54 +1000 +Subject: [PATCH] Log null TileEntity Owner + + +diff --git a/src/main/java/net/minecraft/server/TileEntity.java b/src/main/java/net/minecraft/server/TileEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/TileEntity.java ++++ b/src/main/java/net/minecraft/server/TileEntity.java +@@ -0,0 +0,0 @@ public class TileEntity { + + // CraftBukkit start - add method + public InventoryHolder getOwner() { +- org.bukkit.block.BlockState state = world.getWorld().getBlockAt(x, y, z).getState(); ++ // Spigot start ++ org.bukkit.block.Block block = world.getWorld().getBlockAt(x, y, z); ++ if (block == null) { ++ org.bukkit.Bukkit.getLogger().log(java.util.logging.Level.WARNING, "No block for owner at %s %d %d %d", new Object[]{world.getWorld(), x, y, z}); ++ return null; ++ } ++ // Spigot end ++ org.bukkit.block.BlockState state = block.getState(); + if (state instanceof InventoryHolder) return (InventoryHolder) state; + return null; + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0132-Don-t-special-case-invalid-usernames-for-UUIDs.patch b/CraftBukkit-Patches/0132-Don-t-special-case-invalid-usernames-for-UUIDs.patch new file mode 100644 index 0000000000..e8463260ba --- /dev/null +++ b/CraftBukkit-Patches/0132-Don-t-special-case-invalid-usernames-for-UUIDs.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Sun, 20 Apr 2014 18:58:00 +1000 +Subject: [PATCH] Don't special case 'invalid' usernames for UUIDs. + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -0,0 +0,0 @@ public final class CraftServer implements Server { + Validate.notNull(name, "Name cannot be null"); + com.google.common.base.Preconditions.checkArgument( !org.apache.commons.lang.StringUtils.isBlank( name ), "Name cannot be blank" ); // Spigot + +- // If the name given cannot ever be a valid username give a dummy return, for scoreboard plugins +- if (!validUserPattern.matcher(name).matches()) { +- return new CraftOfflinePlayer(this, new GameProfile(invalidUserUUID, name)); +- } +- + OfflinePlayer result = getPlayerExact(name); + if (result == null) { + // This is potentially blocking :( +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0133-Convert-player-skulls-async.patch b/CraftBukkit-Patches/0133-Convert-player-skulls-async.patch new file mode 100644 index 0000000000..a82d837f3d --- /dev/null +++ b/CraftBukkit-Patches/0133-Convert-player-skulls-async.patch @@ -0,0 +1,123 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Sun, 20 Apr 2014 13:18:55 +0100 +Subject: [PATCH] Convert player skulls async + + +diff --git a/src/main/java/net/minecraft/server/TileEntitySkull.java b/src/main/java/net/minecraft/server/TileEntitySkull.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/TileEntitySkull.java ++++ b/src/main/java/net/minecraft/server/TileEntitySkull.java +@@ -0,0 +0,0 @@ import net.minecraft.util.com.google.common.collect.Iterables; + import net.minecraft.util.com.mojang.authlib.GameProfile; + import net.minecraft.util.com.mojang.authlib.properties.Property; + ++// Spigot start ++import com.google.common.cache.Cache; ++import com.google.common.cache.CacheBuilder; ++import com.google.common.cache.CacheLoader; ++import java.util.concurrent.Executor; ++import java.util.concurrent.Executors; ++import java.util.concurrent.TimeUnit; ++ ++import com.google.common.util.concurrent.ThreadFactoryBuilder; ++import net.minecraft.util.com.mojang.authlib.Agent; ++// Spigot end ++ + public class TileEntitySkull extends TileEntity { + + private int a; + private int i; + private GameProfile j = null; ++ // Spigot start ++ private static final Executor executor = Executors.newFixedThreadPool(3, ++ new ThreadFactoryBuilder() ++ .setNameFormat("Head Conversion Thread - %1$d") ++ .build() ++ ); ++ private static final Cache skinCache = CacheBuilder.newBuilder() ++ .maximumSize( 5000 ) ++ .expireAfterAccess( 60, TimeUnit.MINUTES ) ++ .build( new CacheLoader() ++ { ++ @Override ++ public GameProfile load(String key) throws Exception ++ { ++ GameProfile[] profiles = new GameProfile[1]; ++ GameProfileLookup gameProfileLookup = new GameProfileLookup(profiles); ++ ++ MinecraftServer.getServer().getGameProfileRepository().findProfilesByNames(new String[] { key }, Agent.MINECRAFT, gameProfileLookup); ++ if (!MinecraftServer.getServer().getOnlineMode() && profiles[0] == null) { ++ UUID uuid = EntityHuman.a(new GameProfile(null, key)); ++ GameProfile profile = new GameProfile(uuid, key); ++ ++ gameProfileLookup.onProfileLookupSucceeded(profile); ++ } ++ ++ GameProfile profile = profiles[0]; ++ ++ Property property = Iterables.getFirst(profile.getProperties().get("textures"), null); ++ ++ if (property == null) { ++ profile = MinecraftServer.getServer().av().fillProfileProperties(profile, true); ++ } ++ ++ ++ return profile; ++ } ++ } ); ++ // Spigot end + + public TileEntitySkull() {} + +@@ -0,0 +0,0 @@ public class TileEntitySkull extends TileEntity { + private void d() { + if (this.j != null && !UtilColor.b(this.j.getName())) { + if (!this.j.isComplete() || !this.j.getProperties().containsKey("textures")) { +- GameProfile gameprofile = MinecraftServer.getServer().getUserCache().getProfile(this.j.getName()); +- +- if (gameprofile != null) { +- Property property = (Property) Iterables.getFirst(gameprofile.getProperties().get("textures"), null); +- +- if (property == null) { +- gameprofile = MinecraftServer.getServer().av().fillProfileProperties(gameprofile, true); ++ // Spigot start - Handle async ++ final String name = this.j.getName(); ++ setSkullType( 0 ); // Work around a client bug ++ executor.execute(new Runnable() { ++ @Override ++ public void run() { ++ ++ GameProfile profile = skinCache.getUnchecked( name.toLowerCase() ); ++ ++ if (profile != null) { ++ final GameProfile finalProfile = profile; ++ MinecraftServer.getServer().processQueue.add(new Runnable() { ++ @Override ++ public void run() { ++ a = 3; ++ j = finalProfile; ++ world.notify( x, y, z ); ++ } ++ }); ++ } else { ++ MinecraftServer.getServer().processQueue.add(new Runnable() { ++ @Override ++ public void run() { ++ a = 3; ++ j = new GameProfile( null, name ); ++ world.notify( x, y, z ); ++ } ++ }); ++ } + } +- +- this.j = gameprofile; +- this.update(); +- } ++ }); ++ // Spigot end + } + } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0134-Prevent-NoClassDefError-crash-and-notify-on-crash.patch b/CraftBukkit-Patches/0134-Prevent-NoClassDefError-crash-and-notify-on-crash.patch new file mode 100644 index 0000000000..cae3c70338 --- /dev/null +++ b/CraftBukkit-Patches/0134-Prevent-NoClassDefError-crash-and-notify-on-crash.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: David +Date: Mon, 21 Apr 2014 12:43:08 +0100 +Subject: [PATCH] Prevent NoClassDefError crash and notify on crash + + +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + protected float growthOdds = 100; + protected float modifiedOdds = 100; + private final byte chunkTickRadius; ++ public static boolean haveWeSilencedAPhysicsCrash; ++ public static String blockLocation; + + public static long chunkToKey(int x, int z) + { +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + // CraftBukkit end + + block1.doPhysics(this, i, j, k, block); ++ } catch (StackOverflowError stackoverflowerror) { // Spigot Start ++ haveWeSilencedAPhysicsCrash = true; ++ blockLocation = i + ", " + j + ", " + k; // Spigot End + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.a(throwable, "Exception while updating neighbours"); + CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block being updated"); +diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread + log.log( Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports" ); + log.log( Level.SEVERE, "Spigot version: " + Bukkit.getServer().getVersion() ); + // ++ if(net.minecraft.server.World.haveWeSilencedAPhysicsCrash) ++ { ++ log.log( Level.SEVERE, "------------------------------" ); ++ 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); ++ } ++ // + log.log( Level.SEVERE, "------------------------------" ); + log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Spigot!):" ); + dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().primaryThread.getId(), Integer.MAX_VALUE ), log ); +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0135-Check-Skull-canPlace.patch b/CraftBukkit-Patches/0135-Check-Skull-canPlace.patch new file mode 100644 index 0000000000..88e6597ef5 --- /dev/null +++ b/CraftBukkit-Patches/0135-Check-Skull-canPlace.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Tue, 15 Apr 2014 10:48:35 +1000 +Subject: [PATCH] Check Skull canPlace + + +diff --git a/src/main/java/net/minecraft/server/ItemSkull.java b/src/main/java/net/minecraft/server/ItemSkull.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/ItemSkull.java ++++ b/src/main/java/net/minecraft/server/ItemSkull.java +@@ -0,0 +0,0 @@ public class ItemSkull extends Item { + } + + if (!world.isStatic) { ++ // Spigot Start ++ if ( !Blocks.SKULL.canPlace( world, i, j, k ) ) ++ { ++ return false; ++ } ++ // Spigot End + world.setTypeAndData(i, j, k, Blocks.SKULL, l, 2); + int i1 = 0; + +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0136-Don-t-let-trees-replace-any-block.patch b/CraftBukkit-Patches/0136-Don-t-let-trees-replace-any-block.patch new file mode 100644 index 0000000000..208bac4907 --- /dev/null +++ b/CraftBukkit-Patches/0136-Don-t-let-trees-replace-any-block.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Mon, 20 Jan 2014 20:42:28 +0000 +Subject: [PATCH] Don't let trees replace any block. + + +diff --git a/src/main/java/net/minecraft/server/WorldGenForestTree.java b/src/main/java/net/minecraft/server/WorldGenForestTree.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/WorldGenForestTree.java ++++ b/src/main/java/net/minecraft/server/WorldGenForestTree.java +@@ -0,0 +0,0 @@ public class WorldGenForestTree extends WorldGenTreeAbstract { + int k3; + + for (k3 = 0; k3 < j3; ++k3) { +- this.setTypeAndData(world, i + l2, k2 - k3 - 1, k + i3, Blocks.LOG2, 1); ++ Block block = world.getType(i + l2, k2 - k3 - 1, k + i3); ++ ++ if (block.getMaterial() == Material.AIR || block.getMaterial() == Material.LEAVES) ++ { ++ this.setTypeAndData(world, i + l2, k2 - k3 - 1, k + i3, Blocks.LOG2, 1); ++ } + } + + int l3; +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0137-Fix-race-condition-that-could-kill-connections-befor.patch b/CraftBukkit-Patches/0137-Fix-race-condition-that-could-kill-connections-befor.patch new file mode 100644 index 0000000000..e46ce21164 --- /dev/null +++ b/CraftBukkit-Patches/0137-Fix-race-condition-that-could-kill-connections-befor.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jonas Konrad +Date: Fri, 25 Apr 2014 23:46:46 +0200 +Subject: [PATCH] Fix race condition that could kill connections before they + were initiated + +Because NetworkManagers are registered before they get their channel in +channelActive, the ServerConnection would remove them sometimes because +it thought they were disconnected. This commit fixes this by introducing +a 'preparing' variable that is true while the NetworkManager is not +initialized. The ServerConnection does not remove NetworkManagers with +this flag. + +diff --git a/src/main/java/net/minecraft/server/NetworkManager.java b/src/main/java/net/minecraft/server/NetworkManager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/NetworkManager.java ++++ b/src/main/java/net/minecraft/server/NetworkManager.java +@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler { + public SocketAddress n; + public java.util.UUID spoofedUUID; + public Property[] spoofedProfile; ++ public boolean preparing = true; + // Spigot End + private PacketListener o; + private EnumProtocol p; +@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler { + super.channelActive(channelhandlercontext); + this.m = channelhandlercontext.channel(); + this.n = this.m.remoteAddress(); ++ // Spigot Start ++ this.preparing = false; ++ // Spigot End + this.a(EnumProtocol.HANDSHAKING); + } + +@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler { + } + + public void close(IChatBaseComponent ichatbasecomponent) { ++ // Spigot Start ++ this.preparing = false; ++ // Spigot End + if (this.m.isOpen()) { + this.m.close(); + this.q = ichatbasecomponent; +diff --git a/src/main/java/net/minecraft/server/ServerConnection.java b/src/main/java/net/minecraft/server/ServerConnection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/ServerConnection.java ++++ b/src/main/java/net/minecraft/server/ServerConnection.java +@@ -0,0 +0,0 @@ public class ServerConnection { + NetworkManager networkmanager = (NetworkManager) iterator.next(); + + if (!networkmanager.isConnected()) { ++ // Spigot Start ++ // Fix a race condition where a NetworkManager could be unregistered just before connection. ++ if (networkmanager.preparing) continue; ++ // Spigot End + iterator.remove(); + if (networkmanager.f() != null) { + networkmanager.getPacketListener().a(networkmanager.f()); +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0138-Configurable-UserCache-cap.patch b/CraftBukkit-Patches/0138-Configurable-UserCache-cap.patch new file mode 100644 index 0000000000..7df68c5ad2 --- /dev/null +++ b/CraftBukkit-Patches/0138-Configurable-UserCache-cap.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: drXor +Date: Fri, 25 Apr 2014 18:17:30 -0400 +Subject: [PATCH] Configurable UserCache cap + + +diff --git a/src/main/java/net/minecraft/server/UserCache.java b/src/main/java/net/minecraft/server/UserCache.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/UserCache.java ++++ b/src/main/java/net/minecraft/server/UserCache.java +@@ -0,0 +0,0 @@ public class UserCache { + } + + public void c() { +- String s = this.b.toJson(this.a(1000)); ++ String s = this.b.toJson(this.a(org.spigotmc.SpigotConfig.userCacheCap)); + BufferedWriter bufferedwriter = null; + + try { +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -0,0 +0,0 @@ public class SpigotConfig + replaceCommands = new HashSet( (List) getList( "commands.replace-commands", + Arrays.asList( "setblock", "summon", "testforblock", "tellraw" ) ) ); + } ++ ++ public static int userCacheCap; ++ private static void userCacheCap() ++ { ++ userCacheCap = getInt( "settings.user-cache-size", 1000 ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0139-Implement-PlayerSpawnLocationEvent.patch b/CraftBukkit-Patches/0139-Implement-PlayerSpawnLocationEvent.patch new file mode 100644 index 0000000000..566de01d45 --- /dev/null +++ b/CraftBukkit-Patches/0139-Implement-PlayerSpawnLocationEvent.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ninja +Date: Tue, 8 Apr 2014 14:05:19 +0200 +Subject: [PATCH] Implement PlayerSpawnLocationEvent. + + +diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerList.java ++++ b/src/main/java/net/minecraft/server/PlayerList.java +@@ -0,0 +0,0 @@ import org.bukkit.event.player.PlayerQuitEvent; + import org.bukkit.event.player.PlayerRespawnEvent; + import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; + import org.bukkit.util.Vector; ++import org.spigotmc.event.player.PlayerSpawnLocationEvent; + // CraftBukkit end + + public abstract class PlayerList { +@@ -0,0 +0,0 @@ public abstract class PlayerList { + s1 = networkmanager.getSocketAddress().toString(); + } + ++ // Spigot start - spawn location event ++ Player bukkitPlayer = entityplayer.getBukkitEntity(); ++ PlayerSpawnLocationEvent ev = new PlayerSpawnLocationEvent(bukkitPlayer, bukkitPlayer.getLocation()); ++ Bukkit.getPluginManager().callEvent(ev); ++ ++ Location loc = ev.getSpawnLocation(); ++ WorldServer world = ((CraftWorld) loc.getWorld()).getHandle(); ++ ++ entityplayer.spawnIn(world); ++ entityplayer.setPosition(loc.getX(), loc.getY(), loc.getZ()); ++ entityplayer.b(loc.getYaw(), loc.getPitch()); // should be setYawAndPitch ++ // Spigot end ++ + // CraftBukkit - Moved message to after join + // g.info(entityplayer.getName() + "[" + s1 + "] logged in with entity id " + entityplayer.getId() + " at (" + entityplayer.locX + ", " + entityplayer.locY + ", " + entityplayer.locZ + ")"); + WorldServer worldserver = this.server.getWorldServer(entityplayer.dimension); +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0140-Cap-Objective-Score-Length.patch b/CraftBukkit-Patches/0140-Cap-Objective-Score-Length.patch new file mode 100644 index 0000000000..152da099fb --- /dev/null +++ b/CraftBukkit-Patches/0140-Cap-Objective-Score-Length.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: hauno +Date: Tue, 6 May 2014 18:01:37 -0700 +Subject: [PATCH] Cap Objective Score Length + +Adds a check for Score arguments that would crash the client + +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java +@@ -0,0 +0,0 @@ final class CraftObjective extends CraftScoreboardComponent implements Objective + + public Score getScore(String entry) throws IllegalArgumentException, IllegalStateException { + Validate.notNull(entry, "Entry cannot be null"); ++ if (entry.length() > 16) throw new IllegalArgumentException("Entry cannot be longer than 16 characters!"); // Spigot + CraftScoreboard scoreboard = checkState(); + + return new CraftScore(this, entry); +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0141-Process-conversation-input-on-the-main-thread.-Fixes.patch b/CraftBukkit-Patches/0141-Process-conversation-input-on-the-main-thread.-Fixes.patch new file mode 100644 index 0000000000..66a5f3ba70 --- /dev/null +++ b/CraftBukkit-Patches/0141-Process-conversation-input-on-the-main-thread.-Fixes.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: riking +Date: Wed, 14 May 2014 13:46:48 -0700 +Subject: [PATCH] Process conversation input on the main thread. Fixes + BUKKIT-5611 + + +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketPlayInListener { + } else if (s.isEmpty()) { + c.warn(this.player.getName() + " tried to send an empty message"); + } else if (getPlayer().isConversing()) { +- getPlayer().acceptConversationInput(s); ++ final String message = s; ++ ++ Waitable waitable = new Waitable() { ++ @Override ++ protected Object evaluate() { ++ getPlayer().acceptConversationInput(message); ++ return null; ++ } ++ }; ++ ++ this.minecraftServer.processQueue.add(waitable); ++ ++ try { ++ waitable.get(); ++ } catch (InterruptedException e) { ++ Thread.currentThread().interrupt(); ++ } catch (ExecutionException e) { ++ throw new RuntimeException(e); ++ } + } else if (this.player.getChatFlags() == EnumChatVisibility.SYSTEM) { // Re-add "Command Only" flag check + ChatMessage chatmessage = new ChatMessage("chat.cannotSend", new Object[0]); + +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0142-Configurable-save-on-stop-only-for-UserCache.patch b/CraftBukkit-Patches/0142-Configurable-save-on-stop-only-for-UserCache.patch new file mode 100644 index 0000000000..ea40828977 --- /dev/null +++ b/CraftBukkit-Patches/0142-Configurable-save-on-stop-only-for-UserCache.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: drXor +Date: Fri, 23 May 2014 18:05:10 -0400 +Subject: [PATCH] Configurable save-on-stop-only for UserCache + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + if (this.l.d()) { + this.l.e(); + } ++ // Spigot start ++ if( org.spigotmc.SpigotConfig.saveUserCacheOnStopOnly ) ++ { ++ i.info("Saving usercache.json"); ++ this.X.c(); ++ } ++ //Spigot end + } + } + +diff --git a/src/main/java/net/minecraft/server/UserCache.java b/src/main/java/net/minecraft/server/UserCache.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/UserCache.java ++++ b/src/main/java/net/minecraft/server/UserCache.java +@@ -0,0 +0,0 @@ public class UserCache { + } + } + +- this.c(); ++ if( !org.spigotmc.SpigotConfig.saveUserCacheOnStopOnly ) this.c(); // Spigot - skip saving if disabled + return usercacheentry == null ? null : usercacheentry.a(); + } + +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -0,0 +0,0 @@ public class SpigotConfig + { + userCacheCap = getInt( "settings.user-cache-size", 1000 ); + } ++ ++ public static boolean saveUserCacheOnStopOnly; ++ private static void saveUserCacheOnStopOnly() ++ { ++ saveUserCacheOnStopOnly = getBoolean( "settings.save-user-cache-on-stop-only", false ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0143-Prevent-Unbounded-IntCache-Growth.patch b/CraftBukkit-Patches/0143-Prevent-Unbounded-IntCache-Growth.patch new file mode 100644 index 0000000000..51a0a7544b --- /dev/null +++ b/CraftBukkit-Patches/0143-Prevent-Unbounded-IntCache-Growth.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Fri, 20 Jun 2014 19:40:00 +1000 +Subject: [PATCH] Prevent Unbounded IntCache Growth + +Based on work by Peter Lawrey, this commit prevents unbounded growth of the integer cache and instead caps it to a value specified in the configuration (1024 by default). Should prevent thrashing, especially around world generation. + +diff --git a/src/main/java/net/minecraft/server/IntCache.java b/src/main/java/net/minecraft/server/IntCache.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/IntCache.java ++++ b/src/main/java/net/minecraft/server/IntCache.java +@@ -0,0 +0,0 @@ public class IntCache { + if (i <= 256) { + if (b.isEmpty()) { + aint = new int[256]; +- c.add(aint); ++ if (c.size() < org.spigotmc.SpigotConfig.intCacheLimit) c.add(aint); + return aint; + } else { + aint = (int[]) b.remove(b.size() - 1); +- c.add(aint); ++ if (c.size() < org.spigotmc.SpigotConfig.intCacheLimit) c.add(aint); + return aint; + } + } else if (i > a) { +@@ -0,0 +0,0 @@ public class IntCache { + d.clear(); + e.clear(); + aint = new int[a]; +- e.add(aint); ++ if (e.size() < org.spigotmc.SpigotConfig.intCacheLimit) e.add(aint); + return aint; + } else if (d.isEmpty()) { + aint = new int[a]; +- e.add(aint); ++ if (e.size() < org.spigotmc.SpigotConfig.intCacheLimit) e.add(aint); + return aint; + } else { + aint = (int[]) d.remove(d.size() - 1); +- e.add(aint); ++ if (e.size() < org.spigotmc.SpigotConfig.intCacheLimit) e.add(aint); + return aint; + } + } +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -0,0 +0,0 @@ public class SpigotConfig + { + saveUserCacheOnStopOnly = getBoolean( "settings.save-user-cache-on-stop-only", false ); + } ++ ++ public static int intCacheLimit; ++ private static void intCacheLimit() ++ { ++ intCacheLimit = getInt( "settings.int-cache-limit", 1024 ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0144-Alternative-Hopper-Ticking.patch b/CraftBukkit-Patches/0144-Alternative-Hopper-Ticking.patch new file mode 100644 index 0000000000..a8512d2d01 --- /dev/null +++ b/CraftBukkit-Patches/0144-Alternative-Hopper-Ticking.patch @@ -0,0 +1,500 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Evan A. Haskell" +Date: Sat, 19 Apr 2014 16:58:26 -0400 +Subject: [PATCH] Alternative Hopper Ticking + + +diff --git a/src/main/java/net/minecraft/server/BlockHopper.java b/src/main/java/net/minecraft/server/BlockHopper.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/BlockHopper.java ++++ b/src/main/java/net/minecraft/server/BlockHopper.java +@@ -0,0 +0,0 @@ public class BlockHopper extends BlockContainer { + + if (flag != flag1) { + world.setData(i, j, k, i1 | (flag ? 0 : 8), 4); ++ // Spigot start - When this hopper becomes unpowered, make it active. ++ // Called when this block's power level changes. flag1 is the current ++ // isNotPowered from metadata. flag is the recalculated isNotPowered. ++ if (world.spigotConfig.altHopperTicking) { ++ // e returns the TileEntityHopper associated with this BlockHopper. ++ TileEntityHopper hopper = e((IBlockAccess) world, i, j, k); ++ if (flag && hopper != null) { ++ hopper.makeTick(); ++ } ++ } ++ // Spigot end + } + } + +@@ -0,0 +0,0 @@ public class BlockHopper extends BlockContainer { + public static TileEntityHopper e(IBlockAccess iblockaccess, int i, int j, int k) { + return (TileEntityHopper) iblockaccess.getTileEntity(i, j, k); + } ++ ++ // Spigot start - Use random block updates to make hoppers active. ++ @Override ++ public void a(World world, int i, int j, int k, Random random) { ++ if (world.spigotConfig.altHopperTicking) { ++ // e returns the TileEntityHopper associated with this BlockHopper. ++ TileEntityHopper hopper = e((IBlockAccess) world, i, j, k); ++ if (hopper != null) { ++ hopper.makeTick(); ++ } ++ } ++ } ++ // Spigot end + } +diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Chunk.java ++++ b/src/main/java/net/minecraft/server/Chunk.java +@@ -0,0 +0,0 @@ public class Chunk { + + tileentity.t(); + this.tileEntities.put(chunkposition, tileentity); ++ // Spigot start - The tile entity has a world, now hoppers can be born ticking. ++ if (this.world.spigotConfig.altHopperTicking) { ++ this.world.triggerHoppersList.add(tileentity); ++ } ++ // Spigot end + // CraftBukkit start + } else { + System.out.println("Attempted to place a tile entity (" + tileentity + ") at " + tileentity.x + "," + tileentity.y + "," + tileentity.z +diff --git a/src/main/java/net/minecraft/server/EntityItem.java b/src/main/java/net/minecraft/server/EntityItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityItem.java ++++ b/src/main/java/net/minecraft/server/EntityItem.java +@@ -0,0 +0,0 @@ public class EntityItem extends Entity { + if (this.onGround) { + this.motY *= -0.5D; + } ++ // Spigot start - Make the hopper(s) below this item active. ++ // Called each tick on each item entity. ++ if (this.world.spigotConfig.altHopperTicking) { ++ int xi = MathHelper.floor(this.boundingBox.a); ++ int yi = MathHelper.floor(this.boundingBox.b) - 1; ++ int zi = MathHelper.floor(this.boundingBox.c); ++ int xf = MathHelper.floor(this.boundingBox.d); ++ int yf = MathHelper.floor(this.boundingBox.e) - 1; ++ int zf = MathHelper.floor(this.boundingBox.f); ++ for (int a = xi; a <= xf; a++) { ++ for (int c = zi; c <= zf; c++) { ++ for (int b = yi; b <= yf; b++) { ++ TileEntity tileEntity = this.world.getTileEntity(a, b, c); ++ if (tileEntity instanceof TileEntityHopper) { ++ ((TileEntityHopper) tileEntity).makeTick(); ++ } ++ } ++ } ++ } ++ } ++ // Spigot end + + // ++this.age; // CraftBukkit - Moved up + if (!this.world.isStatic && this.age >= world.spigotConfig.itemDespawnRate) { // Spigot +diff --git a/src/main/java/net/minecraft/server/EntityMinecartAbstract.java b/src/main/java/net/minecraft/server/EntityMinecartAbstract.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityMinecartAbstract.java ++++ b/src/main/java/net/minecraft/server/EntityMinecartAbstract.java +@@ -0,0 +0,0 @@ public abstract class EntityMinecartAbstract extends Entity { + + this.passenger = null; + } ++ // Spigot start - Make hoppers around this container minecart active. ++ // Called each tick on each minecart. ++ if (this.world.spigotConfig.altHopperTicking && this instanceof EntityMinecartContainer) { ++ int xi = MathHelper.floor(this.boundingBox.a) - 1; ++ int yi = MathHelper.floor(this.boundingBox.b) - 1; ++ int zi = MathHelper.floor(this.boundingBox.c) - 1; ++ int xf = MathHelper.floor(this.boundingBox.d) + 1; ++ int yf = MathHelper.floor(this.boundingBox.e) + 1; ++ int zf = MathHelper.floor(this.boundingBox.f) + 1; ++ for (int a = xi; a <= xf; a++) { ++ for (int b = yi; b <= yf; b++) { ++ for (int c = zi; c <= zf; c++) { ++ TileEntity tileEntity = this.world.getTileEntity(a, b, c); ++ if (tileEntity instanceof TileEntityHopper) { ++ ((TileEntityHopper) tileEntity).makeTick(); ++ } ++ } ++ } ++ } ++ } ++ // Spigot end + } + } + +diff --git a/src/main/java/net/minecraft/server/EntityOcelot.java b/src/main/java/net/minecraft/server/EntityOcelot.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityOcelot.java ++++ b/src/main/java/net/minecraft/server/EntityOcelot.java +@@ -0,0 +0,0 @@ public class EntityOcelot extends EntityTameableAnimal { + this.datawatcher.a(18, Byte.valueOf((byte) 0)); + } + ++ // Spigot start - When this ocelot begins standing, chests below this ocelot must be ++ // updated as if its contents have changed. We update chests if this ocelot is sitting ++ // knowing that it may be dead, gone, or standing after this method returns. ++ // Called each tick on each ocelot. ++ @Override ++ public void h() { ++ if (this.world.spigotConfig.altHopperTicking && this.isSitting()) { ++ int xi = MathHelper.floor(this.boundingBox.a); ++ int yi = MathHelper.floor(this.boundingBox.b) - 1; ++ int zi = MathHelper.floor(this.boundingBox.c); ++ int xf = MathHelper.floor(this.boundingBox.d); ++ int yf = MathHelper.floor(this.boundingBox.e) - 1; ++ int zf = MathHelper.floor(this.boundingBox.f); ++ for (int a = xi; a <= xf; a++) { ++ for (int c = zi; c <= zf; c++) { ++ for (int b = yi; b <= yf; b++) { ++ this.world.updateChestAndHoppers(a, b, c); ++ } ++ } ++ } ++ } ++ super.h(); ++ } ++ // Spigot end ++ + public void bp() { + if (this.getControllerMove().a()) { + double d0 = this.getControllerMove().b(); +diff --git a/src/main/java/net/minecraft/server/TileEntity.java b/src/main/java/net/minecraft/server/TileEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/TileEntity.java ++++ b/src/main/java/net/minecraft/server/TileEntity.java +@@ -0,0 +0,0 @@ public class TileEntity { + public int g = -1; + public Block h; + ++ // Spigot start ++ // Helper method for scheduleTicks. If the hopper at x0, y0, z0 is pointed ++ // at this tile entity, then make it active. ++ private void scheduleTick(int x0, int y0, int z0) { ++ TileEntity tileEntity = this.world.getTileEntity(x0, y0, z0); ++ if (tileEntity instanceof TileEntityHopper && tileEntity.world != null) { ++ // i is the metadeta assoiated with the direction the hopper faces. ++ int i = BlockHopper.b(tileEntity.p()); ++ // Facing class provides arrays for direction offset. ++ if (tileEntity.x + Facing.b[i] == this.x && tileEntity.y + Facing.c[i] == this.y && tileEntity.z + Facing.d[i] == this.z) { ++ ((TileEntityHopper) tileEntity).makeTick(); ++ } ++ } ++ } ++ ++ // Called from update when the contents have changed, so hoppers need updates. ++ // Check all 6 faces. ++ public void scheduleTicks() { ++ if (this.world != null && this.world.spigotConfig.altHopperTicking) { ++ // Check the top ++ this.scheduleTick(this.x, this.y + 1, this.z); ++ // Check the sides ++ for (int i = 2; i < 6; i++) { ++ this.scheduleTick(this.x + Facing.b[i], this.y, this.z + Facing.d[i]); ++ } ++ // Check the bottom. ++ TileEntity tileEntity = this.world.getTileEntity(this.x, this.y - 1, this.z); ++ if (tileEntity instanceof TileEntityHopper && tileEntity.world != null) { ++ ((TileEntityHopper) tileEntity).makeTick(); ++ } ++ } ++ } ++ // Spigot end ++ + public TileEntity() {} + + private static void a(Class oclass, String s) { +@@ -0,0 +0,0 @@ public class TileEntity { + if (this.q() != Blocks.AIR) { + this.world.updateAdjacentComparators(this.x, this.y, this.z, this.q()); + } ++ // Spigot start - Called when the contents have changed, so hoppers around this ++ // tile need updating. ++ this.scheduleTicks(); ++ // Spigot end + } + } + +diff --git a/src/main/java/net/minecraft/server/TileEntityHopper.java b/src/main/java/net/minecraft/server/TileEntityHopper.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/TileEntityHopper.java ++++ b/src/main/java/net/minecraft/server/TileEntityHopper.java +@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntity implements IHopper { + private String i; + private int j = -1; + ++ // Spigot start ++ private long nextTick = -1; // Next tick this hopper will be ticked. ++ private long lastTick = -1; // Last tick this hopper was polled. ++ ++ // If this hopper is not cooling down, assaign a visible tick for next time. ++ public void makeTick() { ++ if (!this.j()) { ++ this.c(0); ++ } ++ } ++ ++ // Contents changed, so make this hopper active. ++ public void scheduleHopperTick() { ++ if (this.world != null && this.world.spigotConfig.altHopperTicking) { ++ this.makeTick(); ++ } ++ } ++ ++ // Called after this hopper is assaigned a world or when altHopperTicking is turned ++ // on from reload. ++ public void convertToScheduling() { ++ // j is the cooldown in ticks ++ this.c(this.j); ++ } ++ ++ // Called when alt hopper ticking is turned off from the reload command ++ public void convertToPolling() { ++ long cooldownDiff; ++ if (this.lastTick == this.world.getTime()) { ++ cooldownDiff = this.nextTick - this.world.getTime(); ++ } else { ++ cooldownDiff = this.nextTick - this.world.getTime() + 1; ++ } ++ this.c((int) Math.max(0, Math.min(cooldownDiff, Integer.MAX_VALUE))); ++ } ++ // Spigot end ++ + // CraftBukkit start - add fields and methods + public List transaction = new java.util.ArrayList(); + private int maxStack = MAX_STACK; +@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntity implements IHopper { + } + + nbttagcompound.set("Items", nbttaglist); +- nbttagcompound.setInt("TransferCooldown", this.j); ++ // Spigot start - Need to write the correct cooldown to disk. We convert from long to int on saving. ++ if (this.world != null && this.world.spigotConfig.altHopperTicking) { ++ long cooldownDiff; ++ if (this.lastTick == this.world.getTime()) { ++ cooldownDiff = this.nextTick - this.world.getTime(); ++ } else { ++ cooldownDiff = this.nextTick - this.world.getTime() + 1; ++ } ++ nbttagcompound.setInt("TransferCooldown", (int) Math.max(0, Math.min(cooldownDiff, Integer.MAX_VALUE))); ++ } else { ++ // j is the cooldown in ticks. ++ nbttagcompound.setInt("TransferCooldown", this.j); ++ } ++ // Spigot end + if (this.k_()) { + nbttagcompound.setString("CustomName", this.i); + } +@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntity implements IHopper { + + public void update() { + super.update(); ++ // Spigot start - The contents have changed, so make this hopper active. ++ this.scheduleHopperTick(); ++ // Spigot end + } + + public int getSize() { +@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntity implements IHopper { + + public void h() { + if (this.world != null && !this.world.isStatic) { +- --this.j; +- if (!this.j()) { +- this.c(0); +- this.i(); ++ // Spigot start ++ if (this.world.spigotConfig.altHopperTicking) { ++ this.lastTick = this.world.getTime(); ++ if (this.nextTick == this.world.getTime()) { ++ // Method that does the pushing and pulling. ++ this.i(); ++ } ++ } else { ++ --this.j; ++ if (!this.j()) { ++ this.c(0); ++ this.i(); ++ } + } ++ // Spigot end + } + } + +@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntity implements IHopper { + } + + // Spigot start +- if ( !this.j() ) ++ if ( !world.spigotConfig.altHopperTicking && !this.j() ) + { + this.c( world.spigotConfig.hopperCheck ); + } +@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntity implements IHopper { + } + + public void c(int i) { +- this.j = i; ++ // Spigot start - i is the delay for which this hopper will be ticked next. ++ // i of 1 or below implies a tick next tick. ++ if (this.world != null && this.world.spigotConfig.altHopperTicking) { ++ if (i <= 0) { ++ i = 1; ++ } ++ if (this.lastTick == this.world.getTime()) { ++ this.nextTick = this.world.getTime() + i; ++ } else { ++ this.nextTick = this.world.getTime() + i - 1; ++ } ++ } else { ++ this.j = i; ++ } ++ // Spigot end + } + + public boolean j() { +- return this.j > 0; ++ // Spigot start - Return whether this hopper is cooling down. ++ if (this.world != null && this.world.spigotConfig.altHopperTicking) { ++ if (this.lastTick == this.world.getTime()) { ++ return this.nextTick > this.world.getTime(); ++ } else { ++ return this.nextTick >= this.world.getTime(); ++ } ++ } else { ++ return this.j > 0; ++ } ++ // Spigot end + } + } +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + private final byte chunkTickRadius; + public static boolean haveWeSilencedAPhysicsCrash; + public static String blockLocation; ++ public List triggerHoppersList = new ArrayList(); // Spigot, When altHopperTicking, tile entities being added go through here. + + public static long chunkToKey(int x, int z) + { +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + { + return (int) ( ( ( k >> 32 ) & 0xFFFF0000L ) | ( ( k >> 16 ) & 0x0000FFFF ) ); + } ++ ++ // Spigot Start - Hoppers need to be born ticking. ++ private void initializeHoppers() { ++ if (this.spigotConfig.altHopperTicking) { ++ for (TileEntity o : this.triggerHoppersList) { ++ o.scheduleTicks(); ++ if (o instanceof TileEntityHopper) { ++ ((TileEntityHopper) o).convertToScheduling(); ++ ((TileEntityHopper) o).scheduleHopperTick(); ++ } ++ } ++ } ++ triggerHoppersList.clear(); ++ } ++ ++ // Helper method for altHopperTicking. Updates chests at the specified location, ++ // accounting for double chests. Updating the chest will update adjacent hoppers. ++ public void updateChestAndHoppers(int a, int b, int c) { ++ Block block = this.getType(a, b, c); ++ if (block instanceof BlockChest) { ++ TileEntity tile = this.getTileEntity(a, b, c); ++ if (tile instanceof TileEntityChest) { ++ tile.scheduleTicks(); ++ } ++ for (int i = 2; i < 6; i++) { ++ // Facing class provides arrays for direction offset. ++ if (this.getType(a + Facing.b[i], b, c + Facing.d[i]) == block) { ++ tile = this.getTileEntity(a + Facing.b[i], b, c + Facing.d[i]); ++ if (tile instanceof TileEntityChest) { ++ tile.scheduleTicks(); ++ } ++ break; ++ } ++ } ++ } ++ } + // Spigot end + + public BiomeBase getBiome(int i, int j) { +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + this.notifyAndUpdatePhysics(i, j, k, chunk, block1, block, i1); + // CraftBukkit end + } ++ // Spigot start - If this block is changing to that which a chest beneath it ++ // becomes able to be opened, then the chest must be updated. ++ // block1 is the old block. block is the new block. r returns true if the block type ++ // prevents access to a chest. ++ if (this.spigotConfig.altHopperTicking && block1 != null && block1.r() && !block.r()) { ++ this.updateChestAndHoppers(i, j - 1, k); ++ } ++ // Spigot end + + return flag; + } +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + this.tileEntityList.removeAll(this.b); + this.b.clear(); + } +- // CraftBukkit end ++ // Spigot End + ++ this.initializeHoppers(); // Spigot - Initializes hoppers which have been added recently. + Iterator iterator = this.tileEntityList.iterator(); + + while (iterator.hasNext()) { +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -0,0 +0,0 @@ public class SpigotWorldConfig + log( "Entity Tracking Range: Pl " + playerTrackingRange + " / An " + animalTrackingRange + " / Mo " + monsterTrackingRange + " / Mi " + miscTrackingRange + " / Other " + otherTrackingRange ); + } + ++ public boolean altHopperTicking; + public int hopperTransfer; + public int hopperCheck; + public int hopperAmount; + private void hoppers() + { ++ // Alternate ticking method. Uses inventory changes, redstone updates etc. ++ // to update hoppers. Hopper-check is disabled when this is true. ++ boolean prev = altHopperTicking; ++ altHopperTicking = getBoolean( "hopper-alt-ticking", false ); ++ // Necessary for the reload command ++ if (prev != altHopperTicking) { ++ net.minecraft.server.World world = (net.minecraft.server.World) Bukkit.getWorld(this.worldName); ++ if (world != null) { ++ if (altHopperTicking) { ++ for (Object o : world.tileEntityList) { ++ if (o instanceof net.minecraft.server.TileEntityHopper) { ++ ((net.minecraft.server.TileEntityHopper) o).convertToScheduling(); ++ } ++ } ++ } else { ++ for (Object o : world.tileEntityList) { ++ if (o instanceof net.minecraft.server.TileEntityHopper) { ++ ((net.minecraft.server.TileEntityHopper) o).convertToPolling(); ++ } ++ } ++ } ++ } ++ } + // Set the tick delay between hopper item movements + hopperTransfer = getInt( "ticks-per.hopper-transfer", 8 ); + // Set the tick delay between checking for items after the associated +@@ -0,0 +0,0 @@ public class SpigotWorldConfig + // hopper sorting machines from becoming out of sync. + hopperCheck = getInt( "ticks-per.hopper-check", hopperTransfer ); + hopperAmount = getInt( "hopper-amount", 1 ); ++ log( "Alternative Hopper Ticking: " + altHopperTicking ); + log( "Hopper Transfer: " + hopperTransfer + " Hopper Check: " + hopperCheck + " Hopper Amount: " + hopperAmount ); + } + +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0145-Fix-explosions-not-moving-invulnerable-entities.patch b/CraftBukkit-Patches/0145-Fix-explosions-not-moving-invulnerable-entities.patch new file mode 100644 index 0000000000..b2813dec89 --- /dev/null +++ b/CraftBukkit-Patches/0145-Fix-explosions-not-moving-invulnerable-entities.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Thu, 26 Jun 2014 14:29:11 +0100 +Subject: [PATCH] Fix explosions not moving invulnerable entities + + +diff --git a/src/main/java/net/minecraft/server/Explosion.java b/src/main/java/net/minecraft/server/Explosion.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Explosion.java ++++ b/src/main/java/net/minecraft/server/Explosion.java +@@ -0,0 +0,0 @@ public class Explosion { + // CraftBukkit start + CraftEventFactory.entityDamage = source; + if (!entity.damageEntity(DamageSource.explosion(this), (float) ((int) ((d10 * d10 + d10) / 2.0D * 8.0D * (double) this.size + 1.0D)))) { +- CraftEventFactory.entityDamage = null; +- continue; ++ + } ++ CraftEventFactory.entityDamage = null; + // CraftBukkit end + double d11 = EnchantmentProtection.a(entity, d10); + +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0146-Add-damager-to-the-unhandled-error.patch b/CraftBukkit-Patches/0146-Add-damager-to-the-unhandled-error.patch new file mode 100644 index 0000000000..038224dc6c --- /dev/null +++ b/CraftBukkit-Patches/0146-Add-damager-to-the-unhandled-error.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Thu, 26 Jun 2014 23:42:52 +0100 +Subject: [PATCH] Add damager to the unhandled error + + +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -0,0 +0,0 @@ public class CraftEventFactory { + } else if (source == DamageSource.FALL) { + cause = DamageCause.FALL; + } else { +- throw new RuntimeException("Unhandled entity damage"); ++ throw new RuntimeException("Unhandled entity damage from " + damager.getHandle().getName()); // Spigot - Add damager + } + EntityDamageEvent event = callEvent(new EntityDamageByEntityEvent(damager, entity.getBukkitEntity(), cause, modifiers, modifierFunctions)); + if (!event.isCancelled()) { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0147-Fix-ItemFrame-and-Fireball-EntityDamageByEntityEvent.patch b/CraftBukkit-Patches/0147-Fix-ItemFrame-and-Fireball-EntityDamageByEntityEvent.patch new file mode 100644 index 0000000000..2609732cc4 --- /dev/null +++ b/CraftBukkit-Patches/0147-Fix-ItemFrame-and-Fireball-EntityDamageByEntityEvent.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown <1254957+zachbr@users.noreply.github.com> +Date: Tue, 24 Jun 2014 09:51:05 -0500 +Subject: [PATCH] Fix ItemFrame and Fireball EntityDamageByEntityEvent + + +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -0,0 +0,0 @@ public class CraftEventFactory { + if (event == null) { + return false; + } +- return event.isCancelled() || event.getDamage() == 0; ++ return event.isCancelled(); + } + + public static PlayerLevelChangeEvent callPlayerLevelChangeEvent(Player player, int oldLevel, int newLevel) { +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0148-Cross-World-Entity-Teleportation.patch b/CraftBukkit-Patches/0148-Cross-World-Entity-Teleportation.patch new file mode 100644 index 0000000000..c7a3bb3a9a --- /dev/null +++ b/CraftBukkit-Patches/0148-Cross-World-Entity-Teleportation.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrew Krieger +Date: Tue, 24 Dec 2013 07:55:23 -0800 +Subject: [PATCH] Cross World Entity Teleportation + +Use Entity.teleportTo for cross-world teleportation in CraftEntity. + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + return false; + } + +- entity.world = ((CraftWorld) location.getWorld()).getHandle(); ++ // Spigot start ++ if (!location.getWorld().equals(getWorld())) { ++ entity.teleportTo(location, cause.equals(TeleportCause.NETHER_PORTAL)); ++ return true; ++ } ++ ++ // entity.world = ((CraftWorld) location.getWorld()).getHandle(); ++ // Spigot end + entity.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + // entity.setLocation() throws no event, and so cannot be cancelled + return true; +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0149-Limit-block-placement-interaction-packets.patch b/CraftBukkit-Patches/0149-Limit-block-placement-interaction-packets.patch new file mode 100644 index 0000000000..ba0cdcd7ee --- /dev/null +++ b/CraftBukkit-Patches/0149-Limit-block-placement-interaction-packets.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Sun, 29 Jun 2014 21:10:34 +0100 +Subject: [PATCH] Limit block placement/interaction packets + + +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketPlayInListener { + } + } + ++ // Spigot start - limit place/interactions ++ private long lastPlace = -1; ++ + public void a(PacketPlayInBlockPlace packetplayinblockplace) { ++ boolean throttled = false; ++ if (lastPlace != -1 && packetplayinblockplace.timestamp - lastPlace < 5) { ++ throttled = true; ++ } else ++ { ++ lastPlace = packetplayinblockplace.timestamp; ++ } ++ // Spigot end + WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension); + + // CraftBukkit start +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketPlayInListener { + + // CraftBukkit start + int itemstackAmount = itemstack.count; ++ // Spigot start - skip the event if throttled ++ if (!throttled) { + org.bukkit.event.player.PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.RIGHT_CLICK_AIR, itemstack); + if (event.useItemInHand() != Event.Result.DENY) { + this.player.playerInteractManager.useItem(this.player, this.player.world, itemstack); + } ++ } ++ // Spigot end + + // CraftBukkit - notch decrements the counter by 1 in the above method with food, + // snowballs and so forth, but he does it in a place that doesn't cause the +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketPlayInListener { + return; + } + +- if (!this.player.playerInteractManager.interact(this.player, worldserver, itemstack, i, j, k, l, packetplayinblockplace.h(), packetplayinblockplace.i(), packetplayinblockplace.j())) { ++ if (throttled || !this.player.playerInteractManager.interact(this.player, worldserver, itemstack, i, j, k, l, packetplayinblockplace.h(), packetplayinblockplace.i(), packetplayinblockplace.j())) { // Spigot - skip the event if throttled + always = true; // force PacketPlayOutSetSlot to be sent to client to update ItemStack count + } + // CraftBukkit end +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0150-Better-item-validation.patch b/CraftBukkit-Patches/0150-Better-item-validation.patch new file mode 100644 index 0000000000..b0a8510502 --- /dev/null +++ b/CraftBukkit-Patches/0150-Better-item-validation.patch @@ -0,0 +1,113 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Wed, 2 Jul 2014 23:35:51 +0100 +Subject: [PATCH] Better item validation + + +diff --git a/src/main/java/net/minecraft/server/PacketDataSerializer.java b/src/main/java/net/minecraft/server/PacketDataSerializer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PacketDataSerializer.java ++++ b/src/main/java/net/minecraft/server/PacketDataSerializer.java +@@ -0,0 +0,0 @@ public class PacketDataSerializer extends ByteBuf { + NBTTagCompound nbttagcompound = null; + + if (itemstack.getItem().usesDurability() || itemstack.getItem().s()) { ++ // Spigot start - filter ++ itemstack = itemstack.cloneItemStack(); ++ CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); ++ // Spigot end + nbttagcompound = itemstack.tag; + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +@@ -0,0 +0,0 @@ import com.google.common.base.Strings; + import com.google.common.collect.ImmutableList; + import com.google.common.collect.ImmutableMap.Builder; + ++// Spigot start ++import static org.spigotmc.ValidateUtils.*; ++// Spigot end ++ + @DelegateDeserialization(SerializableMeta.class) + class CraftMetaBook extends CraftMetaItem implements BookMeta { + static final ItemMetaKey BOOK_TITLE = new ItemMetaKey("title"); +@@ -0,0 +0,0 @@ class CraftMetaBook extends CraftMetaItem implements BookMeta { + super(tag); + + if (tag.hasKey(BOOK_TITLE.NBT)) { +- this.title = tag.getString(BOOK_TITLE.NBT); ++ this.title = limit( tag.getString(BOOK_TITLE.NBT), 1024 ); // Spigot + } + + if (tag.hasKey(BOOK_AUTHOR.NBT)) { +- this.author = tag.getString(BOOK_AUTHOR.NBT); ++ this.author = limit( tag.getString(BOOK_AUTHOR.NBT), 1024 ); // Spigot + } + + if (tag.hasKey(BOOK_PAGES.NBT)) { +@@ -0,0 +0,0 @@ class CraftMetaBook extends CraftMetaItem implements BookMeta { + String[] pageArray = new String[pages.size()]; + + for (int i = 0; i < pages.size(); i++) { +- String page = pages.getString(i); ++ String page = limit( pages.getString(i), 2048 ); // Spigot + pageArray[i] = page; + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +@@ -0,0 +0,0 @@ import com.google.common.base.Strings; + import com.google.common.collect.ImmutableList; + import com.google.common.collect.ImmutableMap; + ++// Spigot start ++import static org.spigotmc.ValidateUtils.*; ++// Spigot end ++ + /** + * Children must include the following: + * +@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Repairable { + NBTTagCompound display = tag.getCompound(DISPLAY.NBT); + + if (display.hasKey(NAME.NBT)) { +- displayName = display.getString(NAME.NBT); ++ displayName = limit( display.getString(NAME.NBT), 1024 ); // Spigot + } + + if (display.hasKey(LORE.NBT)) { +@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Repairable { + lore = new ArrayList(list.size()); + + for (int index = 0; index < list.size(); index++) { +- String line = list.getString(index); ++ String line = limit( list.getString(index), 1024 ); // Spigot + lore.add(line); + } + } +diff --git a/src/main/java/org/spigotmc/ValidateUtils.java b/src/main/java/org/spigotmc/ValidateUtils.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/org/spigotmc/ValidateUtils.java +@@ -0,0 +0,0 @@ ++package org.spigotmc; ++ ++public class ValidateUtils ++{ ++ ++ public static String limit(String str, int limit) ++ { ++ if ( str.length() > limit ) ++ { ++ return str.substring( 0, limit ); ++ } ++ return str; ++ } ++} +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0151-Further-Seed-Customisation.patch b/CraftBukkit-Patches/0151-Further-Seed-Customisation.patch new file mode 100644 index 0000000000..e45777f677 --- /dev/null +++ b/CraftBukkit-Patches/0151-Further-Seed-Customisation.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Fri, 4 Jul 2014 13:28:45 +1000 +Subject: [PATCH] Further Seed Customisation + +Allow server admins that really want to to customise the seeds used in world generation even further. + +diff --git a/src/main/java/net/minecraft/server/WorldGenLargeFeature.java b/src/main/java/net/minecraft/server/WorldGenLargeFeature.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/WorldGenLargeFeature.java ++++ b/src/main/java/net/minecraft/server/WorldGenLargeFeature.java +@@ -0,0 +0,0 @@ public class WorldGenLargeFeature extends StructureGenerator { + + int i1 = i / this.g; + int j1 = j / this.g; +- Random random = this.c.A(i1, j1, 14357617); ++ Random random = this.c.A(i1, j1, this.c.spigotConfig.largeFeatureSeed); // Spigot + + i1 *= this.g; + j1 *= this.g; +diff --git a/src/main/java/net/minecraft/server/WorldGenVillage.java b/src/main/java/net/minecraft/server/WorldGenVillage.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/WorldGenVillage.java ++++ b/src/main/java/net/minecraft/server/WorldGenVillage.java +@@ -0,0 +0,0 @@ public class WorldGenVillage extends StructureGenerator { + + int i1 = i / this.g; + int j1 = j / this.g; +- Random random = this.c.A(i1, j1, 10387312); ++ Random random = this.c.A(i1, j1, this.c.spigotConfig.villageSeed); // Spigot + + i1 *= this.g; + j1 *= this.g; +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -0,0 +0,0 @@ public class SpigotWorldConfig + { + witherSpawnSoundRadius = getInt( "wither-spawn-sound-radius", 0 ); + } ++ ++ public int villageSeed; ++ public int largeFeatureSeed; ++ private void initWorldGenSeeds() ++ { ++ villageSeed = getInt( "seed-village", 10387312 ); ++ largeFeatureSeed = getInt( "seed-feature", 14357617 ); ++ log( "Custom Map Seeds: Village: " + villageSeed + " Feature: " + largeFeatureSeed ); ++ } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0152-Disable-ResourceLeakDetector.patch b/CraftBukkit-Patches/0152-Disable-ResourceLeakDetector.patch new file mode 100644 index 0000000000..fe784ee83c --- /dev/null +++ b/CraftBukkit-Patches/0152-Disable-ResourceLeakDetector.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Tue, 8 Jul 2014 09:01:50 +1000 +Subject: [PATCH] Disable ResourceLeakDetector + +Hopefully no plugins are somehow leaking buffers, but disabling the ResourceLeakDetector is a good thing for performance of the Netty IO subsytem (it's been disabled in BungeeCord for a while now). + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + // Spigot end + + public MinecraftServer(OptionSet options, Proxy proxy) { // CraftBukkit - signature file -> OptionSet ++ net.minecraft.util.io.netty.util.ResourceLeakDetector.setEnabled( false ); // Spigot - disable + this.X = new UserCache(this, a); + j = this; + this.d = proxy; +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0153-Add-More-Information-to-session.lock-Errors.patch b/CraftBukkit-Patches/0153-Add-More-Information-to-session.lock-Errors.patch new file mode 100644 index 0000000000..380f042503 --- /dev/null +++ b/CraftBukkit-Patches/0153-Add-More-Information-to-session.lock-Errors.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Suddenly +Date: Sat, 5 Jul 2014 16:56:44 +0100 +Subject: [PATCH] Add More Information to session.lock Errors + + +diff --git a/src/main/java/net/minecraft/server/WorldNBTStorage.java b/src/main/java/net/minecraft/server/WorldNBTStorage.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/WorldNBTStorage.java ++++ b/src/main/java/net/minecraft/server/WorldNBTStorage.java +@@ -0,0 +0,0 @@ public class WorldNBTStorage implements IDataManager, IPlayerFileData { + } + } catch (IOException ioexception) { + ioexception.printStackTrace(); +- throw new RuntimeException("Failed to check session lock, aborting"); ++ throw new RuntimeException("Failed to check session lock for world located at " + this.baseDir + ", aborting. Stop the server and delete the session.lock in this world to prevent further issues."); // Spigot + } + } + +@@ -0,0 +0,0 @@ public class WorldNBTStorage implements IDataManager, IPlayerFileData { + + try { + if (datainputstream.readLong() != this.sessionId) { +- throw new ExceptionWorldConflict("The save is being accessed from another location, aborting"); ++ throw new ExceptionWorldConflict("The save for world located at " + this.baseDir + " is being accessed from another location, aborting"); // Spigot + } + } finally { + datainputstream.close(); + } + } catch (IOException ioexception) { +- throw new ExceptionWorldConflict("Failed to check session lock, aborting"); ++ throw new ExceptionWorldConflict("Failed to check session lock for world located at " + this.baseDir + ", aborting. Stop the server and delete the session.lock in this world to prevent further issues."); // Spigot + } + } + +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0154-Safer-JSON-Loading.patch b/CraftBukkit-Patches/0154-Safer-JSON-Loading.patch new file mode 100644 index 0000000000..25a924356c --- /dev/null +++ b/CraftBukkit-Patches/0154-Safer-JSON-Loading.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Suddenly +Date: Tue, 8 Jul 2014 09:44:18 +1000 +Subject: [PATCH] Safer JSON Loading + + +diff --git a/src/main/java/net/minecraft/server/JsonList.java b/src/main/java/net/minecraft/server/JsonList.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/JsonList.java ++++ b/src/main/java/net/minecraft/server/JsonList.java +@@ -0,0 +0,0 @@ public class JsonList { + try { + bufferedreader = Files.newReader(this.c, Charsets.UTF_8); + collection = (Collection) this.b.fromJson(bufferedreader, f); ++ // Spigot Start ++ } catch ( java.io.FileNotFoundException ex ) ++ { ++ org.bukkit.Bukkit.getLogger().log( java.util.logging.Level.INFO, "Unable to find file {0}, creating it.", this.c ); ++ } catch ( net.minecraft.util.com.google.gson.JsonSyntaxException ex ) ++ { ++ org.bukkit.Bukkit.getLogger().log( java.util.logging.Level.WARNING, "Unable to read file {0}, backing it up to {0}.backup and creating new copy.", this.c ); ++ File backup = new File( this.c + ".backup" ); ++ this.c.renameTo( backup ); ++ this.c.delete(); ++ // Spigot End + } finally { + IOUtils.closeQuietly(bufferedreader); + } +diff --git a/src/main/java/net/minecraft/server/UserCache.java b/src/main/java/net/minecraft/server/UserCache.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/UserCache.java ++++ b/src/main/java/net/minecraft/server/UserCache.java +@@ -0,0 +0,0 @@ public class UserCache { + break label81; + } catch (FileNotFoundException filenotfoundexception) { + ; ++ // Spigot Start ++ } catch (net.minecraft.util.com.google.gson.JsonSyntaxException ex) { ++ org.bukkit.Bukkit.getLogger().warning( "Usercache.json is corrupted or has bad formatting. Deleting it to prevent further issues."); ++ this.g.delete(); ++ // Spigot End + } finally { + IOUtils.closeQuietly(bufferedreader); + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0155-Fix-Slow-Loading-Libraries.patch b/CraftBukkit-Patches/0155-Fix-Slow-Loading-Libraries.patch new file mode 100644 index 0000000000..01c9c092b4 --- /dev/null +++ b/CraftBukkit-Patches/0155-Fix-Slow-Loading-Libraries.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Tue, 8 Jul 2014 20:27:52 +1000 +Subject: [PATCH] Fix Slow "Loading Libraries" + + +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -0,0 +0,0 @@ public class Main { + System.out.println( "Please see http://www.spigotmc.org/wiki/changing-permgen-size/ for more details and more in-depth instructions." ); + } + // Spigot End +- System.out.println("Loading libraries, please wait..."); + MinecraftServer.main(options); + } catch (Throwable t) { + t.printStackTrace(); +diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/resources/log4j2.xml ++++ b/src/main/resources/log4j2.xml +@@ -0,0 +0,0 @@ + +- ++ + + + +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0156-Add-CommandLine-EULA-Flag.patch b/CraftBukkit-Patches/0156-Add-CommandLine-EULA-Flag.patch new file mode 100644 index 0000000000..f1c26262c1 --- /dev/null +++ b/CraftBukkit-Patches/0156-Add-CommandLine-EULA-Flag.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Wed, 9 Jul 2014 10:35:44 +1000 +Subject: [PATCH] Add CommandLine EULA Flag + +This flag contains the same message as eula.txt (albeit with proper grammar for 3rd person plural). By setting this flag you are agreeing to the terms listed in the message printed upon setting this flag, which are no different from those agreed to by any other method. + +This feature only exists for hosting companies and people who manage servers in bulk who wish to agree to the terms by setting a flag in a script. + +diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/DedicatedServer.java +@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + i.info("Loading properties"); + this.propertyManager = new PropertyManager(this.options); // CraftBukkit - CLI argument support + this.n = new EULA(new File("eula.txt")); +- if (!this.n.a()) { ++ // Spigot Start ++ boolean eulaAgreed = Boolean.getBoolean( "com.mojang.eula.agree" ); ++ if ( eulaAgreed ) ++ { ++ System.err.println( "You have used the Spigot command line EULA agreement flag." ); ++ System.err.println( "By using this setting you are indicating your agreement to Mojang's EULA (https://account.mojang.com/documents/minecraft_eula)." ); ++ System.err.println( "If you do not agree to the above EULA please stop your server and remove this flag immediately." ); ++ } ++ // Spigot End ++ if (!this.n.a() && !eulaAgreed) { + i.info("You need to agree to the EULA in order to run the server. Go to eula.txt for more info."); + this.n.b(); + return false; +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0157-Fix-misnamed-function-from-1.7.10-update.patch b/CraftBukkit-Patches/0157-Fix-misnamed-function-from-1.7.10-update.patch new file mode 100644 index 0000000000..c3acf76113 --- /dev/null +++ b/CraftBukkit-Patches/0157-Fix-misnamed-function-from-1.7.10-update.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Suddenly +Date: Mon, 14 Jul 2014 23:43:10 +0100 +Subject: [PATCH] Fix misnamed function from 1.7.10 update + + +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -0,0 +0,0 @@ public abstract class Entity { + + public void ac() { + if (this.passenger != null) { +- this.passenger.setPosition(this.locX, this.locY + this.ad() + this.passenger.ad(), this.locZ); ++ this.passenger.setPosition(this.locX, this.locY + this.ae() + this.passenger.ad(), this.locZ); // Spigot + } + } + +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0158-Fix-for-enchanting-table-wiping-meta-when-placing-st.patch b/CraftBukkit-Patches/0158-Fix-for-enchanting-table-wiping-meta-when-placing-st.patch new file mode 100644 index 0000000000..5b2d67b556 --- /dev/null +++ b/CraftBukkit-Patches/0158-Fix-for-enchanting-table-wiping-meta-when-placing-st.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: drXor +Date: Thu, 17 Jul 2014 21:13:15 -0400 +Subject: [PATCH] Fix for enchanting table wiping meta when placing stacked + items + + +diff --git a/src/main/java/net/minecraft/server/ContainerEnchantTable.java b/src/main/java/net/minecraft/server/ContainerEnchantTable.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/ContainerEnchantTable.java ++++ b/src/main/java/net/minecraft/server/ContainerEnchantTable.java +@@ -0,0 +0,0 @@ public class ContainerEnchantTable extends Container { + ((Slot) this.c.get(0)).set(itemstack1.cloneItemStack()); + itemstack1.count = 0; + } else if (itemstack1.count >= 1) { +- ((Slot) this.c.get(0)).set(new ItemStack(itemstack1.getItem(), 1, itemstack1.getData())); ++ // Spigot start ++ ItemStack clone = itemstack1.cloneItemStack(); ++ clone.count = 1; ++ ((Slot) this.c.get(0)).set(clone); ++ // Spigot end + --itemstack1.count; + } + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0159-Don-t-spawn-bonus-ocelots-when-plugins-spawn-ocelots.patch b/CraftBukkit-Patches/0159-Don-t-spawn-bonus-ocelots-when-plugins-spawn-ocelots.patch new file mode 100644 index 0000000000..3137de0bfe --- /dev/null +++ b/CraftBukkit-Patches/0159-Don-t-spawn-bonus-ocelots-when-plugins-spawn-ocelots.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Sat, 19 Jul 2014 12:49:48 +0100 +Subject: [PATCH] Don't spawn bonus ocelots when plugins spawn ocelots + + +diff --git a/src/main/java/net/minecraft/server/EntityOcelot.java b/src/main/java/net/minecraft/server/EntityOcelot.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityOcelot.java ++++ b/src/main/java/net/minecraft/server/EntityOcelot.java +@@ -0,0 +0,0 @@ package net.minecraft.server; + + public class EntityOcelot extends EntityTameableAnimal { + ++ public boolean spawnBonus = true; // Spigot + private PathfinderGoalTempt bq; + + public EntityOcelot(World world) { +@@ -0,0 +0,0 @@ public class EntityOcelot extends EntityTameableAnimal { + + public GroupDataEntity prepare(GroupDataEntity groupdataentity) { + groupdataentity = super.prepare(groupdataentity); +- if (this.world.random.nextInt(7) == 0) { ++ if (spawnBonus && this.world.random.nextInt(7) == 0) { // Spigot + for (int i = 0; i < 2; ++i) { + EntityOcelot entityocelot = new EntityOcelot(this.world); + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -0,0 +0,0 @@ public class CraftWorld implements World { + } + + if (entity != null) { ++ // Spigot start ++ if (entity instanceof EntityOcelot) ++ { ++ ( (EntityOcelot) entity ).spawnBonus = false; ++ } ++ // Spigot end + if (entity instanceof EntityInsentient) { + ((EntityInsentient) entity).prepare((GroupDataEntity) null); + } +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0160-Prevent-a-crash-involving-attributes.patch b/CraftBukkit-Patches/0160-Prevent-a-crash-involving-attributes.patch new file mode 100644 index 0000000000..d528973dce --- /dev/null +++ b/CraftBukkit-Patches/0160-Prevent-a-crash-involving-attributes.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Sat, 19 Jul 2014 19:54:41 +0100 +Subject: [PATCH] Prevent a crash involving attributes + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + break; + } + } +- collection.add(new AttributeModifiable(getHandle().getAttributeMap(), (new AttributeRanged("generic.maxHealth", scaledHealth ? healthScale : getMaxHealth(), 0.0D, Float.MAX_VALUE)).a("Max Health").a(true))); ++ // Spigot start ++ double healthMod = scaledHealth ? healthScale : getMaxHealth(); ++ if ( healthMod >= Float.MAX_VALUE || healthMod <= 0 ) ++ { ++ healthMod = 20; // Reset health ++ getServer().getLogger().warning( getName() + " tried to crash the server with a large health attribute" ); ++ } ++ collection.add(new AttributeModifiable(getHandle().getAttributeMap(), (new AttributeRanged("generic.maxHealth", healthMod, 0.0D, Float.MAX_VALUE)).a("Max Health").a(true))); ++ // Spigot end + } + + // Spigot start +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0161-Fix-IP-banning.patch b/CraftBukkit-Patches/0161-Fix-IP-banning.patch new file mode 100644 index 0000000000..017d383dbf --- /dev/null +++ b/CraftBukkit-Patches/0161-Fix-IP-banning.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Sat, 19 Jul 2014 22:13:44 +0100 +Subject: [PATCH] Fix IP banning + + +diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerList.java ++++ b/src/main/java/net/minecraft/server/PlayerList.java +@@ -0,0 +0,0 @@ public abstract class PlayerList { + } else if (!this.isWhitelisted(gameprofile)) { + // return "You are not white-listed on this server!"; + event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot +- } else if (this.k.isBanned(socketaddress) && !this.k.get(gameprofile).hasExpired()) { ++ } else if (this.k.isBanned(socketaddress) && !this.k.get(socketaddress).hasExpired()) { // Spigot + IpBanEntry ipbanentry = this.k.get(socketaddress); + + s = "Your IP address is banned from this server!\nReason: " + ipbanentry.getReason(); +-- \ No newline at end of file diff --git a/Bukkit-Patches/0001-Add-float-methods-to-configs.patch b/Spigot-API-Patches/Add-float-methods-to-configs.patch similarity index 100% rename from Bukkit-Patches/0001-Add-float-methods-to-configs.patch rename to Spigot-API-Patches/Add-float-methods-to-configs.patch diff --git a/Spigot-API-Patches/POM-changes.patch b/Spigot-API-Patches/POM-changes.patch new file mode 100644 index 0000000000..35e88d6c32 --- /dev/null +++ b/Spigot-API-Patches/POM-changes.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown <1254957+zachbr@users.noreply.github.com> +Date: Mon, 21 Jul 2014 15:35:46 -0500 +Subject: [PATCH] POM changes + + +diff --git a/pom.xml b/pom.xml +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -0,0 +0,0 @@ + + 4.0.0 +- org.spigotmc +- spigot-api ++ org.github.paperspigot ++ paperspigot-api + 1.7.10-R0.1-SNAPSHOT +- Spigot-API +- http://www.spigotmc.org ++ PaperSpigot-API ++ https://github.com/PaperSpigot/Spigot + + + UTF-8 + + + +- org.spigotmc +- spigot-parent ++ org.github.paperspigot ++ paperspigot-parent + dev-SNAPSHOT + ../pom.xml + +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0013-Ability-to-disable-asynccatcher.patch b/Spigot-Server-Patches/Ability-to-disable-asynccatcher.patch similarity index 100% rename from CraftBukkit-Patches/0013-Ability-to-disable-asynccatcher.patch rename to Spigot-Server-Patches/Ability-to-disable-asynccatcher.patch diff --git a/CraftBukkit-Patches/0012-Add-1.8-recipes-for-stone-variants.patch b/Spigot-Server-Patches/Add-1.8-recipes-for-stone-variants.patch similarity index 100% rename from CraftBukkit-Patches/0012-Add-1.8-recipes-for-stone-variants.patch rename to Spigot-Server-Patches/Add-1.8-recipes-for-stone-variants.patch diff --git a/CraftBukkit-Patches/0022-Add-configurable-despawn-distances-for-living-entiti.patch b/Spigot-Server-Patches/Add-configurable-despawn-distances-for-living-entiti.patch similarity index 100% rename from CraftBukkit-Patches/0022-Add-configurable-despawn-distances-for-living-entiti.patch rename to Spigot-Server-Patches/Add-configurable-despawn-distances-for-living-entiti.patch diff --git a/CraftBukkit-Patches/0023-Allow-for-toggling-of-spawn-chunks.patch b/Spigot-Server-Patches/Allow-for-toggling-of-spawn-chunks.patch similarity index 100% rename from CraftBukkit-Patches/0023-Allow-for-toggling-of-spawn-chunks.patch rename to Spigot-Server-Patches/Allow-for-toggling-of-spawn-chunks.patch diff --git a/CraftBukkit-Patches/0019-Allow-nerfed-mobs-to-jump.patch b/Spigot-Server-Patches/Allow-nerfed-mobs-to-jump.patch similarity index 100% rename from CraftBukkit-Patches/0019-Allow-nerfed-mobs-to-jump.patch rename to Spigot-Server-Patches/Allow-nerfed-mobs-to-jump.patch diff --git a/CraftBukkit-Patches/0003-Allow-undead-horse-types-to-be-leashed.patch b/Spigot-Server-Patches/Allow-undead-horse-types-to-be-leashed.patch similarity index 100% rename from CraftBukkit-Patches/0003-Allow-undead-horse-types-to-be-leashed.patch rename to Spigot-Server-Patches/Allow-undead-horse-types-to-be-leashed.patch diff --git a/CraftBukkit-Patches/0025-Better-EULA-handling.patch b/Spigot-Server-Patches/Better-EULA-handling.patch similarity index 100% rename from CraftBukkit-Patches/0025-Better-EULA-handling.patch rename to Spigot-Server-Patches/Better-EULA-handling.patch diff --git a/CraftBukkit-Patches/0028-Configurable-AI-target-selector-delay.patch b/Spigot-Server-Patches/Configurable-AI-target-selector-delay.patch similarity index 100% rename from CraftBukkit-Patches/0028-Configurable-AI-target-selector-delay.patch rename to Spigot-Server-Patches/Configurable-AI-target-selector-delay.patch diff --git a/CraftBukkit-Patches/0009-Configurable-baby-zombie-movement-speed.patch b/Spigot-Server-Patches/Configurable-baby-zombie-movement-speed.patch similarity index 100% rename from CraftBukkit-Patches/0009-Configurable-baby-zombie-movement-speed.patch rename to Spigot-Server-Patches/Configurable-baby-zombie-movement-speed.patch diff --git a/CraftBukkit-Patches/0008-Configurable-cactus-and-reed-natural-growth-heights.patch b/Spigot-Server-Patches/Configurable-cactus-and-reed-natural-growth-heights.patch similarity index 100% rename from CraftBukkit-Patches/0008-Configurable-cactus-and-reed-natural-growth-heights.patch rename to Spigot-Server-Patches/Configurable-cactus-and-reed-natural-growth-heights.patch diff --git a/CraftBukkit-Patches/0007-Configurable-damage-multiplier-for-PvP-blocking.patch b/Spigot-Server-Patches/Configurable-damage-multiplier-for-PvP-blocking.patch similarity index 100% rename from CraftBukkit-Patches/0007-Configurable-damage-multiplier-for-PvP-blocking.patch rename to Spigot-Server-Patches/Configurable-damage-multiplier-for-PvP-blocking.patch diff --git a/CraftBukkit-Patches/0018-Configurable-fishing-time-ranges.patch b/Spigot-Server-Patches/Configurable-fishing-time-ranges.patch similarity index 100% rename from CraftBukkit-Patches/0018-Configurable-fishing-time-ranges.patch rename to Spigot-Server-Patches/Configurable-fishing-time-ranges.patch diff --git a/CraftBukkit-Patches/0026-Configurable-nerf-for-TNT-cannons.patch b/Spigot-Server-Patches/Configurable-nerf-for-TNT-cannons.patch similarity index 100% rename from CraftBukkit-Patches/0026-Configurable-nerf-for-TNT-cannons.patch rename to Spigot-Server-Patches/Configurable-nerf-for-TNT-cannons.patch diff --git a/CraftBukkit-Patches/0006-Configurable-squid-spawn-ranges.patch b/Spigot-Server-Patches/Configurable-squid-spawn-ranges.patch similarity index 100% rename from CraftBukkit-Patches/0006-Configurable-squid-spawn-ranges.patch rename to Spigot-Server-Patches/Configurable-squid-spawn-ranges.patch diff --git a/CraftBukkit-Patches/0015-Do-not-remove-player-in-world-change.patch b/Spigot-Server-Patches/Do-not-remove-player-in-world-change.patch similarity index 100% rename from CraftBukkit-Patches/0015-Do-not-remove-player-in-world-change.patch rename to Spigot-Server-Patches/Do-not-remove-player-in-world-change.patch diff --git a/CraftBukkit-Patches/0027-Don-t-tick-chests.patch b/Spigot-Server-Patches/Don-t-tick-chests.patch similarity index 100% rename from CraftBukkit-Patches/0027-Don-t-tick-chests.patch rename to Spigot-Server-Patches/Don-t-tick-chests.patch diff --git a/CraftBukkit-Patches/0024-Fix-Null-Tile-Entity-Worlds.patch b/Spigot-Server-Patches/Fix-Null-Tile-Entity-Worlds.patch similarity index 100% rename from CraftBukkit-Patches/0024-Fix-Null-Tile-Entity-Worlds.patch rename to Spigot-Server-Patches/Fix-Null-Tile-Entity-Worlds.patch diff --git a/CraftBukkit-Patches/0016-Fix-directional-TNT-bias.patch b/Spigot-Server-Patches/Fix-directional-TNT-bias.patch similarity index 100% rename from CraftBukkit-Patches/0016-Fix-directional-TNT-bias.patch rename to Spigot-Server-Patches/Fix-directional-TNT-bias.patch diff --git a/CraftBukkit-Patches/0014-Fix-redstone-lag-issues.patch b/Spigot-Server-Patches/Fix-redstone-lag-issues.patch similarity index 100% rename from CraftBukkit-Patches/0014-Fix-redstone-lag-issues.patch rename to Spigot-Server-Patches/Fix-redstone-lag-issues.patch diff --git a/CraftBukkit-Patches/0017-Fix-zombie-sieges-and-their-spawn-mechanics.patch b/Spigot-Server-Patches/Fix-zombie-sieges-and-their-spawn-mechanics.patch similarity index 100% rename from CraftBukkit-Patches/0017-Fix-zombie-sieges-and-their-spawn-mechanics.patch rename to Spigot-Server-Patches/Fix-zombie-sieges-and-their-spawn-mechanics.patch diff --git a/CraftBukkit-Patches/0011-Inverted-Daylight-Detector-Toggle.patch b/Spigot-Server-Patches/Inverted-Daylight-Detector-Toggle.patch similarity index 100% rename from CraftBukkit-Patches/0011-Inverted-Daylight-Detector-Toggle.patch rename to Spigot-Server-Patches/Inverted-Daylight-Detector-Toggle.patch diff --git a/CraftBukkit-Patches/0005-Invisible-players-don-t-have-rights.patch b/Spigot-Server-Patches/Invisible-players-don-t-have-rights.patch similarity index 100% rename from CraftBukkit-Patches/0005-Invisible-players-don-t-have-rights.patch rename to Spigot-Server-Patches/Invisible-players-don-t-have-rights.patch diff --git a/CraftBukkit-Patches/0010-Make-destroyed-boats-drop-the-boat-item.patch b/Spigot-Server-Patches/Make-destroyed-boats-drop-the-boat-item.patch similarity index 100% rename from CraftBukkit-Patches/0010-Make-destroyed-boats-drop-the-boat-item.patch rename to Spigot-Server-Patches/Make-destroyed-boats-drop-the-boat-item.patch diff --git a/Spigot-Server-Patches/POM-changes.patch b/Spigot-Server-Patches/POM-changes.patch new file mode 100644 index 0000000000..162bc8460f --- /dev/null +++ b/Spigot-Server-Patches/POM-changes.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown <1254957+zachbr@users.noreply.github.com> +Date: Mon, 21 Jul 2014 15:36:01 -0500 +Subject: [PATCH] POM changes + + +diff --git a/pom.xml b/pom.xml +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -0,0 +0,0 @@ + + 4.0.0 +- org.spigotmc +- spigot ++ org.github.paperspigot ++ paperspigot + jar + 1.7.10-R0.1-SNAPSHOT +- Spigot +- http://www.spigotmc.org ++ PaperSpigot ++ https://github.com/PaperSpigot/Spigot + + + UTF-8 +@@ -0,0 +0,0 @@ + + + +- org.spigotmc +- spigot-parent ++ org.github.paperspigot ++ paperspigot-parent + dev-SNAPSHOT + ../pom.xml + +@@ -0,0 +0,0 @@ + + + +- org.spigotmc +- spigot-api ++ org.github.paperspigot ++ paperspigot-api + ${project.version} + jar + compile +@@ -0,0 +0,0 @@ + gitdescribe-maven-plugin + 1.3 + +- git-Spigot- ++ git-PaperSpigot- + + + +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0002-PaperSpigot-config-files.patch b/Spigot-Server-Patches/PaperSpigot-config-files.patch similarity index 100% rename from CraftBukkit-Patches/0002-PaperSpigot-config-files.patch rename to Spigot-Server-Patches/PaperSpigot-config-files.patch diff --git a/CraftBukkit-Patches/0021-Player-Exhaustion-Multipliers.patch b/Spigot-Server-Patches/Player-Exhaustion-Multipliers.patch similarity index 100% rename from CraftBukkit-Patches/0021-Player-Exhaustion-Multipliers.patch rename to Spigot-Server-Patches/Player-Exhaustion-Multipliers.patch diff --git a/CraftBukkit-Patches/0004-Teleport-passenger-vehicle-with-player.patch b/Spigot-Server-Patches/Teleport-passenger-vehicle-with-player.patch similarity index 100% rename from CraftBukkit-Patches/0004-Teleport-passenger-vehicle-with-player.patch rename to Spigot-Server-Patches/Teleport-passenger-vehicle-with-player.patch diff --git a/CraftBukkit-Patches/0020-Toggle-for-player-interact-limiter.patch b/Spigot-Server-Patches/Toggle-for-player-interact-limiter.patch similarity index 100% rename from CraftBukkit-Patches/0020-Toggle-for-player-interact-limiter.patch rename to Spigot-Server-Patches/Toggle-for-player-interact-limiter.patch diff --git a/applyPatches.sh b/applyPatches.sh index 32585f94b4..df1518c3fc 100755 --- a/applyPatches.sh +++ b/applyPatches.sh @@ -33,5 +33,11 @@ function applyPatch { echo " Patches applied cleanly to $target" fi } - +echo +echo "Applying SpigotMC patches to CraftBukkit and Bukkit" +echo applyPatch Bukkit Spigot-API && applyPatch CraftBukkit Spigot-Server +echo +echo "Applying PaperSpigot patches to Spigot-Server and Spigot-API" +echo +applyPatch Spigot-API PaperSpigot-API && applyPatch Spigot-Server PaperSpigot-Server \ No newline at end of file diff --git a/pom.xml b/pom.xml index 65ffc5f164..e6529e2c66 100644 --- a/pom.xml +++ b/pom.xml @@ -9,20 +9,20 @@ 7 - org.spigotmc - spigot-parent + org.github.paperspigot + paperspigot-parent dev-SNAPSHOT pom - Spigot-Parent - Parent project for all Spigot modules. - https://github.com/SpigotMC/Spigot + PaperSpigot-Parent + Parent project for all PaperSpigot modules. + https://github.com/PaperSpigot/Spigot MinecraftServer MinecraftRelocate - Spigot-Server - Spigot-API + PaperSpigot-Server + PaperSpigot-API diff --git a/rebuildPatches.sh b/rebuildPatches.sh index 6785d242e8..bc6ae302d4 100755 --- a/rebuildPatches.sh +++ b/rebuildPatches.sh @@ -36,3 +36,5 @@ function savePatches { savePatches Bukkit Spigot-API savePatches CraftBukkit Spigot-Server +savePatches Spigot-API PaperSpigot-API +savePatches Spigot-Server PaperSpigot-Server