From 1362f49b24f39b3cb2cc9221c16418f290e7db51 Mon Sep 17 00:00:00 2001 From: BillyGalbreath Date: Sun, 21 Mar 2021 21:35:08 -0500 Subject: [PATCH] Updated Upstream (Paper, Tuinity, & Airplane) Upstream has released updates that appear to apply and compile correctly Paper Changes: bca97a8f7 replace spaces in world key (touches #5397) de94f6485 Refactor chat message composition (#5396) e27f334bb [CI-SKIP] Fix makemcdevsrc.sh for nms relocations (#5389) ae15e85da Updated Upstream (CraftBukkit) 26fe0ac5a Only set despawnTimer for Wandering Traders spawned by MobSpawnerTrader (#5391) b748eb7b8 Fix VanillaMobGoalTest#testBukkitMap (#5390) 18dbbb578 [Auto] Updated Upstream (CraftBukkit) fac9cc5d5 [CI-SKIP] Ignore .gitignore 087aa70e7 Deprecate ItemStack#setLore(List) and ItemStack#getLore, add Component based alternatives 9889c651c apply fixup c310f0a61 Updated Upstream (Bukkit/CraftBukkit) f17560ab0 wtf is this t file -jmp 347f3a9b8 fix compile 700e9e6a5 rebase cf4dc464a Revert de5f4e469...c270abe96 6870db613 script & POM fix 743c6533c Replace ** with * (BSD/macOS) 376d7b097 Don't remove the .java fcb3fd42a Fix macOS/BSD support 8cfc05249 Link correctly ba1031ca7 Rename work dir c8d844ab7 Actually fix preloading this time e62aa5e3e Fix class preloading 1c03cf898 It's mojang math, not minecraft math 1034873df Apply fixups 39b125771 Use revision file 956150da7 Welcome to 1.16.5-R0.2 ccb217c01 Change cache keys 0d217001c more work f6d820f07 It compiles 0f78e9525 More work 1718f61bf Updated Upstream (CraftBukkit/Spigot) b28d46114 Update scripts for NMS repackaging Tuinity Changes: 9bdcb9b8e Delete work dir when running jar 6351d7ca7 Update Upstream (Paper) 932c199a6 Generate md-dev correctly bf3e73778 Make packet limiter work from IDE 1686f3861 Fix packet limiter config f40f7b425 Update README.md styling (#264) da1c3ace5 GH Actions Changes (#213) 5f325ecf1 Update Upstream (Paper) 0f83fe48d Update Upstream (Paper) Airplane Changes: f94d39947 Merge pull request #18 from notOM3GA/upstream/nms-repackage 0fc622631 Force build for Flare update 08439d6a9 Update Upstream (Tuinity) --- .gitignore | 1 + Paper | 2 +- build.gradle.kts | 4 + mcdevimports.conf | 30 + patches/api/0001-Tuinity-API-Changes.patch | 166 +- patches/api/0002-Airplane-API-Changes.patch | 621 - .../api/0017-Player-invulnerabilities.patch | 8 +- .../0019-ItemStack-convenience-methods.patch | 4 +- ...0024-LivingEntity-broadcastItemBreak.patch | 4 +- patches/api/0025-Item-entity-immunities.patch | 6 +- ...oc-warnings-missing-param-and-return.patch | 35 +- ...on-change-for-adventure-deprecations.patch | 2 +- .../server/0001-Tuinity-Server-Changes.patch | 15387 ++++++++-------- .../server/0002-Airplane-Server-Changes.patch | 2603 +-- patches/server/0003-Rebrand.patch | 16 +- patches/server/0004-Purpur-config-files.patch | 43 +- .../0006-Barrels-and-enderchests-6-rows.patch | 110 +- patches/server/0007-Advancement-API.patch | 51 +- patches/server/0008-Llama-API.patch | 78 +- patches/server/0009-AFK-API.patch | 246 +- .../server/0010-Bring-back-server-name.patch | 12 +- .../0011-Configurable-server-mod-name.patch | 6 +- .../0012-LivingEntity-safeFallDistance.patch | 72 +- patches/server/0013-Lagging-threshold.patch | 10 +- .../0014-ItemFactory-getMonsterEgg.patch | 20 +- ...015-PlayerSetSpawnerTypeWithEggEvent.patch | 30 +- .../0016-EMC-MonsterEggSpawnEvent.patch | 19 +- .../0017-Player-invulnerabilities.patch | 42 +- patches/server/0018-Anvil-API.patch | 38 +- ...19-Configurable-villager-brain-ticks.patch | 14 +- .../0020-Alternative-Keepalive-Handling.patch | 26 +- patches/server/0021-Silk-touch-spawners.patch | 150 +- ...772-Fix-Add-turtle-egg-block-options.patch | 28 +- ...x-vanilla-command-permission-handler.patch | 4 +- ...-settings-suppressing-pointless-logs.patch | 8 +- .../0025-Disable-outdated-build-check.patch | 4 +- patches/server/0026-Giants-AI-settings.patch | 157 +- .../server/0027-Illusioners-AI-settings.patch | 12 +- .../0028-Zombie-horse-naturally-spawn.patch | 20 +- ...0029-Charged-creeper-naturally-spawn.patch | 37 +- ...bit-naturally-spawn-toast-and-killer.patch | 16 +- ...ver-showing-in-ping-before-server-fu.patch | 10 +- .../server/0032-Make-Iron-Golems-Swim.patch | 20 +- ...033-Dont-send-useless-entity-packets.patch | 56 +- .../server/0034-Tulips-change-fox-type.patch | 37 +- .../server/0035-Breedable-Polar-Bears.patch | 40 +- .../server/0036-Chickens-can-retaliate.patch | 27 +- ...option-to-set-armorstand-step-height.patch | 12 +- .../server/0038-Cat-spawning-options.patch | 94 +- ...on-black-cats-spawning-in-swamp-huts.patch | 10 +- patches/server/0040-Cows-eat-mushrooms.patch | 66 +- ...cow-rotation-when-shearing-mooshroom.patch | 10 +- .../server/0042-Pigs-give-saddle-back.patch | 12 +- ...43-Snowman-drop-and-put-back-pumpkin.patch | 14 +- ...44-Ender-dragon-always-drop-full-exp.patch | 12 +- .../0045-Signs-editable-on-right-click.patch | 30 +- .../server/0046-Signs-allow-color-codes.patch | 38 +- ...moisten-from-water-directly-under-it.patch | 12 +- .../server/0048-Controllable-Minecarts.patch | 122 +- ...able-loot-drops-on-death-by-cramming.patch | 12 +- ...050-Players-should-not-cram-to-death.patch | 10 +- ...ption-to-toggle-milk-curing-bad-omen.patch | 21 +- ...hould-check-if-entity-can-use-portal.patch | 10 +- ...0053-Fix-the-dead-lagging-the-server.patch | 20 +- ...-Skip-events-if-there-s-no-listeners.patch | 12 +- .../0055-Add-permission-for-F3-N-debug.patch | 10 +- ...-skeleton-takes-wither-damage-option.patch | 12 +- .../0057-Configurable-TPS-Catchup.patch | 6 +- ...low-loyalty-on-tridents-to-work-in-t.patch | 12 +- ...derman-and-creeper-griefing-controls.patch | 26 +- ...up-loot-bypass-mob-griefing-gamerule.patch | 12 +- ...ing-can-bypass-mob-griefing-gamerule.patch | 12 +- ...0062-Villagers-follow-emerald-blocks.patch | 62 +- .../0063-Allow-leashing-villagers.patch | 40 +- ...urable-search-radius-for-villagers-t.patch | 12 +- .../server/0065-Implement-infinite-lava.patch | 24 +- ...66-Make-lava-flow-speed-configurable.patch | 12 +- ...Add-player-death-exp-control-options.patch | 14 +- .../0068-Add-canSaveToDisk-to-Entity.patch | 34 +- ...0069-Configurable-void-damage-height.patch | 12 +- ...ispenser-curse-of-binding-protection.patch | 32 +- ...n-for-boats-to-eject-players-on-land.patch | 12 +- .../0072-Add-obfhelpers-for-plugin-use.patch | 10 +- ...g-mends-most-damages-equipment-first.patch | 86 +- ...0074-Add-5-second-tps-average-in-tps.patch | 10 +- .../0075-Implement-elytra-settings.patch | 52 +- .../server/0076-Item-entity-immunities.patch | 113 +- patches/server/0077-Add-ping-command.patch | 70 +- .../0078-Configurable-jockey-options.patch | 60 +- ...ed-to-crystals-and-crystals-shoot-ph.patch | 85 +- .../0080-Add-phantom-spawning-options.patch | 115 +- ...0081-Implement-bed-explosion-options.patch | 26 +- ...ent-respawn-anchor-explosion-options.patch | 14 +- ...-Add-allow-water-in-end-world-option.patch | 78 +- .../0084-Allow-color-codes-in-books.patch | 14 +- patches/server/0085-Entity-lifespan.patch | 48 +- ...leport-to-spawn-if-outside-world-bor.patch | 44 +- patches/server/0087-Squid-EAR-immunity.patch | 16 +- .../0088-Configurable-end-spike-seed.patch | 16 +- .../0089-Configurable-dungeon-seed.patch | 14 +- .../server/0090-Phantoms-burn-in-light.patch | 46 +- .../0091-Configurable-villager-breeding.patch | 12 +- .../0092-Redstone-deactivates-spawners.patch | 14 +- .../0093-Totems-work-in-inventory.patch | 12 +- .../server/0094-Populator-seed-controls.patch | 28 +- ...5-Add-vindicator-johnny-spawn-chance.patch | 20 +- ...on-to-disable-mushroom-block-updates.patch | 14 +- .../0097-Dispensers-place-anvils-option.patch | 34 +- patches/server/0098-Allow-anvil-colors.patch | 14 +- .../server/0099-Add-no-tick-block-list.patch | 46 +- ...o-disable-dolphin-treasure-searching.patch | 12 +- .../server/0101-Short-enderman-height.patch | 48 +- ...Stop-squids-floating-on-top-of-water.patch | 30 +- patches/server/0103-Ridables.patch | 7008 +++---- ...d-height-for-nether-surface-builders.patch | 10 +- ...ing-obsidian-valid-for-portal-frames.patch | 36 +- ...tities-can-use-portals-configuration.patch | 14 +- ...0107-LivingEntity-broadcastItemBreak.patch | 4 +- ...stomizable-wither-health-and-healing.patch | 16 +- ...ggling-special-MobSpawners-per-world.patch | 136 +- .../server/0110-Raid-cooldown-setting.patch | 16 +- ...e-config-options-per-projectile-type.patch | 156 +- ...sable-zombie-aggressiveness-towards-.patch | 26 +- ...tent-TileEntity-Lore-and-DisplayName.patch | 135 +- ...e-to-recipe-s-ExactChoice-ingredient.patch | 16 +- patches/server/0115-Flying-squids-Oh-my.patch | 16 +- .../server/0116-Infinity-bow-settings.patch | 14 +- patches/server/0117-Stonecutter-damage.patch | 32 +- .../0118-Configurable-daylight-cycle.patch | 36 +- ...te-and-mending-enchantments-together.patch | 14 +- .../server/0120-Infinite-fuel-furnace.patch | 30 +- ...ows-should-not-reset-despawn-counter.patch | 10 +- ...22-Add-tablist-suffix-option-for-afk.patch | 14 +- ...re-add-farmland-mechanics-from-Alpha.patch | 12 +- ...justable-breeding-cooldown-to-config.patch | 48 +- ...e-entity-breeding-times-configurable.patch | 464 +- ...mes-from-item-forms-of-entities-to-e.patch | 112 +- ...-when-using-a-Name-Tag-on-an-Armor-S.patch | 20 +- ...sting-and-weeping-vines-growth-rates.patch | 66 +- ...-twisting-vines-configurable-max-gro.patch | 46 +- ...llowing-Endermen-to-despawn-even-whi.patch | 12 +- ...-check-to-EntityDamagedByEntityEvent.patch | 18 +- ...132-Add-configurable-snowball-damage.patch | 12 +- ...break-door-minimum-difficulty-option.patch | 38 +- patches/server/0134-Add-demo-command.patch | 38 +- patches/server/0135-Left-handed-API.patch | 2 +- ...mi-Fix-ProtocolLib-issues-on-Java-15.patch | 18 +- ...37-Changeable-Mob-Left-Handed-Chance.patch | 12 +- .../0138-Add-boat-fall-damage-config.patch | 20 +- ...-disable-saving-projectiles-to-disk-.patch | 16 +- .../0140-Snow-Golem-rate-of-fire-config.patch | 12 +- ...g-option-for-Piglins-guarding-chests.patch | 12 +- ...C-Configurable-disable-give-dropping.patch | 20 +- ...-climbing-should-not-bypass-cramming.patch | 6 +- .../0144-Lobotomize-stuck-villagers.patch | 60 +- ...Villager-Clerics-to-farm-Nether-Wart.patch | 196 +- ...fied-Piglin-death-always-counting-as.patch | 14 +- ...d-out-and-optimise-player-list-ticks.patch | 16 +- ...ble-chance-for-wolves-to-spawn-rabid.patch | 135 +- ...nfigurable-default-wolf-collar-color.patch | 24 +- ...-Configurable-entity-base-attributes.patch | 1492 +- .../server/0151-Phantom-flames-on-swoop.patch | 12 +- ...s-to-open-even-with-a-solid-block-on.patch | 12 +- patches/server/0153-Implement-TPSBar.patch | 34 +- .../0154-Striders-give-saddle-back.patch | 12 +- .../server/0155-PlayerBookTooLargeEvent.patch | 14 +- ...therite-armor-grants-fire-resistance.patch | 12 +- ...0157-Fix-rotating-UP-DOWN-CW-and-CCW.patch | 12 +- patches/server/0158-Add-MC-4-fix-back.patch | 10 +- ...iefing-bypass-to-everything-affected.patch | 552 +- ...allow-Note-Block-sounds-when-blocked.patch | 12 +- ...0161-Add-EntityTeleportHinderedEvent.patch | 66 +- .../0162-Add-StructureGenerateEvent.patch | 30 +- .../0163-Farmland-trampling-changes.patch | 30 +- ...4-Movement-options-for-armor-stands.patch} | 38 +- .../server/0165-Fix-stuck-in-portals.patch | 36 +- ...yerEditBookEvent-not-saving-new-book.patch | 10 +- ...-to-use-infinity-bows-without-arrows.patch | 12 +- ...oggle-for-water-sensitive-mob-damage.patch | 94 +- ...69-Config-to-always-tame-in-Creative.patch | 90 +- .../0170-End-crystal-explosion-options.patch | 14 +- ...-Add-unsafe-Entity-serialization-API.patch | 26 +- ...0172-Add-ghast-allow-griefing-option.patch | 24 +- ...ither-Ender-Dragon-can-ride-vehicles.patch | 32 +- .../server/0174-Dont-run-with-scissors.patch | 14 +- patches/server/0175-One-Punch-Man.patch | 22 +- ...0176-Add-config-for-snow-on-blue-ice.patch | 12 +- ...er-Pearl-cooldown-damage-and-Endermi.patch | 28 +- ...-to-ignore-nearby-mobs-when-sleeping.patch | 12 +- ...Enderman-to-aggro-spawned-Endermites.patch | 12 +- ...-Dragon-Head-wearers-and-stare-aggro.patch | 20 +- patches/server/0182-Tick-fluids-config.patch | 16 +- ...183-Config-to-disable-Llama-caravans.patch | 38 +- ...ig-to-make-Creepers-explode-on-death.patch | 26 +- ...urable-ravager-griefable-blocks-list.patch | 38 +- 195 files changed, 17670 insertions(+), 16826 deletions(-) create mode 100644 mcdevimports.conf rename patches/server/{0164-Movement-options-for-armour-stands.patch => 0164-Movement-options-for-armor-stands.patch} (67%) diff --git a/.gitignore b/.gitignore index e42963b87..bc78dbb57 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,4 @@ mc-dev purpurclip.jar *clip.jar last-paper +mcdevimports.conf diff --git a/Paper b/Paper index d4532f7e7..bca97a8f7 160000 --- a/Paper +++ b/Paper @@ -1 +1 @@ -Subproject commit d4532f7e703e23794f12fd48b6d8cd962160e026 +Subproject commit bca97a8f73eae65baca98f65e045f890f6f8b5e1 diff --git a/build.gradle.kts b/build.gradle.kts index efdcb2a97..41b2351b9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -52,3 +52,7 @@ subprojects { credentials(PasswordCredentials::class) } } + +tasks.withType { + applyCommand("am", "--no-3way", "--ignore-whitespace", "--reject", "-C0") +} diff --git a/mcdevimports.conf b/mcdevimports.conf new file mode 100644 index 000000000..5f4f6627c --- /dev/null +++ b/mcdevimports.conf @@ -0,0 +1,30 @@ +# Extra mc-dev imports. Configure extra sources to import from NMS or decompiled libraries. + +# Example library-imports +# +# library-imports=[ +# { +# file=Bicontravariant +# group="com.mojang" +# library=datafixerupper +# prefix="com/mojang/datafixers/optics/profunctors" +# }, +# { +# file=CommandSyntaxException +# group="com.mojang" +# library=brigadier +# prefix="com/mojang/brigadier/exceptions" +# } +# ] +library-imports=[] +# Example nms-imports +# +# nms-imports=[ +# "com.mojang.math.Quaternion", +# "net.minecraft.network.syncher.DataWatcherRegistry", +# "net.minecraft.network.chat.IChatMutableComponent", +# "net.minecraft.network.protocol.game.PacketPlayOutAdvancements", +# "net.minecraft.world.entity.ai.goal.PathfinderGoalFishSchool", +# "net.minecraft.world.level.levelgen.feature.WorldGenFlowers" +# ] +nms-imports=[] diff --git a/patches/api/0001-Tuinity-API-Changes.patch b/patches/api/0001-Tuinity-API-Changes.patch index 828a0f1a2..5b80b2312 100644 --- a/patches/api/0001-Tuinity-API-Changes.patch +++ b/patches/api/0001-Tuinity-API-Changes.patch @@ -3,173 +3,9 @@ From: Spottedleaf Date: Fri, 14 Dec 2018 21:52:29 -0800 Subject: [PATCH] Tuinity API Changes - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/pom.xml b/pom.xml -index bba9d7a8a61018f2fc8b9059ad012d43810599dc..feaa36dc9a113c5b0c45eed2c3b8a3d10e8b4ca7 100644 +index e66661eb84308dc13faa0d39b7487f40c1180443..6c200882954adc4831307f3d6dfa3202571fb30b 100644 --- a/pom.xml +++ b/pom.xml @@ -3,18 +3,18 @@ diff --git a/patches/api/0002-Airplane-API-Changes.patch b/patches/api/0002-Airplane-API-Changes.patch index d91ba77c5..af5683261 100644 --- a/patches/api/0002-Airplane-API-Changes.patch +++ b/patches/api/0002-Airplane-API-Changes.patch @@ -3,627 +3,6 @@ From: Paul Sauve Date: Sat, 19 Dec 2020 19:06:37 -0600 Subject: [PATCH] Airplane API Changes - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java index 7760be3e34fa20825faf145d9fb5b2855c1a4602..79d839034d38c941745c6b91f973f908d6cdb8ee 100644 diff --git a/patches/api/0017-Player-invulnerabilities.patch b/patches/api/0017-Player-invulnerabilities.patch index fff7ce12d..f47925a57 100644 --- a/patches/api/0017-Player-invulnerabilities.patch +++ b/patches/api/0017-Player-invulnerabilities.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Player invulnerabilities diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 023ca23e8c91a6525cc31d483d873dfe14e97da3..88bda8c25ad746ccc584c7d490bd3257a74a6a20 100644 +index 023ca23e8c91a6525cc31d483d873dfe14e97da3..3dd208c763a71f4211b89a32a936a2317555f265 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -2136,5 +2136,26 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM @@ -15,21 +15,21 @@ index 023ca23e8c91a6525cc31d483d873dfe14e97da3..88bda8c25ad746ccc584c7d490bd3257 + + /** + * Check if player is invulnerable from recently spawning or accepting a resource pack -+ * ++ * + * @return True if invulnerable + */ + boolean isSpawnInvulnerable(); + + /** + * Get invulnerable ticks remaining -+ * ++ * + * @return Invulnerable ticks + */ + int getSpawnInvulnerableTicks(); + + /** + * Set invulnerable ticks remaining -+ * ++ * + * @param invulnerableTicks Invulnerable ticks remaining + */ + void setSpawnInvulnerableTicks(int invulnerableTicks); diff --git a/patches/api/0019-ItemStack-convenience-methods.patch b/patches/api/0019-ItemStack-convenience-methods.patch index be6440b5e..cab25ff27 100644 --- a/patches/api/0019-ItemStack-convenience-methods.patch +++ b/patches/api/0019-ItemStack-convenience-methods.patch @@ -46,7 +46,7 @@ index 0a31a5321ac519568db936c94394f71b2e2fcec1..42a77a5f5b8968351a737cb1fd7cebf1 + // Purpur end } diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index 878f09d5e587bc4bd70443fbdb89dac29e5a538d..f0c17f1342d9c70cb4fe1fc46dd8b9006037e860 100644 +index 58f99e3ebac9a01ebffe4d208e16cbee474d4aa3..314658c7dac1b1fbb440ec85133e6670e52ba684 100644 --- a/src/main/java/org/bukkit/inventory/ItemStack.java +++ b/src/main/java/org/bukkit/inventory/ItemStack.java @@ -17,6 +17,18 @@ import org.bukkit.inventory.meta.ItemMeta; @@ -68,7 +68,7 @@ index 878f09d5e587bc4bd70443fbdb89dac29e5a538d..f0c17f1342d9c70cb4fe1fc46dd8b900 /** * Represents a stack of items. -@@ -810,4 +822,627 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor +@@ -843,4 +855,627 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor return itemMeta != null && itemMeta.hasItemFlag(flag); } // Paper end diff --git a/patches/api/0024-LivingEntity-broadcastItemBreak.patch b/patches/api/0024-LivingEntity-broadcastItemBreak.patch index f95146228..0a327c0a0 100644 --- a/patches/api/0024-LivingEntity-broadcastItemBreak.patch +++ b/patches/api/0024-LivingEntity-broadcastItemBreak.patch @@ -5,7 +5,7 @@ Subject: [PATCH] LivingEntity#broadcastItemBreak diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 4ccbb3ef3c597ef9da2c6744f410283a1dc2538c..50c26609aadf8d4a51cd81cc0c8952e4cfeee738 100644 +index 4ccbb3ef3c597ef9da2c6744f410283a1dc2538c..42811d18ff304082f74f45794344891208599c04 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java @@ -865,5 +865,12 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource @@ -15,7 +15,7 @@ index 4ccbb3ef3c597ef9da2c6744f410283a1dc2538c..50c26609aadf8d4a51cd81cc0c8952e4 + + /** + * Play item break animation for the item in specified equipment slot -+ * ++ * + * @param slot Equipment slot to play break animation for + */ + void broadcastItemBreak(@NotNull org.bukkit.inventory.EquipmentSlot slot); diff --git a/patches/api/0025-Item-entity-immunities.patch b/patches/api/0025-Item-entity-immunities.patch index 852ef6388..7356fb0bc 100644 --- a/patches/api/0025-Item-entity-immunities.patch +++ b/patches/api/0025-Item-entity-immunities.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Item entity immunities diff --git a/src/main/java/org/bukkit/entity/Item.java b/src/main/java/org/bukkit/entity/Item.java -index 0ee072645ecf1bf5feb74de6960947ef76db366e..cf3eb7a57e28a76c40e5efa192204766fc037bf5 100644 +index 0ee072645ecf1bf5feb74de6960947ef76db366e..69dae9157053c521a9e2bbdd7f89c17fc8d24840 100644 --- a/src/main/java/org/bukkit/entity/Item.java +++ b/src/main/java/org/bukkit/entity/Item.java @@ -120,4 +120,48 @@ public interface Item extends Entity { @@ -30,7 +30,7 @@ index 0ee072645ecf1bf5feb74de6960947ef76db366e..cf3eb7a57e28a76c40e5efa192204766 + + /** + * Set whether or not this item is immune to explosions -+ * ++ * + * @param immuneToExplosion True to make immune to explosions + */ + void setImmuneToExplosion(boolean immuneToExplosion); @@ -51,7 +51,7 @@ index 0ee072645ecf1bf5feb74de6960947ef76db366e..cf3eb7a57e28a76c40e5efa192204766 + + /** + * Check if item is immune to fire -+ * ++ * + * @return True if immune to fire + */ + boolean isImmuneToFire(); diff --git a/patches/api/0033-Fix-javadoc-warnings-missing-param-and-return.patch b/patches/api/0033-Fix-javadoc-warnings-missing-param-and-return.patch index 137c20d79..a21f11cdc 100644 --- a/patches/api/0033-Fix-javadoc-warnings-missing-param-and-return.patch +++ b/patches/api/0033-Fix-javadoc-warnings-missing-param-and-return.patch @@ -419,6 +419,37 @@ index 5bb677ce585b856b3d3e589e29786a29619c56a7..613f00fa387dcc5af3191e550dea9d4d public class CachedSizeConcurrentLinkedQueue extends ConcurrentLinkedQueue { private final LongAdder cachedSize = new LongAdder(); +diff --git a/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java b/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java +index a0f748957f4472103dd27fc95a711a42de7fae89..c66b49f05be7a9cc26ba595829d7751d38aebeb1 100644 +--- a/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java ++++ b/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java +@@ -19,6 +19,11 @@ public final class AsyncChatEvent extends AbstractChatEvent { + } + + /** ++ * @param async Async ++ * @param player Player ++ * @param recipients Recipients ++ * @param formatter Formatter ++ * @param message Message + * @deprecated use {@link #AsyncChatEvent(boolean, Player, Set, ChatComposer, Component)} + */ + @Deprecated +diff --git a/src/main/java/io/papermc/paper/event/player/ChatEvent.java b/src/main/java/io/papermc/paper/event/player/ChatEvent.java +index 13c5df5fb8ce1d0203d99e88dd691019146a8f52..558d6531e9c06e25369074932fd9f0ab00e9e2c8 100644 +--- a/src/main/java/io/papermc/paper/event/player/ChatEvent.java ++++ b/src/main/java/io/papermc/paper/event/player/ChatEvent.java +@@ -24,6 +24,10 @@ public final class ChatEvent extends AbstractChatEvent { + } + + /** ++ * @param player Player ++ * @param recipients Recipients ++ * @param formatter Formatter ++ * @param message Message + * @deprecated use {@link #ChatEvent(Player, Set, ChatComposer, Component)} + */ + @Deprecated diff --git a/src/main/java/io/papermc/paper/inventory/ItemRarity.java b/src/main/java/io/papermc/paper/inventory/ItemRarity.java index 74ef8395cc040ce488c2acaa416db20272cc2734..b974627a415cd6897b245275e953cc907a5929d8 100644 --- a/src/main/java/io/papermc/paper/inventory/ItemRarity.java @@ -566,7 +597,7 @@ index afb7b136b461202026290624836446cff9f9e45d..087579fdff09237409c9f80446e7a15a /** diff --git a/src/main/java/org/bukkit/WorldCreator.java b/src/main/java/org/bukkit/WorldCreator.java -index 1d93a6c42d6c93ffd50c6054e74f3ff75d745b58..0dc013530b39618a7282a094b0bdb4c024f23712 100644 +index e6a83252f42da31ad38f8dc1beccc7aa2c3f54b8..f3b107210473f1707b051c15771ce3bf2a62f171 100644 --- a/src/main/java/org/bukkit/WorldCreator.java +++ b/src/main/java/org/bukkit/WorldCreator.java @@ -71,6 +71,8 @@ public class WorldCreator { @@ -963,7 +994,7 @@ index a6a7429ed2e1eefb2b12b7480ed74fcc3963a864..e8027e1d505dda6effbb1698550016e8 NORMAL(false), diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 88bda8c25ad746ccc584c7d490bd3257a74a6a20..1f667efd4b9bf00c0be8707849a6927483aef7ca 100644 +index 3dd208c763a71f4211b89a32a936a2317555f265..2ed61f79fc7a625d00b86ee434d591232518ca3c 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -1938,6 +1938,8 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM diff --git a/patches/api/0039-Conflict-on-change-for-adventure-deprecations.patch b/patches/api/0039-Conflict-on-change-for-adventure-deprecations.patch index 1d88fa9bb..81563c3e9 100644 --- a/patches/api/0039-Conflict-on-change-for-adventure-deprecations.patch +++ b/patches/api/0039-Conflict-on-change-for-adventure-deprecations.patch @@ -170,7 +170,7 @@ index 6ea9b54d95d80070c01a612c0ce2ab37f0b4ad41..fe9ec9cb7875df4a40d1c4155e13cca9 /** diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 1f667efd4b9bf00c0be8707849a6927483aef7ca..3821db949b890434857cbc8469f9416056f01093 100644 +index 2ed61f79fc7a625d00b86ee434d591232518ca3c..c0b75477ab8af71e73b37a66568693a84c5bce74 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -72,7 +72,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM diff --git a/patches/server/0001-Tuinity-Server-Changes.patch b/patches/server/0001-Tuinity-Server-Changes.patch index e508b65dc..5aab428ad 100644 --- a/patches/server/0001-Tuinity-Server-Changes.patch +++ b/patches/server/0001-Tuinity-Server-Changes.patch @@ -3,173 +3,590 @@ From: Spottedleaf Date: Fri, 14 Dec 2018 21:53:58 -0800 Subject: [PATCH] Tuinity Server Changes - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 +Brand changes - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. +MC-Dev fixes - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. +Util patch - 0. Additional Definitions. +Tuinity Server Config - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. +Multi-Threaded Server Ticking Vanilla - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. +This patch is the vanilla server changes - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. +Currently a placeholder patch. - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". +Multi-Threaded ticking CraftBukkit - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. +These are the changes to CB - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. +Currently a placeholder patch. - 1. Exception to Section 3 of the GNU GPL. +Add soft async catcher - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. +Must be enabled via -Dtuinity.strict-thread-checks=true - 2. Conveying Modified Versions. +Delay chunk unloads - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: +Chunk unloads are now delayed by 1s. Specifically, ticket level +reduction is delayed by 1s. This is done to allow players to +teleport and have their pets follow them, as the chunks will no longer +unload or have entity ticking status removed. - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or +It's also targetted to reduce performance regressions when +plugins or edge cases in code do not spam sync loads since chunks +without tickets get unloaded immediately. - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. +Configurable under `delay-chunkunloads-by` in config. - 3. Object Code Incorporating Material from Library Header Files. +This patch replaces the paper patch as the paper patch only +affects player loaded chunks, when we want to target all +loads. - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: +Attempt to recalculate regionfile header if it is corrupt - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. +Instead of trying to relocate the chunk, which is seems to never +be the correct choice, so we end up duplicating or swapping chunks, +we instead drop the current regionfile header and recalculate - +hoping that at least then we don't swap chunks, and maybe recover +them all. - b) Accompany the object code with a copy of the GNU GPL and this license - document. +Lag compensate block breaking - 4. Combined Works. +Use time instead of ticks if ticks fall behind - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: +Update version fetcher repo - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. +Sets the target github repo to Tuinity in the version checker. Also disables the jenkins build lookups. - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. +This patch is licensed under the MIT license. See /licenses/MIT.md. - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. +Per World Spawn Limits - d) Do one of the following: +This patch is licensed under the MIT license. See /licenses/MIT.md. - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. +Detail more information in watchdog dumps - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. +- Dump position, world, velocity, and uuid for currently ticking entities +- Dump player name, player uuid, position, and world for packet handling - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) +Execute chunk tasks mid-tick - 5. Combined Libraries. +This will help the server load chunks if tick times are high. - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: +Change writes to use NORMAL priority rather than LOW - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. +Should limit build up of I/O tasks, or at least properly +indicate to server owners that I/O is falling behind - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. +Allow controlled flushing for network manager - 6. Revised Versions of the GNU Lesser General Public License. +Only make one flush call when emptying the packet queue too - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. +This patch will be used to optimise out flush calls in later +patches. - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. +Consolidate flush calls for entity tracker packets - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. +Most server packets seem to be sent from here, so try to avoid +expensive flush calls from them. + +This change was motivated due to local testing: + +- My server spawn has 130 cows in it (for testing a prev. patch) +- Try to let 200 players join spawn + +Without this change, I could only get 20 players on before they +all started timing out due to the load put on the Netty I/O threads. + +With this change I could get all 200 on at 0ms ping. + +(one of the primary issues is that my CPU is kinda trash, and having +4 extra threads at 100% is just too much for it). + +So in general this patch should reduce Netty I/O thread load. + +Time scoreboard search + +Plugins leaking scoreboards will make this very expensive, +let server owners debug it easily + +Make CallbackExecutor strict again + +The correct fix for double scheduling is to avoid it. The reason +this class is used is because double scheduling causes issues +elsewhere, and it acts as an explicit detector of what double +schedules. Effectively, use the callback executor as a tool of +finding issues rather than hiding these issues. + +This patch also reverts incorrect use(s) of the class by paper. + +- getChunkFutureAsynchronously + There is no risk at all of recursion. The future is executed on + the chunk provider's thread queue, the same place general plugin + load callbacks are executed on. Forcing the task execution into + the callback executor also prevents the future from catching + any exception thrown from it. + +Optimise entity hard collision checking + +Very few entities actually hard collide, so store them in their own +entity slices and provide a special getEntites type call just for them. +This reduces entity collision checking impact (in my testing) by 25% +for crammed entities (shove 130 cows into an 8x6 area in one chunk). +Less crammed entities are likely to show significantly less benefit. +Effectively, this patch optimises crammed entity situations. + +Improved oversized chunk data packet handling + +Now target all TE data, except for TE's that do not have +update packets. + +This patch relies upon the improve extra packet handling +patch, as we now use PacketPlayOutMapChunk as an extra packet. +See its patch notes for further details. + +Reduce iterator allocation from chunk gen + +Replace via iterating over an array + +Prevent long map entry creation in light engine + +Use fastiterator to prevent it + +Highly optimise single and multi-AABB VoxelShapes and collisions + +Reduce allocation rate from crammed entities + +Optimise chunk tick iteration + +Use a dedicated list of entity ticking chunks to reduce the cost + +Use entity ticking chunk map for entity tracker + +Should bring us back in-line with tracker performance +before the loaded entity list reversion. + +Improve paper prevent moving into unloaded chunk check + +Check the AABB of the move + +Improve async tp to not load chunks when crossing worlds + +Fixes an issue where a getCubes call would load neighbouring chunks. +Loads less chunks than paper's implementation + +Revert getChunkAt(Async) retaining chunks for long periods of time + +Rework PlayerChunk main thread checks + +These need to fail instead of continuing, as hiding these errors +the way paper has is just going to allow unexpected reordering +of callbacks. + +For example, thanks to this patch incorrect future +completion (completion of the world gen future, +PlayerChunkMap#b(PlayerChunk, ChunkStatus)) was detected and fixed. + +Allow Entities to be removed from a world while ticking + +Fixes issues like disconnecting players while ticking them, or +issues where teleporting players across worlds while ticking. + +Also allows us to run mid tick while ticking entities. + +Prevent unload() calls removing tickets for sync loads + +Optimise collision checking in player move packet handling + +Move collision logic to just the hasNewCollision call instead of getCubes + hasNewCollision + +Manually inline methods in BlockPosition + +Separate lookup locking from state access in UserCache + +Prevent lookups from stalling simple state access/write calls + +Distance manager tick timings + +Recently this has been taking up more time, so add a timings to +really figure out how much. + +Name craft scheduler threads according to the plugin using them + +Provides quick access to culprits running far more threads than +they should be + +Fix swamp hut cat generation deadlock + +The worldgen thread will attempt to get structure references +via the world's getChunkAt method, which is fine if the gen is +not cancelled - but if the chunk was unloaded, the call will block +indefinitely. Instead of using the world state, we use the already +supplied generatoraccess which will always have the chunk available. + +Range check flag dirty calls in PlayerChunk + +Simply return. + +Optimise tab complete + +Some of the toLowerCase calls can be expensive. + +Do not allow ticket level changes while unloading playerchunks + +Sync loading the chunk at this stage would cause it to load +older data, as well as screwing our region state. + +Make sure inlined getChunkAt has inlined logic for loaded chunks + +Tux did some profiling some time ago and showed that the +previous getChunkAt method which had inlined logic for loaded +chunks did get inlined, but the standard CPS.getChunkAt +method was not inlined. + +Paper recently reverted this optimisation, so it's been reintroduced +here. + +Add packet limiter config + +Example config: +packet-limiter: + kick-message: '&cSent too many packets' + limits: + all: + interval: 7.0 + max-packet-rate: 500.0 + PacketPlayInAutoRecipe: + interval: 4.0 + max-packet-rate: 5.0 + action: DROP + +all section refers to all incoming packets, the action for all is +hard coded to KICK. + +For specific limits, the section name is the class's name, +and an action can be defined: DROP or KICK + +If interval or rate are less-than 0, the limit is ignored + +Optimise closest entity lookup + +Rewrites the entity slice storage so that entity by +class lookups look through less entities in total. + +Also optimise the nearest entity by class method +used by entity AI as well. + +As a sidenote, this entity slice implementation +removes the async catchers because it has been +designed to be MT-Safe for reads off of other +threads. + +Optimise nearby player lookups + +Use a distance map to map out close players. +Note that it's important that we cache the distance map value per chunk +since the penalty of a map lookup could outweigh the benefits of +searching less players (as it basically did in the outside range patch). + +Remove streams for villager AI + +Don't lookup fluid state when raytracing + +Just use the iblockdata already retrieved, removes a getType call. + +Reduce pathfinder branches + +Reduce static path type detection to simple lazy-init fields + +Add Velocity natives for encryption and compression + +This patch is licensed under the MIT license. See /licenses/MIT.md. + +Optimise non-flush packet sending + +Places like entity tracking make heavy use of packet sending, +and internally netty will use some very expensive thread wakeup +calls when scheduling. + +Thanks to various hacks in ProtocolLib as well as other +plugins, we cannot simply use a queue of packets to group +send on execute. We have to call execute for each packet. + +Tux's suggestion here is exactly what was needed - tag +the Runnable indicating it should not make a wakeup call. + +Big thanks to Tux for making this possible as I had given +up on this optimisation before he came along. + +Locally this patch drops the entity tracker tick by a full 1.5x. + +Do not retain playerchunkmap instance in light thread factory + +The executor returned is finalizable and of course +that causes issues. + +Do not load chunks during a crash report + +This causes deadlocks in some cases when generating +crash reports. + +Fixes https://github.com/Spottedleaf/Tuinity/issues/215 + +Improve abnormal server shutdown process + +- When we're trying to kill the main thread from watchdog, +step up the stop() spamming after 15s to really kill the main thread. + +- Do not wait for window disposing when disposing of the server +gui. It looks like during sigint shutdown there can be some +deadlock between the server thread and awt shutdown thread here. + +Copy passenger list in enderTeleportTo + +Fixes https://github.com/Spottedleaf/Tuinity/issues/208 + +Revert MC-4 fix + +When messing around with collisions, I ran into problems where +entity position was off by ULP and that caused clipping problems. +Now, the collision epsilon is 1.0e-7 to account for those errors. + +But this patch is going to cause problems on the order of 1.0e-4. + +I do not want to deal with clipping problems. The very fact it works +shows it's causing the clipping to occur serverside. + +Prevent light queue overfill when no players are online + +block changes don't queue light updates (and they shouldn't) + +Don't allow StructureLocateEvent to change worlds + +Callers and even the function itself aren't expecting +this to happen + +Properly handle cancellation of projectile hit event + +Subclasses override and run logic. Some of this logic destroys +the projectile as well, which wouldn't be fitting for cancellation. + +Rewrite the light engine + +The standard vanilla light engine is plagued by +awful performance. Paper's changes to the light engine +help a bit, however they appear to cause some lighting +errors - most easily noticed in coral generation. + +The vanilla light engine's is too abstract to be modified - +so an entirely new implementation is required to fix the +performance and lighting errors. + +The new implementation is designed primarily to optimise +light level propagations (increase and decrease). Unlike +the vanilla light engine, this implementation tracks more +information per queued value when performing a +breadth first search. Vanilla just tracks coordinate, which +means every time they handle a queued value, they must +also determine the coordinate's target light level +from its neighbours - very wasteful, especially considering +these checks read neighbour block data. +The new light engine tracks both position and target level, +as well as whether the target block needs to be read at all +(for checking sided propagation). So, the work done per coordinate +is significantly reduced because no work is done for calculating +the target level. +In my testing, the block get calls were reduced by approximately +an order of magnitude. However, the light read checks were only +reduced by approximately 2x - but this is fine, light read checks +are extremely cheap compared to block gets. + +Generation testing showed that the new light engine improved +total generation (not lighting itself, but the whole generation process) +by 2x. According to cpu time, the light engine itself spent 10x less time +lighting chunks for generation. + +Optimise WorldServer#notify + +Iterating over all of the navigators in the world is pretty expensive. +Instead, only iterate over navigators in the current region that are +eligible for repathing. + +Actually unload POI data + +While it's not likely for a poi data leak to be meaningful, +sometimes it is. + +This patch also prevents the saving/unloading of POI data when +world saving is disabled. + +Send full pos packets for hard colliding entities + +Prevent collision problems due to desync (i.e boats) + +Configurable under +`send-full-pos-for-hard-colliding-entities` + +Fix chunks refusing to unload at low TPS + +The full chunk future is appended to the chunk save future, but +when moving to unloaded ticket level it is not being completed with +the empty chunk access, so the chunk save must wait for the full +chunk future to complete. We can simply schedule to the immediate +executor to get this effect, rather than the main mailbox. + +Fix incorrect isRealPlayer init + +Some plugins, namely ProtocolSupport, don't route to where +paper placed their logic. So it wont correctly set in this case. + +Fix by moving it to a different place. + +Do not run raytrace logic for AIR + +Saves approx. 5% for the raytrace call, as most (expensive) +raytracing tends to go through air and returning early is an +easy win. The remaining problems with this function +are mostly with the block getting itself. + +Make entity tracker use highest range of passengers + +This should prevent people from having to up their animal range +just so players riding horses or whatever can be seen at the +configured player range. + +Do not allow the server to unload chunks at request of plugins + +In general the chunk system is not well suited for this behavior, +especially if it is called during a chunk load. The chunks pushed +to be unloaded will simply be unloaded next tick, rather than +immediately. + +Do not run close logic for inventories on chunk unload + +Still call the event and change the active container though. We +want to avoid close logic because it's possible to load the +chunk through it. This should also be OK from a leak prevention/ +state desync POV because the TE is getting unloaded anyways. + +Fix NPE in pickup logic for arrow + +Apparently the shooter can be null for tridents returning to players. + +Remove chunk lookup & lambda allocation from counting mobs + +The chunk lookup doesn't look cheap. + +Optimise snow & ice in chunk ticking + +Avoid the biome lookups most of the time by +hiding them behind the snow/air checks. The biome +checks take up the most here, followed by the block gets. +Soften some of the block gets by passing the chunk to +the biome methods, removing the need to invoke a chunk +lookup. + +Oprimise map impl for tracked players + +Reference2BooleanOpenHashMap is going to have +better lookups than HashMap. + +Use hash table for maintaing changed block set + +When a lot of block changes occur the iteration for checking can +add up a bit and cause a small performance impact. + +Replace player chunk loader system + +The old one has undebuggable problems. Rewriting seems +the most sensible option. + +This new player chunk manager will also strictly rate limit +chunk sends so that netty threads do not get overloaded, whether +it be from the anti-xray logic or the compression itself. + +Chunk loading is also rate limited in the same manner, so this +will result in a maximum responsiveness for change. + +Config: +``` +player-chunks: + autoconfig-send-distance: true + min-load-radius: 3 + max-concurrent-sends: 12.0 + max-concurrent-loads: 5.0 +``` + +autoconfig-send-distance - Whether to try to use the client's +view distance for the send view distance in the server. In the +case that no plugin has explicitly set the send distance and +the client view distance is less-than the server's send distance, +the client's view distance will be used. This will not affect +tick view distance or no-tick view distance. + +min-load-radius - The radius of chunks around a player that +are not throttled for loading. The number of chunks +affected is actually the configured value plus one as this +config controls the chunks the client will be able to render. + +max-concurrent-sends - The maximum number of chunks that +can be queued to send at any given time. Low values +are generally going to solve server-sided networking +bottlenecks like anti-xray and chunk compression. Client +side networking is unlikely to be helped (i.e this wont help +people running off McDonald's wifi). Setting this +value to negative will make the server dynamically scale it +with players. i.e -5 will use 5 * online players for the max sends. + +max-concurrent-loads - The maxmium number of chunks +that can be queued to be loaded at any given time. Lower +values help the responsitivity to player movement and +higher values help loading when the server is at a low TPS. + +Optimise general POI access + +There are a couple of problems with mojang's POI code. +Firstly, it's all streams. Unsurprisingly, stacking +streams on top of each other is horrible for performance +and ultimately took up half of a villager's tick! + +Secondly, sometime's the search radius is large and there are +a significant number of poi entries per chunk section. Even +removing streams at this point doesn't help much. The only solution +is to start at the search point and iterate outwards. This +type of approach shows massive gains for portals, simply because +we can avoid sync loading a large area of chunks. I also tested +a massive farm I found in JellySquid's discord, which showed +to benefit significantly simply because the farm had so many +portal blocks that searching through them all was very slow. + +Great care has been taken so that behavior remains identical to +vanilla, however I cannot account for oddball Stream API +implementations, if they even exist (streams can technically +be loose with iteration order in a sorted stream given its +source stream is not tagged with ordered, and mojang does not +tag the source stream as ordered). However in my testing on openjdk +there showed no difference, as expected. + +This patch also specifically optimises other areas of code to +use PoiAccess. For example, some villager AI and portaling code +had to be specifically modified. + +Be aware of entity teleports when chunk checking entities + +If an entity were to be teleported via the sync load +that occured from the getChunkAt call, we would either +add to the wrong chunk or add to both chunks! not good. + +Custom table implementation for blockstate state lookups + +Testing some redstone intensive machines showed to bring about a 10% +improvement. diff --git a/pom.xml b/pom.xml -index 11b4d56922cae5ba3f76c21a76a8ae40b3719afa..d9b46ca2fb2ec8f76f3c781d9250fdc68ad7e363 100644 +index 25ec9c4f8c08551fd80a597a1b39854e70e4f895..dad9981b1cd1ca8b27a45972188fd2b92f5146e7 100644 --- a/pom.xml +++ b/pom.xml @@ -1,11 +1,11 @@ @@ -266,10 +683,10 @@ index 11b4d56922cae5ba3f76c21a76a8ae40b3719afa..d9b46ca2fb2ec8f76f3c781d9250fdc6 diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java -index 884b59d478aa7de49906520e77866a7949bed19d..68ab5ccb2fcfe1de0503c9336572f28e11832b2d 100644 +index b4d43ceed368552e703886213327a0c0bb5ccb92..67980e1dc186c0b458eca9f00acfea7d2b26d575 100644 --- a/src/main/java/co/aikar/timings/MinecraftTimings.java +++ b/src/main/java/co/aikar/timings/MinecraftTimings.java -@@ -43,6 +43,9 @@ public final class MinecraftTimings { +@@ -46,6 +46,9 @@ public final class MinecraftTimings { public static final Timing antiXrayUpdateTimer = Timings.ofSafe("anti-xray - update"); public static final Timing antiXrayObfuscateTimer = Timings.ofSafe("anti-xray - obfuscate"); @@ -325,43 +742,23 @@ index dee00aac05f1acf050f05d4db557a08dd0f301c8..52c0ab1ce46e1f3233ef746d9bc69935 metrics.addCustomChart(new Metrics.DrilldownPie("java_version", () -> { Map> map = new HashMap<>(); diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 2f2701b9f0aa1a26a3e3eb7a14eac370f509ce1e..e5bd82016ace4d51608fca78ec771fec96bbce90 100644 +index 12313a37ceeb6a0b6a539c38fdba67e5e43d7413..848eb25ed0640db61a0f28bc26ddabd0444e9ed4 100644 --- a/src/main/java/com/destroystokyo/paper/PaperCommand.java +++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -15,9 +15,11 @@ import net.minecraft.server.BlockPosition; - import net.minecraft.server.Chunk; - import net.minecraft.server.ChunkCoordIntPair; - import net.minecraft.server.ChunkProviderServer; -+import net.minecraft.server.ChunkStatus; - import net.minecraft.server.Entity; - import net.minecraft.server.EntityPlayer; - import net.minecraft.server.EntityTypes; -+import net.minecraft.server.IChunkAccess; - import net.minecraft.server.LightEngineThreaded; - import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftKey; -@@ -54,6 +56,7 @@ import java.util.Collection; - import java.util.Collections; - import java.util.Deque; - import java.util.Iterator; -+import java.util.LinkedHashSet; - import java.util.List; - import java.util.Locale; - import java.util.Map; -@@ -219,6 +222,44 @@ public class PaperCommand extends Command { +@@ -219,6 +219,44 @@ public class PaperCommand extends Command { } } + private void starlightFixLight(EntityPlayer sender, WorldServer world, LightEngineThreaded lightengine, int radius) { + long start = System.nanoTime(); -+ LinkedHashSet chunks = new LinkedHashSet<>(MCUtil.getSpiralOutChunks(sender.getChunkCoordinates(), radius)); // getChunkCoordinates is actually just bad mappings, this function rets position as blockpos ++ java.util.LinkedHashSet chunks = new java.util.LinkedHashSet<>(MCUtil.getSpiralOutChunks(sender.getChunkCoordinates(), radius)); // getChunkCoordinates is actually just bad mappings, this function rets position as blockpos + + int[] pending = new int[1]; + for (java.util.Iterator iterator = chunks.iterator(); iterator.hasNext();) { + final ChunkCoordIntPair chunkPos = iterator.next(); + -+ final IChunkAccess chunk = world.getChunkProvider().getChunkAtImmediately(chunkPos.x, chunkPos.z); -+ if (chunk == null || !chunk.isLit() || !chunk.getChunkStatus().isAtLeastStatus(ChunkStatus.LIGHT)) { ++ final net.minecraft.world.level.chunk.IChunkAccess chunk = world.getChunkProvider().getChunkAtImmediately(chunkPos.x, chunkPos.z); ++ if (chunk == null || !chunk.isLit() || !chunk.getChunkStatus().isAtLeastStatus(net.minecraft.world.level.chunk.ChunkStatus.LIGHT)) { + // cannot relight this chunk + iterator.remove(); + continue; @@ -393,17 +790,17 @@ index 2f2701b9f0aa1a26a3e3eb7a14eac370f509ce1e..e5bd82016ace4d51608fca78ec771fec private void doFixLight(CommandSender sender, String[] args) { if (!(sender instanceof Player)) { sender.sendMessage("Only players can use this command"); -@@ -227,7 +268,7 @@ public class PaperCommand extends Command { +@@ -227,7 +265,7 @@ public class PaperCommand extends Command { int radius = 2; if (args.length > 1) { try { - radius = Math.min(5, Integer.parseInt(args[1])); -+ radius = Math.min(15, Integer.parseInt(args[1])); // Tuinity - MOOOOOORE ++ radius = Math.min(32, Integer.parseInt(args[1])); // Tuinity - MOOOOOORE } catch (Exception e) { sender.sendMessage("Not a number"); return; -@@ -240,6 +281,13 @@ public class PaperCommand extends Command { - net.minecraft.server.WorldServer world = (WorldServer) handle.world; +@@ -240,6 +278,13 @@ public class PaperCommand extends Command { + WorldServer world = (WorldServer) handle.world; LightEngineThreaded lightengine = world.getChunkProvider().getLightEngine(); + // Tuinity start - rewrite light engine @@ -448,7 +845,7 @@ index dc0ea65ab87255fad0d54dfb509300098a0b4864..7063f1da3654b382e26b0093ad5d0ff0 switch (distance) { case -1: diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java -index e7624948ea4aa1a07d84ed3d295cfe2dd354fd14..77df6888803093ad9527d276033f2ed767b39764 100644 +index 8918bad880d6eeed30db39b6326b2f65e24edf45..b870cca05f0ba354e6976a70511235636093d13c 100644 --- a/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java +++ b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java @@ -186,6 +186,7 @@ public final class PaperTickList extends TickListServer { // extend to avo @@ -462,7 +859,7 @@ index e7624948ea4aa1a07d84ed3d295cfe2dd354fd14..77df6888803093ad9527d276033f2ed7 @@ -268,6 +269,7 @@ public final class PaperTickList extends TickListServer { // extend to avo @Override - protected void nextTick() { + public void nextTick() { + com.tuinity.tuinity.util.TickThread.softEnsureTickThread("async tick list tick"); // Tuinity - soft async catcher ++this.currentTick; if (this.currentTick != this.world.getTime()) { @@ -615,7 +1012,7 @@ index 7720578796e28d28e8c0c9aa40155cd205c17d54..e5db29d4cadb5702c7d06b0b6e2d0558 return Suggestions.empty(); diff --git a/src/main/java/com/tuinity/tuinity/chunk/PlayerChunkLoader.java b/src/main/java/com/tuinity/tuinity/chunk/PlayerChunkLoader.java new file mode 100644 -index 0000000000000000000000000000000000000000..afdaa263dd4aa7bb5132b3bcd16ac23f0739c2b8 +index 0000000000000000000000000000000000000000..1fbd220b8a2c77ba85e98349b012b293ee7686a8 --- /dev/null +++ b/src/main/java/com/tuinity/tuinity/chunk/PlayerChunkLoader.java @@ -0,0 +1,955 @@ @@ -629,18 +1026,18 @@ index 0000000000000000000000000000000000000000..afdaa263dd4aa7bb5132b3bcd16ac23f +import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.Reference2ObjectLinkedOpenHashMap; +import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet; -+import net.minecraft.server.Chunk; -+import net.minecraft.server.ChunkCoordIntPair; -+import net.minecraft.server.EntityPlayer; ++import net.minecraft.network.protocol.game.PacketPlayOutViewCentre; ++import net.minecraft.network.protocol.game.PacketPlayOutViewDistance; ++import net.minecraft.server.level.EntityPlayer; ++import net.minecraft.world.level.ChunkCoordIntPair; ++import net.minecraft.world.level.chunk.Chunk; +import net.minecraft.server.MCUtil; -+import net.minecraft.server.MathHelper; ++import net.minecraft.util.MathHelper; +import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.Packet; -+import net.minecraft.server.PacketPlayOutViewCentre; -+import net.minecraft.server.PacketPlayOutViewDistance; -+import net.minecraft.server.PlayerChunk; -+import net.minecraft.server.PlayerChunkMap; -+import net.minecraft.server.TicketType; ++import net.minecraft.network.protocol.Packet; ++import net.minecraft.server.level.PlayerChunk; ++import net.minecraft.server.level.PlayerChunkMap; ++import net.minecraft.server.level.TicketType; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.List; @@ -1576,7 +1973,7 @@ index 0000000000000000000000000000000000000000..afdaa263dd4aa7bb5132b3bcd16ac23f +} diff --git a/src/main/java/com/tuinity/tuinity/chunk/SingleThreadChunkRegionManager.java b/src/main/java/com/tuinity/tuinity/chunk/SingleThreadChunkRegionManager.java new file mode 100644 -index 0000000000000000000000000000000000000000..6985b1df450a3b2b9e9c4696fef60652cb84fa2c +index 0000000000000000000000000000000000000000..5ea5b3933725d80dd193e815ac507ee51ee17630 --- /dev/null +++ b/src/main/java/com/tuinity/tuinity/chunk/SingleThreadChunkRegionManager.java @@ -0,0 +1,477 @@ @@ -1586,9 +1983,9 @@ index 0000000000000000000000000000000000000000..6985b1df450a3b2b9e9c4696fef60652 +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet; +import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; -+import net.minecraft.server.ChunkCoordIntPair; +import net.minecraft.server.MCUtil; -+import net.minecraft.server.WorldServer; ++import net.minecraft.server.level.WorldServer; ++import net.minecraft.world.level.ChunkCoordIntPair; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; @@ -2060,25 +2457,25 @@ index 0000000000000000000000000000000000000000..6985b1df450a3b2b9e9c4696fef60652 \ No newline at end of file diff --git a/src/main/java/com/tuinity/tuinity/chunk/light/BlockStarLightEngine.java b/src/main/java/com/tuinity/tuinity/chunk/light/BlockStarLightEngine.java new file mode 100644 -index 0000000000000000000000000000000000000000..43de95779a5472aaf04da11c9f4c5feb7253c6c3 +index 0000000000000000000000000000000000000000..2b939fabcc4cc45d697bfa2f3cda7fc64a4de8ca --- /dev/null +++ b/src/main/java/com/tuinity/tuinity/chunk/light/BlockStarLightEngine.java @@ -0,0 +1,277 @@ +package com.tuinity.tuinity.chunk.light; + -+import net.minecraft.server.BlockPosition; -+import net.minecraft.server.Chunk; -+import net.minecraft.server.ChunkSection; -+import net.minecraft.server.ChunkStatus; -+import net.minecraft.server.DataPaletteBlock; -+import net.minecraft.server.IBlockData; -+import net.minecraft.server.IChunkAccess; -+import net.minecraft.server.ILightAccess; -+import net.minecraft.server.ProtoChunkExtension; -+import net.minecraft.server.VoxelShape; -+import net.minecraft.server.VoxelShapes; -+import net.minecraft.server.World; -+import net.minecraft.server.WorldServer; ++import net.minecraft.core.BlockPosition; ++import net.minecraft.server.level.WorldServer; ++import net.minecraft.world.level.chunk.Chunk; ++import net.minecraft.world.level.chunk.ChunkSection; ++import net.minecraft.world.level.chunk.ChunkStatus; ++import net.minecraft.world.level.chunk.DataPaletteBlock; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.chunk.IChunkAccess; ++import net.minecraft.world.level.chunk.ILightAccess; ++import net.minecraft.world.level.chunk.ProtoChunkExtension; ++import net.minecraft.world.phys.shapes.VoxelShape; ++import net.minecraft.world.phys.shapes.VoxelShapes; ++import net.minecraft.world.level.World; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; @@ -2343,13 +2740,13 @@ index 0000000000000000000000000000000000000000..43de95779a5472aaf04da11c9f4c5feb +} diff --git a/src/main/java/com/tuinity/tuinity/chunk/light/SWMRNibbleArray.java b/src/main/java/com/tuinity/tuinity/chunk/light/SWMRNibbleArray.java new file mode 100644 -index 0000000000000000000000000000000000000000..051e2db5349b6f20887841efad7fbc183b190f68 +index 0000000000000000000000000000000000000000..81963ada0eafea91947f4437b22bcad47e4709ed --- /dev/null +++ b/src/main/java/com/tuinity/tuinity/chunk/light/SWMRNibbleArray.java @@ -0,0 +1,325 @@ +package com.tuinity.tuinity.chunk.light; + -+import net.minecraft.server.NibbleArray; ++import net.minecraft.world.level.chunk.NibbleArray; +import java.util.ArrayDeque; +import java.util.Arrays; + @@ -2674,7 +3071,7 @@ index 0000000000000000000000000000000000000000..051e2db5349b6f20887841efad7fbc18 +} diff --git a/src/main/java/com/tuinity/tuinity/chunk/light/SkyStarLightEngine.java b/src/main/java/com/tuinity/tuinity/chunk/light/SkyStarLightEngine.java new file mode 100644 -index 0000000000000000000000000000000000000000..26534e05ff5aac5a963906ba678411c843b132e3 +index 0000000000000000000000000000000000000000..86a880d0f13f0fee70b09626c394c9e25551e672 --- /dev/null +++ b/src/main/java/com/tuinity/tuinity/chunk/light/SkyStarLightEngine.java @@ -0,0 +1,706 @@ @@ -2683,17 +3080,17 @@ index 0000000000000000000000000000000000000000..26534e05ff5aac5a963906ba678411c8 +import com.tuinity.tuinity.util.WorldUtil; +import it.unimi.dsi.fastutil.shorts.ShortCollection; +import it.unimi.dsi.fastutil.shorts.ShortIterator; -+import net.minecraft.server.BlockPosition; -+import net.minecraft.server.ChunkCoordIntPair; -+import net.minecraft.server.ChunkSection; -+import net.minecraft.server.ChunkStatus; -+import net.minecraft.server.IBlockAccess; -+import net.minecraft.server.IBlockData; -+import net.minecraft.server.IChunkAccess; -+import net.minecraft.server.ILightAccess; -+import net.minecraft.server.VoxelShape; -+import net.minecraft.server.VoxelShapes; -+import net.minecraft.server.World; ++import net.minecraft.core.BlockPosition; ++import net.minecraft.world.level.ChunkCoordIntPair; ++import net.minecraft.world.level.chunk.ChunkSection; ++import net.minecraft.world.level.chunk.ChunkStatus; ++import net.minecraft.world.level.IBlockAccess; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.chunk.IChunkAccess; ++import net.minecraft.world.level.chunk.ILightAccess; ++import net.minecraft.world.phys.shapes.VoxelShape; ++import net.minecraft.world.phys.shapes.VoxelShapes; ++import net.minecraft.world.level.World; +import java.util.Arrays; +import java.util.Set; + @@ -3386,7 +3783,7 @@ index 0000000000000000000000000000000000000000..26534e05ff5aac5a963906ba678411c8 +} diff --git a/src/main/java/com/tuinity/tuinity/chunk/light/StarLightEngine.java b/src/main/java/com/tuinity/tuinity/chunk/light/StarLightEngine.java new file mode 100644 -index 0000000000000000000000000000000000000000..433c27813bbcddea09b21f7629a0bbce7a658082 +index 0000000000000000000000000000000000000000..e40cf190c945754bd8b5342f76cd7fe2efd127cb --- /dev/null +++ b/src/main/java/com/tuinity/tuinity/chunk/light/StarLightEngine.java @@ -0,0 +1,1615 @@ @@ -3398,21 +3795,21 @@ index 0000000000000000000000000000000000000000..433c27813bbcddea09b21f7629a0bbce +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.shorts.ShortCollection; +import it.unimi.dsi.fastutil.shorts.ShortIterator; -+import net.minecraft.server.BlockPosition; -+import net.minecraft.server.Blocks; -+import net.minecraft.server.ChunkCoordIntPair; -+import net.minecraft.server.ChunkSection; -+import net.minecraft.server.EnumDirection; -+import net.minecraft.server.EnumSkyBlock; -+import net.minecraft.server.IBlockAccess; -+import net.minecraft.server.IBlockData; -+import net.minecraft.server.IChunkAccess; -+import net.minecraft.server.ILightAccess; -+import net.minecraft.server.SectionPosition; -+import net.minecraft.server.VoxelShape; -+import net.minecraft.server.VoxelShapes; -+import net.minecraft.server.World; -+import net.minecraft.server.WorldServer; ++import net.minecraft.core.BlockPosition; ++import net.minecraft.server.level.WorldServer; ++import net.minecraft.world.level.ChunkCoordIntPair; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.chunk.ChunkSection; ++import net.minecraft.core.EnumDirection; ++import net.minecraft.world.level.EnumSkyBlock; ++import net.minecraft.world.level.IBlockAccess; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.chunk.IChunkAccess; ++import net.minecraft.world.level.chunk.ILightAccess; ++import net.minecraft.core.SectionPosition; ++import net.minecraft.world.phys.shapes.VoxelShape; ++import net.minecraft.world.phys.shapes.VoxelShapes; ++import net.minecraft.world.level.World; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; @@ -5007,7 +5404,7 @@ index 0000000000000000000000000000000000000000..433c27813bbcddea09b21f7629a0bbce +} diff --git a/src/main/java/com/tuinity/tuinity/chunk/light/StarLightInterface.java b/src/main/java/com/tuinity/tuinity/chunk/light/StarLightInterface.java new file mode 100644 -index 0000000000000000000000000000000000000000..0fddb331bfcee762da38efea3a36dc6394718519 +index 0000000000000000000000000000000000000000..df686b97460796004cad1477760647a98741d751 --- /dev/null +++ b/src/main/java/com/tuinity/tuinity/chunk/light/StarLightInterface.java @@ -0,0 +1,490 @@ @@ -5018,15 +5415,15 @@ index 0000000000000000000000000000000000000000..0fddb331bfcee762da38efea3a36dc63 +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.shorts.ShortCollection; -+import net.minecraft.server.BlockPosition; -+import net.minecraft.server.ChunkCoordIntPair; -+import net.minecraft.server.ChunkStatus; -+import net.minecraft.server.IChunkAccess; -+import net.minecraft.server.ILightAccess; -+import net.minecraft.server.LightEngineLayerEventListener; -+import net.minecraft.server.NibbleArray; -+import net.minecraft.server.SectionPosition; -+import net.minecraft.server.WorldServer; ++import net.minecraft.core.BlockPosition; ++import net.minecraft.server.level.WorldServer; ++import net.minecraft.world.level.ChunkCoordIntPair; ++import net.minecraft.world.level.chunk.ChunkStatus; ++import net.minecraft.world.level.chunk.IChunkAccess; ++import net.minecraft.world.level.chunk.ILightAccess; ++import net.minecraft.world.level.lighting.LightEngineLayerEventListener; ++import net.minecraft.world.level.chunk.NibbleArray; ++import net.minecraft.core.SectionPosition; +import java.util.ArrayDeque; +import java.util.HashSet; +import java.util.Iterator; @@ -5503,13 +5900,13 @@ index 0000000000000000000000000000000000000000..0fddb331bfcee762da38efea3a36dc63 +} diff --git a/src/main/java/com/tuinity/tuinity/chunk/light/VariableBlockLightHandler.java b/src/main/java/com/tuinity/tuinity/chunk/light/VariableBlockLightHandler.java new file mode 100644 -index 0000000000000000000000000000000000000000..b8a6c59ee3c919e47e4be76fc4e1737d81a5810b +index 0000000000000000000000000000000000000000..b8df658c09a6dc739ff3f4d6e18c9cef7caea6c9 --- /dev/null +++ b/src/main/java/com/tuinity/tuinity/chunk/light/VariableBlockLightHandler.java @@ -0,0 +1,30 @@ +package com.tuinity.tuinity.chunk.light; + -+import net.minecraft.server.BlockPosition; ++import net.minecraft.core.BlockPosition; +import java.util.Collection; + +/** @@ -5539,7 +5936,7 @@ index 0000000000000000000000000000000000000000..b8a6c59ee3c919e47e4be76fc4e1737d +} diff --git a/src/main/java/com/tuinity/tuinity/chunk/light/VariableBlockLightHandlerImpl.java b/src/main/java/com/tuinity/tuinity/chunk/light/VariableBlockLightHandlerImpl.java new file mode 100644 -index 0000000000000000000000000000000000000000..125f59826a9b0174039139ed0715a4ed3df3724b +index 0000000000000000000000000000000000000000..0e4442a94559346b19a536d35ce5def612074838 --- /dev/null +++ b/src/main/java/com/tuinity/tuinity/chunk/light/VariableBlockLightHandlerImpl.java @@ -0,0 +1,112 @@ @@ -5548,7 +5945,7 @@ index 0000000000000000000000000000000000000000..125f59826a9b0174039139ed0715a4ed +import com.tuinity.tuinity.util.CoordinateUtils; +import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -+import net.minecraft.server.BlockPosition; ++import net.minecraft.core.BlockPosition; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; @@ -5657,15 +6054,15 @@ index 0000000000000000000000000000000000000000..125f59826a9b0174039139ed0715a4ed +} diff --git a/src/main/java/com/tuinity/tuinity/config/TuinityConfig.java b/src/main/java/com/tuinity/tuinity/config/TuinityConfig.java new file mode 100644 -index 0000000000000000000000000000000000000000..d1308b8cbb9490f1ccdc5514763e62bc5d66981b +index 0000000000000000000000000000000000000000..d29b537bbe4f852162b720d6b23b741829af21f9 --- /dev/null +++ b/src/main/java/com/tuinity/tuinity/config/TuinityConfig.java -@@ -0,0 +1,406 @@ +@@ -0,0 +1,415 @@ +package com.tuinity.tuinity.config; + +import com.destroystokyo.paper.util.SneakyThrow; +import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.TicketType; ++import net.minecraft.server.level.TicketType; +import org.bukkit.Bukkit; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; @@ -5787,7 +6184,7 @@ index 0000000000000000000000000000000000000000..d1308b8cbb9490f1ccdc5514763e62bc + tickWorldsInParallel = TuinityConfig.getBoolean("tick-worlds-in-parallel", false); + tickThreads = TuinityConfig.getInt("server-tick-threads", 1); // will be 4 in the future + }*/ -+ ++ + public static int delayChunkUnloadsBy; + + private static void delayChunkUnloadsBy() { @@ -5821,7 +6218,7 @@ index 0000000000000000000000000000000000000000..d1308b8cbb9490f1ccdc5514763e62bc + + public static String kickMessage; + public static PacketLimit allPacketsLimit; -+ public static java.util.Map>, PacketLimit> packetSpecificLimits = new java.util.HashMap<>(); ++ public static java.util.Map>, PacketLimit> packetSpecificLimits = new java.util.HashMap<>(); + + private static void packetLimiter() { + packetSpecificLimits.clear(); @@ -5840,26 +6237,35 @@ index 0000000000000000000000000000000000000000..d1308b8cbb9490f1ccdc5514763e62bc + + // auto recipe limiting + TuinityConfig.getDouble("packet-limiter.limits." + -+ net.minecraft.server.PacketPlayInAutoRecipe.class.getSimpleName() + ".interval", 4.0); ++ net.minecraft.network.protocol.game.PacketPlayInAutoRecipe.class.getSimpleName() + ".interval", 4.0); + TuinityConfig.getDouble("packet-limiter.limits." + -+ net.minecraft.server.PacketPlayInAutoRecipe.class.getSimpleName() + ".max-packet-rate", 5.0); ++ net.minecraft.network.protocol.game.PacketPlayInAutoRecipe.class.getSimpleName() + ".max-packet-rate", 5.0); + TuinityConfig.getString("packet-limiter.limits." + -+ net.minecraft.server.PacketPlayInAutoRecipe.class.getSimpleName() + ".action", PacketLimit.ViolateAction.DROP.name()); ++ net.minecraft.network.protocol.game.PacketPlayInAutoRecipe.class.getSimpleName() + ".action", PacketLimit.ViolateAction.DROP.name()); + ++ final String canonicalName = MinecraftServer.class.getCanonicalName(); ++ final String nmsPackage = canonicalName.substring(0, canonicalName.lastIndexOf(".")); + for (final String packetClassName : section.getKeys(false)) { + if (packetClassName.equals("all")) { + continue; + } -+ final Class packetClazz; ++ Class packetClazz = null; + + try { -+ packetClazz = Class.forName("net.minecraft.server." + packetClassName); ++ packetClazz = Class.forName(nmsPackage + "." + packetClassName); + } catch (final ClassNotFoundException ex) { -+ MinecraftServer.LOGGER.warn("Packet '" + packetClassName + "' does not exist, cannot limit it! Please update tuinity.yml"); -+ continue; ++ for (final String subpackage : java.util.Arrays.asList("game", "handshake", "login", "status")) { ++ try { ++ packetClazz = Class.forName("net.minecraft.network.protocol." + subpackage + "." + packetClassName); ++ } catch (final ClassNotFoundException ignore) {} ++ } ++ if (packetClazz == null) { ++ MinecraftServer.LOGGER.warn("Packet '" + packetClassName + "' does not exist, cannot limit it! Please update tuinity.yml"); ++ continue; ++ } + } + -+ if (!net.minecraft.server.Packet.class.isAssignableFrom(packetClazz)) { ++ if (!net.minecraft.network.protocol.Packet.class.isAssignableFrom(packetClazz)) { + MinecraftServer.LOGGER.warn("Packet '" + packetClassName + "' does not exist, cannot limit it! Please update tuinity.yml"); + continue; + } @@ -6070,15 +6476,15 @@ index 0000000000000000000000000000000000000000..d1308b8cbb9490f1ccdc5514763e62bc \ No newline at end of file diff --git a/src/main/java/com/tuinity/tuinity/util/CachedLists.java b/src/main/java/com/tuinity/tuinity/util/CachedLists.java new file mode 100644 -index 0000000000000000000000000000000000000000..21e50c75e0bffaa5cc5faf6aa81ae7428caca731 +index 0000000000000000000000000000000000000000..e0a2f10f92430fd59519e57dee3286035c287bf3 --- /dev/null +++ b/src/main/java/com/tuinity/tuinity/util/CachedLists.java @@ -0,0 +1,74 @@ +package com.tuinity.tuinity.util; + -+import net.minecraft.server.AxisAlignedBB; -+import net.minecraft.server.Chunk; -+import net.minecraft.server.Entity; ++import net.minecraft.world.phys.AxisAlignedBB; ++import net.minecraft.world.level.chunk.Chunk; ++import net.minecraft.world.entity.Entity; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.util.UnsafeList; +import java.util.List; @@ -6150,17 +6556,17 @@ index 0000000000000000000000000000000000000000..21e50c75e0bffaa5cc5faf6aa81ae742 +} diff --git a/src/main/java/com/tuinity/tuinity/util/CoordinateUtils.java b/src/main/java/com/tuinity/tuinity/util/CoordinateUtils.java new file mode 100644 -index 0000000000000000000000000000000000000000..81fe01c122529f1716a264263957500015476f5f +index 0000000000000000000000000000000000000000..17cece8ee25ad6145bc0bdf7d15c2ea988c85f87 --- /dev/null +++ b/src/main/java/com/tuinity/tuinity/util/CoordinateUtils.java @@ -0,0 +1,128 @@ +package com.tuinity.tuinity.util; + -+import net.minecraft.server.BlockPosition; -+import net.minecraft.server.ChunkCoordIntPair; -+import net.minecraft.server.Entity; -+import net.minecraft.server.MathHelper; -+import net.minecraft.server.SectionPosition; ++import net.minecraft.core.BlockPosition; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.util.MathHelper; ++import net.minecraft.core.SectionPosition; ++import net.minecraft.world.level.ChunkCoordIntPair; + +public final class CoordinateUtils { + @@ -6622,7 +7028,7 @@ index 0000000000000000000000000000000000000000..d2c7d2c7920324d7207225ed19484e80 +} diff --git a/src/main/java/com/tuinity/tuinity/util/PoiAccess.java b/src/main/java/com/tuinity/tuinity/util/PoiAccess.java new file mode 100644 -index 0000000000000000000000000000000000000000..ef0b766709fd9369b5ae458148259291583fe565 +index 0000000000000000000000000000000000000000..5018a3378680d98605e0e4a79bf112e032c98925 --- /dev/null +++ b/src/main/java/com/tuinity/tuinity/util/PoiAccess.java @@ -0,0 +1,812 @@ @@ -6631,13 +7037,13 @@ index 0000000000000000000000000000000000000000..ef0b766709fd9369b5ae458148259291 +import it.unimi.dsi.fastutil.doubles.Double2ObjectMap; +import it.unimi.dsi.fastutil.doubles.Double2ObjectRBTreeMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -+import net.minecraft.server.BlockPosition; -+import net.minecraft.server.MathHelper; -+import net.minecraft.server.SectionPosition; -+import net.minecraft.server.VillagePlace; -+import net.minecraft.server.VillagePlaceRecord; -+import net.minecraft.server.VillagePlaceSection; -+import net.minecraft.server.VillagePlaceType; ++import net.minecraft.core.BlockPosition; ++import net.minecraft.util.MathHelper; ++import net.minecraft.core.SectionPosition; ++import net.minecraft.world.entity.ai.village.poi.VillagePlace; ++import net.minecraft.world.entity.ai.village.poi.VillagePlaceRecord; ++import net.minecraft.world.entity.ai.village.poi.VillagePlaceSection; ++import net.minecraft.world.entity.ai.village.poi.VillagePlaceType; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; @@ -7488,13 +7894,13 @@ index 0000000000000000000000000000000000000000..08ed243259f052165c6f75aed1d1d65a \ No newline at end of file diff --git a/src/main/java/com/tuinity/tuinity/util/WorldUtil.java b/src/main/java/com/tuinity/tuinity/util/WorldUtil.java new file mode 100644 -index 0000000000000000000000000000000000000000..141748fe4915eb46671f1d532951f14d7080818d +index 0000000000000000000000000000000000000000..6dca98c5c43126c7b2dea2987b757e3de822c17c --- /dev/null +++ b/src/main/java/com/tuinity/tuinity/util/WorldUtil.java @@ -0,0 +1,48 @@ +package com.tuinity.tuinity.util; + -+import net.minecraft.server.World; ++import net.minecraft.world.level.World; + +public final class WorldUtil { + @@ -8901,9 +9307,175 @@ index 0000000000000000000000000000000000000000..606417a8aeaca2682595f417bba8e9d4 + } + } +} +diff --git a/src/main/java/com/tuinity/tuinity/util/table/ZeroCollidingReferenceStateTable.java b/src/main/java/com/tuinity/tuinity/util/table/ZeroCollidingReferenceStateTable.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6985facdb2d1689a71472d3ac282e4f5f3cb9869 +--- /dev/null ++++ b/src/main/java/com/tuinity/tuinity/util/table/ZeroCollidingReferenceStateTable.java +@@ -0,0 +1,160 @@ ++package com.tuinity.tuinity.util.table; ++ ++import com.google.common.collect.Table; ++import net.minecraft.world.level.block.state.IBlockDataHolder; ++import net.minecraft.world.level.block.state.properties.IBlockState; ++import java.util.Collection; ++import java.util.HashSet; ++import java.util.Map; ++import java.util.Set; ++ ++public final class ZeroCollidingReferenceStateTable { ++ ++ // upper 32 bits: starting index ++ // lower 32 bits: bitset for contained ids ++ protected final long[] this_index_table; ++ protected final Comparable[] this_table; ++ protected final IBlockDataHolder this_state; ++ ++ protected long[] index_table; ++ protected IBlockDataHolder[][] value_table; ++ ++ public ZeroCollidingReferenceStateTable(final IBlockDataHolder state, final Map, Comparable> this_map) { ++ this.this_state = state; ++ this.this_index_table = this.create_table(this_map.keySet()); ++ ++ int max_id = -1; ++ for (final IBlockState property : this_map.keySet()) { ++ final int id = lookup_vindex(property, this.this_index_table); ++ if (id > max_id) { ++ max_id = id; ++ } ++ } ++ ++ this.this_table = new Comparable[max_id + 1]; ++ for (final Map.Entry, Comparable> entry : this_map.entrySet()) { ++ this.this_table[lookup_vindex(entry.getKey(), this.this_index_table)] = entry.getValue(); ++ } ++ } ++ ++ public void loadInTable(final Table, Comparable, IBlockDataHolder> table, ++ final Map, Comparable> this_map) { ++ final Set> combined = new HashSet<>(table.rowKeySet()); ++ combined.addAll(this_map.keySet()); ++ ++ this.index_table = this.create_table(combined); ++ ++ int max_id = -1; ++ for (final IBlockState property : combined) { ++ final int id = lookup_vindex(property, this.index_table); ++ if (id > max_id) { ++ max_id = id; ++ } ++ } ++ ++ this.value_table = new IBlockDataHolder[max_id + 1][]; ++ ++ final Map, Map, IBlockDataHolder>> map = table.rowMap(); ++ for (final IBlockState property : map.keySet()) { ++ final Map, IBlockDataHolder> propertyMap = map.get(property); ++ ++ final int id = lookup_vindex(property, this.index_table); ++ final IBlockDataHolder[] states = this.value_table[id] = new IBlockDataHolder[property.getValues().size()]; ++ ++ for (final Map.Entry, IBlockDataHolder> entry : propertyMap.entrySet()) { ++ if (entry.getValue() == null) { ++ // TODO what ++ continue; ++ } ++ ++ states[((IBlockState)property).getIdFor(entry.getKey())] = entry.getValue(); ++ } ++ } ++ ++ ++ for (final Map.Entry, Comparable> entry : this_map.entrySet()) { ++ final IBlockState property = entry.getKey(); ++ final int index = lookup_vindex(property, this.index_table); ++ ++ if (this.value_table[index] == null) { ++ this.value_table[index] = new IBlockDataHolder[property.getValues().size()]; ++ } ++ ++ this.value_table[index][((IBlockState)property).getIdFor(entry.getValue())] = this.this_state; ++ } ++ } ++ ++ ++ protected long[] create_table(final Collection> collection) { ++ int max_id = -1; ++ for (final IBlockState property : collection) { ++ final int id = property.getId(); ++ if (id > max_id) { ++ max_id = id; ++ } ++ } ++ ++ final long[] ret = new long[((max_id + 1) + 31) >>> 5]; // ceil((max_id + 1) / 32) ++ ++ for (final IBlockState property : collection) { ++ final int id = property.getId(); ++ ++ ret[id >>> 5] |= (1L << (id & 31)); ++ } ++ ++ int total = 0; ++ for (int i = 1, len = ret.length; i < len; ++i) { ++ ret[i] |= (long)(total += Long.bitCount(ret[i - 1] & 0xFFFFFFFFL)) << 32; ++ } ++ ++ return ret; ++ } ++ ++ public Comparable get(final IBlockState state) { ++ final Comparable[] table = this.this_table; ++ final int index = lookup_vindex(state, this.this_index_table); ++ ++ if (index < 0 || index >= table.length) { ++ return null; ++ } ++ return table[index]; ++ } ++ ++ public IBlockDataHolder get(final IBlockState property, final Comparable with) { ++ final int withId = ((IBlockState)property).getIdFor(with); ++ if (withId < 0) { ++ return null; ++ } ++ ++ final int index = lookup_vindex(property, this.index_table); ++ final IBlockDataHolder[][] table = this.value_table; ++ if (index < 0 || index >= table.length) { ++ return null; ++ } ++ ++ final IBlockDataHolder[] values = table[index]; ++ ++ if (withId >= values.length) { ++ return null; ++ } ++ ++ return values[withId]; ++ } ++ ++ protected static int lookup_vindex(final IBlockState property, final long[] index_table) { ++ final int id = property.getId(); ++ final long bitset_mask = (1L << (id & 31)); ++ final long lower_mask = bitset_mask - 1; ++ final int index = id >>> 5; ++ if (index >= index_table.length) { ++ return -1; ++ } ++ final long index_value = index_table[index]; ++ final long contains_check = ((index_value & bitset_mask) - 1) >> (Long.SIZE - 1); // -1L if doesn't contain ++ ++ // index = total bits set in lower table values (upper 32 bits of index_value) plus total bits set in lower indices below id ++ // contains_check is 0 if the bitset had id set, else it's -1: so index is unaffected if contains_check == 0, ++ // otherwise it comes out as -1. ++ return (int)(((index_value >>> 32) + Long.bitCount(index_value & lower_mask)) | contains_check); ++ } ++} diff --git a/src/main/java/com/tuinity/tuinity/voxel/AABBVoxelShape.java b/src/main/java/com/tuinity/tuinity/voxel/AABBVoxelShape.java new file mode 100644 -index 0000000000000000000000000000000000000000..002abb3cbf0f742e685f2f043d2600de03e37a19 +index 0000000000000000000000000000000000000000..ccc6935f45f91eac17cf09d044060b5bb4c2c935 --- /dev/null +++ b/src/main/java/com/tuinity/tuinity/voxel/AABBVoxelShape.java @@ -0,0 +1,165 @@ @@ -8911,10 +9483,10 @@ index 0000000000000000000000000000000000000000..002abb3cbf0f742e685f2f043d2600de + +import it.unimi.dsi.fastutil.doubles.DoubleArrayList; +import it.unimi.dsi.fastutil.doubles.DoubleList; -+import net.minecraft.server.AxisAlignedBB; -+import net.minecraft.server.EnumDirection; -+import net.minecraft.server.VoxelShape; -+import net.minecraft.server.VoxelShapes; ++import net.minecraft.world.phys.AxisAlignedBB; ++import net.minecraft.core.EnumDirection; ++import net.minecraft.world.phys.shapes.VoxelShape; ++import net.minecraft.world.phys.shapes.VoxelShapes; +import java.util.ArrayList; +import java.util.List; + @@ -9074,7 +9646,7 @@ index 0000000000000000000000000000000000000000..002abb3cbf0f742e685f2f043d2600de +} diff --git a/src/main/java/com/tuinity/tuinity/world/ChunkEntitySlices.java b/src/main/java/com/tuinity/tuinity/world/ChunkEntitySlices.java new file mode 100644 -index 0000000000000000000000000000000000000000..7aca38ebeb21af1a952e72c7f3906ff4970aca0e +index 0000000000000000000000000000000000000000..57359791192a90b025e5fea38f3ce37e524aed82 --- /dev/null +++ b/src/main/java/com/tuinity/tuinity/world/ChunkEntitySlices.java @@ -0,0 +1,399 @@ @@ -9082,13 +9654,13 @@ index 0000000000000000000000000000000000000000..7aca38ebeb21af1a952e72c7f3906ff4 + +import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; +import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; -+import net.minecraft.server.AxisAlignedBB; -+import net.minecraft.server.Entity; -+import net.minecraft.server.EntityComplexPart; -+import net.minecraft.server.EntityEnderDragon; -+import net.minecraft.server.EntityTypes; -+import net.minecraft.server.MathHelper; -+import net.minecraft.server.World; ++import net.minecraft.world.entity.boss.EntityComplexPart; ++import net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon; ++import net.minecraft.world.phys.AxisAlignedBB; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EntityTypes; ++import net.minecraft.util.MathHelper; ++import net.minecraft.world.level.World; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; @@ -9479,7 +10051,7 @@ index 0000000000000000000000000000000000000000..7aca38ebeb21af1a952e72c7f3906ff4 +} diff --git a/src/main/java/com/tuinity/tuinity/world/EntitySliceManager.java b/src/main/java/com/tuinity/tuinity/world/EntitySliceManager.java new file mode 100644 -index 0000000000000000000000000000000000000000..000ab23a48186d6b910c62e6922af3b85c198fca +index 0000000000000000000000000000000000000000..3ec78275494f0f0b7ad3c53467ec6c6395cb257d --- /dev/null +++ b/src/main/java/com/tuinity/tuinity/world/EntitySliceManager.java @@ -0,0 +1,115 @@ @@ -9487,7 +10059,7 @@ index 0000000000000000000000000000000000000000..000ab23a48186d6b910c62e6922af3b8 + +import com.tuinity.tuinity.util.CoordinateUtils; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -+import net.minecraft.server.WorldServer; ++import net.minecraft.server.level.WorldServer; +import java.util.concurrent.locks.StampedLock; + +public final class EntitySliceManager { @@ -9598,197 +10170,11 @@ index 0000000000000000000000000000000000000000..000ab23a48186d6b910c62e6922af3b8 + } + } +} -diff --git a/src/main/java/net/minecraft/server/AxisAlignedBB.java b/src/main/java/net/minecraft/server/AxisAlignedBB.java -index ed9b2f9adfecdc6d1b9925579ec510657adde11f..5c3d5b22b833d9f835e17803295b87893fd05e62 100644 ---- a/src/main/java/net/minecraft/server/AxisAlignedBB.java -+++ b/src/main/java/net/minecraft/server/AxisAlignedBB.java -@@ -13,6 +13,157 @@ public class AxisAlignedBB { - public final double maxY; - public final double maxZ; - -+ // Tuinity start -+ public final boolean isEmpty() { -+ return (this.maxX - this.minX) < MCUtil.COLLISION_EPSILON && (this.maxY - this.minY) < MCUtil.COLLISION_EPSILON && (this.maxZ - this.minZ) < MCUtil.COLLISION_EPSILON; -+ } -+ -+ public static AxisAlignedBB getBoxForChunk(int chunkX, int chunkZ) { -+ double x = (double)(chunkX << 4); -+ double z = (double)(chunkZ << 4); -+ // use a bounding box bigger than the chunk to prevent entities from entering it on move -+ return new AxisAlignedBB(x - 3*MCUtil.COLLISION_EPSILON, Double.NEGATIVE_INFINITY, z - 3*MCUtil.COLLISION_EPSILON, x + (16.0 + 3*MCUtil.COLLISION_EPSILON), Double.POSITIVE_INFINITY, z + (16.0 + 3*MCUtil.COLLISION_EPSILON), false); -+ } -+ -+ /* -+ A couple of rules for VoxelShape collisions: -+ Two shapes only intersect if they are actually more than EPSILON units into each other. This also applies to movement -+ checks. -+ If the two shapes strictly collide, then the return value of a collide call will return a value in the opposite -+ direction of the source move. However, this value will not be greater in magnitude than EPSILON. Collision code -+ will automatically round it to 0. -+ */ -+ -+ public final boolean voxelShapeIntersect(AxisAlignedBB other) { -+ return (this.minX - other.maxX) < -MCUtil.COLLISION_EPSILON && (this.maxX - other.minX) > MCUtil.COLLISION_EPSILON && -+ (this.minY - other.maxY) < -MCUtil.COLLISION_EPSILON && (this.maxY - other.minY) > MCUtil.COLLISION_EPSILON && -+ (this.minZ - other.maxZ) < -MCUtil.COLLISION_EPSILON && (this.maxZ - other.minZ) > MCUtil.COLLISION_EPSILON; -+ } -+ -+ public final boolean voxelShapeIntersect(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { -+ return (this.minX - maxX) < -MCUtil.COLLISION_EPSILON && (this.maxX - minX) > MCUtil.COLLISION_EPSILON && -+ (this.minY - maxY) < -MCUtil.COLLISION_EPSILON && (this.maxY - minY) > MCUtil.COLLISION_EPSILON && -+ (this.minZ - maxZ) < -MCUtil.COLLISION_EPSILON && (this.maxZ - minZ) > MCUtil.COLLISION_EPSILON; -+ } -+ -+ public static boolean voxelShapeIntersect(double minX1, double minY1, double minZ1, double maxX1, double maxY1, double maxZ1, -+ double minX2, double minY2, double minZ2, double maxX2, double maxY2, double maxZ2) { -+ return (minX1 - maxX2) < -MCUtil.COLLISION_EPSILON && (maxX1 - minX2) > MCUtil.COLLISION_EPSILON && -+ (minY1 - maxY2) < -MCUtil.COLLISION_EPSILON && (maxY1 - minY2) > MCUtil.COLLISION_EPSILON && -+ (minZ1 - maxZ2) < -MCUtil.COLLISION_EPSILON && (maxZ1 - minZ2) > MCUtil.COLLISION_EPSILON; -+ } -+ -+ public static double collideX(AxisAlignedBB target, AxisAlignedBB source, double source_move) { -+ if (source_move == 0.0) { -+ return 0.0; -+ } -+ -+ if ((source.minY - target.maxY) < -MCUtil.COLLISION_EPSILON && (source.maxY - target.minY) > MCUtil.COLLISION_EPSILON && -+ (source.minZ - target.maxZ) < -MCUtil.COLLISION_EPSILON && (source.maxZ - target.minZ) > MCUtil.COLLISION_EPSILON) { -+ -+ if (source_move >= 0.0) { -+ double max_move = target.minX - source.maxX; // < 0.0 if no strict collision -+ if (max_move < -MCUtil.COLLISION_EPSILON) { -+ return source_move; -+ } -+ return Math.min(max_move, source_move); -+ } else { -+ double max_move = target.maxX - source.minX; // > 0.0 if no strict collision -+ if (max_move > MCUtil.COLLISION_EPSILON) { -+ return source_move; -+ } -+ return Math.max(max_move, source_move); -+ } -+ } -+ return source_move; -+ } -+ -+ public static double collideY(AxisAlignedBB target, AxisAlignedBB source, double source_move) { -+ if (source_move == 0.0) { -+ return 0.0; -+ } -+ -+ if ((source.minX - target.maxX) < -MCUtil.COLLISION_EPSILON && (source.maxX - target.minX) > MCUtil.COLLISION_EPSILON && -+ (source.minZ - target.maxZ) < -MCUtil.COLLISION_EPSILON && (source.maxZ - target.minZ) > MCUtil.COLLISION_EPSILON) { -+ if (source_move >= 0.0) { -+ double max_move = target.minY - source.maxY; // < 0.0 if no strict collision -+ if (max_move < -MCUtil.COLLISION_EPSILON) { -+ return source_move; -+ } -+ return Math.min(max_move, source_move); -+ } else { -+ double max_move = target.maxY - source.minY; // > 0.0 if no strict collision -+ if (max_move > MCUtil.COLLISION_EPSILON) { -+ return source_move; -+ } -+ return Math.max(max_move, source_move); -+ } -+ } -+ return source_move; -+ } -+ -+ public static double collideZ(AxisAlignedBB target, AxisAlignedBB source, double source_move) { -+ if (source_move == 0.0) { -+ return 0.0; -+ } -+ -+ if ((source.minX - target.maxX) < -MCUtil.COLLISION_EPSILON && (source.maxX - target.minX) > MCUtil.COLLISION_EPSILON && -+ (source.minY - target.maxY) < -MCUtil.COLLISION_EPSILON && (source.maxY - target.minY) > MCUtil.COLLISION_EPSILON) { -+ if (source_move >= 0.0) { -+ double max_move = target.minZ - source.maxZ; // < 0.0 if no strict collision -+ if (max_move < -MCUtil.COLLISION_EPSILON) { -+ return source_move; -+ } -+ return Math.min(max_move, source_move); -+ } else { -+ double max_move = target.maxZ - source.minZ; // > 0.0 if no strict collision -+ if (max_move > MCUtil.COLLISION_EPSILON) { -+ return source_move; -+ } -+ return Math.max(max_move, source_move); -+ } -+ } -+ return source_move; -+ } -+ -+ public final AxisAlignedBB offsetX(double dx) { -+ return new AxisAlignedBB(this.minX + dx, this.minY, this.minZ, this.maxX + dx, this.maxY, this.maxZ, false); -+ } -+ -+ public final AxisAlignedBB offsetY(double dy) { -+ return new AxisAlignedBB(this.minX, this.minY + dy, this.minZ, this.maxX, this.maxY + dy, this.maxZ, false); -+ } -+ -+ public final AxisAlignedBB offsetZ(double dz) { -+ return new AxisAlignedBB(this.minX, this.minY, this.minZ + dz, this.maxX, this.maxY, this.maxZ + dz, false); -+ } -+ -+ public AxisAlignedBB(double d0, double d1, double d2, double d3, double d4, double d5, boolean dummy) { -+ this.minX = d0; -+ this.minY = d1; -+ this.minZ = d2; -+ this.maxX = d3; -+ this.maxY = d4; -+ this.maxZ = d5; -+ } -+ -+ public final AxisAlignedBB expandUpwards(double dy) { -+ return new AxisAlignedBB(this.minX, this.minY, this.minZ, this.maxX, this.maxY + dy, this.maxZ, false); -+ } -+ -+ public final AxisAlignedBB cutUpwards(final double dy) { // dy > 0.0 -+ return new AxisAlignedBB(this.minX, this.maxY, this.minZ, this.maxX, this.maxY + dy, this.maxZ, false); -+ } -+ -+ public final AxisAlignedBB cutDownwards(final double dy) { // dy < 0.0 -+ return new AxisAlignedBB(this.minX, this.minY + dy, this.minZ, this.maxX, this.minY, this.maxZ, false); -+ } -+ -+ public final AxisAlignedBB expandUpwardsAndCutBelow(double dy) { -+ return new AxisAlignedBB(this.minX, this.maxY, this.minZ, this.maxX, this.maxY + dy, this.maxZ, false); -+ } -+ // Tuinity end -+ - public AxisAlignedBB(double d0, double d1, double d2, double d3, double d4, double d5) { - this.minX = Math.min(d0, d3); - this.minY = Math.min(d1, d4); -@@ -185,6 +336,7 @@ public class AxisAlignedBB { - return new AxisAlignedBB(d0, d1, d2, d3, d4, d5); - } - -+ public final AxisAlignedBB offset(double d0, double d1, double d2) { return this.d(d0, d1, d2); } // Tuinity - OBFHELPER - public AxisAlignedBB d(double d0, double d1, double d2) { - return new AxisAlignedBB(this.minX + d0, this.minY + d1, this.minZ + d2, this.maxX + d0, this.maxY + d1, this.maxZ + d2); - } -@@ -193,6 +345,7 @@ public class AxisAlignedBB { - return new AxisAlignedBB(this.minX + (double) blockposition.getX(), this.minY + (double) blockposition.getY(), this.minZ + (double) blockposition.getZ(), this.maxX + (double) blockposition.getX(), this.maxY + (double) blockposition.getY(), this.maxZ + (double) blockposition.getZ()); - } - -+ public final AxisAlignedBB offset(Vec3D vec3d) { return this.b(vec3d); } // Tuinity - OBFHELPER - public AxisAlignedBB c(Vec3D vec3d) { - return this.d(vec3d.x, vec3d.y, vec3d.z); - } -@@ -212,6 +365,7 @@ public class AxisAlignedBB { - return this.e(vec3d.x, vec3d.y, vec3d.z); - } - -+ public final boolean contains(double d0, double d1, double d2) { return this.e(d0, d1, d2); } // Tuinity - OBFHELPER - public boolean e(double d0, double d1, double d2) { - return d0 >= this.minX && d0 < this.maxX && d1 >= this.minY && d1 < this.maxY && d2 >= this.minZ && d2 < this.maxZ; - } -diff --git a/src/main/java/net/minecraft/server/BaseBlockPosition.java b/src/main/java/net/minecraft/server/BaseBlockPosition.java -index 6b655b744d31d9660c7521ab596b27bcd92f4d58..e811295b4d6afcd920f60e0ce5440e43300d9085 100644 ---- a/src/main/java/net/minecraft/server/BaseBlockPosition.java -+++ b/src/main/java/net/minecraft/server/BaseBlockPosition.java -@@ -16,9 +16,9 @@ public class BaseBlockPosition implements Comparable { +diff --git a/src/main/java/net/minecraft/core/BaseBlockPosition.java b/src/main/java/net/minecraft/core/BaseBlockPosition.java +index a44bcdb053877a6281e566ffe03ef72ffd50ca08..e72c852517f9fdc7b7a3a5bc5d3aa067815ff944 100644 +--- a/src/main/java/net/minecraft/core/BaseBlockPosition.java ++++ b/src/main/java/net/minecraft/core/BaseBlockPosition.java +@@ -18,9 +18,9 @@ public class BaseBlockPosition implements Comparable { return IntStream.of(new int[]{baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()}); }); public static final BaseBlockPosition ZERO = new BaseBlockPosition(0, 0, 0); @@ -9801,7 +10187,7 @@ index 6b655b744d31d9660c7521ab596b27bcd92f4d58..e811295b4d6afcd920f60e0ce5440e43 // Paper start public boolean isValidLocation() { -@@ -71,15 +71,15 @@ public class BaseBlockPosition implements Comparable { +@@ -73,15 +73,15 @@ public class BaseBlockPosition implements Comparable { return this.e; } @@ -9820,450 +10206,11 @@ index 6b655b744d31d9660c7521ab596b27bcd92f4d58..e811295b4d6afcd920f60e0ce5440e43 this.e = i; } -diff --git a/src/main/java/net/minecraft/server/Behavior.java b/src/main/java/net/minecraft/server/Behavior.java -index 65af976527133ee5c2f52e411e19c4f7f06df3ef..0b9d469a92decfb0632805791868ef7faa88c535 100644 ---- a/src/main/java/net/minecraft/server/Behavior.java -+++ b/src/main/java/net/minecraft/server/Behavior.java -@@ -7,7 +7,7 @@ import java.util.Map.Entry; - public abstract class Behavior { - - protected final Map, MemoryStatus> a; -- private Behavior.Status b; -+ private Behavior.Status b; public final Behavior.Status getStatus() { return this.b; } // Tuinity - OBFHELPER - private long c; - private final int d; - private final int e; -diff --git a/src/main/java/net/minecraft/server/BehaviorFindPosition.java b/src/main/java/net/minecraft/server/BehaviorFindPosition.java -index 63a761ebef80d4af09cdc2682e496d78492c4a3a..83702e07dff72b639af32c8ba9e831e58da92a10 100644 ---- a/src/main/java/net/minecraft/server/BehaviorFindPosition.java -+++ b/src/main/java/net/minecraft/server/BehaviorFindPosition.java -@@ -74,7 +74,11 @@ public class BehaviorFindPosition extends Behavior { - return true; - } - }; -- Set set = (Set) villageplace.b(this.b.c(), predicate, entitycreature.getChunkCoordinates(), 48, VillagePlace.Occupancy.HAS_SPACE).limit(5L).collect(Collectors.toSet()); -+ // Tuinity start - optimise POI access -+ java.util.List poiposes = new java.util.ArrayList<>(); -+ com.tuinity.tuinity.util.PoiAccess.findNearestPoiPositions(villageplace, this.b.c(), predicate, entitycreature.getChunkCoordinates(), 48, 48*48, VillagePlace.Occupancy.HAS_SPACE, false, 5, poiposes); -+ Set set = new java.util.HashSet<>(poiposes); -+ // Tuinity end - optimise POI access - PathEntity pathentity = entitycreature.getNavigation().a(set, this.b.d()); - - if (pathentity != null && pathentity.j()) { -@@ -84,7 +88,7 @@ public class BehaviorFindPosition extends Behavior { - villageplace.a(this.b.c(), (blockposition1) -> { - return blockposition1.equals(blockposition); - }, blockposition, 1); -- entitycreature.getBehaviorController().setMemory(this.c, (Object) GlobalPos.create(worldserver.getDimensionKey(), blockposition)); -+ entitycreature.getBehaviorController().setMemory(this.c, GlobalPos.create(worldserver.getDimensionKey(), blockposition)); // Tuinity - decompile fix - this.e.ifPresent((obyte) -> { - worldserver.broadcastEntityEffect(entitycreature, obyte); - }); -diff --git a/src/main/java/net/minecraft/server/BehaviorGate.java b/src/main/java/net/minecraft/server/BehaviorGate.java -index 46e910581210421c8699637431804dc2f43eb4a6..fb967bc03f58fab8cec2732b1890108f2fc66af8 100644 ---- a/src/main/java/net/minecraft/server/BehaviorGate.java -+++ b/src/main/java/net/minecraft/server/BehaviorGate.java -@@ -12,7 +12,7 @@ public class BehaviorGate extends Behavior { - private final Set> b; - private final BehaviorGate.Order c; - private final BehaviorGate.Execution d; -- private final WeightedList> e = new WeightedList<>(false); // Paper - don't use a clone -+ private final WeightedList> e = new WeightedList<>(false); protected final WeightedList> getList() { return this.e; } // Paper - don't use a clone // Tuinity - OBFHELPER - - public BehaviorGate(Map, MemoryStatus> map, Set> set, BehaviorGate.Order behaviorgate_order, BehaviorGate.Execution behaviorgate_execution, List, Integer>> list) { - super(map); -@@ -26,11 +26,17 @@ public class BehaviorGate extends Behavior { - - @Override - protected boolean b(WorldServer worldserver, E e0, long i) { -- return this.e.c().filter((behavior) -> { -- return behavior.a() == Behavior.Status.RUNNING; -- }).anyMatch((behavior) -> { -- return behavior.b(worldserver, e0, i); -- }); -+ // Tuinity start - remove streams -+ List>> list = this.getList().getList(); -+ for (int index = 0, len = list.size(); index < len; ++index) { -+ Behavior behavior = list.get(index).getValue(); -+ if (behavior.getStatus() == Status.RUNNING && behavior.b(worldserver, e0, i)) { // copied from removed code, make sure to update -+ return true; -+ } -+ } -+ -+ return false; -+ // Tuinity end - remove streams - } - - @Override -@@ -46,20 +52,28 @@ public class BehaviorGate extends Behavior { - - @Override - protected void d(WorldServer worldserver, E e0, long i) { -- this.e.c().filter((behavior) -> { -- return behavior.a() == Behavior.Status.RUNNING; -- }).forEach((behavior) -> { -- behavior.f(worldserver, e0, i); -- }); -+ // Tuinity start - remove streams -+ List>> list = this.getList().getList(); -+ for (int index = 0, len = list.size(); index < len; ++index) { -+ Behavior behavior = list.get(index).getValue(); -+ if (behavior.getStatus() == Behavior.Status.RUNNING) { -+ behavior.f(worldserver, e0, i); // copied from removed code, make sure to update -+ } -+ } -+ // Tuinity end - remove streams - } - - @Override - protected void c(WorldServer worldserver, E e0, long i) { -- this.e.c().filter((behavior) -> { -- return behavior.a() == Behavior.Status.RUNNING; -- }).forEach((behavior) -> { -- behavior.g(worldserver, e0, i); -- }); -+ // Tuinity start - remove streams -+ List>> list = this.getList().getList(); -+ for (int index = 0, len = list.size(); index < len; ++index) { -+ Behavior behavior = list.get(index).getValue(); -+ if (behavior.getStatus() == Behavior.Status.RUNNING) { -+ behavior.g(worldserver, e0, i); // copied from removed code, make sure to update -+ } -+ } -+ // Tuinity end - remove streams - BehaviorController behaviorcontroller = e0.getBehaviorController(); - - this.b.forEach(behaviorcontroller::removeMemory); // Paper - decomp fix -@@ -79,21 +93,29 @@ public class BehaviorGate extends Behavior { - RUN_ONE { - @Override - public void a(WeightedList> weightedlist, WorldServer worldserver, E e0, long i) { -- weightedlist.c().filter((behavior) -> { -- return behavior.a() == Behavior.Status.STOPPED; -- }).filter((behavior) -> { -- return behavior.e(worldserver, e0, i); -- }).findFirst(); -+ // Tuinity start - remove streams -+ List>> list = weightedlist.getList(); -+ for (int index = 0, len = list.size(); index < len; ++index) { -+ Behavior behavior = list.get(index).getValue(); -+ if (behavior.getStatus() == Behavior.Status.STOPPED && behavior.e(worldserver, e0, i)) { // copied from removed code, make sure to update -+ break; -+ } -+ } -+ // Tuinity end - remove streams - } - }, - TRY_ALL { - @Override - public void a(WeightedList> weightedlist, WorldServer worldserver, E e0, long i) { -- weightedlist.c().filter((behavior) -> { -- return behavior.a() == Behavior.Status.STOPPED; -- }).forEach((behavior) -> { -- behavior.e(worldserver, e0, i); -- }); -+ // Tuinity start - remove streams -+ List>> list = weightedlist.getList(); -+ for (int index = 0, len = list.size(); index < len; ++index) { -+ Behavior behavior = list.get(index).getValue(); -+ if (behavior.getStatus() == Behavior.Status.STOPPED) { -+ behavior.e(worldserver, e0, i); // copied from removed code, make sure to update -+ } -+ } -+ // Tuinity end - remove streams - } - }; - -diff --git a/src/main/java/net/minecraft/server/BehaviorLookInteract.java b/src/main/java/net/minecraft/server/BehaviorLookInteract.java -index a33303c31881b6391723e16a06d7841d48679958..ce57e6a4acac97d6da82202094306e7e91f1c87e 100644 ---- a/src/main/java/net/minecraft/server/BehaviorLookInteract.java -+++ b/src/main/java/net/minecraft/server/BehaviorLookInteract.java -@@ -7,7 +7,7 @@ import java.util.function.Predicate; - public class BehaviorLookInteract extends Behavior { - - private final EntityTypes b; -- private final int c; -+ private final int c; private final int getMaxRange() { return this.c; } // Tuinity - OBFHELPER - private final Predicate d; - private final Predicate e; - -@@ -29,7 +29,20 @@ public class BehaviorLookInteract extends Behavior { - - @Override - public boolean a(WorldServer worldserver, EntityLiving entityliving) { -- return this.e.test(entityliving) && this.b(entityliving).stream().anyMatch(this::a); -+ // Tuinity start - remove streams -+ if (!this.e.test(entityliving)) { -+ return false; -+ } -+ -+ List list = this.b(entityliving); -+ for (int index = 0, len = list.size(); index < len; ++index) { -+ if (this.a(list.get(index))) { -+ return true; -+ } -+ } -+ -+ return false; -+ // Tuinity end - remove streams - } - - @Override -@@ -37,16 +50,28 @@ public class BehaviorLookInteract extends Behavior { - super.a(worldserver, entityliving, i); - BehaviorController behaviorcontroller = entityliving.getBehaviorController(); - -- behaviorcontroller.getMemory(MemoryModuleType.VISIBLE_MOBS).ifPresent((list) -> { -- list.stream().filter((entityliving1) -> { -- return entityliving1.h((Entity) entityliving) <= (double) this.c; -- }).filter(this::a).findFirst().ifPresent((entityliving1) -> { -- behaviorcontroller.setMemory(MemoryModuleType.INTERACTION_TARGET, (Object) entityliving1); -- behaviorcontroller.setMemory(MemoryModuleType.LOOK_TARGET, (Object) (new BehaviorPositionEntity(entityliving1, true))); -- }); -- }); -+ // Tuinity start - remove streams -+ List inLOS = behaviorcontroller.getMemory(MemoryModuleType.VISIBLE_MOBS).orElse(null); -+ if (inLOS != null) { -+ double maxRangeSquared = this.getMaxRange(); -+ for (int index = 0, len = inLOS.size(); index < len; ++index) { -+ EntityLiving entity = inLOS.get(index); -+ if (!this.canTarget(entity)) { -+ continue; -+ } -+ double distance = entity.getDistanceSquared(entityliving.locX(), entityliving.locY(), entityliving.locZ()); -+ if (distance > maxRangeSquared) { -+ continue; -+ } -+ behaviorcontroller.setMemory(MemoryModuleType.INTERACTION_TARGET, entity); // Tuinity - decompile fix -+ behaviorcontroller.setMemory(MemoryModuleType.LOOK_TARGET, (new BehaviorPositionEntity(entity, true))); // Tuinity - decompile fix -+ break; -+ } -+ } -+ // Tuinity end - remove streams - } - -+ private final boolean canTarget(EntityLiving entityliving) { return this.a(entityliving); } // Tuinity - OBFHELPER - private boolean a(EntityLiving entityliving) { - return this.b.equals(entityliving.getEntityType()) && this.d.test(entityliving); - } -diff --git a/src/main/java/net/minecraft/server/BiomeBase.java b/src/main/java/net/minecraft/server/BiomeBase.java -index 0854ac9ef586b378420d9899f3afd2755e6f9f33..3fc101552e3c229076c91a1cfa45206b4cc7a04c 100644 ---- a/src/main/java/net/minecraft/server/BiomeBase.java -+++ b/src/main/java/net/minecraft/server/BiomeBase.java -@@ -145,14 +145,33 @@ public final class BiomeBase { - } - - public boolean a(IWorldReader iworldreader, BlockPosition blockposition, boolean flag) { -- if (this.getAdjustedTemperature(blockposition) >= 0.15F) { -+ // Tuinity start - add chunk parameter and lazily get biome -+ return canTurnWaterIntoIce(iworldreader, blockposition, flag, null, new BiomeBase[] { this }); -+ } -+ public static boolean canTurnWaterIntoIce(IWorldReader iworldreader, BlockPosition blockposition, boolean flag, IChunkAccess chunk, BiomeBase[] biomeAbove) { -+ // Tuinity end - add chunk parameter and lazily get biome -+ if (false && biomeAbove[0].getAdjustedTemperature(blockposition) >= 0.15F) { // Tuinity - move this down, this check is expensive - return false; - } else { - if (blockposition.getY() >= 0 && blockposition.getY() < 256 && iworldreader.getBrightness(EnumSkyBlock.BLOCK, blockposition) < 10) { -- IBlockData iblockdata = iworldreader.getType(blockposition); -- Fluid fluid = iworldreader.getFluid(blockposition); -+ // Tuinity start - add chunk parameter -+ if (chunk == null) { -+ chunk = iworldreader.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ } -+ // Tuinity end - add chunk parameter -+ IBlockData iblockdata = chunk.getType(blockposition); // Tuinity - skip chunk lookup, we got the chunk -+ Fluid fluid = iblockdata.getFluid(); // Tuinity - skip another block lookup, we have the blockdata - - if (fluid.getType() == FluidTypes.WATER && iblockdata.getBlock() instanceof BlockFluids) { -+ // Tuinity start - moved down from top, only run when we actually encounter water -+ if (biomeAbove[0] == null) { -+ // lazily-get biome -+ biomeAbove[0] = iworldreader.getBiome(blockposition.up()); // TODO - avoid blockpos alloc -+ } -+ if (biomeAbove[0].getAdjustedTemperature(blockposition) >= 0.15F) { -+ return false; -+ } -+ // Tuinity end - moved down from top, only run when we actually encounter water - if (!flag) { - return true; - } -@@ -170,13 +189,32 @@ public final class BiomeBase { - } - - public boolean b(IWorldReader iworldreader, BlockPosition blockposition) { -- if (this.getAdjustedTemperature(blockposition) >= 0.15F) { -+ // Tuinity start - add chunk parameter and lazily get biome -+ return canTurnAirIntoSnow(iworldreader, blockposition, null, new BiomeBase[]{ this }); -+ } -+ public static boolean canTurnAirIntoSnow(IWorldReader iworldreader, BlockPosition blockposition, IChunkAccess chunk, BiomeBase[] biomeAbove) { -+ // Tuinity end - add chunk parameter and lazily get biome -+ if (false && biomeAbove[0].getAdjustedTemperature(blockposition) >= 0.15F) { // Tuinity - move this down, this check is expensive - return false; - } else { - if (blockposition.getY() >= 0 && blockposition.getY() < 256 && iworldreader.getBrightness(EnumSkyBlock.BLOCK, blockposition) < 10) { -- IBlockData iblockdata = iworldreader.getType(blockposition); -+ // Tuinity start - add chunk parameter -+ if (chunk == null) { -+ chunk = iworldreader.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ } -+ // Tuinity end - add chunk parameter -+ IBlockData iblockdata = chunk.getType(blockposition); // Tuinity - skip chunk lookup, we got the chunk - - if (iblockdata.isAir() && Blocks.SNOW.getBlockData().canPlace(iworldreader, blockposition)) { -+ // Tuinity start - moved down from top, only run when we actually encounter water -+ if (biomeAbove[0] == null) { -+ // lazily-get biome -+ biomeAbove[0] = iworldreader.getBiome(blockposition.up()); // TODO - avoid blockpos alloc -+ } -+ if (biomeAbove[0].getAdjustedTemperature(blockposition) >= 0.15F) { -+ return false; -+ } -+ // Tuinity end - moved down from top, only run when we actually encounter water - return true; - } - } -diff --git a/src/main/java/net/minecraft/server/BlockBase.java b/src/main/java/net/minecraft/server/BlockBase.java -index 1f334d63282bd5c23dc3b275a220f09e60c34537..829d4a7508e1656dbdc912096b7eafcf30cbb5b2 100644 ---- a/src/main/java/net/minecraft/server/BlockBase.java -+++ b/src/main/java/net/minecraft/server/BlockBase.java -@@ -295,21 +295,23 @@ public abstract class BlockBase { - - public abstract static class BlockData extends IBlockDataHolder { - -- private final int b; -- private final boolean e; -+ private final int b; public final int getEmittedLight() { return this.b; } // Tuinity - OBFHELPER -+ private final boolean e; public final boolean isTransparentOnSomeFaces() { return this.e; } // Tuinity - OBFHELPER - private final boolean f; - private final Material g; - private final MaterialMapColor h; - public final float strength; - private final boolean j; -- private final boolean k; -+ private final boolean k; public final boolean isOpaque() { return this.k; } // Tuinity - OBFHELPER - private final BlockBase.e l; - private final BlockBase.e m; - private final BlockBase.e n; - private final BlockBase.e o; - private final BlockBase.e p; - @Nullable -- protected BlockBase.BlockData.Cache a; -+ protected BlockBase.BlockData.Cache a; protected final BlockBase.BlockData.Cache getShapeCache() { return this.a; } // Tuinity - OBFHELPER -+ public PathType staticPathType; // Tuinity - cache static path types -+ public PathType neighbourOverridePathType; // Tuinity - cache static path types - - protected BlockData(Block block, ImmutableMap, Comparable> immutablemap, MapCodec mapcodec) { - super(block, immutablemap, mapcodec); -@@ -328,6 +330,7 @@ public abstract class BlockBase { - this.n = blockbase_info.s; - this.o = blockbase_info.t; - this.p = blockbase_info.u; -+ this.conditionallyFullOpaque = this.isOpaque() & this.isTransparentOnSomeFaces(); // Tuinity - } - // Paper start - impl cached craft block data, lazy load to fix issue with loading at the wrong time - private org.bukkit.craftbukkit.block.data.CraftBlockData cachedCraftBlockData; -@@ -343,12 +346,62 @@ public abstract class BlockBase { - protected Fluid fluid; - // Paper end - -+ // Tuinity start - micro the hell out of this call -+ protected boolean shapeExceedsCube = true; -+ public final boolean shapeExceedsCube() { -+ return this.shapeExceedsCube; -+ } -+ // Tuinity end -+ -+ // Tuinity start -+ protected int opacityIfCached = -1; -+ // ret -1 if opacity is dynamic, or -1 if the block is conditionally full opaque, else return opacity in [0, 15] -+ public final int getOpacityIfCached() { -+ return this.opacityIfCached; -+ } -+ -+ protected final boolean conditionallyFullOpaque; -+ public final boolean isConditionallyFullOpaque() { -+ return this.conditionallyFullOpaque; -+ } -+ // Tuinity end -+ - public void a() { - this.fluid = this.getBlock().d(this.p()); // Paper - moved from getFluid() - this.isTicking = this.getBlock().isTicking(this.p()); // Paper - moved from isTicking() - if (!this.getBlock().o()) { - this.a = new BlockBase.BlockData.Cache(this.p()); - } -+ this.shapeExceedsCube = this.a == null || this.a.c; // Tuinity - moved from actual method to here -+ this.staticPathType = null; // Tuinity - cache static path type -+ this.neighbourOverridePathType = null; // Tuinity - cache static path types -+ this.opacityIfCached = this.a == null || this.isConditionallyFullOpaque() ? -1 : this.a.getOpacity(); // Tuinity - cache opacity for light -+ // Tuinity start - optimise culling shape cache for light -+ if (this.a != null && this.a.getCullingShapeCache() != null) { -+ for (int i = 0, len = this.a.getCullingShapeCache().length; i < len; ++i) { -+ VoxelShape face = this.a.getCullingShapeCache()[i].simplify(); -+ if (face.isEmpty()) { -+ this.a.getCullingShapeCache()[i] = VoxelShapes.getEmptyShape(); -+ continue; -+ } -+ List boxes = face.getBoundingBoxesRepresentation(); -+ if (boxes.size() == 1) { -+ AxisAlignedBB boundingBox = boxes.get(0); -+ if (boundingBox.equals(VoxelShapes.optimisedFullCube.aabb)) { -+ this.a.getCullingShapeCache()[i] = VoxelShapes.fullCube(); -+ } else { -+ this.a.getCullingShapeCache()[i] = VoxelShapes.of(boundingBox); -+ if (!(this.a.getCullingShapeCache()[i] instanceof com.tuinity.tuinity.voxel.AABBVoxelShape) && -+ this.a.getCullingShapeCache()[i].getBoundingBoxesRepresentation().size() == 1) { -+ this.a.getCullingShapeCache()[i] = new com.tuinity.tuinity.voxel.AABBVoxelShape(boundingBox); -+ } -+ } -+ continue; -+ } -+ this.a.getCullingShapeCache()[i] = face; -+ } -+ } -+ // Tuinity end - optimise culling shape cache for light - - } - -@@ -372,10 +425,12 @@ public abstract class BlockBase { - return this.a != null ? this.a.g : this.getBlock().b(this.p(), iblockaccess, blockposition); - } - -+ public final int getOpacity(IBlockAccess iblockaccess, BlockPosition blockposition) { return this.b(iblockaccess, blockposition); } // Tuinity - OBFHELPER - public int b(IBlockAccess iblockaccess, BlockPosition blockposition) { - return this.a != null ? this.a.h : this.getBlock().f(this.p(), iblockaccess, blockposition); - } - -+ public final VoxelShape getCullingFace(IBlockAccess iblockaccess, BlockPosition blockposition, EnumDirection enumdirection) { return this.a(iblockaccess, blockposition, enumdirection); } // Tuinity - OBFHELPER - public VoxelShape a(IBlockAccess iblockaccess, BlockPosition blockposition, EnumDirection enumdirection) { - return this.a != null && this.a.i != null ? this.a.i[enumdirection.ordinal()] : VoxelShapes.a(this.c(iblockaccess, blockposition), enumdirection); - } -@@ -385,7 +440,7 @@ public abstract class BlockBase { - } - - public final boolean d() { // Paper -- return this.a == null || this.a.c; -+ return this.shapeExceedsCube; // Tuinity - moved into shape cache init - } - - public final boolean e() { // Paper -@@ -675,9 +730,9 @@ public abstract class BlockBase { - private static final int f = EnumBlockSupport.values().length; - protected final boolean a; - private final boolean g; -- private final int h; -+ private final int h; private final int getOpacity() { return this.h; } // Tuinity - OBFHELPER - @Nullable -- private final VoxelShape[] i; -+ private final VoxelShape[] i; private final VoxelShape[] getCullingShapeCache () { return this.i; } // Tuinity - OBFHELPER - protected final VoxelShape b; - protected final boolean c; - private final boolean[] j; -diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java -index 2d887af902a33b0e28d8f0a6ac2e59c815a7856e..2291135eaef64c403183724cb6e413cd7e472672 100644 ---- a/src/main/java/net/minecraft/server/BlockPosition.java -+++ b/src/main/java/net/minecraft/server/BlockPosition.java -@@ -449,10 +449,10 @@ public class BlockPosition extends BaseBlockPosition { +diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java +index eb67af795dd716d9f92ac32843accc1ec4efd647..8edc279e7a3fdfb7e10718f1deee34b7e3fb2f28 100644 +--- a/src/main/java/net/minecraft/core/BlockPosition.java ++++ b/src/main/java/net/minecraft/core/BlockPosition.java +@@ -455,10 +455,10 @@ public class BlockPosition extends BaseBlockPosition { } public final BlockPosition.MutableBlockPosition setValues(int i, int j, int k) { return d(i, j, k);} // Paper - OBFHELPER @@ -10278,7 +10225,7 @@ index 2d887af902a33b0e28d8f0a6ac2e59c815a7856e..2291135eaef64c403183724cb6e413cd return this; } -@@ -462,12 +462,18 @@ public class BlockPosition extends BaseBlockPosition { +@@ -468,12 +468,18 @@ public class BlockPosition extends BaseBlockPosition { } public final BlockPosition.MutableBlockPosition setValues(final BaseBlockPosition baseblockposition) { return this.g(baseblockposition); } // Paper - OBFHELPER @@ -10301,7 +10248,7 @@ index 2d887af902a33b0e28d8f0a6ac2e59c815a7856e..2291135eaef64c403183724cb6e413cd } public BlockPosition.MutableBlockPosition a(EnumAxisCycle enumaxiscycle, int i, int j, int k) { -@@ -482,8 +488,11 @@ public class BlockPosition extends BaseBlockPosition { +@@ -488,8 +494,11 @@ public class BlockPosition extends BaseBlockPosition { return this.d(baseblockposition.getX() + i, baseblockposition.getY() + j, baseblockposition.getZ() + k); } @@ -10315,7 +10262,7 @@ index 2d887af902a33b0e28d8f0a6ac2e59c815a7856e..2291135eaef64c403183724cb6e413cd } public BlockPosition.MutableBlockPosition c(EnumDirection enumdirection, int i) { -@@ -511,21 +520,30 @@ public class BlockPosition extends BaseBlockPosition { +@@ -517,21 +526,30 @@ public class BlockPosition extends BaseBlockPosition { } } @@ -10356,576 +10303,1282 @@ index 2d887af902a33b0e28d8f0a6ac2e59c815a7856e..2291135eaef64c403183724cb6e413cd @Override public BlockPosition immutableCopy() { -diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java -index 3bcd63a754538ccfc5965207a8fc79faa31925c0..8e59a794f6190930cb7bb81a2fe1a1d374dacce7 100644 ---- a/src/main/java/net/minecraft/server/Chunk.java -+++ b/src/main/java/net/minecraft/server/Chunk.java -@@ -91,6 +91,158 @@ public class Chunk implements IChunkAccess { - private final int[] inventoryEntityCounts = new int[16]; +diff --git a/src/main/java/net/minecraft/core/EnumDirection.java b/src/main/java/net/minecraft/core/EnumDirection.java +index 703bdefeb615ef8d15b428a893b5e4939d726f13..7918d830a4aef09c9f517284e83a9376299116ad 100644 +--- a/src/main/java/net/minecraft/core/EnumDirection.java ++++ b/src/main/java/net/minecraft/core/EnumDirection.java +@@ -174,8 +174,8 @@ public enum EnumDirection implements INamable { + return EnumDirection.q[MathHelper.a(i % EnumDirection.q.length)]; + } + +- @Nullable +- public static EnumDirection a(int i, int j, int k) { ++ @Nullable public static EnumDirection from(int i, int j, int k) { return a(i, j, k); } // Tuinity - OBFHELPER ++ @Nullable public static EnumDirection a(int i, int j, int k) { + return (EnumDirection) EnumDirection.r.get(BlockPosition.a(i, j, k)); + } + +diff --git a/src/main/java/net/minecraft/core/SectionPosition.java b/src/main/java/net/minecraft/core/SectionPosition.java +index 7d9a16eb81288b74425319c60525f57c98ad3b69..427413c668865e1660f1d81daf6a3385f08a0e38 100644 +--- a/src/main/java/net/minecraft/core/SectionPosition.java ++++ b/src/main/java/net/minecraft/core/SectionPosition.java +@@ -10,7 +10,7 @@ import net.minecraft.world.level.ChunkCoordIntPair; + + public class SectionPosition extends BaseBlockPosition { + +- private SectionPosition(int i, int j, int k) { ++ public SectionPosition(int i, int j, int k) { // Tuinity - private -> public + super(i, j, k); + } + +diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java +index f86f430598026a3a7e27fb8d40cfc5fe7b9b845d..e101b1dccec98d5c7b9ee9a2c8aa2e3b911de652 100644 +--- a/src/main/java/net/minecraft/network/NetworkManager.java ++++ b/src/main/java/net/minecraft/network/NetworkManager.java +@@ -45,6 +45,8 @@ import org.apache.logging.log4j.Logger; + import org.apache.logging.log4j.Marker; + import org.apache.logging.log4j.MarkerManager; + ++import io.netty.util.concurrent.AbstractEventExecutor; // Tuinity ++ + public class NetworkManager extends SimpleChannelInboundHandler> { + + private static final Logger LOGGER = LogManager.getLogger(); +@@ -89,6 +91,61 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + public EnumProtocol protocol; // Paper end -+ // Tuinity start - optimise hard collision handling -+ // Tuinity - optimised entity slices ++ // Tuinity start - allow controlled flushing ++ volatile boolean canFlush = true; ++ private final java.util.concurrent.atomic.AtomicInteger packetWrites = new java.util.concurrent.atomic.AtomicInteger(); ++ private int flushPacketsStart; ++ private final Object flushLock = new Object(); + -+ public final void getHardCollidingEntities(@Nullable Entity entity, AxisAlignedBB axisalignedbb, List into, Predicate predicate) { -+ this.entitySlicesManager.getHardCollidingEntities(entity, axisalignedbb, into, predicate); // Tuinity -+ } -+ // Tuinity end - optimise hard collision handling -+ // Tuinity start - rewrite light engine -+ protected volatile com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] blockNibbles = com.tuinity.tuinity.chunk.light.StarLightEngine.getFilledEmptyLight(); -+ protected volatile com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] skyNibbles = com.tuinity.tuinity.chunk.light.StarLightEngine.getFilledEmptyLight(); -+ protected volatile boolean[] skyEmptinessMap; -+ protected volatile boolean[] blockEmptinessMap; -+ -+ @Override -+ public com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] getBlockNibbles() { -+ return this.blockNibbles; -+ } -+ -+ @Override -+ public void setBlockNibbles(com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] nibbles) { -+ this.blockNibbles = nibbles; -+ } -+ -+ @Override -+ public com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] getSkyNibbles() { -+ return this.skyNibbles; -+ } -+ -+ @Override -+ public void setSkyNibbles(com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] nibbles) { -+ this.skyNibbles = nibbles; -+ } -+ -+ @Override -+ public boolean[] getSkyEmptinessMap() { -+ return this.skyEmptinessMap; -+ } -+ -+ @Override -+ public void setSkyEmptinessMap(boolean[] emptinessMap) { -+ this.skyEmptinessMap = emptinessMap; -+ } -+ -+ @Override -+ public boolean[] getBlockEmptinessMap() { -+ return this.blockEmptinessMap; -+ } -+ -+ @Override -+ public void setBlockEmptinessMap(boolean[] emptinessMap) { -+ this.blockEmptinessMap = emptinessMap; -+ } -+ // Tuinity end - rewrite light engine -+ -+ // Tuinity start - optimised entity slices -+ protected final com.tuinity.tuinity.world.ChunkEntitySlices entitySlicesManager; -+ -+ public final boolean hasEntitiesMaybe(Class clazz) { // Tuinity start -+ return true; // Tuinity end -+ } -+ -+ public final void getEntitiesClass(Class clazz, Entity entity, AxisAlignedBB boundingBox, Predicate predicate, List into) { -+ this.entitySlicesManager.getEntities((Class)clazz, entity, boundingBox, (List)into, (Predicate)predicate); // Tuinity -+ } -+ // Tuinity end - optimised entity slices -+ -+ // Tuinity start - optimise checkDespawn -+ private boolean playerGeneralAreaCacheSet; -+ private com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playerGeneralAreaCache; -+ -+ public com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getPlayerGeneralAreaCache() { -+ if (!this.playerGeneralAreaCacheSet) { -+ this.updateGeneralAreaCache(); ++ public void disableAutomaticFlush() { ++ synchronized (this.flushLock) { ++ this.flushPacketsStart = this.packetWrites.get(); // must be volatile and before canFlush = false ++ this.canFlush = false; + } -+ return this.playerGeneralAreaCache; + } + -+ void updateGeneralAreaCache() { -+ this.updateGeneralAreaCache(((WorldServer)this.world).getChunkProvider().playerChunkMap.playerGeneralAreaMap.getObjectsInRange(this.coordinateKey)); -+ } -+ -+ void updateGeneralAreaCache(com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet value) { -+ this.playerGeneralAreaCacheSet = true; -+ this.playerGeneralAreaCache = value; -+ } -+ -+ public EntityPlayer findNearestPlayer(double sourceX, double sourceY, double sourceZ, double maxRange, Predicate predicate) { -+ if (!this.playerGeneralAreaCacheSet) { -+ this.updateGeneralAreaCache(); -+ } -+ -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet nearby = this.playerGeneralAreaCache; -+ -+ if (nearby == null) { -+ return null; -+ } -+ -+ Object[] backingSet = nearby.getBackingSet(); -+ double closestDistance = maxRange < 0.0 ? Double.MAX_VALUE : maxRange * maxRange; -+ EntityPlayer closest = null; -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object _player = backingSet[i]; -+ if (!(_player instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)_player; -+ -+ double distance = player.getDistanceSquared(sourceX, sourceY, sourceZ); -+ if (distance < closestDistance && predicate.test(player)) { -+ closest = player; -+ closestDistance = distance; ++ public void enableAutomaticFlush() { ++ synchronized (this.flushLock) { ++ this.canFlush = true; ++ if (this.packetWrites.get() != this.flushPacketsStart) { // must be after canFlush = true ++ this.flush(); // only make the flush call if we need to + } + } -+ -+ return closest; + } + -+ public void getNearestPlayers(double sourceX, double sourceY, double sourceZ, Predicate predicate, double range, List ret) { -+ if (!this.playerGeneralAreaCacheSet) { -+ this.updateGeneralAreaCache(); ++ private final void flush() { ++ if (this.channel.eventLoop().inEventLoop()) { ++ this.channel.flush(); ++ } else { ++ this.channel.eventLoop().execute(() -> { ++ this.channel.flush(); ++ }); + } -+ -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet nearby = this.playerGeneralAreaCache; -+ -+ if (nearby == null) { ++ } ++ // Tuinity end - allow controlled flushing ++ // Tuinity start - add pending task queue ++ private final Queue pendingTasks = new java.util.concurrent.ConcurrentLinkedQueue<>(); ++ public void execute(final Runnable run) { ++ if (!this.channel.isRegistered()) { ++ run.run(); + return; + } -+ -+ double rangeSquared = range * range; -+ -+ Object[] backingSet = nearby.getBackingSet(); -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object _player = backingSet[i]; -+ if (!(_player instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)_player; -+ -+ if (range >= 0.0) { -+ double distanceSquared = player.getDistanceSquared(sourceX, sourceY, sourceZ); -+ if (distanceSquared > rangeSquared) { -+ continue; ++ final boolean queue = !this.packetQueue.isEmpty(); ++ if (!queue) { ++ this.channel.eventLoop().execute(run); ++ } else { ++ this.pendingTasks.add(run); ++ if (this.packetQueue.isEmpty()) { ++ // something flushed async, dump tasks now ++ Runnable r; ++ while ((r = this.pendingTasks.poll()) != null) { ++ this.channel.eventLoop().execute(r); + } + } -+ -+ if (predicate == null || predicate.test(player)) { -+ ret.add(player); -+ } + } + } -+ // Tuinity end - optimise checkDespawn ++ // Tuinity end - add pending task queue + - public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage, ChunkConverter chunkconverter, TickList ticklist, TickList ticklist1, long i, @Nullable ChunkSection[] achunksection, @Nullable Consumer consumer) { - this.sections = new ChunkSection[16]; - this.e = Maps.newHashMap(); -@@ -134,6 +286,7 @@ public class Chunk implements IChunkAccess { - - // CraftBukkit start - this.bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this); -+ this.entitySlicesManager = new com.tuinity.tuinity.world.ChunkEntitySlices(this.world, this.loc.x, this.loc.z, 0, 15); // TODO update for 1.17 // Tuinity + public NetworkManager(EnumProtocolDirection enumprotocoldirection) { + this.h = enumprotocoldirection; + } +@@ -163,8 +220,64 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + if (net.minecraft.server.MinecraftServer.getServer().isDebugging()) throwable.printStackTrace(); // Spigot } - public org.bukkit.Chunk bukkitChunk; -@@ -207,12 +360,12 @@ public class Chunk implements IChunkAccess { - PlayerChunkMap chunkMap = chunkProviderServer.playerChunkMap; - // this code handles the addition of ticking tickets - the distance map handles the removal - if (!areNeighboursLoaded(bitsetBefore, 2) && areNeighboursLoaded(bitsetAfter, 2)) { -- if (chunkMap.playerViewDistanceTickMap.getObjectsInRange(this.coordinateKey) != null) { -+ if (chunkMap.playerChunkManager.tickMap.getObjectsInRange(this.coordinateKey) != null) { // Tuinity - replace old player chunk loading system - // now we're ready for entity ticking - chunkProviderServer.serverThreadQueue.execute(() -> { - // double check that this condition still holds. -- if (Chunk.this.areNeighboursLoaded(2) && chunkMap.playerViewDistanceTickMap.getObjectsInRange(Chunk.this.coordinateKey) != null) { -- chunkProviderServer.addTicketAtLevel(TicketType.PLAYER, Chunk.this.loc, 31, Chunk.this.loc); // 31 -> entity ticking, TODO check on update -+ if (Chunk.this.areNeighboursLoaded(2) && chunkMap.playerChunkManager.tickMap.getObjectsInRange(Chunk.this.coordinateKey) != null) { // Tuinity - replace old player chunk loading system -+ chunkMap.playerChunkManager.onChunkPlayerTickReady(this.loc.x, this.loc.z); // Tuinity - replace old player chunk loading system - } - }); - } -@@ -220,31 +373,7 @@ public class Chunk implements IChunkAccess { - - // this code handles the chunk sending - if (!areNeighboursLoaded(bitsetBefore, 1) && areNeighboursLoaded(bitsetAfter, 1)) { -- if (chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(this.coordinateKey) != null) { -- // now we're ready to send -- chunkMap.mailboxMain.a(ChunkTaskQueueSorter.a(chunkMap.getUpdatingChunk(this.coordinateKey), (() -> { // Copied frm PlayerChunkMap -- // double check that this condition still holds. -- if (!Chunk.this.areNeighboursLoaded(1)) { -- return; -- } -- com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(Chunk.this.coordinateKey); -- if (inRange == null) { -- return; -- } -- -- // broadcast -- Object[] backingSet = inRange.getBackingSet(); -- Packet[] chunkPackets = new Packet[10]; -- for (int index = 0, len = backingSet.length; index < len; ++index) { -- Object temp = backingSet[index]; -- if (!(temp instanceof EntityPlayer)) { -- continue; -- } -- EntityPlayer player = (EntityPlayer)temp; -- chunkMap.sendChunk(player, chunkPackets, Chunk.this); -- } -- }))); -- } -+ chunkMap.playerChunkManager.onChunkSendReady(this.loc.x, this.loc.z); // Tuinity - replace old player chunk loading system - } - // Paper end - no-tick view distance - } -@@ -298,6 +427,12 @@ public class Chunk implements IChunkAccess { - - public Chunk(World world, ProtoChunk protochunk) { - this(world, protochunk.getPos(), protochunk.getBiomeIndex(), protochunk.p(), protochunk.n(), protochunk.o(), protochunk.getInhabitedTime(), protochunk.getSections(), (Consumer) null); -+ // Tuinity start - copy over protochunk light -+ this.setBlockNibbles(protochunk.getBlockNibbles()); -+ this.setSkyNibbles(protochunk.getSkyNibbles()); -+ this.setSkyEmptinessMap(protochunk.getSkyEmptinessMap()); -+ this.setBlockEmptinessMap(protochunk.getBlockEmptinessMap()); -+ // Tuinity end - copy over protochunk light - Iterator iterator = protochunk.y().iterator(); - - while (iterator.hasNext()) { -@@ -594,8 +729,9 @@ public class Chunk implements IChunkAccess { - entity.chunkX = this.loc.x; - entity.chunkY = k; - entity.chunkZ = this.loc.z; -- this.entities.add(entity); // Paper - per chunk entity list -- this.entitySlices[k].add(entity); -+ this.entities.add(entity); // Tuinity -+ this.entitySlices[k].add(entity); // Tuinity -+ this.entitySlicesManager.addEntity(entity, k); // Tuinity - // Paper start - if (entity instanceof EntityItem) { - itemCounts[k]++; -@@ -633,7 +769,8 @@ public class Chunk implements IChunkAccess { - entity.entitySlice = null; - entity.inChunk = false; - } -- if (!this.entitySlices[i].remove(entity)) { -+ this.entitySlicesManager.removeEntity(entity, i); // Tuinity -+ if (!this.entitySlices[i].remove(entity)) { // Tuinity - optimise hard colliding entities // Tuinity - entities by class // Tuinity ++ // Tuinity start - packet limiter ++ protected final Object PACKET_LIMIT_LOCK = new Object(); ++ protected final com.tuinity.tuinity.util.IntervalledCounter allPacketCounts = com.tuinity.tuinity.config.TuinityConfig.allPacketsLimit != null ? new com.tuinity.tuinity.util.IntervalledCounter( ++ (long)(com.tuinity.tuinity.config.TuinityConfig.allPacketsLimit.packetLimitInterval * 1.0e9) ++ ) : null; ++ protected final java.util.Map>, com.tuinity.tuinity.util.IntervalledCounter> packetSpecificLimits = new java.util.HashMap<>(); ++ ++ private boolean stopReadingPackets; ++ private void killForPacketSpam() { ++ this.sendPacket(new PacketPlayOutKickDisconnect(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(com.tuinity.tuinity.config.TuinityConfig.kickMessage, true)[0]), (future) -> { ++ this.close(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(com.tuinity.tuinity.config.TuinityConfig.kickMessage, true)[0]); ++ }); ++ this.stopReading(); ++ this.stopReadingPackets = true; ++ } ++ // Tuinity end - packet limiter ++ + protected void channelRead0(ChannelHandlerContext channelhandlercontext, Packet packet) throws Exception { + if (this.channel.isOpen()) { ++ // Tuinity start - packet limiter ++ if (this.stopReadingPackets) { ++ return; ++ } ++ if (this.allPacketCounts != null || ++ com.tuinity.tuinity.config.TuinityConfig.packetSpecificLimits.containsKey(packet.getClass())) { ++ long time = System.nanoTime(); ++ synchronized (PACKET_LIMIT_LOCK) { ++ if (this.allPacketCounts != null) { ++ this.allPacketCounts.updateAndAdd(1, time); ++ if (this.allPacketCounts.getRate() >= com.tuinity.tuinity.config.TuinityConfig.allPacketsLimit.maxPacketRate) { ++ this.killForPacketSpam(); ++ return; ++ } ++ } ++ ++ for (Class check = packet.getClass(); check != Object.class; check = check.getSuperclass()) { ++ com.tuinity.tuinity.config.TuinityConfig.PacketLimit packetSpecificLimit = ++ com.tuinity.tuinity.config.TuinityConfig.packetSpecificLimits.get(check); ++ if (packetSpecificLimit == null) { ++ continue; ++ } ++ com.tuinity.tuinity.util.IntervalledCounter counter = this.packetSpecificLimits.computeIfAbsent((Class)check, (clazz) -> { ++ return new com.tuinity.tuinity.util.IntervalledCounter((long)(packetSpecificLimit.packetLimitInterval * 1.0e9)); ++ }); ++ counter.updateAndAdd(1, time); ++ if (counter.getRate() >= packetSpecificLimit.maxPacketRate) { ++ switch (packetSpecificLimit.violateAction) { ++ case DROP: ++ return; ++ case KICK: ++ this.killForPacketSpam(); ++ return; ++ } ++ } ++ } ++ } ++ } ++ // Tuinity end - packet limiter + try { + a(packet, this.packetListener); + } catch (CancelledPacketHandleException cancelledpackethandleexception) { +@@ -240,7 +353,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + MCUtil.isMainThread() && packet.isReady() && this.packetQueue.isEmpty() && + (packet.getExtraPackets() == null || packet.getExtraPackets().isEmpty()) + ))) { +- this.dispatchPacket(packet, genericfuturelistener); ++ this.writePacket(packet, genericfuturelistener, null); // Tuinity return; } - if (entity instanceof EntityItem) { -@@ -812,6 +949,7 @@ public class Chunk implements IChunkAccess { - // Paper end - neighbour cache - org.bukkit.Server server = this.world.getServer(); - ((WorldServer)this.world).getChunkProvider().addLoadedChunk(this); // Paper -+ ((WorldServer)this.world).getChunkProvider().playerChunkMap.playerChunkManager.onChunkLoad(this.loc.x, this.loc.z); // Tuinity - rewrite player chunk management - if (server != null) { - /* - * If it's a new world, the first few chunks are generated inside -@@ -876,116 +1014,18 @@ public class Chunk implements IChunkAccess { - } + // write the packets to the queue, then flush - antixray hooks there already +@@ -266,6 +379,14 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - public void a(@Nullable Entity entity, AxisAlignedBB axisalignedbb, List list, @Nullable Predicate predicate) { -- org.spigotmc.AsyncCatcher.catchOp("Chunk getEntities call"); // Spigot -- int i = MathHelper.floor((axisalignedbb.minY - 2.0D) / 16.0D); -- int j = MathHelper.floor((axisalignedbb.maxY + 2.0D) / 16.0D); -- -- i = MathHelper.clamp(i, 0, this.entitySlices.length - 1); -- j = MathHelper.clamp(j, 0, this.entitySlices.length - 1); -- -- for (int k = i; k <= j; ++k) { -- List entityslice = this.entitySlices[k]; // Spigot -- List list1 = entityslice; // Spigot -- int l = list1.size(); -- -- for (int i1 = 0; i1 < l; ++i1) { -- Entity entity1 = (Entity) list1.get(i1); -- if (entity1.shouldBeRemoved) continue; // Paper -- -- if (entity1.getBoundingBox().c(axisalignedbb) && entity1 != entity) { -- if (predicate == null || predicate.test(entity1)) { -- list.add(entity1); -- } -- -- if (entity1 instanceof EntityEnderDragon) { -- EntityComplexPart[] aentitycomplexpart = ((EntityEnderDragon) entity1).eJ(); -- int j1 = aentitycomplexpart.length; -- -- for (int k1 = 0; k1 < j1; ++k1) { -- EntityComplexPart entitycomplexpart = aentitycomplexpart[k1]; -- -- if (entitycomplexpart != entity && entitycomplexpart.getBoundingBox().c(axisalignedbb) && (predicate == null || predicate.test(entitycomplexpart))) { -- list.add(entitycomplexpart); -- } -- } -- } -- } -- } -- } -+ this.entitySlicesManager.getEntities(entity, axisalignedbb, list, predicate); // Tuinity - optimised entity slices - - } - - public void a(@Nullable EntityTypes entitytypes, AxisAlignedBB axisalignedbb, List list, Predicate predicate) { -- org.spigotmc.AsyncCatcher.catchOp("Chunk getEntities call"); // Spigot -- int i = MathHelper.floor((axisalignedbb.minY - 2.0D) / 16.0D); -- int j = MathHelper.floor((axisalignedbb.maxY + 2.0D) / 16.0D); -- -- i = MathHelper.clamp(i, 0, this.entitySlices.length - 1); -- j = MathHelper.clamp(j, 0, this.entitySlices.length - 1); -- -- for (int k = i; k <= j; ++k) { -- Iterator iterator = this.entitySlices[k].iterator(); // Spigot -- -- // Paper start - Don't search for inventories if we have none, and that is all we want -- /* -- * We check if they want inventories by seeing if it is the static `IEntitySelector.d` -- * -- * Make sure the inventory selector stays in sync. -- * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` -- */ -- if (predicate == IEntitySelector.isInventory() && inventoryEntityCounts[k] <= 0) continue; -- while (iterator.hasNext()) { -- T entity = (T) iterator.next(); // CraftBukkit - decompile error -- if (entity.shouldBeRemoved) continue; // Paper -- -- if ((entitytypes == null || entity.getEntityType() == entitytypes) && entity.getBoundingBox().c(axisalignedbb) && predicate.test(entity)) { -- list.add(entity); -- } -- } -- } -+ this.entitySlicesManager.getEntities(entitytypes, axisalignedbb, (List)list, (Predicate)predicate); // Tuinity - optimised entity slices - - } - -+ public final void getEntities(Class oclass, AxisAlignedBB axisalignedbb, List list, @Nullable Predicate predicate) { this.a(oclass, axisalignedbb, list, predicate); } // Tuinity - OBFHELPER - public void a(Class oclass, AxisAlignedBB axisalignedbb, List list, @Nullable Predicate predicate) { -- org.spigotmc.AsyncCatcher.catchOp("Chunk getEntities call"); // Spigot -- int i = MathHelper.floor((axisalignedbb.minY - 2.0D) / 16.0D); -- int j = MathHelper.floor((axisalignedbb.maxY + 2.0D) / 16.0D); -- -- i = MathHelper.clamp(i, 0, this.entitySlices.length - 1); -- j = MathHelper.clamp(j, 0, this.entitySlices.length - 1); -- -- // Paper start -- int[] counts; -- if (EntityItem.class.isAssignableFrom(oclass)) { -- counts = itemCounts; -- } else if (IInventory.class.isAssignableFrom(oclass)) { -- counts = inventoryEntityCounts; -- } else { -- counts = null; -- } -- // Paper end -- for (int k = i; k <= j; ++k) { -- if (counts != null && counts[k] <= 0) continue; // Paper - Don't check a chunk if it doesn't have the type we are looking for -- Iterator iterator = this.entitySlices[k].iterator(); // Spigot -- -- // Paper start - Don't search for inventories if we have none, and that is all we want -- /* -- * We check if they want inventories by seeing if it is the static `IEntitySelector.d` -- * -- * Make sure the inventory selector stays in sync. -- * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` -- */ -- if (predicate == IEntitySelector.isInventory() && inventoryEntityCounts[k] <= 0) continue; -- // Paper end -- while (iterator.hasNext()) { -- T t0 = (T) iterator.next(); // CraftBukkit - decompile error -- if (t0.shouldBeRemoved) continue; // Paper -- -- if (oclass.isInstance(t0) && t0.getBoundingBox().c(axisalignedbb) && (predicate == null || predicate.test(t0))) { // Spigot - instance check -- list.add(t0); -- } -- } -- } -+ this.entitySlicesManager.getEntities(oclass, null, axisalignedbb, list, predicate); // Tuinity - optimised entity slices - - } - -diff --git a/src/main/java/net/minecraft/server/ChunkCache.java b/src/main/java/net/minecraft/server/ChunkCache.java -index 8eecdcde510661ec3a13a25a04ba394f6b6dc012..ab1085091fefea3a3fa15f7028bec050d00a6f5e 100644 ---- a/src/main/java/net/minecraft/server/ChunkCache.java -+++ b/src/main/java/net/minecraft/server/ChunkCache.java -@@ -1,5 +1,6 @@ - package net.minecraft.server; - -+import java.util.List; - import java.util.function.Predicate; - import java.util.stream.Stream; - import javax.annotation.Nullable; -@@ -12,6 +13,156 @@ public class ChunkCache implements IBlockAccess, ICollisionAccess { - protected boolean d; - protected final World e; protected final World getWorld() { return e; } // Paper - OBFHELPER - -+ // Tuinity start - optimise pathfinder collision detection -+ @Override -+ public boolean getCubes(Entity entity) { -+ return !this.getCollisionsForBlocksOrWorldBorder(entity, entity.getBoundingBox(), null, true, null); + private void dispatchPacket(Packet packet, @Nullable GenericFutureListener> genericFutureListener) { this.b(packet, genericFutureListener); } // Paper - OBFHELPER + private void b(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { ++ // Tuinity start - add flush parameter ++ this.writePacket(packet, genericfuturelistener, Boolean.TRUE); + } -+ -+ @Override -+ public boolean getCubes(Entity entity, AxisAlignedBB axisalignedbb) { -+ return !this.getCollisionsForBlocksOrWorldBorder(entity, axisalignedbb, null, true, null); -+ } -+ -+ @Override -+ public boolean getCubes(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate) { -+ return !this.getCollisionsForBlocksOrWorldBorder(entity, axisalignedbb, null, true, null); -+ } -+ -+ public boolean getCollisionsForBlocksOrWorldBorder(@Nullable Entity entity, AxisAlignedBB axisalignedbb, List list, -+ boolean collidesWithUnloaded, -+ java.util.function.BiPredicate predicate) { -+ boolean ret = false; -+ final boolean checkOnly = true; -+ -+ if (entity != null) { -+ if (this.getWorldBorder().isAlmostCollidingOnBorder(axisalignedbb)) { -+ if (checkOnly) { -+ return true; -+ } else { -+ VoxelShapes.addBoxesTo(this.getWorldBorder().getCollisionShape(), list); -+ ret = true; -+ } -+ } -+ } -+ -+ int minBlockX = MathHelper.floor(axisalignedbb.minX - MCUtil.COLLISION_EPSILON) - 1; -+ int maxBlockX = MathHelper.floor(axisalignedbb.maxX + MCUtil.COLLISION_EPSILON) + 1; -+ -+ int minBlockY = MathHelper.floor(axisalignedbb.minY - MCUtil.COLLISION_EPSILON) - 1; -+ int maxBlockY = MathHelper.floor(axisalignedbb.maxY + MCUtil.COLLISION_EPSILON) + 1; -+ -+ int minBlockZ = MathHelper.floor(axisalignedbb.minZ - MCUtil.COLLISION_EPSILON) - 1; -+ int maxBlockZ = MathHelper.floor(axisalignedbb.maxZ + MCUtil.COLLISION_EPSILON) + 1; ++ private void writePacket(Packet packet, @Nullable GenericFutureListener> genericfuturelistener, Boolean flushConditional) { ++ this.packetWrites.getAndIncrement(); // must be befeore using canFlush ++ boolean effectiveFlush = flushConditional == null ? this.canFlush : flushConditional.booleanValue(); ++ final boolean flush = effectiveFlush || packet instanceof PacketPlayOutKeepAlive || packet instanceof PacketPlayOutKickDisconnect; // no delay for certain packets ++ // Tuinity end - add flush parameter + EnumProtocol enumprotocol = EnumProtocol.a(packet); + EnumProtocol enumprotocol1 = (EnumProtocol) this.channel.attr(NetworkManager.c).get(); + +@@ -288,7 +409,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + try { + // Paper end + +- ChannelFuture channelfuture = this.channel.writeAndFlush(packet); ++ ChannelFuture channelfuture = (flush) ? this.channel.writeAndFlush(packet) : this.channel.write(packet); // Tuinity - add flush parameter + + if (genericfuturelistener != null) { + channelfuture.addListener(genericfuturelistener); +@@ -308,39 +429,83 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + } + // Paper end + } else { +- this.channel.eventLoop().execute(() -> { +- if (enumprotocol != enumprotocol1) { +- this.setProtocol(enumprotocol); +- } ++ // Tuinity start - optimise packets that are not flushed ++ Runnable choice1 = null; ++ AbstractEventExecutor.LazyRunnable choice2 = null; ++ // note: since the type is not dynamic here, we need to actually copy the old executor code ++ // into two branches. On conflict, just re-copy - no changes were made inside the executor code. ++ if (flush) { ++ choice1 = () -> { ++ if (enumprotocol != enumprotocol1) { ++ this.setProtocol(enumprotocol); ++ } + +- // Paper start +- if (!isConnected()) { +- packet.onPacketDispatchFinish(player, null); +- return; +- } +- try { ++ // Paper start ++ if (!isConnected()) { ++ packet.onPacketDispatchFinish(player, null); ++ return; ++ } ++ try { ++ // Paper end ++ ChannelFuture channelfuture1 = (flush) ? this.channel.writeAndFlush(packet) : this.channel.write(packet); // Tuinity - add flush parameter + + -+ BlockPosition.MutableBlockPosition mutablePos = new BlockPosition.MutableBlockPosition(); -+ VoxelShapeCollision collisionShape = null; -+ -+ // special cases: -+ if (minBlockY > 255 || maxBlockY < 0) { -+ // no point in checking -+ return ret; -+ } -+ -+ int minYIterate = Math.max(0, minBlockY); -+ int maxYIterate = Math.min(255, maxBlockY); -+ -+ int minChunkX = minBlockX >> 4; -+ int maxChunkX = maxBlockX >> 4; -+ -+ int minChunkZ = minBlockZ >> 4; -+ int maxChunkZ = maxBlockZ >> 4; -+ -+ // TODO special case single chunk? -+ -+ for (int currChunkZ = minChunkZ; currChunkZ <= maxChunkZ; ++currChunkZ) { -+ int minZ = currChunkZ == minChunkZ ? minBlockZ & 15 : 0; // coordinate in chunk -+ int maxZ = currChunkZ == maxChunkZ ? maxBlockZ & 15 : 15; // coordinate in chunk -+ -+ for (int currChunkX = minChunkX; currChunkX <= maxChunkX; ++currChunkX) { -+ int minX = currChunkX == minChunkX ? minBlockX & 15 : 0; // coordinate in chunk -+ int maxX = currChunkX == maxChunkX ? maxBlockX & 15 : 15; // coordinate in chunk -+ -+ int chunkXGlobalPos = currChunkX << 4; -+ int chunkZGlobalPos = currChunkZ << 4; -+ Chunk chunk = (Chunk)this.getChunkIfLoaded(currChunkX, currChunkZ); -+ -+ if (chunk == null) { -+ if (collidesWithUnloaded) { -+ if (checkOnly) { -+ return true; -+ } else { -+ list.add(AxisAlignedBB.getBoxForChunk(currChunkX, currChunkZ)); -+ ret = true; ++ if (genericfuturelistener != null) { ++ channelfuture1.addListener(genericfuturelistener); + } -+ } -+ continue; -+ } -+ -+ ChunkSection[] sections = chunk.getSections(); -+ -+ // bound y -+ -+ for (int currY = minYIterate; currY <= maxYIterate; ++currY) { -+ ChunkSection section = sections[currY >>> 4]; -+ if (section == null || section.isFullOfAir()) { -+ // empty -+ // skip to next section -+ currY = (currY & ~(15)) + 15; // increment by 15: iterator loop increments by the extra one -+ continue; -+ } -+ -+ DataPaletteBlock blocks = section.blockIds; -+ -+ for (int currZ = minZ; currZ <= maxZ; ++currZ) { -+ for (int currX = minX; currX <= maxX; ++currX) { -+ int localBlockIndex = (currX) | (currZ << 4) | ((currY & 15) << 8); -+ int blockX = currX | chunkXGlobalPos; -+ int blockY = currY; -+ int blockZ = currZ | chunkZGlobalPos; -+ -+ int edgeCount = ((blockX == minBlockX || blockX == maxBlockX) ? 1 : 0) + -+ ((blockY == minBlockY || blockY == maxBlockY) ? 1 : 0) + -+ ((blockZ == minBlockZ || blockZ == maxBlockZ) ? 1 : 0); -+ if (edgeCount == 3) { -+ continue; -+ } -+ -+ IBlockData blockData = blocks.rawGet(localBlockIndex); -+ -+ if ((edgeCount != 1 || blockData.shapeExceedsCube()) && (edgeCount != 2 || blockData.getBlock() == Blocks.MOVING_PISTON)) { -+ mutablePos.setValues(blockX, blockY, blockZ); -+ if (collisionShape == null) { -+ collisionShape = entity == null ? VoxelShapeCollision.a() : VoxelShapeCollision.a(entity); -+ } -+ VoxelShape voxelshape2 = blockData.getCollisionShape(this, mutablePos, collisionShape); -+ if (voxelshape2 != VoxelShapes.getEmptyShape()) { -+ VoxelShape voxelshape3 = voxelshape2.offset((double)blockX, (double)blockY, (double)blockZ); -+ -+ if (predicate != null && !predicate.test(blockData, mutablePos)) { -+ continue; -+ } -+ -+ if (checkOnly) { -+ if (voxelshape3.intersects(axisalignedbb)) { -+ return true; -+ } -+ } else { -+ ret |= VoxelShapes.addBoxesToIfIntersects(voxelshape3, axisalignedbb, list); -+ } -+ } -+ } ++ // Paper start ++ if (packet.hasFinishListener()) { ++ channelfuture1.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); + } ++ // Paper end ++ ++ channelfuture1.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); ++ // Paper start ++ } catch (Exception e) { ++ LOGGER.error("NetworkException: " + player, e); ++ close(new ChatMessage("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; ++ packet.onPacketDispatchFinish(player, null); + } -+ } + // Paper end +- ChannelFuture channelfuture1 = this.channel.writeAndFlush(packet); +- +- +- if (genericfuturelistener != null) { +- channelfuture1.addListener(genericfuturelistener); +- } +- // Paper start +- if (packet.hasFinishListener()) { +- channelfuture1.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); +- } +- // Paper end ++ }; ++ } else { ++ // explicitly declare a variable to make the lambda use the type ++ choice2 = () -> { ++ if (enumprotocol != enumprotocol1) { ++ this.setProtocol(enumprotocol); ++ } + +- channelfuture1.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); +- // Paper start +- } catch (Exception e) { +- LOGGER.error("NetworkException: " + player, e); +- close(new ChatMessage("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; +- packet.onPacketDispatchFinish(player, null); +- } +- // Paper end +- }); ++ // Paper start ++ if (!isConnected()) { ++ packet.onPacketDispatchFinish(player, null); ++ return; ++ } ++ try { ++ // Paper end ++ ChannelFuture channelfuture1 = (flush) ? this.channel.writeAndFlush(packet) : this.channel.write(packet); // Tuinity - add flush parameter ++ ++ ++ if (genericfuturelistener != null) { ++ channelfuture1.addListener(genericfuturelistener); ++ } ++ // Paper start ++ if (packet.hasFinishListener()) { ++ channelfuture1.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); ++ } ++ // Paper end ++ ++ channelfuture1.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); ++ // Paper start ++ } catch (Exception e) { ++ LOGGER.error("NetworkException: " + player, e); ++ close(new ChatMessage("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; ++ packet.onPacketDispatchFinish(player, null); ++ } ++ // Paper end ++ }; + } ++ this.channel.eventLoop().execute(choice1 != null ? choice1 : choice2); ++ // Tuinity end - optimise packets that are not flushed + } + + } +@@ -362,7 +527,10 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + return false; + } + private boolean processQueue() { ++ try { // Tuinity - add pending task queue + if (this.packetQueue.isEmpty()) return true; ++ final boolean needsFlush = this.canFlush; // Tuinity - make only one flush call per sendPacketQueue() call ++ boolean hasWrotePacket = false; + // If we are on main, we are safe here in that nothing else should be processing queue off main anymore + // But if we are not on main due to login/status, the parent is synchronized on packetQueue + java.util.Iterator iterator = this.packetQueue.iterator(); +@@ -370,19 +538,31 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + NetworkManager.QueuedPacket queued = iterator.next(); // poll -> peek + + // Fix NPE (Spigot bug caused by handleDisconnection()) +- if (queued == null) { ++ if (false && queued == null) { // Tuinity - diff on change, this logic is redundant: iterator guarantees ret of an element - on change, hook the flush logic here + return true; + } + + Packet packet = queued.getPacket(); + if (!packet.isReady()) { ++ // Tuinity start - make only one flush call per sendPacketQueue() call ++ if (hasWrotePacket && (needsFlush || this.canFlush)) { ++ this.flush(); ++ } ++ // Tuinity end - make only one flush call per sendPacketQueue() call + return false; + } else { + iterator.remove(); +- this.dispatchPacket(packet, queued.getGenericFutureListener()); ++ this.writePacket(packet, queued.getGenericFutureListener(), (!iterator.hasNext() && (needsFlush || this.canFlush)) ? Boolean.TRUE : Boolean.FALSE); // Tuinity - make only one flush call per sendPacketQueue() call ++ hasWrotePacket = true; // Tuinity - make only one flush call per sendPacketQueue() call + } + } + return true; ++ } finally { // Tuinity start - add pending task queue ++ Runnable r; ++ while ((r = this.pendingTasks.poll()) != null) { ++ this.channel.eventLoop().execute(r); ++ } ++ } // Tuinity end - add pending task queue + } + // Paper end + +@@ -405,7 +585,14 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + } + + if (this.packetListener instanceof PlayerConnection) { ++ // Tuinity start - detailed watchdog information ++ net.minecraft.network.protocol.PlayerConnectionUtils.packetProcessing.push(this.packetListener); ++ try { ++ // Tuinity end - detailed watchdog information + ((PlayerConnection) this.packetListener).tick(); ++ } finally { // Tuinity start - detailed watchdog information ++ net.minecraft.network.protocol.PlayerConnectionUtils.packetProcessing.pop(); ++ } // Tuinity start - detailed watchdog information + } + + if (this.channel != null) { +@@ -456,10 +643,16 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + return this.channel instanceof LocalChannel || this.channel instanceof LocalServerChannel; + } + +- public void a(Cipher cipher, Cipher cipher1) { ++ public void a(javax.crypto.SecretKey secretkey) { // Tuinity + this.n = true; +- this.channel.pipeline().addBefore("splitter", "decrypt", new PacketDecrypter(cipher)); +- this.channel.pipeline().addBefore("prepender", "encrypt", new PacketEncrypter(cipher1)); ++ // Tuinity start ++ try { ++ this.channel.pipeline().addBefore("splitter", "decrypt", new PacketDecrypter(/*MinecraftEncryption.a(2, secretkey)*/ secretkey)); ++ this.channel.pipeline().addBefore("prepender", "encrypt", new PacketEncrypter(/*MinecraftEncryption.a(1, secretkey)*/ secretkey)); ++ } catch (java.security.GeneralSecurityException e) { ++ throw new RuntimeException("Couldn't enable encryption", e); ++ } ++ // Tuinity end + } + + public boolean isConnected() { +diff --git a/src/main/java/net/minecraft/network/PacketCompressor.java b/src/main/java/net/minecraft/network/PacketCompressor.java +index 45b9d3d3c84d11e7f27f699506a1036dff9fdc53..43ea54479ba70a5c3f4a0f8e4e5a0d03e93162c1 100644 +--- a/src/main/java/net/minecraft/network/PacketCompressor.java ++++ b/src/main/java/net/minecraft/network/PacketCompressor.java +@@ -7,14 +7,18 @@ import java.util.zip.Deflater; + + public class PacketCompressor extends MessageToByteEncoder { + +- private final byte[] a = new byte[8192]; +- private final Deflater b; ++ // Tuinity start - use Velocity natives ++// private final byte[] a = new byte[8192]; ++// private final Deflater b; + private int c; ++ private final com.velocitypowered.natives.compression.VelocityCompressor compressor; + + public PacketCompressor(int i) { + this.c = i; +- this.b = new Deflater(); ++// this.b = new Deflater(); ++ this.compressor = com.velocitypowered.natives.util.Natives.compress.get().create(-1); + } ++ // Tuinity end + + protected void encode(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf, ByteBuf bytebuf1) throws Exception { + int i = bytebuf.readableBytes(); +@@ -24,24 +28,46 @@ public class PacketCompressor extends MessageToByteEncoder { + packetdataserializer.d(0); + packetdataserializer.writeBytes(bytebuf); + } else { +- byte[] abyte = new byte[i]; +- +- bytebuf.readBytes(abyte); +- packetdataserializer.d(abyte.length); +- this.b.setInput(abyte, 0, i); +- this.b.finish(); +- +- while (!this.b.finished()) { +- int j = this.b.deflate(this.a); +- +- packetdataserializer.writeBytes(this.a, 0, j); ++ // Tuinity start - delegate to Velocity natives ++// byte[] abyte = new byte[i]; ++// ++// bytebuf.readBytes(abyte); ++// packetdataserializer.d(abyte.length); ++// this.b.setInput(abyte, 0, i); ++// this.b.finish(); ++// ++// while (!this.b.finished()) { ++// int j = this.b.deflate(this.a); ++// ++// packetdataserializer.writeBytes(this.a, 0, j); ++// } ++// ++// this.b.reset(); ++ packetdataserializer.d(i); ++ ByteBuf source = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelhandlercontext.alloc(), ++ this.compressor, bytebuf); ++ try { ++ this.compressor.deflate(source, bytebuf1); ++ } finally { ++ source.release(); + } +- +- this.b.reset(); ++ // Tuinity end + } + + } + ++ // Tuinity start ++ @Override ++ protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, ByteBuf msg, boolean preferDirect) throws Exception { ++ return com.velocitypowered.natives.util.MoreByteBufUtils.preferredBuffer(ctx.alloc(), this.compressor, msg.readableBytes() + 1); ++ } ++ ++ @Override ++ public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { ++ this.compressor.close(); ++ } ++ // Tuinity end ++ + public void a(int i) { + this.c = i; + } +diff --git a/src/main/java/net/minecraft/network/PacketDecompressor.java b/src/main/java/net/minecraft/network/PacketDecompressor.java +index 1932ca55dad37ca773f215eaec23164533d509d3..ce7d7b4e8c1e5de935c83d7db5186ad8a0849e60 100644 +--- a/src/main/java/net/minecraft/network/PacketDecompressor.java ++++ b/src/main/java/net/minecraft/network/PacketDecompressor.java +@@ -10,13 +10,17 @@ import java.util.zip.Inflater; + + public class PacketDecompressor extends ByteToMessageDecoder { + +- private final Inflater a; ++ // Tuinity start - use Velocity natives ++ //private final Inflater a; ++ private final com.velocitypowered.natives.compression.VelocityCompressor compressor; + private int b; + + public PacketDecompressor(int i) { + this.b = i; +- this.a = new Inflater(); ++ //this.a = new Inflater(); ++ this.compressor = com.velocitypowered.natives.util.Natives.compress.get().create(-1); + } ++ // Tuinity end + + protected void decode(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf, List list) throws Exception { + if (bytebuf.readableBytes() != 0) { +@@ -34,20 +38,41 @@ public class PacketDecompressor extends ByteToMessageDecoder { + throw new DecoderException("Badly compressed packet - size of " + i + " is larger than protocol maximum of " + 2097152); + } + +- byte[] abyte = new byte[packetdataserializer.readableBytes()]; +- +- packetdataserializer.readBytes(abyte); +- this.a.setInput(abyte); +- byte[] abyte1 = new byte[i]; +- +- this.a.inflate(abyte1); +- list.add(Unpooled.wrappedBuffer(abyte1)); +- this.a.reset(); ++ // Tuinity start ++ ByteBuf compatibleIn = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelhandlercontext.alloc(), compressor, bytebuf); ++ ByteBuf uncompressed = com.velocitypowered.natives.util.MoreByteBufUtils.preferredBuffer(channelhandlercontext.alloc(), compressor, i); ++ try { ++ compressor.inflate(compatibleIn, uncompressed, i); ++ list.add(uncompressed); ++ bytebuf.clear(); ++ } catch (Exception e) { ++ uncompressed.release(); ++ throw e; ++ } finally { ++ compatibleIn.release(); ++ } ++// byte[] abyte = new byte[packetdataserializer.readableBytes()]; ++// ++// packetdataserializer.readBytes(abyte); ++// this.a.setInput(abyte); ++// byte[] abyte1 = new byte[i]; ++// ++// this.a.inflate(abyte1); ++// list.add(Unpooled.wrappedBuffer(abyte1)); ++// this.a.reset(); ++ // Tuinity end + } + + } + } + ++ // Tuinity start ++ @Override ++ public void handlerRemoved0(ChannelHandlerContext ctx) throws Exception { ++ this.compressor.close(); ++ } ++ // Tuinity end ++ + public void a(int i) { + this.b = i; + } +diff --git a/src/main/java/net/minecraft/network/PacketDecrypter.java b/src/main/java/net/minecraft/network/PacketDecrypter.java +index c8aa02b288d67efe1f9e20e038248a4f032f92dd..4bd7c7db965818054929c9222a0968f6d127cc5c 100644 +--- a/src/main/java/net/minecraft/network/PacketDecrypter.java ++++ b/src/main/java/net/minecraft/network/PacketDecrypter.java +@@ -8,13 +8,24 @@ import javax.crypto.Cipher; + + public class PacketDecrypter extends MessageToMessageDecoder { + +- private final PacketEncryptionHandler a; ++ // Tuinity start ++ private final com.velocitypowered.natives.encryption.VelocityCipher cipher; ++ //private final PacketEncryptionHandler a; + +- public PacketDecrypter(Cipher cipher) { +- this.a = new PacketEncryptionHandler(cipher); ++ public PacketDecrypter(javax.crypto.SecretKey key /* Cipher cipher */) throws java.security.GeneralSecurityException { ++ //this.a = new PacketEncryptionHandler(cipher); ++ this.cipher = com.velocitypowered.natives.util.Natives.cipher.get().forDecryption(key); + } + + protected void decode(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf, List list) throws Exception { +- list.add(this.a.a(channelhandlercontext, bytebuf)); ++ ByteBuf compatible = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelhandlercontext.alloc(), cipher, bytebuf).slice(); ++ try { ++ cipher.process(compatible); ++ list.add(compatible); ++ } catch (Exception e) { ++ compatible.release(); // compatible will never be used if we throw an exception ++ throw e; ++ } + } ++ // Tuinity end + } +diff --git a/src/main/java/net/minecraft/network/PacketEncrypter.java b/src/main/java/net/minecraft/network/PacketEncrypter.java +index 5759f91d5e9dc52b16c8955b8d318da2b53c7af4..0960f415fd3c6c764cf3dd273bb9e9c59d80ab31 100644 +--- a/src/main/java/net/minecraft/network/PacketEncrypter.java ++++ b/src/main/java/net/minecraft/network/PacketEncrypter.java +@@ -5,15 +5,38 @@ import io.netty.channel.ChannelHandlerContext; + import io.netty.handler.codec.MessageToByteEncoder; + import javax.crypto.Cipher; + +-public class PacketEncrypter extends MessageToByteEncoder { ++// Tuinity start ++// We rewrite this class as the Velocity natives support in-place encryption ++import io.netty.handler.codec.MessageToMessageEncoder; // An unfortunate import, but this is required to fix a compiler error ++public class PacketEncrypter extends MessageToMessageEncoder { + +- private final PacketEncryptionHandler a; ++ private final com.velocitypowered.natives.encryption.VelocityCipher cipher; ++ //private final PacketEncryptionHandler a; + +- public PacketEncrypter(Cipher cipher) { +- this.a = new PacketEncryptionHandler(cipher); ++ public PacketEncrypter(javax.crypto.SecretKey key /* Cipher cipher */) throws java.security.GeneralSecurityException { ++ // this.a = new PacketEncryptionHandler(cipher); ++ this.cipher = com.velocitypowered.natives.util.Natives.cipher.get().forEncryption(key); + } + +- protected void encode(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf, ByteBuf bytebuf1) throws Exception { +- this.a.a(bytebuf, bytebuf1); ++// protected void encode(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf, ByteBuf bytebuf1) throws Exception { ++// this.a.a(bytebuf, bytebuf1); ++// } ++ ++ @Override ++ protected void encode(ChannelHandlerContext ctx, ByteBuf msg, java.util.List out) throws Exception { ++ ByteBuf compatible = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(ctx.alloc(), this.cipher, msg); ++ try { ++ this.cipher.process(compatible); ++ out.add(compatible); ++ } catch (Exception e) { ++ compatible.release(); // compatible will never be used if we throw an exception ++ throw e; ++ } ++ } ++ ++ @Override ++ public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { ++ cipher.close(); + } + } ++// Tuinity end +diff --git a/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java b/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java +index 67d8fe8ad036a9252c774bb6a914c8ec79981876..71a000edfab27c9965d1929af78582821d5af97a 100644 +--- a/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java ++++ b/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java +@@ -25,10 +25,30 @@ public class PlayerConnectionUtils { + ensureMainThread(packet, t0, (IAsyncTaskHandler) worldserver.getMinecraftServer()); + } + ++ // Tuinity start - detailed watchdog information ++ public static final java.util.concurrent.ConcurrentLinkedDeque packetProcessing = new java.util.concurrent.ConcurrentLinkedDeque<>(); ++ static final java.util.concurrent.atomic.AtomicLong totalMainThreadPacketsProcessed = new java.util.concurrent.atomic.AtomicLong(); ++ ++ public static long getTotalProcessedPackets() { ++ return totalMainThreadPacketsProcessed.get(); ++ } ++ ++ public static java.util.List getCurrentPacketProcessors() { ++ java.util.List ret = new java.util.ArrayList<>(4); ++ for (PacketListener listener : packetProcessing) { ++ ret.add(listener); + } + + return ret; + } -+ // Tuinity end - optimise pathfinder collision detection ++ // Tuinity end - detailed watchdog information + - public ChunkCache(World world, BlockPosition blockposition, BlockPosition blockposition1) { - this.e = world; - this.a = blockposition.getX() >> 4; -diff --git a/src/main/java/net/minecraft/server/ChunkGenerator.java b/src/main/java/net/minecraft/server/ChunkGenerator.java -index 097cb9896c525a605c50e83548f828e0c71ab3d5..17cf00dfe8b24adf2fb66eca4710ab7888a894e3 100644 ---- a/src/main/java/net/minecraft/server/ChunkGenerator.java -+++ b/src/main/java/net/minecraft/server/ChunkGenerator.java -@@ -135,7 +135,7 @@ public abstract class ChunkGenerator { - // Get origin location (re)defined by event call. - blockposition = new BlockPosition(event.getOrigin().getBlockX(), event.getOrigin().getBlockY(), event.getOrigin().getBlockZ()); - // Get world (re)defined by event call. -- worldserver = ((org.bukkit.craftbukkit.CraftWorld) event.getOrigin().getWorld()).getHandle(); -+ //worldserver = ((org.bukkit.craftbukkit.CraftWorld) event.getOrigin().getWorld()).getHandle(); // Tuinity - callers and this function don't expect this to change - // Get radius and whether to find unexplored structures (re)defined by event call. - i = event.getRadius(); - flag = event.shouldFindUnexplored(); -diff --git a/src/main/java/net/minecraft/server/ChunkMapDistance.java b/src/main/java/net/minecraft/server/ChunkMapDistance.java -index 76f9bb728def91744910d0b680b73e753f1a2b26..5973c3a89ca5d57629376247a7636e694048a0fd 100644 ---- a/src/main/java/net/minecraft/server/ChunkMapDistance.java -+++ b/src/main/java/net/minecraft/server/ChunkMapDistance.java -@@ -31,9 +31,9 @@ public abstract class ChunkMapDistance { + public static void ensureMainThread(Packet packet, T t0, IAsyncTaskHandler iasynctaskhandler) throws CancelledPacketHandleException { + if (!iasynctaskhandler.isMainThread()) { + Timing timing = MinecraftTimings.getPacketTiming(packet); // Paper - timings + iasynctaskhandler.execute(() -> { ++ packetProcessing.push(t0); // Tuinity - detailed watchdog information ++ try { // Tuinity - detailed watchdog information + if (MinecraftServer.getServer().hasStopped() || (t0 instanceof PlayerConnection && ((PlayerConnection) t0).processedDisconnect)) return; // CraftBukkit, MC-142590 + if (t0.a().isConnected()) { + try (Timing ignored = timing.startTiming()) { // Paper - timings +@@ -52,6 +72,12 @@ public class PlayerConnectionUtils { + } else { + PlayerConnectionUtils.LOGGER.debug("Ignoring packet due to disconnection: " + packet); + } ++ // Tuinity start - detailed watchdog information ++ } finally { ++ totalMainThreadPacketsProcessed.getAndIncrement(); ++ packetProcessing.pop(); ++ } ++ // Tuinity end - detailed watchdog information + + }); + throw CancelledPacketHandleException.INSTANCE; +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutLightUpdate.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutLightUpdate.java +index 9050ff7180f63c1f5756570446c4d0a8cc767779..9dd0f34aaede93ce4fdff9b41f76166edeb95e93 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutLightUpdate.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutLightUpdate.java +@@ -35,12 +35,12 @@ public class PacketPlayOutLightUpdate implements Packet { + + @Override + public void onPacketDispatch(EntityPlayer player) { +- remainingSends.incrementAndGet(); ++ if (!com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine) remainingSends.incrementAndGet(); + } + + @Override + public void onPacketDispatchFinish(EntityPlayer player, ChannelFuture future) { +- if (remainingSends.decrementAndGet() <= 0) { ++ if (!com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine && remainingSends.decrementAndGet() <= 0) { + // incase of any race conditions, schedule this delayed + MCUtil.scheduleTask(5, () -> { + if (remainingSends.get() == 0) { +@@ -53,7 +53,7 @@ public class PacketPlayOutLightUpdate implements Packet { + + @Override + public boolean hasFinishListener() { +- return true; ++ return !com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine; // Tuinity - replace light impl + } + + // Paper end +@@ -63,8 +63,8 @@ public class PacketPlayOutLightUpdate implements Packet { + this.a = chunkcoordintpair.x; + this.b = chunkcoordintpair.z; + this.i = flag; +- this.g = Lists.newArrayList();cleaner1 = MCUtil.registerListCleaner(this, this.g, NibbleArray::releaseBytes); // Paper +- this.h = Lists.newArrayList();cleaner2 = MCUtil.registerListCleaner(this, this.h, NibbleArray::releaseBytes); // Paper ++ this.g = Lists.newArrayList();if (!com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine) cleaner1 = MCUtil.registerListCleaner(this, this.g, NibbleArray::releaseBytes); // Paper // Tuinity - purge cleaner usage ++ this.h = Lists.newArrayList();if (!com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine) cleaner2 = MCUtil.registerListCleaner(this, this.h, NibbleArray::releaseBytes); // Paper // Tuinity - purge cleaner usage + + for (int i = 0; i < 18; ++i) { + NibbleArray nibblearray = lightengine.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, -1 + i)); +@@ -75,7 +75,7 @@ public class PacketPlayOutLightUpdate implements Packet { + this.e |= 1 << i; + } else { + this.c |= 1 << i; +- this.g.add(nibblearray.getCloneIfSet()); // Paper ++ this.g.add(com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? nibblearray.asBytes() : nibblearray.getCloneIfSet()); // Paper // Tuinity - don't clone again + } + } + +@@ -84,7 +84,7 @@ public class PacketPlayOutLightUpdate implements Packet { + this.f |= 1 << i; + } else { + this.d |= 1 << i; +- this.h.add(nibblearray1.getCloneIfSet()); // Paper ++ this.h.add(com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? nibblearray1.asBytes() : nibblearray1.getCloneIfSet()); // Paper // Tuinity - don't clone again + } + } + } +@@ -97,8 +97,8 @@ public class PacketPlayOutLightUpdate implements Packet { + this.i = flag; + this.c = i; + this.d = j; +- this.g = Lists.newArrayList();cleaner1 = MCUtil.registerListCleaner(this, this.g, NibbleArray::releaseBytes); // Paper +- this.h = Lists.newArrayList();cleaner2 = MCUtil.registerListCleaner(this, this.h, NibbleArray::releaseBytes); // Paper ++ this.g = Lists.newArrayList();if (!com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine) cleaner1 = MCUtil.registerListCleaner(this, this.g, NibbleArray::releaseBytes); // Paper // Tuinity - purge cleaner usage ++ this.h = Lists.newArrayList();if (!com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine) cleaner2 = MCUtil.registerListCleaner(this, this.h, NibbleArray::releaseBytes); // Paper // Tuinity - purge cleaner usage + + for (int k = 0; k < 18; ++k) { + NibbleArray nibblearray; +@@ -106,7 +106,7 @@ public class PacketPlayOutLightUpdate implements Packet { + if ((this.c & 1 << k) != 0) { + nibblearray = lightengine.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, -1 + k)); + if (nibblearray != null && !nibblearray.c()) { +- this.g.add(nibblearray.getCloneIfSet()); // Paper ++ this.g.add(com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? nibblearray.asBytes() : nibblearray.getCloneIfSet()); // Paper // Tuinity - don't clone again + } else { + this.c &= ~(1 << k); + if (nibblearray != null) { +@@ -118,7 +118,7 @@ public class PacketPlayOutLightUpdate implements Packet { + if ((this.d & 1 << k) != 0) { + nibblearray = lightengine.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkcoordintpair, -1 + k)); + if (nibblearray != null && !nibblearray.c()) { +- this.h.add(nibblearray.getCloneIfSet()); // Paper ++ this.h.add(com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? nibblearray.asBytes() : nibblearray.getCloneIfSet()); // Paper // Tuinity - don't clone again + } else { + this.d &= ~(1 << k); + if (nibblearray != null) { +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java +index 3047cf8c4ec1b664d6b790f18d2b1657e4b00435..1295c391ae48f0864c243ca9046f31480eb768fe 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java +@@ -32,7 +32,7 @@ public class PacketPlayOutMapChunk implements Packet { + @Nullable + private int[] e; + private byte[] f; private byte[] getData() { return this.f; } // Paper - OBFHELPER +- private List g; ++ private List g; private List getTileEntityData() { return this.g; } // Tuinity - OBFHELPER + private boolean h; + + // Paper start - Async-Anti-Xray - Set the ready flag to true +@@ -44,7 +44,9 @@ public class PacketPlayOutMapChunk implements Packet { + + // Paper start + private final java.util.List extraPackets = new java.util.ArrayList<>(); +- private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750); ++ private static final int TE_LIMIT = Integer.getInteger("tuinity.excessive-te-limit", 750); // Tuinity - handle oversized chunk data packets more robustly ++ private static final int TE_SPLIT_LIMIT = Math.max(4096 + 1, Integer.getInteger("tuinity.te-split-limit", 15_000)); // Tuinity - handle oversized chunk data packets more robustly ++ private boolean mustSplit; // Tuinity - handle oversized chunk data packets more robustly + + @Override + public java.util.List getExtraPackets() { +@@ -53,7 +55,7 @@ public class PacketPlayOutMapChunk implements Packet { + // Paper end + // Paper start - Anti-Xray - Add chunk packet info + @Deprecated public PacketPlayOutMapChunk(Chunk chunk, int i) { this(chunk, i, true); } // Notice for updates: Please make sure this constructor isn't used anywhere +- public PacketPlayOutMapChunk(Chunk chunk, int i, boolean modifyBlocks) { ++ public PacketPlayOutMapChunk(Chunk chunk, int i, boolean modifyBlocks) { final int chunkSectionBitSet = i; // Tuinity - handle oversized chunk data packets more robustly + ChunkPacketInfo chunkPacketInfo = modifyBlocks ? chunk.world.chunkPacketBlockController.getChunkPacketInfo(this, chunk, i) : null; + // Paper end + ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); +@@ -62,27 +64,12 @@ public class PacketPlayOutMapChunk implements Packet { + this.b = chunkcoordintpair.z; + this.h = i == 65535; + this.d = new NBTTagCompound(); +- Iterator iterator = chunk.f().iterator(); +- +- Entry entry; +- +- while (iterator.hasNext()) { +- entry = (Entry) iterator.next(); +- if (((HeightMap.Type) entry.getKey()).c()) { +- this.d.set(((HeightMap.Type) entry.getKey()).b(), new NBTTagLongArray(((HeightMap) entry.getValue()).a())); +- } +- } +- +- if (this.h) { +- this.e = chunk.getBiomeIndex().a(); +- } +- +- this.f = new byte[this.a(chunk, i)]; +- // Paper start - Anti-Xray - Add chunk packet info +- if (chunkPacketInfo != null) { +- chunkPacketInfo.setData(this.getData()); +- } +- this.c = this.writeChunk(new PacketDataSerializer(this.j()), chunk, i, chunkPacketInfo); ++ // Tuinity - move this after the tile entity logic, we need to determine whether we're going to split ++ // Tuinity - before writing chunk block data ++ // Tuinity - note: for future maintenance, git will prefer the smallest diff, so if moving the TE code is ++ // Tuinity - a smaller diff, do that, else move the chunk writing - this makes sure the start/end is correct ++ Iterator iterator; // Tuinity - move declaration up ++ Entry entry; // Tuinity - move delcaration up + // Paper end + this.g = Lists.newArrayList(); + iterator = chunk.getTileEntities().entrySet().iterator(); +@@ -95,8 +82,16 @@ public class PacketPlayOutMapChunk implements Packet { + int j = blockposition.getY() >> 4; + + if (this.f() || (i & 1 << j) != 0) { ++ // Tuinity start - improve oversized chunk data packet handling ++ ++totalTileEntities; ++ if (totalTileEntities > TE_SPLIT_LIMIT) { ++ this.mustSplit = true; ++ this.getTileEntityData().clear(); ++ this.extraPackets.clear(); ++ break; ++ } + // Paper start - improve oversized chunk data packet handling +- if (++totalTileEntities > TE_LIMIT) { ++ if (totalTileEntities > TE_LIMIT) { // Tuinity end - improve oversized chunk data packet handling + PacketPlayOutTileEntityData updatePacket = tileentity.getUpdatePacket(); + if (updatePacket != null) { + this.extraPackets.add(updatePacket); +@@ -110,7 +105,42 @@ public class PacketPlayOutMapChunk implements Packet { + this.g.add(nbttagcompound); + } + } ++ // Tuinity start - moved after tile entity gathering ++ iterator = chunk.f().iterator(); // Declared earlier ++ ++ while (iterator.hasNext()) { ++ entry = (Entry) iterator.next(); ++ if (((HeightMap.Type) entry.getKey()).c()) { ++ this.d.set(((HeightMap.Type) entry.getKey()).b(), new NBTTagLongArray(((HeightMap) entry.getValue()).a())); ++ } ++ } ++ ++ if (this.h) { ++ this.e = chunk.getBiomeIndex().a(); ++ } ++ ++ this.f = new byte[this.a(chunk, i)]; ++ // Paper start - Anti-Xray - Add chunk packet info ++ if (chunkPacketInfo != null) { ++ chunkPacketInfo.setData(this.getData()); ++ } ++ this.c = this.writeChunk(new PacketDataSerializer(this.j()), chunk, i, chunkPacketInfo); ++ // Tuinity end - moved after tile entity gathering + chunk.world.chunkPacketBlockController.modifyBlocks(this, chunkPacketInfo); // Paper - Anti-Xray - Modify blocks ++ // Tuinity start - improve oversized chunk data packet handling ++ if (this.mustSplit) { ++ int chunkSectionBitSetCopy = chunkSectionBitSet; ++ for (int a = 0, len = Integer.bitCount(chunkSectionBitSet); a < len; ++a) { ++ int trailingBit = com.destroystokyo.paper.util.math.IntegerUtil.getTrailingBit(chunkSectionBitSetCopy); ++ int sectionIndex = Integer.numberOfTrailingZeros(trailingBit); ++ chunkSectionBitSetCopy ^= trailingBit; // move on to the next ++ ++ if (chunk.getSections()[sectionIndex] != null) { ++ this.extraPackets.add(new PacketPlayOutMapChunk(chunk, trailingBit)); ++ } ++ } ++ } ++ // Tuinity end - improve oversized chunk data packet handling + } + + // Paper start - Async-Anti-Xray - Getter and Setter for the ready flag +@@ -201,7 +231,7 @@ public class PacketPlayOutMapChunk implements Packet { + for (int l = achunksection.length; k < l; ++k) { + ChunkSection chunksection = achunksection[k]; + +- if (chunksection != Chunk.a && (!this.f() || !chunksection.c()) && (i & 1 << k) != 0) { ++ if ((!this.mustSplit && chunksection != Chunk.a) && (!this.f() || !chunksection.c()) && (i & 1 << k) != 0) { // Tuinity - improve oversized chunk data packet handling + j |= 1 << k; + chunksection.writeChunkSection(packetdataserializer, chunkPacketInfo); // Paper - Anti-Xray - Add chunk packet info + } +@@ -218,7 +248,7 @@ public class PacketPlayOutMapChunk implements Packet { + for (int l = achunksection.length; k < l; ++k) { + ChunkSection chunksection = achunksection[k]; + +- if (chunksection != Chunk.a && (!this.f() || !chunksection.c()) && (i & 1 << k) != 0) { ++ if ((!this.mustSplit && chunksection != Chunk.a) && (!this.f() || !chunksection.c()) && (i & 1 << k) != 0) { + j += chunksection.j(); + } + } +diff --git a/src/main/java/net/minecraft/server/EULA.java b/src/main/java/net/minecraft/server/EULA.java +index a0f53c9eff04a40780b3ba568dbfc5bbe9bd8504..3bc5cd1e53dd7c94b948e7f57f0dc8e073e349b0 100644 +--- a/src/main/java/net/minecraft/server/EULA.java ++++ b/src/main/java/net/minecraft/server/EULA.java +@@ -72,7 +72,7 @@ public class EULA { + Properties properties = new Properties(); + + properties.setProperty("eula", "false"); +- properties.store(outputstream, "By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula).\nYou also agree that tacos are tasty, and the best food in the world."); // Paper - fix lag; ++ properties.store(outputstream, "By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula)."); // Paper - fix lag; // Tuinity - Tacos are disgusting + } catch (Throwable throwable1) { + throwable = throwable1; + throw throwable1; +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index 1d72af9cace7aa8f1d20c7c1c5be621f533e2dad..b7399d17dd64ca8b1f1fab405cb0ac914dc53b98 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -55,6 +55,7 @@ import java.util.function.Consumer; + import java.util.function.Supplier; + + public final class MCUtil { ++ public static final double COLLISION_EPSILON = 1.0E-7; // Tuinity - Just in case mojang changes this... + public static final ThreadPoolExecutor asyncExecutor = new ThreadPoolExecutor( + 0, 2, 60L, TimeUnit.SECONDS, + new LinkedBlockingQueue(), +@@ -238,6 +239,63 @@ public final class MCUtil { + return getBlockKey(getBlockCoordinate(entity.locX()), getBlockCoordinate(entity.locY()), getBlockCoordinate(entity.locZ())); + } + ++ // Tuinity start ++ ++ static final int SECTION_X_BITS = 22; ++ static final long SECTION_X_MASK = (1L << SECTION_X_BITS) - 1; ++ static final int SECTION_Y_BITS = 20; ++ static final long SECTION_Y_MASK = (1L << SECTION_Y_BITS) - 1; ++ static final int SECTION_Z_BITS = 22; ++ static final long SECTION_Z_MASK = (1L << SECTION_Z_BITS) - 1; ++ // format is y,z,x (in order of LSB to MSB) ++ static final int SECTION_Y_SHIFT = 0; ++ static final int SECTION_Z_SHIFT = SECTION_Y_SHIFT + SECTION_Y_BITS; ++ static final int SECTION_X_SHIFT = SECTION_Z_SHIFT + SECTION_X_BITS; ++ static final int SECTION_TO_BLOCK_SHIFT = 4; ++ ++ public static long getSectionKey(final int x, final int y, final int z) { ++ return ((x & SECTION_X_MASK) << SECTION_X_SHIFT) ++ | ((y & SECTION_Y_MASK) << SECTION_Y_SHIFT) ++ | ((z & SECTION_Z_MASK) << SECTION_Z_SHIFT); ++ } ++ ++ public static long getSectionKey(final net.minecraft.core.SectionPosition pos) { ++ return ((pos.getX() & SECTION_X_MASK) << SECTION_X_SHIFT) ++ | ((pos.getY() & SECTION_Y_MASK) << SECTION_Y_SHIFT) ++ | ((pos.getZ() & SECTION_Z_MASK) << SECTION_Z_SHIFT); ++ } ++ ++ public static long getSectionKey(final ChunkCoordIntPair pos, final int y) { ++ return ((pos.x & SECTION_X_MASK) << SECTION_X_SHIFT) ++ | ((y & SECTION_Y_MASK) << SECTION_Y_SHIFT) ++ | ((pos.z & SECTION_Z_MASK) << SECTION_Z_SHIFT); ++ } ++ ++ public static long getSectionKey(final BlockPosition pos) { ++ return (((long)pos.getX() << (SECTION_X_SHIFT - SECTION_TO_BLOCK_SHIFT)) & (SECTION_X_MASK << SECTION_X_SHIFT)) | ++ ((pos.getY() >> SECTION_TO_BLOCK_SHIFT) & (SECTION_Y_MASK << SECTION_Y_SHIFT)) | ++ (((long)pos.getZ() << (SECTION_Z_SHIFT - SECTION_TO_BLOCK_SHIFT)) & (SECTION_Z_MASK << SECTION_Z_SHIFT)); ++ } ++ ++ public static long getSectionKey(final Entity entity) { ++ return ((MCUtil.fastFloor(entity.locX()) & SECTION_X_MASK) << SECTION_X_SHIFT) ++ | ((MCUtil.fastFloor(entity.locY()) & SECTION_Y_MASK) << SECTION_Y_SHIFT) ++ | ((MCUtil.fastFloor(entity.locZ()) & SECTION_Z_MASK) << SECTION_Z_SHIFT); ++ } ++ ++ public static int getSectionX(final long key) { ++ return (int)(key << (Long.SIZE - (SECTION_X_SHIFT + SECTION_X_BITS)) >> (Long.SIZE - SECTION_X_BITS)); ++ } ++ ++ public static int getSectionY(final long key) { ++ return (int)(key << (Long.SIZE - (SECTION_Y_SHIFT + SECTION_Y_BITS)) >> (Long.SIZE - SECTION_Y_BITS)); ++ } ++ ++ public static int getSectionZ(final long key) { ++ return (int)(key << (Long.SIZE - (SECTION_Z_SHIFT + SECTION_Z_BITS)) >> (Long.SIZE - SECTION_Z_BITS)); ++ } ++ // Tuinity end ++ + // assumes the sets have the same comparator, and if this comparator is null then assume T is Comparable + public static void mergeSortedSets(final java.util.function.Consumer consumer, final java.util.Comparator comparator, final java.util.SortedSet...sets) { + final ObjectRBTreeSet all = new ObjectRBTreeSet<>(comparator); +@@ -639,7 +697,7 @@ public final class MCUtil { + + worldData.addProperty("name", world.getWorld().getName()); + worldData.addProperty("view-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()); +- worldData.addProperty("no-view-distance", world.getChunkProvider().playerChunkMap.getRawNoTickViewDistance()); ++ worldData.addProperty("no-view-distance", world.getChunkProvider().playerChunkMap.playerChunkManager.getTargetNoTickViewDistance()); // Tuinity - replace old player chunk management + worldData.addProperty("keep-spawn-loaded", world.keepSpawnInMemory); + worldData.addProperty("keep-spawn-loaded-range", world.paperConfig.keepLoadedRange); + worldData.addProperty("visible-chunk-count", visibleChunks.size()); +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index c372e6897c73fad6f9c478cec9f58303fb0cce17..e757cb5c2d50cb3a4dbe50d4726db09ab845fcbb 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -267,6 +267,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); + public int autosavePeriod; + public boolean serverAutoSave = false; // Paper +@@ -867,10 +868,11 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant= MAX_CHUNK_EXEC_TIME) { ++ if (!moreTasks) { ++ lastMidTickExecuteFailure = currTime; ++ } ++ ++ // note: negative values reduce the time ++ long overuse = diff - MAX_CHUNK_EXEC_TIME; ++ if (overuse >= (10L * 1000L * 1000L)) { // 10ms ++ // make sure something like a GC or dumb plugin doesn't screw us over... ++ overuse = 10L * 1000L * 1000L; // 10ms ++ } ++ ++ double overuseCount = (double)overuse/(double)MAX_CHUNK_EXEC_TIME; ++ long extraSleep = (long)Math.round(overuseCount*CHUNK_TASK_QUEUE_BACKOFF_MIN_TIME); ++ ++ lastMidTickExecute = currTime + extraSleep; ++ return; ++ } ++ } ++ } finally { ++ co.aikar.timings.MinecraftTimings.midTickChunkTasks.stopTiming(); ++ } ++ } ++ // Tuinity end - execute chunk tasks mid tick ++ + private void executeModerately() { + this.executeAll(); + java.util.concurrent.locks.LockSupport.parkNanos("executing tasks", 1000L); +@@ -1208,22 +1282,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { +- midTickLoadChunks(); // will only do loads since we are still considered !canSleepForTick ++ // Tuinity - replace logic + return !this.canOversleep(); + }); + isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); +@@ -1382,6 +1442,8 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant // Spigot - Spigot > // CraftBukkit - cb > vanilla! ++ return "Tuinity"; // Tuinity //Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! + } + + public CrashReport b(CrashReport crashreport) { +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index 52bb528e75eb43156ee2bf19877bc051a35bb6e3..d902efdb8f2d42ea4c3933f7fa76ebe135ee09db 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -214,6 +214,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + com.destroystokyo.paper.PaperConfig.registerCommands(); + com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now + // Paper end ++ com.tuinity.tuinity.config.TuinityConfig.init((java.io.File) options.valueOf("tuinity-settings")); // Tuinity - Server Config + + this.setPVP(dedicatedserverproperties.pvp); + this.setAllowFlight(dedicatedserverproperties.allowFlight); +@@ -398,7 +399,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + } + + if (this.q != null) { +- this.q.b(); ++ //this.q.b(); // Tuinity - do not wait for AWT, causes deadlock with sigint handler (AWT shutdown will properly clear our resources anyways) + } + + if (this.remoteControlListener != null) { +diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java +index 2f8bca35508640f6b8c312fff17d55f129431599..db8532c42fcb2e96f4b3491352d1b9a25a8efe49 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java +@@ -40,9 +40,9 @@ public abstract class ChunkMapDistance { private static final int b = 33 + ChunkStatus.a(ChunkStatus.FULL) - 2; private final Long2ObjectMap> c = new Long2ObjectOpenHashMap(); public final Long2ObjectOpenHashMap>> tickets = new Long2ObjectOpenHashMap(); @@ -10937,7 +11590,7 @@ index 76f9bb728def91744910d0b680b73e753f1a2b26..5973c3a89ca5d57629376247a7636e69 // Paper start use a queue, but still keep unique requirement public final java.util.Queue pendingChunkUpdates = new java.util.ArrayDeque() { @Override -@@ -53,6 +53,47 @@ public abstract class ChunkMapDistance { +@@ -62,6 +62,47 @@ public abstract class ChunkMapDistance { PlayerChunkMap chunkMap; // Paper @@ -10985,7 +11638,7 @@ index 76f9bb728def91744910d0b680b73e753f1a2b26..5973c3a89ca5d57629376247a7636e69 protected ChunkMapDistance(Executor executor, Executor executor1) { executor1.getClass(); Mailbox mailbox = Mailbox.a("player ticket throttler", executor1::execute); -@@ -65,21 +106,45 @@ public abstract class ChunkMapDistance { +@@ -74,21 +115,45 @@ public abstract class ChunkMapDistance { } protected void purgeTickets() { @@ -11035,7 +11688,7 @@ index 76f9bb728def91744910d0b680b73e753f1a2b26..5973c3a89ca5d57629376247a7636e69 } } -@@ -98,9 +163,10 @@ public abstract class ChunkMapDistance { +@@ -107,9 +172,10 @@ public abstract class ChunkMapDistance { protected abstract PlayerChunk a(long i, int j, @Nullable PlayerChunk playerchunk, int k); public boolean a(PlayerChunkMap playerchunkmap) { @@ -11047,7 +11700,7 @@ index 76f9bb728def91744910d0b680b73e753f1a2b26..5973c3a89ca5d57629376247a7636e69 int i = Integer.MAX_VALUE - this.ticketLevelTracker.a(Integer.MAX_VALUE); boolean flag = i != 0; -@@ -176,27 +242,11 @@ public abstract class ChunkMapDistance { +@@ -185,27 +251,11 @@ public abstract class ChunkMapDistance { boolean removed = false; // CraftBukkit if (arraysetsorted.remove(ticket)) { removed = true; // CraftBukkit @@ -11079,7 +11732,7 @@ index 76f9bb728def91744910d0b680b73e753f1a2b26..5973c3a89ca5d57629376247a7636e69 } if (arraysetsorted.isEmpty()) { -@@ -263,7 +313,7 @@ public abstract class ChunkMapDistance { +@@ -272,7 +322,7 @@ public abstract class ChunkMapDistance { AsyncCatcher.catchOp("ChunkMapDistance::addPriorityTicket"); long pair = coords.pair(); PlayerChunk chunk = chunkMap.getUpdatingChunk(pair); @@ -11088,7 +11741,7 @@ index 76f9bb728def91744910d0b680b73e753f1a2b26..5973c3a89ca5d57629376247a7636e69 if (needsTicket) { Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, coords); -@@ -370,6 +420,7 @@ public abstract class ChunkMapDistance { +@@ -379,6 +429,7 @@ public abstract class ChunkMapDistance { } private ArraySetSorted> e(long i) { @@ -11096,7 +11749,7 @@ index 76f9bb728def91744910d0b680b73e753f1a2b26..5973c3a89ca5d57629376247a7636e69 return (ArraySetSorted) this.tickets.computeIfAbsent(i, (j) -> { return ArraySetSorted.a(4); }); -@@ -387,16 +438,18 @@ public abstract class ChunkMapDistance { +@@ -396,16 +447,18 @@ public abstract class ChunkMapDistance { } public void a(SectionPosition sectionposition, EntityPlayer entityplayer) { @@ -11116,7 +11769,7 @@ index 76f9bb728def91744910d0b680b73e753f1a2b26..5973c3a89ca5d57629376247a7636e69 long i = sectionposition.r().pair(); ObjectSet objectset = (ObjectSet) this.c.get(i); if (objectset == null) return; // CraftBukkit - SPIGOT-6208 -@@ -405,7 +458,7 @@ public abstract class ChunkMapDistance { +@@ -414,7 +467,7 @@ public abstract class ChunkMapDistance { if (objectset == null || objectset.isEmpty()) { // Paper this.c.remove(i); //this.f.update(i, Integer.MAX_VALUE, false); // Paper - no longer used @@ -11125,7 +11778,7 @@ index 76f9bb728def91744910d0b680b73e753f1a2b26..5973c3a89ca5d57629376247a7636e69 } } -@@ -424,7 +477,7 @@ public abstract class ChunkMapDistance { +@@ -433,7 +486,7 @@ public abstract class ChunkMapDistance { } protected void setNoTickViewDistance(int i) { // Paper - force abi breakage on usage change @@ -11134,7 +11787,7 @@ index 76f9bb728def91744910d0b680b73e753f1a2b26..5973c3a89ca5d57629376247a7636e69 } public int b() { -@@ -447,6 +500,7 @@ public abstract class ChunkMapDistance { +@@ -456,6 +509,7 @@ public abstract class ChunkMapDistance { // CraftBukkit start public void removeAllTicketsFor(TicketType ticketType, int ticketLevel, T ticketIdentifier) { @@ -11142,7 +11795,7 @@ index 76f9bb728def91744910d0b680b73e753f1a2b26..5973c3a89ca5d57629376247a7636e69 Ticket target = new Ticket<>(ticketType, ticketLevel, ticketIdentifier); for (java.util.Iterator>>> iterator = this.tickets.long2ObjectEntrySet().fastIterator(); iterator.hasNext();) { -@@ -510,6 +564,7 @@ public abstract class ChunkMapDistance { +@@ -519,6 +573,7 @@ public abstract class ChunkMapDistance { } } @@ -11150,7 +11803,7 @@ index 76f9bb728def91744910d0b680b73e753f1a2b26..5973c3a89ca5d57629376247a7636e69 class c extends ChunkMapDistance.b { private int e = 0; -@@ -724,6 +779,7 @@ public abstract class ChunkMapDistance { +@@ -733,6 +788,7 @@ public abstract class ChunkMapDistance { return i <= this.e - 2; } } @@ -11158,13 +11811,13 @@ index 76f9bb728def91744910d0b680b73e753f1a2b26..5973c3a89ca5d57629376247a7636e69 class b extends ChunkMap { -diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java -index 0ea1b25bf98d71c251351807fa92d4d08eb6b06e..b55f7dece329dbb3ff27d57a39c32c69e5baea74 100644 ---- a/src/main/java/net/minecraft/server/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java -@@ -22,6 +22,12 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; +diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +index e542fe5fb63064e67c7fde8fad614826d6f3344c..cb83f1152c52a99d25e4e80cc8bf18c6793e8b50 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +@@ -47,6 +47,12 @@ import net.minecraft.world.level.storage.WorldData; + import net.minecraft.world.level.storage.WorldPersistentData; + import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper +// Tuinity start +import it.unimi.dsi.fastutil.objects.Object2BooleanLinkedOpenHashMap; @@ -11174,8 +11827,8 @@ index 0ea1b25bf98d71c251351807fa92d4d08eb6b06e..b55f7dece329dbb3ff27d57a39c32c69 + public class ChunkProviderServer extends IChunkProvider { - private static final List b = ChunkStatus.a(); static final List getPossibleChunkStatuses() { return ChunkProviderServer.b; } // Paper - OBFHELPER -@@ -112,7 +118,7 @@ public class ChunkProviderServer extends IChunkProvider { + private static final List b = ChunkStatus.a(); public static final List getPossibleChunkStatuses() { return ChunkProviderServer.b; } // Paper - OBFHELPER +@@ -137,7 +143,7 @@ public class ChunkProviderServer extends IChunkProvider { return (Chunk)this.getChunkAt(x, z, ChunkStatus.FULL, true); } @@ -11184,7 +11837,7 @@ index 0ea1b25bf98d71c251351807fa92d4d08eb6b06e..b55f7dece329dbb3ff27d57a39c32c69 public void getEntityTickingChunkAsync(int x, int z, java.util.function.Consumer onLoad) { if (Thread.currentThread() != this.serverThread) { -@@ -174,9 +180,9 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -199,9 +205,9 @@ public class ChunkProviderServer extends IChunkProvider { try { if (onLoad != null) { @@ -11196,7 +11849,7 @@ index 0ea1b25bf98d71c251351807fa92d4d08eb6b06e..b55f7dece329dbb3ff27d57a39c32c69 } } catch (Throwable thr) { if (thr instanceof ThreadDeath) { -@@ -201,6 +207,165 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -226,6 +232,165 @@ public class ChunkProviderServer extends IChunkProvider { } // Paper end - rewrite ticklistserver @@ -11362,7 +12015,7 @@ index 0ea1b25bf98d71c251351807fa92d4d08eb6b06e..b55f7dece329dbb3ff27d57a39c32c69 public ChunkProviderServer(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, ChunkGenerator chunkgenerator, int i, boolean flag, WorldLoadListener worldloadlistener, Supplier supplier) { this.world = worldserver; this.serverThreadQueue = new ChunkProviderServer.a(worldserver); -@@ -544,6 +709,8 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -569,6 +734,8 @@ public class ChunkProviderServer extends IChunkProvider { Arrays.fill(this.cacheChunk, (Object) null); } @@ -11371,7 +12024,7 @@ index 0ea1b25bf98d71c251351807fa92d4d08eb6b06e..b55f7dece329dbb3ff27d57a39c32c69 private CompletableFuture> getChunkFutureMainThread(int i, int j, ChunkStatus chunkstatus, boolean flag) { // Paper start - add isUrgent - old sig left in place for dirty nms plugins return getChunkFutureMainThread(i, j, chunkstatus, flag, false); -@@ -562,9 +729,12 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -587,9 +754,12 @@ public class ChunkProviderServer extends IChunkProvider { PlayerChunk.State currentChunkState = PlayerChunk.getChunkState(playerchunk.getTicketLevel()); currentlyUnloading = (oldChunkState.isAtLeast(PlayerChunk.State.BORDER) && !currentChunkState.isAtLeast(PlayerChunk.State.BORDER)); } @@ -11384,7 +12037,7 @@ index 0ea1b25bf98d71c251351807fa92d4d08eb6b06e..b55f7dece329dbb3ff27d57a39c32c69 if (isUrgent) this.chunkMapDistance.markUrgent(chunkcoordintpair); // Paper if (this.a(playerchunk, l)) { GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler(); -@@ -575,12 +745,20 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -600,12 +770,20 @@ public class ChunkProviderServer extends IChunkProvider { playerchunk = this.getChunk(k); gameprofilerfiller.exit(); if (this.a(playerchunk, l)) { @@ -11406,7 +12059,7 @@ index 0ea1b25bf98d71c251351807fa92d4d08eb6b06e..b55f7dece329dbb3ff27d57a39c32c69 if (isUrgent) { future.thenAccept(either -> this.chunkMapDistance.clearUrgent(chunkcoordintpair)); } -@@ -599,8 +777,8 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -624,8 +802,8 @@ public class ChunkProviderServer extends IChunkProvider { return !this.a(playerchunk, k); } @@ -11417,7 +12070,7 @@ index 0ea1b25bf98d71c251351807fa92d4d08eb6b06e..b55f7dece329dbb3ff27d57a39c32c69 long k = ChunkCoordIntPair.pair(i, j); PlayerChunk playerchunk = this.getChunk(k); -@@ -637,6 +815,8 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -662,6 +840,8 @@ public class ChunkProviderServer extends IChunkProvider { public boolean tickDistanceManager() { // Paper - private -> public if (chunkMapDistance.delayDistanceManagerTick) return false; // Paper @@ -11426,7 +12079,7 @@ index 0ea1b25bf98d71c251351807fa92d4d08eb6b06e..b55f7dece329dbb3ff27d57a39c32c69 boolean flag = this.chunkMapDistance.a(this.playerChunkMap); boolean flag1 = this.playerChunkMap.b(); -@@ -646,6 +826,7 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -671,6 +851,7 @@ public class ChunkProviderServer extends IChunkProvider { this.clearCache(); return true; } @@ -11434,7 +12087,7 @@ index 0ea1b25bf98d71c251351807fa92d4d08eb6b06e..b55f7dece329dbb3ff27d57a39c32c69 } public final boolean isInEntityTickingChunk(Entity entity) { return this.a(entity); } // Paper - OBFHELPER -@@ -720,6 +901,7 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -745,6 +926,7 @@ public class ChunkProviderServer extends IChunkProvider { // CraftBukkit start - modelled on below public void purgeUnload() { @@ -11442,7 +12095,7 @@ index 0ea1b25bf98d71c251351807fa92d4d08eb6b06e..b55f7dece329dbb3ff27d57a39c32c69 this.world.getMethodProfiler().enter("purge"); this.chunkMapDistance.purgeTickets(); this.tickDistanceManager(); -@@ -734,17 +916,18 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -759,17 +941,18 @@ public class ChunkProviderServer extends IChunkProvider { this.world.getMethodProfiler().enter("purge"); this.world.timings.doChunkMap.startTiming(); // Spigot this.chunkMapDistance.purgeTickets(); @@ -11463,7 +12116,7 @@ index 0ea1b25bf98d71c251351807fa92d4d08eb6b06e..b55f7dece329dbb3ff27d57a39c32c69 this.world.timings.doChunkUnload.stopTiming(); // Spigot this.world.getMethodProfiler().exit(); this.clearCache(); -@@ -809,31 +992,37 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -834,31 +1017,37 @@ public class ChunkProviderServer extends IChunkProvider { for (EntityPlayer player : this.world.players) { Arrays.fill(player.mobCounts, 0); } @@ -11511,7 +12164,7 @@ index 0ea1b25bf98d71c251351807fa92d4d08eb6b06e..b55f7dece329dbb3ff27d57a39c32c69 ChunkCoordIntPair chunkcoordintpair = playerchunk.i(); if (!this.playerChunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, false)) { // Paper - optimise isOutsideOfRange -@@ -845,11 +1034,15 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -870,11 +1059,15 @@ public class ChunkProviderServer extends IChunkProvider { this.world.timings.chunkTicks.startTiming(); // Spigot // Paper this.world.a(chunk, k); this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper @@ -11529,14 +12182,14 @@ index 0ea1b25bf98d71c251351807fa92d4d08eb6b06e..b55f7dece329dbb3ff27d57a39c32c69 this.world.getMethodProfiler().enter("customSpawners"); if (flag1) { try (co.aikar.timings.Timing ignored = this.world.timings.miscMobSpawning.startTiming()) { // Paper - timings -@@ -861,7 +1054,25 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -886,7 +1079,25 @@ public class ChunkProviderServer extends IChunkProvider { this.world.getMethodProfiler().exit(); } + // Tuinity start - controlled flush for entity tracker packets -+ List disabledFlushes = new java.util.ArrayList<>(this.world.getPlayers().size()); ++ List disabledFlushes = new java.util.ArrayList<>(this.world.getPlayers().size()); + for (EntityPlayer player : this.world.getPlayers()) { -+ PlayerConnection connection = player.playerConnection; ++ net.minecraft.server.network.PlayerConnection connection = player.playerConnection; + if (connection != null) { + connection.networkManager.disableAutomaticFlush(); + disabledFlushes.add(connection.networkManager); @@ -11547,7 +12200,7 @@ index 0ea1b25bf98d71c251351807fa92d4d08eb6b06e..b55f7dece329dbb3ff27d57a39c32c69 this.playerChunkMap.g(); + // Tuinity start - controlled flush for entity tracker packets + } finally { -+ for (NetworkManager networkManager : disabledFlushes) { ++ for (net.minecraft.network.NetworkManager networkManager : disabledFlushes) { + networkManager.enableAutomaticFlush(); + } + } @@ -11555,7 +12208,7 @@ index 0ea1b25bf98d71c251351807fa92d4d08eb6b06e..b55f7dece329dbb3ff27d57a39c32c69 } private void a(long i, Consumer consumer) { -@@ -1001,51 +1212,19 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -1026,51 +1237,19 @@ public class ChunkProviderServer extends IChunkProvider { ChunkProviderServer.this.world.getMethodProfiler().c("runTask"); super.executeTask(runnable); } @@ -11611,915 +12264,11 @@ index 0ea1b25bf98d71c251351807fa92d4d08eb6b06e..b55f7dece329dbb3ff27d57a39c32c69 return super.executeNext() || execChunkTask; // Paper } } finally { -diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -index f51bf71c8d6eef3c054ac64765709794fcfad5ee..076d6c1e1cc049dd312ecb30518e7b25fc2d7371 100644 ---- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -@@ -24,6 +24,14 @@ public class ChunkRegionLoader { - - private static final Logger LOGGER = LogManager.getLogger(); - -+ // Tuinity start -+ // TODO: Check on update -+ public static long getLastWorldSaveTime(NBTTagCompound chunkData) { -+ NBTTagCompound levelData = chunkData.getCompound("Level"); -+ return levelData.getLong("LastUpdate"); -+ } -+ // Tuinity end -+ - // Paper start - guard against serializing mismatching coordinates - // TODO Note: This needs to be re-checked each update - public static ChunkCoordIntPair getChunkCoordinate(NBTTagCompound chunkData) { -@@ -56,6 +64,13 @@ public class ChunkRegionLoader { - private static final boolean JUST_CORRUPT_IT = Boolean.getBoolean("Paper.ignoreWorldDataVersion"); - // Paper end - -+ // Tuinity start - rewrite light engine -+ private static final int STARLIGHT_LIGHT_VERSION = 4; -+ -+ private static final String UNINITIALISED_SKYLIGHT_TAG = "starlight.skylight_uninit"; -+ private static final String STARLIGHT_VERSION_TAG = "starlight.light_version"; -+ // Tuinity end - rewrite light engine -+ - public static InProgressChunkHolder loadChunk(WorldServer worldserver, DefinedStructureManager definedstructuremanager, VillagePlace villageplace, ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound, boolean distinguish) { - ArrayDeque tasksToExecuteOnMain = new ArrayDeque<>(); - // Paper end -@@ -85,13 +100,17 @@ public class ChunkRegionLoader { - ProtoChunkTickList protochunkticklist1 = new ProtoChunkTickList<>((fluidtype) -> { - return fluidtype == null || fluidtype == FluidTypes.EMPTY; - }, chunkcoordintpair, nbttagcompound1.getList("LiquidsToBeTicked", 9)); -- boolean flag = nbttagcompound1.getBoolean("isLightOn"); -+ boolean flag = (com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? nbttagcompound1.getInt(STARLIGHT_VERSION_TAG) == STARLIGHT_LIGHT_VERSION : nbttagcompound1.getBoolean("isLightOn")); boolean canUseSkyLight = flag && getStatus(nbttagcompound).isAtLeastStatus(ChunkStatus.LIGHT); boolean canUseBlockLight = canUseSkyLight; // Tuinity - NBTTagList nbttaglist = nbttagcompound1.getList("Sections", 10); - boolean flag1 = true; - ChunkSection[] achunksection = new ChunkSection[16]; - boolean flag2 = worldserver.getDimensionManager().hasSkyLight(); - ChunkProviderServer chunkproviderserver = worldserver.getChunkProvider(); - LightEngine lightengine = chunkproviderserver.getLightEngine(); -+ com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] blockNibbles = com.tuinity.tuinity.chunk.light.StarLightEngine.getFilledEmptyLight(worldserver); // Tuinity - replace light impl -+ com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] skyNibbles = com.tuinity.tuinity.chunk.light.StarLightEngine.getFilledEmptyLight(worldserver); // Tuinity - replace light impl -+ final int minSection = com.tuinity.tuinity.util.WorldUtil.getMinLightSection(worldserver); -+ final int maxSection = com.tuinity.tuinity.util.WorldUtil.getMaxLightSection(worldserver); - - if (flag) { - tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main -@@ -119,6 +138,7 @@ public class ChunkRegionLoader { - - if (flag) { - if (nbttagcompound2.hasKeyOfType("BlockLight", 7)) { -+ if (com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine && canUseBlockLight) blockNibbles[b0 - minSection] = new com.tuinity.tuinity.chunk.light.SWMRNibbleArray(nbttagcompound2.getByteArray("BlockLight").clone()); // Tuinity - replace light impl - // Paper start - delay this task since we're executing off-main - NibbleArray blockLight = new NibbleArray(nbttagcompound2.getByteArray("BlockLight")); - tasksToExecuteOnMain.add(() -> { -@@ -128,13 +148,14 @@ public class ChunkRegionLoader { - } - - if (flag2 && nbttagcompound2.hasKeyOfType("SkyLight", 7)) { -+ if (com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine && canUseSkyLight) skyNibbles[b0 - minSection] = new com.tuinity.tuinity.chunk.light.SWMRNibbleArray(nbttagcompound2.getByteArray("SkyLight").clone()); // Tuinity - replace light impl - // Paper start - delay this task since we're executing off-main - NibbleArray skyLight = new NibbleArray(nbttagcompound2.getByteArray("SkyLight")); - tasksToExecuteOnMain.add(() -> { - lightengine.a(EnumSkyBlock.SKY, SectionPosition.a(chunkcoordintpair, b0), skyLight, true); - }); - // Paper end - delay this task since we're executing off-main -- } -+ } else if (flag2 && nbttagcompound2.getBoolean(UNINITIALISED_SKYLIGHT_TAG)) skyNibbles[b0 - minSection] = new com.tuinity.tuinity.chunk.light.SWMRNibbleArray(); // Tuinity - replace light impl - } - } - -@@ -173,8 +194,12 @@ public class ChunkRegionLoader { - object = new Chunk(worldserver.getMinecraftWorld(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, // Paper start - fix massive nbt memory leak due to lambda. move lambda into a container method to not leak scope. Only clone needed NBT keys. - createLoadEntitiesConsumer(new SafeNBTCopy(nbttagcompound1, "TileEntities", "Entities", "ChunkBukkitValues")) // Paper - move CB Chunk PDC into here - );// Paper end -+ ((Chunk)object).setBlockNibbles(blockNibbles); // Tuinity - replace light impl -+ ((Chunk)object).setSkyNibbles(skyNibbles); // Tuinity - replace light impl - } else { - ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, worldserver); // Paper - Anti-Xray - Add parameter -+ protochunk.setBlockNibbles(blockNibbles); // Tuinity - replace light impl -+ protochunk.setSkyNibbles(skyNibbles); // Tuinity - replace light impl - - protochunk.a(biomestorage); - object = protochunk; -@@ -353,15 +378,20 @@ public class ChunkRegionLoader { - NibbleArray[] blockLight = new NibbleArray[17 - (-1)]; - NibbleArray[] skyLight = new NibbleArray[17 - (-1)]; - -+ // Tuinity start - rewrite light impl -+ final int minSection = com.tuinity.tuinity.util.WorldUtil.getMinLightSection(world); -+ final int maxSection = com.tuinity.tuinity.util.WorldUtil.getMaxLightSection(world); -+ // Tuinity end - rewrite light impl -+ - for (int i = -1; i < 17; ++i) { -- NibbleArray blockArray = lightenginethreaded.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkPos, i)); -- NibbleArray skyArray = lightenginethreaded.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkPos, i)); -+ NibbleArray blockArray = com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? (!lightenginethreaded.hasBlockLight ? null : (chunk.getBlockNibbles()[i - minSection].isAllZero() ? new NibbleArray() : chunk.getBlockNibbles()[i - minSection].toVanillaNibble())) : lightenginethreaded.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkPos, i)); // Tuinity - chunk might not be loaded -+ NibbleArray skyArray = com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? (!lightenginethreaded.hasSkyLight ? null : (chunk.getSkyNibbles()[i - minSection].isAllZero() ? new NibbleArray() : chunk.getSkyNibbles()[i - minSection].toVanillaNibble())) : lightenginethreaded.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkPos, i)); // Tuinity - chunk might not be loaded - - // copy data for safety -- if (blockArray != null) { -+ if (!com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine && blockArray != null) { // Tuinity - data already copied - blockArray = blockArray.copy(); - } -- if (skyArray != null) { -+ if (!com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine && skyArray != null) { // Tuinity - data already copied - skyArray = skyArray.copy(); - } - -@@ -396,15 +426,19 @@ public class ChunkRegionLoader { - } - public static NBTTagCompound saveChunk(WorldServer worldserver, IChunkAccess ichunkaccess, AsyncSaveData asyncsavedata) { - // Paper end -+ // Tuinity start - rewrite light impl -+ final int minSection = com.tuinity.tuinity.util.WorldUtil.getMinLightSection(worldserver); -+ final int maxSection = com.tuinity.tuinity.util.WorldUtil.getMaxLightSection(worldserver); -+ // Tuinity end - rewrite light impl - ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos(); - NBTTagCompound nbttagcompound = new NBTTagCompound(); - NBTTagCompound nbttagcompound1 = new NBTTagCompound(); - - nbttagcompound.setInt("DataVersion", SharedConstants.getGameVersion().getWorldVersion()); -- nbttagcompound.set("Level", nbttagcompound1); -+ nbttagcompound.set("Level", nbttagcompound1); // Tuinity - diff on change - nbttagcompound1.setInt("xPos", chunkcoordintpair.x); - nbttagcompound1.setInt("zPos", chunkcoordintpair.z); -- nbttagcompound1.setLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : worldserver.getTime()); // Paper - async chunk unloading -+ nbttagcompound1.setLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : worldserver.getTime()); // Paper - async chunk unloading // Tuinity - diff on change - nbttagcompound1.setLong("InhabitedTime", ichunkaccess.getInhabitedTime()); - nbttagcompound1.setString("Status", ichunkaccess.getChunkStatus().d()); - ChunkConverter chunkconverter = ichunkaccess.p(); -@@ -429,8 +463,8 @@ public class ChunkRegionLoader { - NibbleArray nibblearray; // block light - NibbleArray nibblearray1; // sky light - if (asyncsavedata == null) { -- nibblearray = lightenginethreaded.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkcoordintpair, i)); /// Paper - diff on method change (see getAsyncSaveData) -- nibblearray1 = lightenginethreaded.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, i)); // Paper - diff on method change (see getAsyncSaveData) -+ nibblearray = com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? (!lightenginethreaded.hasBlockLight ? null : (ichunkaccess.getBlockNibbles()[i - minSection].isAllZero() ? new NibbleArray() : ichunkaccess.getBlockNibbles()[i - minSection].toVanillaNibble())) : lightenginethreaded.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkcoordintpair, i)); // Tuinity - chunk might not be loaded -+ nibblearray1 = com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? (!lightenginethreaded.hasSkyLight ? null : (ichunkaccess.getSkyNibbles()[i - minSection].isAllZero() ? new NibbleArray() : ichunkaccess.getSkyNibbles()[i - minSection].toVanillaNibble())) : lightenginethreaded.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, i)); // Tuinity - chunk might not be loaded - } else { - nibblearray = asyncsavedata.blockLight[i + 1]; // +1 to offset the -1 starting index - nibblearray1 = asyncsavedata.skyLight[i + 1]; // +1 to offset the -1 starting index -@@ -444,12 +478,12 @@ public class ChunkRegionLoader { - } - - if (nibblearray != null && !nibblearray.c()) { -- nbttagcompound2.setByteArray("BlockLight", nibblearray.asBytesPoolSafe().clone()); // Paper -+ nbttagcompound2.setByteArray("BlockLight", com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? nibblearray.asBytes() : nibblearray.asBytesPoolSafe().clone()); // Paper // Tuinity - data is already cloned - } - - if (nibblearray1 != null && !nibblearray1.c()) { -- nbttagcompound2.setByteArray("SkyLight", nibblearray1.asBytesPoolSafe().clone()); // Paper -- } -+ nbttagcompound2.setByteArray("SkyLight", com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? nibblearray1.asBytes() : nibblearray1.asBytesPoolSafe().clone()); // Paper // Tuinity - data is already cloned -+ } else if (nibblearray1 != null && com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine) nbttagcompound2.setBoolean(UNINITIALISED_SKYLIGHT_TAG, true); // Tuinity - store uninitialised tags - - nbttaglist.add(nbttagcompound2); - } -@@ -457,7 +491,7 @@ public class ChunkRegionLoader { - - nbttagcompound1.set("Sections", nbttaglist); - if (flag) { -- nbttagcompound1.setBoolean("isLightOn", true); -+ nbttagcompound1.setBoolean("isLightOn", com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? false : true); if (com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine) nbttagcompound1.setInt(STARLIGHT_VERSION_TAG, STARLIGHT_LIGHT_VERSION); // Tuinity - } - - BiomeStorage biomestorage = ichunkaccess.getBiomeIndex(); -diff --git a/src/main/java/net/minecraft/server/ChunkSection.java b/src/main/java/net/minecraft/server/ChunkSection.java -index e52df8096e399c84ff8a2637fdd65ea57d9001d0..33b8f4e0f09fdc41c8ea48b6ed77af199136ab92 100644 ---- a/src/main/java/net/minecraft/server/ChunkSection.java -+++ b/src/main/java/net/minecraft/server/ChunkSection.java -@@ -11,7 +11,7 @@ public class ChunkSection { - short nonEmptyBlockCount; // Paper - package-private - short tickingBlockCount; // Paper - private -> package-private - private short e; -- final DataPaletteBlock blockIds; // Paper - package-private -+ public final DataPaletteBlock blockIds; // Paper - package-private // Tuinity - public - - final com.destroystokyo.paper.util.maplist.IBlockDataList tickingList = new com.destroystokyo.paper.util.maplist.IBlockDataList(); // Paper - -@@ -96,6 +96,7 @@ public class ChunkSection { - return iblockdata1; - } - -+ public final boolean isFullOfAir() { return this.c(); } // Tuinity - OBFHELPER - public boolean c() { - return this.nonEmptyBlockCount == 0; - } -diff --git a/src/main/java/net/minecraft/server/ChunkStatus.java b/src/main/java/net/minecraft/server/ChunkStatus.java -index f6c9bdbf52d773d7aa601125b887b347163f9328..51ea295d66312c95685b9fe4ee502a029d2fff20 100644 ---- a/src/main/java/net/minecraft/server/ChunkStatus.java -+++ b/src/main/java/net/minecraft/server/ChunkStatus.java -@@ -109,7 +109,7 @@ public class ChunkStatus { - private final ChunkStatus.c w; - private final int x; - private final ChunkStatus.Type y; -- private final EnumSet z; -+ private final EnumSet z; public final HeightMap.Type[] heightMaps; // Tuinity - - private static CompletableFuture> a(ChunkStatus chunkstatus, LightEngineThreaded lightenginethreaded, IChunkAccess ichunkaccess) { - boolean flag = a(chunkstatus, ichunkaccess); -@@ -171,7 +171,7 @@ public class ChunkStatus { - this.w = chunkstatus_c; - this.x = i; - this.y = chunkstatus_type; -- this.z = enumset; -+ this.z = enumset; this.heightMaps = new java.util.ArrayList<>(this.z).toArray(new HeightMap.Type[0]); // Tuinity - this.t = chunkstatus == null ? 0 : chunkstatus.c() + 1; - } - -diff --git a/src/main/java/net/minecraft/server/DataPaletteBlock.java b/src/main/java/net/minecraft/server/DataPaletteBlock.java -index 95ef96286855624590b72d69514b0fc0e08fddba..73163b417af7e522a4509bf9c1ab56d6499be622 100644 ---- a/src/main/java/net/minecraft/server/DataPaletteBlock.java -+++ b/src/main/java/net/minecraft/server/DataPaletteBlock.java -@@ -163,6 +163,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { - return this.a(j << 8 | k << 4 | i); // Paper - inline - } - -+ public final T rawGet(int index) { return this.a(index); } // Tuinity - OBFHELPER - protected T a(int i) { - T t0 = this.h.a(this.a.a(i)); - -diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java -index d4793a1d476d8d6687ec8782501c31265f284daa..2644b190813cc934914aeab78fbd6515d1a37c4a 100644 ---- a/src/main/java/net/minecraft/server/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/DedicatedServer.java -@@ -175,6 +175,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - com.destroystokyo.paper.PaperConfig.registerCommands(); - com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now - // Paper end -+ com.tuinity.tuinity.config.TuinityConfig.init((java.io.File) options.valueOf("tuinity-settings")); // Tuinity - Server Config - - this.setPVP(dedicatedserverproperties.pvp); - this.setAllowFlight(dedicatedserverproperties.allowFlight); -@@ -359,7 +360,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - } - - if (this.q != null) { -- this.q.b(); -+ //this.q.b(); // Tuinity - do not wait for AWT, causes deadlock with sigint handler (AWT shutdown will properly clear our resources anyways) - } - - if (this.remoteControlListener != null) { -diff --git a/src/main/java/net/minecraft/server/EULA.java b/src/main/java/net/minecraft/server/EULA.java -index 550232cb3819138b3bae0fa1c51429485e8bc593..229c3b0f0c650b501f31147adaa17194af57fedd 100644 ---- a/src/main/java/net/minecraft/server/EULA.java -+++ b/src/main/java/net/minecraft/server/EULA.java -@@ -70,7 +70,7 @@ public class EULA { - Properties properties = new Properties(); - - properties.setProperty("eula", "false"); -- properties.store(outputstream, "By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula).\nYou also agree that tacos are tasty, and the best food in the world."); // Paper - fix lag; -+ properties.store(outputstream, "By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula)."); // Paper - fix lag; // Tuinity - Tacos are disgusting - } catch (Throwable throwable1) { - throwable = throwable1; - throw throwable1; -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 534238688be75c53058dcfeabcdf86d9c0504089..2ec48858be8eb2c522c9685b43bd36b3b581cf8b 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -136,7 +136,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - public double D; - public double E; - public double F; -- public float G; -+ public float G; public final float getStepHeight() { return this.G; } // Tuinity - OBFHELPER - public boolean noclip; - public float I; - protected final Random random; -@@ -207,6 +207,14 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - } - // CraftBukkit end - -+ // Tuinity start -+ public final AxisAlignedBB getBoundingBoxAt(double x, double y, double z) { -+ double widthHalf = (double)this.size.width / 2.0; -+ double height = (double)this.size.height; -+ return new AxisAlignedBB(x - widthHalf, y, z - widthHalf, x + widthHalf, y + height, z + widthHalf); -+ } -+ // Tuinity end -+ - // Paper start - optimise entity tracking - final org.spigotmc.TrackingRange.TrackingRangeType trackingRangeType = org.spigotmc.TrackingRange.getTrackingRangeType(this); - -@@ -217,11 +225,59 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - } - - final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getPlayersInTrackRange() { -- return ((WorldServer)this.world).getChunkProvider().playerChunkMap.playerEntityTrackerTrackMaps[this.trackingRangeType.ordinal()] -- .getObjectsInRange(MCUtil.getCoordinateKey(this)); -+ Collection passengers = this.getAllPassengers(); -+ PlayerChunkMap chunkMap = ((WorldServer)this.world).getChunkProvider().playerChunkMap; -+ org.spigotmc.TrackingRange.TrackingRangeType type = this.trackingRangeType; -+ int range = chunkMap.entityTrackerTrackRanges[type.ordinal()]; -+ -+ for (Entity passenger : passengers) { -+ org.spigotmc.TrackingRange.TrackingRangeType passengerType = passenger.trackingRangeType; -+ int passengerRange = chunkMap.entityTrackerTrackRanges[passengerType.ordinal()]; -+ if (passengerRange > range) { -+ type = passengerType; -+ range = passengerRange; -+ } -+ } -+ -+ return chunkMap.playerEntityTrackerTrackMaps[type.ordinal()].getObjectsInRange(MCUtil.getCoordinateKey(this)); - } - // Paper end - optimise entity tracking - -+ // Tuinity start -+ /** -+ * Overriding this field will cause memory leaks. -+ */ -+ private final boolean hardCollides; -+ -+ private static final java.util.Map, Boolean> cachedOverrides = java.util.Collections.synchronizedMap(new java.util.WeakHashMap<>()); -+ { -+ Boolean hardCollides = cachedOverrides.get(this.getClass()); -+ if (hardCollides == null) { -+ try { -+ java.lang.reflect.Method getHardCollisionBoxEntityMethod = Entity.class.getMethod("j", Entity.class); -+ java.lang.reflect.Method hasHardCollisionBoxMethod = Entity.class.getMethod("aZ"); -+ if (!this.getClass().getMethod(hasHardCollisionBoxMethod.getName(), hasHardCollisionBoxMethod.getParameterTypes()).equals(hasHardCollisionBoxMethod) -+ || !this.getClass().getMethod(getHardCollisionBoxEntityMethod.getName(), getHardCollisionBoxEntityMethod.getParameterTypes()).equals(getHardCollisionBoxEntityMethod)) { -+ hardCollides = Boolean.TRUE; -+ } else { -+ hardCollides = Boolean.FALSE; -+ } -+ cachedOverrides.put(this.getClass(), hardCollides); -+ } -+ catch (ThreadDeath thr) { throw thr; } -+ catch (Throwable thr) { -+ // shouldn't happen, just explode -+ throw new RuntimeException(thr); -+ } -+ } -+ this.hardCollides = hardCollides.booleanValue(); -+ } -+ -+ public final boolean hardCollides() { -+ return this.hardCollides; -+ } -+ // Tuinity end -+ - public Entity(EntityTypes entitytypes, World world) { - this.id = Entity.entityCount.incrementAndGet(); - this.passengers = Lists.newArrayList(); -@@ -591,7 +647,39 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - return this.onGround; - } - -+ // Tuinity start - detailed watchdog information -+ private Vec3D moveVector; -+ private double moveStartX; -+ private double moveStartY; -+ private double moveStartZ; -+ -+ public final Vec3D getMoveVector() { -+ return this.moveVector; -+ } -+ -+ public final double getMoveStartX() { -+ return this.moveStartX; -+ } -+ -+ public final double getMoveStartY() { -+ return this.moveStartY; -+ } -+ -+ public final double getMoveStartZ() { -+ return this.moveStartZ; -+ } -+ // Tuinity end - detailed watchdog information - public void move(EnumMoveType enummovetype, Vec3D vec3d) { -+ // Tuinity start - detailed watchdog information -+ com.tuinity.tuinity.util.TickThread.ensureTickThread("Cannot move an entity off-main"); -+ synchronized (this.posLock) { -+ this.moveStartX = this.locX(); -+ this.moveStartY = this.locY(); -+ this.moveStartZ = this.locZ(); -+ this.moveVector = vec3d; -+ } -+ try { -+ // Tuinity end - detailed watchdog information - if (this.noclip) { - this.a(this.getBoundingBox().c(vec3d)); - this.recalcPosition(); -@@ -619,7 +707,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - // Paper end - - vec3d = this.a(vec3d, enummovetype); -- Vec3D vec3d1 = this.g(vec3d); -+ Vec3D vec3d1 = this.performCollision(vec3d); // Tuinity - optimise collisions - - if (vec3d1.g() > 1.0E-7D) { - this.a(this.getBoundingBox().c(vec3d1)); -@@ -710,7 +798,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - } - - try { -- this.checkBlockCollisions(); -+ this.checkBlockCollisions(this.fireTicks <= 0); // Tuinity - move fire checking into method here - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.a(throwable, "Checking entity block collision"); - CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity being checked for collision"); -@@ -722,11 +810,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - float f2 = this.getBlockSpeedFactor(); - - this.setMot(this.getMot().d((double) f2, 1.0D, (double) f2)); -- if (this.world.c(this.getBoundingBox().shrink(0.001D)).noneMatch((iblockdata1) -> { -- return iblockdata1.a((Tag) TagsBlock.FIRE) || iblockdata1.a(Blocks.LAVA); -- }) && this.fireTicks <= 0) { -- this.setFireTicks(-this.getMaxFireTicks()); -- } -+ // Tuinity - move into checkBlockCollisions - - if (this.aG() && this.isBurning()) { - this.playSound(SoundEffects.ENTITY_GENERIC_EXTINGUISH_FIRE, 0.7F, 1.6F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); -@@ -735,6 +819,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - - this.world.getMethodProfiler().exit(); - } -+ // Tuinity start - detailed watchdog information -+ } finally { -+ synchronized (this.posLock) { // Tuinity -+ this.moveVector = null; -+ } // Tuinity -+ } -+ // Tuinity end - detailed watchdog information - } - - protected BlockPosition ap() { -@@ -815,6 +906,137 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - return d0; - } - -+ // Tuinity start - optimise entity movement -+ private static double performCollisionsX(AxisAlignedBB currentBoundingBox, double value, List potentialCollisions) { -+ for (int i = 0, len = potentialCollisions.size(); i < len; ++i) { -+ AxisAlignedBB target = potentialCollisions.get(i); -+ value = AxisAlignedBB.collideX(target, currentBoundingBox, value); -+ } -+ -+ return value; -+ } -+ -+ private static double performCollisionsY(AxisAlignedBB currentBoundingBox, double value, List potentialCollisions) { -+ for (int i = 0, len = potentialCollisions.size(); i < len; ++i) { -+ AxisAlignedBB target = potentialCollisions.get(i); -+ value = AxisAlignedBB.collideY(target, currentBoundingBox, value); -+ } -+ -+ return value; -+ } -+ -+ private static double performCollisionsZ(AxisAlignedBB currentBoundingBox, double value, List potentialCollisions) { -+ for (int i = 0, len = potentialCollisions.size(); i < len; ++i) { -+ AxisAlignedBB target = potentialCollisions.get(i); -+ value = AxisAlignedBB.collideZ(target, currentBoundingBox, value); -+ } -+ -+ return value; -+ } -+ -+ private static Vec3D performCollisions(Vec3D moveVector, AxisAlignedBB axisalignedbb, List potentialCollisions) { -+ double x = moveVector.x; -+ double y = moveVector.y; -+ double z = moveVector.z; -+ -+ if (y != 0.0) { -+ y = Entity.performCollisionsY(axisalignedbb, y, potentialCollisions); -+ if (y != 0.0) { -+ axisalignedbb = axisalignedbb.offsetY(y); -+ } -+ } -+ -+ boolean xSmaller = Math.abs(x) < Math.abs(z); -+ -+ if (xSmaller && z != 0.0) { -+ z = Entity.performCollisionsZ(axisalignedbb, z, potentialCollisions); -+ if (z != 0.0) { -+ axisalignedbb = axisalignedbb.offsetZ(z); -+ } -+ } -+ -+ if (x != 0.0) { -+ x = Entity.performCollisionsX(axisalignedbb, x, potentialCollisions); -+ if (!xSmaller && x != 0.0) { -+ axisalignedbb = axisalignedbb.offsetX(x); -+ } -+ } -+ -+ if (!xSmaller && z != 0.0) { -+ z = Entity.performCollisionsZ(axisalignedbb, z, potentialCollisions); -+ } -+ -+ return new Vec3D(x, y, z); -+ } -+ -+ Vec3D performCollision(Vec3D moveVector) { -+ if (moveVector.getX() == 0.0 && moveVector.getY() == 0.0 && moveVector.getZ() == 0.0) { -+ return moveVector; -+ } -+ -+ WorldServer world = ((WorldServer)this.world); -+ AxisAlignedBB currBoundingBox = this.getBoundingBox(); -+ -+ List potentialCollisions = com.tuinity.tuinity.util.CachedLists.getTempCollisionList(); -+ try { -+ AxisAlignedBB collisionBox; -+ double stepHeight = (double)this.getStepHeight(); -+ -+ if (moveVector.x == 0.0 && moveVector.z == 0.0 && moveVector.y != 0.0) { -+ // a lot of entities just stand still. optimise the search AABB -+ if (moveVector.y > 0.0) { -+ collisionBox = currBoundingBox.cutUpwards(moveVector.y); -+ } else { -+ collisionBox = currBoundingBox.cutDownwards(moveVector.y); -+ } -+ } else { -+ if (stepHeight > 0.0 && (this.onGround || (moveVector.y < 0.0)) && (moveVector.x != 0.0 || moveVector.z != 0.0)) { -+ // don't bother getting the collisions if we don't need them. -+ if (moveVector.y <= 0.0) { -+ collisionBox = currBoundingBox.expand(moveVector.x, moveVector.y, moveVector.z).expandUpwards(stepHeight); -+ } else { -+ collisionBox = currBoundingBox.expand(moveVector.x, Math.max(stepHeight, moveVector.y), moveVector.z); -+ } -+ } else { -+ collisionBox = currBoundingBox.expand(moveVector.x, moveVector.y, moveVector.z); -+ } -+ } -+ -+ world.getCollisions(this, collisionBox, potentialCollisions, this instanceof EntityPlayer && !this.world.paperConfig.preventMovingIntoUnloadedChunks); -+ if (world.getWorldBorder().isCollidingWithBorderEdge(collisionBox)) { -+ VoxelShapes.addBoxesToIfIntersects(world.getWorldBorder().getCollisionShape(), collisionBox, potentialCollisions); -+ } -+ -+ Vec3D limitedMoveVector = Entity.performCollisions(moveVector, currBoundingBox, potentialCollisions); -+ -+ if (stepHeight > 0.0 -+ && (this.onGround || (limitedMoveVector.y != moveVector.y && moveVector.y < 0.0)) -+ && (limitedMoveVector.x != moveVector.x || limitedMoveVector.z != moveVector.z)) { -+ Vec3D vec3d2 = Entity.performCollisions(new Vec3D(moveVector.x, stepHeight, moveVector.z), currBoundingBox, potentialCollisions); -+ Vec3D vec3d3 = Entity.performCollisions(new Vec3D(0.0, stepHeight, 0.0), currBoundingBox.expand(moveVector.x, 0.0, moveVector.z), potentialCollisions); -+ -+ if (vec3d3.y < stepHeight) { -+ Vec3D vec3d4 = Entity.performCollisions(new Vec3D(moveVector.x, 0.0D, moveVector.z), currBoundingBox.offset(vec3d3), potentialCollisions).add(vec3d3); -+ -+ if (Entity.getXZSquared(vec3d4) > Entity.getXZSquared(vec3d2)) { -+ vec3d2 = vec3d4; -+ } -+ } -+ -+ if (Entity.getXZSquared(vec3d2) > Entity.getXZSquared(limitedMoveVector)) { -+ return vec3d2.add(Entity.performCollisions(new Vec3D(0.0D, -vec3d2.y + moveVector.y, 0.0D), currBoundingBox.offset(vec3d2), potentialCollisions)); -+ } -+ -+ return limitedMoveVector; -+ } else { -+ return limitedMoveVector; -+ } -+ } finally { -+ com.tuinity.tuinity.util.CachedLists.returnTempCollisionList(potentialCollisions); -+ } -+ } -+ // Tuinity end - optimise entity movement -+ - private Vec3D g(Vec3D vec3d) { - AxisAlignedBB axisalignedbb = this.getBoundingBox(); - VoxelShapeCollision voxelshapecollision = VoxelShapeCollision.a(this); -@@ -850,6 +1072,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - return vec3d1; - } - -+ public static double getXZSquared(Vec3D vec3d) { return Entity.c(vec3d); } // Tuinity - OBFHELPER - public static double c(Vec3D vec3d) { - return vec3d.x * vec3d.x + vec3d.z * vec3d.z; - } -@@ -962,18 +1185,34 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - } - - protected void checkBlockCollisions() { -+ // Tuinity start -+ this.checkBlockCollisions(false); -+ } -+ protected void checkBlockCollisions(boolean checkFire) { -+ boolean inFire = false; -+ // Tuinity end - AxisAlignedBB axisalignedbb = this.getBoundingBox(); - BlockPosition blockposition = new BlockPosition(axisalignedbb.minX + 0.001D, axisalignedbb.minY + 0.001D, axisalignedbb.minZ + 0.001D); - BlockPosition blockposition1 = new BlockPosition(axisalignedbb.maxX - 0.001D, axisalignedbb.maxY - 0.001D, axisalignedbb.maxZ - 0.001D); - BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); - - if (this.world.areChunksLoadedBetween(blockposition, blockposition1)) { -- for (int i = blockposition.getX(); i <= blockposition1.getX(); ++i) { -- for (int j = blockposition.getY(); j <= blockposition1.getY(); ++j) { -- for (int k = blockposition.getZ(); k <= blockposition1.getZ(); ++k) { -+ // Tuinity start - reorder iteration to more cache aware -+ for (int j = blockposition.getY(); j <= blockposition1.getY(); ++j) { -+ for (int k = blockposition.getZ(); k <= blockposition1.getZ(); ++k) { -+ for (int i = blockposition.getX(); i <= blockposition1.getX(); ++i) { -+ // Tuinity end - reorder iteration to more cache aware - blockposition_mutableblockposition.d(i, j, k); - IBlockData iblockdata = this.world.getType(blockposition_mutableblockposition); - -+ // Tuinity start - move fire checking in here - reuse getType from this method -+ if (checkFire) { -+ if (!inFire && (iblockdata.a(TagsBlock.FIRE) || iblockdata.a(Blocks.LAVA))) { -+ inFire = true; -+ } -+ } -+ // Tuinity end - move fire checking in here - reuse getType from this method -+ - try { - iblockdata.a(this.world, blockposition_mutableblockposition, this); - this.a(iblockdata); -@@ -987,6 +1226,11 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - } - } - } -+ // Tuinity start - move fire checking in here - reuse getType from this method -+ if (checkFire & !inFire) { -+ this.setFireTicks(-this.getMaxFireTicks()); -+ } -+ // Tuinity end - move fire checking in here - reuse getType from this method - } - - } -@@ -1358,6 +1602,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - return d3 * d3 + d4 * d4 + d5 * d5; - } - -+ public final double getDistanceSquared(Entity other) { return this.h(other); } // Tuinity - OBFHELPER - public double h(Entity entity) { - return this.e(entity.getPositionVector()); - } -@@ -1945,9 +2190,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - float f1 = this.size.width * 0.8F; - AxisAlignedBB axisalignedbb = AxisAlignedBB.g((double) f1, 0.10000000149011612D, (double) f1).d(this.locX(), this.getHeadY(), this.locZ()); - -- return this.world.b(this, axisalignedbb, (iblockdata, blockposition) -> { -+ return ((WorldServer)this.world).collidesWithAnyBlockOrWorldBorder(this, axisalignedbb, false, false, (iblockdata, blockposition) -> { // Tuinity - use optimised method - return iblockdata.o(this.world, blockposition); -- }).findAny().isPresent(); -+ }); // Tuinity - use optimised method - } - } - -@@ -1955,11 +2200,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - return EnumInteractionResult.PASS; - } - -- public boolean j(Entity entity) { -+ public final boolean hardCollidesWith(Entity other) { return this.j(other); } // Tuinity - OBFHELPER -+ public boolean j(Entity entity) { // Tuinity - diff on change, hard colliding entities override this - return entity.aZ() && !this.isSameVehicle(entity); - } - -- public boolean aZ() { -+ public final boolean collisionBoxIsHard() { return this.aZ(); } // Tuinity - OBFHELPER -+ public boolean aZ() {// Tuinity - diff on change, hard colliding entities override this - return false; - } - -@@ -2850,7 +3097,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - this.recursiveStream().forEach((entity) -> { - worldserver.chunkCheck(entity); - entity.az = true; -- Iterator iterator = entity.passengers.iterator(); -+ Iterator iterator = new java.util.ArrayList<>(entity.passengers).iterator(); // Tuinity - copy list to guard against CME - - while (iterator.hasNext()) { - Entity entity1 = (Entity) iterator.next(); -@@ -3308,12 +3555,16 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - return this.locBlock; - } - -+ public final Object posLock = new Object(); // Tuinity - log detailed entity tick information -+ - public Vec3D getMot() { - return this.mot; - } - - public void setMot(Vec3D vec3d) { -+ synchronized (this.posLock) { // Tuinity - this.mot = vec3d; -+ } // Tuinity - } - - public void setMot(double d0, double d1, double d2) { -@@ -3368,7 +3619,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - } - // Paper end - if (this.loc.x != d0 || this.loc.y != d1 || this.loc.z != d2) { -+ synchronized (this.posLock) { // Tuinity - this.loc = new Vec3D(d0, d1, d2); -+ } // Tuinity - int i = MathHelper.floor(d0); - int j = MathHelper.floor(d1); - int k = MathHelper.floor(d2); -diff --git a/src/main/java/net/minecraft/server/EntityArrow.java b/src/main/java/net/minecraft/server/EntityArrow.java -index 1e7f5957d879d1ba8cf2b29cf9397b8e204e4381..7532e4e6fc561645e7e7a4f703025af77825b0bd 100644 ---- a/src/main/java/net/minecraft/server/EntityArrow.java -+++ b/src/main/java/net/minecraft/server/EntityArrow.java -@@ -173,7 +173,9 @@ public abstract class EntityArrow extends IProjectile { - // Paper end - - if (object != null && !flag) { -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, (MovingObjectPosition) object)) { // CraftBukkit - Call event // Paper - make cancellable // Tuinity - implement cancellation properly - this.a((MovingObjectPosition) object); -+ } // Tuinity - implement cancellation properly - this.impulse = true; - } - -@@ -507,7 +509,8 @@ public abstract class EntityArrow extends IProjectile { - } - itemstack = item.getItemStack(); - } -- boolean flag = this.fromPlayer == EntityArrow.PickupStatus.ALLOWED || this.fromPlayer == EntityArrow.PickupStatus.CREATIVE_ONLY && entityhuman.abilities.canInstantlyBuild || this.t() && this.getShooter().getUniqueID() == entityhuman.getUniqueID(); -+ Entity shooter; // Tuinity - fix NPE here -+ boolean flag = this.fromPlayer == EntityArrow.PickupStatus.ALLOWED || this.fromPlayer == EntityArrow.PickupStatus.CREATIVE_ONLY && entityhuman.abilities.canInstantlyBuild || this.t() && ((shooter = this.getShooter()) != null && shooter.getUniqueID() == entityhuman.getUniqueID()); // Tuinity - fix NPE here - - if (this.fromPlayer == EntityArrow.PickupStatus.ALLOWED && !entityhuman.inventory.pickup(itemstack)) { - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/server/EntityCat.java b/src/main/java/net/minecraft/server/EntityCat.java -index 8bc8dcf7dfe79c5522bc715ad60aeaab4b1d85da..675083e3952779e43bf8cc3175ad70458a79e49c 100644 ---- a/src/main/java/net/minecraft/server/EntityCat.java -+++ b/src/main/java/net/minecraft/server/EntityCat.java -@@ -292,7 +292,7 @@ public class EntityCat extends EntityTameableAnimal { - - WorldServer worldserver = worldaccess.getMinecraftWorld(); - -- if (worldserver instanceof WorldServer && ((WorldServer) worldserver).getStructureManager().a(this.getChunkCoordinates(), true, StructureGenerator.SWAMP_HUT).e()) { -+ if (worldserver instanceof WorldServer && ((WorldServer) worldserver).getStructureManager().getStructureStarts(this.getChunkCoordinates(), true, StructureGenerator.SWAMP_HUT, worldaccess).e()) { // Tuinity - fix deadlock on chunk gen - this.setCatType(10); - this.setPersistent(); - } -diff --git a/src/main/java/net/minecraft/server/EntityEnderDragon.java b/src/main/java/net/minecraft/server/EntityEnderDragon.java -index 7289d6c706b6c845584bac616c9babea80f8e885..50b93c93cfede2d64a996a22b811994b352149af 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/server/EntityEnderDragon.java -@@ -576,9 +576,9 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - if (this.deathAnimationTicks == 1 && !this.isSilent()) { - // CraftBukkit start - Use relative location for far away sounds - // this.world.b(1028, this.getChunkCoordinates(), 0); -- int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ // int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API // Tuinity - apply view distance patch - for (EntityPlayer player : (List) ((WorldServer)world).getPlayers()) { -- // final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch -+ final int viewDistance = player.getBukkitEntity().getViewDistance(); // Tuinity - apply view distance patch - // Paper end - double deltaX = this.locX() - player.locX(); - double deltaZ = this.locZ() - player.locZ(); -diff --git a/src/main/java/net/minecraft/server/EntityFireball.java b/src/main/java/net/minecraft/server/EntityFireball.java -index 0840fdf3585407ec317f0326359619220c64db78..6b9b64539d2272070b523ed6b927de02d2b00af5 100644 ---- a/src/main/java/net/minecraft/server/EntityFireball.java -+++ b/src/main/java/net/minecraft/server/EntityFireball.java -@@ -67,7 +67,9 @@ public abstract class EntityFireball extends IProjectile { - // Paper end - - if (movingobjectposition != null && movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS) { // Paper - add null check in case cancelled -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition)) { // CraftBukkit - Call event // Paper - make cancellable // Tuinity - implement cancellation properly - this.a(movingobjectposition); -+ } // Tuinity - implement cancellation properly - - // CraftBukkit start - Fire ProjectileHitEvent - if (this.dead) { -diff --git a/src/main/java/net/minecraft/server/EntityFireworks.java b/src/main/java/net/minecraft/server/EntityFireworks.java -index 9bc4d3dbd4c64a6fbf33dcf28afde59ace9171ba..7ec62d734542d64809c71776eb865ff8ca51dc7f 100644 ---- a/src/main/java/net/minecraft/server/EntityFireworks.java -+++ b/src/main/java/net/minecraft/server/EntityFireworks.java -@@ -125,7 +125,9 @@ public class EntityFireworks extends IProjectile { - MovingObjectPosition movingobjectposition = ProjectileHelper.a((Entity) this, this::a); - - if (!this.noclip) { -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition)) { // CraftBukkit - Call event // Paper - make cancellable // Tuinity - implement cancellation properly - this.a(movingobjectposition); -+ } // Tuinity - implement cancellation properly - this.impulse = true; - } - -diff --git a/src/main/java/net/minecraft/server/EntityFishingHook.java b/src/main/java/net/minecraft/server/EntityFishingHook.java -index 3580f40b2bb30bceca0ce374edb29608168a00c0..9841c7c27cd296a5156ba79ab734d45922bacaf7 100644 ---- a/src/main/java/net/minecraft/server/EntityFishingHook.java -+++ b/src/main/java/net/minecraft/server/EntityFishingHook.java -@@ -227,7 +227,9 @@ public class EntityFishingHook extends IProjectile { - private void m() { - MovingObjectPosition movingobjectposition = ProjectileHelper.a((Entity) this, this::a); - -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition)) { // CraftBukkit - Call event // Paper - make cancellable // Tuinity - implement cancellation properly - this.a(movingobjectposition); -+ } // Tuinity - implement cancellation properly - } - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java -index cc2127b26e41182c14fa95afde878e9b5100a117..f034977f4666385d6e7c7288e453d058c270be01 100644 ---- a/src/main/java/net/minecraft/server/EntityHuman.java -+++ b/src/main/java/net/minecraft/server/EntityHuman.java -@@ -356,6 +356,12 @@ public abstract class EntityHuman extends EntityLiving { - this.activeContainer = this.defaultContainer; - } - // Paper end -+ // Tuinity start - special close for unloaded inventory -+ public void closeUnloadedInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { -+ closeInventory(); -+ this.activeContainer = this.defaultContainer; -+ } -+ // Tuinity end - special close for unloaded inventory - - public void closeInventory() { - this.activeContainer = this.defaultContainer; -diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java -index a88521745f9f9b6935a61db52db915ea483af227..a47217c020d2c2a3caddafa0549dc827373798dd 100644 ---- a/src/main/java/net/minecraft/server/EntityInsentient.java -+++ b/src/main/java/net/minecraft/server/EntityInsentient.java -@@ -711,7 +711,13 @@ public abstract class EntityInsentient extends EntityLiving { - if (this.world.getDifficulty() == EnumDifficulty.PEACEFUL && this.L()) { - this.die(); - } else if (!this.isPersistent() && !this.isSpecialPersistence()) { -- EntityHuman entityhuman = this.world.findNearbyPlayer(this, -1.0D, IEntitySelector.affectsSpawning); // Paper -+ // Tuinity start - optimise checkDespawn -+ Chunk chunk = this.getCurrentChunk(); -+ EntityHuman entityhuman = chunk == null || this.world.paperConfig.hardDespawnDistance >= (PlayerChunkMap.GENERAL_AREA_MAP_ACCEPTABLE_SEARCH_RANGE_SQUARED) ? this.world.findNearbyPlayer(this, -1.0D, IEntitySelector.affectsSpawning) : chunk.findNearestPlayer(this.locX(), this.locY(), this.locZ(), -1.0, IEntitySelector.affectsSpawning); // Paper -+ if (entityhuman == null) { -+ entityhuman = ((WorldServer)this.world).playersAffectingSpawning.isEmpty() ? null : ((WorldServer)this.world).playersAffectingSpawning.get(0); -+ } -+ // Tuinity end - optimise checkDespawn - - if (entityhuman != null) { - double d0 = entityhuman.h((Entity) this); // CraftBukkit - decompile error -diff --git a/src/main/java/net/minecraft/server/EntityItem.java b/src/main/java/net/minecraft/server/EntityItem.java -index 5dfb54e17fcfe6bd30e6b2a449944606e1a0ef17..9a8b7e06f14f17dfea08d7031c83f77491aaca65 100644 ---- a/src/main/java/net/minecraft/server/EntityItem.java -+++ b/src/main/java/net/minecraft/server/EntityItem.java -@@ -527,7 +527,7 @@ public class EntityItem extends Entity { - - // Paper start - fix MC-4 - public void setPositionRaw(double x, double y, double z) { -- if (com.destroystokyo.paper.PaperConfig.fixEntityPositionDesync) { -+ if (false && com.destroystokyo.paper.PaperConfig.fixEntityPositionDesync) { // Tuinity - revert - // encode/decode from PacketPlayOutEntity - x = MathHelper.floorLong(x * 4096.0D) * (1 / 4096.0D); - y = MathHelper.floorLong(y * 4096.0D) * (1 / 4096.0D); -diff --git a/src/main/java/net/minecraft/server/EntityLightning.java b/src/main/java/net/minecraft/server/EntityLightning.java -index 5200b0396ee41edb42ff727c78cf3b5fce091d6b..239f504430b6c59923fd677d1be0121be5022604 100644 ---- a/src/main/java/net/minecraft/server/EntityLightning.java -+++ b/src/main/java/net/minecraft/server/EntityLightning.java -@@ -61,8 +61,9 @@ public class EntityLightning extends Entity { - // CraftBukkit start - Use relative location for far away sounds - // this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_LIGHTNING_BOLT_THUNDER, SoundCategory.WEATHER, 10000.0F, 0.8F + this.random.nextFloat() * 0.2F); - float pitch = 0.8F + this.random.nextFloat() * 0.2F; -- int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; -+ //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Tuinity - apply view distance patch - for (EntityPlayer player : (List) (List) this.world.getPlayers()) { -+ final int viewDistance = player.getBukkitEntity().getViewDistance(); // Tuinity - apply view distance patch - double deltaX = this.locX() - player.locX(); - double deltaZ = this.locZ() - player.locZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; -diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index 9a79371b40803947ed5deef68c50d45683aaae52..d568db532de83a85d5c387121cec151c160f36bf 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -2879,7 +2879,11 @@ public abstract class EntityLiving extends Entity { - return; - } - // Paper - end don't run getEntities if we're not going to use its result -- List list = this.world.getEntities(this, this.getBoundingBox(), IEntitySelector.pushable(this, world.paperConfig.fixClimbingBypassingCrammingRule)); // Paper - fix climbing bypassing cramming rule -+ // Tuinity start - reduce memory allocation from collideNearby -+ List list = com.tuinity.tuinity.util.CachedLists.getTempGetEntitiesList(); -+ this.world.getEntities(this, this.getBoundingBox(), IEntitySelector.pushable(this, world.paperConfig.fixClimbingBypassingCrammingRule), list); // Paper - fix climbing bypassing cramming rule -+ try { -+ // Tuinity end - reduce memory allocation from collideNearby - - if (!list.isEmpty()) { - // Paper - move up -@@ -2908,6 +2912,9 @@ public abstract class EntityLiving extends Entity { - this.C(entity); - } - } -+ } finally { // Tuinity start - reduce memory allocation from collideNearby -+ com.tuinity.tuinity.util.CachedLists.returnTempGetEntitiesList(list); -+ } // Tuinity end - reduce memory allocation from collideNearby - - } - -diff --git a/src/main/java/net/minecraft/server/EntityLlamaSpit.java b/src/main/java/net/minecraft/server/EntityLlamaSpit.java -index 7636a51a7ef0aa05b5b2aaa9d17e7b551dedac96..480a02a8f6ec7110f9af8f2037fdc09a7a54ef01 100644 ---- a/src/main/java/net/minecraft/server/EntityLlamaSpit.java -+++ b/src/main/java/net/minecraft/server/EntityLlamaSpit.java -@@ -19,7 +19,9 @@ public class EntityLlamaSpit extends IProjectile { - MovingObjectPosition movingobjectposition = ProjectileHelper.a((Entity) this, this::a); - - if (movingobjectposition != null) { -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition)) { // CraftBukkit - Call event // Paper - make cancellable // Tuinity - implement cancellation properly - this.a(movingobjectposition); -+ } // Tuinity - implement cancellation properly - } - - double d0 = this.locX() + vec3d.x; -diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index d51925612bc3d37164a8e821833ef1721b6e6976..c086579073c785b3b7cd556bbb629b91560bd449 100644 ---- a/src/main/java/net/minecraft/server/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/EntityPlayer.java -@@ -131,7 +131,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 37c9b5fd712e30a9a0faccc840f738f4b2cfc723..59989db6dcf96a8ab5a75775bb588c31cec3418a 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -261,7 +261,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks @@ -12528,7 +12277,7 @@ index d51925612bc3d37164a8e821833ef1721b6e6976..c086579073c785b3b7cd556bbb629b91 public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - there are a lot of changes to do if we change all methods leading to the event public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) { -@@ -531,6 +531,185 @@ public class EntityPlayer extends EntityHuman implements ICrafting { +@@ -661,6 +661,185 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } } @@ -12714,7 +12463,7 @@ index d51925612bc3d37164a8e821833ef1721b6e6976..c086579073c785b3b7cd556bbb629b91 if (this.getHealth() != this.lastHealthSent || this.lastFoodSent != this.foodData.getFoodLevel() || this.foodData.getSaturationLevel() == 0.0F != this.lastSentSaturationZero) { this.playerConnection.sendPacket(new PacketPlayOutUpdateHealth(this.getBukkitEntity().getScaledHealth(), this.foodData.getFoodLevel(), this.foodData.getSaturationLevel())); // CraftBukkit this.lastHealthSent = this.getHealth(); -@@ -1409,6 +1588,17 @@ public class EntityPlayer extends EntityHuman implements ICrafting { +@@ -1539,6 +1718,17 @@ public class EntityPlayer extends EntityHuman implements ICrafting { this.playerConnection.sendPacket(new PacketPlayOutCloseWindow(this.activeContainer.windowId)); this.o(); } @@ -12732,37 +12481,11 @@ index d51925612bc3d37164a8e821833ef1721b6e6976..c086579073c785b3b7cd556bbb629b91 public void broadcastCarriedItem() { if (!this.e) { -diff --git a/src/main/java/net/minecraft/server/EntityProjectile.java b/src/main/java/net/minecraft/server/EntityProjectile.java -index 53a8ea7d1eff84abe6c49464d556aa2788a6abcb..d85a19905efab7189e461a61becb6ca2b8c50803 100644 ---- a/src/main/java/net/minecraft/server/EntityProjectile.java -+++ b/src/main/java/net/minecraft/server/EntityProjectile.java -@@ -48,7 +48,7 @@ public abstract class EntityProjectile extends IProjectile { - movingobjectposition = null; - } - } -- if (movingobjectposition != null) { -+ if (movingobjectposition != null && org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition)) { // Tuinity - implement cancellation properly - // Paper end - this.a(movingobjectposition); - } // Paper -diff --git a/src/main/java/net/minecraft/server/EntityShulkerBullet.java b/src/main/java/net/minecraft/server/EntityShulkerBullet.java -index 23017b5486530bcf76b3934cfa8621e8b4772b27..a4d94385ede0303417d676155c2c0b226681cc59 100644 ---- a/src/main/java/net/minecraft/server/EntityShulkerBullet.java -+++ b/src/main/java/net/minecraft/server/EntityShulkerBullet.java -@@ -206,7 +206,7 @@ public class EntityShulkerBullet extends IProjectile { - - MovingObjectPosition movingobjectposition = ProjectileHelper.a((Entity) this, this::a); - -- if (movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS) { -+ if (movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS && org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition)) { // Tuinity - implement cancellation properly - this.a(movingobjectposition); - } - } -diff --git a/src/main/java/net/minecraft/server/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/EntityTrackerEntry.java -index f2a9396c2ec64c79391782249db7507f12a69a9e..2402c18e6a18221a43bea9fc68278da9d19eede4 100644 ---- a/src/main/java/net/minecraft/server/EntityTrackerEntry.java -+++ b/src/main/java/net/minecraft/server/EntityTrackerEntry.java -@@ -74,6 +74,7 @@ public class EntityTrackerEntry { +diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java +index f65eb0168ed365e5c1b490c56ec84e3b7ff87c1d..a1512ee8422fa39a95e4f19c86fe71b77af54ca0 100644 +--- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java ++++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java +@@ -103,6 +103,7 @@ public class EntityTrackerEntry { public final void tick() { this.a(); } // Paper - OBFHELPER public void a() { @@ -12770,7 +12493,7 @@ index f2a9396c2ec64c79391782249db7507f12a69a9e..2402c18e6a18221a43bea9fc68278da9 List list = this.tracker.passengers; // Paper - do not copy list if (!list.equals(this.p)) { -@@ -156,7 +157,7 @@ public class EntityTrackerEntry { +@@ -185,7 +186,7 @@ public class EntityTrackerEntry { // Paper end - remove allocation of Vec3D here boolean flag4 = k < -32768L || k > 32767L || l < -32768L || l > 32767L || i1 < -32768L || i1 > 32767L; @@ -12779,324 +12502,11 @@ index f2a9396c2ec64c79391782249db7507f12a69a9e..2402c18e6a18221a43bea9fc68278da9 if ((!flag2 || !flag3) && !(this.tracker instanceof EntityArrow)) { if (flag2) { packet1 = new PacketPlayOutEntity.PacketPlayOutRelEntityMove(this.tracker.getId(), (short) ((int) k), (short) ((int) l), (short) ((int) i1), this.tracker.isOnGround()); -diff --git a/src/main/java/net/minecraft/server/EntityWither.java b/src/main/java/net/minecraft/server/EntityWither.java -index b1159f0258eca2bee52ec0939ba86792d24a1f99..3230c5454ccc39a2e3c89fdf8ca015cf7a15f380 100644 ---- a/src/main/java/net/minecraft/server/EntityWither.java -+++ b/src/main/java/net/minecraft/server/EntityWither.java -@@ -214,9 +214,9 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - if (!this.isSilent()) { - // CraftBukkit start - Use relative location for far away sounds - // this.world.b(1023, new BlockPosition(this), 0); -- int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API // Tuinity - apply view distance patch - for (EntityPlayer player : (List)this.world.getPlayers()) { -- // final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch -+ final int viewDistance = player.getBukkitEntity().getViewDistance(); // Tuinity - apply view distance patch - double deltaX = this.locX() - player.locX(); - double deltaZ = this.locZ() - player.locZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; -diff --git a/src/main/java/net/minecraft/server/EnumDirection.java b/src/main/java/net/minecraft/server/EnumDirection.java -index 05b0090ae36cf61f67e26aad478df30c89f31941..30ba21ac1bced18a9d0946b7c3ed55971ada48bb 100644 ---- a/src/main/java/net/minecraft/server/EnumDirection.java -+++ b/src/main/java/net/minecraft/server/EnumDirection.java -@@ -170,8 +170,8 @@ public enum EnumDirection implements INamable { - return EnumDirection.q[MathHelper.a(i % EnumDirection.q.length)]; - } - -- @Nullable -- public static EnumDirection a(int i, int j, int k) { -+ @Nullable public static EnumDirection from(int i, int j, int k) { return a(i, j, k); } // Tuinity - OBFHELPER -+ @Nullable public static EnumDirection a(int i, int j, int k) { - return (EnumDirection) EnumDirection.r.get(BlockPosition.a(i, j, k)); - } - -diff --git a/src/main/java/net/minecraft/server/HeightMap.java b/src/main/java/net/minecraft/server/HeightMap.java -index 068b92c5c4ae112771757626ea75694e59f3d255..476da43b9f0ef35b4985f88e4784b1f8c5222af3 100644 ---- a/src/main/java/net/minecraft/server/HeightMap.java -+++ b/src/main/java/net/minecraft/server/HeightMap.java -@@ -101,6 +101,7 @@ public class HeightMap { - } - } - -+ public final int get(int x, int z) { return this.a(x, z); } // Tuinity - OBFHELPER - public int a(int i, int j) { - return this.a(c(i, j)); - } -@@ -137,7 +138,7 @@ public class HeightMap { - private final String h; - private final HeightMap.Use i; - private final Predicate j; -- private static final Map k = (Map) SystemUtils.a((Object) Maps.newHashMap(), (hashmap) -> { -+ private static final Map k = (Map) SystemUtils.a(Maps.newHashMap(), (hashmap) -> { // Tuinity - decompile fix - HeightMap.Type[] aheightmap_type = values(); - int i = aheightmap_type.length; - -@@ -149,7 +150,7 @@ public class HeightMap { - - }); - -- private Type(String s, HeightMap.Use heightmap_use, Predicate predicate) { -+ private Type(String s, HeightMap.Use heightmap_use, Predicate predicate) { // Tuinity - decompile fix - this.h = s; - this.i = heightmap_use; - this.j = predicate; -diff --git a/src/main/java/net/minecraft/server/IBlockAccess.java b/src/main/java/net/minecraft/server/IBlockAccess.java -index c4a83448ed4513f6e4ab179d1d43e5bb0cb13641..5ccf6b483fe15d4ad12ce2d3d11e9440ee9e8ab7 100644 ---- a/src/main/java/net/minecraft/server/IBlockAccess.java -+++ b/src/main/java/net/minecraft/server/IBlockAccess.java -@@ -55,7 +55,8 @@ public interface IBlockAccess { - return MovingObjectPositionBlock.a(raytrace1.a(), EnumDirection.a(vec3d.x, vec3d.y, vec3d.z), new BlockPosition(raytrace1.a())); - } - // Paper end -- Fluid fluid = this.getFluid(blockposition); -+ if (iblockdata.isAir()) return null; // Tuinity - optimise air cases -+ Fluid fluid = iblockdata.getFluid(); // Tuinity - don't need to go to world state again - Vec3D vec3d = raytrace1.b(); - Vec3D vec3d1 = raytrace1.a(); - VoxelShape voxelshape = raytrace1.a(iblockdata, this, blockposition); -diff --git a/src/main/java/net/minecraft/server/IChunkAccess.java b/src/main/java/net/minecraft/server/IChunkAccess.java -index 180b6b58dc5663158db84b6f1257591439b48c31..eb0d794b7275af7f860e7c7b85a9e3b2aa4a863f 100644 ---- a/src/main/java/net/minecraft/server/IChunkAccess.java -+++ b/src/main/java/net/minecraft/server/IChunkAccess.java -@@ -24,6 +24,36 @@ public interface IChunkAccess extends IBlockAccess, IStructureAccess { - } - // Paper end - -+ // Tuinity start -+ default com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] getBlockNibbles() { -+ throw new UnsupportedOperationException(this.getClass().getName()); -+ } -+ default void setBlockNibbles(com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] nibbles) { -+ throw new UnsupportedOperationException(this.getClass().getName()); -+ } -+ -+ default com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] getSkyNibbles() { -+ throw new UnsupportedOperationException(this.getClass().getName()); -+ } -+ default void setSkyNibbles(com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] nibbles) { -+ throw new UnsupportedOperationException(this.getClass().getName()); -+ } -+ public default boolean[] getSkyEmptinessMap() { -+ throw new UnsupportedOperationException(this.getClass().getName()); -+ } -+ public default void setSkyEmptinessMap(final boolean[] emptinessMap) { -+ throw new UnsupportedOperationException(this.getClass().getName()); -+ } -+ -+ public default boolean[] getBlockEmptinessMap() { -+ throw new UnsupportedOperationException(this.getClass().getName()); -+ } -+ -+ public default void setBlockEmptinessMap(final boolean[] emptinessMap) { -+ throw new UnsupportedOperationException(this.getClass().getName()); -+ } -+ // Tuinity end -+ - IBlockData getType(final int x, final int y, final int z); // Paper - @Nullable - IBlockData setType(BlockPosition blockposition, IBlockData iblockdata, boolean flag); -@@ -122,6 +152,7 @@ public interface IChunkAccess extends IBlockAccess, IStructureAccess { - @Nullable - NBTTagCompound j(BlockPosition blockposition); - -+ default Stream getLightSources() { return this.m(); } // Tuinity - OBFHELPER - Stream m(); - - TickList n(); -@@ -142,7 +173,9 @@ public interface IChunkAccess extends IBlockAccess, IStructureAccess { - return ashortlist[i]; - } - -+ default boolean isLit() { return this.r(); } // Tuinity - OBFHELPER - boolean r(); - -+ default void setLit(boolean lit) { this.b(lit); } // Tuinity - OBFHELPER - void b(boolean flag); - } -diff --git a/src/main/java/net/minecraft/server/IChunkLoader.java b/src/main/java/net/minecraft/server/IChunkLoader.java -index 582a5695bac7d078e3022b8ee70c512c0680d992..5601088cd5024a40e8296bab979f43de924c2b62 100644 ---- a/src/main/java/net/minecraft/server/IChunkLoader.java -+++ b/src/main/java/net/minecraft/server/IChunkLoader.java -@@ -21,7 +21,7 @@ public class IChunkLoader implements AutoCloseable { - protected final RegionFileCache regionFileCache; - - public IChunkLoader(File file, DataFixer datafixer, boolean flag) { -- this.regionFileCache = new RegionFileCache(file, flag); // Paper - nuke IOWorker -+ this.regionFileCache = new RegionFileCache(file, flag, true); // Paper - nuke IOWorker // Tuinity - this.b = datafixer; - // Paper - nuke IOWorker - } -diff --git a/src/main/java/net/minecraft/server/ICollisionAccess.java b/src/main/java/net/minecraft/server/ICollisionAccess.java -index 25e54a1fadc5d31fb250a3f47524b4f345fc8cc6..cce0ac8a36bef3b9e5a2b95e0c3dd137e8525226 100644 ---- a/src/main/java/net/minecraft/server/ICollisionAccess.java -+++ b/src/main/java/net/minecraft/server/ICollisionAccess.java -@@ -28,6 +28,11 @@ public interface ICollisionAccess extends IBlockAccess { - } - - default boolean b(AxisAlignedBB axisalignedbb) { -+ // Tuinity start - allow overriding in WorldServer -+ return this.getCubes(axisalignedbb); -+ } -+ default boolean getCubes(AxisAlignedBB axisalignedbb) { -+ // Tuinity end - allow overriding in WorldServer - return this.b((Entity) null, axisalignedbb, (entity) -> { - return true; - }); -@@ -46,6 +51,11 @@ public interface ICollisionAccess extends IBlockAccess { - } - - default boolean b(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate) { -+ // Tuinity start - allow overriding in WorldServer -+ return this.getCubes(entity, axisalignedbb, predicate); -+ } -+ default boolean getCubes(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate) { -+ // Tuinity end - allow overriding in WorldServer - try { if (entity != null) entity.collisionLoadChunks = true; // Paper - return this.d(entity, axisalignedbb, predicate).allMatch(VoxelShape::isEmpty); - } finally { if (entity != null) entity.collisionLoadChunks = false; } // Paper -diff --git a/src/main/java/net/minecraft/server/IEntityAccess.java b/src/main/java/net/minecraft/server/IEntityAccess.java -index 2639c17b7f6100533f33124f9e49990cd303d161..ad286848ddb7803640ef7eeea46b58473dd1d0c4 100644 ---- a/src/main/java/net/minecraft/server/IEntityAccess.java -+++ b/src/main/java/net/minecraft/server/IEntityAccess.java -@@ -55,16 +55,26 @@ public interface IEntityAccess { - return this.b(oclass, axisalignedbb, IEntitySelector.g); - } - -+ // Tuinity start - optimise hard collision -+ /** -+ * Not guaranteed to only return hard colliding entities -+ */ -+ default List getHardCollidingEntities(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate) { -+ return this.getEntities(entity, axisalignedbb, predicate); -+ } -+ // Tuinity end - optimise hard collision -+ - default Stream c(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate) { - if (axisalignedbb.a() < 1.0E-7D) { - return Stream.empty(); - } else { -- AxisAlignedBB axisalignedbb1 = axisalignedbb.g(1.0E-7D); -+ AxisAlignedBB axisalignedbb1 = axisalignedbb.g(-1.0E-7D); // Tuinity - to comply with vanilla intersection rules, expand by -epsilon so we only get stuff we definitely collide with. expanding by +epsilon gives us stuff we don't collide with, which will screw over callers in some cases. - -- return this.getEntities(entity, axisalignedbb1, predicate.and((entity1) -> { -+ if (predicate == null) predicate = (e) -> true; // Tuinity - allow nullable -+ predicate = predicate.and((entity1) -> { // Tuinity - optimise entity hard collisions // Tuinity - allow nullable - boolean flag; - -- if (entity1.getBoundingBox().c(axisalignedbb1)) { -+ if (true || entity1.getBoundingBox().c(axisalignedbb1)) { // Tuinity - always true, wtf did they think this.getEntities(entity, axisalignedbb1) does? - label25: - { - if (entity == null) { -@@ -82,13 +92,13 @@ public interface IEntityAccess { - - flag = false; - return flag; -- })).stream().map(Entity::getBoundingBox).map(VoxelShapes::a); -+ }); return ((entity != null && entity.hardCollides()) ? this.getEntities(entity, axisalignedbb1, predicate) : this.getHardCollidingEntities(entity, axisalignedbb1, predicate)).stream().map(Entity::getBoundingBox).map(VoxelShapes::a); // Tuinity - optimise entity hard collisions - } - } - - default EntityHuman findNearbyPlayer(Entity entity, double d0, @Nullable Predicate predicate) { return this.findNearbyPlayer(entity.locX(), entity.locY(), entity.locZ(), d0, predicate); } // Paper - @Nullable default EntityHuman findNearbyPlayer(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { return a(d0, d1, d2, d3, predicate); } // Paper - OBFHELPER -- @Nullable default EntityHuman a(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { // Paper -+ @Nullable default EntityHuman a(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { // Paper // Tuinity - diff on change, override in World - this should be "get closest player that matches predicate" - double d4 = -1.0D; - EntityHuman entityhuman = null; - Iterator iterator = this.getPlayers().iterator(); -@@ -189,27 +199,27 @@ public interface IEntityAccess { - } - - @Nullable -- default EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving) { -+ default EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving) { // Tuinity - diff on change, override in World - this should be "get closest player that matches path finder target condition" - return (EntityHuman) this.a(this.getPlayers(), pathfindertargetcondition, entityliving, entityliving.locX(), entityliving.locY(), entityliving.locZ()); - } - - @Nullable -- default EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving, double d0, double d1, double d2) { -+ default EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving, double d0, double d1, double d2) { // Tuinity - diff on change, override in World - this should be "get closest player that matches path finder target condition" - return (EntityHuman) this.a(this.getPlayers(), pathfindertargetcondition, entityliving, d0, d1, d2); - } - - @Nullable -- default EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, double d0, double d1, double d2) { -+ default EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, double d0, double d1, double d2) { // Tuinity - diff on change, override in World - this should be "get closest player that matches path finder target condition" - return (EntityHuman) this.a(this.getPlayers(), pathfindertargetcondition, (EntityLiving) null, d0, d1, d2); - } - - @Nullable -- default T a(Class oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { -+ default T a(Class oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { // Tuinity - diff on change, override in World - this should be "get closest entity by class that matches path finder target condition" - return this.a(this.a(oclass, axisalignedbb, null), pathfindertargetcondition, entityliving, d0, d1, d2); // Paper - decompile fix - } - - @Nullable -- default T b(Class oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { -+ default T b(Class oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { // Tuinity - diff on change, override in World - this should be "get closest entity by class that matches path finder target condition" - return this.a(this.b(oclass, axisalignedbb, null), pathfindertargetcondition, entityliving, d0, d1, d2); // Paper - decompile fix - } - -@@ -235,7 +245,7 @@ public interface IEntityAccess { - return t0; - } - -- default List a(PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving, AxisAlignedBB axisalignedbb) { -+ default List a(PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving, AxisAlignedBB axisalignedbb) { // Tuinity - diff on change, override in World - this should be "get players that matches path finder target condition" - List list = Lists.newArrayList(); - Iterator iterator = this.getPlayers().iterator(); - -diff --git a/src/main/java/net/minecraft/server/ILightAccess.java b/src/main/java/net/minecraft/server/ILightAccess.java -index be5384ee41290b24b0c419c3e8f4553db34b2399..df28f7a6bf4c650a22ddf046eae4d5e8ca5879a9 100644 ---- a/src/main/java/net/minecraft/server/ILightAccess.java -+++ b/src/main/java/net/minecraft/server/ILightAccess.java -@@ -4,9 +4,10 @@ import javax.annotation.Nullable; - - public interface ILightAccess { - -- @Nullable -- IBlockAccess c(int i, int j); -+ default @Nullable IBlockAccess getFeaturesReadyChunk(int i, int j) { return this.c(i, j); } // Tuinity - OBFHELPER -+ @Nullable IBlockAccess c(int i, int j); - -+ default void markLightSectionDirty(EnumSkyBlock enumskyblock, SectionPosition sectionposition) { this.a(enumskyblock, sectionposition); } // Tuinity - OBFHELPER - default void a(EnumSkyBlock enumskyblock, SectionPosition sectionposition) {} - - IBlockAccess getWorld(); -diff --git a/src/main/java/net/minecraft/server/IProjectile.java b/src/main/java/net/minecraft/server/IProjectile.java -index bbc089b41fcbe0141f13591db2cb44b9e688cac4..dc9f2a1a132b3a7925bd62aa1da0512afd90b8b1 100644 ---- a/src/main/java/net/minecraft/server/IProjectile.java -+++ b/src/main/java/net/minecraft/server/IProjectile.java -@@ -118,7 +118,7 @@ public abstract class IProjectile extends Entity { - } - - protected void a(MovingObjectPosition movingobjectposition) { -- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition)) return; // CraftBukkit - Call event // Paper - make cancellable -+ // Tuinity - proper cancellation requires moving this into the caller (see method overrides) - TODO this unfortunately means we need to manually inspect each call on update - MovingObjectPosition.EnumMovingObjectType movingobjectposition_enummovingobjecttype = movingobjectposition.getType(); - - if (movingobjectposition_enummovingobjecttype == MovingObjectPosition.EnumMovingObjectType.ENTITY) { -diff --git a/src/main/java/net/minecraft/server/ItemEnderEye.java b/src/main/java/net/minecraft/server/ItemEnderEye.java -index 3296d888a66e8d0ad861ed093cd62b0d2da6ff0b..bc6e2d7dda6c85e89967d06649558aafd8f2624b 100644 ---- a/src/main/java/net/minecraft/server/ItemEnderEye.java -+++ b/src/main/java/net/minecraft/server/ItemEnderEye.java -@@ -36,9 +36,10 @@ public class ItemEnderEye extends Item { - - // CraftBukkit start - Use relative location for far away sounds - // world.b(1038, blockposition1.b(1, 0, 1), 0); -- int viewDistance = world.getServer().getViewDistance() * 16; -+ //int viewDistance = world.getServer().getViewDistance() * 16; // Tuinity - apply view distance patch - BlockPosition soundPos = blockposition1.b(1, 0, 1); - for (EntityPlayer player : world.getServer().getServer().getPlayerList().players) { -+ final int viewDistance = player.getBukkitEntity().getViewDistance(); // Tuinity - apply view distance patch - double deltaX = soundPos.getX() - player.locX(); - double deltaZ = soundPos.getZ() - player.locZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; -diff --git a/src/main/java/net/minecraft/server/LightEngineGraphSection.java b/src/main/java/net/minecraft/server/LightEngineGraphSection.java -index 13d067f48647dea63ef1bf3a2a3e0868074ba75f..04afd7f285db2f281a038e0be6f557b8a692936b 100644 ---- a/src/main/java/net/minecraft/server/LightEngineGraphSection.java -+++ b/src/main/java/net/minecraft/server/LightEngineGraphSection.java -@@ -74,8 +74,10 @@ public abstract class LightEngineGraphSection extends LightEngineGraph { +diff --git a/src/main/java/net/minecraft/server/level/LightEngineGraphSection.java b/src/main/java/net/minecraft/server/level/LightEngineGraphSection.java +index 4ee7070364a8989eece4fa4237b529926821f9c9..f22ab98d2e250081df8949be8a99737069c83d34 100644 +--- a/src/main/java/net/minecraft/server/level/LightEngineGraphSection.java ++++ b/src/main/java/net/minecraft/server/level/LightEngineGraphSection.java +@@ -77,8 +77,10 @@ public abstract class LightEngineGraphSection extends LightEngineGraph { return i == Long.MAX_VALUE ? this.b(j) : k + 1; } @@ -13107,43 +12517,11 @@ index 13d067f48647dea63ef1bf3a2a3e0868074ba75f..04afd7f285db2f281a038e0be6f557b8 public void b(long i, int j, boolean flag) { this.a(Long.MAX_VALUE, i, j, flag); } -diff --git a/src/main/java/net/minecraft/server/LightEngineStorage.java b/src/main/java/net/minecraft/server/LightEngineStorage.java -index b98e60772bad7e06845b50fdc11e98c0ea775d3d..e0bbfe1422cbad811ecb43d7436380d86b0f8abc 100644 ---- a/src/main/java/net/minecraft/server/LightEngineStorage.java -+++ b/src/main/java/net/minecraft/server/LightEngineStorage.java -@@ -23,7 +23,8 @@ public abstract class LightEngineStorage> e - protected final M f; protected final M updating; // Paper - diff on change, should be "updating" - protected final LongSet g = new LongOpenHashSet(); - protected final LongSet h = new LongOpenHashSet(); LongSet dirty = h; // Paper - OBFHELPER -- protected final Long2ObjectMap i = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap()); -+ protected final Long2ObjectOpenHashMap i_synchronized_map_real = new Long2ObjectOpenHashMap<>(); // Tuinity - store wrapped map, we need fastIterator -+ protected final Long2ObjectMap i = Long2ObjectMaps.synchronize(this.i_synchronized_map_real); // Tuinity - store wrapped map, we need fastIterator - private final LongSet n = new LongOpenHashSet(); - private final LongSet o = new LongOpenHashSet(); - private final LongSet p = new LongOpenHashSet(); -@@ -247,7 +248,7 @@ public abstract class LightEngineStorage> e - - this.p.clear(); - this.j = false; -- ObjectIterator objectiterator = this.i.long2ObjectEntrySet().iterator(); -+ ObjectIterator objectiterator = this.i_synchronized_map_real.long2ObjectEntrySet().fastIterator(); // Tuinity - use fast iterator to reduce entry creation - - Entry entry; - long j; -@@ -284,7 +285,7 @@ public abstract class LightEngineStorage> e - } - - this.n.clear(); -- objectiterator = this.i.long2ObjectEntrySet().iterator(); -+ objectiterator = this.i_synchronized_map_real.long2ObjectEntrySet().fastIterator(); // Tuinity - use fast iterator to reduce entry creation; - - while (objectiterator.hasNext()) { - entry = (Entry) objectiterator.next(); -diff --git a/src/main/java/net/minecraft/server/LightEngineThreaded.java b/src/main/java/net/minecraft/server/LightEngineThreaded.java -index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375b1a49bd6 100644 ---- a/src/main/java/net/minecraft/server/LightEngineThreaded.java -+++ b/src/main/java/net/minecraft/server/LightEngineThreaded.java -@@ -2,6 +2,11 @@ package net.minecraft.server; +diff --git a/src/main/java/net/minecraft/server/level/LightEngineThreaded.java b/src/main/java/net/minecraft/server/level/LightEngineThreaded.java +index 0b80569648c1df01aab52d0b8d47028cda925d86..381bd11075599d44e4c705a8e754769d29883d75 100644 +--- a/src/main/java/net/minecraft/server/level/LightEngineThreaded.java ++++ b/src/main/java/net/minecraft/server/level/LightEngineThreaded.java +@@ -2,6 +2,11 @@ package net.minecraft.server.level; import com.mojang.datafixers.util.Pair; import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; // Paper @@ -13155,7 +12533,7 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectList; import it.unimi.dsi.fastutil.objects.ObjectListIterator; -@@ -15,11 +20,12 @@ import org.apache.logging.log4j.Logger; +@@ -28,11 +33,12 @@ import org.apache.logging.log4j.Logger; public class LightEngineThreaded extends LightEngine implements AutoCloseable { private static final Logger LOGGER = LogManager.getLogger(); @@ -13169,7 +12547,7 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 PlayerChunk playerChunk = playerChunkMap.getVisibleChunk(pair); if (playerChunk == null) { return false; -@@ -156,13 +162,218 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { +@@ -169,13 +175,218 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { private volatile int f = 5; private final AtomicBoolean g = new AtomicBoolean(); @@ -13222,7 +12600,7 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 + + final Long id = Long.valueOf(this.relightCounter++); + -+ this.theLightEngine.getWorld().getChunkProvider().addTicketAtLevel(TicketType.CHUNK_RELIGHT, chunkPos, MCUtil.getTicketLevelFor(ChunkStatus.LIGHT), id); ++ this.theLightEngine.getWorld().getChunkProvider().addTicketAtLevel(TicketType.CHUNK_RELIGHT, chunkPos, net.minecraft.server.MCUtil.getTicketLevelFor(ChunkStatus.LIGHT), id); + ticketIds.put(chunkPos, id); + + ++totalChunks; @@ -13232,8 +12610,8 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 + this.theLightEngine.relightChunks(chunks, (ChunkCoordIntPair chunkPos) -> { + chunkLightCallback.accept(chunkPos); + ((java.util.concurrent.Executor)this.theLightEngine.getWorld().getChunkProvider().serverThreadQueue).execute(() -> { -+ this.theLightEngine.getWorld().getChunkProvider().playerChunkMap.getUpdatingChunk(chunkPos.pair()).sendPacketToTrackedPlayers(new PacketPlayOutLightUpdate(chunkPos, this, true), false); -+ this.theLightEngine.getWorld().getChunkProvider().removeTicketAtLevel(TicketType.CHUNK_RELIGHT, chunkPos, MCUtil.getTicketLevelFor(ChunkStatus.LIGHT), ticketIds.get(chunkPos)); ++ this.theLightEngine.getWorld().getChunkProvider().playerChunkMap.getUpdatingChunk(chunkPos.pair()).sendPacketToTrackedPlayers(new net.minecraft.network.protocol.game.PacketPlayOutLightUpdate(chunkPos, this, true), false); ++ this.theLightEngine.getWorld().getChunkProvider().removeTicketAtLevel(TicketType.CHUNK_RELIGHT, chunkPos, net.minecraft.server.MCUtil.getTicketLevelFor(ChunkStatus.LIGHT), ticketIds.get(chunkPos)); + }); + }, onComplete); + }); @@ -13246,12 +12624,12 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 + protected final LongArrayList postWorkTicketRelease = new LongArrayList(); + + private void addLightWorkTicket(int chunkX, int chunkZ) { -+ final long coordinate = MCUtil.getCoordinateKey(chunkX, chunkZ); ++ final long coordinate = net.minecraft.server.MCUtil.getCoordinateKey(chunkX, chunkZ); + final int current = this.holdingChunks.putIfAbsent(coordinate, 1); + if (current == 0) { + final ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(coordinate); + this.theLightEngine.getWorld().getChunkProvider().addTicketAtLevel(TicketType.LIGHT_UPDATE, chunkPos, -+ MCUtil.getTicketLevelFor(ChunkStatus.LIGHT), chunkPos); ++ net.minecraft.server.MCUtil.getTicketLevelFor(ChunkStatus.LIGHT), chunkPos); + this.theLightEngine.getWorld().getChunkProvider().tickDistanceManager(); + } else { + this.holdingChunks.put(coordinate, current + 1); @@ -13259,13 +12637,13 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 + } + + protected final void releaseLightWorkChunk(int chunkX, int chunkZ) { -+ final long coordinate = MCUtil.getCoordinateKey(chunkX, chunkZ); ++ final long coordinate = net.minecraft.server.MCUtil.getCoordinateKey(chunkX, chunkZ); + final int current = this.holdingChunks.get(coordinate); + if (current == 1) { + this.holdingChunks.remove(coordinate); + final ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(coordinate); + this.theLightEngine.getWorld().getChunkProvider().removeTicketAtLevel(TicketType.LIGHT_UPDATE, chunkPos, -+ MCUtil.getTicketLevelFor(ChunkStatus.LIGHT), chunkPos); ++ net.minecraft.server.MCUtil.getTicketLevelFor(ChunkStatus.LIGHT), chunkPos); + } else { + this.holdingChunks.put(coordinate, current - 1); + } @@ -13274,17 +12652,17 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 + protected final CompletableFuture acquireLightWorkChunk(int chunkX, int chunkZ) { + ChunkProviderServer chunkProvider = this.theLightEngine.getWorld().getChunkProvider(); + PlayerChunkMap chunkMap = chunkProvider.playerChunkMap; -+ int targetLevel = MCUtil.getTicketLevelFor(ChunkStatus.LIGHT); ++ int targetLevel = net.minecraft.server.MCUtil.getTicketLevelFor(ChunkStatus.LIGHT); + + this.addLightWorkTicket(chunkX, chunkZ); + + // light doesn't always load one radius neighbours... + // i.e if they get unloaded + boolean neighboursAtFeatures = true; -+ int targetNeighbourLevel = MCUtil.getTicketLevelFor(ChunkStatus.LIGHT.getPreviousStatus()); ++ int targetNeighbourLevel = net.minecraft.server.MCUtil.getTicketLevelFor(ChunkStatus.LIGHT.getPreviousStatus()); + for (int dx = -1; dx <= 1; ++dx) { + for (int dz = -1; dz <= 1; ++dz) { -+ PlayerChunk neighbour = chunkMap.getUpdatingChunk(MCUtil.getCoordinateKey(dx + chunkX, dz + chunkZ)); ++ PlayerChunk neighbour = chunkMap.getUpdatingChunk(net.minecraft.server.MCUtil.getCoordinateKey(dx + chunkX, dz + chunkZ)); + ChunkStatus status; + if (neighbour == null || neighbour.getTicketLevel() > targetNeighbourLevel || + (status = neighbour.getChunkHolderStatus()) == null || @@ -13295,7 +12673,7 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 + } + } + -+ PlayerChunk playerChunk = chunkMap.getUpdatingChunk(MCUtil.getCoordinateKey(chunkX, chunkZ)); ++ PlayerChunk playerChunk = chunkMap.getUpdatingChunk(net.minecraft.server.MCUtil.getCoordinateKey(chunkX, chunkZ)); + ChunkStatus holderStatus; + if (!neighboursAtFeatures || playerChunk == null || playerChunk.getTicketLevel() > targetLevel || + (holderStatus = playerChunk.getChunkHolderStatus()) == null || @@ -13341,14 +12719,14 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 + + this.acquireLightWorkChunk(chunkX, chunkZ).whenCompleteAsync((chunk, throwable) -> { + if (throwable != null) { -+ MinecraftServer.LOGGER.fatal("Failed to load light chunk for light work", throwable); ++ LOGGER.fatal("Failed to load light chunk for light work", throwable); + this.releaseLightWorkChunk(chunkX, chunkZ); + } else { + this.scheduleTask(chunkX, chunkZ, type, () -> { + try { + task.run(); + } finally { -+ this.postWorkTicketRelease.add(MCUtil.getCoordinateKey(chunkX, chunkZ)); ++ this.postWorkTicketRelease.add(net.minecraft.server.MCUtil.getCoordinateKey(chunkX, chunkZ)); + } + }); + } @@ -13363,7 +12741,7 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 + } + + @Override -+ public LightEngineLayerEventListener a(EnumSkyBlock var0) { ++ public net.minecraft.world.level.lighting.LightEngineLayerEventListener a(EnumSkyBlock var0) { + if (this.theLightEngine == null) { + return super.a(var0); + } @@ -13388,7 +12766,7 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 public void close() {} @Override -@@ -179,6 +390,15 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { +@@ -192,6 +403,15 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { public void a(BlockPosition blockposition) { BlockPosition blockposition1 = blockposition.immutableCopy(); @@ -13404,7 +12782,7 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 this.a(blockposition.getX() >> 4, blockposition.getZ() >> 4, LightEngineThreaded.Update.POST_UPDATE, SystemUtils.a(() -> { super.a(blockposition1); }, () -> { -@@ -187,6 +407,11 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { +@@ -200,6 +420,11 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { } protected void a(ChunkCoordIntPair chunkcoordintpair) { @@ -13416,7 +12794,7 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 this.a(chunkcoordintpair.x, chunkcoordintpair.z, () -> { return 0; }, LightEngineThreaded.Update.PRE_UPDATE, SystemUtils.a(() -> { -@@ -211,6 +436,14 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { +@@ -224,6 +449,14 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { @Override public void a(SectionPosition sectionposition, boolean flag) { @@ -13431,7 +12809,7 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 this.a(sectionposition.a(), sectionposition.c(), () -> { return 0; }, LightEngineThreaded.Update.PRE_UPDATE, SystemUtils.a(() -> { -@@ -222,6 +455,11 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { +@@ -235,6 +468,11 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { @Override public void a(ChunkCoordIntPair chunkcoordintpair, boolean flag) { @@ -13443,7 +12821,7 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 this.a(chunkcoordintpair.x, chunkcoordintpair.z, LightEngineThreaded.Update.PRE_UPDATE, SystemUtils.a(() -> { super.a(chunkcoordintpair, flag); }, () -> { -@@ -231,6 +469,11 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { +@@ -244,6 +482,11 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { @Override public void a(EnumSkyBlock enumskyblock, SectionPosition sectionposition, @Nullable NibbleArray nibblearray, boolean flag) { @@ -13455,7 +12833,7 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 this.a(sectionposition.a(), sectionposition.c(), () -> { return 0; }, LightEngineThreaded.Update.PRE_UPDATE, SystemUtils.a(() -> { -@@ -240,6 +483,7 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { +@@ -253,6 +496,7 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { })); } @@ -13463,7 +12841,7 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 private void a(int i, int j, LightEngineThreaded.Update lightenginethreaded_update, Runnable runnable) { this.a(i, j, this.d.c(ChunkCoordIntPair.pair(i, j)), lightenginethreaded_update, runnable); } -@@ -252,6 +496,11 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { +@@ -265,6 +509,11 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { @Override public void b(ChunkCoordIntPair chunkcoordintpair, boolean flag) { @@ -13475,7 +12853,7 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 this.a(chunkcoordintpair.x, chunkcoordintpair.z, () -> { return 0; }, LightEngineThreaded.Update.PRE_UPDATE, SystemUtils.a(() -> { -@@ -264,6 +513,35 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { +@@ -277,6 +526,35 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { public CompletableFuture a(IChunkAccess ichunkaccess, boolean flag) { ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos(); @@ -13502,7 +12880,7 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 + LightEngineThreaded.this.queueUpdate(); + }).whenComplete((IChunkAccess chunk, Throwable throwable) -> { + if (throwable != null && !(throwable instanceof ThreadDeath)) { -+ MinecraftServer.LOGGER.fatal("Failed to light chunk " + ichunkaccess.getPos().toString() + " in world '" + this.theLightEngine.getWorld().getWorld().getName() + "'"); ++ LOGGER.fatal("Failed to light chunk " + ichunkaccess.getPos().toString() + " in world '" + this.theLightEngine.getWorld().getWorld().getName() + "'"); + } + }); + } @@ -13511,7 +12889,7 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 // Paper start //ichunkaccess.b(false); // Don't need to disable this long pair = chunkcoordintpair.pair(); -@@ -311,7 +589,7 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { +@@ -324,7 +602,7 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { } public void queueUpdate() { @@ -13520,7 +12898,7 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 this.b.a((() -> { // Paper - decompile error this.b(); this.g.set(false); -@@ -325,17 +603,36 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { +@@ -338,17 +616,36 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { private final java.util.List pre = new java.util.ArrayList<>(); private final java.util.List post = new java.util.ArrayList<>(); private void b() { @@ -13547,7 +12925,7 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 + LongIterator iterator = copy.iterator(); + while (iterator.hasNext()) { + long coordinate = iterator.nextLong(); -+ this.releaseLightWorkChunk(MCUtil.getCoordinateX(coordinate), MCUtil.getCoordinateZ(coordinate)); ++ this.releaseLightWorkChunk(net.minecraft.server.MCUtil.getCoordinateX(coordinate), net.minecraft.server.MCUtil.getCoordinateZ(coordinate)); + } + }); + } @@ -13559,1374 +12937,11 @@ index 2f9c97dd4e1d705a87772d18c7ab4883a876af08..b2f51a6786d4bb92c9cbbceeea812375 } public void a(int i) { -diff --git a/src/main/java/net/minecraft/server/LoginListener.java b/src/main/java/net/minecraft/server/LoginListener.java -index 6be12b7ae8501c22a7c544638c44fc6faedd5b07..2b4ac8d1f3218e89b73fb9e1d3eed8cb8bf7334d 100644 ---- a/src/main/java/net/minecraft/server/LoginListener.java -+++ b/src/main/java/net/minecraft/server/LoginListener.java -@@ -235,7 +235,7 @@ public class LoginListener implements PacketLoginInListener { - - s = (new BigInteger(MinecraftEncryption.a("", this.server.getKeyPair().getPublic(), this.loginKey))).toString(16); - this.g = LoginListener.EnumProtocolState.AUTHENTICATING; -- this.networkManager.a(cipher, cipher1); -+ this.networkManager.a(this.loginKey); // Tuinity - } catch (CryptographyException cryptographyexception) { - throw new IllegalStateException("Protocol error", cryptographyexception); - } -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index ff74be14512a947e81b62d53e616131ca7d7f609..7438ed7671acb181fe88abd2db415cb09873db4f 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -38,6 +38,7 @@ import java.util.function.Consumer; - import java.util.function.Supplier; - - public final class MCUtil { -+ public static final double COLLISION_EPSILON = 1.0E-7; // Tuinity - Just in case mojang changes this... - public static final ThreadPoolExecutor asyncExecutor = new ThreadPoolExecutor( - 0, 2, 60L, TimeUnit.SECONDS, - new LinkedBlockingQueue(), -@@ -221,6 +222,63 @@ public final class MCUtil { - return getBlockKey(getBlockCoordinate(entity.locX()), getBlockCoordinate(entity.locY()), getBlockCoordinate(entity.locZ())); - } - -+ // Tuinity start -+ -+ static final int SECTION_X_BITS = 22; -+ static final long SECTION_X_MASK = (1L << SECTION_X_BITS) - 1; -+ static final int SECTION_Y_BITS = 20; -+ static final long SECTION_Y_MASK = (1L << SECTION_Y_BITS) - 1; -+ static final int SECTION_Z_BITS = 22; -+ static final long SECTION_Z_MASK = (1L << SECTION_Z_BITS) - 1; -+ // format is y,z,x (in order of LSB to MSB) -+ static final int SECTION_Y_SHIFT = 0; -+ static final int SECTION_Z_SHIFT = SECTION_Y_SHIFT + SECTION_Y_BITS; -+ static final int SECTION_X_SHIFT = SECTION_Z_SHIFT + SECTION_X_BITS; -+ static final int SECTION_TO_BLOCK_SHIFT = 4; -+ -+ public static long getSectionKey(final int x, final int y, final int z) { -+ return ((x & SECTION_X_MASK) << SECTION_X_SHIFT) -+ | ((y & SECTION_Y_MASK) << SECTION_Y_SHIFT) -+ | ((z & SECTION_Z_MASK) << SECTION_Z_SHIFT); -+ } -+ -+ public static long getSectionKey(final SectionPosition pos) { -+ return ((pos.getX() & SECTION_X_MASK) << SECTION_X_SHIFT) -+ | ((pos.getY() & SECTION_Y_MASK) << SECTION_Y_SHIFT) -+ | ((pos.getZ() & SECTION_Z_MASK) << SECTION_Z_SHIFT); -+ } -+ -+ public static long getSectionKey(final ChunkCoordIntPair pos, final int y) { -+ return ((pos.x & SECTION_X_MASK) << SECTION_X_SHIFT) -+ | ((y & SECTION_Y_MASK) << SECTION_Y_SHIFT) -+ | ((pos.z & SECTION_Z_MASK) << SECTION_Z_SHIFT); -+ } -+ -+ public static long getSectionKey(final BlockPosition pos) { -+ return (((long)pos.getX() << (SECTION_X_SHIFT - SECTION_TO_BLOCK_SHIFT)) & (SECTION_X_MASK << SECTION_X_SHIFT)) | -+ ((pos.getY() >> SECTION_TO_BLOCK_SHIFT) & (SECTION_Y_MASK << SECTION_Y_SHIFT)) | -+ (((long)pos.getZ() << (SECTION_Z_SHIFT - SECTION_TO_BLOCK_SHIFT)) & (SECTION_Z_MASK << SECTION_Z_SHIFT)); -+ } -+ -+ public static long getSectionKey(final Entity entity) { -+ return ((MCUtil.fastFloor(entity.locX()) & SECTION_X_MASK) << SECTION_X_SHIFT) -+ | ((MCUtil.fastFloor(entity.locY()) & SECTION_Y_MASK) << SECTION_Y_SHIFT) -+ | ((MCUtil.fastFloor(entity.locZ()) & SECTION_Z_MASK) << SECTION_Z_SHIFT); -+ } -+ -+ public static int getSectionX(final long key) { -+ return (int)(key << (Long.SIZE - (SECTION_X_SHIFT + SECTION_X_BITS)) >> (Long.SIZE - SECTION_X_BITS)); -+ } -+ -+ public static int getSectionY(final long key) { -+ return (int)(key << (Long.SIZE - (SECTION_Y_SHIFT + SECTION_Y_BITS)) >> (Long.SIZE - SECTION_Y_BITS)); -+ } -+ -+ public static int getSectionZ(final long key) { -+ return (int)(key << (Long.SIZE - (SECTION_Z_SHIFT + SECTION_Z_BITS)) >> (Long.SIZE - SECTION_Z_BITS)); -+ } -+ // Tuinity end -+ - // assumes the sets have the same comparator, and if this comparator is null then assume T is Comparable - public static void mergeSortedSets(final java.util.function.Consumer consumer, final java.util.Comparator comparator, final java.util.SortedSet...sets) { - final ObjectRBTreeSet all = new ObjectRBTreeSet<>(comparator); -@@ -622,7 +680,7 @@ public final class MCUtil { - - worldData.addProperty("name", world.getWorld().getName()); - worldData.addProperty("view-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()); -- worldData.addProperty("no-view-distance", world.getChunkProvider().playerChunkMap.getRawNoTickViewDistance()); -+ worldData.addProperty("no-view-distance", world.getChunkProvider().playerChunkMap.playerChunkManager.getTargetNoTickViewDistance()); // Tuinity - replace old player chunk management - worldData.addProperty("keep-spawn-loaded", world.keepSpawnInMemory); - worldData.addProperty("keep-spawn-loaded-range", world.paperConfig.keepLoadedRange); - worldData.addProperty("visible-chunk-count", visibleChunks.size()); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index c572ef2830f2653e2b30622bbac0a3b072bacd7a..afc22e545df03a38c801362d308d135df90361e2 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -155,6 +155,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); - public int autosavePeriod; - public boolean serverAutoSave = false; // Paper -@@ -755,10 +756,11 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant= MAX_CHUNK_EXEC_TIME) { -+ if (!moreTasks) { -+ lastMidTickExecuteFailure = currTime; -+ } -+ -+ // note: negative values reduce the time -+ long overuse = diff - MAX_CHUNK_EXEC_TIME; -+ if (overuse >= (10L * 1000L * 1000L)) { // 10ms -+ // make sure something like a GC or dumb plugin doesn't screw us over... -+ overuse = 10L * 1000L * 1000L; // 10ms -+ } -+ -+ double overuseCount = (double)overuse/(double)MAX_CHUNK_EXEC_TIME; -+ long extraSleep = (long)Math.round(overuseCount*CHUNK_TASK_QUEUE_BACKOFF_MIN_TIME); -+ -+ lastMidTickExecute = currTime + extraSleep; -+ return; -+ } -+ } -+ } finally { -+ co.aikar.timings.MinecraftTimings.midTickChunkTasks.stopTiming(); -+ } -+ } -+ // Tuinity end - execute chunk tasks mid tick -+ - private void executeModerately() { - this.executeAll(); - java.util.concurrent.locks.LockSupport.parkNanos("executing tasks", 1000L); -@@ -1096,22 +1170,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -- midTickLoadChunks(); // will only do loads since we are still considered !canSleepForTick -+ // Tuinity - replace logic - return !this.canOversleep(); - }); - isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); -@@ -1270,6 +1330,8 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant // Spigot - Spigot > // CraftBukkit - cb > vanilla! -+ return "Tuinity"; // Tuinity //Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! - } - - public CrashReport b(CrashReport crashreport) { -diff --git a/src/main/java/net/minecraft/server/NavigationAbstract.java b/src/main/java/net/minecraft/server/NavigationAbstract.java -index 1558c5f8256f50be6850f1d7f70eee3e8ec76496..6aec5098d346c1b7498fd8b800154cd31ce08a97 100644 ---- a/src/main/java/net/minecraft/server/NavigationAbstract.java -+++ b/src/main/java/net/minecraft/server/NavigationAbstract.java -@@ -8,7 +8,7 @@ import javax.annotation.Nullable; - - public abstract class NavigationAbstract { - -- protected final EntityInsentient a; public Entity getEntity() { return a; } // Paper - OBFHELPER -+ protected final EntityInsentient a; public final EntityInsentient getEntity() { return a; } // Paper - OBFHELPER // Tuinity - match types - protected final World b; - @Nullable - protected PathEntity c; protected final PathEntity getCurrentPath() { return this.c; } // Paper - OBFHELPER -@@ -21,7 +21,7 @@ public abstract class NavigationAbstract { - protected long j; - protected double k; - protected float l; -- protected boolean m; -+ protected boolean m; protected final boolean needsPathRecalculation() { return this.m; } // Tuinity - OBFHELPER - protected long n; - protected PathfinderAbstract o; - private BlockPosition p; -@@ -30,6 +30,13 @@ public abstract class NavigationAbstract { - private final Pathfinder s; public Pathfinder getPathfinder() { return this.s; } // Paper - OBFHELPER - private boolean t; - -+ // Tuinity start -+ public boolean isViableForPathRecalculationChecking() { -+ return !this.needsPathRecalculation() && -+ (this.c != null && !this.c.c() && this.c.e() != 0); -+ } -+ // Tuinity end -+ - public NavigationAbstract(EntityInsentient entityinsentient, World world) { - this.g = Vec3D.ORIGIN; - this.h = BaseBlockPosition.ZERO; -@@ -393,7 +400,7 @@ public abstract class NavigationAbstract { - } - - public void b(BlockPosition blockposition) { -- if (this.c != null && !this.c.c() && this.c.e() != 0) { -+ if (this.c != null && !this.c.c() && this.c.e() != 0) { // Tuinity - diff on change - needed for isViableForPathRecalculationChecking() - PathPoint pathpoint = this.c.d(); - Vec3D vec3d = new Vec3D(((double) pathpoint.a + this.a.locX()) / 2.0D, ((double) pathpoint.b + this.a.locY()) / 2.0D, ((double) pathpoint.c + this.a.locZ()) / 2.0D); - -diff --git a/src/main/java/net/minecraft/server/NetworkManager.java b/src/main/java/net/minecraft/server/NetworkManager.java -index fb1e3c705b8abee13695762cdfd0e9f1bfdb5ad8..d93634391501da01cb1afe70fedd5247c654e8fc 100644 ---- a/src/main/java/net/minecraft/server/NetworkManager.java -+++ b/src/main/java/net/minecraft/server/NetworkManager.java -@@ -27,6 +27,8 @@ import org.apache.logging.log4j.Logger; - import org.apache.logging.log4j.Marker; - import org.apache.logging.log4j.MarkerManager; - -+import io.netty.util.concurrent.AbstractEventExecutor; // Tuinity -+ - public class NetworkManager extends SimpleChannelInboundHandler> { - - private static final Logger LOGGER = LogManager.getLogger(); -@@ -71,6 +73,61 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - EnumProtocol protocol; - // Paper end - -+ // Tuinity start - allow controlled flushing -+ volatile boolean canFlush = true; -+ private final java.util.concurrent.atomic.AtomicInteger packetWrites = new java.util.concurrent.atomic.AtomicInteger(); -+ private int flushPacketsStart; -+ private final Object flushLock = new Object(); -+ -+ void disableAutomaticFlush() { -+ synchronized (this.flushLock) { -+ this.flushPacketsStart = this.packetWrites.get(); // must be volatile and before canFlush = false -+ this.canFlush = false; -+ } -+ } -+ -+ void enableAutomaticFlush() { -+ synchronized (this.flushLock) { -+ this.canFlush = true; -+ if (this.packetWrites.get() != this.flushPacketsStart) { // must be after canFlush = true -+ this.flush(); // only make the flush call if we need to -+ } -+ } -+ } -+ -+ private final void flush() { -+ if (this.channel.eventLoop().inEventLoop()) { -+ this.channel.flush(); -+ } else { -+ this.channel.eventLoop().execute(() -> { -+ this.channel.flush(); -+ }); -+ } -+ } -+ // Tuinity end - allow controlled flushing -+ // Tuinity start - add pending task queue -+ private final Queue pendingTasks = new java.util.concurrent.ConcurrentLinkedQueue<>(); -+ public void execute(final Runnable run) { -+ if (!this.channel.isRegistered()) { -+ run.run(); -+ return; -+ } -+ final boolean queue = !this.packetQueue.isEmpty(); -+ if (!queue) { -+ this.channel.eventLoop().execute(run); -+ } else { -+ this.pendingTasks.add(run); -+ if (this.packetQueue.isEmpty()) { -+ // something flushed async, dump tasks now -+ Runnable r; -+ while ((r = this.pendingTasks.poll()) != null) { -+ this.channel.eventLoop().execute(r); -+ } -+ } -+ } -+ } -+ // Tuinity end - add pending task queue -+ - public NetworkManager(EnumProtocolDirection enumprotocoldirection) { - this.h = enumprotocoldirection; - } -@@ -145,8 +202,63 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - if (MinecraftServer.getServer().isDebugging()) throwable.printStackTrace(); // Spigot - } - -+ // Tuinity start - packet limiter -+ protected final Object PACKET_LIMIT_LOCK = new Object(); -+ protected final com.tuinity.tuinity.util.IntervalledCounter allPacketCounts = com.tuinity.tuinity.config.TuinityConfig.allPacketsLimit != null ? new com.tuinity.tuinity.util.IntervalledCounter( -+ (long)(com.tuinity.tuinity.config.TuinityConfig.allPacketsLimit.packetLimitInterval * 1.0e9) -+ ) : null; -+ protected final java.util.Map>, com.tuinity.tuinity.util.IntervalledCounter> packetSpecificLimits = new java.util.HashMap<>(); -+ -+ private boolean stopReadingPackets; -+ private void killForPacketSpam() { -+ this.sendPacket(new PacketPlayOutKickDisconnect(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(com.tuinity.tuinity.config.TuinityConfig.kickMessage, true)[0]), (future) -> { -+ this.close(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(com.tuinity.tuinity.config.TuinityConfig.kickMessage, true)[0]); -+ }); -+ this.stopReading(); -+ this.stopReadingPackets = true; -+ } -+ // Tuinity end - packet limiter - protected void channelRead0(ChannelHandlerContext channelhandlercontext, Packet packet) throws Exception { - if (this.channel.isOpen()) { -+ // Tuinity start - packet limiter -+ if (this.stopReadingPackets) { -+ return; -+ } -+ if (this.allPacketCounts != null || -+ com.tuinity.tuinity.config.TuinityConfig.packetSpecificLimits.containsKey(packet.getClass())) { -+ long time = System.nanoTime(); -+ synchronized (PACKET_LIMIT_LOCK) { -+ if (this.allPacketCounts != null) { -+ this.allPacketCounts.updateAndAdd(1, time); -+ if (this.allPacketCounts.getRate() >= com.tuinity.tuinity.config.TuinityConfig.allPacketsLimit.maxPacketRate) { -+ this.killForPacketSpam(); -+ return; -+ } -+ } -+ -+ for (Class check = packet.getClass(); check != Object.class; check = check.getSuperclass()) { -+ com.tuinity.tuinity.config.TuinityConfig.PacketLimit packetSpecificLimit = -+ com.tuinity.tuinity.config.TuinityConfig.packetSpecificLimits.get(check); -+ if (packetSpecificLimit == null) { -+ continue; -+ } -+ com.tuinity.tuinity.util.IntervalledCounter counter = this.packetSpecificLimits.computeIfAbsent((Class)check, (clazz) -> { -+ return new com.tuinity.tuinity.util.IntervalledCounter((long)(packetSpecificLimit.packetLimitInterval * 1.0e9)); -+ }); -+ counter.updateAndAdd(1, time); -+ if (counter.getRate() >= packetSpecificLimit.maxPacketRate) { -+ switch (packetSpecificLimit.violateAction) { -+ case DROP: -+ return; -+ case KICK: -+ this.killForPacketSpam(); -+ return; -+ } -+ } -+ } -+ } -+ } -+ // Tuinity end - packet limiter - try { - a(packet, this.packetListener); - } catch (CancelledPacketHandleException cancelledpackethandleexception) { -@@ -222,7 +334,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - MCUtil.isMainThread() && packet.isReady() && this.packetQueue.isEmpty() && - (packet.getExtraPackets() == null || packet.getExtraPackets().isEmpty()) - ))) { -- this.dispatchPacket(packet, genericfuturelistener); -+ this.writePacket(packet, genericfuturelistener, null); // Tuinity - return; - } - // write the packets to the queue, then flush - antixray hooks there already -@@ -248,6 +360,14 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - - private void dispatchPacket(Packet packet, @Nullable GenericFutureListener> genericFutureListener) { this.b(packet, genericFutureListener); } // Paper - OBFHELPER - private void b(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { -+ // Tuinity start - add flush parameter -+ this.writePacket(packet, genericfuturelistener, Boolean.TRUE); -+ } -+ private void writePacket(Packet packet, @Nullable GenericFutureListener> genericfuturelistener, Boolean flushConditional) { -+ this.packetWrites.getAndIncrement(); // must be befeore using canFlush -+ boolean effectiveFlush = flushConditional == null ? this.canFlush : flushConditional.booleanValue(); -+ final boolean flush = effectiveFlush || packet instanceof PacketPlayOutKeepAlive || packet instanceof PacketPlayOutKickDisconnect; // no delay for certain packets -+ // Tuinity end - add flush parameter - EnumProtocol enumprotocol = EnumProtocol.a(packet); - EnumProtocol enumprotocol1 = (EnumProtocol) this.channel.attr(NetworkManager.c).get(); - -@@ -270,7 +390,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - try { - // Paper end - -- ChannelFuture channelfuture = this.channel.writeAndFlush(packet); -+ ChannelFuture channelfuture = (flush) ? this.channel.writeAndFlush(packet) : this.channel.write(packet); // Tuinity - add flush parameter - - if (genericfuturelistener != null) { - channelfuture.addListener(genericfuturelistener); -@@ -290,39 +410,83 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - } - // Paper end - } else { -- this.channel.eventLoop().execute(() -> { -- if (enumprotocol != enumprotocol1) { -- this.setProtocol(enumprotocol); -- } -+ // Tuinity start - optimise packets that are not flushed -+ Runnable choice1 = null; -+ AbstractEventExecutor.LazyRunnable choice2 = null; -+ // note: since the type is not dynamic here, we need to actually copy the old executor code -+ // into two branches. On conflict, just re-copy - no changes were made inside the executor code. -+ if (flush) { -+ choice1 = () -> { -+ if (enumprotocol != enumprotocol1) { -+ this.setProtocol(enumprotocol); -+ } - -- // Paper start -- if (!isConnected()) { -- packet.onPacketDispatchFinish(player, null); -- return; -- } -- try { -+ // Paper start -+ if (!isConnected()) { -+ packet.onPacketDispatchFinish(player, null); -+ return; -+ } -+ try { -+ // Paper end -+ ChannelFuture channelfuture1 = (flush) ? this.channel.writeAndFlush(packet) : this.channel.write(packet); // Tuinity - add flush parameter -+ -+ -+ if (genericfuturelistener != null) { -+ channelfuture1.addListener(genericfuturelistener); -+ } -+ // Paper start -+ if (packet.hasFinishListener()) { -+ channelfuture1.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); -+ } -+ // Paper end -+ -+ channelfuture1.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); -+ // Paper start -+ } catch (Exception e) { -+ LOGGER.error("NetworkException: " + player, e); -+ close(new ChatMessage("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; -+ packet.onPacketDispatchFinish(player, null); -+ } - // Paper end -- ChannelFuture channelfuture1 = this.channel.writeAndFlush(packet); -- -- -- if (genericfuturelistener != null) { -- channelfuture1.addListener(genericfuturelistener); -- } -- // Paper start -- if (packet.hasFinishListener()) { -- channelfuture1.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); -- } -- // Paper end -+ }; -+ } else { -+ // explicitly declare a variable to make the lambda use the type -+ choice2 = () -> { -+ if (enumprotocol != enumprotocol1) { -+ this.setProtocol(enumprotocol); -+ } - -- channelfuture1.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); -- // Paper start -- } catch (Exception e) { -- LOGGER.error("NetworkException: " + player, e); -- close(new ChatMessage("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; -- packet.onPacketDispatchFinish(player, null); -- } -- // Paper end -- }); -+ // Paper start -+ if (!isConnected()) { -+ packet.onPacketDispatchFinish(player, null); -+ return; -+ } -+ try { -+ // Paper end -+ ChannelFuture channelfuture1 = (flush) ? this.channel.writeAndFlush(packet) : this.channel.write(packet); // Tuinity - add flush parameter -+ -+ -+ if (genericfuturelistener != null) { -+ channelfuture1.addListener(genericfuturelistener); -+ } -+ // Paper start -+ if (packet.hasFinishListener()) { -+ channelfuture1.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); -+ } -+ // Paper end -+ -+ channelfuture1.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); -+ // Paper start -+ } catch (Exception e) { -+ LOGGER.error("NetworkException: " + player, e); -+ close(new ChatMessage("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; -+ packet.onPacketDispatchFinish(player, null); -+ } -+ // Paper end -+ }; -+ } -+ this.channel.eventLoop().execute(choice1 != null ? choice1 : choice2); -+ // Tuinity end - optimise packets that are not flushed - } - - } -@@ -344,7 +508,10 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - return false; - } - private boolean processQueue() { -+ try { // Tuinity - add pending task queue - if (this.packetQueue.isEmpty()) return true; -+ final boolean needsFlush = this.canFlush; // Tuinity - make only one flush call per sendPacketQueue() call -+ boolean hasWrotePacket = false; - // If we are on main, we are safe here in that nothing else should be processing queue off main anymore - // But if we are not on main due to login/status, the parent is synchronized on packetQueue - java.util.Iterator iterator = this.packetQueue.iterator(); -@@ -352,19 +519,31 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - NetworkManager.QueuedPacket queued = iterator.next(); // poll -> peek - - // Fix NPE (Spigot bug caused by handleDisconnection()) -- if (queued == null) { -+ if (false && queued == null) { // Tuinity - diff on change, this logic is redundant: iterator guarantees ret of an element - on change, hook the flush logic here - return true; - } - - Packet packet = queued.getPacket(); - if (!packet.isReady()) { -+ // Tuinity start - make only one flush call per sendPacketQueue() call -+ if (hasWrotePacket && (needsFlush || this.canFlush)) { -+ this.flush(); -+ } -+ // Tuinity end - make only one flush call per sendPacketQueue() call - return false; - } else { - iterator.remove(); -- this.dispatchPacket(packet, queued.getGenericFutureListener()); -+ this.writePacket(packet, queued.getGenericFutureListener(), (!iterator.hasNext() && (needsFlush || this.canFlush)) ? Boolean.TRUE : Boolean.FALSE); // Tuinity - make only one flush call per sendPacketQueue() call -+ hasWrotePacket = true; // Tuinity - make only one flush call per sendPacketQueue() call - } - } - return true; -+ } finally { // Tuinity start - add pending task queue -+ Runnable r; -+ while ((r = this.pendingTasks.poll()) != null) { -+ this.channel.eventLoop().execute(r); -+ } -+ } // Tuinity end - add pending task queue - } - // Paper end - -@@ -387,7 +566,14 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - } - - if (this.packetListener instanceof PlayerConnection) { -+ // Tuinity start - detailed watchdog information -+ PlayerConnectionUtils.packetProcessing.push(this.packetListener); -+ try { -+ // Tuinity end - detailed watchdog information - ((PlayerConnection) this.packetListener).tick(); -+ } finally { // Tuinity start - detailed watchdog information -+ PlayerConnectionUtils.packetProcessing.pop(); -+ } // Tuinity start - detailed watchdog information - } - - if (this.channel != null) { -@@ -438,10 +624,16 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - return this.channel instanceof LocalChannel || this.channel instanceof LocalServerChannel; - } - -- public void a(Cipher cipher, Cipher cipher1) { -+ public void a(javax.crypto.SecretKey secretkey) { // Tuinity - this.n = true; -- this.channel.pipeline().addBefore("splitter", "decrypt", new PacketDecrypter(cipher)); -- this.channel.pipeline().addBefore("prepender", "encrypt", new PacketEncrypter(cipher1)); -+ // Tuinity start -+ try { -+ this.channel.pipeline().addBefore("splitter", "decrypt", new PacketDecrypter(/*MinecraftEncryption.a(2, secretkey)*/ secretkey)); -+ this.channel.pipeline().addBefore("prepender", "encrypt", new PacketEncrypter(/*MinecraftEncryption.a(1, secretkey)*/ secretkey)); -+ } catch (java.security.GeneralSecurityException e) { -+ throw new RuntimeException("Couldn't enable encryption", e); -+ } -+ // Tuinity end - } - - public boolean isConnected() { -diff --git a/src/main/java/net/minecraft/server/NibbleArray.java b/src/main/java/net/minecraft/server/NibbleArray.java -index 4085426af03f032cf405bdfd1e40a8e5dc27c1d1..348d16ddec3b4da0b6b4e4f49916b966005b5259 100644 ---- a/src/main/java/net/minecraft/server/NibbleArray.java -+++ b/src/main/java/net/minecraft/server/NibbleArray.java -@@ -56,6 +56,7 @@ public class NibbleArray { - boolean poolSafe = false; - public java.lang.Runnable cleaner; - private void registerCleaner() { -+ if (com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine) return; // Tuinity - purge cleaner usage - if (!poolSafe) { - cleaner = MCUtil.registerCleaner(this, this.a, NibbleArray::releaseBytes); - } else { -@@ -63,7 +64,7 @@ public class NibbleArray { - } - } - // Paper end -- @Nullable protected byte[] a; -+ @Nullable protected byte[] a; public final byte[] justGiveMeTheFuckingByteArrayNoCleanerBullshitJesusFuckingChrist() { return this.a; } - - - public NibbleArray() {} -@@ -74,7 +75,7 @@ public class NibbleArray { - } - public NibbleArray(byte[] abyte, boolean isSafe) { - this.a = abyte; -- if (!isSafe) this.a = getCloneIfSet(); // Paper - clone for safety -+ if (!com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine && !isSafe) this.a = getCloneIfSet(); // Paper - clone for safety // Tuinity - no need to clone - registerCleaner(); - // Paper end - if (abyte.length != 2048) { -@@ -162,7 +163,7 @@ public class NibbleArray { - - public NibbleArray copy() { return this.b(); } // Paper - OBFHELPER - public NibbleArray b() { -- return this.a == null ? new NibbleArray() : new NibbleArray(this.a); // Paper - clone in ctor -+ return this.a == null ? new NibbleArray() : new NibbleArray(com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? this.a.clone() : this.a); // Paper - clone in ctor // Tuinity - no longer clone in constructor - } - - public String toString() { -diff --git a/src/main/java/net/minecraft/server/PacketCompressor.java b/src/main/java/net/minecraft/server/PacketCompressor.java -index 3cdd07cad85ef2d2c4b6c27a55a878695b4a7b12..50b2a8dfbdd0fe60e295d7c7214d7c99bcbeb19a 100644 ---- a/src/main/java/net/minecraft/server/PacketCompressor.java -+++ b/src/main/java/net/minecraft/server/PacketCompressor.java -@@ -7,14 +7,18 @@ import java.util.zip.Deflater; - - public class PacketCompressor extends MessageToByteEncoder { - -- private final byte[] a = new byte[8192]; -- private final Deflater b; -+ // Tuinity start - use Velocity natives -+// private final byte[] a = new byte[8192]; -+// private final Deflater b; - private int c; -+ private final com.velocitypowered.natives.compression.VelocityCompressor compressor; - - public PacketCompressor(int i) { - this.c = i; -- this.b = new Deflater(); -+// this.b = new Deflater(); -+ this.compressor = com.velocitypowered.natives.util.Natives.compress.get().create(-1); - } -+ // Tuinity end - - protected void encode(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf, ByteBuf bytebuf1) throws Exception { - int i = bytebuf.readableBytes(); -@@ -24,24 +28,46 @@ public class PacketCompressor extends MessageToByteEncoder { - packetdataserializer.d(0); - packetdataserializer.writeBytes(bytebuf); - } else { -- byte[] abyte = new byte[i]; -- -- bytebuf.readBytes(abyte); -- packetdataserializer.d(abyte.length); -- this.b.setInput(abyte, 0, i); -- this.b.finish(); -- -- while (!this.b.finished()) { -- int j = this.b.deflate(this.a); -- -- packetdataserializer.writeBytes(this.a, 0, j); -+ // Tuinity start - delegate to Velocity natives -+// byte[] abyte = new byte[i]; -+// -+// bytebuf.readBytes(abyte); -+// packetdataserializer.d(abyte.length); -+// this.b.setInput(abyte, 0, i); -+// this.b.finish(); -+// -+// while (!this.b.finished()) { -+// int j = this.b.deflate(this.a); -+// -+// packetdataserializer.writeBytes(this.a, 0, j); -+// } -+// -+// this.b.reset(); -+ packetdataserializer.d(i); -+ ByteBuf source = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelhandlercontext.alloc(), -+ this.compressor, bytebuf); -+ try { -+ this.compressor.deflate(source, bytebuf1); -+ } finally { -+ source.release(); - } -- -- this.b.reset(); -+ // Tuinity end - } - - } - -+ // Tuinity start -+ @Override -+ protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, ByteBuf msg, boolean preferDirect) throws Exception { -+ return com.velocitypowered.natives.util.MoreByteBufUtils.preferredBuffer(ctx.alloc(), this.compressor, msg.readableBytes() + 1); -+ } -+ -+ @Override -+ public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { -+ this.compressor.close(); -+ } -+ // Tuinity end -+ - public void a(int i) { - this.c = i; - } -diff --git a/src/main/java/net/minecraft/server/PacketDecompressor.java b/src/main/java/net/minecraft/server/PacketDecompressor.java -index 23c850be0155c1ece807d244117a196488f0a13b..4bab19a52b400071e69b06b940ab6432dfe59a1b 100644 ---- a/src/main/java/net/minecraft/server/PacketDecompressor.java -+++ b/src/main/java/net/minecraft/server/PacketDecompressor.java -@@ -10,13 +10,17 @@ import java.util.zip.Inflater; - - public class PacketDecompressor extends ByteToMessageDecoder { - -- private final Inflater a; -+ // Tuinity start - use Velocity natives -+ //private final Inflater a; -+ private final com.velocitypowered.natives.compression.VelocityCompressor compressor; - private int b; - - public PacketDecompressor(int i) { - this.b = i; -- this.a = new Inflater(); -+ //this.a = new Inflater(); -+ this.compressor = com.velocitypowered.natives.util.Natives.compress.get().create(-1); - } -+ // Tuinity end - - protected void decode(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf, List list) throws Exception { - if (bytebuf.readableBytes() != 0) { -@@ -34,20 +38,41 @@ public class PacketDecompressor extends ByteToMessageDecoder { - throw new DecoderException("Badly compressed packet - size of " + i + " is larger than protocol maximum of " + 2097152); - } - -- byte[] abyte = new byte[packetdataserializer.readableBytes()]; -- -- packetdataserializer.readBytes(abyte); -- this.a.setInput(abyte); -- byte[] abyte1 = new byte[i]; -- -- this.a.inflate(abyte1); -- list.add(Unpooled.wrappedBuffer(abyte1)); -- this.a.reset(); -+ // Tuinity start -+ ByteBuf compatibleIn = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelhandlercontext.alloc(), compressor, bytebuf); -+ ByteBuf uncompressed = com.velocitypowered.natives.util.MoreByteBufUtils.preferredBuffer(channelhandlercontext.alloc(), compressor, i); -+ try { -+ compressor.inflate(compatibleIn, uncompressed, i); -+ list.add(uncompressed); -+ bytebuf.clear(); -+ } catch (Exception e) { -+ uncompressed.release(); -+ throw e; -+ } finally { -+ compatibleIn.release(); -+ } -+// byte[] abyte = new byte[packetdataserializer.readableBytes()]; -+// -+// packetdataserializer.readBytes(abyte); -+// this.a.setInput(abyte); -+// byte[] abyte1 = new byte[i]; -+// -+// this.a.inflate(abyte1); -+// list.add(Unpooled.wrappedBuffer(abyte1)); -+// this.a.reset(); -+ // Tuinity end - } - - } - } - -+ // Tuinity start -+ @Override -+ public void handlerRemoved0(ChannelHandlerContext ctx) throws Exception { -+ this.compressor.close(); -+ } -+ // Tuinity end -+ - public void a(int i) { - this.b = i; - } -diff --git a/src/main/java/net/minecraft/server/PacketDecrypter.java b/src/main/java/net/minecraft/server/PacketDecrypter.java -index c85f291c5b22a8e85c7556b220cba698701748f2..771cc0f4fa98be294abba65c83442205b6b0ef0b 100644 ---- a/src/main/java/net/minecraft/server/PacketDecrypter.java -+++ b/src/main/java/net/minecraft/server/PacketDecrypter.java -@@ -8,13 +8,24 @@ import javax.crypto.Cipher; - - public class PacketDecrypter extends MessageToMessageDecoder { - -- private final PacketEncryptionHandler a; -+ // Tuinity start -+ private final com.velocitypowered.natives.encryption.VelocityCipher cipher; -+ //private final PacketEncryptionHandler a; - -- public PacketDecrypter(Cipher cipher) { -- this.a = new PacketEncryptionHandler(cipher); -+ public PacketDecrypter(javax.crypto.SecretKey key /* Cipher cipher */) throws java.security.GeneralSecurityException { -+ //this.a = new PacketEncryptionHandler(cipher); -+ this.cipher = com.velocitypowered.natives.util.Natives.cipher.get().forDecryption(key); - } - - protected void decode(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf, List list) throws Exception { -- list.add(this.a.a(channelhandlercontext, bytebuf)); -+ ByteBuf compatible = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelhandlercontext.alloc(), cipher, bytebuf).slice(); -+ try { -+ cipher.process(compatible); -+ list.add(compatible); -+ } catch (Exception e) { -+ compatible.release(); // compatible will never be used if we throw an exception -+ throw e; -+ } - } -+ // Tuinity end - } -diff --git a/src/main/java/net/minecraft/server/PacketEncrypter.java b/src/main/java/net/minecraft/server/PacketEncrypter.java -index e35369476839e9622520af1027d7478aa6d1b037..aba14794cc4cb114fea17bb92816ac29a64b44f8 100644 ---- a/src/main/java/net/minecraft/server/PacketEncrypter.java -+++ b/src/main/java/net/minecraft/server/PacketEncrypter.java -@@ -5,15 +5,38 @@ import io.netty.channel.ChannelHandlerContext; - import io.netty.handler.codec.MessageToByteEncoder; - import javax.crypto.Cipher; - --public class PacketEncrypter extends MessageToByteEncoder { -+// Tuinity start -+// We rewrite this class as the Velocity natives support in-place encryption -+import io.netty.handler.codec.MessageToMessageEncoder; // An unfortunate import, but this is required to fix a compiler error -+public class PacketEncrypter extends MessageToMessageEncoder { - -- private final PacketEncryptionHandler a; -+ private final com.velocitypowered.natives.encryption.VelocityCipher cipher; -+ //private final PacketEncryptionHandler a; - -- public PacketEncrypter(Cipher cipher) { -- this.a = new PacketEncryptionHandler(cipher); -+ public PacketEncrypter(javax.crypto.SecretKey key /* Cipher cipher */) throws java.security.GeneralSecurityException { -+ // this.a = new PacketEncryptionHandler(cipher); -+ this.cipher = com.velocitypowered.natives.util.Natives.cipher.get().forEncryption(key); - } - -- protected void encode(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf, ByteBuf bytebuf1) throws Exception { -- this.a.a(bytebuf, bytebuf1); -+// protected void encode(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf, ByteBuf bytebuf1) throws Exception { -+// this.a.a(bytebuf, bytebuf1); -+// } -+ -+ @Override -+ protected void encode(ChannelHandlerContext ctx, ByteBuf msg, java.util.List out) throws Exception { -+ ByteBuf compatible = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(ctx.alloc(), this.cipher, msg); -+ try { -+ this.cipher.process(compatible); -+ out.add(compatible); -+ } catch (Exception e) { -+ compatible.release(); // compatible will never be used if we throw an exception -+ throw e; -+ } -+ } -+ -+ @Override -+ public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { -+ cipher.close(); - } - } -+// Tuinity end -diff --git a/src/main/java/net/minecraft/server/PacketPlayOutLightUpdate.java b/src/main/java/net/minecraft/server/PacketPlayOutLightUpdate.java -index a22f0cccecc85b4e4fe4603bcfa213f15c23db69..6cc4a035c8b1312b59685b20039d5e82bb1e1a3e 100644 ---- a/src/main/java/net/minecraft/server/PacketPlayOutLightUpdate.java -+++ b/src/main/java/net/minecraft/server/PacketPlayOutLightUpdate.java -@@ -26,12 +26,12 @@ public class PacketPlayOutLightUpdate implements Packet { - - @Override - public void onPacketDispatch(EntityPlayer player) { -- remainingSends.incrementAndGet(); -+ if (!com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine) remainingSends.incrementAndGet(); - } - - @Override - public void onPacketDispatchFinish(EntityPlayer player, ChannelFuture future) { -- if (remainingSends.decrementAndGet() <= 0) { -+ if (!com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine && remainingSends.decrementAndGet() <= 0) { - // incase of any race conditions, schedule this delayed - MCUtil.scheduleTask(5, () -> { - if (remainingSends.get() == 0) { -@@ -44,7 +44,7 @@ public class PacketPlayOutLightUpdate implements Packet { - - @Override - public boolean hasFinishListener() { -- return true; -+ return !com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine; // Tuinity - replace light impl - } - - // Paper end -@@ -54,8 +54,8 @@ public class PacketPlayOutLightUpdate implements Packet { - this.a = chunkcoordintpair.x; - this.b = chunkcoordintpair.z; - this.i = flag; -- this.g = Lists.newArrayList();cleaner1 = MCUtil.registerListCleaner(this, this.g, NibbleArray::releaseBytes); // Paper -- this.h = Lists.newArrayList();cleaner2 = MCUtil.registerListCleaner(this, this.h, NibbleArray::releaseBytes); // Paper -+ this.g = Lists.newArrayList();if (!com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine) cleaner1 = MCUtil.registerListCleaner(this, this.g, NibbleArray::releaseBytes); // Paper // Tuinity - purge cleaner usage -+ this.h = Lists.newArrayList();if (!com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine) cleaner2 = MCUtil.registerListCleaner(this, this.h, NibbleArray::releaseBytes); // Paper // Tuinity - purge cleaner usage - - for (int i = 0; i < 18; ++i) { - NibbleArray nibblearray = lightengine.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, -1 + i)); -@@ -66,7 +66,7 @@ public class PacketPlayOutLightUpdate implements Packet { - this.e |= 1 << i; - } else { - this.c |= 1 << i; -- this.g.add(nibblearray.getCloneIfSet()); // Paper -+ this.g.add(com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? nibblearray.asBytes() : nibblearray.getCloneIfSet()); // Paper // Tuinity - don't clone again - } - } - -@@ -75,7 +75,7 @@ public class PacketPlayOutLightUpdate implements Packet { - this.f |= 1 << i; - } else { - this.d |= 1 << i; -- this.h.add(nibblearray1.getCloneIfSet()); // Paper -+ this.h.add(com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? nibblearray1.asBytes() : nibblearray1.getCloneIfSet()); // Paper // Tuinity - don't clone again - } - } - } -@@ -88,8 +88,8 @@ public class PacketPlayOutLightUpdate implements Packet { - this.i = flag; - this.c = i; - this.d = j; -- this.g = Lists.newArrayList();cleaner1 = MCUtil.registerListCleaner(this, this.g, NibbleArray::releaseBytes); // Paper -- this.h = Lists.newArrayList();cleaner2 = MCUtil.registerListCleaner(this, this.h, NibbleArray::releaseBytes); // Paper -+ this.g = Lists.newArrayList();if (!com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine) cleaner1 = MCUtil.registerListCleaner(this, this.g, NibbleArray::releaseBytes); // Paper // Tuinity - purge cleaner usage -+ this.h = Lists.newArrayList();if (!com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine) cleaner2 = MCUtil.registerListCleaner(this, this.h, NibbleArray::releaseBytes); // Paper // Tuinity - purge cleaner usage - - for (int k = 0; k < 18; ++k) { - NibbleArray nibblearray; -@@ -97,7 +97,7 @@ public class PacketPlayOutLightUpdate implements Packet { - if ((this.c & 1 << k) != 0) { - nibblearray = lightengine.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, -1 + k)); - if (nibblearray != null && !nibblearray.c()) { -- this.g.add(nibblearray.getCloneIfSet()); // Paper -+ this.g.add(com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? nibblearray.asBytes() : nibblearray.getCloneIfSet()); // Paper // Tuinity - don't clone again - } else { - this.c &= ~(1 << k); - if (nibblearray != null) { -@@ -109,7 +109,7 @@ public class PacketPlayOutLightUpdate implements Packet { - if ((this.d & 1 << k) != 0) { - nibblearray = lightengine.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkcoordintpair, -1 + k)); - if (nibblearray != null && !nibblearray.c()) { -- this.h.add(nibblearray.getCloneIfSet()); // Paper -+ this.h.add(com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? nibblearray.asBytes() : nibblearray.getCloneIfSet()); // Paper // Tuinity - don't clone again - } else { - this.d &= ~(1 << k); - if (nibblearray != null) { -diff --git a/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java -index b9276928a58d56ca9aac95d262d8555522946bd7..d5a8036b764699a70a69b7dc3d45ea6d10835c44 100644 ---- a/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java -+++ b/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java -@@ -19,7 +19,7 @@ public class PacketPlayOutMapChunk implements Packet { - @Nullable - private int[] e; - private byte[] f; private byte[] getData() { return this.f; } // Paper - OBFHELPER -- private List g; -+ private List g; private List getTileEntityData() { return this.g; } // Tuinity - OBFHELPER - private boolean h; - - // Paper start - Async-Anti-Xray - Set the ready flag to true -@@ -31,7 +31,9 @@ public class PacketPlayOutMapChunk implements Packet { - - // Paper start - private final java.util.List extraPackets = new java.util.ArrayList<>(); -- private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750); -+ private static final int TE_LIMIT = Integer.getInteger("tuinity.excessive-te-limit", 750); // Tuinity - handle oversized chunk data packets more robustly -+ private static final int TE_SPLIT_LIMIT = Math.max(4096 + 1, Integer.getInteger("tuinity.te-split-limit", 15_000)); // Tuinity - handle oversized chunk data packets more robustly -+ private boolean mustSplit; // Tuinity - handle oversized chunk data packets more robustly - - @Override - public java.util.List getExtraPackets() { -@@ -40,7 +42,7 @@ public class PacketPlayOutMapChunk implements Packet { - // Paper end - // Paper start - Anti-Xray - Add chunk packet info - @Deprecated public PacketPlayOutMapChunk(Chunk chunk, int i) { this(chunk, i, true); } // Notice for updates: Please make sure this constructor isn't used anywhere -- public PacketPlayOutMapChunk(Chunk chunk, int i, boolean modifyBlocks) { -+ public PacketPlayOutMapChunk(Chunk chunk, int i, boolean modifyBlocks) { final int chunkSectionBitSet = i; // Tuinity - handle oversized chunk data packets more robustly - ChunkPacketInfo chunkPacketInfo = modifyBlocks ? chunk.world.chunkPacketBlockController.getChunkPacketInfo(this, chunk, i) : null; - // Paper end - ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); -@@ -49,27 +51,12 @@ public class PacketPlayOutMapChunk implements Packet { - this.b = chunkcoordintpair.z; - this.h = i == 65535; - this.d = new NBTTagCompound(); -- Iterator iterator = chunk.f().iterator(); -- -- Entry entry; -- -- while (iterator.hasNext()) { -- entry = (Entry) iterator.next(); -- if (((HeightMap.Type) entry.getKey()).c()) { -- this.d.set(((HeightMap.Type) entry.getKey()).b(), new NBTTagLongArray(((HeightMap) entry.getValue()).a())); -- } -- } -- -- if (this.h) { -- this.e = chunk.getBiomeIndex().a(); -- } -- -- this.f = new byte[this.a(chunk, i)]; -- // Paper start - Anti-Xray - Add chunk packet info -- if (chunkPacketInfo != null) { -- chunkPacketInfo.setData(this.getData()); -- } -- this.c = this.writeChunk(new PacketDataSerializer(this.j()), chunk, i, chunkPacketInfo); -+ // Tuinity - move this after the tile entity logic, we need to determine whether we're going to split -+ // Tuinity - before writing chunk block data -+ // Tuinity - note: for future maintenance, git will prefer the smallest diff, so if moving the TE code is -+ // Tuinity - a smaller diff, do that, else move the chunk writing - this makes sure the start/end is correct -+ Iterator iterator; // Tuinity - move declaration up -+ Entry entry; // Tuinity - move delcaration up - // Paper end - this.g = Lists.newArrayList(); - iterator = chunk.getTileEntities().entrySet().iterator(); -@@ -82,8 +69,16 @@ public class PacketPlayOutMapChunk implements Packet { - int j = blockposition.getY() >> 4; - - if (this.f() || (i & 1 << j) != 0) { -+ // Tuinity start - improve oversized chunk data packet handling -+ ++totalTileEntities; -+ if (totalTileEntities > TE_SPLIT_LIMIT) { -+ this.mustSplit = true; -+ this.getTileEntityData().clear(); -+ this.extraPackets.clear(); -+ break; -+ } - // Paper start - improve oversized chunk data packet handling -- if (++totalTileEntities > TE_LIMIT) { -+ if (totalTileEntities > TE_LIMIT) { // Tuinity end - improve oversized chunk data packet handling - PacketPlayOutTileEntityData updatePacket = tileentity.getUpdatePacket(); - if (updatePacket != null) { - this.extraPackets.add(updatePacket); -@@ -97,7 +92,42 @@ public class PacketPlayOutMapChunk implements Packet { - this.g.add(nbttagcompound); - } - } -+ // Tuinity start - moved after tile entity gathering -+ iterator = chunk.f().iterator(); // Declared earlier -+ -+ while (iterator.hasNext()) { -+ entry = (Entry) iterator.next(); -+ if (((HeightMap.Type) entry.getKey()).c()) { -+ this.d.set(((HeightMap.Type) entry.getKey()).b(), new NBTTagLongArray(((HeightMap) entry.getValue()).a())); -+ } -+ } -+ -+ if (this.h) { -+ this.e = chunk.getBiomeIndex().a(); -+ } -+ -+ this.f = new byte[this.a(chunk, i)]; -+ // Paper start - Anti-Xray - Add chunk packet info -+ if (chunkPacketInfo != null) { -+ chunkPacketInfo.setData(this.getData()); -+ } -+ this.c = this.writeChunk(new PacketDataSerializer(this.j()), chunk, i, chunkPacketInfo); -+ // Tuinity end - moved after tile entity gathering - chunk.world.chunkPacketBlockController.modifyBlocks(this, chunkPacketInfo); // Paper - Anti-Xray - Modify blocks -+ // Tuinity start - improve oversized chunk data packet handling -+ if (this.mustSplit) { -+ int chunkSectionBitSetCopy = chunkSectionBitSet; -+ for (int a = 0, len = Integer.bitCount(chunkSectionBitSet); a < len; ++a) { -+ int trailingBit = com.destroystokyo.paper.util.math.IntegerUtil.getTrailingBit(chunkSectionBitSetCopy); -+ int sectionIndex = Integer.numberOfTrailingZeros(trailingBit); -+ chunkSectionBitSetCopy ^= trailingBit; // move on to the next -+ -+ if (chunk.getSections()[sectionIndex] != null) { -+ this.extraPackets.add(new PacketPlayOutMapChunk(chunk, trailingBit)); -+ } -+ } -+ } -+ // Tuinity end - improve oversized chunk data packet handling - } - - // Paper start - Async-Anti-Xray - Getter and Setter for the ready flag -@@ -188,7 +218,7 @@ public class PacketPlayOutMapChunk implements Packet { - for (int l = achunksection.length; k < l; ++k) { - ChunkSection chunksection = achunksection[k]; - -- if (chunksection != Chunk.a && (!this.f() || !chunksection.c()) && (i & 1 << k) != 0) { -+ if ((!this.mustSplit && chunksection != Chunk.a) && (!this.f() || !chunksection.c()) && (i & 1 << k) != 0) { // Tuinity - improve oversized chunk data packet handling - j |= 1 << k; - chunksection.writeChunkSection(packetdataserializer, chunkPacketInfo); // Paper - Anti-Xray - Add chunk packet info - } -@@ -205,7 +235,7 @@ public class PacketPlayOutMapChunk implements Packet { - for (int l = achunksection.length; k < l; ++k) { - ChunkSection chunksection = achunksection[k]; - -- if (chunksection != Chunk.a && (!this.f() || !chunksection.c()) && (i & 1 << k) != 0) { -+ if ((!this.mustSplit && chunksection != Chunk.a) && (!this.f() || !chunksection.c()) && (i & 1 << k) != 0) { - j += chunksection.j(); - } - } -diff --git a/src/main/java/net/minecraft/server/PathType.java b/src/main/java/net/minecraft/server/PathType.java -index fb37f5b500c52f915b4536e5ec35552b75056046..52a2d3db7da3596bfdd6fd51147cc93bbe6c7ed0 100644 ---- a/src/main/java/net/minecraft/server/PathType.java -+++ b/src/main/java/net/minecraft/server/PathType.java -@@ -4,6 +4,8 @@ public enum PathType { - - BLOCKED(-1.0F), OPEN(0.0F), WALKABLE(0.0F), WALKABLE_DOOR(0.0F), TRAPDOOR(0.0F), FENCE(-1.0F), LAVA(-1.0F), WATER(8.0F), WATER_BORDER(8.0F), RAIL(0.0F), UNPASSABLE_RAIL(-1.0F), DANGER_FIRE(8.0F), DAMAGE_FIRE(16.0F), DANGER_CACTUS(8.0F), DAMAGE_CACTUS(-1.0F), DANGER_OTHER(8.0F), DAMAGE_OTHER(-1.0F), DOOR_OPEN(0.0F), DOOR_WOOD_CLOSED(-1.0F), DOOR_IRON_CLOSED(-1.0F), BREACH(4.0F), LEAVES(-1.0F), STICKY_HONEY(8.0F), COCOA(0.0F); - -+ PathType belowOverride; // Tuinity -+ - private final float y; - - private PathType(float f) { -diff --git a/src/main/java/net/minecraft/server/PathfinderNormal.java b/src/main/java/net/minecraft/server/PathfinderNormal.java -index 74e81e1e4aea6f74b14a84231ddeb7f2fb845ae7..33804e68931e8b4145b896eedeab79bde78779f2 100644 ---- a/src/main/java/net/minecraft/server/PathfinderNormal.java -+++ b/src/main/java/net/minecraft/server/PathfinderNormal.java -@@ -421,6 +421,12 @@ public class PathfinderNormal extends PathfinderAbstract { - if (pathtype == PathType.OPEN && j >= 1) { - PathType pathtype1 = b(iblockaccess, blockposition_mutableblockposition.d(i, j - 1, k)); - -+ // Tuinity start - reduce pathfinder branches -+ if (pathtype1.belowOverride != null) { -+ pathtype = pathtype1.belowOverride; -+ } else { -+ PathType original1 = pathtype1; -+ // Tuinity end - reduce pathfinder branches - pathtype = pathtype1 != PathType.WALKABLE && pathtype1 != PathType.OPEN && pathtype1 != PathType.WATER && pathtype1 != PathType.LAVA ? PathType.WALKABLE : PathType.OPEN; - if (pathtype1 == PathType.DAMAGE_FIRE) { - pathtype = PathType.DAMAGE_FIRE; -@@ -437,6 +443,7 @@ public class PathfinderNormal extends PathfinderAbstract { - if (pathtype1 == PathType.STICKY_HONEY) { - pathtype = PathType.STICKY_HONEY; - } -+ original1.belowOverride = pathtype; } // Tuinity - reduce pathfinder branches - } - - if (pathtype == PathType.WALKABLE) { -@@ -462,22 +469,29 @@ public class PathfinderNormal extends PathfinderAbstract { - pathtype = PathType.BLOCKED; - } else { - // Paper end -- -+ // Tuinity start - reduce pathfinder branching -+ if (iblockdata.neighbourOverridePathType == PathType.OPEN) { -+ continue; -+ } else if (iblockdata.neighbourOverridePathType != null) { -+ return iblockdata.neighbourOverridePathType; -+ } -+ // Tuinity end - reduce pathfinder branching - if (iblockdata.a(Blocks.CACTUS)) { -- return PathType.DANGER_CACTUS; -+ return iblockdata.neighbourOverridePathType = PathType.DANGER_CACTUS; // Tuinity - reduce pathfinder branching - } - - if (iblockdata.a(Blocks.SWEET_BERRY_BUSH)) { -- return PathType.DANGER_OTHER; -+ return iblockdata.neighbourOverridePathType = PathType.DANGER_OTHER; // Tuinity - reduce pathfinder branching - } - - if (a(iblockdata)) { -- return PathType.DANGER_FIRE; -+ return iblockdata.neighbourOverridePathType = PathType.DANGER_FIRE; // Tuinity - reduce pathfinder branching - } - - if (iblockdata.getFluid().a((Tag) TagsFluid.WATER)) { // Paper - remove another getType call -- return PathType.WATER_BORDER; -+ return iblockdata.neighbourOverridePathType = PathType.WATER_BORDER; // Tuinity - reduce pathfinder branching - } -+ iblockdata.neighbourOverridePathType = PathType.OPEN; // Tuinity - reduce pathfinder branching - } // Paper - } - } -@@ -490,6 +504,20 @@ public class PathfinderNormal extends PathfinderAbstract { - protected static PathType b(IBlockAccess iblockaccess, BlockPosition blockposition) { - IBlockData iblockdata = iblockaccess.getTypeIfLoaded(blockposition); // Paper - if (iblockdata == null) return PathType.BLOCKED; // Paper -+ // Tuinity start - reduce pathfinder branches -+ if (iblockdata.staticPathType != null) { -+ return iblockdata.staticPathType; -+ } -+ if (iblockdata.getShapeCache() == null) { -+ // while it might be called static, it might vary on shape! However, only a few blocks have variable shape. -+ // So we rarely enter here. -+ return getStaticTypeSlow(iblockaccess, blockposition, iblockdata); -+ } else { -+ return iblockdata.staticPathType = getStaticTypeSlow(iblockaccess, blockposition, iblockdata); -+ } -+ } -+ protected static PathType getStaticTypeSlow(IBlockAccess iblockaccess, BlockPosition blockposition, IBlockData iblockdata) { -+ // Tuinity end - reduce pathfinder branches - Block block = iblockdata.getBlock(); - Material material = iblockdata.getMaterial(); - -diff --git a/src/main/java/net/minecraft/server/PathfinderTargetCondition.java b/src/main/java/net/minecraft/server/PathfinderTargetCondition.java -index 253377c6238594de1f76cafcbf8223592e4d3f6b..3ebe3d0dc4c2c6aee6ea349006a74cbe5aa8e78f 100644 ---- a/src/main/java/net/minecraft/server/PathfinderTargetCondition.java -+++ b/src/main/java/net/minecraft/server/PathfinderTargetCondition.java -@@ -51,6 +51,7 @@ public class PathfinderTargetCondition { - return this; - } - -+ public final boolean test(@Nullable EntityLiving entityliving, EntityLiving entityliving1) { return this.a(entityliving, entityliving1); } // Tuinity - OBFHELPER - public boolean a(@Nullable EntityLiving entityliving, EntityLiving entityliving1) { - if (entityliving == entityliving1) { - return false; -diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java -index 904c6a7d0a36b57bb4f693fc4fd0dd5b17adcbac..dcf13e62264f97384fb2f6c30cbc183a63cf3f97 100644 ---- a/src/main/java/net/minecraft/server/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/PlayerChunk.java -@@ -3,6 +3,7 @@ package net.minecraft.server; +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java +index a323b76f68c273a73cb3f20167a668b2100f4944..d9b134302f739efd93f50e93c8730b474f9a8ccf 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunk.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java +@@ -3,6 +3,7 @@ package net.minecraft.server.level; import com.mojang.datafixers.util.Either; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper import it.unimi.dsi.fastutil.shorts.ShortArraySet; @@ -14934,7 +12949,7 @@ index 904c6a7d0a36b57bb4f693fc4fd0dd5b17adcbac..dcf13e62264f97384fb2f6c30cbc183a import it.unimi.dsi.fastutil.shorts.ShortSet; import java.util.List; import java.util.Optional; -@@ -56,6 +57,12 @@ public class PlayerChunk { +@@ -82,6 +83,12 @@ public class PlayerChunk { long key = net.minecraft.server.MCUtil.getCoordinateKey(this.location); this.playersInMobSpawnRange = this.chunkMap.playerMobSpawnMap.getObjectsInRange(key); this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key); @@ -14947,7 +12962,7 @@ index 904c6a7d0a36b57bb4f693fc4fd0dd5b17adcbac..dcf13e62264f97384fb2f6c30cbc183a } // Paper end - optimise isOutsideOfRange // Paper start - optimize chunk status progression without jumping through thread pool -@@ -366,13 +373,13 @@ public class PlayerChunk { +@@ -392,13 +399,13 @@ public class PlayerChunk { if (!blockposition.isValidLocation()) return; // Paper - SPIGOT-6086 for all invalid locations; avoid acquiring locks Chunk chunk = this.getSendingChunk(); // Paper - no-tick view distance @@ -14963,7 +12978,7 @@ index 904c6a7d0a36b57bb4f693fc4fd0dd5b17adcbac..dcf13e62264f97384fb2f6c30cbc183a } this.dirtyBlocks[b0].add(SectionPosition.b(blockposition)); -@@ -381,13 +388,14 @@ public class PlayerChunk { +@@ -407,13 +414,14 @@ public class PlayerChunk { public void a(EnumSkyBlock enumskyblock, int i) { Chunk chunk = this.getSendingChunk(); // Paper - no-tick view distance @@ -14980,7 +12995,7 @@ index 904c6a7d0a36b57bb4f693fc4fd0dd5b17adcbac..dcf13e62264f97384fb2f6c30cbc183a } } -@@ -425,7 +433,7 @@ public class PlayerChunk { +@@ -451,7 +459,7 @@ public class PlayerChunk { this.a(world, blockposition, iblockdata); } else { ChunkSection chunksection = chunk.getSections()[sectionposition.getY()]; @@ -14989,7 +13004,7 @@ index 904c6a7d0a36b57bb4f693fc4fd0dd5b17adcbac..dcf13e62264f97384fb2f6c30cbc183a PacketPlayOutMultiBlockChange packetplayoutmultiblockchange = new PacketPlayOutMultiBlockChange(sectionposition, shortset, chunksection, this.x); this.a(packetplayoutmultiblockchange, false); -@@ -467,7 +475,7 @@ public class PlayerChunk { +@@ -493,7 +501,7 @@ public class PlayerChunk { // Paper start - per player view distance // there can be potential desync with player's last mapped section and the view distance map, so use the // view distance map here. @@ -14998,7 +13013,7 @@ index 904c6a7d0a36b57bb4f693fc4fd0dd5b17adcbac..dcf13e62264f97384fb2f6c30cbc183a com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet players = viewDistanceMap.getObjectsInRange(this.location); if (players == null) { return; -@@ -481,6 +489,7 @@ public class PlayerChunk { +@@ -507,6 +515,7 @@ public class PlayerChunk { continue; } EntityPlayer player = (EntityPlayer)temp; @@ -15006,7 +13021,7 @@ index 904c6a7d0a36b57bb4f693fc4fd0dd5b17adcbac..dcf13e62264f97384fb2f6c30cbc183a int viewDistance = viewDistanceMap.getLastViewDistance(player); long lastPosition = viewDistanceMap.getLastCoordinate(player); -@@ -500,6 +509,7 @@ public class PlayerChunk { +@@ -526,6 +535,7 @@ public class PlayerChunk { continue; } EntityPlayer player = (EntityPlayer)temp; @@ -15014,7 +13029,7 @@ index 904c6a7d0a36b57bb4f693fc4fd0dd5b17adcbac..dcf13e62264f97384fb2f6c30cbc183a player.playerConnection.sendPacket(packet); } } -@@ -508,6 +518,7 @@ public class PlayerChunk { +@@ -534,6 +544,7 @@ public class PlayerChunk { // Paper end - per player view distance } @@ -15022,7 +13037,7 @@ index 904c6a7d0a36b57bb4f693fc4fd0dd5b17adcbac..dcf13e62264f97384fb2f6c30cbc183a public CompletableFuture> a(ChunkStatus chunkstatus, PlayerChunkMap playerchunkmap) { int i = chunkstatus.c(); CompletableFuture> completablefuture = (CompletableFuture) this.statusFutures.get(i); -@@ -563,6 +574,7 @@ public class PlayerChunk { +@@ -589,6 +600,7 @@ public class PlayerChunk { } protected void a(PlayerChunkMap playerchunkmap) { @@ -15030,7 +13045,7 @@ index 904c6a7d0a36b57bb4f693fc4fd0dd5b17adcbac..dcf13e62264f97384fb2f6c30cbc183a ChunkStatus chunkstatus = getChunkStatus(this.oldTicketLevel); ChunkStatus chunkstatus1 = getChunkStatus(this.ticketLevel); boolean flag = this.oldTicketLevel <= PlayerChunkMap.GOLDEN_TICKET; -@@ -572,7 +584,8 @@ public class PlayerChunk { +@@ -598,7 +610,8 @@ public class PlayerChunk { // CraftBukkit start // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins. if (playerchunk_state.isAtLeast(PlayerChunk.State.BORDER) && !playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER)) { @@ -15040,7 +13055,7 @@ index 904c6a7d0a36b57bb4f693fc4fd0dd5b17adcbac..dcf13e62264f97384fb2f6c30cbc183a Chunk chunk = (Chunk)either.left().orElse(null); if (chunk != null) { playerchunkmap.callbackExecutor.execute(() -> { -@@ -637,7 +650,8 @@ public class PlayerChunk { +@@ -663,7 +676,8 @@ public class PlayerChunk { if (!flag2 && flag3) { // Paper start - cache ticking ready status int expectCreateCount = ++this.fullChunkCreateCount; @@ -15050,7 +13065,7 @@ index 904c6a7d0a36b57bb4f693fc4fd0dd5b17adcbac..dcf13e62264f97384fb2f6c30cbc183a if (either.left().isPresent() && PlayerChunk.this.fullChunkCreateCount == expectCreateCount) { // note: Here is a very good place to add callbacks to logic waiting on this. Chunk fullChunk = either.left().get(); -@@ -668,7 +682,8 @@ public class PlayerChunk { +@@ -694,7 +708,8 @@ public class PlayerChunk { if (!flag4 && flag5) { // Paper start - cache ticking ready status @@ -15060,7 +13075,7 @@ index 904c6a7d0a36b57bb4f693fc4fd0dd5b17adcbac..dcf13e62264f97384fb2f6c30cbc183a if (either.left().isPresent()) { // note: Here is a very good place to add callbacks to logic waiting on this. Chunk tickingChunk = either.left().get(); -@@ -678,6 +693,9 @@ public class PlayerChunk { +@@ -704,6 +719,9 @@ public class PlayerChunk { // Paper start - rewrite ticklistserver PlayerChunk.this.chunkMap.world.onChunkSetTicking(PlayerChunk.this.location.x, PlayerChunk.this.location.z); // Paper end - rewrite ticklistserver @@ -15070,7 +13085,7 @@ index 904c6a7d0a36b57bb4f693fc4fd0dd5b17adcbac..dcf13e62264f97384fb2f6c30cbc183a } }); -@@ -688,6 +706,12 @@ public class PlayerChunk { +@@ -714,6 +732,12 @@ public class PlayerChunk { if (flag4 && !flag5) { this.tickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); this.isTickingReady = false; // Paper - cache chunk ticking stage this.tickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; @@ -15083,7 +13098,7 @@ index 904c6a7d0a36b57bb4f693fc4fd0dd5b17adcbac..dcf13e62264f97384fb2f6c30cbc183a } boolean flag6 = playerchunk_state.isAtLeast(PlayerChunk.State.ENTITY_TICKING); -@@ -699,13 +723,16 @@ public class PlayerChunk { +@@ -725,13 +749,16 @@ public class PlayerChunk { } // Paper start - cache ticking ready status @@ -15102,7 +13117,7 @@ index 904c6a7d0a36b57bb4f693fc4fd0dd5b17adcbac..dcf13e62264f97384fb2f6c30cbc183a } -@@ -717,6 +744,12 @@ public class PlayerChunk { +@@ -743,6 +770,12 @@ public class PlayerChunk { if (flag6 && !flag7) { this.entityTickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); this.isEntityTickingReady = false; // Paper - cache chunk ticking stage this.entityTickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; @@ -15115,7 +13130,7 @@ index 904c6a7d0a36b57bb4f693fc4fd0dd5b17adcbac..dcf13e62264f97384fb2f6c30cbc183a } // Paper start - raise IO/load priority if priority changes, use our preferred priority -@@ -742,7 +775,8 @@ public class PlayerChunk { +@@ -768,7 +801,8 @@ public class PlayerChunk { // CraftBukkit start // ChunkLoadEvent: Called after the chunk is loaded: isChunkLoaded returns true and chunk is ready to be modified by plugins. if (!playerchunk_state.isAtLeast(PlayerChunk.State.BORDER) && playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER)) { @@ -15125,19 +13140,19 @@ index 904c6a7d0a36b57bb4f693fc4fd0dd5b17adcbac..dcf13e62264f97384fb2f6c30cbc183a Chunk chunk = (Chunk)either.left().orElse(null); if (chunk != null) { playerchunkmap.callbackExecutor.execute(() -> { -diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java -index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677eccfba1525 100644 ---- a/src/main/java/net/minecraft/server/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java -@@ -49,6 +49,7 @@ import java.util.stream.Collectors; - import java.util.stream.Stream; - import javax.annotation.Nullable; +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index 300884804bf9ac3fba7c30a04d8adf52e3dd2e3e..d7eede51f1c4ebbe8e00b16efd6331c87db53bb4 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -103,6 +103,7 @@ import net.minecraft.world.level.storage.WorldDataServer; + import net.minecraft.world.level.storage.WorldPersistentData; + import net.minecraft.world.phys.Vec3D; import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper +import it.unimi.dsi.fastutil.objects.Reference2BooleanOpenHashMap; // Tuinity import org.apache.commons.lang3.mutable.MutableBoolean; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -@@ -122,31 +123,28 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -176,31 +177,28 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() public final CallbackExecutor callbackExecutor = new CallbackExecutor(); public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable { @@ -15180,7 +13195,16 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec task.run(); } } -@@ -184,23 +182,17 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -220,7 +218,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + // inlined EnumMap, TrackingRange.TrackingRangeType + static final org.spigotmc.TrackingRange.TrackingRangeType[] TRACKING_RANGE_TYPES = org.spigotmc.TrackingRange.TrackingRangeType.values(); + public final com.destroystokyo.paper.util.misc.PlayerAreaMap[] playerEntityTrackerTrackMaps; +- final int[] entityTrackerTrackRanges; ++ final int[] entityTrackerTrackRanges; public int getEntityTrackerRange(final int ordinal) { return this.entityTrackerTrackRanges[ordinal]; } // Tuinity - public read + + private int convertSpigotRangeToVanilla(final int vanilla) { + return MinecraftServer.getServer().applyTrackingRangeScale(vanilla); +@@ -238,23 +236,17 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerChunkTickRangeMap; // Paper end - optimise PlayerChunkMap#isOutsideRange // Paper start - no-tick view distance @@ -15212,7 +13236,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec int chunkX = MCUtil.getChunkCoordinate(player.locX()); int chunkZ = MCUtil.getChunkCoordinate(player.locZ()); // Note: players need to be explicitly added to distance maps before they can be updated -@@ -209,28 +201,22 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -263,28 +255,22 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { com.destroystokyo.paper.util.misc.PlayerAreaMap trackMap = this.playerEntityTrackerTrackMaps[i]; int trackRange = this.entityTrackerTrackRanges[i]; @@ -15247,7 +13271,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec // Paper start - use distance map to optimise tracker for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { this.playerEntityTrackerTrackMaps[i].remove(player); -@@ -241,13 +227,15 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -295,13 +281,15 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { this.playerChunkTickRangeMap.remove(player); // Paper end - optimise PlayerChunkMap#isOutsideRange // Paper start - no-tick view distance @@ -15266,7 +13290,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec int chunkX = MCUtil.getChunkCoordinate(player.locX()); int chunkZ = MCUtil.getChunkCoordinate(player.locZ()); // Note: players need to be explicitly added to distance maps before they can be updated -@@ -256,27 +244,124 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -310,27 +298,124 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { com.destroystokyo.paper.util.misc.PlayerAreaMap trackMap = this.playerEntityTrackerTrackMaps[i]; int trackRange = this.entityTrackerTrackRanges[i]; @@ -15289,7 +13313,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec + // Paper end + + // Tuinity start -+ protected final List regionManagers = new java.util.ArrayList<>(); ++ public final List regionManagers = new java.util.ArrayList<>(); + public final com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager dataRegionManager; + + public static final class DataRegionData implements com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionData { @@ -15402,7 +13426,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec private final java.util.concurrent.ExecutorService lightThread; public PlayerChunkMap(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, IAsyncTaskHandler iasynctaskhandler, ILightAccess ilightaccess, ChunkGenerator chunkgenerator, WorldLoadListener worldloadlistener, Supplier supplier, int i, boolean flag) { -@@ -311,9 +396,10 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -365,9 +450,10 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { this.worldLoadListener = worldloadlistener; // Paper start - use light thread @@ -15414,7 +13438,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec thread.setDaemon(true); thread.setPriority(Thread.NORM_PRIORITY+1); return thread; -@@ -403,48 +489,29 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -457,48 +543,29 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { // Paper end - optimise PlayerChunkMap#isOutsideRange // Paper start - no-tick view distance this.setNoTickViewDistance(this.world.paperConfig.noTickViewDistance); @@ -15478,7 +13502,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec } // Paper start - Chunk Prioritization public void queueHolderUpdate(PlayerChunk playerchunk) { -@@ -477,6 +544,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -531,6 +598,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { } public void checkHighPriorityChunks(EntityPlayer player) { @@ -15486,7 +13510,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec int currentTick = MinecraftServer.currentTick; if (currentTick - player.lastHighPriorityChecked < 20 || !player.isRealPlayer) { // weed out fake players return; -@@ -484,7 +552,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -538,7 +606,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { player.lastHighPriorityChecked = currentTick; Long2IntOpenHashMap priorities = new Long2IntOpenHashMap(); @@ -15495,7 +13519,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(); // Prioritize circular near -@@ -550,7 +618,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -604,7 +672,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { } private boolean shouldSkipPrioritization(ChunkCoordIntPair coord) { @@ -15504,7 +13528,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec PlayerChunk chunk = getUpdatingChunk(coord.pair()); return chunk != null && (chunk.isFullChunkReady()); } -@@ -757,6 +825,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -811,6 +879,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { @Nullable private PlayerChunk a(long i, int j, @Nullable PlayerChunk playerchunk, int k) { @@ -15513,7 +13537,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec if (k > PlayerChunkMap.GOLDEN_TICKET && j > PlayerChunkMap.GOLDEN_TICKET) { return playerchunk; } else { -@@ -779,7 +849,13 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -833,7 +903,13 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { playerchunk.a(j); } else { playerchunk = new PlayerChunk(new ChunkCoordIntPair(i), j, this.lightEngine, this.p, this); @@ -15527,16 +13551,16 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec this.updatingChunks.put(i, playerchunk); this.updatingChunksModified = true; -@@ -905,7 +981,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -959,7 +1035,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { } - private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.90; // Spigot // Paper - unload more -+ static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.90; // Spigot // Paper - unload more // Tuinity - private -> package private ++ public static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.90; // Spigot // Paper - unload more // Tuinity - private -> public protected void unloadChunks(BooleanSupplier booleansupplier) { GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler(); -@@ -971,7 +1047,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -1025,7 +1101,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { } com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, chunkPos.x, chunkPos.z, @@ -15545,7 +13569,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec if (!chunk.isNeedsSaving()) { return; -@@ -1005,7 +1081,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -1059,7 +1135,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { asyncSaveData = ChunkRegionLoader.getAsyncSaveData(this.world, chunk); } @@ -15554,7 +13578,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec asyncSaveData, chunk); chunk.setLastSaved(this.world.getTime()); -@@ -1013,6 +1089,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -1067,6 +1143,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { } // Paper end @@ -15563,7 +13587,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec private void a(long i, PlayerChunk playerchunk) { CompletableFuture completablefuture = playerchunk.getChunkSave(); Consumer consumer = (ichunkaccess) -> { // CraftBukkit - decompile error -@@ -1021,7 +1099,21 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -1075,7 +1153,21 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { if (completablefuture1 != completablefuture) { this.a(i, playerchunk); } else { @@ -15586,7 +13610,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec if (ichunkaccess instanceof Chunk) { ((Chunk) ichunkaccess).setLoaded(false); } -@@ -1044,7 +1136,15 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -1098,7 +1190,15 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { this.lightEngine.a(ichunkaccess.getPos()); this.lightEngine.queueUpdate(); this.worldLoadListener.a(ichunkaccess.getPos(), (ChunkStatus) null); @@ -15603,7 +13627,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec } }; -@@ -1060,6 +1160,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -1114,6 +1214,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { } protected boolean b() { @@ -15611,7 +13635,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec if (!this.updatingChunksModified) { return false; } else { -@@ -1105,7 +1206,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -1159,7 +1260,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { if (ichunkaccess.getChunkStatus().b(chunkstatus)) { CompletableFuture> completablefuture1; // Paper @@ -15620,7 +13644,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec completablefuture1 = this.b(playerchunk, chunkstatus); } else { completablefuture1 = chunkstatus.a(this.world, this.definedStructureManager, this.lightEngine, (ichunkaccess1) -> { -@@ -1135,6 +1236,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -1189,6 +1290,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { this.getVillagePlace().loadInData(chunkcoordintpair, chunkHolder.poiData); chunkHolder.tasks.forEach(Runnable::run); @@ -15628,7 +13652,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec // Paper end if (chunkHolder.protoChunk != null) {try (Timing ignored2 = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings // Paper - chunk is created async -@@ -1247,9 +1349,13 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -1301,9 +1403,13 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { } // Paper end this.mailboxWorldGen.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); @@ -15643,7 +13667,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec protected void c(ChunkCoordIntPair chunkcoordintpair) { this.executor.a(SystemUtils.a(() -> { this.chunkDistanceManager.b(TicketType.LIGHT, chunkcoordintpair, 33 + ChunkStatus.a(ChunkStatus.FEATURES), chunkcoordintpair); -@@ -1416,9 +1522,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -1470,9 +1576,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { chunk.B(); return chunk; }); @@ -15654,7 +13678,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec } public int c() { -@@ -1499,39 +1603,27 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -1553,39 +1657,27 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { } public void setViewDistance(int i) { // Paper - public @@ -15699,7 +13723,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec if (entityplayer.world == this.world) { if (flag1 && !flag) { PlayerChunk playerchunk = this.getVisibleChunk(chunkcoordintpair.pair()); -@@ -1627,7 +1719,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -1681,7 +1773,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { if (Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave( this.world, chunkcoordintpair.x, chunkcoordintpair.z, null, nbttagcompound, @@ -15708,7 +13732,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec return; } super.write(chunkcoordintpair, nbttagcompound); -@@ -1711,6 +1803,11 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -1765,6 +1857,11 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { return chunkHolder == null ? null : chunkHolder.getAvailableChunkNow(); } // Paper end @@ -15720,7 +13744,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec // Paper start - async io -@@ -1920,6 +2017,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -1974,6 +2071,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { }*/ // Paper end - replaced by distance map this.updateMaps(entityplayer); // Paper - distance maps @@ -15728,7 +13752,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec } -@@ -1928,7 +2026,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -1982,7 +2080,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { // Paper start - per player view distance // there can be potential desync with player's last mapped section and the view distance map, so use the // view distance map here. @@ -15737,7 +13761,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec if (inRange == null) { return Stream.empty(); -@@ -1944,8 +2042,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -1998,8 +2096,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { continue; } EntityPlayer player = (EntityPlayer)temp; @@ -15749,7 +13773,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - chunkcoordintpair.x); int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - chunkcoordintpair.z); -@@ -1960,6 +2059,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -2014,6 +2113,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { continue; } EntityPlayer player = (EntityPlayer)temp; @@ -15757,7 +13781,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec players.add(player); } } -@@ -2038,22 +2138,25 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -2092,22 +2192,25 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { private final void processTrackQueue() { this.world.timings.tracker1.startTiming(); try { @@ -15796,7 +13820,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec } } // Paper end - optimised tracker -@@ -2175,6 +2278,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially +@@ -2229,6 +2332,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially apacket[1] = new PacketPlayOutLightUpdate(chunk.getPos(), this.lightEngine, true); // Paper start - Fix MC-162253 @@ -15804,7 +13828,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec final int lightMask = getLightMask(chunk); int i = 1; for (int x = -1; x <= 1; x++) { -@@ -2199,10 +2303,12 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially +@@ -2253,10 +2357,12 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially apacket[i] = new PacketPlayOutLightUpdate(new ChunkCoordIntPair(chunk.getPos().x + x, chunk.getPos().z + z), lightEngine, updateLightMask, 0, true); } } @@ -15819,7 +13843,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec int j = 1; for (int x = -1; x <= 1; x++) { -@@ -2227,6 +2333,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially +@@ -2281,6 +2387,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially entityplayer.playerConnection.sendPacket(packet); } } @@ -15827,7 +13851,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec // Paper end - Fix MC-162253 entityplayer.a(chunk.getPos(), apacket[0], apacket[1]); -@@ -2302,7 +2409,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially +@@ -2356,7 +2463,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially // Paper start // Replace trackedPlayers Set with a Map. The value is true until the player receives // their first update (which is forced to have absolute coordinates), false afterward. @@ -15836,7 +13860,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec public Set trackedPlayers = trackedPlayerMap.keySet(); public EntityTracker(Entity entity, int i, int j, boolean flag) { -@@ -2403,7 +2510,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially +@@ -2457,7 +2564,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially double vec3d_dy = entityplayer.locY() - this.tracker.locY(); double vec3d_dz = entityplayer.locZ() - this.tracker.locZ(); // Paper end - remove allocation of Vec3D here @@ -15845,7 +13869,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec boolean flag = vec3d_dx >= (double) (-i) && vec3d_dx <= (double) i && vec3d_dz >= (double) (-i) && vec3d_dz <= (double) i && this.tracker.a(entityplayer); // Paper - remove allocation of Vec3D here if (flag) { -@@ -2413,7 +2520,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially +@@ -2467,7 +2574,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(this.tracker.chunkX, this.tracker.chunkZ); PlayerChunk playerchunk = PlayerChunkMap.this.getVisibleChunk(chunkcoordintpair.pair()); @@ -15854,7 +13878,7 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec flag1 = PlayerChunkMap.b(chunkcoordintpair, entityplayer, false) <= PlayerChunkMap.this.viewDistance; } } -@@ -2453,7 +2560,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially +@@ -2507,7 +2614,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially int j = entity.getEntityType().getChunkRange() * 16; j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper @@ -15863,242 +13887,11 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..945d16f57317406bff3cbe20756677ec i = j; } } -diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 3435eb1584546d2963324372ddab1645dcf6327a..9146b60cff0aa06e2f6b6003bfe9e2be9d2f0d56 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -423,7 +423,9 @@ public class PlayerConnection implements PacketListenerPlayIn { - speed *= 2f; // TODO: Get the speed of the vehicle instead of the player - - // Paper start - Prevent moving into unloaded chunks -- if (player.world.paperConfig.preventMovingIntoUnloadedChunks && worldserver.getChunkIfLoadedImmediately((int) Math.floor(packetplayinvehiclemove.getX()) >> 4, (int) Math.floor(packetplayinvehiclemove.getZ()) >> 4) == null) { -+ if (player.world.paperConfig.preventMovingIntoUnloadedChunks // Tuinity - improve this check -+ && (!worldserver.areChunksLoadedForMove(this.player.getBoundingBoxAt(this.player.locX(), this.player.locY(), this.player.locZ()).expand(toX - this.player.locX(), toY - this.player.locY(), toZ - this.player.locZ()))) // Tuinity - improve this check -+ || !worldserver.areChunksLoadedForMove(entity.getBoundingBoxAt(entity.locX(), entity.locY(), entity.locZ()).expand(toX - entity.locX(), toY - entity.locY(), toZ - entity.locZ()))) { // Tuinity - improve this check - this.networkManager.sendPacket(new PacketPlayOutVehicleMove(entity)); - return; - } -@@ -436,12 +438,14 @@ public class PlayerConnection implements PacketListenerPlayIn { - return; - } - -- boolean flag = worldserver.getCubes(entity, entity.getBoundingBox().shrink(0.0625D)); -+ //boolean flag = worldserver.getCubes(entity, entity.getBoundingBox().shrink(0.0625D)); // Tuinity - replace with different checks -+ AxisAlignedBB oldBox = entity.getBoundingBox(); // Tuinity - copy from player movement packet - - d6 = d3 - this.v; - d7 = d4 - this.w - 1.0E-6D; - d8 = d5 - this.x; - entity.move(EnumMoveType.PLAYER, new Vec3D(d6, d7, d8)); -+ boolean didCollide = toX != entity.locX() || toY != entity.locY() || toZ != entity.locZ(); // Tuinity - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be... - double d11 = d7; - - d6 = d3 - entity.locX(); -@@ -455,16 +459,25 @@ public class PlayerConnection implements PacketListenerPlayIn { - boolean flag1 = false; - - if (d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot -- flag1 = true; -+ flag1 = true; // Tuinity - diff on change, this should be moved wrongly - PlayerConnection.LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", entity.getDisplayName().getString(), this.player.getDisplayName().getString(), Math.sqrt(d10)); - } - Location curPos = this.getPlayer().getLocation(); // Spigot - - entity.setLocation(d3, d4, d5, f, f1); - player.setLocation(d3, d4, d5, this.player.yaw, this.player.pitch); // CraftBukkit -- boolean flag2 = worldserver.getCubes(entity, entity.getBoundingBox().shrink(0.0625D)); -- -- if (flag && (flag1 || !flag2)) { -+ //boolean flag2 = worldserver.getCubes(entity, entity.getBoundingBox().shrink(0.0625D)); // Tuinity - replace with different checks -+ -+ // Tuinity start - optimise out extra getCubes -+ boolean teleportBack = flag1; // violating this is always a fail -+ if (!teleportBack) { -+ // note: only call after setLocation, or else getBoundingBox is wrong -+ AxisAlignedBB newBox = entity.getBoundingBox(); -+ if (didCollide || !oldBox.equals(newBox)) { -+ teleportBack = this.hasNewCollision(worldserver, entity, oldBox, newBox); -+ } // else: no collision at all detected, why do we care? -+ } -+ if (teleportBack) { // Tuinity end - optimise out extra getCubes - entity.setLocation(d0, d1, d2, f, f1); - player.setLocation(d0, d1, d2, this.player.yaw, this.player.pitch); // CraftBukkit - this.networkManager.sendPacket(new PacketPlayOutVehicleMove(entity)); -@@ -550,7 +563,32 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - - private boolean a(Entity entity) { -- return entity.world.a(entity.getBoundingBox().g(0.0625D).b(0.0D, -0.55D, 0.0D)).allMatch(BlockBase.BlockData::isAir); -+ // Tuinity start - stop using streams, this is already a known fixed problem in Entity#move -+ AxisAlignedBB box = entity.getBoundingBox().g(0.0625D).b(0.0D, -0.55D, 0.0D); -+ int minX = MathHelper.floor(box.minX); -+ int minY = MathHelper.floor(box.minY); -+ int minZ = MathHelper.floor(box.minZ); -+ int maxX = MathHelper.floor(box.maxX); -+ int maxY = MathHelper.floor(box.maxY); -+ int maxZ = MathHelper.floor(box.maxZ); -+ -+ World world = entity.world; -+ BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(); -+ -+ for (int y = minY; y <= maxY; ++y) { -+ for (int z = minZ; z <= maxZ; ++z) { -+ for (int x = minX; x <= maxX; ++x) { -+ pos.setValues(x, y, z); -+ IBlockData type = world.getTypeIfLoaded(pos); -+ if (type != null && !type.isAir()) { -+ return false; -+ } -+ } -+ } -+ } -+ -+ return true; -+ // Tuinity end - stop using streams, this is already a known fixed problem in Entity#move - } - - @Override -@@ -1072,7 +1110,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - - if (this.teleportPos != null) { -- if (this.e - this.A > 20) { -+ if (false && this.e - this.A > 20) { // Tuinity - this will greatly screw with clients with > 1000ms RTT - this.A = this.e; - this.a(this.teleportPos.x, this.teleportPos.y, this.teleportPos.z, this.player.yaw, this.player.pitch); - } -@@ -1142,7 +1180,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - speed = player.abilities.walkSpeed * 10f; - } - // Paper start - Prevent moving into unloaded chunks -- if (player.world.paperConfig.preventMovingIntoUnloadedChunks && (this.player.locX() != toX || this.player.locZ() != toZ) && worldserver.getChunkIfLoadedImmediately((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4) == null) { // Paper - use getIfLoadedImmediately -+ if (player.world.paperConfig.preventMovingIntoUnloadedChunks && !((WorldServer)this.player.world).areChunksLoadedForMove(this.player.getBoundingBoxAt(this.player.locX(), this.player.locY(), this.player.locZ()).expand(toX - this.player.locX(), toY - this.player.locY(), toZ - this.player.locZ()))) { // Paper - use getIfLoadedImmediately // Tuinity - improve this check - this.internalTeleport(this.player.locX(), this.player.locY(), this.player.locZ(), this.player.yaw, this.player.pitch, Collections.emptySet()); - return; - } -@@ -1159,7 +1197,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - } - -- AxisAlignedBB axisalignedbb = this.player.getBoundingBox(); -+ AxisAlignedBB axisalignedbb = this.player.getBoundingBox(); // Tuinity - diff on change, should be old AABB - - d7 = d4 - this.o; - d8 = d5 - this.p; -@@ -1198,6 +1236,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - - this.player.move(EnumMoveType.PLAYER, new Vec3D(d7, d8, d9)); -+ boolean didCollide = toX != this.player.locX() || toY != this.player.locY() || toZ != this.player.locZ(); // Tuinity - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be... - this.player.setOnGround(packetplayinflying.b()); // CraftBukkit - SPIGOT-5810, SPIGOT-5835: reset by this.player.move - // Paper start - prevent position desync - if (this.teleportPos != null) { -@@ -1217,12 +1256,23 @@ public class PlayerConnection implements PacketListenerPlayIn { - boolean flag1 = false; - - if (!this.player.H() && d11 > org.spigotmc.SpigotConfig.movedWronglyThreshold && !this.player.isSleeping() && !this.player.playerInteractManager.isCreative() && this.player.playerInteractManager.getGameMode() != EnumGamemode.SPECTATOR) { // Spigot -- flag1 = true; -+ flag1 = true; // Tuinity - diff on change, this should be moved wrongly - PlayerConnection.LOGGER.warn("{} moved wrongly!", this.player.getDisplayName().getString()); - } - - this.player.setLocation(d4, d5, d6, f, f1); -- if (!this.player.noclip && !this.player.isSleeping() && (flag1 && worldserver.getCubes(this.player, axisalignedbb) || this.a((IWorldReader) worldserver, axisalignedbb))) { -+ // Tuinity start - optimise out extra getCubes -+ // Original for reference: -+ // boolean teleportBack = flag1 && worldserver.getCubes(this.player, axisalignedbb) || (didCollide && this.a((IWorldReader) worldserver, axisalignedbb)); -+ boolean teleportBack = flag1; // violating this is always a fail -+ if (!this.player.noclip && !this.player.isSleeping() && !teleportBack) { -+ AxisAlignedBB newBox = this.player.getBoundingBox(); -+ if (didCollide || !axisalignedbb.equals(newBox)) { -+ // note: only call after setLocation, or else getBoundingBox is wrong -+ teleportBack = this.hasNewCollision(worldserver, this.player, axisalignedbb, newBox); -+ } // else: no collision at all detected, why do we care? -+ } -+ if (!this.player.noclip && !this.player.isSleeping() && teleportBack) { // Tuinity end - optimise out extra getCubes - this.a(d0, d1, d2, f, f1); - } else { - // CraftBukkit start - fire PlayerMoveEvent -@@ -1309,6 +1359,26 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - } - -+ // Tuinity start - optimise out extra getCubes -+ private boolean hasNewCollision(final WorldServer world, final Entity entity, final AxisAlignedBB oldBox, final AxisAlignedBB newBox) { -+ final List collisions = com.tuinity.tuinity.util.CachedLists.getTempCollisionList(); -+ try { -+ world.getCollisions(entity, newBox, collisions, true); -+ -+ for (int i = 0, len = collisions.size(); i < len; ++i) { -+ final AxisAlignedBB box = collisions.get(i); -+ if (!box.voxelShapeIntersect(oldBox)) { -+ return true; -+ } -+ } -+ -+ return false; -+ } finally { -+ com.tuinity.tuinity.util.CachedLists.returnTempCollisionList(collisions); -+ } -+ } -+ // Tuinity end - optimise out extra getCubes -+ - private boolean a(IWorldReader iworldreader, AxisAlignedBB axisalignedbb) { - Stream stream = iworldreader.d(this.player, this.player.getBoundingBox().shrink(9.999999747378752E-6D), (entity) -> { - return true; -diff --git a/src/main/java/net/minecraft/server/PlayerConnectionUtils.java b/src/main/java/net/minecraft/server/PlayerConnectionUtils.java -index 8c7080777b370f97e1291dfedde5b419290f39cc..8112b01f15c33f50fe5ec9aebf75d8091d440994 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnectionUtils.java -+++ b/src/main/java/net/minecraft/server/PlayerConnectionUtils.java -@@ -13,10 +13,30 @@ public class PlayerConnectionUtils { - ensureMainThread(packet, t0, (IAsyncTaskHandler) worldserver.getMinecraftServer()); - } - -+ // Tuinity start - detailed watchdog information -+ static final java.util.concurrent.ConcurrentLinkedDeque packetProcessing = new java.util.concurrent.ConcurrentLinkedDeque<>(); -+ static final java.util.concurrent.atomic.AtomicLong totalMainThreadPacketsProcessed = new java.util.concurrent.atomic.AtomicLong(); -+ -+ public static long getTotalProcessedPackets() { -+ return totalMainThreadPacketsProcessed.get(); -+ } -+ -+ public static java.util.List getCurrentPacketProcessors() { -+ java.util.List ret = new java.util.ArrayList<>(4); -+ for (PacketListener listener : packetProcessing) { -+ ret.add(listener); -+ } -+ -+ return ret; -+ } -+ // Tuinity end - detailed watchdog information -+ - public static void ensureMainThread(Packet packet, T t0, IAsyncTaskHandler iasynctaskhandler) throws CancelledPacketHandleException { - if (!iasynctaskhandler.isMainThread()) { - Timing timing = MinecraftTimings.getPacketTiming(packet); // Paper - timings - iasynctaskhandler.execute(() -> { -+ packetProcessing.push(t0); // Tuinity - detailed watchdog information -+ try { // Tuinity - detailed watchdog information - if (MinecraftServer.getServer().hasStopped() || (t0 instanceof PlayerConnection && ((PlayerConnection) t0).processedDisconnect)) return; // CraftBukkit, MC-142590 - if (t0.a().isConnected()) { - try (Timing ignored = timing.startTiming()) { // Paper - timings -@@ -40,6 +60,12 @@ public class PlayerConnectionUtils { - } else { - PlayerConnectionUtils.LOGGER.debug("Ignoring packet due to disconnection: " + packet); - } -+ // Tuinity start - detailed watchdog information -+ } finally { -+ totalMainThreadPacketsProcessed.getAndIncrement(); -+ packetProcessing.pop(); -+ } -+ // Tuinity end - detailed watchdog information - - }); - throw CancelledPacketHandleException.INSTANCE; -diff --git a/src/main/java/net/minecraft/server/PlayerInteractManager.java b/src/main/java/net/minecraft/server/PlayerInteractManager.java -index d57784c5dd44cc110b7c863ffff82263178e7d9a..967443a44106563fe71a528703751ff00415f61a 100644 ---- a/src/main/java/net/minecraft/server/PlayerInteractManager.java -+++ b/src/main/java/net/minecraft/server/PlayerInteractManager.java -@@ -22,14 +22,29 @@ public class PlayerInteractManager { +diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java +index 1511cf54fea53577a2808b5d84417eee834db984..e47a743fd3adc62aa47beec722f49eeaded246bc 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java ++++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java +@@ -55,14 +55,29 @@ public class PlayerInteractManager { private EnumGamemode gamemode; private EnumGamemode e; private boolean f; @@ -16131,7 +13924,7 @@ index d57784c5dd44cc110b7c863ffff82263178e7d9a..967443a44106563fe71a528703751ff0 public PlayerInteractManager(WorldServer worldserver) { this.gamemode = EnumGamemode.NOT_SET; this.e = EnumGamemode.NOT_SET; -@@ -85,7 +100,7 @@ public class PlayerInteractManager { +@@ -118,7 +133,7 @@ public class PlayerInteractManager { if (iblockdata == null || iblockdata.isAir()) { // Paper this.j = false; } else { @@ -16140,7 +13933,7 @@ index d57784c5dd44cc110b7c863ffff82263178e7d9a..967443a44106563fe71a528703751ff0 if (f >= 1.0F) { this.j = false; -@@ -105,7 +120,7 @@ public class PlayerInteractManager { +@@ -138,7 +153,7 @@ public class PlayerInteractManager { this.m = -1; this.f = false; } else { @@ -16149,7 +13942,7 @@ index d57784c5dd44cc110b7c863ffff82263178e7d9a..967443a44106563fe71a528703751ff0 } } -@@ -113,6 +128,12 @@ public class PlayerInteractManager { +@@ -146,6 +161,12 @@ public class PlayerInteractManager { private float a(IBlockData iblockdata, BlockPosition blockposition, int i) { int j = this.currentTick - i; @@ -16162,7 +13955,7 @@ index d57784c5dd44cc110b7c863ffff82263178e7d9a..967443a44106563fe71a528703751ff0 float f = iblockdata.getDamage(this.player, this.player.world, blockposition) * (float) (j + 1); int k = (int) (f * 10.0F); -@@ -180,7 +201,7 @@ public class PlayerInteractManager { +@@ -213,7 +234,7 @@ public class PlayerInteractManager { return; } @@ -16171,7 +13964,7 @@ index d57784c5dd44cc110b7c863ffff82263178e7d9a..967443a44106563fe71a528703751ff0 float f = 1.0F; iblockdata = this.world.getType(blockposition); -@@ -233,12 +254,12 @@ public class PlayerInteractManager { +@@ -266,12 +287,12 @@ public class PlayerInteractManager { int j = (int) (f * 10.0F); this.world.a(this.player.getId(), blockposition, j); @@ -16186,7 +13979,7 @@ index d57784c5dd44cc110b7c863ffff82263178e7d9a..967443a44106563fe71a528703751ff0 iblockdata = this.world.getType(blockposition); if (!iblockdata.isAir()) { -@@ -255,12 +276,18 @@ public class PlayerInteractManager { +@@ -288,12 +309,18 @@ public class PlayerInteractManager { this.f = false; this.j = true; this.k = blockposition; @@ -16206,7 +13999,7 @@ index d57784c5dd44cc110b7c863ffff82263178e7d9a..967443a44106563fe71a528703751ff0 } else if (packetplayinblockdig_enumplayerdigtype == PacketPlayInBlockDig.EnumPlayerDigType.ABORT_DESTROY_BLOCK) { this.f = false; if (!Objects.equals(this.h, blockposition) && !BlockPosition.ZERO.equals(this.h)) { -@@ -272,7 +299,7 @@ public class PlayerInteractManager { +@@ -305,7 +332,7 @@ public class PlayerInteractManager { } this.world.a(this.player.getId(), blockposition, -1); @@ -16215,7 +14008,7 @@ index d57784c5dd44cc110b7c863ffff82263178e7d9a..967443a44106563fe71a528703751ff0 } } -@@ -282,7 +309,13 @@ public class PlayerInteractManager { +@@ -315,7 +342,13 @@ public class PlayerInteractManager { public void a(BlockPosition blockposition, PacketPlayInBlockDig.EnumPlayerDigType packetplayinblockdig_enumplayerdigtype, String s) { if (this.breakBlock(blockposition)) { @@ -16229,1448 +14022,10 @@ index d57784c5dd44cc110b7c863ffff82263178e7d9a..967443a44106563fe71a528703751ff0 } else { this.player.playerConnection.sendPacket(new PacketPlayOutBlockChange(this.world, blockposition)); // CraftBukkit - SPIGOT-5196 } -diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java -index 184a0d30f4a1d4a6a07449fdd1375a8582da9332..a12e58668e74f2287ddff5bedc00daf2b0a416c1 100644 ---- a/src/main/java/net/minecraft/server/PlayerList.java -+++ b/src/main/java/net/minecraft/server/PlayerList.java -@@ -96,6 +96,7 @@ public abstract class PlayerList { - abstract public void loadAndSaveFiles(); // Paper - moved from DedicatedPlayerList constructor - - public void a(NetworkManager networkmanager, EntityPlayer entityplayer) { -+ entityplayer.isRealPlayer = true; // Paper // Tuinity - this is a better place to write this that works and isn't overriden by plugins - EntityPlayer prev = pendingPlayers.put(entityplayer.getUniqueID(), entityplayer);// Paper - if (prev != null) { - disconnectPendingPlayer(prev); -@@ -184,7 +185,7 @@ public abstract class PlayerList { - boolean flag1 = gamerules.getBoolean(GameRules.REDUCED_DEBUG_INFO); - - // Spigot - view distance -- playerconnection.sendPacket(new PacketPlayOutLogin(entityplayer.getId(), entityplayer.playerInteractManager.getGameMode(), entityplayer.playerInteractManager.c(), BiomeManager.a(worldserver1.getSeed()), worlddata.isHardcore(), this.server.F(), this.s, worldserver1.getDimensionManager(), worldserver1.getDimensionKey(), this.getMaxPlayers(), worldserver1.getChunkProvider().playerChunkMap.getLoadViewDistance(), flag1, !flag, worldserver1.isDebugWorld(), worldserver1.isFlatWorld())); // Paper - no-tick view distance -+ playerconnection.sendPacket(new PacketPlayOutLogin(entityplayer.getId(), entityplayer.playerInteractManager.getGameMode(), entityplayer.playerInteractManager.c(), BiomeManager.a(worldserver1.getSeed()), worlddata.isHardcore(), this.server.F(), this.s, worldserver1.getDimensionManager(), worldserver1.getDimensionKey(), this.getMaxPlayers(), worldserver1.getChunkProvider().playerChunkMap.playerChunkManager.getLoadDistance(), flag1, !flag, worldserver1.isDebugWorld(), worldserver1.isFlatWorld())); // Paper - no-tick view distance // Tuinity - replace old player chunk management - entityplayer.getBukkitEntity().sendSupportedChannels(); // CraftBukkit - playerconnection.sendPacket(new PacketPlayOutCustomPayload(PacketPlayOutCustomPayload.a, (new PacketDataSerializer(Unpooled.buffer())).a(this.getServer().getServerModName()))); - playerconnection.sendPacket(new PacketPlayOutServerDifficulty(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); -@@ -636,7 +637,7 @@ public abstract class PlayerList { - SocketAddress socketaddress = loginlistener.networkManager.getSocketAddress(); - - EntityPlayer entity = new EntityPlayer(this.server, this.server.getWorldServer(World.OVERWORLD), gameprofile, new PlayerInteractManager(this.server.getWorldServer(World.OVERWORLD))); -- entity.isRealPlayer = true; // Paper -+ // Tuinity - some plugins (namely protocolsupport) bypass this logic completely! So this needs to be moved. - Player player = entity.getBukkitEntity(); - PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.networkManager.getRawAddress()).getAddress()); - -@@ -856,7 +857,7 @@ public abstract class PlayerList { - // CraftBukkit start - WorldData worlddata = worldserver1.getWorldData(); - entityplayer1.playerConnection.sendPacket(new PacketPlayOutRespawn(worldserver1.getDimensionManager(), worldserver1.getDimensionKey(), BiomeManager.a(worldserver1.getSeed()), entityplayer1.playerInteractManager.getGameMode(), entityplayer1.playerInteractManager.c(), worldserver1.isDebugWorld(), worldserver1.isFlatWorld(), flag)); -- entityplayer1.playerConnection.sendPacket(new PacketPlayOutViewDistance(worldserver1.getChunkProvider().playerChunkMap.getLoadViewDistance())); // Spigot // Paper - no-tick view distance -+ entityplayer1.playerConnection.sendPacket(new PacketPlayOutViewDistance(worldserver1.getChunkProvider().playerChunkMap.playerChunkManager.getLoadDistance())); // Spigot // Paper - no-tick view distance // Tuinity - replace old player chunk management - entityplayer1.spawnIn(worldserver1); - entityplayer1.dead = false; - entityplayer1.playerConnection.teleport(new Location(worldserver1.getWorld(), entityplayer1.locX(), entityplayer1.locY(), entityplayer1.locZ(), entityplayer1.yaw, entityplayer1.pitch)); -@@ -1125,7 +1126,7 @@ public abstract class PlayerList { - // Really shouldn't happen... - backingSet = world != null ? world.players.toArray() : players.toArray(); - } else { -- com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet nearbyPlayers = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(MCUtil.fastFloor(d0) >> 4, MCUtil.fastFloor(d2) >> 4); -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet nearbyPlayers = chunkMap.playerChunkManager.broadcastMap.getObjectsInRange(MCUtil.fastFloor(d0) >> 4, MCUtil.fastFloor(d2) >> 4); // Tuinity - replace old player chunk management - if (nearbyPlayers == null) { - return; - } -diff --git a/src/main/java/net/minecraft/server/PortalTravelAgent.java b/src/main/java/net/minecraft/server/PortalTravelAgent.java -index e10995ec30dd9a10d781b3c1709fd2db5a9becdd..77aa805267497f91231d63067d62ad3f10508216 100644 ---- a/src/main/java/net/minecraft/server/PortalTravelAgent.java -+++ b/src/main/java/net/minecraft/server/PortalTravelAgent.java -@@ -22,16 +22,34 @@ public class PortalTravelAgent { - // int i = flag ? 16 : 128; - // CraftBukkit end - -- villageplace.a(this.world, blockposition, i); -- Optional optional = villageplace.b((villageplacetype) -> { -- return villageplacetype == VillagePlaceType.v; -- }, blockposition, i, VillagePlace.Occupancy.ANY).sorted(Comparator.comparingDouble((VillagePlaceRecord villageplacerecord) -> { // CraftBukkit - decompile error -- return villageplacerecord.f().j(blockposition); -- }).thenComparingInt((villageplacerecord) -> { -- return villageplacerecord.f().getY(); -- })).filter((villageplacerecord) -> { -- return this.world.getType(villageplacerecord.f()).b(BlockProperties.E); -- }).findFirst(); -+ // Tuinity start - optimise portals -+ //villageplace.a(this.world, blockposition, i); -+ Optional optional; -+ java.util.List records = new java.util.ArrayList<>(); -+ com.tuinity.tuinity.util.PoiAccess.findClosestPoiDataRecords(villageplace, -+ (VillagePlaceType villageplacetype) -> { -+ return villageplacetype == VillagePlaceType.v; // this should break this entire diff on update if it changes, so TODO check that on diff break -+ }, -+ (BlockPosition pos) -> { -+ IChunkAccess lowest = this.world.getChunkAt(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.EMPTY); -+ if (!lowest.getChunkStatus().isAtLeastStatus(ChunkStatus.FULL)) { -+ // why would we generate the chunk? -+ return false; -+ } -+ return lowest.getType(pos).contains(BlockProperties.E); // this should break this entire diff on update if it changes, so TODO check that on diff break -+ }, blockposition, i, Double.MAX_VALUE, VillagePlace.Occupancy.ANY, true, records); -+ // this gets us most of the way there, but we bias towards lower y values. -+ VillagePlaceRecord lowestYRecord = null; -+ for (VillagePlaceRecord record : records) { -+ if (lowestYRecord == null) { -+ lowestYRecord = record; -+ } else if (lowestYRecord.getPosition().getY() > record.getPosition().getY()) { -+ lowestYRecord = record; -+ } -+ } -+ // now we're done -+ optional = Optional.ofNullable(lowestYRecord); -+ // Tuinity end - optimise portals - - return optional.map((villageplacerecord) -> { - BlockPosition blockposition1 = villageplacerecord.f(); -diff --git a/src/main/java/net/minecraft/server/ProtoChunk.java b/src/main/java/net/minecraft/server/ProtoChunk.java -index 5b0cd414ca1949ab53b289f7159f18da07d21f14..d8b759874545293764690b2ba08a4bd7605c76ae 100644 ---- a/src/main/java/net/minecraft/server/ProtoChunk.java -+++ b/src/main/java/net/minecraft/server/ProtoChunk.java -@@ -48,6 +48,54 @@ public class ProtoChunk implements IChunkAccess { - private volatile boolean u; - final World world; // Paper - Anti-Xray - Add world // Paper - private -> default - -+ // Tuinity start - rewrite light engine -+ protected volatile com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] blockNibbles = com.tuinity.tuinity.chunk.light.StarLightEngine.getFilledEmptyLight(); -+ protected volatile com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] skyNibbles = com.tuinity.tuinity.chunk.light.StarLightEngine.getFilledEmptyLight(); -+ protected volatile boolean[] skyEmptinessMap; -+ protected volatile boolean[] blockEmptinessMap; -+ -+ @Override -+ public com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] getBlockNibbles() { -+ return this.blockNibbles; -+ } -+ -+ @Override -+ public void setBlockNibbles(com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] nibbles) { -+ this.blockNibbles = nibbles; -+ } -+ -+ @Override -+ public com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] getSkyNibbles() { -+ return this.skyNibbles; -+ } -+ -+ @Override -+ public void setSkyNibbles(com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] nibbles) { -+ this.skyNibbles = nibbles; -+ } -+ -+ @Override -+ public boolean[] getSkyEmptinessMap() { -+ return this.skyEmptinessMap; -+ } -+ -+ @Override -+ public void setSkyEmptinessMap(boolean[] emptinessMap) { -+ this.skyEmptinessMap = emptinessMap; -+ } -+ -+ @Override -+ public boolean[] getBlockEmptinessMap() { -+ return this.blockEmptinessMap; -+ } -+ -+ @Override -+ public void setBlockEmptinessMap(boolean[] emptinessMap) { -+ this.blockEmptinessMap = emptinessMap; -+ } -+ -+ // Tuinity end - rewrite light engine -+ - // Paper start - Anti-Xray - Add world - @Deprecated public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter) { this(chunkcoordintpair, chunkconverter, null); } // Notice for updates: Please make sure this constructor isn't used anywhere - public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter, World world) { -@@ -173,20 +221,17 @@ public class ProtoChunk implements IChunkAccess { - ChunkSection chunksection = this.a(j >> 4); - IBlockData iblockdata1 = chunksection.setType(i & 15, j & 15, k & 15, iblockdata); - -- if (this.g.b(ChunkStatus.FEATURES) && iblockdata != iblockdata1 && (iblockdata.b((IBlockAccess) this, blockposition) != iblockdata1.b((IBlockAccess) this, blockposition) || iblockdata.f() != iblockdata1.f() || iblockdata.e() || iblockdata1.e())) { -+ if ((com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? (this.g.b(ChunkStatus.LIGHT) && this.isLit()) : (this.g.b(ChunkStatus.FEATURES))) && iblockdata != iblockdata1 && (iblockdata.b((IBlockAccess) this, blockposition) != iblockdata1.b((IBlockAccess) this, blockposition) || iblockdata.f() != iblockdata1.f() || iblockdata.e() || iblockdata1.e())) { // Tuinity - move block updates to only happen after lighting occurs - LightEngine lightengine = this.e(); - - lightengine.a(blockposition); - } - -- EnumSet enumset = this.getChunkStatus().h(); -+ HeightMap.Type[] enumset = this.getChunkStatus().heightMaps; // Tuinity - reduce iterator creation - EnumSet enumset1 = null; -- Iterator iterator = enumset.iterator(); -- -- HeightMap.Type heightmap_type; -+ // Tuinity - reduce iterator creation - -- while (iterator.hasNext()) { -- heightmap_type = (HeightMap.Type) iterator.next(); -+ for (HeightMap.Type heightmap_type : enumset) { // Tuinity - reduce iterator creation - HeightMap heightmap = (HeightMap) this.f.get(heightmap_type); - - if (heightmap == null) { -@@ -202,10 +247,9 @@ public class ProtoChunk implements IChunkAccess { - HeightMap.a(this, enumset1); - } - -- iterator = enumset.iterator(); -- -- while (iterator.hasNext()) { -- heightmap_type = (HeightMap.Type) iterator.next(); -+ // Tuinity start - reduce iterator creation -+ for (HeightMap.Type heightmap_type : enumset) { -+ // Tuinity end - reduce iterator creation - ((HeightMap) this.f.get(heightmap_type)).a(i & 15, j, k & 15, iblockdata); - } - -diff --git a/src/main/java/net/minecraft/server/ProtoChunkExtension.java b/src/main/java/net/minecraft/server/ProtoChunkExtension.java -index 300cbb8b01d94e7eb0cded0c8e118103c416d4b6..2d7c86c9a323fb7294607ee5685cef8f9ef52794 100644 ---- a/src/main/java/net/minecraft/server/ProtoChunkExtension.java -+++ b/src/main/java/net/minecraft/server/ProtoChunkExtension.java -@@ -8,7 +8,50 @@ import javax.annotation.Nullable; - - public class ProtoChunkExtension extends ProtoChunk { - -- private final Chunk a; -+ private final Chunk a; public final Chunk getWrappedChunk() { return this.a; } // Tuinity - OBFHELPER -+ -+ // Tuinity start - rewrite light engine -+ @Override -+ public com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] getBlockNibbles() { -+ return this.getWrappedChunk().getBlockNibbles(); -+ } -+ -+ @Override -+ public void setBlockNibbles(com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] nibbles) { -+ this.getWrappedChunk().setBlockNibbles(nibbles); -+ } -+ -+ @Override -+ public com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] getSkyNibbles() { -+ return this.getWrappedChunk().getSkyNibbles(); -+ } -+ -+ @Override -+ public void setSkyNibbles(com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] nibbles) { -+ this.getWrappedChunk().setSkyNibbles(nibbles); -+ } -+ -+ @Override -+ public boolean[] getSkyEmptinessMap() { -+ return this.getWrappedChunk().getSkyEmptinessMap(); -+ } -+ -+ @Override -+ public void setSkyEmptinessMap(final boolean[] emptinessMap) { -+ this.getWrappedChunk().setSkyEmptinessMap(emptinessMap); -+ } -+ -+ @Override -+ public boolean[] getBlockEmptinessMap() { -+ return this.getWrappedChunk().getBlockEmptinessMap(); -+ } -+ -+ @Override -+ public void setBlockEmptinessMap(boolean[] emptinessMap) { -+ this.getWrappedChunk().setBlockEmptinessMap(emptinessMap); -+ } -+ -+ // Tuinity end - rewrite light engine - - public ProtoChunkExtension(Chunk chunk) { - super(chunk.getPos(), ChunkConverter.a, chunk.world); // Paper - Anti-Xray - Add parameter -diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java -index 1751fb6934d9242e475c1a44b2a4a1ade6987766..1ffa213a819f9d39488ca3599f77e771de8081a5 100644 ---- a/src/main/java/net/minecraft/server/RegionFile.java -+++ b/src/main/java/net/minecraft/server/RegionFile.java -@@ -5,6 +5,7 @@ import java.io.BufferedInputStream; - import java.io.BufferedOutputStream; - import java.io.ByteArrayInputStream; - import java.io.ByteArrayOutputStream; -+import java.io.DataInput; - import java.io.DataInputStream; - import java.io.DataOutputStream; - import java.io.File; -@@ -29,15 +30,350 @@ public class RegionFile implements AutoCloseable { - private static final Logger LOGGER = LogManager.getLogger(); - private static final ByteBuffer c = ByteBuffer.allocateDirect(1); - private final FileChannel dataFile; -- private final java.nio.file.Path e; -- private final RegionFileCompression f; -+ private final java.nio.file.Path e; private final java.nio.file.Path getContainingDataFolder() { return this.e; } // Tuinity - OBFHELPER -+ private final RegionFileCompression f; private final RegionFileCompression getRegionFileCompression() { return this.f; } // Tuinity - OBFHELPER - private final ByteBuffer g; -- private final IntBuffer h; -- private final IntBuffer i; -+ private final IntBuffer h; private final IntBuffer getOffsets() { return this.h; } // Tuinity - OBFHELPER -+ private final IntBuffer i; private final IntBuffer getTimestamps() { return this.i; } // Tuinity - OBFHELPER - @VisibleForTesting - protected final RegionFileBitSet freeSectors; - public final File file; // Paper - -+ // Tuinity start - try to recover from RegionFile header corruption -+ private static long roundToSectors(long bytes) { -+ long sectors = bytes >>> 12; // 4096 = 2^12 -+ long remainingBytes = bytes & 4095; -+ long sign = -remainingBytes; // sign is 1 if nonzero -+ return sectors + (sign >>> 63); -+ } -+ -+ private static final NBTTagCompound OVERSIZED_COMPOUND = new NBTTagCompound(); -+ -+ private NBTTagCompound attemptRead(long sector, int chunkDataLength, long fileLength) throws IOException { -+ try { -+ if (chunkDataLength < 0) { -+ return null; -+ } -+ -+ long offset = sector * 4096L + 4L; // offset for chunk data -+ -+ if ((offset + chunkDataLength) > fileLength) { -+ return null; -+ } -+ -+ ByteBuffer chunkData = ByteBuffer.allocate(chunkDataLength); -+ if (chunkDataLength != this.dataFile.read(chunkData, offset)) { -+ return null; -+ } -+ -+ ((java.nio.Buffer)chunkData).flip(); -+ -+ byte compressionType = chunkData.get(); -+ if (compressionType < 0) { // compressionType & 128 != 0 -+ // oversized chunk -+ return OVERSIZED_COMPOUND; -+ } -+ -+ RegionFileCompression compression = RegionFileCompression.getByType(compressionType); -+ if (compression == null) { -+ return null; -+ } -+ -+ InputStream input = compression.wrap(new ByteArrayInputStream(chunkData.array(), chunkData.position(), chunkDataLength - chunkData.position())); -+ -+ return NBTCompressedStreamTools.readNBT((java.io.DataInput)new DataInputStream(new BufferedInputStream(input))); -+ } catch (Exception ex) { -+ return null; -+ } -+ } -+ -+ private int getLength(long sector) throws IOException { -+ ByteBuffer length = ByteBuffer.allocate(4); -+ if (4 != this.dataFile.read(length, sector * 4096L)) { -+ return -1; -+ } -+ -+ return length.getInt(0); -+ } -+ -+ private void backupRegionFile() { -+ File backup = new File(this.file.getParent(), this.file.getName() + "." + new java.util.Random().nextLong() + ".backup"); -+ this.backupRegionFile(backup); -+ } -+ -+ private void backupRegionFile(File to) { -+ try { -+ this.dataFile.force(true); -+ MinecraftServer.LOGGER.warn("Backing up regionfile \"" + this.file.getAbsolutePath() + "\" to " + to.getAbsolutePath()); -+ java.nio.file.Files.copy(this.file.toPath(), to.toPath()); -+ MinecraftServer.LOGGER.warn("Backed up the regionfile to " + to.getAbsolutePath()); -+ } catch (IOException ex) { -+ MinecraftServer.LOGGER.error("Failed to backup to " + to.getAbsolutePath(), ex); -+ } -+ } -+ -+ // note: only call for CHUNK regionfiles -+ void recalculateHeader() throws IOException { -+ if (!this.canRecalcHeader) { -+ return; -+ } -+ synchronized (this) { -+ MinecraftServer.LOGGER.warn("Corrupt regionfile header detected! Attempting to re-calculate header offsets for regionfile " + this.file.getAbsolutePath(), new Throwable()); -+ -+ // try to backup file so maybe it could be sent to us for further investigation -+ -+ this.backupRegionFile(); -+ NBTTagCompound[] compounds = new NBTTagCompound[32 * 32]; // only in the regionfile (i.e exclude mojang/aikar oversized data) -+ int[] rawLengths = new int[32 * 32]; // length of chunk data including 4 byte length field, bytes -+ int[] sectorOffsets = new int[32 * 32]; // in sectors -+ boolean[] hasAikarOversized = new boolean[32 * 32]; -+ -+ long fileLength = this.dataFile.size(); -+ long totalSectors = roundToSectors(fileLength); -+ -+ // search the regionfile from start to finish for the most up-to-date chunk data -+ -+ for (long i = 2, maxSector = Math.min((long)(Integer.MAX_VALUE >>> 8), totalSectors); i < maxSector; ++i) { // first two sectors are header, skip -+ int chunkDataLength = this.getLength(i); -+ NBTTagCompound compound = this.attemptRead(i, chunkDataLength, fileLength); -+ if (compound == null || compound == OVERSIZED_COMPOUND) { -+ continue; -+ } -+ -+ ChunkCoordIntPair chunkPos = ChunkRegionLoader.getChunkCoordinate(compound); -+ int location = (chunkPos.x & 31) | ((chunkPos.z & 31) << 5); -+ -+ NBTTagCompound otherCompound = compounds[location]; -+ -+ if (otherCompound != null && ChunkRegionLoader.getLastWorldSaveTime(otherCompound) > ChunkRegionLoader.getLastWorldSaveTime(compound)) { -+ continue; // don't overwrite newer data. -+ } -+ -+ // aikar oversized? -+ File aikarOversizedFile = this.getOversizedFile(chunkPos.x, chunkPos.z); -+ boolean isAikarOversized = false; -+ if (aikarOversizedFile.exists()) { -+ try { -+ NBTTagCompound aikarOversizedCompound = this.getOversizedData(chunkPos.x, chunkPos.z); -+ if (ChunkRegionLoader.getLastWorldSaveTime(compound) == ChunkRegionLoader.getLastWorldSaveTime(aikarOversizedCompound)) { -+ // best we got for an id. hope it's good enough -+ isAikarOversized = true; -+ } -+ } catch (Exception ex) { -+ MinecraftServer.LOGGER.error("Failed to read aikar oversized data for absolute chunk (" + chunkPos.x + "," + chunkPos.z + ") in regionfile " + this.file.getAbsolutePath() + ", oversized data for this chunk will be lost", ex); -+ // fall through, if we can't read aikar oversized we can't risk corrupting chunk data -+ } -+ } -+ -+ hasAikarOversized[location] = isAikarOversized; -+ compounds[location] = compound; -+ rawLengths[location] = chunkDataLength + 4; -+ sectorOffsets[location] = (int)i; -+ -+ int chunkSectorLength = (int)roundToSectors(rawLengths[location]); -+ i += chunkSectorLength; -+ --i; // gets incremented next iteration -+ } -+ -+ // forge style oversized data is already handled by the local search, and aikar data we just hope -+ // we get it right as aikar data has no identifiers we could use to try and find its corresponding -+ // local data compound -+ -+ java.nio.file.Path containingFolder = this.getContainingDataFolder(); -+ File[] regionFiles = containingFolder.toFile().listFiles(); -+ boolean[] oversized = new boolean[32 * 32]; -+ RegionFileCompression[] oversizedCompressionTypes = new RegionFileCompression[32 * 32]; -+ -+ if (regionFiles != null) { -+ ChunkCoordIntPair ourLowerLeftPosition = RegionFileCache.getRegionFileCoordinates(this.file); -+ -+ if (ourLowerLeftPosition == null) { -+ MinecraftServer.LOGGER.fatal("Unable to get chunk location of regionfile " + this.file.getAbsolutePath() + ", cannot recover oversized chunks"); -+ } else { -+ int lowerXBound = ourLowerLeftPosition.x; // inclusive -+ int lowerZBound = ourLowerLeftPosition.z; // inclusive -+ int upperXBound = lowerXBound + 32 - 1; // inclusive -+ int upperZBound = lowerZBound + 32 - 1; // inclusive -+ -+ // read mojang oversized data -+ for (File regionFile : regionFiles) { -+ ChunkCoordIntPair oversizedCoords = getOversizedChunkPair(regionFile); -+ if (oversizedCoords == null) { -+ continue; -+ } -+ -+ if ((oversizedCoords.x < lowerXBound || oversizedCoords.x > upperXBound) || (oversizedCoords.z < lowerZBound || oversizedCoords.z > upperZBound)) { -+ continue; // not in our regionfile -+ } -+ -+ // ensure oversized data is valid & is newer than data in the regionfile -+ -+ int location = (oversizedCoords.x & 31) | ((oversizedCoords.z & 31) << 5); -+ -+ byte[] chunkData; -+ try { -+ chunkData = Files.readAllBytes(regionFile.toPath()); -+ } catch (Exception ex) { -+ MinecraftServer.LOGGER.error("Failed to read oversized chunk data in file " + regionFile.getAbsolutePath() + ", data will be lost", ex); -+ continue; -+ } -+ -+ NBTTagCompound compound = null; -+ -+ // We do not know the compression type, as it's stored in the regionfile. So we need to try all of them -+ RegionFileCompression compression = null; -+ for (RegionFileCompression compressionType : RegionFileCompression.getCompressionTypes().values()) { -+ try { -+ DataInputStream in = new DataInputStream(new BufferedInputStream(compressionType.wrap(new ByteArrayInputStream(chunkData)))); // typical java -+ compound = NBTCompressedStreamTools.readNBT((DataInput)in); -+ compression = compressionType; -+ break; // reaches here iff readNBT does not throw -+ } catch (Exception ex) { -+ continue; -+ } -+ } -+ -+ if (compound == null) { -+ MinecraftServer.LOGGER.error("Failed to read oversized chunk data in file " + regionFile.getAbsolutePath() + ", it's corrupt. Its data will be lost"); -+ continue; -+ } -+ -+ if (compounds[location] == null || ChunkRegionLoader.getLastWorldSaveTime(compound) > ChunkRegionLoader.getLastWorldSaveTime(compounds[location])) { -+ oversized[location] = true; -+ oversizedCompressionTypes[location] = compression; -+ } -+ } -+ } -+ } -+ -+ // now we need to calculate a new offset header -+ -+ int[] calculatedOffsets = new int[32 * 32]; -+ RegionFileBitSet newSectorAllocations = new RegionFileBitSet(); -+ newSectorAllocations.allocate(0, 2); // make space for header -+ -+ // allocate sectors for normal chunks -+ -+ for (int chunkX = 0; chunkX < 32; ++chunkX) { -+ for (int chunkZ = 0; chunkZ < 32; ++chunkZ) { -+ int location = chunkX | (chunkZ << 5); -+ -+ if (oversized[location]) { -+ continue; -+ } -+ -+ int rawLength = rawLengths[location]; // bytes -+ int sectorOffset = sectorOffsets[location]; // sectors -+ int sectorLength = (int)roundToSectors(rawLength); -+ -+ if (newSectorAllocations.tryAllocate(sectorOffset, sectorLength)) { -+ calculatedOffsets[location] = sectorOffset << 8 | (sectorLength > 255 ? 255 : sectorLength); // support forge style oversized -+ } else { -+ MinecraftServer.LOGGER.error("Failed to allocate space for local chunk (overlapping data??) at (" + chunkX + "," + chunkZ + ") in regionfile " + this.file.getAbsolutePath() + ", chunk will be regenerated"); -+ } -+ } -+ } -+ -+ // allocate sectors for oversized chunks -+ -+ for (int chunkX = 0; chunkX < 32; ++chunkX) { -+ for (int chunkZ = 0; chunkZ < 32; ++chunkZ) { -+ int location = chunkX | (chunkZ << 5); -+ -+ if (!oversized[location]) { -+ continue; -+ } -+ -+ int sectorOffset = newSectorAllocations.allocateNewSpace(1); -+ int sectorLength = 1; -+ -+ try { -+ this.dataFile.write(this.getOversizedChunkHolderData(oversizedCompressionTypes[location]), sectorOffset * 4096); -+ // only allocate in the new offsets if the write succeeds -+ calculatedOffsets[location] = sectorOffset << 8 | (sectorLength > 255 ? 255 : sectorLength); // support forge style oversized -+ } catch (IOException ex) { -+ newSectorAllocations.free(sectorOffset, sectorLength); -+ MinecraftServer.LOGGER.error("Failed to write new oversized chunk data holder, local chunk at (" + chunkX + "," + chunkZ + ") in regionfile " + this.file.getAbsolutePath() + " will be regenerated"); -+ } -+ } -+ } -+ -+ // rewrite aikar oversized data -+ -+ this.oversizedCount = 0; -+ for (int chunkX = 0; chunkX < 32; ++chunkX) { -+ for (int chunkZ = 0; chunkZ < 32; ++chunkZ) { -+ int location = chunkX | (chunkZ << 5); -+ int isAikarOversized = hasAikarOversized[location] ? 1 : 0; -+ -+ this.oversizedCount += isAikarOversized; -+ this.oversized[location] = (byte)isAikarOversized; -+ } -+ } -+ -+ if (this.oversizedCount > 0) { -+ try { -+ this.writeOversizedMeta(); -+ } catch (Exception ex) { -+ MinecraftServer.LOGGER.error("Failed to write aikar oversized chunk meta, all aikar style oversized chunk data will be lost for regionfile " + this.file.getAbsolutePath(), ex); -+ this.getOversizedMetaFile().delete(); -+ } -+ } else { -+ this.getOversizedMetaFile().delete(); -+ } -+ -+ this.freeSectors.copyFrom(newSectorAllocations); -+ -+ // before we overwrite the old sectors, print a summary of the chunks that got changed. -+ -+ MinecraftServer.LOGGER.info("Starting summary of changes for regionfile " + this.file.getAbsolutePath()); -+ -+ for (int chunkX = 0; chunkX < 32; ++chunkX) { -+ for (int chunkZ = 0; chunkZ < 32; ++chunkZ) { -+ int location = chunkX | (chunkZ << 5); -+ -+ int oldOffset = this.getOffsets().get(location); -+ int newOffset = calculatedOffsets[location]; -+ -+ if (oldOffset == newOffset) { -+ continue; -+ } -+ -+ this.getOffsets().put(location, newOffset); // overwrite incorrect offset -+ -+ if (oldOffset == 0) { -+ // found lost data -+ MinecraftServer.LOGGER.info("Found missing data for local chunk (" + chunkX + "," + chunkZ + ") in regionfile " + this.file.getAbsolutePath()); -+ } else if (newOffset == 0) { -+ MinecraftServer.LOGGER.warn("Data for local chunk (" + chunkX + "," + chunkZ + ") could not be recovered in regionfile " + this.file.getAbsolutePath() + ", it will be regenerated"); -+ } else { -+ MinecraftServer.LOGGER.info("Local chunk (" + chunkX + "," + chunkZ + ") changed to point to newer data or correct chunk in regionfile " + this.file.getAbsolutePath()); -+ } -+ } -+ } -+ -+ MinecraftServer.LOGGER.info("End of change summary for regionfile " + this.file.getAbsolutePath()); -+ -+ // simply destroy the timestamp header, it's not used -+ -+ for (int i = 0; i < 32 * 32; ++i) { -+ this.getTimestamps().put(i, calculatedOffsets[i] != 0 ? (int)System.currentTimeMillis() : 0); // write a valid timestamp for valid chunks, I do not want to find out whatever dumb program actually checks this -+ } -+ -+ // write new header -+ try { -+ this.flushHeader(); -+ this.dataFile.force(true); // try to ensure it goes through... -+ MinecraftServer.LOGGER.info("Successfully wrote new header to disk for regionfile " + this.file.getAbsolutePath()); -+ } catch (IOException ex) { -+ MinecraftServer.LOGGER.fatal("Failed to write new header to disk for regionfile " + this.file.getAbsolutePath(), ex); -+ } -+ } -+ } -+ -+ final boolean canRecalcHeader; // final forces compile fail on new constructor -+ // Tuinity end -+ - public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper - - // Paper start - Cache chunk status -@@ -65,11 +401,22 @@ public class RegionFile implements AutoCloseable { - // Paper end - - public RegionFile(File file, File file1, boolean flag) throws IOException { -+ // Tuinity start - add can recalc flag - this(file.toPath(), file1.toPath(), RegionFileCompression.b, flag); - } -+ public RegionFile(File file, File file1, boolean flag, boolean canRecalcHeader) throws IOException { -+ this(file.toPath(), file1.toPath(), RegionFileCompression.b, flag, canRecalcHeader); -+ // Tuinity end - add can recalc flag -+ } - - public RegionFile(java.nio.file.Path java_nio_file_path, java.nio.file.Path java_nio_file_path1, RegionFileCompression regionfilecompression, boolean flag) throws IOException { -+ // Tuinity start - add can recalc flag -+ this(java_nio_file_path, java_nio_file_path1, regionfilecompression, flag, false); -+ } -+ public RegionFile(java.nio.file.Path java_nio_file_path, java.nio.file.Path java_nio_file_path1, RegionFileCompression regionfilecompression, boolean flag, boolean canRecalcHeader) throws IOException { - this.g = ByteBuffer.allocateDirect(8192); -+ this.canRecalcHeader = canRecalcHeader; -+ // Tuinity end - add can recalc flag - this.file = java_nio_file_path.toFile(); // Paper - initOversizedState(); // Paper - this.freeSectors = new RegionFileBitSet(); -@@ -97,14 +444,16 @@ public class RegionFile implements AutoCloseable { - RegionFile.LOGGER.warn("Region file {} has truncated header: {}", java_nio_file_path, i); - } - -- long j = Files.size(java_nio_file_path); -+ final long j = Files.size(java_nio_file_path); final long regionFileSize = j; - -+ boolean needsHeaderRecalc = false; // Tuinity - recalculate header on header corruption -+ boolean hasBackedUp = false; // Tuinity - recalculate header on header corruption - for (int k = 0; k < 1024; ++k) { -- int l = this.h.get(k); -+ int l = this.h.get(k); final int headerLocation = k; // Tuinity - we expect this to be the header location - - if (l != 0) { -- int i1 = b(l); -- int j1 = a(l); -+ final int i1 = b(l); final int offset = i1; // Tuinity - we expect this to be offset in file in sectors -+ int j1 = a(l); final int sectorLength; // Tuinity - diff on change, we expect this to be sector length of region - watch out for reassignments - // Spigot start - if (j1 == 255) { - // We're maxed out, so we need to read the proper length from the section -@@ -112,33 +461,105 @@ public class RegionFile implements AutoCloseable { - this.dataFile.read(realLen, i1 * 4096); - j1 = (realLen.getInt(0) + 4) / 4096 + 1; - } -+ sectorLength = j1; // Tuinity - diff on change, we expect this to be sector length of region - // Spigot end - - if (i1 < 2) { - RegionFile.LOGGER.warn("Region file {} has invalid sector at index: {}; sector {} overlaps with header", java_nio_file_path, k, i1); -- this.h.put(k, 0); -- } else if (j1 == 0) { -+ //this.h.put(k, 0); // Tuinity - we catch this, but need it in the header for the summary change -+ } else if (j1 <= 0) { // Tuinity - <= 0, not == - RegionFile.LOGGER.warn("Region file {} has an invalid sector at index: {}; size has to be > 0", java_nio_file_path, k); -- this.h.put(k, 0); -+ //this.h.put(k, 0); // Tuinity - we catch this, but need it in the header for the summary change - } else if ((long) i1 * 4096L > j) { - RegionFile.LOGGER.warn("Region file {} has an invalid sector at index: {}; sector {} is out of bounds", java_nio_file_path, k, i1); -- this.h.put(k, 0); -+ //this.h.put(k, 0); // Tuinity - we catch this, but need it in the header for the summary change - } else { -- this.freeSectors.a(i1, j1); -+ //this.freeSectors.a(i1, j1); // Tuinity - move this down so we can check if it fails to allocate -+ } -+ // Tuinity start - recalculate header on header corruption -+ if (offset < 2 || sectorLength <= 0 || ((long)offset * 4096L) > regionFileSize) { -+ if (canRecalcHeader) { -+ MinecraftServer.LOGGER.error("Detected invalid header for regionfile " + this.file.getAbsolutePath() + "! Recalculating header..."); -+ needsHeaderRecalc = true; -+ break; -+ } else { -+ // location = chunkX | (chunkZ << 5); -+ MinecraftServer.LOGGER.fatal("Detected invalid header for regionfile " + this.file.getAbsolutePath() + -+ "! Cannot recalculate, removing local chunk (" + (headerLocation & 31) + "," + (headerLocation >>> 5) + ") from header"); -+ if (!hasBackedUp) { -+ hasBackedUp = true; -+ this.backupRegionFile(); -+ } -+ this.getTimestamps().put(headerLocation, 0); // be consistent, delete the timestamp too -+ this.getOffsets().put(headerLocation, 0); // delete the entry from header -+ continue; -+ } -+ } -+ boolean failedToAllocate = !this.freeSectors.tryAllocate(offset, sectorLength); -+ if (failedToAllocate) { -+ MinecraftServer.LOGGER.error("Overlapping allocation by local chunk (" + (headerLocation & 31) + "," + (headerLocation >>> 5) + ") in regionfile " + this.file.getAbsolutePath()); - } -+ if (failedToAllocate & !canRecalcHeader) { -+ // location = chunkX | (chunkZ << 5); -+ MinecraftServer.LOGGER.fatal("Detected invalid header for regionfile " + this.file.getAbsolutePath() + -+ "! Cannot recalculate, removing local chunk (" + (headerLocation & 31) + "," + (headerLocation >>> 5) + ") from header"); -+ if (!hasBackedUp) { -+ hasBackedUp = true; -+ this.backupRegionFile(); -+ } -+ this.getTimestamps().put(headerLocation, 0); // be consistent, delete the timestamp too -+ this.getOffsets().put(headerLocation, 0); // delete the entry from header -+ continue; -+ } -+ needsHeaderRecalc |= failedToAllocate; -+ // Tuinity end - recalculate header on header corruption - } - } -+ -+ // Tuinity start - recalculate header on header corruption -+ // we move the recalc here so comparison to old header is correct when logging to console -+ if (needsHeaderRecalc) { // true if header gave us overlapping allocations or had other issues -+ MinecraftServer.LOGGER.error("Recalculating regionfile " + this.file.getAbsolutePath() + ", header gave erroneous offsets & locations"); -+ this.recalculateHeader(); -+ } -+ // Tuinity end - } - - } - } - -+ private final java.nio.file.Path getOversizedChunkPath(ChunkCoordIntPair chunkcoordintpair) { return this.e(chunkcoordintpair); } // Tuinity - OBFHELPER - private java.nio.file.Path e(ChunkCoordIntPair chunkcoordintpair) { -- String s = "c." + chunkcoordintpair.x + "." + chunkcoordintpair.z + ".mcc"; -+ String s = "c." + chunkcoordintpair.x + "." + chunkcoordintpair.z + ".mcc"; // Tuinity - diff on change - - return this.e.resolve(s); - } - -+ // Tuinity start -+ private static ChunkCoordIntPair getOversizedChunkPair(File file) { -+ String fileName = file.getName(); -+ -+ if (!fileName.startsWith("c.") || !fileName.endsWith(".mcc")) { -+ return null; -+ } -+ -+ String[] split = fileName.split("\\."); -+ -+ if (split.length != 4) { -+ return null; -+ } -+ -+ try { -+ int x = Integer.parseInt(split[1]); -+ int z = Integer.parseInt(split[2]); -+ -+ return new ChunkCoordIntPair(x, z); -+ } catch (NumberFormatException ex) { -+ return null; -+ } -+ } -+ // Tuinity end -+ - @Nullable public synchronized DataInputStream getReadStream(ChunkCoordIntPair chunkCoordIntPair) throws IOException { return a(chunkCoordIntPair);} // Paper - OBFHELPER - @Nullable - public synchronized DataInputStream a(ChunkCoordIntPair chunkcoordintpair) throws IOException { -@@ -163,6 +584,12 @@ public class RegionFile implements AutoCloseable { - ((java.nio.Buffer) bytebuffer).flip(); - if (bytebuffer.remaining() < 5) { - RegionFile.LOGGER.error("Chunk {} header is truncated: expected {} but read {}", chunkcoordintpair, l, bytebuffer.remaining()); -+ // Tuinity start - recalculate header on regionfile corruption -+ if (this.canRecalcHeader) { -+ this.recalculateHeader(); -+ return this.getReadStream(chunkcoordintpair); -+ } -+ // Tuinity end - return null; - } else { - int i1 = bytebuffer.getInt(); -@@ -170,6 +597,12 @@ public class RegionFile implements AutoCloseable { - - if (i1 == 0) { - RegionFile.LOGGER.warn("Chunk {} is allocated, but stream is missing", chunkcoordintpair); -+ // Tuinity start - recalculate header on regionfile corruption -+ if (this.canRecalcHeader) { -+ this.recalculateHeader(); -+ return this.getReadStream(chunkcoordintpair); -+ } -+ // Tuinity end - recalculate header on regionfile corruption - return null; - } else { - int j1 = i1 - 1; -@@ -177,17 +610,49 @@ public class RegionFile implements AutoCloseable { - if (a(b0)) { - if (j1 != 0) { - RegionFile.LOGGER.warn("Chunk has both internal and external streams"); -+ // Tuinity start - recalculate header on regionfile corruption -+ if (this.canRecalcHeader) { -+ this.recalculateHeader(); -+ return this.getReadStream(chunkcoordintpair); -+ } -+ // Tuinity end - recalculate header on regionfile corruption - } - -- return this.a(chunkcoordintpair, b(b0)); -+ // Tuinity start - recalculate header on regionfile corruption -+ DataInputStream ret = this.a(chunkcoordintpair, b(b0)); -+ if (ret == null && this.canRecalcHeader) { -+ this.recalculateHeader(); -+ return this.getReadStream(chunkcoordintpair); -+ } -+ return ret; -+ // Tuinity end - recalculate header on regionfile corruption - } else if (j1 > bytebuffer.remaining()) { - RegionFile.LOGGER.error("Chunk {} stream is truncated: expected {} but read {}", chunkcoordintpair, j1, bytebuffer.remaining()); -+ // Tuinity start - recalculate header on regionfile corruption -+ if (this.canRecalcHeader) { -+ this.recalculateHeader(); -+ return this.getReadStream(chunkcoordintpair); -+ } -+ // Tuinity end - return null; - } else if (j1 < 0) { - RegionFile.LOGGER.error("Declared size {} of chunk {} is negative", i1, chunkcoordintpair); -+ // Tuinity start - recalculate header on regionfile corruption -+ if (this.canRecalcHeader) { -+ this.recalculateHeader(); -+ return this.getReadStream(chunkcoordintpair); -+ } -+ // Tuinity end - recalculate header on regionfile corruption - return null; - } else { -- return this.a(chunkcoordintpair, b0, a(bytebuffer, j1)); -+ // Tuinity start - recalculate header on regionfile corruption -+ DataInputStream ret = this.a(chunkcoordintpair, b0, a(bytebuffer, j1)); -+ if (ret == null && this.canRecalcHeader) { -+ this.recalculateHeader(); -+ return this.getReadStream(chunkcoordintpair); -+ } -+ return ret; -+ // Tuinity end - recalculate header on regionfile corruption - } - } - } -@@ -347,10 +812,15 @@ public class RegionFile implements AutoCloseable { - } - - private ByteBuffer b() { -+ // Tuinity start - add compressionType param -+ return this.getOversizedChunkHolderData(this.getRegionFileCompression()); -+ } -+ private ByteBuffer getOversizedChunkHolderData(RegionFileCompression compressionType) { -+ // Tuinity end - ByteBuffer bytebuffer = ByteBuffer.allocate(5); - - bytebuffer.putInt(1); -- bytebuffer.put((byte) (this.f.a() | 128)); -+ bytebuffer.put((byte) (compressionType.compressionTypeId() | 128)); // Tuinity - replace with compressionType - ((java.nio.Buffer) bytebuffer).flip(); - return bytebuffer; - } -@@ -387,6 +857,7 @@ public class RegionFile implements AutoCloseable { - }; - } - -+ private final void flushHeader() throws IOException { this.b(); } // Tuinity - OBFHELPER - private void c() throws IOException { - ((java.nio.Buffer) this.g).position(0); - this.dataFile.write(this.g, 0L); -diff --git a/src/main/java/net/minecraft/server/RegionFileBitSet.java b/src/main/java/net/minecraft/server/RegionFileBitSet.java -index 1ebdf73cc927405bc536dc74a5118d2a086db0e5..cfa3ecb031b59ec677f016ecdea92d16436fb511 100644 ---- a/src/main/java/net/minecraft/server/RegionFileBitSet.java -+++ b/src/main/java/net/minecraft/server/RegionFileBitSet.java -@@ -4,18 +4,42 @@ import java.util.BitSet; - - public class RegionFileBitSet { - -- private final BitSet a = new BitSet(); -+ private final BitSet a = new BitSet(); private final BitSet getBitset() { return this.a; } // Tuinity - OBFHELPER - - public RegionFileBitSet() {} - -+ public final void allocate(int from, int length) { this.a(from, length); } // Tuinity - OBFHELPER - public void a(int i, int j) { - this.a.set(i, i + j); - } - -+ public final void free(int from, int length) { this.b(from, length); } // Tuinity - OBFHELPER - public void b(int i, int j) { - this.a.clear(i, i + j); - } - -+ // Tuinity start -+ public final void copyFrom(RegionFileBitSet other) { -+ BitSet thisBitset = this.getBitset(); -+ BitSet otherBitset = other.getBitset(); -+ -+ for (int i = 0; i < Math.max(thisBitset.size(), otherBitset.size()); ++i) { -+ thisBitset.set(i, otherBitset.get(i)); -+ } -+ } -+ -+ public final boolean tryAllocate(int from, int length) { -+ BitSet bitset = this.getBitset(); -+ int firstSet = bitset.nextSetBit(from); -+ if (firstSet > 0 && firstSet < (from + length)) { -+ return false; -+ } -+ bitset.set(from, from + length); -+ return true; -+ } -+ // Tuinity end -+ -+ public final int allocateNewSpace(final int requiredLength) { return this.a(requiredLength); } // Tuinity - OBFHELPER - public int a(int i) { - int j = 0; - -diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java -index d64f7ad925e5f40740a58ceee0845ac2db5419f2..8b341c14e7082fc96a464f2386a3dedea31ec59c 100644 ---- a/src/main/java/net/minecraft/server/RegionFileCache.java -+++ b/src/main/java/net/minecraft/server/RegionFileCache.java -@@ -15,12 +15,43 @@ public class RegionFileCache implements AutoCloseable { // Paper - no final - public final Long2ObjectLinkedOpenHashMap cache = new Long2ObjectLinkedOpenHashMap(); - private final File b; - private final boolean c; -+ private final boolean isChunkData; // Tuinity - - RegionFileCache(File file, boolean flag) { -+ // Tuinity start - add isChunkData param -+ this(file, flag, false); -+ } -+ RegionFileCache(File file, boolean flag, boolean isChunkData) { -+ this.isChunkData = isChunkData; -+ // Tuinity end - add isChunkData param - this.b = file; - this.c = flag; - } - -+ // Tuinity start -+ public static ChunkCoordIntPair getRegionFileCoordinates(File file) { -+ String fileName = file.getName(); -+ if (!fileName.startsWith("r.") || !fileName.endsWith(".mca")) { -+ return null; -+ } -+ -+ String[] split = fileName.split("\\."); -+ -+ if (split.length != 4) { -+ return null; -+ } -+ -+ try { -+ int x = Integer.parseInt(split[1]); -+ int z = Integer.parseInt(split[2]); -+ -+ return new ChunkCoordIntPair(x << 5, z << 5); -+ } catch (NumberFormatException ex) { -+ return null; -+ } -+ } -+ // Tuinity end -+ - - // Paper start - public synchronized RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) { // Paper - synchronize for async io -@@ -54,9 +85,9 @@ public class RegionFileCache implements AutoCloseable { // Paper - no final - this.b.mkdirs(); - } - -- File file = new File(this.b, "r." + chunkcoordintpair.getRegionX() + "." + chunkcoordintpair.getRegionZ() + ".mca"); -+ File file = new File(this.b, "r." + chunkcoordintpair.getRegionX() + "." + chunkcoordintpair.getRegionZ() + ".mca"); // Tuinity - diff on change - if (existingOnly && !file.exists()) return null; // CraftBukkit -- RegionFile regionfile1 = new RegionFile(file, this.b, this.c); -+ RegionFile regionfile1 = new RegionFile(file, this.b, this.c, this.isChunkData); // Tuinity - allow for chunk regionfiles to regen header - - this.cache.putAndMoveToFirst(i, regionfile1); - // Paper start -@@ -145,6 +176,13 @@ public class RegionFileCache implements AutoCloseable { // Paper - no final - return null; - } - // CraftBukkit end -+ // Tuinity start - Add regionfile parameter -+ return this.readFromRegionFile(regionfile, chunkcoordintpair); -+ } -+ private NBTTagCompound readFromRegionFile(RegionFile regionfile, ChunkCoordIntPair chunkcoordintpair) throws IOException { -+ // We add the regionfile parameter to avoid the potential deadlock (on fileLock) if we went back to obtain a regionfile -+ // if we decide to re-read -+ // Tuinity end - try { // Paper - DataInputStream datainputstream = regionfile.a(chunkcoordintpair); - // Paper start -@@ -160,6 +198,17 @@ public class RegionFileCache implements AutoCloseable { // Paper - no final - try { - if (datainputstream != null) { - nbttagcompound = NBTCompressedStreamTools.a((DataInput) datainputstream); -+ // Tuinity start - recover from corrupt regionfile header -+ if (this.isChunkData) { -+ ChunkCoordIntPair chunkPos = ChunkRegionLoader.getChunkCoordinate(nbttagcompound); -+ if (!chunkPos.equals(chunkcoordintpair)) { -+ MinecraftServer.LOGGER.error("Attempting to read chunk data at " + chunkcoordintpair.toString() + " but got chunk data for " + chunkPos.toString() + " instead! Attempting regionfile recalculation for regionfile " + regionfile.file.getAbsolutePath()); -+ regionfile.recalculateHeader(); -+ regionfile.fileLock.lock(); // otherwise we will unlock twice and only lock once. -+ return this.readFromRegionFile(regionfile, chunkcoordintpair); -+ } -+ } -+ // Tuinity end - recover from corrupt regionfile header - return nbttagcompound; - } - -diff --git a/src/main/java/net/minecraft/server/RegionFileCompression.java b/src/main/java/net/minecraft/server/RegionFileCompression.java -index 3382d678e68e559b8d3cb9dced4fce24206cd38f..3b7894256dc8daa81be35f845cb5f8de02d7cb00 100644 ---- a/src/main/java/net/minecraft/server/RegionFileCompression.java -+++ b/src/main/java/net/minecraft/server/RegionFileCompression.java -@@ -13,7 +13,7 @@ import javax.annotation.Nullable; - - public class RegionFileCompression { - -- private static final Int2ObjectMap d = new Int2ObjectOpenHashMap(); -+ private static final Int2ObjectMap d = new Int2ObjectOpenHashMap(); static final Int2ObjectMap getCompressionTypes() { return RegionFileCompression.d; } // Tuinity - OBFHELPER - public static final RegionFileCompression a = a(new RegionFileCompression(1, GZIPInputStream::new, GZIPOutputStream::new)); - public static final RegionFileCompression b = a(new RegionFileCompression(2, InflaterInputStream::new, DeflaterOutputStream::new)); - public static final RegionFileCompression c = a(new RegionFileCompression(3, (inputstream) -> { -@@ -36,8 +36,8 @@ public class RegionFileCompression { - return regionfilecompression; - } - -- @Nullable -- public static RegionFileCompression a(int i) { -+ @Nullable public static RegionFileCompression getByType(int type) { return RegionFileCompression.a(type); } // Tuinity - OBFHELPER -+ @Nullable public static RegionFileCompression a(int i) { // Tuinity - OBFHELPER - return (RegionFileCompression) RegionFileCompression.d.get(i); - } - -@@ -45,6 +45,7 @@ public class RegionFileCompression { - return RegionFileCompression.d.containsKey(i); - } - -+ public final int compressionTypeId() { return this.a(); } // Tuinity - OBFHELPER - public int a() { - return this.e; - } -@@ -53,6 +54,7 @@ public class RegionFileCompression { - return (OutputStream) this.g.wrap(outputstream); - } - -+ public final InputStream wrap(InputStream inputstream) throws IOException { return this.a(inputstream); } // Tuinity - OBFHELPER - public InputStream a(InputStream inputstream) throws IOException { - return (InputStream) this.f.wrap(inputstream); - } -diff --git a/src/main/java/net/minecraft/server/RegionFileSection.java b/src/main/java/net/minecraft/server/RegionFileSection.java -index 04256a95108b8182e8f808e856e0d2b62165e242..d1ea47654db190e7cb7fa4ec1ac002f64277cb47 100644 ---- a/src/main/java/net/minecraft/server/RegionFileSection.java -+++ b/src/main/java/net/minecraft/server/RegionFileSection.java -@@ -25,8 +25,8 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab - - private static final Logger LOGGER = LogManager.getLogger(); - // Paper - nuke IOWorker -- private final Long2ObjectMap> c = new Long2ObjectOpenHashMap(); -- protected final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet(); // Paper - private -> protected -+ private final Long2ObjectMap> c = new Long2ObjectOpenHashMap(); protected final Long2ObjectMap> getDataBySection() { return this.c; } // Tuinity - OBFHELPER -+ protected final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet(); protected final LongLinkedOpenHashSet getDirtySections() { return this.d; } // Paper - private -> protected // Tuinity - OBFHELPER - private final Function> e; - private final Function f; - private final DataFixer g; -@@ -50,11 +50,46 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab - - } - -- @Nullable -- protected Optional c(long i) { -+ // Tuinity start - actually unload POI data -+ public void unloadData(long coordinate) { -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(coordinate); -+ this.writeDirtyData(chunkPos); -+ -+ Long2ObjectMap> data = this.getDataBySection(); -+ int before = data.size(); -+ -+ for (int section = 0; section < 16; ++section) { -+ data.remove(SectionPosition.asLong(chunkPos.x, section, chunkPos.z)); -+ } -+ -+ if (before != data.size()) { -+ this.onUnload(coordinate); -+ } -+ } -+ -+ protected void onUnload(long coordinate) {} -+ -+ public boolean isEmpty(long coordinate) { -+ Long2ObjectMap> data = this.getDataBySection(); -+ int x = MCUtil.getCoordinateX(coordinate); -+ int z = MCUtil.getCoordinateZ(coordinate); -+ for (int section = 0; section < 16; ++section) { -+ Optional optional = data.get(SectionPosition.asLong(x, section, z)); -+ if (optional != null && optional.orElse(null) != null) { -+ return false; -+ } -+ } -+ -+ return true; -+ } -+ // Tuinity end - actually unload POI data -+ -+ @Nullable public final Optional getIfLoaded(long value) { return this.c(value); } // Tuinity - OBFHELPER // Tuinity - OBFHELPER -+ @Nullable protected Optional c(long i) { // Tuinity - OBFHELPER - return (Optional) this.c.get(i); - } - -+ public final Optional getOrLoad(long coordinate) { return this.d(coordinate); } // Tuinity - OBFHELPER - protected Optional d(long i) { - SectionPosition sectionposition = SectionPosition.a(i); - -@@ -150,6 +185,7 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab - }); - } - } -+ if (this instanceof VillagePlace) { ((VillagePlace)this).queueUnload(chunkcoordintpair.pair(), MinecraftServer.currentTickLong + 1); } // Tuinity - unload POI data - - } - -@@ -221,6 +257,7 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab - return dynamic.get("DataVersion").asInt(1945); - } - -+ public final void writeDirtyData(ChunkCoordIntPair chunkcoordintpair) { this.a(chunkcoordintpair); } // Tuinity - OBFHELPER - public void a(ChunkCoordIntPair chunkcoordintpair) { - if (!this.d.isEmpty()) { - for (int i = 0; i < 16; ++i) { -diff --git a/src/main/java/net/minecraft/server/SectionPosition.java b/src/main/java/net/minecraft/server/SectionPosition.java -index f95925f1c5d091f1a129d0437bb6e175c6ac080f..0bb3ad0bffc04eba38cd827eaf5c63e8bf2aee93 100644 ---- a/src/main/java/net/minecraft/server/SectionPosition.java -+++ b/src/main/java/net/minecraft/server/SectionPosition.java -@@ -7,7 +7,7 @@ import java.util.stream.StreamSupport; - - public class SectionPosition extends BaseBlockPosition { - -- private SectionPosition(int i, int j, int k) { -+ public SectionPosition(int i, int j, int k) { // Tuinity - private -> public - super(i, j, k); - } - -diff --git a/src/main/java/net/minecraft/server/SensorNearestBed.java b/src/main/java/net/minecraft/server/SensorNearestBed.java -index ad3609f2b884f64f1a1a449036cece49a46e933e..89f8ce32225bc560b9927273f5984c6206360ac7 100644 ---- a/src/main/java/net/minecraft/server/SensorNearestBed.java -+++ b/src/main/java/net/minecraft/server/SensorNearestBed.java -@@ -40,15 +40,19 @@ public class SensorNearestBed extends Sensor { - return true; - } - }; -- Stream stream = villageplace.a(VillagePlaceType.r.c(), predicate, entityinsentient.getChunkCoordinates(), 48, VillagePlace.Occupancy.ANY); -- PathEntity pathentity = entityinsentient.getNavigation().a(stream, VillagePlaceType.r.d()); -+ // Tuinity start - optimise POI access -+ java.util.List poiposes = new java.util.ArrayList<>(); -+ // don't ask me why it's unbounded. ask mojang. -+ com.tuinity.tuinity.util.PoiAccess.findAnyPoiPositions(villageplace, VillagePlaceType.r.c(), predicate, entityinsentient.getChunkCoordinates(), 48, VillagePlace.Occupancy.ANY, false, Integer.MAX_VALUE, poiposes); -+ PathEntity pathentity = entityinsentient.getNavigation().a(new java.util.HashSet<>(poiposes), VillagePlaceType.r.d()); -+ // Tuinity end - optimise POI access - - if (pathentity != null && pathentity.j()) { - BlockPosition blockposition = pathentity.m(); - Optional optional = villageplace.c(blockposition); - - if (optional.isPresent()) { -- entityinsentient.getBehaviorController().setMemory(MemoryModuleType.NEAREST_BED, (Object) blockposition); -+ entityinsentient.getBehaviorController().setMemory(MemoryModuleType.NEAREST_BED, blockposition); // Tuinity - decompile fix - } - } else if (this.b < 5) { - this.a.long2LongEntrySet().removeIf((entry) -> { -diff --git a/src/main/java/net/minecraft/server/SensorNearestItems.java b/src/main/java/net/minecraft/server/SensorNearestItems.java -index edf7d31e8e06f67be58282b2a76d1ac899b4f3e8..1de170b9fe6f2888da6dcf0151aaf1f865691c6a 100644 ---- a/src/main/java/net/minecraft/server/SensorNearestItems.java -+++ b/src/main/java/net/minecraft/server/SensorNearestItems.java -@@ -18,19 +18,24 @@ public class SensorNearestItems extends Sensor { - - protected void a(WorldServer worldserver, EntityInsentient entityinsentient) { - BehaviorController behaviorcontroller = entityinsentient.getBehaviorController(); -- List list = worldserver.a(EntityItem.class, entityinsentient.getBoundingBox().grow(8.0D, 4.0D, 8.0D), (entityitem) -> { -- return true; -+ // Tuinity start - remove streams -+ List list = worldserver.a(EntityItem.class, entityinsentient.getBoundingBox().grow(8.0D, 4.0D, 8.0D), (EntityItem item) -> { -+ return entityinsentient.i(item.getItemStack()) && item.a((Entity)entityinsentient, 9.0D); // copied from removed code, make sure to update - move here so we sort less - }); -- // Paper start - remove streams in favour of lists -- list.sort(Comparator.comparingDouble(entityinsentient::h)); -+ -+ list.sort(Comparator.comparingDouble(entityinsentient::h)); // better to take the sort perf hit than using line of sight more than we need to. - EntityItem nearest = null; -- for (EntityItem entityItem : list) { -- if (entityinsentient.i(entityItem.getItemStack()) && entityItem.a(entityinsentient, 9.0D) && entityinsentient.hasLineOfSight(entityItem)) { -- nearest = entityItem; -+ for (int index = 0, len = list.size(); index < len; ++index) { -+ EntityItem item = list.get(index); -+ if (entityinsentient.hasLineOfSight(item)) { -+ nearest = item; - break; - } - } -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, Optional.ofNullable(nearest)); -- // Paper end -+ -+ Optional optional = Optional.ofNullable(nearest); -+ // Tuinity end - remove streams -+ -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, optional); - } - } -diff --git a/src/main/java/net/minecraft/server/SensorNearestLivingEntities.java b/src/main/java/net/minecraft/server/SensorNearestLivingEntities.java -index b3388d4a665e8f91083a2e746482a9f0bd988da1..83e47ab6eb27847f7260f297d7b04a8e6c82d619 100644 ---- a/src/main/java/net/minecraft/server/SensorNearestLivingEntities.java -+++ b/src/main/java/net/minecraft/server/SensorNearestLivingEntities.java -@@ -22,11 +22,16 @@ public class SensorNearestLivingEntities extends Sensor { - BehaviorController behaviorcontroller = entityliving.getBehaviorController(); - - behaviorcontroller.setMemory(MemoryModuleType.MOBS, list); // Paper - decompile error -- // Paper start - remove streams in favour of lists -- List visibleMobs = new java.util.ArrayList<>(list); -- visibleMobs.removeIf(otherEntityLiving -> !Sensor.a(entityliving, otherEntityLiving)); -- behaviorcontroller.setMemory(MemoryModuleType.VISIBLE_MOBS, visibleMobs); -- // Paper end -+ // Tuinity start - remove streams -+ List visible = new java.util.ArrayList<>(list.size()); -+ for (int index = 0, len = list.size(); index < len; ++index) { -+ EntityLiving nearby = list.get(index); -+ if (Sensor.a(entityliving, nearby)) { // copied from removed code, make sure to update -+ visible.add(nearby); -+ } -+ } -+ behaviorcontroller.setMemory(MemoryModuleType.VISIBLE_MOBS, visible); -+ // Tuinity end - remove streams - } - - @Override -diff --git a/src/main/java/net/minecraft/server/SensorNearestPlayers.java b/src/main/java/net/minecraft/server/SensorNearestPlayers.java -index ae946619f10a757171e4217e414d6a5248a45494..fa2d366ca6695c099c29469bf69a7845350b4f07 100644 ---- a/src/main/java/net/minecraft/server/SensorNearestPlayers.java -+++ b/src/main/java/net/minecraft/server/SensorNearestPlayers.java -@@ -19,26 +19,31 @@ public class SensorNearestPlayers extends Sensor { - - @Override - protected void a(WorldServer worldserver, EntityLiving entityliving) { -- // Paper start - remove streams in favour of lists -- List players = new java.util.ArrayList<>(worldserver.getPlayers()); -- players.removeIf(player -> !IEntitySelector.notSpectator().test(player) || !entityliving.a(player, 16.0D)); // Paper - removeIf only re-allocates once compared to iterator -- players.sort(Comparator.comparingDouble(entityliving::h)); -- -+ // Tuinity start - remove streams -+ List nearby = (List)worldserver.getNearbyPlayers(entityliving, entityliving.locX(), entityliving.locY(), entityliving.locZ(), -+ 16.0, IEntitySelector.g); -+ nearby.sort((e1, e2) -> Double.compare(entityliving.getDistanceSquared(e1), entityliving.getDistanceSquared(e2))); - BehaviorController behaviorcontroller = entityliving.getBehaviorController(); -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_PLAYERS, players); - -- EntityHuman nearest = null, nearestTargetable = null; -- for (EntityHuman player : players) { -- if (Sensor.a(entityliving, player)) { -- if (nearest == null) nearest = player; -- if (IEntitySelector.canAITarget().test(player)) { -- nearestTargetable = player; -- break; // Both variables are assigned, no reason to loop further -- } -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_PLAYERS, nearby); -+ EntityHuman first = null; -+ EntityHuman firstNonSpectator = null; -+ for (int index = 0, len = nearby.size(); index < len; ++index) { -+ EntityHuman entity = nearby.get(index); -+ if (!Sensor.a(entityliving, (EntityLiving)entity)) { // copied from removed code, make sure to update -+ continue; -+ } -+ if (first == null) { -+ first = entity; -+ } -+ if (IEntitySelector.f.test(entity)) { // copied from removed code, make sure to update -+ firstNonSpectator = entity; -+ break; - } - } -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, nearest); -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, nearestTargetable); -- // Paper end -+ -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, first); -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, Optional.ofNullable(firstNonSpectator)); -+ // Tuinity end - remove streams - } - } -diff --git a/src/main/java/net/minecraft/server/SensorVillagerBabies.java b/src/main/java/net/minecraft/server/SensorVillagerBabies.java -index a367bbfde4fbfeca6d01dec49c05f5e185aab43a..794b33a13b7f11b973caf085b0bded9b2135a4d7 100644 ---- a/src/main/java/net/minecraft/server/SensorVillagerBabies.java -+++ b/src/main/java/net/minecraft/server/SensorVillagerBabies.java -@@ -17,11 +17,23 @@ public class SensorVillagerBabies extends Sensor { - - @Override - protected void a(WorldServer worldserver, EntityLiving entityliving) { -- entityliving.getBehaviorController().setMemory(MemoryModuleType.VISIBLE_VILLAGER_BABIES, (Object) this.a(entityliving)); -+ entityliving.getBehaviorController().setMemory(MemoryModuleType.VISIBLE_VILLAGER_BABIES, this.a(entityliving)); // Tuinity - decompile fix - } - - private List a(EntityLiving entityliving) { -- return (List) this.c(entityliving).stream().filter(this::b).collect(Collectors.toList()); -+ // Tuinity start - remove streams -+ List nearby = this.c(entityliving); // copied from removed code, make sure to update -+ List ret = new java.util.ArrayList<>(); -+ -+ for (int index = 0, len = nearby.size(); index < len; ++index) { -+ EntityLiving entity = nearby.get(index); -+ if (this.b(entity)) { // copied from removed code, make sure to update -+ ret.add(entity); -+ } -+ } -+ -+ return ret; -+ // Tuinity end - remove streams - } - - private boolean b(EntityLiving entityliving) { -diff --git a/src/main/java/net/minecraft/server/ServerConnection.java b/src/main/java/net/minecraft/server/ServerConnection.java -index 5f4dacf9c93c2495a07df2647fe0411f796da6af..0668d383db1f3a81d1053954d72678c7ac5aecec 100644 ---- a/src/main/java/net/minecraft/server/ServerConnection.java -+++ b/src/main/java/net/minecraft/server/ServerConnection.java -@@ -74,6 +74,11 @@ public class ServerConnection { - ServerConnection.LOGGER.info("Using default channel type"); - } - -+ // Tuinity start - indicate Velocity natives in use -+ ServerConnection.LOGGER.info("Tuinity: Using " + com.velocitypowered.natives.util.Natives.compress.getLoadedVariant() + " compression from Velocity."); -+ ServerConnection.LOGGER.info("Tuinity: Using " + com.velocitypowered.natives.util.Natives.cipher.getLoadedVariant() + " cipher from Velocity."); -+ // Tuinity end -+ - this.listeningChannels.add(((ServerBootstrap) ((ServerBootstrap) (new ServerBootstrap()).channel(oclass)).childHandler(new ChannelInitializer() { - protected void initChannel(Channel channel) throws Exception { - try { -diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java -index 661ad8f8e67046211e001ea40d97660d7c88f8e5..53fd0549c965b2252ad80648d61ff1f7cd2b837a 100644 ---- a/src/main/java/net/minecraft/server/SpawnerCreature.java -+++ b/src/main/java/net/minecraft/server/SpawnerCreature.java -@@ -30,9 +30,9 @@ public final class SpawnerCreature { - - public static SpawnerCreature.d a(int i, Iterable iterable, SpawnerCreature.b spawnercreature_b) { - // Paper start - add countMobs parameter -- return countMobs(i, iterable, spawnercreature_b, false); -+ return countMobs(i, iterable, spawnercreature_b, false, null); // Tuinity - it'll still be broken no matter what - } -- public static SpawnerCreature.d countMobs(int i, Iterable iterable, SpawnerCreature.b spawnercreature_b, boolean countMobs) { -+ public static SpawnerCreature.d countMobs(int i, Iterable iterable, SpawnerCreature.b spawnercreature_b, boolean countMobs, ChunkProviderServer chunkProvider) { // Tuinity - add CPS param - // Paper end - add countMobs parameter - SpawnerCreatureProbabilities spawnercreatureprobabilities = new SpawnerCreatureProbabilities(); - Object2IntOpenHashMap object2intopenhashmap = new Object2IntOpenHashMap(); -@@ -63,7 +63,16 @@ public final class SpawnerCreature { - BlockPosition blockposition = entity.getChunkCoordinates(); - long j = ChunkCoordIntPair.pair(blockposition.getX() >> 4, blockposition.getZ() >> 4); - -- spawnercreature_b.query(j, (chunk) -> { -+ // Tuinity start - remove chunk lookup and lambda -+ Chunk chunk = entity.getCurrentChunk(); -+ if (chunk == null || j != chunk.coordinateKey) { // no chunk or coordinate doesn't match -+ chunk = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ if (chunk == null) { -+ // unloaded chunk! no longer FULL. -+ continue; -+ } -+ } -+ // Tuinity end - remove chunk lookup and lambda - BiomeSettingsMobs.b biomesettingsmobs_b = b(blockposition, chunk).b().a(entity.getEntityType()); - - if (biomesettingsmobs_b != null) { -@@ -73,10 +82,10 @@ public final class SpawnerCreature { - object2intopenhashmap.addTo(enumcreaturetype, 1); - // Paper start - if (countMobs) { -- ((WorldServer)chunk.world).getChunkProvider().playerChunkMap.updatePlayerMobTypeMap(entity); -+ chunkProvider.playerChunkMap.updatePlayerMobTypeMap(entity); // Tuinity - directly use chunk provider - } - // Paper end -- }); -+ // Tuinity - remove chunk lookup and lambda - } - } - -@@ -216,7 +225,7 @@ public final class SpawnerCreature { - blockposition_mutableblockposition.d(l, i, i1); - double d0 = (double) l + 0.5D; - double d1 = (double) i1 + 0.5D; -- EntityHuman entityhuman = worldserver.a(d0, (double) i, d1, -1.0D, false); -+ EntityHuman entityhuman = worldserver.a(d0, (double) i, d1, 576.0D, false); // Tuinity - copied from below method for range, for the love of god we do not need to fucking find the closet player outside of this range - limiting range lets us use the distance map - - if (entityhuman != null) { - double d2 = entityhuman.h(d0, (double) i, d1); -@@ -288,7 +297,7 @@ public final class SpawnerCreature { - } - - private static boolean a(WorldServer worldserver, IChunkAccess ichunkaccess, BlockPosition.MutableBlockPosition blockposition_mutableblockposition, double d0) { -- if (d0 <= 576.0D) { -+ if (d0 <= 576.0D) { // Tuinity - diff on change, copy into caller - return false; - } else if (worldserver.getSpawn().a((IPosition) (new Vec3D((double) blockposition_mutableblockposition.getX() + 0.5D, (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + 0.5D)), 24.0D)) { - return false; -diff --git a/src/main/java/net/minecraft/server/StructureManager.java b/src/main/java/net/minecraft/server/StructureManager.java -index f199368a6d78b0cd52f11ca2c8509d729b918852..2598ae3710d46c2cfd2be5d6be2a56e59ceef6ea 100644 ---- a/src/main/java/net/minecraft/server/StructureManager.java -+++ b/src/main/java/net/minecraft/server/StructureManager.java -@@ -35,8 +35,13 @@ public class StructureManager { - - // Paper start - remove structure streams - public java.util.List> getFeatureStarts(SectionPosition sectionPosition, StructureGenerator structureGenerator) { -+ // Tuinity start - add world parameter -+ return this.getFeatureStarts(sectionPosition, structureGenerator, null); -+ } -+ public java.util.List> getFeatureStarts(SectionPosition sectionPosition, StructureGenerator structureGenerator, IWorldReader world) { -+ // Tuinity end - add world parameter - java.util.List> list = new ObjectArrayList<>(); -- for (Long curLong: getLevel().getChunkAt(sectionPosition.a(), sectionPosition.c(), ChunkStatus.STRUCTURE_REFERENCES).b(structureGenerator)) { -+ for (Long curLong: (world == null ? getLevel() : world).getChunkAt(sectionPosition.a(), sectionPosition.c(), ChunkStatus.STRUCTURE_REFERENCES).b(structureGenerator)) { // Tuinity - fix deadlock on world gen - chunk can be unloaded while generating, so we should be using the generator's regionlimitedaccess so we always get the chunk - SectionPosition sectionPosition1 = SectionPosition.a(new ChunkCoordIntPair(curLong), 0); - StructureStart structurestart = a(sectionPosition1, structureGenerator, getLevel().getChunkAt(sectionPosition1.a(), sectionPosition1.c(), ChunkStatus.STRUCTURE_STARTS)); - if (structurestart != null && structurestart.e()) { -@@ -65,8 +70,12 @@ public class StructureManager { - } - - public StructureStart a(BlockPosition blockposition, boolean flag, StructureGenerator structuregenerator) { -+ // Tuinity start - add world parameter -+ return this.getStructureStarts(blockposition,flag, structuregenerator, null); -+ } -+ public StructureStart getStructureStarts(BlockPosition blockposition, boolean flag, StructureGenerator structuregenerator, IWorldReader world) { - // Paper start - remove structure streams -- for (StructureStart structurestart : getFeatureStarts(SectionPosition.a(blockposition), structuregenerator)) { -+ for (StructureStart structurestart : getFeatureStarts(SectionPosition.a(blockposition), structuregenerator, world)) { // Tuinity end - add world parameter - if (structurestart.c().b(blockposition)) { - if (!flag) { - return structurestart; -diff --git a/src/main/java/net/minecraft/server/Ticket.java b/src/main/java/net/minecraft/server/Ticket.java -index e41cb8613efc86499dfe3be36c9130ab6dc9b89e..c19ffb925a02d123da8a5c77186e6105422dccf7 100644 ---- a/src/main/java/net/minecraft/server/Ticket.java -+++ b/src/main/java/net/minecraft/server/Ticket.java +diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java +index 6e5ae954c6eb40590bf8c83f592c22088d489be8..c9b395dd0e4881a2e2e409bf782491b42ff087e6 100644 +--- a/src/main/java/net/minecraft/server/level/Ticket.java ++++ b/src/main/java/net/minecraft/server/level/Ticket.java @@ -5,17 +5,17 @@ import java.util.Objects; public final class Ticket implements Comparable> { @@ -17704,11 +14059,11 @@ index e41cb8613efc86499dfe3be36c9130ab6dc9b89e..c19ffb925a02d123da8a5c77186e6105 return j != 0L && i - this.d > j; } -diff --git a/src/main/java/net/minecraft/server/TicketType.java b/src/main/java/net/minecraft/server/TicketType.java -index 5c789b25f1df2eae8ea8ceb4ba977ba336fe6d5e..3c964f26592fc84bb5fc11c60808d11c65d93b16 100644 ---- a/src/main/java/net/minecraft/server/TicketType.java -+++ b/src/main/java/net/minecraft/server/TicketType.java -@@ -26,8 +26,22 @@ public class TicketType { +diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java +index 3c804c7b20a14ea6e510810e2be10c1cc89ff5c1..3738c51b5e673c439d88a7ef7f4614f338a61c2a 100644 +--- a/src/main/java/net/minecraft/server/level/TicketType.java ++++ b/src/main/java/net/minecraft/server/level/TicketType.java +@@ -30,8 +30,22 @@ public class TicketType { public static final TicketType ASYNC_LOAD = a("async_load", Long::compareTo); // Paper public static final TicketType PRIORITY = a("priority", Comparator.comparingLong(ChunkCoordIntPair::pair), 300); // Paper public static final TicketType URGENT = a("urgent", Comparator.comparingLong(ChunkCoordIntPair::pair), 300); // Paper @@ -17732,1265 +14087,11 @@ index 5c789b25f1df2eae8ea8ceb4ba977ba336fe6d5e..3c964f26592fc84bb5fc11c60808d11c public static TicketType a(String s, Comparator comparator) { return new TicketType<>(s, comparator, 0L); } -diff --git a/src/main/java/net/minecraft/server/UserCache.java b/src/main/java/net/minecraft/server/UserCache.java -index 8c3aa47a28914fd69a7f2e55a8c8f91d8e02371e..afc2ddf519cf4930663f1859b8ce89a7b825f332 100644 ---- a/src/main/java/net/minecraft/server/UserCache.java -+++ b/src/main/java/net/minecraft/server/UserCache.java -@@ -49,6 +49,11 @@ public class UserCache { - private final File g; - private final AtomicLong h = new AtomicLong(); - -+ // Tuinity start -+ protected final java.util.concurrent.locks.ReentrantLock stateLock = new java.util.concurrent.locks.ReentrantLock(); -+ protected final java.util.concurrent.locks.ReentrantLock lookupLock = new java.util.concurrent.locks.ReentrantLock(); -+ // Tuinity end -+ - public UserCache(GameProfileRepository gameprofilerepository, File file) { - this.e = gameprofilerepository; - this.g = file; -@@ -56,6 +61,7 @@ public class UserCache { - } - - private void a(UserCache.UserCacheEntry usercache_usercacheentry) { -+ try { this.stateLock.lock(); // Tuinity - allow better concurrency - GameProfile gameprofile = usercache_usercacheentry.a(); - - usercache_usercacheentry.a(this.d()); -@@ -70,6 +76,7 @@ public class UserCache { - if (uuid != null) { - this.d.put(uuid, usercache_usercacheentry); - } -+ } finally { this.stateLock.unlock(); } // Tuinity - allow better concurrency - - } - -@@ -107,7 +114,7 @@ public class UserCache { - } - - public void saveProfile(GameProfile gameprofile) { a(gameprofile); } // Paper - OBFHELPER -- public synchronized void a(GameProfile gameprofile) { // Paper - synchronize -+ public void a(GameProfile gameprofile) { // Paper - synchronize // Tuinity - allow better concurrency - Calendar calendar = Calendar.getInstance(); - - calendar.setTime(new Date()); -@@ -124,8 +131,9 @@ public class UserCache { - } - - @Nullable -- public synchronized GameProfile getProfile(String s) { // Paper - synchronize -+ public GameProfile getProfile(String s) { // Paper - synchronize // Tuinity start - allow better concurrency - String s1 = s.toLowerCase(Locale.ROOT); -+ boolean stateLocked = true; try { this.stateLock.lock(); // Tuinity - allow better concurrency - UserCache.UserCacheEntry usercache_usercacheentry = (UserCache.UserCacheEntry) this.c.get(s1); - boolean flag = false; - -@@ -139,10 +147,14 @@ public class UserCache { - GameProfile gameprofile; - - if (usercache_usercacheentry != null) { -+ stateLocked = false; this.stateLock.unlock(); // Tuinity - allow better concurrency - usercache_usercacheentry.a(this.d()); - gameprofile = usercache_usercacheentry.a(); - } else { -+ stateLocked = false; this.stateLock.unlock(); // Tuinity - allow better concurrency -+ try { this.lookupLock.lock(); // Tuinity - allow better concurrency - gameprofile = a(this.e, s); // Spigot - use correct case for offline players -+ } finally { this.lookupLock.unlock(); } // Tuinity - allow better concurrency - if (gameprofile != null) { - this.a(gameprofile); - flag = false; -@@ -154,6 +166,7 @@ public class UserCache { - } - - return gameprofile; -+ } finally { if (stateLocked) { this.stateLock.unlock(); } } // Tuinity - allow better concurrency - } - - // Paper start -@@ -288,7 +301,9 @@ public class UserCache { - } - - private Stream a(int i) { -+ try { this.stateLock.lock(); // Tuinity - allow better concurrency - return ImmutableList.copyOf(this.d.values()).stream().sorted(Comparator.comparing(UserCache.UserCacheEntry::c).reversed()).limit((long) i); -+ } finally { this.stateLock.unlock(); } // Tuinity - allow better concurrency - } - - private static JsonElement a(UserCache.UserCacheEntry usercache_usercacheentry, DateFormat dateformat) { -diff --git a/src/main/java/net/minecraft/server/Vec3D.java b/src/main/java/net/minecraft/server/Vec3D.java -index 7f05587d42b7cdb09552277ec2e467f0edf06f10..7190316a38e6b4edf5501bfedbb12be79e990797 100644 ---- a/src/main/java/net/minecraft/server/Vec3D.java -+++ b/src/main/java/net/minecraft/server/Vec3D.java -@@ -4,11 +4,17 @@ import java.util.EnumSet; - - public class Vec3D implements IPosition { - -- public static final Vec3D ORIGIN = new Vec3D(0.0D, 0.0D, 0.0D); -+ public static final Vec3D ORIGIN = new Vec3D(0.0D, 0.0D, 0.0D); public static Vec3D getZeroVector() { return Vec3D.ORIGIN; } // Tuinity - OBFHELPER - public final double x; - public final double y; - public final double z; - -+ // Tuinity start -+ public final double magnitudeXZSquared() { -+ return (this.x * this.x) + (this.z * this.z); -+ } -+ // Tuinity end -+ - public static Vec3D a(BaseBlockPosition baseblockposition) { - return new Vec3D((double) baseblockposition.getX() + 0.5D, (double) baseblockposition.getY() + 0.5D, (double) baseblockposition.getZ() + 0.5D); - } -@@ -61,6 +67,7 @@ public class Vec3D implements IPosition { - return this.add(-d0, -d1, -d2); - } - -+ public final Vec3D add(Vec3D vec3d) { return this.e(vec3d); } // Tuinity - OBFHELPER - public Vec3D e(Vec3D vec3d) { - return this.add(vec3d.x, vec3d.y, vec3d.z); - } -@@ -109,10 +116,12 @@ public class Vec3D implements IPosition { - return new Vec3D(this.x * d0, this.y * d1, this.z * d2); - } - -+ public final double magnitude() { return this.f(); } // Tuinity - OBFHELPER - public double f() { - return (double) MathHelper.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); - } - -+ public final double magnitudeSquared() { return this.g(); } // Tuinity - OBFHELPER - public double g() { - return this.x * this.x + this.y * this.y + this.z * this.z; - } -diff --git a/src/main/java/net/minecraft/server/VillagePlace.java b/src/main/java/net/minecraft/server/VillagePlace.java -index 6a0f07b13eef5560dfc7c7b39618c0b825533aec..245bdedd17b844dcd13aa0b60dffb1cac6a5bdb8 100644 ---- a/src/main/java/net/minecraft/server/VillagePlace.java -+++ b/src/main/java/net/minecraft/server/VillagePlace.java -@@ -4,6 +4,7 @@ import com.mojang.datafixers.DataFixer; - import com.mojang.datafixers.util.Pair; - import it.unimi.dsi.fastutil.longs.Long2ByteMap; - import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap; -+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Tuinity - import it.unimi.dsi.fastutil.longs.LongOpenHashSet; - import it.unimi.dsi.fastutil.longs.LongSet; - import java.io.File; -@@ -22,8 +23,24 @@ import java.util.stream.Stream; - - public class VillagePlace extends RegionFileSection { - -- private final VillagePlace.a a = new VillagePlace.a(); -- private final LongSet b = new LongOpenHashSet(); -+ // Tuinity start - unload poi data -+ // the vanilla tracker needs to be replaced because it does not support level removes -+ private final com.tuinity.tuinity.util.misc.Delayed26WayDistancePropagator3D villageDistanceTracker = new com.tuinity.tuinity.util.misc.Delayed26WayDistancePropagator3D(); -+ static final int POI_DATA_SOURCE = 7; -+ public static int convertBetweenLevels(final int level) { -+ return POI_DATA_SOURCE - level; -+ } -+ -+ protected void updateDistanceTracking(long section) { -+ if (this.isSectionDistanceTrackerSource(section)) { -+ this.villageDistanceTracker.setSource(section, POI_DATA_SOURCE); -+ } else { -+ this.villageDistanceTracker.removeSource(section); -+ } -+ } -+ // Tuinity end - unload poi data -+ -+ private final LongSet b = new LongOpenHashSet(); private final LongSet getLoadedChunks() { return this.b; } // Tuinity - OBFHELPER - - private final WorldServer world; // Paper - -@@ -34,9 +51,124 @@ public class VillagePlace extends RegionFileSection { - public VillagePlace(File file, DataFixer datafixer, boolean flag, WorldServer world) { - super(file, VillagePlaceSection::a, VillagePlaceSection::new, datafixer, DataFixTypes.POI_CHUNK, flag); - this.world = world; -+ if (world == null) { throw new IllegalStateException("world must be non-null"); }// Tuinity - require non-null - // Paper end - add world parameter - } - -+ // Tuinity start - actually unload POI data -+ private final java.util.TreeSet queuedUnloads = new java.util.TreeSet<>(); -+ private final Long2ObjectOpenHashMap queuedUnloadsByCoordinate = new Long2ObjectOpenHashMap<>(); -+ -+ static final class QueuedUnload implements Comparable { -+ -+ private final long unloadTick; -+ private final long coordinate; -+ -+ public QueuedUnload(long unloadTick, long coordinate) { -+ this.unloadTick = unloadTick; -+ this.coordinate = coordinate; -+ } -+ -+ @Override -+ public int compareTo(QueuedUnload other) { -+ if (other.unloadTick == this.unloadTick) { -+ return Long.compare(this.coordinate, other.coordinate); -+ } else { -+ return Long.compare(this.unloadTick, other.unloadTick); -+ } -+ } -+ -+ @Override -+ public int hashCode() { -+ int hash = 1; -+ hash = hash * 31 + Long.hashCode(this.unloadTick); -+ hash = hash * 31 + Long.hashCode(this.coordinate); -+ return hash; -+ } -+ -+ @Override -+ public boolean equals(Object obj) { -+ if (obj == null || obj.getClass() != QueuedUnload.class) { -+ return false; -+ } -+ QueuedUnload other = (QueuedUnload)obj; -+ return other.unloadTick == this.unloadTick && other.coordinate == this.coordinate; -+ } -+ } -+ -+ long determineDelay(long coordinate) { -+ if (this.isEmpty(coordinate)) { -+ return 5 * 60 * 20; -+ } else { -+ return 60 * 20; -+ } -+ } -+ -+ public void queueUnload(long coordinate, long minTarget) { -+ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("async poi unload queue"); -+ QueuedUnload unload = new QueuedUnload(minTarget + this.determineDelay(coordinate), coordinate); -+ QueuedUnload existing = this.queuedUnloadsByCoordinate.put(coordinate, unload); -+ if (existing != null) { -+ this.queuedUnloads.remove(existing); -+ } -+ this.queuedUnloads.add(unload); -+ } -+ -+ public void dequeueUnload(long coordinate) { -+ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("async poi unload dequeue"); -+ QueuedUnload unload = this.queuedUnloadsByCoordinate.remove(coordinate); -+ if (unload != null) { -+ this.queuedUnloads.remove(unload); -+ } -+ } -+ -+ public void pollUnloads(BooleanSupplier canSleepForTick) { -+ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("async poi unload"); -+ long currentTick = MinecraftServer.currentTickLong; -+ ChunkProviderServer chunkProvider = this.world.getChunkProvider(); -+ PlayerChunkMap playerChunkMap = chunkProvider.playerChunkMap; -+ // copied target determination from PlayerChunkMap -+ int target = Math.min(this.queuedUnloads.size() - 100, (int) (this.queuedUnloads.size() * PlayerChunkMap.UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Make more aggressive -+ for (java.util.Iterator iterator = this.queuedUnloads.iterator(); -+ iterator.hasNext() && (this.queuedUnloads.size() > target || canSleepForTick.getAsBoolean());) { -+ QueuedUnload unload = iterator.next(); -+ if (unload.unloadTick > currentTick) { -+ break; -+ } -+ -+ long coordinate = unload.coordinate; -+ -+ iterator.remove(); -+ this.queuedUnloadsByCoordinate.remove(coordinate); -+ -+ if (playerChunkMap.getUnloadingPlayerChunk(MCUtil.getCoordinateX(coordinate), MCUtil.getCoordinateZ(coordinate)) != null -+ || playerChunkMap.getUpdatingChunk(coordinate) != null) { -+ continue; -+ } -+ -+ this.unloadData(coordinate); -+ } -+ } -+ -+ @Override -+ public void unloadData(long coordinate) { -+ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("async unloading poi data"); -+ super.unloadData(coordinate); -+ } -+ -+ @Override -+ protected void onUnload(long coordinate) { -+ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("async poi unload callback"); -+ this.getLoadedChunks().remove(coordinate); -+ int chunkX = MCUtil.getCoordinateX(coordinate); -+ int chunkZ = MCUtil.getCoordinateZ(coordinate); -+ for (int section = 0; section < 16; ++section) { -+ long sectionPos = SectionPosition.asLong(chunkX, section, chunkZ); -+ this.updateDistanceTracking(sectionPos); -+ } -+ } -+ // Tuinity end - actually unload POI data -+ - public void a(BlockPosition blockposition, VillagePlaceType villageplacetype) { - ((VillagePlaceSection) this.e(SectionPosition.a(blockposition).s())).a(blockposition, villageplacetype); - } -@@ -95,31 +227,47 @@ public class VillagePlace extends RegionFileSection { - } - - public Optional c(Predicate predicate, Predicate predicate1, BlockPosition blockposition, int i, VillagePlace.Occupancy villageplace_occupancy) { -- return this.a(predicate, predicate1, blockposition, i, villageplace_occupancy).findFirst(); -+ // Tuinity start - re-route to faster logic -+ BlockPosition ret = com.tuinity.tuinity.util.PoiAccess.findAnyPoiPosition(this, predicate, predicate1, blockposition, i, villageplace_occupancy, false); -+ return Optional.ofNullable(ret); -+ // Tuinity end - re-route to faster logic - } - - public Optional d(Predicate predicate, BlockPosition blockposition, int i, VillagePlace.Occupancy villageplace_occupancy) { -- return this.c(predicate, blockposition, i, villageplace_occupancy).map(VillagePlaceRecord::f).min(Comparator.comparingDouble((blockposition1) -> { -- return blockposition1.j(blockposition); -- })); -+ // Tuinity start - re-route to faster logic -+ BlockPosition ret = com.tuinity.tuinity.util.PoiAccess.findClosestPoiDataPosition(this, predicate, null, blockposition, i, i*i, villageplace_occupancy, false); -+ return Optional.ofNullable(ret); -+ // Tuinity end - re-route to faster logic - } - - public Optional a(Predicate predicate, Predicate predicate1, BlockPosition blockposition, int i) { -- return this.c(predicate, blockposition, i, VillagePlace.Occupancy.HAS_SPACE).filter((villageplacerecord) -> { -- return predicate1.test(villageplacerecord.f()); -- }).findFirst().map((villageplacerecord) -> { -- villageplacerecord.b(); -- return villageplacerecord.f(); -- }); -+ // Tuinity start - re-route to faster logic -+ VillagePlaceRecord ret = com.tuinity.tuinity.util.PoiAccess.findAnyPoiRecord(this, predicate, predicate1, blockposition, i, -+ VillagePlace.Occupancy.HAS_SPACE, false); -+ if (ret == null) { -+ return Optional.empty(); -+ } -+ // copy from the map() from the old code -+ ret.b(); -+ return Optional.ofNullable(ret.f()); -+ // Tuinity end - re-route to faster logic - } - - public Optional a(Predicate predicate, Predicate predicate1, VillagePlace.Occupancy villageplace_occupancy, BlockPosition blockposition, int i, Random random) { -- List list = (List) this.c(predicate, blockposition, i, villageplace_occupancy).collect(Collectors.toList()); -- -- Collections.shuffle(list, random); -- return list.stream().filter((villageplacerecord) -> { -- return predicate1.test(villageplacerecord.f()); -- }).findFirst().map(VillagePlaceRecord::f); -+ // Tuinity start - re-route to faster logic -+ List list = new java.util.ArrayList<>(); -+ com.tuinity.tuinity.util.PoiAccess.findAnyPoiRecords(this, predicate, predicate1, blockposition, i, villageplace_occupancy, false, Integer.MAX_VALUE, list); -+ // Tuinity end - re-route to faster logic -+ -+ // Tuinity start - rewrite this to use improved logic -+ // the old method shuffled the list and then tried to find the first element in it that -+ // matched predicate1, however we moved predicate1 into the poi search. This means we can avoid a shuffle -+ // entirely, and just pick a random element from list -+ if (list.isEmpty()) { -+ return Optional.empty(); -+ } -+ return Optional.ofNullable(list.get(random.nextInt(list.size())).f()); -+ // Tuinity end - rewrite this to use improved logic - } - - public boolean b(BlockPosition blockposition) { -@@ -140,10 +288,11 @@ public class VillagePlace extends RegionFileSection { - } - - public int a(SectionPosition sectionposition) { -- this.a.a(); -- return this.a.c(sectionposition.s()); -+ this.villageDistanceTracker.propagateUpdates(); // Tuinity - replace distance tracking util -+ return convertBetweenLevels(this.villageDistanceTracker.getLevel(MCUtil.getSectionKey(sectionposition))); // Tuinity - replace distance tracking util - } - -+ private boolean isSectionDistanceTrackerSource(long section) { return this.f(section); } // Tuinity - OBFHELPER - private boolean f(long i) { - Optional optional = this.c(i); - -@@ -159,7 +308,7 @@ public class VillagePlace extends RegionFileSection { - super.a(booleansupplier); - } else { - //super.a(booleansupplier); // re-implement below -- while (!((RegionFileSection)this).d.isEmpty() && booleansupplier.getAsBoolean()) { -+ while (!((RegionFileSection)this).d.isEmpty() && booleansupplier.getAsBoolean() && !this.world.isSavingDisabled()) { // Tuinity - unload POI data - don't write to disk if saving is disabled - ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(((RegionFileSection)this).d.firstLong()).r(); - - NBTTagCompound data; -@@ -167,22 +316,27 @@ public class VillagePlace extends RegionFileSection { - data = this.getData(chunkcoordintpair); - } - com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, -- chunkcoordintpair.x, chunkcoordintpair.z, data, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY); -+ chunkcoordintpair.x, chunkcoordintpair.z, data, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY); // Tuinity - use normal priority - } - } -+ // Tuinity start - unload POI data -+ if (!this.world.isSavingDisabled()) { // don't write to disk if saving is disabled -+ this.pollUnloads(booleansupplier); -+ } -+ // Tuinity end - unload POI data - // Paper end -- this.a.a(); -+ this.villageDistanceTracker.propagateUpdates(); // Tuinity - replace distance tracking until - } - - @Override - protected void a(long i) { - super.a(i); -- this.a.b(i, this.a.b(i), false); -+ this.updateDistanceTracking(i); // Tuinity - move to new distance tracking util - } - - @Override - protected void b(long i) { -- this.a.b(i, this.a.b(i), false); -+ this.updateDistanceTracking(i); // Tuinity - move to new distance tracking util - } - - public void a(ChunkCoordIntPair chunkcoordintpair, ChunkSection chunksection) { -@@ -247,7 +401,7 @@ public class VillagePlace extends RegionFileSection { - - @Override - protected int b(long i) { -- return VillagePlace.this.f(i) ? 0 : 7; -+ return VillagePlace.this.f(i) ? 0 : 7; // Tuinity - unload poi data - diff on change, this specifies the source level to use for distance tracking - } - - @Override -@@ -292,7 +446,7 @@ public class VillagePlace extends RegionFileSection { - if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { - com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave( - this.world, chunkcoordintpair.x, chunkcoordintpair.z, nbttagcompound, null, -- com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread()); -+ com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY); // Tuinity - writes are async, no need for priority - return; - } - super.write(chunkcoordintpair, nbttagcompound); -@@ -311,6 +465,7 @@ public class VillagePlace extends RegionFileSection { - this.d = predicate; - } - -+ public final Predicate getPredicate() { return this.a(); } // Tuinity - OBFHELPER - public Predicate a() { - return this.d; - } -diff --git a/src/main/java/net/minecraft/server/VillagePlaceRecord.java b/src/main/java/net/minecraft/server/VillagePlaceRecord.java -index 0b40c2f4dada7d8432e3f91e9cf206c2bda3b24b..6eaf9fc9cc93f79a497b07a3549d459ba66be849 100644 ---- a/src/main/java/net/minecraft/server/VillagePlaceRecord.java -+++ b/src/main/java/net/minecraft/server/VillagePlaceRecord.java -@@ -6,7 +6,7 @@ import java.util.Objects; - - public class VillagePlaceRecord { - -- private final BlockPosition a; -+ private final BlockPosition a; public final BlockPosition getPosition() { return this.a; } // Tuinity - OBFHELPER - private final VillagePlaceType b; - private int c; - private final Runnable d; -diff --git a/src/main/java/net/minecraft/server/VillagePlaceSection.java b/src/main/java/net/minecraft/server/VillagePlaceSection.java -index b86963aa34b5ae479f924c5a52afc5b5b66dba76..943a437ff27162eae09211c28bdc0d141fa6a404 100644 ---- a/src/main/java/net/minecraft/server/VillagePlaceSection.java -+++ b/src/main/java/net/minecraft/server/VillagePlaceSection.java -@@ -23,12 +23,12 @@ public class VillagePlaceSection { - - private static final Logger LOGGER = LogManager.getLogger(); - private final Short2ObjectMap b; -- private final Map> c; -+ private final Map> c; public final Map> getData() { return this.c; } // Tuinity - OBFHELPER - private final Runnable d; - private boolean e; - - public static Codec a(Runnable runnable) { -- Codec codec = RecordCodecBuilder.create((instance) -> { -+ Codec codec = RecordCodecBuilder.create((instance) -> { // Tuinity - decompile fix - return instance.group(RecordCodecBuilder.point(runnable), Codec.BOOL.optionalFieldOf("Valid", false).forGetter((villageplacesection) -> { - return villageplacesection.e; - }), VillagePlaceRecord.a(runnable).listOf().fieldOf("Records").forGetter((villageplacesection) -> { -diff --git a/src/main/java/net/minecraft/server/VoxelShape.java b/src/main/java/net/minecraft/server/VoxelShape.java -index eb926b74e17fb2f88c1d6ce2fb546541f8e6e274..e3b72922e2dfad07f3452ec5ee2af379d968c52d 100644 ---- a/src/main/java/net/minecraft/server/VoxelShape.java -+++ b/src/main/java/net/minecraft/server/VoxelShape.java -@@ -8,11 +8,11 @@ import javax.annotation.Nullable; - - public abstract class VoxelShape { - -- protected final VoxelShapeDiscrete a; -+ protected final VoxelShapeDiscrete a; public final VoxelShapeDiscrete getShape() { return this.a; } // Tuinity - OBFHELPER - @Nullable - private VoxelShape[] b; - -- VoxelShape(VoxelShapeDiscrete voxelshapediscrete) { -+ protected VoxelShape(VoxelShapeDiscrete voxelshapediscrete) { // Tuinity - this.a = voxelshapediscrete; - } - -@@ -48,9 +48,16 @@ public abstract class VoxelShape { - - public final VoxelShape offset(double x, double y, double z) { return this.a(x, y, z); } // Paper - OBFHELPER - public VoxelShape a(double d0, double d1, double d2) { -- return (VoxelShape) (this.isEmpty() ? VoxelShapes.a() : new VoxelShapeArray(this.a, new DoubleListOffset(this.a(EnumDirection.EnumAxis.X), d0), new DoubleListOffset(this.a(EnumDirection.EnumAxis.Y), d1), new DoubleListOffset(this.a(EnumDirection.EnumAxis.Z), d2))); -+ return (VoxelShape) (this.isEmpty() ? VoxelShapes.a() : new VoxelShapeArray(this.a, new DoubleListOffset(this.a(EnumDirection.EnumAxis.X), d0), new DoubleListOffset(this.a(EnumDirection.EnumAxis.Y), d1), new DoubleListOffset(this.a(EnumDirection.EnumAxis.Z), d2))); // Tuinity - diff on change, copied into VoxelShapeArray override - } - -+ // Tuinity start - optimise multi-aabb shapes -+ public boolean intersects(final AxisAlignedBB axisalingedbb) { -+ return VoxelShapes.applyOperation(this, new com.tuinity.tuinity.voxel.AABBVoxelShape(axisalingedbb), OperatorBoolean.AND); -+ } -+ // Tuinity end - optimise multi-aabb shapes -+ -+ public final VoxelShape simplify() { return this.c(); } // Tuinity - OBFHELPER - public VoxelShape c() { - VoxelShape[] avoxelshape = new VoxelShape[]{VoxelShapes.a()}; - -@@ -70,6 +77,7 @@ public abstract class VoxelShape { - }, true); - } - -+ public final List getBoundingBoxesRepresentation() { return this.d(); } // Tuinity - OBFHELPER - public List d() { - List list = Lists.newArrayList(); - -diff --git a/src/main/java/net/minecraft/server/VoxelShapeArray.java b/src/main/java/net/minecraft/server/VoxelShapeArray.java -index 3c29cb1452cde1308f630bfcb82876ef19057e8f..c14b7bd63e3917bc5f495655c40d8825a8d2062f 100644 ---- a/src/main/java/net/minecraft/server/VoxelShapeArray.java -+++ b/src/main/java/net/minecraft/server/VoxelShapeArray.java -@@ -3,6 +3,7 @@ package net.minecraft.server; - import it.unimi.dsi.fastutil.doubles.DoubleArrayList; - import it.unimi.dsi.fastutil.doubles.DoubleList; - import java.util.Arrays; -+import java.util.List; - - public final class VoxelShapeArray extends VoxelShape { - -@@ -10,11 +11,25 @@ public final class VoxelShapeArray extends VoxelShape { - private final DoubleList c; - private final DoubleList d; - -+ // Tuinity start - optimise multi-aabb shapes -+ static final AxisAlignedBB[] EMPTY = new AxisAlignedBB[0]; -+ final AxisAlignedBB[] boundingBoxesRepresentation; -+ -+ final double offsetX; -+ final double offsetY; -+ final double offsetZ; -+ // Tuinity end - optimise multi-aabb shapes -+ - protected VoxelShapeArray(VoxelShapeDiscrete voxelshapediscrete, double[] adouble, double[] adouble1, double[] adouble2) { - this(voxelshapediscrete, (DoubleList) DoubleArrayList.wrap(Arrays.copyOf(adouble, voxelshapediscrete.b() + 1)), (DoubleList) DoubleArrayList.wrap(Arrays.copyOf(adouble1, voxelshapediscrete.c() + 1)), (DoubleList) DoubleArrayList.wrap(Arrays.copyOf(adouble2, voxelshapediscrete.d() + 1))); - } - - VoxelShapeArray(VoxelShapeDiscrete voxelshapediscrete, DoubleList doublelist, DoubleList doublelist1, DoubleList doublelist2) { -+ // Tuinity start - optimise multi-aabb shapes -+ this(voxelshapediscrete, doublelist, doublelist1, doublelist2, null, null, 0.0, 0.0, 0.0); -+ } -+ VoxelShapeArray(VoxelShapeDiscrete voxelshapediscrete, DoubleList doublelist, DoubleList doublelist1, DoubleList doublelist2, VoxelShapeArray original, AxisAlignedBB[] boundingBoxesRepresentation, double offsetX, double offsetY, double offsetZ) { -+ // Tuinity end - optimise multi-aabb shapes - super(voxelshapediscrete); - int i = voxelshapediscrete.b() + 1; - int j = voxelshapediscrete.c() + 1; -@@ -27,6 +42,18 @@ public final class VoxelShapeArray extends VoxelShape { - } else { - throw (IllegalArgumentException) SystemUtils.c((Throwable) (new IllegalArgumentException("Lengths of point arrays must be consistent with the size of the VoxelShape."))); - } -+ // Tuinity start - optimise multi-aabb shapes -+ this.boundingBoxesRepresentation = boundingBoxesRepresentation == null ? this.getBoundingBoxesRepresentation().toArray(EMPTY) : boundingBoxesRepresentation; // Tuinity - optimise multi-aabb shapes -+ if (original == null) { -+ this.offsetX = offsetX; -+ this.offsetY = offsetY; -+ this.offsetZ = offsetZ; -+ } else { -+ this.offsetX = offsetX + original.offsetX; -+ this.offsetY = offsetY + original.offsetY; -+ this.offsetZ = offsetZ + original.offsetZ; -+ } -+ // Tuinity end - optimise multi-aabb shapes - } - - @Override -@@ -42,4 +69,63 @@ public final class VoxelShapeArray extends VoxelShape { - throw new IllegalArgumentException(); - } - } -+ -+ // Tuinity start - optimise multi-aabb shapes -+ @Override -+ public VoxelShape a(double d0, double d1, double d2) { -+ if (this == VoxelShapes.getEmptyShape() || this.boundingBoxesRepresentation.length == 0) { -+ return this; -+ } -+ return new VoxelShapeArray(this.a, new DoubleListOffset(this.a(EnumDirection.EnumAxis.X), d0), new DoubleListOffset(this.a(EnumDirection.EnumAxis.Y), d1), new DoubleListOffset(this.a(EnumDirection.EnumAxis.Z), d2), this, this.boundingBoxesRepresentation, d0, d1, d2); -+ } -+ -+ @Override -+ public List d() { // getBoundingBoxesRepresentation -+ if (this.boundingBoxesRepresentation == null) { -+ return super.d(); -+ } -+ List ret = new java.util.ArrayList<>(this.boundingBoxesRepresentation.length); -+ -+ double offX = this.offsetX; -+ double offY = this.offsetY; -+ double offZ = this.offsetZ; -+ for (AxisAlignedBB boundingBox : this.boundingBoxesRepresentation) { -+ ret.add(boundingBox.offset(offX, offY, offZ)); -+ } -+ -+ return ret; -+ } -+ -+ public final AxisAlignedBB[] getBoundingBoxesRepresentationRaw() { -+ return this.boundingBoxesRepresentation; -+ } -+ -+ public final double getOffsetX() { -+ return this.offsetX; -+ } -+ -+ public final double getOffsetY() { -+ return this.offsetY; -+ } -+ -+ public final double getOffsetZ() { -+ return this.offsetZ; -+ } -+ -+ public final boolean intersects(AxisAlignedBB axisalingedbb) { -+ // this can be optimised by checking an "overall shape" first, but not needed -+ double offX = this.offsetX; -+ double offY = this.offsetY; -+ double offZ = this.offsetZ; -+ -+ for (AxisAlignedBB boundingBox : this.boundingBoxesRepresentation) { -+ if (axisalingedbb.voxelShapeIntersect(boundingBox.minX + offX, boundingBox.minY + offY, boundingBox.minZ + offZ, -+ boundingBox.maxX + offX, boundingBox.maxY + offY, boundingBox.maxZ + offZ)) { -+ return true; -+ } -+ } -+ -+ return false; -+ } -+ // Tuinity end - optimise multi-aabb shapes - } -diff --git a/src/main/java/net/minecraft/server/VoxelShapeSpliterator.java b/src/main/java/net/minecraft/server/VoxelShapeSpliterator.java -index e841611bb7c36dffec44bb9e74a0a9657a113263..259605daabb18aedb15d56c78e6553ae2d22e13f 100644 ---- a/src/main/java/net/minecraft/server/VoxelShapeSpliterator.java -+++ b/src/main/java/net/minecraft/server/VoxelShapeSpliterator.java -@@ -91,7 +91,7 @@ public class VoxelShapeSpliterator extends AbstractSpliterator { - VoxelShape voxelshape = iblockdata.b((IBlockAccess) this.g, this.e, this.c); - - if (voxelshape == VoxelShapes.b()) { -- if (!this.b.a((double) i, (double) j, (double) k, (double) i + 1.0D, (double) j + 1.0D, (double) k + 1.0D)) { -+ if (!this.b.voxelShapeIntersect((double) i, (double) j, (double) k, (double) i + 1.0D, (double) j + 1.0D, (double) k + 1.0D)) { // Tuinity - keep vanilla behavior for voxelshape intersection - See comment in AxisAlignedBB - continue; - } - -diff --git a/src/main/java/net/minecraft/server/VoxelShapes.java b/src/main/java/net/minecraft/server/VoxelShapes.java -index e21c747b6c39155c44bf30860681d67b0b29fb12..636bbbc42466cb54c300352f400464fe64cc2e79 100644 ---- a/src/main/java/net/minecraft/server/VoxelShapes.java -+++ b/src/main/java/net/minecraft/server/VoxelShapes.java -@@ -17,18 +17,101 @@ public final class VoxelShapes { - - voxelshapebitset.a(0, 0, 0, true, true); - return new VoxelShapeCube(voxelshapebitset); -- }); -+ }); public static final VoxelShape getFullUnoptimisedCube() { return VoxelShapes.b; } // Tuinity - OBFHELPER - public static final VoxelShape a = create(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); -- private static final VoxelShape c = new VoxelShapeArray(new VoxelShapeBitSet(0, 0, 0), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D})); -+ private static final VoxelShape c = new VoxelShapeArray(new VoxelShapeBitSet(0, 0, 0), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D})); public static final VoxelShape getEmptyShape() { return VoxelShapes.c; } // Tuinity - OBFHELPER -+ -+ // Tuinity start - optimise voxelshapes -+ public static boolean isEmpty(VoxelShape voxelshape) { -+ // helper function for determining empty shapes fast -+ return voxelshape == getEmptyShape() || voxelshape.isEmpty(); -+ } -+ // Tuinity end - optimise voxelshapes - - public static final VoxelShape empty() {return a();} // Paper - OBFHELPER - public static VoxelShape a() { - return VoxelShapes.c; - } - -+ static final com.tuinity.tuinity.voxel.AABBVoxelShape optimisedFullCube = new com.tuinity.tuinity.voxel.AABBVoxelShape(new AxisAlignedBB(0, 0, 0, 1.0, 1.0, 1.0)); // Tuinity - optimise voxelshape -+ -+ // Tuinity start - optimise voxelshapes -+ public static boolean addBoxesToIfIntersects(VoxelShape shape, AxisAlignedBB aabb, java.util.List list) { -+ if (shape instanceof com.tuinity.tuinity.voxel.AABBVoxelShape) { -+ com.tuinity.tuinity.voxel.AABBVoxelShape shapeCasted = (com.tuinity.tuinity.voxel.AABBVoxelShape)shape; -+ if (!shapeCasted.aabb.isEmpty() && shapeCasted.aabb.voxelShapeIntersect(aabb)) { -+ list.add(shapeCasted.aabb); -+ return true; -+ } -+ return false; -+ } else if (shape instanceof VoxelShapeArray) { -+ VoxelShapeArray shapeCasted = (VoxelShapeArray)shape; -+ // this can be optimised by checking an "overall shape" first, but not needed -+ -+ double offX = shapeCasted.offsetX; -+ double offY = shapeCasted.offsetY; -+ double offZ = shapeCasted.offsetZ; -+ -+ boolean ret = false; -+ -+ for (AxisAlignedBB boundingBox : shapeCasted.boundingBoxesRepresentation) { -+ double minX, minY, minZ, maxX, maxY, maxZ; -+ if (aabb.voxelShapeIntersect(minX = boundingBox.minX + offX, minY = boundingBox.minY + offY, minZ = boundingBox.minZ + offZ, -+ maxX = boundingBox.maxX + offX, maxY = boundingBox.maxY + offY, maxZ = boundingBox.maxZ + offZ)) { -+ AxisAlignedBB box = new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ, false); -+ if (!box.isEmpty()) { -+ list.add(box); -+ ret = true; -+ } -+ } -+ } -+ -+ return ret; -+ } else { -+ boolean ret = false; -+ -+ java.util.List boxes = shape.getBoundingBoxesRepresentation(); -+ for (int i = 0, len = boxes.size(); i < len; ++i) { -+ AxisAlignedBB box = boxes.get(i); -+ if (!box.isEmpty() && box.voxelShapeIntersect(aabb)) { -+ list.add(box); -+ ret = true; -+ } -+ } -+ -+ return ret; -+ } -+ } -+ -+ public static void addBoxesTo(VoxelShape shape, java.util.List list) { -+ if (shape instanceof com.tuinity.tuinity.voxel.AABBVoxelShape) { -+ com.tuinity.tuinity.voxel.AABBVoxelShape shapeCasted = (com.tuinity.tuinity.voxel.AABBVoxelShape)shape; -+ if (!shapeCasted.isEmpty()) { -+ list.add(shapeCasted.aabb); -+ } -+ } else if (shape instanceof VoxelShapeArray) { -+ VoxelShapeArray shapeCasted = (VoxelShapeArray)shape; -+ -+ for (AxisAlignedBB boundingBox : shapeCasted.boundingBoxesRepresentation) { -+ if (!boundingBox.isEmpty()) { -+ list.add(boundingBox.offset(shapeCasted.offsetX, shapeCasted.offsetY, shapeCasted.offsetZ)); -+ } -+ } -+ } else { -+ java.util.List boxes = shape.getBoundingBoxesRepresentation(); -+ for (int i = 0, len = boxes.size(); i < len; ++i) { -+ AxisAlignedBB box = boxes.get(i); -+ if (!box.isEmpty()) { -+ list.add(box); -+ } -+ } -+ } -+ } -+ // Tuinity end - optimise voxelshapes -+ - public static final VoxelShape fullCube() {return b();} // Paper - OBFHELPER - public static VoxelShape b() { -- return VoxelShapes.b; -+ return VoxelShapes.optimisedFullCube; // Tuinity - optimise voxelshape - } - - public static VoxelShape create(double d0, double d1, double d2, double d3, double d4, double d5) { -@@ -67,7 +150,7 @@ public final class VoxelShapes { - return new VoxelShapeCube(voxelshapebitset); - } - } else { -- return new VoxelShapeArray(VoxelShapes.b.a, new double[]{axisalignedbb.minX, axisalignedbb.maxX}, new double[]{axisalignedbb.minY, axisalignedbb.maxY}, new double[]{axisalignedbb.minZ, axisalignedbb.maxZ}); -+ return new com.tuinity.tuinity.voxel.AABBVoxelShape(axisalignedbb); // Tuinity - optimise VoxelShapes for single AABB shapes - } - } - -@@ -132,6 +215,20 @@ public final class VoxelShapes { - - public static final boolean applyOperation(VoxelShape voxelshape, VoxelShape voxelshape1, OperatorBoolean operatorboolean) { return VoxelShapes.c(voxelshape, voxelshape1, operatorboolean); } // Paper - OBFHELPER - public static boolean c(VoxelShape voxelshape, VoxelShape voxelshape1, OperatorBoolean operatorboolean) { -+ // Tuinity start - optimise voxelshape -+ if (operatorboolean == OperatorBoolean.AND) { -+ if (voxelshape instanceof com.tuinity.tuinity.voxel.AABBVoxelShape && voxelshape1 instanceof com.tuinity.tuinity.voxel.AABBVoxelShape) { -+ return ((com.tuinity.tuinity.voxel.AABBVoxelShape)voxelshape).aabb.voxelShapeIntersect(((com.tuinity.tuinity.voxel.AABBVoxelShape)voxelshape1).aabb); -+ } else if (voxelshape instanceof com.tuinity.tuinity.voxel.AABBVoxelShape && voxelshape1 instanceof VoxelShapeArray) { -+ return ((VoxelShapeArray)voxelshape1).intersects(((com.tuinity.tuinity.voxel.AABBVoxelShape)voxelshape).aabb); -+ } else if (voxelshape1 instanceof com.tuinity.tuinity.voxel.AABBVoxelShape && voxelshape instanceof VoxelShapeArray) { -+ return ((VoxelShapeArray)voxelshape).intersects(((com.tuinity.tuinity.voxel.AABBVoxelShape)voxelshape1).aabb); -+ } -+ } -+ return abstract_c(voxelshape, voxelshape1, operatorboolean); -+ } -+ public static boolean abstract_c(VoxelShape voxelshape, VoxelShape voxelshape1, OperatorBoolean operatorboolean) { -+ // Tuinity end - optimise voxelshape - if (operatorboolean.apply(false, false)) { - throw (IllegalArgumentException) SystemUtils.c((Throwable) (new IllegalArgumentException())); - } else if (voxelshape == voxelshape1) { -@@ -314,8 +411,52 @@ public final class VoxelShapes { - } - } - -+ public static boolean combinationOccludes(VoxelShape voxelshape, VoxelShape voxelshape1) { return b(voxelshape, voxelshape1); } // Tuinity - OBFHELPER - public static boolean b(VoxelShape voxelshape, VoxelShape voxelshape1) { -- return voxelshape != b() && voxelshape1 != b() ? (voxelshape.isEmpty() && voxelshape1.isEmpty() ? false : !c(b(), b(voxelshape, voxelshape1, OperatorBoolean.OR), OperatorBoolean.ONLY_FIRST)) : true; -+ if (voxelshape == getFullUnoptimisedCube() || voxelshape == optimisedFullCube -+ || voxelshape1 == getFullUnoptimisedCube() || voxelshape1 == optimisedFullCube) { -+ return true; -+ } -+ boolean v1Empty = voxelshape == getEmptyShape(); -+ boolean v2Empty = voxelshape1 == getEmptyShape(); -+ if (v1Empty && v2Empty) { -+ return false; -+ } -+ if ((voxelshape instanceof com.tuinity.tuinity.voxel.AABBVoxelShape || v1Empty) && (voxelshape1 instanceof com.tuinity.tuinity.voxel.AABBVoxelShape || v2Empty)) { -+ if (!v1Empty && !v2Empty && (voxelshape != voxelshape1)) { -+ AxisAlignedBB boundingBox1 = ((com.tuinity.tuinity.voxel.AABBVoxelShape)voxelshape).aabb; -+ AxisAlignedBB boundingBox2 = ((com.tuinity.tuinity.voxel.AABBVoxelShape)voxelshape1).aabb; -+ // can call it here in some cases -+ -+ // check overall bounding box -+ double minY = Math.min(boundingBox1.minY, boundingBox2.minY); -+ double maxY = Math.max(boundingBox1.maxY, boundingBox2.maxY); -+ if (minY > MCUtil.COLLISION_EPSILON || maxY < (1 - MCUtil.COLLISION_EPSILON)) { -+ return false; -+ } -+ double minX = Math.min(boundingBox1.minX, boundingBox2.minX); -+ double maxX = Math.max(boundingBox1.maxX, boundingBox2.maxX); -+ if (minX > MCUtil.COLLISION_EPSILON || maxX < (1 - MCUtil.COLLISION_EPSILON)) { -+ return false; -+ } -+ double minZ = Math.min(boundingBox1.minZ, boundingBox2.minZ); -+ double maxZ = Math.max(boundingBox1.maxZ, boundingBox2.maxZ); -+ if (minZ > MCUtil.COLLISION_EPSILON || maxZ < (1 - MCUtil.COLLISION_EPSILON)) { -+ return false; -+ } -+ // fall through to full merge check -+ } else { -+ AxisAlignedBB boundingBox = v1Empty ? ((com.tuinity.tuinity.voxel.AABBVoxelShape)voxelshape1).aabb : ((com.tuinity.tuinity.voxel.AABBVoxelShape)voxelshape).aabb; -+ // check if the bounding box encloses the full cube -+ return (boundingBox.minY <= MCUtil.COLLISION_EPSILON && boundingBox.maxY >= (1 - MCUtil.COLLISION_EPSILON)) && -+ (boundingBox.minX <= MCUtil.COLLISION_EPSILON && boundingBox.maxX >= (1 - MCUtil.COLLISION_EPSILON)) && -+ (boundingBox.minZ <= MCUtil.COLLISION_EPSILON && boundingBox.maxZ >= (1 - MCUtil.COLLISION_EPSILON)); -+ } -+ } -+ return b_rare(voxelshape, voxelshape1); -+ } -+ public static boolean b_rare(VoxelShape voxelshape, VoxelShape voxelshape1) { -+ return (voxelshape != b() || voxelshape != getFullUnoptimisedCube()) && (voxelshape1 != b() || voxelshape1 != getFullUnoptimisedCube()) ? ((voxelshape == VoxelShapes.getEmptyShape() || voxelshape.isEmpty()) && (voxelshape1 == VoxelShapes.getEmptyShape() || voxelshape1.isEmpty()) ? false : !c(b(), b(voxelshape, voxelshape1, OperatorBoolean.OR), OperatorBoolean.ONLY_FIRST)) : true; // Tuinity - optimise call by checking against more constant shapes - } - - @VisibleForTesting -diff --git a/src/main/java/net/minecraft/server/WeightedList.java b/src/main/java/net/minecraft/server/WeightedList.java -index 5d9d58411f2fad9d5da703f964d269b4a7c2b205..f0fdfd6891e59891e7370a2d682b65c647b28e9e 100644 ---- a/src/main/java/net/minecraft/server/WeightedList.java -+++ b/src/main/java/net/minecraft/server/WeightedList.java -@@ -14,7 +14,7 @@ import java.util.stream.Stream; - - public class WeightedList { - -- protected final List> list; // Paper - decompile conflict -+ protected final List> list; public final List> getList() { return this.list; } // Paper - decompile conflict // Tuinity - OBFHELPER - private final Random b; - private final boolean isUnsafe; // Paper - -@@ -74,7 +74,7 @@ public class WeightedList { - - public static class a { - -- private final T a; -+ private final T a; public final T getValue() { return this.a; } // Tuinity - OBFHELPER - private final int b; - private double c; - -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index f5ab99156ce5429e63976183cbf115d5340a83a1..bf06ef09cfd4d7618365249d1332d264d8ff1377 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -94,6 +94,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper - public final ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray - -+ public final com.tuinity.tuinity.config.TuinityConfig.WorldConfig tuinityConfig; // Tuinity - Server Config -+ - public final co.aikar.timings.WorldTimingsHandler timings; // Paper - public static BlockPosition lastPhysicsProblem; // Spigot - private org.spigotmc.TickLimiter entityLimiter; -@@ -121,10 +123,70 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return typeKey; - } - -+ // Tuinity start - optimise checkDespawn -+ public final List getNearbyPlayers(@Nullable Entity source, double sourceX, double sourceY, double sourceZ, double maxRange, @Nullable Predicate predicate) { -+ Chunk chunk; -+ if (source == null || (chunk = source.getCurrentChunk()) == null || maxRange < 0.0 || maxRange >= PlayerChunkMap.GENERAL_AREA_MAP_ACCEPTABLE_SEARCH_RANGE) { -+ return this.getNearbyPlayersSlow(source, sourceX, sourceY, sourceZ, maxRange, predicate); -+ } -+ -+ List ret = new java.util.ArrayList<>(); -+ chunk.getNearestPlayers(sourceX, sourceY, sourceZ, predicate, maxRange, ret); -+ return ret; -+ } -+ -+ private List getNearbyPlayersSlow(@Nullable Entity source, double sourceX, double sourceY, double sourceZ, double maxRange, @Nullable Predicate predicate) { -+ List ret = new java.util.ArrayList<>(); -+ double maxRangeSquared = maxRange * maxRange; -+ -+ for (EntityPlayer player : (List)this.getPlayers()) { -+ if ((maxRange < 0.0 || player.getDistanceSquared(sourceX, sourceY, sourceZ) < maxRangeSquared)) { -+ if (predicate == null || predicate.test(player)) { -+ ret.add(player); -+ } -+ } -+ } -+ -+ return ret; -+ } -+ -+ private EntityPlayer getNearestPlayerSlow(@Nullable Entity source, double sourceX, double sourceY, double sourceZ, double maxRange, @Nullable Predicate predicate) { -+ EntityPlayer closest = null; -+ double closestRangeSquared = maxRange < 0.0 ? Double.MAX_VALUE : maxRange * maxRange; -+ -+ for (EntityPlayer player : (List)this.getPlayers()) { -+ double distanceSquared = player.getDistanceSquared(sourceX, sourceY, sourceZ); -+ if (distanceSquared < closestRangeSquared && (predicate == null || predicate.test(player))) { -+ closest = player; -+ closestRangeSquared = distanceSquared; -+ } -+ } -+ -+ return closest; -+ } -+ -+ -+ public final EntityPlayer getNearestPlayer(@Nullable Entity source, double sourceX, double sourceY, double sourceZ, double maxRange, @Nullable Predicate predicate) { -+ Chunk chunk; -+ if (source == null || (chunk = source.getCurrentChunk()) == null || maxRange < 0.0 || maxRange >= PlayerChunkMap.GENERAL_AREA_MAP_ACCEPTABLE_SEARCH_RANGE) { -+ return this.getNearestPlayerSlow(source, sourceX, sourceY, sourceZ, maxRange, predicate); -+ } -+ -+ return chunk.findNearestPlayer(sourceX, sourceY, sourceZ, maxRange, predicate); -+ } -+ -+ @Override -+ public @Nullable EntityHuman a(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { -+ return this.getNearestPlayer(null, d0, d1, d2, d3, predicate); -+ } -+ -+ // Tuinity end - optimise checkDespawn -+ - protected World(WorldDataMutable worlddatamutable, ResourceKey resourcekey, final DimensionManager dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper - this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((WorldDataServer) worlddatamutable).getName()); // Spigot - this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper - this.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this, executor) : ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray -+ this.tuinityConfig = new com.tuinity.tuinity.config.TuinityConfig.WorldConfig(((WorldDataServer)worlddatamutable).getName()); // Tuinity - Server Config - this.generator = gen; - this.world = new CraftWorld((WorldServer) this, gen, env); - this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit -@@ -286,6 +348,15 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - @Override - public final Chunk getChunkAt(int i, int j) { // Paper - final to help inline -+ // Tuinity start - make sure loaded chunks get the inlined variant of this function -+ ChunkProviderServer cps = ((WorldServer)this).chunkProvider; -+ if (cps.serverThread == Thread.currentThread()) { -+ Chunk ifLoaded = cps.getChunkAtIfLoadedMainThread(i, j); -+ if (ifLoaded != null) { -+ return ifLoaded; -+ } -+ } -+ // Tuinity end - make sure loaded chunks get the inlined variant of this function - return (Chunk) this.getChunkAt(i, j, ChunkStatus.FULL, true); // Paper - avoid a method jump - } - -@@ -360,6 +431,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - @Override - public boolean a(BlockPosition blockposition, IBlockData iblockdata, int i, int j) { -+ org.spigotmc.AsyncCatcher.catchOp("set type call"); // Tuinity - // CraftBukkit start - tree generation - if (this.captureTreeGeneration) { - // Paper start -@@ -461,6 +533,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - // CraftBukkit start - Split off from above in order to directly send client and physic updates - public void notifyAndUpdatePhysics(BlockPosition blockposition, Chunk chunk, IBlockData oldBlock, IBlockData newBlock, IBlockData actualBlock, int i, int j) { -+ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Async notify and update"); // Tuinity - IBlockData iblockdata = newBlock; - IBlockData iblockdata1 = oldBlock; - IBlockData iblockdata2 = actualBlock; -@@ -473,7 +546,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - this.notify(blockposition, iblockdata1, iblockdata, i); - // Paper start - per player view distance - allow block updates for non-ticking chunks in player view distance - // if copied from above -- } else if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || ((WorldServer)this).getChunkProvider().playerChunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(MCUtil.getCoordinateKey(blockposition)) != null)) { -+ } else if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || ((WorldServer)this).getChunkProvider().playerChunkMap.playerChunkManager.broadcastMap.getObjectsInRange(MCUtil.getCoordinateKey(blockposition)) != null)) { // Tuinity - replace old player chunk management - ((WorldServer)this).getChunkProvider().flagDirty(blockposition); - // Paper end - per player view distance - } -@@ -895,6 +968,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return; - // Paper end - } -+ MinecraftServer.getServer().executeMidTickTasks(); // Tuinity - execute chunk tasks mid tick - } - // Paper start - Prevent armor stands from doing entity lookups - @Override -@@ -1078,10 +1152,44 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return this.getChunkAt(i, j, ChunkStatus.FULL, false); - } - -+ // Tuinity start - optimise hard collision handling -+ @Override -+ public List getHardCollidingEntities(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate) { -+ return this.getHardCollidingEntities(entity, axisalignedbb, predicate, Lists.newArrayList()); -+ } -+ -+ public List getHardCollidingEntities(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate, List list) { -+ // copied from below -+ int i = MathHelper.floor((axisalignedbb.minX - 2.0D) / 16.0D); -+ int j = MathHelper.floor((axisalignedbb.maxX + 2.0D) / 16.0D); -+ int k = MathHelper.floor((axisalignedbb.minZ - 2.0D) / 16.0D); -+ int l = MathHelper.floor((axisalignedbb.maxZ + 2.0D) / 16.0D); -+ -+ ChunkProviderServer chunkProvider = ((WorldServer)this).getChunkProvider(); -+ -+ for (int i1 = i; i1 <= j; ++i1) { -+ for (int j1 = k; j1 <= l; ++j1) { -+ Chunk chunk = chunkProvider.getChunkAtIfLoadedMainThread(i1, j1); -+ -+ if (chunk != null) { -+ chunk.getHardCollidingEntities(entity, axisalignedbb, list, predicate); -+ } -+ } -+ } -+ -+ return list; -+ } -+ // Tuinity end - optimise hard collision handling -+ - @Override - public List getEntities(@Nullable Entity entity, AxisAlignedBB axisalignedbb, @Nullable Predicate predicate) { -- this.getMethodProfiler().c("getEntities"); -+ // Tuinity start - add list parameter - List list = Lists.newArrayList(); -+ return this.getEntities(entity, axisalignedbb, predicate, list); -+ } -+ public List getEntities(@Nullable Entity entity, AxisAlignedBB axisalignedbb, @Nullable Predicate predicate, List list) { -+ // Tuinity end - add list parameter -+ this.getMethodProfiler().c("getEntities"); - int i = MathHelper.floor((axisalignedbb.minX - 2.0D) / 16.0D); - int j = MathHelper.floor((axisalignedbb.maxX + 2.0D) / 16.0D); - int k = MathHelper.floor((axisalignedbb.minZ - 2.0D) / 16.0D); -@@ -1137,7 +1245,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper - - if (chunk != null) { -- chunk.a(oclass, axisalignedbb, list, predicate); -+ chunk.getEntitiesClass(oclass, null, axisalignedbb, (Predicate)predicate, (List)list); // Tuinity - optimise lookup by entity class - } - } - } -@@ -1160,7 +1268,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper - - if (chunk != null) { -- chunk.a(oclass, axisalignedbb, list, predicate); -+ chunk.getEntitiesClass(oclass, null, axisalignedbb, (Predicate)predicate, (List)list); // Tuinity - optimise lookup by entity class - } - } - } -@@ -1168,6 +1276,106 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return list; - } - -+ // Tuinity start -+ @Override -+ public T b(Class oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { -+ return this.getClosestEntity(oclass, pathfindertargetcondition, entityliving, d0, d1, d2, axisalignedbb); -+ } -+ -+ @Override -+ public T a(Class oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { -+ return this.getClosestEntity(oclass, pathfindertargetcondition, entityliving, d0, d1, d2, axisalignedbb); -+ } -+ -+ public final T getClosestEntity(Class clazz, -+ PathfinderTargetCondition condition, -+ @Nullable EntityLiving source, -+ double x, double y, double z, -+ AxisAlignedBB boundingBox) { -+ org.bukkit.craftbukkit.util.UnsafeList entities = com.tuinity.tuinity.util.CachedLists.getTempGetEntitiesList(); -+ try { -+ int lowerX = MCUtil.fastFloor((boundingBox.minX - 2.0D)) >> 4; -+ int upperX = MCUtil.fastFloor((boundingBox.maxX + 2.0D)) >> 4; -+ int lowerZ = MCUtil.fastFloor((boundingBox.minZ - 2.0D)) >> 4; -+ int upperZ = MCUtil.fastFloor((boundingBox.maxZ + 2.0D)) >> 4; -+ -+ org.bukkit.craftbukkit.util.UnsafeList chunks = com.tuinity.tuinity.util.CachedLists.getTempGetChunksList(); -+ try { -+ T closest = null; -+ double closestDistance = Double.MAX_VALUE; -+ ChunkProviderServer chunkProvider = ((WorldServer)this).getChunkProvider(); -+ -+ int centerX = (lowerX + upperX) >> 1; -+ int centerZ = (lowerZ + upperZ) >> 1; -+ // Copied from MCUtil.getSpiralOutChunks -+ Chunk temp; -+ if ((temp = chunkProvider.getChunkAtIfLoadedImmediately(centerX, centerZ)) != null && temp.hasEntitiesMaybe(clazz)) { -+ chunks.add(temp); -+ } -+ int radius = Math.max((upperX - lowerX + 1) >> 1, (upperZ - lowerZ + 1) >> 1); -+ for (int r = 1; r <= radius; r++) { -+ int ox = -r; -+ int oz = r; -+ -+ // Iterates the edge of half of the box; then negates for other half. -+ while (ox <= r && oz > -r) { -+ { -+ int cx = centerX + ox; -+ int cz = centerZ + oz; -+ if (cx >= lowerX && cx <= upperX && cz >= lowerZ && cz <= upperZ && -+ (temp = chunkProvider.getChunkAtIfLoadedImmediately(cx, cz)) != null && -+ temp.hasEntitiesMaybe(clazz)) { -+ chunks.add(temp); -+ } -+ } -+ { -+ int cx = centerX - ox; -+ int cz = centerZ - oz; -+ if (cx >= lowerX && cx <= upperX && cz >= lowerZ && cz <= upperZ && -+ (temp = chunkProvider.getChunkAtIfLoadedImmediately(cx, cz)) != null && -+ temp.hasEntitiesMaybe(clazz)) { -+ chunks.add(temp); -+ } -+ } -+ -+ if (ox < r) { -+ ox++; -+ } else { -+ oz--; -+ } -+ } -+ } -+ -+ Object[] chunkData = chunks.getRawDataArray(); -+ for (int cindex = 0, clen = chunks.size(); cindex < clen; ++cindex) { -+ final Chunk chunk = (Chunk)chunkData[cindex]; -+ -+ chunk.getEntitiesClass(clazz, source, boundingBox, null, entities); -+ -+ Object[] entityData = entities.getRawDataArray(); -+ for (int eindex = 0, entities_len = entities.size(); eindex < entities_len; ++eindex) { -+ T entity = (T)entityData[eindex]; -+ double distance = entity.getDistanceSquared(x, y, z); -+ // check distance first, as it's the least expensive -+ if (distance < closestDistance && condition.test(source, entity)) { -+ closest = entity; -+ closestDistance = distance; -+ } -+ } -+ -+ entities.setSize(0); -+ } -+ -+ return closest; -+ } finally { -+ com.tuinity.tuinity.util.CachedLists.returnTempGetChunksList(chunks); -+ } -+ } finally { -+ com.tuinity.tuinity.util.CachedLists.returnTempGetEntitiesList(entities); -+ } -+ } -+ // Tuinity end -+ - @Nullable - public abstract Entity getEntity(int i); - -diff --git a/src/main/java/net/minecraft/server/WorldBorder.java b/src/main/java/net/minecraft/server/WorldBorder.java -index 6e82c1d1b272a95144bfc78d34b630c24466fa3e..6b4c007550c3e2e405314d8931630557655ce6f1 100644 ---- a/src/main/java/net/minecraft/server/WorldBorder.java -+++ b/src/main/java/net/minecraft/server/WorldBorder.java -@@ -50,11 +50,59 @@ public class WorldBorder { - return axisalignedbb.maxX > this.e() && axisalignedbb.minX < this.g() && axisalignedbb.maxZ > this.f() && axisalignedbb.minZ < this.h(); - } - -+ // Tuinity start - optimise collisions -+ // determines whether we are almost colliding with the world border -+ // for clear collisions, this rets false -+ public final boolean isAlmostCollidingOnBorder(AxisAlignedBB boundingBox) { -+ return this.isAlmostCollidingOnBorder(boundingBox.minX, boundingBox.maxX, boundingBox.minZ, boundingBox.maxZ); -+ } -+ -+ public final boolean isAlmostCollidingOnBorder(double boxMinX, double boxMaxX, double boxMinZ, double boxMaxZ) { -+ double borderMinX = this.getMinX(); -+ double borderMaxX = this.getMaxX(); -+ -+ double borderMinZ = this.getMinZ(); -+ double borderMaxZ = this.getMaxZ(); -+ -+ return -+ // Not intersecting if we're smaller -+ !AxisAlignedBB.voxelShapeIntersect( -+ boxMinX + MCUtil.COLLISION_EPSILON, Double.NEGATIVE_INFINITY, boxMinZ + MCUtil.COLLISION_EPSILON, -+ boxMaxX - MCUtil.COLLISION_EPSILON, Double.POSITIVE_INFINITY, boxMaxZ - MCUtil.COLLISION_EPSILON, -+ borderMinX, Double.NEGATIVE_INFINITY, borderMinZ, borderMaxX, Double.POSITIVE_INFINITY, borderMaxZ -+ ) -+ && -+ -+ // Are intersecting if we're larger -+ AxisAlignedBB.voxelShapeIntersect( -+ boxMinX - MCUtil.COLLISION_EPSILON, Double.NEGATIVE_INFINITY, boxMinZ - MCUtil.COLLISION_EPSILON, -+ boxMaxX + MCUtil.COLLISION_EPSILON, Double.POSITIVE_INFINITY, boxMaxZ + MCUtil.COLLISION_EPSILON, -+ borderMinX, Double.NEGATIVE_INFINITY, borderMinZ, borderMaxX, Double.POSITIVE_INFINITY, borderMaxZ -+ ) -+ ; -+ } -+ -+ public final boolean isCollidingWithBorderEdge(AxisAlignedBB boundingBox) { -+ return this.isCollidingWithBorderEdge(boundingBox.minX, boundingBox.maxX, boundingBox.minZ, boundingBox.maxZ); -+ } -+ -+ public final boolean isCollidingWithBorderEdge(double boxMinX, double boxMaxX, double boxMinZ, double boxMaxZ) { -+ double borderMinX = this.getMinX() + MCUtil.COLLISION_EPSILON; -+ double borderMaxX = this.getMaxX() - MCUtil.COLLISION_EPSILON; -+ -+ double borderMinZ = this.getMinZ() + MCUtil.COLLISION_EPSILON; -+ double borderMaxZ = this.getMaxZ() - MCUtil.COLLISION_EPSILON; -+ -+ return boxMinX < borderMinX || boxMaxX > borderMaxX || boxMinZ < borderMinZ || boxMaxZ > borderMaxZ; -+ } -+ // Tuinity end - optimise collisions -+ - public double a(Entity entity) { - return this.b(entity.locX(), entity.locZ()); - } - - public final VoxelShape asVoxelShape(){ return c();} // Paper - OBFHELPER -+ public final VoxelShape getCollisionShape() { return this.c(); } // Tuinity - OBFHELPER - public VoxelShape c() { - return this.j.m(); - } -@@ -70,18 +118,22 @@ public class WorldBorder { - return Math.min(d6, d3); - } - -+ public final double getMinX() { return this.e(); } // Tuinity - OBFHELPER - public double e() { - return this.j.a(); - } - -+ public final double getMinZ() { return this.f(); } // Tuinity - OBFHELPER - public double f() { - return this.j.c(); - } - -+ public final double getMaxX() { return this.g(); } // Tuinity - OBFHELPER - public double g() { - return this.j.b(); - } - -+ public final double getMaxZ() { return this.h(); } // Tuinity - OBFHELPER - public double h() { - return this.j.d(); - } -diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc7fd51eea 100644 ---- a/src/main/java/net/minecraft/server/WorldServer.java -+++ b/src/main/java/net/minecraft/server/WorldServer.java -@@ -55,12 +55,13 @@ import org.bukkit.event.server.MapInitializeEvent; +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 0a698a5a4a6502a488c9afb0ad97165e60030896..46f960b9276dced41deb8f741454b6cce5a81529 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -168,12 +168,13 @@ import org.bukkit.event.server.MapInitializeEvent; import org.bukkit.event.weather.LightningStrikeEvent; import org.bukkit.event.world.TimeSkipEvent; // CraftBukkit end @@ -19005,7 +14106,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc private final Map entitiesByUUID = Maps.newHashMap(); private final Queue entitiesToAdd = Queues.newArrayDeque(); public final List players = Lists.newArrayList(); // Paper - private -> public -@@ -84,7 +85,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -197,7 +198,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { private final PortalTravelAgent portalTravelAgent; private final TickListServer nextTickListBlock; private final TickListServer nextTickListFluid; @@ -19014,7 +14115,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc protected final PersistentRaid persistentRaid; private final ObjectLinkedOpenHashSet L; private boolean ticking; -@@ -206,6 +207,208 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -319,6 +320,208 @@ public class WorldServer extends World implements GeneratorAccessSeed { } // Paper end - rewrite ticklistserver @@ -19109,14 +14210,14 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc + // Tuinity end + + // Tuinity start - execute chunk tasks mid tick -+ long lastMidTickExecuteFailure; ++ public long lastMidTickExecuteFailure; + // Tuinity end - execute chunk tasks mid tick + + // Tuinity start - optimise checkDespawn -+ final List playersAffectingSpawning = new java.util.ArrayList<>(); ++ public final List playersAffectingSpawning = new java.util.ArrayList<>(); + // Tuinity end - optimise checkDespawn + // Tuinity start - optimise get nearest players for entity AI -+ public final EntityPlayer getNearestPlayer(PathfinderTargetCondition condition, @Nullable EntityLiving source, ++ public final EntityPlayer getNearestPlayer(net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition condition, @Nullable EntityLiving source, + double centerX, double centerY, double centerZ) { + com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet nearby; + if (source != null) { @@ -19158,22 +14259,22 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc + } + + @Override -+ public EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving) { ++ public EntityHuman a(net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving) { + return this.getNearestPlayer(pathfindertargetcondition, entityliving, entityliving.locX(), entityliving.locY(), entityliving.locZ()); + } + + @Override -+ public EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2) { ++ public EntityHuman a(net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2) { + return this.getNearestPlayer(pathfindertargetcondition, entityliving, d0, d1, d2); + } + + @Override -+ public EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, double d0, double d1, double d2) { ++ public EntityHuman a(net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition pathfindertargetcondition, double d0, double d1, double d2) { + return this.getNearestPlayer(pathfindertargetcondition, null, d0, d1, d2); + } + + @Override -+ public List a(PathfinderTargetCondition condition, EntityLiving source, AxisAlignedBB axisalignedbb) { ++ public List a(net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition condition, EntityLiving source, AxisAlignedBB axisalignedbb) { + com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet nearby; + double centerX = (axisalignedbb.maxX + axisalignedbb.minX) * 0.5; + double centerZ = (axisalignedbb.maxZ + axisalignedbb.minZ) * 0.5; @@ -19223,7 +14324,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc // Add env and gen to constructor, WorldData -> WorldDataServer public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor -@@ -266,6 +469,251 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -379,6 +582,251 @@ public class WorldServer extends World implements GeneratorAccessSeed { this.asyncChunkTaskManager = new com.destroystokyo.paper.io.chunk.ChunkTaskManager(this); // Paper } @@ -19307,7 +14408,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc + + + BlockPosition.MutableBlockPosition mutablePos = new BlockPosition.MutableBlockPosition(); -+ VoxelShapeCollision collisionShape = null; ++ net.minecraft.world.phys.shapes.VoxelShapeCollision collisionShape = null; + + // special cases: + if (minBlockY > 255 || maxBlockY < 0) { @@ -19364,7 +14465,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc + continue; + } + -+ DataPaletteBlock blocks = section.blockIds; ++ net.minecraft.world.level.chunk.DataPaletteBlock blocks = section.blockIds; + + for (int currZ = minZ; currZ <= maxZ; ++currZ) { + for (int currX = minX; currX <= maxX; ++currX) { @@ -19385,7 +14486,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc + if ((edgeCount != 1 || blockData.shapeExceedsCube()) && (edgeCount != 2 || blockData.getBlock() == Blocks.MOVING_PISTON)) { + mutablePos.setValues(blockX, blockY, blockZ); + if (collisionShape == null) { -+ collisionShape = entity == null ? VoxelShapeCollision.a() : VoxelShapeCollision.a(entity); ++ collisionShape = entity == null ? net.minecraft.world.phys.shapes.VoxelShapeCollision.a() : net.minecraft.world.phys.shapes.VoxelShapeCollision.a(entity); + } + VoxelShape voxelshape2 = blockData.getCollisionShape(this, mutablePos, collisionShape); + if (voxelshape2 != VoxelShapes.getEmptyShape()) { @@ -19461,28 +14562,28 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc + + @Override + public boolean getCubes(@Nullable Entity entity, AxisAlignedBB axisalignedbb) { -+ if (entity instanceof EntityArmorStand && !entity.world.paperConfig.armorStandEntityLookups) return false; ++ if (entity instanceof net.minecraft.world.entity.decoration.EntityArmorStand && !entity.world.paperConfig.armorStandEntityLookups) return false; + return !this.hasAnyCollisions(entity, axisalignedbb); + } + + @Override + public boolean getCubes(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate) { -+ if (entity instanceof EntityArmorStand && !entity.world.paperConfig.armorStandEntityLookups) return false; ++ if (entity instanceof net.minecraft.world.entity.decoration.EntityArmorStand && !entity.world.paperConfig.armorStandEntityLookups) return false; + return !this.collidesWithAnyBlockOrWorldBorder(entity, axisalignedbb, true, true) && !this.hardCollidesWithAnyEntities(entity, axisalignedbb, predicate); + } + // Tuinity end - optimise collision + // CraftBukkit start @Override - protected TileEntity getTileEntity(BlockPosition pos, boolean validate) { -@@ -319,6 +767,14 @@ public class WorldServer extends World implements GeneratorAccessSeed { + public TileEntity getTileEntity(BlockPosition pos, boolean validate) { +@@ -432,6 +880,14 @@ public class WorldServer extends World implements GeneratorAccessSeed { public void doTick(BooleanSupplier booleansupplier) { GameProfilerFiller gameprofilerfiller = this.getMethodProfiler(); + // Tuinity start - optimise checkDespawn + this.playersAffectingSpawning.clear(); + for (EntityPlayer player : this.getPlayers()) { -+ if (IEntitySelector.affectsSpawning.test(player)) { ++ if (net.minecraft.world.entity.IEntitySelector.affectsSpawning.test(player)) { + this.playersAffectingSpawning.add(player); + } + } @@ -19490,7 +14591,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc this.ticking = true; gameprofilerfiller.enter("world border"); -@@ -468,7 +924,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -581,7 +1037,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { } timings.scheduledBlocks.stopTiming(); // Paper @@ -19499,7 +14600,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc gameprofilerfiller.exitEnter("raid"); this.timings.raids.startTiming(); // Paper - timings this.persistentRaid.a(); -@@ -477,7 +933,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -590,7 +1046,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { timings.doSounds.startTiming(); // Spigot this.ak(); timings.doSounds.stopTiming(); // Spigot @@ -19508,7 +14609,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc this.ticking = false; gameprofilerfiller.exitEnter("entities"); boolean flag3 = true || !this.players.isEmpty() || !this.getForceLoadedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players -@@ -493,13 +949,12 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -606,13 +1062,12 @@ public class WorldServer extends World implements GeneratorAccessSeed { } this.tickingEntities = true; @@ -19524,7 +14625,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc Entity entity1 = entity.getVehicle(); /* CraftBukkit start - We prevent spawning in general, so this butchering is not needed -@@ -515,6 +970,15 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -628,6 +1083,15 @@ public class WorldServer extends World implements GeneratorAccessSeed { gameprofilerfiller.enter("checkDespawn"); if (!entity.dead) { entity.checkDespawn(); @@ -19540,7 +14641,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc } gameprofilerfiller.exit(); -@@ -535,14 +999,22 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -648,14 +1112,22 @@ public class WorldServer extends World implements GeneratorAccessSeed { gameprofilerfiller.enter("remove"); if (entity.dead) { this.removeEntityFromChunk(entity); @@ -19564,7 +14665,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc this.tickingEntities = false; // Paper start for (java.lang.Runnable run : this.afterEntityTickingTasks) { -@@ -554,7 +1026,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -667,7 +1139,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { } this.afterEntityTickingTasks.clear(); // Paper end @@ -19573,7 +14674,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc Entity entity2; -@@ -564,7 +1036,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -677,7 +1149,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { } timings.tickEntities.stopTiming(); // Spigot @@ -19582,7 +14683,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc this.tickBlockEntities(); } -@@ -611,6 +1083,9 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -724,6 +1196,9 @@ public class WorldServer extends World implements GeneratorAccessSeed { private final BlockPosition.MutableBlockPosition chunkTickMutablePosition = new BlockPosition.MutableBlockPosition(); private final com.destroystokyo.paper.util.math.ThreadUnsafeRandom randomTickRandom = new com.destroystokyo.paper.util.math.ThreadUnsafeRandom(); // Paper end @@ -19592,7 +14693,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc public void a(Chunk chunk, int i) { final int randomTickSpeed = i; // Paper ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); -@@ -648,28 +1123,32 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -761,28 +1236,32 @@ public class WorldServer extends World implements GeneratorAccessSeed { gameprofilerfiller.exitEnter("iceandsnow"); if (!this.paperConfig.disableIceAndSnow && this.randomTickRandom.nextInt(16) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking // Paper start - optimise chunk ticking @@ -19625,11 +14726,11 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc // Paper start - optimise chunk ticking blockposition.setY(downY); - if (flag && this.getBiome(blockposition).c() == BiomeBase.Precipitation.RAIN) { -+ if (flag && chunk.getType(blockposition).getBlock() instanceof BlockCauldron && this.getBiome(blockposition).c() == BiomeBase.Precipitation.RAIN) { // Tuinity - only cauldron uses that method, and it's not likely to hit. So, avoid the expensive biome lookup and replace it with a block lookup TODO check on update for overrides ++ if (flag && chunk.getType(blockposition).getBlock() instanceof net.minecraft.world.level.block.BlockCauldron && this.getBiome(blockposition).c() == BiomeBase.Precipitation.RAIN) { // Tuinity - only cauldron uses that method, and it's not likely to hit. So, avoid the expensive biome lookup and replace it with a block lookup TODO check on update for overrides chunk.getType(blockposition).getBlock().c((World) this, blockposition); // Paper end } -@@ -715,7 +1194,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -828,7 +1307,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { } gameprofilerfiller.exit(); timings.chunkTicksBlocks.stopTiming(); // Paper @@ -19638,7 +14739,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc // Paper end } } -@@ -810,7 +1289,26 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -923,7 +1402,26 @@ public class WorldServer extends World implements GeneratorAccessSeed { } @@ -19665,7 +14766,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc if (!(entity instanceof EntityHuman) && !this.getChunkProvider().a(entity)) { this.chunkCheck(entity); } else { -@@ -863,6 +1361,13 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -976,6 +1474,13 @@ public class WorldServer extends World implements GeneratorAccessSeed { //} finally { timer.stopTiming(); } // Paper - timings - move up } @@ -19679,7 +14780,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc } public void a(Entity entity, Entity entity1) { -@@ -921,6 +1426,12 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -1034,6 +1539,12 @@ public class WorldServer extends World implements GeneratorAccessSeed { int i = MathHelper.floor(entity.locX() / 16.0D); int j = Math.min(15, Math.max(0, MathHelper.floor(entity.locY() / 16.0D))); // Paper - stay consistent with chunk add/remove behavior int k = MathHelper.floor(entity.locZ() / 16.0D); @@ -19692,7 +14793,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc if (!entity.inChunk || entity.chunkX != i || entity.chunkY != j || entity.chunkZ != k) { // Paper start - remove entity if its in a chunk more correctly. -@@ -930,6 +1441,12 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -1043,6 +1554,12 @@ public class WorldServer extends World implements GeneratorAccessSeed { } // Paper end @@ -19705,7 +14806,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc if (entity.inChunk && this.isChunkLoaded(entity.chunkX, entity.chunkZ)) { this.getChunkAt(entity.chunkX, entity.chunkZ).a(entity, entity.chunkY); } -@@ -941,8 +1458,41 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -1054,8 +1571,41 @@ public class WorldServer extends World implements GeneratorAccessSeed { entity.inChunk = false; } else { @@ -19748,22 +14849,23 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc } this.getMethodProfiler().exit(); -@@ -1279,9 +1829,13 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -1392,10 +1942,14 @@ public class WorldServer extends World implements GeneratorAccessSeed { // Spigot Start for (TileEntity tileentity : chunk.getTileEntities().values()) { - if (tileentity instanceof IInventory) { + if (tileentity instanceof net.minecraft.world.IInventory) { + // Tuinity start - this area looks like it can load chunks, change the behavior + // chests for example can apply physics to the world + // so instead we just change the active container and call the event - for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((IInventory) tileentity).getViewers())) { + for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((net.minecraft.world.IInventory) tileentity).getViewers())) { - h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper -+ ((org.bukkit.craftbukkit.entity.CraftHumanEntity)h).getHandle().closeUnloadedInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper ++ ((org.bukkit.craftbukkit.entity.CraftHumanEntity) h).getHandle().closeUnloadedInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper } -+ // Tuiniy end } ++ // Tuiniy end } // Spigot End -@@ -1298,7 +1852,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + this.tileEntityListUnload.addAll(chunk.getTileEntities().values()); +@@ -1411,7 +1965,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { Entity entity = (Entity) iterator.next(); if (!(entity instanceof EntityPlayer)) { @@ -19772,7 +14874,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc throw (IllegalStateException) SystemUtils.c((Throwable) (new IllegalStateException("Removing entity while ticking!"))); } -@@ -1326,6 +1880,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -1439,6 +1993,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { public void unregisterEntity(Entity entity) { org.spigotmc.AsyncCatcher.catchOp("entity unregister"); // Spigot @@ -19780,7 +14882,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc // Paper start - fix entity registration issues if (entity instanceof EntityComplexPart) { // Usually this is a no-op for complex parts, and ID's should be removed, but go ahead and remove it anyways -@@ -1392,17 +1947,76 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -1505,17 +2060,76 @@ public class WorldServer extends World implements GeneratorAccessSeed { this.getScoreboard().a(entity); // CraftBukkit start - SPIGOT-5278 if (entity instanceof EntityDrowned) { @@ -19860,7 +14962,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc private void registerEntity(Entity entity) { org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot // Paper start - don't double enqueue entity registration -@@ -1413,7 +2027,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -1526,7 +2140,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { return; } // Paper end @@ -19869,7 +14971,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc if (!entity.isQueuedForRegister) { // Paper this.entitiesToAdd.add(entity); entity.isQueuedForRegister = true; // Paper -@@ -1421,6 +2035,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -1534,6 +2148,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { } else { entity.isQueuedForRegister = false; // Paper this.entitiesById.put(entity.getId(), entity); @@ -19877,7 +14979,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc if (entity instanceof EntityEnderDragon) { EntityComplexPart[] aentitycomplexpart = ((EntityEnderDragon) entity).eJ(); int i = aentitycomplexpart.length; -@@ -1429,6 +2044,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -1542,6 +2157,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { EntityComplexPart entitycomplexpart = aentitycomplexpart[j]; this.entitiesById.put(entitycomplexpart.getId(), entitycomplexpart); @@ -19885,7 +14987,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc } } -@@ -1453,12 +2069,16 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -1566,12 +2182,16 @@ public class WorldServer extends World implements GeneratorAccessSeed { // this.getChunkProvider().addEntity(entity); // Paper - moved down below valid=true // CraftBukkit start - SPIGOT-5278 if (entity instanceof EntityDrowned) { @@ -19905,7 +15007,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc } entity.valid = true; // CraftBukkit this.getChunkProvider().addEntity(entity); // Paper - from above to be below valid=true -@@ -1474,7 +2094,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -1587,7 +2207,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { } public void removeEntity(Entity entity) { @@ -19914,7 +15016,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc throw (IllegalStateException) SystemUtils.c((Throwable) (new IllegalStateException("Removing entity while ticking!"))); } else { this.removeEntityFromChunk(entity); -@@ -1570,20 +2190,33 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -1683,20 +2303,33 @@ public class WorldServer extends World implements GeneratorAccessSeed { @Override public void notify(BlockPosition blockposition, IBlockData iblockdata, IBlockData iblockdata1, int i) { @@ -19950,7 +15052,7 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc } catch (java.util.ConcurrentModificationException ex) { // This can happen because the pathfinder update below may trigger a chunk load, which in turn may cause more navigators to register // In this case we just run the update again across all the iterators as the chunk will then be loaded -@@ -1597,6 +2230,9 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -1710,6 +2343,9 @@ public class WorldServer extends World implements GeneratorAccessSeed { navigationabstract.b(blockposition); } } @@ -19960,11 +15062,356 @@ index cf7d94aabab600822eb5e27f38690b06456d5fcc..18d21f21c10974d21d17abe2f9319cdc this.tickingEntities = wasTicking; // Paper } -diff --git a/src/main/java/net/minecraft/server/WorldUpgrader.java b/src/main/java/net/minecraft/server/WorldUpgrader.java -index 5ccdc0b87b922724c3dd3085860c55d4959ca0b4..888dae2d5ee8a71e83dd24e5f3c6bc8513016f9d 100644 ---- a/src/main/java/net/minecraft/server/WorldUpgrader.java -+++ b/src/main/java/net/minecraft/server/WorldUpgrader.java -@@ -218,7 +218,7 @@ public class WorldUpgrader { +diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java +index 185667110cd6f566b23546728d20fc79223f3c92..dc98ef48a664d9ee2a302fff8c611fd16dc704b6 100644 +--- a/src/main/java/net/minecraft/server/network/LoginListener.java ++++ b/src/main/java/net/minecraft/server/network/LoginListener.java +@@ -255,7 +255,7 @@ public class LoginListener implements PacketLoginInListener { + + s = (new BigInteger(MinecraftEncryption.a("", this.server.getKeyPair().getPublic(), this.loginKey))).toString(16); + this.g = LoginListener.EnumProtocolState.AUTHENTICATING; +- this.networkManager.a(cipher, cipher1); ++ this.networkManager.a(this.loginKey); // Tuinity + } catch (CryptographyException cryptographyexception) { + throw new IllegalStateException("Protocol error", cryptographyexception); + } +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index a15230235ba0244c42346f51cabb470cb362a455..b7e72fe1cd04219391c75beb7d67a1e32e393a16 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -568,7 +568,9 @@ public class PlayerConnection implements PacketListenerPlayIn { + speed *= 2f; // TODO: Get the speed of the vehicle instead of the player + + // Paper start - Prevent moving into unloaded chunks +- if (player.world.paperConfig.preventMovingIntoUnloadedChunks && worldserver.getChunkIfLoadedImmediately((int) Math.floor(packetplayinvehiclemove.getX()) >> 4, (int) Math.floor(packetplayinvehiclemove.getZ()) >> 4) == null) { ++ if (player.world.paperConfig.preventMovingIntoUnloadedChunks // Tuinity - improve this check ++ && (!worldserver.areChunksLoadedForMove(this.player.getBoundingBoxAt(this.player.locX(), this.player.locY(), this.player.locZ()).expand(toX - this.player.locX(), toY - this.player.locY(), toZ - this.player.locZ()))) // Tuinity - improve this check ++ || !worldserver.areChunksLoadedForMove(entity.getBoundingBoxAt(entity.locX(), entity.locY(), entity.locZ()).expand(toX - entity.locX(), toY - entity.locY(), toZ - entity.locZ()))) { // Tuinity - improve this check + this.networkManager.sendPacket(new PacketPlayOutVehicleMove(entity)); + return; + } +@@ -581,12 +583,14 @@ public class PlayerConnection implements PacketListenerPlayIn { + return; + } + +- boolean flag = worldserver.getCubes(entity, entity.getBoundingBox().shrink(0.0625D)); ++ //boolean flag = worldserver.getCubes(entity, entity.getBoundingBox().shrink(0.0625D)); // Tuinity - replace with different checks ++ AxisAlignedBB oldBox = entity.getBoundingBox(); // Tuinity - copy from player movement packet + + d6 = d3 - this.v; + d7 = d4 - this.w - 1.0E-6D; + d8 = d5 - this.x; + entity.move(EnumMoveType.PLAYER, new Vec3D(d6, d7, d8)); ++ boolean didCollide = toX != entity.locX() || toY != entity.locY() || toZ != entity.locZ(); // Tuinity - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be... + double d11 = d7; + + d6 = d3 - entity.locX(); +@@ -600,16 +604,25 @@ public class PlayerConnection implements PacketListenerPlayIn { + boolean flag1 = false; + + if (d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot +- flag1 = true; ++ flag1 = true; // Tuinity - diff on change, this should be moved wrongly + PlayerConnection.LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", entity.getDisplayName().getString(), this.player.getDisplayName().getString(), Math.sqrt(d10)); + } + Location curPos = this.getPlayer().getLocation(); // Spigot + + entity.setLocation(d3, d4, d5, f, f1); + player.setLocation(d3, d4, d5, this.player.yaw, this.player.pitch); // CraftBukkit +- boolean flag2 = worldserver.getCubes(entity, entity.getBoundingBox().shrink(0.0625D)); +- +- if (flag && (flag1 || !flag2)) { ++ //boolean flag2 = worldserver.getCubes(entity, entity.getBoundingBox().shrink(0.0625D)); // Tuinity - replace with different checks ++ ++ // Tuinity start - optimise out extra getCubes ++ boolean teleportBack = flag1; // violating this is always a fail ++ if (!teleportBack) { ++ // note: only call after setLocation, or else getBoundingBox is wrong ++ AxisAlignedBB newBox = entity.getBoundingBox(); ++ if (didCollide || !oldBox.equals(newBox)) { ++ teleportBack = this.hasNewCollision(worldserver, entity, oldBox, newBox); ++ } // else: no collision at all detected, why do we care? ++ } ++ if (teleportBack) { // Tuinity end - optimise out extra getCubes + entity.setLocation(d0, d1, d2, f, f1); + player.setLocation(d0, d1, d2, this.player.yaw, this.player.pitch); // CraftBukkit + this.networkManager.sendPacket(new PacketPlayOutVehicleMove(entity)); +@@ -695,7 +708,32 @@ public class PlayerConnection implements PacketListenerPlayIn { + } + + private boolean a(Entity entity) { +- return entity.world.a(entity.getBoundingBox().g(0.0625D).b(0.0D, -0.55D, 0.0D)).allMatch(BlockBase.BlockData::isAir); ++ // Tuinity start - stop using streams, this is already a known fixed problem in Entity#move ++ AxisAlignedBB box = entity.getBoundingBox().g(0.0625D).b(0.0D, -0.55D, 0.0D); ++ int minX = MathHelper.floor(box.minX); ++ int minY = MathHelper.floor(box.minY); ++ int minZ = MathHelper.floor(box.minZ); ++ int maxX = MathHelper.floor(box.maxX); ++ int maxY = MathHelper.floor(box.maxY); ++ int maxZ = MathHelper.floor(box.maxZ); ++ ++ World world = entity.world; ++ BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(); ++ ++ for (int y = minY; y <= maxY; ++y) { ++ for (int z = minZ; z <= maxZ; ++z) { ++ for (int x = minX; x <= maxX; ++x) { ++ pos.setValues(x, y, z); ++ IBlockData type = world.getTypeIfLoaded(pos); ++ if (type != null && !type.isAir()) { ++ return false; ++ } ++ } ++ } ++ } ++ ++ return true; ++ // Tuinity end - stop using streams, this is already a known fixed problem in Entity#move + } + + @Override +@@ -1217,7 +1255,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + } + + if (this.teleportPos != null) { +- if (this.e - this.A > 20) { ++ if (false && this.e - this.A > 20) { // Tuinity - this will greatly screw with clients with > 1000ms RTT + this.A = this.e; + this.a(this.teleportPos.x, this.teleportPos.y, this.teleportPos.z, this.player.yaw, this.player.pitch); + } +@@ -1287,7 +1325,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + speed = player.abilities.walkSpeed * 10f; + } + // Paper start - Prevent moving into unloaded chunks +- if (player.world.paperConfig.preventMovingIntoUnloadedChunks && (this.player.locX() != toX || this.player.locZ() != toZ) && worldserver.getChunkIfLoadedImmediately((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4) == null) { // Paper - use getIfLoadedImmediately ++ if (player.world.paperConfig.preventMovingIntoUnloadedChunks && !((WorldServer)this.player.world).areChunksLoadedForMove(this.player.getBoundingBoxAt(this.player.locX(), this.player.locY(), this.player.locZ()).expand(toX - this.player.locX(), toY - this.player.locY(), toZ - this.player.locZ()))) { // Paper - use getIfLoadedImmediately // Tuinity - improve this check + this.internalTeleport(this.player.locX(), this.player.locY(), this.player.locZ(), this.player.yaw, this.player.pitch, Collections.emptySet()); + return; + } +@@ -1304,7 +1342,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + } + } + +- AxisAlignedBB axisalignedbb = this.player.getBoundingBox(); ++ AxisAlignedBB axisalignedbb = this.player.getBoundingBox(); // Tuinity - diff on change, should be old AABB + + d7 = d4 - this.o; + d8 = d5 - this.p; +@@ -1343,6 +1381,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + } + + this.player.move(EnumMoveType.PLAYER, new Vec3D(d7, d8, d9)); ++ boolean didCollide = toX != this.player.locX() || toY != this.player.locY() || toZ != this.player.locZ(); // Tuinity - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be... + this.player.setOnGround(packetplayinflying.b()); // CraftBukkit - SPIGOT-5810, SPIGOT-5835: reset by this.player.move + // Paper start - prevent position desync + if (this.teleportPos != null) { +@@ -1362,12 +1401,23 @@ public class PlayerConnection implements PacketListenerPlayIn { + boolean flag1 = false; + + if (!this.player.H() && d11 > org.spigotmc.SpigotConfig.movedWronglyThreshold && !this.player.isSleeping() && !this.player.playerInteractManager.isCreative() && this.player.playerInteractManager.getGameMode() != EnumGamemode.SPECTATOR) { // Spigot +- flag1 = true; ++ flag1 = true; // Tuinity - diff on change, this should be moved wrongly + PlayerConnection.LOGGER.warn("{} moved wrongly!", this.player.getDisplayName().getString()); + } + + this.player.setLocation(d4, d5, d6, f, f1); +- if (!this.player.noclip && !this.player.isSleeping() && (flag1 && worldserver.getCubes(this.player, axisalignedbb) || this.a((IWorldReader) worldserver, axisalignedbb))) { ++ // Tuinity start - optimise out extra getCubes ++ // Original for reference: ++ // boolean teleportBack = flag1 && worldserver.getCubes(this.player, axisalignedbb) || (didCollide && this.a((IWorldReader) worldserver, axisalignedbb)); ++ boolean teleportBack = flag1; // violating this is always a fail ++ if (!this.player.noclip && !this.player.isSleeping() && !teleportBack) { ++ AxisAlignedBB newBox = this.player.getBoundingBox(); ++ if (didCollide || !axisalignedbb.equals(newBox)) { ++ // note: only call after setLocation, or else getBoundingBox is wrong ++ teleportBack = this.hasNewCollision(worldserver, this.player, axisalignedbb, newBox); ++ } // else: no collision at all detected, why do we care? ++ } ++ if (!this.player.noclip && !this.player.isSleeping() && teleportBack) { // Tuinity end - optimise out extra getCubes + this.a(d0, d1, d2, f, f1); + } else { + // CraftBukkit start - fire PlayerMoveEvent +@@ -1454,6 +1504,26 @@ public class PlayerConnection implements PacketListenerPlayIn { + } + } + ++ // Tuinity start - optimise out extra getCubes ++ private boolean hasNewCollision(final WorldServer world, final Entity entity, final AxisAlignedBB oldBox, final AxisAlignedBB newBox) { ++ final List collisions = com.tuinity.tuinity.util.CachedLists.getTempCollisionList(); ++ try { ++ world.getCollisions(entity, newBox, collisions, true); ++ ++ for (int i = 0, len = collisions.size(); i < len; ++i) { ++ final AxisAlignedBB box = collisions.get(i); ++ if (!box.voxelShapeIntersect(oldBox)) { ++ return true; ++ } ++ } ++ ++ return false; ++ } finally { ++ com.tuinity.tuinity.util.CachedLists.returnTempCollisionList(collisions); ++ } ++ } ++ // Tuinity end - optimise out extra getCubes ++ + private boolean a(IWorldReader iworldreader, AxisAlignedBB axisalignedbb) { + Stream stream = iworldreader.d(this.player, this.player.getBoundingBox().shrink(9.999999747378752E-6D), (entity) -> { + return true; +diff --git a/src/main/java/net/minecraft/server/network/ServerConnection.java b/src/main/java/net/minecraft/server/network/ServerConnection.java +index dc362724ea0cc1b2f9d9ceffff483217b4356c40..70fde7bad2e0a6d7432d8509fdb7c46d9f020d4c 100644 +--- a/src/main/java/net/minecraft/server/network/ServerConnection.java ++++ b/src/main/java/net/minecraft/server/network/ServerConnection.java +@@ -87,6 +87,11 @@ public class ServerConnection { + ServerConnection.LOGGER.info("Using default channel type"); + } + ++ // Tuinity start - indicate Velocity natives in use ++ ServerConnection.LOGGER.info("Tuinity: Using " + com.velocitypowered.natives.util.Natives.compress.getLoadedVariant() + " compression from Velocity."); ++ ServerConnection.LOGGER.info("Tuinity: Using " + com.velocitypowered.natives.util.Natives.cipher.getLoadedVariant() + " cipher from Velocity."); ++ // Tuinity end ++ + this.listeningChannels.add(((ServerBootstrap) ((ServerBootstrap) (new ServerBootstrap()).channel(oclass)).childHandler(new ChannelInitializer() { + protected void initChannel(Channel channel) throws Exception { + try { +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 92ed4938d5fe6b76e3a9ac5491d6e9c004ade843..ac98a3122ee30971b31761f3bc564b41d5ac879f 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -178,6 +178,7 @@ public abstract class PlayerList { + abstract public void loadAndSaveFiles(); // Paper - moved from DedicatedPlayerList constructor + + public void a(NetworkManager networkmanager, EntityPlayer entityplayer) { ++ entityplayer.isRealPlayer = true; // Paper // Tuinity - this is a better place to write this that works and isn't overriden by plugins + EntityPlayer prev = pendingPlayers.put(entityplayer.getUniqueID(), entityplayer);// Paper + if (prev != null) { + disconnectPendingPlayer(prev); +@@ -268,7 +269,7 @@ public abstract class PlayerList { + boolean flag1 = gamerules.getBoolean(GameRules.REDUCED_DEBUG_INFO); + + // Spigot - view distance +- playerconnection.sendPacket(new PacketPlayOutLogin(entityplayer.getId(), entityplayer.playerInteractManager.getGameMode(), entityplayer.playerInteractManager.c(), BiomeManager.a(worldserver1.getSeed()), worlddata.isHardcore(), this.server.F(), this.s, worldserver1.getDimensionManager(), worldserver1.getDimensionKey(), this.getMaxPlayers(), worldserver1.getChunkProvider().playerChunkMap.getLoadViewDistance(), flag1, !flag, worldserver1.isDebugWorld(), worldserver1.isFlatWorld())); // Paper - no-tick view distance ++ playerconnection.sendPacket(new PacketPlayOutLogin(entityplayer.getId(), entityplayer.playerInteractManager.getGameMode(), entityplayer.playerInteractManager.c(), BiomeManager.a(worldserver1.getSeed()), worlddata.isHardcore(), this.server.F(), this.s, worldserver1.getDimensionManager(), worldserver1.getDimensionKey(), this.getMaxPlayers(), worldserver1.getChunkProvider().playerChunkMap.playerChunkManager.getLoadDistance(), flag1, !flag, worldserver1.isDebugWorld(), worldserver1.isFlatWorld())); // Paper - no-tick view distance // Tuinity - replace old player chunk management + entityplayer.getBukkitEntity().sendSupportedChannels(); // CraftBukkit + playerconnection.sendPacket(new PacketPlayOutCustomPayload(PacketPlayOutCustomPayload.a, (new PacketDataSerializer(Unpooled.buffer())).a(this.getServer().getServerModName()))); + playerconnection.sendPacket(new PacketPlayOutServerDifficulty(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); +@@ -720,7 +721,7 @@ public abstract class PlayerList { + SocketAddress socketaddress = loginlistener.networkManager.getSocketAddress(); + + EntityPlayer entity = new EntityPlayer(this.server, this.server.getWorldServer(World.OVERWORLD), gameprofile, new PlayerInteractManager(this.server.getWorldServer(World.OVERWORLD))); +- entity.isRealPlayer = true; // Paper ++ // Tuinity - some plugins (namely protocolsupport) bypass this logic completely! So this needs to be moved. + Player player = entity.getBukkitEntity(); + PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.networkManager.getRawAddress()).getAddress()); + +@@ -940,7 +941,7 @@ public abstract class PlayerList { + // CraftBukkit start + WorldData worlddata = worldserver1.getWorldData(); + entityplayer1.playerConnection.sendPacket(new PacketPlayOutRespawn(worldserver1.getDimensionManager(), worldserver1.getDimensionKey(), BiomeManager.a(worldserver1.getSeed()), entityplayer1.playerInteractManager.getGameMode(), entityplayer1.playerInteractManager.c(), worldserver1.isDebugWorld(), worldserver1.isFlatWorld(), flag)); +- entityplayer1.playerConnection.sendPacket(new PacketPlayOutViewDistance(worldserver1.getChunkProvider().playerChunkMap.getLoadViewDistance())); // Spigot // Paper - no-tick view distance ++ entityplayer1.playerConnection.sendPacket(new PacketPlayOutViewDistance(worldserver1.getChunkProvider().playerChunkMap.playerChunkManager.getLoadDistance())); // Spigot // Paper - no-tick view distance // Tuinity - replace old player chunk management + entityplayer1.spawnIn(worldserver1); + entityplayer1.dead = false; + entityplayer1.playerConnection.teleport(new Location(worldserver1.getWorld(), entityplayer1.locX(), entityplayer1.locY(), entityplayer1.locZ(), entityplayer1.yaw, entityplayer1.pitch)); +@@ -1209,7 +1210,7 @@ public abstract class PlayerList { + // Really shouldn't happen... + backingSet = world != null ? world.players.toArray() : players.toArray(); + } else { +- com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet nearbyPlayers = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(MCUtil.fastFloor(d0) >> 4, MCUtil.fastFloor(d2) >> 4); ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet nearbyPlayers = chunkMap.playerChunkManager.broadcastMap.getObjectsInRange(MCUtil.fastFloor(d0) >> 4, MCUtil.fastFloor(d2) >> 4); // Tuinity - replace old player chunk management + if (nearbyPlayers == null) { + return; + } +diff --git a/src/main/java/net/minecraft/server/players/UserCache.java b/src/main/java/net/minecraft/server/players/UserCache.java +index 74b024a51f6c3ee88db730cbf97a24af66fa332b..66eee0998be2210042db8e6b537fa10a016a9c8a 100644 +--- a/src/main/java/net/minecraft/server/players/UserCache.java ++++ b/src/main/java/net/minecraft/server/players/UserCache.java +@@ -51,6 +51,11 @@ public class UserCache { + private final File g; + private final AtomicLong h = new AtomicLong(); + ++ // Tuinity start ++ protected final java.util.concurrent.locks.ReentrantLock stateLock = new java.util.concurrent.locks.ReentrantLock(); ++ protected final java.util.concurrent.locks.ReentrantLock lookupLock = new java.util.concurrent.locks.ReentrantLock(); ++ // Tuinity end ++ + public UserCache(GameProfileRepository gameprofilerepository, File file) { + this.e = gameprofilerepository; + this.g = file; +@@ -58,6 +63,7 @@ public class UserCache { + } + + private void a(UserCache.UserCacheEntry usercache_usercacheentry) { ++ try { this.stateLock.lock(); // Tuinity - allow better concurrency + GameProfile gameprofile = usercache_usercacheentry.a(); + + usercache_usercacheentry.a(this.d()); +@@ -72,6 +78,7 @@ public class UserCache { + if (uuid != null) { + this.d.put(uuid, usercache_usercacheentry); + } ++ } finally { this.stateLock.unlock(); } // Tuinity - allow better concurrency + + } + +@@ -109,7 +116,7 @@ public class UserCache { + } + + public void saveProfile(GameProfile gameprofile) { a(gameprofile); } // Paper - OBFHELPER +- public synchronized void a(GameProfile gameprofile) { // Paper - synchronize ++ public void a(GameProfile gameprofile) { // Paper - synchronize // Tuinity - allow better concurrency + Calendar calendar = Calendar.getInstance(); + + calendar.setTime(new Date()); +@@ -126,8 +133,9 @@ public class UserCache { + } + + @Nullable +- public synchronized GameProfile getProfile(String s) { // Paper - synchronize ++ public GameProfile getProfile(String s) { // Paper - synchronize // Tuinity start - allow better concurrency + String s1 = s.toLowerCase(Locale.ROOT); ++ boolean stateLocked = true; try { this.stateLock.lock(); // Tuinity - allow better concurrency + UserCache.UserCacheEntry usercache_usercacheentry = (UserCache.UserCacheEntry) this.c.get(s1); + boolean flag = false; + +@@ -141,10 +149,14 @@ public class UserCache { + GameProfile gameprofile; + + if (usercache_usercacheentry != null) { ++ stateLocked = false; this.stateLock.unlock(); // Tuinity - allow better concurrency + usercache_usercacheentry.a(this.d()); + gameprofile = usercache_usercacheentry.a(); + } else { ++ stateLocked = false; this.stateLock.unlock(); // Tuinity - allow better concurrency ++ try { this.lookupLock.lock(); // Tuinity - allow better concurrency + gameprofile = a(this.e, s); // Spigot - use correct case for offline players ++ } finally { this.lookupLock.unlock(); } // Tuinity - allow better concurrency + if (gameprofile != null) { + this.a(gameprofile); + flag = false; +@@ -156,6 +168,7 @@ public class UserCache { + } + + return gameprofile; ++ } finally { if (stateLocked) { this.stateLock.unlock(); } } // Tuinity - allow better concurrency + } + + // Paper start +@@ -290,7 +303,9 @@ public class UserCache { + } + + private Stream a(int i) { ++ try { this.stateLock.lock(); // Tuinity - allow better concurrency + return ImmutableList.copyOf(this.d.values()).stream().sorted(Comparator.comparing(UserCache.UserCacheEntry::c).reversed()).limit((long) i); ++ } finally { this.stateLock.unlock(); } // Tuinity - allow better concurrency + } + + private static JsonElement a(UserCache.UserCacheEntry usercache_usercacheentry, DateFormat dateformat) { +diff --git a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java +index a4970654496c52fcd02c5c055ff5ac551bd19da3..6725b31a5183d5af7f8f7566ed21eb61797ef4c9 100644 +--- a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java ++++ b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java +@@ -235,7 +235,7 @@ public class WorldUpgrader { int l = Integer.parseInt(matcher.group(2)) << 5; try { @@ -19973,8 +15420,5310 @@ index 5ccdc0b87b922724c3dd3085860c55d4959ca0b4..888dae2d5ee8a71e83dd24e5f3c6bc85 Throwable throwable = null; try { +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 429f0591c6a55f6c5d08a0755f7d39da676468bc..feab0ae1930b5271fe0d06a40c180317dcbc9d1d 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -228,7 +228,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + public double D; + public double E; + public double F; +- public float G; ++ public float G; public final float getStepHeight() { return this.G; } // Tuinity - OBFHELPER + public boolean noclip; + public float I; + protected final Random random; +@@ -299,6 +299,14 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + // CraftBukkit end + ++ // Tuinity start ++ public final AxisAlignedBB getBoundingBoxAt(double x, double y, double z) { ++ double widthHalf = (double)this.size.width / 2.0; ++ double height = (double)this.size.height; ++ return new AxisAlignedBB(x - widthHalf, y, z - widthHalf, x + widthHalf, y + height, z + widthHalf); ++ } ++ // Tuinity end ++ + // Paper start - optimise entity tracking + final org.spigotmc.TrackingRange.TrackingRangeType trackingRangeType = org.spigotmc.TrackingRange.getTrackingRangeType(this); + +@@ -309,11 +317,59 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getPlayersInTrackRange() { +- return ((WorldServer)this.world).getChunkProvider().playerChunkMap.playerEntityTrackerTrackMaps[this.trackingRangeType.ordinal()] +- .getObjectsInRange(MCUtil.getCoordinateKey(this)); ++ Collection passengers = this.getAllPassengers(); ++ net.minecraft.server.level.PlayerChunkMap chunkMap = ((WorldServer)this.world).getChunkProvider().playerChunkMap; ++ org.spigotmc.TrackingRange.TrackingRangeType type = this.trackingRangeType; ++ int range = chunkMap.getEntityTrackerRange(type.ordinal()); ++ ++ for (Entity passenger : passengers) { ++ org.spigotmc.TrackingRange.TrackingRangeType passengerType = passenger.trackingRangeType; ++ int passengerRange = chunkMap.getEntityTrackerRange(passengerType.ordinal()); ++ if (passengerRange > range) { ++ type = passengerType; ++ range = passengerRange; ++ } ++ } ++ ++ return chunkMap.playerEntityTrackerTrackMaps[type.ordinal()].getObjectsInRange(MCUtil.getCoordinateKey(this)); + } + // Paper end - optimise entity tracking + ++ // Tuinity start ++ /** ++ * Overriding this field will cause memory leaks. ++ */ ++ private final boolean hardCollides; ++ ++ private static final java.util.Map, Boolean> cachedOverrides = java.util.Collections.synchronizedMap(new java.util.WeakHashMap<>()); ++ { ++ Boolean hardCollides = cachedOverrides.get(this.getClass()); ++ if (hardCollides == null) { ++ try { ++ java.lang.reflect.Method getHardCollisionBoxEntityMethod = Entity.class.getMethod("j", Entity.class); ++ java.lang.reflect.Method hasHardCollisionBoxMethod = Entity.class.getMethod("aZ"); ++ if (!this.getClass().getMethod(hasHardCollisionBoxMethod.getName(), hasHardCollisionBoxMethod.getParameterTypes()).equals(hasHardCollisionBoxMethod) ++ || !this.getClass().getMethod(getHardCollisionBoxEntityMethod.getName(), getHardCollisionBoxEntityMethod.getParameterTypes()).equals(getHardCollisionBoxEntityMethod)) { ++ hardCollides = Boolean.TRUE; ++ } else { ++ hardCollides = Boolean.FALSE; ++ } ++ cachedOverrides.put(this.getClass(), hardCollides); ++ } ++ catch (ThreadDeath thr) { throw thr; } ++ catch (Throwable thr) { ++ // shouldn't happen, just explode ++ throw new RuntimeException(thr); ++ } ++ } ++ this.hardCollides = hardCollides.booleanValue(); ++ } ++ ++ public final boolean hardCollides() { ++ return this.hardCollides; ++ } ++ // Tuinity end ++ + public Entity(EntityTypes entitytypes, World world) { + this.id = Entity.entityCount.incrementAndGet(); + this.passengers = Lists.newArrayList(); +@@ -683,7 +739,39 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return this.onGround; + } + ++ // Tuinity start - detailed watchdog information ++ private Vec3D moveVector; ++ private double moveStartX; ++ private double moveStartY; ++ private double moveStartZ; ++ ++ public final Vec3D getMoveVector() { ++ return this.moveVector; ++ } ++ ++ public final double getMoveStartX() { ++ return this.moveStartX; ++ } ++ ++ public final double getMoveStartY() { ++ return this.moveStartY; ++ } ++ ++ public final double getMoveStartZ() { ++ return this.moveStartZ; ++ } ++ // Tuinity end - detailed watchdog information + public void move(EnumMoveType enummovetype, Vec3D vec3d) { ++ // Tuinity start - detailed watchdog information ++ com.tuinity.tuinity.util.TickThread.ensureTickThread("Cannot move an entity off-main"); ++ synchronized (this.posLock) { ++ this.moveStartX = this.locX(); ++ this.moveStartY = this.locY(); ++ this.moveStartZ = this.locZ(); ++ this.moveVector = vec3d; ++ } ++ try { ++ // Tuinity end - detailed watchdog information + if (this.noclip) { + this.a(this.getBoundingBox().c(vec3d)); + this.recalcPosition(); +@@ -711,7 +799,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + // Paper end + + vec3d = this.a(vec3d, enummovetype); +- Vec3D vec3d1 = this.g(vec3d); ++ Vec3D vec3d1 = this.performCollision(vec3d); // Tuinity - optimise collisions + + if (vec3d1.g() > 1.0E-7D) { + this.a(this.getBoundingBox().c(vec3d1)); +@@ -802,7 +890,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + try { +- this.checkBlockCollisions(); ++ this.checkBlockCollisions(this.fireTicks <= 0); // Tuinity - move fire checking into method here + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.a(throwable, "Checking entity block collision"); + CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity being checked for collision"); +@@ -814,11 +902,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + float f2 = this.getBlockSpeedFactor(); + + this.setMot(this.getMot().d((double) f2, 1.0D, (double) f2)); +- if (this.world.c(this.getBoundingBox().shrink(0.001D)).noneMatch((iblockdata1) -> { +- return iblockdata1.a((Tag) TagsBlock.FIRE) || iblockdata1.a(Blocks.LAVA); +- }) && this.fireTicks <= 0) { +- this.setFireTicks(-this.getMaxFireTicks()); +- } ++ // Tuinity - move into checkBlockCollisions + + if (this.aG() && this.isBurning()) { + this.playSound(SoundEffects.ENTITY_GENERIC_EXTINGUISH_FIRE, 0.7F, 1.6F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); +@@ -827,6 +911,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + + this.world.getMethodProfiler().exit(); + } ++ // Tuinity start - detailed watchdog information ++ } finally { ++ synchronized (this.posLock) { // Tuinity ++ this.moveVector = null; ++ } // Tuinity ++ } ++ // Tuinity end - detailed watchdog information + } + + protected BlockPosition ap() { +@@ -907,6 +998,137 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return d0; + } + ++ // Tuinity start - optimise entity movement ++ private static double performCollisionsX(AxisAlignedBB currentBoundingBox, double value, List potentialCollisions) { ++ for (int i = 0, len = potentialCollisions.size(); i < len; ++i) { ++ AxisAlignedBB target = potentialCollisions.get(i); ++ value = AxisAlignedBB.collideX(target, currentBoundingBox, value); ++ } ++ ++ return value; ++ } ++ ++ private static double performCollisionsY(AxisAlignedBB currentBoundingBox, double value, List potentialCollisions) { ++ for (int i = 0, len = potentialCollisions.size(); i < len; ++i) { ++ AxisAlignedBB target = potentialCollisions.get(i); ++ value = AxisAlignedBB.collideY(target, currentBoundingBox, value); ++ } ++ ++ return value; ++ } ++ ++ private static double performCollisionsZ(AxisAlignedBB currentBoundingBox, double value, List potentialCollisions) { ++ for (int i = 0, len = potentialCollisions.size(); i < len; ++i) { ++ AxisAlignedBB target = potentialCollisions.get(i); ++ value = AxisAlignedBB.collideZ(target, currentBoundingBox, value); ++ } ++ ++ return value; ++ } ++ ++ private static Vec3D performCollisions(Vec3D moveVector, AxisAlignedBB axisalignedbb, List potentialCollisions) { ++ double x = moveVector.x; ++ double y = moveVector.y; ++ double z = moveVector.z; ++ ++ if (y != 0.0) { ++ y = Entity.performCollisionsY(axisalignedbb, y, potentialCollisions); ++ if (y != 0.0) { ++ axisalignedbb = axisalignedbb.offsetY(y); ++ } ++ } ++ ++ boolean xSmaller = Math.abs(x) < Math.abs(z); ++ ++ if (xSmaller && z != 0.0) { ++ z = Entity.performCollisionsZ(axisalignedbb, z, potentialCollisions); ++ if (z != 0.0) { ++ axisalignedbb = axisalignedbb.offsetZ(z); ++ } ++ } ++ ++ if (x != 0.0) { ++ x = Entity.performCollisionsX(axisalignedbb, x, potentialCollisions); ++ if (!xSmaller && x != 0.0) { ++ axisalignedbb = axisalignedbb.offsetX(x); ++ } ++ } ++ ++ if (!xSmaller && z != 0.0) { ++ z = Entity.performCollisionsZ(axisalignedbb, z, potentialCollisions); ++ } ++ ++ return new Vec3D(x, y, z); ++ } ++ ++ Vec3D performCollision(Vec3D moveVector) { ++ if (moveVector.getX() == 0.0 && moveVector.getY() == 0.0 && moveVector.getZ() == 0.0) { ++ return moveVector; ++ } ++ ++ WorldServer world = ((WorldServer)this.world); ++ AxisAlignedBB currBoundingBox = this.getBoundingBox(); ++ ++ List potentialCollisions = com.tuinity.tuinity.util.CachedLists.getTempCollisionList(); ++ try { ++ AxisAlignedBB collisionBox; ++ double stepHeight = (double)this.getStepHeight(); ++ ++ if (moveVector.x == 0.0 && moveVector.z == 0.0 && moveVector.y != 0.0) { ++ // a lot of entities just stand still. optimise the search AABB ++ if (moveVector.y > 0.0) { ++ collisionBox = currBoundingBox.cutUpwards(moveVector.y); ++ } else { ++ collisionBox = currBoundingBox.cutDownwards(moveVector.y); ++ } ++ } else { ++ if (stepHeight > 0.0 && (this.onGround || (moveVector.y < 0.0)) && (moveVector.x != 0.0 || moveVector.z != 0.0)) { ++ // don't bother getting the collisions if we don't need them. ++ if (moveVector.y <= 0.0) { ++ collisionBox = currBoundingBox.expand(moveVector.x, moveVector.y, moveVector.z).expandUpwards(stepHeight); ++ } else { ++ collisionBox = currBoundingBox.expand(moveVector.x, Math.max(stepHeight, moveVector.y), moveVector.z); ++ } ++ } else { ++ collisionBox = currBoundingBox.expand(moveVector.x, moveVector.y, moveVector.z); ++ } ++ } ++ ++ world.getCollisions(this, collisionBox, potentialCollisions, this instanceof EntityPlayer && !this.world.paperConfig.preventMovingIntoUnloadedChunks); ++ if (world.getWorldBorder().isCollidingWithBorderEdge(collisionBox)) { ++ VoxelShapes.addBoxesToIfIntersects(world.getWorldBorder().getCollisionShape(), collisionBox, potentialCollisions); ++ } ++ ++ Vec3D limitedMoveVector = Entity.performCollisions(moveVector, currBoundingBox, potentialCollisions); ++ ++ if (stepHeight > 0.0 ++ && (this.onGround || (limitedMoveVector.y != moveVector.y && moveVector.y < 0.0)) ++ && (limitedMoveVector.x != moveVector.x || limitedMoveVector.z != moveVector.z)) { ++ Vec3D vec3d2 = Entity.performCollisions(new Vec3D(moveVector.x, stepHeight, moveVector.z), currBoundingBox, potentialCollisions); ++ Vec3D vec3d3 = Entity.performCollisions(new Vec3D(0.0, stepHeight, 0.0), currBoundingBox.expand(moveVector.x, 0.0, moveVector.z), potentialCollisions); ++ ++ if (vec3d3.y < stepHeight) { ++ Vec3D vec3d4 = Entity.performCollisions(new Vec3D(moveVector.x, 0.0D, moveVector.z), currBoundingBox.offset(vec3d3), potentialCollisions).add(vec3d3); ++ ++ if (Entity.getXZSquared(vec3d4) > Entity.getXZSquared(vec3d2)) { ++ vec3d2 = vec3d4; ++ } ++ } ++ ++ if (Entity.getXZSquared(vec3d2) > Entity.getXZSquared(limitedMoveVector)) { ++ return vec3d2.add(Entity.performCollisions(new Vec3D(0.0D, -vec3d2.y + moveVector.y, 0.0D), currBoundingBox.offset(vec3d2), potentialCollisions)); ++ } ++ ++ return limitedMoveVector; ++ } else { ++ return limitedMoveVector; ++ } ++ } finally { ++ com.tuinity.tuinity.util.CachedLists.returnTempCollisionList(potentialCollisions); ++ } ++ } ++ // Tuinity end - optimise entity movement ++ + private Vec3D g(Vec3D vec3d) { + AxisAlignedBB axisalignedbb = this.getBoundingBox(); + VoxelShapeCollision voxelshapecollision = VoxelShapeCollision.a(this); +@@ -942,6 +1164,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return vec3d1; + } + ++ public static double getXZSquared(Vec3D vec3d) { return Entity.c(vec3d); } // Tuinity - OBFHELPER + public static double c(Vec3D vec3d) { + return vec3d.x * vec3d.x + vec3d.z * vec3d.z; + } +@@ -1054,18 +1277,34 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + protected void checkBlockCollisions() { ++ // Tuinity start ++ this.checkBlockCollisions(false); ++ } ++ protected void checkBlockCollisions(boolean checkFire) { ++ boolean inFire = false; ++ // Tuinity end + AxisAlignedBB axisalignedbb = this.getBoundingBox(); + BlockPosition blockposition = new BlockPosition(axisalignedbb.minX + 0.001D, axisalignedbb.minY + 0.001D, axisalignedbb.minZ + 0.001D); + BlockPosition blockposition1 = new BlockPosition(axisalignedbb.maxX - 0.001D, axisalignedbb.maxY - 0.001D, axisalignedbb.maxZ - 0.001D); + BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); + + if (this.world.areChunksLoadedBetween(blockposition, blockposition1)) { +- for (int i = blockposition.getX(); i <= blockposition1.getX(); ++i) { +- for (int j = blockposition.getY(); j <= blockposition1.getY(); ++j) { +- for (int k = blockposition.getZ(); k <= blockposition1.getZ(); ++k) { ++ // Tuinity start - reorder iteration to more cache aware ++ for (int j = blockposition.getY(); j <= blockposition1.getY(); ++j) { ++ for (int k = blockposition.getZ(); k <= blockposition1.getZ(); ++k) { ++ for (int i = blockposition.getX(); i <= blockposition1.getX(); ++i) { ++ // Tuinity end - reorder iteration to more cache aware + blockposition_mutableblockposition.d(i, j, k); + IBlockData iblockdata = this.world.getType(blockposition_mutableblockposition); + ++ // Tuinity start - move fire checking in here - reuse getType from this method ++ if (checkFire) { ++ if (!inFire && (iblockdata.a(TagsBlock.FIRE) || iblockdata.a(Blocks.LAVA))) { ++ inFire = true; ++ } ++ } ++ // Tuinity end - move fire checking in here - reuse getType from this method ++ + try { + iblockdata.a(this.world, blockposition_mutableblockposition, this); + this.a(iblockdata); +@@ -1079,6 +1318,11 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + } + } ++ // Tuinity start - move fire checking in here - reuse getType from this method ++ if (checkFire & !inFire) { ++ this.setFireTicks(-this.getMaxFireTicks()); ++ } ++ // Tuinity end - move fire checking in here - reuse getType from this method + } + + } +@@ -1450,6 +1694,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return d3 * d3 + d4 * d4 + d5 * d5; + } + ++ public final double getDistanceSquared(Entity other) { return this.h(other); } // Tuinity - OBFHELPER + public double h(Entity entity) { + return this.e(entity.getPositionVector()); + } +@@ -2037,9 +2282,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + float f1 = this.size.width * 0.8F; + AxisAlignedBB axisalignedbb = AxisAlignedBB.g((double) f1, 0.10000000149011612D, (double) f1).d(this.locX(), this.getHeadY(), this.locZ()); + +- return this.world.b(this, axisalignedbb, (iblockdata, blockposition) -> { ++ return ((WorldServer)this.world).collidesWithAnyBlockOrWorldBorder(this, axisalignedbb, false, false, (iblockdata, blockposition) -> { // Tuinity - use optimised method + return iblockdata.o(this.world, blockposition); +- }).findAny().isPresent(); ++ }); // Tuinity - use optimised method + } + } + +@@ -2047,11 +2292,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return EnumInteractionResult.PASS; + } + +- public boolean j(Entity entity) { ++ public final boolean hardCollidesWith(Entity other) { return this.j(other); } // Tuinity - OBFHELPER ++ public boolean j(Entity entity) { // Tuinity - diff on change, hard colliding entities override this + return entity.aZ() && !this.isSameVehicle(entity); + } + +- public boolean aZ() { ++ public final boolean collisionBoxIsHard() { return this.aZ(); } // Tuinity - OBFHELPER ++ public boolean aZ() {// Tuinity - diff on change, hard colliding entities override this + return false; + } + +@@ -2942,7 +3189,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + this.recursiveStream().forEach((entity) -> { + worldserver.chunkCheck(entity); + entity.az = true; +- Iterator iterator = entity.passengers.iterator(); ++ Iterator iterator = new java.util.ArrayList<>(entity.passengers).iterator(); // Tuinity - copy list to guard against CME + + while (iterator.hasNext()) { + Entity entity1 = (Entity) iterator.next(); +@@ -3400,12 +3647,16 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return this.locBlock; + } + ++ public final Object posLock = new Object(); // Tuinity - log detailed entity tick information ++ + public Vec3D getMot() { + return this.mot; + } + + public void setMot(Vec3D vec3d) { ++ synchronized (this.posLock) { // Tuinity + this.mot = vec3d; ++ } // Tuinity + } + + public void setMot(double d0, double d1, double d2) { +@@ -3460,7 +3711,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + // Paper end + if (this.loc.x != d0 || this.loc.y != d1 || this.loc.z != d2) { ++ synchronized (this.posLock) { // Tuinity + this.loc = new Vec3D(d0, d1, d2); ++ } // Tuinity + int i = MathHelper.floor(d0); + int j = MathHelper.floor(d1); + int k = MathHelper.floor(d2); +diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +index a246edd09854dabf095da75c9d200f5cf26e7138..aae13c2e6c2a30b69c33417932c6a4d0aefeb7f5 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java ++++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +@@ -779,7 +779,13 @@ public abstract class EntityInsentient extends EntityLiving { + if (this.world.getDifficulty() == EnumDifficulty.PEACEFUL && this.L()) { + this.die(); + } else if (!this.isPersistent() && !this.isSpecialPersistence()) { +- EntityHuman entityhuman = this.world.findNearbyPlayer(this, -1.0D, IEntitySelector.affectsSpawning); // Paper ++ // Tuinity start - optimise checkDespawn ++ net.minecraft.world.level.chunk.Chunk chunk = this.getCurrentChunk(); ++ EntityHuman entityhuman = chunk == null || this.world.paperConfig.hardDespawnDistance >= (net.minecraft.server.level.PlayerChunkMap.GENERAL_AREA_MAP_ACCEPTABLE_SEARCH_RANGE_SQUARED) ? this.world.findNearbyPlayer(this, -1.0D, IEntitySelector.affectsSpawning) : chunk.findNearestPlayer(this.locX(), this.locY(), this.locZ(), -1.0, IEntitySelector.affectsSpawning); // Paper ++ if (entityhuman == null) { ++ entityhuman = ((WorldServer)this.world).playersAffectingSpawning.isEmpty() ? null : ((WorldServer)this.world).playersAffectingSpawning.get(0); ++ } ++ // Tuinity end - optimise checkDespawn + + if (entityhuman != null) { + double d0 = entityhuman.h((Entity) this); // CraftBukkit - decompile error +diff --git a/src/main/java/net/minecraft/world/entity/EntityLightning.java b/src/main/java/net/minecraft/world/entity/EntityLightning.java +index 85f571a791bce63989890f277857bc7bdeec0cb5..9e4137768c7d8966759324a4b368330c35faa8a5 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLightning.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLightning.java +@@ -81,8 +81,9 @@ public class EntityLightning extends Entity { + // CraftBukkit start - Use relative location for far away sounds + // this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_LIGHTNING_BOLT_THUNDER, SoundCategory.WEATHER, 10000.0F, 0.8F + this.random.nextFloat() * 0.2F); + float pitch = 0.8F + this.random.nextFloat() * 0.2F; +- int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; ++ //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Tuinity - apply view distance patch + for (EntityPlayer player : (List) (List) this.world.getPlayers()) { ++ final int viewDistance = player.getBukkitEntity().getViewDistance(); // Tuinity - apply view distance patch + double deltaX = this.locX() - player.locX(); + double deltaZ = this.locZ() - player.locZ(); + double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index b0ee9e98d5f1e56c8d82e90dd7761c8ef79cfb1c..561905be42428855a07a2e63aca80d5dd63b22bf 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -2973,7 +2973,11 @@ public abstract class EntityLiving extends Entity { + return; + } + // Paper - end don't run getEntities if we're not going to use its result +- List list = this.world.getEntities(this, this.getBoundingBox(), IEntitySelector.pushable(this, world.paperConfig.fixClimbingBypassingCrammingRule)); // Paper - fix climbing bypassing cramming rule ++ // Tuinity start - reduce memory allocation from collideNearby ++ List list = com.tuinity.tuinity.util.CachedLists.getTempGetEntitiesList(); ++ this.world.getEntities(this, this.getBoundingBox(), IEntitySelector.pushable(this, world.paperConfig.fixClimbingBypassingCrammingRule), list); // Paper - fix climbing bypassing cramming rule ++ try { ++ // Tuinity end - reduce memory allocation from collideNearby + + if (!list.isEmpty()) { + // Paper - move up +@@ -3002,6 +3006,9 @@ public abstract class EntityLiving extends Entity { + this.C(entity); + } + } ++ } finally { // Tuinity start - reduce memory allocation from collideNearby ++ com.tuinity.tuinity.util.CachedLists.returnTempGetEntitiesList(list); ++ } // Tuinity end - reduce memory allocation from collideNearby + + } + +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/Behavior.java b/src/main/java/net/minecraft/world/entity/ai/behavior/Behavior.java +index a30b92736d8b36f750eb721d4a056bdfc98845b5..717e5f71fb919ac8952a077714d7f4581d546a28 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/Behavior.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/Behavior.java +@@ -11,7 +11,7 @@ import net.minecraft.world.entity.ai.memory.MemoryStatus; + public abstract class Behavior { + + protected final Map, MemoryStatus> a; +- private Behavior.Status b; ++ private Behavior.Status b; public final Behavior.Status getStatus() { return this.b; } // Tuinity - OBFHELPER + private long c; + private final int d; + private final int e; +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFindPosition.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFindPosition.java +index a04d4dc665f34687b5d744fea56bc46263f27235..bc8786e2aaeab4dbae4e9c7666ad816bc5bfac3f 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFindPosition.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFindPosition.java +@@ -84,7 +84,11 @@ public class BehaviorFindPosition extends Behavior { + return true; + } + }; +- Set set = (Set) villageplace.b(this.b.c(), predicate, entitycreature.getChunkCoordinates(), 48, VillagePlace.Occupancy.HAS_SPACE).limit(5L).collect(Collectors.toSet()); ++ // Tuinity start - optimise POI access ++ java.util.List poiposes = new java.util.ArrayList<>(); ++ com.tuinity.tuinity.util.PoiAccess.findNearestPoiPositions(villageplace, this.b.c(), predicate, entitycreature.getChunkCoordinates(), 48, 48*48, VillagePlace.Occupancy.HAS_SPACE, false, 5, poiposes); ++ Set set = new java.util.HashSet<>(poiposes); ++ // Tuinity end - optimise POI access + PathEntity pathentity = entitycreature.getNavigation().a(set, this.b.d()); + + if (pathentity != null && pathentity.j()) { +@@ -94,7 +98,7 @@ public class BehaviorFindPosition extends Behavior { + villageplace.a(this.b.c(), (blockposition1) -> { + return blockposition1.equals(blockposition); + }, blockposition, 1); +- entitycreature.getBehaviorController().setMemory(this.c, (Object) GlobalPos.create(worldserver.getDimensionKey(), blockposition)); ++ entitycreature.getBehaviorController().setMemory(this.c, GlobalPos.create(worldserver.getDimensionKey(), blockposition)); // Tuinity - decompile fix + this.e.ifPresent((obyte) -> { + worldserver.broadcastEntityEffect(entitycreature, obyte); + }); +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java +index 2d4345de154fb2d31f34695672ebdb4dac31b181..c46cdffe3d877bff70b843766c8189eae06148ff 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java +@@ -17,7 +17,7 @@ public class BehaviorGate extends Behavior { + private final Set> b; + private final BehaviorGate.Order c; + private final BehaviorGate.Execution d; +- private final WeightedList> e = new WeightedList<>(false); // Paper - don't use a clone ++ private final WeightedList> e = new WeightedList<>(false); protected final WeightedList> getList() { return this.e; } // Paper - don't use a clone // Tuinity - OBFHELPER + + public BehaviorGate(Map, MemoryStatus> map, Set> set, BehaviorGate.Order behaviorgate_order, BehaviorGate.Execution behaviorgate_execution, List, Integer>> list) { + super(map); +@@ -31,11 +31,17 @@ public class BehaviorGate extends Behavior { + + @Override + protected boolean b(WorldServer worldserver, E e0, long i) { +- return this.e.c().filter((behavior) -> { +- return behavior.a() == Behavior.Status.RUNNING; +- }).anyMatch((behavior) -> { +- return behavior.b(worldserver, e0, i); +- }); ++ // Tuinity start - remove streams ++ List>> list = this.getList().getList(); ++ for (int index = 0, len = list.size(); index < len; ++index) { ++ Behavior behavior = list.get(index).getValue(); ++ if (behavior.getStatus() == Status.RUNNING && behavior.b(worldserver, e0, i)) { // copied from removed code, make sure to update ++ return true; ++ } ++ } ++ ++ return false; ++ // Tuinity end - remove streams + } + + @Override +@@ -51,20 +57,28 @@ public class BehaviorGate extends Behavior { + + @Override + protected void d(WorldServer worldserver, E e0, long i) { +- this.e.c().filter((behavior) -> { +- return behavior.a() == Behavior.Status.RUNNING; +- }).forEach((behavior) -> { +- behavior.f(worldserver, e0, i); +- }); ++ // Tuinity start - remove streams ++ List>> list = this.getList().getList(); ++ for (int index = 0, len = list.size(); index < len; ++index) { ++ Behavior behavior = list.get(index).getValue(); ++ if (behavior.getStatus() == Behavior.Status.RUNNING) { ++ behavior.f(worldserver, e0, i); // copied from removed code, make sure to update ++ } ++ } ++ // Tuinity end - remove streams + } + + @Override + protected void c(WorldServer worldserver, E e0, long i) { +- this.e.c().filter((behavior) -> { +- return behavior.a() == Behavior.Status.RUNNING; +- }).forEach((behavior) -> { +- behavior.g(worldserver, e0, i); +- }); ++ // Tuinity start - remove streams ++ List>> list = this.getList().getList(); ++ for (int index = 0, len = list.size(); index < len; ++index) { ++ Behavior behavior = list.get(index).getValue(); ++ if (behavior.getStatus() == Behavior.Status.RUNNING) { ++ behavior.g(worldserver, e0, i); // copied from removed code, make sure to update ++ } ++ } ++ // Tuinity end - remove streams + BehaviorController behaviorcontroller = e0.getBehaviorController(); + + this.b.forEach(behaviorcontroller::removeMemory); // Paper - decomp fix +@@ -84,21 +98,29 @@ public class BehaviorGate extends Behavior { + RUN_ONE { + @Override + public void a(WeightedList> weightedlist, WorldServer worldserver, E e0, long i) { +- weightedlist.c().filter((behavior) -> { +- return behavior.a() == Behavior.Status.STOPPED; +- }).filter((behavior) -> { +- return behavior.e(worldserver, e0, i); +- }).findFirst(); ++ // Tuinity start - remove streams ++ List>> list = weightedlist.getList(); ++ for (int index = 0, len = list.size(); index < len; ++index) { ++ Behavior behavior = list.get(index).getValue(); ++ if (behavior.getStatus() == Behavior.Status.STOPPED && behavior.e(worldserver, e0, i)) { // copied from removed code, make sure to update ++ break; ++ } ++ } ++ // Tuinity end - remove streams + } + }, + TRY_ALL { + @Override + public void a(WeightedList> weightedlist, WorldServer worldserver, E e0, long i) { +- weightedlist.c().filter((behavior) -> { +- return behavior.a() == Behavior.Status.STOPPED; +- }).forEach((behavior) -> { +- behavior.e(worldserver, e0, i); +- }); ++ // Tuinity start - remove streams ++ List>> list = weightedlist.getList(); ++ for (int index = 0, len = list.size(); index < len; ++index) { ++ Behavior behavior = list.get(index).getValue(); ++ if (behavior.getStatus() == Behavior.Status.STOPPED) { ++ behavior.e(worldserver, e0, i); // copied from removed code, make sure to update ++ } ++ } ++ // Tuinity end - remove streams + } + }; + +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorLookInteract.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorLookInteract.java +index f56072c77b9dfd0eeafb7a6970eecf593315f63e..196a5659a1f2c8c20a10f36c3fa81a8edc43a00c 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorLookInteract.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorLookInteract.java +@@ -14,7 +14,7 @@ import net.minecraft.world.entity.ai.memory.MemoryStatus; + public class BehaviorLookInteract extends Behavior { + + private final EntityTypes b; +- private final int c; ++ private final int c; private final int getMaxRange() { return this.c; } // Tuinity - OBFHELPER + private final Predicate d; + private final Predicate e; + +@@ -36,7 +36,20 @@ public class BehaviorLookInteract extends Behavior { + + @Override + public boolean a(WorldServer worldserver, EntityLiving entityliving) { +- return this.e.test(entityliving) && this.b(entityliving).stream().anyMatch(this::a); ++ // Tuinity start - remove streams ++ if (!this.e.test(entityliving)) { ++ return false; ++ } ++ ++ List list = this.b(entityliving); ++ for (int index = 0, len = list.size(); index < len; ++index) { ++ if (this.a(list.get(index))) { ++ return true; ++ } ++ } ++ ++ return false; ++ // Tuinity end - remove streams + } + + @Override +@@ -44,16 +57,28 @@ public class BehaviorLookInteract extends Behavior { + super.a(worldserver, entityliving, i); + BehaviorController behaviorcontroller = entityliving.getBehaviorController(); + +- behaviorcontroller.getMemory(MemoryModuleType.VISIBLE_MOBS).ifPresent((list) -> { +- list.stream().filter((entityliving1) -> { +- return entityliving1.h((Entity) entityliving) <= (double) this.c; +- }).filter(this::a).findFirst().ifPresent((entityliving1) -> { +- behaviorcontroller.setMemory(MemoryModuleType.INTERACTION_TARGET, (Object) entityliving1); +- behaviorcontroller.setMemory(MemoryModuleType.LOOK_TARGET, (Object) (new BehaviorPositionEntity(entityliving1, true))); +- }); +- }); ++ // Tuinity start - remove streams ++ List inLOS = behaviorcontroller.getMemory(MemoryModuleType.VISIBLE_MOBS).orElse(null); ++ if (inLOS != null) { ++ double maxRangeSquared = this.getMaxRange(); ++ for (int index = 0, len = inLOS.size(); index < len; ++index) { ++ EntityLiving entity = inLOS.get(index); ++ if (!this.canTarget(entity)) { ++ continue; ++ } ++ double distance = entity.getDistanceSquared(entityliving.locX(), entityliving.locY(), entityliving.locZ()); ++ if (distance > maxRangeSquared) { ++ continue; ++ } ++ behaviorcontroller.setMemory(MemoryModuleType.INTERACTION_TARGET, entity); // Tuinity - decompile fix ++ behaviorcontroller.setMemory(MemoryModuleType.LOOK_TARGET, (new BehaviorPositionEntity(entity, true))); // Tuinity - decompile fix ++ break; ++ } ++ } ++ // Tuinity end - remove streams + } + ++ private final boolean canTarget(EntityLiving entityliving) { return this.a(entityliving); } // Tuinity - OBFHELPER + private boolean a(EntityLiving entityliving) { + return this.b.equals(entityliving.getEntityType()) && this.d.test(entityliving); + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java b/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java +index 1ca9b0595ae9d914d23590ec0b0c2e857c39b250..e2b5d6155bebdbf99b0850de7f9e1f5d342f9e2f 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java +@@ -14,7 +14,7 @@ import java.util.stream.Stream; + + public class WeightedList { + +- protected final List> list; // Paper - decompile conflict ++ protected final List> list; public final List> getList() { return this.list; } // Paper - decompile conflict // Tuinity - OBFHELPER + private final Random b; + private final boolean isUnsafe; // Paper + +@@ -74,7 +74,7 @@ public class WeightedList { + + public static class a { + +- private final T a; ++ private final T a; public final T getValue() { return this.a; } // Tuinity - OBFHELPER + private final int b; + private double c; + +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java +index e6ba9b7fbf08ae0dd083a1ebee8eb7ed8a937751..148bdbc2cffb002d8b6dd05e70854ab503804949 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java +@@ -30,7 +30,7 @@ import net.minecraft.world.phys.Vec3D; + + public abstract class NavigationAbstract { + +- protected final EntityInsentient a; public Entity getEntity() { return a; } // Paper - OBFHELPER ++ protected final EntityInsentient a; public final EntityInsentient getEntity() { return a; } // Paper - OBFHELPER // Tuinity - match types + protected final World b; + @Nullable + protected PathEntity c; protected final PathEntity getCurrentPath() { return this.c; } // Paper - OBFHELPER +@@ -43,7 +43,7 @@ public abstract class NavigationAbstract { + protected long j; + protected double k; + protected float l; +- protected boolean m; ++ protected boolean m; protected final boolean needsPathRecalculation() { return this.m; } // Tuinity - OBFHELPER + protected long n; + protected PathfinderAbstract o; + private BlockPosition p; +@@ -52,6 +52,13 @@ public abstract class NavigationAbstract { + private final Pathfinder s; public Pathfinder getPathfinder() { return this.s; } // Paper - OBFHELPER + private boolean t; + ++ // Tuinity start ++ public boolean isViableForPathRecalculationChecking() { ++ return !this.needsPathRecalculation() && ++ (this.c != null && !this.c.c() && this.c.e() != 0); ++ } ++ // Tuinity end ++ + public NavigationAbstract(EntityInsentient entityinsentient, World world) { + this.g = Vec3D.ORIGIN; + this.h = BaseBlockPosition.ZERO; +@@ -415,7 +422,7 @@ public abstract class NavigationAbstract { + } + + public void b(BlockPosition blockposition) { +- if (this.c != null && !this.c.c() && this.c.e() != 0) { ++ if (this.c != null && !this.c.c() && this.c.e() != 0) { // Tuinity - diff on change - needed for isViableForPathRecalculationChecking() + PathPoint pathpoint = this.c.d(); + Vec3D vec3d = new Vec3D(((double) pathpoint.a + this.a.locX()) / 2.0D, ((double) pathpoint.b + this.a.locY()) / 2.0D, ((double) pathpoint.c + this.a.locZ()) / 2.0D); + +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestBed.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestBed.java +index 1e58a06860125243d0f7c062aca095dd2aae98f2..9427072575df9c0f1b9dfb065b6bef43df1f8fc5 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestBed.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestBed.java +@@ -47,15 +47,19 @@ public class SensorNearestBed extends Sensor { + return true; + } + }; +- Stream stream = villageplace.a(VillagePlaceType.r.c(), predicate, entityinsentient.getChunkCoordinates(), 48, VillagePlace.Occupancy.ANY); +- PathEntity pathentity = entityinsentient.getNavigation().a(stream, VillagePlaceType.r.d()); ++ // Tuinity start - optimise POI access ++ java.util.List poiposes = new java.util.ArrayList<>(); ++ // don't ask me why it's unbounded. ask mojang. ++ com.tuinity.tuinity.util.PoiAccess.findAnyPoiPositions(villageplace, VillagePlaceType.r.c(), predicate, entityinsentient.getChunkCoordinates(), 48, VillagePlace.Occupancy.ANY, false, Integer.MAX_VALUE, poiposes); ++ PathEntity pathentity = entityinsentient.getNavigation().a(new java.util.HashSet<>(poiposes), VillagePlaceType.r.d()); ++ // Tuinity end - optimise POI access + + if (pathentity != null && pathentity.j()) { + BlockPosition blockposition = pathentity.m(); + Optional optional = villageplace.c(blockposition); + + if (optional.isPresent()) { +- entityinsentient.getBehaviorController().setMemory(MemoryModuleType.NEAREST_BED, (Object) blockposition); ++ entityinsentient.getBehaviorController().setMemory(MemoryModuleType.NEAREST_BED, blockposition); // Tuinity - decompile fix + } + } else if (this.b < 5) { + this.a.long2LongEntrySet().removeIf((entry) -> { +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestItems.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestItems.java +index 2e3149a0b15299468079796bd3ea56eabdb4998c..943e269b99321cbd7373181a898dcdfa6cbb6a89 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestItems.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestItems.java +@@ -24,19 +24,24 @@ public class SensorNearestItems extends Sensor { + + protected void a(WorldServer worldserver, EntityInsentient entityinsentient) { + BehaviorController behaviorcontroller = entityinsentient.getBehaviorController(); +- List list = worldserver.a(EntityItem.class, entityinsentient.getBoundingBox().grow(8.0D, 4.0D, 8.0D), (entityitem) -> { +- return true; ++ // Tuinity start - remove streams ++ List list = worldserver.a(EntityItem.class, entityinsentient.getBoundingBox().grow(8.0D, 4.0D, 8.0D), (EntityItem item) -> { ++ return entityinsentient.i(item.getItemStack()) && item.a((Entity)entityinsentient, 9.0D); // copied from removed code, make sure to update - move here so we sort less + }); +- // Paper start - remove streams in favour of lists +- list.sort(Comparator.comparingDouble(entityinsentient::h)); ++ ++ list.sort(Comparator.comparingDouble(entityinsentient::h)); // better to take the sort perf hit than using line of sight more than we need to. + EntityItem nearest = null; +- for (EntityItem entityItem : list) { +- if (entityinsentient.i(entityItem.getItemStack()) && entityItem.a(entityinsentient, 9.0D) && entityinsentient.hasLineOfSight(entityItem)) { +- nearest = entityItem; ++ for (int index = 0, len = list.size(); index < len; ++index) { ++ EntityItem item = list.get(index); ++ if (entityinsentient.hasLineOfSight(item)) { ++ nearest = item; + break; + } + } +- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, Optional.ofNullable(nearest)); +- // Paper end ++ ++ Optional optional = Optional.ofNullable(nearest); ++ // Tuinity end - remove streams ++ ++ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, optional); + } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestLivingEntities.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestLivingEntities.java +index 0bc17d148e91277efdf72541e5470fa56d455670..845ed38e48fe404df1d2b0d5aba657628b1e2056 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestLivingEntities.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestLivingEntities.java +@@ -27,11 +27,16 @@ public class SensorNearestLivingEntities extends Sensor { + BehaviorController behaviorcontroller = entityliving.getBehaviorController(); + + behaviorcontroller.setMemory(MemoryModuleType.MOBS, list); // Paper - decompile error +- // Paper start - remove streams in favour of lists +- List visibleMobs = new java.util.ArrayList<>(list); +- visibleMobs.removeIf(otherEntityLiving -> !Sensor.a(entityliving, otherEntityLiving)); +- behaviorcontroller.setMemory(MemoryModuleType.VISIBLE_MOBS, visibleMobs); +- // Paper end ++ // Tuinity start - remove streams ++ List visible = new java.util.ArrayList<>(list.size()); ++ for (int index = 0, len = list.size(); index < len; ++index) { ++ EntityLiving nearby = list.get(index); ++ if (Sensor.a(entityliving, nearby)) { // copied from removed code, make sure to update ++ visible.add(nearby); ++ } ++ } ++ behaviorcontroller.setMemory(MemoryModuleType.VISIBLE_MOBS, visible); ++ // Tuinity end - remove streams + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestPlayers.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestPlayers.java +index 60e4da9217d4d950b5077baf6b50eaee20f8df09..c2afe3481265eb9390592ad46ba78d5be48d500f 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestPlayers.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestPlayers.java +@@ -26,26 +26,31 @@ public class SensorNearestPlayers extends Sensor { + + @Override + protected void a(WorldServer worldserver, EntityLiving entityliving) { +- // Paper start - remove streams in favour of lists +- List players = new java.util.ArrayList<>(worldserver.getPlayers()); +- players.removeIf(player -> !IEntitySelector.notSpectator().test(player) || !entityliving.a(player, 16.0D)); // Paper - removeIf only re-allocates once compared to iterator +- players.sort(Comparator.comparingDouble(entityliving::h)); +- ++ // Tuinity start - remove streams ++ List nearby = (List)worldserver.getNearbyPlayers(entityliving, entityliving.locX(), entityliving.locY(), entityliving.locZ(), ++ 16.0, IEntitySelector.g); ++ nearby.sort((e1, e2) -> Double.compare(entityliving.getDistanceSquared(e1), entityliving.getDistanceSquared(e2))); + BehaviorController behaviorcontroller = entityliving.getBehaviorController(); +- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_PLAYERS, players); + +- EntityHuman nearest = null, nearestTargetable = null; +- for (EntityHuman player : players) { +- if (Sensor.a(entityliving, player)) { +- if (nearest == null) nearest = player; +- if (IEntitySelector.canAITarget().test(player)) { +- nearestTargetable = player; +- break; // Both variables are assigned, no reason to loop further +- } ++ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_PLAYERS, nearby); ++ EntityHuman first = null; ++ EntityHuman firstNonSpectator = null; ++ for (int index = 0, len = nearby.size(); index < len; ++index) { ++ EntityHuman entity = nearby.get(index); ++ if (!Sensor.a(entityliving, (EntityLiving)entity)) { // copied from removed code, make sure to update ++ continue; ++ } ++ if (first == null) { ++ first = entity; ++ } ++ if (IEntitySelector.f.test(entity)) { // copied from removed code, make sure to update ++ firstNonSpectator = entity; ++ break; + } + } +- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, nearest); +- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, nearestTargetable); +- // Paper end ++ ++ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, first); ++ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, Optional.ofNullable(firstNonSpectator)); ++ // Tuinity end - remove streams + } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorVillagerBabies.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorVillagerBabies.java +index e5e246143f014d78dac765c97a5d9e3ac91a7793..aaf31114f3e09304db83270f4f521fa7f566da06 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorVillagerBabies.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorVillagerBabies.java +@@ -21,11 +21,23 @@ public class SensorVillagerBabies extends Sensor { + + @Override + protected void a(WorldServer worldserver, EntityLiving entityliving) { +- entityliving.getBehaviorController().setMemory(MemoryModuleType.VISIBLE_VILLAGER_BABIES, (Object) this.a(entityliving)); ++ entityliving.getBehaviorController().setMemory(MemoryModuleType.VISIBLE_VILLAGER_BABIES, this.a(entityliving)); // Tuinity - decompile fix + } + + private List a(EntityLiving entityliving) { +- return (List) this.c(entityliving).stream().filter(this::b).collect(Collectors.toList()); ++ // Tuinity start - remove streams ++ List nearby = this.c(entityliving); // copied from removed code, make sure to update ++ List ret = new java.util.ArrayList<>(); ++ ++ for (int index = 0, len = nearby.size(); index < len; ++index) { ++ EntityLiving entity = nearby.get(index); ++ if (this.b(entity)) { // copied from removed code, make sure to update ++ ret.add(entity); ++ } ++ } ++ ++ return ret; ++ // Tuinity end - remove streams + } + + private boolean b(EntityLiving entityliving) { +diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java b/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java +index e6988f7ea428f1503e3db63876b13e57f898ee30..88972dd8252bd2d2d8e384d616484ff682949fa8 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java ++++ b/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java +@@ -55,6 +55,7 @@ public class PathfinderTargetCondition { + return this; + } + ++ public final boolean test(@Nullable EntityLiving entityliving, EntityLiving entityliving1) { return this.a(entityliving, entityliving1); } // Tuinity - OBFHELPER + public boolean a(@Nullable EntityLiving entityliving, EntityLiving entityliving1) { + if (entityliving == entityliving1) { + return false; +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java +index ce165233739c7b92a76031b949f269bd0a11149c..13d94ecd703b3cd0412e138532d2dd74e5bf250d 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java ++++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java +@@ -4,6 +4,7 @@ import com.mojang.datafixers.DataFixer; + import com.mojang.datafixers.util.Pair; + import it.unimi.dsi.fastutil.longs.Long2ByteMap; + import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap; ++import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Tuinity + import it.unimi.dsi.fastutil.longs.LongOpenHashSet; + import it.unimi.dsi.fastutil.longs.LongSet; + import java.io.File; +@@ -35,8 +36,24 @@ import net.minecraft.world.level.chunk.storage.RegionFileSection; + + public class VillagePlace extends RegionFileSection { + +- private final VillagePlace.a a = new VillagePlace.a(); +- private final LongSet b = new LongOpenHashSet(); ++ // Tuinity start - unload poi data ++ // the vanilla tracker needs to be replaced because it does not support level removes ++ private final com.tuinity.tuinity.util.misc.Delayed26WayDistancePropagator3D villageDistanceTracker = new com.tuinity.tuinity.util.misc.Delayed26WayDistancePropagator3D(); ++ static final int POI_DATA_SOURCE = 7; ++ public static int convertBetweenLevels(final int level) { ++ return POI_DATA_SOURCE - level; ++ } ++ ++ protected void updateDistanceTracking(long section) { ++ if (this.isSectionDistanceTrackerSource(section)) { ++ this.villageDistanceTracker.setSource(section, POI_DATA_SOURCE); ++ } else { ++ this.villageDistanceTracker.removeSource(section); ++ } ++ } ++ // Tuinity end - unload poi data ++ ++ private final LongSet b = new LongOpenHashSet(); private final LongSet getLoadedChunks() { return this.b; } // Tuinity - OBFHELPER + + private final WorldServer world; // Paper + +@@ -47,9 +64,124 @@ public class VillagePlace extends RegionFileSection { + public VillagePlace(File file, DataFixer datafixer, boolean flag, WorldServer world) { + super(file, VillagePlaceSection::a, VillagePlaceSection::new, datafixer, DataFixTypes.POI_CHUNK, flag); + this.world = world; ++ if (world == null) { throw new IllegalStateException("world must be non-null"); }// Tuinity - require non-null + // Paper end - add world parameter + } + ++ // Tuinity start - actually unload POI data ++ private final java.util.TreeSet queuedUnloads = new java.util.TreeSet<>(); ++ private final Long2ObjectOpenHashMap queuedUnloadsByCoordinate = new Long2ObjectOpenHashMap<>(); ++ ++ static final class QueuedUnload implements Comparable { ++ ++ private final long unloadTick; ++ private final long coordinate; ++ ++ public QueuedUnload(long unloadTick, long coordinate) { ++ this.unloadTick = unloadTick; ++ this.coordinate = coordinate; ++ } ++ ++ @Override ++ public int compareTo(QueuedUnload other) { ++ if (other.unloadTick == this.unloadTick) { ++ return Long.compare(this.coordinate, other.coordinate); ++ } else { ++ return Long.compare(this.unloadTick, other.unloadTick); ++ } ++ } ++ ++ @Override ++ public int hashCode() { ++ int hash = 1; ++ hash = hash * 31 + Long.hashCode(this.unloadTick); ++ hash = hash * 31 + Long.hashCode(this.coordinate); ++ return hash; ++ } ++ ++ @Override ++ public boolean equals(Object obj) { ++ if (obj == null || obj.getClass() != QueuedUnload.class) { ++ return false; ++ } ++ QueuedUnload other = (QueuedUnload)obj; ++ return other.unloadTick == this.unloadTick && other.coordinate == this.coordinate; ++ } ++ } ++ ++ long determineDelay(long coordinate) { ++ if (this.isEmpty(coordinate)) { ++ return 5 * 60 * 20; ++ } else { ++ return 60 * 20; ++ } ++ } ++ ++ public void queueUnload(long coordinate, long minTarget) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("async poi unload queue"); ++ QueuedUnload unload = new QueuedUnload(minTarget + this.determineDelay(coordinate), coordinate); ++ QueuedUnload existing = this.queuedUnloadsByCoordinate.put(coordinate, unload); ++ if (existing != null) { ++ this.queuedUnloads.remove(existing); ++ } ++ this.queuedUnloads.add(unload); ++ } ++ ++ public void dequeueUnload(long coordinate) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("async poi unload dequeue"); ++ QueuedUnload unload = this.queuedUnloadsByCoordinate.remove(coordinate); ++ if (unload != null) { ++ this.queuedUnloads.remove(unload); ++ } ++ } ++ ++ public void pollUnloads(BooleanSupplier canSleepForTick) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("async poi unload"); ++ long currentTick = net.minecraft.server.MinecraftServer.currentTickLong; ++ net.minecraft.server.level.ChunkProviderServer chunkProvider = this.world.getChunkProvider(); ++ net.minecraft.server.level.PlayerChunkMap playerChunkMap = chunkProvider.playerChunkMap; ++ // copied target determination from PlayerChunkMap ++ int target = Math.min(this.queuedUnloads.size() - 100, (int) (this.queuedUnloads.size() * net.minecraft.server.level.PlayerChunkMap.UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Make more aggressive ++ for (java.util.Iterator iterator = this.queuedUnloads.iterator(); ++ iterator.hasNext() && (this.queuedUnloads.size() > target || canSleepForTick.getAsBoolean());) { ++ QueuedUnload unload = iterator.next(); ++ if (unload.unloadTick > currentTick) { ++ break; ++ } ++ ++ long coordinate = unload.coordinate; ++ ++ iterator.remove(); ++ this.queuedUnloadsByCoordinate.remove(coordinate); ++ ++ if (playerChunkMap.getUnloadingPlayerChunk(net.minecraft.server.MCUtil.getCoordinateX(coordinate), net.minecraft.server.MCUtil.getCoordinateZ(coordinate)) != null ++ || playerChunkMap.getUpdatingChunk(coordinate) != null) { ++ continue; ++ } ++ ++ this.unloadData(coordinate); ++ } ++ } ++ ++ @Override ++ public void unloadData(long coordinate) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("async unloading poi data"); ++ super.unloadData(coordinate); ++ } ++ ++ @Override ++ protected void onUnload(long coordinate) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("async poi unload callback"); ++ this.getLoadedChunks().remove(coordinate); ++ int chunkX = net.minecraft.server.MCUtil.getCoordinateX(coordinate); ++ int chunkZ = net.minecraft.server.MCUtil.getCoordinateZ(coordinate); ++ for (int section = 0; section < 16; ++section) { ++ long sectionPos = SectionPosition.asLong(chunkX, section, chunkZ); ++ this.updateDistanceTracking(sectionPos); ++ } ++ } ++ // Tuinity end - actually unload POI data ++ + public void a(BlockPosition blockposition, VillagePlaceType villageplacetype) { + ((VillagePlaceSection) this.e(SectionPosition.a(blockposition).s())).a(blockposition, villageplacetype); + } +@@ -108,31 +240,47 @@ public class VillagePlace extends RegionFileSection { + } + + public Optional c(Predicate predicate, Predicate predicate1, BlockPosition blockposition, int i, VillagePlace.Occupancy villageplace_occupancy) { +- return this.a(predicate, predicate1, blockposition, i, villageplace_occupancy).findFirst(); ++ // Tuinity start - re-route to faster logic ++ BlockPosition ret = com.tuinity.tuinity.util.PoiAccess.findAnyPoiPosition(this, predicate, predicate1, blockposition, i, villageplace_occupancy, false); ++ return Optional.ofNullable(ret); ++ // Tuinity end - re-route to faster logic + } + + public Optional d(Predicate predicate, BlockPosition blockposition, int i, VillagePlace.Occupancy villageplace_occupancy) { +- return this.c(predicate, blockposition, i, villageplace_occupancy).map(VillagePlaceRecord::f).min(Comparator.comparingDouble((blockposition1) -> { +- return blockposition1.j(blockposition); +- })); ++ // Tuinity start - re-route to faster logic ++ BlockPosition ret = com.tuinity.tuinity.util.PoiAccess.findClosestPoiDataPosition(this, predicate, null, blockposition, i, i*i, villageplace_occupancy, false); ++ return Optional.ofNullable(ret); ++ // Tuinity end - re-route to faster logic + } + + public Optional a(Predicate predicate, Predicate predicate1, BlockPosition blockposition, int i) { +- return this.c(predicate, blockposition, i, VillagePlace.Occupancy.HAS_SPACE).filter((villageplacerecord) -> { +- return predicate1.test(villageplacerecord.f()); +- }).findFirst().map((villageplacerecord) -> { +- villageplacerecord.b(); +- return villageplacerecord.f(); +- }); ++ // Tuinity start - re-route to faster logic ++ VillagePlaceRecord ret = com.tuinity.tuinity.util.PoiAccess.findAnyPoiRecord(this, predicate, predicate1, blockposition, i, ++ VillagePlace.Occupancy.HAS_SPACE, false); ++ if (ret == null) { ++ return Optional.empty(); ++ } ++ // copy from the map() from the old code ++ ret.b(); ++ return Optional.ofNullable(ret.f()); ++ // Tuinity end - re-route to faster logic + } + + public Optional a(Predicate predicate, Predicate predicate1, VillagePlace.Occupancy villageplace_occupancy, BlockPosition blockposition, int i, Random random) { +- List list = (List) this.c(predicate, blockposition, i, villageplace_occupancy).collect(Collectors.toList()); +- +- Collections.shuffle(list, random); +- return list.stream().filter((villageplacerecord) -> { +- return predicate1.test(villageplacerecord.f()); +- }).findFirst().map(VillagePlaceRecord::f); ++ // Tuinity start - re-route to faster logic ++ List list = new java.util.ArrayList<>(); ++ com.tuinity.tuinity.util.PoiAccess.findAnyPoiRecords(this, predicate, predicate1, blockposition, i, villageplace_occupancy, false, Integer.MAX_VALUE, list); ++ // Tuinity end - re-route to faster logic ++ ++ // Tuinity start - rewrite this to use improved logic ++ // the old method shuffled the list and then tried to find the first element in it that ++ // matched predicate1, however we moved predicate1 into the poi search. This means we can avoid a shuffle ++ // entirely, and just pick a random element from list ++ if (list.isEmpty()) { ++ return Optional.empty(); ++ } ++ return Optional.ofNullable(list.get(random.nextInt(list.size())).f()); ++ // Tuinity end - rewrite this to use improved logic + } + + public boolean b(BlockPosition blockposition) { +@@ -153,10 +301,11 @@ public class VillagePlace extends RegionFileSection { + } + + public int a(SectionPosition sectionposition) { +- this.a.a(); +- return this.a.c(sectionposition.s()); ++ this.villageDistanceTracker.propagateUpdates(); // Tuinity - replace distance tracking util ++ return convertBetweenLevels(this.villageDistanceTracker.getLevel(net.minecraft.server.MCUtil.getSectionKey(sectionposition))); // Tuinity - replace distance tracking util + } + ++ private boolean isSectionDistanceTrackerSource(long section) { return this.f(section); } // Tuinity - OBFHELPER + private boolean f(long i) { + Optional optional = this.c(i); + +@@ -172,7 +321,7 @@ public class VillagePlace extends RegionFileSection { + super.a(booleansupplier); + } else { + //super.a(booleansupplier); // re-implement below +- while (!((RegionFileSection)this).d.isEmpty() && booleansupplier.getAsBoolean()) { ++ while (!((RegionFileSection)this).d.isEmpty() && booleansupplier.getAsBoolean() && !this.world.isSavingDisabled()) { // Tuinity - unload POI data - don't write to disk if saving is disabled + ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(((RegionFileSection)this).d.firstLong()).r(); + + NBTTagCompound data; +@@ -180,22 +329,27 @@ public class VillagePlace extends RegionFileSection { + data = this.getData(chunkcoordintpair); + } + com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, +- chunkcoordintpair.x, chunkcoordintpair.z, data, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY); ++ chunkcoordintpair.x, chunkcoordintpair.z, data, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY); // Tuinity - use normal priority + } + } ++ // Tuinity start - unload POI data ++ if (!this.world.isSavingDisabled()) { // don't write to disk if saving is disabled ++ this.pollUnloads(booleansupplier); ++ } ++ // Tuinity end - unload POI data + // Paper end +- this.a.a(); ++ this.villageDistanceTracker.propagateUpdates(); // Tuinity - replace distance tracking until + } + + @Override + protected void a(long i) { + super.a(i); +- this.a.b(i, this.a.b(i), false); ++ this.updateDistanceTracking(i); // Tuinity - move to new distance tracking util + } + + @Override + protected void b(long i) { +- this.a.b(i, this.a.b(i), false); ++ this.updateDistanceTracking(i); // Tuinity - move to new distance tracking util + } + + public void a(ChunkCoordIntPair chunkcoordintpair, ChunkSection chunksection) { +@@ -260,7 +414,7 @@ public class VillagePlace extends RegionFileSection { + + @Override + protected int b(long i) { +- return VillagePlace.this.f(i) ? 0 : 7; ++ return VillagePlace.this.f(i) ? 0 : 7; // Tuinity - unload poi data - diff on change, this specifies the source level to use for distance tracking + } + + @Override +@@ -305,7 +459,7 @@ public class VillagePlace extends RegionFileSection { + if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { + com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave( + this.world, chunkcoordintpair.x, chunkcoordintpair.z, nbttagcompound, null, +- com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread()); ++ com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY); // Tuinity - writes are async, no need for priority + return; + } + super.write(chunkcoordintpair, nbttagcompound); +@@ -324,6 +478,7 @@ public class VillagePlace extends RegionFileSection { + this.d = predicate; + } + ++ public final Predicate getPredicate() { return this.a(); } // Tuinity - OBFHELPER + public Predicate a() { + return this.d; + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlaceRecord.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlaceRecord.java +index 3fcbf223c4835b92a7da0df9e5443ca1e5217bb4..29a291bc08d8043e5bd8353798be930582455feb 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlaceRecord.java ++++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlaceRecord.java +@@ -8,7 +8,7 @@ import net.minecraft.core.IRegistry; + + public class VillagePlaceRecord { + +- private final BlockPosition a; ++ private final BlockPosition a; public final BlockPosition getPosition() { return this.a; } // Tuinity - OBFHELPER + private final VillagePlaceType b; + private int c; + private final Runnable d; +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlaceSection.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlaceSection.java +index a72bd9ce8f683ae3f4d9c08c973292e3433e8f16..41ffad7cbb6c77713736f37b3728b201d315f6d4 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlaceSection.java ++++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlaceSection.java +@@ -27,12 +27,12 @@ public class VillagePlaceSection { + + private static final Logger LOGGER = LogManager.getLogger(); + private final Short2ObjectMap b; +- private final Map> c; ++ private final Map> c; public final Map> getData() { return this.c; } // Tuinity - OBFHELPER + private final Runnable d; + private boolean e; + + public static Codec a(Runnable runnable) { +- Codec codec = RecordCodecBuilder.create((instance) -> { ++ Codec codec = RecordCodecBuilder.create((instance) -> { // Tuinity - decompile fix + return instance.group(RecordCodecBuilder.point(runnable), Codec.BOOL.optionalFieldOf("Valid", false).forGetter((villageplacesection) -> { + return villageplacesection.e; + }), VillagePlaceRecord.a(runnable).listOf().fieldOf("Records").forGetter((villageplacesection) -> { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCat.java b/src/main/java/net/minecraft/world/entity/animal/EntityCat.java +index 054a1a74c48a3d936e45cc6b62a9fd6a90663cbc..c8f529b3fd227ce3354f442038b27cd716f57254 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityCat.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityCat.java +@@ -355,7 +355,7 @@ public class EntityCat extends EntityTameableAnimal { + + WorldServer worldserver = worldaccess.getMinecraftWorld(); + +- if (worldserver instanceof WorldServer && ((WorldServer) worldserver).getStructureManager().a(this.getChunkCoordinates(), true, StructureGenerator.SWAMP_HUT).e()) { ++ if (worldserver instanceof WorldServer && ((WorldServer) worldserver).getStructureManager().getStructureStarts(this.getChunkCoordinates(), true, StructureGenerator.SWAMP_HUT, worldaccess).e()) { // Tuinity - fix deadlock on chunk gen + this.setCatType(10); + this.setPersistent(); + } +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +index c296fcf80c2f3f210fa020416973ec8d5db541ba..07160de8725787551df327c0790b2d6e0876524f 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +@@ -625,9 +625,9 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { + if (this.deathAnimationTicks == 1 && !this.isSilent()) { + // CraftBukkit start - Use relative location for far away sounds + // this.world.b(1028, this.getChunkCoordinates(), 0); +- int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API ++ //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API // Tuinity - apply view distance patch + for (net.minecraft.server.level.EntityPlayer player : (List) ((WorldServer)world).getPlayers()) { +- // final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch ++ final int viewDistance = player.getBukkitEntity().getViewDistance(); // Tuinity - apply view distance patch + // Paper end + double deltaX = this.locX() - player.locX(); + double deltaZ = this.locZ() - player.locZ(); +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java +index 229eabe0510e6c3660236ed0fb3e80d41074642c..930fc752ec0a988b17bc556cd428161638a14f27 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java +@@ -264,9 +264,9 @@ public class EntityWither extends EntityMonster implements IRangedEntity { + if (!this.isSilent()) { + // CraftBukkit start - Use relative location for far away sounds + // this.world.b(1023, new BlockPosition(this), 0); +- int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API ++ //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API // Tuinity - apply view distance patch + for (EntityPlayer player : (List)this.world.getPlayers()) { +- // final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch ++ final int viewDistance = player.getBukkitEntity().getViewDistance(); // Tuinity - apply view distance patch + double deltaX = this.locX() - player.locX(); + double deltaZ = this.locZ() - player.locZ(); + double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; +diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +index 575833807ff647f30d7c2b7abcd01701c7dec85b..5dc3670f35b04d933e96c4b42aa9fbcf941e69c7 100644 +--- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java ++++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +@@ -553,7 +553,7 @@ public class EntityItem extends Entity { + + // Paper start - fix MC-4 + public void setPositionRaw(double x, double y, double z) { +- if (com.destroystokyo.paper.PaperConfig.fixEntityPositionDesync) { ++ if (false && com.destroystokyo.paper.PaperConfig.fixEntityPositionDesync) { // Tuinity - revert + // encode/decode from PacketPlayOutEntity + x = MathHelper.floorLong(x * 4096.0D) * (1 / 4096.0D); + y = MathHelper.floorLong(y * 4096.0D) * (1 / 4096.0D); +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index ec0956a98c133bcd3d4f92f696c667eab6ff98f1..44038dd278b988508047023107683e5370af54ad 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -453,6 +453,12 @@ public abstract class EntityHuman extends EntityLiving { + this.activeContainer = this.defaultContainer; + } + // Paper end ++ // Tuinity start - special close for unloaded inventory ++ public void closeUnloadedInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ closeInventory(); ++ this.activeContainer = this.defaultContainer; ++ } ++ // Tuinity end - special close for unloaded inventory + + public void closeInventory() { + this.activeContainer = this.defaultContainer; +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java +index 2f8b3587f527620152609d5be342b328a7621e0f..e440d26c920c4efddf958c61bfdfa508273062cc 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java +@@ -211,7 +211,9 @@ public abstract class EntityArrow extends IProjectile { + // Paper end + + if (object != null && !flag) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, (MovingObjectPosition) object)) { // CraftBukkit - Call event // Paper - make cancellable // Tuinity - implement cancellation properly + this.a((MovingObjectPosition) object); ++ } // Tuinity - implement cancellation properly + this.impulse = true; + } + +@@ -545,7 +547,8 @@ public abstract class EntityArrow extends IProjectile { + } + itemstack = item.getItemStack(); + } +- boolean flag = this.fromPlayer == EntityArrow.PickupStatus.ALLOWED || this.fromPlayer == EntityArrow.PickupStatus.CREATIVE_ONLY && entityhuman.abilities.canInstantlyBuild || this.t() && this.getShooter().getUniqueID() == entityhuman.getUniqueID(); ++ Entity shooter; // Tuinity - fix NPE here ++ boolean flag = this.fromPlayer == EntityArrow.PickupStatus.ALLOWED || this.fromPlayer == EntityArrow.PickupStatus.CREATIVE_ONLY && entityhuman.abilities.canInstantlyBuild || this.t() && ((shooter = this.getShooter()) != null && shooter.getUniqueID() == entityhuman.getUniqueID()); // Tuinity - fix NPE here + + if (this.fromPlayer == EntityArrow.PickupStatus.ALLOWED && !entityhuman.inventory.pickup(itemstack)) { + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java +index b9680f6f2e30ec9397d6a9c83e79563d9253aff6..546de0ec2b624a781480ac95f65b2cbfbb5dcf2e 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java +@@ -83,7 +83,9 @@ public abstract class EntityFireball extends IProjectile { + // Paper end + + if (movingobjectposition != null && movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS) { // Paper - add null check in case cancelled ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition)) { // CraftBukkit - Call event // Paper - make cancellable // Tuinity - implement cancellation properly + this.a(movingobjectposition); ++ } // Tuinity - implement cancellation properly + + // CraftBukkit start - Fire ProjectileHitEvent + if (this.dead) { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java +index 9cc59439ae2c4e758c44b2a92b78bc328efdfa1b..f9a355c847d778a9aad1987882fc816af92450ba 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java +@@ -149,7 +149,9 @@ public class EntityFireworks extends IProjectile { + MovingObjectPosition movingobjectposition = ProjectileHelper.a((Entity) this, this::a); + + if (!this.noclip) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition)) { // CraftBukkit - Call event // Paper - make cancellable // Tuinity - implement cancellation properly + this.a(movingobjectposition); ++ } // Tuinity - implement cancellation properly + this.impulse = true; + } + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java +index addea9c1309a308b76c93ee71e839c915bc773e8..dc6d279766ccc83a8f450028a09491b1c88f524c 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java +@@ -265,7 +265,9 @@ public class EntityFishingHook extends IProjectile { + private void m() { + MovingObjectPosition movingobjectposition = ProjectileHelper.a((Entity) this, this::a); + ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition)) { // CraftBukkit - Call event // Paper - make cancellable // Tuinity - implement cancellation properly + this.a(movingobjectposition); ++ } // Tuinity - implement cancellation properly + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityLlamaSpit.java b/src/main/java/net/minecraft/world/entity/projectile/EntityLlamaSpit.java +index 39b34e619cf7ac3ad308f98551c796ac47073484..8aef834a6e8fcf5d44986745affb8f27bc3dfd6b 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityLlamaSpit.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityLlamaSpit.java +@@ -34,7 +34,9 @@ public class EntityLlamaSpit extends IProjectile { + MovingObjectPosition movingobjectposition = ProjectileHelper.a((Entity) this, this::a); + + if (movingobjectposition != null) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition)) { // CraftBukkit - Call event // Paper - make cancellable // Tuinity - implement cancellation properly + this.a(movingobjectposition); ++ } // Tuinity - implement cancellation properly + } + + double d0 = this.locX() + vec3d.x; +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java +index 3b379e83b79bd9b46dbdd4a48ac3842abc4dfbb8..e55061b6c04b4bde92404a6ef58ba9a52cd99c1d 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java +@@ -65,7 +65,7 @@ public abstract class EntityProjectile extends IProjectile { + movingobjectposition = null; + } + } +- if (movingobjectposition != null) { ++ if (movingobjectposition != null && org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition)) { // Tuinity - implement cancellation properly + // Paper end + this.a(movingobjectposition); + } // Paper +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityShulkerBullet.java b/src/main/java/net/minecraft/world/entity/projectile/EntityShulkerBullet.java +index c3dcebad0706386e52ef2d28f2074cb6aed9f9e4..1ae528ccd09a6536b3aac320e6218f03c274d6a9 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityShulkerBullet.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityShulkerBullet.java +@@ -230,7 +230,7 @@ public class EntityShulkerBullet extends IProjectile { + + MovingObjectPosition movingobjectposition = ProjectileHelper.a((Entity) this, this::a); + +- if (movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS) { ++ if (movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS && org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition)) { // Tuinity - implement cancellation properly + this.a(movingobjectposition); + } + } +diff --git a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java +index 9f2e7d345d98f50e6d47cbf4bb35714852fa42da..2e2e4ee98619cfbeaecffa1ebae78ccc1d7666ca 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java +@@ -130,7 +130,7 @@ public abstract class IProjectile extends Entity { + } + + protected void a(MovingObjectPosition movingobjectposition) { +- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition)) return; // CraftBukkit - Call event // Paper - make cancellable ++ // Tuinity - proper cancellation requires moving this into the caller (see method overrides) - TODO this unfortunately means we need to manually inspect each call on update + MovingObjectPosition.EnumMovingObjectType movingobjectposition_enummovingobjecttype = movingobjectposition.getType(); + + if (movingobjectposition_enummovingobjecttype == MovingObjectPosition.EnumMovingObjectType.ENTITY) { +diff --git a/src/main/java/net/minecraft/world/item/ItemEnderEye.java b/src/main/java/net/minecraft/world/item/ItemEnderEye.java +index f74685a7cdb905af8e9712ca8597e7ed3dc8b120..feedbd8c97c1b1c56eaff359e6a940696d416906 100644 +--- a/src/main/java/net/minecraft/world/item/ItemEnderEye.java ++++ b/src/main/java/net/minecraft/world/item/ItemEnderEye.java +@@ -60,9 +60,10 @@ public class ItemEnderEye extends Item { + + // CraftBukkit start - Use relative location for far away sounds + // world.b(1038, blockposition1.b(1, 0, 1), 0); +- int viewDistance = world.getServer().getViewDistance() * 16; ++ //int viewDistance = world.getServer().getViewDistance() * 16; // Tuinity - apply view distance patch + BlockPosition soundPos = blockposition1.b(1, 0, 1); + for (EntityPlayer player : world.getServer().getServer().getPlayerList().players) { ++ final int viewDistance = player.getBukkitEntity().getViewDistance(); // Tuinity - apply view distance patch + double deltaX = soundPos.getX() - player.locX(); + double deltaZ = soundPos.getZ() - player.locZ(); + double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; +diff --git a/src/main/java/net/minecraft/world/level/ChunkCache.java b/src/main/java/net/minecraft/world/level/ChunkCache.java +index 7a760ef0264c9041c38bdfb8fd31333052c26139..b547eb352f90f68cf36ffb82e43ad7acb1892f6a 100644 +--- a/src/main/java/net/minecraft/world/level/ChunkCache.java ++++ b/src/main/java/net/minecraft/world/level/ChunkCache.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.level; + ++import java.util.List; + import java.util.function.Predicate; + import java.util.stream.Stream; + import javax.annotation.Nullable; +@@ -26,6 +27,156 @@ public class ChunkCache implements IBlockAccess, ICollisionAccess { + protected boolean d; + protected final World e; protected final World getWorld() { return e; } // Paper - OBFHELPER + ++ // Tuinity start - optimise pathfinder collision detection ++ @Override ++ public boolean getCubes(Entity entity) { ++ return !this.getCollisionsForBlocksOrWorldBorder(entity, entity.getBoundingBox(), null, true, null); ++ } ++ ++ @Override ++ public boolean getCubes(Entity entity, AxisAlignedBB axisalignedbb) { ++ return !this.getCollisionsForBlocksOrWorldBorder(entity, axisalignedbb, null, true, null); ++ } ++ ++ @Override ++ public boolean getCubes(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate) { ++ return !this.getCollisionsForBlocksOrWorldBorder(entity, axisalignedbb, null, true, null); ++ } ++ ++ public boolean getCollisionsForBlocksOrWorldBorder(@Nullable Entity entity, AxisAlignedBB axisalignedbb, List list, ++ boolean collidesWithUnloaded, ++ java.util.function.BiPredicate predicate) { ++ boolean ret = false; ++ final boolean checkOnly = true; ++ ++ if (entity != null) { ++ if (this.getWorldBorder().isAlmostCollidingOnBorder(axisalignedbb)) { ++ if (checkOnly) { ++ return true; ++ } else { ++ net.minecraft.world.phys.shapes.VoxelShapes.addBoxesTo(this.getWorldBorder().getCollisionShape(), list); ++ ret = true; ++ } ++ } ++ } ++ ++ int minBlockX = net.minecraft.util.MathHelper.floor(axisalignedbb.minX - net.minecraft.server.MCUtil.COLLISION_EPSILON) - 1; ++ int maxBlockX = net.minecraft.util.MathHelper.floor(axisalignedbb.maxX + net.minecraft.server.MCUtil.COLLISION_EPSILON) + 1; ++ ++ int minBlockY = net.minecraft.util.MathHelper.floor(axisalignedbb.minY - net.minecraft.server.MCUtil.COLLISION_EPSILON) - 1; ++ int maxBlockY = net.minecraft.util.MathHelper.floor(axisalignedbb.maxY + net.minecraft.server.MCUtil.COLLISION_EPSILON) + 1; ++ ++ int minBlockZ = net.minecraft.util.MathHelper.floor(axisalignedbb.minZ - net.minecraft.server.MCUtil.COLLISION_EPSILON) - 1; ++ int maxBlockZ = net.minecraft.util.MathHelper.floor(axisalignedbb.maxZ + net.minecraft.server.MCUtil.COLLISION_EPSILON) + 1; ++ ++ ++ BlockPosition.MutableBlockPosition mutablePos = new BlockPosition.MutableBlockPosition(); ++ net.minecraft.world.phys.shapes.VoxelShapeCollision collisionShape = null; ++ ++ // special cases: ++ if (minBlockY > 255 || maxBlockY < 0) { ++ // no point in checking ++ return ret; ++ } ++ ++ int minYIterate = Math.max(0, minBlockY); ++ int maxYIterate = Math.min(255, maxBlockY); ++ ++ int minChunkX = minBlockX >> 4; ++ int maxChunkX = maxBlockX >> 4; ++ ++ int minChunkZ = minBlockZ >> 4; ++ int maxChunkZ = maxBlockZ >> 4; ++ ++ // TODO special case single chunk? ++ ++ for (int currChunkZ = minChunkZ; currChunkZ <= maxChunkZ; ++currChunkZ) { ++ int minZ = currChunkZ == minChunkZ ? minBlockZ & 15 : 0; // coordinate in chunk ++ int maxZ = currChunkZ == maxChunkZ ? maxBlockZ & 15 : 15; // coordinate in chunk ++ ++ for (int currChunkX = minChunkX; currChunkX <= maxChunkX; ++currChunkX) { ++ int minX = currChunkX == minChunkX ? minBlockX & 15 : 0; // coordinate in chunk ++ int maxX = currChunkX == maxChunkX ? maxBlockX & 15 : 15; // coordinate in chunk ++ ++ int chunkXGlobalPos = currChunkX << 4; ++ int chunkZGlobalPos = currChunkZ << 4; ++ net.minecraft.world.level.chunk.Chunk chunk = (net.minecraft.world.level.chunk.Chunk)this.getChunkIfLoaded(currChunkX, currChunkZ); ++ ++ if (chunk == null) { ++ if (collidesWithUnloaded) { ++ if (checkOnly) { ++ return true; ++ } else { ++ list.add(AxisAlignedBB.getBoxForChunk(currChunkX, currChunkZ)); ++ ret = true; ++ } ++ } ++ continue; ++ } ++ ++ net.minecraft.world.level.chunk.ChunkSection[] sections = chunk.getSections(); ++ ++ // bound y ++ ++ for (int currY = minYIterate; currY <= maxYIterate; ++currY) { ++ net.minecraft.world.level.chunk.ChunkSection section = sections[currY >>> 4]; ++ if (section == null || section.isFullOfAir()) { ++ // empty ++ // skip to next section ++ currY = (currY & ~(15)) + 15; // increment by 15: iterator loop increments by the extra one ++ continue; ++ } ++ ++ net.minecraft.world.level.chunk.DataPaletteBlock blocks = section.blockIds; ++ ++ for (int currZ = minZ; currZ <= maxZ; ++currZ) { ++ for (int currX = minX; currX <= maxX; ++currX) { ++ int localBlockIndex = (currX) | (currZ << 4) | ((currY & 15) << 8); ++ int blockX = currX | chunkXGlobalPos; ++ int blockY = currY; ++ int blockZ = currZ | chunkZGlobalPos; ++ ++ int edgeCount = ((blockX == minBlockX || blockX == maxBlockX) ? 1 : 0) + ++ ((blockY == minBlockY || blockY == maxBlockY) ? 1 : 0) + ++ ((blockZ == minBlockZ || blockZ == maxBlockZ) ? 1 : 0); ++ if (edgeCount == 3) { ++ continue; ++ } ++ ++ IBlockData blockData = blocks.rawGet(localBlockIndex); ++ ++ if ((edgeCount != 1 || blockData.shapeExceedsCube()) && (edgeCount != 2 || blockData.getBlock() == Blocks.MOVING_PISTON)) { ++ mutablePos.setValues(blockX, blockY, blockZ); ++ if (collisionShape == null) { ++ collisionShape = entity == null ? net.minecraft.world.phys.shapes.VoxelShapeCollision.a() : net.minecraft.world.phys.shapes.VoxelShapeCollision.a(entity); ++ } ++ VoxelShape voxelshape2 = blockData.getCollisionShape(this, mutablePos, collisionShape); ++ if (voxelshape2 != net.minecraft.world.phys.shapes.VoxelShapes.getEmptyShape()) { ++ VoxelShape voxelshape3 = voxelshape2.offset((double)blockX, (double)blockY, (double)blockZ); ++ ++ if (predicate != null && !predicate.test(blockData, mutablePos)) { ++ continue; ++ } ++ ++ if (checkOnly) { ++ if (voxelshape3.intersects(axisalignedbb)) { ++ return true; ++ } ++ } else { ++ ret |= net.minecraft.world.phys.shapes.VoxelShapes.addBoxesToIfIntersects(voxelshape3, axisalignedbb, list); ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ return ret; ++ } ++ // Tuinity end - optimise pathfinder collision detection ++ + public ChunkCache(World world, BlockPosition blockposition, BlockPosition blockposition1) { + this.e = world; + this.a = blockposition.getX() >> 4; +diff --git a/src/main/java/net/minecraft/world/level/IBlockAccess.java b/src/main/java/net/minecraft/world/level/IBlockAccess.java +index 21ce19b9caf3150535a3f84027242a93bdd0d263..e612e1d30f76e217b1aa23488ab025adce048f57 100644 +--- a/src/main/java/net/minecraft/world/level/IBlockAccess.java ++++ b/src/main/java/net/minecraft/world/level/IBlockAccess.java +@@ -67,7 +67,8 @@ public interface IBlockAccess { + return MovingObjectPositionBlock.a(raytrace1.a(), EnumDirection.a(vec3d.x, vec3d.y, vec3d.z), new BlockPosition(raytrace1.a())); + } + // Paper end +- Fluid fluid = this.getFluid(blockposition); ++ if (iblockdata.isAir()) return null; // Tuinity - optimise air cases ++ Fluid fluid = iblockdata.getFluid(); // Tuinity - don't need to go to world state again + Vec3D vec3d = raytrace1.b(); + Vec3D vec3d1 = raytrace1.a(); + VoxelShape voxelshape = raytrace1.a(iblockdata, this, blockposition); +diff --git a/src/main/java/net/minecraft/world/level/ICollisionAccess.java b/src/main/java/net/minecraft/world/level/ICollisionAccess.java +index fcb3e2f9dea97138e0fd4cd2eb11b54799e1d3b5..1c66d6c69148e6aa45641c0351d63c9b96ffb1d3 100644 +--- a/src/main/java/net/minecraft/world/level/ICollisionAccess.java ++++ b/src/main/java/net/minecraft/world/level/ICollisionAccess.java +@@ -36,6 +36,11 @@ public interface ICollisionAccess extends IBlockAccess { + } + + default boolean b(AxisAlignedBB axisalignedbb) { ++ // Tuinity start - allow overriding in WorldServer ++ return this.getCubes(axisalignedbb); ++ } ++ default boolean getCubes(AxisAlignedBB axisalignedbb) { ++ // Tuinity end - allow overriding in WorldServer + return this.b((Entity) null, axisalignedbb, (entity) -> { + return true; + }); +@@ -54,6 +59,11 @@ public interface ICollisionAccess extends IBlockAccess { + } + + default boolean b(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate) { ++ // Tuinity start - allow overriding in WorldServer ++ return this.getCubes(entity, axisalignedbb, predicate); ++ } ++ default boolean getCubes(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate) { ++ // Tuinity end - allow overriding in WorldServer + try { if (entity != null) entity.collisionLoadChunks = true; // Paper + return this.d(entity, axisalignedbb, predicate).allMatch(VoxelShape::isEmpty); + } finally { if (entity != null) entity.collisionLoadChunks = false; } // Paper +diff --git a/src/main/java/net/minecraft/world/level/IEntityAccess.java b/src/main/java/net/minecraft/world/level/IEntityAccess.java +index 1ff9e771788a4ab52129070e355ca48df2949470..a7f2304acf8ee0a15d6eae8c42060e003be13ae7 100644 +--- a/src/main/java/net/minecraft/world/level/IEntityAccess.java ++++ b/src/main/java/net/minecraft/world/level/IEntityAccess.java +@@ -64,16 +64,26 @@ public interface IEntityAccess { + return this.b(oclass, axisalignedbb, IEntitySelector.g); + } + ++ // Tuinity start - optimise hard collision ++ /** ++ * Not guaranteed to only return hard colliding entities ++ */ ++ default List getHardCollidingEntities(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate) { ++ return this.getEntities(entity, axisalignedbb, predicate); ++ } ++ // Tuinity end - optimise hard collision ++ + default Stream c(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate) { + if (axisalignedbb.a() < 1.0E-7D) { + return Stream.empty(); + } else { +- AxisAlignedBB axisalignedbb1 = axisalignedbb.g(1.0E-7D); ++ AxisAlignedBB axisalignedbb1 = axisalignedbb.g(-1.0E-7D); // Tuinity - to comply with vanilla intersection rules, expand by -epsilon so we only get stuff we definitely collide with. expanding by +epsilon gives us stuff we don't collide with, which will screw over callers in some cases. + +- return this.getEntities(entity, axisalignedbb1, predicate.and((entity1) -> { ++ if (predicate == null) predicate = (e) -> true; // Tuinity - allow nullable ++ predicate = predicate.and((entity1) -> { // Tuinity - optimise entity hard collisions // Tuinity - allow nullable + boolean flag; + +- if (entity1.getBoundingBox().c(axisalignedbb1)) { ++ if (true || entity1.getBoundingBox().c(axisalignedbb1)) { // Tuinity - always true, wtf did they think this.getEntities(entity, axisalignedbb1) does? + label25: + { + if (entity == null) { +@@ -91,13 +101,13 @@ public interface IEntityAccess { + + flag = false; + return flag; +- })).stream().map(Entity::getBoundingBox).map(VoxelShapes::a); ++ }); return ((entity != null && entity.hardCollides()) ? this.getEntities(entity, axisalignedbb1, predicate) : this.getHardCollidingEntities(entity, axisalignedbb1, predicate)).stream().map(Entity::getBoundingBox).map(VoxelShapes::a); // Tuinity - optimise entity hard collisions + } + } + + default EntityHuman findNearbyPlayer(Entity entity, double d0, @Nullable Predicate predicate) { return this.findNearbyPlayer(entity.locX(), entity.locY(), entity.locZ(), d0, predicate); } // Paper + @Nullable default EntityHuman findNearbyPlayer(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { return a(d0, d1, d2, d3, predicate); } // Paper - OBFHELPER +- @Nullable default EntityHuman a(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { // Paper ++ @Nullable default EntityHuman a(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { // Paper // Tuinity - diff on change, override in World - this should be "get closest player that matches predicate" + double d4 = -1.0D; + EntityHuman entityhuman = null; + Iterator iterator = this.getPlayers().iterator(); +@@ -198,27 +208,27 @@ public interface IEntityAccess { + } + + @Nullable +- default EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving) { ++ default EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving) { // Tuinity - diff on change, override in World - this should be "get closest player that matches path finder target condition" + return (EntityHuman) this.a(this.getPlayers(), pathfindertargetcondition, entityliving, entityliving.locX(), entityliving.locY(), entityliving.locZ()); + } + + @Nullable +- default EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving, double d0, double d1, double d2) { ++ default EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving, double d0, double d1, double d2) { // Tuinity - diff on change, override in World - this should be "get closest player that matches path finder target condition" + return (EntityHuman) this.a(this.getPlayers(), pathfindertargetcondition, entityliving, d0, d1, d2); + } + + @Nullable +- default EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, double d0, double d1, double d2) { ++ default EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, double d0, double d1, double d2) { // Tuinity - diff on change, override in World - this should be "get closest player that matches path finder target condition" + return (EntityHuman) this.a(this.getPlayers(), pathfindertargetcondition, (EntityLiving) null, d0, d1, d2); + } + + @Nullable +- default T a(Class oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { ++ default T a(Class oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { // Tuinity - diff on change, override in World - this should be "get closest entity by class that matches path finder target condition" + return this.a(this.a(oclass, axisalignedbb, null), pathfindertargetcondition, entityliving, d0, d1, d2); // Paper - decompile fix + } + + @Nullable +- default T b(Class oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { ++ default T b(Class oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { // Tuinity - diff on change, override in World - this should be "get closest entity by class that matches path finder target condition" + return this.a(this.b(oclass, axisalignedbb, null), pathfindertargetcondition, entityliving, d0, d1, d2); // Paper - decompile fix + } + +@@ -244,7 +254,7 @@ public interface IEntityAccess { + return t0; + } + +- default List a(PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving, AxisAlignedBB axisalignedbb) { ++ default List a(PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving, AxisAlignedBB axisalignedbb) { // Tuinity - diff on change, override in World - this should be "get players that matches path finder target condition" + List list = Lists.newArrayList(); + Iterator iterator = this.getPlayers().iterator(); + +diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java +index 24771c3522ea74ac12058591137eafc21adf3762..d497006f05f79015cd791849888832bb53f4a414 100644 +--- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java ++++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java +@@ -64,9 +64,9 @@ public final class SpawnerCreature { + + public static SpawnerCreature.d a(int i, Iterable iterable, SpawnerCreature.b spawnercreature_b) { + // Paper start - add countMobs parameter +- return countMobs(i, iterable, spawnercreature_b, false); ++ return countMobs(i, iterable, spawnercreature_b, false, null); // Tuinity - it'll still be broken no matter what + } +- public static SpawnerCreature.d countMobs(int i, Iterable iterable, SpawnerCreature.b spawnercreature_b, boolean countMobs) { ++ public static SpawnerCreature.d countMobs(int i, Iterable iterable, SpawnerCreature.b spawnercreature_b, boolean countMobs, net.minecraft.server.level.ChunkProviderServer chunkProvider) { // Tuinity - add CPS param + // Paper end - add countMobs parameter + SpawnerCreatureProbabilities spawnercreatureprobabilities = new SpawnerCreatureProbabilities(); + Object2IntOpenHashMap object2intopenhashmap = new Object2IntOpenHashMap(); +@@ -97,7 +97,16 @@ public final class SpawnerCreature { + BlockPosition blockposition = entity.getChunkCoordinates(); + long j = ChunkCoordIntPair.pair(blockposition.getX() >> 4, blockposition.getZ() >> 4); + +- spawnercreature_b.query(j, (chunk) -> { ++ // Tuinity start - remove chunk lookup and lambda ++ Chunk chunk = entity.getCurrentChunk(); ++ if (chunk == null || j != chunk.coordinateKey) { // no chunk or coordinate doesn't match ++ chunk = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ if (chunk == null) { ++ // unloaded chunk! no longer FULL. ++ continue; ++ } ++ } ++ // Tuinity end - remove chunk lookup and lambda + BiomeSettingsMobs.b biomesettingsmobs_b = b(blockposition, chunk).b().a(entity.getEntityType()); + + if (biomesettingsmobs_b != null) { +@@ -107,10 +116,10 @@ public final class SpawnerCreature { + object2intopenhashmap.addTo(enumcreaturetype, 1); + // Paper start + if (countMobs) { +- ((WorldServer)chunk.world).getChunkProvider().playerChunkMap.updatePlayerMobTypeMap(entity); ++ chunkProvider.playerChunkMap.updatePlayerMobTypeMap(entity); // Tuinity - directly use chunk provider + } + // Paper end +- }); ++ // Tuinity - remove chunk lookup and lambda + } + } + +@@ -250,7 +259,7 @@ public final class SpawnerCreature { + blockposition_mutableblockposition.d(l, i, i1); + double d0 = (double) l + 0.5D; + double d1 = (double) i1 + 0.5D; +- EntityHuman entityhuman = worldserver.a(d0, (double) i, d1, -1.0D, false); ++ EntityHuman entityhuman = worldserver.a(d0, (double) i, d1, 576.0D, false); // Tuinity - copied from below method for range, for the love of god we do not need to fucking find the closet player outside of this range - limiting range lets us use the distance map + + if (entityhuman != null) { + double d2 = entityhuman.h(d0, (double) i, d1); +@@ -322,7 +331,7 @@ public final class SpawnerCreature { + } + + private static boolean a(WorldServer worldserver, IChunkAccess ichunkaccess, BlockPosition.MutableBlockPosition blockposition_mutableblockposition, double d0) { +- if (d0 <= 576.0D) { ++ if (d0 <= 576.0D) { // Tuinity - diff on change, copy into caller + return false; + } else if (worldserver.getSpawn().a((IPosition) (new Vec3D((double) blockposition_mutableblockposition.getX() + 0.5D, (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + 0.5D)), 24.0D)) { + return false; +diff --git a/src/main/java/net/minecraft/world/level/StructureManager.java b/src/main/java/net/minecraft/world/level/StructureManager.java +index 1077f988e16688f74c9e40d6da517c954cb06ecb..acacbf9617f99b97fc7fd2ba718775e1b3e429e9 100644 +--- a/src/main/java/net/minecraft/world/level/StructureManager.java ++++ b/src/main/java/net/minecraft/world/level/StructureManager.java +@@ -45,8 +45,13 @@ public class StructureManager { + + // Paper start - remove structure streams + public java.util.List> getFeatureStarts(SectionPosition sectionPosition, StructureGenerator structureGenerator) { ++ // Tuinity start - add world parameter ++ return this.getFeatureStarts(sectionPosition, structureGenerator, null); ++ } ++ public java.util.List> getFeatureStarts(SectionPosition sectionPosition, StructureGenerator structureGenerator, IWorldReader world) { ++ // Tuinity end - add world parameter + java.util.List> list = new ObjectArrayList<>(); +- for (Long curLong: getLevel().getChunkAt(sectionPosition.a(), sectionPosition.c(), ChunkStatus.STRUCTURE_REFERENCES).b(structureGenerator)) { ++ for (Long curLong: (world == null ? getLevel() : world).getChunkAt(sectionPosition.a(), sectionPosition.c(), ChunkStatus.STRUCTURE_REFERENCES).b(structureGenerator)) { // Tuinity - fix deadlock on world gen - chunk can be unloaded while generating, so we should be using the generator's regionlimitedaccess so we always get the chunk + SectionPosition sectionPosition1 = SectionPosition.a(new ChunkCoordIntPair(curLong), 0); + StructureStart structurestart = a(sectionPosition1, structureGenerator, getLevel().getChunkAt(sectionPosition1.a(), sectionPosition1.c(), ChunkStatus.STRUCTURE_STARTS)); + if (structurestart != null && structurestart.e()) { +@@ -75,8 +80,12 @@ public class StructureManager { + } + + public StructureStart a(BlockPosition blockposition, boolean flag, StructureGenerator structuregenerator) { ++ // Tuinity start - add world parameter ++ return this.getStructureStarts(blockposition,flag, structuregenerator, null); ++ } ++ public StructureStart getStructureStarts(BlockPosition blockposition, boolean flag, StructureGenerator structuregenerator, IWorldReader world) { + // Paper start - remove structure streams +- for (StructureStart structurestart : getFeatureStarts(SectionPosition.a(blockposition), structuregenerator)) { ++ for (StructureStart structurestart : getFeatureStarts(SectionPosition.a(blockposition), structuregenerator, world)) { // Tuinity end - add world parameter + if (structurestart.c().b(blockposition)) { + if (!flag) { + return structurestart; +diff --git a/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java b/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java +index 03584572fa5bf0d96fc4cecece573547f9c94cea..8bc965a3b3d0d4140c6b94636f0b33b2805c5867 100644 +--- a/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java ++++ b/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java +@@ -106,7 +106,7 @@ public class VoxelShapeSpliterator extends AbstractSpliterator { + VoxelShape voxelshape = iblockdata.b((IBlockAccess) this.g, this.e, this.c); + + if (voxelshape == VoxelShapes.b()) { +- if (!this.b.a((double) i, (double) j, (double) k, (double) i + 1.0D, (double) j + 1.0D, (double) k + 1.0D)) { ++ if (!this.b.voxelShapeIntersect((double) i, (double) j, (double) k, (double) i + 1.0D, (double) j + 1.0D, (double) k + 1.0D)) { // Tuinity - keep vanilla behavior for voxelshape intersection - See comment in AxisAlignedBB + continue; + } + +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 78dcba08d6d796d5d97c8304bf1f1e7d1e650d5d..c8a5d4972431ce9615312280f36181a2b9645df7 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -154,6 +154,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper + public final ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray + ++ public final com.tuinity.tuinity.config.TuinityConfig.WorldConfig tuinityConfig; // Tuinity - Server Config ++ + public final co.aikar.timings.WorldTimingsHandler timings; // Paper + public static BlockPosition lastPhysicsProblem; // Spigot + private org.spigotmc.TickLimiter entityLimiter; +@@ -181,10 +183,70 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + return typeKey; + } + ++ // Tuinity start - optimise checkDespawn ++ public final List getNearbyPlayers(@Nullable Entity source, double sourceX, double sourceY, double sourceZ, double maxRange, @Nullable Predicate predicate) { ++ Chunk chunk; ++ if (source == null || (chunk = source.getCurrentChunk()) == null || maxRange < 0.0 || maxRange >= net.minecraft.server.level.PlayerChunkMap.GENERAL_AREA_MAP_ACCEPTABLE_SEARCH_RANGE) { ++ return this.getNearbyPlayersSlow(source, sourceX, sourceY, sourceZ, maxRange, predicate); ++ } ++ ++ List ret = new java.util.ArrayList<>(); ++ chunk.getNearestPlayers(sourceX, sourceY, sourceZ, predicate, maxRange, ret); ++ return ret; ++ } ++ ++ private List getNearbyPlayersSlow(@Nullable Entity source, double sourceX, double sourceY, double sourceZ, double maxRange, @Nullable Predicate predicate) { ++ List ret = new java.util.ArrayList<>(); ++ double maxRangeSquared = maxRange * maxRange; ++ ++ for (EntityPlayer player : (List)this.getPlayers()) { ++ if ((maxRange < 0.0 || player.getDistanceSquared(sourceX, sourceY, sourceZ) < maxRangeSquared)) { ++ if (predicate == null || predicate.test(player)) { ++ ret.add(player); ++ } ++ } ++ } ++ ++ return ret; ++ } ++ ++ private EntityPlayer getNearestPlayerSlow(@Nullable Entity source, double sourceX, double sourceY, double sourceZ, double maxRange, @Nullable Predicate predicate) { ++ EntityPlayer closest = null; ++ double closestRangeSquared = maxRange < 0.0 ? Double.MAX_VALUE : maxRange * maxRange; ++ ++ for (EntityPlayer player : (List)this.getPlayers()) { ++ double distanceSquared = player.getDistanceSquared(sourceX, sourceY, sourceZ); ++ if (distanceSquared < closestRangeSquared && (predicate == null || predicate.test(player))) { ++ closest = player; ++ closestRangeSquared = distanceSquared; ++ } ++ } ++ ++ return closest; ++ } ++ ++ ++ public final EntityPlayer getNearestPlayer(@Nullable Entity source, double sourceX, double sourceY, double sourceZ, double maxRange, @Nullable Predicate predicate) { ++ Chunk chunk; ++ if (source == null || (chunk = source.getCurrentChunk()) == null || maxRange < 0.0 || maxRange >= net.minecraft.server.level.PlayerChunkMap.GENERAL_AREA_MAP_ACCEPTABLE_SEARCH_RANGE) { ++ return this.getNearestPlayerSlow(source, sourceX, sourceY, sourceZ, maxRange, predicate); ++ } ++ ++ return chunk.findNearestPlayer(sourceX, sourceY, sourceZ, maxRange, predicate); ++ } ++ ++ @Override ++ public @Nullable EntityHuman a(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { ++ return this.getNearestPlayer(null, d0, d1, d2, d3, predicate); ++ } ++ ++ // Tuinity end - optimise checkDespawn ++ + protected World(WorldDataMutable worlddatamutable, ResourceKey resourcekey, final DimensionManager dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper + this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName()); // Spigot + this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper + this.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this, executor) : ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray ++ this.tuinityConfig = new com.tuinity.tuinity.config.TuinityConfig.WorldConfig(((net.minecraft.world.level.storage.WorldDataServer)worlddatamutable).getName()); // Tuinity - Server Config + this.generator = gen; + this.world = new CraftWorld((WorldServer) this, gen, env); + this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit +@@ -346,6 +408,15 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + + @Override + public final Chunk getChunkAt(int i, int j) { // Paper - final to help inline ++ // Tuinity start - make sure loaded chunks get the inlined variant of this function ++ net.minecraft.server.level.ChunkProviderServer cps = ((WorldServer)this).chunkProvider; ++ if (cps.serverThread == Thread.currentThread()) { ++ Chunk ifLoaded = cps.getChunkAtIfLoadedMainThread(i, j); ++ if (ifLoaded != null) { ++ return ifLoaded; ++ } ++ } ++ // Tuinity end - make sure loaded chunks get the inlined variant of this function + return (Chunk) this.getChunkAt(i, j, ChunkStatus.FULL, true); // Paper - avoid a method jump + } + +@@ -420,6 +491,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + + @Override + public boolean a(BlockPosition blockposition, IBlockData iblockdata, int i, int j) { ++ org.spigotmc.AsyncCatcher.catchOp("set type call"); // Tuinity + // CraftBukkit start - tree generation + if (this.captureTreeGeneration) { + // Paper start +@@ -521,6 +593,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + + // CraftBukkit start - Split off from above in order to directly send client and physic updates + public void notifyAndUpdatePhysics(BlockPosition blockposition, Chunk chunk, IBlockData oldBlock, IBlockData newBlock, IBlockData actualBlock, int i, int j) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Async notify and update"); // Tuinity + IBlockData iblockdata = newBlock; + IBlockData iblockdata1 = oldBlock; + IBlockData iblockdata2 = actualBlock; +@@ -533,7 +606,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + this.notify(blockposition, iblockdata1, iblockdata, i); + // Paper start - per player view distance - allow block updates for non-ticking chunks in player view distance + // if copied from above +- } else if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || ((WorldServer)this).getChunkProvider().playerChunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(MCUtil.getCoordinateKey(blockposition)) != null)) { ++ } else if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || ((WorldServer)this).getChunkProvider().playerChunkMap.playerChunkManager.broadcastMap.getObjectsInRange(MCUtil.getCoordinateKey(blockposition)) != null)) { // Tuinity - replace old player chunk management + ((WorldServer)this).getChunkProvider().flagDirty(blockposition); + // Paper end - per player view distance + } +@@ -955,6 +1028,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + return; + // Paper end + } ++ MinecraftServer.getServer().executeMidTickTasks(); // Tuinity - execute chunk tasks mid tick + } + // Paper start - Prevent armor stands from doing entity lookups + @Override +@@ -1138,10 +1212,44 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + return this.getChunkAt(i, j, ChunkStatus.FULL, false); + } + ++ // Tuinity start - optimise hard collision handling ++ @Override ++ public List getHardCollidingEntities(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate) { ++ return this.getHardCollidingEntities(entity, axisalignedbb, predicate, Lists.newArrayList()); ++ } ++ ++ public List getHardCollidingEntities(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate, List list) { ++ // copied from below ++ int i = MathHelper.floor((axisalignedbb.minX - 2.0D) / 16.0D); ++ int j = MathHelper.floor((axisalignedbb.maxX + 2.0D) / 16.0D); ++ int k = MathHelper.floor((axisalignedbb.minZ - 2.0D) / 16.0D); ++ int l = MathHelper.floor((axisalignedbb.maxZ + 2.0D) / 16.0D); ++ ++ net.minecraft.server.level.ChunkProviderServer chunkProvider = ((WorldServer)this).getChunkProvider(); ++ ++ for (int i1 = i; i1 <= j; ++i1) { ++ for (int j1 = k; j1 <= l; ++j1) { ++ Chunk chunk = chunkProvider.getChunkAtIfLoadedMainThread(i1, j1); ++ ++ if (chunk != null) { ++ chunk.getHardCollidingEntities(entity, axisalignedbb, list, predicate); ++ } ++ } ++ } ++ ++ return list; ++ } ++ // Tuinity end - optimise hard collision handling ++ + @Override + public List getEntities(@Nullable Entity entity, AxisAlignedBB axisalignedbb, @Nullable Predicate predicate) { +- this.getMethodProfiler().c("getEntities"); ++ // Tuinity start - add list parameter + List list = Lists.newArrayList(); ++ return this.getEntities(entity, axisalignedbb, predicate, list); ++ } ++ public List getEntities(@Nullable Entity entity, AxisAlignedBB axisalignedbb, @Nullable Predicate predicate, List list) { ++ // Tuinity end - add list parameter ++ this.getMethodProfiler().c("getEntities"); + int i = MathHelper.floor((axisalignedbb.minX - 2.0D) / 16.0D); + int j = MathHelper.floor((axisalignedbb.maxX + 2.0D) / 16.0D); + int k = MathHelper.floor((axisalignedbb.minZ - 2.0D) / 16.0D); +@@ -1197,7 +1305,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper + + if (chunk != null) { +- chunk.a(oclass, axisalignedbb, list, predicate); ++ chunk.getEntitiesClass(oclass, null, axisalignedbb, (Predicate)predicate, (List)list); // Tuinity - optimise lookup by entity class + } + } + } +@@ -1220,7 +1328,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper + + if (chunk != null) { +- chunk.a(oclass, axisalignedbb, list, predicate); ++ chunk.getEntitiesClass(oclass, null, axisalignedbb, (Predicate)predicate, (List)list); // Tuinity - optimise lookup by entity class + } + } + } +@@ -1228,6 +1336,106 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + return list; + } + ++ // Tuinity start ++ @Override ++ public T b(Class oclass, net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition pathfindertargetcondition, @Nullable net.minecraft.world.entity.EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { ++ return this.getClosestEntity(oclass, pathfindertargetcondition, entityliving, d0, d1, d2, axisalignedbb); ++ } ++ ++ @Override ++ public T a(Class oclass, net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition pathfindertargetcondition, @Nullable net.minecraft.world.entity.EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { ++ return this.getClosestEntity(oclass, pathfindertargetcondition, entityliving, d0, d1, d2, axisalignedbb); ++ } ++ ++ public final T getClosestEntity(Class clazz, ++ net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition condition, ++ @Nullable net.minecraft.world.entity.EntityLiving source, ++ double x, double y, double z, ++ AxisAlignedBB boundingBox) { ++ org.bukkit.craftbukkit.util.UnsafeList entities = com.tuinity.tuinity.util.CachedLists.getTempGetEntitiesList(); ++ try { ++ int lowerX = MCUtil.fastFloor((boundingBox.minX - 2.0D)) >> 4; ++ int upperX = MCUtil.fastFloor((boundingBox.maxX + 2.0D)) >> 4; ++ int lowerZ = MCUtil.fastFloor((boundingBox.minZ - 2.0D)) >> 4; ++ int upperZ = MCUtil.fastFloor((boundingBox.maxZ + 2.0D)) >> 4; ++ ++ org.bukkit.craftbukkit.util.UnsafeList chunks = com.tuinity.tuinity.util.CachedLists.getTempGetChunksList(); ++ try { ++ T closest = null; ++ double closestDistance = Double.MAX_VALUE; ++ net.minecraft.server.level.ChunkProviderServer chunkProvider = ((WorldServer)this).getChunkProvider(); ++ ++ int centerX = (lowerX + upperX) >> 1; ++ int centerZ = (lowerZ + upperZ) >> 1; ++ // Copied from MCUtil.getSpiralOutChunks ++ Chunk temp; ++ if ((temp = chunkProvider.getChunkAtIfLoadedImmediately(centerX, centerZ)) != null && temp.hasEntitiesMaybe(clazz)) { ++ chunks.add(temp); ++ } ++ int radius = Math.max((upperX - lowerX + 1) >> 1, (upperZ - lowerZ + 1) >> 1); ++ for (int r = 1; r <= radius; r++) { ++ int ox = -r; ++ int oz = r; ++ ++ // Iterates the edge of half of the box; then negates for other half. ++ while (ox <= r && oz > -r) { ++ { ++ int cx = centerX + ox; ++ int cz = centerZ + oz; ++ if (cx >= lowerX && cx <= upperX && cz >= lowerZ && cz <= upperZ && ++ (temp = chunkProvider.getChunkAtIfLoadedImmediately(cx, cz)) != null && ++ temp.hasEntitiesMaybe(clazz)) { ++ chunks.add(temp); ++ } ++ } ++ { ++ int cx = centerX - ox; ++ int cz = centerZ - oz; ++ if (cx >= lowerX && cx <= upperX && cz >= lowerZ && cz <= upperZ && ++ (temp = chunkProvider.getChunkAtIfLoadedImmediately(cx, cz)) != null && ++ temp.hasEntitiesMaybe(clazz)) { ++ chunks.add(temp); ++ } ++ } ++ ++ if (ox < r) { ++ ox++; ++ } else { ++ oz--; ++ } ++ } ++ } ++ ++ Object[] chunkData = chunks.getRawDataArray(); ++ for (int cindex = 0, clen = chunks.size(); cindex < clen; ++cindex) { ++ final Chunk chunk = (Chunk)chunkData[cindex]; ++ ++ chunk.getEntitiesClass(clazz, source, boundingBox, null, entities); ++ ++ Object[] entityData = entities.getRawDataArray(); ++ for (int eindex = 0, entities_len = entities.size(); eindex < entities_len; ++eindex) { ++ T entity = (T)entityData[eindex]; ++ double distance = entity.getDistanceSquared(x, y, z); ++ // check distance first, as it's the least expensive ++ if (distance < closestDistance && condition.test(source, entity)) { ++ closest = entity; ++ closestDistance = distance; ++ } ++ } ++ ++ entities.setSize(0); ++ } ++ ++ return closest; ++ } finally { ++ com.tuinity.tuinity.util.CachedLists.returnTempGetChunksList(chunks); ++ } ++ } finally { ++ com.tuinity.tuinity.util.CachedLists.returnTempGetEntitiesList(entities); ++ } ++ } ++ // Tuinity end ++ + @Nullable + public abstract Entity getEntity(int i); + +diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeBase.java b/src/main/java/net/minecraft/world/level/biome/BiomeBase.java +index 15096a9c2719b8b4c099f62d0a1c808e56b63a8e..9bbd175f7e20591bbefdbddcb5e998e7098c5adb 100644 +--- a/src/main/java/net/minecraft/world/level/biome/BiomeBase.java ++++ b/src/main/java/net/minecraft/world/level/biome/BiomeBase.java +@@ -175,14 +175,33 @@ public final class BiomeBase { + } + + public boolean a(IWorldReader iworldreader, BlockPosition blockposition, boolean flag) { +- if (this.getAdjustedTemperature(blockposition) >= 0.15F) { ++ // Tuinity start - add chunk parameter and lazily get biome ++ return canTurnWaterIntoIce(iworldreader, blockposition, flag, null, new BiomeBase[] { this }); ++ } ++ public static boolean canTurnWaterIntoIce(IWorldReader iworldreader, BlockPosition blockposition, boolean flag, IChunkAccess chunk, BiomeBase[] biomeAbove) { ++ // Tuinity end - add chunk parameter and lazily get biome ++ if (false && biomeAbove[0].getAdjustedTemperature(blockposition) >= 0.15F) { // Tuinity - move this down, this check is expensive + return false; + } else { + if (blockposition.getY() >= 0 && blockposition.getY() < 256 && iworldreader.getBrightness(EnumSkyBlock.BLOCK, blockposition) < 10) { +- IBlockData iblockdata = iworldreader.getType(blockposition); +- Fluid fluid = iworldreader.getFluid(blockposition); ++ // Tuinity start - add chunk parameter ++ if (chunk == null) { ++ chunk = iworldreader.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ } ++ // Tuinity end - add chunk parameter ++ IBlockData iblockdata = chunk.getType(blockposition); // Tuinity - skip chunk lookup, we got the chunk ++ Fluid fluid = iblockdata.getFluid(); // Tuinity - skip another block lookup, we have the blockdata + + if (fluid.getType() == FluidTypes.WATER && iblockdata.getBlock() instanceof BlockFluids) { ++ // Tuinity start - moved down from top, only run when we actually encounter water ++ if (biomeAbove[0] == null) { ++ // lazily-get biome ++ biomeAbove[0] = iworldreader.getBiome(blockposition.up()); // TODO - avoid blockpos alloc ++ } ++ if (biomeAbove[0].getAdjustedTemperature(blockposition) >= 0.15F) { ++ return false; ++ } ++ // Tuinity end - moved down from top, only run when we actually encounter water + if (!flag) { + return true; + } +@@ -200,13 +219,32 @@ public final class BiomeBase { + } + + public boolean b(IWorldReader iworldreader, BlockPosition blockposition) { +- if (this.getAdjustedTemperature(blockposition) >= 0.15F) { ++ // Tuinity start - add chunk parameter and lazily get biome ++ return canTurnAirIntoSnow(iworldreader, blockposition, null, new BiomeBase[]{ this }); ++ } ++ public static boolean canTurnAirIntoSnow(IWorldReader iworldreader, BlockPosition blockposition, IChunkAccess chunk, BiomeBase[] biomeAbove) { ++ // Tuinity end - add chunk parameter and lazily get biome ++ if (false && biomeAbove[0].getAdjustedTemperature(blockposition) >= 0.15F) { // Tuinity - move this down, this check is expensive + return false; + } else { + if (blockposition.getY() >= 0 && blockposition.getY() < 256 && iworldreader.getBrightness(EnumSkyBlock.BLOCK, blockposition) < 10) { +- IBlockData iblockdata = iworldreader.getType(blockposition); ++ // Tuinity start - add chunk parameter ++ if (chunk == null) { ++ chunk = iworldreader.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ } ++ // Tuinity end - add chunk parameter ++ IBlockData iblockdata = chunk.getType(blockposition); // Tuinity - skip chunk lookup, we got the chunk + + if (iblockdata.isAir() && Blocks.SNOW.getBlockData().canPlace(iworldreader, blockposition)) { ++ // Tuinity start - moved down from top, only run when we actually encounter water ++ if (biomeAbove[0] == null) { ++ // lazily-get biome ++ biomeAbove[0] = iworldreader.getBiome(blockposition.up()); // TODO - avoid blockpos alloc ++ } ++ if (biomeAbove[0].getAdjustedTemperature(blockposition) >= 0.15F) { ++ return false; ++ } ++ // Tuinity end - moved down from top, only run when we actually encounter water + return true; + } + } +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java +index ac3709c8158d42ccafd457cfa44a16dc8c9eb949..0b852fa247c65cb1e889ad4e55886e256f89a763 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java +@@ -347,21 +347,23 @@ public abstract class BlockBase { + + public abstract static class BlockData extends IBlockDataHolder { + +- private final int b; +- private final boolean e; ++ private final int b; public final int getEmittedLight() { return this.b; } // Tuinity - OBFHELPER ++ private final boolean e; public final boolean isTransparentOnSomeFaces() { return this.e; } // Tuinity - OBFHELPER + private final boolean f; + private final Material g; + private final MaterialMapColor h; + public final float strength; + private final boolean j; +- private final boolean k; ++ private final boolean k; public final boolean isOpaque() { return this.k; } // Tuinity - OBFHELPER + private final BlockBase.e l; + private final BlockBase.e m; + private final BlockBase.e n; + private final BlockBase.e o; + private final BlockBase.e p; + @Nullable +- protected BlockBase.BlockData.Cache a; ++ protected BlockBase.BlockData.Cache a; public final BlockBase.BlockData.Cache getShapeCache() { return this.a; } // Tuinity - OBFHELPER ++ public net.minecraft.world.level.pathfinder.PathType staticPathType; // Tuinity - cache static path types ++ public net.minecraft.world.level.pathfinder.PathType neighbourOverridePathType; // Tuinity - cache static path types + + protected BlockData(Block block, ImmutableMap, Comparable> immutablemap, MapCodec mapcodec) { + super(block, immutablemap, mapcodec); +@@ -380,6 +382,7 @@ public abstract class BlockBase { + this.n = blockbase_info.s; + this.o = blockbase_info.t; + this.p = blockbase_info.u; ++ this.conditionallyFullOpaque = this.isOpaque() & this.isTransparentOnSomeFaces(); // Tuinity + } + // Paper start - impl cached craft block data, lazy load to fix issue with loading at the wrong time + private org.bukkit.craftbukkit.block.data.CraftBlockData cachedCraftBlockData; +@@ -395,12 +398,63 @@ public abstract class BlockBase { + protected Fluid fluid; + // Paper end + ++ // Tuinity start - micro the hell out of this call ++ protected boolean shapeExceedsCube = true; ++ public final boolean shapeExceedsCube() { ++ return this.shapeExceedsCube; ++ } ++ // Tuinity end ++ ++ // Tuinity start ++ protected int opacityIfCached = -1; ++ // ret -1 if opacity is dynamic, or -1 if the block is conditionally full opaque, else return opacity in [0, 15] ++ public final int getOpacityIfCached() { ++ return this.opacityIfCached; ++ } ++ ++ protected final boolean conditionallyFullOpaque; ++ public final boolean isConditionallyFullOpaque() { ++ return this.conditionallyFullOpaque; ++ } ++ // Tuinity end ++ + public void a() { + this.fluid = this.getBlock().d(this.p()); // Paper - moved from getFluid() + this.isTicking = this.getBlock().isTicking(this.p()); // Paper - moved from isTicking() + if (!this.getBlock().o()) { + this.a = new BlockBase.BlockData.Cache(this.p()); + } ++ this.shapeExceedsCube = this.a == null || this.a.c; // Tuinity - moved from actual method to here ++ this.staticPathType = null; // Tuinity - cache static path type ++ this.neighbourOverridePathType = null; // Tuinity - cache static path types ++ this.opacityIfCached = this.a == null || this.isConditionallyFullOpaque() ? -1 : this.a.getOpacity(); // Tuinity - cache opacity for light ++ // Tuinity start - optimise culling shape cache for light ++ if (this.a != null && this.a.getCullingShapeCache() != null) { ++ for (int i = 0, len = this.a.getCullingShapeCache().length; i < len; ++i) { ++ VoxelShape face = this.a.getCullingShapeCache()[i].simplify(); ++ if (face.isEmpty()) { ++ this.a.getCullingShapeCache()[i] = VoxelShapes.getEmptyShape(); ++ continue; ++ } ++ List boxes = face.getBoundingBoxesRepresentation(); ++ ++ if (boxes.size() == 1) { ++ net.minecraft.world.phys.AxisAlignedBB boundingBox = boxes.get(0); ++ if (boundingBox.equals(VoxelShapes.optimisedFullCube.aabb)) { ++ this.a.getCullingShapeCache()[i] = VoxelShapes.fullCube(); ++ } else { ++ this.a.getCullingShapeCache()[i] = VoxelShapes.of(boundingBox); ++ if (!(this.a.getCullingShapeCache()[i] instanceof com.tuinity.tuinity.voxel.AABBVoxelShape) && ++ this.a.getCullingShapeCache()[i].getBoundingBoxesRepresentation().size() == 1) { ++ this.a.getCullingShapeCache()[i] = new com.tuinity.tuinity.voxel.AABBVoxelShape(boundingBox); ++ } ++ } ++ continue; ++ } ++ this.a.getCullingShapeCache()[i] = face; ++ } ++ } ++ // Tuinity end - optimise culling shape cache for light + + } + +@@ -424,10 +478,12 @@ public abstract class BlockBase { + return this.a != null ? this.a.g : this.getBlock().b(this.p(), iblockaccess, blockposition); + } + ++ public final int getOpacity(IBlockAccess iblockaccess, BlockPosition blockposition) { return this.b(iblockaccess, blockposition); } // Tuinity - OBFHELPER + public int b(IBlockAccess iblockaccess, BlockPosition blockposition) { + return this.a != null ? this.a.h : this.getBlock().f(this.p(), iblockaccess, blockposition); + } + ++ public final VoxelShape getCullingFace(IBlockAccess iblockaccess, BlockPosition blockposition, EnumDirection enumdirection) { return this.a(iblockaccess, blockposition, enumdirection); } // Tuinity - OBFHELPER + public VoxelShape a(IBlockAccess iblockaccess, BlockPosition blockposition, EnumDirection enumdirection) { + return this.a != null && this.a.i != null ? this.a.i[enumdirection.ordinal()] : VoxelShapes.a(this.c(iblockaccess, blockposition), enumdirection); + } +@@ -437,7 +493,7 @@ public abstract class BlockBase { + } + + public final boolean d() { // Paper +- return this.a == null || this.a.c; ++ return this.shapeExceedsCube; // Tuinity - moved into shape cache init + } + + public final boolean e() { // Paper +@@ -727,9 +783,9 @@ public abstract class BlockBase { + private static final int f = EnumBlockSupport.values().length; + protected final boolean a; + private final boolean g; +- private final int h; ++ private final int h; private final int getOpacity() { return this.h; } // Tuinity - OBFHELPER + @Nullable +- private final VoxelShape[] i; ++ private final VoxelShape[] i; private final VoxelShape[] getCullingShapeCache () { return this.i; } // Tuinity - OBFHELPER + protected final VoxelShape b; + protected final boolean c; + private final boolean[] j; +diff --git a/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java b/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java +index ba046cffdd8331c7e0427f19fa54d0c7a99077d9..9f9a3210a68e489dcdeabaeeddf01b59775eebd2 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java ++++ b/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java +@@ -40,11 +40,13 @@ public abstract class IBlockDataHolder { + private final ImmutableMap, Comparable> b; + private Table, Comparable, S> e; + protected final MapCodec d; ++ protected com.tuinity.tuinity.util.table.ZeroCollidingReferenceStateTable optimisedTable; // Tuinity - optimise state lookup + + protected IBlockDataHolder(O o0, ImmutableMap, Comparable> immutablemap, MapCodec mapcodec) { + this.c = o0; + this.b = immutablemap; + this.d = mapcodec; ++ this.optimisedTable = new com.tuinity.tuinity.util.table.ZeroCollidingReferenceStateTable(this, immutablemap); // Tuinity - optimise state lookup + } + + public > S a(IBlockState iblockstate) { +@@ -86,11 +88,11 @@ public abstract class IBlockDataHolder { + + public > boolean contains(IBlockState iblockstate) { return this.b(iblockstate); } // Paper - OBFHELPER + public > boolean b(IBlockState iblockstate) { +- return this.b.containsKey(iblockstate); ++ return this.optimisedTable.get(iblockstate) != null; // Tuinity - optimise state lookup + } + + public > T get(IBlockState iblockstate) { +- Comparable comparable = (Comparable) this.b.get(iblockstate); ++ final Comparable comparable = this.optimisedTable.get(iblockstate); // Tuinity - optimise state lookup + + if (comparable == null) { + throw new IllegalArgumentException("Cannot get property " + iblockstate + " as it does not exist in " + this.c); +@@ -100,27 +102,21 @@ public abstract class IBlockDataHolder { + } + + public > Optional d(IBlockState iblockstate) { +- Comparable comparable = (Comparable) this.b.get(iblockstate); ++ final Comparable comparable = this.optimisedTable.get(iblockstate); // Tuinity - optimise state lookup + + return comparable == null ? Optional.empty() : Optional.of(iblockstate.getType().cast(comparable)); + } + + public , V extends T> S set(IBlockState iblockstate, V v0) { +- Comparable comparable = (Comparable) this.b.get(iblockstate); ++ // Tuinity start - optimise state lookup ++ final S ret = (S)this.optimisedTable.get(iblockstate, v0); + +- if (comparable == null) { +- throw new IllegalArgumentException("Cannot set property " + iblockstate + " as it does not exist in " + this.c); +- } else if (comparable == v0) { +- return (S) this; // Paper - decompile error +- } else { +- S s0 = this.e.get(iblockstate, v0); +- +- if (s0 == null) { +- throw new IllegalArgumentException("Cannot set property " + iblockstate + " to " + v0 + " on " + this.c + ", it is not an allowed value"); +- } else { +- return s0; +- } ++ if (ret == null) { ++ throw new IllegalArgumentException("Cannot set property " + iblockstate + " to " + v0 + " on " + this.c + ", it is not an allowed value"); + } ++ ++ return ret; ++ // Tuinity end - optimise state lookup + } + + public void a(Map, Comparable>, S> map) { +@@ -144,7 +140,8 @@ public abstract class IBlockDataHolder { + } + } + +- this.e = (Table) (table.isEmpty() ? table : ArrayTable.create(table)); ++ this.e = (Table) (table.isEmpty() ? table : ArrayTable.create(table)); this.optimisedTable.loadInTable((Table)this.e, this.b); // Tuinity - optimise state lookup ++ + } + } + +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateBoolean.java b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateBoolean.java +index f2f94950681b198ae7a4c31a044fd62e98e448ab..2c7306c2b0c1d9e701bc3aa2c115434abeab3d72 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateBoolean.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateBoolean.java +@@ -12,6 +12,13 @@ public class BlockStateBoolean extends IBlockState { + super(s, Boolean.class); + } + ++ // Tuinity start - optimise iblockdata state lookup ++ @Override ++ public final int getIdFor(final Boolean value) { ++ return value.booleanValue() ? 1 : 0; ++ } ++ // Tuinity end - optimise iblockdata state lookup ++ + @Override + public Collection getValues() { + return this.a; +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java +index 3079cd13ea1465f4221fde4fec7df639f7c1eb49..a11069695b64e515f0e76e1d6ccddc33503492cd 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java +@@ -18,6 +18,15 @@ public class BlockStateEnum & INamable> extends IBlockState + private final ImmutableSet a; + private final Map b = Maps.newHashMap(); + ++ // Tuinity start - optimise iblockdata state lookup ++ private int[] idLookupTable; ++ ++ @Override ++ public final int getIdFor(final T value) { ++ return this.idLookupTable[value.ordinal()]; ++ } ++ // Tuinity end - optimise iblockdata state lookup ++ + protected BlockStateEnum(String s, Class oclass, Collection collection) { + super(s, oclass); + this.a = ImmutableSet.copyOf(collection); +@@ -33,6 +42,14 @@ public class BlockStateEnum & INamable> extends IBlockState + + this.b.put(s1, t0); + } ++ // Tuinity start - optimise iblockdata state lookup ++ int id = 0; ++ this.idLookupTable = new int[oclass.getEnumConstants().length]; ++ java.util.Arrays.fill(this.idLookupTable, -1); ++ for (final T value : this.getValues()) { ++ this.idLookupTable[value.ordinal()] = id++; ++ } ++ // Tuinity end - optimise iblockdata state lookup + + } + +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateInteger.java b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateInteger.java +index 190978c889222185b47065e9e5f96a82e59c7b4e..e8165d4de4acca241924aa4076fc8868e1f453d9 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateInteger.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateInteger.java +@@ -13,6 +13,16 @@ public class BlockStateInteger extends IBlockState { + public final int min; + public final int max; + ++ // Tuinity start - optimise iblockdata state lookup ++ @Override ++ public final int getIdFor(final Integer value) { ++ final int val = value.intValue(); ++ final int ret = val - this.min; ++ ++ return ret | ((this.max - ret) >> 31); ++ } ++ // Tuinity end - optimise iblockdata state lookup ++ + protected BlockStateInteger(String s, int i, int j) { + super(s, Integer.class); + this.min = i; +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java b/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java +index 759d6a4adaa511488ace5e2650eb685cbb6c4c16..21250d10a51bd0697709f0aa059908f9f71491d5 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java +@@ -16,6 +16,17 @@ public abstract class IBlockState> { + private final Codec d; + private final Codec> e; + ++ // Tuinity start - optimise iblockdata state lookup ++ private static final java.util.concurrent.atomic.AtomicInteger ID_GENERATOR = new java.util.concurrent.atomic.AtomicInteger(); ++ private final int id = ID_GENERATOR.getAndIncrement(); ++ ++ public final int getId() { ++ return this.id; ++ } ++ ++ public abstract int getIdFor(final T value); ++ // Tuinity end - optimise state lookup ++ + protected IBlockState(String s, Class oclass) { + this.d = Codec.STRING.comapFlatMap((s1) -> this.b(s1).map(DataResult::success).orElseGet(() -> { // Paper - decompile error + return DataResult.error("Unable to read property: " + this + " with value: " + s1); +diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +index 3c25021835d6d8fd112fc89636616bfd744e7f1a..aa49565cd364db3781a110ee138ee1a4edbfa288 100644 +--- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java ++++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +@@ -60,11 +60,59 @@ public class WorldBorder { + return axisalignedbb.maxX > this.e() && axisalignedbb.minX < this.g() && axisalignedbb.maxZ > this.f() && axisalignedbb.minZ < this.h(); + } + ++ // Tuinity start - optimise collisions ++ // determines whether we are almost colliding with the world border ++ // for clear collisions, this rets false ++ public final boolean isAlmostCollidingOnBorder(AxisAlignedBB boundingBox) { ++ return this.isAlmostCollidingOnBorder(boundingBox.minX, boundingBox.maxX, boundingBox.minZ, boundingBox.maxZ); ++ } ++ ++ public final boolean isAlmostCollidingOnBorder(double boxMinX, double boxMaxX, double boxMinZ, double boxMaxZ) { ++ double borderMinX = this.getMinX(); ++ double borderMaxX = this.getMaxX(); ++ ++ double borderMinZ = this.getMinZ(); ++ double borderMaxZ = this.getMaxZ(); ++ ++ return ++ // Not intersecting if we're smaller ++ !AxisAlignedBB.voxelShapeIntersect( ++ boxMinX + net.minecraft.server.MCUtil.COLLISION_EPSILON, Double.NEGATIVE_INFINITY, boxMinZ + net.minecraft.server.MCUtil.COLLISION_EPSILON, ++ boxMaxX - net.minecraft.server.MCUtil.COLLISION_EPSILON, Double.POSITIVE_INFINITY, boxMaxZ - net.minecraft.server.MCUtil.COLLISION_EPSILON, ++ borderMinX, Double.NEGATIVE_INFINITY, borderMinZ, borderMaxX, Double.POSITIVE_INFINITY, borderMaxZ ++ ) ++ && ++ ++ // Are intersecting if we're larger ++ AxisAlignedBB.voxelShapeIntersect( ++ boxMinX - net.minecraft.server.MCUtil.COLLISION_EPSILON, Double.NEGATIVE_INFINITY, boxMinZ - net.minecraft.server.MCUtil.COLLISION_EPSILON, ++ boxMaxX + net.minecraft.server.MCUtil.COLLISION_EPSILON, Double.POSITIVE_INFINITY, boxMaxZ + net.minecraft.server.MCUtil.COLLISION_EPSILON, ++ borderMinX, Double.NEGATIVE_INFINITY, borderMinZ, borderMaxX, Double.POSITIVE_INFINITY, borderMaxZ ++ ) ++ ; ++ } ++ ++ public final boolean isCollidingWithBorderEdge(AxisAlignedBB boundingBox) { ++ return this.isCollidingWithBorderEdge(boundingBox.minX, boundingBox.maxX, boundingBox.minZ, boundingBox.maxZ); ++ } ++ ++ public final boolean isCollidingWithBorderEdge(double boxMinX, double boxMaxX, double boxMinZ, double boxMaxZ) { ++ double borderMinX = this.getMinX() + net.minecraft.server.MCUtil.COLLISION_EPSILON; ++ double borderMaxX = this.getMaxX() - net.minecraft.server.MCUtil.COLLISION_EPSILON; ++ ++ double borderMinZ = this.getMinZ() + net.minecraft.server.MCUtil.COLLISION_EPSILON; ++ double borderMaxZ = this.getMaxZ() - net.minecraft.server.MCUtil.COLLISION_EPSILON; ++ ++ return boxMinX < borderMinX || boxMaxX > borderMaxX || boxMinZ < borderMinZ || boxMaxZ > borderMaxZ; ++ } ++ // Tuinity end - optimise collisions ++ + public double a(Entity entity) { + return this.b(entity.locX(), entity.locZ()); + } + + public final VoxelShape asVoxelShape(){ return c();} // Paper - OBFHELPER ++ public final VoxelShape getCollisionShape() { return this.c(); } // Tuinity - OBFHELPER + public VoxelShape c() { + return this.j.m(); + } +@@ -80,18 +128,22 @@ public class WorldBorder { + return Math.min(d6, d3); + } + ++ public final double getMinX() { return this.e(); } // Tuinity - OBFHELPER + public double e() { + return this.j.a(); + } + ++ public final double getMinZ() { return this.f(); } // Tuinity - OBFHELPER + public double f() { + return this.j.c(); + } + ++ public final double getMaxX() { return this.g(); } // Tuinity - OBFHELPER + public double g() { + return this.j.b(); + } + ++ public final double getMaxZ() { return this.h(); } // Tuinity - OBFHELPER + public double h() { + return this.j.d(); + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index 34a9f7b2f998f77b1279516cd09397ab6c2ac1cc..259d4ac89e84fd334ff65ea8a606e1fc50cc882b 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -137,6 +137,158 @@ public class Chunk implements IChunkAccess { + private final int[] inventoryEntityCounts = new int[16]; + // Paper end + ++ // Tuinity start - optimise hard collision handling ++ // Tuinity - optimised entity slices ++ ++ public final void getHardCollidingEntities(@Nullable Entity entity, AxisAlignedBB axisalignedbb, List into, Predicate predicate) { ++ this.entitySlicesManager.getHardCollidingEntities(entity, axisalignedbb, into, predicate); // Tuinity ++ } ++ // Tuinity end - optimise hard collision handling ++ // Tuinity start - rewrite light engine ++ protected volatile com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] blockNibbles = com.tuinity.tuinity.chunk.light.StarLightEngine.getFilledEmptyLight(); ++ protected volatile com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] skyNibbles = com.tuinity.tuinity.chunk.light.StarLightEngine.getFilledEmptyLight(); ++ protected volatile boolean[] skyEmptinessMap; ++ protected volatile boolean[] blockEmptinessMap; ++ ++ @Override ++ public com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] getBlockNibbles() { ++ return this.blockNibbles; ++ } ++ ++ @Override ++ public void setBlockNibbles(com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] nibbles) { ++ this.blockNibbles = nibbles; ++ } ++ ++ @Override ++ public com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] getSkyNibbles() { ++ return this.skyNibbles; ++ } ++ ++ @Override ++ public void setSkyNibbles(com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] nibbles) { ++ this.skyNibbles = nibbles; ++ } ++ ++ @Override ++ public boolean[] getSkyEmptinessMap() { ++ return this.skyEmptinessMap; ++ } ++ ++ @Override ++ public void setSkyEmptinessMap(boolean[] emptinessMap) { ++ this.skyEmptinessMap = emptinessMap; ++ } ++ ++ @Override ++ public boolean[] getBlockEmptinessMap() { ++ return this.blockEmptinessMap; ++ } ++ ++ @Override ++ public void setBlockEmptinessMap(boolean[] emptinessMap) { ++ this.blockEmptinessMap = emptinessMap; ++ } ++ // Tuinity end - rewrite light engine ++ ++ // Tuinity start - optimised entity slices ++ protected final com.tuinity.tuinity.world.ChunkEntitySlices entitySlicesManager; ++ ++ public final boolean hasEntitiesMaybe(Class clazz) { // Tuinity start ++ return true; // Tuinity end ++ } ++ ++ public final void getEntitiesClass(Class clazz, Entity entity, AxisAlignedBB boundingBox, Predicate predicate, List into) { ++ this.entitySlicesManager.getEntities((Class)clazz, entity, boundingBox, (List)into, (Predicate)predicate); // Tuinity ++ } ++ // Tuinity end - optimised entity slices ++ ++ // Tuinity start - optimise checkDespawn ++ private boolean playerGeneralAreaCacheSet; ++ private com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playerGeneralAreaCache; ++ ++ public com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getPlayerGeneralAreaCache() { ++ if (!this.playerGeneralAreaCacheSet) { ++ this.updateGeneralAreaCache(); ++ } ++ return this.playerGeneralAreaCache; ++ } ++ ++ public void updateGeneralAreaCache() { ++ this.updateGeneralAreaCache(((WorldServer)this.world).getChunkProvider().playerChunkMap.playerGeneralAreaMap.getObjectsInRange(this.coordinateKey)); ++ } ++ ++ public void updateGeneralAreaCache(com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet value) { ++ this.playerGeneralAreaCacheSet = true; ++ this.playerGeneralAreaCache = value; ++ } ++ ++ public EntityPlayer findNearestPlayer(double sourceX, double sourceY, double sourceZ, double maxRange, Predicate predicate) { ++ if (!this.playerGeneralAreaCacheSet) { ++ this.updateGeneralAreaCache(); ++ } ++ ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet nearby = this.playerGeneralAreaCache; ++ ++ if (nearby == null) { ++ return null; ++ } ++ ++ Object[] backingSet = nearby.getBackingSet(); ++ double closestDistance = maxRange < 0.0 ? Double.MAX_VALUE : maxRange * maxRange; ++ EntityPlayer closest = null; ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object _player = backingSet[i]; ++ if (!(_player instanceof EntityPlayer)) { ++ continue; ++ } ++ EntityPlayer player = (EntityPlayer)_player; ++ ++ double distance = player.getDistanceSquared(sourceX, sourceY, sourceZ); ++ if (distance < closestDistance && predicate.test(player)) { ++ closest = player; ++ closestDistance = distance; ++ } ++ } ++ ++ return closest; ++ } ++ ++ public void getNearestPlayers(double sourceX, double sourceY, double sourceZ, Predicate predicate, double range, List ret) { ++ if (!this.playerGeneralAreaCacheSet) { ++ this.updateGeneralAreaCache(); ++ } ++ ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet nearby = this.playerGeneralAreaCache; ++ ++ if (nearby == null) { ++ return; ++ } ++ ++ double rangeSquared = range * range; ++ ++ Object[] backingSet = nearby.getBackingSet(); ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object _player = backingSet[i]; ++ if (!(_player instanceof EntityPlayer)) { ++ continue; ++ } ++ EntityPlayer player = (EntityPlayer)_player; ++ ++ if (range >= 0.0) { ++ double distanceSquared = player.getDistanceSquared(sourceX, sourceY, sourceZ); ++ if (distanceSquared > rangeSquared) { ++ continue; ++ } ++ } ++ ++ if (predicate == null || predicate.test(player)) { ++ ret.add(player); ++ } ++ } ++ } ++ // Tuinity end - optimise checkDespawn ++ + public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage, ChunkConverter chunkconverter, TickList ticklist, TickList ticklist1, long i, @Nullable ChunkSection[] achunksection, @Nullable Consumer consumer) { + this.sections = new ChunkSection[16]; + this.e = Maps.newHashMap(); +@@ -180,6 +332,7 @@ public class Chunk implements IChunkAccess { + + // CraftBukkit start + this.bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this); ++ this.entitySlicesManager = new com.tuinity.tuinity.world.ChunkEntitySlices(this.world, this.loc.x, this.loc.z, 0, 15); // TODO update for 1.17 // Tuinity + } + + public org.bukkit.Chunk bukkitChunk; +@@ -253,12 +406,12 @@ public class Chunk implements IChunkAccess { + PlayerChunkMap chunkMap = chunkProviderServer.playerChunkMap; + // this code handles the addition of ticking tickets - the distance map handles the removal + if (!areNeighboursLoaded(bitsetBefore, 2) && areNeighboursLoaded(bitsetAfter, 2)) { +- if (chunkMap.playerViewDistanceTickMap.getObjectsInRange(this.coordinateKey) != null) { ++ if (chunkMap.playerChunkManager.tickMap.getObjectsInRange(this.coordinateKey) != null) { // Tuinity - replace old player chunk loading system + // now we're ready for entity ticking + chunkProviderServer.serverThreadQueue.execute(() -> { + // double check that this condition still holds. +- if (Chunk.this.areNeighboursLoaded(2) && chunkMap.playerViewDistanceTickMap.getObjectsInRange(Chunk.this.coordinateKey) != null) { +- chunkProviderServer.addTicketAtLevel(TicketType.PLAYER, Chunk.this.loc, 31, Chunk.this.loc); // 31 -> entity ticking, TODO check on update ++ if (Chunk.this.areNeighboursLoaded(2) && chunkMap.playerChunkManager.tickMap.getObjectsInRange(Chunk.this.coordinateKey) != null) { // Tuinity - replace old player chunk loading system ++ chunkMap.playerChunkManager.onChunkPlayerTickReady(this.loc.x, this.loc.z); // Tuinity - replace old player chunk loading system + } + }); + } +@@ -266,31 +419,7 @@ public class Chunk implements IChunkAccess { + + // this code handles the chunk sending + if (!areNeighboursLoaded(bitsetBefore, 1) && areNeighboursLoaded(bitsetAfter, 1)) { +- if (chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(this.coordinateKey) != null) { +- // now we're ready to send +- chunkMap.mailboxMain.a(ChunkTaskQueueSorter.a(chunkMap.getUpdatingChunk(this.coordinateKey), (() -> { // Copied frm PlayerChunkMap +- // double check that this condition still holds. +- if (!Chunk.this.areNeighboursLoaded(1)) { +- return; +- } +- com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(Chunk.this.coordinateKey); +- if (inRange == null) { +- return; +- } +- +- // broadcast +- Object[] backingSet = inRange.getBackingSet(); +- Packet[] chunkPackets = new Packet[10]; +- for (int index = 0, len = backingSet.length; index < len; ++index) { +- Object temp = backingSet[index]; +- if (!(temp instanceof EntityPlayer)) { +- continue; +- } +- EntityPlayer player = (EntityPlayer)temp; +- chunkMap.sendChunk(player, chunkPackets, Chunk.this); +- } +- }))); +- } ++ chunkMap.playerChunkManager.onChunkSendReady(this.loc.x, this.loc.z); // Tuinity - replace old player chunk loading system + } + // Paper end - no-tick view distance + } +@@ -344,6 +473,12 @@ public class Chunk implements IChunkAccess { + + public Chunk(World world, ProtoChunk protochunk) { + this(world, protochunk.getPos(), protochunk.getBiomeIndex(), protochunk.p(), protochunk.n(), protochunk.o(), protochunk.getInhabitedTime(), protochunk.getSections(), (Consumer) null); ++ // Tuinity start - copy over protochunk light ++ this.setBlockNibbles(protochunk.getBlockNibbles()); ++ this.setSkyNibbles(protochunk.getSkyNibbles()); ++ this.setSkyEmptinessMap(protochunk.getSkyEmptinessMap()); ++ this.setBlockEmptinessMap(protochunk.getBlockEmptinessMap()); ++ // Tuinity end - copy over protochunk light + Iterator iterator = protochunk.y().iterator(); + + while (iterator.hasNext()) { +@@ -640,8 +775,9 @@ public class Chunk implements IChunkAccess { + entity.chunkX = this.loc.x; + entity.chunkY = k; + entity.chunkZ = this.loc.z; +- this.entities.add(entity); // Paper - per chunk entity list +- this.entitySlices[k].add(entity); ++ this.entities.add(entity); // Tuinity ++ this.entitySlices[k].add(entity); // Tuinity ++ this.entitySlicesManager.addEntity(entity, k); // Tuinity + // Paper start + if (entity instanceof EntityItem) { + itemCounts[k]++; +@@ -679,7 +815,8 @@ public class Chunk implements IChunkAccess { + entity.entitySlice = null; + entity.inChunk = false; + } +- if (!this.entitySlices[i].remove(entity)) { ++ this.entitySlicesManager.removeEntity(entity, i); // Tuinity ++ if (!this.entitySlices[i].remove(entity)) { // Tuinity - optimise hard colliding entities // Tuinity - entities by class // Tuinity + return; + } + if (entity instanceof EntityItem) { +@@ -858,6 +995,7 @@ public class Chunk implements IChunkAccess { + // Paper end - neighbour cache + org.bukkit.Server server = this.world.getServer(); + ((WorldServer)this.world).getChunkProvider().addLoadedChunk(this); // Paper ++ ((WorldServer)this.world).getChunkProvider().playerChunkMap.playerChunkManager.onChunkLoad(this.loc.x, this.loc.z); // Tuinity - rewrite player chunk management + if (server != null) { + /* + * If it's a new world, the first few chunks are generated inside +@@ -922,116 +1060,18 @@ public class Chunk implements IChunkAccess { + } + + public void a(@Nullable Entity entity, AxisAlignedBB axisalignedbb, List list, @Nullable Predicate predicate) { +- org.spigotmc.AsyncCatcher.catchOp("Chunk getEntities call"); // Spigot +- int i = MathHelper.floor((axisalignedbb.minY - 2.0D) / 16.0D); +- int j = MathHelper.floor((axisalignedbb.maxY + 2.0D) / 16.0D); +- +- i = MathHelper.clamp(i, 0, this.entitySlices.length - 1); +- j = MathHelper.clamp(j, 0, this.entitySlices.length - 1); +- +- for (int k = i; k <= j; ++k) { +- List entityslice = this.entitySlices[k]; // Spigot +- List list1 = entityslice; // Spigot +- int l = list1.size(); +- +- for (int i1 = 0; i1 < l; ++i1) { +- Entity entity1 = (Entity) list1.get(i1); +- if (entity1.shouldBeRemoved) continue; // Paper +- +- if (entity1.getBoundingBox().c(axisalignedbb) && entity1 != entity) { +- if (predicate == null || predicate.test(entity1)) { +- list.add(entity1); +- } +- +- if (entity1 instanceof EntityEnderDragon) { +- EntityComplexPart[] aentitycomplexpart = ((EntityEnderDragon) entity1).eJ(); +- int j1 = aentitycomplexpart.length; +- +- for (int k1 = 0; k1 < j1; ++k1) { +- EntityComplexPart entitycomplexpart = aentitycomplexpart[k1]; +- +- if (entitycomplexpart != entity && entitycomplexpart.getBoundingBox().c(axisalignedbb) && (predicate == null || predicate.test(entitycomplexpart))) { +- list.add(entitycomplexpart); +- } +- } +- } +- } +- } +- } ++ this.entitySlicesManager.getEntities(entity, axisalignedbb, list, predicate); // Tuinity - optimised entity slices + + } + + public void a(@Nullable EntityTypes entitytypes, AxisAlignedBB axisalignedbb, List list, Predicate predicate) { +- org.spigotmc.AsyncCatcher.catchOp("Chunk getEntities call"); // Spigot +- int i = MathHelper.floor((axisalignedbb.minY - 2.0D) / 16.0D); +- int j = MathHelper.floor((axisalignedbb.maxY + 2.0D) / 16.0D); +- +- i = MathHelper.clamp(i, 0, this.entitySlices.length - 1); +- j = MathHelper.clamp(j, 0, this.entitySlices.length - 1); +- +- for (int k = i; k <= j; ++k) { +- Iterator iterator = this.entitySlices[k].iterator(); // Spigot +- +- // Paper start - Don't search for inventories if we have none, and that is all we want +- /* +- * We check if they want inventories by seeing if it is the static `IEntitySelector.d` +- * +- * Make sure the inventory selector stays in sync. +- * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` +- */ +- if (predicate == IEntitySelector.isInventory() && inventoryEntityCounts[k] <= 0) continue; +- while (iterator.hasNext()) { +- T entity = (T) iterator.next(); // CraftBukkit - decompile error +- if (entity.shouldBeRemoved) continue; // Paper +- +- if ((entitytypes == null || entity.getEntityType() == entitytypes) && entity.getBoundingBox().c(axisalignedbb) && predicate.test(entity)) { +- list.add(entity); +- } +- } +- } ++ this.entitySlicesManager.getEntities(entitytypes, axisalignedbb, (List)list, (Predicate)predicate); // Tuinity - optimised entity slices + + } + ++ public final void getEntities(Class oclass, AxisAlignedBB axisalignedbb, List list, @Nullable Predicate predicate) { this.a(oclass, axisalignedbb, list, predicate); } // Tuinity - OBFHELPER + public void a(Class oclass, AxisAlignedBB axisalignedbb, List list, @Nullable Predicate predicate) { +- org.spigotmc.AsyncCatcher.catchOp("Chunk getEntities call"); // Spigot +- int i = MathHelper.floor((axisalignedbb.minY - 2.0D) / 16.0D); +- int j = MathHelper.floor((axisalignedbb.maxY + 2.0D) / 16.0D); +- +- i = MathHelper.clamp(i, 0, this.entitySlices.length - 1); +- j = MathHelper.clamp(j, 0, this.entitySlices.length - 1); +- +- // Paper start +- int[] counts; +- if (EntityItem.class.isAssignableFrom(oclass)) { +- counts = itemCounts; +- } else if (IInventory.class.isAssignableFrom(oclass)) { +- counts = inventoryEntityCounts; +- } else { +- counts = null; +- } +- // Paper end +- for (int k = i; k <= j; ++k) { +- if (counts != null && counts[k] <= 0) continue; // Paper - Don't check a chunk if it doesn't have the type we are looking for +- Iterator iterator = this.entitySlices[k].iterator(); // Spigot +- +- // Paper start - Don't search for inventories if we have none, and that is all we want +- /* +- * We check if they want inventories by seeing if it is the static `IEntitySelector.d` +- * +- * Make sure the inventory selector stays in sync. +- * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` +- */ +- if (predicate == IEntitySelector.isInventory() && inventoryEntityCounts[k] <= 0) continue; +- // Paper end +- while (iterator.hasNext()) { +- T t0 = (T) iterator.next(); // CraftBukkit - decompile error +- if (t0.shouldBeRemoved) continue; // Paper +- +- if (oclass.isInstance(t0) && t0.getBoundingBox().c(axisalignedbb) && (predicate == null || predicate.test(t0))) { // Spigot - instance check +- list.add(t0); +- } +- } +- } ++ this.entitySlicesManager.getEntities(oclass, null, axisalignedbb, list, predicate); // Tuinity - optimised entity slices + + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java +index f2621f61cb372ec436fe81e7a93f1aef7d360f3f..316287af6e405ff224636255c2964f46003215ce 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java +@@ -171,7 +171,7 @@ public abstract class ChunkGenerator { + // Get origin location (re)defined by event call. + blockposition = new BlockPosition(event.getOrigin().getBlockX(), event.getOrigin().getBlockY(), event.getOrigin().getBlockZ()); + // Get world (re)defined by event call. +- worldserver = ((org.bukkit.craftbukkit.CraftWorld) event.getOrigin().getWorld()).getHandle(); ++ //worldserver = ((org.bukkit.craftbukkit.CraftWorld) event.getOrigin().getWorld()).getHandle(); // Tuinity - callers and this function don't expect this to change + // Get radius and whether to find unexplored structures (re)defined by event call. + i = event.getRadius(); + flag = event.shouldFindUnexplored(); +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java +index 8fe060c3b2ad0873f96218eb7d02cdff3279224e..b5eb43174d2c2f34bb17bbcdb803aafe58989678 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java +@@ -18,7 +18,7 @@ public class ChunkSection { + short nonEmptyBlockCount; // Paper - package-private + short tickingBlockCount; // Paper - private -> package-private + private short e; +- final DataPaletteBlock blockIds; // Paper - package-private ++ public final DataPaletteBlock blockIds; // Paper - package-private // Tuinity - public + + public final com.destroystokyo.paper.util.maplist.IBlockDataList tickingList = new com.destroystokyo.paper.util.maplist.IBlockDataList(); // Paper + +@@ -103,6 +103,7 @@ public class ChunkSection { + return iblockdata1; + } + ++ public final boolean isFullOfAir() { return this.c(); } // Tuinity - OBFHELPER + public boolean c() { + return this.nonEmptyBlockCount == 0; + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java +index f094ddf6b4d155f3c7a08a3b811c98b0862fd098..f4a4d63a2e21b08580023cf0dcd15a68d192cf14 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java +@@ -120,7 +120,7 @@ public class ChunkStatus { + private final ChunkStatus.c w; + private final int x; + private final ChunkStatus.Type y; +- private final EnumSet z; ++ private final EnumSet z; public final HeightMap.Type[] heightMaps; // Tuinity + + private static CompletableFuture> a(ChunkStatus chunkstatus, LightEngineThreaded lightenginethreaded, IChunkAccess ichunkaccess) { + boolean flag = a(chunkstatus, ichunkaccess); +@@ -182,7 +182,7 @@ public class ChunkStatus { + this.w = chunkstatus_c; + this.x = i; + this.y = chunkstatus_type; +- this.z = enumset; ++ this.z = enumset; this.heightMaps = new java.util.ArrayList<>(this.z).toArray(new HeightMap.Type[0]); // Tuinity + this.t = chunkstatus == null ? 0 : chunkstatus.c() + 1; + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java +index 86dfab740883c138a0df8a3da9dfb4eb9acefaa3..a6937366cd9c9d708edb5cd1ab3ac096e7b2032e 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java ++++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java +@@ -172,6 +172,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { + return this.a(j << 8 | k << 4 | i); // Paper - inline + } + ++ public final T rawGet(int index) { return this.a(index); } // Tuinity - OBFHELPER + protected T a(int i) { + T t0 = this.h.a(this.a.a(i)); + +diff --git a/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java +index cdf612d7553a8f4aaebb5e0e66bd2a47a280457a..3a7039ceb770e3bb97bf77c9c57e6479ef8224e0 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java ++++ b/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java +@@ -37,6 +37,36 @@ public interface IChunkAccess extends IBlockAccess, IStructureAccess { + } + // Paper end + ++ // Tuinity start ++ default com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] getBlockNibbles() { ++ throw new UnsupportedOperationException(this.getClass().getName()); ++ } ++ default void setBlockNibbles(com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] nibbles) { ++ throw new UnsupportedOperationException(this.getClass().getName()); ++ } ++ ++ default com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] getSkyNibbles() { ++ throw new UnsupportedOperationException(this.getClass().getName()); ++ } ++ default void setSkyNibbles(com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] nibbles) { ++ throw new UnsupportedOperationException(this.getClass().getName()); ++ } ++ public default boolean[] getSkyEmptinessMap() { ++ throw new UnsupportedOperationException(this.getClass().getName()); ++ } ++ public default void setSkyEmptinessMap(final boolean[] emptinessMap) { ++ throw new UnsupportedOperationException(this.getClass().getName()); ++ } ++ ++ public default boolean[] getBlockEmptinessMap() { ++ throw new UnsupportedOperationException(this.getClass().getName()); ++ } ++ ++ public default void setBlockEmptinessMap(final boolean[] emptinessMap) { ++ throw new UnsupportedOperationException(this.getClass().getName()); ++ } ++ // Tuinity end ++ + IBlockData getType(final int x, final int y, final int z); // Paper + @Nullable + IBlockData setType(BlockPosition blockposition, IBlockData iblockdata, boolean flag); +@@ -135,6 +165,7 @@ public interface IChunkAccess extends IBlockAccess, IStructureAccess { + @Nullable + NBTTagCompound j(BlockPosition blockposition); + ++ default Stream getLightSources() { return this.m(); } // Tuinity - OBFHELPER + Stream m(); + + TickList n(); +@@ -155,7 +186,9 @@ public interface IChunkAccess extends IBlockAccess, IStructureAccess { + return ashortlist[i]; + } + ++ default boolean isLit() { return this.r(); } // Tuinity - OBFHELPER + boolean r(); + ++ default void setLit(boolean lit) { this.b(lit); } // Tuinity - OBFHELPER + void b(boolean flag); + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/ILightAccess.java b/src/main/java/net/minecraft/world/level/chunk/ILightAccess.java +index 43b8361e8ad0a8c429406cb6ff538020f670bdbd..bb63ed58e1eaeb474e99992e39d811b2589f88d9 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ILightAccess.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ILightAccess.java +@@ -7,9 +7,10 @@ import net.minecraft.world.level.IBlockAccess; + + public interface ILightAccess { + +- @Nullable +- IBlockAccess c(int i, int j); ++ default @Nullable IBlockAccess getFeaturesReadyChunk(int i, int j) { return this.c(i, j); } // Tuinity - OBFHELPER ++ @Nullable IBlockAccess c(int i, int j); + ++ default void markLightSectionDirty(EnumSkyBlock enumskyblock, SectionPosition sectionposition) { this.a(enumskyblock, sectionposition); } // Tuinity - OBFHELPER + default void a(EnumSkyBlock enumskyblock, SectionPosition sectionposition) {} + + IBlockAccess getWorld(); +diff --git a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java +index 3a85a89be2a736e5b6b7f08032f4becd6bb39ed1..d32369d9a555fd7595df175e56f853ce8b012522 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java ++++ b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java +@@ -58,6 +58,7 @@ public class NibbleArray { + boolean poolSafe = false; + public java.lang.Runnable cleaner; + private void registerCleaner() { ++ if (com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine) return; // Tuinity - purge cleaner usage + if (!poolSafe) { + cleaner = MCUtil.registerCleaner(this, this.a, NibbleArray::releaseBytes); + } else { +@@ -65,7 +66,7 @@ public class NibbleArray { + } + } + // Paper end +- @Nullable protected byte[] a; ++ @Nullable protected byte[] a; public final byte[] justGiveMeTheFuckingByteArrayNoCleanerBullshitJesusFuckingChrist() { return this.a; } + + + public NibbleArray() {} +@@ -76,7 +77,7 @@ public class NibbleArray { + } + public NibbleArray(byte[] abyte, boolean isSafe) { + this.a = abyte; +- if (!isSafe) this.a = getCloneIfSet(); // Paper - clone for safety ++ if (!com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine && !isSafe) this.a = getCloneIfSet(); // Paper - clone for safety // Tuinity - no need to clone + registerCleaner(); + // Paper end + if (abyte.length != 2048) { +@@ -164,7 +165,7 @@ public class NibbleArray { + + public NibbleArray copy() { return this.b(); } // Paper - OBFHELPER + public NibbleArray b() { +- return this.a == null ? new NibbleArray() : new NibbleArray(this.a); // Paper - clone in ctor ++ return this.a == null ? new NibbleArray() : new NibbleArray(com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? this.a.clone() : this.a); // Paper - clone in ctor // Tuinity - no longer clone in constructor + } + + public String toString() { +diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +index 7bfac4e852c4a6697435647dab173913df6034e9..692658893f9d33938fc4fed854ad31c14c920e95 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +@@ -66,6 +66,54 @@ public class ProtoChunk implements IChunkAccess { + private volatile boolean u; + final World world; // Paper - Anti-Xray - Add world // Paper - private -> default + ++ // Tuinity start - rewrite light engine ++ protected volatile com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] blockNibbles = com.tuinity.tuinity.chunk.light.StarLightEngine.getFilledEmptyLight(); ++ protected volatile com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] skyNibbles = com.tuinity.tuinity.chunk.light.StarLightEngine.getFilledEmptyLight(); ++ protected volatile boolean[] skyEmptinessMap; ++ protected volatile boolean[] blockEmptinessMap; ++ ++ @Override ++ public com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] getBlockNibbles() { ++ return this.blockNibbles; ++ } ++ ++ @Override ++ public void setBlockNibbles(com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] nibbles) { ++ this.blockNibbles = nibbles; ++ } ++ ++ @Override ++ public com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] getSkyNibbles() { ++ return this.skyNibbles; ++ } ++ ++ @Override ++ public void setSkyNibbles(com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] nibbles) { ++ this.skyNibbles = nibbles; ++ } ++ ++ @Override ++ public boolean[] getSkyEmptinessMap() { ++ return this.skyEmptinessMap; ++ } ++ ++ @Override ++ public void setSkyEmptinessMap(boolean[] emptinessMap) { ++ this.skyEmptinessMap = emptinessMap; ++ } ++ ++ @Override ++ public boolean[] getBlockEmptinessMap() { ++ return this.blockEmptinessMap; ++ } ++ ++ @Override ++ public void setBlockEmptinessMap(boolean[] emptinessMap) { ++ this.blockEmptinessMap = emptinessMap; ++ } ++ ++ // Tuinity end - rewrite light engine ++ + // Paper start - Anti-Xray - Add world + @Deprecated public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter) { this(chunkcoordintpair, chunkconverter, null); } // Notice for updates: Please make sure this constructor isn't used anywhere + public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter, World world) { +@@ -191,20 +239,17 @@ public class ProtoChunk implements IChunkAccess { + ChunkSection chunksection = this.a(j >> 4); + IBlockData iblockdata1 = chunksection.setType(i & 15, j & 15, k & 15, iblockdata); + +- if (this.g.b(ChunkStatus.FEATURES) && iblockdata != iblockdata1 && (iblockdata.b((IBlockAccess) this, blockposition) != iblockdata1.b((IBlockAccess) this, blockposition) || iblockdata.f() != iblockdata1.f() || iblockdata.e() || iblockdata1.e())) { ++ if ((com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? (this.g.b(ChunkStatus.LIGHT) && this.isLit()) : (this.g.b(ChunkStatus.FEATURES))) && iblockdata != iblockdata1 && (iblockdata.b((IBlockAccess) this, blockposition) != iblockdata1.b((IBlockAccess) this, blockposition) || iblockdata.f() != iblockdata1.f() || iblockdata.e() || iblockdata1.e())) { // Tuinity - move block updates to only happen after lighting occurs + LightEngine lightengine = this.e(); + + lightengine.a(blockposition); + } + +- EnumSet enumset = this.getChunkStatus().h(); ++ HeightMap.Type[] enumset = this.getChunkStatus().heightMaps; // Tuinity - reduce iterator creation + EnumSet enumset1 = null; +- Iterator iterator = enumset.iterator(); +- +- HeightMap.Type heightmap_type; ++ // Tuinity - reduce iterator creation + +- while (iterator.hasNext()) { +- heightmap_type = (HeightMap.Type) iterator.next(); ++ for (HeightMap.Type heightmap_type : enumset) { // Tuinity - reduce iterator creation + HeightMap heightmap = (HeightMap) this.f.get(heightmap_type); + + if (heightmap == null) { +@@ -220,10 +265,9 @@ public class ProtoChunk implements IChunkAccess { + HeightMap.a(this, enumset1); + } + +- iterator = enumset.iterator(); +- +- while (iterator.hasNext()) { +- heightmap_type = (HeightMap.Type) iterator.next(); ++ // Tuinity start - reduce iterator creation ++ for (HeightMap.Type heightmap_type : enumset) { ++ // Tuinity end - reduce iterator creation + ((HeightMap) this.f.get(heightmap_type)).a(i & 15, j, k & 15, iblockdata); + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java +index 7a82d43d51d80a3054e0871bf4b9aa7635920efc..980727261b328dc69f133f33906e957aa75f8600 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java +@@ -24,7 +24,50 @@ import net.minecraft.world.level.material.FluidTypes; + + public class ProtoChunkExtension extends ProtoChunk { + +- private final Chunk a; ++ private final Chunk a; public final Chunk getWrappedChunk() { return this.a; } // Tuinity - OBFHELPER ++ ++ // Tuinity start - rewrite light engine ++ @Override ++ public com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] getBlockNibbles() { ++ return this.getWrappedChunk().getBlockNibbles(); ++ } ++ ++ @Override ++ public void setBlockNibbles(com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] nibbles) { ++ this.getWrappedChunk().setBlockNibbles(nibbles); ++ } ++ ++ @Override ++ public com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] getSkyNibbles() { ++ return this.getWrappedChunk().getSkyNibbles(); ++ } ++ ++ @Override ++ public void setSkyNibbles(com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] nibbles) { ++ this.getWrappedChunk().setSkyNibbles(nibbles); ++ } ++ ++ @Override ++ public boolean[] getSkyEmptinessMap() { ++ return this.getWrappedChunk().getSkyEmptinessMap(); ++ } ++ ++ @Override ++ public void setSkyEmptinessMap(final boolean[] emptinessMap) { ++ this.getWrappedChunk().setSkyEmptinessMap(emptinessMap); ++ } ++ ++ @Override ++ public boolean[] getBlockEmptinessMap() { ++ return this.getWrappedChunk().getBlockEmptinessMap(); ++ } ++ ++ @Override ++ public void setBlockEmptinessMap(boolean[] emptinessMap) { ++ this.getWrappedChunk().setBlockEmptinessMap(emptinessMap); ++ } ++ ++ // Tuinity end - rewrite light engine + + public ProtoChunkExtension(Chunk chunk) { + super(chunk.getPos(), ChunkConverter.a, chunk.world); // Paper - Anti-Xray - Add parameter +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +index 4eaf497d048324a85ce49fc1c6e9559991c20df7..ec2b238480413ba9c123d9ddeaa787d9520e1b74 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +@@ -68,6 +68,14 @@ public class ChunkRegionLoader { + + private static final Logger LOGGER = LogManager.getLogger(); + ++ // Tuinity start ++ // TODO: Check on update ++ public static long getLastWorldSaveTime(NBTTagCompound chunkData) { ++ NBTTagCompound levelData = chunkData.getCompound("Level"); ++ return levelData.getLong("LastUpdate"); ++ } ++ // Tuinity end ++ + // Paper start - guard against serializing mismatching coordinates + // TODO Note: This needs to be re-checked each update + public static ChunkCoordIntPair getChunkCoordinate(NBTTagCompound chunkData) { +@@ -100,6 +108,13 @@ public class ChunkRegionLoader { + private static final boolean JUST_CORRUPT_IT = Boolean.getBoolean("Paper.ignoreWorldDataVersion"); + // Paper end + ++ // Tuinity start - rewrite light engine ++ private static final int STARLIGHT_LIGHT_VERSION = 4; ++ ++ private static final String UNINITIALISED_SKYLIGHT_TAG = "starlight.skylight_uninit"; ++ private static final String STARLIGHT_VERSION_TAG = "starlight.light_version"; ++ // Tuinity end - rewrite light engine ++ + public static InProgressChunkHolder loadChunk(WorldServer worldserver, DefinedStructureManager definedstructuremanager, VillagePlace villageplace, ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound, boolean distinguish) { + ArrayDeque tasksToExecuteOnMain = new ArrayDeque<>(); + // Paper end +@@ -129,13 +144,17 @@ public class ChunkRegionLoader { + ProtoChunkTickList protochunkticklist1 = new ProtoChunkTickList<>((fluidtype) -> { + return fluidtype == null || fluidtype == FluidTypes.EMPTY; + }, chunkcoordintpair, nbttagcompound1.getList("LiquidsToBeTicked", 9)); +- boolean flag = nbttagcompound1.getBoolean("isLightOn"); ++ boolean flag = (com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? nbttagcompound1.getInt(STARLIGHT_VERSION_TAG) == STARLIGHT_LIGHT_VERSION : nbttagcompound1.getBoolean("isLightOn")); boolean canUseSkyLight = flag && getStatus(nbttagcompound).isAtLeastStatus(ChunkStatus.LIGHT); boolean canUseBlockLight = canUseSkyLight; // Tuinity + NBTTagList nbttaglist = nbttagcompound1.getList("Sections", 10); + boolean flag1 = true; + ChunkSection[] achunksection = new ChunkSection[16]; + boolean flag2 = worldserver.getDimensionManager().hasSkyLight(); + ChunkProviderServer chunkproviderserver = worldserver.getChunkProvider(); + LightEngine lightengine = chunkproviderserver.getLightEngine(); ++ com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] blockNibbles = com.tuinity.tuinity.chunk.light.StarLightEngine.getFilledEmptyLight(worldserver); // Tuinity - replace light impl ++ com.tuinity.tuinity.chunk.light.SWMRNibbleArray[] skyNibbles = com.tuinity.tuinity.chunk.light.StarLightEngine.getFilledEmptyLight(worldserver); // Tuinity - replace light impl ++ final int minSection = com.tuinity.tuinity.util.WorldUtil.getMinLightSection(worldserver); ++ final int maxSection = com.tuinity.tuinity.util.WorldUtil.getMaxLightSection(worldserver); + + if (flag) { + tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main +@@ -163,6 +182,7 @@ public class ChunkRegionLoader { + + if (flag) { + if (nbttagcompound2.hasKeyOfType("BlockLight", 7)) { ++ if (com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine && canUseBlockLight) blockNibbles[b0 - minSection] = new com.tuinity.tuinity.chunk.light.SWMRNibbleArray(nbttagcompound2.getByteArray("BlockLight").clone()); // Tuinity - replace light impl + // Paper start - delay this task since we're executing off-main + NibbleArray blockLight = new NibbleArray(nbttagcompound2.getByteArray("BlockLight")); + tasksToExecuteOnMain.add(() -> { +@@ -172,13 +192,14 @@ public class ChunkRegionLoader { + } + + if (flag2 && nbttagcompound2.hasKeyOfType("SkyLight", 7)) { ++ if (com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine && canUseSkyLight) skyNibbles[b0 - minSection] = new com.tuinity.tuinity.chunk.light.SWMRNibbleArray(nbttagcompound2.getByteArray("SkyLight").clone()); // Tuinity - replace light impl + // Paper start - delay this task since we're executing off-main + NibbleArray skyLight = new NibbleArray(nbttagcompound2.getByteArray("SkyLight")); + tasksToExecuteOnMain.add(() -> { + lightengine.a(EnumSkyBlock.SKY, SectionPosition.a(chunkcoordintpair, b0), skyLight, true); + }); + // Paper end - delay this task since we're executing off-main +- } ++ } else if (flag2 && nbttagcompound2.getBoolean(UNINITIALISED_SKYLIGHT_TAG)) skyNibbles[b0 - minSection] = new com.tuinity.tuinity.chunk.light.SWMRNibbleArray(); // Tuinity - replace light impl + } + } + +@@ -217,8 +238,12 @@ public class ChunkRegionLoader { + object = new Chunk(worldserver.getMinecraftWorld(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, // Paper start - fix massive nbt memory leak due to lambda. move lambda into a container method to not leak scope. Only clone needed NBT keys. + createLoadEntitiesConsumer(new SafeNBTCopy(nbttagcompound1, "TileEntities", "Entities", "ChunkBukkitValues")) // Paper - move CB Chunk PDC into here + );// Paper end ++ ((Chunk)object).setBlockNibbles(blockNibbles); // Tuinity - replace light impl ++ ((Chunk)object).setSkyNibbles(skyNibbles); // Tuinity - replace light impl + } else { + ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, worldserver); // Paper - Anti-Xray - Add parameter ++ protochunk.setBlockNibbles(blockNibbles); // Tuinity - replace light impl ++ protochunk.setSkyNibbles(skyNibbles); // Tuinity - replace light impl + + protochunk.a(biomestorage); + object = protochunk; +@@ -397,15 +422,20 @@ public class ChunkRegionLoader { + NibbleArray[] blockLight = new NibbleArray[17 - (-1)]; + NibbleArray[] skyLight = new NibbleArray[17 - (-1)]; + ++ // Tuinity start - rewrite light impl ++ final int minSection = com.tuinity.tuinity.util.WorldUtil.getMinLightSection(world); ++ final int maxSection = com.tuinity.tuinity.util.WorldUtil.getMaxLightSection(world); ++ // Tuinity end - rewrite light impl ++ + for (int i = -1; i < 17; ++i) { +- NibbleArray blockArray = lightenginethreaded.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkPos, i)); +- NibbleArray skyArray = lightenginethreaded.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkPos, i)); ++ NibbleArray blockArray = com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? (!lightenginethreaded.hasBlockLight ? null : (chunk.getBlockNibbles()[i - minSection].isAllZero() ? new NibbleArray() : chunk.getBlockNibbles()[i - minSection].toVanillaNibble())) : lightenginethreaded.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkPos, i)); // Tuinity - chunk might not be loaded ++ NibbleArray skyArray = com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? (!lightenginethreaded.hasSkyLight ? null : (chunk.getSkyNibbles()[i - minSection].isAllZero() ? new NibbleArray() : chunk.getSkyNibbles()[i - minSection].toVanillaNibble())) : lightenginethreaded.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkPos, i)); // Tuinity - chunk might not be loaded + + // copy data for safety +- if (blockArray != null) { ++ if (!com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine && blockArray != null) { // Tuinity - data already copied + blockArray = blockArray.copy(); + } +- if (skyArray != null) { ++ if (!com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine && skyArray != null) { // Tuinity - data already copied + skyArray = skyArray.copy(); + } + +@@ -440,15 +470,19 @@ public class ChunkRegionLoader { + } + public static NBTTagCompound saveChunk(WorldServer worldserver, IChunkAccess ichunkaccess, AsyncSaveData asyncsavedata) { + // Paper end ++ // Tuinity start - rewrite light impl ++ final int minSection = com.tuinity.tuinity.util.WorldUtil.getMinLightSection(worldserver); ++ final int maxSection = com.tuinity.tuinity.util.WorldUtil.getMaxLightSection(worldserver); ++ // Tuinity end - rewrite light impl + ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos(); + NBTTagCompound nbttagcompound = new NBTTagCompound(); + NBTTagCompound nbttagcompound1 = new NBTTagCompound(); + + nbttagcompound.setInt("DataVersion", SharedConstants.getGameVersion().getWorldVersion()); +- nbttagcompound.set("Level", nbttagcompound1); ++ nbttagcompound.set("Level", nbttagcompound1); // Tuinity - diff on change + nbttagcompound1.setInt("xPos", chunkcoordintpair.x); + nbttagcompound1.setInt("zPos", chunkcoordintpair.z); +- nbttagcompound1.setLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : worldserver.getTime()); // Paper - async chunk unloading ++ nbttagcompound1.setLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : worldserver.getTime()); // Paper - async chunk unloading // Tuinity - diff on change + nbttagcompound1.setLong("InhabitedTime", ichunkaccess.getInhabitedTime()); + nbttagcompound1.setString("Status", ichunkaccess.getChunkStatus().d()); + ChunkConverter chunkconverter = ichunkaccess.p(); +@@ -473,8 +507,8 @@ public class ChunkRegionLoader { + NibbleArray nibblearray; // block light + NibbleArray nibblearray1; // sky light + if (asyncsavedata == null) { +- nibblearray = lightenginethreaded.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkcoordintpair, i)); /// Paper - diff on method change (see getAsyncSaveData) +- nibblearray1 = lightenginethreaded.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, i)); // Paper - diff on method change (see getAsyncSaveData) ++ nibblearray = com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? (!lightenginethreaded.hasBlockLight ? null : (ichunkaccess.getBlockNibbles()[i - minSection].isAllZero() ? new NibbleArray() : ichunkaccess.getBlockNibbles()[i - minSection].toVanillaNibble())) : lightenginethreaded.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkcoordintpair, i)); // Tuinity - chunk might not be loaded ++ nibblearray1 = com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? (!lightenginethreaded.hasSkyLight ? null : (ichunkaccess.getSkyNibbles()[i - minSection].isAllZero() ? new NibbleArray() : ichunkaccess.getSkyNibbles()[i - minSection].toVanillaNibble())) : lightenginethreaded.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, i)); // Tuinity - chunk might not be loaded + } else { + nibblearray = asyncsavedata.blockLight[i + 1]; // +1 to offset the -1 starting index + nibblearray1 = asyncsavedata.skyLight[i + 1]; // +1 to offset the -1 starting index +@@ -488,12 +522,12 @@ public class ChunkRegionLoader { + } + + if (nibblearray != null && !nibblearray.c()) { +- nbttagcompound2.setByteArray("BlockLight", nibblearray.asBytesPoolSafe().clone()); // Paper ++ nbttagcompound2.setByteArray("BlockLight", com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? nibblearray.asBytes() : nibblearray.asBytesPoolSafe().clone()); // Paper // Tuinity - data is already cloned + } + + if (nibblearray1 != null && !nibblearray1.c()) { +- nbttagcompound2.setByteArray("SkyLight", nibblearray1.asBytesPoolSafe().clone()); // Paper +- } ++ nbttagcompound2.setByteArray("SkyLight", com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? nibblearray1.asBytes() : nibblearray1.asBytesPoolSafe().clone()); // Paper // Tuinity - data is already cloned ++ } else if (nibblearray1 != null && com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine) nbttagcompound2.setBoolean(UNINITIALISED_SKYLIGHT_TAG, true); // Tuinity - store uninitialised tags + + nbttaglist.add(nbttagcompound2); + } +@@ -501,7 +535,7 @@ public class ChunkRegionLoader { + + nbttagcompound1.set("Sections", nbttaglist); + if (flag) { +- nbttagcompound1.setBoolean("isLightOn", true); ++ nbttagcompound1.setBoolean("isLightOn", com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine ? false : true); if (com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine) nbttagcompound1.setInt(STARLIGHT_VERSION_TAG, STARLIGHT_LIGHT_VERSION); // Tuinity + } + + BiomeStorage biomestorage = ichunkaccess.getBiomeIndex(); +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java +index 890362d28ab9cb760c73fe5014e144fb08ada6b8..3c532d3996dfc734ec07181701280b6072bff55f 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java +@@ -39,7 +39,7 @@ public class IChunkLoader implements AutoCloseable { + public final RegionFileCache regionFileCache; + + public IChunkLoader(File file, DataFixer datafixer, boolean flag) { +- this.regionFileCache = new RegionFileCache(file, flag); // Paper - nuke IOWorker ++ this.regionFileCache = new RegionFileCache(file, flag, true); // Paper - nuke IOWorker // Tuinity + this.b = datafixer; + // Paper - nuke IOWorker + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +index 4999ba61fb04713ffe3d23c556f732dc4abbf0bc..0bba434d29b09d7d164f5ca4f49cd660bec66927 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +@@ -5,6 +5,7 @@ import java.io.BufferedInputStream; + import java.io.BufferedOutputStream; + import java.io.ByteArrayInputStream; + import java.io.ByteArrayOutputStream; ++import java.io.DataInput; + import java.io.DataInputStream; + import java.io.DataOutputStream; + import java.io.File; +@@ -35,15 +36,350 @@ public class RegionFile implements AutoCloseable { + private static final Logger LOGGER = LogManager.getLogger(); + private static final ByteBuffer c = ByteBuffer.allocateDirect(1); + private final FileChannel dataFile; +- private final Path e; +- private final RegionFileCompression f; ++ private final Path e; private final java.nio.file.Path getContainingDataFolder() { return this.e; } // Tuinity - OBFHELPER ++ private final RegionFileCompression f; private final RegionFileCompression getRegionFileCompression() { return this.f; } // Tuinity - OBFHELPER + private final ByteBuffer g; +- private final IntBuffer h; +- private final IntBuffer i; ++ private final IntBuffer h; private final IntBuffer getOffsets() { return this.h; } // Tuinity - OBFHELPER ++ private final IntBuffer i; private final IntBuffer getTimestamps() { return this.i; } // Tuinity - OBFHELPER + @VisibleForTesting + protected final RegionFileBitSet freeSectors; + public final File file; // Paper + ++ // Tuinity start - try to recover from RegionFile header corruption ++ private static long roundToSectors(long bytes) { ++ long sectors = bytes >>> 12; // 4096 = 2^12 ++ long remainingBytes = bytes & 4095; ++ long sign = -remainingBytes; // sign is 1 if nonzero ++ return sectors + (sign >>> 63); ++ } ++ ++ private static final NBTTagCompound OVERSIZED_COMPOUND = new NBTTagCompound(); ++ ++ private NBTTagCompound attemptRead(long sector, int chunkDataLength, long fileLength) throws IOException { ++ try { ++ if (chunkDataLength < 0) { ++ return null; ++ } ++ ++ long offset = sector * 4096L + 4L; // offset for chunk data ++ ++ if ((offset + chunkDataLength) > fileLength) { ++ return null; ++ } ++ ++ ByteBuffer chunkData = ByteBuffer.allocate(chunkDataLength); ++ if (chunkDataLength != this.dataFile.read(chunkData, offset)) { ++ return null; ++ } ++ ++ ((java.nio.Buffer)chunkData).flip(); ++ ++ byte compressionType = chunkData.get(); ++ if (compressionType < 0) { // compressionType & 128 != 0 ++ // oversized chunk ++ return OVERSIZED_COMPOUND; ++ } ++ ++ RegionFileCompression compression = RegionFileCompression.getByType(compressionType); ++ if (compression == null) { ++ return null; ++ } ++ ++ InputStream input = compression.wrap(new ByteArrayInputStream(chunkData.array(), chunkData.position(), chunkDataLength - chunkData.position())); ++ ++ return NBTCompressedStreamTools.readNBT((java.io.DataInput)new DataInputStream(new BufferedInputStream(input))); ++ } catch (Exception ex) { ++ return null; ++ } ++ } ++ ++ private int getLength(long sector) throws IOException { ++ ByteBuffer length = ByteBuffer.allocate(4); ++ if (4 != this.dataFile.read(length, sector * 4096L)) { ++ return -1; ++ } ++ ++ return length.getInt(0); ++ } ++ ++ private void backupRegionFile() { ++ File backup = new File(this.file.getParent(), this.file.getName() + "." + new java.util.Random().nextLong() + ".backup"); ++ this.backupRegionFile(backup); ++ } ++ ++ private void backupRegionFile(File to) { ++ try { ++ this.dataFile.force(true); ++ LOGGER.warn("Backing up regionfile \"" + this.file.getAbsolutePath() + "\" to " + to.getAbsolutePath()); ++ java.nio.file.Files.copy(this.file.toPath(), to.toPath()); ++ LOGGER.warn("Backed up the regionfile to " + to.getAbsolutePath()); ++ } catch (IOException ex) { ++ LOGGER.error("Failed to backup to " + to.getAbsolutePath(), ex); ++ } ++ } ++ ++ // note: only call for CHUNK regionfiles ++ void recalculateHeader() throws IOException { ++ if (!this.canRecalcHeader) { ++ return; ++ } ++ synchronized (this) { ++ LOGGER.warn("Corrupt regionfile header detected! Attempting to re-calculate header offsets for regionfile " + this.file.getAbsolutePath(), new Throwable()); ++ ++ // try to backup file so maybe it could be sent to us for further investigation ++ ++ this.backupRegionFile(); ++ NBTTagCompound[] compounds = new NBTTagCompound[32 * 32]; // only in the regionfile (i.e exclude mojang/aikar oversized data) ++ int[] rawLengths = new int[32 * 32]; // length of chunk data including 4 byte length field, bytes ++ int[] sectorOffsets = new int[32 * 32]; // in sectors ++ boolean[] hasAikarOversized = new boolean[32 * 32]; ++ ++ long fileLength = this.dataFile.size(); ++ long totalSectors = roundToSectors(fileLength); ++ ++ // search the regionfile from start to finish for the most up-to-date chunk data ++ ++ for (long i = 2, maxSector = Math.min((long)(Integer.MAX_VALUE >>> 8), totalSectors); i < maxSector; ++i) { // first two sectors are header, skip ++ int chunkDataLength = this.getLength(i); ++ NBTTagCompound compound = this.attemptRead(i, chunkDataLength, fileLength); ++ if (compound == null || compound == OVERSIZED_COMPOUND) { ++ continue; ++ } ++ ++ ChunkCoordIntPair chunkPos = ChunkRegionLoader.getChunkCoordinate(compound); ++ int location = (chunkPos.x & 31) | ((chunkPos.z & 31) << 5); ++ ++ NBTTagCompound otherCompound = compounds[location]; ++ ++ if (otherCompound != null && ChunkRegionLoader.getLastWorldSaveTime(otherCompound) > ChunkRegionLoader.getLastWorldSaveTime(compound)) { ++ continue; // don't overwrite newer data. ++ } ++ ++ // aikar oversized? ++ File aikarOversizedFile = this.getOversizedFile(chunkPos.x, chunkPos.z); ++ boolean isAikarOversized = false; ++ if (aikarOversizedFile.exists()) { ++ try { ++ NBTTagCompound aikarOversizedCompound = this.getOversizedData(chunkPos.x, chunkPos.z); ++ if (ChunkRegionLoader.getLastWorldSaveTime(compound) == ChunkRegionLoader.getLastWorldSaveTime(aikarOversizedCompound)) { ++ // best we got for an id. hope it's good enough ++ isAikarOversized = true; ++ } ++ } catch (Exception ex) { ++ LOGGER.error("Failed to read aikar oversized data for absolute chunk (" + chunkPos.x + "," + chunkPos.z + ") in regionfile " + this.file.getAbsolutePath() + ", oversized data for this chunk will be lost", ex); ++ // fall through, if we can't read aikar oversized we can't risk corrupting chunk data ++ } ++ } ++ ++ hasAikarOversized[location] = isAikarOversized; ++ compounds[location] = compound; ++ rawLengths[location] = chunkDataLength + 4; ++ sectorOffsets[location] = (int)i; ++ ++ int chunkSectorLength = (int)roundToSectors(rawLengths[location]); ++ i += chunkSectorLength; ++ --i; // gets incremented next iteration ++ } ++ ++ // forge style oversized data is already handled by the local search, and aikar data we just hope ++ // we get it right as aikar data has no identifiers we could use to try and find its corresponding ++ // local data compound ++ ++ java.nio.file.Path containingFolder = this.getContainingDataFolder(); ++ File[] regionFiles = containingFolder.toFile().listFiles(); ++ boolean[] oversized = new boolean[32 * 32]; ++ RegionFileCompression[] oversizedCompressionTypes = new RegionFileCompression[32 * 32]; ++ ++ if (regionFiles != null) { ++ ChunkCoordIntPair ourLowerLeftPosition = RegionFileCache.getRegionFileCoordinates(this.file); ++ ++ if (ourLowerLeftPosition == null) { ++ LOGGER.fatal("Unable to get chunk location of regionfile " + this.file.getAbsolutePath() + ", cannot recover oversized chunks"); ++ } else { ++ int lowerXBound = ourLowerLeftPosition.x; // inclusive ++ int lowerZBound = ourLowerLeftPosition.z; // inclusive ++ int upperXBound = lowerXBound + 32 - 1; // inclusive ++ int upperZBound = lowerZBound + 32 - 1; // inclusive ++ ++ // read mojang oversized data ++ for (File regionFile : regionFiles) { ++ ChunkCoordIntPair oversizedCoords = getOversizedChunkPair(regionFile); ++ if (oversizedCoords == null) { ++ continue; ++ } ++ ++ if ((oversizedCoords.x < lowerXBound || oversizedCoords.x > upperXBound) || (oversizedCoords.z < lowerZBound || oversizedCoords.z > upperZBound)) { ++ continue; // not in our regionfile ++ } ++ ++ // ensure oversized data is valid & is newer than data in the regionfile ++ ++ int location = (oversizedCoords.x & 31) | ((oversizedCoords.z & 31) << 5); ++ ++ byte[] chunkData; ++ try { ++ chunkData = Files.readAllBytes(regionFile.toPath()); ++ } catch (Exception ex) { ++ LOGGER.error("Failed to read oversized chunk data in file " + regionFile.getAbsolutePath() + ", data will be lost", ex); ++ continue; ++ } ++ ++ NBTTagCompound compound = null; ++ ++ // We do not know the compression type, as it's stored in the regionfile. So we need to try all of them ++ RegionFileCompression compression = null; ++ for (RegionFileCompression compressionType : RegionFileCompression.getCompressionTypes().values()) { ++ try { ++ DataInputStream in = new DataInputStream(new BufferedInputStream(compressionType.wrap(new ByteArrayInputStream(chunkData)))); // typical java ++ compound = NBTCompressedStreamTools.readNBT((DataInput)in); ++ compression = compressionType; ++ break; // reaches here iff readNBT does not throw ++ } catch (Exception ex) { ++ continue; ++ } ++ } ++ ++ if (compound == null) { ++ LOGGER.error("Failed to read oversized chunk data in file " + regionFile.getAbsolutePath() + ", it's corrupt. Its data will be lost"); ++ continue; ++ } ++ ++ if (compounds[location] == null || ChunkRegionLoader.getLastWorldSaveTime(compound) > ChunkRegionLoader.getLastWorldSaveTime(compounds[location])) { ++ oversized[location] = true; ++ oversizedCompressionTypes[location] = compression; ++ } ++ } ++ } ++ } ++ ++ // now we need to calculate a new offset header ++ ++ int[] calculatedOffsets = new int[32 * 32]; ++ RegionFileBitSet newSectorAllocations = new RegionFileBitSet(); ++ newSectorAllocations.allocate(0, 2); // make space for header ++ ++ // allocate sectors for normal chunks ++ ++ for (int chunkX = 0; chunkX < 32; ++chunkX) { ++ for (int chunkZ = 0; chunkZ < 32; ++chunkZ) { ++ int location = chunkX | (chunkZ << 5); ++ ++ if (oversized[location]) { ++ continue; ++ } ++ ++ int rawLength = rawLengths[location]; // bytes ++ int sectorOffset = sectorOffsets[location]; // sectors ++ int sectorLength = (int)roundToSectors(rawLength); ++ ++ if (newSectorAllocations.tryAllocate(sectorOffset, sectorLength)) { ++ calculatedOffsets[location] = sectorOffset << 8 | (sectorLength > 255 ? 255 : sectorLength); // support forge style oversized ++ } else { ++ LOGGER.error("Failed to allocate space for local chunk (overlapping data??) at (" + chunkX + "," + chunkZ + ") in regionfile " + this.file.getAbsolutePath() + ", chunk will be regenerated"); ++ } ++ } ++ } ++ ++ // allocate sectors for oversized chunks ++ ++ for (int chunkX = 0; chunkX < 32; ++chunkX) { ++ for (int chunkZ = 0; chunkZ < 32; ++chunkZ) { ++ int location = chunkX | (chunkZ << 5); ++ ++ if (!oversized[location]) { ++ continue; ++ } ++ ++ int sectorOffset = newSectorAllocations.allocateNewSpace(1); ++ int sectorLength = 1; ++ ++ try { ++ this.dataFile.write(this.getOversizedChunkHolderData(oversizedCompressionTypes[location]), sectorOffset * 4096); ++ // only allocate in the new offsets if the write succeeds ++ calculatedOffsets[location] = sectorOffset << 8 | (sectorLength > 255 ? 255 : sectorLength); // support forge style oversized ++ } catch (IOException ex) { ++ newSectorAllocations.free(sectorOffset, sectorLength); ++ LOGGER.error("Failed to write new oversized chunk data holder, local chunk at (" + chunkX + "," + chunkZ + ") in regionfile " + this.file.getAbsolutePath() + " will be regenerated"); ++ } ++ } ++ } ++ ++ // rewrite aikar oversized data ++ ++ this.oversizedCount = 0; ++ for (int chunkX = 0; chunkX < 32; ++chunkX) { ++ for (int chunkZ = 0; chunkZ < 32; ++chunkZ) { ++ int location = chunkX | (chunkZ << 5); ++ int isAikarOversized = hasAikarOversized[location] ? 1 : 0; ++ ++ this.oversizedCount += isAikarOversized; ++ this.oversized[location] = (byte)isAikarOversized; ++ } ++ } ++ ++ if (this.oversizedCount > 0) { ++ try { ++ this.writeOversizedMeta(); ++ } catch (Exception ex) { ++ LOGGER.error("Failed to write aikar oversized chunk meta, all aikar style oversized chunk data will be lost for regionfile " + this.file.getAbsolutePath(), ex); ++ this.getOversizedMetaFile().delete(); ++ } ++ } else { ++ this.getOversizedMetaFile().delete(); ++ } ++ ++ this.freeSectors.copyFrom(newSectorAllocations); ++ ++ // before we overwrite the old sectors, print a summary of the chunks that got changed. ++ ++ LOGGER.info("Starting summary of changes for regionfile " + this.file.getAbsolutePath()); ++ ++ for (int chunkX = 0; chunkX < 32; ++chunkX) { ++ for (int chunkZ = 0; chunkZ < 32; ++chunkZ) { ++ int location = chunkX | (chunkZ << 5); ++ ++ int oldOffset = this.getOffsets().get(location); ++ int newOffset = calculatedOffsets[location]; ++ ++ if (oldOffset == newOffset) { ++ continue; ++ } ++ ++ this.getOffsets().put(location, newOffset); // overwrite incorrect offset ++ ++ if (oldOffset == 0) { ++ // found lost data ++ LOGGER.info("Found missing data for local chunk (" + chunkX + "," + chunkZ + ") in regionfile " + this.file.getAbsolutePath()); ++ } else if (newOffset == 0) { ++ LOGGER.warn("Data for local chunk (" + chunkX + "," + chunkZ + ") could not be recovered in regionfile " + this.file.getAbsolutePath() + ", it will be regenerated"); ++ } else { ++ LOGGER.info("Local chunk (" + chunkX + "," + chunkZ + ") changed to point to newer data or correct chunk in regionfile " + this.file.getAbsolutePath()); ++ } ++ } ++ } ++ ++ LOGGER.info("End of change summary for regionfile " + this.file.getAbsolutePath()); ++ ++ // simply destroy the timestamp header, it's not used ++ ++ for (int i = 0; i < 32 * 32; ++i) { ++ this.getTimestamps().put(i, calculatedOffsets[i] != 0 ? (int)System.currentTimeMillis() : 0); // write a valid timestamp for valid chunks, I do not want to find out whatever dumb program actually checks this ++ } ++ ++ // write new header ++ try { ++ this.flushHeader(); ++ this.dataFile.force(true); // try to ensure it goes through... ++ LOGGER.info("Successfully wrote new header to disk for regionfile " + this.file.getAbsolutePath()); ++ } catch (IOException ex) { ++ LOGGER.fatal("Failed to write new header to disk for regionfile " + this.file.getAbsolutePath(), ex); ++ } ++ } ++ } ++ ++ final boolean canRecalcHeader; // final forces compile fail on new constructor ++ // Tuinity end ++ + public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper + + // Paper start - Cache chunk status +@@ -71,10 +407,21 @@ public class RegionFile implements AutoCloseable { + // Paper end + + public RegionFile(File file, File file1, boolean flag) throws IOException { ++ // Tuinity start - add can recalc flag + this(file.toPath(), file1.toPath(), RegionFileCompression.b, flag); + } ++ public RegionFile(File file, File file1, boolean flag, boolean canRecalcHeader) throws IOException { ++ this(file.toPath(), file1.toPath(), RegionFileCompression.b, flag, canRecalcHeader); ++ // Tuinity end - add can recalc flag ++ } + + public RegionFile(Path path, Path path1, RegionFileCompression regionfilecompression, boolean flag) throws IOException { ++ // Tuinity start - add can recalc flag ++ this(path, path1, regionfilecompression, flag, false); ++ } ++ public RegionFile(Path path, Path path1, RegionFileCompression regionfilecompression, boolean flag, boolean canRecalcHeader) throws IOException { ++ this.canRecalcHeader = canRecalcHeader; ++ // Tuinity start - add can recalc flag + this.g = ByteBuffer.allocateDirect(8192); + this.file = path.toFile(); // Paper + initOversizedState(); // Paper +@@ -103,14 +450,16 @@ public class RegionFile implements AutoCloseable { + RegionFile.LOGGER.warn("Region file {} has truncated header: {}", path, i); + } + +- long j = Files.size(path); ++ final long j = Files.size(path); final long regionFileSize = j; // Tuinity - recalculate header on header corruption + ++ boolean needsHeaderRecalc = false; // Tuinity - recalculate header on header corruption ++ boolean hasBackedUp = false; // Tuinity - recalculate header on header corruption + for (int k = 0; k < 1024; ++k) { +- int l = this.h.get(k); ++ int l = this.h.get(k); final int headerLocation = k; // Tuinity - we expect this to be the header location + + if (l != 0) { +- int i1 = b(l); +- int j1 = a(l); ++ final int i1 = b(l); final int offset = i1; // Tuinity - we expect this to be offset in file in sectors ++ int j1 = a(l); final int sectorLength; // Tuinity - diff on change, we expect this to be sector length of region - watch out for reassignments + // Spigot start + if (j1 == 255) { + // We're maxed out, so we need to read the proper length from the section +@@ -118,33 +467,105 @@ public class RegionFile implements AutoCloseable { + this.dataFile.read(realLen, i1 * 4096); + j1 = (realLen.getInt(0) + 4) / 4096 + 1; + } ++ sectorLength = j1; // Tuinity - diff on change, we expect this to be sector length of region + // Spigot end + + if (i1 < 2) { + RegionFile.LOGGER.warn("Region file {} has invalid sector at index: {}; sector {} overlaps with header", path, k, i1); +- this.h.put(k, 0); +- } else if (j1 == 0) { ++ //this.h.put(k, 0); // Tuinity - we catch this, but need it in the header for the summary change ++ } else if (j1 <= 0) { // Tuinity - <= 0, not == + RegionFile.LOGGER.warn("Region file {} has an invalid sector at index: {}; size has to be > 0", path, k); +- this.h.put(k, 0); ++ //this.h.put(k, 0); // Tuinity - we catch this, but need it in the header for the summary change + } else if ((long) i1 * 4096L > j) { + RegionFile.LOGGER.warn("Region file {} has an invalid sector at index: {}; sector {} is out of bounds", path, k, i1); +- this.h.put(k, 0); ++ //this.h.put(k, 0); // Tuinity - we catch this, but need it in the header for the summary change + } else { +- this.freeSectors.a(i1, j1); ++ //this.freeSectors.a(i1, j1); // Tuinity - move this down so we can check if it fails to allocate ++ } ++ // Tuinity start - recalculate header on header corruption ++ if (offset < 2 || sectorLength <= 0 || ((long)offset * 4096L) > regionFileSize) { ++ if (canRecalcHeader) { ++ LOGGER.error("Detected invalid header for regionfile " + this.file.getAbsolutePath() + "! Recalculating header..."); ++ needsHeaderRecalc = true; ++ break; ++ } else { ++ // location = chunkX | (chunkZ << 5); ++ LOGGER.fatal("Detected invalid header for regionfile " + this.file.getAbsolutePath() + ++ "! Cannot recalculate, removing local chunk (" + (headerLocation & 31) + "," + (headerLocation >>> 5) + ") from header"); ++ if (!hasBackedUp) { ++ hasBackedUp = true; ++ this.backupRegionFile(); ++ } ++ this.getTimestamps().put(headerLocation, 0); // be consistent, delete the timestamp too ++ this.getOffsets().put(headerLocation, 0); // delete the entry from header ++ continue; ++ } ++ } ++ boolean failedToAllocate = !this.freeSectors.tryAllocate(offset, sectorLength); ++ if (failedToAllocate) { ++ LOGGER.error("Overlapping allocation by local chunk (" + (headerLocation & 31) + "," + (headerLocation >>> 5) + ") in regionfile " + this.file.getAbsolutePath()); + } ++ if (failedToAllocate & !canRecalcHeader) { ++ // location = chunkX | (chunkZ << 5); ++ LOGGER.fatal("Detected invalid header for regionfile " + this.file.getAbsolutePath() + ++ "! Cannot recalculate, removing local chunk (" + (headerLocation & 31) + "," + (headerLocation >>> 5) + ") from header"); ++ if (!hasBackedUp) { ++ hasBackedUp = true; ++ this.backupRegionFile(); ++ } ++ this.getTimestamps().put(headerLocation, 0); // be consistent, delete the timestamp too ++ this.getOffsets().put(headerLocation, 0); // delete the entry from header ++ continue; ++ } ++ needsHeaderRecalc |= failedToAllocate; ++ // Tuinity end - recalculate header on header corruption + } + } ++ ++ // Tuinity start - recalculate header on header corruption ++ // we move the recalc here so comparison to old header is correct when logging to console ++ if (needsHeaderRecalc) { // true if header gave us overlapping allocations or had other issues ++ LOGGER.error("Recalculating regionfile " + this.file.getAbsolutePath() + ", header gave erroneous offsets & locations"); ++ this.recalculateHeader(); ++ } ++ // Tuinity end + } + + } + } + ++ private final java.nio.file.Path getOversizedChunkPath(ChunkCoordIntPair chunkcoordintpair) { return this.e(chunkcoordintpair); } // Tuinity - OBFHELPER + private Path e(ChunkCoordIntPair chunkcoordintpair) { +- String s = "c." + chunkcoordintpair.x + "." + chunkcoordintpair.z + ".mcc"; ++ String s = "c." + chunkcoordintpair.x + "." + chunkcoordintpair.z + ".mcc"; // Tuinity - diff on change + + return this.e.resolve(s); + } + ++ // Tuinity start ++ private static ChunkCoordIntPair getOversizedChunkPair(File file) { ++ String fileName = file.getName(); ++ ++ if (!fileName.startsWith("c.") || !fileName.endsWith(".mcc")) { ++ return null; ++ } ++ ++ String[] split = fileName.split("\\."); ++ ++ if (split.length != 4) { ++ return null; ++ } ++ ++ try { ++ int x = Integer.parseInt(split[1]); ++ int z = Integer.parseInt(split[2]); ++ ++ return new ChunkCoordIntPair(x, z); ++ } catch (NumberFormatException ex) { ++ return null; ++ } ++ } ++ // Tuinity end ++ + @Nullable public synchronized DataInputStream getReadStream(ChunkCoordIntPair chunkCoordIntPair) throws IOException { return a(chunkCoordIntPair);} // Paper - OBFHELPER + @Nullable + public synchronized DataInputStream a(ChunkCoordIntPair chunkcoordintpair) throws IOException { +@@ -169,6 +590,12 @@ public class RegionFile implements AutoCloseable { + ((java.nio.Buffer) bytebuffer).flip(); + if (bytebuffer.remaining() < 5) { + RegionFile.LOGGER.error("Chunk {} header is truncated: expected {} but read {}", chunkcoordintpair, l, bytebuffer.remaining()); ++ // Tuinity start - recalculate header on regionfile corruption ++ if (this.canRecalcHeader) { ++ this.recalculateHeader(); ++ return this.getReadStream(chunkcoordintpair); ++ } ++ // Tuinity end + return null; + } else { + int i1 = bytebuffer.getInt(); +@@ -176,6 +603,12 @@ public class RegionFile implements AutoCloseable { + + if (i1 == 0) { + RegionFile.LOGGER.warn("Chunk {} is allocated, but stream is missing", chunkcoordintpair); ++ // Tuinity start - recalculate header on regionfile corruption ++ if (this.canRecalcHeader) { ++ this.recalculateHeader(); ++ return this.getReadStream(chunkcoordintpair); ++ } ++ // Tuinity end - recalculate header on regionfile corruption + return null; + } else { + int j1 = i1 - 1; +@@ -183,17 +616,49 @@ public class RegionFile implements AutoCloseable { + if (a(b0)) { + if (j1 != 0) { + RegionFile.LOGGER.warn("Chunk has both internal and external streams"); ++ // Tuinity start - recalculate header on regionfile corruption ++ if (this.canRecalcHeader) { ++ this.recalculateHeader(); ++ return this.getReadStream(chunkcoordintpair); ++ } ++ // Tuinity end - recalculate header on regionfile corruption + } + +- return this.a(chunkcoordintpair, b(b0)); ++ // Tuinity start - recalculate header on regionfile corruption ++ DataInputStream ret = this.a(chunkcoordintpair, b(b0)); ++ if (ret == null && this.canRecalcHeader) { ++ this.recalculateHeader(); ++ return this.getReadStream(chunkcoordintpair); ++ } ++ return ret; ++ // Tuinity end - recalculate header on regionfile corruption + } else if (j1 > bytebuffer.remaining()) { + RegionFile.LOGGER.error("Chunk {} stream is truncated: expected {} but read {}", chunkcoordintpair, j1, bytebuffer.remaining()); ++ // Tuinity start - recalculate header on regionfile corruption ++ if (this.canRecalcHeader) { ++ this.recalculateHeader(); ++ return this.getReadStream(chunkcoordintpair); ++ } ++ // Tuinity end + return null; + } else if (j1 < 0) { + RegionFile.LOGGER.error("Declared size {} of chunk {} is negative", i1, chunkcoordintpair); ++ // Tuinity start - recalculate header on regionfile corruption ++ if (this.canRecalcHeader) { ++ this.recalculateHeader(); ++ return this.getReadStream(chunkcoordintpair); ++ } ++ // Tuinity end - recalculate header on regionfile corruption + return null; + } else { +- return this.a(chunkcoordintpair, b0, a(bytebuffer, j1)); ++ // Tuinity start - recalculate header on regionfile corruption ++ DataInputStream ret = this.a(chunkcoordintpair, b0, a(bytebuffer, j1)); ++ if (ret == null && this.canRecalcHeader) { ++ this.recalculateHeader(); ++ return this.getReadStream(chunkcoordintpair); ++ } ++ return ret; ++ // Tuinity end - recalculate header on regionfile corruption + } + } + } +@@ -353,10 +818,15 @@ public class RegionFile implements AutoCloseable { + } + + private ByteBuffer b() { ++ // Tuinity start - add compressionType param ++ return this.getOversizedChunkHolderData(this.getRegionFileCompression()); ++ } ++ private ByteBuffer getOversizedChunkHolderData(RegionFileCompression compressionType) { ++ // Tuinity end + ByteBuffer bytebuffer = ByteBuffer.allocate(5); + + bytebuffer.putInt(1); +- bytebuffer.put((byte) (this.f.a() | 128)); ++ bytebuffer.put((byte) (compressionType.compressionTypeId() | 128)); // Tuinity - replace with compressionType + ((java.nio.Buffer) bytebuffer).flip(); + return bytebuffer; + } +@@ -393,6 +863,7 @@ public class RegionFile implements AutoCloseable { + }; + } + ++ private final void flushHeader() throws IOException { this.b(); } // Tuinity - OBFHELPER + private void c() throws IOException { + ((java.nio.Buffer) this.g).position(0); + this.dataFile.write(this.g, 0L); +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileBitSet.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileBitSet.java +index c96eac4b0b519b2807153fa5a8ebf5a020a2b140..b5c8d9b17c2d5e229db5b48448709194d1fc04f8 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileBitSet.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileBitSet.java +@@ -4,18 +4,42 @@ import java.util.BitSet; + + public class RegionFileBitSet { + +- private final BitSet a = new BitSet(); ++ private final BitSet a = new BitSet(); private final BitSet getBitset() { return this.a; } // Tuinity - OBFHELPER + + public RegionFileBitSet() {} + ++ public final void allocate(int from, int length) { this.a(from, length); } // Tuinity - OBFHELPER + public void a(int i, int j) { + this.a.set(i, i + j); + } + ++ public final void free(int from, int length) { this.b(from, length); } // Tuinity - OBFHELPER + public void b(int i, int j) { + this.a.clear(i, i + j); + } + ++ // Tuinity start ++ public final void copyFrom(RegionFileBitSet other) { ++ BitSet thisBitset = this.getBitset(); ++ BitSet otherBitset = other.getBitset(); ++ ++ for (int i = 0; i < Math.max(thisBitset.size(), otherBitset.size()); ++i) { ++ thisBitset.set(i, otherBitset.get(i)); ++ } ++ } ++ ++ public final boolean tryAllocate(int from, int length) { ++ BitSet bitset = this.getBitset(); ++ int firstSet = bitset.nextSetBit(from); ++ if (firstSet > 0 && firstSet < (from + length)) { ++ return false; ++ } ++ bitset.set(from, from + length); ++ return true; ++ } ++ // Tuinity end ++ ++ public final int allocateNewSpace(final int requiredLength) { return this.a(requiredLength); } // Tuinity - OBFHELPER + public int a(int i) { + int j = 0; + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java +index ebb0d6988f87013ea5d523ab4a1b31cb669ccc43..68cdbe184cd2e490595900d988c64f2011e47495 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java +@@ -22,12 +22,43 @@ public class RegionFileCache implements AutoCloseable { // Paper - no final + public final Long2ObjectLinkedOpenHashMap cache = new Long2ObjectLinkedOpenHashMap(); + private final File b; + private final boolean c; ++ private final boolean isChunkData; // Tuinity + + RegionFileCache(File file, boolean flag) { ++ // Tuinity start - add isChunkData param ++ this(file, flag, false); ++ } ++ RegionFileCache(File file, boolean flag, boolean isChunkData) { ++ this.isChunkData = isChunkData; ++ // Tuinity end - add isChunkData param + this.b = file; + this.c = flag; + } + ++ // Tuinity start ++ public static ChunkCoordIntPair getRegionFileCoordinates(File file) { ++ String fileName = file.getName(); ++ if (!fileName.startsWith("r.") || !fileName.endsWith(".mca")) { ++ return null; ++ } ++ ++ String[] split = fileName.split("\\."); ++ ++ if (split.length != 4) { ++ return null; ++ } ++ ++ try { ++ int x = Integer.parseInt(split[1]); ++ int z = Integer.parseInt(split[2]); ++ ++ return new ChunkCoordIntPair(x << 5, z << 5); ++ } catch (NumberFormatException ex) { ++ return null; ++ } ++ } ++ // Tuinity end ++ + + // Paper start + public synchronized RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) { // Paper - synchronize for async io +@@ -61,9 +92,9 @@ public class RegionFileCache implements AutoCloseable { // Paper - no final + this.b.mkdirs(); + } + +- File file = new File(this.b, "r." + chunkcoordintpair.getRegionX() + "." + chunkcoordintpair.getRegionZ() + ".mca"); ++ File file = new File(this.b, "r." + chunkcoordintpair.getRegionX() + "." + chunkcoordintpair.getRegionZ() + ".mca"); // Tuinity - diff on change + if (existingOnly && !file.exists()) return null; // CraftBukkit +- RegionFile regionfile1 = new RegionFile(file, this.b, this.c); ++ RegionFile regionfile1 = new RegionFile(file, this.b, this.c, this.isChunkData); // Tuinity - allow for chunk regionfiles to regen header + + this.cache.putAndMoveToFirst(i, regionfile1); + // Paper start +@@ -152,6 +183,13 @@ public class RegionFileCache implements AutoCloseable { // Paper - no final + return null; + } + // CraftBukkit end ++ // Tuinity start - Add regionfile parameter ++ return this.readFromRegionFile(regionfile, chunkcoordintpair); ++ } ++ private NBTTagCompound readFromRegionFile(RegionFile regionfile, ChunkCoordIntPair chunkcoordintpair) throws IOException { ++ // We add the regionfile parameter to avoid the potential deadlock (on fileLock) if we went back to obtain a regionfile ++ // if we decide to re-read ++ // Tuinity end + try { // Paper + DataInputStream datainputstream = regionfile.a(chunkcoordintpair); + // Paper start +@@ -167,6 +205,17 @@ public class RegionFileCache implements AutoCloseable { // Paper - no final + try { + if (datainputstream != null) { + nbttagcompound = NBTCompressedStreamTools.a((DataInput) datainputstream); ++ // Tuinity start - recover from corrupt regionfile header ++ if (this.isChunkData) { ++ ChunkCoordIntPair chunkPos = ChunkRegionLoader.getChunkCoordinate(nbttagcompound); ++ if (!chunkPos.equals(chunkcoordintpair)) { ++ MinecraftServer.LOGGER.error("Attempting to read chunk data at " + chunkcoordintpair.toString() + " but got chunk data for " + chunkPos.toString() + " instead! Attempting regionfile recalculation for regionfile " + regionfile.file.getAbsolutePath()); ++ regionfile.recalculateHeader(); ++ regionfile.fileLock.lock(); // otherwise we will unlock twice and only lock once. ++ return this.readFromRegionFile(regionfile, chunkcoordintpair); ++ } ++ } ++ // Tuinity end - recover from corrupt regionfile header + return nbttagcompound; + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCompression.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCompression.java +index 78728e064479e7056b7c69e306854330691faa12..d94640f8bdc71d708efca9a95e1986872e1a00d7 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCompression.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCompression.java +@@ -13,7 +13,7 @@ import javax.annotation.Nullable; + + public class RegionFileCompression { + +- private static final Int2ObjectMap d = new Int2ObjectOpenHashMap(); ++ private static final Int2ObjectMap d = new Int2ObjectOpenHashMap(); static final Int2ObjectMap getCompressionTypes() { return RegionFileCompression.d; } // Tuinity - OBFHELPER + public static final RegionFileCompression a = a(new RegionFileCompression(1, GZIPInputStream::new, GZIPOutputStream::new)); + public static final RegionFileCompression b = a(new RegionFileCompression(2, InflaterInputStream::new, DeflaterOutputStream::new)); + public static final RegionFileCompression c = a(new RegionFileCompression(3, (inputstream) -> { +@@ -36,8 +36,8 @@ public class RegionFileCompression { + return regionfilecompression; + } + +- @Nullable +- public static RegionFileCompression a(int i) { ++ @Nullable public static RegionFileCompression getByType(int type) { return RegionFileCompression.a(type); } // Tuinity - OBFHELPER ++ @Nullable public static RegionFileCompression a(int i) { // Tuinity - OBFHELPER + return (RegionFileCompression) RegionFileCompression.d.get(i); + } + +@@ -45,6 +45,7 @@ public class RegionFileCompression { + return RegionFileCompression.d.containsKey(i); + } + ++ public final int compressionTypeId() { return this.a(); } // Tuinity - OBFHELPER + public int a() { + return this.e; + } +@@ -53,6 +54,7 @@ public class RegionFileCompression { + return (OutputStream) this.g.wrap(outputstream); + } + ++ public final InputStream wrap(InputStream inputstream) throws IOException { return this.a(inputstream); } // Tuinity - OBFHELPER + public InputStream a(InputStream inputstream) throws IOException { + return (InputStream) this.f.wrap(inputstream); + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java +index d3b9a9e4695655860c72db5f2188472681e8d37a..f70c14385c95763b5f270a6e2ce372cf047ba7bb 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java +@@ -34,8 +34,8 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab + + private static final Logger LOGGER = LogManager.getLogger(); + // Paper - nuke IOWorker +- private final Long2ObjectMap> c = new Long2ObjectOpenHashMap(); +- public final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet(); // Paper - private -> public ++ private final Long2ObjectMap> c = new Long2ObjectOpenHashMap(); protected final Long2ObjectMap> getDataBySection() { return this.c; } // Tuinity - OBFHELPER ++ public final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet(); protected final LongLinkedOpenHashSet getDirtySections() { return this.d; } // Paper - private -> public // Tuinity - OBFHELPER + private final Function> e; + private final Function f; + private final DataFixer g; +@@ -59,11 +59,46 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab + + } + +- @Nullable +- protected Optional c(long i) { ++ // Tuinity start - actually unload POI data ++ public void unloadData(long coordinate) { ++ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(coordinate); ++ this.writeDirtyData(chunkPos); ++ ++ Long2ObjectMap> data = this.getDataBySection(); ++ int before = data.size(); ++ ++ for (int section = 0; section < 16; ++section) { ++ data.remove(SectionPosition.asLong(chunkPos.x, section, chunkPos.z)); ++ } ++ ++ if (before != data.size()) { ++ this.onUnload(coordinate); ++ } ++ } ++ ++ protected void onUnload(long coordinate) {} ++ ++ public boolean isEmpty(long coordinate) { ++ Long2ObjectMap> data = this.getDataBySection(); ++ int x = net.minecraft.server.MCUtil.getCoordinateX(coordinate); ++ int z = net.minecraft.server.MCUtil.getCoordinateZ(coordinate); ++ for (int section = 0; section < 16; ++section) { ++ Optional optional = data.get(SectionPosition.asLong(x, section, z)); ++ if (optional != null && optional.orElse(null) != null) { ++ return false; ++ } ++ } ++ ++ return true; ++ } ++ // Tuinity end - actually unload POI data ++ ++ @Nullable public final Optional getIfLoaded(long value) { return this.c(value); } // Tuinity - OBFHELPER // Tuinity - OBFHELPER ++ @Nullable protected Optional c(long i) { // Tuinity - OBFHELPER + return (Optional) this.c.get(i); + } + ++ public final Optional getOrLoad(long coordinate) { return this.d(coordinate); } // Tuinity - OBFHELPER + protected Optional d(long i) { + SectionPosition sectionposition = SectionPosition.a(i); + +@@ -159,6 +194,7 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab + }); + } + } ++ if (this instanceof net.minecraft.world.entity.ai.village.poi.VillagePlace) { ((net.minecraft.world.entity.ai.village.poi.VillagePlace)this).queueUnload(chunkcoordintpair.pair(), net.minecraft.server.MinecraftServer.currentTickLong + 1); } // Tuinity - unload POI data + + } + +@@ -230,6 +266,7 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab + return dynamic.get("DataVersion").asInt(1945); + } + ++ public final void writeDirtyData(ChunkCoordIntPair chunkcoordintpair) { this.a(chunkcoordintpair); } // Tuinity - OBFHELPER + public void a(ChunkCoordIntPair chunkcoordintpair) { + if (!this.d.isEmpty()) { + for (int i = 0; i < 16; ++i) { +diff --git a/src/main/java/net/minecraft/world/level/levelgen/HeightMap.java b/src/main/java/net/minecraft/world/level/levelgen/HeightMap.java +index bcb620e9b7f47341f51af0f3bb7fbd6a348f9739..79214a93c533839d0c560a1e4f5904c62265590e 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/HeightMap.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/HeightMap.java +@@ -109,6 +109,7 @@ public class HeightMap { + } + } + ++ public final int get(int x, int z) { return this.a(x, z); } // Tuinity - OBFHELPER + public int a(int i, int j) { + return this.a(c(i, j)); + } +@@ -145,7 +146,7 @@ public class HeightMap { + private final String h; + private final HeightMap.Use i; + private final Predicate j; +- private static final Map k = (Map) SystemUtils.a((Object) Maps.newHashMap(), (hashmap) -> { ++ private static final Map k = (Map) SystemUtils.a(Maps.newHashMap(), (hashmap) -> { // Tuinity - decompile fix + HeightMap.Type[] aheightmap_type = values(); + int i = aheightmap_type.length; + +@@ -157,7 +158,7 @@ public class HeightMap { + + }); + +- private Type(String s, HeightMap.Use heightmap_use, Predicate predicate) { ++ private Type(String s, HeightMap.Use heightmap_use, Predicate predicate) { // Tuinity - decompile fix + this.h = s; + this.i = heightmap_use; + this.j = predicate; +diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java +index fc0162e7f543d230277457638f208a66537560d7..3825a3ddea21e7dd14c455daac1a6af5b0871e00 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java +@@ -30,7 +30,8 @@ public abstract class LightEngineStorage> e + protected final M f; protected final M updating; // Paper - diff on change, should be "updating" + protected final LongSet g = new LongOpenHashSet(); + protected final LongSet h = new LongOpenHashSet(); LongSet dirty = h; // Paper - OBFHELPER +- protected final Long2ObjectMap i = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap()); ++ protected final Long2ObjectOpenHashMap i_synchronized_map_real = new Long2ObjectOpenHashMap<>(); // Tuinity - store wrapped map, we need fastIterator ++ protected final Long2ObjectMap i = Long2ObjectMaps.synchronize(this.i_synchronized_map_real); // Tuinity - store wrapped map, we need fastIterator + private final LongSet n = new LongOpenHashSet(); + private final LongSet o = new LongOpenHashSet(); + private final LongSet p = new LongOpenHashSet(); +@@ -254,7 +255,7 @@ public abstract class LightEngineStorage> e + + this.p.clear(); + this.j = false; +- ObjectIterator objectiterator = this.i.long2ObjectEntrySet().iterator(); ++ ObjectIterator objectiterator = this.i_synchronized_map_real.long2ObjectEntrySet().fastIterator(); // Tuinity - use fast iterator to reduce entry creation + + Entry entry; + long j; +@@ -291,7 +292,7 @@ public abstract class LightEngineStorage> e + } + + this.n.clear(); +- objectiterator = this.i.long2ObjectEntrySet().iterator(); ++ objectiterator = this.i_synchronized_map_real.long2ObjectEntrySet().fastIterator(); // Tuinity - use fast iterator to reduce entry creation; + + while (objectiterator.hasNext()) { + entry = (Entry) objectiterator.next(); +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathType.java b/src/main/java/net/minecraft/world/level/pathfinder/PathType.java +index fd20802155097d4951cbe273f64de4809dee5c96..a07612f68f08aaaf75c3c656b6f90886b587d7ee 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/PathType.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/PathType.java +@@ -4,6 +4,8 @@ public enum PathType { + + BLOCKED(-1.0F), OPEN(0.0F), WALKABLE(0.0F), WALKABLE_DOOR(0.0F), TRAPDOOR(0.0F), FENCE(-1.0F), LAVA(-1.0F), WATER(8.0F), WATER_BORDER(8.0F), RAIL(0.0F), UNPASSABLE_RAIL(-1.0F), DANGER_FIRE(8.0F), DAMAGE_FIRE(16.0F), DANGER_CACTUS(8.0F), DAMAGE_CACTUS(-1.0F), DANGER_OTHER(8.0F), DAMAGE_OTHER(-1.0F), DOOR_OPEN(0.0F), DOOR_WOOD_CLOSED(-1.0F), DOOR_IRON_CLOSED(-1.0F), BREACH(4.0F), LEAVES(-1.0F), STICKY_HONEY(8.0F), COCOA(0.0F); + ++ PathType belowOverride; // Tuinity ++ + private final float y; + + private PathType(float f) { +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java +index a0c7d3ab747ba1a3cf07e716f3591663a8a9e14b..7b92a54cfb64fb77af99e6bf66eacbdb9e769dc1 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java +@@ -444,6 +444,12 @@ public class PathfinderNormal extends PathfinderAbstract { + if (pathtype == PathType.OPEN && j >= 1) { + PathType pathtype1 = b(iblockaccess, blockposition_mutableblockposition.d(i, j - 1, k)); + ++ // Tuinity start - reduce pathfinder branches ++ if (pathtype1.belowOverride != null) { ++ pathtype = pathtype1.belowOverride; ++ } else { ++ PathType original1 = pathtype1; ++ // Tuinity end - reduce pathfinder branches + pathtype = pathtype1 != PathType.WALKABLE && pathtype1 != PathType.OPEN && pathtype1 != PathType.WATER && pathtype1 != PathType.LAVA ? PathType.WALKABLE : PathType.OPEN; + if (pathtype1 == PathType.DAMAGE_FIRE) { + pathtype = PathType.DAMAGE_FIRE; +@@ -460,6 +466,7 @@ public class PathfinderNormal extends PathfinderAbstract { + if (pathtype1 == PathType.STICKY_HONEY) { + pathtype = PathType.STICKY_HONEY; + } ++ original1.belowOverride = pathtype; } // Tuinity - reduce pathfinder branches + } + + if (pathtype == PathType.WALKABLE) { +@@ -485,22 +492,29 @@ public class PathfinderNormal extends PathfinderAbstract { + pathtype = PathType.BLOCKED; + } else { + // Paper end +- ++ // Tuinity start - reduce pathfinder branching ++ if (iblockdata.neighbourOverridePathType == PathType.OPEN) { ++ continue; ++ } else if (iblockdata.neighbourOverridePathType != null) { ++ return iblockdata.neighbourOverridePathType; ++ } ++ // Tuinity end - reduce pathfinder branching + if (iblockdata.a(Blocks.CACTUS)) { +- return PathType.DANGER_CACTUS; ++ return iblockdata.neighbourOverridePathType = PathType.DANGER_CACTUS; // Tuinity - reduce pathfinder branching + } + + if (iblockdata.a(Blocks.SWEET_BERRY_BUSH)) { +- return PathType.DANGER_OTHER; ++ return iblockdata.neighbourOverridePathType = PathType.DANGER_OTHER; // Tuinity - reduce pathfinder branching + } + + if (a(iblockdata)) { +- return PathType.DANGER_FIRE; ++ return iblockdata.neighbourOverridePathType = PathType.DANGER_FIRE; // Tuinity - reduce pathfinder branching + } + + if (iblockdata.getFluid().a((Tag) TagsFluid.WATER)) { // Paper - remove another getType call +- return PathType.WATER_BORDER; ++ return iblockdata.neighbourOverridePathType = PathType.WATER_BORDER; // Tuinity - reduce pathfinder branching + } ++ iblockdata.neighbourOverridePathType = PathType.OPEN; // Tuinity - reduce pathfinder branching + } // Paper + } + } +@@ -513,6 +527,20 @@ public class PathfinderNormal extends PathfinderAbstract { + protected static PathType b(IBlockAccess iblockaccess, BlockPosition blockposition) { + IBlockData iblockdata = iblockaccess.getTypeIfLoaded(blockposition); // Paper + if (iblockdata == null) return PathType.BLOCKED; // Paper ++ // Tuinity start - reduce pathfinder branches ++ if (iblockdata.staticPathType != null) { ++ return iblockdata.staticPathType; ++ } ++ if (iblockdata.getShapeCache() == null) { ++ // while it might be called static, it might vary on shape! However, only a few blocks have variable shape. ++ // So we rarely enter here. ++ return getStaticTypeSlow(iblockaccess, blockposition, iblockdata); ++ } else { ++ return iblockdata.staticPathType = getStaticTypeSlow(iblockaccess, blockposition, iblockdata); ++ } ++ } ++ protected static PathType getStaticTypeSlow(IBlockAccess iblockaccess, BlockPosition blockposition, IBlockData iblockdata) { ++ // Tuinity end - reduce pathfinder branches + Block block = iblockdata.getBlock(); + Material material = iblockdata.getMaterial(); + +diff --git a/src/main/java/net/minecraft/world/level/portal/PortalTravelAgent.java b/src/main/java/net/minecraft/world/level/portal/PortalTravelAgent.java +index 77dfa7eaf178baa55041a829c9dec4851efeedfc..0de6225e11b98cc3d22c002d5f27748cde42a5a0 100644 +--- a/src/main/java/net/minecraft/world/level/portal/PortalTravelAgent.java ++++ b/src/main/java/net/minecraft/world/level/portal/PortalTravelAgent.java +@@ -39,16 +39,34 @@ public class PortalTravelAgent { + // int i = flag ? 16 : 128; + // CraftBukkit end + +- villageplace.a(this.world, blockposition, i); +- Optional optional = villageplace.b((villageplacetype) -> { +- return villageplacetype == VillagePlaceType.v; +- }, blockposition, i, VillagePlace.Occupancy.ANY).sorted(Comparator.comparingDouble((VillagePlaceRecord villageplacerecord) -> { // CraftBukkit - decompile error +- return villageplacerecord.f().j(blockposition); +- }).thenComparingInt((villageplacerecord) -> { +- return villageplacerecord.f().getY(); +- })).filter((villageplacerecord) -> { +- return this.world.getType(villageplacerecord.f()).b(BlockProperties.E); +- }).findFirst(); ++ // Tuinity start - optimise portals ++ //villageplace.a(this.world, blockposition, i); ++ Optional optional; ++ java.util.List records = new java.util.ArrayList<>(); ++ com.tuinity.tuinity.util.PoiAccess.findClosestPoiDataRecords(villageplace, ++ (VillagePlaceType villageplacetype) -> { ++ return villageplacetype == VillagePlaceType.v; // this should break this entire diff on update if it changes, so TODO check that on diff break ++ }, ++ (BlockPosition pos) -> { ++ net.minecraft.world.level.chunk.IChunkAccess lowest = this.world.getChunkAt(pos.getX() >> 4, pos.getZ() >> 4, net.minecraft.world.level.chunk.ChunkStatus.EMPTY); ++ if (!lowest.getChunkStatus().isAtLeastStatus(net.minecraft.world.level.chunk.ChunkStatus.FULL)) { ++ // why would we generate the chunk? ++ return false; ++ } ++ return lowest.getType(pos).contains(BlockProperties.E); // this should break this entire diff on update if it changes, so TODO check that on diff break ++ }, blockposition, i, Double.MAX_VALUE, VillagePlace.Occupancy.ANY, true, records); ++ // this gets us most of the way there, but we bias towards lower y values. ++ VillagePlaceRecord lowestYRecord = null; ++ for (VillagePlaceRecord record : records) { ++ if (lowestYRecord == null) { ++ lowestYRecord = record; ++ } else if (lowestYRecord.getPosition().getY() > record.getPosition().getY()) { ++ lowestYRecord = record; ++ } ++ } ++ // now we're done ++ optional = Optional.ofNullable(lowestYRecord); ++ // Tuinity end - optimise portals + + return optional.map((villageplacerecord) -> { + BlockPosition blockposition1 = villageplacerecord.f(); +diff --git a/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java b/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java +index 62513c812b497bb9d8dafe1d9c2f574059aebf15..0248ff18bf3f2dede4d0dda90df5e0eea56b7708 100644 +--- a/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java ++++ b/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java +@@ -17,6 +17,157 @@ public class AxisAlignedBB { + public final double maxY; + public final double maxZ; + ++ // Tuinity start ++ public final boolean isEmpty() { ++ return (this.maxX - this.minX) < net.minecraft.server.MCUtil.COLLISION_EPSILON && (this.maxY - this.minY) < net.minecraft.server.MCUtil.COLLISION_EPSILON && (this.maxZ - this.minZ) < net.minecraft.server.MCUtil.COLLISION_EPSILON; ++ } ++ ++ public static AxisAlignedBB getBoxForChunk(int chunkX, int chunkZ) { ++ double x = (double)(chunkX << 4); ++ double z = (double)(chunkZ << 4); ++ // use a bounding box bigger than the chunk to prevent entities from entering it on move ++ return new AxisAlignedBB(x - 3*net.minecraft.server.MCUtil.COLLISION_EPSILON, Double.NEGATIVE_INFINITY, z - 3*net.minecraft.server.MCUtil.COLLISION_EPSILON, x + (16.0 + 3*net.minecraft.server.MCUtil.COLLISION_EPSILON), Double.POSITIVE_INFINITY, z + (16.0 + 3*net.minecraft.server.MCUtil.COLLISION_EPSILON), false); ++ } ++ ++ /* ++ A couple of rules for VoxelShape collisions: ++ Two shapes only intersect if they are actually more than EPSILON units into each other. This also applies to movement ++ checks. ++ If the two shapes strictly collide, then the return value of a collide call will return a value in the opposite ++ direction of the source move. However, this value will not be greater in magnitude than EPSILON. Collision code ++ will automatically round it to 0. ++ */ ++ ++ public final boolean voxelShapeIntersect(AxisAlignedBB other) { ++ return (this.minX - other.maxX) < -net.minecraft.server.MCUtil.COLLISION_EPSILON && (this.maxX - other.minX) > net.minecraft.server.MCUtil.COLLISION_EPSILON && ++ (this.minY - other.maxY) < -net.minecraft.server.MCUtil.COLLISION_EPSILON && (this.maxY - other.minY) > net.minecraft.server.MCUtil.COLLISION_EPSILON && ++ (this.minZ - other.maxZ) < -net.minecraft.server.MCUtil.COLLISION_EPSILON && (this.maxZ - other.minZ) > net.minecraft.server.MCUtil.COLLISION_EPSILON; ++ } ++ ++ public final boolean voxelShapeIntersect(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { ++ return (this.minX - maxX) < -net.minecraft.server.MCUtil.COLLISION_EPSILON && (this.maxX - minX) > net.minecraft.server.MCUtil.COLLISION_EPSILON && ++ (this.minY - maxY) < -net.minecraft.server.MCUtil.COLLISION_EPSILON && (this.maxY - minY) > net.minecraft.server.MCUtil.COLLISION_EPSILON && ++ (this.minZ - maxZ) < -net.minecraft.server.MCUtil.COLLISION_EPSILON && (this.maxZ - minZ) > net.minecraft.server.MCUtil.COLLISION_EPSILON; ++ } ++ ++ public static boolean voxelShapeIntersect(double minX1, double minY1, double minZ1, double maxX1, double maxY1, double maxZ1, ++ double minX2, double minY2, double minZ2, double maxX2, double maxY2, double maxZ2) { ++ return (minX1 - maxX2) < -net.minecraft.server.MCUtil.COLLISION_EPSILON && (maxX1 - minX2) > net.minecraft.server.MCUtil.COLLISION_EPSILON && ++ (minY1 - maxY2) < -net.minecraft.server.MCUtil.COLLISION_EPSILON && (maxY1 - minY2) > net.minecraft.server.MCUtil.COLLISION_EPSILON && ++ (minZ1 - maxZ2) < -net.minecraft.server.MCUtil.COLLISION_EPSILON && (maxZ1 - minZ2) > net.minecraft.server.MCUtil.COLLISION_EPSILON; ++ } ++ ++ public static double collideX(AxisAlignedBB target, AxisAlignedBB source, double source_move) { ++ if (source_move == 0.0) { ++ return 0.0; ++ } ++ ++ if ((source.minY - target.maxY) < -net.minecraft.server.MCUtil.COLLISION_EPSILON && (source.maxY - target.minY) > net.minecraft.server.MCUtil.COLLISION_EPSILON && ++ (source.minZ - target.maxZ) < -net.minecraft.server.MCUtil.COLLISION_EPSILON && (source.maxZ - target.minZ) > net.minecraft.server.MCUtil.COLLISION_EPSILON) { ++ ++ if (source_move >= 0.0) { ++ double max_move = target.minX - source.maxX; // < 0.0 if no strict collision ++ if (max_move < -net.minecraft.server.MCUtil.COLLISION_EPSILON) { ++ return source_move; ++ } ++ return Math.min(max_move, source_move); ++ } else { ++ double max_move = target.maxX - source.minX; // > 0.0 if no strict collision ++ if (max_move > net.minecraft.server.MCUtil.COLLISION_EPSILON) { ++ return source_move; ++ } ++ return Math.max(max_move, source_move); ++ } ++ } ++ return source_move; ++ } ++ ++ public static double collideY(AxisAlignedBB target, AxisAlignedBB source, double source_move) { ++ if (source_move == 0.0) { ++ return 0.0; ++ } ++ ++ if ((source.minX - target.maxX) < -net.minecraft.server.MCUtil.COLLISION_EPSILON && (source.maxX - target.minX) > net.minecraft.server.MCUtil.COLLISION_EPSILON && ++ (source.minZ - target.maxZ) < -net.minecraft.server.MCUtil.COLLISION_EPSILON && (source.maxZ - target.minZ) > net.minecraft.server.MCUtil.COLLISION_EPSILON) { ++ if (source_move >= 0.0) { ++ double max_move = target.minY - source.maxY; // < 0.0 if no strict collision ++ if (max_move < -net.minecraft.server.MCUtil.COLLISION_EPSILON) { ++ return source_move; ++ } ++ return Math.min(max_move, source_move); ++ } else { ++ double max_move = target.maxY - source.minY; // > 0.0 if no strict collision ++ if (max_move > net.minecraft.server.MCUtil.COLLISION_EPSILON) { ++ return source_move; ++ } ++ return Math.max(max_move, source_move); ++ } ++ } ++ return source_move; ++ } ++ ++ public static double collideZ(AxisAlignedBB target, AxisAlignedBB source, double source_move) { ++ if (source_move == 0.0) { ++ return 0.0; ++ } ++ ++ if ((source.minX - target.maxX) < -net.minecraft.server.MCUtil.COLLISION_EPSILON && (source.maxX - target.minX) > net.minecraft.server.MCUtil.COLLISION_EPSILON && ++ (source.minY - target.maxY) < -net.minecraft.server.MCUtil.COLLISION_EPSILON && (source.maxY - target.minY) > net.minecraft.server.MCUtil.COLLISION_EPSILON) { ++ if (source_move >= 0.0) { ++ double max_move = target.minZ - source.maxZ; // < 0.0 if no strict collision ++ if (max_move < -net.minecraft.server.MCUtil.COLLISION_EPSILON) { ++ return source_move; ++ } ++ return Math.min(max_move, source_move); ++ } else { ++ double max_move = target.maxZ - source.minZ; // > 0.0 if no strict collision ++ if (max_move > net.minecraft.server.MCUtil.COLLISION_EPSILON) { ++ return source_move; ++ } ++ return Math.max(max_move, source_move); ++ } ++ } ++ return source_move; ++ } ++ ++ public final AxisAlignedBB offsetX(double dx) { ++ return new AxisAlignedBB(this.minX + dx, this.minY, this.minZ, this.maxX + dx, this.maxY, this.maxZ, false); ++ } ++ ++ public final AxisAlignedBB offsetY(double dy) { ++ return new AxisAlignedBB(this.minX, this.minY + dy, this.minZ, this.maxX, this.maxY + dy, this.maxZ, false); ++ } ++ ++ public final AxisAlignedBB offsetZ(double dz) { ++ return new AxisAlignedBB(this.minX, this.minY, this.minZ + dz, this.maxX, this.maxY, this.maxZ + dz, false); ++ } ++ ++ public AxisAlignedBB(double d0, double d1, double d2, double d3, double d4, double d5, boolean dummy) { ++ this.minX = d0; ++ this.minY = d1; ++ this.minZ = d2; ++ this.maxX = d3; ++ this.maxY = d4; ++ this.maxZ = d5; ++ } ++ ++ public final AxisAlignedBB expandUpwards(double dy) { ++ return new AxisAlignedBB(this.minX, this.minY, this.minZ, this.maxX, this.maxY + dy, this.maxZ, false); ++ } ++ ++ public final AxisAlignedBB cutUpwards(final double dy) { // dy > 0.0 ++ return new AxisAlignedBB(this.minX, this.maxY, this.minZ, this.maxX, this.maxY + dy, this.maxZ, false); ++ } ++ ++ public final AxisAlignedBB cutDownwards(final double dy) { // dy < 0.0 ++ return new AxisAlignedBB(this.minX, this.minY + dy, this.minZ, this.maxX, this.minY, this.maxZ, false); ++ } ++ ++ public final AxisAlignedBB expandUpwardsAndCutBelow(double dy) { ++ return new AxisAlignedBB(this.minX, this.maxY, this.minZ, this.maxX, this.maxY + dy, this.maxZ, false); ++ } ++ // Tuinity end ++ + public AxisAlignedBB(double d0, double d1, double d2, double d3, double d4, double d5) { + this.minX = Math.min(d0, d3); + this.minY = Math.min(d1, d4); +@@ -189,6 +340,7 @@ public class AxisAlignedBB { + return new AxisAlignedBB(d0, d1, d2, d3, d4, d5); + } + ++ public final AxisAlignedBB offset(double d0, double d1, double d2) { return this.d(d0, d1, d2); } // Tuinity - OBFHELPER + public AxisAlignedBB d(double d0, double d1, double d2) { + return new AxisAlignedBB(this.minX + d0, this.minY + d1, this.minZ + d2, this.maxX + d0, this.maxY + d1, this.maxZ + d2); + } +@@ -197,6 +349,7 @@ public class AxisAlignedBB { + return new AxisAlignedBB(this.minX + (double) blockposition.getX(), this.minY + (double) blockposition.getY(), this.minZ + (double) blockposition.getZ(), this.maxX + (double) blockposition.getX(), this.maxY + (double) blockposition.getY(), this.maxZ + (double) blockposition.getZ()); + } + ++ public final AxisAlignedBB offset(Vec3D vec3d) { return this.b(vec3d); } // Tuinity - OBFHELPER + public AxisAlignedBB c(Vec3D vec3d) { + return this.d(vec3d.x, vec3d.y, vec3d.z); + } +@@ -216,6 +369,7 @@ public class AxisAlignedBB { + return this.e(vec3d.x, vec3d.y, vec3d.z); + } + ++ public final boolean contains(double d0, double d1, double d2) { return this.e(d0, d1, d2); } // Tuinity - OBFHELPER + public boolean e(double d0, double d1, double d2) { + return d0 >= this.minX && d0 < this.maxX && d1 >= this.minY && d1 < this.maxY && d2 >= this.minZ && d2 < this.maxZ; + } +diff --git a/src/main/java/net/minecraft/world/phys/Vec3D.java b/src/main/java/net/minecraft/world/phys/Vec3D.java +index b71e119eed6fa283d99dc033144c8be7b336d9c4..a19a26a88f247d359354902efeece9923f3e0e0b 100644 +--- a/src/main/java/net/minecraft/world/phys/Vec3D.java ++++ b/src/main/java/net/minecraft/world/phys/Vec3D.java +@@ -9,11 +9,17 @@ import net.minecraft.util.MathHelper; + + public class Vec3D implements IPosition { + +- public static final Vec3D ORIGIN = new Vec3D(0.0D, 0.0D, 0.0D); ++ public static final Vec3D ORIGIN = new Vec3D(0.0D, 0.0D, 0.0D); public static Vec3D getZeroVector() { return Vec3D.ORIGIN; } // Tuinity - OBFHELPER + public final double x; + public final double y; + public final double z; + ++ // Tuinity start ++ public final double magnitudeXZSquared() { ++ return (this.x * this.x) + (this.z * this.z); ++ } ++ // Tuinity end ++ + public static Vec3D a(BaseBlockPosition baseblockposition) { + return new Vec3D((double) baseblockposition.getX() + 0.5D, (double) baseblockposition.getY() + 0.5D, (double) baseblockposition.getZ() + 0.5D); + } +@@ -66,6 +72,7 @@ public class Vec3D implements IPosition { + return this.add(-d0, -d1, -d2); + } + ++ public final Vec3D add(Vec3D vec3d) { return this.e(vec3d); } // Tuinity - OBFHELPER + public Vec3D e(Vec3D vec3d) { + return this.add(vec3d.x, vec3d.y, vec3d.z); + } +@@ -114,10 +121,12 @@ public class Vec3D implements IPosition { + return new Vec3D(this.x * d0, this.y * d1, this.z * d2); + } + ++ public final double magnitude() { return this.f(); } // Tuinity - OBFHELPER + public double f() { + return (double) MathHelper.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); + } + ++ public final double magnitudeSquared() { return this.g(); } // Tuinity - OBFHELPER + public double g() { + return this.x * this.x + this.y * this.y + this.z * this.z; + } +diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java +index 887016224c16f8a38c10a98eb0e2ae6cb353a153..9567630593da7c77a0173b93c9a57ceb7887a59b 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java +@@ -16,11 +16,11 @@ import net.minecraft.world.phys.Vec3D; + + public abstract class VoxelShape { + +- protected final VoxelShapeDiscrete a; ++ protected final VoxelShapeDiscrete a; public final VoxelShapeDiscrete getShape() { return this.a; } // Tuinity - OBFHELPER + @Nullable + private VoxelShape[] b; + +- VoxelShape(VoxelShapeDiscrete voxelshapediscrete) { ++ protected VoxelShape(VoxelShapeDiscrete voxelshapediscrete) { // Tuinity + this.a = voxelshapediscrete; + } + +@@ -56,9 +56,16 @@ public abstract class VoxelShape { + + public final VoxelShape offset(double x, double y, double z) { return this.a(x, y, z); } // Paper - OBFHELPER + public VoxelShape a(double d0, double d1, double d2) { +- return (VoxelShape) (this.isEmpty() ? VoxelShapes.a() : new VoxelShapeArray(this.a, new DoubleListOffset(this.a(EnumDirection.EnumAxis.X), d0), new DoubleListOffset(this.a(EnumDirection.EnumAxis.Y), d1), new DoubleListOffset(this.a(EnumDirection.EnumAxis.Z), d2))); ++ return (VoxelShape) (this.isEmpty() ? VoxelShapes.a() : new VoxelShapeArray(this.a, new DoubleListOffset(this.a(EnumDirection.EnumAxis.X), d0), new DoubleListOffset(this.a(EnumDirection.EnumAxis.Y), d1), new DoubleListOffset(this.a(EnumDirection.EnumAxis.Z), d2))); // Tuinity - diff on change, copied into VoxelShapeArray override + } + ++ // Tuinity start - optimise multi-aabb shapes ++ public boolean intersects(final AxisAlignedBB axisalingedbb) { ++ return VoxelShapes.applyOperation(this, new com.tuinity.tuinity.voxel.AABBVoxelShape(axisalingedbb), OperatorBoolean.AND); ++ } ++ // Tuinity end - optimise multi-aabb shapes ++ ++ public final VoxelShape simplify() { return this.c(); } // Tuinity - OBFHELPER + public VoxelShape c() { + VoxelShape[] avoxelshape = new VoxelShape[]{VoxelShapes.a()}; + +@@ -78,6 +85,7 @@ public abstract class VoxelShape { + }, true); + } + ++ public final List getBoundingBoxesRepresentation() { return this.d(); } // Tuinity - OBFHELPER + public List d() { + List list = Lists.newArrayList(); + +diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeArray.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeArray.java +index 56f0b3a74f676d288d81671a4791337e169b9758..5a0f8a9f5bfb3f271ccf8293bbe9fe99dcb116a1 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeArray.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeArray.java +@@ -12,11 +12,25 @@ public final class VoxelShapeArray extends VoxelShape { + private final DoubleList c; + private final DoubleList d; + ++ // Tuinity start - optimise multi-aabb shapes ++ static final net.minecraft.world.phys.AxisAlignedBB[] EMPTY = new net.minecraft.world.phys.AxisAlignedBB[0]; ++ final net.minecraft.world.phys.AxisAlignedBB[] boundingBoxesRepresentation; ++ ++ final double offsetX; ++ final double offsetY; ++ final double offsetZ; ++ // Tuinity end - optimise multi-aabb shapes ++ + protected VoxelShapeArray(VoxelShapeDiscrete voxelshapediscrete, double[] adouble, double[] adouble1, double[] adouble2) { + this(voxelshapediscrete, (DoubleList) DoubleArrayList.wrap(Arrays.copyOf(adouble, voxelshapediscrete.b() + 1)), (DoubleList) DoubleArrayList.wrap(Arrays.copyOf(adouble1, voxelshapediscrete.c() + 1)), (DoubleList) DoubleArrayList.wrap(Arrays.copyOf(adouble2, voxelshapediscrete.d() + 1))); + } + + VoxelShapeArray(VoxelShapeDiscrete voxelshapediscrete, DoubleList doublelist, DoubleList doublelist1, DoubleList doublelist2) { ++ // Tuinity start - optimise multi-aabb shapes ++ this(voxelshapediscrete, doublelist, doublelist1, doublelist2, null, null, 0.0, 0.0, 0.0); ++ } ++ VoxelShapeArray(VoxelShapeDiscrete voxelshapediscrete, DoubleList doublelist, DoubleList doublelist1, DoubleList doublelist2, VoxelShapeArray original, net.minecraft.world.phys.AxisAlignedBB[] boundingBoxesRepresentation, double offsetX, double offsetY, double offsetZ) { ++ // Tuinity end - optimise multi-aabb shapes + super(voxelshapediscrete); + int i = voxelshapediscrete.b() + 1; + int j = voxelshapediscrete.c() + 1; +@@ -29,6 +43,18 @@ public final class VoxelShapeArray extends VoxelShape { + } else { + throw (IllegalArgumentException) SystemUtils.c((Throwable) (new IllegalArgumentException("Lengths of point arrays must be consistent with the size of the VoxelShape."))); + } ++ // Tuinity start - optimise multi-aabb shapes ++ this.boundingBoxesRepresentation = boundingBoxesRepresentation == null ? this.getBoundingBoxesRepresentation().toArray(EMPTY) : boundingBoxesRepresentation; // Tuinity - optimise multi-aabb shapes ++ if (original == null) { ++ this.offsetX = offsetX; ++ this.offsetY = offsetY; ++ this.offsetZ = offsetZ; ++ } else { ++ this.offsetX = offsetX + original.offsetX; ++ this.offsetY = offsetY + original.offsetY; ++ this.offsetZ = offsetZ + original.offsetZ; ++ } ++ // Tuinity end - optimise multi-aabb shapes + } + + @Override +@@ -44,4 +70,63 @@ public final class VoxelShapeArray extends VoxelShape { + throw new IllegalArgumentException(); + } + } ++ ++ // Tuinity start - optimise multi-aabb shapes ++ @Override ++ public VoxelShape a(double d0, double d1, double d2) { ++ if (this == VoxelShapes.getEmptyShape() || this.boundingBoxesRepresentation.length == 0) { ++ return this; ++ } ++ return new VoxelShapeArray(this.a, new DoubleListOffset(this.a(EnumDirection.EnumAxis.X), d0), new DoubleListOffset(this.a(EnumDirection.EnumAxis.Y), d1), new DoubleListOffset(this.a(EnumDirection.EnumAxis.Z), d2), this, this.boundingBoxesRepresentation, d0, d1, d2); ++ } ++ ++ @Override ++ public java.util.List d() { // getBoundingBoxesRepresentation ++ if (this.boundingBoxesRepresentation == null) { ++ return super.d(); ++ } ++ java.util.List ret = new java.util.ArrayList<>(this.boundingBoxesRepresentation.length); ++ ++ double offX = this.offsetX; ++ double offY = this.offsetY; ++ double offZ = this.offsetZ; ++ for (net.minecraft.world.phys.AxisAlignedBB boundingBox : this.boundingBoxesRepresentation) { ++ ret.add(boundingBox.offset(offX, offY, offZ)); ++ } ++ ++ return ret; ++ } ++ ++ public final net.minecraft.world.phys.AxisAlignedBB[] getBoundingBoxesRepresentationRaw() { ++ return this.boundingBoxesRepresentation; ++ } ++ ++ public final double getOffsetX() { ++ return this.offsetX; ++ } ++ ++ public final double getOffsetY() { ++ return this.offsetY; ++ } ++ ++ public final double getOffsetZ() { ++ return this.offsetZ; ++ } ++ ++ public final boolean intersects(net.minecraft.world.phys.AxisAlignedBB axisalingedbb) { ++ // this can be optimised by checking an "overall shape" first, but not needed ++ double offX = this.offsetX; ++ double offY = this.offsetY; ++ double offZ = this.offsetZ; ++ ++ for (net.minecraft.world.phys.AxisAlignedBB boundingBox : this.boundingBoxesRepresentation) { ++ if (axisalingedbb.voxelShapeIntersect(boundingBox.minX + offX, boundingBox.minY + offY, boundingBox.minZ + offZ, ++ boundingBox.maxX + offX, boundingBox.maxY + offY, boundingBox.maxZ + offZ)) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ // Tuinity end - optimise multi-aabb shapes + } +diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java +index 858d4689e618c72250447adb61e0bcc3c156f8f3..98e787e6383a39de1708428137fd7f9e057ff153 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java +@@ -27,18 +27,101 @@ public final class VoxelShapes { + + voxelshapebitset.a(0, 0, 0, true, true); + return new VoxelShapeCube(voxelshapebitset); +- }); ++ }); public static final VoxelShape getFullUnoptimisedCube() { return VoxelShapes.b; } // Tuinity - OBFHELPER + public static final VoxelShape a = create(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); +- private static final VoxelShape c = new VoxelShapeArray(new VoxelShapeBitSet(0, 0, 0), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D})); ++ private static final VoxelShape c = new VoxelShapeArray(new VoxelShapeBitSet(0, 0, 0), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D})); public static final VoxelShape getEmptyShape() { return VoxelShapes.c; } // Tuinity - OBFHELPER ++ ++ // Tuinity start - optimise voxelshapes ++ public static boolean isEmpty(VoxelShape voxelshape) { ++ // helper function for determining empty shapes fast ++ return voxelshape == getEmptyShape() || voxelshape.isEmpty(); ++ } ++ // Tuinity end - optimise voxelshapes + + public static final VoxelShape empty() {return a();} // Paper - OBFHELPER + public static VoxelShape a() { + return VoxelShapes.c; + } + ++ public static final com.tuinity.tuinity.voxel.AABBVoxelShape optimisedFullCube = new com.tuinity.tuinity.voxel.AABBVoxelShape(new AxisAlignedBB(0, 0, 0, 1.0, 1.0, 1.0)); // Tuinity - optimise voxelshape ++ ++ // Tuinity start - optimise voxelshapes ++ public static boolean addBoxesToIfIntersects(VoxelShape shape, AxisAlignedBB aabb, java.util.List list) { ++ if (shape instanceof com.tuinity.tuinity.voxel.AABBVoxelShape) { ++ com.tuinity.tuinity.voxel.AABBVoxelShape shapeCasted = (com.tuinity.tuinity.voxel.AABBVoxelShape)shape; ++ if (!shapeCasted.aabb.isEmpty() && shapeCasted.aabb.voxelShapeIntersect(aabb)) { ++ list.add(shapeCasted.aabb); ++ return true; ++ } ++ return false; ++ } else if (shape instanceof VoxelShapeArray) { ++ VoxelShapeArray shapeCasted = (VoxelShapeArray)shape; ++ // this can be optimised by checking an "overall shape" first, but not needed ++ ++ double offX = shapeCasted.offsetX; ++ double offY = shapeCasted.offsetY; ++ double offZ = shapeCasted.offsetZ; ++ ++ boolean ret = false; ++ ++ for (AxisAlignedBB boundingBox : shapeCasted.boundingBoxesRepresentation) { ++ double minX, minY, minZ, maxX, maxY, maxZ; ++ if (aabb.voxelShapeIntersect(minX = boundingBox.minX + offX, minY = boundingBox.minY + offY, minZ = boundingBox.minZ + offZ, ++ maxX = boundingBox.maxX + offX, maxY = boundingBox.maxY + offY, maxZ = boundingBox.maxZ + offZ)) { ++ AxisAlignedBB box = new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ, false); ++ if (!box.isEmpty()) { ++ list.add(box); ++ ret = true; ++ } ++ } ++ } ++ ++ return ret; ++ } else { ++ boolean ret = false; ++ ++ java.util.List boxes = shape.getBoundingBoxesRepresentation(); ++ for (int i = 0, len = boxes.size(); i < len; ++i) { ++ AxisAlignedBB box = boxes.get(i); ++ if (!box.isEmpty() && box.voxelShapeIntersect(aabb)) { ++ list.add(box); ++ ret = true; ++ } ++ } ++ ++ return ret; ++ } ++ } ++ ++ public static void addBoxesTo(VoxelShape shape, java.util.List list) { ++ if (shape instanceof com.tuinity.tuinity.voxel.AABBVoxelShape) { ++ com.tuinity.tuinity.voxel.AABBVoxelShape shapeCasted = (com.tuinity.tuinity.voxel.AABBVoxelShape)shape; ++ if (!shapeCasted.isEmpty()) { ++ list.add(shapeCasted.aabb); ++ } ++ } else if (shape instanceof VoxelShapeArray) { ++ VoxelShapeArray shapeCasted = (VoxelShapeArray)shape; ++ ++ for (AxisAlignedBB boundingBox : shapeCasted.boundingBoxesRepresentation) { ++ if (!boundingBox.isEmpty()) { ++ list.add(boundingBox.offset(shapeCasted.offsetX, shapeCasted.offsetY, shapeCasted.offsetZ)); ++ } ++ } ++ } else { ++ java.util.List boxes = shape.getBoundingBoxesRepresentation(); ++ for (int i = 0, len = boxes.size(); i < len; ++i) { ++ AxisAlignedBB box = boxes.get(i); ++ if (!box.isEmpty()) { ++ list.add(box); ++ } ++ } ++ } ++ } ++ // Tuinity end - optimise voxelshapes ++ + public static final VoxelShape fullCube() {return b();} // Paper - OBFHELPER + public static VoxelShape b() { +- return VoxelShapes.b; ++ return VoxelShapes.optimisedFullCube; // Tuinity - optimise voxelshape + } + + public static VoxelShape create(double d0, double d1, double d2, double d3, double d4, double d5) { +@@ -77,7 +160,7 @@ public final class VoxelShapes { + return new VoxelShapeCube(voxelshapebitset); + } + } else { +- return new VoxelShapeArray(VoxelShapes.b.a, new double[]{axisalignedbb.minX, axisalignedbb.maxX}, new double[]{axisalignedbb.minY, axisalignedbb.maxY}, new double[]{axisalignedbb.minZ, axisalignedbb.maxZ}); ++ return new com.tuinity.tuinity.voxel.AABBVoxelShape(axisalignedbb); // Tuinity - optimise VoxelShapes for single AABB shapes + } + } + +@@ -142,6 +225,20 @@ public final class VoxelShapes { + + public static final boolean applyOperation(VoxelShape voxelshape, VoxelShape voxelshape1, OperatorBoolean operatorboolean) { return VoxelShapes.c(voxelshape, voxelshape1, operatorboolean); } // Paper - OBFHELPER + public static boolean c(VoxelShape voxelshape, VoxelShape voxelshape1, OperatorBoolean operatorboolean) { ++ // Tuinity start - optimise voxelshape ++ if (operatorboolean == OperatorBoolean.AND) { ++ if (voxelshape instanceof com.tuinity.tuinity.voxel.AABBVoxelShape && voxelshape1 instanceof com.tuinity.tuinity.voxel.AABBVoxelShape) { ++ return ((com.tuinity.tuinity.voxel.AABBVoxelShape)voxelshape).aabb.voxelShapeIntersect(((com.tuinity.tuinity.voxel.AABBVoxelShape)voxelshape1).aabb); ++ } else if (voxelshape instanceof com.tuinity.tuinity.voxel.AABBVoxelShape && voxelshape1 instanceof VoxelShapeArray) { ++ return ((VoxelShapeArray)voxelshape1).intersects(((com.tuinity.tuinity.voxel.AABBVoxelShape)voxelshape).aabb); ++ } else if (voxelshape1 instanceof com.tuinity.tuinity.voxel.AABBVoxelShape && voxelshape instanceof VoxelShapeArray) { ++ return ((VoxelShapeArray)voxelshape).intersects(((com.tuinity.tuinity.voxel.AABBVoxelShape)voxelshape1).aabb); ++ } ++ } ++ return abstract_c(voxelshape, voxelshape1, operatorboolean); ++ } ++ public static boolean abstract_c(VoxelShape voxelshape, VoxelShape voxelshape1, OperatorBoolean operatorboolean) { ++ // Tuinity end - optimise voxelshape + if (operatorboolean.apply(false, false)) { + throw (IllegalArgumentException) SystemUtils.c((Throwable) (new IllegalArgumentException())); + } else if (voxelshape == voxelshape1) { +@@ -324,8 +421,52 @@ public final class VoxelShapes { + } + } + ++ public static boolean combinationOccludes(VoxelShape voxelshape, VoxelShape voxelshape1) { return b(voxelshape, voxelshape1); } // Tuinity - OBFHELPER + public static boolean b(VoxelShape voxelshape, VoxelShape voxelshape1) { +- return voxelshape != b() && voxelshape1 != b() ? (voxelshape.isEmpty() && voxelshape1.isEmpty() ? false : !c(b(), b(voxelshape, voxelshape1, OperatorBoolean.OR), OperatorBoolean.ONLY_FIRST)) : true; ++ if (voxelshape == getFullUnoptimisedCube() || voxelshape == optimisedFullCube ++ || voxelshape1 == getFullUnoptimisedCube() || voxelshape1 == optimisedFullCube) { ++ return true; ++ } ++ boolean v1Empty = voxelshape == getEmptyShape(); ++ boolean v2Empty = voxelshape1 == getEmptyShape(); ++ if (v1Empty && v2Empty) { ++ return false; ++ } ++ if ((voxelshape instanceof com.tuinity.tuinity.voxel.AABBVoxelShape || v1Empty) && (voxelshape1 instanceof com.tuinity.tuinity.voxel.AABBVoxelShape || v2Empty)) { ++ if (!v1Empty && !v2Empty && (voxelshape != voxelshape1)) { ++ AxisAlignedBB boundingBox1 = ((com.tuinity.tuinity.voxel.AABBVoxelShape)voxelshape).aabb; ++ AxisAlignedBB boundingBox2 = ((com.tuinity.tuinity.voxel.AABBVoxelShape)voxelshape1).aabb; ++ // can call it here in some cases ++ ++ // check overall bounding box ++ double minY = Math.min(boundingBox1.minY, boundingBox2.minY); ++ double maxY = Math.max(boundingBox1.maxY, boundingBox2.maxY); ++ if (minY > net.minecraft.server.MCUtil.COLLISION_EPSILON || maxY < (1 - net.minecraft.server.MCUtil.COLLISION_EPSILON)) { ++ return false; ++ } ++ double minX = Math.min(boundingBox1.minX, boundingBox2.minX); ++ double maxX = Math.max(boundingBox1.maxX, boundingBox2.maxX); ++ if (minX > net.minecraft.server.MCUtil.COLLISION_EPSILON || maxX < (1 - net.minecraft.server.MCUtil.COLLISION_EPSILON)) { ++ return false; ++ } ++ double minZ = Math.min(boundingBox1.minZ, boundingBox2.minZ); ++ double maxZ = Math.max(boundingBox1.maxZ, boundingBox2.maxZ); ++ if (minZ > net.minecraft.server.MCUtil.COLLISION_EPSILON || maxZ < (1 - net.minecraft.server.MCUtil.COLLISION_EPSILON)) { ++ return false; ++ } ++ // fall through to full merge check ++ } else { ++ AxisAlignedBB boundingBox = v1Empty ? ((com.tuinity.tuinity.voxel.AABBVoxelShape)voxelshape1).aabb : ((com.tuinity.tuinity.voxel.AABBVoxelShape)voxelshape).aabb; ++ // check if the bounding box encloses the full cube ++ return (boundingBox.minY <= net.minecraft.server.MCUtil.COLLISION_EPSILON && boundingBox.maxY >= (1 - net.minecraft.server.MCUtil.COLLISION_EPSILON)) && ++ (boundingBox.minX <= net.minecraft.server.MCUtil.COLLISION_EPSILON && boundingBox.maxX >= (1 - net.minecraft.server.MCUtil.COLLISION_EPSILON)) && ++ (boundingBox.minZ <= net.minecraft.server.MCUtil.COLLISION_EPSILON && boundingBox.maxZ >= (1 - net.minecraft.server.MCUtil.COLLISION_EPSILON)); ++ } ++ } ++ return b_rare(voxelshape, voxelshape1); ++ } ++ public static boolean b_rare(VoxelShape voxelshape, VoxelShape voxelshape1) { ++ return (voxelshape != b() || voxelshape != getFullUnoptimisedCube()) && (voxelshape1 != b() || voxelshape1 != getFullUnoptimisedCube()) ? ((voxelshape == VoxelShapes.getEmptyShape() || voxelshape.isEmpty()) && (voxelshape1 == VoxelShapes.getEmptyShape() || voxelshape1.isEmpty()) ? false : !c(b(), b(voxelshape, voxelshape1, OperatorBoolean.OR), OperatorBoolean.ONLY_FIRST)) : true; // Tuinity - optimise call by checking against more constant shapes + } + + @VisibleForTesting diff --git a/src/main/java/org/bukkit/craftbukkit/CraftCrashReport.java b/src/main/java/org/bukkit/craftbukkit/CraftCrashReport.java -index 7511e38130f38703164395a670f12d1af648ff04..e602efcb3fad390bb6bff1055e782bba909d7694 100644 +index e50731723d266ba65b2163df2e935afb8b013a93..a6736d15282715d920bab85eb92074cd2b4f57d6 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftCrashReport.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftCrashReport.java @@ -37,7 +37,7 @@ public class CraftCrashReport implements CrashReportCallable { @@ -19982,12 +20731,12 @@ index 7511e38130f38703164395a670f12d1af648ff04..e602efcb3fad390bb6bff1055e782bba for (World world : Bukkit.getWorlds()) { value.append(' ').append(world.getName()).append(": {"); - for (Map.Entry> entry : world.getPluginChunkTickets().entrySet()) { -+ for (Map.Entry> entry : ((CraftWorld)world).getPluginChunkTicketsCoordinates().entrySet()) { // Tuinity - do not load chunks in crash reports ++ for (Map.Entry> entry : ((CraftWorld)world).getPluginChunkTicketsCoordinates().entrySet()) { // Tuinity - do not load chunks in crash reports value.append(' ').append(entry.getKey().getDescription().getFullName()).append(": ").append(Integer.toString(entry.getValue().size())).append(','); } value.append("},"); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 1398b18409db3b3741ce199ee7156a2dfe2cc96c..f994e99ebc8fe22e6f6b45f6379ec410a598789f 100644 +index 03b8d67a5f0088c0254b2099f27e8dcae32a6221..fd3333fef4112e6469ccd316ba2c82926c04e5db 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -232,7 +232,7 @@ import javax.annotation.Nullable; // Paper @@ -20043,7 +20792,7 @@ index 1398b18409db3b3741ce199ee7156a2dfe2cc96c..f994e99ebc8fe22e6f6b45f6379ec410 public void restart() { org.spigotmc.RestartCommand.restart(); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index cade3ed6079011f44eba613dece3d69ec18f8f04..902aaee6a53dbb4dccd7a34b3d6283769604d309 100644 +index 16567619d7ca84a997ef46417d72f92e6db6993d..292bd2187eb08fe535a8c1f8047be2bb29f55c53 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -342,6 +342,14 @@ public class CraftWorld implements World { @@ -20066,7 +20815,7 @@ index cade3ed6079011f44eba613dece3d69ec18f8f04..902aaee6a53dbb4dccd7a34b3d628376 @Override public Chunk getChunkAt(int x, int z) { - // Paper start - add ticket to hold chunk for a little while longer if plugin accesses it -- net.minecraft.server.Chunk chunk = world.getChunkProvider().getChunkAtIfLoadedImmediately(x, z); +- net.minecraft.world.level.chunk.Chunk chunk = world.getChunkProvider().getChunkAtIfLoadedImmediately(x, z); - if (chunk == null) { - addTicket(x, z); - chunk = this.world.getChunkProvider().getChunkAt(x, z, true); @@ -20119,13 +20868,21 @@ index cade3ed6079011f44eba613dece3d69ec18f8f04..902aaee6a53dbb4dccd7a34b3d628376 @@ -2581,7 +2607,7 @@ public class CraftWorld implements World { } return this.world.getChunkProvider().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { - net.minecraft.server.Chunk chunk = (net.minecraft.server.Chunk) either.left().orElse(null); + net.minecraft.world.level.chunk.Chunk chunk = (net.minecraft.world.level.chunk.Chunk) either.left().orElse(null); - if (chunk != null) addTicket(x, z); // Paper + if (false && chunk != null) addTicket(x, z); // Paper // Tuinity - revert return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); - }, MinecraftServer.getServer()); + }, net.minecraft.server.MinecraftServer.getServer()); + } +@@ -2606,14 +2632,14 @@ public class CraftWorld implements World { + throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); + } + PlayerChunkMap chunkMap = getHandle().getChunkProvider().playerChunkMap; +- if (viewDistance != chunkMap.getEffectiveViewDistance()) { ++ if (true) { // Tuinity - replace old player chunk management + chunkMap.setViewDistance(viewDistance); + } } -@@ -2613,7 +2639,7 @@ public class CraftWorld implements World { @Override public int getNoTickViewDistance() { @@ -20137,7 +20894,7 @@ index cade3ed6079011f44eba613dece3d69ec18f8f04..902aaee6a53dbb4dccd7a34b3d628376 @@ -2622,11 +2648,22 @@ public class CraftWorld implements World { throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); } - net.minecraft.server.PlayerChunkMap chunkMap = getHandle().getChunkProvider().playerChunkMap; + PlayerChunkMap chunkMap = getHandle().getChunkProvider().playerChunkMap; - if (viewDistance != chunkMap.getRawNoTickViewDistance()) { + if (true) { // Tuinity - replace old player chunk management chunkMap.setNoTickViewDistance(viewDistance); @@ -20159,10 +20916,10 @@ index cade3ed6079011f44eba613dece3d69ec18f8f04..902aaee6a53dbb4dccd7a34b3d628376 // Spigot start private final org.bukkit.World.Spigot spigot = new org.bukkit.World.Spigot() diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 22bde395939f97086e411cef190bb2b1e7ede79a..0f6cb508a170360b6479f9c34048412453fbb89d 100644 +index 23389d0a0e7bd8aeb2f1ab0ea6a149ef99e800fb..2774abda3dd1390ae904bf2b177bdd0f11968f40 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -138,6 +138,13 @@ public class Main { +@@ -140,6 +140,13 @@ public class Main { .defaultsTo(new File("paper.yml")) .describedAs("Yml file"); // Paper end @@ -20176,7 +20933,7 @@ index 22bde395939f97086e411cef190bb2b1e7ede79a..0f6cb508a170360b6479f9c340484124 // Paper start acceptsAll(asList("server-name"), "Name of the server") -@@ -252,7 +259,7 @@ public class Main { +@@ -254,7 +261,7 @@ public class Main { if (buildDate.before(deadline.getTime())) { // Paper start - This is some stupid bullshit System.err.println("*** Warning, you've not updated in a while! ***"); @@ -20186,42 +20943,26 @@ index 22bde395939f97086e411cef190bb2b1e7ede79a..0f6cb508a170360b6479f9c340484124 //Thread.sleep(TimeUnit.SECONDS.toMillis(20)); // Paper End diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 2fc101869775711533a1e50f9ae608cd74d36d3a..2af3bee540ee25ea32a7548fd0d64dea16a0a268 100644 +index 295ffab08672d77d88aca368cb5b56f80bc4f1b5..dee4d12a49468d38f077784b219199f0070786f2 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -509,27 +509,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -512,27 +512,36 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { entity.setHeadRotation(yaw); } - @Override// Paper start - public java.util.concurrent.CompletableFuture teleportAsync(Location loc, @javax.annotation.Nonnull org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { -- net.minecraft.server.PlayerChunkMap playerChunkMap = ((CraftWorld) loc.getWorld()).getHandle().getChunkProvider().playerChunkMap; +- PlayerChunkMap playerChunkMap = ((CraftWorld) loc.getWorld()).getHandle().getChunkProvider().playerChunkMap; - java.util.concurrent.CompletableFuture future = new java.util.concurrent.CompletableFuture<>(); - - loc.getWorld().getChunkAtAsyncUrgently(loc).thenCompose(chunk -> { -- net.minecraft.server.ChunkCoordIntPair pair = new net.minecraft.server.ChunkCoordIntPair(chunk.getX(), chunk.getZ()); -- ((CraftWorld) loc.getWorld()).getHandle().getChunkProvider().addTicketAtLevel(net.minecraft.server.TicketType.POST_TELEPORT, pair, 31, 0); -- net.minecraft.server.PlayerChunk updatingChunk = playerChunkMap.getUpdatingChunk(pair.pair()); +- ChunkCoordIntPair pair = new ChunkCoordIntPair(chunk.getX(), chunk.getZ()); +- ((CraftWorld) loc.getWorld()).getHandle().getChunkProvider().addTicketAtLevel(TicketType.POST_TELEPORT, pair, 31, 0); +- PlayerChunk updatingChunk = playerChunkMap.getUpdatingChunk(pair.pair()); - if (updatingChunk != null) { - return updatingChunk.getEntityTickingFuture(); - } else { - return java.util.concurrent.CompletableFuture.completedFuture(com.mojang.datafixers.util.Either.left(((org.bukkit.craftbukkit.CraftChunk)chunk).getHandle())); -- } -- }).thenAccept((chunk) -> future.complete(teleport(loc, cause))).exceptionally(ex -> { -- future.completeExceptionally(ex); -- return null; -- }); -- return future; -- } -- // Paper end -+ // Tuinity - - @Override - public boolean teleport(Location location) { -@@ -563,6 +543,37 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - return true; - } - + // Tuinity start - implement teleportAsync better + @Override + public java.util.concurrent.CompletableFuture teleportAsync(Location location, TeleportCause cause) { @@ -20229,14 +20970,17 @@ index 2fc101869775711533a1e50f9ae608cd74d36d3a..2af3bee540ee25ea32a7548fd0d64dea + location.checkFinite(); + Location locationClone = location.clone(); // clone so we don't need to worry about mutations after this call. + -+ net.minecraft.server.WorldServer world = ((CraftWorld)locationClone.getWorld()).getHandle(); ++ net.minecraft.server.level.WorldServer world = ((CraftWorld)locationClone.getWorld()).getHandle(); + java.util.concurrent.CompletableFuture ret = new java.util.concurrent.CompletableFuture<>(); + + world.loadChunksForMoveAsync(getHandle().getBoundingBoxAt(locationClone.getX(), locationClone.getY(), locationClone.getZ()), location.getX(), location.getZ(), (list) -> { -+ net.minecraft.server.ChunkProviderServer chunkProviderServer = world.getChunkProvider(); -+ for (net.minecraft.server.IChunkAccess chunk : list) { -+ chunkProviderServer.addTicketAtLevel(net.minecraft.server.TicketType.POST_TELEPORT, chunk.getPos(), 33, CraftEntity.this.getEntityId()); -+ } ++ net.minecraft.server.level.ChunkProviderServer chunkProviderServer = world.getChunkProvider(); ++ for (net.minecraft.world.level.chunk.IChunkAccess chunk : list) { ++ chunkProviderServer.addTicketAtLevel(net.minecraft.server.level.TicketType.POST_TELEPORT, chunk.getPos(), 33, CraftEntity.this.getEntityId()); + } +- }).thenAccept((chunk) -> future.complete(teleport(loc, cause))).exceptionally(ex -> { +- future.completeExceptionally(ex); +- return null; + net.minecraft.server.MinecraftServer.getServer().scheduleOnMain(() -> { + try { + ret.complete(CraftEntity.this.teleport(locationClone, cause) ? Boolean.TRUE : Boolean.FALSE); @@ -20247,27 +20991,28 @@ index 2fc101869775711533a1e50f9ae608cd74d36d3a..2af3bee540ee25ea32a7548fd0d64dea + ret.completeExceptionally(throwable); + } + }); -+ }); + }); +- return future; + + return ret; -+ } + } +- // Paper end + // Tuinity end - implement teleportAsync better -+ + @Override - public boolean teleport(org.bukkit.entity.Entity destination) { - return teleport(destination.getLocation()); + public boolean teleport(Location location) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index f965b071cd2f6a70a216679e4f19956115edee4f..b3636032fd36efe2e7e546dbebdfd5c1208f9951 100644 +index e5549439b3d4d608cf37dd33b6c8c9e10dfe9328..45e786565ac988abadffda2e7ba3ff1e2880b786 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2248,15 +2248,70 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2257,15 +2257,70 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } } + // Tuinity start - implement view distances + @Override + public int getSendViewDistance() { -+ net.minecraft.server.PlayerChunkMap chunkMap = this.getHandle().getWorldServer().getChunkProvider().playerChunkMap; ++ net.minecraft.server.level.PlayerChunkMap chunkMap = this.getHandle().getWorldServer().getChunkProvider().playerChunkMap; + com.tuinity.tuinity.chunk.PlayerChunkLoader.PlayerLoaderData data = chunkMap.playerChunkManager.getData(this.getHandle()); + if (data == null) { + return chunkMap.playerChunkManager.getTargetSendDistance(); @@ -20277,7 +21022,7 @@ index f965b071cd2f6a70a216679e4f19956115edee4f..b3636032fd36efe2e7e546dbebdfd5c1 + + @Override + public void setSendViewDistance(int viewDistance) { -+ net.minecraft.server.PlayerChunkMap chunkMap = this.getHandle().getWorldServer().getChunkProvider().playerChunkMap; ++ net.minecraft.server.level.PlayerChunkMap chunkMap = this.getHandle().getWorldServer().getChunkProvider().playerChunkMap; + com.tuinity.tuinity.chunk.PlayerChunkLoader.PlayerLoaderData data = chunkMap.playerChunkManager.getData(this.getHandle()); + if (data == null) { + throw new IllegalStateException("Player is not attached to world"); @@ -20288,7 +21033,7 @@ index f965b071cd2f6a70a216679e4f19956115edee4f..b3636032fd36efe2e7e546dbebdfd5c1 + + @Override + public int getNoTickViewDistance() { -+ net.minecraft.server.PlayerChunkMap chunkMap = this.getHandle().getWorldServer().getChunkProvider().playerChunkMap; ++ net.minecraft.server.level.PlayerChunkMap chunkMap = this.getHandle().getWorldServer().getChunkProvider().playerChunkMap; + com.tuinity.tuinity.chunk.PlayerChunkLoader.PlayerLoaderData data = chunkMap.playerChunkManager.getData(this.getHandle()); + if (data == null) { + return chunkMap.playerChunkManager.getTargetNoTickViewDistance(); @@ -20298,7 +21043,7 @@ index f965b071cd2f6a70a216679e4f19956115edee4f..b3636032fd36efe2e7e546dbebdfd5c1 + + @Override + public void setNoTickViewDistance(int viewDistance) { -+ net.minecraft.server.PlayerChunkMap chunkMap = this.getHandle().getWorldServer().getChunkProvider().playerChunkMap; ++ net.minecraft.server.level.PlayerChunkMap chunkMap = this.getHandle().getWorldServer().getChunkProvider().playerChunkMap; + com.tuinity.tuinity.chunk.PlayerChunkLoader.PlayerLoaderData data = chunkMap.playerChunkManager.getData(this.getHandle()); + if (data == null) { + throw new IllegalStateException("Player is not attached to world"); @@ -20310,7 +21055,7 @@ index f965b071cd2f6a70a216679e4f19956115edee4f..b3636032fd36efe2e7e546dbebdfd5c1 @Override public int getViewDistance() { - throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO -+ net.minecraft.server.PlayerChunkMap chunkMap = this.getHandle().getWorldServer().getChunkProvider().playerChunkMap; ++ net.minecraft.server.level.PlayerChunkMap chunkMap = this.getHandle().getWorldServer().getChunkProvider().playerChunkMap; + com.tuinity.tuinity.chunk.PlayerChunkLoader.PlayerLoaderData data = chunkMap.playerChunkManager.getData(this.getHandle()); + if (data == null) { + return chunkMap.playerChunkManager.getTargetViewDistance(); @@ -20321,7 +21066,7 @@ index f965b071cd2f6a70a216679e4f19956115edee4f..b3636032fd36efe2e7e546dbebdfd5c1 @Override public void setViewDistance(int viewDistance) { - throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO -+ net.minecraft.server.PlayerChunkMap chunkMap = this.getHandle().getWorldServer().getChunkProvider().playerChunkMap; ++ net.minecraft.server.level.PlayerChunkMap chunkMap = this.getHandle().getWorldServer().getChunkProvider().playerChunkMap; + com.tuinity.tuinity.chunk.PlayerChunkLoader.PlayerLoaderData data = chunkMap.playerChunkManager.getData(this.getHandle()); + if (data == null) { + throw new IllegalStateException("Player is not attached to world"); @@ -20357,7 +21102,7 @@ index fd32d1450a6a2ede3405be7d31697cd16957f553..c38e514b004a4684026d5a89c606399a LinkedList getWorkers() { diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java -index 6fa2e271f7f01cd0bf247e2071fa33bd8c5c6cbe..3a9491e9495bec93d5556bd8c09196ea117161d5 100644 +index 9c30a79cc55c6455aa18e3798728deaacc3434ca..332e4bb8a5a426b27b1f580e7a2d77dc1a13064c 100644 --- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java +++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java @@ -113,9 +113,18 @@ public final class CraftScoreboardManager implements ScoreboardManager { @@ -20459,7 +21204,7 @@ index 9f7d2ef932ab41cef5d3d0736d20a7c7e4a2c888..51e9c54cddf4b28ba3d3d892322c4877 } } diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index ae8903ee1decd22e2ad6138f29fbc757b807e0a7..089ddda8892c3660c5dcb62d0fd56544857a2eba 100644 +index 30a665c090f419985e1d0f49df9e8d110c83943a..00c728704a1a7aa8b3a2e7679eaa0d2f604da087 100644 --- a/src/main/java/org/spigotmc/WatchdogThread.java +++ b/src/main/java/org/spigotmc/WatchdogThread.java @@ -65,6 +65,78 @@ public class WatchdogThread extends Thread @@ -20467,12 +21212,12 @@ index ae8903ee1decd22e2ad6138f29fbc757b807e0a7..089ddda8892c3660c5dcb62d0fd56544 } + // Tuinity start - log detailed tick information -+ private void dumpEntity(net.minecraft.server.Entity entity) { ++ private void dumpEntity(net.minecraft.world.entity.Entity entity) { + Logger log = Bukkit.getServer().getLogger(); + double posX, posY, posZ; -+ net.minecraft.server.Vec3D mot; ++ net.minecraft.world.phys.Vec3D mot; + double moveStartX, moveStartY, moveStartZ; -+ net.minecraft.server.Vec3D moveVec; ++ net.minecraft.world.phys.Vec3D moveVec; + synchronized (entity.posLock) { + posX = entity.locX(); + posY = entity.locY(); @@ -20486,7 +21231,7 @@ index ae8903ee1decd22e2ad6138f29fbc757b807e0a7..089ddda8892c3660c5dcb62d0fd56544 + + String entityType = entity.getMinecraftKey().toString(); + java.util.UUID entityUUID = entity.getUniqueID(); -+ net.minecraft.server.World world = entity.getWorld(); ++ net.minecraft.world.level.World world = entity.getWorld(); + + log.log(Level.SEVERE, "Ticking entity: " + entityType + ", entity class: " + entity.getClass().getName()); + log.log(Level.SEVERE, "Entity status: dead: " + entity.dead + ", valid: " + entity.valid + ", alive: " + entity.isAlive() + ", is passenger: " + entity.isPassenger()); @@ -20505,9 +21250,9 @@ index ae8903ee1decd22e2ad6138f29fbc757b807e0a7..089ddda8892c3660c5dcb62d0fd56544 + Logger log = Bukkit.getServer().getLogger(); + + // ticking entities -+ for (net.minecraft.server.Entity entity : net.minecraft.server.WorldServer.getCurrentlyTickingEntities()) { ++ for (net.minecraft.world.entity.Entity entity : net.minecraft.server.level.WorldServer.getCurrentlyTickingEntities()) { + this.dumpEntity(entity); -+ net.minecraft.server.Entity vehicle = entity.getVehicle(); ++ net.minecraft.world.entity.Entity vehicle = entity.getVehicle(); + if (vehicle != null) { + log.log(Level.SEVERE, "Detailing vehicle for above entity:"); + this.dumpEntity(vehicle); @@ -20515,16 +21260,16 @@ index ae8903ee1decd22e2ad6138f29fbc757b807e0a7..089ddda8892c3660c5dcb62d0fd56544 + } + + // packet processors -+ for (net.minecraft.server.PacketListener packetListener : net.minecraft.server.PlayerConnectionUtils.getCurrentPacketProcessors()) { -+ if (packetListener instanceof net.minecraft.server.PlayerConnection) { -+ net.minecraft.server.EntityPlayer player = ((net.minecraft.server.PlayerConnection)packetListener).player; -+ long totalPackets = net.minecraft.server.PlayerConnectionUtils.getTotalProcessedPackets(); ++ for (net.minecraft.network.PacketListener packetListener : net.minecraft.network.protocol.PlayerConnectionUtils.getCurrentPacketProcessors()) { ++ if (packetListener instanceof net.minecraft.server.network.PlayerConnection) { ++ net.minecraft.server.level.EntityPlayer player = ((net.minecraft.server.network.PlayerConnection)packetListener).player; ++ long totalPackets = net.minecraft.network.protocol.PlayerConnectionUtils.getTotalProcessedPackets(); + if (player == null) { + log.log(Level.SEVERE, "Handling packet for player connection or ticking player connection (null player): " + packetListener); + log.log(Level.SEVERE, "Total packets processed on the main thread for all players: " + totalPackets); + } else { + this.dumpEntity(player); -+ net.minecraft.server.Entity vehicle = player.getVehicle(); ++ net.minecraft.world.entity.Entity vehicle = player.getVehicle(); + if (vehicle != null) { + log.log(Level.SEVERE, "Detailing vehicle for above entity:"); + this.dumpEntity(vehicle); diff --git a/patches/server/0002-Airplane-Server-Changes.patch b/patches/server/0002-Airplane-Server-Changes.patch index b257209fb..48bae8577 100644 --- a/patches/server/0002-Airplane-Server-Changes.patch +++ b/patches/server/0002-Airplane-Server-Changes.patch @@ -3,630 +3,9 @@ From: Paul Sauve Date: Sat, 31 Oct 2020 19:21:42 -0500 Subject: [PATCH] Airplane Server Changes - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS diff --git a/pom.xml b/pom.xml -index d9b46ca2fb2ec8f76f3c781d9250fdc68ad7e363..1c8ff351df082c4afe8c722b3132e4446e9b42e7 100644 +index dad9981b1cd1ca8b27a45972188fd2b92f5146e7..fc2c3714b6c772d67e258be269aa92dda80cdb12 100644 --- a/pom.xml +++ b/pom.xml @@ -27,8 +27,8 @@ @@ -1630,14 +1009,14 @@ index 0000000000000000000000000000000000000000..ace29adb0f140d99a8d85ac824654bed +} diff --git a/src/main/java/gg/airplane/structs/TrackQueue.java b/src/main/java/gg/airplane/structs/TrackQueue.java new file mode 100644 -index 0000000000000000000000000000000000000000..e72229128285e1a48b9b461620620976ca0dc0a4 +index 0000000000000000000000000000000000000000..ae7c5430b4f5970ede602bb234b5ffcee424f6a7 --- /dev/null +++ b/src/main/java/gg/airplane/structs/TrackQueue.java @@ -0,0 +1,84 @@ +package gg.airplane.structs; + +import com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet; -+import net.minecraft.server.Chunk; ++import net.minecraft.world.level.chunk.Chunk; +import net.minecraft.server.MinecraftServer; +import org.apache.logging.log4j.Level; + @@ -1718,11 +1097,601 @@ index 0000000000000000000000000000000000000000..e72229128285e1a48b9b461620620976 + } + +} -diff --git a/src/main/java/net/minecraft/server/BehaviorBetterJob.java b/src/main/java/net/minecraft/server/BehaviorBetterJob.java -index 19f8cf4384ff7a1515ad33a5f573ea0061bab93d..e6507a9bef705e1496497ad6b58a546348a0779e 100644 ---- a/src/main/java/net/minecraft/server/BehaviorBetterJob.java -+++ b/src/main/java/net/minecraft/server/BehaviorBetterJob.java -@@ -14,11 +14,31 @@ public class BehaviorBetterJob extends Behavior { +diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java +index 8edc279e7a3fdfb7e10718f1deee34b7e3fb2f28..73ec17dea5d5668e49c9a6ad679bd3a362960c72 100644 +--- a/src/main/java/net/minecraft/core/BlockPosition.java ++++ b/src/main/java/net/minecraft/core/BlockPosition.java +@@ -438,6 +438,14 @@ public class BlockPosition extends BaseBlockPosition { + public BlockPosition b(int i, int j, int k) { + return super.b(i, j, k).immutableCopy(); + } ++ // Airplane start - version of b that doesn't copy ++ public BlockPosition addValues(int x, int y, int z) { ++ ((BaseBlockPosition)this).a += x; ++ ((BaseBlockPosition)this).b += y; ++ ((BaseBlockPosition)this).e += z; ++ return this; ++ } ++ // Airplane end + + @Override + public BlockPosition shift(EnumDirection enumdirection, int i) { +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index e757cb5c2d50cb3a4dbe50d4726db09ab845fcbb..7cbbc1b1161f26f22a7f7832395af0d4a781cb1a 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1636,7 +1636,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant // Spigot - Spigot > // CraftBukkit - cb > vanilla! ++ return "Airplane"; // Airplane // Tuinity //Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! + } + + public CrashReport b(CrashReport crashreport) { +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index d902efdb8f2d42ea4c3933f7fa76ebe135ee09db..24a46ad36613faa5f5a1a12b70f7af886e1608ae 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -215,6 +215,8 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now + // Paper end + com.tuinity.tuinity.config.TuinityConfig.init((java.io.File) options.valueOf("tuinity-settings")); // Tuinity - Server Config ++ gg.airplane.AirplaneConfig.load(); // Airplane - config ++ gg.airplane.commands.AirplaneCommands.init(); // Airplane - command + + this.setPVP(dedicatedserverproperties.pvp); + this.setAllowFlight(dedicatedserverproperties.allowFlight); +diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +index cb83f1152c52a99d25e4e80cc8bf18c6793e8b50..87c87b9767003652814c3726eece64470dbb69a8 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +@@ -1000,6 +1000,7 @@ public class ChunkProviderServer extends IChunkProvider { + } + // Paper end - optimize isOutisdeRange + this.world.getMethodProfiler().enter("pollingChunks"); ++ this.world.resetIceAndSnowTick(); // Airplane - reset ice & snow tick random + int k = this.world.getGameRules().getInt(GameRules.RANDOM_TICK_SPEED); + boolean flag2 = world.ticksPerAnimalSpawns != 0L && worlddata.getTime() % world.ticksPerAnimalSpawns == 0L; // CraftBukkit + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 59989db6dcf96a8ab5a75775bb588c31cec3418a..534c7266fe9d6f60b74a71e5e61ed248e515dffd 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -182,7 +182,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + public NetworkManager networkManager; // Paper + public final MinecraftServer server; + public final PlayerInteractManager playerInteractManager; +- public final Deque removeQueue = new ArrayDeque<>(); // Paper ++ public final Deque removeQueue = new java.util.concurrent.ConcurrentLinkedDeque<>(); // Paper // Airplane concurrent deque + private final AdvancementDataPlayer advancementDataPlayer; + private final ServerStatisticManager serverStatisticManager; + private float lastHealthScored = Float.MIN_VALUE; +diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java +index a1512ee8422fa39a95e4f19c86fe71b77af54ca0..c830b257054b7f8153aa9225c1f61f49a6ea0a84 100644 +--- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java ++++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java +@@ -75,6 +75,10 @@ public class EntityTrackerEntry { + * Requested in https://github.com/PaperMC/Paper/issues/1537 to allow intercepting packets + */ + public void sendPlayerPacket(EntityPlayer player, Packet packet) { ++ if (!gg.airplane.AirplaneConfig.entityTrackerAsyncPackets && !org.bukkit.Bukkit.isPrimaryThread()) { ++ this.b.chunkProvider.playerChunkMap.trackerEnsureMain(() -> sendPlayerPacket(player, packet)); ++ return; ++ } + player.playerConnection.sendPacket(packet); + } + +@@ -103,7 +107,7 @@ public class EntityTrackerEntry { + + public final void tick() { this.a(); } // Paper - OBFHELPER + public void a() { +- com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Tracker update"); // Tuinity ++ //com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Tracker update"); // Tuinity // Airplane - allow multithreaded + List list = this.tracker.passengers; // Paper - do not copy list + + if (!list.equals(this.p)) { +@@ -117,6 +121,8 @@ public class EntityTrackerEntry { + ItemStack itemstack = entityitemframe.getItem(); + + if (this.tickCounter % 10 == 0 && itemstack.getItem() instanceof ItemWorldMap) { // CraftBukkit - Moved this.tickCounter % 10 logic here so item frames do not enter the other blocks ++ // Airplane start - process maps on main ++ this.b.chunkProvider.playerChunkMap.trackerEnsureMain(() -> { + WorldMap worldmap = ItemWorldMap.getSavedMap(itemstack, this.b); + Iterator iterator = this.trackedPlayers.iterator(); // CraftBukkit + +@@ -130,6 +136,8 @@ public class EntityTrackerEntry { + entityplayer.playerConnection.sendPacket(packet); + } + } ++ }); ++ // Airplane end + } + + this.c(); +@@ -264,18 +272,25 @@ public class EntityTrackerEntry { + // CraftBukkit start - Create PlayerVelocity event + boolean cancelled = false; + +- if (this.tracker instanceof EntityPlayer) { ++ if (this.tracker instanceof EntityPlayer && PlayerVelocityEvent.getHandlerList().getRegisteredListeners().length > 0) { // Airplane - ensure there's listeners ++ // Airplane start - run on main thread ++ this.b.chunkProvider.playerChunkMap.trackerEnsureMain(() -> { + Player player = (Player) this.tracker.getBukkitEntity(); + org.bukkit.util.Vector velocity = player.getVelocity(); + + PlayerVelocityEvent event = new PlayerVelocityEvent(player, velocity.clone()); + this.tracker.world.getServer().getPluginManager().callEvent(event); + +- if (event.isCancelled()) { +- cancelled = true; +- } else if (!velocity.equals(event.getVelocity())) { ++ if (!event.isCancelled() && !velocity.equals(event.getVelocity())) { + player.setVelocity(event.getVelocity()); + } ++ if (!event.isCancelled()) { ++ this.broadcastIncludingSelf(new PacketPlayOutEntityVelocity(this.tracker)); // duplicate from !cancelled below ++ } ++ ++ }); ++ cancelled = true; // don't broadcast until the event has finished ++ // Airplane end + } + + if (!cancelled) { +@@ -359,7 +374,9 @@ public class EntityTrackerEntry { + if (!list.isEmpty()) { + consumer.accept(new PacketPlayOutEntityEquipment(this.tracker.getId(), list)); + } ++ this.b.chunkProvider.playerChunkMap.trackerEnsureMain(() -> { // Airplane + ((EntityLiving) this.tracker).updateEquipment(); // CraftBukkit - SPIGOT-3789: sync again immediately after sending ++ }); // Airplane + } + + // CraftBukkit start - Fix for nonsensical head yaw +@@ -437,6 +454,10 @@ public class EntityTrackerEntry { + // Paper end + + private void broadcastIncludingSelf(Packet packet) { ++ if (!gg.airplane.AirplaneConfig.entityTrackerAsyncPackets && !org.bukkit.Bukkit.isPrimaryThread()) { ++ this.b.chunkProvider.playerChunkMap.trackerEnsureMain(() -> broadcastIncludingSelf(packet)); ++ return; ++ } + this.f.accept(packet); + if (this.tracker instanceof EntityPlayer) { + ((EntityPlayer) this.tracker).playerConnection.sendPacket(packet); +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index d7eede51f1c4ebbe8e00b16efd6331c87db53bb4..c9d6ddd8874195c07b3573c6b1f61ffdcff2dddd 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -705,7 +705,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + return d2 * d2 + d3 * d3; + } + +- private static int b(ChunkCoordIntPair chunkcoordintpair, EntityPlayer entityplayer, boolean flag) { ++ // Airplane start - create copy that accepts x/z instead of allocating pair ++ private static int b(ChunkCoordIntPair chunkcoordintpair, EntityPlayer entityplayer, boolean flag) { return someDistanceCalculation(chunkcoordintpair.x, chunkcoordintpair.z, entityplayer, flag); } ++ private static int someDistanceCalculation(int x, int z, EntityPlayer entityplayer, boolean flag) { + int i; + int j; + +@@ -719,12 +721,16 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + j = MathHelper.floor(entityplayer.locZ() / 16.0D); + } + +- return a(chunkcoordintpair, i, j); ++ return someOtherDistanceCalculation(x, z, i, j); ++ // Airplane end + } + +- private static int a(ChunkCoordIntPair chunkcoordintpair, int i, int j) { +- int k = chunkcoordintpair.x - i; +- int l = chunkcoordintpair.z - j; ++ // Airplane start - create copy that accepts x/z instead of allocating pair ++ private static int a(ChunkCoordIntPair chunkcoordintpair, int i, int j) { return someOtherDistanceCalculation(chunkcoordintpair.x, chunkcoordintpair.z, i, j); } ++ private static int someOtherDistanceCalculation(int x, int z, int i, int j) { ++ int k = x - i; ++ int l = z - j; ++ // Airplane end + + return Math.max(Math.abs(k), Math.abs(l)); + } +@@ -785,6 +791,11 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + return (PlayerChunk) (this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.get(i) : ((ProtectedVisibleChunksMap)this.visibleChunks).safeGet(i)); + // Paper end + } ++ // Airplane start - since neither map can be updated during tracker tick, it's safe to allow direct retrieval here ++ private PlayerChunk trackerGetVisibleChunk(long i) { ++ return this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.get(i) : ((ProtectedVisibleChunksMap) this.visibleChunks).safeGet(i); ++ } ++ // Airplane end + + protected final IntSupplier getPrioritySupplier(long i) { return c(i); } // Paper - OBFHELPER + protected IntSupplier c(long i) { +@@ -2188,10 +2199,30 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + entity.tracker = null; // Paper - We're no longer tracked + } + ++ // Airplane start - tools to ensure main thread ++ private final java.util.concurrent.ConcurrentLinkedQueue trackerMainQueue = new java.util.concurrent.ConcurrentLinkedQueue<>(); ++ private gg.airplane.structs.TrackQueue trackQueue; ++ ++ void trackerEnsureMain(Runnable runnable) { ++ if (this.world.serverThread == Thread.currentThread()) { ++ runnable.run(); ++ } else { ++ this.trackerMainQueue.add(runnable); ++ } ++ } ++ // Airplane end ++ + // Paper start - optimised tracker + private final void processTrackQueue() { + this.world.timings.tracker1.startTiming(); + try { ++ // Airplane start - multithreaded tracker ++ if (this.trackQueue == null) this.trackQueue = new gg.airplane.structs.TrackQueue(this.world.getChunkProvider().entityTickingChunks, trackerMainQueue); ++ if (gg.airplane.AirplaneConfig.multithreadedEntityTracker) { ++ this.trackQueue.start(); ++ return; ++ } ++ // Airplane end + com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet.Iterator iterator = this.world.getChunkProvider().entityTickingChunks.iterator(); + try { + while (iterator.hasNext()) { +@@ -2457,7 +2488,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially + public class EntityTracker { + + final EntityTrackerEntry trackerEntry; // Paper - private -> package private +- private final Entity tracker; ++ public final Entity tracker; // Airplane - public for chunk + private final int trackingDistance; + private SectionPosition e; + // Paper start +@@ -2476,7 +2507,9 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially + // Paper start - use distance map to optimise tracker + com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet lastTrackerCandidates; + +- final void updatePlayers(com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newTrackerCandidates) { ++ public synchronized final void tickEntry() { this.trackerEntry.tick(); } // Airplane - move entry tick into sync block ++ ++ public synchronized final void updatePlayers(com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newTrackerCandidates) { // Airplane + com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet oldTrackerCandidates = this.lastTrackerCandidates; + this.lastTrackerCandidates = newTrackerCandidates; + +@@ -2517,7 +2550,13 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially + return this.tracker.getId(); + } + +- public void broadcast(Packet packet) { ++ public synchronized void broadcast(Packet packet) { // Airplane - synchronized for tracked player ++ // Airplane start ++ if (!gg.airplane.AirplaneConfig.entityTrackerAsyncPackets && !org.bukkit.Bukkit.isPrimaryThread()) { ++ trackerEnsureMain(() -> broadcast(packet)); ++ return; ++ } ++ // Airplane end + Iterator iterator = this.trackedPlayers.iterator(); + + while (iterator.hasNext()) { +@@ -2529,6 +2568,12 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially + } + + public void broadcastIncludingSelf(Packet packet) { ++ // Airplane start ++ if (!gg.airplane.AirplaneConfig.entityTrackerAsyncPackets && !org.bukkit.Bukkit.isPrimaryThread()) { ++ trackerEnsureMain(() -> broadcastIncludingSelf(packet)); ++ return; ++ } ++ // Airplane end + this.broadcast(packet); + if (this.tracker instanceof EntityPlayer) { + ((EntityPlayer) this.tracker).playerConnection.sendPacket(packet); +@@ -2555,8 +2600,8 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially + + } + +- public void updatePlayer(EntityPlayer entityplayer) { +- org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot ++ public synchronized void updatePlayer(EntityPlayer entityplayer) { // Airplane - sync for access to map ++ //org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot // Airplane - allow sync for tracker + if (entityplayer != this.tracker) { + // Paper start - remove allocation of Vec3D here + //Vec3D vec3d = entityplayer.getPositionVector().d(this.tracker.getPositionVector()); // MC-155077, SPIGOT-5113 +@@ -2571,11 +2616,17 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially + boolean flag1 = this.tracker.attachedToPlayer; + + if (!flag1) { ++ // Airplane start - use int/longs instead of ChunkCoordIntPair ++ /* + ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(this.tracker.chunkX, this.tracker.chunkZ); +- PlayerChunk playerchunk = PlayerChunkMap.this.getVisibleChunk(chunkcoordintpair.pair()); ++ */ ++ int x = this.tracker.chunkX, z = this.tracker.chunkZ; ++ long chunkcoordintpair = ChunkCoordIntPair.pair(x, z); ++ PlayerChunk playerchunk = PlayerChunkMap.this.trackerGetVisibleChunk(chunkcoordintpair); // Airplane + + if (playerchunk != null && playerchunk.getSendingChunk() != null && PlayerChunkMap.this.playerChunkManager.isChunkSent(entityplayer, MathHelper.floor(this.tracker.locX()) >> 4, MathHelper.floor(this.tracker.locZ()) >> 4)) { // Paper - no-tick view distance // Tuinity - don't broadcast in chunks the player hasn't received +- flag1 = PlayerChunkMap.b(chunkcoordintpair, entityplayer, false) <= PlayerChunkMap.this.viewDistance; ++ flag1 = PlayerChunkMap.someDistanceCalculation(x, z, entityplayer, false) <= PlayerChunkMap.this.viewDistance; ++ // Airplane end + } + } + +@@ -2605,8 +2656,10 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially + } + + private int b() { ++ // Airplane start ++ int i = this.trackingDistance; // move out of if statement ++ if (!this.tracker.passengers.isEmpty()) { + Collection collection = this.tracker.getAllPassengers(); +- int i = this.trackingDistance; + Iterator iterator = collection.iterator(); + + while (iterator.hasNext()) { +@@ -2618,6 +2671,8 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially + i = j; + } + } ++ } ++ // Airplane end + + return this.a(i); + } +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 46f960b9276dced41deb8f741454b6cce5a81529..9d97e2ea5c207c42f1cc9aa14bc87dc8e0a1bb1e 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -1081,11 +1081,12 @@ public class WorldServer extends World implements GeneratorAccessSeed { + // CraftBukkit end */ + + gameprofilerfiller.enter("checkDespawn"); ++ boolean entityTickingChunk = false; if (!entity.dead) entityTickingChunk = this.getChunkProvider().isInEntityTickingChunk(entity); // Airplane - check once, chunks won't unload ticking entities + if (!entity.dead) { + entity.checkDespawn(); + // Tuinity start - optimise notify() + if (entity.inChunk && entity.valid) { +- if (this.getChunkProvider().isInEntityTickingChunk(entity)) { ++ if (entityTickingChunk) { // Airplane - reuse + this.updateNavigatorsInRegion(entity); + } + } else { +@@ -1105,7 +1106,28 @@ public class WorldServer extends World implements GeneratorAccessSeed { + + gameprofilerfiller.enter("tick"); + if (!entity.dead && !(entity instanceof EntityComplexPart)) { ++ // Airplane start - inline this.a to prevent creation of lambda ++ /* + this.a(this::entityJoinedWorld, entity); ++ */ ++ boolean doMidTick = false; // usually there's a returns in the catch, so treat it like that ++ try { ++ this.entityJoinedWorld(entity, entityTickingChunk); // Airplane - reuse ++ doMidTick = true; ++ } catch (Throwable throwable) { ++ if (throwable instanceof ThreadDeath) throw throwable; // Paper ++ // Paper start - Prevent tile entity and entity crashes ++ String msg = "Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX() + "," + entity.locY() + "," + entity.locZ(); ++ System.err.println(msg); ++ throwable.printStackTrace(); ++ getServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, throwable))); ++ entity.dead = true; ++ // Paper end ++ } ++ if (doMidTick) { ++ MinecraftServer.getServer().executeMidTickTasks(); // Tuinity - execute chunk tasks mid tick ++ } ++ // Airplane end + } + + gameprofilerfiller.exit(); +@@ -1115,7 +1137,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + this.entitiesById.remove(entity.getId()); // Tuinity + this.unregisterEntity(entity); + } else if (entity.inChunk && entity.valid) { // Tuinity start - optimise notify() +- if (this.getChunkProvider().isInEntityTickingChunk(entity)) { ++ if (entityTickingChunk) { // Airplane - reuse + this.updateNavigatorsInRegion(entity); + } + } else { +@@ -1200,6 +1222,8 @@ public class WorldServer extends World implements GeneratorAccessSeed { + private final BiomeBase[] biomeBaseCache = new BiomeBase[1]; + // Tuinity end - optimise chunk ice snow ticking + ++ private int currentIceAndSnowTick = 0; protected void resetIceAndSnowTick() { this.currentIceAndSnowTick = this.randomTickRandom.nextInt(16); } // Airplane ++ + public void a(Chunk chunk, int i) { final int randomTickSpeed = i; // Paper + ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); + boolean flag = this.isRaining(); +@@ -1210,7 +1234,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + gameprofilerfiller.enter("thunder"); + final BlockPosition.MutableBlockPosition blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change + +- if (!this.paperConfig.disableThunder && flag && this.W() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder ++ if (!this.paperConfig.disableThunder && flag && chunk.shouldDoLightning(this.random) && this.W()) { // Paper - Disable thunder // Airplane - check this.W last // Airplane - replace random with shouldDoLighting + blockposition.setValues(this.a(this.a(j, 0, k, 15))); // Paper + if (this.isRainingAt(blockposition)) { + DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition); +@@ -1234,7 +1258,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + + gameprofilerfiller.exitEnter("iceandsnow"); +- if (!this.paperConfig.disableIceAndSnow && this.randomTickRandom.nextInt(16) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking ++ if (!this.paperConfig.disableIceAndSnow && (this.currentIceAndSnowTick++ & 15) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking // Airplane - optimize further random ticking + // Paper start - optimise chunk ticking + // Tuinity start - optimise chunk ice snow ticking + BiomeBase[] biomeCache = this.biomeBaseCache; +@@ -1414,7 +1438,9 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + // Tuinity end - log detailed entity tick information + +- public void entityJoinedWorld(Entity entity) { ++ // Airplane start - reuse check for in entity ticking chunk ++ public void entityJoinedWorld(Entity entity) { entityJoinedWorld(entity, this.getChunkProvider().isInEntityTickingChunk(entity)); } ++ public void entityJoinedWorld(Entity entity, boolean entityTickingChunk) { // Airplane end + // Tuinity start - log detailed entity tick information + com.tuinity.tuinity.util.TickThread.ensureTickThread("Cannot tick an entity off-main"); + try { +@@ -1422,7 +1448,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + currentlyTickingEntity.lazySet(entity); + } + // Tuinity end - log detailed entity tick information +- if (!(entity instanceof EntityHuman) && !this.getChunkProvider().a(entity)) { ++ if (!(entity instanceof EntityHuman) && !entityTickingChunk) { // Airplane - reuse + this.chunkCheck(entity); + } else { + ++TimingHistory.entityTicks; // Paper - timings +@@ -1448,9 +1474,14 @@ public class WorldServer extends World implements GeneratorAccessSeed { + ++entity.ticksLived; + GameProfilerFiller gameprofilerfiller = this.getMethodProfiler(); + ++ // Airplane start - create debug lambda once, todo do we even WANT the method profiler? ++ /* + gameprofilerfiller.a(() -> { + return IRegistry.ENTITY_TYPE.getKey(entity.getEntityType()).toString(); + }); ++ */ ++ gameprofilerfiller.a(entity.getEntityType().getEntityName); ++ // Airplane end + gameprofilerfiller.c("tickNonPassenger"); + if (isActive) { // Paper - EAR 2 + TimingHistory.activatedEntityTicks++; // Paper +diff --git a/src/main/java/net/minecraft/util/MathHelper.java b/src/main/java/net/minecraft/util/MathHelper.java +index cc566784c7dd21cc2c44e0f351347f657e57ddcf..e9e7fcf2b63febe2a7d055826fabb86bc13a5cf3 100644 +--- a/src/main/java/net/minecraft/util/MathHelper.java ++++ b/src/main/java/net/minecraft/util/MathHelper.java +@@ -240,6 +240,7 @@ public class MathHelper { + return f - (float) d(f); + } + ++ public static double getDecimals(double num) { return h(num); } // Airplane + public static double h(double d0) { + return d0 - (double) d(d0); + } +@@ -418,6 +419,7 @@ public class MathHelper { + return f1 + f * (f2 - f1); + } + ++ public static double linearInterpolation(double value1, double value2, double amount) { return d(value1, value2, amount); } // Airplane - OBFHELPER + public static double d(double d0, double d1, double d2) { + return d1 + d0 * (d2 - d1); + } +@@ -434,6 +436,7 @@ public class MathHelper { + return d0 * d0 * d0 * (d0 * (d0 * 6.0D - 15.0D) + 10.0D); + } + ++ public static int sign(double num) { return k(num); } // Airplane - OBFHELPER + public static int k(double d0) { + return d0 == 0.0D ? 0 : (d0 > 0.0D ? 1 : -1); + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index feab0ae1930b5271fe0d06a40c180317dcbc9d1d..c6b4af810fe3bda7797ab94316b2357178c9cd49 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -289,6 +289,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + public void inactiveTick() { } + // Spigot end + public boolean shouldBeRemoved; // Paper ++ // Airplane start ++ public int activatedPriority = gg.airplane.AirplaneConfig.maximumActivationPrio; // golf score ++ // Airplane end + + public float getBukkitYaw() { + return this.yaw; +diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +index aae13c2e6c2a30b69c33417932c6a4d0aefeb7f5..f4440a5c4aedb1d7d303517f86a07c856dd1309b 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java ++++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +@@ -201,10 +201,10 @@ public abstract class EntityInsentient extends EntityLiving { + @Override + public void inactiveTick() { + super.inactiveTick(); +- if (this.goalSelector.inactiveTick()) { ++ if (this.goalSelector.inactiveTick(this.activatedPriority)) { // Airplane - pass activated priroity + this.goalSelector.doTick(); + } +- if (this.targetSelector.inactiveTick()) { ++ if (this.targetSelector.inactiveTick(this.activatedPriority)) { // Airplane - pass activated priority + this.targetSelector.doTick(); + } + } +@@ -829,9 +829,11 @@ public abstract class EntityInsentient extends EntityLiving { + this.bo.a(); + this.world.getMethodProfiler().exit(); + this.world.getMethodProfiler().enter("targetSelector"); ++ if (this.targetSelector.inactiveTick(this.activatedPriority)) // Airplane - use this to alternate ticking + this.targetSelector.doTick(); + this.world.getMethodProfiler().exit(); + this.world.getMethodProfiler().enter("goalSelector"); ++ if (this.goalSelector.inactiveTick(this.activatedPriority)) // Airplane - use this to alternate ticking + this.goalSelector.doTick(); + this.world.getMethodProfiler().exit(); + this.world.getMethodProfiler().enter("navigation"); +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 561905be42428855a07a2e63aca80d5dd63b22bf..1a7866bed9cb7f0431454d3af4733de05c0cba78 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -111,6 +111,7 @@ import net.minecraft.world.phys.AxisAlignedBB; + import net.minecraft.world.phys.MovingObjectPosition; + import net.minecraft.world.phys.MovingObjectPositionEntity; + import net.minecraft.world.phys.Vec3D; ++import net.minecraft.world.phys.shapes.VoxelShapeCollision; + import net.minecraft.world.scores.ScoreboardTeam; + import org.apache.logging.log4j.Logger; + +@@ -909,11 +910,13 @@ public abstract class EntityLiving extends Entity { + } + + if (entity != null) { +- ItemStack itemstack = this.getEquipment(EnumItemSlot.HEAD); +- Item item = itemstack.getItem(); ++ // Airplane start - don't get equipment if not needed ++ //ItemStack itemstack = this.getEquipment(EnumItemSlot.HEAD); ++ //Item item = itemstack.getItem(); + EntityTypes entitytypes = entity.getEntityType(); + +- if (entitytypes == EntityTypes.SKELETON && item == Items.SKELETON_SKULL || entitytypes == EntityTypes.ZOMBIE && item == Items.ZOMBIE_HEAD || entitytypes == EntityTypes.CREEPER && item == Items.CREEPER_HEAD) { ++ if (entitytypes == EntityTypes.SKELETON && this.getEquipment(EnumItemSlot.HEAD).getItem() == Items.SKELETON_SKULL || entitytypes == EntityTypes.ZOMBIE && this.getEquipment(EnumItemSlot.HEAD).getItem() == Items.ZOMBIE_HEAD || entitytypes == EntityTypes.CREEPER && this.getEquipment(EnumItemSlot.HEAD).getItem() == Items.CREEPER_HEAD) { ++ // Airplane end + d0 *= 0.5D; + } + } +@@ -3101,7 +3104,7 @@ public abstract class EntityLiving extends Entity { + Vec3D vec3d = new Vec3D(this.locX(), this.getHeadY(), this.locZ()); + Vec3D vec3d1 = new Vec3D(entity.locX(), entity.getHeadY(), entity.locZ()); + +- return this.world.rayTrace(new RayTrace(vec3d, vec3d1, RayTrace.BlockCollisionOption.COLLIDER, RayTrace.FluidCollisionOption.NONE, this)).getType() == MovingObjectPosition.EnumMovingObjectType.MISS; ++ return this.world.rayTraceDirect(vec3d, vec3d1, VoxelShapeCollision.a(this)) == MovingObjectPosition.EnumMovingObjectType.MISS; // Airplane - use direct method + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java +index 80c229c1852199fda85c03453d64cae33e413e89..7f70dda656ff9d802200f18139d2695e58c551c7 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityTypes.java ++++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java +@@ -270,6 +270,8 @@ public class EntityTypes { + private MinecraftKey bq; + private final EntitySize br; + ++ public java.util.function.Supplier getEntityName = () -> IRegistry.ENTITY_TYPE.getKey(this).toString(); // Airplane - create lambda ones ++ + private static EntityTypes a(String s, EntityTypes.Builder entitytypes_builder) { // CraftBukkit - decompile error + return (EntityTypes) IRegistry.a((IRegistry) IRegistry.ENTITY_TYPE, s, (Object) entitytypes_builder.a(s)); + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorBetterJob.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorBetterJob.java +index 72f1031e95b375823790f8cac4c102ba1205c9e8..e4821c1a7ceac582b019102230dbe5221add9050 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorBetterJob.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorBetterJob.java +@@ -3,6 +3,7 @@ package net.minecraft.world.entity.ai.behavior; + import com.google.common.collect.ImmutableMap; + import net.minecraft.core.GlobalPos; + import net.minecraft.server.level.WorldServer; ++import net.minecraft.world.entity.EntityLiving; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + import net.minecraft.world.entity.ai.memory.MemoryStatus; + import net.minecraft.world.entity.ai.village.poi.VillagePlaceType; +@@ -21,11 +22,31 @@ public class BehaviorBetterJob extends Behavior { protected void a(WorldServer worldserver, EntityVillager entityvillager, long i) { GlobalPos globalpos = (GlobalPos) entityvillager.getBehaviorController().getMemory(MemoryModuleType.JOB_SITE).get(); @@ -1754,11 +1723,11 @@ index 19f8cf4384ff7a1515ad33a5f573ea0061bab93d..e6507a9bef705e1496497ad6b58a5463 } private static EntityVillager a(EntityVillager entityvillager, EntityVillager entityvillager1) { -diff --git a/src/main/java/net/minecraft/server/BehaviorFindPosition.java b/src/main/java/net/minecraft/server/BehaviorFindPosition.java -index 83702e07dff72b639af32c8ba9e831e58da92a10..a48f2f82517bc391d5d5b7961e3c7a75175abb65 100644 ---- a/src/main/java/net/minecraft/server/BehaviorFindPosition.java -+++ b/src/main/java/net/minecraft/server/BehaviorFindPosition.java -@@ -57,6 +57,7 @@ public class BehaviorFindPosition extends Behavior { +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFindPosition.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFindPosition.java +index bc8786e2aaeab4dbae4e9c7666ad816bc5bfac3f..09133c5822bc1386bc3d8a5f3c94196420bbfaea 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFindPosition.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFindPosition.java +@@ -67,6 +67,7 @@ public class BehaviorFindPosition extends Behavior { protected void a(WorldServer worldserver, EntityCreature entitycreature, long i) { this.f = i + 20L + (long) worldserver.getRandom().nextInt(20); @@ -1766,190 +1735,77 @@ index 83702e07dff72b639af32c8ba9e831e58da92a10..a48f2f82517bc391d5d5b7961e3c7a75 VillagePlace villageplace = worldserver.y(); this.g.long2ObjectEntrySet().removeIf((entry) -> { -diff --git a/src/main/java/net/minecraft/server/BlockDirtSnowSpreadable.java b/src/main/java/net/minecraft/server/BlockDirtSnowSpreadable.java -index 7b29d47dfdef7611db58068af285f76d92a9f12a..6c5d96853d47850b81ce85e56a516c554819ef25 100644 ---- a/src/main/java/net/minecraft/server/BlockDirtSnowSpreadable.java -+++ b/src/main/java/net/minecraft/server/BlockDirtSnowSpreadable.java -@@ -43,8 +43,14 @@ public abstract class BlockDirtSnowSpreadable extends BlockDirtSnow { - if (worldserver.getLightLevel(blockposition.up()) >= 9) { - IBlockData iblockdata1 = this.getBlockData(); +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java +index 637928664f8c7b1c694a234e507c20724294e450..f303c5d6b2e55fc9fd8b49ec21121805e7351034 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java +@@ -44,9 +44,14 @@ public class PathfinderGoalSelector { + } -+ // Airplane start - use mutable position -+ BlockPosition.MutableBlockPosition blockposition1 = new BlockPosition.MutableBlockPosition(); - for (int i = 0; i < 4; ++i) { -+ blockposition1.setValues(blockposition).addValues(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1); -+ /* - BlockPosition blockposition1 = blockposition.b(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1); -+ */ -+ // Airplane end - - if (worldserver.getType(blockposition1).a(Blocks.DIRT) && c(iblockdata1, (IWorldReader) worldserver, blockposition1)) { - org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(worldserver, blockposition, blockposition1, (IBlockData) iblockdata1.set(BlockDirtSnowSpreadable.a, worldserver.getType(blockposition1.up()).a(Blocks.SNOW))); // CraftBukkit -diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java -index 2291135eaef64c403183724cb6e413cd7e472672..72ee5fe0ca25844cbcd8f1bbbbd6a7f8ced24bc4 100644 ---- a/src/main/java/net/minecraft/server/BlockPosition.java -+++ b/src/main/java/net/minecraft/server/BlockPosition.java -@@ -432,6 +432,14 @@ public class BlockPosition extends BaseBlockPosition { - public BlockPosition b(int i, int j, int k) { - return super.b(i, j, k).immutableCopy(); - } -+ // Airplane start - version of b that doesn't copy -+ public BlockPosition addValues(int x, int y, int z) { -+ ((BaseBlockPosition)this).a += x; -+ ((BaseBlockPosition)this).b += y; -+ ((BaseBlockPosition)this).e += z; -+ return this; -+ } -+ // Airplane end - - @Override - public BlockPosition shift(EnumDirection enumdirection, int i) { -diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java -index 8e59a794f6190930cb7bb81a2fe1a1d374dacce7..6cde93d62c4c324a6544401cabe045cbb80f465e 100644 ---- a/src/main/java/net/minecraft/server/Chunk.java -+++ b/src/main/java/net/minecraft/server/Chunk.java -@@ -53,6 +53,38 @@ public class Chunk implements IChunkAccess { - private final ChunkCoordIntPair loc; public final long coordinateKey; public final int locX; public final int locZ; // Paper - cache coordinate key - private volatile boolean x; - -+ // Airplane start - instead of using a random every time the chunk is ticked, define when lightning strikes preemptively -+ private int lightningTick; -+ // shouldDoLightning compiles down to 29 bytes, which with the default of 35 byte inlining should guarantee an inline -+ public final boolean shouldDoLightning(java.util.Random random) { -+ if (this.lightningTick-- <= 0) { -+ this.lightningTick = random.nextInt(100000) << 1; + // Paper start +- public boolean inactiveTick() { +- incRate(); +- return getCurRate() % getTickRate() == 0; ++ public boolean inactiveTick(int tickRate) { // Airplane - take tick rate ++ tickRate = Math.max(tickRate, getTickRate()); // Airplane ++ if (this.curRate++ % tickRate != 0) { // Airplane - use tick rate / increment curRate every tick ++ //incRate(); ++ return false; ++ } else { + return true; + } -+ return false; -+ } -+ // Airplane end -+ -+ // Airplane start - entity tracker runnable -+ // prevents needing to allocate new lambda in processTrackQueue -+ public final Runnable entityTracker = new Runnable() { -+ @Override -+ public void run() { -+ Entity[] entities = Chunk.this.entities.getRawData(); -+ for (int i = 0, len = Chunk.this.entities.size(); i < len; ++i) { -+ Entity entity = entities[i]; -+ if (entity != null) { -+ PlayerChunkMap.EntityTracker tracker = ((WorldServer) Chunk.this.getWorld()).getChunkProvider().playerChunkMap.trackedEntities.get(entity.getId()); -+ if (tracker != null) { -+ tracker.updatePlayers(tracker.tracker.getPlayersInTrackRange()); -+ tracker.tickEntry(); -+ } -+ } -+ } -+ } -+ }; -+ // Airplane end -+ - public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage) { - this(world, chunkcoordintpair, biomestorage, ChunkConverter.a, TickListEmpty.b(), TickListEmpty.b(), 0L, (ChunkSection[]) null, (Consumer) null); } -@@ -287,6 +319,7 @@ public class Chunk implements IChunkAccess { - // CraftBukkit start - this.bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this); - this.entitySlicesManager = new com.tuinity.tuinity.world.ChunkEntitySlices(this.world, this.loc.x, this.loc.z, 0, 15); // TODO update for 1.17 // Tuinity -+ this.lightningTick = this.world.random.nextInt(100000) << 1; // Airplane - initialize lightning tick + public boolean hasTasks() { + for (PathfinderGoalWrapped task : getTasks()) { +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java +index 148bdbc2cffb002d8b6dd05e70854ab503804949..48e6a4c588ef39a4bde067d79b96a656c68750ce 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java +@@ -433,6 +433,7 @@ public abstract class NavigationAbstract { + } } - public org.bukkit.Chunk bukkitChunk; -diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java -index b55f7dece329dbb3ff27d57a39c32c69e5baea74..5897d462d350dfbd1464feb92ecf77725651c694 100644 ---- a/src/main/java/net/minecraft/server/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java -@@ -975,6 +975,7 @@ public class ChunkProviderServer extends IChunkProvider { - } - // Paper end - optimize isOutisdeRange - this.world.getMethodProfiler().enter("pollingChunks"); -+ this.world.resetIceAndSnowTick(); // Airplane - reset ice & snow tick random - int k = this.world.getGameRules().getInt(GameRules.RANDOM_TICK_SPEED); - boolean flag2 = world.ticksPerAnimalSpawns != 0L && worlddata.getTime() % world.ticksPerAnimalSpawns == 0L; // CraftBukkit - -diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -index 076d6c1e1cc049dd312ecb30518e7b25fc2d7371..68538ae94806d5980cd531e61fa52a01a5cc8997 100644 ---- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -@@ -424,6 +424,7 @@ public class ChunkRegionLoader { - public static NBTTagCompound saveChunk(WorldServer worldserver, IChunkAccess ichunkaccess) { - return saveChunk(worldserver, ichunkaccess, null); ++ public boolean isStuck() { return this.t(); } // Airplane - OBFHELPER + public boolean t() { + return this.t; } -+ private static final ThreadLocal paletteArray = ThreadLocal.withInitial(() -> new int[4096]); // Airplane - public static NBTTagCompound saveChunk(WorldServer worldserver, IChunkAccess ichunkaccess, AsyncSaveData asyncsavedata) { - // Paper end - // Tuinity start - rewrite light impl -@@ -454,6 +455,7 @@ public class ChunkRegionLoader { - - NBTTagCompound nbttagcompound2; - -+ int[] aint = paletteArray.get(); // Airplane - use cached - for (int i = -1; i < 17; ++i) { // Paper - conflict on loop parameter change - int finalI = i; // CraftBukkit - decompile errors - ChunkSection chunksection = (ChunkSection) Arrays.stream(achunksection).filter((chunksection1) -> { -@@ -474,7 +476,7 @@ public class ChunkRegionLoader { - nbttagcompound2 = new NBTTagCompound(); - nbttagcompound2.setByte("Y", (byte) (i & 255)); - if (chunksection != Chunk.a) { -- chunksection.getBlocks().a(nbttagcompound2, "Palette", "BlockStates"); -+ chunksection.getBlocks().a(nbttagcompound2, "Palette", "BlockStates", aint); // Airplane +diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java b/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java +index 88972dd8252bd2d2d8e384d616484ff682949fa8..5e8d3b84cbad299e09e8f25bfc712d11e1d1068e 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java ++++ b/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java +@@ -84,9 +84,17 @@ public class PathfinderTargetCondition { } - if (nibblearray != null && !nibblearray.c()) { -diff --git a/src/main/java/net/minecraft/server/DataPaletteBlock.java b/src/main/java/net/minecraft/server/DataPaletteBlock.java -index 73163b417af7e522a4509bf9c1ab56d6499be622..2855a2757c35afc5751a7ca6f3a12cc27c24bf96 100644 ---- a/src/main/java/net/minecraft/server/DataPaletteBlock.java -+++ b/src/main/java/net/minecraft/server/DataPaletteBlock.java -@@ -226,12 +226,16 @@ public class DataPaletteBlock implements DataPaletteExpandable { - this.b(); - } + if (this.b > 0.0D) { ++ // Airplane start - try to return early ++ double range = (useFollowRange ? getFollowRange(entityliving) : this.b); ++ double d2 = entityliving.h(entityliving1.locX(), entityliving1.locY(), entityliving1.locZ()); // move up here to use early ++ ++ if (d2 > range * range) { // if they're further than the absolute furthest allowed, they don't match ++ return false; ++ } ++ + double d0 = this.g ? entityliving1.A(entityliving) : 1.0D; +- double d1 = Math.max((useFollowRange ? getFollowRange(entityliving) : this.b) * d0, 2.0D); // Paper +- double d2 = entityliving.h(entityliving1.locX(), entityliving1.locY(), entityliving1.locZ()); ++ double d1 = Math.max(range * d0, 2.0D); // Paper // Airplane - reuse range calculated above ++ // Airplane end -+ // Airplane start - add parameter for reusing aint - public synchronized void a(NBTTagCompound nbttagcompound, String s, String s1) { // Paper - synchronize -+ a(nbttagcompound, s, s1, new int[4096]); -+ } -+ public synchronized void a(NBTTagCompound nbttagcompound, String s, String s1, int[] aint) { // Paper - synchronize // Airplane end - this.a(); - DataPaletteHash datapalettehash = new DataPaletteHash<>(this.d, this.i, this.c, this.e, this.f); - T t0 = this.g; - int i = datapalettehash.a(this.g); -- int[] aint = new int[4096]; -+ //int[] aint = new int[4096]; // Airplane - use parameter - - for (int j = 0; j < 4096; ++j) { - T t1 = this.a(j); -diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java -index 2644b190813cc934914aeab78fbd6515d1a37c4a..665d2d03676fde8d7e7d09fef3fd9cc13110d98d 100644 ---- a/src/main/java/net/minecraft/server/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/DedicatedServer.java -@@ -176,6 +176,8 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now - // Paper end - com.tuinity.tuinity.config.TuinityConfig.init((java.io.File) options.valueOf("tuinity-settings")); // Tuinity - Server Config -+ gg.airplane.AirplaneConfig.load(); // Airplane - config -+ gg.airplane.commands.AirplaneCommands.init(); // Airplane - command - - this.setPVP(dedicatedserverproperties.pvp); - this.setAllowFlight(dedicatedserverproperties.allowFlight); -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 2ec48858be8eb2c522c9685b43bd36b3b581cf8b..1d718095cf29ee70dd031b0c374e772774b8e11b 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -197,6 +197,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - public void inactiveTick() { } - // Spigot end - public boolean shouldBeRemoved; // Paper -+ // Airplane start -+ public int activatedPriority = gg.airplane.AirplaneConfig.maximumActivationPrio; // golf score -+ // Airplane end - - public float getBukkitYaw() { - return this.yaw; -diff --git a/src/main/java/net/minecraft/server/EntityBat.java b/src/main/java/net/minecraft/server/EntityBat.java -index 451ffcfd1fc9fa3091dc2bd697e5d829dcf6443f..f06ffdca027e5477332c6bc0c381264b47633f78 100644 ---- a/src/main/java/net/minecraft/server/EntityBat.java -+++ b/src/main/java/net/minecraft/server/EntityBat.java -@@ -222,13 +222,22 @@ public class EntityBat extends EntityAmbient { + if (d2 > d1 * d1) { + return false; +diff --git a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java +index 61ebb278cf4ef57ae7a86c6c6ef1fa14559f21e2..341b95f73a839a548b202e7bf97fd18760c71fd8 100644 +--- a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java ++++ b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java +@@ -10,6 +10,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.util.MathHelper; +@@ -247,13 +248,22 @@ public class EntityBat extends EntityAmbient { } } @@ -1973,11 +1829,19 @@ index 451ffcfd1fc9fa3091dc2bd697e5d829dcf6443f..f06ffdca027e5477332c6bc0c381264b @Override protected float b(EntityPose entitypose, EntitySize entitysize) { -diff --git a/src/main/java/net/minecraft/server/EntityEnderman.java b/src/main/java/net/minecraft/server/EntityEnderman.java -index f53525eb32a6096ae24fd23756b2169d5d39e9d4..a192400f0ea4517c56c473d39e4bd04396b4eb72 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderman.java -+++ b/src/main/java/net/minecraft/server/EntityEnderman.java -@@ -260,11 +260,18 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +index e993b1849beb60515c51ee4f37617faab63ca223..4d7b5d47ab6bd3b1408811c3b9c157b1eb5c30ae 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +@@ -57,6 +57,7 @@ import net.minecraft.world.level.World; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.chunk.Chunk; + import net.minecraft.world.level.pathfinder.PathType; + import net.minecraft.world.phys.AxisAlignedBB; + import net.minecraft.world.phys.MovingObjectPositionBlock; +@@ -314,11 +315,18 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { private boolean p(double d0, double d1, double d2) { BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(d0, d1, d2); @@ -1998,11 +1862,11 @@ index f53525eb32a6096ae24fd23756b2169d5d39e9d4..a192400f0ea4517c56c473d39e4bd043 boolean flag = iblockdata.getMaterial().isSolid(); boolean flag1 = iblockdata.getFluid().a((Tag) TagsFluid.WATER); -diff --git a/src/main/java/net/minecraft/server/EntityHoglin.java b/src/main/java/net/minecraft/server/EntityHoglin.java -index f6797925365836b6c2d3d2c48c746a4d58e28bf3..7bd22c81d75368697113915a97c7fbe55ed2a268 100644 ---- a/src/main/java/net/minecraft/server/EntityHoglin.java -+++ b/src/main/java/net/minecraft/server/EntityHoglin.java -@@ -13,7 +13,7 @@ public class EntityHoglin extends EntityAnimal implements IMonster, IOglin { +diff --git a/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java b/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java +index 375409f4b72edc7990da90460b30486fb2980fb6..9aa4850e021076fde306eea7eec104c31086c57f 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java ++++ b/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java +@@ -54,7 +54,7 @@ public class EntityHoglin extends EntityAnimal implements IMonster, IOglin { public int conversionTicks = 0; public boolean cannotBeHunted = false; protected static final ImmutableList>> bo = ImmutableList.of(SensorType.c, SensorType.d, SensorType.n, SensorType.m); @@ -2011,7 +1875,7 @@ index f6797925365836b6c2d3d2c48c746a4d58e28bf3..7bd22c81d75368697113915a97c7fbe5 public EntityHoglin(EntityTypes entitytypes, World world) { super(entitytypes, world); -@@ -77,15 +77,20 @@ public class EntityHoglin extends EntityAnimal implements IMonster, IOglin { +@@ -118,15 +118,20 @@ public class EntityHoglin extends EntityAnimal implements IMonster, IOglin { @Override public BehaviorController getBehaviorController() { @@ -2034,7 +1898,7 @@ index f6797925365836b6c2d3d2c48c746a4d58e28bf3..7bd22c81d75368697113915a97c7fbe5 if (this.isConverting()) { ++this.conversionTicks; if (this.conversionTicks > 300) { -@@ -259,7 +264,7 @@ public class EntityHoglin extends EntityAnimal implements IMonster, IOglin { +@@ -300,7 +305,7 @@ public class EntityHoglin extends EntityAnimal implements IMonster, IOglin { @Override protected SoundEffect getSoundAmbient() { @@ -2043,98 +1907,11 @@ index f6797925365836b6c2d3d2c48c746a4d58e28bf3..7bd22c81d75368697113915a97c7fbe5 } @Override -diff --git a/src/main/java/net/minecraft/server/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java -index f034977f4666385d6e7c7288e453d058c270be01..48a820e34d45623432a3dc3b01d0bba8824c6414 100644 ---- a/src/main/java/net/minecraft/server/EntityHuman.java -+++ b/src/main/java/net/minecraft/server/EntityHuman.java -@@ -65,7 +65,8 @@ public abstract class EntityHuman extends EntityLiving { - protected int bG; - protected final float bH = 0.02F; - private int g; -- private GameProfile bJ; public final void setProfile(final GameProfile profile) { this.bJ = profile; } // Paper - OBFHELPER -+ private IChatBaseComponent displayName; // Airplane - cache displayName -+ private GameProfile bJ; public final void setProfile(final GameProfile profile) { this.bJ = profile; this.displayName = null; } // Paper - OBFHELPER // Airplane - use to reset displayName - private ItemStack bL; - private final ItemCooldown bM; - @Nullable -@@ -1731,7 +1732,12 @@ public abstract class EntityHuman extends EntityLiving { - - @Override - public IChatBaseComponent getDisplayName() { -- return new ChatComponentText(this.bJ.getName()); -+ // Airplane start - cache display name -+ if (this.displayName == null) { -+ this.displayName = new ChatComponentText(this.getProfile().getName()); -+ } -+ return this.displayName; -+ // Airplane end - } - - public InventoryEnderChest getEnderChest() { -diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java -index a47217c020d2c2a3caddafa0549dc827373798dd..81a91d63dd26a940c381b5a4f18eb60d42bbd61e 100644 ---- a/src/main/java/net/minecraft/server/EntityInsentient.java -+++ b/src/main/java/net/minecraft/server/EntityInsentient.java -@@ -133,10 +133,10 @@ public abstract class EntityInsentient extends EntityLiving { - @Override - public void inactiveTick() { - super.inactiveTick(); -- if (this.goalSelector.inactiveTick()) { -+ if (this.goalSelector.inactiveTick(this.activatedPriority)) { // Airplane - pass activated priroity - this.goalSelector.doTick(); - } -- if (this.targetSelector.inactiveTick()) { -+ if (this.targetSelector.inactiveTick(this.activatedPriority)) { // Airplane - pass activated priority - this.targetSelector.doTick(); - } - } -@@ -761,9 +761,11 @@ public abstract class EntityInsentient extends EntityLiving { - this.bo.a(); - this.world.getMethodProfiler().exit(); - this.world.getMethodProfiler().enter("targetSelector"); -+ if (this.targetSelector.inactiveTick(this.activatedPriority)) // Airplane - use this to alternate ticking - this.targetSelector.doTick(); - this.world.getMethodProfiler().exit(); - this.world.getMethodProfiler().enter("goalSelector"); -+ if (this.goalSelector.inactiveTick(this.activatedPriority)) // Airplane - use this to alternate ticking - this.goalSelector.doTick(); - this.world.getMethodProfiler().exit(); - this.world.getMethodProfiler().enter("navigation"); -diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index d568db532de83a85d5c387121cec151c160f36bf..58af082b95a7eff44e2c71c3609a288a31d28d01 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -815,11 +815,13 @@ public abstract class EntityLiving extends Entity { - } - - if (entity != null) { -- ItemStack itemstack = this.getEquipment(EnumItemSlot.HEAD); -- Item item = itemstack.getItem(); -+ // Airplane start - don't get equipment if not needed -+ //ItemStack itemstack = this.getEquipment(EnumItemSlot.HEAD); -+ //Item item = itemstack.getItem(); - EntityTypes entitytypes = entity.getEntityType(); - -- if (entitytypes == EntityTypes.SKELETON && item == Items.SKELETON_SKULL || entitytypes == EntityTypes.ZOMBIE && item == Items.ZOMBIE_HEAD || entitytypes == EntityTypes.CREEPER && item == Items.CREEPER_HEAD) { -+ if (entitytypes == EntityTypes.SKELETON && this.getEquipment(EnumItemSlot.HEAD).getItem() == Items.SKELETON_SKULL || entitytypes == EntityTypes.ZOMBIE && this.getEquipment(EnumItemSlot.HEAD).getItem() == Items.ZOMBIE_HEAD || entitytypes == EntityTypes.CREEPER && this.getEquipment(EnumItemSlot.HEAD).getItem() == Items.CREEPER_HEAD) { -+ // Airplane end - d0 *= 0.5D; - } - } -@@ -3007,7 +3009,7 @@ public abstract class EntityLiving extends Entity { - Vec3D vec3d = new Vec3D(this.locX(), this.getHeadY(), this.locZ()); - Vec3D vec3d1 = new Vec3D(entity.locX(), entity.getHeadY(), entity.locZ()); - -- return this.world.rayTrace(new RayTrace(vec3d, vec3d1, RayTrace.BlockCollisionOption.COLLIDER, RayTrace.FluidCollisionOption.NONE, this)).getType() == MovingObjectPosition.EnumMovingObjectType.MISS; -+ return this.world.rayTraceDirect(vec3d, vec3d1, VoxelShapeCollision.a(this)) == MovingObjectPosition.EnumMovingObjectType.MISS; // Airplane - use direct method - } - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityPiglin.java b/src/main/java/net/minecraft/server/EntityPiglin.java -index ca7f9dc54ed2e58f521613b5d8027494bd20edd2..682b241ae0e2859aa57faea8a4521c1c07192b7d 100644 ---- a/src/main/java/net/minecraft/server/EntityPiglin.java -+++ b/src/main/java/net/minecraft/server/EntityPiglin.java -@@ -143,7 +143,7 @@ public class EntityPiglin extends EntityPiglinAbstract implements ICrossbow { +diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java +index f2f65dc0612cc232009ea7ff12f5c1ba4e6b15ea..48acef830eb1d919499e9b79dc6a9af4bdf8a17b 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java ++++ b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java +@@ -188,7 +188,7 @@ public class EntityPiglin extends EntityPiglinAbstract implements ICrossbow { @Override public BehaviorController getBehaviorController() { @@ -2143,7 +1920,7 @@ index ca7f9dc54ed2e58f521613b5d8027494bd20edd2..682b241ae0e2859aa57faea8a4521c1c } @Override -@@ -199,12 +199,17 @@ public class EntityPiglin extends EntityPiglinAbstract implements ICrossbow { +@@ -244,12 +244,17 @@ public class EntityPiglin extends EntityPiglinAbstract implements ICrossbow { return !this.cannotHunt; } @@ -2162,7 +1939,7 @@ index ca7f9dc54ed2e58f521613b5d8027494bd20edd2..682b241ae0e2859aa57faea8a4521c1c super.mobTick(); } -@@ -341,7 +346,7 @@ public class EntityPiglin extends EntityPiglinAbstract implements ICrossbow { +@@ -386,7 +391,7 @@ public class EntityPiglin extends EntityPiglinAbstract implements ICrossbow { @Override protected SoundEffect getSoundAmbient() { @@ -2171,24 +1948,105 @@ index ca7f9dc54ed2e58f521613b5d8027494bd20edd2..682b241ae0e2859aa57faea8a4521c1c } @Override -diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index c086579073c785b3b7cd556bbb629b91560bd449..90d64eb2a7e318c8501b7efb2314d2049441bd6f 100644 ---- a/src/main/java/net/minecraft/server/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/EntityPlayer.java -@@ -52,7 +52,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public NetworkManager networkManager; // Paper - public final MinecraftServer server; - public final PlayerInteractManager playerInteractManager; -- public final Deque removeQueue = new ArrayDeque<>(); // Paper -+ public final Deque removeQueue = new java.util.concurrent.ConcurrentLinkedDeque<>(); // Paper // Airplane concurrent deque - private final AdvancementDataPlayer advancementDataPlayer; - private final ServerStatisticManager serverStatisticManager; - private float lastHealthScored = Float.MIN_VALUE; -diff --git a/src/main/java/net/minecraft/server/EntityProjectile.java b/src/main/java/net/minecraft/server/EntityProjectile.java -index d85a19905efab7189e461a61becb6ca2b8c50803..4b3d5731a18177c74f02eef91820720104145d1c 100644 ---- a/src/main/java/net/minecraft/server/EntityProjectile.java -+++ b/src/main/java/net/minecraft/server/EntityProjectile.java -@@ -85,6 +85,37 @@ public abstract class EntityProjectile extends IProjectile { +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +index 2d0b83923d58cc7b6918b4e2ff2bece13ca26899..d8028675fc82883d716bcfb44431ca6ac7dfda36 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +@@ -231,11 +231,17 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + } + // Spigot End + ++ private int behaviorTick = 0; ++ + @Override + protected void mobTick() { mobTick(false); } + protected void mobTick(boolean inactive) { + this.world.getMethodProfiler().enter("villagerBrain"); +- if (!inactive) this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error // Paper ++ if (!inactive) { ++ if (!gg.airplane.AirplaneConfig.dynamicVillagerBehavior || behaviorTick++ % this.activatedPriority == 0) { ++ this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error // Paper ++ } ++ } + this.world.getMethodProfiler().exit(); + if (this.bF) { + this.bF = false; +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index 44038dd278b988508047023107683e5370af54ad..ad85dda5c50b797904824a08513fbcec042128ea 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -162,7 +162,8 @@ public abstract class EntityHuman extends EntityLiving { + protected int bG; + protected final float bH = 0.02F; + private int g; +- private GameProfile bJ; public final void setProfile(final GameProfile profile) { this.bJ = profile; } // Paper - OBFHELPER ++ private IChatBaseComponent displayName; // Airplane - cache displayName ++ private GameProfile bJ; public final void setProfile(final GameProfile profile) { this.bJ = profile; this.displayName = null; } // Paper - OBFHELPER // Airplane - use to reset displayName + private ItemStack bL; + private final ItemCooldown bM; + @Nullable +@@ -1828,7 +1829,12 @@ public abstract class EntityHuman extends EntityLiving { + + @Override + public IChatBaseComponent getDisplayName() { +- return new ChatComponentText(this.bJ.getName()); ++ // Airplane start - cache display name ++ if (this.displayName == null) { ++ this.displayName = new ChatComponentText(this.getProfile().getName()); ++ } ++ return this.displayName; ++ // Airplane end + } + + public InventoryEnderChest getEnderChest() { +diff --git a/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java b/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java +index 2df3ae0b72ccb5f816d55fed15396ba5a1affb7f..754a3ea18905b79ae5ae4fc2442c94f0611b6d0e 100644 +--- a/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java ++++ b/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java +@@ -630,6 +630,8 @@ public class PlayerInventory implements IInventory, INamableTileEntity { + } + + public boolean h(ItemStack itemstack) { ++ // Airplane start - skip using abstract iterators and stuff, they're generic and slow and allocating them sucks ++ /* + Iterator iterator = this.f.iterator(); + + while (iterator.hasNext()) { +@@ -644,6 +646,20 @@ public class PlayerInventory implements IInventory, INamableTileEntity { + } + } + } ++ */ ++ List> components = this.getComponents(); ++ for (int i = 0; i < components.size(); i++) { ++ List list = components.get(i); ++ ++ for (int j = 0; j < list.size(); j++) { ++ ItemStack itemstack1 = list.get(j); ++ ++ if (!itemstack1.isEmpty() && itemstack1.doMaterialsMatch(itemstack)) { ++ return true; ++ } ++ } ++ } ++ // Airplane end + + return false; + } +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java +index e55061b6c04b4bde92404a6ef58ba9a52cd99c1d..24d205dd1f31ece82d5cf516b8642eb0172e1a97 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java +@@ -4,6 +4,8 @@ import net.minecraft.core.BlockPosition; + import net.minecraft.core.particles.Particles; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.util.MathHelper; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityLiving; + import net.minecraft.world.entity.EntityTypes; +@@ -102,6 +104,37 @@ public abstract class EntityProjectile extends IProjectile { this.setPosition(d0, d1, d2); } @@ -2226,514 +2084,11 @@ index d85a19905efab7189e461a61becb6ca2b8c50803..4b3d5731a18177c74f02eef918207201 protected float k() { return 0.03F; } -diff --git a/src/main/java/net/minecraft/server/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/EntityTrackerEntry.java -index 2402c18e6a18221a43bea9fc68278da9d19eede4..4b7e83e4f64a8bc4bf5b4ca569c32efefb0b3149 100644 ---- a/src/main/java/net/minecraft/server/EntityTrackerEntry.java -+++ b/src/main/java/net/minecraft/server/EntityTrackerEntry.java -@@ -46,6 +46,10 @@ public class EntityTrackerEntry { - * Requested in https://github.com/PaperMC/Paper/issues/1537 to allow intercepting packets - */ - public void sendPlayerPacket(EntityPlayer player, Packet packet) { -+ if (!gg.airplane.AirplaneConfig.entityTrackerAsyncPackets && !org.bukkit.Bukkit.isPrimaryThread()) { -+ this.b.chunkProvider.playerChunkMap.trackerEnsureMain(() -> sendPlayerPacket(player, packet)); -+ return; -+ } - player.playerConnection.sendPacket(packet); - } - -@@ -74,7 +78,7 @@ public class EntityTrackerEntry { - - public final void tick() { this.a(); } // Paper - OBFHELPER - public void a() { -- com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Tracker update"); // Tuinity -+ //com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Tracker update"); // Tuinity // Airplane - allow multithreaded - List list = this.tracker.passengers; // Paper - do not copy list - - if (!list.equals(this.p)) { -@@ -88,6 +92,8 @@ public class EntityTrackerEntry { - ItemStack itemstack = entityitemframe.getItem(); - - if (this.tickCounter % 10 == 0 && itemstack.getItem() instanceof ItemWorldMap) { // CraftBukkit - Moved this.tickCounter % 10 logic here so item frames do not enter the other blocks -+ // Airplane start - process maps on main -+ this.b.chunkProvider.playerChunkMap.trackerEnsureMain(() -> { - WorldMap worldmap = ItemWorldMap.getSavedMap(itemstack, this.b); - Iterator iterator = this.trackedPlayers.iterator(); // CraftBukkit - -@@ -101,6 +107,8 @@ public class EntityTrackerEntry { - entityplayer.playerConnection.sendPacket(packet); - } - } -+ }); -+ // Airplane end - } - - this.c(); -@@ -235,18 +243,25 @@ public class EntityTrackerEntry { - // CraftBukkit start - Create PlayerVelocity event - boolean cancelled = false; - -- if (this.tracker instanceof EntityPlayer) { -+ if (this.tracker instanceof EntityPlayer && PlayerVelocityEvent.getHandlerList().getRegisteredListeners().length > 0) { // Airplane - ensure there's listeners -+ // Airplane start - run on main thread -+ this.b.chunkProvider.playerChunkMap.trackerEnsureMain(() -> { - Player player = (Player) this.tracker.getBukkitEntity(); - org.bukkit.util.Vector velocity = player.getVelocity(); - - PlayerVelocityEvent event = new PlayerVelocityEvent(player, velocity.clone()); - this.tracker.world.getServer().getPluginManager().callEvent(event); - -- if (event.isCancelled()) { -- cancelled = true; -- } else if (!velocity.equals(event.getVelocity())) { -+ if (!event.isCancelled() && !velocity.equals(event.getVelocity())) { - player.setVelocity(event.getVelocity()); - } -+ if (!event.isCancelled()) { -+ this.broadcastIncludingSelf(new PacketPlayOutEntityVelocity(this.tracker)); // duplicate from !cancelled below -+ } -+ -+ }); -+ cancelled = true; // don't broadcast until the event has finished -+ // Airplane end - } - - if (!cancelled) { -@@ -330,7 +345,9 @@ public class EntityTrackerEntry { - if (!list.isEmpty()) { - consumer.accept(new PacketPlayOutEntityEquipment(this.tracker.getId(), list)); - } -+ this.b.chunkProvider.playerChunkMap.trackerEnsureMain(() -> { // Airplane - ((EntityLiving) this.tracker).updateEquipment(); // CraftBukkit - SPIGOT-3789: sync again immediately after sending -+ }); // Airplane - } - - // CraftBukkit start - Fix for nonsensical head yaw -@@ -408,6 +425,10 @@ public class EntityTrackerEntry { - // Paper end - - private void broadcastIncludingSelf(Packet packet) { -+ if (!gg.airplane.AirplaneConfig.entityTrackerAsyncPackets && !org.bukkit.Bukkit.isPrimaryThread()) { -+ this.b.chunkProvider.playerChunkMap.trackerEnsureMain(() -> broadcastIncludingSelf(packet)); -+ return; -+ } - this.f.accept(packet); - if (this.tracker instanceof EntityPlayer) { - ((EntityPlayer) this.tracker).playerConnection.sendPacket(packet); -diff --git a/src/main/java/net/minecraft/server/EntityTypes.java b/src/main/java/net/minecraft/server/EntityTypes.java -index 93b5a6471cde31739d2bd5f2a9fc0e0d974d0eb0..4410939423a75357cc2d16bc4a3b96a504942320 100644 ---- a/src/main/java/net/minecraft/server/EntityTypes.java -+++ b/src/main/java/net/minecraft/server/EntityTypes.java -@@ -139,6 +139,8 @@ public class EntityTypes { - private MinecraftKey bq; - private final EntitySize br; - -+ public java.util.function.Supplier getEntityName = () -> IRegistry.ENTITY_TYPE.getKey(this).toString(); // Airplane - create lambda ones -+ - private static EntityTypes a(String s, EntityTypes.Builder entitytypes_builder) { // CraftBukkit - decompile error - return (EntityTypes) IRegistry.a((IRegistry) IRegistry.ENTITY_TYPE, s, (Object) entitytypes_builder.a(s)); - } -diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java -index bf9732058c7e55e8f1ed38b3b5e8831e6b21706c..98b26a2f537594facb4ef32f9e3b6a81e41d6545 100644 ---- a/src/main/java/net/minecraft/server/EntityVillager.java -+++ b/src/main/java/net/minecraft/server/EntityVillager.java -@@ -160,11 +160,17 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - } - // Spigot End - -+ private int behaviorTick = 0; -+ - @Override - protected void mobTick() { mobTick(false); } - protected void mobTick(boolean inactive) { - this.world.getMethodProfiler().enter("villagerBrain"); -- if (!inactive) this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error // Paper -+ if (!inactive) { -+ if (!gg.airplane.AirplaneConfig.dynamicVillagerBehavior || behaviorTick++ % this.activatedPriority == 0) { -+ this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error // Paper -+ } -+ } - this.world.getMethodProfiler().exit(); - if (this.bF) { - this.bF = false; -diff --git a/src/main/java/net/minecraft/server/IBlockAccess.java b/src/main/java/net/minecraft/server/IBlockAccess.java -index 5ccf6b483fe15d4ad12ce2d3d11e9440ee9e8ab7..ec82d91804eeed49a6ef67a92fd24a06ae7ee3fb 100644 ---- a/src/main/java/net/minecraft/server/IBlockAccess.java -+++ b/src/main/java/net/minecraft/server/IBlockAccess.java -@@ -44,6 +44,15 @@ public interface IBlockAccess { - return BlockPosition.a(axisalignedbb).map(this::getType); - } - -+ // Airplane start - broken down variant of below rayTraceBlock, used by World#rayTraceDirect -+ default MovingObjectPosition.EnumMovingObjectType rayTraceBlockDirect(Vec3D vec3d, Vec3D vec3d1, BlockPosition blockposition, IBlockData iblockdata, VoxelShapeCollision voxelshapecoll) { -+ VoxelShape voxelshape = RayTrace.BlockCollisionOption.COLLIDER.get(iblockdata, this, blockposition, voxelshapecoll); -+ MovingObjectPositionBlock movingobjectpositionblock = this.rayTrace(vec3d, vec3d1, blockposition, voxelshape, iblockdata); -+ -+ return movingobjectpositionblock == null ? null : movingobjectpositionblock.getType(); -+ } -+ // Airplane end -+ - // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace - default MovingObjectPositionBlock rayTraceBlock(RayTrace raytrace1, BlockPosition blockposition) { - // Paper start - Prevent raytrace from loading chunks -diff --git a/src/main/java/net/minecraft/server/LootTableInfo.java b/src/main/java/net/minecraft/server/LootTableInfo.java -index addeb268d4d487e18ddaadebf96f078fd079246f..25b6e240cf135da0643250b3f498a077dae070da 100644 ---- a/src/main/java/net/minecraft/server/LootTableInfo.java -+++ b/src/main/java/net/minecraft/server/LootTableInfo.java -@@ -34,8 +34,8 @@ public class LootTableInfo { - this.world = worldserver; - this.d = function; - this.f = function1; -- this.h = ImmutableMap.copyOf(map); -- this.i = ImmutableMap.copyOf(map1); -+ this.h = java.util.Collections.unmodifiableMap(map); // Airplane -+ this.i = java.util.Collections.unmodifiableMap(map1); // Airplane - } - - public boolean hasContextParameter(LootContextParameter lootcontextparameter) { -@@ -53,7 +53,7 @@ public class LootTableInfo { - - @Nullable - public T getContextParameter(LootContextParameter lootcontextparameter) { -- return this.h.get(lootcontextparameter); -+ return (T) this.h.get(lootcontextparameter); // Airplane - compile error - } - - public boolean a(LootTable loottable) { -@@ -207,7 +207,7 @@ public class LootTableInfo { - } - - public T a(LootContextParameter lootcontextparameter) { -- T t0 = this.b.get(lootcontextparameter); -+ T t0 = (T) this.b.get(lootcontextparameter); // Airplane - compile error - - if (t0 == null) { - throw new IllegalArgumentException("No parameter " + lootcontextparameter); -@@ -218,7 +218,7 @@ public class LootTableInfo { - - @Nullable - public T b(LootContextParameter lootcontextparameter) { -- return this.b.get(lootcontextparameter); -+ return (T) this.b.get(lootcontextparameter); // Airplane - compile error - } - - public LootTableInfo build(LootContextParameterSet lootcontextparameterset) { -diff --git a/src/main/java/net/minecraft/server/MathHelper.java b/src/main/java/net/minecraft/server/MathHelper.java -index 2e7721a650c5a351b3584665bd236f92ef577761..b3c2b461b2a654a9e37a57f2f62b3ba8b5bb1634 100644 ---- a/src/main/java/net/minecraft/server/MathHelper.java -+++ b/src/main/java/net/minecraft/server/MathHelper.java -@@ -238,6 +238,7 @@ public class MathHelper { - return f - (float) d(f); - } - -+ public static double getDecimals(double num) { return h(num); } // Airplane - public static double h(double d0) { - return d0 - (double) d(d0); - } -@@ -416,6 +417,7 @@ public class MathHelper { - return f1 + f * (f2 - f1); - } - -+ public static double linearInterpolation(double value1, double value2, double amount) { return d(value1, value2, amount); } // Airplane - OBFHELPER - public static double d(double d0, double d1, double d2) { - return d1 + d0 * (d2 - d1); - } -@@ -432,6 +434,7 @@ public class MathHelper { - return d0 * d0 * d0 * (d0 * (d0 * 6.0D - 15.0D) + 10.0D); - } - -+ public static int sign(double num) { return k(num); } // Airplane - OBFHELPER - public static int k(double d0) { - return d0 == 0.0D ? 0 : (d0 > 0.0D ? 1 : -1); - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index afc22e545df03a38c801362d308d135df90361e2..ec6ef20e93af2298bdb3953b15e1ec24e8c72261 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1524,7 +1524,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant // Spigot - Spigot > // CraftBukkit - cb > vanilla! -+ return "Airplane"; // Airplane // Tuinity //Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! - } - - public CrashReport b(CrashReport crashreport) { -diff --git a/src/main/java/net/minecraft/server/NavigationAbstract.java b/src/main/java/net/minecraft/server/NavigationAbstract.java -index 6aec5098d346c1b7498fd8b800154cd31ce08a97..be243d411abf68686e75d46023c93fb8bb5c84e0 100644 ---- a/src/main/java/net/minecraft/server/NavigationAbstract.java -+++ b/src/main/java/net/minecraft/server/NavigationAbstract.java -@@ -411,6 +411,7 @@ public abstract class NavigationAbstract { - } - } - -+ public boolean isStuck() { return this.t(); } // Airplane - OBFHELPER - public boolean t() { - return this.t; - } -diff --git a/src/main/java/net/minecraft/server/PathfinderGoalSelector.java b/src/main/java/net/minecraft/server/PathfinderGoalSelector.java -index 9cad895c7d008487ce885cbcc2c3966645df4c19..2ce5e07f4dcd0c76073840c35be66b7c65c6e7e8 100644 ---- a/src/main/java/net/minecraft/server/PathfinderGoalSelector.java -+++ b/src/main/java/net/minecraft/server/PathfinderGoalSelector.java -@@ -43,9 +43,14 @@ public class PathfinderGoalSelector { - } - - // Paper start -- public boolean inactiveTick() { -- incRate(); -- return getCurRate() % getTickRate() == 0; -+ public boolean inactiveTick(int tickRate) { // Airplane - take tick rate -+ tickRate = Math.max(tickRate, getTickRate()); // Airplane -+ if (this.curRate++ % tickRate != 0) { // Airplane - use tick rate / increment curRate every tick -+ //incRate(); -+ return false; -+ } else { -+ return true; -+ } - } - public boolean hasTasks() { - for (PathfinderGoalWrapped task : getTasks()) { -diff --git a/src/main/java/net/minecraft/server/PathfinderTargetCondition.java b/src/main/java/net/minecraft/server/PathfinderTargetCondition.java -index 3ebe3d0dc4c2c6aee6ea349006a74cbe5aa8e78f..7b80f6f08f274fd1adff114a81919bf41bf2cd53 100644 ---- a/src/main/java/net/minecraft/server/PathfinderTargetCondition.java -+++ b/src/main/java/net/minecraft/server/PathfinderTargetCondition.java -@@ -80,9 +80,17 @@ public class PathfinderTargetCondition { - } - - if (this.b > 0.0D) { -+ // Airplane start - try to return early -+ double range = (useFollowRange ? getFollowRange(entityliving) : this.b); -+ double d2 = entityliving.h(entityliving1.locX(), entityliving1.locY(), entityliving1.locZ()); // move up here to use early -+ -+ if (d2 > range * range) { // if they're further than the absolute furthest allowed, they don't match -+ return false; -+ } -+ - double d0 = this.g ? entityliving1.A(entityliving) : 1.0D; -- double d1 = Math.max((useFollowRange ? getFollowRange(entityliving) : this.b) * d0, 2.0D); // Paper -- double d2 = entityliving.h(entityliving1.locX(), entityliving1.locY(), entityliving1.locZ()); -+ double d1 = Math.max(range * d0, 2.0D); // Paper // Airplane - reuse range calculated above -+ // Airplane end - - if (d2 > d1 * d1) { - return false; -diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java -index 945d16f57317406bff3cbe20756677eccfba1525..05250a66202cf7f6c8b7dba5e70682ed4d354156 100644 ---- a/src/main/java/net/minecraft/server/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java -@@ -651,7 +651,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return d2 * d2 + d3 * d3; - } - -- private static int b(ChunkCoordIntPair chunkcoordintpair, EntityPlayer entityplayer, boolean flag) { -+ // Airplane start - create copy that accepts x/z instead of allocating pair -+ private static int b(ChunkCoordIntPair chunkcoordintpair, EntityPlayer entityplayer, boolean flag) { return someDistanceCalculation(chunkcoordintpair.x, chunkcoordintpair.z, entityplayer, flag); } -+ private static int someDistanceCalculation(int x, int z, EntityPlayer entityplayer, boolean flag) { - int i; - int j; - -@@ -665,12 +667,16 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - j = MathHelper.floor(entityplayer.locZ() / 16.0D); - } - -- return a(chunkcoordintpair, i, j); -+ return someOtherDistanceCalculation(x, z, i, j); -+ // Airplane end - } - -- private static int a(ChunkCoordIntPair chunkcoordintpair, int i, int j) { -- int k = chunkcoordintpair.x - i; -- int l = chunkcoordintpair.z - j; -+ // Airplane start - create copy that accepts x/z instead of allocating pair -+ private static int a(ChunkCoordIntPair chunkcoordintpair, int i, int j) { return someOtherDistanceCalculation(chunkcoordintpair.x, chunkcoordintpair.z, i, j); } -+ private static int someOtherDistanceCalculation(int x, int z, int i, int j) { -+ int k = x - i; -+ int l = z - j; -+ // Airplane end - - return Math.max(Math.abs(k), Math.abs(l)); - } -@@ -731,6 +737,11 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return (PlayerChunk) (this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.get(i) : ((ProtectedVisibleChunksMap)this.visibleChunks).safeGet(i)); - // Paper end - } -+ // Airplane start - since neither map can be updated during tracker tick, it's safe to allow direct retrieval here -+ private PlayerChunk trackerGetVisibleChunk(long i) { -+ return this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.get(i) : ((ProtectedVisibleChunksMap) this.visibleChunks).safeGet(i); -+ } -+ // Airplane end - - protected final IntSupplier getPrioritySupplier(long i) { return c(i); } // Paper - OBFHELPER - protected IntSupplier c(long i) { -@@ -2134,10 +2145,30 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - entity.tracker = null; // Paper - We're no longer tracked - } - -+ // Airplane start - tools to ensure main thread -+ private final java.util.concurrent.ConcurrentLinkedQueue trackerMainQueue = new java.util.concurrent.ConcurrentLinkedQueue<>(); -+ private gg.airplane.structs.TrackQueue trackQueue; -+ -+ void trackerEnsureMain(Runnable runnable) { -+ if (this.world.serverThread == Thread.currentThread()) { -+ runnable.run(); -+ } else { -+ this.trackerMainQueue.add(runnable); -+ } -+ } -+ // Airplane end -+ - // Paper start - optimised tracker - private final void processTrackQueue() { - this.world.timings.tracker1.startTiming(); - try { -+ // Airplane start - multithreaded tracker -+ if (this.trackQueue == null) this.trackQueue = new gg.airplane.structs.TrackQueue(this.world.getChunkProvider().entityTickingChunks, trackerMainQueue); -+ if (gg.airplane.AirplaneConfig.multithreadedEntityTracker) { -+ this.trackQueue.start(); -+ return; -+ } -+ // Airplane end - com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet.Iterator iterator = this.world.getChunkProvider().entityTickingChunks.iterator(); - try { - while (iterator.hasNext()) { -@@ -2403,7 +2434,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - public class EntityTracker { - - final EntityTrackerEntry trackerEntry; // Paper - private -> package private -- private final Entity tracker; -+ protected final Entity tracker; // Airplane - public for chunk - private final int trackingDistance; - private SectionPosition e; - // Paper start -@@ -2422,7 +2453,9 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - // Paper start - use distance map to optimise tracker - com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet lastTrackerCandidates; - -- final void updatePlayers(com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newTrackerCandidates) { -+ synchronized final void tickEntry() { this.trackerEntry.tick(); } // Airplane - move entry tick into sync block -+ -+ synchronized final void updatePlayers(com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newTrackerCandidates) { // Airplane - com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet oldTrackerCandidates = this.lastTrackerCandidates; - this.lastTrackerCandidates = newTrackerCandidates; - -@@ -2463,7 +2496,13 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - return this.tracker.getId(); - } - -- public void broadcast(Packet packet) { -+ public synchronized void broadcast(Packet packet) { // Airplane - synchronized for tracked player -+ // Airplane start -+ if (!gg.airplane.AirplaneConfig.entityTrackerAsyncPackets && !org.bukkit.Bukkit.isPrimaryThread()) { -+ trackerEnsureMain(() -> broadcast(packet)); -+ return; -+ } -+ // Airplane end - Iterator iterator = this.trackedPlayers.iterator(); - - while (iterator.hasNext()) { -@@ -2475,6 +2514,12 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - } - - public void broadcastIncludingSelf(Packet packet) { -+ // Airplane start -+ if (!gg.airplane.AirplaneConfig.entityTrackerAsyncPackets && !org.bukkit.Bukkit.isPrimaryThread()) { -+ trackerEnsureMain(() -> broadcastIncludingSelf(packet)); -+ return; -+ } -+ // Airplane end - this.broadcast(packet); - if (this.tracker instanceof EntityPlayer) { - ((EntityPlayer) this.tracker).playerConnection.sendPacket(packet); -@@ -2501,8 +2546,8 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - - } - -- public void updatePlayer(EntityPlayer entityplayer) { -- org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot -+ public synchronized void updatePlayer(EntityPlayer entityplayer) { // Airplane - sync for access to map -+ //org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot // Airplane - allow sync for tracker - if (entityplayer != this.tracker) { - // Paper start - remove allocation of Vec3D here - //Vec3D vec3d = entityplayer.getPositionVector().d(this.tracker.getPositionVector()); // MC-155077, SPIGOT-5113 -@@ -2517,11 +2562,17 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - boolean flag1 = this.tracker.attachedToPlayer; - - if (!flag1) { -+ // Airplane start - use int/longs instead of ChunkCoordIntPair -+ /* - ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(this.tracker.chunkX, this.tracker.chunkZ); -- PlayerChunk playerchunk = PlayerChunkMap.this.getVisibleChunk(chunkcoordintpair.pair()); -+ */ -+ int x = this.tracker.chunkX, z = this.tracker.chunkZ; -+ long chunkcoordintpair = ChunkCoordIntPair.pair(x, z); -+ PlayerChunk playerchunk = PlayerChunkMap.this.trackerGetVisibleChunk(chunkcoordintpair); // Airplane - - if (playerchunk != null && playerchunk.getSendingChunk() != null && PlayerChunkMap.this.playerChunkManager.isChunkSent(entityplayer, MathHelper.floor(this.tracker.locX()) >> 4, MathHelper.floor(this.tracker.locZ()) >> 4)) { // Paper - no-tick view distance // Tuinity - don't broadcast in chunks the player hasn't received -- flag1 = PlayerChunkMap.b(chunkcoordintpair, entityplayer, false) <= PlayerChunkMap.this.viewDistance; -+ flag1 = PlayerChunkMap.someDistanceCalculation(x, z, entityplayer, false) <= PlayerChunkMap.this.viewDistance; -+ // Airplane end - } - } - -@@ -2551,8 +2602,10 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - } - - private int b() { -+ // Airplane start -+ int i = this.trackingDistance; // move out of if statement -+ if (!this.tracker.passengers.isEmpty()) { - Collection collection = this.tracker.getAllPassengers(); -- int i = this.trackingDistance; - Iterator iterator = collection.iterator(); - - while (iterator.hasNext()) { -@@ -2564,6 +2617,8 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - i = j; - } - } -+ } -+ // Airplane end - - return this.a(i); - } -diff --git a/src/main/java/net/minecraft/server/PlayerInventory.java b/src/main/java/net/minecraft/server/PlayerInventory.java -index 3b65711b91c51ac7b4b5b2b0144ffd279fe60eeb..478f33dbbd0b5a9b81ee420f77c97fa8c40e27d6 100644 ---- a/src/main/java/net/minecraft/server/PlayerInventory.java -+++ b/src/main/java/net/minecraft/server/PlayerInventory.java -@@ -609,6 +609,8 @@ public class PlayerInventory implements IInventory, INamableTileEntity { - } - - public boolean h(ItemStack itemstack) { -+ // Airplane start - skip using abstract iterators and stuff, they're generic and slow and allocating them sucks -+ /* - Iterator iterator = this.f.iterator(); - - while (iterator.hasNext()) { -@@ -623,6 +625,20 @@ public class PlayerInventory implements IInventory, INamableTileEntity { - } - } - } -+ */ -+ List> components = this.getComponents(); -+ for (int i = 0; i < components.size(); i++) { -+ List list = components.get(i); -+ -+ for (int j = 0; j < list.size(); j++) { -+ ItemStack itemstack1 = list.get(j); -+ -+ if (!itemstack1.isEmpty() && itemstack1.doMaterialsMatch(itemstack)) { -+ return true; -+ } -+ } -+ } -+ // Airplane end - - return false; - } -diff --git a/src/main/java/net/minecraft/server/ShapelessRecipes.java b/src/main/java/net/minecraft/server/ShapelessRecipes.java -index ecd63281912ae0ed93c5eb5ccb4249833cb23ab1..97825ec914709ca037159c46ecee218a6013ff58 100644 ---- a/src/main/java/net/minecraft/server/ShapelessRecipes.java -+++ b/src/main/java/net/minecraft/server/ShapelessRecipes.java -@@ -18,8 +18,16 @@ public class ShapelessRecipes implements RecipeCrafting { +diff --git a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java +index e112d149fc3a7af7f0c9a5280c94c9b03b2aba2d..d2afc367fb393c6206f9cd599d4603294d457608 100644 +--- a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java ++++ b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java +@@ -26,8 +26,16 @@ public class ShapelessRecipes implements RecipeCrafting { private final String group; private final ItemStack result; private final NonNullList ingredients; @@ -2750,7 +2105,7 @@ index ecd63281912ae0ed93c5eb5ccb4249833cb23ab1..97825ec914709ca037159c46ecee218a this.key = minecraftkey; this.group = s; this.result = itemstack; -@@ -61,6 +69,28 @@ public class ShapelessRecipes implements RecipeCrafting { +@@ -69,6 +77,28 @@ public class ShapelessRecipes implements RecipeCrafting { } public boolean a(InventoryCrafting inventorycrafting, World world) { @@ -2779,11 +2134,43 @@ index ecd63281912ae0ed93c5eb5ccb4249833cb23ab1..97825ec914709ca037159c46ecee218a AutoRecipeStackManager autorecipestackmanager = new AutoRecipeStackManager(); int i = 0; -diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java -index 53fd0549c965b2252ad80648d61ff1f7cd2b837a..c7573e1271288bd2b9dfe9801ea8f8804089f6ce 100644 ---- a/src/main/java/net/minecraft/server/SpawnerCreature.java -+++ b/src/main/java/net/minecraft/server/SpawnerCreature.java -@@ -381,7 +381,10 @@ public final class SpawnerCreature { +diff --git a/src/main/java/net/minecraft/world/level/IBlockAccess.java b/src/main/java/net/minecraft/world/level/IBlockAccess.java +index e612e1d30f76e217b1aa23488ab025adce048f57..c9198d242b9053fad6fa5b53c1894679002d50a7 100644 +--- a/src/main/java/net/minecraft/world/level/IBlockAccess.java ++++ b/src/main/java/net/minecraft/world/level/IBlockAccess.java +@@ -14,9 +14,11 @@ import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Material; + import net.minecraft.world.phys.AxisAlignedBB; ++import net.minecraft.world.phys.MovingObjectPosition; + import net.minecraft.world.phys.MovingObjectPositionBlock; + import net.minecraft.world.phys.Vec3D; + import net.minecraft.world.phys.shapes.VoxelShape; ++import net.minecraft.world.phys.shapes.VoxelShapeCollision; + + public interface IBlockAccess { + +@@ -56,6 +58,15 @@ public interface IBlockAccess { + return BlockPosition.a(axisalignedbb).map(this::getType); + } + ++ // Airplane start - broken down variant of below rayTraceBlock, used by World#rayTraceDirect ++ default MovingObjectPosition.EnumMovingObjectType rayTraceBlockDirect(Vec3D vec3d, Vec3D vec3d1, BlockPosition blockposition, IBlockData iblockdata, VoxelShapeCollision voxelshapecoll) { ++ VoxelShape voxelshape = RayTrace.BlockCollisionOption.COLLIDER.get(iblockdata, this, blockposition, voxelshapecoll); ++ MovingObjectPositionBlock movingobjectpositionblock = this.rayTrace(vec3d, vec3d1, blockposition, voxelshape, iblockdata); ++ ++ return movingobjectpositionblock == null ? null : movingobjectpositionblock.getType(); ++ } ++ // Airplane end ++ + // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace + default MovingObjectPositionBlock rayTraceBlock(RayTrace raytrace1, BlockPosition blockposition) { + // Paper start - Prevent raytrace from loading chunks +diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java +index d497006f05f79015cd791849888832bb53f4a414..d98526785ff2fa3b72e8ffffcb89a57a2203a5c8 100644 +--- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java ++++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java +@@ -415,7 +415,10 @@ public final class SpawnerCreature { } private static List a(WorldServer worldserver, StructureManager structuremanager, ChunkGenerator chunkgenerator, EnumCreatureType enumcreaturetype, BlockPosition blockposition, @Nullable BiomeBase biomebase) { @@ -2795,13 +2182,13 @@ index 53fd0549c965b2252ad80648d61ff1f7cd2b837a..c7573e1271288bd2b9dfe9801ea8f880 } private static BlockPosition getRandomPosition(World world, Chunk chunk) { -diff --git a/src/main/java/net/minecraft/server/StructureManager.java b/src/main/java/net/minecraft/server/StructureManager.java -index 2598ae3710d46c2cfd2be5d6be2a56e59ceef6ea..fd1f1e2d7e4be227697f534bdc6d9c52ceeeda4b 100644 ---- a/src/main/java/net/minecraft/server/StructureManager.java -+++ b/src/main/java/net/minecraft/server/StructureManager.java -@@ -5,6 +5,11 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList; // Paper - import java.util.stream.Stream; - import javax.annotation.Nullable; +diff --git a/src/main/java/net/minecraft/world/level/StructureManager.java b/src/main/java/net/minecraft/world/level/StructureManager.java +index acacbf9617f99b97fc7fd2ba718775e1b3e429e9..967ae0212028d57d366497f7f25c61776c1ac3f2 100644 +--- a/src/main/java/net/minecraft/world/level/StructureManager.java ++++ b/src/main/java/net/minecraft/world/level/StructureManager.java +@@ -15,6 +15,11 @@ import net.minecraft.world.level.levelgen.feature.StructureGenerator; + import net.minecraft.world.level.levelgen.structure.StructurePiece; + import net.minecraft.world.level.levelgen.structure.StructureStart; +// Airplane start +import it.unimi.dsi.fastutil.longs.LongIterator; @@ -2811,7 +2198,7 @@ index 2598ae3710d46c2cfd2be5d6be2a56e59ceef6ea..fd1f1e2d7e4be227697f534bdc6d9c52 public class StructureManager { private final GeneratorAccess a; public GeneratorAccess getLevel() { return a; } // Paper - OBFHELPER -@@ -41,13 +46,15 @@ public class StructureManager { +@@ -51,13 +56,15 @@ public class StructureManager { public java.util.List> getFeatureStarts(SectionPosition sectionPosition, StructureGenerator structureGenerator, IWorldReader world) { // Tuinity end - add world parameter java.util.List> list = new ObjectArrayList<>(); @@ -2830,7 +2217,7 @@ index 2598ae3710d46c2cfd2be5d6be2a56e59ceef6ea..fd1f1e2d7e4be227697f534bdc6d9c52 return list; } // Paper end -@@ -75,7 +82,18 @@ public class StructureManager { +@@ -85,7 +92,18 @@ public class StructureManager { } public StructureStart getStructureStarts(BlockPosition blockposition, boolean flag, StructureGenerator structuregenerator, IWorldReader world) { // Paper start - remove structure streams @@ -2850,7 +2237,7 @@ index 2598ae3710d46c2cfd2be5d6be2a56e59ceef6ea..fd1f1e2d7e4be227697f534bdc6d9c52 if (structurestart.c().b(blockposition)) { if (!flag) { return structurestart; -@@ -86,7 +104,10 @@ public class StructureManager { +@@ -96,7 +114,10 @@ public class StructureManager { } } } @@ -2861,11 +2248,20 @@ index 2598ae3710d46c2cfd2be5d6be2a56e59ceef6ea..fd1f1e2d7e4be227697f534bdc6d9c52 return StructureStart.a; // Paper end } -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index bf06ef09cfd4d7618365249d1332d264d8ff1377..996fa5b4652f847f4e64d4cd191fe5a597471afe 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -44,7 +44,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index c8a5d4972431ce9615312280f36181a2b9645df7..e3f1f20608cab7067674b2cdd2759a34902b6626 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -69,6 +69,8 @@ import net.minecraft.world.level.saveddata.maps.WorldMap; + import net.minecraft.world.level.storage.WorldData; + import net.minecraft.world.level.storage.WorldDataMutable; + import net.minecraft.world.phys.AxisAlignedBB; ++import net.minecraft.world.phys.MovingObjectPosition; ++import net.minecraft.world.phys.Vec3D; + import net.minecraft.world.phys.shapes.OperatorBoolean; + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; +@@ -104,7 +106,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { //public final List tileEntityList = Lists.newArrayList(); // Paper - remove unused list public final List tileEntityListTick = Lists.newArrayList(); protected final List tileEntityListPending = Lists.newArrayList(); @@ -2874,12 +2270,12 @@ index bf06ef09cfd4d7618365249d1332d264d8ff1377..996fa5b4652f847f4e64d4cd191fe5a5 public final Thread serverThread; private final boolean debugWorld; private int d; -@@ -318,6 +318,91 @@ public abstract class World implements GeneratorAccess, AutoCloseable { +@@ -378,6 +380,91 @@ public abstract class World implements GeneratorAccess, AutoCloseable { return null; } + // Airplane start - broken down method of raytracing for EntityLiving#hasLineOfSight, replaces IBlockAccess#rayTrace(RayTrace) -+ protected MovingObjectPosition.EnumMovingObjectType rayTraceDirect(Vec3D vec3d, Vec3D vec3d1, VoxelShapeCollision voxelshapecoll) { ++ public MovingObjectPosition.EnumMovingObjectType rayTraceDirect(Vec3D vec3d, Vec3D vec3d1, VoxelShapeCollision voxelshapecoll) { + // most of this code comes from IBlockAccess#a(RayTrace, BiFunction, Function), but removes the needless functions + if (vec3d.equals(vec3d1)) { + return MovingObjectPosition.EnumMovingObjectType.MISS; @@ -2966,7 +2362,7 @@ index bf06ef09cfd4d7618365249d1332d264d8ff1377..996fa5b4652f847f4e64d4cd191fe5a5 public static boolean isValidLocation(BlockPosition blockposition) { return blockposition.isValidLocation(); // Paper - use better/optimized check } -@@ -839,12 +924,17 @@ public abstract class World implements GeneratorAccess, AutoCloseable { +@@ -899,12 +986,17 @@ public abstract class World implements GeneratorAccess, AutoCloseable { gameprofilerfiller.enter("blockEntities"); timings.tileEntityTick.startTiming(); // Spigot if (!this.tileEntityListUnload.isEmpty()) { @@ -2984,7 +2380,7 @@ index bf06ef09cfd4d7618365249d1332d264d8ff1377..996fa5b4652f847f4e64d4cd191fe5a5 this.tileEntityListUnload.clear(); } -@@ -956,19 +1046,19 @@ public abstract class World implements GeneratorAccess, AutoCloseable { +@@ -1016,19 +1108,19 @@ public abstract class World implements GeneratorAccess, AutoCloseable { public void a(Consumer consumer, Entity entity) { try { @@ -3007,126 +2403,171 @@ index bf06ef09cfd4d7618365249d1332d264d8ff1377..996fa5b4652f847f4e64d4cd191fe5a5 } // Paper start - Prevent armor stands from doing entity lookups @Override -diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index 18d21f21c10974d21d17abe2f9319cdc7fd51eea..a2b8aa9ebef69535a8560e4eef42471e58e84e7f 100644 ---- a/src/main/java/net/minecraft/server/WorldServer.java -+++ b/src/main/java/net/minecraft/server/WorldServer.java -@@ -968,11 +968,12 @@ public class WorldServer extends World implements GeneratorAccessSeed { - // CraftBukkit end */ +diff --git a/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java b/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java +index 712596420af83e6e1b9d147ae2fd8d8a1f36e1b9..9c29fa3efac7e16df81b8a44934e3286bb37f1f6 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java +@@ -54,8 +54,14 @@ public abstract class BlockDirtSnowSpreadable extends BlockDirtSnow { + if (worldserver.getLightLevel(blockposition.up()) >= 9) { + IBlockData iblockdata1 = this.getBlockData(); - gameprofilerfiller.enter("checkDespawn"); -+ boolean entityTickingChunk = false; if (!entity.dead) entityTickingChunk = this.getChunkProvider().isInEntityTickingChunk(entity); // Airplane - check once, chunks won't unload ticking entities - if (!entity.dead) { - entity.checkDespawn(); - // Tuinity start - optimise notify() - if (entity.inChunk && entity.valid) { -- if (this.getChunkProvider().isInEntityTickingChunk(entity)) { -+ if (entityTickingChunk) { // Airplane - reuse - this.updateNavigatorsInRegion(entity); - } - } else { -@@ -992,7 +993,28 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - gameprofilerfiller.enter("tick"); - if (!entity.dead && !(entity instanceof EntityComplexPart)) { -+ // Airplane start - inline this.a to prevent creation of lambda ++ // Airplane start - use mutable position ++ BlockPosition.MutableBlockPosition blockposition1 = new BlockPosition.MutableBlockPosition(); + for (int i = 0; i < 4; ++i) { ++ blockposition1.setValues(blockposition).addValues(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1); + /* - this.a(this::entityJoinedWorld, entity); + BlockPosition blockposition1 = blockposition.b(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1); + */ -+ boolean doMidTick = false; // usually there's a returns in the catch, so treat it like that -+ try { -+ this.entityJoinedWorld(entity, entityTickingChunk); // Airplane - reuse -+ doMidTick = true; -+ } catch (Throwable throwable) { -+ if (throwable instanceof ThreadDeath) throw throwable; // Paper -+ // Paper start - Prevent tile entity and entity crashes -+ String msg = "Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX() + "," + entity.locY() + "," + entity.locZ(); -+ System.err.println(msg); -+ throwable.printStackTrace(); -+ getServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, throwable))); -+ entity.dead = true; -+ // Paper end -+ } -+ if (doMidTick) { -+ MinecraftServer.getServer().executeMidTickTasks(); // Tuinity - execute chunk tasks mid tick -+ } + // Airplane end + + if (worldserver.getType(blockposition1).a(Blocks.DIRT) && c(iblockdata1, (IWorldReader) worldserver, blockposition1)) { + org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(worldserver, blockposition, blockposition1, (IBlockData) iblockdata1.set(BlockDirtSnowSpreadable.a, worldserver.getType(blockposition1.up()).a(Blocks.SNOW))); // CraftBukkit +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index 259d4ac89e84fd334ff65ea8a606e1fc50cc882b..4f5f9eb110cf71a966d1365c7813ba55b5127890 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -99,6 +99,38 @@ public class Chunk implements IChunkAccess { + private final ChunkCoordIntPair loc; public final long coordinateKey; public final int locX; public final int locZ; // Paper - cache coordinate key + private volatile boolean x; + ++ // Airplane start - instead of using a random every time the chunk is ticked, define when lightning strikes preemptively ++ private int lightningTick; ++ // shouldDoLightning compiles down to 29 bytes, which with the default of 35 byte inlining should guarantee an inline ++ public final boolean shouldDoLightning(java.util.Random random) { ++ if (this.lightningTick-- <= 0) { ++ this.lightningTick = random.nextInt(100000) << 1; ++ return true; ++ } ++ return false; ++ } ++ // Airplane end ++ ++ // Airplane start - entity tracker runnable ++ // prevents needing to allocate new lambda in processTrackQueue ++ public final Runnable entityTracker = new Runnable() { ++ @Override ++ public void run() { ++ Entity[] entities = Chunk.this.entities.getRawData(); ++ for (int i = 0, len = Chunk.this.entities.size(); i < len; ++i) { ++ Entity entity = entities[i]; ++ if (entity != null) { ++ PlayerChunkMap.EntityTracker tracker = ((WorldServer) Chunk.this.getWorld()).getChunkProvider().playerChunkMap.trackedEntities.get(entity.getId()); ++ if (tracker != null) { ++ tracker.updatePlayers(tracker.tracker.getPlayersInTrackRange()); ++ tracker.tickEntry(); ++ } ++ } ++ } ++ } ++ }; ++ // Airplane end ++ + public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage) { + this(world, chunkcoordintpair, biomestorage, ChunkConverter.a, TickListEmpty.b(), TickListEmpty.b(), 0L, (ChunkSection[]) null, (Consumer) null); + } +@@ -333,6 +365,7 @@ public class Chunk implements IChunkAccess { + // CraftBukkit start + this.bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this); + this.entitySlicesManager = new com.tuinity.tuinity.world.ChunkEntitySlices(this.world, this.loc.x, this.loc.z, 0, 15); // TODO update for 1.17 // Tuinity ++ this.lightningTick = this.world.random.nextInt(100000) << 1; // Airplane - initialize lightning tick + } + + public org.bukkit.Chunk bukkitChunk; +diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java +index a6937366cd9c9d708edb5cd1ab3ac096e7b2032e..a579c5bf9e20c74aa3bf8ef6bc00576409805ca6 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java ++++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java +@@ -235,12 +235,16 @@ public class DataPaletteBlock implements DataPaletteExpandable { + this.b(); + } + ++ // Airplane start - add parameter for reusing aint + public synchronized void a(NBTTagCompound nbttagcompound, String s, String s1) { // Paper - synchronize ++ a(nbttagcompound, s, s1, new int[4096]); ++ } ++ public synchronized void a(NBTTagCompound nbttagcompound, String s, String s1, int[] aint) { // Paper - synchronize // Airplane end + this.a(); + DataPaletteHash datapalettehash = new DataPaletteHash<>(this.d, this.i, this.c, this.e, this.f); + T t0 = this.g; + int i = datapalettehash.a(this.g); +- int[] aint = new int[4096]; ++ //int[] aint = new int[4096]; // Airplane - use parameter + + for (int j = 0; j < 4096; ++j) { + T t1 = this.a(j); +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +index ec2b238480413ba9c123d9ddeaa787d9520e1b74..bf96f9e538fc29ca914536e8a7ce727ebe43a8b2 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +@@ -468,6 +468,7 @@ public class ChunkRegionLoader { + public static NBTTagCompound saveChunk(WorldServer worldserver, IChunkAccess ichunkaccess) { + return saveChunk(worldserver, ichunkaccess, null); + } ++ private static final ThreadLocal paletteArray = ThreadLocal.withInitial(() -> new int[4096]); // Airplane + public static NBTTagCompound saveChunk(WorldServer worldserver, IChunkAccess ichunkaccess, AsyncSaveData asyncsavedata) { + // Paper end + // Tuinity start - rewrite light impl +@@ -498,6 +499,7 @@ public class ChunkRegionLoader { + + NBTTagCompound nbttagcompound2; + ++ int[] aint = paletteArray.get(); // Airplane - use cached + for (int i = -1; i < 17; ++i) { // Paper - conflict on loop parameter change + int finalI = i; // CraftBukkit - decompile errors + ChunkSection chunksection = (ChunkSection) Arrays.stream(achunksection).filter((chunksection1) -> { +@@ -518,7 +520,7 @@ public class ChunkRegionLoader { + nbttagcompound2 = new NBTTagCompound(); + nbttagcompound2.setByte("Y", (byte) (i & 255)); + if (chunksection != Chunk.a) { +- chunksection.getBlocks().a(nbttagcompound2, "Palette", "BlockStates"); ++ chunksection.getBlocks().a(nbttagcompound2, "Palette", "BlockStates", aint); // Airplane } - gameprofilerfiller.exit(); -@@ -1002,7 +1024,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.entitiesById.remove(entity.getId()); // Tuinity - this.unregisterEntity(entity); - } else if (entity.inChunk && entity.valid) { // Tuinity start - optimise notify() -- if (this.getChunkProvider().isInEntityTickingChunk(entity)) { -+ if (entityTickingChunk) { // Airplane - reuse - this.updateNavigatorsInRegion(entity); - } - } else { -@@ -1087,6 +1109,8 @@ public class WorldServer extends World implements GeneratorAccessSeed { - private final BiomeBase[] biomeBaseCache = new BiomeBase[1]; - // Tuinity end - optimise chunk ice snow ticking + if (nibblearray != null && !nibblearray.c()) { +diff --git a/src/main/java/net/minecraft/world/level/storage/loot/LootTableInfo.java b/src/main/java/net/minecraft/world/level/storage/loot/LootTableInfo.java +index 95d0c9f22d79194ca83ca6f6a8e6d91180a3c8da..20cc04be75ab202d4c4ee9a07e9876ceff8422ca 100644 +--- a/src/main/java/net/minecraft/world/level/storage/loot/LootTableInfo.java ++++ b/src/main/java/net/minecraft/world/level/storage/loot/LootTableInfo.java +@@ -43,8 +43,8 @@ public class LootTableInfo { + this.world = worldserver; + this.d = function; + this.f = function1; +- this.h = ImmutableMap.copyOf(map); +- this.i = ImmutableMap.copyOf(map1); ++ this.h = java.util.Collections.unmodifiableMap(map); // Airplane ++ this.i = java.util.Collections.unmodifiableMap(map1); // Airplane + } -+ private int currentIceAndSnowTick = 0; protected void resetIceAndSnowTick() { this.currentIceAndSnowTick = this.randomTickRandom.nextInt(16); } // Airplane -+ - public void a(Chunk chunk, int i) { final int randomTickSpeed = i; // Paper - ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); - boolean flag = this.isRaining(); -@@ -1097,7 +1121,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - gameprofilerfiller.enter("thunder"); - final BlockPosition.MutableBlockPosition blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change + public boolean hasContextParameter(LootContextParameter lootcontextparameter) { +@@ -62,7 +62,7 @@ public class LootTableInfo { -- if (!this.paperConfig.disableThunder && flag && this.W() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder -+ if (!this.paperConfig.disableThunder && flag && chunk.shouldDoLightning(this.random) && this.W()) { // Paper - Disable thunder // Airplane - check this.W last // Airplane - replace random with shouldDoLighting - blockposition.setValues(this.a(this.a(j, 0, k, 15))); // Paper - if (this.isRainingAt(blockposition)) { - DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition); -@@ -1121,7 +1145,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + @Nullable + public T getContextParameter(LootContextParameter lootcontextparameter) { +- return this.h.get(lootcontextparameter); ++ return (T) this.h.get(lootcontextparameter); // Airplane - compile error + } + + public boolean a(LootTable loottable) { +@@ -216,7 +216,7 @@ public class LootTableInfo { } - gameprofilerfiller.exitEnter("iceandsnow"); -- if (!this.paperConfig.disableIceAndSnow && this.randomTickRandom.nextInt(16) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking -+ if (!this.paperConfig.disableIceAndSnow && (this.currentIceAndSnowTick++ & 15) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking // Airplane - optimize further random ticking - // Paper start - optimise chunk ticking - // Tuinity start - optimise chunk ice snow ticking - BiomeBase[] biomeCache = this.biomeBaseCache; -@@ -1301,7 +1325,9 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - // Tuinity end - log detailed entity tick information + public T a(LootContextParameter lootcontextparameter) { +- T t0 = this.b.get(lootcontextparameter); ++ T t0 = (T) this.b.get(lootcontextparameter); // Airplane - compile error -- public void entityJoinedWorld(Entity entity) { -+ // Airplane start - reuse check for in entity ticking chunk -+ public void entityJoinedWorld(Entity entity) { entityJoinedWorld(entity, this.getChunkProvider().isInEntityTickingChunk(entity)); } -+ public void entityJoinedWorld(Entity entity, boolean entityTickingChunk) { // Airplane end - // Tuinity start - log detailed entity tick information - com.tuinity.tuinity.util.TickThread.ensureTickThread("Cannot tick an entity off-main"); - try { -@@ -1309,7 +1335,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - currentlyTickingEntity.lazySet(entity); - } - // Tuinity end - log detailed entity tick information -- if (!(entity instanceof EntityHuman) && !this.getChunkProvider().a(entity)) { -+ if (!(entity instanceof EntityHuman) && !entityTickingChunk) { // Airplane - reuse - this.chunkCheck(entity); - } else { - ++TimingHistory.entityTicks; // Paper - timings -@@ -1335,9 +1361,14 @@ public class WorldServer extends World implements GeneratorAccessSeed { - ++entity.ticksLived; - GameProfilerFiller gameprofilerfiller = this.getMethodProfiler(); + if (t0 == null) { + throw new IllegalArgumentException("No parameter " + lootcontextparameter); +@@ -227,7 +227,7 @@ public class LootTableInfo { -+ // Airplane start - create debug lambda once, todo do we even WANT the method profiler? -+ /* - gameprofilerfiller.a(() -> { - return IRegistry.ENTITY_TYPE.getKey(entity.getEntityType()).toString(); - }); -+ */ -+ gameprofilerfiller.a(entity.getEntityType().getEntityName); -+ // Airplane end - gameprofilerfiller.c("tickNonPassenger"); - if (isActive) { // Paper - EAR 2 - TimingHistory.activatedEntityTicks++; // Paper + @Nullable + public T b(LootContextParameter lootcontextparameter) { +- return this.b.get(lootcontextparameter); ++ return (T) this.b.get(lootcontextparameter); // Airplane - compile error + } + + public LootTableInfo build(LootContextParameterSet lootcontextparameterset) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index f994e99ebc8fe22e6f6b45f6379ec410a598789f..ea91e1a9b99a42c462befa8245dea029ea536e01 100644 +index fd3333fef4112e6469ccd316ba2c82926c04e5db..aec6c036ed42078a6cc3540f1f6e46a551e87a2f 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -232,7 +232,7 @@ import javax.annotation.Nullable; // Paper @@ -3151,7 +2592,7 @@ index f994e99ebc8fe22e6f6b45f6379ec410a598789f..ea91e1a9b99a42c462befa8245dea029 } // Paper end diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java -index 4aba511fe8078164bf1467b39645dd9bf6a931e7..56b781e438f0cf1c12dd55eb37356601e47de47f 100644 +index de9c5ed6b03a290fe77eec719f0079fd7bd9b7f5..8c02f6fdffb59153712a3be778f9c454fd87b73b 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java @@ -44,6 +44,6 @@ public class CraftShapelessRecipe extends ShapelessRecipe implements CraftRecipe @@ -3213,20 +2654,20 @@ index 001b1e5197eaa51bfff9031aa6c69876c9a47960..1788d79ea489e446d3d9f541693d4ba3 if (stream != null) { diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 18295dceeacefd2586f3e3fe8bd58790740ba14d..b72f55c4b34ec7a91cdfdfa1c7efe4225bb2d791 100644 +index 5c2eaca0bc63c7880ee928aba6a24761737aa649..6c4c4580faef39e48de5af4db003cf2e3b8a99b5 100644 --- a/src/main/java/org/spigotmc/ActivationRange.java +++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -49,6 +49,9 @@ import net.minecraft.server.EntityInsentient; - import net.minecraft.server.EntityLlama; - import net.minecraft.server.EntityWaterAnimal; +@@ -47,6 +47,9 @@ import net.minecraft.world.entity.schedule.Activity; + import net.minecraft.world.entity.item.EntityFallingBlock; + import net.minecraft.world.entity.projectile.EntityEnderSignal; // Paper end +// Airplane start -+import net.minecraft.server.Vec3D; ++import net.minecraft.world.phys.Vec3D; +// Airplane end public class ActivationRange { -@@ -229,7 +232,7 @@ public class ActivationRange +@@ -227,7 +230,7 @@ public class ActivationRange Chunk chunk = chunkProvider.getChunkAtIfLoadedMainThreadNoCache( i1, j1 ); // Paper if ( chunk != null ) { @@ -3235,7 +2676,7 @@ index 18295dceeacefd2586f3e3fe8bd58790740ba14d..b72f55c4b34ec7a91cdfdfa1c7efe422 } } } -@@ -242,7 +245,7 @@ public class ActivationRange +@@ -240,7 +243,7 @@ public class ActivationRange * * @param chunk */ @@ -3244,7 +2685,7 @@ index 18295dceeacefd2586f3e3fe8bd58790740ba14d..b72f55c4b34ec7a91cdfdfa1c7efe422 { // Paper start Entity[] rawData = chunk.entities.getRawData(); -@@ -251,11 +254,19 @@ public class ActivationRange +@@ -249,11 +252,19 @@ public class ActivationRange //for ( Entity entity : (Collection) slice ) // Paper end { diff --git a/patches/server/0003-Rebrand.patch b/patches/server/0003-Rebrand.patch index e3c42e68b..6448decee 100644 --- a/patches/server/0003-Rebrand.patch +++ b/patches/server/0003-Rebrand.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Rebrand diff --git a/pom.xml b/pom.xml -index 1c8ff351df082c4afe8c722b3132e4446e9b42e7..37569029a241a7b3439325392e21a35b719a0067 100644 +index fc2c3714b6c772d67e258be269aa92dda80cdb12..cf6e53e9f483d21b17e2782816be4403fa5be717 100644 --- a/pom.xml +++ b/pom.xml @@ -27,8 +27,10 @@ @@ -22,7 +22,7 @@ index 1c8ff351df082c4afe8c722b3132e4446e9b42e7..37569029a241a7b3439325392e21a35b compile diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -index 74ed02fa9296583977bb721014b10ff8b708b43c..c1280478ee4565003883df9607d4a8a0e8fe4faa 100644 +index 89eeb9d202405747409e65fcf226d95379987e29..4d9e685c691a37078ff7452e50ab8c13999dbe10 100644 --- a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java +++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java @@ -17,7 +17,7 @@ public final class PaperConsole extends SimpleTerminalConsole { @@ -47,10 +47,10 @@ index f4976428bc721319d2926e97cbe0f64c6e9e503c..044ad28bd1fd1c1e25061f9f811fc10b }; diff --git a/src/main/java/net/minecraft/server/EULA.java b/src/main/java/net/minecraft/server/EULA.java -index 229c3b0f0c650b501f31147adaa17194af57fedd..f88cf526d272fe47b5a474c0b344b748ee4009fa 100644 +index 3bc5cd1e53dd7c94b948e7f57f0dc8e073e349b0..87891161f5b06bb8be0e2016b490484e6daca9d7 100644 --- a/src/main/java/net/minecraft/server/EULA.java +++ b/src/main/java/net/minecraft/server/EULA.java -@@ -70,7 +70,7 @@ public class EULA { +@@ -72,7 +72,7 @@ public class EULA { Properties properties = new Properties(); properties.setProperty("eula", "false"); @@ -60,10 +60,10 @@ index 229c3b0f0c650b501f31147adaa17194af57fedd..f88cf526d272fe47b5a474c0b344b748 throwable = throwable1; throw throwable1; diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index ec6ef20e93af2298bdb3953b15e1ec24e8c72261..576a344b8bd66d69e3fd438b254f772b678471ba 100644 +index 7cbbc1b1161f26f22a7f7832395af0d4a781cb1a..9301d93ffb5a961cb68a5c37c30b656087c1b45c 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1524,7 +1524,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant resourcekey, final DimensionManager dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper - this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((WorldDataServer) worlddatamutable).getName()); // Spigot - this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper -- this.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this, executor) : ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray - this.tuinityConfig = new com.tuinity.tuinity.config.TuinityConfig.WorldConfig(((WorldDataServer)worlddatamutable).getName()); // Tuinity - Server Config -+ this.purpurConfig = new net.pl3x.purpur.PurpurWorldConfig((((WorldDataServer)worlddatamutable).getName())); // Purpur -+ this.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this, executor) : ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray +@@ -249,6 +250,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper + this.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this, executor) : ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray + this.tuinityConfig = new com.tuinity.tuinity.config.TuinityConfig.WorldConfig(((net.minecraft.world.level.storage.WorldDataServer)worlddatamutable).getName()); // Tuinity - Server Config ++ this.purpurConfig = new net.pl3x.purpur.PurpurWorldConfig((((net.minecraft.world.level.storage.WorldDataServer)worlddatamutable).getName())); // Purpur this.generator = gen; this.world = new CraftWorld((WorldServer) this, gen, env); this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit @@ -290,14 +287,14 @@ index 0000000000000000000000000000000000000000..361f7857e461578e90cb71e15027dada +} diff --git a/src/main/java/net/pl3x/purpur/command/PurpurCommand.java b/src/main/java/net/pl3x/purpur/command/PurpurCommand.java new file mode 100644 -index 0000000000000000000000000000000000000000..4904be939c7a4b1d1583fd7b6232c930b79caba6 +index 0000000000000000000000000000000000000000..536955124afaec5c8a070249c7432cb99bf43d67 --- /dev/null +++ b/src/main/java/net/pl3x/purpur/command/PurpurCommand.java @@ -0,0 +1,65 @@ +package net.pl3x.purpur.command; + +import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.WorldServer; ++import net.minecraft.server.level.WorldServer; +import net.pl3x.purpur.PurpurConfig; +import org.bukkit.ChatColor; +import org.bukkit.Location; @@ -360,7 +357,7 @@ index 0000000000000000000000000000000000000000..4904be939c7a4b1d1583fd7b6232c930 + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index ffafb7d67f66a60a7d65cb353f24c5f9a9e15154..e48298f9ca28be83c3441afd8a8f0a6033ae0781 100644 +index f9913d7bd66935f975b756f31e26153ec160b3b1..3e0b92259ad00541a8da595a918275c1a5b2bc39 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -865,6 +865,7 @@ public final class CraftServer implements Server { @@ -407,10 +404,10 @@ index ffafb7d67f66a60a7d65cb353f24c5f9a9e15154..e48298f9ca28be83c3441afd8a8f0a60 public void restart() { org.spigotmc.RestartCommand.restart(); diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 0f6cb508a170360b6479f9c34048412453fbb89d..a92721dff5c2a9a2a167b36c23d1ef22d2bbd3e1 100644 +index 2774abda3dd1390ae904bf2b177bdd0f11968f40..d28088d510a4a40f3948f224a40a63de4645fa42 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -146,6 +146,14 @@ public class Main { +@@ -148,6 +148,14 @@ public class Main { .describedAs("Yml file"); /* Conctete End - Server Config */ diff --git a/patches/server/0006-Barrels-and-enderchests-6-rows.patch b/patches/server/0006-Barrels-and-enderchests-6-rows.patch index f2d1d3b8e..646b9520d 100644 --- a/patches/server/0006-Barrels-and-enderchests-6-rows.patch +++ b/patches/server/0006-Barrels-and-enderchests-6-rows.patch @@ -4,43 +4,11 @@ Date: Thu, 23 May 2019 21:50:37 -0500 Subject: [PATCH] Barrels and enderchests 6 rows -diff --git a/src/main/java/net/minecraft/server/BlockEnderChest.java b/src/main/java/net/minecraft/server/BlockEnderChest.java -index 896d99d404419fef5bdf6f9083e07dfc978f4e67..9ab8336df4f1702e9cabefb63f279034fdd57486 100644 ---- a/src/main/java/net/minecraft/server/BlockEnderChest.java -+++ b/src/main/java/net/minecraft/server/BlockEnderChest.java -@@ -48,6 +48,27 @@ public class BlockEnderChest extends BlockChestAbstract im - - inventoryenderchest.a(tileentityenderchest); - entityhuman.openContainer(new TileInventory((i, playerinventory, entityhuman1) -> { -+ // Purpur start -+ if (net.pl3x.purpur.PurpurConfig.enderChestSixRows) { -+ if (net.pl3x.purpur.PurpurConfig.enderChestPermissionRows) { -+ org.bukkit.craftbukkit.entity.CraftHumanEntity player = entityhuman.getBukkitEntity(); -+ if (player.hasPermission("purpur.enderchest.rows.six")) { -+ return new ContainerChest(Containers.GENERIC_9X6, i, playerinventory, inventoryenderchest, 6); -+ } else if (player.hasPermission("purpur.enderchest.rows.five")) { -+ return new ContainerChest(Containers.GENERIC_9X5, i, playerinventory, inventoryenderchest, 5); -+ } else if (player.hasPermission("purpur.enderchest.rows.four")) { -+ return new ContainerChest(Containers.GENERIC_9X4, i, playerinventory, inventoryenderchest, 4); -+ } else if (player.hasPermission("purpur.enderchest.rows.three")) { -+ return new ContainerChest(Containers.GENERIC_9X3, i, playerinventory, inventoryenderchest, 3); -+ } else if (player.hasPermission("purpur.enderchest.rows.two")) { -+ return new ContainerChest(Containers.GENERIC_9X2, i, playerinventory, inventoryenderchest, 2); -+ } else if (player.hasPermission("purpur.enderchest.rows.one")) { -+ return new ContainerChest(Containers.GENERIC_9X1, i, playerinventory, inventoryenderchest, 1); -+ } -+ } -+ return new ContainerChest(Containers.GENERIC_9X6, i, playerinventory, inventoryenderchest, 6); -+ } -+ // Purpur end - return ContainerChest.a(i, playerinventory, inventoryenderchest); - }, BlockEnderChest.e)); - entityhuman.a(StatisticList.OPEN_ENDERCHEST); -diff --git a/src/main/java/net/minecraft/server/InventoryEnderChest.java b/src/main/java/net/minecraft/server/InventoryEnderChest.java -index 8e167a664431b48875a7466be3a440eae089092b..df11848a03d2c08e935624e46489a62bc56de1da 100644 ---- a/src/main/java/net/minecraft/server/InventoryEnderChest.java -+++ b/src/main/java/net/minecraft/server/InventoryEnderChest.java -@@ -21,11 +21,34 @@ public class InventoryEnderChest extends InventorySubcontainer { +diff --git a/src/main/java/net/minecraft/world/inventory/InventoryEnderChest.java b/src/main/java/net/minecraft/world/inventory/InventoryEnderChest.java +index 85b9eba1dba3de69ab65b0e1c5ebb8740ce6e9e5..97f6ba97a4b2a35c0b8a003e1e27ad38831d859d 100644 +--- a/src/main/java/net/minecraft/world/inventory/InventoryEnderChest.java ++++ b/src/main/java/net/minecraft/world/inventory/InventoryEnderChest.java +@@ -28,11 +28,34 @@ public class InventoryEnderChest extends InventorySubcontainer { } public InventoryEnderChest(EntityHuman owner) { @@ -76,11 +44,59 @@ index 8e167a664431b48875a7466be3a440eae089092b..df11848a03d2c08e935624e46489a62b public void a(TileEntityEnderChest tileentityenderchest) { this.a = tileentityenderchest; } -diff --git a/src/main/java/net/minecraft/server/TileEntityBarrel.java b/src/main/java/net/minecraft/server/TileEntityBarrel.java -index 31d0b40fb7b30b89be1aa923c54af77e40b90b19..e5703b7d37c5f37c850328e9c8bf186d15934bdb 100644 ---- a/src/main/java/net/minecraft/server/TileEntityBarrel.java -+++ b/src/main/java/net/minecraft/server/TileEntityBarrel.java -@@ -49,7 +49,7 @@ public class TileEntityBarrel extends TileEntityLootable { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockEnderChest.java b/src/main/java/net/minecraft/world/level/block/BlockEnderChest.java +index 70d10c492b6ba893d56a463c0e71ac6aa8707f81..34ea9d2aeb9d606d487be796283c9d5ed614a6af 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockEnderChest.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockEnderChest.java +@@ -11,6 +11,7 @@ import net.minecraft.world.TileInventory; + import net.minecraft.world.entity.monster.piglin.PiglinAI; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.inventory.ContainerChest; ++import net.minecraft.world.inventory.Containers; + import net.minecraft.world.inventory.InventoryEnderChest; + import net.minecraft.world.item.context.BlockActionContext; + import net.minecraft.world.level.GeneratorAccess; +@@ -81,6 +82,27 @@ public class BlockEnderChest extends BlockChestAbstract im + + inventoryenderchest.a(tileentityenderchest); + entityhuman.openContainer(new TileInventory((i, playerinventory, entityhuman1) -> { ++ // Purpur start ++ if (net.pl3x.purpur.PurpurConfig.enderChestSixRows) { ++ if (net.pl3x.purpur.PurpurConfig.enderChestPermissionRows) { ++ org.bukkit.craftbukkit.entity.CraftHumanEntity player = entityhuman.getBukkitEntity(); ++ if (player.hasPermission("purpur.enderchest.rows.six")) { ++ return new ContainerChest(Containers.GENERIC_9X6, i, playerinventory, inventoryenderchest, 6); ++ } else if (player.hasPermission("purpur.enderchest.rows.five")) { ++ return new ContainerChest(Containers.GENERIC_9X5, i, playerinventory, inventoryenderchest, 5); ++ } else if (player.hasPermission("purpur.enderchest.rows.four")) { ++ return new ContainerChest(Containers.GENERIC_9X4, i, playerinventory, inventoryenderchest, 4); ++ } else if (player.hasPermission("purpur.enderchest.rows.three")) { ++ return new ContainerChest(Containers.GENERIC_9X3, i, playerinventory, inventoryenderchest, 3); ++ } else if (player.hasPermission("purpur.enderchest.rows.two")) { ++ return new ContainerChest(Containers.GENERIC_9X2, i, playerinventory, inventoryenderchest, 2); ++ } else if (player.hasPermission("purpur.enderchest.rows.one")) { ++ return new ContainerChest(Containers.GENERIC_9X1, i, playerinventory, inventoryenderchest, 1); ++ } ++ } ++ return new ContainerChest(Containers.GENERIC_9X6, i, playerinventory, inventoryenderchest, 6); ++ } ++ // Purpur end + return ContainerChest.a(i, playerinventory, inventoryenderchest); + }, BlockEnderChest.e)); + entityhuman.a(StatisticList.OPEN_ENDERCHEST); +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBarrel.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBarrel.java +index 7a6f150490bc3ef8a5ed43c401fd70bcc67f40f0..449d2c38abdd35b782a6732006eebb381815bcba 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBarrel.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBarrel.java +@@ -14,6 +14,7 @@ import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.entity.player.PlayerInventory; + import net.minecraft.world.inventory.Container; + import net.minecraft.world.inventory.ContainerChest; ++import net.minecraft.world.inventory.Containers; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.BlockBarrel; + import net.minecraft.world.level.block.Blocks; +@@ -68,7 +69,7 @@ public class TileEntityBarrel extends TileEntityLootable { private TileEntityBarrel(TileEntityTypes tileentitytypes) { super(tileentitytypes); @@ -89,7 +105,7 @@ index 31d0b40fb7b30b89be1aa923c54af77e40b90b19..e5703b7d37c5f37c850328e9c8bf186d } public TileEntityBarrel() { -@@ -78,7 +78,7 @@ public class TileEntityBarrel extends TileEntityLootable { +@@ -97,7 +98,7 @@ public class TileEntityBarrel extends TileEntityLootable { @Override public int getSize() { @@ -98,7 +114,7 @@ index 31d0b40fb7b30b89be1aa923c54af77e40b90b19..e5703b7d37c5f37c850328e9c8bf186d } @Override -@@ -98,6 +98,7 @@ public class TileEntityBarrel extends TileEntityLootable { +@@ -117,6 +118,7 @@ public class TileEntityBarrel extends TileEntityLootable { @Override protected Container createContainer(int i, PlayerInventory playerinventory) { @@ -143,7 +159,7 @@ index 00eb196f8caa2e4f2478972c14f4596071adbd2a..cb7e34924cb5dbff25d1ffe05cfe5bc2 + } } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java -index 9c49d9c21630c48ae6783bfc0f9cbe455862d686..613912e014070382d66d1e3a2e805af1bc741966 100644 +index 614ab2d73db2293116f2272f6cd5c16da446132d..2885dc250f171917393c0356a005b476b23f9c5f 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java @@ -212,8 +212,10 @@ public class CraftContainer extends Container { @@ -159,10 +175,10 @@ index 9c49d9c21630c48ae6783bfc0f9cbe455862d686..613912e014070382d66d1e3a2e805af1 case DISPENSER: case DROPPER: diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -index bba9bddc1c0aacade9b7ad56afb1e630caa078fc..c2802c5bfb5ec82daad32d3a3375f4428ae76dfd 100644 +index c3fa97ac34e1fc61ae02f224f8afe5a0b486fb4d..40e5a2fae032445467ac453f1fab7e366e911283 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -@@ -81,7 +81,7 @@ public class CraftInventory implements Inventory { +@@ -82,7 +82,7 @@ public class CraftInventory implements Inventory { @Override public void setContents(ItemStack[] items) { diff --git a/patches/server/0007-Advancement-API.patch b/patches/server/0007-Advancement-API.patch index 1ce8a56be..7fb48f16a 100644 --- a/patches/server/0007-Advancement-API.patch +++ b/patches/server/0007-Advancement-API.patch @@ -4,11 +4,11 @@ Date: Fri, 31 May 2019 21:24:33 -0500 Subject: [PATCH] Advancement API -diff --git a/src/main/java/net/minecraft/server/Advancement.java b/src/main/java/net/minecraft/server/Advancement.java -index c405047c00d354bbc1449fd2f917b73f980ef1a5..384d4090f8ff1ea718de16affa5c146a2f58d28a 100644 ---- a/src/main/java/net/minecraft/server/Advancement.java -+++ b/src/main/java/net/minecraft/server/Advancement.java -@@ -64,7 +64,7 @@ public class Advancement { +diff --git a/src/main/java/net/minecraft/advancements/Advancement.java b/src/main/java/net/minecraft/advancements/Advancement.java +index e3d5d55a2fe5d86db621d3e0c9322f553386d731..8bfd20ff9a3c96fa9ff5cc618ca7e858e62943a0 100644 +--- a/src/main/java/net/minecraft/advancements/Advancement.java ++++ b/src/main/java/net/minecraft/advancements/Advancement.java +@@ -77,7 +77,7 @@ public class Advancement { } @Nullable @@ -17,11 +17,11 @@ index c405047c00d354bbc1449fd2f917b73f980ef1a5..384d4090f8ff1ea718de16affa5c146a return this.display; } -diff --git a/src/main/java/net/minecraft/server/AdvancementDisplay.java b/src/main/java/net/minecraft/server/AdvancementDisplay.java -index b0d4b7a67679a35fa8f88c241193c0f3814f1e7b..ac4fac89837f4e77dcaec6f9ca90c5aa8a78c4be 100644 ---- a/src/main/java/net/minecraft/server/AdvancementDisplay.java -+++ b/src/main/java/net/minecraft/server/AdvancementDisplay.java -@@ -15,10 +15,11 @@ public class AdvancementDisplay { +diff --git a/src/main/java/net/minecraft/advancements/AdvancementDisplay.java b/src/main/java/net/minecraft/advancements/AdvancementDisplay.java +index 721d7fbab447117349994f710338ca616ab11067..35b84373da154a070f691b0049086cc788f7de4d 100644 +--- a/src/main/java/net/minecraft/advancements/AdvancementDisplay.java ++++ b/src/main/java/net/minecraft/advancements/AdvancementDisplay.java +@@ -25,10 +25,11 @@ public class AdvancementDisplay { private final MinecraftKey d; private final AdvancementFrameType e; private final boolean f; @@ -35,7 +35,7 @@ index b0d4b7a67679a35fa8f88c241193c0f3814f1e7b..ac4fac89837f4e77dcaec6f9ca90c5aa public AdvancementDisplay(ItemStack itemstack, IChatBaseComponent ichatbasecomponent, IChatBaseComponent ichatbasecomponent1, @Nullable MinecraftKey minecraftkey, AdvancementFrameType advancementframetype, boolean flag, boolean flag1, boolean flag2) { this.a = ichatbasecomponent; -@@ -36,22 +37,29 @@ public class AdvancementDisplay { +@@ -46,22 +47,29 @@ public class AdvancementDisplay { this.j = f1; } @@ -65,12 +65,13 @@ index b0d4b7a67679a35fa8f88c241193c0f3814f1e7b..ac4fac89837f4e77dcaec6f9ca90c5aa public boolean j() { return this.h; } -diff --git a/src/main/java/net/minecraft/server/AdvancementFrameType.java b/src/main/java/net/minecraft/server/AdvancementFrameType.java -index 90b78e49c0688dc2fb02df0b6784cd82fad4bc07..9a3a53cf3576c299629a84ba76cb5b9b86a14491 100644 ---- a/src/main/java/net/minecraft/server/AdvancementFrameType.java -+++ b/src/main/java/net/minecraft/server/AdvancementFrameType.java -@@ -1,15 +1,26 @@ - package net.minecraft.server; +diff --git a/src/main/java/net/minecraft/advancements/AdvancementFrameType.java b/src/main/java/net/minecraft/advancements/AdvancementFrameType.java +index f5d24950d317c78a971472821595fc1b44befc6e..f096ecf8d77b085e6c2ef4c3b64f0b65409bb287 100644 +--- a/src/main/java/net/minecraft/advancements/AdvancementFrameType.java ++++ b/src/main/java/net/minecraft/advancements/AdvancementFrameType.java +@@ -4,16 +4,27 @@ import net.minecraft.EnumChatFormat; + import net.minecraft.network.chat.ChatMessage; + import net.minecraft.network.chat.IChatBaseComponent; +import org.bukkit.advancement.FrameType; // Purpur + @@ -98,11 +99,11 @@ index 90b78e49c0688dc2fb02df0b6784cd82fad4bc07..9a3a53cf3576c299629a84ba76cb5b9b this.d = s; this.e = i; this.f = enumchatformat; -diff --git a/src/main/java/net/minecraft/server/CriterionTrigger.java b/src/main/java/net/minecraft/server/CriterionTrigger.java -index cfb420a9c7e64ec240fff81d2e3fd32f607847b3..6fd3671c37a4fc42aa438a93d5a749b52f618b1e 100644 ---- a/src/main/java/net/minecraft/server/CriterionTrigger.java -+++ b/src/main/java/net/minecraft/server/CriterionTrigger.java -@@ -26,6 +26,7 @@ public interface CriterionTrigger { +diff --git a/src/main/java/net/minecraft/advancements/CriterionTrigger.java b/src/main/java/net/minecraft/advancements/CriterionTrigger.java +index f2d74473caf96ca6e871311ef87afa128cd4d0bf..851e69a2f5155d9fa2e5652abdea9aee59e4b20a 100644 +--- a/src/main/java/net/minecraft/advancements/CriterionTrigger.java ++++ b/src/main/java/net/minecraft/advancements/CriterionTrigger.java +@@ -29,6 +29,7 @@ public interface CriterionTrigger { this.c = s; } @@ -111,7 +112,7 @@ index cfb420a9c7e64ec240fff81d2e3fd32f607847b3..6fd3671c37a4fc42aa438a93d5a749b5 return this.a; } diff --git a/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancement.java b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancement.java -index a5aadf2850f273e258f84b6c7bc9ca3649fb884d..b0a7092d623adccd61fd3e094f1ec5e8d95c3691 100644 +index 77abcd6de43302985cdbb2085abece4f621068d4..c859fc16c263e0c50cb01fc722b6f6723d682481 100644 --- a/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancement.java +++ b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancement.java @@ -27,4 +27,11 @@ public class CraftAdvancement implements org.bukkit.advancement.Advancement { @@ -128,13 +129,13 @@ index a5aadf2850f273e258f84b6c7bc9ca3649fb884d..b0a7092d623adccd61fd3e094f1ec5e8 } diff --git a/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementDisplay.java b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementDisplay.java new file mode 100644 -index 0000000000000000000000000000000000000000..1cbb1e67b64a7e830cfabcd1fc07e998434476c3 +index 0000000000000000000000000000000000000000..0b4ff544e04ec314e78a7a48b5bf90ee699b2ad6 --- /dev/null +++ b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementDisplay.java @@ -0,0 +1,47 @@ +package org.bukkit.craftbukkit.advancement; + -+import net.minecraft.server.AdvancementDisplay; ++import net.minecraft.advancements.AdvancementDisplay; +import org.bukkit.advancement.FrameType; +import org.bukkit.craftbukkit.util.CraftChatMessage; + diff --git a/patches/server/0008-Llama-API.patch b/patches/server/0008-Llama-API.patch index 1aa1fd6a7..dd9d6492c 100644 --- a/patches/server/0008-Llama-API.patch +++ b/patches/server/0008-Llama-API.patch @@ -4,11 +4,40 @@ Date: Fri, 18 Oct 2019 22:50:12 -0500 Subject: [PATCH] Llama API -diff --git a/src/main/java/net/minecraft/server/EntityLlama.java b/src/main/java/net/minecraft/server/EntityLlama.java -index d9e1b43283bee15c659dd3a99e45d9412aedd0bc..e61f53816cbf09e775762403d97e9c591fb405a6 100644 ---- a/src/main/java/net/minecraft/server/EntityLlama.java -+++ b/src/main/java/net/minecraft/server/EntityLlama.java -@@ -13,7 +13,8 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalLlamaFollow.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalLlamaFollow.java +index 4fd1744f13b87c79ae3f46b28a56daeaba343aa6..34a854131dd939693a6df4d52103714ebe373dc3 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalLlamaFollow.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalLlamaFollow.java +@@ -11,7 +11,7 @@ import net.minecraft.world.phys.Vec3D; + + public class PathfinderGoalLlamaFollow extends PathfinderGoal { + +- public final EntityLlama a; ++ public final EntityLlama a; public EntityLlama getLlama() { return a; } // Purpur + private double b; + private int c; + +@@ -23,6 +23,7 @@ public class PathfinderGoalLlamaFollow extends PathfinderGoal { + + @Override + public boolean a() { ++ if (!getLlama().shouldJoinCaravan) return false; // Purpur + if (!this.a.isLeashed() && !this.a.fC()) { + List list = this.a.world.getEntities(this.a, this.a.getBoundingBox().grow(9.0D, 4.0D, 9.0D), (entity) -> { + EntityTypes entitytypes = entity.getEntityType(); +@@ -82,6 +83,7 @@ public class PathfinderGoalLlamaFollow extends PathfinderGoal { + + @Override + public boolean b() { ++ if (!getLlama().shouldJoinCaravan) return false; // Purpur + if (this.a.fC() && this.a.fD().isAlive() && this.a(this.a, 0)) { + double d0 = this.a.h((Entity) this.a.fD()); + +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java +index 2005cb484ba6b5929ad81d3d120521f247f3d4cf..1c6435bf2cd870b795f87368057d8dfc1e1c938a 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java +@@ -63,7 +63,8 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn @Nullable private EntityLlama bB; @Nullable @@ -18,7 +47,7 @@ index d9e1b43283bee15c659dd3a99e45d9412aedd0bc..e61f53816cbf09e775762403d97e9c59 public EntityLlama(EntityTypes entitytypes, World world) { super(entitytypes, world); -@@ -42,6 +43,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn +@@ -92,6 +93,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn nbttagcompound.set("DecorItem", this.inventoryChest.getItem(1).save(new NBTTagCompound())); } @@ -26,7 +55,7 @@ index d9e1b43283bee15c659dd3a99e45d9412aedd0bc..e61f53816cbf09e775762403d97e9c59 } @Override -@@ -53,6 +55,11 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn +@@ -103,6 +105,11 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn this.inventoryChest.setItem(1, ItemStack.a(nbttagcompound.getCompound("DecorItem"))); } @@ -38,7 +67,7 @@ index d9e1b43283bee15c659dd3a99e45d9412aedd0bc..e61f53816cbf09e775762403d97e9c59 this.fe(); } -@@ -387,19 +394,24 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn +@@ -437,19 +444,24 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn } } @@ -63,7 +92,7 @@ index d9e1b43283bee15c659dd3a99e45d9412aedd0bc..e61f53816cbf09e775762403d97e9c59 public boolean fB() { return this.bC != null; } -@@ -410,7 +422,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn +@@ -460,7 +472,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn } @Nullable @@ -72,37 +101,8 @@ index d9e1b43283bee15c659dd3a99e45d9412aedd0bc..e61f53816cbf09e775762403d97e9c59 return this.bB; } -diff --git a/src/main/java/net/minecraft/server/PathfinderGoalLlamaFollow.java b/src/main/java/net/minecraft/server/PathfinderGoalLlamaFollow.java -index 1b29ca2ca0bc5d17673de43bdc854d5b4c96b8b6..47ffa669681da7512ee594ecb643f28576dee444 100644 ---- a/src/main/java/net/minecraft/server/PathfinderGoalLlamaFollow.java -+++ b/src/main/java/net/minecraft/server/PathfinderGoalLlamaFollow.java -@@ -6,7 +6,7 @@ import java.util.List; - - public class PathfinderGoalLlamaFollow extends PathfinderGoal { - -- public final EntityLlama a; -+ public final EntityLlama a; public EntityLlama getLlama() { return a; } // Purpur - private double b; - private int c; - -@@ -18,6 +18,7 @@ public class PathfinderGoalLlamaFollow extends PathfinderGoal { - - @Override - public boolean a() { -+ if (!getLlama().shouldJoinCaravan) return false; // Purpur - if (!this.a.isLeashed() && !this.a.fC()) { - List list = this.a.world.getEntities(this.a, this.a.getBoundingBox().grow(9.0D, 4.0D, 9.0D), (entity) -> { - EntityTypes entitytypes = entity.getEntityType(); -@@ -77,6 +78,7 @@ public class PathfinderGoalLlamaFollow extends PathfinderGoal { - - @Override - public boolean b() { -+ if (!getLlama().shouldJoinCaravan) return false; // Purpur - if (this.a.fC() && this.a.fD().isAlive() && this.a(this.a, 0)) { - double d0 = this.a.h((Entity) this.a.fD()); - diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java -index 71faa1b38f613db468ee939a7ffac7aaed733d20..43536b0744e5618c10790ae9db399c0506567f2a 100644 +index 818034c62893a71808e3af0aa33393605611acdd..71536b6ae6a423e33667efcf584a0020f36fb189 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java @@ -66,4 +66,48 @@ public class CraftLlama extends CraftChestedHorse implements Llama, CraftRangedE diff --git a/patches/server/0009-AFK-API.patch b/patches/server/0009-AFK-API.patch index ab468cc09..92c246f7c 100644 --- a/patches/server/0009-AFK-API.patch +++ b/patches/server/0009-AFK-API.patch @@ -4,31 +4,11 @@ Date: Thu, 8 Aug 2019 15:29:15 -0500 Subject: [PATCH] AFK API -diff --git a/src/main/java/net/minecraft/server/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java -index 48a820e34d45623432a3dc3b01d0bba8824c6414..a3aa2c8760b43e09f77f2790d6e21b8a2dc9dd3c 100644 ---- a/src/main/java/net/minecraft/server/EntityHuman.java -+++ b/src/main/java/net/minecraft/server/EntityHuman.java -@@ -85,6 +85,15 @@ public abstract class EntityHuman extends EntityLiving { - } - // CraftBukkit end - -+ // Purpur start -+ public void setAfk(boolean setAfk){ -+ } -+ -+ public boolean isAfk() { -+ return false; -+ } -+ // Purpur end -+ - public EntityHuman(World world, BlockPosition blockposition, float f, GameProfile gameprofile) { - super(EntityTypes.PLAYER, world); - this.bL = ItemStack.b; -diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index 90d64eb2a7e318c8501b7efb2314d2049441bd6f..9be41dab47230046e576f4472c4c1c23523aa28c 100644 ---- a/src/main/java/net/minecraft/server/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/EntityPlayer.java -@@ -1940,8 +1940,54 @@ public class EntityPlayer extends EntityHuman implements ICrafting { +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 534c7266fe9d6f60b74a71e5e61ed248e515dffd..f30dcbd26ed56ba8f1a99260722a0b395c220954 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -2070,8 +2070,54 @@ public class EntityPlayer extends EntityHuman implements ICrafting { public void resetIdleTimer() { this.ca = SystemUtils.getMonotonicMillis(); @@ -43,7 +23,7 @@ index 90d64eb2a7e318c8501b7efb2314d2049441bd6f..9be41dab47230046e576f4472c4c1c23 + if (this.isAfk == setAfk) { + return; + } -+ ++ + String msg = setAfk ? net.pl3x.purpur.PurpurConfig.afkBroadcastAway : net.pl3x.purpur.PurpurConfig.afkBroadcastBack; + + net.pl3x.purpur.event.PlayerAFKEvent event = new net.pl3x.purpur.event.PlayerAFKEvent(getBukkitEntity(), setAfk, world.purpurConfig.idleTimeoutKick, msg, !Bukkit.isPrimaryThread()); @@ -83,11 +63,117 @@ index 90d64eb2a7e318c8501b7efb2314d2049441bd6f..9be41dab47230046e576f4472c4c1c23 public ServerStatisticManager getStatisticManager() { return this.serverStatisticManager; } -diff --git a/src/main/java/net/minecraft/server/IEntityAccess.java b/src/main/java/net/minecraft/server/IEntityAccess.java -index ad286848ddb7803640ef7eeea46b58473dd1d0c4..2e514b8291a544a88667fbca2389bde4c2ecb109 100644 ---- a/src/main/java/net/minecraft/server/IEntityAccess.java -+++ b/src/main/java/net/minecraft/server/IEntityAccess.java -@@ -174,28 +174,18 @@ public interface IEntityAccess { +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 9d97e2ea5c207c42f1cc9aa14bc87dc8e0a1bb1e..984a90a0a69f60315536d60eff597f65b6d49c57 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -1000,7 +1000,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + // CraftBukkit end + + if (this.everyoneSleeping && this.players.stream().noneMatch((entityplayer) -> { +- return !entityplayer.isSpectator() && !entityplayer.isDeeplySleeping() && !entityplayer.fauxSleeping; // CraftBukkit ++ return !entityplayer.isSpectator() && !entityplayer.isDeeplySleeping() && !entityplayer.fauxSleeping && !(purpurConfig.idleTimeoutCountAsSleeping && entityplayer.isAfk()); // CraftBukkit // Purpur + })) { + // CraftBukkit start + long l = this.worldData.getDayTime() + 24000L; +@@ -1368,7 +1368,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + while (iterator.hasNext()) { + EntityPlayer entityplayer = (EntityPlayer) iterator.next(); + +- if (entityplayer.isSpectator() || (entityplayer.fauxSleeping && !entityplayer.isSleeping())) { // CraftBukkit ++ if (entityplayer.isSpectator() || (entityplayer.fauxSleeping && !entityplayer.isSleeping()) || (purpurConfig.idleTimeoutCountAsSleeping && entityplayer.isAfk())) { // CraftBukkit // Purpur + ++i; + } else if (entityplayer.isSleeping()) { + ++j; +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index b7e72fe1cd04219391c75beb7d67a1e32e393a16..789cf1652fec8346c1ea3ca47d9ac43c0765528a 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -397,6 +397,12 @@ public class PlayerConnection implements PacketListenerPlayIn { + } + + if (this.player.F() > 0L && this.minecraftServer.getIdleTimeout() > 0 && SystemUtils.getMonotonicMillis() - this.player.F() > (long) (this.minecraftServer.getIdleTimeout() * 1000 * 60)) { ++ // Purpur start ++ this.player.setAfk(true); ++ if (!this.player.world.purpurConfig.idleTimeoutKick) { ++ return; ++ } ++ // Purpur end + this.player.resetIdleTimer(); // CraftBukkit - SPIGOT-854 + this.disconnect(new ChatMessage("multiplayer.disconnect.idling")); + } +@@ -666,6 +672,8 @@ public class PlayerConnection implements PacketListenerPlayIn { + this.lastYaw = to.getYaw(); + this.lastPitch = to.getPitch(); + ++ if (!to.getWorld().getUID().equals(from.getWorld().getUID()) || to.getBlockX() != from.getBlockX() || to.getBlockY() != from.getBlockY() || to.getBlockZ() != from.getBlockZ() || to.getYaw() != from.getYaw() || to.getPitch() != from.getPitch()) this.player.resetIdleTimer(); // Purpur ++ + // Skip the first time we do this + if (true) { // Spigot - don't skip any move events + Location oldTo = to.clone(); +@@ -1402,7 +1410,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + + if (!this.player.H() && d11 > org.spigotmc.SpigotConfig.movedWronglyThreshold && !this.player.isSleeping() && !this.player.playerInteractManager.isCreative() && this.player.playerInteractManager.getGameMode() != EnumGamemode.SPECTATOR) { // Spigot + flag1 = true; // Tuinity - diff on change, this should be moved wrongly +- PlayerConnection.LOGGER.warn("{} moved wrongly!", this.player.getDisplayName().getString()); ++ PlayerConnection.LOGGER.warn("{} moved wrongly! ({})", this.player.getDisplayName().getString(), d11); // Purpur + } + + this.player.setLocation(d4, d5, d6, f, f1); +@@ -1452,6 +1460,8 @@ public class PlayerConnection implements PacketListenerPlayIn { + this.lastYaw = to.getYaw(); + this.lastPitch = to.getPitch(); + ++ if (!to.getWorld().getUID().equals(from.getWorld().getUID()) || to.getBlockX() != from.getBlockX() || to.getBlockY() != from.getBlockY() || to.getBlockZ() != from.getBlockZ() || to.getYaw() != from.getYaw() || to.getPitch() != from.getPitch()) this.player.resetIdleTimer(); // Purpur ++ + // Skip the first time we do this + if (from.getX() != Double.MAX_VALUE) { + Location oldTo = to.clone(); +diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java +index f5e32faeb6d937cf90b1f3ea251b5cfc91f2338d..f9908fb7cc27a8947030c2100dccf1dc1a4e24f7 100644 +--- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java ++++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java +@@ -15,6 +15,7 @@ import net.minecraft.world.scores.ScoreboardTeamBase; + public final class IEntitySelector { + + public static final Predicate a = Entity::isAlive; ++ public static Predicate isLivingAlive() { return b; } // Purpur - OBFHELPER + public static final Predicate b = EntityLiving::isAlive; + public static final Predicate c = (entity) -> { + return entity.isAlive() && !entity.isVehicle() && !entity.isPassenger(); +@@ -35,6 +36,7 @@ public final class IEntitySelector { + return !entity.isSpectator(); + }; + public static Predicate isInsomniac = (player) -> MathHelper.clamp(((EntityPlayer) player).getStatisticManager().getStatisticValue(StatisticList.CUSTOM.get(StatisticList.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= 72000; // Paper ++ public static Predicate notAfk = (player) -> !player.isAfk(); // Purpur + + // Paper start + public static final Predicate affectsSpawning = (entity) -> { +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index ad85dda5c50b797904824a08513fbcec042128ea..8f9d0769e7855c3565a34927f3f3741c43e45f35 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -182,6 +182,15 @@ public abstract class EntityHuman extends EntityLiving { + } + // CraftBukkit end + ++ // Purpur start ++ public void setAfk(boolean setAfk){ ++ } ++ ++ public boolean isAfk() { ++ return false; ++ } ++ // Purpur end ++ + public EntityHuman(World world, BlockPosition blockposition, float f, GameProfile gameprofile) { + super(EntityTypes.PLAYER, world); + this.bL = ItemStack.b; +diff --git a/src/main/java/net/minecraft/world/level/IEntityAccess.java b/src/main/java/net/minecraft/world/level/IEntityAccess.java +index a7f2304acf8ee0a15d6eae8c42060e003be13ae7..fd56b2f15e570f266a79c25823a3b3530a693510 100644 +--- a/src/main/java/net/minecraft/world/level/IEntityAccess.java ++++ b/src/main/java/net/minecraft/world/level/IEntityAccess.java +@@ -183,28 +183,18 @@ public interface IEntityAccess { } // Paper end @@ -128,101 +214,15 @@ index ad286848ddb7803640ef7eeea46b58473dd1d0c4..2e514b8291a544a88667fbca2389bde4 } @Nullable -diff --git a/src/main/java/net/minecraft/server/IEntitySelector.java b/src/main/java/net/minecraft/server/IEntitySelector.java -index b5e1a860a2569d7668330827614d221b60f3fc78..5f85a1d513f4fdc21b64e1a2b6882e3325b98ddd 100644 ---- a/src/main/java/net/minecraft/server/IEntitySelector.java -+++ b/src/main/java/net/minecraft/server/IEntitySelector.java -@@ -7,6 +7,7 @@ import javax.annotation.Nullable; - public final class IEntitySelector { - - public static final Predicate a = Entity::isAlive; -+ public static Predicate isLivingAlive() { return b; } // Purpur - OBFHELPER - public static final Predicate b = EntityLiving::isAlive; - public static final Predicate c = (entity) -> { - return entity.isAlive() && !entity.isVehicle() && !entity.isPassenger(); -@@ -27,6 +28,7 @@ public final class IEntitySelector { - return !entity.isSpectator(); - }; - public static Predicate isInsomniac = (player) -> MathHelper.clamp(((EntityPlayer) player).getStatisticManager().getStatisticValue(StatisticList.CUSTOM.get(StatisticList.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= 72000; // Paper -+ public static Predicate notAfk = (player) -> !player.isAfk(); // Purpur - - // Paper start - public static final Predicate affectsSpawning = (entity) -> { -diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 9146b60cff0aa06e2f6b6003bfe9e2be9d2f0d56..bba8dc8fd10dc34179ca3c8cf471fbb3739fa7b4 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -252,6 +252,12 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - - if (this.player.F() > 0L && this.minecraftServer.getIdleTimeout() > 0 && SystemUtils.getMonotonicMillis() - this.player.F() > (long) (this.minecraftServer.getIdleTimeout() * 1000 * 60)) { -+ // Purpur start -+ this.player.setAfk(true); -+ if (!this.player.world.purpurConfig.idleTimeoutKick) { -+ return; -+ } -+ // Purpur end - this.player.resetIdleTimer(); // CraftBukkit - SPIGOT-854 - this.disconnect(new ChatMessage("multiplayer.disconnect.idling")); - } -@@ -521,6 +527,8 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.lastYaw = to.getYaw(); - this.lastPitch = to.getPitch(); - -+ if (!to.getWorld().getUID().equals(from.getWorld().getUID()) || to.getBlockX() != from.getBlockX() || to.getBlockY() != from.getBlockY() || to.getBlockZ() != from.getBlockZ() || to.getYaw() != from.getYaw() || to.getPitch() != from.getPitch()) this.player.resetIdleTimer(); // Purpur -+ - // Skip the first time we do this - if (true) { // Spigot - don't skip any move events - Location oldTo = to.clone(); -@@ -1257,7 +1265,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - - if (!this.player.H() && d11 > org.spigotmc.SpigotConfig.movedWronglyThreshold && !this.player.isSleeping() && !this.player.playerInteractManager.isCreative() && this.player.playerInteractManager.getGameMode() != EnumGamemode.SPECTATOR) { // Spigot - flag1 = true; // Tuinity - diff on change, this should be moved wrongly -- PlayerConnection.LOGGER.warn("{} moved wrongly!", this.player.getDisplayName().getString()); -+ PlayerConnection.LOGGER.warn("{} moved wrongly! ({})", this.player.getDisplayName().getString(), d11); // Purpur - } - - this.player.setLocation(d4, d5, d6, f, f1); -@@ -1307,6 +1315,8 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.lastYaw = to.getYaw(); - this.lastPitch = to.getPitch(); - -+ if (!to.getWorld().getUID().equals(from.getWorld().getUID()) || to.getBlockX() != from.getBlockX() || to.getBlockY() != from.getBlockY() || to.getBlockZ() != from.getBlockZ() || to.getYaw() != from.getYaw() || to.getPitch() != from.getPitch()) this.player.resetIdleTimer(); // Purpur -+ - // Skip the first time we do this - if (from.getX() != Double.MAX_VALUE) { - Location oldTo = to.clone(); -diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index a2b8aa9ebef69535a8560e4eef42471e58e84e7f..2d72803f1c52acf8bc069777351a3ef4d75f6e6c 100644 ---- a/src/main/java/net/minecraft/server/WorldServer.java -+++ b/src/main/java/net/minecraft/server/WorldServer.java -@@ -887,7 +887,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - // CraftBukkit end - - if (this.everyoneSleeping && this.players.stream().noneMatch((entityplayer) -> { -- return !entityplayer.isSpectator() && !entityplayer.isDeeplySleeping() && !entityplayer.fauxSleeping; // CraftBukkit -+ return !entityplayer.isSpectator() && !entityplayer.isDeeplySleeping() && !entityplayer.fauxSleeping && !(purpurConfig.idleTimeoutCountAsSleeping && entityplayer.isAfk()); // CraftBukkit // Purpur - })) { - // CraftBukkit start - long l = this.worldData.getDayTime() + 24000L; -@@ -1255,7 +1255,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - while (iterator.hasNext()) { - EntityPlayer entityplayer = (EntityPlayer) iterator.next(); - -- if (entityplayer.isSpectator() || (entityplayer.fauxSleeping && !entityplayer.isSleeping())) { // CraftBukkit -+ if (entityplayer.isSpectator() || (entityplayer.fauxSleeping && !entityplayer.isSleeping()) || (purpurConfig.idleTimeoutCountAsSleeping && entityplayer.isAfk())) { // CraftBukkit // Purpur - ++i; - } else if (entityplayer.isSleeping()) { - ++j; diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index cb7e34924cb5dbff25d1ffe05cfe5bc22e4a90ed..406e840499e09638e8b325d0e52b764e80acc777 100644 +index cb7e34924cb5dbff25d1ffe05cfe5bc22e4a90ed..ee99289165cab9f58b689a7e07aa01622e203863 100644 --- a/src/main/java/net/pl3x/purpur/PurpurConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java @@ -1,6 +1,7 @@ package net.pl3x.purpur; import com.google.common.base.Throwables; -+import net.minecraft.server.LocaleLanguage; ++import net.minecraft.locale.LocaleLanguage; import net.minecraft.server.MinecraftServer; import net.pl3x.purpur.command.PurpurCommand; import org.bukkit.Bukkit; @@ -263,10 +263,10 @@ index 361f7857e461578e90cb71e15027dadaf794cb69..2578a4677d1ee060f687be531e696b7c + } } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index b3636032fd36efe2e7e546dbebdfd5c1208f9951..abf2a6b9d18f04baa077ededa3562a30dbaa4fe4 100644 +index 45e786565ac988abadffda2e7ba3ff1e2880b786..f4052aaa2235894b996d65c569a083f1a09b59a3 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2482,4 +2482,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2491,4 +2491,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return spigot; } // Spigot end @@ -289,10 +289,10 @@ index b3636032fd36efe2e7e546dbebdfd5c1208f9951..abf2a6b9d18f04baa077ededa3562a30 + // Purpur end } diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index b72f55c4b34ec7a91cdfdfa1c7efe4225bb2d791..c8ef3856d398fc7a966385c04cadeb1e8e8504f7 100644 +index 6c4c4580faef39e48de5af4db003cf2e3b8a99b5..dc2d880ded328f8377c207ce15f604ec5c25176c 100644 --- a/src/main/java/org/spigotmc/ActivationRange.java +++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -209,6 +209,7 @@ public class ActivationRange +@@ -207,6 +207,7 @@ public class ActivationRange { player.activatedTick = MinecraftServer.currentTick; diff --git a/patches/server/0010-Bring-back-server-name.patch b/patches/server/0010-Bring-back-server-name.patch index 7a47cf2fa..d68487a2c 100644 --- a/patches/server/0010-Bring-back-server-name.patch +++ b/patches/server/0010-Bring-back-server-name.patch @@ -4,11 +4,11 @@ Date: Sun, 26 May 2019 15:19:14 -0500 Subject: [PATCH] Bring back server name -diff --git a/src/main/java/net/minecraft/server/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/DedicatedServerProperties.java -index 15a4f921b1ae2bbc66b7d58238b60151123a7eb3..fe5937d890762ab37a90f189c4992af389d2c41d 100644 ---- a/src/main/java/net/minecraft/server/DedicatedServerProperties.java -+++ b/src/main/java/net/minecraft/server/DedicatedServerProperties.java -@@ -14,6 +14,7 @@ public class DedicatedServerProperties extends PropertyManager entitytypes, World world) { - super(entitytypes, world); -+ this.safeFallDistance = 10.0F; // Purpur - } - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityHorseAbstract.java b/src/main/java/net/minecraft/server/EntityHorseAbstract.java -index acbdaa097dfd1cba18add0a09ad54ca78d3e0c24..784819d252d94e8040a87f53431fcf2c7a19d1a7 100644 ---- a/src/main/java/net/minecraft/server/EntityHorseAbstract.java -+++ b/src/main/java/net/minecraft/server/EntityHorseAbstract.java -@@ -211,7 +211,7 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven - - @Override - protected int e(float f, float f1) { -- return MathHelper.f((f * 0.5F - 3.0F) * f1); -+ return MathHelper.f((f * 0.5F - this.safeFallDistance) * f1); // Purpur - } - - protected int getChestSlots() { -diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index 58af082b95a7eff44e2c71c3609a288a31d28d01..c3f36275943c1cd03b65a1c7c6fbb22d1af3a6e3 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -133,6 +133,7 @@ public abstract class EntityLiving extends Entity { +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 1a7866bed9cb7f0431454d3af4733de05c0cba78..30aabde3d6703eefcb6d57bab43666b97197ba1f 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -228,6 +228,7 @@ public abstract class EntityLiving extends Entity { // CraftBukkit start public int expToDrop; public int maxAirTicks = 300; + public float safeFallDistance = 3.0F; // Purpur - boolean forceDrops; - ArrayList drops = new ArrayList(); + public boolean forceDrops; + public ArrayList drops = new ArrayList(); public final org.bukkit.craftbukkit.attribute.CraftAttributeMap craftAttributes; -@@ -227,8 +228,8 @@ public abstract class EntityLiving extends Entity { +@@ -322,8 +323,8 @@ public abstract class EntityLiving extends Entity { this.cR(); } @@ -52,7 +27,7 @@ index 58af082b95a7eff44e2c71c3609a288a31d28d01..c3f36275943c1cd03b65a1c7c6fbb22d if (!iblockdata.isAir()) { double d1 = Math.min((double) (0.2F + f / 15.0F), 2.5D); -@@ -1695,7 +1696,7 @@ public abstract class EntityLiving extends Entity { +@@ -1790,7 +1791,7 @@ public abstract class EntityLiving extends Entity { MobEffect mobeffect = this.getEffect(MobEffects.JUMP); float f2 = mobeffect == null ? 0.0F : (float) (mobeffect.getAmplifier() + 1); @@ -61,11 +36,36 @@ index 58af082b95a7eff44e2c71c3609a288a31d28d01..c3f36275943c1cd03b65a1c7c6fbb22d } protected void playBlockStepSound() { +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java +index 1e41c45af6dbcf097d7d6104e63db637f199301a..cb6e2053d1315b65812e7bff8a17988b5b8ab0e4 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java +@@ -272,7 +272,7 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven + + @Override + protected int e(float f, float f1) { +- return MathHelper.f((f * 0.5F - 3.0F) * f1); ++ return MathHelper.f((f * 0.5F - this.safeFallDistance) * f1); // Purpur + } + + protected int getChestSlots() { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGiantZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityGiantZombie.java +index 3b004160da9a2aed440a3ccda538d78f91c61e87..5e6a92dcdbca686d5a8cfc4aaff72b70b81b111f 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityGiantZombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityGiantZombie.java +@@ -13,6 +13,7 @@ public class EntityGiantZombie extends EntityMonster { + + public EntityGiantZombie(EntityTypes entitytypes, World world) { + super(entitytypes, world); ++ this.safeFallDistance = 10.0F; // Purpur + } + + @Override diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index c1350bbf62fc5c5e18509f378edf16e8b210cfe8..84aeffac2c2c12d98e9cec05314668a93bb5ed91 100644 +index 3d497f69f89455b88fba423de8effb3db83e7af4..b5040de9885556561416bf3282476f3b33925a62 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -833,4 +833,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { +@@ -843,4 +843,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { getHandle().setHurtDirection(hurtDirection); } // Paper end diff --git a/patches/server/0013-Lagging-threshold.patch b/patches/server/0013-Lagging-threshold.patch index 5a141b04a..72dae110e 100644 --- a/patches/server/0013-Lagging-threshold.patch +++ b/patches/server/0013-Lagging-threshold.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Lagging threshold diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index eafff4dcf1088b77ecae317a28b5d65dec997a7b..5e647afa74950bcb09de630ac641b9d178ef71c2 100644 +index 2af7c84167f75f1d16d0fd74a4c8156502325446..34793bc4bd14dc7a34f32ccfec05cf50eb77cee2 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -167,6 +167,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant d; diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index c79623339cfe8fb8484bcc2a8c3eb119b9e83093..3a6a1f8ce0a30f2bdc08ec36fe9a2381439e7fa4 100644 +index 6966b9d1ce674232d3f867798fa58bd0933ff69e..1cc473eb4d346b1b498a7b170973fb44d8b8aea6 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java @@ -396,4 +396,18 @@ public final class CraftItemFactory implements ItemFactory { @@ -33,10 +33,10 @@ index c79623339cfe8fb8484bcc2a8c3eb119b9e83093..3a6a1f8ce0a30f2bdc08ec36fe9a2381 + return null; + } + String name = type.getKey().toString(); -+ net.minecraft.server.MinecraftKey key = new net.minecraft.server.MinecraftKey(name); -+ net.minecraft.server.EntityTypes types = net.minecraft.server.EntityTypes.getFromKey(key); -+ net.minecraft.server.ItemMonsterEgg egg = net.minecraft.server.ItemMonsterEgg.a.get(types); -+ return new net.minecraft.server.ItemStack(egg).asBukkitMirror(); ++ net.minecraft.resources.MinecraftKey key = new net.minecraft.resources.MinecraftKey(name); ++ net.minecraft.world.entity.EntityTypes types = net.minecraft.world.entity.EntityTypes.getFromKey(key); ++ net.minecraft.world.item.ItemMonsterEgg egg = net.minecraft.world.item.ItemMonsterEgg.a.get(types); ++ return new net.minecraft.world.item.ItemStack(egg).asBukkitMirror(); + } + // Purpur end } diff --git a/patches/server/0015-PlayerSetSpawnerTypeWithEggEvent.patch b/patches/server/0015-PlayerSetSpawnerTypeWithEggEvent.patch index 03bc3ec06..1956caf21 100644 --- a/patches/server/0015-PlayerSetSpawnerTypeWithEggEvent.patch +++ b/patches/server/0015-PlayerSetSpawnerTypeWithEggEvent.patch @@ -4,11 +4,11 @@ Date: Fri, 5 Jul 2019 18:21:00 -0500 Subject: [PATCH] PlayerSetSpawnerTypeWithEggEvent -diff --git a/src/main/java/net/minecraft/server/EntityTypes.java b/src/main/java/net/minecraft/server/EntityTypes.java -index 4410939423a75357cc2d16bc4a3b96a504942320..9575d5a8a9cf0beddc6d10da86a089b5425f2320 100644 ---- a/src/main/java/net/minecraft/server/EntityTypes.java -+++ b/src/main/java/net/minecraft/server/EntityTypes.java -@@ -145,6 +145,16 @@ public class EntityTypes { +diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java +index 7f70dda656ff9d802200f18139d2695e58c551c7..e858e41e046665016327f0ef3f19cf5db765fe3b 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityTypes.java ++++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java +@@ -276,6 +276,16 @@ public class EntityTypes { return (EntityTypes) IRegistry.a((IRegistry) IRegistry.ENTITY_TYPE, s, (Object) entitytypes_builder.a(s)); } @@ -25,7 +25,7 @@ index 4410939423a75357cc2d16bc4a3b96a504942320..9575d5a8a9cf0beddc6d10da86a089b5 public static MinecraftKey getName(EntityTypes entitytypes) { return IRegistry.ENTITY_TYPE.getKey(entitytypes); } -@@ -303,6 +313,16 @@ public class EntityTypes { +@@ -441,6 +451,16 @@ public class EntityTypes { return this.bg; } @@ -42,7 +42,7 @@ index 4410939423a75357cc2d16bc4a3b96a504942320..9575d5a8a9cf0beddc6d10da86a089b5 public String getDescriptionId() { return f(); } // Paper - OBFHELPER public String f() { if (this.bo == null) { -@@ -312,6 +332,7 @@ public class EntityTypes { +@@ -450,6 +470,7 @@ public class EntityTypes { return this.bo; } @@ -50,13 +50,13 @@ index 4410939423a75357cc2d16bc4a3b96a504942320..9575d5a8a9cf0beddc6d10da86a089b5 public IChatBaseComponent g() { if (this.bp == null) { this.bp = new ChatMessage(this.f()); -diff --git a/src/main/java/net/minecraft/server/ItemMonsterEgg.java b/src/main/java/net/minecraft/server/ItemMonsterEgg.java -index eeac4aeaf21b43647aa643ec55a1ae842a7ac197..d66acf90d0b1bcd5c6481d2a2ee753c7693995b0 100644 ---- a/src/main/java/net/minecraft/server/ItemMonsterEgg.java -+++ b/src/main/java/net/minecraft/server/ItemMonsterEgg.java -@@ -7,6 +7,13 @@ import java.util.Objects; - import java.util.Optional; - import javax.annotation.Nullable; +diff --git a/src/main/java/net/minecraft/world/item/ItemMonsterEgg.java b/src/main/java/net/minecraft/world/item/ItemMonsterEgg.java +index addddb64956c63563fc072b35cc511d31c9afd45..5e2d0246146af8bf1de1038f6a1953451b99f0f5 100644 +--- a/src/main/java/net/minecraft/world/item/ItemMonsterEgg.java ++++ b/src/main/java/net/minecraft/world/item/ItemMonsterEgg.java +@@ -33,6 +33,13 @@ import net.minecraft.world.phys.MovingObjectPosition; + import net.minecraft.world.phys.MovingObjectPositionBlock; + import net.minecraft.world.phys.Vec3D; +// Purpur start +import net.pl3x.purpur.event.PlayerSetSpawnerTypeWithEggEvent; @@ -68,7 +68,7 @@ index eeac4aeaf21b43647aa643ec55a1ae842a7ac197..d66acf90d0b1bcd5c6481d2a2ee753c7 public class ItemMonsterEgg extends Item { public static final Map, ItemMonsterEgg> a = Maps.newIdentityHashMap(); // Purpur - private -> public -@@ -41,6 +48,15 @@ public class ItemMonsterEgg extends Item { +@@ -67,6 +74,15 @@ public class ItemMonsterEgg extends Item { MobSpawnerAbstract mobspawnerabstract = ((TileEntityMobSpawner) tileentity).getSpawner(); EntityTypes entitytypes = this.a(itemstack.getTag()); diff --git a/patches/server/0016-EMC-MonsterEggSpawnEvent.patch b/patches/server/0016-EMC-MonsterEggSpawnEvent.patch index 19d322c9d..a7bf0ae04 100644 --- a/patches/server/0016-EMC-MonsterEggSpawnEvent.patch +++ b/patches/server/0016-EMC-MonsterEggSpawnEvent.patch @@ -4,11 +4,11 @@ Date: Sat, 20 Jul 2013 22:40:56 -0400 Subject: [PATCH] EMC - MonsterEggSpawnEvent -diff --git a/src/main/java/net/minecraft/server/EntityTypes.java b/src/main/java/net/minecraft/server/EntityTypes.java -index 9575d5a8a9cf0beddc6d10da86a089b5425f2320..eea7cf2121f447e0eb172224ae6a7d5c8fa4b10b 100644 ---- a/src/main/java/net/minecraft/server/EntityTypes.java -+++ b/src/main/java/net/minecraft/server/EntityTypes.java -@@ -189,13 +189,20 @@ public class EntityTypes { +diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java +index e858e41e046665016327f0ef3f19cf5db765fe3b..acf4cbfd9780f186880c595c8fac8d91b8f56e68 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityTypes.java ++++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java +@@ -320,13 +320,20 @@ public class EntityTypes { @Nullable public Entity spawnCreature(WorldServer worldserver, @Nullable ItemStack itemstack, @Nullable EntityHuman entityhuman, BlockPosition blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1) { @@ -27,22 +27,23 @@ index 9575d5a8a9cf0beddc6d10da86a089b5425f2320..eea7cf2121f447e0eb172224ae6a7d5c + // Purpur end // CraftBukkit start - return this.spawnCreature(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG); -+ return this.spawnCreature(worldserver, itemstack, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG); // Purpur ++ return this.spawnCreature(worldserver, itemstack, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG, null); // Purpur } @Nullable -@@ -214,8 +221,28 @@ public class EntityTypes { +@@ -351,9 +358,29 @@ public class EntityTypes { } } // Paper end + // Purpur start -+ return spawnCreature(worldserver, null, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1, spawnReason); ++ return spawnCreature(worldserver, null, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1, spawnReason, op); + } + + @Nullable -+ public T spawnCreature(WorldServer worldserver, @Nullable ItemStack itemstack, @Nullable NBTTagCompound nbttagcompound, @Nullable IChatBaseComponent ichatbasecomponent, @Nullable EntityHuman entityhuman, BlockPosition blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ public T spawnCreature(WorldServer worldserver, @Nullable ItemStack itemstack, @Nullable NBTTagCompound nbttagcompound, @Nullable IChatBaseComponent ichatbasecomponent, @Nullable EntityHuman entityhuman, BlockPosition blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason, @Nullable java.util.function.Consumer op) { + // Purpur end T t0 = this.createCreature(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1); + if (t0 != null && op != null) op.accept(t0); // Paper + // Purpur start + if (spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG && itemstack != null && t0 != null) { diff --git a/patches/server/0017-Player-invulnerabilities.patch b/patches/server/0017-Player-invulnerabilities.patch index 996d91d8a..db4086523 100644 --- a/patches/server/0017-Player-invulnerabilities.patch +++ b/patches/server/0017-Player-invulnerabilities.patch @@ -4,11 +4,11 @@ Date: Sat, 2 May 2020 20:55:44 -0500 Subject: [PATCH] Player invulnerabilities -diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index 9be41dab47230046e576f4472c4c1c23523aa28c..2660a87fcfbed135c834acc13db6c758a66ccf8c 100644 ---- a/src/main/java/net/minecraft/server/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/EntityPlayer.java -@@ -154,6 +154,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index f30dcbd26ed56ba8f1a99260722a0b395c220954..7cd1ae92768164b657af9febe9b4feb7fd02f55a 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -284,6 +284,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { this.canPickUpLoot = true; this.maxHealthCache = this.getMaxHealth(); this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper @@ -17,7 +17,7 @@ index 9be41dab47230046e576f4472c4c1c23523aa28c..2660a87fcfbed135c834acc13db6c758 } // Paper start public BlockPosition getPointInFront(double inFront) { -@@ -989,6 +991,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting { +@@ -1119,6 +1121,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } @@ -30,7 +30,7 @@ index 9be41dab47230046e576f4472c4c1c23523aa28c..2660a87fcfbed135c834acc13db6c758 @Override public boolean damageEntity(DamageSource damagesource, float f) { if (this.isInvulnerable(damagesource)) { -@@ -996,7 +1004,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { +@@ -1126,7 +1134,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } else { boolean flag = this.server.j() && this.canPvP() && "fall".equals(damagesource.translationIndex); @@ -39,7 +39,7 @@ index 9be41dab47230046e576f4472c4c1c23523aa28c..2660a87fcfbed135c834acc13db6c758 return false; } else { if (damagesource instanceof EntityDamageSource) { -@@ -1172,6 +1180,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { +@@ -1302,6 +1310,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } // Paper end @@ -47,7 +47,7 @@ index 9be41dab47230046e576f4472c4c1c23523aa28c..2660a87fcfbed135c834acc13db6c758 return this; } } -@@ -2358,9 +2367,17 @@ public class EntityPlayer extends EntityHuman implements ICrafting { +@@ -2488,9 +2497,17 @@ public class EntityPlayer extends EntityHuman implements ICrafting { @Override public boolean isFrozen() { // Paper - protected > public @@ -66,11 +66,11 @@ index 9be41dab47230046e576f4472c4c1c23523aa28c..2660a87fcfbed135c834acc13db6c758 @Override public Scoreboard getScoreboard() { return getBukkitEntity().getScoreboard().getHandle(); -diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index bba8dc8fd10dc34179ca3c8cf471fbb3739fa7b4..c586005b34c59710cf398e30924ff3653e0d62fd 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -1737,6 +1737,7 @@ public class PlayerConnection implements PacketListenerPlayIn { +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 789cf1652fec8346c1ea3ca47d9ac43c0765528a..a056adcae8c4c46ede25fdd33aeab616a1af3a76 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -1882,6 +1882,7 @@ public class PlayerConnection implements PacketListenerPlayIn { PlayerConnectionUtils.ensureMainThread(packetplayinresourcepackstatus, this, this.player.getWorldServer()); // Paper start PlayerResourcePackStatusEvent.Status packStatus = PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.status.ordinal()]; @@ -78,11 +78,11 @@ index bba8dc8fd10dc34179ca3c8cf471fbb3739fa7b4..c586005b34c59710cf398e30924ff365 player.getBukkitEntity().setResourcePackStatus(packStatus); this.server.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), packStatus)); // Paper end -diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java -index a12e58668e74f2287ddff5bedc00daf2b0a416c1..7f784709ab8c560fd2dae551b6c8c234a2d134c6 100644 ---- a/src/main/java/net/minecraft/server/PlayerList.java -+++ b/src/main/java/net/minecraft/server/PlayerList.java -@@ -914,6 +914,8 @@ public abstract class PlayerList { +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index ac98a3122ee30971b31761f3bc564b41d5ac879f..49acc6e43748a2d2a68f1b134421831b2feedd7b 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -998,6 +998,8 @@ public abstract class PlayerList { } // Paper end @@ -108,10 +108,10 @@ index 2578a4677d1ee060f687be531e696b7c7be89e84..c441fcea9b2b5a77b801c8a69541cf42 + } } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index abf2a6b9d18f04baa077ededa3562a30dbaa4fe4..8bf29aca4b5aa0d51ed3cda25b37d30e6c986848 100644 +index f4052aaa2235894b996d65c569a083f1a09b59a3..1ff48eae5e5b732fbd1e720c55e08a30669bebfa 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2498,5 +2498,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2507,5 +2507,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { public void resetIdleTimer() { getHandle().resetIdleTimer(); } diff --git a/patches/server/0018-Anvil-API.patch b/patches/server/0018-Anvil-API.patch index e7794f5ee..8465320bc 100644 --- a/patches/server/0018-Anvil-API.patch +++ b/patches/server/0018-Anvil-API.patch @@ -4,11 +4,25 @@ Date: Sun, 19 Apr 2020 00:17:56 -0500 Subject: [PATCH] Anvil API -diff --git a/src/main/java/net/minecraft/server/ContainerAnvil.java b/src/main/java/net/minecraft/server/ContainerAnvil.java -index fc2038df89f25c07f6f853f6df41fe9b203c3585..4aa6b035a6a8ea39401c6566cd286de39f60e942 100644 ---- a/src/main/java/net/minecraft/server/ContainerAnvil.java -+++ b/src/main/java/net/minecraft/server/ContainerAnvil.java -@@ -20,6 +20,8 @@ public class ContainerAnvil extends ContainerAnvilAbstract { +diff --git a/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java b/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java +index ae5674ae9c539720a657838a640050cd3b4dc5b5..1b2d633f3d5d735039f18f27fb1387bd5a74f0d8 100644 +--- a/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java ++++ b/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java +@@ -2,8 +2,13 @@ package net.minecraft.world.inventory; + + import java.util.Iterator; + import java.util.Map; ++ ++import net.minecraft.nbt.NBTTagInt; + import net.minecraft.network.chat.ChatComponentText; + import net.minecraft.network.chat.IChatBaseComponent; ++import net.minecraft.network.protocol.game.PacketPlayOutSetSlot; ++import net.minecraft.network.protocol.game.PacketPlayOutWindowData; ++import net.minecraft.server.level.EntityPlayer; + import net.minecraft.tags.Tag; + import net.minecraft.tags.TagsBlock; + import net.minecraft.world.entity.player.EntityHuman; +@@ -33,6 +38,8 @@ public class ContainerAnvil extends ContainerAnvilAbstract { public int maximumRepairCost = 40; private CraftInventoryView bukkitEntity; // CraftBukkit end @@ -17,7 +31,7 @@ index fc2038df89f25c07f6f853f6df41fe9b203c3585..4aa6b035a6a8ea39401c6566cd286de3 public ContainerAnvil(int i, PlayerInventory playerinventory) { this(i, playerinventory, ContainerAccess.a); -@@ -38,12 +40,14 @@ public class ContainerAnvil extends ContainerAnvilAbstract { +@@ -51,12 +58,14 @@ public class ContainerAnvil extends ContainerAnvilAbstract { @Override protected boolean b(EntityHuman entityhuman, boolean flag) { @@ -33,7 +47,7 @@ index fc2038df89f25c07f6f853f6df41fe9b203c3585..4aa6b035a6a8ea39401c6566cd286de3 entityhuman.levelDown(-this.levelCost.get()); } -@@ -94,6 +98,12 @@ public class ContainerAnvil extends ContainerAnvilAbstract { +@@ -107,6 +116,12 @@ public class ContainerAnvil extends ContainerAnvilAbstract { @Override public void e() { @@ -46,7 +60,7 @@ index fc2038df89f25c07f6f853f6df41fe9b203c3585..4aa6b035a6a8ea39401c6566cd286de3 ItemStack itemstack = this.repairInventory.getItem(0); this.levelCost.set(1); -@@ -170,7 +180,7 @@ public class ContainerAnvil extends ContainerAnvilAbstract { +@@ -183,7 +198,7 @@ public class ContainerAnvil extends ContainerAnvilAbstract { int i2 = (Integer) map1.get(enchantment); i2 = l1 == i2 ? i2 + 1 : Math.max(i2, l1); @@ -55,7 +69,7 @@ index fc2038df89f25c07f6f853f6df41fe9b203c3585..4aa6b035a6a8ea39401c6566cd286de3 if (this.player.abilities.canInstantlyBuild || itemstack.getItem() == Items.ENCHANTED_BOOK) { flag3 = true; -@@ -182,7 +192,7 @@ public class ContainerAnvil extends ContainerAnvilAbstract { +@@ -195,7 +210,7 @@ public class ContainerAnvil extends ContainerAnvilAbstract { Enchantment enchantment1 = (Enchantment) iterator1.next(); if (enchantment1 != enchantment && !enchantment.isCompatible(enchantment1)) { @@ -64,7 +78,7 @@ index fc2038df89f25c07f6f853f6df41fe9b203c3585..4aa6b035a6a8ea39401c6566cd286de3 ++i; } } -@@ -253,6 +263,13 @@ public class ContainerAnvil extends ContainerAnvilAbstract { +@@ -266,6 +281,13 @@ public class ContainerAnvil extends ContainerAnvilAbstract { this.levelCost.set(maximumRepairCost - 1); // CraftBukkit } @@ -78,7 +92,7 @@ index fc2038df89f25c07f6f853f6df41fe9b203c3585..4aa6b035a6a8ea39401c6566cd286de3 if (this.levelCost.get() >= maximumRepairCost && !this.player.abilities.canInstantlyBuild) { // CraftBukkit itemstack1 = ItemStack.b; } -@@ -274,6 +291,12 @@ public class ContainerAnvil extends ContainerAnvilAbstract { +@@ -287,6 +309,12 @@ public class ContainerAnvil extends ContainerAnvilAbstract { org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), itemstack1); // CraftBukkit this.c(); @@ -92,7 +106,7 @@ index fc2038df89f25c07f6f853f6df41fe9b203c3585..4aa6b035a6a8ea39401c6566cd286de3 } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryAnvil.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryAnvil.java -index 9374c27061280e51bcbae24573eb5d36736c3e4f..d45f356be39cbe271cd2a257b9dac66b88a346fd 100644 +index fd59f77d78a97898657919a77405b39ca24cddc9..151c478c6cb19d88000da46b6fbb952e97e58c95 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryAnvil.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryAnvil.java @@ -9,7 +9,7 @@ import org.bukkit.inventory.AnvilInventory; diff --git a/patches/server/0019-Configurable-villager-brain-ticks.patch b/patches/server/0019-Configurable-villager-brain-ticks.patch index 1313ce40e..ec7452386 100644 --- a/patches/server/0019-Configurable-villager-brain-ticks.patch +++ b/patches/server/0019-Configurable-villager-brain-ticks.patch @@ -4,11 +4,11 @@ Date: Tue, 23 Jul 2019 08:28:21 -0500 Subject: [PATCH] Configurable villager brain ticks -diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java -index 98b26a2f537594facb4ef32f9e3b6a81e41d6545..4491b2199acd4ba9706d82c7e69d80fbc6083344 100644 ---- a/src/main/java/net/minecraft/server/EntityVillager.java -+++ b/src/main/java/net/minecraft/server/EntityVillager.java -@@ -56,6 +56,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +index d8028675fc82883d716bcfb44431ca6ac7dfda36..5539c4cbea46398e92ab6ec56bb9b821e5f01e02 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +@@ -127,6 +127,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation }, MemoryModuleType.MEETING_POINT, (entityvillager, villageplacetype) -> { return villageplacetype == VillagePlaceType.s; }); @@ -16,7 +16,7 @@ index 98b26a2f537594facb4ef32f9e3b6a81e41d6545..4491b2199acd4ba9706d82c7e69d80fb public EntityVillager(EntityTypes entitytypes, World world) { this(entitytypes, world, VillagerType.PLAINS); -@@ -68,6 +69,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation +@@ -139,6 +140,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation this.getNavigation().d(true); this.setCanPickupLoot(true); this.setVillagerData(this.getVillagerData().withType(villagertype).withProfession(VillagerProfession.NONE)); @@ -24,7 +24,7 @@ index 98b26a2f537594facb4ef32f9e3b6a81e41d6545..4491b2199acd4ba9706d82c7e69d80fb } @Override -@@ -166,6 +168,10 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation +@@ -237,6 +239,10 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation protected void mobTick() { mobTick(false); } protected void mobTick(boolean inactive) { this.world.getMethodProfiler().enter("villagerBrain"); diff --git a/patches/server/0020-Alternative-Keepalive-Handling.patch b/patches/server/0020-Alternative-Keepalive-Handling.patch index 898dcc4fb..6538d8c40 100644 --- a/patches/server/0020-Alternative-Keepalive-Handling.patch +++ b/patches/server/0020-Alternative-Keepalive-Handling.patch @@ -4,11 +4,11 @@ Date: Fri, 11 Oct 2019 00:17:39 -0500 Subject: [PATCH] Alternative Keepalive Handling -diff --git a/src/main/java/net/minecraft/server/PacketPlayInKeepAlive.java b/src/main/java/net/minecraft/server/PacketPlayInKeepAlive.java -index 8e93f1540ba5f995489c1fbcec70d10b011cd9c3..470f92c4fb0919d052b19acff8dff533724fbcc1 100644 ---- a/src/main/java/net/minecraft/server/PacketPlayInKeepAlive.java -+++ b/src/main/java/net/minecraft/server/PacketPlayInKeepAlive.java -@@ -22,6 +22,7 @@ public class PacketPlayInKeepAlive implements Packet { +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInKeepAlive.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInKeepAlive.java +index b4c37287362907b8507d156b978ba5b9d961bb7b..9e6e6636539702507abb78515e002819661027af 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInKeepAlive.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInKeepAlive.java +@@ -24,6 +24,7 @@ public class PacketPlayInKeepAlive implements Packet { packetdataserializer.writeLong(this.a); } @@ -16,11 +16,11 @@ index 8e93f1540ba5f995489c1fbcec70d10b011cd9c3..470f92c4fb0919d052b19acff8dff533 public long b() { return this.a; } -diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index c586005b34c59710cf398e30924ff3653e0d62fd..be29ecfa00d53ad2067015a5261184b4157c604b 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -86,6 +86,7 @@ public class PlayerConnection implements PacketListenerPlayIn { +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index a056adcae8c4c46ede25fdd33aeab616a1af3a76..68200fe85fc4e66bb58dd35df306ba37604b6b94 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -231,6 +231,7 @@ public class PlayerConnection implements PacketListenerPlayIn { private long lastKeepAlive = SystemUtils.getMonotonicMillis(); private void setLastPing(long lastPing) { this.lastKeepAlive = lastPing;}; private long getLastPing() { return this.lastKeepAlive;}; // Paper - OBFHELPER private boolean awaitingKeepAlive; private void setPendingPing(boolean isPending) { this.awaitingKeepAlive = isPending;}; private boolean isPendingPing() { return this.awaitingKeepAlive;}; // Paper - OBFHELPER private long h; private void setKeepAliveID(long keepAliveID) { this.h = keepAliveID;}; private long getKeepAliveID() {return this.h; }; // Paper - OBFHELPER @@ -28,7 +28,7 @@ index c586005b34c59710cf398e30924ff3653e0d62fd..be29ecfa00d53ad2067015a5261184b4 // CraftBukkit start - multithreaded fields private volatile int chatThrottle; private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(PlayerConnection.class, "chatThrottle"); -@@ -220,6 +221,21 @@ public class PlayerConnection implements PacketListenerPlayIn { +@@ -365,6 +366,21 @@ public class PlayerConnection implements PacketListenerPlayIn { long currentTime = SystemUtils.getMonotonicMillis(); long elapsedTime = currentTime - this.getLastPing(); @@ -50,7 +50,7 @@ index c586005b34c59710cf398e30924ff3653e0d62fd..be29ecfa00d53ad2067015a5261184b4 if (this.isPendingPing()) { if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected PlayerConnection.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getName()); // more info -@@ -2908,6 +2924,16 @@ public class PlayerConnection implements PacketListenerPlayIn { +@@ -3053,6 +3069,16 @@ public class PlayerConnection implements PacketListenerPlayIn { @Override public void a(PacketPlayInKeepAlive packetplayinkeepalive) { @@ -68,7 +68,7 @@ index c586005b34c59710cf398e30924ff3653e0d62fd..be29ecfa00d53ad2067015a5261184b4 if (this.awaitingKeepAlive && packetplayinkeepalive.b() == this.h) { int i = (int) (SystemUtils.getMonotonicMillis() - this.lastKeepAlive); diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index a34ed978596f1a466b0b48e7db92ac4f1345a996..9593ac057ef5b79fb54501d7cce1e69e49102918 100644 +index b54ea480321a3d9153a89e842787b27875e43ef4..c856e5bd83f0b6582efdad036262511ff89ec49f 100644 --- a/src/main/java/net/pl3x/purpur/PurpurConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java @@ -155,6 +155,11 @@ public class PurpurConfig { diff --git a/patches/server/0021-Silk-touch-spawners.patch b/patches/server/0021-Silk-touch-spawners.patch index 45f82ecd6..5f72d5aaa 100644 --- a/patches/server/0021-Silk-touch-spawners.patch +++ b/patches/server/0021-Silk-touch-spawners.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Silk touch spawners diff --git a/src/main/java/io/papermc/paper/adventure/PaperAdventure.java b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java -index c45d48cef53476fa1602cebaa57c72894bba10d3..d563694540fd22c89ada65787d9e996eecee26f4 100644 +index 71938ad7b3494e803beca7e4022aad12a51f2096..0b77884d8134c328f8fd1bbb8230d260606dc5ee 100644 --- a/src/main/java/io/papermc/paper/adventure/PaperAdventure.java +++ b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java @@ -81,6 +81,7 @@ public final class PaperAdventure { @@ -16,12 +16,92 @@ index c45d48cef53476fa1602cebaa57c72894bba10d3..d563694540fd22c89ada65787d9e996e public static final PlainComponentSerializer PLAIN = PlainComponentSerializer.builder().flattener(FLATTENER).build(); static final GsonComponentSerializer GSON = GsonComponentSerializer.builder() .legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.INSTANCE) -diff --git a/src/main/java/net/minecraft/server/BlockMobSpawner.java b/src/main/java/net/minecraft/server/BlockMobSpawner.java -index 81e145ff0759322f74888c81df8d2133fece7144..567a6a064254d99ae6a931b91e6bdd94badb19fc 100644 ---- a/src/main/java/net/minecraft/server/BlockMobSpawner.java -+++ b/src/main/java/net/minecraft/server/BlockMobSpawner.java -@@ -1,5 +1,17 @@ - package net.minecraft.server; +diff --git a/src/main/java/net/minecraft/server/ItemSpawner.java b/src/main/java/net/minecraft/server/ItemSpawner.java +new file mode 100644 +index 0000000000000000000000000000000000000000..599672ed4d0fc412ad3c0fa2e9d9df7035694fa2 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/ItemSpawner.java +@@ -0,0 +1,35 @@ ++package net.minecraft.server; ++ ++import net.minecraft.core.BlockPosition; ++import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.world.entity.EntityTypes; ++import net.minecraft.world.entity.player.EntityHuman; ++import net.minecraft.world.item.ItemBlock; ++import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.level.World; ++import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.entity.TileEntity; ++import net.minecraft.world.level.block.entity.TileEntityMobSpawner; ++import net.minecraft.world.level.block.state.IBlockData; ++ ++public class ItemSpawner extends ItemBlock { ++ public ItemSpawner(Block block, Info info) { ++ super(block, info); ++ } ++ ++ @Override ++ protected boolean a(BlockPosition blockposition, World world, EntityHuman entityhuman, ItemStack itemstack, IBlockData iblockdata) { ++ boolean handled = super.a(blockposition, world, entityhuman, itemstack, iblockdata); ++ if (world.purpurConfig.silkTouchEnabled && entityhuman.getBukkitEntity().hasPermission("purpur.place.spawners")) { ++ TileEntity spawner = world.getTileEntity(blockposition); ++ if (spawner instanceof TileEntityMobSpawner && itemstack.hasTag()) { ++ NBTTagCompound tag = itemstack.getTag(); ++ if (tag.hasKey("Purpur.mob_type")) { ++ EntityTypes.getByName(tag.getString("Purpur.mob_type")).ifPresent(type -> ++ ((TileEntityMobSpawner) spawner).getSpawner().setMobName(type)); ++ } ++ } ++ } ++ return handled; ++ } ++} +diff --git a/src/main/java/net/minecraft/world/item/Items.java b/src/main/java/net/minecraft/world/item/Items.java +index fc5cc610e7ea584ce72600b9d9f47543265725bb..8e9a25495d76251a86268d3059e2960a86dc46b3 100644 +--- a/src/main/java/net/minecraft/world/item/Items.java ++++ b/src/main/java/net/minecraft/world/item/Items.java +@@ -2,6 +2,7 @@ package net.minecraft.world.item; + + import net.minecraft.core.IRegistry; + import net.minecraft.resources.MinecraftKey; ++import net.minecraft.server.ItemSpawner; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.EnumItemSlot; +@@ -193,7 +194,7 @@ public class Items { + public static final Item ct = a(Blocks.PURPUR_BLOCK, CreativeModeTab.b); + public static final Item cu = a(Blocks.PURPUR_PILLAR, CreativeModeTab.b); + public static final Item cv = a(Blocks.PURPUR_STAIRS, CreativeModeTab.b); +- public static final Item cw = a(Blocks.SPAWNER); ++ public static final Item cw = a(Blocks.SPAWNER, new ItemSpawner(Blocks.SPAWNER, new Item.Info().a(EnumItemRarity.EPIC))); // Purpur + public static final Item cx = a(Blocks.OAK_STAIRS, CreativeModeTab.b); + public static final Item cy = a(Blocks.CHEST, CreativeModeTab.c); + public static final Item cz = a(Blocks.DIAMOND_ORE, CreativeModeTab.b); +diff --git a/src/main/java/net/minecraft/world/level/block/BlockMobSpawner.java b/src/main/java/net/minecraft/world/level/block/BlockMobSpawner.java +index 287dd5f1b2b913df4029966860cd1a426947b187..af3c1a6307fb9e244226794508382d2ffa2aeb4b 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockMobSpawner.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockMobSpawner.java +@@ -1,14 +1,35 @@ + package net.minecraft.world.level.block; + + import net.minecraft.core.BlockPosition; ++import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.nbt.NBTTagList; ++import net.minecraft.nbt.NBTTagString; ++import net.minecraft.resources.MinecraftKey; + import net.minecraft.server.level.WorldServer; ++import net.minecraft.world.entity.EntityTypes; ++import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.item.enchantment.EnchantmentManager; ++import net.minecraft.world.item.enchantment.Enchantments; + import net.minecraft.world.level.IBlockAccess; ++import net.minecraft.world.level.World; + import net.minecraft.world.level.block.entity.TileEntity; + import net.minecraft.world.level.block.entity.TileEntityMobSpawner; + import net.minecraft.world.level.block.state.BlockBase; + import net.minecraft.world.level.block.state.IBlockData; +// Purpur start +import io.papermc.paper.adventure.PaperAdventure; @@ -38,7 +118,7 @@ index 81e145ff0759322f74888c81df8d2133fece7144..567a6a064254d99ae6a931b91e6bdd94 public class BlockMobSpawner extends BlockTileEntity { protected BlockMobSpawner(BlockBase.Info blockbase_info) { -@@ -11,6 +23,59 @@ public class BlockMobSpawner extends BlockTileEntity { +@@ -20,6 +41,59 @@ public class BlockMobSpawner extends BlockTileEntity { return new TileEntityMobSpawner(); } @@ -98,7 +178,7 @@ index 81e145ff0759322f74888c81df8d2133fece7144..567a6a064254d99ae6a931b91e6bdd94 @Override public void dropNaturally(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, ItemStack itemstack) { super.dropNaturally(iblockdata, worldserver, blockposition, itemstack); -@@ -23,6 +88,7 @@ public class BlockMobSpawner extends BlockTileEntity { +@@ -32,6 +106,7 @@ public class BlockMobSpawner extends BlockTileEntity { @Override public int getExpDrop(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, ItemStack itemstack) { @@ -106,59 +186,17 @@ index 81e145ff0759322f74888c81df8d2133fece7144..567a6a064254d99ae6a931b91e6bdd94 int i = 15 + worldserver.random.nextInt(15) + worldserver.random.nextInt(15); return i; -diff --git a/src/main/java/net/minecraft/server/ItemSpawner.java b/src/main/java/net/minecraft/server/ItemSpawner.java -new file mode 100644 -index 0000000000000000000000000000000000000000..5c7f73918542bbdbc8d8f97671f24091fc6cb83b ---- /dev/null -+++ b/src/main/java/net/minecraft/server/ItemSpawner.java -@@ -0,0 +1,23 @@ -+package net.minecraft.server; -+ -+public class ItemSpawner extends ItemBlock { -+ public ItemSpawner(Block block, Info info) { -+ super(block, info); -+ } -+ -+ @Override -+ protected boolean a(BlockPosition blockposition, World world, EntityHuman entityhuman, ItemStack itemstack, IBlockData iblockdata) { -+ boolean handled = super.a(blockposition, world, entityhuman, itemstack, iblockdata); -+ if (world.purpurConfig.silkTouchEnabled && entityhuman.getBukkitEntity().hasPermission("purpur.place.spawners")) { -+ TileEntity spawner = world.getTileEntity(blockposition); -+ if (spawner instanceof TileEntityMobSpawner && itemstack.hasTag()) { -+ NBTTagCompound tag = itemstack.getTag(); -+ if (tag.hasKey("Purpur.mob_type")) { -+ EntityTypes.getByName(tag.getString("Purpur.mob_type")).ifPresent(type -> -+ ((TileEntityMobSpawner) spawner).getSpawner().setMobName(type)); -+ } -+ } -+ } -+ return handled; -+ } -+} -diff --git a/src/main/java/net/minecraft/server/Items.java b/src/main/java/net/minecraft/server/Items.java -index 1c861bccc2652057cb154667a5bf7269092b2db4..67ebcbe4daa1ef3cef6ca43ec92befbe4156842e 100644 ---- a/src/main/java/net/minecraft/server/Items.java -+++ b/src/main/java/net/minecraft/server/Items.java -@@ -180,7 +180,7 @@ public class Items { - public static final Item ct = a(Blocks.PURPUR_BLOCK, CreativeModeTab.b); - public static final Item cu = a(Blocks.PURPUR_PILLAR, CreativeModeTab.b); - public static final Item cv = a(Blocks.PURPUR_STAIRS, CreativeModeTab.b); -- public static final Item cw = a(Blocks.SPAWNER); -+ public static final Item cw = a(Blocks.SPAWNER, new ItemSpawner(Blocks.SPAWNER, new Item.Info().a(EnumItemRarity.EPIC))); // Purpur - public static final Item cx = a(Blocks.OAK_STAIRS, CreativeModeTab.b); - public static final Item cy = a(Blocks.CHEST, CreativeModeTab.c); - public static final Item cz = a(Blocks.DIAMOND_ORE, CreativeModeTab.b); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index c7fb5a737cab0083c39732247acb8f4e87562894..ba89efb3159ab04a6239865967f93055cb6be7a9 100644 +index c7fb5a737cab0083c39732247acb8f4e87562894..10a6fcd70869719ed2b2d1442a83ab912e00c898 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -1,6 +1,12 @@ package net.pl3x.purpur; -+import net.minecraft.server.IRegistry; -+import net.minecraft.server.Item; -+import net.minecraft.server.Items; -+import net.minecraft.server.MinecraftKey; ++import net.minecraft.core.IRegistry; ++import net.minecraft.world.item.Item; ++import net.minecraft.world.item.Items; ++import net.minecraft.resources.MinecraftKey; import org.bukkit.configuration.ConfigurationSection; + +import java.util.ArrayList; diff --git a/patches/server/0022-MC-168772-Fix-Add-turtle-egg-block-options.patch b/patches/server/0022-MC-168772-Fix-Add-turtle-egg-block-options.patch index 2c3888d61..ae221310a 100644 --- a/patches/server/0022-MC-168772-Fix-Add-turtle-egg-block-options.patch +++ b/patches/server/0022-MC-168772-Fix-Add-turtle-egg-block-options.patch @@ -4,11 +4,27 @@ Date: Thu, 6 Jun 2019 22:15:46 -0500 Subject: [PATCH] MC-168772 Fix - Add turtle egg block options -diff --git a/src/main/java/net/minecraft/server/BlockTurtleEgg.java b/src/main/java/net/minecraft/server/BlockTurtleEgg.java -index 00c37493c28805558dea06a20973f32ab0359016..0f147dc938cef428452bd3137c68b52a78f9fbde 100644 ---- a/src/main/java/net/minecraft/server/BlockTurtleEgg.java -+++ b/src/main/java/net/minecraft/server/BlockTurtleEgg.java -@@ -163,6 +163,23 @@ public class BlockTurtleEgg extends Block { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockTurtleEgg.java b/src/main/java/net/minecraft/world/level/block/BlockTurtleEgg.java +index 6093d4c7431a286477c9be97163ea8d64168c3b0..04504901b1933ed760b34b8abb994de8ec340a4e 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockTurtleEgg.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockTurtleEgg.java +@@ -9,12 +9,15 @@ import net.minecraft.sounds.SoundEffects; + import net.minecraft.tags.Tag; + import net.minecraft.tags.TagsBlock; + import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EntityExperienceOrb; + import net.minecraft.world.entity.EntityLiving; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.ambient.EntityBat; + import net.minecraft.world.entity.animal.EntityTurtle; ++import net.minecraft.world.entity.item.EntityItem; + import net.minecraft.world.entity.monster.EntityZombie; + import net.minecraft.world.entity.player.EntityHuman; ++import net.minecraft.world.entity.vehicle.EntityMinecartAbstract; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.context.BlockActionContext; + import net.minecraft.world.level.GameRules; +@@ -189,6 +192,23 @@ public class BlockTurtleEgg extends Block { } private boolean a(World world, Entity entity) { @@ -34,7 +50,7 @@ index 00c37493c28805558dea06a20973f32ab0359016..0f147dc938cef428452bd3137c68b52a } } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index ba89efb3159ab04a6239865967f93055cb6be7a9..f403f9dc6cd148b9f9c901f27ce6a77d4225a53f 100644 +index 10a6fcd70869719ed2b2d1442a83ab912e00c898..2f18ca7ae23e913155f25fd07627f376e401ab0f 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -104,6 +104,15 @@ public class PurpurWorldConfig { diff --git a/patches/server/0023-Fix-vanilla-command-permission-handler.patch b/patches/server/0023-Fix-vanilla-command-permission-handler.patch index 6e928c666..6a393adb9 100644 --- a/patches/server/0023-Fix-vanilla-command-permission-handler.patch +++ b/patches/server/0023-Fix-vanilla-command-permission-handler.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Fix vanilla command permission handler diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java -index d9c47f3fc18266df3be1f564c01dfc3e26941380..cf35c9d545582173f81347a656faf1940892716f 100644 +index c0fac7369b111e65b896a15848ae22457e5e8914..5278997e522b495b83e53cac5968388d6eca45e4 100644 --- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java +++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java @@ -35,6 +35,7 @@ public abstract class CommandNode implements Comparable> { @@ -17,7 +17,7 @@ index d9c47f3fc18266df3be1f564c01dfc3e26941380..cf35c9d545582173f81347a656faf194 public void removeCommand(String name) { children.remove(name); diff --git a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java -index f34461460049a80c5ff57805927053a36a4db426..8d89e671eb9081f9198f2b2b2ae0b7bd186c1522 100644 +index 5702f18cd39c1e7b5614c28a628108e2204b2ec1..b069ee845b2011b2c669b6c75d0a773f52e06e10 100644 --- a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java +++ b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java @@ -87,6 +87,7 @@ public final class VanillaCommandWrapper extends BukkitCommand { diff --git a/patches/server/0024-Logger-settings-suppressing-pointless-logs.patch b/patches/server/0024-Logger-settings-suppressing-pointless-logs.patch index 467241dbd..cff6db86d 100644 --- a/patches/server/0024-Logger-settings-suppressing-pointless-logs.patch +++ b/patches/server/0024-Logger-settings-suppressing-pointless-logs.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Logger settings (suppressing pointless logs) diff --git a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -index c680319e4040be2b60795b22a5e65d6444cc67ed..eaa1063ff2bc5621e93043c4de41ca62f1323fde 100644 +index 7a8a1960882e291c46301d07da3e1c5415516893..59d781b5e61c5d2c004bc92300d8d42e81821308 100644 --- a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java +++ b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -@@ -170,6 +170,7 @@ public class AdvancementDataPlayer { +@@ -189,6 +189,7 @@ public class AdvancementDataPlayer { if (advancement == null) { // CraftBukkit start if (entry.getKey().getNamespace().equals("minecraft")) { @@ -17,7 +17,7 @@ index c680319e4040be2b60795b22a5e65d6444cc67ed..eaa1063ff2bc5621e93043c4de41ca62 } // CraftBukkit end diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index 9593ac057ef5b79fb54501d7cce1e69e49102918..ec8efc913f8f0bf6ff559a3a5b439a3d24f3a9b6 100644 +index c856e5bd83f0b6582efdad036262511ff89ec49f..d3c51f1083c4d4df8e413f47d0636ec829dc37a4 100644 --- a/src/main/java/net/pl3x/purpur/PurpurConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java @@ -178,4 +178,11 @@ public class PurpurConfig { @@ -33,7 +33,7 @@ index 9593ac057ef5b79fb54501d7cce1e69e49102918..ec8efc913f8f0bf6ff559a3a5b439a3d + } } diff --git a/src/main/java/org/bukkit/craftbukkit/legacy/CraftLegacy.java b/src/main/java/org/bukkit/craftbukkit/legacy/CraftLegacy.java -index b14333ce9e6921024bc93c2847b84f1fb40a5508..d25204f7d4af1ddd37005ccbcbe6c03d8eefcf47 100644 +index b86604cbf3543b978df000d8f74c6185aa2ae7ec..5df82b0409278bd298e837aa43941247de3f94fe 100644 --- a/src/main/java/org/bukkit/craftbukkit/legacy/CraftLegacy.java +++ b/src/main/java/org/bukkit/craftbukkit/legacy/CraftLegacy.java @@ -254,6 +254,7 @@ public final class CraftLegacy { diff --git a/patches/server/0025-Disable-outdated-build-check.patch b/patches/server/0025-Disable-outdated-build-check.patch index 87d21d81d..5cf42bd3c 100644 --- a/patches/server/0025-Disable-outdated-build-check.patch +++ b/patches/server/0025-Disable-outdated-build-check.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Disable outdated build check diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index a92721dff5c2a9a2a167b36c23d1ef22d2bbd3e1..b10873022efc8f01ef172e86cad07831d7bf0d5e 100644 +index d28088d510a4a40f3948f224a40a63de4645fa42..a471a3a4191872dae5da7e4f7b41de4491040d5d 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -259,7 +259,7 @@ public class Main { +@@ -261,7 +261,7 @@ public class Main { System.setProperty(TerminalConsoleAppender.JLINE_OVERRIDE_PROPERTY, "false"); // Paper } diff --git a/patches/server/0026-Giants-AI-settings.patch b/patches/server/0026-Giants-AI-settings.patch index 0c6dfa2ed..84798f012 100644 --- a/patches/server/0026-Giants-AI-settings.patch +++ b/patches/server/0026-Giants-AI-settings.patch @@ -4,11 +4,11 @@ Date: Sun, 12 May 2019 00:43:12 -0500 Subject: [PATCH] Giants AI settings -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 1d718095cf29ee70dd031b0c374e772774b8e11b..bc80d583104528a9cb3ffd1ea87e7b4dfc14c168 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -136,7 +136,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index c6b4af810fe3bda7797ab94316b2357178c9cd49..b7c72eaf5715a30bb8f82891f9830f9f62ec03c9 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -228,7 +228,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne public double D; public double E; public double F; @@ -17,11 +17,94 @@ index 1d718095cf29ee70dd031b0c374e772774b8e11b..bc80d583104528a9cb3ffd1ea87e7b4d public boolean noclip; public float I; protected final Random random; -diff --git a/src/main/java/net/minecraft/server/EntityGiantZombie.java b/src/main/java/net/minecraft/server/EntityGiantZombie.java -index 9f4f56c47ecd4b35ebf33ca0bf9a040074ababf2..565c938d879940d8e12fe320ea8524d2cf679c1f 100644 ---- a/src/main/java/net/minecraft/server/EntityGiantZombie.java -+++ b/src/main/java/net/minecraft/server/EntityGiantZombie.java -@@ -4,9 +4,66 @@ public class EntityGiantZombie extends EntityMonster { +diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +index f4440a5c4aedb1d7d303517f86a07c856dd1309b..7443fe924486404931c11793acc67e2f03de4e41 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java ++++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +@@ -1020,6 +1020,7 @@ public abstract class EntityInsentient extends EntityLiving { + return f; + } + ++ protected void setEquipmentBasedOnDifficulty(DifficultyDamageScaler difficultydamagescaler) { a(difficultydamagescaler); } // Purpur - OBFHELPER + protected void a(DifficultyDamageScaler difficultydamagescaler) { + if (this.random.nextFloat() < 0.15F * difficultydamagescaler.d()) { + int i = this.random.nextInt(2); +@@ -1127,6 +1128,7 @@ public abstract class EntityInsentient extends EntityLiving { + } + } + ++ protected void setEnchantmentBasedOnDifficulty(DifficultyDamageScaler difficultydamagescaler) { b(difficultydamagescaler); } // Purpur - OBFHELPER + protected void b(DifficultyDamageScaler difficultydamagescaler) { + float f = difficultydamagescaler.d(); + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 30aabde3d6703eefcb6d57bab43666b97197ba1f..ffc5ca763a22a1c4d06ffdb72c30482c13ec0a7b 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -261,6 +261,7 @@ public abstract class EntityLiving extends Entity { + this.activeItem = ItemStack.b; + this.by = Optional.empty(); + this.attributeMap = new AttributeMapBase(AttributeDefaults.a(entitytypes)); ++ this.initAttributes(); // Purpur + this.craftAttributes = new CraftAttributeMap(attributeMap); // CraftBukkit + // CraftBukkit - setHealth(getMaxHealth()) inlined and simplified to skip the instanceof check for EntityPlayer, as getBukkitEntity() is not initialized in constructor + this.datawatcher.set(EntityLiving.HEALTH, (float) this.getAttributeInstance(GenericAttributes.MAX_HEALTH).getValue()); +@@ -276,6 +277,8 @@ public abstract class EntityLiving extends Entity { + this.bg = this.a(new Dynamic(dynamicopsnbt, dynamicopsnbt.createMap((Map) ImmutableMap.of(dynamicopsnbt.createString("memories"), dynamicopsnbt.emptyMap())))); + } + ++ protected void initAttributes() {} // Purpur ++ + public BehaviorController getBehaviorController() { + return this.bg; + } +@@ -2276,7 +2279,7 @@ public abstract class EntityLiving extends Entity { + this.enderTeleportTo(vec3d.x, vec3d.y, vec3d.z); + } + +- protected float dJ() { ++ protected float dJ() { return getJumpHeight(); } public float getJumpHeight() { // Purpur - OBFHELPER + return 0.42F * this.getBlockJumpFactor(); + } + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGiantZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityGiantZombie.java +index 5e6a92dcdbca686d5a8cfc4aaff72b70b81b111f..a188a89143cb1b0243dacdec33c446ca4120219f 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityGiantZombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityGiantZombie.java +@@ -1,21 +1,99 @@ + package net.minecraft.world.entity.monster; + + import net.minecraft.core.BlockPosition; ++import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.world.DifficultyDamageScaler; ++import net.minecraft.world.EnumDifficulty; + import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySize; + import net.minecraft.world.entity.EntityTypes; ++import net.minecraft.world.entity.EnumItemSlot; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.ai.attributes.AttributeProvider; + import net.minecraft.world.entity.ai.attributes.GenericAttributes; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalLookAtPlayer; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalMeleeAttack; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalMoveTowardsRestriction; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalRandomLookaround; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalRandomStrollLand; ++import net.minecraft.world.entity.ai.goal.target.PathfinderGoalHurtByTarget; ++import net.minecraft.world.entity.ai.goal.target.PathfinderGoalNearestAttackableTarget; ++import net.minecraft.world.entity.animal.EntityIronGolem; ++import net.minecraft.world.entity.animal.EntityTurtle; ++import net.minecraft.world.entity.npc.EntityVillager; ++import net.minecraft.world.entity.player.EntityHuman; ++import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.item.Items; + import net.minecraft.world.level.IWorldReader; + import net.minecraft.world.level.World; ++import net.minecraft.world.level.WorldAccess; + + public class EntityGiantZombie extends EntityMonster { public EntityGiantZombie(EntityTypes entitytypes, World world) { super(entitytypes, world); @@ -89,7 +172,7 @@ index 9f4f56c47ecd4b35ebf33ca0bf9a040074ababf2..565c938d879940d8e12fe320ea8524d2 @Override protected float b(EntityPose entitypose, EntitySize entitysize) { return 10.440001F; -@@ -18,6 +75,6 @@ public class EntityGiantZombie extends EntityMonster { +@@ -27,6 +105,6 @@ public class EntityGiantZombie extends EntityMonster { @Override public float a(BlockPosition blockposition, IWorldReader iworldreader) { @@ -97,58 +180,8 @@ index 9f4f56c47ecd4b35ebf33ca0bf9a040074ababf2..565c938d879940d8e12fe320ea8524d2 + return super.a(blockposition, iworldreader); // Purpur - fix light requirements for natural spawns } } -diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java -index 81a91d63dd26a940c381b5a4f18eb60d42bbd61e..257f349217c55f6c02b42676bcd708c14e4a5fb8 100644 ---- a/src/main/java/net/minecraft/server/EntityInsentient.java -+++ b/src/main/java/net/minecraft/server/EntityInsentient.java -@@ -952,6 +952,7 @@ public abstract class EntityInsentient extends EntityLiving { - return f; - } - -+ protected void setEquipmentBasedOnDifficulty(DifficultyDamageScaler difficultydamagescaler) { a(difficultydamagescaler); } // Purpur - OBFHELPER - protected void a(DifficultyDamageScaler difficultydamagescaler) { - if (this.random.nextFloat() < 0.15F * difficultydamagescaler.d()) { - int i = this.random.nextInt(2); -@@ -1059,6 +1060,7 @@ public abstract class EntityInsentient extends EntityLiving { - } - } - -+ protected void setEnchantmentBasedOnDifficulty(DifficultyDamageScaler difficultydamagescaler) { b(difficultydamagescaler); } // Purpur - OBFHELPER - protected void b(DifficultyDamageScaler difficultydamagescaler) { - float f = difficultydamagescaler.d(); - -diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index c3f36275943c1cd03b65a1c7c6fbb22d1af3a6e3..57f2db9a975216408e4d7e646b0f907c11310502 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -166,6 +166,7 @@ public abstract class EntityLiving extends Entity { - this.activeItem = ItemStack.b; - this.by = Optional.empty(); - this.attributeMap = new AttributeMapBase(AttributeDefaults.a(entitytypes)); -+ this.initAttributes(); // Purpur - this.craftAttributes = new CraftAttributeMap(attributeMap); // CraftBukkit - // CraftBukkit - setHealth(getMaxHealth()) inlined and simplified to skip the instanceof check for EntityPlayer, as getBukkitEntity() is not initialized in constructor - this.datawatcher.set(EntityLiving.HEALTH, (float) this.getAttributeInstance(GenericAttributes.MAX_HEALTH).getValue()); -@@ -181,6 +182,8 @@ public abstract class EntityLiving extends Entity { - this.bg = this.a(new Dynamic(dynamicopsnbt, dynamicopsnbt.createMap((Map) ImmutableMap.of(dynamicopsnbt.createString("memories"), dynamicopsnbt.emptyMap())))); - } - -+ protected void initAttributes() {} // Purpur -+ - public BehaviorController getBehaviorController() { - return this.bg; - } -@@ -2181,7 +2184,7 @@ public abstract class EntityLiving extends Entity { - this.enderTeleportTo(vec3d.x, vec3d.y, vec3d.z); - } - -- protected float dJ() { -+ protected float dJ() { return getJumpHeight(); } public float getJumpHeight() { // Purpur - OBFHELPER - return 0.42F * this.getBlockJumpFactor(); - } - diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index f403f9dc6cd148b9f9c901f27ce6a77d4225a53f..3207b8b6166bd28796cb9c199c3ab466f7c0a02e 100644 +index 2f18ca7ae23e913155f25fd07627f376e401ab0f..1c87c929aaae17631100d1aa30b3e7ecce52686f 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -113,6 +113,28 @@ public class PurpurWorldConfig { diff --git a/patches/server/0027-Illusioners-AI-settings.patch b/patches/server/0027-Illusioners-AI-settings.patch index de8ef59bc..ffcf44acc 100644 --- a/patches/server/0027-Illusioners-AI-settings.patch +++ b/patches/server/0027-Illusioners-AI-settings.patch @@ -4,11 +4,11 @@ Date: Fri, 5 Jul 2019 11:09:25 -0500 Subject: [PATCH] Illusioners AI settings -diff --git a/src/main/java/net/minecraft/server/EntityIllagerIllusioner.java b/src/main/java/net/minecraft/server/EntityIllagerIllusioner.java -index 50442b3a498d1bab4270e69952a79f5182153ece..c57bf5091430709778dc21d70c8a32819c9d6639 100644 ---- a/src/main/java/net/minecraft/server/EntityIllagerIllusioner.java -+++ b/src/main/java/net/minecraft/server/EntityIllagerIllusioner.java -@@ -19,6 +19,15 @@ public class EntityIllagerIllusioner extends EntityIllagerWizard implements IRan +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java b/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java +index fee9a5140f097225b5da58b18bfbd528dffdc77b..cb092bee9d6827d4b0276bfa9b033cf7ca86ead4 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java +@@ -56,6 +56,15 @@ public class EntityIllagerIllusioner extends EntityIllagerWizard implements IRan } @@ -25,7 +25,7 @@ index 50442b3a498d1bab4270e69952a79f5182153ece..c57bf5091430709778dc21d70c8a3281 protected void initPathfinder() { super.initPathfinder(); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 3207b8b6166bd28796cb9c199c3ab466f7c0a02e..5c716a6b4f9ff33912ebb274b36eef70679ea87b 100644 +index 1c87c929aaae17631100d1aa30b3e7ecce52686f..d6bd971a62af7341f8dc8b3afe32786ced6fcd41 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -135,6 +135,20 @@ public class PurpurWorldConfig { diff --git a/patches/server/0028-Zombie-horse-naturally-spawn.patch b/patches/server/0028-Zombie-horse-naturally-spawn.patch index db9cb2244..520276bde 100644 --- a/patches/server/0028-Zombie-horse-naturally-spawn.patch +++ b/patches/server/0028-Zombie-horse-naturally-spawn.patch @@ -4,11 +4,19 @@ Date: Sun, 7 Jul 2019 19:52:16 -0500 Subject: [PATCH] Zombie horse naturally spawn -diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index 2d72803f1c52acf8bc069777351a3ef4d75f6e6c..1421c3036c9a374f65f30ebfb2ccc015560ee04c 100644 ---- a/src/main/java/net/minecraft/server/WorldServer.java -+++ b/src/main/java/net/minecraft/server/WorldServer.java -@@ -1128,12 +1128,18 @@ public class WorldServer extends World implements GeneratorAccessSeed { +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 984a90a0a69f60315536d60eff597f65b6d49c57..bdc1aaa02836cb675224062e59cd635c6fe6e28a 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -96,6 +96,7 @@ import net.minecraft.world.entity.ai.village.poi.VillagePlace; + import net.minecraft.world.entity.ai.village.poi.VillagePlaceType; + import net.minecraft.world.entity.animal.EntityAnimal; + import net.minecraft.world.entity.animal.EntityWaterAnimal; ++import net.minecraft.world.entity.animal.horse.EntityHorseAbstract; + import net.minecraft.world.entity.animal.horse.EntityHorseSkeleton; + import net.minecraft.world.entity.boss.EntityComplexPart; + import net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon; +@@ -1241,12 +1242,18 @@ public class WorldServer extends World implements GeneratorAccessSeed { boolean flag1 = this.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.b() * paperConfig.skeleHorseSpawnChance; // Paper if (flag1) { @@ -34,7 +42,7 @@ index 2d72803f1c52acf8bc069777351a3ef4d75f6e6c..1421c3036c9a374f65f30ebfb2ccc015 EntityLightning entitylightning = (EntityLightning) EntityTypes.LIGHTNING_BOLT.a((World) this); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 5c716a6b4f9ff33912ebb274b36eef70679ea87b..04dfb820053925c2835bdcec702d5a467a9fe48e 100644 +index d6bd971a62af7341f8dc8b3afe32786ced6fcd41..81b0e17a4bc5022ea757f03c2546808148d6e957 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -155,4 +155,9 @@ public class PurpurWorldConfig { diff --git a/patches/server/0029-Charged-creeper-naturally-spawn.patch b/patches/server/0029-Charged-creeper-naturally-spawn.patch index c35e4b077..3f2e7f991 100644 --- a/patches/server/0029-Charged-creeper-naturally-spawn.patch +++ b/patches/server/0029-Charged-creeper-naturally-spawn.patch @@ -4,11 +4,36 @@ Date: Fri, 29 Nov 2019 22:37:44 -0600 Subject: [PATCH] Charged creeper naturally spawn -diff --git a/src/main/java/net/minecraft/server/EntityCreeper.java b/src/main/java/net/minecraft/server/EntityCreeper.java -index b2f028422d9a7a84e49e383b78032feb887a85c0..ff80ac7db73b7c7dd6ac62ac128af1cab961d075 100644 ---- a/src/main/java/net/minecraft/server/EntityCreeper.java -+++ b/src/main/java/net/minecraft/server/EntityCreeper.java -@@ -24,6 +24,17 @@ public class EntityCreeper extends EntityMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java +index 9c8abb18c0ed850939b6691396f5d551e13c7af9..1986f6a672b97c1f0366bdb76e185815b8ca3bd6 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java +@@ -9,6 +9,7 @@ import net.minecraft.network.syncher.DataWatcherRegistry; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; ++import net.minecraft.world.DifficultyDamageScaler; + import net.minecraft.world.EnumHand; + import net.minecraft.world.EnumInteractionResult; + import net.minecraft.world.damagesource.DamageSource; +@@ -17,6 +18,8 @@ import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityAreaEffectCloud; + import net.minecraft.world.entity.EntityLightning; + import net.minecraft.world.entity.EntityTypes; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.ai.attributes.AttributeProvider; + import net.minecraft.world.entity.ai.attributes.GenericAttributes; + import net.minecraft.world.entity.ai.goal.PathfinderGoalAvoidTarget; +@@ -39,6 +42,7 @@ import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.World; + + // CraftBukkit start ++import net.minecraft.world.level.WorldAccess; + import org.bukkit.craftbukkit.event.CraftEventFactory; + import org.bukkit.event.entity.CreatureSpawnEvent; + import org.bukkit.event.entity.ExplosionPrimeEvent; +@@ -59,6 +63,17 @@ public class EntityCreeper extends EntityMonster { super(entitytypes, world); } @@ -27,7 +52,7 @@ index b2f028422d9a7a84e49e383b78032feb887a85c0..ff80ac7db73b7c7dd6ac62ac128af1ca protected void initPathfinder() { this.goalSelector.a(1, new PathfinderGoalFloat(this)); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 04dfb820053925c2835bdcec702d5a467a9fe48e..5b8961a061c4a877cfa856f6d9f6d77060060829 100644 +index 81b0e17a4bc5022ea757f03c2546808148d6e957..638ee71a78d9e75de6ddd7f0aec67a023bb8c06a 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -113,6 +113,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0030-Rabbit-naturally-spawn-toast-and-killer.patch b/patches/server/0030-Rabbit-naturally-spawn-toast-and-killer.patch index 4c7f3102e..53243413c 100644 --- a/patches/server/0030-Rabbit-naturally-spawn-toast-and-killer.patch +++ b/patches/server/0030-Rabbit-naturally-spawn-toast-and-killer.patch @@ -4,11 +4,11 @@ Date: Sat, 31 Aug 2019 17:47:11 -0500 Subject: [PATCH] Rabbit naturally spawn toast and killer -diff --git a/src/main/java/net/minecraft/server/EntityRabbit.java b/src/main/java/net/minecraft/server/EntityRabbit.java -index 80a4a71753a1fd9f62e75f0b4ea9307ed7072c4f..25a9b7906be35e981566610c7d08aa8df5050d74 100644 ---- a/src/main/java/net/minecraft/server/EntityRabbit.java -+++ b/src/main/java/net/minecraft/server/EntityRabbit.java -@@ -297,6 +297,10 @@ public class EntityRabbit extends EntityAnimal { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java b/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java +index dcbb07fb6ab799d4526a2da0614c193c7abba715..180fc927074dc683ad4d482a00dd4e04ff7923d0 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java +@@ -352,6 +352,10 @@ public class EntityRabbit extends EntityAnimal { if (!this.hasCustomName()) { this.setCustomName(new ChatMessage(SystemUtils.a("entity", EntityRabbit.bp))); } @@ -19,7 +19,7 @@ index 80a4a71753a1fd9f62e75f0b4ea9307ed7072c4f..25a9b7906be35e981566610c7d08aa8d } this.datawatcher.set(EntityRabbit.bo, i); -@@ -318,6 +322,16 @@ public class EntityRabbit extends EntityAnimal { +@@ -373,6 +377,16 @@ public class EntityRabbit extends EntityAnimal { } private int a(GeneratorAccess generatoraccess) { @@ -32,12 +32,12 @@ index 80a4a71753a1fd9f62e75f0b4ea9307ed7072c4f..25a9b7906be35e981566610c7d08aa8d + return 98; + } + // Purpur end -+ ++ BiomeBase biomebase = generatoraccess.getBiome(this.getChunkCoordinates()); int i = this.random.nextInt(100); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 5b8961a061c4a877cfa856f6d9f6d77060060829..f51f60110dd6117979b9d9b230065ad21135824c 100644 +index 638ee71a78d9e75de6ddd7f0aec67a023bb8c06a..6dcfbebd850d71587da5a78a3acf09d8ae413072 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -154,6 +154,13 @@ public class PurpurWorldConfig { diff --git a/patches/server/0031-Fix-outdated-server-showing-in-ping-before-server-fu.patch b/patches/server/0031-Fix-outdated-server-showing-in-ping-before-server-fu.patch index 40454d09d..fecb9d6b0 100644 --- a/patches/server/0031-Fix-outdated-server-showing-in-ping-before-server-fu.patch +++ b/patches/server/0031-Fix-outdated-server-showing-in-ping-before-server-fu.patch @@ -5,11 +5,11 @@ Subject: [PATCH] Fix 'outdated server' showing in ping before server fully boots -diff --git a/src/main/java/net/minecraft/server/PacketStatusListener.java b/src/main/java/net/minecraft/server/PacketStatusListener.java -index d0fad346dd4511722f958a8c0bda67492184fb62..1df22ad7b35d6bd974e7fe805920542654c1b9d0 100644 ---- a/src/main/java/net/minecraft/server/PacketStatusListener.java -+++ b/src/main/java/net/minecraft/server/PacketStatusListener.java -@@ -133,6 +133,7 @@ public class PacketStatusListener implements PacketStatusInListener { +diff --git a/src/main/java/net/minecraft/server/network/PacketStatusListener.java b/src/main/java/net/minecraft/server/network/PacketStatusListener.java +index e1997563984540e6edf5d3b697d029dc5f3c40e1..847c91305d23b99e612b9e5f988df14d3fb84a8c 100644 +--- a/src/main/java/net/minecraft/server/network/PacketStatusListener.java ++++ b/src/main/java/net/minecraft/server/network/PacketStatusListener.java +@@ -146,6 +146,7 @@ public class PacketStatusListener implements PacketStatusInListener { this.networkManager.sendPacket(new PacketStatusOutServerInfo(ping)); */ diff --git a/patches/server/0032-Make-Iron-Golems-Swim.patch b/patches/server/0032-Make-Iron-Golems-Swim.patch index 04f7ed161..13b90cada 100644 --- a/patches/server/0032-Make-Iron-Golems-Swim.patch +++ b/patches/server/0032-Make-Iron-Golems-Swim.patch @@ -4,11 +4,19 @@ Date: Sat, 15 Jun 2019 03:12:15 -0500 Subject: [PATCH] Make Iron Golems Swim -diff --git a/src/main/java/net/minecraft/server/EntityIronGolem.java b/src/main/java/net/minecraft/server/EntityIronGolem.java -index 0a5c27e732540e03c87e6da0fbdc6e3c2e382810..bdff2368836dca230a6622a205d5772834afc6ee 100644 ---- a/src/main/java/net/minecraft/server/EntityIronGolem.java -+++ b/src/main/java/net/minecraft/server/EntityIronGolem.java -@@ -24,6 +24,7 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java b/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java +index 5e2b49d120b724cb5a7ae00940ded4f4875ea8a1..62cff5faafa076d05ebc59ad5c4fb020bea0509e 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java +@@ -30,6 +30,7 @@ import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.IEntityAngerable; + import net.minecraft.world.entity.ai.attributes.AttributeProvider; + import net.minecraft.world.entity.ai.attributes.GenericAttributes; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat; + import net.minecraft.world.entity.ai.goal.PathfinderGoalLookAtPlayer; + import net.minecraft.world.entity.ai.goal.PathfinderGoalMeleeAttack; + import net.minecraft.world.entity.ai.goal.PathfinderGoalMoveTowardsTarget; +@@ -70,6 +71,7 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable { @Override protected void initPathfinder() { @@ -17,7 +25,7 @@ index 0a5c27e732540e03c87e6da0fbdc6e3c2e382810..bdff2368836dca230a6622a205d57728 this.goalSelector.a(2, new PathfinderGoalMoveTowardsTarget(this, 0.9D, 32.0F)); this.goalSelector.a(2, new PathfinderGoalStrollVillage(this, 0.6D, false)); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index f51f60110dd6117979b9d9b230065ad21135824c..3ec33a96396e49d1ddb9f7eea804e4ae8080efbd 100644 +index 6dcfbebd850d71587da5a78a3acf09d8ae413072..decd0e755deede2b092866a8f7f6b46520435bbe 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -154,6 +154,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0033-Dont-send-useless-entity-packets.patch b/patches/server/0033-Dont-send-useless-entity-packets.patch index 9b48e9bf5..a363d91e1 100644 --- a/patches/server/0033-Dont-send-useless-entity-packets.patch +++ b/patches/server/0033-Dont-send-useless-entity-packets.patch @@ -4,11 +4,32 @@ Date: Sat, 6 Jul 2019 17:00:04 -0500 Subject: [PATCH] Dont send useless entity packets -diff --git a/src/main/java/net/minecraft/server/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/EntityTrackerEntry.java -index 4b7e83e4f64a8bc4bf5b4ca569c32efefb0b3149..9f6d767ce8139999032d4c51221da743c694cb09 100644 ---- a/src/main/java/net/minecraft/server/EntityTrackerEntry.java -+++ b/src/main/java/net/minecraft/server/EntityTrackerEntry.java -@@ -180,6 +180,7 @@ public class EntityTrackerEntry { +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutEntity.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutEntity.java +index 0eed10a6c4e0c7245f219d19ed1e2e5c94364db9..2b54a5f3347f788b751892105f888663bb349629 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutEntity.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutEntity.java +@@ -9,11 +9,11 @@ import net.minecraft.world.phys.Vec3D; + public class PacketPlayOutEntity implements Packet { + + protected int a; +- protected short b; +- protected short c; +- protected short d; +- protected byte e; +- protected byte f; ++ protected short b; public short getX() { return b; } // Purpur - OBFHELPER ++ protected short c; public short getY() { return c; } // Purpur - OBFHELPER ++ protected short d; public short getZ() { return d; } // Purpur - OBFHELPER ++ protected byte e; public byte getYaw() { return e; } // Purpur - OBFHELPER ++ protected byte f; public byte getPitch() { return f; } // Purpur - OBFHELPER + protected boolean g; + protected boolean h; + protected boolean i; +diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java +index c830b257054b7f8153aa9225c1f61f49a6ea0a84..3a66a34db2b8ac612431131cea80e57ee72de05f 100644 +--- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java ++++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java +@@ -209,6 +209,7 @@ public class EntityTrackerEntry { this.o = 0; packet1 = new PacketPlayOutEntityTeleport(this.tracker); } @@ -16,7 +37,7 @@ index 4b7e83e4f64a8bc4bf5b4ca569c32efefb0b3149..9f6d767ce8139999032d4c51221da743 } if ((this.e || this.tracker.impulse || this.tracker instanceof EntityLiving && ((EntityLiving) this.tracker).isGliding()) && this.tickCounter > 0) { -@@ -273,6 +274,22 @@ public class EntityTrackerEntry { +@@ -302,6 +303,22 @@ public class EntityTrackerEntry { } @@ -39,29 +60,8 @@ index 4b7e83e4f64a8bc4bf5b4ca569c32efefb0b3149..9f6d767ce8139999032d4c51221da743 public void a(EntityPlayer entityplayer) { this.tracker.c(entityplayer); entityplayer.c(this.tracker); -diff --git a/src/main/java/net/minecraft/server/PacketPlayOutEntity.java b/src/main/java/net/minecraft/server/PacketPlayOutEntity.java -index 8e48407fd405ac4c3eece7762b8155c5d0f00fa0..91c4e658230bb8bbce9d0f56db0768a7c09f0095 100644 ---- a/src/main/java/net/minecraft/server/PacketPlayOutEntity.java -+++ b/src/main/java/net/minecraft/server/PacketPlayOutEntity.java -@@ -5,11 +5,11 @@ import java.io.IOException; - public class PacketPlayOutEntity implements Packet { - - protected int a; -- protected short b; -- protected short c; -- protected short d; -- protected byte e; -- protected byte f; -+ protected short b; public short getX() { return b; } // Purpur - OBFHELPER -+ protected short c; public short getY() { return c; } // Purpur - OBFHELPER -+ protected short d; public short getZ() { return d; } // Purpur - OBFHELPER -+ protected byte e; public byte getYaw() { return e; } // Purpur - OBFHELPER -+ protected byte f; public byte getPitch() { return f; } // Purpur - OBFHELPER - protected boolean g; - protected boolean h; - protected boolean i; diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index ec8efc913f8f0bf6ff559a3a5b439a3d24f3a9b6..a2f3c5c81d93814f89a778c8c58d36b416ea1efc 100644 +index d3c51f1083c4d4df8e413f47d0636ec829dc37a4..d12749a8084ede08d8efa80db279511f3c84b044 100644 --- a/src/main/java/net/pl3x/purpur/PurpurConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java @@ -179,6 +179,11 @@ public class PurpurConfig { diff --git a/patches/server/0034-Tulips-change-fox-type.patch b/patches/server/0034-Tulips-change-fox-type.patch index 1be434183..4c440e6ed 100644 --- a/patches/server/0034-Tulips-change-fox-type.patch +++ b/patches/server/0034-Tulips-change-fox-type.patch @@ -4,11 +4,20 @@ Date: Sat, 13 Jul 2019 15:56:22 -0500 Subject: [PATCH] Tulips change fox type -diff --git a/src/main/java/net/minecraft/server/EntityFox.java b/src/main/java/net/minecraft/server/EntityFox.java -index 56c119e8d11c5ffb1f90ac4249bce434b3e78884..8845afd83d47902d5192ec1a9146b6f20c5667d3 100644 ---- a/src/main/java/net/minecraft/server/EntityFox.java -+++ b/src/main/java/net/minecraft/server/EntityFox.java -@@ -37,9 +37,9 @@ public class EntityFox extends EntityAnimal { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java +index a3b714a9d63c6bb33a2731fb9293c9d155754b17..cea46348c0876e168376061fbaf258048e9358cb 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java +@@ -30,6 +30,8 @@ import net.minecraft.tags.Tag; + import net.minecraft.tags.TagsFluid; + import net.minecraft.util.MathHelper; + import net.minecraft.world.DifficultyDamageScaler; ++import net.minecraft.world.EnumHand; ++import net.minecraft.world.EnumInteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityAgeable; +@@ -107,9 +109,9 @@ public class EntityFox extends EntityAnimal { private static final Predicate bv = (entity) -> { return !entity.bx() && IEntitySelector.e.test(entity); }; @@ -21,7 +30,7 @@ index 56c119e8d11c5ffb1f90ac4249bce434b3e78884..8845afd83d47902d5192ec1a9146b6f2 private float bz; private float bA; private float bB; -@@ -227,6 +227,11 @@ public class EntityFox extends EntityAnimal { +@@ -297,6 +299,11 @@ public class EntityFox extends EntityAnimal { } private void initializePathFinderGoals() { @@ -33,7 +42,7 @@ index 56c119e8d11c5ffb1f90ac4249bce434b3e78884..8845afd83d47902d5192ec1a9146b6f2 if (this.getFoxType() == EntityFox.Type.RED) { this.targetSelector.a(4, this.bw); this.targetSelector.a(4, this.bx); -@@ -259,6 +264,7 @@ public class EntityFox extends EntityAnimal { +@@ -329,6 +336,7 @@ public class EntityFox extends EntityAnimal { public void setFoxType(EntityFox.Type entityfox_type) { this.datawatcher.set(EntityFox.bo, entityfox_type.b()); @@ -41,7 +50,7 @@ index 56c119e8d11c5ffb1f90ac4249bce434b3e78884..8845afd83d47902d5192ec1a9146b6f2 } private List fa() { -@@ -576,6 +582,27 @@ public class EntityFox extends EntityAnimal { +@@ -646,6 +654,27 @@ public class EntityFox extends EntityAnimal { return this.fa().contains(uuid); } @@ -69,11 +78,11 @@ index 56c119e8d11c5ffb1f90ac4249bce434b3e78884..8845afd83d47902d5192ec1a9146b6f2 @Override protected org.bukkit.event.entity.EntityDeathEvent d(DamageSource damagesource) { // Paper ItemStack itemstack = this.getEquipment(EnumItemSlot.MAINHAND).cloneItemStack(); // Paper -diff --git a/src/main/java/net/minecraft/server/Items.java b/src/main/java/net/minecraft/server/Items.java -index 67ebcbe4daa1ef3cef6ca43ec92befbe4156842e..4c379916d8d7797038d2980761c49f44c010dea8 100644 ---- a/src/main/java/net/minecraft/server/Items.java -+++ b/src/main/java/net/minecraft/server/Items.java -@@ -119,8 +119,8 @@ public class Items { +diff --git a/src/main/java/net/minecraft/world/item/Items.java b/src/main/java/net/minecraft/world/item/Items.java +index 8e9a25495d76251a86268d3059e2960a86dc46b3..993a88a5937417016821ef9d7cd58e4ee097491c 100644 +--- a/src/main/java/net/minecraft/world/item/Items.java ++++ b/src/main/java/net/minecraft/world/item/Items.java +@@ -133,8 +133,8 @@ public class Items { public static final Item bk = a(Blocks.ALLIUM, CreativeModeTab.c); public static final Item bl = a(Blocks.AZURE_BLUET, CreativeModeTab.c); public static final Item bm = a(Blocks.RED_TULIP, CreativeModeTab.c); @@ -85,7 +94,7 @@ index 67ebcbe4daa1ef3cef6ca43ec92befbe4156842e..4c379916d8d7797038d2980761c49f44 public static final Item bq = a(Blocks.OXEYE_DAISY, CreativeModeTab.c); public static final Item br = a(Blocks.CORNFLOWER, CreativeModeTab.c); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 3ec33a96396e49d1ddb9f7eea804e4ae8080efbd..459ff8ffe7c0bf09fe93d89b3433bc930bb52f06 100644 +index decd0e755deede2b092866a8f7f6b46520435bbe..081675005077c5070f7745e24fd2ee7400fe2320 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -118,6 +118,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0035-Breedable-Polar-Bears.patch b/patches/server/0035-Breedable-Polar-Bears.patch index f7eff4163..4a2ecee2c 100644 --- a/patches/server/0035-Breedable-Polar-Bears.patch +++ b/patches/server/0035-Breedable-Polar-Bears.patch @@ -4,11 +4,33 @@ Date: Thu, 26 Mar 2020 19:46:44 -0500 Subject: [PATCH] Breedable Polar Bears -diff --git a/src/main/java/net/minecraft/server/EntityPolarBear.java b/src/main/java/net/minecraft/server/EntityPolarBear.java -index 914c6e48d60ac8feadc08e52e050899fe1396a8d..99f0bd8f82520778d469ec51745034e6ebd3238a 100644 ---- a/src/main/java/net/minecraft/server/EntityPolarBear.java -+++ b/src/main/java/net/minecraft/server/EntityPolarBear.java -@@ -23,6 +23,30 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java b/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java +index 49f26d487229a732902d5bf48d305b0864e90d63..f25f5ced218555af0d62844a78842cfc7599d608 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java +@@ -34,6 +34,7 @@ import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.IEntityAngerable; + import net.minecraft.world.entity.ai.attributes.AttributeProvider; + import net.minecraft.world.entity.ai.attributes.GenericAttributes; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalBreed; + import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat; + import net.minecraft.world.entity.ai.goal.PathfinderGoalFollowParent; + import net.minecraft.world.entity.ai.goal.PathfinderGoalLookAtPlayer; +@@ -41,11 +42,13 @@ import net.minecraft.world.entity.ai.goal.PathfinderGoalMeleeAttack; + import net.minecraft.world.entity.ai.goal.PathfinderGoalPanic; + import net.minecraft.world.entity.ai.goal.PathfinderGoalRandomLookaround; + import net.minecraft.world.entity.ai.goal.PathfinderGoalRandomStroll; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalTempt; + import net.minecraft.world.entity.ai.goal.target.PathfinderGoalHurtByTarget; + import net.minecraft.world.entity.ai.goal.target.PathfinderGoalNearestAttackableTarget; + import net.minecraft.world.entity.ai.goal.target.PathfinderGoalUniversalAngerReset; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.item.crafting.RecipeItemStack; + import net.minecraft.world.level.GeneratorAccess; + import net.minecraft.world.level.World; + import net.minecraft.world.level.WorldAccess; +@@ -68,6 +71,30 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { super(entitytypes, world); } @@ -39,7 +61,7 @@ index 914c6e48d60ac8feadc08e52e050899fe1396a8d..99f0bd8f82520778d469ec51745034e6 @Override public EntityAgeable createChild(WorldServer worldserver, EntityAgeable entityageable) { return (EntityAgeable) EntityTypes.POLAR_BEAR.a((World) worldserver); -@@ -30,7 +54,7 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { +@@ -75,7 +102,7 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { @Override public boolean k(ItemStack itemstack) { @@ -48,7 +70,7 @@ index 914c6e48d60ac8feadc08e52e050899fe1396a8d..99f0bd8f82520778d469ec51745034e6 } @Override -@@ -39,6 +63,12 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { +@@ -84,6 +111,12 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { this.goalSelector.a(0, new PathfinderGoalFloat(this)); this.goalSelector.a(1, new EntityPolarBear.c()); this.goalSelector.a(1, new EntityPolarBear.d()); @@ -61,7 +83,7 @@ index 914c6e48d60ac8feadc08e52e050899fe1396a8d..99f0bd8f82520778d469ec51745034e6 this.goalSelector.a(4, new PathfinderGoalFollowParent(this, 1.25D)); this.goalSelector.a(5, new PathfinderGoalRandomStroll(this, 1.0D)); this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F)); -@@ -180,10 +210,12 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { +@@ -225,10 +258,12 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { return flag; } @@ -75,7 +97,7 @@ index 914c6e48d60ac8feadc08e52e050899fe1396a8d..99f0bd8f82520778d469ec51745034e6 this.datawatcher.set(EntityPolarBear.bo, flag); } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 459ff8ffe7c0bf09fe93d89b3433bc930bb52f06..09b66b9ca3185528d0bc5f0a1d811c5a42039339 100644 +index 081675005077c5070f7745e24fd2ee7400fe2320..fa43c015976aabaae8843983976c9c939a49016f 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -164,6 +164,14 @@ public class PurpurWorldConfig { diff --git a/patches/server/0036-Chickens-can-retaliate.patch b/patches/server/0036-Chickens-can-retaliate.patch index 853a05075..3fa2e23da 100644 --- a/patches/server/0036-Chickens-can-retaliate.patch +++ b/patches/server/0036-Chickens-can-retaliate.patch @@ -4,11 +4,24 @@ Date: Sun, 12 Apr 2020 13:19:34 -0500 Subject: [PATCH] Chickens can retaliate -diff --git a/src/main/java/net/minecraft/server/EntityChicken.java b/src/main/java/net/minecraft/server/EntityChicken.java -index 182469fd39cb23633a3225cf1a64ab6b291e4cdf..8fb5d5c75e79a81ab46af3fbb96ebc41804113c4 100644 ---- a/src/main/java/net/minecraft/server/EntityChicken.java -+++ b/src/main/java/net/minecraft/server/EntityChicken.java -@@ -17,16 +17,33 @@ public class EntityChicken extends EntityAnimal { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java b/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java +index cd6fb8efb20a2d32de59d479b1dbf5ee69d5df37..600d6ebdf554dbaa8ca46a22a12d8b4e3255d987 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java +@@ -20,10 +20,12 @@ import net.minecraft.world.entity.ai.goal.PathfinderGoalBreed; + import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat; + import net.minecraft.world.entity.ai.goal.PathfinderGoalFollowParent; + import net.minecraft.world.entity.ai.goal.PathfinderGoalLookAtPlayer; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalMeleeAttack; + import net.minecraft.world.entity.ai.goal.PathfinderGoalPanic; + import net.minecraft.world.entity.ai.goal.PathfinderGoalRandomLookaround; + import net.minecraft.world.entity.ai.goal.PathfinderGoalRandomStrollLand; + import net.minecraft.world.entity.ai.goal.PathfinderGoalTempt; ++import net.minecraft.world.entity.ai.goal.target.PathfinderGoalHurtByTarget; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +@@ -51,16 +53,33 @@ public class EntityChicken extends EntityAnimal { this.a(PathType.WATER, 0.0F); } @@ -43,7 +56,7 @@ index 182469fd39cb23633a3225cf1a64ab6b291e4cdf..8fb5d5c75e79a81ab46af3fbb96ebc41 } @Override -@@ -35,7 +52,7 @@ public class EntityChicken extends EntityAnimal { +@@ -69,7 +88,7 @@ public class EntityChicken extends EntityAnimal { } public static AttributeProvider.Builder eK() { @@ -53,7 +66,7 @@ index 182469fd39cb23633a3225cf1a64ab6b291e4cdf..8fb5d5c75e79a81ab46af3fbb96ebc41 @Override diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 09b66b9ca3185528d0bc5f0a1d811c5a42039339..c2a13de7f0cafc8c93c5255e0f65f5e8ad439c7a 100644 +index fa43c015976aabaae8843983976c9c939a49016f..78218f2d59203b8f2b286fd09b3f6bdebb47565c 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -113,6 +113,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0037-Add-option-to-set-armorstand-step-height.patch b/patches/server/0037-Add-option-to-set-armorstand-step-height.patch index cef5e3517..0a3d19160 100644 --- a/patches/server/0037-Add-option-to-set-armorstand-step-height.patch +++ b/patches/server/0037-Add-option-to-set-armorstand-step-height.patch @@ -4,11 +4,11 @@ Date: Sun, 6 Oct 2019 12:46:35 -0500 Subject: [PATCH] Add option to set armorstand step height -diff --git a/src/main/java/net/minecraft/server/EntityArmorStand.java b/src/main/java/net/minecraft/server/EntityArmorStand.java -index 0ef9516fbe9283cb1aca71eb9dbdbec0d98c8fa4..9e37bf25689691f9640b294c482978e8e3b6e627 100644 ---- a/src/main/java/net/minecraft/server/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/server/EntityArmorStand.java -@@ -625,6 +625,7 @@ public class EntityArmorStand extends EntityLiving { +diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java +index c0e0750adef0ae6aff7635c84f6585f06c5fc38d..89d3734489b65245e815376edf4e2d9baea1563a 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java +@@ -660,6 +660,7 @@ public class EntityArmorStand extends EntityLiving { @Override public void tick() { @@ -17,7 +17,7 @@ index 0ef9516fbe9283cb1aca71eb9dbdbec0d98c8fa4..9e37bf25689691f9640b294c482978e8 if (!this.canTick) { if (this.noTickPoseDirty) { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index c2a13de7f0cafc8c93c5255e0f65f5e8ad439c7a..0fa01267fa35f1afdc81c2636f9efa8506bcebb6 100644 +index 78218f2d59203b8f2b286fd09b3f6bdebb47565c..90f367f2f04f9bf66b7f54ffe784db16c7ca868b 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -63,6 +63,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0038-Cat-spawning-options.patch b/patches/server/0038-Cat-spawning-options.patch index 87d154a08..5ba975a93 100644 --- a/patches/server/0038-Cat-spawning-options.patch +++ b/patches/server/0038-Cat-spawning-options.patch @@ -4,23 +4,44 @@ Date: Thu, 26 Dec 2019 18:52:55 -0600 Subject: [PATCH] Cat spawning options -diff --git a/src/main/java/net/minecraft/server/IEntityAccess.java b/src/main/java/net/minecraft/server/IEntityAccess.java -index 2e514b8291a544a88667fbca2389bde4c2ecb109..288105ae657ade252032aa0ac9c191a8e8ebf549 100644 ---- a/src/main/java/net/minecraft/server/IEntityAccess.java -+++ b/src/main/java/net/minecraft/server/IEntityAccess.java -@@ -47,6 +47,7 @@ public interface IEntityAccess { - } +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java +index 13d94ecd703b3cd0412e138532d2dd74e5bf250d..6082eed2d28f3be65daa7e7eb6f2c2a89bb28ff1 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java ++++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java +@@ -191,6 +191,7 @@ public class VillagePlace extends RegionFileSection { + ((VillagePlaceSection) this.e(SectionPosition.a(blockposition).s())).a(blockposition); } -+ default List getEntitiesInAABB(Class oclass, AxisAlignedBB axisalignedbb) { return a(oclass, axisalignedbb); } // Purpur - OBFHELPER - default List a(Class oclass, AxisAlignedBB axisalignedbb) { - return this.a(oclass, axisalignedbb, IEntitySelector.g); ++ public long count(Predicate predicate, BlockPosition blockposition, int i, VillagePlace.Occupancy villageplace_occupancy) { return a(predicate, blockposition, i, villageplace_occupancy); } // Purpur - OBFHELPER + public long a(Predicate predicate, BlockPosition blockposition, int i, VillagePlace.Occupancy villageplace_occupancy) { + return this.c(predicate, blockposition, i, villageplace_occupancy).count(); } -diff --git a/src/main/java/net/minecraft/server/MobSpawnerCat.java b/src/main/java/net/minecraft/server/MobSpawnerCat.java -index 5e17868a76ea8e3f105c11d496d6da12afa0da41..5a0f8779672a9e34f6970045361630ab5af3990b 100644 ---- a/src/main/java/net/minecraft/server/MobSpawnerCat.java -+++ b/src/main/java/net/minecraft/server/MobSpawnerCat.java -@@ -16,7 +16,7 @@ public class MobSpawnerCat implements MobSpawner { +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlaceType.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlaceType.java +index db1ddce5774754891dc8a3ea5b66951ebc3a07a8..6a45ab049a4beeeaf7b3b5acf2946767f6e1198f 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlaceType.java ++++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlaceType.java +@@ -53,7 +53,7 @@ public class VillagePlaceType { + public static final VillagePlaceType o = a("shepherd", a(Blocks.LOOM), 1, 1); + public static final VillagePlaceType p = a("toolsmith", a(Blocks.SMITHING_TABLE), 1, 1); + public static final VillagePlaceType q = a("weaponsmith", a(Blocks.GRINDSTONE), 1, 1); +- public static final VillagePlaceType r = a("home", VillagePlaceType.z, 1, 1); ++ public static final VillagePlaceType r = a("home", VillagePlaceType.z, 1, 1); public static VillagePlaceType home() { return r; } // Purpur - OBFHELPER + public static final VillagePlaceType s = a("meeting", a(Blocks.BELL), 32, 6); + public static final VillagePlaceType t = a("beehive", a(Blocks.BEEHIVE), 0, 1); + public static final VillagePlaceType u = a("bee_nest", a(Blocks.BEE_NEST), 0, 1); +@@ -92,6 +92,7 @@ public class VillagePlaceType { + return this.D; + } + ++ public Predicate predicate() { return c(); } // Purpur - OBFHELPER + public Predicate c() { + return this.E; + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/MobSpawnerCat.java b/src/main/java/net/minecraft/world/entity/npc/MobSpawnerCat.java +index 7a495cf88d723790ee3f63645cb4792052284f32..2f54c26151c049df9d071c887dd33e48df041437 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/MobSpawnerCat.java ++++ b/src/main/java/net/minecraft/world/entity/npc/MobSpawnerCat.java +@@ -34,7 +34,7 @@ public class MobSpawnerCat implements MobSpawner { if (this.a > 0) { return 0; } else { @@ -29,7 +50,7 @@ index 5e17868a76ea8e3f105c11d496d6da12afa0da41..5a0f8779672a9e34f6970045361630ab EntityPlayer entityplayer = worldserver.q_(); if (entityplayer == null) { -@@ -50,10 +50,12 @@ public class MobSpawnerCat implements MobSpawner { +@@ -68,10 +68,12 @@ public class MobSpawnerCat implements MobSpawner { } private int a(WorldServer worldserver, BlockPosition blockposition) { @@ -46,7 +67,7 @@ index 5e17868a76ea8e3f105c11d496d6da12afa0da41..5a0f8779672a9e34f6970045361630ab if (list.size() < 5) { return this.a(blockposition, worldserver); -@@ -64,9 +66,11 @@ public class MobSpawnerCat implements MobSpawner { +@@ -82,9 +84,11 @@ public class MobSpawnerCat implements MobSpawner { } private int b(WorldServer worldserver, BlockPosition blockposition) { @@ -61,41 +82,20 @@ index 5e17868a76ea8e3f105c11d496d6da12afa0da41..5a0f8779672a9e34f6970045361630ab return list.size() < 1 ? this.a(blockposition, worldserver) : 0; } -diff --git a/src/main/java/net/minecraft/server/VillagePlace.java b/src/main/java/net/minecraft/server/VillagePlace.java -index 245bdedd17b844dcd13aa0b60dffb1cac6a5bdb8..64e251fb63e67b9ebf11779580b1bff6def6d1c6 100644 ---- a/src/main/java/net/minecraft/server/VillagePlace.java -+++ b/src/main/java/net/minecraft/server/VillagePlace.java -@@ -178,6 +178,7 @@ public class VillagePlace extends RegionFileSection { - ((VillagePlaceSection) this.e(SectionPosition.a(blockposition).s())).a(blockposition); +diff --git a/src/main/java/net/minecraft/world/level/IEntityAccess.java b/src/main/java/net/minecraft/world/level/IEntityAccess.java +index fd56b2f15e570f266a79c25823a3b3530a693510..18a5d11cce748695c8f03be565d2ea37a276a981 100644 +--- a/src/main/java/net/minecraft/world/level/IEntityAccess.java ++++ b/src/main/java/net/minecraft/world/level/IEntityAccess.java +@@ -56,6 +56,7 @@ public interface IEntityAccess { + } } -+ public long count(Predicate predicate, BlockPosition blockposition, int i, VillagePlace.Occupancy villageplace_occupancy) { return a(predicate, blockposition, i, villageplace_occupancy); } // Purpur - OBFHELPER - public long a(Predicate predicate, BlockPosition blockposition, int i, VillagePlace.Occupancy villageplace_occupancy) { - return this.c(predicate, blockposition, i, villageplace_occupancy).count(); - } -diff --git a/src/main/java/net/minecraft/server/VillagePlaceType.java b/src/main/java/net/minecraft/server/VillagePlaceType.java -index a5718af9b614ae505067131f04ebb490617d6aa4..b6b4c8c491d692f93d2c38d602ff99b0611b72aa 100644 ---- a/src/main/java/net/minecraft/server/VillagePlaceType.java -+++ b/src/main/java/net/minecraft/server/VillagePlaceType.java -@@ -44,7 +44,7 @@ public class VillagePlaceType { - public static final VillagePlaceType o = a("shepherd", a(Blocks.LOOM), 1, 1); - public static final VillagePlaceType p = a("toolsmith", a(Blocks.SMITHING_TABLE), 1, 1); - public static final VillagePlaceType q = a("weaponsmith", a(Blocks.GRINDSTONE), 1, 1); -- public static final VillagePlaceType r = a("home", VillagePlaceType.z, 1, 1); -+ public static final VillagePlaceType r = a("home", VillagePlaceType.z, 1, 1); public static VillagePlaceType home() { return r; } // Purpur - OBFHELPER - public static final VillagePlaceType s = a("meeting", a(Blocks.BELL), 32, 6); - public static final VillagePlaceType t = a("beehive", a(Blocks.BEEHIVE), 0, 1); - public static final VillagePlaceType u = a("bee_nest", a(Blocks.BEE_NEST), 0, 1); -@@ -83,6 +83,7 @@ public class VillagePlaceType { - return this.D; - } - -+ public Predicate predicate() { return c(); } // Purpur - OBFHELPER - public Predicate c() { - return this.E; ++ default List getEntitiesInAABB(Class oclass, AxisAlignedBB axisalignedbb) { return a(oclass, axisalignedbb); } // Purpur - OBFHELPER + default List a(Class oclass, AxisAlignedBB axisalignedbb) { + return this.a(oclass, axisalignedbb, IEntitySelector.g); } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 0fa01267fa35f1afdc81c2636f9efa8506bcebb6..9c5de125a6ed207f238dff1e17e38a4083c4c251 100644 +index 90f367f2f04f9bf66b7f54ffe784db16c7ca868b..9e935668147d1cd822f33c9e8d41e9541022aa8a 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -118,6 +118,15 @@ public class PurpurWorldConfig { diff --git a/patches/server/0039-MC-147659-Fix-non-black-cats-spawning-in-swamp-huts.patch b/patches/server/0039-MC-147659-Fix-non-black-cats-spawning-in-swamp-huts.patch index 3355e6bea..d57feb8e6 100644 --- a/patches/server/0039-MC-147659-Fix-non-black-cats-spawning-in-swamp-huts.patch +++ b/patches/server/0039-MC-147659-Fix-non-black-cats-spawning-in-swamp-huts.patch @@ -4,11 +4,11 @@ Date: Thu, 2 Jan 2020 01:23:22 -0600 Subject: [PATCH] MC-147659 - Fix non black cats spawning in swamp huts -diff --git a/src/main/java/net/minecraft/server/MobSpawnerCat.java b/src/main/java/net/minecraft/server/MobSpawnerCat.java -index 5a0f8779672a9e34f6970045361630ab5af3990b..25bb494350cd771166a78a7b14726cee8f01b02e 100644 ---- a/src/main/java/net/minecraft/server/MobSpawnerCat.java -+++ b/src/main/java/net/minecraft/server/MobSpawnerCat.java -@@ -80,8 +80,9 @@ public class MobSpawnerCat implements MobSpawner { +diff --git a/src/main/java/net/minecraft/world/entity/npc/MobSpawnerCat.java b/src/main/java/net/minecraft/world/entity/npc/MobSpawnerCat.java +index 2f54c26151c049df9d071c887dd33e48df041437..5d0da07970bfe304debe244e5df39981f90161f6 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/MobSpawnerCat.java ++++ b/src/main/java/net/minecraft/world/entity/npc/MobSpawnerCat.java +@@ -98,8 +98,9 @@ public class MobSpawnerCat implements MobSpawner { if (entitycat == null) { return 0; } else { diff --git a/patches/server/0040-Cows-eat-mushrooms.patch b/patches/server/0040-Cows-eat-mushrooms.patch index 28dace9cd..32aa6e245 100644 --- a/patches/server/0040-Cows-eat-mushrooms.patch +++ b/patches/server/0040-Cows-eat-mushrooms.patch @@ -4,11 +4,11 @@ Date: Sat, 4 May 2019 01:10:30 -0500 Subject: [PATCH] Cows eat mushrooms -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index bc80d583104528a9cb3ffd1ea87e7b4dfc14c168..983ed53eed9e15a14d83c68d72f004417cee2657 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -2794,6 +2794,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index b7c72eaf5715a30bb8f82891f9830f9f62ec03c9..c8071e2909c03bd8eafb92fbf8fd8701642df1f9 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2886,6 +2886,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne this.invulnerable = flag; } @@ -16,11 +16,40 @@ index bc80d583104528a9cb3ffd1ea87e7b4dfc14c168..983ed53eed9e15a14d83c68d72f00441 public void u(Entity entity) { this.setPositionRotation(entity.locX(), entity.locY(), entity.locZ(), entity.yaw, entity.pitch); } -diff --git a/src/main/java/net/minecraft/server/EntityCow.java b/src/main/java/net/minecraft/server/EntityCow.java -index 42e6761c8b18b79ffd3f4d5e853ea87a2c153c23..cfb009c811bd2908d38da1b0007cb7aaed4e42c3 100644 ---- a/src/main/java/net/minecraft/server/EntityCow.java -+++ b/src/main/java/net/minecraft/server/EntityCow.java -@@ -16,6 +16,7 @@ public class EntityCow extends EntityAnimal { +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index ffc5ca763a22a1c4d06ffdb72c30482c13ec0a7b..1902b706345ff0031aaa8babde8cabffced99b78 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -176,7 +176,7 @@ public abstract class EntityLiving extends Entity { + public int maxNoDamageTicks; + public final float ay; + public final float az; +- public float aA; ++ public float aA; public float getRenderYawOffset() { return this.aA; } public void setRenderYawOffset(float f) { this.aA = f; } // Purpur - OBFHELPER + public float aB; + public float aC; + public float aD; +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCow.java b/src/main/java/net/minecraft/world/entity/animal/EntityCow.java +index 1b43688ad232620410aa924cef02b54630ab1313..962dde5fcc617bc39b7d06a1e295370b9d60696c 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityCow.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityCow.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.entity.animal; + + import net.minecraft.core.BlockPosition; ++import net.minecraft.core.particles.Particles; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -28,6 +29,7 @@ import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.item.crafting.RecipeItemStack; + import net.minecraft.world.level.World; ++import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.IBlockData; + + // CraftBukkit start +@@ -46,6 +48,7 @@ public class EntityCow extends EntityAnimal { this.goalSelector.a(0, new PathfinderGoalFloat(this)); this.goalSelector.a(1, new PathfinderGoalPanic(this, 2.0D)); this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D)); @@ -28,7 +57,7 @@ index 42e6761c8b18b79ffd3f4d5e853ea87a2c153c23..cfb009c811bd2908d38da1b0007cb7aa this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.25D, RecipeItemStack.a(Items.WHEAT), false)); this.goalSelector.a(4, new PathfinderGoalFollowParent(this, 1.25D)); this.goalSelector.a(5, new PathfinderGoalRandomStrollLand(this, 1.0D)); -@@ -70,11 +71,80 @@ public class EntityCow extends EntityAnimal { +@@ -100,11 +103,80 @@ public class EntityCow extends EntityAnimal { entityhuman.a(enumhand, itemstack1); return EnumInteractionResult.a(this.world.isClientSide); @@ -109,21 +138,8 @@ index 42e6761c8b18b79ffd3f4d5e853ea87a2c153c23..cfb009c811bd2908d38da1b0007cb7aa @Override public EntityCow createChild(WorldServer worldserver, EntityAgeable entityageable) { return (EntityCow) EntityTypes.COW.a((World) worldserver); -diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index 57f2db9a975216408e4d7e646b0f907c11310502..0eae140eb55526e5eb88dab0e267b45fdef43ff6 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -81,7 +81,7 @@ public abstract class EntityLiving extends Entity { - public int maxNoDamageTicks; - public final float ay; - public final float az; -- public float aA; -+ public float aA; public float getRenderYawOffset() { return this.aA; } public void setRenderYawOffset(float f) { this.aA = f; } // Purpur - OBFHELPER - public float aB; - public float aC; - public float aD; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 9c5de125a6ed207f238dff1e17e38a4083c4c251..0c841b824a93d5e43bad171d1ca828eca3e891df 100644 +index 9e935668147d1cd822f33c9e8d41e9541022aa8a..277cc8361e8faf54b95be1e9f1467a97de14ecc4 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -132,6 +132,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0041-Fix-cow-rotation-when-shearing-mooshroom.patch b/patches/server/0041-Fix-cow-rotation-when-shearing-mooshroom.patch index aa8b1176b..6f2139403 100644 --- a/patches/server/0041-Fix-cow-rotation-when-shearing-mooshroom.patch +++ b/patches/server/0041-Fix-cow-rotation-when-shearing-mooshroom.patch @@ -4,11 +4,11 @@ Date: Fri, 3 May 2019 23:53:16 -0500 Subject: [PATCH] Fix cow rotation when shearing mooshroom -diff --git a/src/main/java/net/minecraft/server/EntityMushroomCow.java b/src/main/java/net/minecraft/server/EntityMushroomCow.java -index c9112f783c81d58570e622a0e784da1e2a93d0ff..91cfe60f764a573e3724b48a9ae02e806c1e4fb8 100644 ---- a/src/main/java/net/minecraft/server/EntityMushroomCow.java -+++ b/src/main/java/net/minecraft/server/EntityMushroomCow.java -@@ -136,7 +136,13 @@ public class EntityMushroomCow extends EntityCow implements IShearable { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java b/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java +index 9face4480dcc89d9106ebe596020c1888350ef2d..d28d4d2c1eff2c130f49c2bce3c19da212dba5dc 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java +@@ -172,7 +172,13 @@ public class EntityMushroomCow extends EntityCow implements IShearable { entitycow.setPositionRotation(this.locX(), this.locY(), this.locZ(), this.yaw, this.pitch); entitycow.setHealth(this.getHealth()); diff --git a/patches/server/0042-Pigs-give-saddle-back.patch b/patches/server/0042-Pigs-give-saddle-back.patch index 5d5df6e57..4645c333f 100644 --- a/patches/server/0042-Pigs-give-saddle-back.patch +++ b/patches/server/0042-Pigs-give-saddle-back.patch @@ -4,11 +4,11 @@ Date: Sun, 12 May 2019 01:14:46 -0500 Subject: [PATCH] Pigs give saddle back -diff --git a/src/main/java/net/minecraft/server/EntityPig.java b/src/main/java/net/minecraft/server/EntityPig.java -index 01ca5983cade997b1f0d27fdf495c74c6daa0922..6ea3e4ffc3f42f4282adf3554944f24d92ca2079 100644 ---- a/src/main/java/net/minecraft/server/EntityPig.java -+++ b/src/main/java/net/minecraft/server/EntityPig.java -@@ -109,6 +109,18 @@ public class EntityPig extends EntityAnimal implements ISteerable, ISaddleable { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java +index 676ca381a5e111fc15f319e73504e4e60dbf0d2b..1a540e41e6161d011ca4ed30c68ae9df4567b8db 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java +@@ -156,6 +156,18 @@ public class EntityPig extends EntityAnimal implements ISteerable, ISaddleable { if (!flag && this.hasSaddle() && !this.isVehicle() && !entityhuman.eq()) { if (!this.world.isClientSide) { @@ -28,7 +28,7 @@ index 01ca5983cade997b1f0d27fdf495c74c6daa0922..6ea3e4ffc3f42f4282adf3554944f24d } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 0c841b824a93d5e43bad171d1ca828eca3e891df..24ef91788ff69004eed1b136a0ceb6176db00e76 100644 +index 277cc8361e8faf54b95be1e9f1467a97de14ecc4..5ac1aba522151c42255caf9d29c5b780218ccd32 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -188,6 +188,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0043-Snowman-drop-and-put-back-pumpkin.patch b/patches/server/0043-Snowman-drop-and-put-back-pumpkin.patch index e6f2006dc..42df6eaea 100644 --- a/patches/server/0043-Snowman-drop-and-put-back-pumpkin.patch +++ b/patches/server/0043-Snowman-drop-and-put-back-pumpkin.patch @@ -4,11 +4,11 @@ Date: Fri, 3 May 2019 23:58:44 -0500 Subject: [PATCH] Snowman drop and put back pumpkin -diff --git a/src/main/java/net/minecraft/server/EntitySnowman.java b/src/main/java/net/minecraft/server/EntitySnowman.java -index a11c599a9779aa084a1d7d1b6b3485d5b9c23906..c39f3c06eb199a24f32a5c581e877073b580502c 100644 ---- a/src/main/java/net/minecraft/server/EntitySnowman.java -+++ b/src/main/java/net/minecraft/server/EntitySnowman.java -@@ -124,6 +124,14 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java b/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java +index b1e2892c7c9f0e35f69332e93917593d97c304a8..44119f52a4f169ffcea53fb69393bfedfd1a62a7 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java +@@ -160,6 +160,14 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt } return EnumInteractionResult.a(this.world.isClientSide); @@ -23,7 +23,7 @@ index a11c599a9779aa084a1d7d1b6b3485d5b9c23906..c39f3c06eb199a24f32a5c581e877073 } else { return EnumInteractionResult.PASS; } -@@ -134,6 +142,7 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt +@@ -170,6 +178,7 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt this.world.playSound((EntityHuman) null, (Entity) this, SoundEffects.ENTITY_SNOW_GOLEM_SHEAR, soundcategory, 1.0F, 1.0F); if (!this.world.s_()) { this.setHasPumpkin(false); @@ -32,7 +32,7 @@ index a11c599a9779aa084a1d7d1b6b3485d5b9c23906..c39f3c06eb199a24f32a5c581e877073 } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 24ef91788ff69004eed1b136a0ceb6176db00e76..609307a409365829e61430da47aa75125afcb8c4 100644 +index 5ac1aba522151c42255caf9d29c5b780218ccd32..fa01ef3c0cc723acaaf348066cddf91f1deb3c72 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -208,6 +208,13 @@ public class PurpurWorldConfig { diff --git a/patches/server/0044-Ender-dragon-always-drop-full-exp.patch b/patches/server/0044-Ender-dragon-always-drop-full-exp.patch index 1f34cc0d6..9dd6fd48b 100644 --- a/patches/server/0044-Ender-dragon-always-drop-full-exp.patch +++ b/patches/server/0044-Ender-dragon-always-drop-full-exp.patch @@ -4,11 +4,11 @@ Date: Sat, 24 Aug 2019 14:42:54 -0500 Subject: [PATCH] Ender dragon always drop full exp -diff --git a/src/main/java/net/minecraft/server/EntityEnderDragon.java b/src/main/java/net/minecraft/server/EntityEnderDragon.java -index 50b93c93cfede2d64a996a22b811994b352149af..de025a48c7ca08d8ae71d2d9239121dc4a86a339 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/server/EntityEnderDragon.java -@@ -564,7 +564,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +index 07160de8725787551df327c0790b2d6e0876524f..3fff101637708a1a12f9a457bd3512ae94a8f884 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +@@ -613,7 +613,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { boolean flag = this.world.getGameRules().getBoolean(GameRules.DO_MOB_LOOT); short short0 = 500; @@ -18,7 +18,7 @@ index 50b93c93cfede2d64a996a22b811994b352149af..de025a48c7ca08d8ae71d2d9239121dc } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 609307a409365829e61430da47aa75125afcb8c4..66c0725c3dc28e49387d2b9f1a15aa0758763c08 100644 +index fa01ef3c0cc723acaaf348066cddf91f1deb3c72..bab91f0416f31a8273593bb7725658674eb41621 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -142,6 +142,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0045-Signs-editable-on-right-click.patch b/patches/server/0045-Signs-editable-on-right-click.patch index c217038d0..706c4e9aa 100644 --- a/patches/server/0045-Signs-editable-on-right-click.patch +++ b/patches/server/0045-Signs-editable-on-right-click.patch @@ -4,11 +4,19 @@ Date: Fri, 24 May 2019 02:39:25 -0500 Subject: [PATCH] Signs editable on right click -diff --git a/src/main/java/net/minecraft/server/BlockSign.java b/src/main/java/net/minecraft/server/BlockSign.java -index 3585fd82c14338a82302ca403e91e6cfe65e1c19..770ad5edfb44acb69e7da33226ca6bf7c01a77b7 100644 ---- a/src/main/java/net/minecraft/server/BlockSign.java -+++ b/src/main/java/net/minecraft/server/BlockSign.java -@@ -56,6 +56,17 @@ public abstract class BlockSign extends BlockTileEntity implements IBlockWaterlo +diff --git a/src/main/java/net/minecraft/world/level/block/BlockSign.java b/src/main/java/net/minecraft/world/level/block/BlockSign.java +index 6b461080439dd9ce5b8d34b79d446558bbd5c1f1..19f4403b9f1142c71e7b2c7c0fd5a78027d4ffe4 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockSign.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockSign.java +@@ -6,6 +6,7 @@ import net.minecraft.world.EnumHand; + import net.minecraft.world.EnumInteractionResult; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.ItemDye; ++import net.minecraft.world.item.ItemSign; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.GeneratorAccess; + import net.minecraft.world.level.IBlockAccess; +@@ -80,6 +81,17 @@ public abstract class BlockSign extends BlockTileEntity implements IBlockWaterlo } } @@ -26,11 +34,11 @@ index 3585fd82c14338a82302ca403e91e6cfe65e1c19..770ad5edfb44acb69e7da33226ca6bf7 return tileentitysign.b(entityhuman) ? EnumInteractionResult.SUCCESS : EnumInteractionResult.PASS; } else { return EnumInteractionResult.PASS; -diff --git a/src/main/java/net/minecraft/server/TileEntitySign.java b/src/main/java/net/minecraft/server/TileEntitySign.java -index 3c7847b1156a486e253a0e9f74a857e841d90619..1e6bb566c0a718bba289b2e727a832e0aa6b7f15 100644 ---- a/src/main/java/net/minecraft/server/TileEntitySign.java -+++ b/src/main/java/net/minecraft/server/TileEntitySign.java -@@ -112,6 +112,7 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java +index 7f78f388584899b13ff983f0dc37c679bfb1507e..96d0524482281f8570464962c0fd5319199440d7 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java +@@ -132,6 +132,7 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // return this.isEditable; } @@ -39,7 +47,7 @@ index 3c7847b1156a486e253a0e9f74a857e841d90619..1e6bb566c0a718bba289b2e727a832e0 // Paper start //this.c = entityhuman; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 66c0725c3dc28e49387d2b9f1a15aa0758763c08..8393a0253ac16a8f15f78288d6cc31f8688c403c 100644 +index bab91f0416f31a8273593bb7725658674eb41621..ea95a4116371d58eb36be51093af7f0fa28e3dfd 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -109,6 +109,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0046-Signs-allow-color-codes.patch b/patches/server/0046-Signs-allow-color-codes.patch index 0a89a030f..542180f7a 100644 --- a/patches/server/0046-Signs-allow-color-codes.patch +++ b/patches/server/0046-Signs-allow-color-codes.patch @@ -4,11 +4,11 @@ Date: Thu, 6 Jun 2019 17:40:30 -0500 Subject: [PATCH] Signs allow color codes -diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index 2660a87fcfbed135c834acc13db6c758a66ccf8c..e03c80f4b61e211c104e809d52d16a400b713f00 100644 ---- a/src/main/java/net/minecraft/server/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/EntityPlayer.java -@@ -1449,6 +1449,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 7cd1ae92768164b657af9febe9b4feb7fd02f55a..fe583fbc58309564d35d4cdd56fafc4de8ba31c8 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -1579,6 +1579,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { @Override public void openSign(TileEntitySign tileentitysign) { @@ -16,11 +16,11 @@ index 2660a87fcfbed135c834acc13db6c758a66ccf8c..e03c80f4b61e211c104e809d52d16a40 tileentitysign.a((EntityHuman) this); this.playerConnection.sendPacket(new PacketPlayOutOpenSignEditor(tileentitysign.getPosition())); } -diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index be29ecfa00d53ad2067015a5261184b4157c604b..4d0dcbcc00e44c4912302dd0e7331471f33cb370 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -2902,6 +2902,15 @@ public class PlayerConnection implements PacketListenerPlayIn { +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 68200fe85fc4e66bb58dd35df306ba37604b6b94..bbb3b44bdceb8fb0363f771b8cf1b8245b5c8d3d 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -3047,6 +3047,15 @@ public class PlayerConnection implements PacketListenerPlayIn { } } // Paper end @@ -36,19 +36,19 @@ index be29ecfa00d53ad2067015a5261184b4157c604b..4d0dcbcc00e44c4912302dd0e7331471 lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(currentLine))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. } SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); -diff --git a/src/main/java/net/minecraft/server/TileEntitySign.java b/src/main/java/net/minecraft/server/TileEntitySign.java -index 1e6bb566c0a718bba289b2e727a832e0aa6b7f15..b2afbf72ccf467d01449d75bc5123eb1816afd03 100644 ---- a/src/main/java/net/minecraft/server/TileEntitySign.java -+++ b/src/main/java/net/minecraft/server/TileEntitySign.java +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java +index 96d0524482281f8570464962c0fd5319199440d7..a87a2fa507dc3bd6d9979db5868e7ef6ea1eddbd 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java @@ -1,6 +1,7 @@ - package net.minecraft.server; + package net.minecraft.world.level.block.entity; import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.papermc.paper.adventure.PaperAdventure; // Purpur import javax.annotation.Nullable; - - public class TileEntitySign extends TileEntity implements ICommandListener { // CraftBukkit - implements -@@ -92,6 +93,18 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // + import net.minecraft.commands.CommandListenerWrapper; + import net.minecraft.commands.ICommandListener; +@@ -112,6 +113,18 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // this.g[i] = null; } @@ -68,7 +68,7 @@ index 1e6bb566c0a718bba289b2e727a832e0aa6b7f15..b2afbf72ccf467d01449d75bc5123eb1 @Override public PacketPlayOutTileEntityData getUpdatePacket() { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 8393a0253ac16a8f15f78288d6cc31f8688c403c..484da2bf267cab4e4569c98111398af64c834eed 100644 +index ea95a4116371d58eb36be51093af7f0fa28e3dfd..b67f87f38d0ff99ff62d2103ecc737317a435102 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -109,8 +109,10 @@ public class PurpurWorldConfig { diff --git a/patches/server/0047-Allow-soil-to-moisten-from-water-directly-under-it.patch b/patches/server/0047-Allow-soil-to-moisten-from-water-directly-under-it.patch index 68ddef66a..4363243bc 100644 --- a/patches/server/0047-Allow-soil-to-moisten-from-water-directly-under-it.patch +++ b/patches/server/0047-Allow-soil-to-moisten-from-water-directly-under-it.patch @@ -4,11 +4,11 @@ Date: Fri, 21 Jun 2019 14:37:10 -0500 Subject: [PATCH] Allow soil to moisten from water directly under it -diff --git a/src/main/java/net/minecraft/server/BlockSoil.java b/src/main/java/net/minecraft/server/BlockSoil.java -index a315e2628c35ee713b68741c6e52c4b140c05f27..8dd48669c29dd51ed4d535dad0b0319f4bb2250c 100644 ---- a/src/main/java/net/minecraft/server/BlockSoil.java -+++ b/src/main/java/net/minecraft/server/BlockSoil.java -@@ -116,19 +116,14 @@ public class BlockSoil extends Block { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockSoil.java b/src/main/java/net/minecraft/world/level/block/BlockSoil.java +index 3bedb1c6a0f221c7b40ee0a50f676e8b05bd37a7..2bbaa2fb426869223a9b2f07406496c1b0daff3f 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockSoil.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockSoil.java +@@ -139,19 +139,14 @@ public class BlockSoil extends Block { } private static boolean a(IWorldReader iworldreader, BlockPosition blockposition) { @@ -36,7 +36,7 @@ index a315e2628c35ee713b68741c6e52c4b140c05f27..8dd48669c29dd51ed4d535dad0b0319f @Override diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 484da2bf267cab4e4569c98111398af64c834eed..56793a9e8f963b63a22aac5337299fbfb07389f0 100644 +index b67f87f38d0ff99ff62d2103ecc737317a435102..2e4a928a3e88fb3d961d9530695cd7154321c79b 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -109,6 +109,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0048-Controllable-Minecarts.patch b/patches/server/0048-Controllable-Minecarts.patch index bba4b509f..6a1ed278e 100644 --- a/patches/server/0048-Controllable-Minecarts.patch +++ b/patches/server/0048-Controllable-Minecarts.patch @@ -4,11 +4,19 @@ Date: Sat, 29 Jun 2019 02:32:40 -0500 Subject: [PATCH] Controllable Minecarts -diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java -index 72ee5fe0ca25844cbcd8f1bbbbd6a7f8ced24bc4..f38382cc681f03d9a6a0efa85f045e3770398739 100644 ---- a/src/main/java/net/minecraft/server/BlockPosition.java -+++ b/src/main/java/net/minecraft/server/BlockPosition.java -@@ -36,6 +36,12 @@ public class BlockPosition extends BaseBlockPosition { +diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java +index 73ec17dea5d5668e49c9a6ad679bd3a362960c72..54e97ae219d49a595441af6c5bae8ecef6bfc1ad 100644 +--- a/src/main/java/net/minecraft/core/BlockPosition.java ++++ b/src/main/java/net/minecraft/core/BlockPosition.java +@@ -11,6 +11,7 @@ import java.util.stream.StreamSupport; + import javax.annotation.concurrent.Immutable; + import net.minecraft.SystemUtils; + import net.minecraft.util.MathHelper; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.block.EnumBlockRotation; + import net.minecraft.world.level.levelgen.structure.StructureBoundingBox; + import net.minecraft.world.phys.AxisAlignedBB; +@@ -42,6 +43,12 @@ public class BlockPosition extends BaseBlockPosition { private static final int m = 38; // Paper end @@ -21,11 +29,31 @@ index 72ee5fe0ca25844cbcd8f1bbbbd6a7f8ced24bc4..f38382cc681f03d9a6a0efa85f045e37 public BlockPosition(int i, int j, int k) { super(i, j, k); } -diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index 0eae140eb55526e5eb88dab0e267b45fdef43ff6..65dfe107566244b96a9eb1520336caa8cc79361d 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -99,9 +99,9 @@ public abstract class EntityLiving extends Entity { +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index fe583fbc58309564d35d4cdd56fafc4de8ba31c8..4a2ea4c83107e957bda69604ca0ae98c504cf962 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -106,6 +106,7 @@ import net.minecraft.world.entity.monster.EntityMonster; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.entity.player.EnumChatVisibility; + import net.minecraft.world.entity.projectile.EntityArrow; ++import net.minecraft.world.entity.vehicle.EntityMinecartAbstract; + import net.minecraft.world.inventory.Container; + import net.minecraft.world.inventory.ContainerHorse; + import net.minecraft.world.inventory.ICrafting; +@@ -1132,6 +1133,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + if (this.isInvulnerable(damagesource)) { + return false; + } else { ++ if (damagesource == DamageSource.FALL && getRootVehicle() instanceof EntityMinecartAbstract && world.purpurConfig.controllableMinecarts && !world.purpurConfig.controllableMinecartsFallDamage) return false; // Purpur + boolean flag = this.server.j() && this.canPvP() && "fall".equals(damagesource.translationIndex); + + if (!flag && isSpawnInvulnerable() && damagesource != DamageSource.OUT_OF_WORLD) { // Purpur +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 1902b706345ff0031aaa8babde8cabffced99b78..c3acf0de92f1dbbcfbe7a9673c843107a6bd00b7 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -194,9 +194,9 @@ public abstract class EntityLiving extends Entity { protected int aO;protected int getKillCount() { return this.aO; } // Paper - OBFHELPER public float lastDamage; public boolean jumping; // Paper protected -> public @@ -38,11 +66,11 @@ index 0eae140eb55526e5eb88dab0e267b45fdef43ff6..65dfe107566244b96a9eb1520336caa8 protected int aU; protected double aV; protected double aW; -diff --git a/src/main/java/net/minecraft/server/EntityMinecartAbstract.java b/src/main/java/net/minecraft/server/EntityMinecartAbstract.java -index be859a1b41254b299a507d03e453dc8efee6f3dd..4de2877f30a9b231a5c8bbd1739416991e9d7633 100644 ---- a/src/main/java/net/minecraft/server/EntityMinecartAbstract.java -+++ b/src/main/java/net/minecraft/server/EntityMinecartAbstract.java -@@ -445,16 +445,62 @@ public abstract class EntityMinecartAbstract extends Entity { +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java +index 75a88ab5d5b0fdb98ea8d61bb6b82049b21101f3..3cd9a7956f9cbb3f66764adfede12b3b25024c41 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java +@@ -484,16 +484,62 @@ public abstract class EntityMinecartAbstract extends Entity { public void a(int i, int j, int k, boolean flag) {} @@ -52,11 +80,11 @@ index be859a1b41254b299a507d03e453dc8efee6f3dd..4de2877f30a9b231a5c8bbd173941699 + public double getControllableSpeed() { + BlockPosition position = new BlockPosition(this); + Block block = world.getType(position).getBlock(); -+ if (!block.material.isSolid()) { ++ if (!block.getMaterial().isSolid()) { + block = world.getType(position.shift(EnumDirection.DOWN)).getBlock(); + } + Double speed = world.purpurConfig.controllableMinecartsBlockSpeeds.get(block); -+ if (!block.material.isSolid()) { ++ if (!block.getMaterial().isSolid()) { + speed = lastSpeed; + } else if (speed == null) { + speed = world.purpurConfig.controllableMinecartsBaseSpeed; @@ -105,23 +133,11 @@ index be859a1b41254b299a507d03e453dc8efee6f3dd..4de2877f30a9b231a5c8bbd173941699 this.move(EnumMoveType.SELF, this.getMot()); if (!this.onGround) { -diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index e03c80f4b61e211c104e809d52d16a400b713f00..b05137eb7de2d5b236d9195db37b613733b99cf2 100644 ---- a/src/main/java/net/minecraft/server/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/EntityPlayer.java -@@ -1002,6 +1002,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - if (this.isInvulnerable(damagesource)) { - return false; - } else { -+ if (damagesource == DamageSource.FALL && getRootVehicle() instanceof EntityMinecartAbstract && world.purpurConfig.controllableMinecarts && !world.purpurConfig.controllableMinecartsFallDamage) return false; // Purpur - boolean flag = this.server.j() && this.canPvP() && "fall".equals(damagesource.translationIndex); - - if (!flag && isSpawnInvulnerable() && damagesource != DamageSource.OUT_OF_WORLD) { // Purpur -diff --git a/src/main/java/net/minecraft/server/ItemMinecart.java b/src/main/java/net/minecraft/server/ItemMinecart.java -index ceef7aaf923026ff1044d6feba4297279eb44157..002651aaf3b8a9b489fe323756cd1ad13f9874e8 100644 ---- a/src/main/java/net/minecraft/server/ItemMinecart.java -+++ b/src/main/java/net/minecraft/server/ItemMinecart.java -@@ -103,8 +103,10 @@ public class ItemMinecart extends Item { +diff --git a/src/main/java/net/minecraft/world/item/ItemMinecart.java b/src/main/java/net/minecraft/world/item/ItemMinecart.java +index 527f3ed664854cdd938c34f00a064bc2f77148cc..d50a1093aa9b6d7187b59566309a3abd05125e07 100644 +--- a/src/main/java/net/minecraft/world/item/ItemMinecart.java ++++ b/src/main/java/net/minecraft/world/item/ItemMinecart.java +@@ -121,8 +121,10 @@ public class ItemMinecart extends Item { IBlockData iblockdata = world.getType(blockposition); if (!iblockdata.a((Tag) TagsBlock.RAILS)) { @@ -134,7 +150,7 @@ index ceef7aaf923026ff1044d6feba4297279eb44157..002651aaf3b8a9b489fe323756cd1ad1 ItemStack itemstack = itemactioncontext.getItemStack(); if (!world.isClientSide) { -@@ -131,6 +133,6 @@ public class ItemMinecart extends Item { +@@ -149,6 +151,6 @@ public class ItemMinecart extends Item { itemstack.subtract(1); return EnumInteractionResult.a(world.isClientSide); @@ -142,19 +158,39 @@ index ceef7aaf923026ff1044d6feba4297279eb44157..002651aaf3b8a9b489fe323756cd1ad1 + //} // Purpur - place minecarts anywhere } } +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index 596b4597313b87296d39027b13555b5ad1cba9e6..5ea059cde9e1a089c2ade12512e4a7abd07c5b8a 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -41,6 +41,7 @@ import net.minecraft.world.level.block.entity.TileEntity; + import net.minecraft.world.level.block.state.BlockBase; + import net.minecraft.world.level.block.state.BlockStateList; + import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.material.Material; + import net.minecraft.world.level.storage.loot.LootTableInfo; + import net.minecraft.world.level.storage.loot.parameters.LootContextParameters; + import net.minecraft.world.phys.Vec3D; +@@ -83,6 +84,7 @@ public class Block extends BlockBase implements IMaterial { + return timing; + } + // Paper end ++ public Material getMaterial() { return material; } // Purpur - OBFHELPER + @Nullable + private String name; + @Nullable diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 56793a9e8f963b63a22aac5337299fbfb07389f0..c6682064ff5d653d14f658396a6a5461d4554fab 100644 +index 2e4a928a3e88fb3d961d9530695cd7154321c79b..3a6a19bd4e952a6deb1def80755387cab75bbad8 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -1,5 +1,7 @@ +@@ -1,13 +1,18 @@ package net.pl3x.purpur; -+import net.minecraft.server.Block; -+import net.minecraft.server.Blocks; - import net.minecraft.server.IRegistry; - import net.minecraft.server.Item; - import net.minecraft.server.Items; -@@ -7,7 +9,10 @@ import net.minecraft.server.MinecraftKey; + import net.minecraft.core.IRegistry; ++import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.Items; + import net.minecraft.resources.MinecraftKey; import org.bukkit.configuration.ConfigurationSection; import java.util.ArrayList; diff --git a/patches/server/0049-Disable-loot-drops-on-death-by-cramming.patch b/patches/server/0049-Disable-loot-drops-on-death-by-cramming.patch index 8e0f238d2..a0f217601 100644 --- a/patches/server/0049-Disable-loot-drops-on-death-by-cramming.patch +++ b/patches/server/0049-Disable-loot-drops-on-death-by-cramming.patch @@ -4,11 +4,11 @@ Date: Wed, 3 Jul 2019 23:58:31 -0500 Subject: [PATCH] Disable loot drops on death by cramming -diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index 65dfe107566244b96a9eb1520336caa8cc79361d..3745bf3de3fc4e8096feb247b64b53c66a93d7d4 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -1503,8 +1503,10 @@ public abstract class EntityLiving extends Entity { +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index c3acf0de92f1dbbcfbe7a9673c843107a6bd00b7..1602c00e04cccdee4e9eb4f4512145e8b1aeaf57 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -1598,8 +1598,10 @@ public abstract class EntityLiving extends Entity { this.dropInventory(); // CraftBukkit - from below if (this.cW() && this.world.getGameRules().getBoolean(GameRules.DO_MOB_LOOT)) { @@ -20,7 +20,7 @@ index 65dfe107566244b96a9eb1520336caa8cc79361d..3745bf3de3fc4e8096feb247b64b53c6 // CraftBukkit start - Call death event org.bukkit.event.entity.EntityDeathEvent deathEvent = CraftEventFactory.callEntityDeathEvent(this, this.drops); // Paper diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index c6682064ff5d653d14f658396a6a5461d4554fab..8d1ad37f17935331ee867c15f91842cdc53d4450 100644 +index 3a6a19bd4e952a6deb1def80755387cab75bbad8..b16ea97f4119fe2cd7c218f3fecbb7202c362665 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -112,6 +112,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0050-Players-should-not-cram-to-death.patch b/patches/server/0050-Players-should-not-cram-to-death.patch index 86b12d7be..0c25fcd82 100644 --- a/patches/server/0050-Players-should-not-cram-to-death.patch +++ b/patches/server/0050-Players-should-not-cram-to-death.patch @@ -4,11 +4,11 @@ Date: Sun, 21 Jul 2019 18:01:46 -0500 Subject: [PATCH] Players should not cram to death -diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index b05137eb7de2d5b236d9195db37b613733b99cf2..ec5248d7d472aa6868a5a3763ded267a919b3e58 100644 ---- a/src/main/java/net/minecraft/server/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/EntityPlayer.java -@@ -1426,7 +1426,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 4a2ea4c83107e957bda69604ca0ae98c504cf962..e129480fa1045fbeaafa97045d53696b44952bcf 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -1557,7 +1557,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { @Override public boolean isInvulnerable(DamageSource damagesource) { diff --git a/patches/server/0051-Option-to-toggle-milk-curing-bad-omen.patch b/patches/server/0051-Option-to-toggle-milk-curing-bad-omen.patch index 8b3e52e7a..a109e04ba 100644 --- a/patches/server/0051-Option-to-toggle-milk-curing-bad-omen.patch +++ b/patches/server/0051-Option-to-toggle-milk-curing-bad-omen.patch @@ -4,11 +4,20 @@ Date: Wed, 10 Jul 2019 20:43:05 -0500 Subject: [PATCH] Option to toggle milk curing bad omen -diff --git a/src/main/java/net/minecraft/server/ItemMilkBucket.java b/src/main/java/net/minecraft/server/ItemMilkBucket.java -index fcf254bbaeb3c0ffdb6834a8d5ad2c3cf4235e5b..79554e18fc39ecd9db87618a59d2e6709049820e 100644 ---- a/src/main/java/net/minecraft/server/ItemMilkBucket.java -+++ b/src/main/java/net/minecraft/server/ItemMilkBucket.java -@@ -20,7 +20,9 @@ public class ItemMilkBucket extends Item { +diff --git a/src/main/java/net/minecraft/world/item/ItemMilkBucket.java b/src/main/java/net/minecraft/world/item/ItemMilkBucket.java +index 6085c5f75bd85cca3462613c18c2e2bf26205d1b..e20452f55c531f76ecaae9ba5d0ea3f8edf96127 100644 +--- a/src/main/java/net/minecraft/world/item/ItemMilkBucket.java ++++ b/src/main/java/net/minecraft/world/item/ItemMilkBucket.java +@@ -5,6 +5,8 @@ import net.minecraft.server.level.EntityPlayer; + import net.minecraft.stats.StatisticList; + import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultWrapper; ++import net.minecraft.world.effect.MobEffect; ++import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.EntityLiving; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.level.World; +@@ -29,7 +31,9 @@ public class ItemMilkBucket extends Item { } if (!world.isClientSide) { @@ -19,7 +28,7 @@ index fcf254bbaeb3c0ffdb6834a8d5ad2c3cf4235e5b..79554e18fc39ecd9db87618a59d2e670 return itemstack.isEmpty() ? new ItemStack(Items.BUCKET) : itemstack; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 8d1ad37f17935331ee867c15f91842cdc53d4450..bec457e5aac17b0db0788110ceda778c81f26042 100644 +index b16ea97f4119fe2cd7c218f3fecbb7202c362665..a892d9af3753c4ca8f3733c64bece1cd1ed468c6 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -113,8 +113,10 @@ public class PurpurWorldConfig { diff --git a/patches/server/0052-End-gateway-should-check-if-entity-can-use-portal.patch b/patches/server/0052-End-gateway-should-check-if-entity-can-use-portal.patch index a5e2168cb..b1cf7f922 100644 --- a/patches/server/0052-End-gateway-should-check-if-entity-can-use-portal.patch +++ b/patches/server/0052-End-gateway-should-check-if-entity-can-use-portal.patch @@ -4,11 +4,11 @@ Date: Sat, 21 Mar 2020 18:33:05 -0500 Subject: [PATCH] End gateway should check if entity can use portal -diff --git a/src/main/java/net/minecraft/server/TileEntityEndGateway.java b/src/main/java/net/minecraft/server/TileEntityEndGateway.java -index b740c9b66a77df1ff20fba794c49a1de4292ba88..e616b3759561e0d6e471f914f3dc843fe7464f2e 100644 ---- a/src/main/java/net/minecraft/server/TileEntityEndGateway.java -+++ b/src/main/java/net/minecraft/server/TileEntityEndGateway.java -@@ -128,6 +128,7 @@ public class TileEntityEndGateway extends TileEntityEnderPortal implements ITick +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java +index 855c49164277ca96ca08fb204d851a5ad6789990..d918194e45953764fa3fd286b715714330a60941 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java +@@ -153,6 +153,7 @@ public class TileEntityEndGateway extends TileEntityEnderPortal implements ITick public void b(Entity entity) { if (this.world instanceof WorldServer && !this.f()) { diff --git a/patches/server/0053-Fix-the-dead-lagging-the-server.patch b/patches/server/0053-Fix-the-dead-lagging-the-server.patch index 7c1182e38..f24ce7d26 100644 --- a/patches/server/0053-Fix-the-dead-lagging-the-server.patch +++ b/patches/server/0053-Fix-the-dead-lagging-the-server.patch @@ -4,11 +4,11 @@ Date: Fri, 6 Mar 2020 13:37:26 -0600 Subject: [PATCH] Fix the dead lagging the server -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 983ed53eed9e15a14d83c68d72f004417cee2657..88598f55da691ce880d7fb8044c87c10f372aefd 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -1539,6 +1539,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index c8071e2909c03bd8eafb92fbf8fd8701642df1f9..7c9fc120d2b58ca969b8a0ff9619e96f4f34b1c4 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1631,6 +1631,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne this.pitch = MathHelper.a(f1, -90.0F, 90.0F) % 360.0F; this.lastYaw = this.yaw; this.lastPitch = this.pitch; @@ -16,11 +16,11 @@ index 983ed53eed9e15a14d83c68d72f004417cee2657..88598f55da691ce880d7fb8044c87c10 } public void f(double d0, double d1, double d2) { -diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index 3745bf3de3fc4e8096feb247b64b53c66a93d7d4..d0c73d296a3ab5f65835de0cf226d72174f6902d 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -2502,7 +2502,7 @@ public abstract class EntityLiving extends Entity { +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 1602c00e04cccdee4e9eb4f4512145e8b1aeaf57..c540886511261303d2266ac97353e1b98c1f9601 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -2597,7 +2597,7 @@ public abstract class EntityLiving extends Entity { } } diff --git a/patches/server/0054-Skip-events-if-there-s-no-listeners.patch b/patches/server/0054-Skip-events-if-there-s-no-listeners.patch index 0ac08c763..70de86833 100644 --- a/patches/server/0054-Skip-events-if-there-s-no-listeners.patch +++ b/patches/server/0054-Skip-events-if-there-s-no-listeners.patch @@ -4,11 +4,11 @@ Date: Sat, 4 Apr 2020 03:07:59 -0500 Subject: [PATCH] Skip events if there's no listeners -diff --git a/src/main/java/net/minecraft/server/CommandDispatcher.java b/src/main/java/net/minecraft/server/CommandDispatcher.java -index e56ff365118c50486f36cb15a4ca062c5a481674..17753c8a997aa286460be5d8eb6508e2eaed18ce 100644 ---- a/src/main/java/net/minecraft/server/CommandDispatcher.java -+++ b/src/main/java/net/minecraft/server/CommandDispatcher.java -@@ -278,6 +278,7 @@ public class CommandDispatcher { +diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java +index a70e0761aeddee8fafff971b5cbd0422ab560fb5..6fc5ee06c3bed8d9aa0e13dd7fa8d70ff6711f85 100644 +--- a/src/main/java/net/minecraft/commands/CommandDispatcher.java ++++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java +@@ -362,6 +362,7 @@ public class CommandDispatcher { } private void runSync(EntityPlayer entityplayer, Collection bukkit, RootCommandNode rootcommandnode) { @@ -16,7 +16,7 @@ index e56ff365118c50486f36cb15a4ca062c5a481674..17753c8a997aa286460be5d8eb6508e2 // Paper end - Async command map building new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent(entityplayer.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper PlayerCommandSendEvent event = new PlayerCommandSendEvent(entityplayer.getBukkitEntity(), new LinkedHashSet<>(bukkit)); -@@ -290,6 +291,7 @@ public class CommandDispatcher { +@@ -374,6 +375,7 @@ public class CommandDispatcher { } } // CraftBukkit end diff --git a/patches/server/0055-Add-permission-for-F3-N-debug.patch b/patches/server/0055-Add-permission-for-F3-N-debug.patch index 56fcc54c9..a1955281c 100644 --- a/patches/server/0055-Add-permission-for-F3-N-debug.patch +++ b/patches/server/0055-Add-permission-for-F3-N-debug.patch @@ -4,11 +4,11 @@ Date: Sat, 28 Dec 2019 04:21:54 -0600 Subject: [PATCH] Add permission for F3+N debug -diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java -index 7f784709ab8c560fd2dae551b6c8c234a2d134c6..f9043744ad0a622c6aa5e5bd3986fb9f60cab4c3 100644 ---- a/src/main/java/net/minecraft/server/PlayerList.java -+++ b/src/main/java/net/minecraft/server/PlayerList.java -@@ -1073,6 +1073,7 @@ public abstract class PlayerList { +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 49acc6e43748a2d2a68f1b134421831b2feedd7b..54e009ee763a689125eb521f9144951aac53a4c0 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -1157,6 +1157,7 @@ public abstract class PlayerList { } else { b0 = (byte) (24 + i); } diff --git a/patches/server/0056-Add-wither-skeleton-takes-wither-damage-option.patch b/patches/server/0056-Add-wither-skeleton-takes-wither-damage-option.patch index f756a37ab..84f792bb4 100644 --- a/patches/server/0056-Add-wither-skeleton-takes-wither-damage-option.patch +++ b/patches/server/0056-Add-wither-skeleton-takes-wither-damage-option.patch @@ -4,11 +4,11 @@ Date: Tue, 14 Jan 2020 19:43:40 -0600 Subject: [PATCH] Add wither skeleton takes wither damage option -diff --git a/src/main/java/net/minecraft/server/EntitySkeletonWither.java b/src/main/java/net/minecraft/server/EntitySkeletonWither.java -index 1ae9910fefece1a3fe6410b27642da6edd8f296d..c872be77a6cd767520d5412b38ec4ed4fa87ac2f 100644 ---- a/src/main/java/net/minecraft/server/EntitySkeletonWither.java -+++ b/src/main/java/net/minecraft/server/EntitySkeletonWither.java -@@ -97,6 +97,6 @@ public class EntitySkeletonWither extends EntitySkeletonAbstract { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java +index 85ba95615963fd6b28c454b25992e7c5b7019ae5..a90ac635ef7aef5289d21f948db7b170b23160d3 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java +@@ -122,6 +122,6 @@ public class EntitySkeletonWither extends EntitySkeletonAbstract { @Override public boolean d(MobEffect mobeffect) { @@ -17,7 +17,7 @@ index 1ae9910fefece1a3fe6410b27642da6edd8f296d..c872be77a6cd767520d5412b38ec4ed4 } } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index bec457e5aac17b0db0788110ceda778c81f26042..d6a95f47c42538b574ec55c0cfffe064b80fdef0 100644 +index a892d9af3753c4ca8f3733c64bece1cd1ed468c6..28ac3fcfb73acddd13712f5c625bd61be99cb7c5 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -279,6 +279,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0057-Configurable-TPS-Catchup.patch b/patches/server/0057-Configurable-TPS-Catchup.patch index aadc0a941..ecd7757a6 100644 --- a/patches/server/0057-Configurable-TPS-Catchup.patch +++ b/patches/server/0057-Configurable-TPS-Catchup.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable TPS Catchup diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 5e647afa74950bcb09de630ac641b9d178ef71c2..bbc92489fd2e9037834fdea3a4514b5687ae86d7 100644 +index 34793bc4bd14dc7a34f32ccfec05cf50eb77cee2..5367c3b7bdfb6951986e5c844fb978f42a0bfec5 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1010,7 +1010,13 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && !this.z()) { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index d6a95f47c42538b574ec55c0cfffe064b80fdef0..4a0bbc0cd41b4a50ebad9b4569e07d727fc3e482 100644 +index 28ac3fcfb73acddd13712f5c625bd61be99cb7c5..5d4432177aabbfd72e549b3bb5cf5381f71ce07a 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -114,9 +114,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0059-Add-enderman-and-creeper-griefing-controls.patch b/patches/server/0059-Add-enderman-and-creeper-griefing-controls.patch index e6331d425..ef0b18939 100644 --- a/patches/server/0059-Add-enderman-and-creeper-griefing-controls.patch +++ b/patches/server/0059-Add-enderman-and-creeper-griefing-controls.patch @@ -4,11 +4,11 @@ Date: Sun, 26 Apr 2020 16:28:38 -0500 Subject: [PATCH] Add enderman and creeper griefing controls -diff --git a/src/main/java/net/minecraft/server/EntityCreeper.java b/src/main/java/net/minecraft/server/EntityCreeper.java -index ff80ac7db73b7c7dd6ac62ac128af1cab961d075..36bf307985624a3567eb1196e034470bd7002e1e 100644 ---- a/src/main/java/net/minecraft/server/EntityCreeper.java -+++ b/src/main/java/net/minecraft/server/EntityCreeper.java -@@ -216,7 +216,7 @@ public class EntityCreeper extends EntityMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java +index 1986f6a672b97c1f0366bdb76e185815b8ca3bd6..f1ff9a323eaa636b21e64860d2a83a2ba6c164ea 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java +@@ -255,7 +255,7 @@ public class EntityCreeper extends EntityMonster { public void explode() { if (!this.world.isClientSide) { @@ -17,11 +17,11 @@ index ff80ac7db73b7c7dd6ac62ac128af1cab961d075..36bf307985624a3567eb1196e034470b float f = this.isPowered() ? 2.0F : 1.0F; // CraftBukkit start -diff --git a/src/main/java/net/minecraft/server/EntityEnderman.java b/src/main/java/net/minecraft/server/EntityEnderman.java -index a192400f0ea4517c56c473d39e4bd04396b4eb72..5914c50e5e254d391a5b83581d100c566243d1c5 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderman.java -+++ b/src/main/java/net/minecraft/server/EntityEnderman.java -@@ -376,6 +376,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +index 4d7b5d47ab6bd3b1408811c3b9c157b1eb5c30ae..72142f5c777c6218050bc2b69891072d256ea57d 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +@@ -431,6 +431,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { @Override public boolean a() { @@ -29,7 +29,7 @@ index a192400f0ea4517c56c473d39e4bd04396b4eb72..5914c50e5e254d391a5b83581d100c56 return this.enderman.getCarried() != null ? false : (!this.enderman.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) ? false : this.enderman.getRandom().nextInt(20) == 0); } -@@ -409,7 +410,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { +@@ -464,7 +465,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { static class PathfinderGoalEndermanPlaceBlock extends PathfinderGoal { @@ -38,7 +38,7 @@ index a192400f0ea4517c56c473d39e4bd04396b4eb72..5914c50e5e254d391a5b83581d100c56 public PathfinderGoalEndermanPlaceBlock(EntityEnderman entityenderman) { this.a = entityenderman; -@@ -417,6 +418,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { +@@ -472,6 +473,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { @Override public boolean a() { @@ -47,7 +47,7 @@ index a192400f0ea4517c56c473d39e4bd04396b4eb72..5914c50e5e254d391a5b83581d100c56 } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 4a0bbc0cd41b4a50ebad9b4569e07d727fc3e482..236b4f51ea805c671b905c1b081538b67cee7f57 100644 +index 5d4432177aabbfd72e549b3bb5cf5381f71ce07a..ab703cbb1b4322b62246d974e3efa08884496ede 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -191,8 +191,10 @@ public class PurpurWorldConfig { diff --git a/patches/server/0060-Entities-pick-up-loot-bypass-mob-griefing-gamerule.patch b/patches/server/0060-Entities-pick-up-loot-bypass-mob-griefing-gamerule.patch index efc51c043..38589b23e 100644 --- a/patches/server/0060-Entities-pick-up-loot-bypass-mob-griefing-gamerule.patch +++ b/patches/server/0060-Entities-pick-up-loot-bypass-mob-griefing-gamerule.patch @@ -4,11 +4,11 @@ Date: Fri, 24 Apr 2020 09:33:11 -0500 Subject: [PATCH] Entities pick up loot bypass mob-griefing gamerule -diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java -index 257f349217c55f6c02b42676bcd708c14e4a5fb8..6e1599537adaf923e5ceb05ce18d41fe2b02fc2c 100644 ---- a/src/main/java/net/minecraft/server/EntityInsentient.java -+++ b/src/main/java/net/minecraft/server/EntityInsentient.java -@@ -546,7 +546,7 @@ public abstract class EntityInsentient extends EntityLiving { +diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +index 7443fe924486404931c11793acc67e2f03de4e41..d8a627ed1fad1fca37d8f8a3a344b80a60fc5e2f 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java ++++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +@@ -614,7 +614,7 @@ public abstract class EntityInsentient extends EntityLiving { public void movementTick() { super.movementTick(); this.world.getMethodProfiler().enter("looting"); @@ -18,7 +18,7 @@ index 257f349217c55f6c02b42676bcd708c14e4a5fb8..6e1599537adaf923e5ceb05ce18d41fe Iterator iterator = list.iterator(); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 236b4f51ea805c671b905c1b081538b67cee7f57..2fae60a6fd767cc6d0aed7a6241ba5a6bf05eaca 100644 +index ab703cbb1b4322b62246d974e3efa08884496ede..29cab794e485b8e07b9e56f8cfb917934364121b 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -113,10 +113,12 @@ public class PurpurWorldConfig { diff --git a/patches/server/0061-Villagers-farming-can-bypass-mob-griefing-gamerule.patch b/patches/server/0061-Villagers-farming-can-bypass-mob-griefing-gamerule.patch index 846453c87..a13ad74cb 100644 --- a/patches/server/0061-Villagers-farming-can-bypass-mob-griefing-gamerule.patch +++ b/patches/server/0061-Villagers-farming-can-bypass-mob-griefing-gamerule.patch @@ -4,11 +4,11 @@ Date: Fri, 24 Apr 2020 09:37:29 -0500 Subject: [PATCH] Villagers farming can bypass mob-griefing gamerule -diff --git a/src/main/java/net/minecraft/server/BehaviorFarm.java b/src/main/java/net/minecraft/server/BehaviorFarm.java -index 54a555509e3d83e9749609dc35897ad151bca681..0ff202c0d77681f7e0d55d57c69dd0e455336eba 100644 ---- a/src/main/java/net/minecraft/server/BehaviorFarm.java -+++ b/src/main/java/net/minecraft/server/BehaviorFarm.java -@@ -18,7 +18,7 @@ public class BehaviorFarm extends Behavior { +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFarm.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFarm.java +index bd998ea93d7e8748b0a938f0a76b4ccf388c7b27..42c70a6c2972ac38e889a6d42fe2d7d4f6017d57 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFarm.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFarm.java +@@ -38,7 +38,7 @@ public class BehaviorFarm extends Behavior { } protected boolean a(WorldServer worldserver, EntityVillager entityvillager) { @@ -18,7 +18,7 @@ index 54a555509e3d83e9749609dc35897ad151bca681..0ff202c0d77681f7e0d55d57c69dd0e4 } else if (entityvillager.getVillagerData().getProfession() != VillagerProfession.FARMER) { return false; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 2fae60a6fd767cc6d0aed7a6241ba5a6bf05eaca..edcbec38dfb5b32f4b8ba40c7a1ac6e26f0a4c3b 100644 +index 29cab794e485b8e07b9e56f8cfb917934364121b..c51628f1f30bcd0206fc2b04ed83aca4ab7fd51a 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -285,9 +285,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0062-Villagers-follow-emerald-blocks.patch b/patches/server/0062-Villagers-follow-emerald-blocks.patch index cbeecb3e3..5eafb9e9e 100644 --- a/patches/server/0062-Villagers-follow-emerald-blocks.patch +++ b/patches/server/0062-Villagers-follow-emerald-blocks.patch @@ -4,11 +4,19 @@ Date: Fri, 29 Nov 2019 22:10:12 -0600 Subject: [PATCH] Villagers follow emerald blocks -diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java -index 4491b2199acd4ba9706d82c7e69d80fbc6083344..244b36c9efd9d57fdcda2367a909c2fc280ab045 100644 ---- a/src/main/java/net/minecraft/server/EntityVillager.java -+++ b/src/main/java/net/minecraft/server/EntityVillager.java -@@ -72,6 +72,13 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +index 5539c4cbea46398e92ab6ec56bb9b821e5f01e02..2464f1a5a922a5557e2d00233033714533acad76 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +@@ -59,6 +59,7 @@ import net.minecraft.world.entity.ai.BehaviorController; + import net.minecraft.world.entity.ai.attributes.AttributeProvider; + import net.minecraft.world.entity.ai.attributes.GenericAttributes; + import net.minecraft.world.entity.ai.behavior.Behaviors; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalTempt; + import net.minecraft.world.entity.ai.gossip.Reputation; + import net.minecraft.world.entity.ai.gossip.ReputationType; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; +@@ -143,6 +144,13 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation this.brainTickOffset = getRandom().nextInt(100); // Purpur } @@ -22,11 +30,25 @@ index 4491b2199acd4ba9706d82c7e69d80fbc6083344..244b36c9efd9d57fdcda2367a909c2fc @Override public BehaviorController getBehaviorController() { return (BehaviorController) super.getBehaviorController(); // CraftBukkit - decompile error -diff --git a/src/main/java/net/minecraft/server/EntityVillagerAbstract.java b/src/main/java/net/minecraft/server/EntityVillagerAbstract.java -index e0cc45a7494cd6f06169b64ee8ffc16aa1932f8f..baf74566ec8569677e6f03aef96645c13ec94d89 100644 ---- a/src/main/java/net/minecraft/server/EntityVillagerAbstract.java -+++ b/src/main/java/net/minecraft/server/EntityVillagerAbstract.java -@@ -18,6 +18,8 @@ import io.papermc.paper.event.player.PlayerTradeEvent; +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java +index 49821f0f26864c35be84a4a4288857a04668fbba..91142526187f96615b5cbd3ed3b68d9175cb9f8b 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java +@@ -25,11 +25,13 @@ import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.item.crafting.RecipeItemStack; + import net.minecraft.world.item.trading.IMerchant; + import net.minecraft.world.item.trading.MerchantRecipe; + import net.minecraft.world.item.trading.MerchantRecipeList; + import net.minecraft.world.level.World; + import net.minecraft.world.level.WorldAccess; ++import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.pathfinder.PathType; + + // CraftBukkit start +@@ -45,6 +47,8 @@ import io.papermc.paper.event.player.PlayerTradeEvent; public abstract class EntityVillagerAbstract extends EntityAgeable implements NPC, IMerchant { @@ -35,11 +57,19 @@ index e0cc45a7494cd6f06169b64ee8ffc16aa1932f8f..baf74566ec8569677e6f03aef96645c1 // CraftBukkit start private CraftMerchant craftMerchant; -diff --git a/src/main/java/net/minecraft/server/EntityVillagerTrader.java b/src/main/java/net/minecraft/server/EntityVillagerTrader.java -index 250a4e5ddd626794482678a64023f0f5459520e1..d990aae60e5a6056b44249cb7039470c6757b7fb 100644 ---- a/src/main/java/net/minecraft/server/EntityVillagerTrader.java -+++ b/src/main/java/net/minecraft/server/EntityVillagerTrader.java -@@ -42,6 +42,7 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java +index 37e1b2bf33510c3603efadf219b462e667f573c2..6c13a34a7ab220a3bba1c091f4f6a9e1340212f6 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java +@@ -26,6 +26,7 @@ import net.minecraft.world.entity.ai.goal.PathfinderGoalLookAtTradingPlayer; + import net.minecraft.world.entity.ai.goal.PathfinderGoalMoveTowardsRestriction; + import net.minecraft.world.entity.ai.goal.PathfinderGoalPanic; + import net.minecraft.world.entity.ai.goal.PathfinderGoalRandomStrollLand; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalTempt; + import net.minecraft.world.entity.ai.goal.PathfinderGoalTradeWithPlayer; + import net.minecraft.world.entity.ai.goal.PathfinderGoalUseItem; + import net.minecraft.world.entity.monster.EntityEvoker; +@@ -85,6 +86,7 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { this.goalSelector.a(1, new PathfinderGoalPanic(this, 0.5D)); this.goalSelector.a(1, new PathfinderGoalLookAtTradingPlayer(this)); this.goalSelector.a(2, new EntityVillagerTrader.a(this, 2.0D, 0.35D)); @@ -48,7 +78,7 @@ index 250a4e5ddd626794482678a64023f0f5459520e1..d990aae60e5a6056b44249cb7039470c this.goalSelector.a(8, new PathfinderGoalRandomStrollLand(this, 0.35D)); this.goalSelector.a(9, new PathfinderGoalInteract(this, EntityHuman.class, 3.0F, 1.0F)); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index edcbec38dfb5b32f4b8ba40c7a1ac6e26f0a4c3b..a1f85ef007f2ed410f1662405b0b1175c544e0b6 100644 +index c51628f1f30bcd0206fc2b04ed83aca4ab7fd51a..7d66e253391522d754146275024ffb017a685e6f 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -286,10 +286,17 @@ public class PurpurWorldConfig { diff --git a/patches/server/0063-Allow-leashing-villagers.patch b/patches/server/0063-Allow-leashing-villagers.patch index b275b6ee9..ebe097cca 100644 --- a/patches/server/0063-Allow-leashing-villagers.patch +++ b/patches/server/0063-Allow-leashing-villagers.patch @@ -4,11 +4,19 @@ Date: Thu, 3 Oct 2019 18:08:03 -0500 Subject: [PATCH] Allow leashing villagers -diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java -index 6e1599537adaf923e5ceb05ce18d41fe2b02fc2c..82d2c2ced979ebe6c683e8b3c18ea34defcfe7db 100644 ---- a/src/main/java/net/minecraft/server/EntityInsentient.java -+++ b/src/main/java/net/minecraft/server/EntityInsentient.java -@@ -1149,6 +1149,7 @@ public abstract class EntityInsentient extends EntityLiving { +diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +index d8a627ed1fad1fca37d8f8a3a344b80a60fc5e2f..1a1561ab4276bd3654adc2cc2219f3bdb3924b88 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java ++++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +@@ -49,6 +49,7 @@ import net.minecraft.world.entity.item.EntityItem; + import net.minecraft.world.entity.monster.EntityBlaze; + import net.minecraft.world.entity.monster.EntityEnderman; + import net.minecraft.world.entity.monster.IMonster; ++import net.minecraft.world.entity.npc.EntityVillagerAbstract; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.entity.vehicle.EntityBoat; + import net.minecraft.world.item.Item; +@@ -1217,6 +1218,7 @@ public abstract class EntityInsentient extends EntityLiving { if (!this.isAlive()) { return EnumInteractionResult.PASS; } else if (this.getLeashHolder() == entityhuman) { @@ -16,11 +24,11 @@ index 6e1599537adaf923e5ceb05ce18d41fe2b02fc2c..82d2c2ced979ebe6c683e8b3c18ea34d // CraftBukkit start - fire PlayerUnleashEntityEvent // Paper start - drop leash variable PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(this, entityhuman, !entityhuman.abilities.canInstantlyBuild); -diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java -index 244b36c9efd9d57fdcda2367a909c2fc280ab045..f731894a10988945db7205501432ca9cb92771a3 100644 ---- a/src/main/java/net/minecraft/server/EntityVillager.java -+++ b/src/main/java/net/minecraft/server/EntityVillager.java -@@ -77,6 +77,11 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +index 2464f1a5a922a5557e2d00233033714533acad76..aeb3c82afeda3f1688b1b6617c6d05da2e7a3c76 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +@@ -149,6 +149,11 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation protected void initPathfinder() { if (world.purpurConfig.villagerFollowEmeraldBlock) this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.0D, false, TEMPT_ITEMS)); } @@ -32,11 +40,11 @@ index 244b36c9efd9d57fdcda2367a909c2fc280ab045..f731894a10988945db7205501432ca9c // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityVillagerTrader.java b/src/main/java/net/minecraft/server/EntityVillagerTrader.java -index d990aae60e5a6056b44249cb7039470c6757b7fb..432956d9d5f2706014d67232b88e6b86011484f3 100644 ---- a/src/main/java/net/minecraft/server/EntityVillagerTrader.java -+++ b/src/main/java/net/minecraft/server/EntityVillagerTrader.java -@@ -49,6 +49,13 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java +index 6c13a34a7ab220a3bba1c091f4f6a9e1340212f6..e0324cdb2d4c85714eaad490a7a5c826b38e6b16 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java +@@ -93,6 +93,13 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 8.0F)); } @@ -51,7 +59,7 @@ index d990aae60e5a6056b44249cb7039470c6757b7fb..432956d9d5f2706014d67232b88e6b86 @Override public EntityAgeable createChild(WorldServer worldserver, EntityAgeable entityageable) { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index a1f85ef007f2ed410f1662405b0b1175c544e0b6..a9e7ddd55aa2b9b2c8f172069353b070c427b806 100644 +index 7d66e253391522d754146275024ffb017a685e6f..b6d6685f135ee66a25f29c0f00a63bbe78d0c3a5 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -285,17 +285,21 @@ public class PurpurWorldConfig { diff --git a/patches/server/0064-Implement-configurable-search-radius-for-villagers-t.patch b/patches/server/0064-Implement-configurable-search-radius-for-villagers-t.patch index 536cd4e86..1d450ba23 100644 --- a/patches/server/0064-Implement-configurable-search-radius-for-villagers-t.patch +++ b/patches/server/0064-Implement-configurable-search-radius-for-villagers-t.patch @@ -5,11 +5,11 @@ Subject: [PATCH] Implement configurable search radius for villagers to spawn iron golems -diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java -index f731894a10988945db7205501432ca9cb92771a3..1563791a0193dcd0a00968d2bb6275716742dc19 100644 ---- a/src/main/java/net/minecraft/server/EntityVillager.java -+++ b/src/main/java/net/minecraft/server/EntityVillager.java -@@ -898,6 +898,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +index aeb3c82afeda3f1688b1b6617c6d05da2e7a3c76..2fad37812bfa39872e99c4432e1982d62f65efb7 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +@@ -970,6 +970,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation @Nullable private EntityIronGolem d(WorldServer worldserver) { @@ -18,7 +18,7 @@ index f731894a10988945db7205501432ca9cb92771a3..1563791a0193dcd0a00968d2bb627571 for (int i = 0; i < 10; ++i) { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index a9e7ddd55aa2b9b2c8f172069353b070c427b806..0de099d29b5e351822e59af6e389dc91c67eb2b2 100644 +index b6d6685f135ee66a25f29c0f00a63bbe78d0c3a5..81f0538f6e5ab48a07459b102ea1f4533a63d031 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -288,12 +288,16 @@ public class PurpurWorldConfig { diff --git a/patches/server/0065-Implement-infinite-lava.patch b/patches/server/0065-Implement-infinite-lava.patch index d3a7fa09b..5c1093d6d 100644 --- a/patches/server/0065-Implement-infinite-lava.patch +++ b/patches/server/0065-Implement-infinite-lava.patch @@ -4,11 +4,11 @@ Date: Sat, 23 Nov 2019 17:55:42 -0600 Subject: [PATCH] Implement infinite lava -diff --git a/src/main/java/net/minecraft/server/FluidTypeFlowing.java b/src/main/java/net/minecraft/server/FluidTypeFlowing.java -index cf9d3faabe8732d27c436f4806c727592e475f81..46bdeca19a0da06a1fcbd7043a26689b64459d67 100644 ---- a/src/main/java/net/minecraft/server/FluidTypeFlowing.java -+++ b/src/main/java/net/minecraft/server/FluidTypeFlowing.java -@@ -196,7 +196,7 @@ public abstract class FluidTypeFlowing extends FluidType { +diff --git a/src/main/java/net/minecraft/world/level/material/FluidTypeFlowing.java b/src/main/java/net/minecraft/world/level/material/FluidTypeFlowing.java +index 6bb4ec00e40795ced73648fefcd1f5027e0113cd..963b7edab813cd32f04c51fd2c6c137988e2a754 100644 +--- a/src/main/java/net/minecraft/world/level/material/FluidTypeFlowing.java ++++ b/src/main/java/net/minecraft/world/level/material/FluidTypeFlowing.java +@@ -217,7 +217,7 @@ public abstract class FluidTypeFlowing extends FluidType { } } @@ -17,7 +17,7 @@ index cf9d3faabe8732d27c436f4806c727592e475f81..46bdeca19a0da06a1fcbd7043a26689b IBlockData iblockdata2 = iworldreader.getType(blockposition.down()); Fluid fluid1 = iblockdata2.getFluid(); -@@ -267,6 +267,17 @@ public abstract class FluidTypeFlowing extends FluidType { +@@ -288,6 +288,17 @@ public abstract class FluidTypeFlowing extends FluidType { return (Fluid) this.e().h().set(FluidTypeFlowing.FALLING, flag); } @@ -35,11 +35,11 @@ index cf9d3faabe8732d27c436f4806c727592e475f81..46bdeca19a0da06a1fcbd7043a26689b protected abstract boolean f(); protected void a(GeneratorAccess generatoraccess, BlockPosition blockposition, IBlockData iblockdata, EnumDirection enumdirection, Fluid fluid) { -diff --git a/src/main/java/net/minecraft/server/FluidTypeLava.java b/src/main/java/net/minecraft/server/FluidTypeLava.java -index 29930e801cdcb97bec2fb113ec478fe9c4a63b63..ffab2391925f577420ee52f3aa05041afa61464e 100644 ---- a/src/main/java/net/minecraft/server/FluidTypeLava.java -+++ b/src/main/java/net/minecraft/server/FluidTypeLava.java -@@ -147,6 +147,18 @@ public abstract class FluidTypeLava extends FluidTypeFlowing { +diff --git a/src/main/java/net/minecraft/world/level/material/FluidTypeLava.java b/src/main/java/net/minecraft/world/level/material/FluidTypeLava.java +index b362a728b5d17256768847ab09e2505a9cc1918b..86f2e969d98c833700f0f48baf7610ad95b3f8a1 100644 +--- a/src/main/java/net/minecraft/world/level/material/FluidTypeLava.java ++++ b/src/main/java/net/minecraft/world/level/material/FluidTypeLava.java +@@ -163,6 +163,18 @@ public abstract class FluidTypeLava extends FluidTypeFlowing { generatoraccess.triggerEffect(1501, blockposition, 0); } @@ -59,7 +59,7 @@ index 29930e801cdcb97bec2fb113ec478fe9c4a63b63..ffab2391925f577420ee52f3aa05041a protected boolean f() { return false; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 0de099d29b5e351822e59af6e389dc91c67eb2b2..37bc3033b3b7281da4f8783d3fbe9a0a4d33a9de 100644 +index 81f0538f6e5ab48a07459b102ea1f4533a63d031..29bb808b1efe392157971a1a21c66eb9b85579d8 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -158,6 +158,13 @@ public class PurpurWorldConfig { diff --git a/patches/server/0066-Make-lava-flow-speed-configurable.patch b/patches/server/0066-Make-lava-flow-speed-configurable.patch index 56ea9ec1a..c5dd85c1f 100644 --- a/patches/server/0066-Make-lava-flow-speed-configurable.patch +++ b/patches/server/0066-Make-lava-flow-speed-configurable.patch @@ -4,11 +4,11 @@ Date: Thu, 2 Jan 2020 11:31:36 -0600 Subject: [PATCH] Make lava flow speed configurable -diff --git a/src/main/java/net/minecraft/server/FluidTypeLava.java b/src/main/java/net/minecraft/server/FluidTypeLava.java -index ffab2391925f577420ee52f3aa05041afa61464e..d981aa5a5f001333675eabd50497bbfa2dcf1df3 100644 ---- a/src/main/java/net/minecraft/server/FluidTypeLava.java -+++ b/src/main/java/net/minecraft/server/FluidTypeLava.java -@@ -129,7 +129,7 @@ public abstract class FluidTypeLava extends FluidTypeFlowing { +diff --git a/src/main/java/net/minecraft/world/level/material/FluidTypeLava.java b/src/main/java/net/minecraft/world/level/material/FluidTypeLava.java +index 86f2e969d98c833700f0f48baf7610ad95b3f8a1..e706695d42d7557f818595aa30fb3cfc35ba9f6b 100644 +--- a/src/main/java/net/minecraft/world/level/material/FluidTypeLava.java ++++ b/src/main/java/net/minecraft/world/level/material/FluidTypeLava.java +@@ -145,7 +145,7 @@ public abstract class FluidTypeLava extends FluidTypeFlowing { @Override public int a(IWorldReader iworldreader) { @@ -18,7 +18,7 @@ index ffab2391925f577420ee52f3aa05041afa61464e..d981aa5a5f001333675eabd50497bbfa @Override diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 37bc3033b3b7281da4f8783d3fbe9a0a4d33a9de..d5adf653c6a561fe1de9e340d85c9439f8c559f5 100644 +index 29bb808b1efe392157971a1a21c66eb9b85579d8..d51ee6ff1b73f0bafec88fd5445df37a1182c5d0 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -160,9 +160,13 @@ public class PurpurWorldConfig { diff --git a/patches/server/0067-Add-player-death-exp-control-options.patch b/patches/server/0067-Add-player-death-exp-control-options.patch index 89337da10..c3a58fd69 100644 --- a/patches/server/0067-Add-player-death-exp-control-options.patch +++ b/patches/server/0067-Add-player-death-exp-control-options.patch @@ -4,11 +4,11 @@ Date: Thu, 26 Dec 2019 22:08:37 -0600 Subject: [PATCH] Add player death exp control options -diff --git a/src/main/java/net/minecraft/server/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java -index a3aa2c8760b43e09f77f2790d6e21b8a2dc9dd3c..0f7b60642c44630000d47f0e1fdebad15e14a810 100644 ---- a/src/main/java/net/minecraft/server/EntityHuman.java -+++ b/src/main/java/net/minecraft/server/EntityHuman.java -@@ -86,6 +86,8 @@ public abstract class EntityHuman extends EntityLiving { +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index 8f9d0769e7855c3565a34927f3f3741c43e45f35..2ee7daa155d812af8f84ba646106d801d2fb0fec 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -183,6 +183,8 @@ public abstract class EntityHuman extends EntityLiving { // CraftBukkit end // Purpur start @@ -17,7 +17,7 @@ index a3aa2c8760b43e09f77f2790d6e21b8a2dc9dd3c..0f7b60642c44630000d47f0e1fdebad1 public void setAfk(boolean setAfk){ } -@@ -1717,9 +1719,18 @@ public abstract class EntityHuman extends EntityLiving { +@@ -1814,9 +1816,18 @@ public abstract class EntityHuman extends EntityLiving { @Override protected int getExpValue(EntityHuman entityhuman) { if (!this.world.getGameRules().getBoolean(GameRules.KEEP_INVENTORY) && !this.isSpectator()) { @@ -40,7 +40,7 @@ index a3aa2c8760b43e09f77f2790d6e21b8a2dc9dd3c..0f7b60642c44630000d47f0e1fdebad1 return 0; } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index d5adf653c6a561fe1de9e340d85c9439f8c559f5..c5574ac52d050cc1b89ab2dbd4dad5ce5e331f83 100644 +index d51ee6ff1b73f0bafec88fd5445df37a1182c5d0..e10aa8ddbcea3588b2da08de929eed18cb9f022c 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -123,6 +123,13 @@ public class PurpurWorldConfig { diff --git a/patches/server/0068-Add-canSaveToDisk-to-Entity.patch b/patches/server/0068-Add-canSaveToDisk-to-Entity.patch index 2c2fb4e8f..545c81122 100644 --- a/patches/server/0068-Add-canSaveToDisk-to-Entity.patch +++ b/patches/server/0068-Add-canSaveToDisk-to-Entity.patch @@ -4,23 +4,11 @@ Date: Tue, 18 Feb 2020 20:07:08 -0600 Subject: [PATCH] Add canSaveToDisk to Entity -diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -index 68538ae94806d5980cd531e61fa52a01a5cc8997..e77da341b765725771726283d3a8249b514b40da 100644 ---- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -@@ -538,6 +538,7 @@ public class ChunkRegionLoader { - - while (iterator1.hasNext()) { - Entity entity = (Entity) iterator1.next(); -+ if (!entity.canSaveToDisk()) continue; // Purpur - final EntityTypes entityType = entity.getEntityType(); - final int saveLimit = worldserver.paperConfig.entityPerChunkSaveLimits.getOrDefault(entityType, -1); - if (saveLimit > -1) { -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 88598f55da691ce880d7fb8044c87c10f372aefd..a9020ef4ebccc4d5497dae5ad1b2ecad20ed4075 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -324,6 +324,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 7c9fc120d2b58ca969b8a0ff9619e96f4f34b1c4..4e6ec59c982fe0870f514b59082ab0a7de4d93ef 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -416,6 +416,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne this.headHeight = this.getHeadHeight(EntityPose.STANDING, this.size); } @@ -33,3 +21,15 @@ index 88598f55da691ce880d7fb8044c87c10f372aefd..a9020ef4ebccc4d5497dae5ad1b2ecad public boolean isSpectator() { return false; } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +index bf96f9e538fc29ca914536e8a7ce727ebe43a8b2..5997f3e47f3d509c271f38eb2785f126066f5c6e 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +@@ -582,6 +582,7 @@ public class ChunkRegionLoader { + + while (iterator1.hasNext()) { + Entity entity = (Entity) iterator1.next(); ++ if (!entity.canSaveToDisk()) continue; // Purpur + final EntityTypes entityType = entity.getEntityType(); + final int saveLimit = worldserver.paperConfig.entityPerChunkSaveLimits.getOrDefault(entityType, -1); + if (saveLimit > -1) { diff --git a/patches/server/0069-Configurable-void-damage-height.patch b/patches/server/0069-Configurable-void-damage-height.patch index 1eaf586d3..8ce3026a9 100644 --- a/patches/server/0069-Configurable-void-damage-height.patch +++ b/patches/server/0069-Configurable-void-damage-height.patch @@ -4,11 +4,11 @@ Date: Thu, 27 Feb 2020 21:42:19 -0600 Subject: [PATCH] Configurable void damage height -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index a9020ef4ebccc4d5497dae5ad1b2ecad20ed4075..e93d028a3908aa4d0c1daf7929acc2a426bbb0df 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -627,7 +627,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 4e6ec59c982fe0870f514b59082ab0a7de4d93ef..b114d12d9d17071fb96f5ab225b85cdd5ad06861 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -719,7 +719,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne // Paper start protected void performVoidDamage() { @@ -18,7 +18,7 @@ index a9020ef4ebccc4d5497dae5ad1b2ecad20ed4075..e93d028a3908aa4d0c1daf7929acc2a4 && this.locY() >= world.paperConfig.netherVoidTopDamageHeight)) { this.doVoidDamage(); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index c5574ac52d050cc1b89ab2dbd4dad5ce5e331f83..4d34957c6255af571e593e015fa9dcafa733aceb 100644 +index e10aa8ddbcea3588b2da08de929eed18cb9f022c..ef5a691861cdf249f0430fca7f7bbe241479926e 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -116,11 +116,13 @@ public class PurpurWorldConfig { diff --git a/patches/server/0070-Dispenser-curse-of-binding-protection.patch b/patches/server/0070-Dispenser-curse-of-binding-protection.patch index 252aab350..9edb53f94 100644 --- a/patches/server/0070-Dispenser-curse-of-binding-protection.patch +++ b/patches/server/0070-Dispenser-curse-of-binding-protection.patch @@ -4,11 +4,19 @@ Date: Sun, 25 Aug 2019 00:09:52 -0500 Subject: [PATCH] Dispenser curse of binding protection -diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java -index 82d2c2ced979ebe6c683e8b3c18ea34defcfe7db..4e3af139712323a12066728426615e0faa274e4b 100644 ---- a/src/main/java/net/minecraft/server/EntityInsentient.java -+++ b/src/main/java/net/minecraft/server/EntityInsentient.java -@@ -998,6 +998,13 @@ public abstract class EntityInsentient extends EntityLiving { +diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +index 1a1561ab4276bd3654adc2cc2219f3bdb3924b88..462bcb7cfe2daa27c10a7a0318bef9b739e586f4 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java ++++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +@@ -65,6 +65,7 @@ import net.minecraft.world.item.ItemSword; + import net.minecraft.world.item.ItemTool; + import net.minecraft.world.item.Items; + import net.minecraft.world.item.enchantment.EnchantmentManager; ++import net.minecraft.world.item.enchantment.Enchantments; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.GeneratorAccess; + import net.minecraft.world.level.IBlockAccess; +@@ -1067,6 +1068,13 @@ public abstract class EntityInsentient extends EntityLiving { } @@ -22,11 +30,11 @@ index 82d2c2ced979ebe6c683e8b3c18ea34defcfe7db..4e3af139712323a12066728426615e0f public static EnumItemSlot j(ItemStack itemstack) { Item item = itemstack.getItem(); -diff --git a/src/main/java/net/minecraft/server/ItemArmor.java b/src/main/java/net/minecraft/server/ItemArmor.java -index 669a5041184846ca8430a7f0d3197025fe6d437e..7cd2e871b5a429a86dbc3c4208d247a4246ea1a8 100644 ---- a/src/main/java/net/minecraft/server/ItemArmor.java -+++ b/src/main/java/net/minecraft/server/ItemArmor.java -@@ -35,7 +35,7 @@ public class ItemArmor extends Item implements ItemWearable { +diff --git a/src/main/java/net/minecraft/world/item/ItemArmor.java b/src/main/java/net/minecraft/world/item/ItemArmor.java +index 7962808aebf67cf9bc1dc4c1e106e943536fdced..d072b604a1cd8835c1fe658831cdaf9f27d02cd5 100644 +--- a/src/main/java/net/minecraft/world/item/ItemArmor.java ++++ b/src/main/java/net/minecraft/world/item/ItemArmor.java +@@ -54,7 +54,7 @@ public class ItemArmor extends Item implements ItemWearable { return false; } else { EntityLiving entityliving = (EntityLiving) list.get(0); @@ -35,7 +43,7 @@ index 669a5041184846ca8430a7f0d3197025fe6d437e..7cd2e871b5a429a86dbc3c4208d247a4 ItemStack itemstack1 = itemstack.cloneAndSubtract(1); // CraftBukkit start World world = isourceblock.getWorld(); -@@ -94,6 +94,7 @@ public class ItemArmor extends Item implements ItemWearable { +@@ -113,6 +113,7 @@ public class ItemArmor extends Item implements ItemWearable { this.m = builder.build(); } @@ -44,7 +52,7 @@ index 669a5041184846ca8430a7f0d3197025fe6d437e..7cd2e871b5a429a86dbc3c4208d247a4 return this.b; } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 4d34957c6255af571e593e015fa9dcafa733aceb..26df95f502d117398c7c9c65b298b97b62021700 100644 +index ef5a691861cdf249f0430fca7f7bbe241479926e..5b42e8347a42a16f79fbbc122e5cd82533e53b8c 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -162,6 +162,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0071-Add-option-for-boats-to-eject-players-on-land.patch b/patches/server/0071-Add-option-for-boats-to-eject-players-on-land.patch index ced4a492d..96abfcc62 100644 --- a/patches/server/0071-Add-option-for-boats-to-eject-players-on-land.patch +++ b/patches/server/0071-Add-option-for-boats-to-eject-players-on-land.patch @@ -4,11 +4,11 @@ Date: Sat, 7 Sep 2019 22:47:59 -0500 Subject: [PATCH] Add option for boats to eject players on land -diff --git a/src/main/java/net/minecraft/server/EntityBoat.java b/src/main/java/net/minecraft/server/EntityBoat.java -index 15ce9f90306d062f36d1651d7426813e897523bf..05c702bbdb8addea5c69faa0479609e8959945f1 100644 ---- a/src/main/java/net/minecraft/server/EntityBoat.java -+++ b/src/main/java/net/minecraft/server/EntityBoat.java -@@ -442,6 +442,7 @@ public class EntityBoat extends Entity { +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java +index 5e2c13bd6e52ffe182ef034e05ba6fe1cb301005..01839c7319e175477ded7001e00e5937734ff516 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java +@@ -487,6 +487,7 @@ public class EntityBoat extends Entity { if (f > 0.0F) { this.aw = f; @@ -17,7 +17,7 @@ index 15ce9f90306d062f36d1651d7426813e897523bf..05c702bbdb8addea5c69faa0479609e8 } else { return EntityBoat.EnumStatus.IN_AIR; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 26df95f502d117398c7c9c65b298b97b62021700..5eae6c99e35d53f5340bc81034823a2f1ed85544 100644 +index 5b42e8347a42a16f79fbbc122e5cd82533e53b8c..f443fadcafdbc3d69c86730e3fb1a71078d7fdf5 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -112,12 +112,14 @@ public class PurpurWorldConfig { diff --git a/patches/server/0072-Add-obfhelpers-for-plugin-use.patch b/patches/server/0072-Add-obfhelpers-for-plugin-use.patch index 217ab639f..793fe557f 100644 --- a/patches/server/0072-Add-obfhelpers-for-plugin-use.patch +++ b/patches/server/0072-Add-obfhelpers-for-plugin-use.patch @@ -4,11 +4,11 @@ Date: Wed, 1 Jan 2020 20:12:39 -0600 Subject: [PATCH] Add obfhelpers for plugin use -diff --git a/src/main/java/net/minecraft/server/ItemStack.java b/src/main/java/net/minecraft/server/ItemStack.java -index afa1dc693bc2e2e68294a1d3dec1c078ea95b286..7f3df9ba37076c0a982803148d21b0985f62f12c 100644 ---- a/src/main/java/net/minecraft/server/ItemStack.java -+++ b/src/main/java/net/minecraft/server/ItemStack.java -@@ -639,6 +639,7 @@ public final class ItemStack { +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index fee862951f2767d4a3c5268dff157c185378a939..91a1b2e955b04f0cc1ca05d7ee4d832d9efb97cb 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -694,6 +694,7 @@ public final class ItemStack { return this.tag; } diff --git a/patches/server/0073-Mending-mends-most-damages-equipment-first.patch b/patches/server/0073-Mending-mends-most-damages-equipment-first.patch index 405619543..275938dbb 100644 --- a/patches/server/0073-Mending-mends-most-damages-equipment-first.patch +++ b/patches/server/0073-Mending-mends-most-damages-equipment-first.patch @@ -4,11 +4,48 @@ Date: Sun, 14 Jul 2019 19:52:47 -0500 Subject: [PATCH] Mending mends most damages equipment first -diff --git a/src/main/java/net/minecraft/server/EnchantmentManager.java b/src/main/java/net/minecraft/server/EnchantmentManager.java -index 7b263594304a9b745f583fe7178ac16936cbd93b..33e2dc3a1003fe95fa71999fc24df84131238a6a 100644 ---- a/src/main/java/net/minecraft/server/EnchantmentManager.java -+++ b/src/main/java/net/minecraft/server/EnchantmentManager.java -@@ -251,7 +251,30 @@ public class EnchantmentManager { +diff --git a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java +index a7551e95185895a290be70d501496279eaf884ae..31d36ead273e8397ba2c826b791a2cf59306ff7f 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java +@@ -236,7 +236,7 @@ public class EntityExperienceOrb extends Entity { + if (this.d == 0 && entityhuman.bu == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(((EntityPlayer) entityhuman).getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper + entityhuman.bu = 2; + entityhuman.receive(this, 1); +- Entry entry = EnchantmentManager.a(Enchantments.MENDING, (EntityLiving) entityhuman, ItemStack::f); ++ Entry entry = world.purpurConfig.useBetterMending ? EnchantmentManager.getMostDamagedEquipment(Enchantments.MENDING, entityhuman) : EnchantmentManager.a(Enchantments.MENDING, entityhuman, ItemStack::isDamaged); // Purpur + + if (entry != null) { + ItemStack itemstack = (ItemStack) entry.getValue(); +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 91a1b2e955b04f0cc1ca05d7ee4d832d9efb97cb..fcc6ee9481d577d39339cd0ac24dab06bd76e5c6 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -468,10 +468,19 @@ public final class ItemStack { + } + } + ++ public boolean isDamaged() { return f(); } // Purpur - OBFHELPER + public boolean f() { + return this.e() && this.getDamage() > 0; + } + ++ public float getDamagePercent() { ++ if (isDamaged()) { ++ return (float) getDamage() / (float) getItem().getMaxDurability(); ++ } else { ++ return 0F; ++ } ++ } ++ + public int getDamage() { + return this.tag == null ? 0 : this.tag.getInt("Damage"); + } +diff --git a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentManager.java b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentManager.java +index 72afbf8f537770540e90a2880ea81de137ea10f5..b2d28c2bf0a9e93d38583e2d734c12fed4f63d5d 100644 +--- a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentManager.java ++++ b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentManager.java +@@ -269,7 +269,30 @@ public class EnchantmentManager { return getEnchantmentLevel(Enchantments.CHANNELING, itemstack) > 0; } @@ -40,45 +77,8 @@ index 7b263594304a9b745f583fe7178ac16936cbd93b..33e2dc3a1003fe95fa71999fc24df841 @Nullable public static Entry b(Enchantment enchantment, EntityLiving entityliving) { return a(enchantment, entityliving, (itemstack) -> { return true; -diff --git a/src/main/java/net/minecraft/server/EntityExperienceOrb.java b/src/main/java/net/minecraft/server/EntityExperienceOrb.java -index 4a94ce72d559263ef5fa4fb16dc286f531f51d55..4aee11c980105a523bdcb35470053aae51b002df 100644 ---- a/src/main/java/net/minecraft/server/EntityExperienceOrb.java -+++ b/src/main/java/net/minecraft/server/EntityExperienceOrb.java -@@ -221,7 +221,7 @@ public class EntityExperienceOrb extends Entity { - if (this.d == 0 && entityhuman.bu == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(((EntityPlayer) entityhuman).getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper - entityhuman.bu = 2; - entityhuman.receive(this, 1); -- Entry entry = EnchantmentManager.a(Enchantments.MENDING, (EntityLiving) entityhuman, ItemStack::f); -+ Entry entry = world.purpurConfig.useBetterMending ? EnchantmentManager.getMostDamagedEquipment(Enchantments.MENDING, entityhuman) : EnchantmentManager.a(Enchantments.MENDING, entityhuman, ItemStack::isDamaged); // Purpur - - if (entry != null) { - ItemStack itemstack = (ItemStack) entry.getValue(); -diff --git a/src/main/java/net/minecraft/server/ItemStack.java b/src/main/java/net/minecraft/server/ItemStack.java -index 7f3df9ba37076c0a982803148d21b0985f62f12c..e747ee83f1a69a4a4bad87e720abc9b085fb6149 100644 ---- a/src/main/java/net/minecraft/server/ItemStack.java -+++ b/src/main/java/net/minecraft/server/ItemStack.java -@@ -413,10 +413,19 @@ public final class ItemStack { - } - } - -+ public boolean isDamaged() { return f(); } // Purpur - OBFHELPER - public boolean f() { - return this.e() && this.getDamage() > 0; - } - -+ public float getDamagePercent() { -+ if (isDamaged()) { -+ return (float) getDamage() / (float) getItem().getMaxDurability(); -+ } else { -+ return 0F; -+ } -+ } -+ - public int getDamage() { - return this.tag == null ? 0 : this.tag.getInt("Damage"); - } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 5eae6c99e35d53f5340bc81034823a2f1ed85544..66e74ee74b56e25ca46704ca6cec403f15126c33 100644 +index f443fadcafdbc3d69c86730e3fb1a71078d7fdf5..e66b79218e960d11da4759187e4473685ccb9a9e 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -112,6 +112,7 @@ public class PurpurWorldConfig { diff --git a/patches/server/0074-Add-5-second-tps-average-in-tps.patch b/patches/server/0074-Add-5-second-tps-average-in-tps.patch index 180e992c7..2201dc095 100644 --- a/patches/server/0074-Add-5-second-tps-average-in-tps.patch +++ b/patches/server/0074-Add-5-second-tps-average-in-tps.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add 5 second tps average in /tps diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index bbc92489fd2e9037834fdea3a4514b5687ae86d7..e46705e7ab5d5c69e5d2bdd29d5066c4b2d60675 100644 +index 5367c3b7bdfb6951986e5c844fb978f42a0bfec5..c6c4349954cb302e933739870814f54e426bd825 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -166,7 +166,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0) { @@ -58,7 +66,7 @@ index e747ee83f1a69a4a4bad87e720abc9b085fb6149..a4edfb02fd350433020b0f3699726b61 int k = 0; for (int l = 0; j > 0 && l < i; ++l) { -@@ -491,6 +491,12 @@ public final class ItemStack { +@@ -546,6 +546,12 @@ public final class ItemStack { if (this.isDamaged(i, t0.getRandom(), t0 instanceof EntityPlayer ? (EntityPlayer) t0 : null)) { consumer.accept(t0); Item item = this.getItem(); @@ -71,11 +79,11 @@ index e747ee83f1a69a4a4bad87e720abc9b085fb6149..a4edfb02fd350433020b0f3699726b61 // CraftBukkit start - Check for item breaking if (this.count == 1 && t0 instanceof EntityHuman) { org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemBreakEvent((EntityHuman) t0, this); -diff --git a/src/main/java/net/minecraft/server/ItemTrident.java b/src/main/java/net/minecraft/server/ItemTrident.java -index 4eeeecef51cedcd0fe46ac4983472e214ccc9dad..0109d8db4f154802daef570e6d8b479cb5a49dab 100644 ---- a/src/main/java/net/minecraft/server/ItemTrident.java -+++ b/src/main/java/net/minecraft/server/ItemTrident.java -@@ -101,6 +101,16 @@ public class ItemTrident extends Item implements ItemVanishable { +diff --git a/src/main/java/net/minecraft/world/item/ItemTrident.java b/src/main/java/net/minecraft/world/item/ItemTrident.java +index 9896477b54cf91a88bdfc3d85018a59193b32859..0711d195c654edef5875f587e391bacfdea096da 100644 +--- a/src/main/java/net/minecraft/world/item/ItemTrident.java ++++ b/src/main/java/net/minecraft/world/item/ItemTrident.java +@@ -123,6 +123,16 @@ public class ItemTrident extends Item implements ItemVanishable { f2 *= f6 / f5; f3 *= f6 / f5; f4 *= f6 / f5; @@ -93,7 +101,7 @@ index 4eeeecef51cedcd0fe46ac4983472e214ccc9dad..0109d8db4f154802daef570e6d8b479c entityhuman.r(20); if (entityhuman.isOnGround()) { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 66e74ee74b56e25ca46704ca6cec403f15126c33..ef977c50ab987f0762e1f9efd8ac6f559c38aaef 100644 +index e66b79218e960d11da4759187e4473685ccb9a9e..7f6b028f32af113e5898a0f2f39e0ec6c4e4dd11 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -129,6 +129,19 @@ public class PurpurWorldConfig { diff --git a/patches/server/0076-Item-entity-immunities.patch b/patches/server/0076-Item-entity-immunities.patch index 2f6d7d085..f4fbceea7 100644 --- a/patches/server/0076-Item-entity-immunities.patch +++ b/patches/server/0076-Item-entity-immunities.patch @@ -4,11 +4,61 @@ Date: Sat, 22 Feb 2020 15:54:08 -0600 Subject: [PATCH] Item entity immunities -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index e93d028a3908aa4d0c1daf7929acc2a426bbb0df..3ba980830d6ecab81aa4c07f4804e1c30c7a12d6 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -1488,6 +1488,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java +index 3a66a34db2b8ac612431131cea80e57ee72de05f..70a1ff235690a5990f94bd9cf97d670b2f4c2aea 100644 +--- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java ++++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java +@@ -31,6 +31,7 @@ import net.minecraft.world.entity.EntityLiving; + import net.minecraft.world.entity.EnumItemSlot; + import net.minecraft.world.entity.ai.attributes.AttributeModifiable; + import net.minecraft.world.entity.decoration.EntityItemFrame; ++import net.minecraft.world.entity.item.EntityItem; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.entity.projectile.EntityArrow; + import net.minecraft.world.item.ItemStack; +@@ -67,7 +68,7 @@ public class EntityTrackerEntry { + private boolean q; + private boolean r; + // CraftBukkit start +- final Set trackedPlayers; // Paper - private -> package ++ public final Set trackedPlayers; // Paper - private -> public + // Paper start + private java.util.Map trackedPlayerMap = null; + +@@ -143,6 +144,15 @@ public class EntityTrackerEntry { + this.c(); + } + ++ // Purpur start - respawn burning item entities on client (client kills them) ++ if (tracker.fireTicks > 0 && tracker instanceof EntityItem) { ++ EntityItem item = (EntityItem) tracker; ++ if (item.immuneToFire && !item.dead) { ++ item.respawnOnClient(); ++ } ++ } ++ // Purpur end ++ + if (this.tickCounter % this.d == 0 || this.tracker.impulse || this.tracker.getDataWatcher().a()) { + int i; + int j; +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index c9d6ddd8874195c07b3573c6b1f61ffdcff2dddd..4f11a19137531a0406a5214cd0cce0bea06d0088 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -2487,7 +2487,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially + + public class EntityTracker { + +- final EntityTrackerEntry trackerEntry; // Paper - private -> package private ++ public final EntityTrackerEntry trackerEntry; // Paper - private -> public + public final Entity tracker; // Airplane - public for chunk + private final int trackingDistance; + private SectionPosition e; +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index b114d12d9d17071fb96f5ab225b85cdd5ad06861..7f897bebdc1fe2b7ce9528db9a7dd0fc0cf6c008 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1580,6 +1580,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne } @@ -16,11 +66,24 @@ index e93d028a3908aa4d0c1daf7929acc2a426bbb0df..3ba980830d6ecab81aa4c07f4804e1c3 public boolean a(Tag tag) { return this.O == tag; } -diff --git a/src/main/java/net/minecraft/server/EntityItem.java b/src/main/java/net/minecraft/server/EntityItem.java -index 9a8b7e06f14f17dfea08d7031c83f77491aaca65..c25dce9a75b0e79f9b59f31892d863f46e2565e9 100644 ---- a/src/main/java/net/minecraft/server/EntityItem.java -+++ b/src/main/java/net/minecraft/server/EntityItem.java -@@ -24,6 +24,9 @@ public class EntityItem extends Entity { +diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +index 5dc3670f35b04d933e96c4b42aa9fbcf941e69c7..3b84039a76843a0784e2d71bb66dc322450c2cab 100644 +--- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java ++++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +@@ -10,10 +10,12 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.chat.ChatMessage; + import net.minecraft.network.chat.IChatBaseComponent; + import net.minecraft.network.protocol.Packet; ++import net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata; + import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.stats.StatisticList; +@@ -50,6 +52,9 @@ public class EntityItem extends Entity { public final float b; private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit public boolean canMobPickup = true; // Paper @@ -30,7 +93,7 @@ index 9a8b7e06f14f17dfea08d7031c83f77491aaca65..c25dce9a75b0e79f9b59f31892d863f4 public EntityItem(EntityTypes entitytypes, World world) { super(entitytypes, world); -@@ -275,6 +278,16 @@ public class EntityItem extends Entity { +@@ -301,6 +306,16 @@ public class EntityItem extends Entity { return false; } else if (!this.getItemStack().getItem().a(damagesource)) { return false; @@ -47,7 +110,7 @@ index 9a8b7e06f14f17dfea08d7031c83f77491aaca65..c25dce9a75b0e79f9b59f31892d863f4 } else { // CraftBukkit start if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, damagesource, f)) { -@@ -455,6 +468,9 @@ public class EntityItem extends Entity { +@@ -481,6 +496,9 @@ public class EntityItem extends Entity { com.google.common.base.Preconditions.checkArgument(!itemstack.isEmpty(), "Cannot drop air"); // CraftBukkit this.getDataWatcher().set(EntityItem.ITEM, itemstack); this.getDataWatcher().markDirty(EntityItem.ITEM); // CraftBukkit - SPIGOT-4591, must mark dirty @@ -57,7 +120,7 @@ index 9a8b7e06f14f17dfea08d7031c83f77491aaca65..c25dce9a75b0e79f9b59f31892d863f4 } @Override -@@ -536,4 +552,15 @@ public class EntityItem extends Entity { +@@ -562,4 +580,15 @@ public class EntityItem extends Entity { super.setPositionRaw(x, y, z); } // Paper end - fix MC-4 @@ -73,28 +136,8 @@ index 9a8b7e06f14f17dfea08d7031c83f77491aaca65..c25dce9a75b0e79f9b59f31892d863f4 + } + // Purpur end } -diff --git a/src/main/java/net/minecraft/server/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/EntityTrackerEntry.java -index 9f6d767ce8139999032d4c51221da743c694cb09..63bcd1b61d0485b064d619ddfa0e201034087772 100644 ---- a/src/main/java/net/minecraft/server/EntityTrackerEntry.java -+++ b/src/main/java/net/minecraft/server/EntityTrackerEntry.java -@@ -114,6 +114,15 @@ public class EntityTrackerEntry { - this.c(); - } - -+ // Purpur start - respawn burning item entities on client (client kills them) -+ if (tracker.fireTicks > 0 && tracker instanceof EntityItem) { -+ EntityItem item = (EntityItem) tracker; -+ if (item.immuneToFire && !item.dead) { -+ item.respawnOnClient(); -+ } -+ } -+ // Purpur end -+ - if (this.tickCounter % this.d == 0 || this.tracker.impulse || this.tracker.getDataWatcher().a()) { - int i; - int j; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index ef977c50ab987f0762e1f9efd8ac6f559c38aaef..1e38e2e87ad30a908d9cf8d1455bb9250e281e55 100644 +index 7f6b028f32af113e5898a0f2f39e0ec6c4e4dd11..54ec01c01026f14f1f91aad2639109af853e10e4 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -101,6 +101,39 @@ public class PurpurWorldConfig { @@ -138,7 +181,7 @@ index ef977c50ab987f0762e1f9efd8ac6f559c38aaef..1e38e2e87ad30a908d9cf8d1455bb925 public boolean idleTimeoutTickNearbyEntities = true; public boolean idleTimeoutCountAsSleeping = false; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -index bcbaad11852a51436a00c8e172bdd841ba93ec3c..8c0b618ac66688f1fef42ae292745c2844aa12df 100644 +index 7a78ef2f6f673568c0528fa46168c69d21f51a66..0418291a69216081353c05c99d11dcd913b6b8cb 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java @@ -114,4 +114,36 @@ public class CraftItem extends CraftEntity implements Item { diff --git a/patches/server/0077-Add-ping-command.patch b/patches/server/0077-Add-ping-command.patch index 88cd37db6..794b27b4b 100644 --- a/patches/server/0077-Add-ping-command.patch +++ b/patches/server/0077-Add-ping-command.patch @@ -4,28 +4,11 @@ Date: Fri, 13 Mar 2020 22:29:10 -0500 Subject: [PATCH] Add /ping command -diff --git a/src/main/java/net/minecraft/server/ArgumentEntity.java b/src/main/java/net/minecraft/server/ArgumentEntity.java -index 1194f91a51f87bc461af039fe0819aaf3e5c8bdd..9141976d1d6c5cef9eb4d415df2ad3b8f14ce913 100644 ---- a/src/main/java/net/minecraft/server/ArgumentEntity.java -+++ b/src/main/java/net/minecraft/server/ArgumentEntity.java -@@ -69,10 +69,12 @@ public class ArgumentEntity implements ArgumentType { - return ((EntitySelector) commandcontext.getArgument(s, EntitySelector.class)).c((CommandListenerWrapper) commandcontext.getSource()); - } - -+ public static ArgumentEntity players() { return d(); } // Purpur - OBFHELPER - public static ArgumentEntity d() { - return new ArgumentEntity(false, true); - } - -+ public static Collection getPlayers(CommandContext commandcontext, String s) throws CommandSyntaxException { return f(commandcontext, s); } // Purpur - OBFHELPER - public static Collection f(CommandContext commandcontext, String s) throws CommandSyntaxException { - List list = ((EntitySelector) commandcontext.getArgument(s, EntitySelector.class)).d((CommandListenerWrapper) commandcontext.getSource()); - -diff --git a/src/main/java/net/minecraft/server/CommandDispatcher.java b/src/main/java/net/minecraft/server/CommandDispatcher.java -index 17753c8a997aa286460be5d8eb6508e2eaed18ce..d080bf58ebc9c1dc9d41fae7d515547bc3f26d54 100644 ---- a/src/main/java/net/minecraft/server/CommandDispatcher.java -+++ b/src/main/java/net/minecraft/server/CommandDispatcher.java -@@ -107,6 +107,7 @@ public class CommandDispatcher { +diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java +index 6fc5ee06c3bed8d9aa0e13dd7fa8d70ff6711f85..e8fe4984fdc67536561a1ad08b328a30b30b8717 100644 +--- a/src/main/java/net/minecraft/commands/CommandDispatcher.java ++++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java +@@ -191,6 +191,7 @@ public class CommandDispatcher { CommandIdleTimeout.a(this.b); CommandStop.a(this.b); CommandWhitelist.a(this.b); @@ -33,7 +16,7 @@ index 17753c8a997aa286460be5d8eb6508e2eaed18ce..d080bf58ebc9c1dc9d41fae7d515547b } if (commanddispatcher_servertype.d) { -@@ -338,10 +339,12 @@ public class CommandDispatcher { +@@ -422,10 +423,12 @@ public class CommandDispatcher { } @@ -46,7 +29,7 @@ index 17753c8a997aa286460be5d8eb6508e2eaed18ce..d080bf58ebc9c1dc9d41fae7d515547b public static RequiredArgumentBuilder a(String s, ArgumentType argumenttype) { return RequiredArgumentBuilder.argument(s, argumenttype); } -@@ -357,6 +360,7 @@ public class CommandDispatcher { +@@ -441,6 +444,7 @@ public class CommandDispatcher { }; } @@ -54,11 +37,11 @@ index 17753c8a997aa286460be5d8eb6508e2eaed18ce..d080bf58ebc9c1dc9d41fae7d515547b public com.mojang.brigadier.CommandDispatcher a() { return this.b; } -diff --git a/src/main/java/net/minecraft/server/CommandListenerWrapper.java b/src/main/java/net/minecraft/server/CommandListenerWrapper.java -index 31543b38a7c46d93333c5f96fdb718b0a7a087b2..8a605b88584a574d5814e97d83c63661b56cf753 100644 ---- a/src/main/java/net/minecraft/server/CommandListenerWrapper.java -+++ b/src/main/java/net/minecraft/server/CommandListenerWrapper.java -@@ -190,6 +190,7 @@ public class CommandListenerWrapper implements ICompletionProvider, com.destroys +diff --git a/src/main/java/net/minecraft/commands/CommandListenerWrapper.java b/src/main/java/net/minecraft/commands/CommandListenerWrapper.java +index 8402af32cc476d7f468842eb4f34c7521d72bcc8..4480fe75cfad35a5104b5116c5ec2c80d18f15f5 100644 +--- a/src/main/java/net/minecraft/commands/CommandListenerWrapper.java ++++ b/src/main/java/net/minecraft/commands/CommandListenerWrapper.java +@@ -211,6 +211,7 @@ public class CommandListenerWrapper implements ICompletionProvider, com.destroys } } @@ -66,8 +49,25 @@ index 31543b38a7c46d93333c5f96fdb718b0a7a087b2..8a605b88584a574d5814e97d83c63661 public EntityPlayer h() throws CommandSyntaxException { if (!(this.k instanceof EntityPlayer)) { throw CommandListenerWrapper.a.create(); +diff --git a/src/main/java/net/minecraft/commands/arguments/ArgumentEntity.java b/src/main/java/net/minecraft/commands/arguments/ArgumentEntity.java +index bbad2b1399d9d2e16bfa77563bd564f7c6f640d7..a85c4525335fa46bc23a6dd57cfaea1f697b3daa 100644 +--- a/src/main/java/net/minecraft/commands/arguments/ArgumentEntity.java ++++ b/src/main/java/net/minecraft/commands/arguments/ArgumentEntity.java +@@ -78,10 +78,12 @@ public class ArgumentEntity implements ArgumentType { + return ((EntitySelector) commandcontext.getArgument(s, EntitySelector.class)).c((CommandListenerWrapper) commandcontext.getSource()); + } + ++ public static ArgumentEntity players() { return d(); } // Purpur - OBFHELPER + public static ArgumentEntity d() { + return new ArgumentEntity(false, true); + } + ++ public static Collection getPlayers(CommandContext commandcontext, String s) throws CommandSyntaxException { return f(commandcontext, s); } // Purpur - OBFHELPER + public static Collection f(CommandContext commandcontext, String s) throws CommandSyntaxException { + List list = ((EntitySelector) commandcontext.getArgument(s, EntitySelector.class)).d((CommandListenerWrapper) commandcontext.getSource()); + diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index 10900ef825f88657f287c8c5b71a89338ba54c11..ebf74ddb9786d3bcccb62c85352bb6c2278433f3 100644 +index 8572cc59ad94cb5ac8b7625587c4dc23a1efbd4d..33c135aa02bbbaebbc503aaf665d8d00998b6b40 100644 --- a/src/main/java/net/pl3x/purpur/PurpurConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java @@ -133,10 +133,12 @@ public class PurpurConfig { @@ -85,16 +85,16 @@ index 10900ef825f88657f287c8c5b71a89338ba54c11..ebf74ddb9786d3bcccb62c85352bb6c2 public static String serverModName = "Purpur"; diff --git a/src/main/java/net/pl3x/purpur/command/PingCommand.java b/src/main/java/net/pl3x/purpur/command/PingCommand.java new file mode 100644 -index 0000000000000000000000000000000000000000..3d4762c4a179aaf4e270af018b940f93f1a7d9cd +index 0000000000000000000000000000000000000000..1d636d7c541d127a473d5be2509e5db29936e8ad --- /dev/null +++ b/src/main/java/net/pl3x/purpur/command/PingCommand.java @@ -0,0 +1,37 @@ +package net.pl3x.purpur.command; + -+import net.minecraft.server.ArgumentEntity; -+import net.minecraft.server.CommandDispatcher; -+import net.minecraft.server.CommandListenerWrapper; -+import net.minecraft.server.EntityPlayer; ++import net.minecraft.commands.arguments.ArgumentEntity; ++import net.minecraft.commands.CommandDispatcher; ++import net.minecraft.commands.CommandListenerWrapper; ++import net.minecraft.server.level.EntityPlayer; +import net.pl3x.purpur.PurpurConfig; +import org.bukkit.craftbukkit.util.CraftChatMessage; + diff --git a/patches/server/0078-Configurable-jockey-options.patch b/patches/server/0078-Configurable-jockey-options.patch index 20427c193..bc0f3d15b 100644 --- a/patches/server/0078-Configurable-jockey-options.patch +++ b/patches/server/0078-Configurable-jockey-options.patch @@ -4,11 +4,11 @@ Date: Thu, 26 Mar 2020 21:39:32 -0500 Subject: [PATCH] Configurable jockey options -diff --git a/src/main/java/net/minecraft/server/EntityDrowned.java b/src/main/java/net/minecraft/server/EntityDrowned.java -index 9ae0897bfd6a4577901d9189d0dba22f3ec2110c..1a102816921fa3b40f6d364bb826db4459f68eb2 100644 ---- a/src/main/java/net/minecraft/server/EntityDrowned.java -+++ b/src/main/java/net/minecraft/server/EntityDrowned.java -@@ -21,6 +21,23 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java b/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java +index e4794760fc918cccbdc3f8d10ab21dd9b6f29e8e..ea776755767f29e49de2792afa30f79420d0fa4c 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java +@@ -72,6 +72,23 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { this.navigationLand = new Navigation(this, world); } @@ -32,11 +32,11 @@ index 9ae0897bfd6a4577901d9189d0dba22f3ec2110c..1a102816921fa3b40f6d364bb826db44 @Override protected void m() { this.goalSelector.a(1, new EntityDrowned.c(this, 1.0D)); -diff --git a/src/main/java/net/minecraft/server/EntityPigZombie.java b/src/main/java/net/minecraft/server/EntityPigZombie.java -index 65bae8c9f28c23b0b5dd5d048e7fc7daf328075c..32b75f710b12efbcecec2c8d72d4d8cb725870fe 100644 ---- a/src/main/java/net/minecraft/server/EntityPigZombie.java -+++ b/src/main/java/net/minecraft/server/EntityPigZombie.java -@@ -21,6 +21,23 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java +index cc1bff409cad2eb6264d4b691599576960080ccd..af00a4245ca39f208810d1ec758e512cbf5648f3 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java +@@ -55,6 +55,23 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { this.a(PathType.LAVA, 8.0F); } @@ -60,11 +60,11 @@ index 65bae8c9f28c23b0b5dd5d048e7fc7daf328075c..32b75f710b12efbcecec2c8d72d4d8cb @Override public void setAngerTarget(@Nullable UUID uuid) { this.br = uuid; -diff --git a/src/main/java/net/minecraft/server/EntityZombie.java b/src/main/java/net/minecraft/server/EntityZombie.java -index c081dfa775dc93afd96eff88953c9a5f21f2adb9..291748b3436c18653fa959cfd8c92240aa17508c 100644 ---- a/src/main/java/net/minecraft/server/EntityZombie.java -+++ b/src/main/java/net/minecraft/server/EntityZombie.java -@@ -3,6 +3,7 @@ package net.minecraft.server; +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +index 634416c354184bc6a2348c27c55e9868009ccd28..5ac950614fc90d02a568bb38f71faee124584c16 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +@@ -3,6 +3,7 @@ package net.minecraft.world.entity.monster; import com.mojang.serialization.DynamicOps; import java.time.LocalDate; import java.time.temporal.ChronoField; @@ -72,7 +72,7 @@ index c081dfa775dc93afd96eff88953c9a5f21f2adb9..291748b3436c18653fa959cfd8c92240 import java.util.List; import java.util.Random; import java.util.UUID; -@@ -44,6 +45,20 @@ public class EntityZombie extends EntityMonster { +@@ -106,6 +107,20 @@ public class EntityZombie extends EntityMonster { this(EntityTypes.ZOMBIE, world); } @@ -93,7 +93,7 @@ index c081dfa775dc93afd96eff88953c9a5f21f2adb9..291748b3436c18653fa959cfd8c92240 @Override protected void initPathfinder() { if (world.paperConfig.zombiesTargetTurtleEggs) this.goalSelector.a(4, new EntityZombie.a(this, 1.0D, 3)); // Paper -@@ -444,19 +459,19 @@ public class EntityZombie extends EntityMonster { +@@ -506,19 +521,19 @@ public class EntityZombie extends EntityMonster { if (object instanceof EntityZombie.GroupDataZombie) { EntityZombie.GroupDataZombie entityzombie_groupdatazombie = (EntityZombie.GroupDataZombie) object; @@ -119,7 +119,7 @@ index c081dfa775dc93afd96eff88953c9a5f21f2adb9..291748b3436c18653fa959cfd8c92240 EntityChicken entitychicken1 = (EntityChicken) EntityTypes.CHICKEN.a(this.world); entitychicken1.setPositionRotation(this.locX(), this.locY(), this.locZ(), this.yaw, 0.0F); -@@ -464,6 +479,7 @@ public class EntityZombie extends EntityMonster { +@@ -526,6 +541,7 @@ public class EntityZombie extends EntityMonster { entitychicken1.setChickenJockey(true); this.startRiding(entitychicken1); worldaccess.addEntity(entitychicken1, CreatureSpawnEvent.SpawnReason.MOUNT); // CraftBukkit @@ -127,7 +127,7 @@ index c081dfa775dc93afd96eff88953c9a5f21f2adb9..291748b3436c18653fa959cfd8c92240 } } } -@@ -566,7 +582,7 @@ public class EntityZombie extends EntityMonster { +@@ -628,7 +644,7 @@ public class EntityZombie extends EntityMonster { public static class GroupDataZombie implements GroupDataEntity { @@ -136,11 +136,11 @@ index c081dfa775dc93afd96eff88953c9a5f21f2adb9..291748b3436c18653fa959cfd8c92240 public final boolean b; public GroupDataZombie(boolean flag, boolean flag1) { -diff --git a/src/main/java/net/minecraft/server/EntityZombieHusk.java b/src/main/java/net/minecraft/server/EntityZombieHusk.java -index 2d2830adc5229a8db7fc4b1170ea4c6f263e7182..ce6d79780197eb9300130036a8ed84648a17f9cf 100644 ---- a/src/main/java/net/minecraft/server/EntityZombieHusk.java -+++ b/src/main/java/net/minecraft/server/EntityZombieHusk.java -@@ -8,6 +8,23 @@ public class EntityZombieHusk extends EntityZombie { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java +index ce08413134de6101420ccb957da925ea1e3b0884..5d3e5873f19aaf8389eb5525693b9378ea9f94ee 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java +@@ -22,6 +22,23 @@ public class EntityZombieHusk extends EntityZombie { super(entitytypes, world); } @@ -164,11 +164,11 @@ index 2d2830adc5229a8db7fc4b1170ea4c6f263e7182..ce6d79780197eb9300130036a8ed8464 public static boolean a(EntityTypes entitytypes, WorldAccess worldaccess, EnumMobSpawn enummobspawn, BlockPosition blockposition, Random random) { return b(entitytypes, worldaccess, enummobspawn, blockposition, random) && (enummobspawn == EnumMobSpawn.SPAWNER || worldaccess.e(blockposition)); } -diff --git a/src/main/java/net/minecraft/server/EntityZombieVillager.java b/src/main/java/net/minecraft/server/EntityZombieVillager.java -index b90605c463d378cea06c3cb84aad4c97145d00ce..5a71381c9f1832710001b6bfa63d6815c3cd1ab0 100644 ---- a/src/main/java/net/minecraft/server/EntityZombieVillager.java -+++ b/src/main/java/net/minecraft/server/EntityZombieVillager.java -@@ -28,6 +28,23 @@ public class EntityZombieVillager extends EntityZombie implements VillagerDataHo +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java +index c03f4655dcca3d9635a7e13244b7977425a3f291..167ea96ec4072a9415a2ae9d7a0db118bfb94e19 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java +@@ -70,6 +70,23 @@ public class EntityZombieVillager extends EntityZombie implements VillagerDataHo this.setVillagerData(this.getVillagerData().withProfession((VillagerProfession) IRegistry.VILLAGER_PROFESSION.a(this.random))); } @@ -193,7 +193,7 @@ index b90605c463d378cea06c3cb84aad4c97145d00ce..5a71381c9f1832710001b6bfa63d6815 protected void initDatawatcher() { super.initDatawatcher(); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 1e38e2e87ad30a908d9cf8d1455bb9250e281e55..dd6a86d5765008f98e59b54a365d824e390fdf94 100644 +index 54ec01c01026f14f1f91aad2639109af853e10e4..1ebc8d04020aec7e36dfed5196dde9e9fe6ada0f 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -275,6 +275,15 @@ public class PurpurWorldConfig { diff --git a/patches/server/0079-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch b/patches/server/0079-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch index 60be279c3..49562dcb1 100644 --- a/patches/server/0079-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch +++ b/patches/server/0079-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch @@ -4,11 +4,11 @@ Date: Thu, 9 May 2019 18:26:06 -0500 Subject: [PATCH] Phantoms attracted to crystals and crystals shoot phantoms -diff --git a/src/main/java/net/minecraft/server/DamageSource.java b/src/main/java/net/minecraft/server/DamageSource.java -index 6fe5678cffc2487fe00c953d772f764bb37a4b11..bd0267ee4b3782f6d1ec39cba7966ba4f62f1adf 100644 ---- a/src/main/java/net/minecraft/server/DamageSource.java -+++ b/src/main/java/net/minecraft/server/DamageSource.java -@@ -88,6 +88,7 @@ public class DamageSource { +diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java +index 53ea8a6d90faf4f7f8fd0819be4499422bdd4cbe..6ba14f603b8ec69597c70677cc317f802d6afae9 100644 +--- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java ++++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java +@@ -99,6 +99,7 @@ public class DamageSource { return (new EntityDamageSourceIndirect("thrown", entity, entity1)).c(); } @@ -16,11 +16,11 @@ index 6fe5678cffc2487fe00c953d772f764bb37a4b11..bd0267ee4b3782f6d1ec39cba7966ba4 public static DamageSource c(Entity entity, @Nullable Entity entity1) { return (new EntityDamageSourceIndirect("indirectMagic", entity, entity1)).setIgnoreArmor().setMagic(); } -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 3ba980830d6ecab81aa4c07f4804e1c30c7a12d6..13217b14834f4aaf3eddba8da3c3bc4a97cb27c6 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -2154,8 +2154,8 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 7f897bebdc1fe2b7ce9528db9a7dd0fc0cf6c008..5ac6b7759cf43dbbad1bcf74d5d86efd69883cf5 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2246,8 +2246,8 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne return this.a(new ItemStack(imaterial), (float) i); } @@ -31,11 +31,19 @@ index 3ba980830d6ecab81aa4c07f4804e1c30c7a12d6..13217b14834f4aaf3eddba8da3c3bc4a return this.a(itemstack, 0.0F); } -diff --git a/src/main/java/net/minecraft/server/EntityEnderCrystal.java b/src/main/java/net/minecraft/server/EntityEnderCrystal.java -index 362ca695d88a7c788421cc557b8110b954d8153a..1942fae27051af79b6eb1d790a219da100bf889e 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderCrystal.java -+++ b/src/main/java/net/minecraft/server/EntityEnderCrystal.java -@@ -13,6 +13,12 @@ public class EntityEnderCrystal extends Entity { +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java +index 9658d93615a51375204481cfe0a1fce6f105fd70..2c983e6a092464d1867fcbe875b2e1461ec8556b 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java +@@ -14,6 +14,7 @@ import net.minecraft.server.level.WorldServer; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityTypes; ++import net.minecraft.world.entity.monster.EntityPhantom; + import net.minecraft.world.level.Explosion; + import net.minecraft.world.level.IBlockAccess; + import net.minecraft.world.level.World; +@@ -30,6 +31,12 @@ public class EntityEnderCrystal extends Entity { private static final DataWatcherObject> c = DataWatcher.a(EntityEnderCrystal.class, DataWatcherRegistry.m); private static final DataWatcherObject d = DataWatcher.a(EntityEnderCrystal.class, DataWatcherRegistry.i); public int b; @@ -48,7 +56,7 @@ index 362ca695d88a7c788421cc557b8110b954d8153a..1942fae27051af79b6eb1d790a219da1 public EntityEnderCrystal(EntityTypes entitytypes, World world) { super(entitytypes, world); -@@ -51,7 +57,50 @@ public class EntityEnderCrystal extends Entity { +@@ -68,7 +75,50 @@ public class EntityEnderCrystal extends Entity { } } @@ -99,11 +107,32 @@ index 362ca695d88a7c788421cc557b8110b954d8153a..1942fae27051af79b6eb1d790a219da1 @Override protected void saveData(NBTTagCompound nbttagcompound) { -diff --git a/src/main/java/net/minecraft/server/EntityPhantom.java b/src/main/java/net/minecraft/server/EntityPhantom.java -index 3a70900c73e3a6c4f40cf74406534f4bfd3eb67b..dfce36368da9bdd9285c490a802f7a0cc4a339f6 100644 ---- a/src/main/java/net/minecraft/server/EntityPhantom.java -+++ b/src/main/java/net/minecraft/server/EntityPhantom.java -@@ -9,9 +9,10 @@ import javax.annotation.Nullable; +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java +index 42cf3fa42b73739182d26fbb524ee5b304c799b2..daf738e8f0987aa6ab200189d7a26d166918b8fc 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java +@@ -12,6 +12,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundCategory; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -36,18 +37,23 @@ import net.minecraft.world.entity.ai.control.EntityAIBodyControl; + import net.minecraft.world.entity.ai.goal.PathfinderGoal; + import net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition; + import net.minecraft.world.entity.animal.EntityCat; ++import net.minecraft.world.entity.boss.enderdragon.EntityEnderCrystal; + import net.minecraft.world.entity.player.EntityHuman; ++import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.item.Items; + import net.minecraft.world.level.World; + import net.minecraft.world.level.WorldAccess; + import net.minecraft.world.level.levelgen.HeightMap; ++import net.minecraft.world.level.storage.loot.LootTableInfo; + import net.minecraft.world.phys.Vec3D; + public class EntityPhantom extends EntityFlying implements IMonster { private static final DataWatcherObject b = DataWatcher.a(EntityPhantom.class, DataWatcherRegistry.b); @@ -117,7 +146,7 @@ index 3a70900c73e3a6c4f40cf74406534f4bfd3eb67b..dfce36368da9bdd9285c490a802f7a0c public EntityPhantom(EntityTypes entitytypes, World world) { super(entitytypes, world); -@@ -30,11 +31,37 @@ public class EntityPhantom extends EntityFlying implements IMonster { +@@ -66,11 +72,37 @@ public class EntityPhantom extends EntityFlying implements IMonster { @Override protected void initPathfinder() { @@ -159,8 +188,8 @@ index 3a70900c73e3a6c4f40cf74406534f4bfd3eb67b..dfce36368da9bdd9285c490a802f7a0c @Override protected void initDatawatcher() { -@@ -198,6 +225,136 @@ public class EntityPhantom extends EntityFlying implements IMonster { - } +@@ -235,6 +267,136 @@ public class EntityPhantom extends EntityFlying implements IMonster { + public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; } // Paper end + // Purpur start @@ -296,7 +325,7 @@ index 3a70900c73e3a6c4f40cf74406534f4bfd3eb67b..dfce36368da9bdd9285c490a802f7a0c class b extends PathfinderGoal { private final PathfinderTargetCondition b; -@@ -210,6 +367,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { +@@ -247,6 +409,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { @Override public boolean a() { @@ -304,7 +333,7 @@ index 3a70900c73e3a6c4f40cf74406534f4bfd3eb67b..dfce36368da9bdd9285c490a802f7a0c if (this.c > 0) { --this.c; return false; -@@ -238,6 +396,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { +@@ -275,6 +438,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { @Override public boolean b() { @@ -312,7 +341,7 @@ index 3a70900c73e3a6c4f40cf74406534f4bfd3eb67b..dfce36368da9bdd9285c490a802f7a0c EntityLiving entityliving = EntityPhantom.this.getGoalTarget(); return entityliving != null ? EntityPhantom.this.a(entityliving, PathfinderTargetCondition.a) : false; -@@ -252,6 +411,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { +@@ -289,6 +453,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { @Override public boolean a() { @@ -321,7 +350,7 @@ index 3a70900c73e3a6c4f40cf74406534f4bfd3eb67b..dfce36368da9bdd9285c490a802f7a0c return entityliving != null ? EntityPhantom.this.a(EntityPhantom.this.getGoalTarget(), PathfinderTargetCondition.a) : false; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index dd6a86d5765008f98e59b54a365d824e390fdf94..88cac6394f67ec113a781a552261f760fc95eb16 100644 +index 1ebc8d04020aec7e36dfed5196dde9e9fe6ada0f..d5e1ca888c6fe0910f54e30b3b59af4dfde86cb3 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -349,6 +349,15 @@ public class PurpurWorldConfig { diff --git a/patches/server/0080-Add-phantom-spawning-options.patch b/patches/server/0080-Add-phantom-spawning-options.patch index 8e99b8179..e99243d6b 100644 --- a/patches/server/0080-Add-phantom-spawning-options.patch +++ b/patches/server/0080-Add-phantom-spawning-options.patch @@ -4,11 +4,11 @@ Date: Fri, 3 Jul 2020 00:03:52 -0500 Subject: [PATCH] Add phantom spawning options -diff --git a/src/main/java/net/minecraft/server/DifficultyDamageScaler.java b/src/main/java/net/minecraft/server/DifficultyDamageScaler.java -index 75745af3435434bddd420536ca3bbea3a9f181d6..84c0ec1b50758b433980765d087e15d8a8eaaaf7 100644 ---- a/src/main/java/net/minecraft/server/DifficultyDamageScaler.java -+++ b/src/main/java/net/minecraft/server/DifficultyDamageScaler.java -@@ -13,6 +13,7 @@ public class DifficultyDamageScaler { +diff --git a/src/main/java/net/minecraft/world/DifficultyDamageScaler.java b/src/main/java/net/minecraft/world/DifficultyDamageScaler.java +index c2fe4329576e6dcd5df435bc580d79a2b6db1fcd..44f19d8c8f5d344b2659cf01eb4be40f5510a2c2 100644 +--- a/src/main/java/net/minecraft/world/DifficultyDamageScaler.java ++++ b/src/main/java/net/minecraft/world/DifficultyDamageScaler.java +@@ -14,6 +14,7 @@ public class DifficultyDamageScaler { this.b = this.a(enumdifficulty, i, j, f); } @@ -16,7 +16,7 @@ index 75745af3435434bddd420536ca3bbea3a9f181d6..84c0ec1b50758b433980765d087e15d8 public EnumDifficulty a() { return this.a; } -@@ -21,6 +22,7 @@ public class DifficultyDamageScaler { +@@ -22,6 +23,7 @@ public class DifficultyDamageScaler { return this.b; } @@ -24,11 +24,11 @@ index 75745af3435434bddd420536ca3bbea3a9f181d6..84c0ec1b50758b433980765d087e15d8 public boolean a(float f) { return this.b > f; } -diff --git a/src/main/java/net/minecraft/server/EnumDifficulty.java b/src/main/java/net/minecraft/server/EnumDifficulty.java -index e0e72779c0f4e4856ed5682122fedf0321db11cb..386eae71a146e06ca60f8bf11429fe2131232a21 100644 ---- a/src/main/java/net/minecraft/server/EnumDifficulty.java -+++ b/src/main/java/net/minecraft/server/EnumDifficulty.java -@@ -19,6 +19,7 @@ public enum EnumDifficulty { +diff --git a/src/main/java/net/minecraft/world/EnumDifficulty.java b/src/main/java/net/minecraft/world/EnumDifficulty.java +index 53fac6aa71938805264b7cc4769e63a9d4a66114..a1a80aab7ef6fdb2a35082fa452d0b46c1fcdcbe 100644 +--- a/src/main/java/net/minecraft/world/EnumDifficulty.java ++++ b/src/main/java/net/minecraft/world/EnumDifficulty.java +@@ -21,6 +21,7 @@ public enum EnumDifficulty { this.g = s; } @@ -36,11 +36,11 @@ index e0e72779c0f4e4856ed5682122fedf0321db11cb..386eae71a146e06ca60f8bf11429fe21 public int a() { return this.f; } -diff --git a/src/main/java/net/minecraft/server/IBlockLightAccess.java b/src/main/java/net/minecraft/server/IBlockLightAccess.java -index 03a89301f2b3d29e39c6c9d05ee072527f652efc..fa5eb188da64cc1409cc614515e8c70b0a341dd0 100644 ---- a/src/main/java/net/minecraft/server/IBlockLightAccess.java -+++ b/src/main/java/net/minecraft/server/IBlockLightAccess.java -@@ -12,6 +12,7 @@ public interface IBlockLightAccess extends IBlockAccess { +diff --git a/src/main/java/net/minecraft/world/level/IBlockLightAccess.java b/src/main/java/net/minecraft/world/level/IBlockLightAccess.java +index 8b2e57c833c03940f2e0727e00decce59f263269..642bf019d32a2fdc18718337ecfe45d24022f8bd 100644 +--- a/src/main/java/net/minecraft/world/level/IBlockLightAccess.java ++++ b/src/main/java/net/minecraft/world/level/IBlockLightAccess.java +@@ -15,6 +15,7 @@ public interface IBlockLightAccess extends IBlockAccess { return this.e().b(blockposition, i); } @@ -48,15 +48,56 @@ index 03a89301f2b3d29e39c6c9d05ee072527f652efc..fa5eb188da64cc1409cc614515e8c70b default boolean e(BlockPosition blockposition) { return this.getBrightness(EnumSkyBlock.SKY, blockposition) >= this.K(); } -diff --git a/src/main/java/net/minecraft/server/MobSpawnerPhantom.java b/src/main/java/net/minecraft/server/MobSpawnerPhantom.java -index 4e3f01bc79b6ed2a322155f29f1d0dcf298c8b82..ac1ea2f0c15bccf94f203194a5a7b10ec125ffb8 100644 ---- a/src/main/java/net/minecraft/server/MobSpawnerPhantom.java -+++ b/src/main/java/net/minecraft/server/MobSpawnerPhantom.java -@@ -1,85 +1,99 @@ - package net.minecraft.server; +diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java +index d98526785ff2fa3b72e8ffffcb89a57a2203a5c8..7859d84471436b427138593776ebd30a0429b6b4 100644 +--- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java ++++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java +@@ -431,6 +431,7 @@ public final class SpawnerCreature { + return new BlockPosition(i, l, j); + } + ++ public static boolean canSpawn(IBlockAccess iblockaccess, BlockPosition blockposition, IBlockData iblockdata, Fluid fluid, EntityTypes entitytypes) { return a(iblockaccess, blockposition, iblockdata, fluid, entitytypes); } // Purpur - OBFHELPER + public static boolean a(IBlockAccess iblockaccess, BlockPosition blockposition, IBlockData iblockdata, Fluid fluid, EntityTypes entitytypes) { + return iblockdata.r(iblockaccess, blockposition) ? false : (iblockdata.isPowerSource() ? false : (!fluid.isEmpty() ? false : (iblockdata.a((Tag) TagsBlock.PREVENT_MOB_SPAWNING_INSIDE) ? false : !entitytypes.a(iblockdata)))); + } +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index cef8e9b379c4205386d1001e86abc7dcb0b18eb6..4fa0f6ce7f8e6f5fba68d66a2c81ad4a53ca2146 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -1749,6 +1749,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + return new DifficultyDamageScaler(this.getDifficulty(), this.getDayTime(), i, f); + } + ++ public int getSkyDarkness() { return c(); } // Purpur - OBFHELPER + @Override + public int c() { + return this.d; +diff --git a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java +index e4f5e570636862481aac92ec9b74d6cf5723eb6e..e954adeff4fbfc1aa85ac3785c0c4c86bde24cdb 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java +@@ -1,9 +1,6 @@ + package net.minecraft.world.level.levelgen; -import java.util.Iterator; -import java.util.Random; + import net.minecraft.core.BlockPosition; +-import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.server.MCUtil; + import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.WorldServer; +@@ -15,92 +12,103 @@ import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.monster.EntityPhantom; +-import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.level.GameRules; +-import net.minecraft.world.level.IBlockAccess; + import net.minecraft.world.level.MobSpawner; + import net.minecraft.world.level.SpawnerCreature; +-import net.minecraft.world.level.World; +-import net.minecraft.world.level.block.state.IBlockData; +-import net.minecraft.world.level.material.Fluid; +import com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent; +import org.bukkit.event.entity.CreatureSpawnEvent; @@ -132,7 +173,7 @@ index 4e3f01bc79b6ed2a322155f29f1d0dcf298c8b82..ac1ea2f0c15bccf94f203194a5a7b10e - } - // Paper end - EntityPhantom entityphantom = (EntityPhantom) EntityTypes.PHANTOM.a((World) worldserver); -- entityphantom.spawningEntity = entityhuman.uniqueID; // Paper +- entityphantom.setSpawningEntity(entityhuman.getUniqueID()); // Paper - entityphantom.setPositionRotation(blockposition1, 0.0F, 0.0F); - groupdataentity = entityphantom.prepare(worldserver, difficultydamagescaler, EnumMobSpawn.NATURAL, groupdataentity, (NBTTagCompound) null); - worldserver.addAllEntities(entityphantom, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit @@ -207,7 +248,7 @@ index 4e3f01bc79b6ed2a322155f29f1d0dcf298c8b82..ac1ea2f0c15bccf94f203194a5a7b10e + continue; } + -+ phantom.spawningEntity = player.uniqueID; // Paper ++ phantom.setSpawningEntity(player.getUniqueID()); // Paper + phantom.setPositionRotation(spawnPos, 0.0F, 0.0F); + groupData = phantom.prepare(world, dmgScaler, EnumMobSpawn.NATURAL, groupData, null); + world.addEntity(phantom, CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit @@ -220,32 +261,8 @@ index 4e3f01bc79b6ed2a322155f29f1d0dcf298c8b82..ac1ea2f0c15bccf94f203194a5a7b10e + // Purpur end - rewrite entire thing } } -diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java -index c7573e1271288bd2b9dfe9801ea8f8804089f6ce..b5b0f295d63eb245a6221f88110f1bb1694c641c 100644 ---- a/src/main/java/net/minecraft/server/SpawnerCreature.java -+++ b/src/main/java/net/minecraft/server/SpawnerCreature.java -@@ -397,6 +397,7 @@ public final class SpawnerCreature { - return new BlockPosition(i, l, j); - } - -+ public static boolean canSpawn(IBlockAccess iblockaccess, BlockPosition blockposition, IBlockData iblockdata, Fluid fluid, EntityTypes entitytypes) { return a(iblockaccess, blockposition, iblockdata, fluid, entitytypes); } // Purpur - OBFHELPER - public static boolean a(IBlockAccess iblockaccess, BlockPosition blockposition, IBlockData iblockdata, Fluid fluid, EntityTypes entitytypes) { - return iblockdata.r(iblockaccess, blockposition) ? false : (iblockdata.isPowerSource() ? false : (!fluid.isEmpty() ? false : (iblockdata.a((Tag) TagsBlock.PREVENT_MOB_SPAWNING_INSIDE) ? false : !entitytypes.a(iblockdata)))); - } -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 068d303853572519efc16bb9cd3b799e458e39e7..ad7360cd5ae79e4d031ae866bf911fb87a2c0cdf 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -1687,6 +1687,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return new DifficultyDamageScaler(this.getDifficulty(), this.getDayTime(), i, f); - } - -+ public int getSkyDarkness() { return c(); } // Purpur - OBFHELPER - @Override - public int c() { - return this.d; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 88cac6394f67ec113a781a552261f760fc95eb16..fedc39bdbbd328296c5c08d220d6695fe08fdf91 100644 +index d5e1ca888c6fe0910f54e30b3b59af4dfde86cb3..104947fbf7c68c94e5b0b72b13307197e041ae1c 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -352,10 +352,34 @@ public class PurpurWorldConfig { diff --git a/patches/server/0081-Implement-bed-explosion-options.patch b/patches/server/0081-Implement-bed-explosion-options.patch index f03b86fa8..3867f4852 100644 --- a/patches/server/0081-Implement-bed-explosion-options.patch +++ b/patches/server/0081-Implement-bed-explosion-options.patch @@ -4,11 +4,11 @@ Date: Sat, 4 Jul 2020 13:12:43 -0500 Subject: [PATCH] Implement bed explosion options -diff --git a/src/main/java/net/minecraft/server/BlockBed.java b/src/main/java/net/minecraft/server/BlockBed.java -index 24a5c64b65f0098b1395d352cc2f99bbbbaf9c94..738535d01adf8bfd895b5057e595042253f32f87 100644 ---- a/src/main/java/net/minecraft/server/BlockBed.java -+++ b/src/main/java/net/minecraft/server/BlockBed.java -@@ -88,7 +88,7 @@ public class BlockBed extends BlockFacingHorizontal implements ITileEntity { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockBed.java b/src/main/java/net/minecraft/world/level/block/BlockBed.java +index eca84595342756e3550883551e487aaf79574fde..d81c05c092173b7e74045cfab1018d2eed28c401 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockBed.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockBed.java +@@ -127,7 +127,7 @@ public class BlockBed extends BlockFacingHorizontal implements ITileEntity { world.a(blockposition1, false); } @@ -18,17 +18,17 @@ index 24a5c64b65f0098b1395d352cc2f99bbbbaf9c94..738535d01adf8bfd895b5057e5950422 } } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index fedc39bdbbd328296c5c08d220d6695fe08fdf91..35e4f4160358b12b61d2763b8d2f5ff51022b666 100644 +index 104947fbf7c68c94e5b0b72b13307197e041ae1c..5486dd15752e9c260275a6b3d5ed702e6bf14a81 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -2,6 +2,7 @@ package net.pl3x.purpur; +@@ -1,6 +1,7 @@ + package net.pl3x.purpur; - import net.minecraft.server.Block; - import net.minecraft.server.Blocks; -+import net.minecraft.server.Explosion; - import net.minecraft.server.IRegistry; - import net.minecraft.server.Item; - import net.minecraft.server.Items; + import net.minecraft.core.IRegistry; ++import net.minecraft.world.level.Explosion; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.item.Item; @@ -12,6 +13,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; diff --git a/patches/server/0082-Implement-respawn-anchor-explosion-options.patch b/patches/server/0082-Implement-respawn-anchor-explosion-options.patch index 506b6b6cb..669c9d392 100644 --- a/patches/server/0082-Implement-respawn-anchor-explosion-options.patch +++ b/patches/server/0082-Implement-respawn-anchor-explosion-options.patch @@ -4,11 +4,11 @@ Date: Sat, 4 Jul 2020 13:23:19 -0500 Subject: [PATCH] Implement respawn anchor explosion options -diff --git a/src/main/java/net/minecraft/server/BlockRespawnAnchor.java b/src/main/java/net/minecraft/server/BlockRespawnAnchor.java -index 21c5ad83a95bcd23071423c0e8336656b760fcde..521d161a3d015b641b61de21401c79ac20eb73a7 100644 ---- a/src/main/java/net/minecraft/server/BlockRespawnAnchor.java -+++ b/src/main/java/net/minecraft/server/BlockRespawnAnchor.java -@@ -83,10 +83,7 @@ public class BlockRespawnAnchor extends Block { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockRespawnAnchor.java b/src/main/java/net/minecraft/world/level/block/BlockRespawnAnchor.java +index 028e98decf8b0496b4ebcd1aad3aa474e5c4e7c1..9b7a7f1ae50baf53d314bbf1588afeb8e61dae5d 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockRespawnAnchor.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockRespawnAnchor.java +@@ -115,10 +115,7 @@ public class BlockRespawnAnchor extends Block { private void d(IBlockData iblockdata, World world, final BlockPosition blockposition) { world.a(blockposition, false); @@ -20,7 +20,7 @@ index 21c5ad83a95bcd23071423c0e8336656b760fcde..521d161a3d015b641b61de21401c79ac return a(blockposition1, world); }); final boolean flag1 = flag || world.getFluid(blockposition.up()).a((Tag) TagsFluid.WATER); -@@ -97,7 +94,7 @@ public class BlockRespawnAnchor extends Block { +@@ -129,7 +126,7 @@ public class BlockRespawnAnchor extends Block { } }; @@ -30,7 +30,7 @@ index 21c5ad83a95bcd23071423c0e8336656b760fcde..521d161a3d015b641b61de21401c79ac public static boolean a(World world) { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 35e4f4160358b12b61d2763b8d2f5ff51022b666..07e60861c99db1ee1ba7a01c7a666a83e644aa2a 100644 +index 5486dd15752e9c260275a6b3d5ed702e6bf14a81..a366742e8d11513b469ffb8dafd98a4c0d8ab30a 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -251,6 +251,22 @@ public class PurpurWorldConfig { diff --git a/patches/server/0083-Add-allow-water-in-end-world-option.patch b/patches/server/0083-Add-allow-water-in-end-world-option.patch index e825ea5d7..af35da066 100644 --- a/patches/server/0083-Add-allow-water-in-end-world-option.patch +++ b/patches/server/0083-Add-allow-water-in-end-world-option.patch @@ -4,33 +4,11 @@ Date: Sun, 5 Jul 2020 23:40:16 -0500 Subject: [PATCH] Add allow water in end world option -diff --git a/src/main/java/net/minecraft/server/BlockIce.java b/src/main/java/net/minecraft/server/BlockIce.java -index aba5c6b8713c04302632bd1d289fd968c9e0607a..b75f6ded5d4bd3150789fba773a2c76c3e55bb90 100644 ---- a/src/main/java/net/minecraft/server/BlockIce.java -+++ b/src/main/java/net/minecraft/server/BlockIce.java -@@ -13,7 +13,7 @@ public class BlockIce extends BlockHalfTransparent { - public void a(World world, EntityHuman entityhuman, BlockPosition blockposition, IBlockData iblockdata, @Nullable TileEntity tileentity, ItemStack itemstack) { - super.a(world, entityhuman, blockposition, iblockdata, tileentity, itemstack); - if (EnchantmentManager.getEnchantmentLevel(Enchantments.SILK_TOUCH, itemstack) == 0) { -- if (world.getDimensionManager().isNether()) { -+ if (world.isNether() || (world.isTheEnd() && !net.pl3x.purpur.PurpurConfig.allowWaterPlacementInTheEnd)) { // Purpur - world.a(blockposition, false); - return; - } -@@ -41,7 +41,7 @@ public class BlockIce extends BlockHalfTransparent { - return; - } - // CraftBukkit end -- if (world.getDimensionManager().isNether()) { -+ if (world.isNether() || (world.isTheEnd() && !net.pl3x.purpur.PurpurConfig.allowWaterPlacementInTheEnd)) { // Purpur - world.a(blockposition, false); - } else { - world.setTypeUpdate(blockposition, Blocks.WATER.getBlockData()); -diff --git a/src/main/java/net/minecraft/server/ItemBucket.java b/src/main/java/net/minecraft/server/ItemBucket.java -index 223361a1a8b41ebe91e0db39f40cf12a4968b1b4..07f23572bdf15c57a53e32646f2fc64fff404948 100644 ---- a/src/main/java/net/minecraft/server/ItemBucket.java -+++ b/src/main/java/net/minecraft/server/ItemBucket.java -@@ -123,7 +123,7 @@ public class ItemBucket extends Item { +diff --git a/src/main/java/net/minecraft/world/item/ItemBucket.java b/src/main/java/net/minecraft/world/item/ItemBucket.java +index d126f668828e0788e369294c0b376ef52b344f2c..154a76b1b77a97bdf65153250c41275f72f6f73f 100644 +--- a/src/main/java/net/minecraft/world/item/ItemBucket.java ++++ b/src/main/java/net/minecraft/world/item/ItemBucket.java +@@ -152,7 +152,7 @@ public class ItemBucket extends Item { // CraftBukkit end if (!flag1) { return movingobjectpositionblock != null && this.a(entityhuman, world, movingobjectpositionblock.getBlockPosition().shift(movingobjectpositionblock.getDirection()), (MovingObjectPositionBlock) null, enumdirection, clicked, itemstack, enumhand); // CraftBukkit // Paper - add enumhand @@ -39,7 +17,7 @@ index 223361a1a8b41ebe91e0db39f40cf12a4968b1b4..07f23572bdf15c57a53e32646f2fc64f int i = blockposition.getX(); int j = blockposition.getY(); int k = blockposition.getZ(); -@@ -131,7 +131,7 @@ public class ItemBucket extends Item { +@@ -160,7 +160,7 @@ public class ItemBucket extends Item { world.playSound(entityhuman, blockposition, SoundEffects.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 0.5F, 2.6F + (world.random.nextFloat() - world.random.nextFloat()) * 0.8F); for (int l = 0; l < 8; ++l) { @@ -48,11 +26,11 @@ index 223361a1a8b41ebe91e0db39f40cf12a4968b1b4..07f23572bdf15c57a53e32646f2fc64f } return true; -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index ad7360cd5ae79e4d031ae866bf911fb87a2c0cdf..404fcc307454e7f00dcc180dda53677c5a0f43e8 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -1762,4 +1762,14 @@ public abstract class World implements GeneratorAccess, AutoCloseable { +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 4fa0f6ce7f8e6f5fba68d66a2c81ad4a53ca2146..93cbdcd641762e3ab00258fd94ac381ebe47fb79 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -1824,4 +1824,14 @@ public abstract class World implements GeneratorAccess, AutoCloseable { public final boolean isDebugWorld() { return this.debugWorld; } @@ -67,19 +45,33 @@ index ad7360cd5ae79e4d031ae866bf911fb87a2c0cdf..404fcc307454e7f00dcc180dda53677c + } + // Purpur end } +diff --git a/src/main/java/net/minecraft/world/level/block/BlockIce.java b/src/main/java/net/minecraft/world/level/block/BlockIce.java +index 461c85b426aab30c34529897e55aa842b45d0555..486a03f2582d6ece2775cb2db127953d31d041f8 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockIce.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockIce.java +@@ -27,7 +27,7 @@ public class BlockIce extends BlockHalfTransparent { + public void a(World world, EntityHuman entityhuman, BlockPosition blockposition, IBlockData iblockdata, @Nullable TileEntity tileentity, ItemStack itemstack) { + super.a(world, entityhuman, blockposition, iblockdata, tileentity, itemstack); + if (EnchantmentManager.getEnchantmentLevel(Enchantments.SILK_TOUCH, itemstack) == 0) { +- if (world.getDimensionManager().isNether()) { ++ if (world.isNether() || (world.isTheEnd() && !net.pl3x.purpur.PurpurConfig.allowWaterPlacementInTheEnd)) { // Purpur + world.a(blockposition, false); + return; + } +@@ -55,7 +55,7 @@ public class BlockIce extends BlockHalfTransparent { + return; + } + // CraftBukkit end +- if (world.getDimensionManager().isNether()) { ++ if (world.isNether() || (world.isTheEnd() && !net.pl3x.purpur.PurpurConfig.allowWaterPlacementInTheEnd)) { // Purpur + world.a(blockposition, false); + } else { + world.setTypeUpdate(blockposition, Blocks.WATER.getBlockData()); diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index ebf74ddb9786d3bcccb62c85352bb6c2278433f3..c12146fe8ac1d89c6c1051a8f64ea29a9214e64b 100644 +index 33c135aa02bbbaebbc503aaf665d8d00998b6b40..c7962b45e818bbfa841a1249156472dc750d6194 100644 --- a/src/main/java/net/pl3x/purpur/PurpurConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java -@@ -1,7 +1,6 @@ - package net.pl3x.purpur; - - import com.google.common.base.Throwables; --import net.minecraft.server.LocaleLanguage; - import net.minecraft.server.MinecraftServer; - import net.pl3x.purpur.command.PurpurCommand; - import org.bukkit.Bukkit; -@@ -186,6 +185,11 @@ public class PurpurConfig { +@@ -186,6 +186,11 @@ public class PurpurConfig { dontSendUselessEntityPackets = getBoolean("settings.dont-send-useless-entity-packets", dontSendUselessEntityPackets); } diff --git a/patches/server/0084-Allow-color-codes-in-books.patch b/patches/server/0084-Allow-color-codes-in-books.patch index 0383380b1..d6a1964f7 100644 --- a/patches/server/0084-Allow-color-codes-in-books.patch +++ b/patches/server/0084-Allow-color-codes-in-books.patch @@ -4,11 +4,11 @@ Date: Tue, 3 Nov 2020 01:25:06 -0600 Subject: [PATCH] Allow color codes in books -diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 4d0dcbcc00e44c4912302dd0e7331471f33cb370..70cb98b3db5f9966e91da0ccd81e7610455a4f4e 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -1058,7 +1058,8 @@ public class PlayerConnection implements PacketListenerPlayIn { +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index bbb3b44bdceb8fb0363f771b8cf1b8245b5c8d3d..c2d9b76a915bbfaa3382512b3f9ab906e058c0f9 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -1203,7 +1203,8 @@ public class PlayerConnection implements PacketListenerPlayIn { if (itemstack.getItem() == Items.WRITABLE_BOOK) { NBTTagList nbttaglist = new NBTTagList(); @@ -18,7 +18,7 @@ index 4d0dcbcc00e44c4912302dd0e7331471f33cb370..70cb98b3db5f9966e91da0ccd81e7610 ItemStack old = itemstack.cloneItemStack(); // CraftBukkit itemstack.a("pages", (NBTBase) nbttaglist); CraftEventFactory.handleEditBookEvent(player, i, old, itemstack); // CraftBukkit -@@ -1076,13 +1077,14 @@ public class PlayerConnection implements PacketListenerPlayIn { +@@ -1221,13 +1222,14 @@ public class PlayerConnection implements PacketListenerPlayIn { itemstack1.setTag(nbttagcompound.clone()); } @@ -35,7 +35,7 @@ index 4d0dcbcc00e44c4912302dd0e7331471f33cb370..70cb98b3db5f9966e91da0ccd81e7610 ChatComponentText chatcomponenttext = new ChatComponentText(s1); String s2 = IChatBaseComponent.ChatSerializer.a((IChatBaseComponent) chatcomponenttext); -@@ -1094,6 +1096,16 @@ public class PlayerConnection implements PacketListenerPlayIn { +@@ -1239,6 +1241,16 @@ public class PlayerConnection implements PacketListenerPlayIn { } } diff --git a/patches/server/0085-Entity-lifespan.patch b/patches/server/0085-Entity-lifespan.patch index f96195f24..40344f020 100644 --- a/patches/server/0085-Entity-lifespan.patch +++ b/patches/server/0085-Entity-lifespan.patch @@ -4,11 +4,23 @@ Date: Sat, 11 Jul 2020 19:41:34 -0500 Subject: [PATCH] Entity lifespan -diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java -index 4e3af139712323a12066728426615e0faa274e4b..37902ee004a7c5aa18165237e75c77117c2eec81 100644 ---- a/src/main/java/net/minecraft/server/EntityInsentient.java -+++ b/src/main/java/net/minecraft/server/EntityInsentient.java -@@ -54,7 +54,7 @@ public abstract class EntityInsentient extends EntityLiving { +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index c2d9b76a915bbfaa3382512b3f9ab906e058c0f9..319d9d2ba8ce3b5311746938b06999702847ce0b 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -2443,6 +2443,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + boolean triggerLeashUpdate = itemInHand != null && itemInHand.getItem() == Items.LEAD && entity instanceof EntityInsentient; + Item origItem = this.player.inventory.getItemInHand() == null ? null : this.player.inventory.getItemInHand().getItem(); + PlayerInteractEntityEvent event; ++ if (entity instanceof EntityInsentient) ((EntityInsentient) entity).ticksSinceLastInteraction = 0; // Purpur + if (packetplayinuseentity.b() == PacketPlayInUseEntity.EnumEntityUseAction.INTERACT) { + event = new PlayerInteractEntityEvent((Player) this.getPlayer(), entity.getBukkitEntity(), (packetplayinuseentity.c() == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); + } else { +diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +index 462bcb7cfe2daa27c10a7a0318bef9b739e586f4..c9136f1b54ff0620a621b703b4e7487f4a63b01d 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java ++++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +@@ -124,7 +124,7 @@ public abstract class EntityInsentient extends EntityLiving { private NBTTagCompound by; private BlockPosition bz; private float bA; @@ -17,7 +29,7 @@ index 4e3af139712323a12066728426615e0faa274e4b..37902ee004a7c5aa18165237e75c7711 public boolean aware = true; // CraftBukkit protected EntityInsentient(EntityTypes entitytypes, World world) { -@@ -206,6 +206,7 @@ public abstract class EntityInsentient extends EntityLiving { +@@ -276,6 +276,7 @@ public abstract class EntityInsentient extends EntityLiving { entityliving = null; } } @@ -25,7 +37,7 @@ index 4e3af139712323a12066728426615e0faa274e4b..37902ee004a7c5aa18165237e75c7711 this.goalTarget = entityliving; return true; // CraftBukkit end -@@ -250,10 +251,35 @@ public abstract class EntityInsentient extends EntityLiving { +@@ -320,10 +321,35 @@ public abstract class EntityInsentient extends EntityLiving { this.m(); this.F(); } @@ -51,7 +63,7 @@ index 4e3af139712323a12066728426615e0faa274e4b..37902ee004a7c5aa18165237e75c7711 + this.dead = true; + } + } -+ ++ + @Override + public boolean damageEntity(DamageSource damagesource, float f) { + if (damagesource.getEntity() instanceof EntityPlayer) this.ticksSinceLastInteraction = 0; // Purpur @@ -62,7 +74,7 @@ index 4e3af139712323a12066728426615e0faa274e4b..37902ee004a7c5aa18165237e75c7711 @Override protected void c(DamageSource damagesource) { this.m(); -@@ -427,6 +453,7 @@ public abstract class EntityInsentient extends EntityLiving { +@@ -497,6 +523,7 @@ public abstract class EntityInsentient extends EntityLiving { } nbttagcompound.setBoolean("Bukkit.Aware", this.aware); // CraftBukkit @@ -70,7 +82,7 @@ index 4e3af139712323a12066728426615e0faa274e4b..37902ee004a7c5aa18165237e75c7711 } @Override -@@ -497,6 +524,11 @@ public abstract class EntityInsentient extends EntityLiving { +@@ -567,6 +594,11 @@ public abstract class EntityInsentient extends EntityLiving { this.aware = nbttagcompound.getBoolean("Bukkit.Aware"); } // CraftBukkit end @@ -82,7 +94,7 @@ index 4e3af139712323a12066728426615e0faa274e4b..37902ee004a7c5aa18165237e75c7711 } @Override -@@ -1555,7 +1587,7 @@ public abstract class EntityInsentient extends EntityLiving { +@@ -1625,7 +1657,7 @@ public abstract class EntityInsentient extends EntityLiving { this.a((EntityLiving) this, entity); this.z(entity); } @@ -91,20 +103,8 @@ index 4e3af139712323a12066728426615e0faa274e4b..37902ee004a7c5aa18165237e75c7711 return flag; } -diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 70cb98b3db5f9966e91da0ccd81e7610455a4f4e..48d032ed74effcfd66e1ab01548913964bca4d19 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -2298,6 +2298,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - boolean triggerLeashUpdate = itemInHand != null && itemInHand.getItem() == Items.LEAD && entity instanceof EntityInsentient; - Item origItem = this.player.inventory.getItemInHand() == null ? null : this.player.inventory.getItemInHand().getItem(); - PlayerInteractEntityEvent event; -+ if (entity instanceof EntityInsentient) ((EntityInsentient) entity).ticksSinceLastInteraction = 0; // Purpur - if (packetplayinuseentity.b() == PacketPlayInUseEntity.EnumEntityUseAction.INTERACT) { - event = new PlayerInteractEntityEvent((Player) this.getPlayer(), entity.getBukkitEntity(), (packetplayinuseentity.c() == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); - } else { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 07e60861c99db1ee1ba7a01c7a666a83e644aa2a..2e3fee6bc4f3af7ad07a0db5657ffb3238e77e96 100644 +index a366742e8d11513b469ffb8dafd98a4c0d8ab30a..021dbb20793dd365c181c4d8a2ebc429af85778b 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -103,6 +103,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0086-Add-option-to-teleport-to-spawn-if-outside-world-bor.patch b/patches/server/0086-Add-option-to-teleport-to-spawn-if-outside-world-bor.patch index 6b12e14d1..0b3facab0 100644 --- a/patches/server/0086-Add-option-to-teleport-to-spawn-if-outside-world-bor.patch +++ b/patches/server/0086-Add-option-to-teleport-to-spawn-if-outside-world-bor.patch @@ -4,23 +4,11 @@ Date: Mon, 13 Jul 2020 11:40:00 -0500 Subject: [PATCH] Add option to teleport to spawn if outside world border -diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index 4b7909a0c7e41cf41d4219ba7dda79519c0ee3c6..2de7fbd9651a7143802507d9cbed148458c74e7b 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -281,6 +281,7 @@ public abstract class EntityLiving extends Entity { - double d1 = this.world.getWorldBorder().getDamageAmount(); - - if (d1 > 0.0D) { -+ if (world.purpurConfig.teleportIfOutsideBorder && this instanceof EntityPlayer) { ((EntityPlayer) this).teleport(MCUtil.toLocation(world, world.getSpawn())); return; } // Purpur - this.damageEntity(DamageSource.STUCK, (float) Math.max(1, MathHelper.floor(-d0 * d1))); - } - } -diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index ec5248d7d472aa6868a5a3763ded267a919b3e58..c69ff970f4afe5c860fa8794b9be1f6b818ac395 100644 ---- a/src/main/java/net/minecraft/server/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/EntityPlayer.java -@@ -2425,4 +2425,26 @@ public class EntityPlayer extends EntityHuman implements ICrafting { +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index e129480fa1045fbeaafa97045d53696b44952bcf..9de660f0c679f101512bddf7c6582ca6cd18ca5b 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -2556,4 +2556,26 @@ public class EntityPlayer extends EntityHuman implements ICrafting { return (CraftPlayer) super.getBukkitEntity(); } // CraftBukkit end @@ -47,8 +35,28 @@ index ec5248d7d472aa6868a5a3763ded267a919b3e58..c69ff970f4afe5c860fa8794b9be1f6b + } + // Purpur end } +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 5a060b98fe9f3edc199cd520a636505c653556e9..e453502c34f717797c4b67a7149d2e0da1b1232d 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -45,6 +45,7 @@ import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; + import net.minecraft.resources.MinecraftKey; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ChunkProviderServer; + import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.WorldServer; +@@ -376,6 +377,7 @@ public abstract class EntityLiving extends Entity { + double d1 = this.world.getWorldBorder().getDamageAmount(); + + if (d1 > 0.0D) { ++ if (world.purpurConfig.teleportIfOutsideBorder && this instanceof EntityPlayer) { ((EntityPlayer) this).teleport(MCUtil.toLocation(world, world.getSpawn())); return; } // Purpur + this.damageEntity(DamageSource.STUCK, (float) Math.max(1, MathHelper.floor(-d0 * d1))); + } + } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 2e3fee6bc4f3af7ad07a0db5657ffb3238e77e96..5d35651f43de81c8cf047479ad9c88c4b3f1c38c 100644 +index 021dbb20793dd365c181c4d8a2ebc429af85778b..b9e252c3db715c288493d5b98fc20d84de46c4e4 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -196,6 +196,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0087-Squid-EAR-immunity.patch b/patches/server/0087-Squid-EAR-immunity.patch index abba77705..d3e351854 100644 --- a/patches/server/0087-Squid-EAR-immunity.patch +++ b/patches/server/0087-Squid-EAR-immunity.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Squid EAR immunity diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 5d35651f43de81c8cf047479ad9c88c4b3f1c38c..32bb2524641722d16b6bafcc6b1af2793c1d9a45 100644 +index b9e252c3db715c288493d5b98fc20d84de46c4e4..cdb7a97ecececa78a200acc898535d33c950a668 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -453,6 +453,11 @@ public class PurpurWorldConfig { @@ -21,14 +21,22 @@ index 5d35651f43de81c8cf047479ad9c88c4b3f1c38c..32bb2524641722d16b6bafcc6b1af279 public boolean villagerUseBrainTicksOnlyWhenLagging = true; public boolean villagerCanBeLeashed = false; diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index c8ef3856d398fc7a966385c04cadeb1e8e8504f7..7cc27df3c9429ccd840b394fcc3b96215a8449ac 100644 +index dc2d880ded328f8377c207ce15f604ec5c25176c..5881497825b3c11ce5d23e4f609fd769ba6a76e1 100644 --- a/src/main/java/org/spigotmc/ActivationRange.java +++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -388,6 +388,7 @@ public class ActivationRange +@@ -11,6 +11,7 @@ import net.minecraft.world.entity.EntityLiving; + import net.minecraft.world.entity.ambient.EntityAmbient; + import net.minecraft.world.entity.animal.EntityAnimal; + import net.minecraft.world.entity.animal.EntitySheep; ++import net.minecraft.world.entity.animal.EntitySquid; + import net.minecraft.world.entity.boss.EntityComplexPart; + import net.minecraft.world.entity.boss.enderdragon.EntityEnderCrystal; + import net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon; +@@ -386,6 +387,7 @@ public class ActivationRange */ public static boolean checkIfActive(Entity entity) { -+ if (entity.world.purpurConfig.squidImmuneToEAR && entity instanceof net.minecraft.server.EntitySquid) return true; // Purpur ++ if (entity.world.purpurConfig.squidImmuneToEAR && entity instanceof EntitySquid) return true; // Purpur // Never safe to skip fireworks or entities not yet added to chunk if ( !entity.inChunk || entity instanceof EntityFireworks ) { return true; diff --git a/patches/server/0088-Configurable-end-spike-seed.patch b/patches/server/0088-Configurable-end-spike-seed.patch index fd9b5fce6..f3fbc88ee 100644 --- a/patches/server/0088-Configurable-end-spike-seed.patch +++ b/patches/server/0088-Configurable-end-spike-seed.patch @@ -4,11 +4,11 @@ Date: Wed, 15 Jul 2020 11:49:36 -0500 Subject: [PATCH] Configurable end spike seed -diff --git a/src/main/java/net/minecraft/server/WorldGenEnder.java b/src/main/java/net/minecraft/server/WorldGenEnder.java -index 00a1707209b21fc0163960c957864f798da15554..5eb9b3d35e12c2d3dc5f158cbed0b0a0853ee116 100644 ---- a/src/main/java/net/minecraft/server/WorldGenEnder.java -+++ b/src/main/java/net/minecraft/server/WorldGenEnder.java -@@ -23,12 +23,14 @@ public class WorldGenEnder extends WorldGenerator a(GeneratorAccessSeed generatoraccessseed) { @@ -25,7 +25,7 @@ index 00a1707209b21fc0163960c957864f798da15554..5eb9b3d35e12c2d3dc5f158cbed0b0a0 List list = worldgenfeatureendspikeconfiguration.c(); diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index c12146fe8ac1d89c6c1051a8f64ea29a9214e64b..c86f5178590f0b496f018858e21086a594de5dce 100644 +index c7962b45e818bbfa841a1249156472dc750d6194..4eaf0857339a10570a23259e802b65677a2aa018 100644 --- a/src/main/java/net/pl3x/purpur/PurpurConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java @@ -1,5 +1,6 @@ @@ -33,9 +33,9 @@ index c12146fe8ac1d89c6c1051a8f64ea29a9214e64b..c86f5178590f0b496f018858e21086a5 +import co.aikar.timings.TimingsManager; import com.google.common.base.Throwables; + import net.minecraft.locale.LocaleLanguage; import net.minecraft.server.MinecraftServer; - import net.pl3x.purpur.command.PurpurCommand; -@@ -140,6 +141,13 @@ public class PurpurConfig { +@@ -141,6 +142,13 @@ public class PurpurConfig { pingCommandOutput = getString("settings.messages.ping-command-output", pingCommandOutput); } diff --git a/patches/server/0089-Configurable-dungeon-seed.patch b/patches/server/0089-Configurable-dungeon-seed.patch index c63b1a9b0..8f0bf6541 100644 --- a/patches/server/0089-Configurable-dungeon-seed.patch +++ b/patches/server/0089-Configurable-dungeon-seed.patch @@ -4,11 +4,11 @@ Date: Wed, 15 Jul 2020 12:40:25 -0500 Subject: [PATCH] Configurable dungeon seed -diff --git a/src/main/java/net/minecraft/server/WorldGenDungeons.java b/src/main/java/net/minecraft/server/WorldGenDungeons.java -index 07f7b69fefe66ec4f26ca7b4fb3b752e80aeed07..6aa1626f38df0cd8ae8a417dc4fca213b82664c9 100644 ---- a/src/main/java/net/minecraft/server/WorldGenDungeons.java -+++ b/src/main/java/net/minecraft/server/WorldGenDungeons.java -@@ -11,12 +11,21 @@ public class WorldGenDungeons extends WorldGenerator[] ab = new EntityTypes[]{EntityTypes.SKELETON, EntityTypes.ZOMBIE, EntityTypes.ZOMBIE, EntityTypes.SPIDER}; private static final IBlockData ac = Blocks.CAVE_AIR.getBlockData(); @@ -31,10 +31,10 @@ index 07f7b69fefe66ec4f26ca7b4fb3b752e80aeed07..6aa1626f38df0cd8ae8a417dc4fca213 int i = random.nextInt(2) + 2; int j = -i - 1; diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index c86f5178590f0b496f018858e21086a594de5dce..d0b4a9a1a9dea069ea543aa63b950fc5d08c9d02 100644 +index 4eaf0857339a10570a23259e802b65677a2aa018..6faa180bb2a5aa3bd8c4b4845848a63b9366f1eb 100644 --- a/src/main/java/net/pl3x/purpur/PurpurConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java -@@ -141,10 +141,13 @@ public class PurpurConfig { +@@ -142,10 +142,13 @@ public class PurpurConfig { pingCommandOutput = getString("settings.messages.ping-command-output", pingCommandOutput); } diff --git a/patches/server/0090-Phantoms-burn-in-light.patch b/patches/server/0090-Phantoms-burn-in-light.patch index 79673c8a5..69a703cea 100644 --- a/patches/server/0090-Phantoms-burn-in-light.patch +++ b/patches/server/0090-Phantoms-burn-in-light.patch @@ -4,11 +4,27 @@ Date: Sun, 12 Apr 2020 20:41:59 -0700 Subject: [PATCH] Phantoms burn in light -diff --git a/src/main/java/net/minecraft/server/EntityPhantom.java b/src/main/java/net/minecraft/server/EntityPhantom.java -index dfce36368da9bdd9285c490a802f7a0cc4a339f6..bdfe073dcd255a7359127f9ae3a962642be5526d 100644 ---- a/src/main/java/net/minecraft/server/EntityPhantom.java -+++ b/src/main/java/net/minecraft/server/EntityPhantom.java -@@ -13,6 +13,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java +index daf738e8f0987aa6ab200189d7a26d166918b8fc..07ede7b75a65a5815f1ae1ebf03ec0fdb4621afb 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java +@@ -18,6 +18,7 @@ import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.util.MathHelper; + import net.minecraft.world.DifficultyDamageScaler; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityFlying; +@@ -41,6 +42,7 @@ import net.minecraft.world.entity.boss.enderdragon.EntityEnderCrystal; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; ++import net.minecraft.world.item.crafting.RecipeItemStack; + import net.minecraft.world.level.World; + import net.minecraft.world.level.WorldAccess; + import net.minecraft.world.level.levelgen.HeightMap; +@@ -54,6 +56,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { private BlockPosition d; public void setHome(BlockPosition home) { this.d = home; } public BlockPosition getHome() { return this.d; } // Purpur - OBFHELPER private EntityPhantom.AttackPhase bo; public AttackPhase getAttackPhase() { return this.bo; } // Purpur - OBFHELPER private Vec3D crystalPosition; // Purpur @@ -16,7 +32,7 @@ index dfce36368da9bdd9285c490a802f7a0cc4a339f6..bdfe073dcd255a7359127f9ae3a96264 public EntityPhantom(EntityTypes entitytypes, World world) { super(entitytypes, world); -@@ -125,7 +126,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { +@@ -166,7 +169,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { @Override public void movementTick() { @@ -25,7 +41,7 @@ index dfce36368da9bdd9285c490a802f7a0cc4a339f6..bdfe073dcd255a7359127f9ae3a96264 this.setOnFire(8); } -@@ -374,7 +375,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { +@@ -416,7 +419,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { } else { this.c = 60; List list = EntityPhantom.this.world.a(this.b, (EntityLiving) EntityPhantom.this, EntityPhantom.this.getBoundingBox().grow(16.0D, 64.0D, 16.0D)); @@ -34,7 +50,7 @@ index dfce36368da9bdd9285c490a802f7a0cc4a339f6..bdfe073dcd255a7359127f9ae3a96264 if (!list.isEmpty()) { list.sort(Comparator.comparing(Entity::locY).reversed()); Iterator iterator = list.iterator(); -@@ -473,6 +474,12 @@ public class EntityPhantom extends EntityFlying implements IMonster { +@@ -515,6 +518,12 @@ public class EntityPhantom extends EntityFlying implements IMonster { return false; } else if (entityliving instanceof EntityHuman && (((EntityHuman) entityliving).isSpectator() || ((EntityHuman) entityliving).isCreative())) { return false; @@ -47,11 +63,11 @@ index dfce36368da9bdd9285c490a802f7a0cc4a339f6..bdfe073dcd255a7359127f9ae3a96264 } else if (!this.a()) { return false; } else { -diff --git a/src/main/java/net/minecraft/server/Items.java b/src/main/java/net/minecraft/server/Items.java -index 4c379916d8d7797038d2980761c49f44c010dea8..ea6b61c9b88f33d29f7266d7614c80372db31b72 100644 ---- a/src/main/java/net/minecraft/server/Items.java -+++ b/src/main/java/net/minecraft/server/Items.java -@@ -173,7 +173,7 @@ public class Items { +diff --git a/src/main/java/net/minecraft/world/item/Items.java b/src/main/java/net/minecraft/world/item/Items.java +index 993a88a5937417016821ef9d7cd58e4ee097491c..64b4fcf6f43c39db0fe57fc7a74f0d954e966a61 100644 +--- a/src/main/java/net/minecraft/world/item/Items.java ++++ b/src/main/java/net/minecraft/world/item/Items.java +@@ -187,7 +187,7 @@ public class Items { public static final Item cm = a(Blocks.BOOKSHELF, CreativeModeTab.b); public static final Item cn = a(Blocks.MOSSY_COBBLESTONE, CreativeModeTab.b); public static final Item co = a(Blocks.OBSIDIAN, CreativeModeTab.b); @@ -60,7 +76,7 @@ index 4c379916d8d7797038d2980761c49f44c010dea8..ea6b61c9b88f33d29f7266d7614c8037 public static final Item cq = a(Blocks.END_ROD, CreativeModeTab.c); public static final Item cr = a(Blocks.CHORUS_PLANT, CreativeModeTab.c); public static final Item cs = a(Blocks.CHORUS_FLOWER, CreativeModeTab.c); -@@ -225,7 +225,7 @@ public class Items { +@@ -239,7 +239,7 @@ public class Items { public static final Item dm = a(Blocks.SOUL_SOIL, CreativeModeTab.b); public static final Item dn = a(Blocks.BASALT, CreativeModeTab.b); public static final Item do_ = a(Blocks.cP, CreativeModeTab.b); @@ -70,7 +86,7 @@ index 4c379916d8d7797038d2980761c49f44c010dea8..ea6b61c9b88f33d29f7266d7614c8037 public static final Item dr = a(Blocks.JACK_O_LANTERN, CreativeModeTab.b); public static final Item ds = a(Blocks.OAK_TRAPDOOR, CreativeModeTab.d); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 32bb2524641722d16b6bafcc6b1af2793c1d9a45..fd7eabb033d8900bfab28c3d4a06626f7c0c3ef3 100644 +index cdb7a97ecececa78a200acc898535d33c950a668..0a6b27327b0252911ac68f0584643e2d1c5bf09a 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -408,6 +408,9 @@ public class PurpurWorldConfig { diff --git a/patches/server/0091-Configurable-villager-breeding.patch b/patches/server/0091-Configurable-villager-breeding.patch index 0cc5af345..c1451ec4b 100644 --- a/patches/server/0091-Configurable-villager-breeding.patch +++ b/patches/server/0091-Configurable-villager-breeding.patch @@ -4,11 +4,11 @@ Date: Tue, 31 Mar 2020 23:48:55 -0700 Subject: [PATCH] Configurable villager breeding -diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java -index 1563791a0193dcd0a00968d2bb6275716742dc19..40085497e61c55789f3888a8a642c44cabed3466 100644 ---- a/src/main/java/net/minecraft/server/EntityVillager.java -+++ b/src/main/java/net/minecraft/server/EntityVillager.java -@@ -646,7 +646,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +index 2fad37812bfa39872e99c4432e1982d62f65efb7..d3032682af94428419daa02f55b6040090d8df73 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +@@ -718,7 +718,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation @Override public boolean canBreed() { @@ -18,7 +18,7 @@ index 1563791a0193dcd0a00968d2bb6275716742dc19..40085497e61c55789f3888a8a642c44c private boolean fr() { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index fd7eabb033d8900bfab28c3d4a06626f7c0c3ef3..a47962e2cc277a5c86b9cb5ab793e84286bd9af1 100644 +index 0a6b27327b0252911ac68f0584643e2d1c5bf09a..d56ec897bd3c7706b63d210568e60069c48b1a62 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -471,6 +471,7 @@ public class PurpurWorldConfig { diff --git a/patches/server/0092-Redstone-deactivates-spawners.patch b/patches/server/0092-Redstone-deactivates-spawners.patch index ecf5db435..62de831a1 100644 --- a/patches/server/0092-Redstone-deactivates-spawners.patch +++ b/patches/server/0092-Redstone-deactivates-spawners.patch @@ -4,11 +4,11 @@ Date: Tue, 14 Apr 2020 00:35:12 -0700 Subject: [PATCH] Redstone deactivates spawners -diff --git a/src/main/java/net/minecraft/server/MobSpawnerAbstract.java b/src/main/java/net/minecraft/server/MobSpawnerAbstract.java -index c2e830db7aa2944a477624e149a3ba66d112b68a..3b4cc9871c123cfd134783745145c407bbccea0f 100644 ---- a/src/main/java/net/minecraft/server/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/server/MobSpawnerAbstract.java -@@ -51,6 +51,7 @@ public abstract class MobSpawnerAbstract { +diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java +index 5538404456dfee42257fad9040fcc0fefdfc5fab..b3a03dc66e803d9dc7000cc7d6960e87b089b3ed 100644 +--- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java ++++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java +@@ -69,6 +69,7 @@ public abstract class MobSpawnerAbstract { private boolean h() { BlockPosition blockposition = this.b(); @@ -16,7 +16,7 @@ index c2e830db7aa2944a477624e149a3ba66d112b68a..3b4cc9871c123cfd134783745145c407 return this.a().isAffectsSpawningPlayerNearby((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, (double) this.requiredPlayerRange); // Paper } -@@ -329,7 +330,7 @@ public abstract class MobSpawnerAbstract { +@@ -347,7 +348,7 @@ public abstract class MobSpawnerAbstract { public abstract void a(int i); @@ -26,7 +26,7 @@ index c2e830db7aa2944a477624e149a3ba66d112b68a..3b4cc9871c123cfd134783745145c407 public abstract BlockPosition b(); } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index a47962e2cc277a5c86b9cb5ab793e84286bd9af1..743d1fe2eab2157a1100d0ef13d65ce85b10dbaa 100644 +index d56ec897bd3c7706b63d210568e60069c48b1a62..ad32a4b3a601396c8d485d2264088d6cb4c92ebf 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -284,6 +284,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0093-Totems-work-in-inventory.patch b/patches/server/0093-Totems-work-in-inventory.patch index e34b6b3fd..83c0864b1 100644 --- a/patches/server/0093-Totems-work-in-inventory.patch +++ b/patches/server/0093-Totems-work-in-inventory.patch @@ -4,11 +4,11 @@ Date: Wed, 29 Apr 2020 00:45:58 -0700 Subject: [PATCH] Totems work in inventory -diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index 2de7fbd9651a7143802507d9cbed148458c74e7b..bd89fa598b7dda7272cc512862fda33b64e2af99 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -1330,6 +1330,19 @@ public abstract class EntityLiving extends Entity { +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index e453502c34f717797c4b67a7149d2e0da1b1232d..df9ab64ed3800dfdf9e175fc95a8d3d7dba00c51 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -1426,6 +1426,19 @@ public abstract class EntityLiving extends Entity { } } @@ -29,7 +29,7 @@ index 2de7fbd9651a7143802507d9cbed148458c74e7b..bd89fa598b7dda7272cc512862fda33b event.setCancelled(itemstack == null); this.world.getServer().getPluginManager().callEvent(event); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 743d1fe2eab2157a1100d0ef13d65ce85b10dbaa..40a248746ea53640697395a155c18215fd2bbe51 100644 +index ad32a4b3a601396c8d485d2264088d6cb4c92ebf..2e3667c2c2530a1222f2ad7a4988ba8076759dc4 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -201,6 +201,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0094-Populator-seed-controls.patch b/patches/server/0094-Populator-seed-controls.patch index 03e63a9d1..81310b66b 100644 --- a/patches/server/0094-Populator-seed-controls.patch +++ b/patches/server/0094-Populator-seed-controls.patch @@ -18,7 +18,7 @@ index 5e672a0660d0aceffcdb26d185590ca18aa4f023..4b171a2a60e24947e884f8988920f335 } final Object val = config.get(key); diff --git a/src/main/java/com/tuinity/tuinity/config/TuinityConfig.java b/src/main/java/com/tuinity/tuinity/config/TuinityConfig.java -index d1308b8cbb9490f1ccdc5514763e62bc5d66981b..f11d07f6e388dedc318868ffa95e80ae2d89119e 100644 +index d29b537bbe4f852162b720d6b23b741829af21f9..c3669383050241df97e25c89d80720ad446c690d 100644 --- a/src/main/java/com/tuinity/tuinity/config/TuinityConfig.java +++ b/src/main/java/com/tuinity/tuinity/config/TuinityConfig.java @@ -1,5 +1,6 @@ @@ -27,8 +27,8 @@ index d1308b8cbb9490f1ccdc5514763e62bc5d66981b..f11d07f6e388dedc318868ffa95e80ae +import co.aikar.timings.TimingsManager; import com.destroystokyo.paper.util.SneakyThrow; import net.minecraft.server.MinecraftServer; - import net.minecraft.server.TicketType; -@@ -401,6 +402,19 @@ public final class TuinityConfig { + import net.minecraft.server.level.TicketType; +@@ -410,6 +411,19 @@ public final class TuinityConfig { this.spawnLimitAmbient = this.getInt(path + ".ambient", -1); } @@ -49,11 +49,21 @@ index d1308b8cbb9490f1ccdc5514763e62bc5d66981b..f11d07f6e388dedc318868ffa95e80ae } \ No newline at end of file -diff --git a/src/main/java/net/minecraft/server/BiomeBase.java b/src/main/java/net/minecraft/server/BiomeBase.java -index 3fc101552e3c229076c91a1cfa45206b4cc7a04c..60d5c08706dc8b2f895ff7083d3a611a73ac19d2 100644 ---- a/src/main/java/net/minecraft/server/BiomeBase.java -+++ b/src/main/java/net/minecraft/server/BiomeBase.java -@@ -227,6 +227,10 @@ public final class BiomeBase { +diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeBase.java b/src/main/java/net/minecraft/world/level/biome/BiomeBase.java +index 9bbd175f7e20591bbefdbddcb5e998e7098c5adb..c4fb051739c1c186c1574185e0653f513755987d 100644 +--- a/src/main/java/net/minecraft/world/level/biome/BiomeBase.java ++++ b/src/main/java/net/minecraft/world/level/biome/BiomeBase.java +@@ -23,7 +23,9 @@ import net.minecraft.core.SectionPosition; + import net.minecraft.data.RegistryGeneration; + import net.minecraft.resources.MinecraftKey; + import net.minecraft.resources.RegistryFileCodec; ++import net.minecraft.server.level.ChunkProviderServer; + import net.minecraft.server.level.RegionLimitedWorldAccess; ++import net.minecraft.server.level.WorldServer; + import net.minecraft.util.INamable; + import net.minecraft.world.level.ChunkCoordIntPair; + import net.minecraft.world.level.EnumSkyBlock; +@@ -257,6 +259,10 @@ public final class BiomeBase { return this.k; } @@ -64,7 +74,7 @@ index 3fc101552e3c229076c91a1cfa45206b4cc7a04c..60d5c08706dc8b2f895ff7083d3a611a public void a(StructureManager structuremanager, ChunkGenerator chunkgenerator, RegionLimitedWorldAccess regionlimitedworldaccess, long i, SeededRandom seededrandom, BlockPosition blockposition) { List>>> list = this.k.c(); int j = WorldGenStage.Decoration.values().length; -@@ -263,12 +267,24 @@ public final class BiomeBase { +@@ -293,12 +299,24 @@ public final class BiomeBase { } } diff --git a/patches/server/0095-Add-vindicator-johnny-spawn-chance.patch b/patches/server/0095-Add-vindicator-johnny-spawn-chance.patch index 5d463fc91..260c328a6 100644 --- a/patches/server/0095-Add-vindicator-johnny-spawn-chance.patch +++ b/patches/server/0095-Add-vindicator-johnny-spawn-chance.patch @@ -4,11 +4,19 @@ Date: Fri, 24 Jul 2020 19:38:21 -0500 Subject: [PATCH] Add vindicator johnny spawn chance -diff --git a/src/main/java/net/minecraft/server/EntityVindicator.java b/src/main/java/net/minecraft/server/EntityVindicator.java -index 4761ddfedeed54e79788a6f60f06a805efd60ab1..23b350f793539672b6990327ed52e9bb3bdbf54e 100644 ---- a/src/main/java/net/minecraft/server/EntityVindicator.java -+++ b/src/main/java/net/minecraft/server/EntityVindicator.java -@@ -82,6 +82,12 @@ public class EntityVindicator extends EntityIllagerAbstract { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java +index f0eda0b83bab8e3a8adbb569b5997402b0e08e9a..fe84d6d2b74b6ae00c4c66682107296a40b69adc 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java +@@ -6,6 +6,7 @@ import java.util.Map; + import java.util.function.Predicate; + import javax.annotation.Nullable; + import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.network.chat.ChatMessage; + import net.minecraft.network.chat.IChatBaseComponent; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; +@@ -122,6 +123,12 @@ public class EntityVindicator extends EntityIllagerAbstract { ((Navigation) this.getNavigation()).a(true); this.a(difficultydamagescaler); this.b(difficultydamagescaler); @@ -22,7 +30,7 @@ index 4761ddfedeed54e79788a6f60f06a805efd60ab1..23b350f793539672b6990327ed52e9bb } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 40a248746ea53640697395a155c18215fd2bbe51..87c68707aaab2d0e49d4e9c17de94b28a4324799 100644 +index 2e3667c2c2530a1222f2ad7a4988ba8076759dc4..4901e9b0f418132fbe48a424df57d0e7a8103821 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -40,6 +40,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0096-Add-option-to-disable-mushroom-block-updates.patch b/patches/server/0096-Add-option-to-disable-mushroom-block-updates.patch index 34604e823..29d6cca5f 100644 --- a/patches/server/0096-Add-option-to-disable-mushroom-block-updates.patch +++ b/patches/server/0096-Add-option-to-disable-mushroom-block-updates.patch @@ -4,11 +4,11 @@ Date: Tue, 4 Aug 2020 17:11:58 -0500 Subject: [PATCH] Add option to disable mushroom block updates -diff --git a/src/main/java/net/minecraft/server/BlockHugeMushroom.java b/src/main/java/net/minecraft/server/BlockHugeMushroom.java -index e8f340b9f2a1e5de9cf7e8cf595de8a806cb528a..3490af6fe0cf2eccac9753778cf4085f95d5da93 100644 ---- a/src/main/java/net/minecraft/server/BlockHugeMushroom.java -+++ b/src/main/java/net/minecraft/server/BlockHugeMushroom.java -@@ -14,30 +14,57 @@ public class BlockHugeMushroom extends Block { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockHugeMushroom.java b/src/main/java/net/minecraft/world/level/block/BlockHugeMushroom.java +index 987301bfb9d963e3bebc2653bd95cf7f17a2a1e4..fd61c18905e81b1b193260f1c32b4ad0e29be227 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockHugeMushroom.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockHugeMushroom.java +@@ -24,30 +24,57 @@ public class BlockHugeMushroom extends Block { public BlockHugeMushroom(BlockBase.Info blockbase_info) { super(blockbase_info); @@ -73,10 +73,10 @@ index e8f340b9f2a1e5de9cf7e8cf595de8a806cb528a..3490af6fe0cf2eccac9753778cf4085f @Override diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index d0b4a9a1a9dea069ea543aa63b950fc5d08c9d02..17a8b43892fdab87a80cbf076c7814bfab087142 100644 +index 6faa180bb2a5aa3bd8c4b4845848a63b9366f1eb..b50c740b799062240e65625cbf44c32ee07f3551 100644 --- a/src/main/java/net/pl3x/purpur/PurpurConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java -@@ -201,6 +201,11 @@ public class PurpurConfig { +@@ -202,6 +202,11 @@ public class PurpurConfig { allowWaterPlacementInTheEnd = getBoolean("settings.allow-water-placement-in-the-end", allowWaterPlacementInTheEnd); } diff --git a/patches/server/0097-Dispensers-place-anvils-option.patch b/patches/server/0097-Dispensers-place-anvils-option.patch index cbebe0205..e4141e44c 100644 --- a/patches/server/0097-Dispensers-place-anvils-option.patch +++ b/patches/server/0097-Dispensers-place-anvils-option.patch @@ -4,11 +4,11 @@ Date: Tue, 4 Aug 2020 21:11:03 -0500 Subject: [PATCH] Dispensers place anvils option -diff --git a/src/main/java/net/minecraft/server/EnumDirection.java b/src/main/java/net/minecraft/server/EnumDirection.java -index 30ba21ac1bced18a9d0946b7c3ed55971ada48bb..23796bd657f071a337fdf76d777e33c207baf7a7 100644 ---- a/src/main/java/net/minecraft/server/EnumDirection.java -+++ b/src/main/java/net/minecraft/server/EnumDirection.java -@@ -112,6 +112,7 @@ public enum EnumDirection implements INamable { +diff --git a/src/main/java/net/minecraft/core/EnumDirection.java b/src/main/java/net/minecraft/core/EnumDirection.java +index 7918d830a4aef09c9f517284e83a9376299116ad..29d747f7fc5824a222755ebf96dfe053896d43d0 100644 +--- a/src/main/java/net/minecraft/core/EnumDirection.java ++++ b/src/main/java/net/minecraft/core/EnumDirection.java +@@ -116,6 +116,7 @@ public enum EnumDirection implements INamable { return fromType1(this.h); } @@ -16,7 +16,7 @@ index 30ba21ac1bced18a9d0946b7c3ed55971ada48bb..23796bd657f071a337fdf76d777e33c2 public EnumDirection g() { switch (this) { case NORTH: -@@ -127,6 +128,7 @@ public enum EnumDirection implements INamable { +@@ -131,6 +132,7 @@ public enum EnumDirection implements INamable { } } @@ -24,7 +24,7 @@ index 30ba21ac1bced18a9d0946b7c3ed55971ada48bb..23796bd657f071a337fdf76d777e33c2 public EnumDirection h() { switch (this) { case NORTH: -@@ -158,6 +160,7 @@ public enum EnumDirection implements INamable { +@@ -162,6 +164,7 @@ public enum EnumDirection implements INamable { return this.j; } @@ -32,11 +32,19 @@ index 30ba21ac1bced18a9d0946b7c3ed55971ada48bb..23796bd657f071a337fdf76d777e33c2 public EnumDirection.EnumAxis n() { return this.k; } -diff --git a/src/main/java/net/minecraft/server/IDispenseBehavior.java b/src/main/java/net/minecraft/server/IDispenseBehavior.java -index 1277a9c8f06936c53f02dc6cfd2eb5184a7b37a2..5675544e018ce6d4fa608680989980edb0ea625a 100644 ---- a/src/main/java/net/minecraft/server/IDispenseBehavior.java -+++ b/src/main/java/net/minecraft/server/IDispenseBehavior.java -@@ -915,6 +915,23 @@ public interface IDispenseBehavior { +diff --git a/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java b/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java +index 93093c05da53e5ddc59fac179081af2e0893706d..a6f74fc09843de9ad5af5c45e303e754ceea2c6d 100644 +--- a/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java ++++ b/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java +@@ -52,6 +52,7 @@ import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.IWorldReader; + import net.minecraft.world.level.World; + import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.BlockAnvil; + import net.minecraft.world.level.block.BlockBeehive; + import net.minecraft.world.level.block.BlockCampfire; + import net.minecraft.world.level.block.BlockDispenser; +@@ -989,6 +990,23 @@ public interface IDispenseBehavior { } })); BlockDispenser.a((IMaterial) Items.SHEARS.getItem(), (IDispenseBehavior) (new DispenseBehaviorShears())); @@ -61,7 +69,7 @@ index 1277a9c8f06936c53f02dc6cfd2eb5184a7b37a2..5675544e018ce6d4fa608680989980ed static void a(ISourceBlock isourceblock, Entity entity, EnumDirection enumdirection) { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 87c68707aaab2d0e49d4e9c17de94b28a4324799..ade194e572b37365cc2becc69081bac8ca34ca46 100644 +index 4901e9b0f418132fbe48a424df57d0e7a8103821..de573b8e09a3ad334991cc313208e0c91990e8a9 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -251,8 +251,10 @@ public class PurpurWorldConfig { diff --git a/patches/server/0098-Allow-anvil-colors.patch b/patches/server/0098-Allow-anvil-colors.patch index 8f946d112..7b2e4ab6e 100644 --- a/patches/server/0098-Allow-anvil-colors.patch +++ b/patches/server/0098-Allow-anvil-colors.patch @@ -4,11 +4,11 @@ Date: Tue, 4 Aug 2020 22:08:23 -0500 Subject: [PATCH] Allow anvil colors -diff --git a/src/main/java/net/minecraft/server/ContainerAnvil.java b/src/main/java/net/minecraft/server/ContainerAnvil.java -index 4aa6b035a6a8ea39401c6566cd286de39f60e942..02924766a4c655f149b58bf1ded8e0610f8900a3 100644 ---- a/src/main/java/net/minecraft/server/ContainerAnvil.java -+++ b/src/main/java/net/minecraft/server/ContainerAnvil.java -@@ -10,6 +10,13 @@ import org.apache.logging.log4j.Logger; +diff --git a/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java b/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java +index 1b2d633f3d5d735039f18f27fb1387bd5a74f0d8..77810fbb70bf2e1ad03c28c0d69ceaa63221d94c 100644 +--- a/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java ++++ b/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java +@@ -28,6 +28,13 @@ import org.apache.logging.log4j.Logger; import org.bukkit.craftbukkit.inventory.CraftInventoryView; // CraftBukkit end @@ -22,7 +22,7 @@ index 4aa6b035a6a8ea39401c6566cd286de39f60e942..02924766a4c655f149b58bf1ded8e061 public class ContainerAnvil extends ContainerAnvilAbstract { private static final Logger LOGGER = LogManager.getLogger(); -@@ -251,6 +258,17 @@ public class ContainerAnvil extends ContainerAnvilAbstract { +@@ -269,6 +276,17 @@ public class ContainerAnvil extends ContainerAnvilAbstract { } else if (!this.renameText.equals(itemstack.getName().getString())) { b1 = 1; i += b1; @@ -41,7 +41,7 @@ index 4aa6b035a6a8ea39401c6566cd286de39f60e942..02924766a4c655f149b58bf1ded8e061 } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index ade194e572b37365cc2becc69081bac8ca34ca46..227bdc2d24d4d6dbacbf5b93497d1a4b61290af0 100644 +index de573b8e09a3ad334991cc313208e0c91990e8a9..1e5dfaac19af7047243b991745a341782850cf20 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -234,6 +234,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0099-Add-no-tick-block-list.patch b/patches/server/0099-Add-no-tick-block-list.patch index 09c107f1e..8521e42e5 100644 --- a/patches/server/0099-Add-no-tick-block-list.patch +++ b/patches/server/0099-Add-no-tick-block-list.patch @@ -4,28 +4,11 @@ Date: Fri, 7 Aug 2020 12:53:36 -0500 Subject: [PATCH] Add no-tick block list -diff --git a/src/main/java/net/minecraft/server/BlockBase.java b/src/main/java/net/minecraft/server/BlockBase.java -index 829d4a7508e1656dbdc912096b7eafcf30cbb5b2..6aea156d7c7a9ca8a357aad6a6781d7209c9b8ae 100644 ---- a/src/main/java/net/minecraft/server/BlockBase.java -+++ b/src/main/java/net/minecraft/server/BlockBase.java -@@ -617,10 +617,12 @@ public abstract class BlockBase { - } - - public void a(WorldServer worldserver, BlockPosition blockposition, Random random) { -+ if (worldserver.purpurConfig.noTickBlocks.contains(getBlock())) return; // Purpur - this.getBlock().tickAlways(this.p(), worldserver, blockposition, random); - } - - public void b(WorldServer worldserver, BlockPosition blockposition, Random random) { -+ if (worldserver.purpurConfig.noTickBlocks.contains(getBlock())) return; // Purpur - this.getBlock().tick(this.p(), worldserver, blockposition, random); - } - -diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index 1421c3036c9a374f65f30ebfb2ccc015560ee04c..03e3c0250c399b29817285fb4f2db5714f5f66dc 100644 ---- a/src/main/java/net/minecraft/server/WorldServer.java -+++ b/src/main/java/net/minecraft/server/WorldServer.java -@@ -418,14 +418,14 @@ public class WorldServer extends World implements GeneratorAccessSeed { +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index bdc1aaa02836cb675224062e59cd635c6fe6e28a..3341a82207ac02be2be8d8baf5a10da183445a7e 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -532,14 +532,14 @@ public class WorldServer extends World implements GeneratorAccessSeed { // CraftBukkit end if (com.destroystokyo.paper.PaperConfig.useOptimizedTickList) { this.nextTickListBlock = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (block) -> { @@ -42,8 +25,25 @@ index 1421c3036c9a374f65f30ebfb2ccc015560ee04c..03e3c0250c399b29817285fb4f2db571 }, IRegistry.BLOCK::getKey, this::b, "Blocks"); // Paper - Timings this.nextTickListFluid = new TickListServer<>(this, (fluidtype) -> { return fluidtype == null || fluidtype == FluidTypes.EMPTY; +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java +index 0b852fa247c65cb1e889ad4e55886e256f89a763..2ec82dcb9d989590e59f88a02d1c205b3200cadc 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java +@@ -670,10 +670,12 @@ public abstract class BlockBase { + } + + public void a(WorldServer worldserver, BlockPosition blockposition, Random random) { ++ if (worldserver.purpurConfig.noTickBlocks.contains(getBlock())) return; // Purpur + this.getBlock().tickAlways(this.p(), worldserver, blockposition, random); + } + + public void b(WorldServer worldserver, BlockPosition blockposition, Random random) { ++ if (worldserver.purpurConfig.noTickBlocks.contains(getBlock())) return; // Purpur + this.getBlock().tick(this.p(), worldserver, blockposition, random); + } + diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 227bdc2d24d4d6dbacbf5b93497d1a4b61290af0..5b344d7eb8e4c031deb660955f2d1914f3ce4800 100644 +index 1e5dfaac19af7047243b991745a341782850cf20..608bd272762314f661920ab16bf17dbf108df178 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -11,8 +11,10 @@ import org.bukkit.configuration.ConfigurationSection; diff --git a/patches/server/0100-Add-option-to-disable-dolphin-treasure-searching.patch b/patches/server/0100-Add-option-to-disable-dolphin-treasure-searching.patch index 748e9e07c..856b2230c 100644 --- a/patches/server/0100-Add-option-to-disable-dolphin-treasure-searching.patch +++ b/patches/server/0100-Add-option-to-disable-dolphin-treasure-searching.patch @@ -4,11 +4,11 @@ Date: Sat, 8 Aug 2020 16:11:51 -0500 Subject: [PATCH] Add option to disable dolphin treasure searching -diff --git a/src/main/java/net/minecraft/server/EntityDolphin.java b/src/main/java/net/minecraft/server/EntityDolphin.java -index 2916ee89ef7a14619703dfbe7efd5c78a2f34337..664f9693368852bfb06a7a3bd0862a10cbc81747 100644 ---- a/src/main/java/net/minecraft/server/EntityDolphin.java -+++ b/src/main/java/net/minecraft/server/EntityDolphin.java -@@ -329,6 +329,7 @@ public class EntityDolphin extends EntityWaterAnimal { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java b/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java +index 5d18e19eafd5dc01a6caa45075d8c0598f1bb709..e0a9b931c26dbd4e7739d09ae45e1cee72ab210c 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java +@@ -393,6 +393,7 @@ public class EntityDolphin extends EntityWaterAnimal { @Override public boolean a() { @@ -17,7 +17,7 @@ index 2916ee89ef7a14619703dfbe7efd5c78a2f34337..664f9693368852bfb06a7a3bd0862a10 } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 5b344d7eb8e4c031deb660955f2d1914f3ce4800..07cc9766d420d5584c53692e37abaca5b5ac95f5 100644 +index 608bd272762314f661920ab16bf17dbf108df178..450a582b007fda07e1a2afbb40201a9929b554ba 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -353,6 +353,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0101-Short-enderman-height.patch b/patches/server/0101-Short-enderman-height.patch index 6393988f0..2f5b26934 100644 --- a/patches/server/0101-Short-enderman-height.patch +++ b/patches/server/0101-Short-enderman-height.patch @@ -4,23 +4,11 @@ Date: Mon, 10 Aug 2020 21:46:22 -0500 Subject: [PATCH] Short enderman height -diff --git a/src/main/java/net/minecraft/server/EntityEnderman.java b/src/main/java/net/minecraft/server/EntityEnderman.java -index 5914c50e5e254d391a5b83581d100c566243d1c5..9728f5eb59d31535dd9cda6083172cb2ddd20a8e 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderman.java -+++ b/src/main/java/net/minecraft/server/EntityEnderman.java -@@ -328,6 +328,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - public boolean damageEntity(DamageSource damagesource, float f) { - if (this.isInvulnerable(damagesource)) { - return false; -+ } else if (net.pl3x.purpur.PurpurConfig.endermanShortHeight && damagesource == DamageSource.STUCK) { return false; // Purpur - no suffocation damage if short height - } else if (damagesource instanceof EntityDamageSourceIndirect) { - if (this.tryEscape(EndermanEscapeEvent.Reason.INDIRECT)) { // Paper start - for (int i = 0; i < 64; ++i) { -diff --git a/src/main/java/net/minecraft/server/EntityTypes.java b/src/main/java/net/minecraft/server/EntityTypes.java -index eea7cf2121f447e0eb172224ae6a7d5c8fa4b10b..4de08939f8a5de464e510e47228291fc513b8104 100644 ---- a/src/main/java/net/minecraft/server/EntityTypes.java -+++ b/src/main/java/net/minecraft/server/EntityTypes.java -@@ -137,7 +137,8 @@ public class EntityTypes { +diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java +index acf4cbfd9780f186880c595c8fac8d91b8f56e68..cc963bbc0fa909b3121a25786b511b31ee4b9561 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityTypes.java ++++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java +@@ -268,7 +268,8 @@ public class EntityTypes { private IChatBaseComponent bp; @Nullable private MinecraftKey bq; @@ -30,20 +18,32 @@ index eea7cf2121f447e0eb172224ae6a7d5c8fa4b10b..4de08939f8a5de464e510e47228291fc public java.util.function.Supplier getEntityName = () -> IRegistry.ENTITY_TYPE.getKey(this).toString(); // Airplane - create lambda ones +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +index 72142f5c777c6218050bc2b69891072d256ea57d..52aa47036acee2ec21ae2d6f4df634ecbf04b3b0 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +@@ -383,6 +383,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { + public boolean damageEntity(DamageSource damagesource, float f) { + if (this.isInvulnerable(damagesource)) { + return false; ++ } else if (net.pl3x.purpur.PurpurConfig.endermanShortHeight && damagesource == DamageSource.STUCK) { return false; // Purpur - no suffocation damage if short height + } else if (damagesource instanceof EntityDamageSourceIndirect) { + if (this.tryEscape(EndermanEscapeEvent.Reason.INDIRECT)) { // Paper start + for (int i = 0; i < 64; ++i) { diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index 17a8b43892fdab87a80cbf076c7814bfab087142..c314a8c9a921a95cea43b748e2037521d948e1e7 100644 +index b50c740b799062240e65625cbf44c32ee07f3551..bfae3043ef6bf402011045bd9682117aa3021468 100644 --- a/src/main/java/net/pl3x/purpur/PurpurConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java -@@ -2,6 +2,8 @@ package net.pl3x.purpur; - - import co.aikar.timings.TimingsManager; +@@ -4,6 +4,8 @@ import co.aikar.timings.TimingsManager; import com.google.common.base.Throwables; -+import net.minecraft.server.EntitySize; -+import net.minecraft.server.EntityTypes; + import net.minecraft.locale.LocaleLanguage; import net.minecraft.server.MinecraftServer; ++import net.minecraft.world.entity.EntitySize; ++import net.minecraft.world.entity.EntityTypes; import net.pl3x.purpur.command.PurpurCommand; import org.bukkit.Bukkit; -@@ -191,6 +193,12 @@ public class PurpurConfig { + import org.bukkit.command.Command; +@@ -192,6 +194,12 @@ public class PurpurConfig { enderChestPermissionRows = getBoolean("settings.blocks.ender_chest.use-permissions-for-rows", enderChestPermissionRows); } diff --git a/patches/server/0102-Stop-squids-floating-on-top-of-water.patch b/patches/server/0102-Stop-squids-floating-on-top-of-water.patch index 38982135a..3cb8f1087 100644 --- a/patches/server/0102-Stop-squids-floating-on-top-of-water.patch +++ b/patches/server/0102-Stop-squids-floating-on-top-of-water.patch @@ -4,11 +4,11 @@ Date: Thu, 13 Aug 2020 04:00:26 -0500 Subject: [PATCH] Stop squids floating on top of water -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 13217b14834f4aaf3eddba8da3c3bc4a97cb27c6..e50a3182dad6f2108f31ffc40274643607ce27d5 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -3464,8 +3464,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 5ac6b7759cf43dbbad1bcf74d5d86efd69883cf5..240f30f6ca6007ba8e7de1c3e033b2a8493838e7 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -3556,8 +3556,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne this.lastYaw = this.yaw; } @@ -23,11 +23,19 @@ index 13217b14834f4aaf3eddba8da3c3bc4a97cb27c6..e50a3182dad6f2108f31ffc402746436 int i = MathHelper.floor(axisalignedbb.minX); int j = MathHelper.f(axisalignedbb.maxX); int k = MathHelper.floor(axisalignedbb.minY); -diff --git a/src/main/java/net/minecraft/server/EntitySquid.java b/src/main/java/net/minecraft/server/EntitySquid.java -index b21605a62365fe24f315f35bd840b4740fc80f0e..148e4b158734f136832e5c17bdc69634c0f294aa 100644 ---- a/src/main/java/net/minecraft/server/EntitySquid.java -+++ b/src/main/java/net/minecraft/server/EntitySquid.java -@@ -25,6 +25,14 @@ public class EntitySquid extends EntityWaterAnimal { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java +index 92ff03f8e8286f710fd5e63b4d103e489787d453..081929990a8208f643d298a885acc4ddfa401bfb 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java +@@ -26,6 +26,7 @@ import net.minecraft.world.level.GeneratorAccess; + import net.minecraft.world.level.World; + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.Fluid; ++import net.minecraft.world.phys.AxisAlignedBB; + import net.minecraft.world.phys.Vec3D; + + public class EntitySquid extends EntityWaterAnimal { +@@ -51,6 +52,14 @@ public class EntitySquid extends EntityWaterAnimal { this.bu = 1.0F / (this.random.nextFloat() + 1.0F) * 0.2F; } @@ -43,7 +51,7 @@ index b21605a62365fe24f315f35bd840b4740fc80f0e..148e4b158734f136832e5c17bdc69634 protected void initPathfinder() { this.goalSelector.a(0, new EntitySquid.PathfinderGoalSquid(this)); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 07cc9766d420d5584c53692e37abaca5b5ac95f5..637cac2758a44e72794953b9fbca2accb7d86b6a 100644 +index 450a582b007fda07e1a2afbb40201a9929b554ba..4f5b815f22a906d8438c82204d24417e5d1cc66c 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -499,8 +499,10 @@ public class PurpurWorldConfig { diff --git a/patches/server/0103-Ridables.patch b/patches/server/0103-Ridables.patch index 6bbd42490..1870bd0ec 100644 --- a/patches/server/0103-Ridables.patch +++ b/patches/server/0103-Ridables.patch @@ -4,11 +4,501 @@ Date: Sun, 5 Jul 2020 22:19:49 -0500 Subject: [PATCH] Ridables -diff --git a/src/main/java/net/minecraft/server/AttributeDefaults.java b/src/main/java/net/minecraft/server/AttributeDefaults.java -index 8f95a4e49714e352b9cdf82d7f4acdd3459978ad..ab05b5e403cf54756aa35891dc0d950187a9d4ec 100644 ---- a/src/main/java/net/minecraft/server/AttributeDefaults.java -+++ b/src/main/java/net/minecraft/server/AttributeDefaults.java -@@ -9,7 +9,80 @@ import org.apache.logging.log4j.Logger; +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index c6c4349954cb302e933739870814f54e426bd825..5de12553875af626fa597ca440e52682624e35c8 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1530,6 +1530,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0; // Paper + worldserver.hasEntityMoveEvent = EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper ++ worldserver.hasRidableMoveEvent = net.pl3x.purpur.event.entity.RidableMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Purpur + TileEntityHopper.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper + + this.methodProfiler.a(() -> { +diff --git a/src/main/java/net/minecraft/server/PathfinderGoalHasRider.java b/src/main/java/net/minecraft/server/PathfinderGoalHasRider.java +new file mode 100644 +index 0000000000000000000000000000000000000000..70961ec1d385dfd7c17fed6f33e4eb7fd57bc34a +--- /dev/null ++++ b/src/main/java/net/minecraft/server/PathfinderGoalHasRider.java +@@ -0,0 +1,21 @@ ++package net.minecraft.server; ++ ++import net.minecraft.world.entity.EntityInsentient; ++import net.minecraft.world.entity.ai.goal.PathfinderGoal; ++ ++import java.util.EnumSet; ++ ++public class PathfinderGoalHasRider extends PathfinderGoal { ++ public final EntityInsentient entity; ++ ++ public PathfinderGoalHasRider(EntityInsentient entity) { ++ this.entity = entity; ++ setTypes(EnumSet.of(Type.JUMP, Type.MOVE, Type.LOOK, Type.TARGET, Type.UNKNOWN_BEHAVIOR)); ++ } ++ ++ // shouldExecute ++ @Override ++ public boolean a() { ++ return entity.hasRider(); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/PathfinderGoalHorseHasRider.java b/src/main/java/net/minecraft/server/PathfinderGoalHorseHasRider.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8b66d1215a6eef1302b5ecb46a4b3d502846fef8 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/PathfinderGoalHorseHasRider.java +@@ -0,0 +1,18 @@ ++package net.minecraft.server; ++ ++import net.minecraft.world.entity.animal.horse.EntityHorseAbstract; ++ ++public class PathfinderGoalHorseHasRider extends PathfinderGoalHasRider { ++ private final EntityHorseAbstract horse; ++ ++ public PathfinderGoalHorseHasRider(EntityHorseAbstract entity) { ++ super(entity); ++ this.horse = entity; ++ } ++ ++ // shouldExecute ++ @Override ++ public boolean a() { ++ return super.a() && horse.hasSaddle(); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 9de660f0c679f101512bddf7c6582ca6cd18ca5b..e1a6e4a359eb2aa484d479fde398473c349a63ba 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -643,6 +643,15 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + } + + this.advancementDataPlayer.b(this); ++ ++ // Purpur start ++ if (this.world.purpurConfig.useNightVisionWhenRiding && this.getVehicle() != null && this.getVehicle().getRider() == this && world.getTime() % 100 == 0) { // 5 seconds ++ MobEffect nightVision = this.getEffect(MobEffects.NIGHT_VISION); ++ if (nightVision == null || nightVision.getDuration() <= 300) { // 15 seconds ++ this.addEffect(new MobEffect(MobEffects.NIGHT_VISION, 400, 0)); // 20 seconds ++ } ++ } ++ // Purpur end + } + + public void playerTick() { +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 3341a82207ac02be2be8d8baf5a10da183445a7e..dd1a0cffedc434d570c1b03fa8cf55d90de1f324 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -216,6 +216,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + public final UUID uuid; + public boolean hasPhysicsEvent = true; // Paper + public boolean hasEntityMoveEvent = false; // Paper ++ public boolean hasRidableMoveEvent = false; // Purpur + private static Throwable getAddToWorldStackTrace(Entity entity) { + return new Throwable(entity + " Added to world at " + new java.util.Date()); + } +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 319d9d2ba8ce3b5311746938b06999702847ce0b..8d53548bc0d8076d3831b72673ab5412a77919a4 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -2452,6 +2452,8 @@ public class PlayerConnection implements PacketListenerPlayIn { + } + this.server.getPluginManager().callEvent(event); + ++ player.processClick(enumhand); // Purpur ++ + // Fish bucket - SPIGOT-4048 + if ((entity instanceof EntityFish && origItem != null && origItem.getItem() == Items.WATER_BUCKET) && (event.isCancelled() || this.player.inventory.getItemInHand() == null || this.player.inventory.getItemInHand().getItem() != origItem)) { + this.sendPacket(new PacketPlayOutSpawnEntityLiving((EntityFish) entity)); +diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java +index 6ba14f603b8ec69597c70677cc317f802d6afae9..24fd920394774bf38d2818a4cd013670f7b20ba9 100644 +--- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java ++++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java +@@ -67,6 +67,7 @@ public class DamageSource { + return new EntityDamageSource("mob", entityliving); + } + ++ public static DamageSource indirectMobAttack(Entity entity, EntityLiving entityliving) { return a(entity, entityliving); } // Purpur - OBFHELPER + public static DamageSource a(Entity entity, EntityLiving entityliving) { + return new EntityDamageSourceIndirect("mob", entity, entityliving); + } +@@ -128,6 +129,7 @@ public class DamageSource { + return this.B; + } + ++ public DamageSource setProjectile() { return c(); } // Purpur - OBFHELPER + public DamageSource c() { + this.B = true; + return this; +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 240f30f6ca6007ba8e7de1c3e033b2a8493838e7..d1bbf4127a2e0836bedb33a81e3fd18a8e8eb962 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -22,6 +22,7 @@ import net.minecraft.BlockUtil; + import net.minecraft.CrashReport; + import net.minecraft.CrashReportSystemDetails; + import net.minecraft.ReportedException; ++import net.minecraft.SystemUtils; + import net.minecraft.advancements.CriterionTriggers; + import net.minecraft.commands.CommandListenerWrapper; + import net.minecraft.commands.ICommandListener; +@@ -197,7 +198,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + private int id; + public boolean i; public final boolean blocksEntitySpawning() { return this.i; } // Paper - OBFHELPER + public final List passengers; +- protected int j; ++ protected int j; public int getRideCooldown() { return j; } // Purpur - OBFHELPER + @Nullable + private Entity vehicle; + public boolean attachedToPlayer; +@@ -213,7 +214,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + public float lastYaw; + public float lastPitch; + private AxisAlignedBB boundingBox; +- protected boolean onGround; ++ public boolean onGround; // Purpur - protected -> public + public boolean positionChanged; + public boolean v; + public boolean velocityChanged; +@@ -269,7 +270,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + private boolean az; + private final double[] aA; + private long aB; +- private EntitySize size; ++ protected EntitySize size; // Purpur - private -> protected + private float headHeight; + // CraftBukkit start + public boolean persist = true; +@@ -1590,6 +1591,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return !this.justCreated && this.M.getDouble(TagsFluid.LAVA) > 0.0D; + } + ++ public void moveRelative(float speed, Vec3D motion) { this.a(speed, motion); } // Purpur - OBFHELPER + public void a(float f, Vec3D vec3d) { + Vec3D vec3d1 = a(vec3d, f, this.yaw); + +@@ -2346,6 +2348,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return this.a(entity, false); + } + ++ public boolean startRiding(Entity entity, boolean flag) { return a(entity, flag); } // Purpur - OBFHELPER + public boolean a(Entity entity, boolean flag) { + for (Entity entity1 = entity; entity1.vehicle != null; entity1 = entity1.vehicle) { + if (entity1.vehicle == this) { +@@ -2441,6 +2444,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + this.passengers.add(entity); + } + ++ // Purpur start ++ if (isRidable() && passengers.get(0) == entity && entity instanceof EntityHuman) { ++ EntityHuman entityhuman = (EntityHuman) entity; ++ onMount(entityhuman); ++ this.rider = entityhuman; ++ } ++ // Purpur end + } + return true; // CraftBukkit + } +@@ -2481,6 +2491,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return false; + } + // Spigot end ++ // Purpur start ++ if (rider != null && passengers.get(0) == rider) { ++ onDismount(rider); ++ this.rider = null; ++ } ++ // Purpur end + this.passengers.remove(entity); + entity.j = 60; + } +@@ -2646,6 +2662,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + this.setFlag(4, flag); + } + ++ public boolean isGlowing() { return bE(); } // Purpur - OBFHELPER + public boolean bE() { + return this.glowing || this.world.isClientSide && this.getFlag(6); + } +@@ -2868,6 +2885,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + + public void setHeadRotation(float f) {} + ++ public void setBodyYaw(float yaw) { n(yaw); } // Purpur - OBFHELPER + public void n(float f) {} + + public boolean bL() { +@@ -3309,6 +3327,18 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return false; + } + ++ // Purpur Start ++ public void sendMessage(String str) { ++ sendMessage(org.bukkit.craftbukkit.util.CraftChatMessage.fromStringOrNull(str)); ++ } ++ ++ public void sendMessage(IChatBaseComponent ichatbasecomponent) { ++ if (ichatbasecomponent != null) { ++ sendMessage(ichatbasecomponent, SystemUtils.getNullUUID()); ++ } ++ } ++ // Purpur end ++ + @Override + public void sendMessage(IChatBaseComponent ichatbasecomponent, UUID uuid) {} + +@@ -3761,4 +3791,47 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return ((ChunkProviderServer) world.getChunkProvider()).isInEntityTickingChunk(this); + } + // Paper end ++ ++ // Purpur start ++ private EntityHuman rider; ++ ++ public EntityHuman getRider() { ++ return rider; ++ } ++ ++ public boolean hasRider() { ++ return rider != null; ++ } ++ ++ public boolean isRidable() { ++ return false; ++ } ++ ++ public boolean isRidableInWater() { ++ return false; ++ } ++ ++ public void onMount(EntityHuman entityhuman) { ++ if (this instanceof EntityInsentient) { ++ ((EntityInsentient) this).setGoalTarget(null, null, false); ++ ((EntityInsentient) this).getNavigation().stopPathfinding(); ++ } ++ entityhuman.setJumping(false); // fixes jump on mount ++ } ++ ++ public void onDismount(EntityHuman entityhuman) { ++ } ++ ++ public boolean onSpacebar() { ++ return false; ++ } ++ ++ public boolean onClick(EnumHand hand) { ++ return false; ++ } ++ ++ public boolean processClick(EnumHand hand) { ++ return false; ++ } ++ // Purpur end + } +diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +index c9136f1b54ff0620a621b703b4e7487f4a63b01d..8b7f840bb1b24996b40c9bef85f4c1e98e39caec 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java ++++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +@@ -100,7 +100,7 @@ public abstract class EntityInsentient extends EntityLiving { + protected int f; + protected ControllerLook lookController; + protected ControllerMove moveController; +- protected ControllerJump bi; ++ protected ControllerJump bi; public ControllerJump getJumpController() { return bi; } // Purpur - OBFHELPER + private final EntityAIBodyControl c; + protected NavigationAbstract navigation; + public PathfinderGoalSelector goalSelector; +@@ -138,8 +138,8 @@ public abstract class EntityInsentient extends EntityLiving { + this.bA = -1.0F; + this.goalSelector = new PathfinderGoalSelector(world.getMethodProfilerSupplier()); + this.targetSelector = new PathfinderGoalSelector(world.getMethodProfilerSupplier()); +- this.lookController = new ControllerLook(this); +- this.moveController = new ControllerMove(this); ++ this.lookController = new net.pl3x.purpur.controller.ControllerLookWASD(this); // Purpur ++ this.moveController = new net.pl3x.purpur.controller.ControllerMoveWASD(this); // Purpur + this.bi = new ControllerJump(this); + this.c = this.r(); + this.navigation = this.b(world); +@@ -328,10 +328,10 @@ public abstract class EntityInsentient extends EntityLiving { + // Purpur start + private void incrementTicksSinceLastInteraction() { + ++ticksSinceLastInteraction; +- //if (hasRider()) { +- // ticksSinceLastInteraction = 0; +- // return; +- //} ++ if (hasRider()) { ++ ticksSinceLastInteraction = 0; ++ return; ++ } + if (world.purpurConfig.entityLifeSpan <= 0) { + return; // feature disabled + } +@@ -626,14 +626,17 @@ public abstract class EntityInsentient extends EntityLiving { + return super.dp(); + } + ++ public void setForwardSpeed(float speed) { this.t(speed); } // Purpur - OBFHELPER + public void t(float f) { + this.aT = f; + } + ++ public void setVerticalSpeed(float speed) { this.u(speed); } // Purpur - OBFHELPER + public void u(float f) { + this.aS = f; + } + ++ public void setStrafeSpeed(float speed) { this.v(speed); } // Purpur - OBFHELPER + public void v(float f) { + this.aR = f; + } +@@ -1325,7 +1328,7 @@ public abstract class EntityInsentient extends EntityLiving { + protected void a(EntityHuman entityhuman, EntityInsentient entityinsentient) {} + + protected EnumInteractionResult b(EntityHuman entityhuman, EnumHand enumhand) { +- return EnumInteractionResult.PASS; ++ return tryRide(entityhuman, enumhand); // Purpur + } + + public boolean ev() { +@@ -1706,4 +1709,54 @@ public abstract class EntityInsentient extends EntityLiving { + this.unleash(true, event.isDropLeash()); + // Paper end + } ++ ++ // Purpur start ++ public double getMaxY() { ++ return world.getHeight(); ++ } ++ ++ public EnumInteractionResult tryRide(EntityHuman entityhuman, EnumHand enumhand) { ++ if (!isRidable()) { ++ return EnumInteractionResult.PASS; ++ } ++ if (enumhand != EnumHand.MAIN_HAND) { ++ return EnumInteractionResult.PASS; ++ } ++ if (entityhuman.isSneaking()) { ++ return EnumInteractionResult.PASS; ++ } ++ if (!entityhuman.getItemInHand(enumhand).isEmpty()) { ++ return EnumInteractionResult.PASS; ++ } ++ if (!passengers.isEmpty() || entityhuman.isPassenger()) { ++ return EnumInteractionResult.PASS; ++ } ++ if (this instanceof EntityTameableAnimal) { ++ EntityTameableAnimal tameable = (EntityTameableAnimal) this; ++ if (tameable.isTamed() && !tameable.isOwner(entityhuman)) { ++ return EnumInteractionResult.PASS; ++ } ++ if (!tameable.isTamed() && !world.purpurConfig.untamedTamablesAreRidable) { ++ return EnumInteractionResult.PASS; ++ } ++ } ++ if (this instanceof EntityAgeable) { ++ EntityAgeable ageable = (EntityAgeable) this; ++ if (ageable.isBaby() && !world.purpurConfig.babiesAreRidable) { ++ return EnumInteractionResult.PASS; ++ } ++ } ++ if (!entityhuman.getBukkitEntity().hasPermission("allow.ride." + getEntityType().getName())) { ++ entityhuman.sendMessage(net.pl3x.purpur.PurpurConfig.cannotRideMob); ++ return EnumInteractionResult.PASS; ++ } ++ entityhuman.yaw = this.yaw; ++ entityhuman.pitch = this.pitch; ++ if (entityhuman.startRiding(this)) { ++ return EnumInteractionResult.SUCCESS; ++ } else { ++ return EnumInteractionResult.PASS; ++ } ++ } ++ // Purpur end + } +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index df9ab64ed3800dfdf9e175fc95a8d3d7dba00c51..617657ff7f27996ed7d97801dc49c9a39f59a240 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -559,7 +559,7 @@ public abstract class EntityLiving extends Entity { + + @Override + public boolean bt() { +- return false; ++ return isRidableInWater(); // Purpur + } + + protected void cU() { +@@ -2300,7 +2300,7 @@ public abstract class EntityLiving extends Entity { + return 0.42F * this.getBlockJumpFactor(); + } + +- protected void jump() { ++ public void jump() { // Purpur - protected -> public + float f = this.dJ(); + + if (this.hasEffect(MobEffects.JUMP)) { +@@ -2549,10 +2549,12 @@ public abstract class EntityLiving extends Entity { + return this.onGround ? this.dN() * (0.21600002F / (f * f * f)) : this.aE; + } + ++ public float getSpeed() { return dN(); } // Purpur - OBFHELPER + public float dN() { + return this.bu; + } + ++ public void setSpeed(float speed) { q(speed); } // Purpur - OBFHELPER + public void q(float f) { + this.bu = f; + } +@@ -2951,6 +2953,20 @@ public abstract class EntityLiving extends Entity { + } + } + // Paper end ++ // Purpur start ++ if (hasRider() && ((WorldServer) world).hasRidableMoveEvent && this instanceof EntityInsentient) { ++ if (lastX != locX() || lastY != locY() || lastZ != locZ() || lastYaw != yaw || lastPitch != pitch) { ++ Location from = new Location(world.getWorld(), lastX, lastY, lastZ, lastYaw, lastPitch); ++ Location to = new Location (world.getWorld(), locX(), locY(), locZ(), yaw, pitch); ++ net.pl3x.purpur.event.entity.RidableMoveEvent event = new net.pl3x.purpur.event.entity.RidableMoveEvent((org.bukkit.entity.Mob) getBukkitLivingEntity(), (Player) getRider().getBukkitEntity(), from, to.clone()); ++ if (!event.callEvent()) { ++ setLocation(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch()); ++ } else if (!to.equals(event.getTo())) { ++ setLocation(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch()); ++ } ++ } ++ } ++ // Purpur end + if (!this.world.isClientSide && this.dO() && this.aG()) { + this.damageEntity(DamageSource.DROWN, 1.0F); + } +diff --git a/src/main/java/net/minecraft/world/entity/EntityTameableAnimal.java b/src/main/java/net/minecraft/world/entity/EntityTameableAnimal.java +index 74636c4c0851da1cd5732daa0a2d1a4edda2050f..cdb56555889d17913d7b0c03d5ba23408a500f26 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityTameableAnimal.java ++++ b/src/main/java/net/minecraft/world/entity/EntityTameableAnimal.java +@@ -144,6 +144,7 @@ public abstract class EntityTameableAnimal extends EntityAnimal { + return this.i(entityliving) ? false : super.c(entityliving); + } + ++ public boolean isOwner(EntityLiving entityLiving) { return i(entityLiving); } // Purpur - OBFHELPER + public boolean i(EntityLiving entityliving) { + return entityliving == this.getOwner(); + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeDefaults.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeDefaults.java +index 1b9cf77aa5d73b4834e5260a91d338620e0bb6b3..b6cc0e1286294e64568d11c452684071d4c5b636 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeDefaults.java ++++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeDefaults.java +@@ -50,6 +50,7 @@ import net.minecraft.world.entity.monster.EntityGuardianElder; + import net.minecraft.world.entity.monster.EntityIllagerIllusioner; + import net.minecraft.world.entity.monster.EntityMagmaCube; + import net.minecraft.world.entity.monster.EntityMonster; ++import net.minecraft.world.entity.monster.EntityPhantom; + import net.minecraft.world.entity.monster.EntityPigZombie; + import net.minecraft.world.entity.monster.EntityPillager; + import net.minecraft.world.entity.monster.EntityRavager; +@@ -74,7 +75,80 @@ import org.apache.logging.log4j.Logger; public class AttributeDefaults { private static final Logger LOGGER = LogManager.getLogger(); @@ -90,11 +580,11 @@ index 8f95a4e49714e352b9cdf82d7f4acdd3459978ad..ab05b5e403cf54756aa35891dc0d9501 public static AttributeProvider a(EntityTypes entitytypes) { return (AttributeProvider) AttributeDefaults.b.get(entitytypes); -diff --git a/src/main/java/net/minecraft/server/AttributeProvider.java b/src/main/java/net/minecraft/server/AttributeProvider.java -index dd235a6fc4bc731a344d7211879f9b40bb622c3e..ac902c614dd3054f1a09298a42a88248b69552cd 100644 ---- a/src/main/java/net/minecraft/server/AttributeProvider.java -+++ b/src/main/java/net/minecraft/server/AttributeProvider.java -@@ -101,6 +101,7 @@ public class AttributeProvider { +diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeProvider.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeProvider.java +index c75659d0f2a6a198f338c38b600e639a4cb3d9ee..5edad3ee07cc0357442ede3a1e14e8d5c121e530 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeProvider.java ++++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeProvider.java +@@ -102,6 +102,7 @@ public class AttributeProvider { return this; } @@ -102,19 +592,20 @@ index dd235a6fc4bc731a344d7211879f9b40bb622c3e..ac902c614dd3054f1a09298a42a88248 public AttributeProvider a() { this.b = true; return new AttributeProvider(this.a); -diff --git a/src/main/java/net/minecraft/server/ControllerLookDolphin.java b/src/main/java/net/minecraft/server/ControllerLookDolphin.java -index e5bdddfc14b36b3a7b72ca92a9a14245fddb8833..8200ba60b7642a49742809a9c2e2ab7587259a71 100644 ---- a/src/main/java/net/minecraft/server/ControllerLookDolphin.java -+++ b/src/main/java/net/minecraft/server/ControllerLookDolphin.java -@@ -1,6 +1,6 @@ - package net.minecraft.server; +diff --git a/src/main/java/net/minecraft/world/entity/ai/control/ControllerLookDolphin.java b/src/main/java/net/minecraft/world/entity/ai/control/ControllerLookDolphin.java +index bf059f201c662d6492b093184e7feec711b846e8..1b472a659c140b368173237d54633f0dfbeb7419 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/control/ControllerLookDolphin.java ++++ b/src/main/java/net/minecraft/world/entity/ai/control/ControllerLookDolphin.java +@@ -3,7 +3,7 @@ package net.minecraft.world.entity.ai.control; + import net.minecraft.util.MathHelper; + import net.minecraft.world.entity.EntityInsentient; -public class ControllerLookDolphin extends ControllerLook { +public class ControllerLookDolphin extends net.pl3x.purpur.controller.ControllerLookWASD { // Purpur private final int h; -@@ -10,7 +10,7 @@ public class ControllerLookDolphin extends ControllerLook { +@@ -13,7 +13,7 @@ public class ControllerLookDolphin extends ControllerLook { } @Override @@ -123,11 +614,11 @@ index e5bdddfc14b36b3a7b72ca92a9a14245fddb8833..8200ba60b7642a49742809a9c2e2ab75 if (this.d) { this.d = false; this.a.aC = this.a(this.a.aC, this.h() + 20.0F, this.b); -diff --git a/src/main/java/net/minecraft/server/ControllerMove.java b/src/main/java/net/minecraft/server/ControllerMove.java -index 8f9fb058c11ba5c2e887df048025284cd834ffe9..eaf44694683685e06dd1f012699e5c9d1f91c850 100644 ---- a/src/main/java/net/minecraft/server/ControllerMove.java -+++ b/src/main/java/net/minecraft/server/ControllerMove.java -@@ -6,9 +6,9 @@ public class ControllerMove { +diff --git a/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java b/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java +index 2aa5789437ba7eb20579da238c407a65a25b1d44..434229b146978ba7dc08a83ea55fdb3ab743fbf8 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java ++++ b/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java +@@ -20,9 +20,9 @@ public class ControllerMove { protected double b; protected double c; protected double d; @@ -140,188 +631,19 @@ index 8f9fb058c11ba5c2e887df048025284cd834ffe9..eaf44694683685e06dd1f012699e5c9d protected ControllerMove.Operation h; public ControllerMove(EntityInsentient entityinsentient) { -diff --git a/src/main/java/net/minecraft/server/DamageSource.java b/src/main/java/net/minecraft/server/DamageSource.java -index bd0267ee4b3782f6d1ec39cba7966ba4f62f1adf..8b36ac2b0950a827763aa2357700f37eec5d00d3 100644 ---- a/src/main/java/net/minecraft/server/DamageSource.java -+++ b/src/main/java/net/minecraft/server/DamageSource.java -@@ -56,6 +56,7 @@ public class DamageSource { - return new EntityDamageSource("mob", entityliving); - } - -+ public static DamageSource indirectMobAttack(Entity entity, EntityLiving entityliving) { return a(entity, entityliving); } // Purpur - OBFHELPER - public static DamageSource a(Entity entity, EntityLiving entityliving) { - return new EntityDamageSourceIndirect("mob", entity, entityliving); - } -@@ -117,6 +118,7 @@ public class DamageSource { - return this.B; - } - -+ public DamageSource setProjectile() { return c(); } // Purpur - OBFHELPER - public DamageSource c() { - this.B = true; - return this; -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index e50a3182dad6f2108f31ffc40274643607ce27d5..bcae44f59b3f90b3f2c3f0680b13ce58688ed77b 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -105,7 +105,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - private int id; - public boolean i; public final boolean blocksEntitySpawning() { return this.i; } // Paper - OBFHELPER - public final List passengers; -- protected int j; -+ protected int j; public int getRideCooldown() { return j; } // Purpur - OBFHELPER - @Nullable - private Entity vehicle; - public boolean attachedToPlayer; -@@ -121,7 +121,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - public float lastYaw; - public float lastPitch; - private AxisAlignedBB boundingBox; -- protected boolean onGround; -+ public boolean onGround; // Purpur - protected -> public - public boolean positionChanged; - public boolean v; - public boolean velocityChanged; -@@ -177,7 +177,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - private boolean az; - private final double[] aA; - private long aB; -- private EntitySize size; -+ protected EntitySize size; // Purpur - private -> protected - private float headHeight; - // CraftBukkit start - public boolean persist = true; -@@ -1498,6 +1498,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - return !this.justCreated && this.M.getDouble(TagsFluid.LAVA) > 0.0D; - } - -+ public void moveRelative(float speed, Vec3D motion) { this.a(speed, motion); } // Purpur - OBFHELPER - public void a(float f, Vec3D vec3d) { - Vec3D vec3d1 = a(vec3d, f, this.yaw); - -@@ -2254,6 +2255,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - return this.a(entity, false); - } - -+ public boolean startRiding(Entity entity, boolean flag) { return a(entity, flag); } // Purpur - OBFHELPER - public boolean a(Entity entity, boolean flag) { - for (Entity entity1 = entity; entity1.vehicle != null; entity1 = entity1.vehicle) { - if (entity1.vehicle == this) { -@@ -2349,6 +2351,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - this.passengers.add(entity); - } - -+ // Purpur start -+ if (isRidable() && passengers.get(0) == entity && entity instanceof EntityHuman) { -+ EntityHuman entityhuman = (EntityHuman) entity; -+ onMount(entityhuman); -+ this.rider = entityhuman; -+ } -+ // Purpur end - } - return true; // CraftBukkit - } -@@ -2389,6 +2398,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - return false; - } - // Spigot end -+ // Purpur start -+ if (rider != null && passengers.get(0) == rider) { -+ onDismount(rider); -+ this.rider = null; -+ } -+ // Purpur end - this.passengers.remove(entity); - entity.j = 60; - } -@@ -2554,6 +2569,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - this.setFlag(4, flag); - } - -+ public boolean isGlowing() { return bE(); } // Purpur - OBFHELPER - public boolean bE() { - return this.glowing || this.world.isClientSide && this.getFlag(6); - } -@@ -2776,6 +2792,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - - public void setHeadRotation(float f) {} - -+ public void setBodyYaw(float yaw) { n(yaw); } // Purpur - OBFHELPER - public void n(float f) {} - - public boolean bL() { -@@ -3217,6 +3234,18 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - return false; - } - -+ // Purpur Start -+ public void sendMessage(String str) { -+ sendMessage(org.bukkit.craftbukkit.util.CraftChatMessage.fromStringOrNull(str)); -+ } -+ -+ public void sendMessage(IChatBaseComponent ichatbasecomponent) { -+ if (ichatbasecomponent != null) { -+ sendMessage(ichatbasecomponent, SystemUtils.getNullUUID()); -+ } -+ } -+ // Purpur end -+ - @Override - public void sendMessage(IChatBaseComponent ichatbasecomponent, UUID uuid) {} - -@@ -3669,4 +3698,47 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - return ((ChunkProviderServer) world.getChunkProvider()).isInEntityTickingChunk(this); - } - // Paper end -+ -+ // Purpur start -+ private EntityHuman rider; -+ -+ public EntityHuman getRider() { -+ return rider; -+ } -+ -+ public boolean hasRider() { -+ return rider != null; -+ } -+ -+ public boolean isRidable() { -+ return false; -+ } -+ -+ public boolean isRidableInWater() { -+ return false; -+ } -+ -+ public void onMount(EntityHuman entityhuman) { -+ if (this instanceof EntityInsentient) { -+ ((EntityInsentient) this).setGoalTarget(null, null, false); -+ ((EntityInsentient) this).getNavigation().stopPathfinding(); -+ } -+ entityhuman.setJumping(false); // fixes jump on mount -+ } -+ -+ public void onDismount(EntityHuman entityhuman) { -+ } -+ -+ public boolean onSpacebar() { -+ return false; -+ } -+ -+ public boolean onClick(EnumHand hand) { -+ return false; -+ } -+ -+ public boolean processClick(EnumHand hand) { -+ return false; -+ } -+ // Purpur end - } -diff --git a/src/main/java/net/minecraft/server/EntityBat.java b/src/main/java/net/minecraft/server/EntityBat.java -index f06ffdca027e5477332c6bc0c381264b47633f78..7a18c59689b84fa277709ad11c39a72d77df4afb 100644 ---- a/src/main/java/net/minecraft/server/EntityBat.java -+++ b/src/main/java/net/minecraft/server/EntityBat.java -@@ -15,9 +15,48 @@ public class EntityBat extends EntityAmbient { +diff --git a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java +index 341b95f73a839a548b202e7bf97fd18760c71fd8..eed98fd7e84b4f390b8b356258f5011da561a343 100644 +--- a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java ++++ b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java +@@ -22,6 +22,7 @@ import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySize; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.ai.attributes.AttributeProvider; + import net.minecraft.world.entity.ai.attributes.GenericAttributes; + import net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition; +@@ -41,9 +42,48 @@ public class EntityBat extends EntityAmbient { public EntityBat(EntityTypes entitytypes, World world) { super(entitytypes, world); @@ -370,7 +692,7 @@ index f06ffdca027e5477332c6bc0c381264b47633f78..7a18c59689b84fa277709ad11c39a72d @Override protected void initDatawatcher() { super.initDatawatcher(); -@@ -62,7 +101,7 @@ public class EntityBat extends EntityAmbient { +@@ -88,7 +128,7 @@ public class EntityBat extends EntityAmbient { protected void collideNearby() {} public static AttributeProvider.Builder m() { @@ -379,7 +701,7 @@ index f06ffdca027e5477332c6bc0c381264b47633f78..7a18c59689b84fa277709ad11c39a72d } public boolean isAsleep() { -@@ -94,6 +133,13 @@ public class EntityBat extends EntityAmbient { +@@ -120,6 +160,13 @@ public class EntityBat extends EntityAmbient { @Override protected void mobTick() { @@ -393,11 +715,27 @@ index f06ffdca027e5477332c6bc0c381264b47633f78..7a18c59689b84fa277709ad11c39a72d super.mobTick(); BlockPosition blockposition = this.getChunkCoordinates(); BlockPosition blockposition1 = blockposition.up(); -diff --git a/src/main/java/net/minecraft/server/EntityBee.java b/src/main/java/net/minecraft/server/EntityBee.java -index f73641ddb3e82bc653732105ef0a3d41a28e845f..d8354ec4d19fc3fbddc2551ee217acb137482e63 100644 ---- a/src/main/java/net/minecraft/server/EntityBee.java -+++ b/src/main/java/net/minecraft/server/EntityBee.java -@@ -37,6 +37,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java +index 1d1f71a995a99b2101891a7a5bda7bec5d67f118..0c6d3dae70eeea844a31f9edf54410db13e0b04b 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java +@@ -22,6 +22,7 @@ import net.minecraft.network.protocol.game.PacketDebug; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -44,6 +45,7 @@ import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySize; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.EnumMonsterType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.IEntityAngerable; + import net.minecraft.world.entity.ai.attributes.AttributeProvider; + import net.minecraft.world.entity.ai.attributes.GenericAttributes; +@@ -111,6 +113,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB public EntityBee(EntityTypes entitytypes, World world) { super(entitytypes, world); @@ -405,7 +743,7 @@ index f73641ddb3e82bc653732105ef0a3d41a28e845f..d8354ec4d19fc3fbddc2551ee217acb1 // Paper start - apply gravity to bees when they get stuck in the void, fixes MC-167279 this.moveController = new ControllerMoveFlying(this, 20, true) { @Override -@@ -46,6 +47,22 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB +@@ -120,6 +123,22 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB } super.tick(); } @@ -428,7 +766,7 @@ index f73641ddb3e82bc653732105ef0a3d41a28e845f..d8354ec4d19fc3fbddc2551ee217acb1 }; // Paper end this.lookController = new EntityBee.j(this); -@@ -56,6 +73,35 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB +@@ -130,6 +149,35 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB this.a(PathType.FENCE, -1.0F); } @@ -464,7 +802,7 @@ index f73641ddb3e82bc653732105ef0a3d41a28e845f..d8354ec4d19fc3fbddc2551ee217acb1 @Override protected void initDatawatcher() { super.initDatawatcher(); -@@ -70,6 +116,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB +@@ -144,6 +192,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB @Override protected void initPathfinder() { @@ -472,7 +810,7 @@ index f73641ddb3e82bc653732105ef0a3d41a28e845f..d8354ec4d19fc3fbddc2551ee217acb1 this.goalSelector.a(0, new EntityBee.b(this, 1.399999976158142D, true)); this.goalSelector.a(1, new EntityBee.d()); this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D)); -@@ -85,6 +132,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB +@@ -159,6 +208,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB this.goalSelector.a(7, new EntityBee.g()); this.goalSelector.a(8, new EntityBee.l()); this.goalSelector.a(9, new PathfinderGoalFloat(this)); @@ -480,7 +818,7 @@ index f73641ddb3e82bc653732105ef0a3d41a28e845f..d8354ec4d19fc3fbddc2551ee217acb1 this.targetSelector.a(1, (new EntityBee.h(this)).a(new Class[0])); this.targetSelector.a(2, new EntityBee.c(this)); this.targetSelector.a(3, new PathfinderGoalUniversalAngerReset<>(this, true)); -@@ -555,6 +603,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB +@@ -629,6 +679,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB private d() { super(); // CraftBukkit - decompile error @@ -488,7 +826,7 @@ index f73641ddb3e82bc653732105ef0a3d41a28e845f..d8354ec4d19fc3fbddc2551ee217acb1 } @Override -@@ -617,6 +666,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB +@@ -691,6 +742,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB private g() { super(); // CraftBukkit - decompile error @@ -496,7 +834,7 @@ index f73641ddb3e82bc653732105ef0a3d41a28e845f..d8354ec4d19fc3fbddc2551ee217acb1 } @Override -@@ -681,6 +731,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB +@@ -755,6 +807,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB private i() { super(); // CraftBukkit - decompile error @@ -504,7 +842,7 @@ index f73641ddb3e82bc653732105ef0a3d41a28e845f..d8354ec4d19fc3fbddc2551ee217acb1 } @Override -@@ -904,16 +955,16 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB +@@ -978,16 +1031,16 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB } } @@ -524,11 +862,2463 @@ index f73641ddb3e82bc653732105ef0a3d41a28e845f..d8354ec4d19fc3fbddc2551ee217acb1 } } -diff --git a/src/main/java/net/minecraft/server/EntityBlaze.java b/src/main/java/net/minecraft/server/EntityBlaze.java -index 74082136b38491a0a50d152c455edfa61a6afb9f..dcfad16e06450068d5801fc002c9650102dbf995 100644 ---- a/src/main/java/net/minecraft/server/EntityBlaze.java -+++ b/src/main/java/net/minecraft/server/EntityBlaze.java -@@ -10,6 +10,7 @@ public class EntityBlaze extends EntityMonster { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCat.java b/src/main/java/net/minecraft/world/entity/animal/EntityCat.java +index c8f529b3fd227ce3354f442038b27cd716f57254..3efb010d0e045d14051a33bd7465669e415c26bd 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityCat.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityCat.java +@@ -14,6 +14,7 @@ import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; + import net.minecraft.resources.MinecraftKey; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -104,6 +105,25 @@ public class EntityCat extends EntityTameableAnimal { + super(entitytypes, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.catRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.catRidableInWater; ++ } ++ ++ public void onMount(EntityHuman entityhuman) { ++ super.onMount(entityhuman); ++ setSitting(false); ++ setSleepingWithOwner(false); ++ setHeadDown(false); ++ } ++ // Purpur end ++ + public MinecraftKey eU() { + return (MinecraftKey) EntityCat.bq.getOrDefault(this.getCatType(), EntityCat.bq.get(0)); + } +@@ -111,7 +131,8 @@ public class EntityCat extends EntityTameableAnimal { + @Override + protected void initPathfinder() { + this.bx = new EntityCat.PathfinderGoalTemptChance(this, 0.6D, EntityCat.br, true); +- this.goalSelector.a(1, new PathfinderGoalFloat(this)); ++ this.goalSelector.a(0, new PathfinderGoalFloat(this)); // Purpur ++ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.goalSelector.a(1, new PathfinderGoalSit(this)); + this.goalSelector.a(2, new EntityCat.b(this)); + this.goalSelector.a(3, this.bx); +@@ -123,6 +144,7 @@ public class EntityCat extends EntityTameableAnimal { + this.goalSelector.a(10, new PathfinderGoalBreed(this, 0.8D)); + this.goalSelector.a(11, new PathfinderGoalRandomStrollLand(this, 0.8D, 1.0000001E-5F)); + this.goalSelector.a(12, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 10.0F)); ++ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.targetSelector.a(1, new PathfinderGoalRandomTargetNonTamed<>(this, EntityRabbit.class, false, (Predicate) null)); + this.targetSelector.a(1, new PathfinderGoalRandomTargetNonTamed<>(this, EntityTurtle.class, false, EntityTurtle.bo)); + } +@@ -139,6 +161,7 @@ public class EntityCat extends EntityTameableAnimal { + this.datawatcher.set(EntityCat.bs, i); + } + ++ public void setSleepingWithOwner(boolean flag) { x(flag); } // Purpur - OBFHELPER + public void x(boolean flag) { + this.datawatcher.set(EntityCat.bt, flag); + } +@@ -147,6 +170,7 @@ public class EntityCat extends EntityTameableAnimal { + return (Boolean) this.datawatcher.get(EntityCat.bt); + } + ++ public void setHeadDown(boolean flag) { y(flag); } // Purpur - OBFHELPER + public void y(boolean flag) { + this.datawatcher.set(EntityCat.bu, flag); + } +@@ -365,6 +389,7 @@ public class EntityCat extends EntityTameableAnimal { + + @Override + public EnumInteractionResult b(EntityHuman entityhuman, EnumHand enumhand) { ++ if (hasRider()) return EnumInteractionResult.PASS; // Purpur + ItemStack itemstack = entityhuman.b(enumhand); + Item item = itemstack.getItem(); + +@@ -462,6 +487,7 @@ public class EntityCat extends EntityTameableAnimal { + + public b(EntityCat entitycat) { + this.a = entitycat; ++ this.a(java.util.EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - lay on owner + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java b/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java +index 600d6ebdf554dbaa8ca46a22a12d8b4e3255d987..5c744f1eac19e144c39a2c146d312f0547d6e589 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java +@@ -2,6 +2,7 @@ package net.minecraft.world.entity.animal; + + import net.minecraft.core.BlockPosition; + import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -54,6 +55,16 @@ public class EntityChicken extends EntityAnimal { + } + + // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.chickenRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.chickenRidableInWater; ++ } ++ + @Override + protected void initAttributes() { + if (world.purpurConfig.chickenRetaliate) { +@@ -65,6 +76,7 @@ public class EntityChicken extends EntityAnimal { + @Override + protected void initPathfinder() { + this.goalSelector.a(0, new PathfinderGoalFloat(this)); ++ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + //this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.4D)); // Purpur - moved down + this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D)); + this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.0D, false, EntityChicken.bv)); +@@ -75,6 +87,7 @@ public class EntityChicken extends EntityAnimal { + // Purpur start + if (world.purpurConfig.chickenRetaliate) { + this.goalSelector.a(1, new PathfinderGoalMeleeAttack(this, 1.0D, false)); ++ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this)); + } else { + this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.4D)); +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCod.java b/src/main/java/net/minecraft/world/entity/animal/EntityCod.java +index aac7992a30a0b69cb34097aeb0fe021f54a3cdac..897e0d5ca44a0c475634f08e7d4fcf129ee197ab 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityCod.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityCod.java +@@ -14,6 +14,18 @@ public class EntityCod extends EntityFishSchool { + super(entitytypes, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.codRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return true; ++ } ++ // Purpur end ++ + @Override + protected ItemStack eK() { + return new ItemStack(Items.COD_BUCKET); +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCow.java b/src/main/java/net/minecraft/world/entity/animal/EntityCow.java +index 962dde5fcc617bc39b7d06a1e295370b9d60696c..cad256514c7df92847522c8d7ddf45ebe02658c4 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityCow.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityCow.java +@@ -2,6 +2,7 @@ package net.minecraft.world.entity.animal; + + import net.minecraft.core.BlockPosition; + import net.minecraft.core.particles.Particles; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -43,9 +44,22 @@ public class EntityCow extends EntityAnimal { + super(entitytypes, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.cowRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.cowRidableInWater; ++ } ++ // Purpur end ++ + @Override + protected void initPathfinder() { + this.goalSelector.a(0, new PathfinderGoalFloat(this)); ++ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.goalSelector.a(1, new PathfinderGoalPanic(this, 2.0D)); + this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D)); + if (world.purpurConfig.cowFeedMushrooms > 0) this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.25D, RecipeItemStack.a(Items.WHEAT, Blocks.RED_MUSHROOM.getItem(), Blocks.BROWN_MUSHROOM.getItem()), false)); else // Purpur +@@ -87,6 +101,7 @@ public class EntityCow extends EntityAnimal { + + @Override + public EnumInteractionResult b(EntityHuman entityhuman, EnumHand enumhand) { ++ if (hasRider()) return EnumInteractionResult.PASS; // Purpur + ItemStack itemstack = entityhuman.b(enumhand); + + if (itemstack.getItem() == Items.BUCKET && !this.isBaby()) { +@@ -94,7 +109,7 @@ public class EntityCow extends EntityAnimal { + org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) entityhuman.world, entityhuman, this.getChunkCoordinates(), this.getChunkCoordinates(), null, itemstack, Items.MILK_BUCKET, enumhand); // Paper - add enumHand + + if (event.isCancelled()) { +- return EnumInteractionResult.PASS; ++ return tryRide(entityhuman, enumhand); // Purpur + } + // CraftBukkit end + +@@ -105,7 +120,7 @@ public class EntityCow extends EntityAnimal { + return EnumInteractionResult.a(this.world.isClientSide); + // Purpur start - feed mushroom to change to mooshroom + } else if (world.purpurConfig.cowFeedMushrooms > 0 && getEntityType() != EntityTypes.MOOSHROOM && isMushroom(itemstack)) { +- return feedMushroom(entityhuman, itemstack); ++ return feedMushroom(entityhuman, enumhand, itemstack); + // Purpur end + } else { + return super.b(entityhuman, enumhand); +@@ -128,7 +143,7 @@ public class EntityCow extends EntityAnimal { + } + } + +- private EnumInteractionResult feedMushroom(EntityHuman entityhuman, ItemStack itemstack) { ++ private EnumInteractionResult feedMushroom(EntityHuman entityhuman, EnumHand enumhand, ItemStack itemstack) { + world.broadcastEntityEffect(this, (byte) 18); // hearts + playSound(SoundEffects.ENTITY_COW_MILK, 1.0F, 1.0F); + if (incrementFeedCount(itemstack) < world.purpurConfig.cowFeedMushrooms) { +@@ -139,7 +154,7 @@ public class EntityCow extends EntityAnimal { + } + EntityMushroomCow mooshroom = EntityTypes.MOOSHROOM.create(world); + if (mooshroom == null) { +- return EnumInteractionResult.PASS; ++ return tryRide(entityhuman, enumhand); + } + if (itemstack.getItem() == Blocks.BROWN_MUSHROOM.getItem()) { + mooshroom.setVariant(EntityMushroomCow.Type.BROWN); +@@ -158,10 +173,10 @@ public class EntityCow extends EntityAnimal { + mooshroom.setCustomName(this.getCustomName()); + } + if (CraftEventFactory.callEntityTransformEvent(this, mooshroom, org.bukkit.event.entity.EntityTransformEvent.TransformReason.INFECTION).isCancelled()) { +- return EnumInteractionResult.PASS; ++ return tryRide(entityhuman, enumhand); + } + if (!new com.destroystokyo.paper.event.entity.EntityTransformedEvent(this.getBukkitEntity(), mooshroom.getBukkitEntity(), com.destroystokyo.paper.event.entity.EntityTransformedEvent.TransformedReason.INFECTED).callEvent()) { +- return EnumInteractionResult.PASS; ++ return tryRide(entityhuman, enumhand); + } + this.world.addEntity(mooshroom); + this.die(); +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java b/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java +index e0a9b931c26dbd4e7739d09ae45e1cee72ab210c..880c3aaf4e684209879dc921480619e7c61ee4a0 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java +@@ -16,6 +16,7 @@ import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; + import net.minecraft.resources.ResourceKey; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -81,6 +82,7 @@ public class EntityDolphin extends EntityWaterAnimal { + public static final Predicate b = (entityitem) -> { + return !entityitem.p() && entityitem.isAlive() && entityitem.isInWater(); + }; ++ private int spitCooldown; // Purpur + + public EntityDolphin(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -89,6 +91,45 @@ public class EntityDolphin extends EntityWaterAnimal { + this.setCanPickupLoot(true); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.dolphinRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return true; ++ } ++ ++ @Override ++ public boolean onSpacebar() { ++ if (spitCooldown == 0 && hasRider()) { ++ spitCooldown = world.purpurConfig.dolphinSpitCooldown; ++ if (!hasRider()) { ++ return false; ++ } ++ ++ org.bukkit.craftbukkit.entity.CraftPlayer player = (org.bukkit.craftbukkit.entity.CraftPlayer) getRider().getBukkitEntity(); ++ if (!player.hasPermission("allow.special.dolphin")) { ++ return false; ++ } ++ ++ org.bukkit.Location loc = player.getEyeLocation(); ++ loc.setPitch(loc.getPitch() - 10); ++ org.bukkit.util.Vector target = loc.getDirection().normalize().multiply(10).add(loc.toVector()); ++ ++ net.pl3x.purpur.entity.DolphinSpit spit = new net.pl3x.purpur.entity.DolphinSpit(world, this); ++ spit.shoot(target.getX() - locX(), target.getY() - locY(), target.getZ() - locZ(), world.purpurConfig.dolphinSpitSpeed, 5.0F); ++ ++ world.addEntity(spit); ++ playSound(SoundEffects.ENTITY_DOLPHIN_ATTACK, 1.0F, 1.0F + (random.nextFloat() - random.nextFloat()) * 0.2F); ++ return true; ++ } ++ return false; ++ } ++ // Purpur end ++ + @Nullable + @Override + public GroupDataEntity prepare(WorldAccess worldaccess, DifficultyDamageScaler difficultydamagescaler, EnumMobSpawn enummobspawn, @Nullable GroupDataEntity groupdataentity, @Nullable NBTTagCompound nbttagcompound) { +@@ -163,6 +204,7 @@ public class EntityDolphin extends EntityWaterAnimal { + protected void initPathfinder() { + this.goalSelector.a(0, new PathfinderGoalBreath(this)); + this.goalSelector.a(0, new PathfinderGoalWater(this)); ++ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.goalSelector.a(1, new EntityDolphin.b(this)); + this.goalSelector.a(2, new EntityDolphin.c(this, 4.0D)); + this.goalSelector.a(4, new PathfinderGoalRandomSwim(this, 1.0D, 10)); +@@ -173,6 +215,7 @@ public class EntityDolphin extends EntityWaterAnimal { + this.goalSelector.a(8, new EntityDolphin.d()); + this.goalSelector.a(8, new PathfinderGoalFollowBoat(this)); + this.goalSelector.a(9, new PathfinderGoalAvoidTarget<>(this, EntityGuardian.class, 8.0F, 1.0D, 1.0D)); ++ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityGuardian.class})).a(new Class[0])); // CraftBukkit - decompile error + } + +@@ -224,7 +267,7 @@ public class EntityDolphin extends EntityWaterAnimal { + + @Override + protected boolean n(Entity entity) { +- return true; ++ return getRideCooldown() <= 0; // Purpur - make dolphin honor ride cooldown like all other non-boss mobs + } + + @Override +@@ -259,6 +302,9 @@ public class EntityDolphin extends EntityWaterAnimal { + @Override + public void tick() { + super.tick(); ++ if (spitCooldown > 0) { ++ spitCooldown--; ++ } + if (this.isNoAI()) { + this.setAirTicks(this.bH()); + } else { +@@ -532,7 +578,7 @@ public class EntityDolphin extends EntityWaterAnimal { + + private int b; + +- private d() {} ++ private d() { this.a(java.util.EnumSet.of(PathfinderGoal.Type.MOVE)); } // Purpur - play with item + + @Override + public boolean a() { +@@ -600,7 +646,7 @@ public class EntityDolphin extends EntityWaterAnimal { + } + } + +- static class a extends ControllerMove { ++ static class a extends net.pl3x.purpur.controller.ControllerMoveWASDWater { // Purpur + + private final EntityDolphin i; + +@@ -610,7 +656,20 @@ public class EntityDolphin extends EntityWaterAnimal { + } + + @Override +- public void a() { ++ // Purpur start ++ public void tick(EntityHuman rider) { ++ if (this.i.getAirTicks() < 150) { ++ // if drowning override player WASD controls to find air ++ tick(); ++ } else { ++ super.tick(rider); ++ this.i.setMot(this.i.getMot().add(0.0D, 0.005D, 0.0D)); ++ } ++ } ++ ++ @Override ++ public void tick() { ++ // Purpur end + if (this.i.isInWater()) { + this.i.setMot(this.i.getMot().add(0.0D, 0.005D, 0.0D)); + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFish.java b/src/main/java/net/minecraft/world/entity/animal/EntityFish.java +index e28f84be745647960c936c7208a87713dfa75682..e1e4ea73f42a09ac20d36a58f4d7232d4e1a2f08 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityFish.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityFish.java +@@ -8,6 +8,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.EntityPlayer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -108,13 +109,12 @@ public abstract class EntityFish extends EntityWaterAnimal { + @Override + protected void initPathfinder() { + super.initPathfinder(); +- this.goalSelector.a(0, new PathfinderGoalPanic(this, 1.25D)); +- PathfinderGoalSelector pathfindergoalselector = this.goalSelector; +- Predicate predicate = IEntitySelector.g; +- +- predicate.getClass(); +- pathfindergoalselector.a(2, new PathfinderGoalAvoidTarget<>(this, EntityHuman.class, 8.0F, 1.6D, 1.4D, predicate::test)); +- this.goalSelector.a(4, new EntityFish.b(this)); ++ // Purpur start ++ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur ++ this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.25D)); ++ this.goalSelector.a(3, new PathfinderGoalAvoidTarget<>(this, EntityHuman.class, 8.0F, 1.6D, 1.4D, IEntitySelector.g::test)); // Purpur - decompile error ++ this.goalSelector.a(5, new EntityFish.b(this)); ++ // Purpur end + } + + @Override +@@ -125,7 +125,7 @@ public abstract class EntityFish extends EntityWaterAnimal { + @Override + public void g(Vec3D vec3d) { + if (this.doAITick() && this.isInWater()) { +- this.a(0.01F, vec3d); ++ this.a(hasRider() ? getSpeed() : 0.01F, vec3d); // Purpur + this.move(EnumMoveType.SELF, this.getMot()); + this.setMot(this.getMot().a(0.9D)); + if (this.getGoalTarget() == null) { +@@ -199,9 +199,9 @@ public abstract class EntityFish extends EntityWaterAnimal { + @Override + protected void b(BlockPosition blockposition, IBlockData iblockdata) {} + +- static class a extends ControllerMove { ++ static class a extends net.pl3x.purpur.controller.ControllerMoveWASDWater { // Purpur + +- private final EntityFish i; ++ private final EntityFish i; public EntityFish getFish() { return i; } // Purpur - OBFHELPER + + a(EntityFish entityfish) { + super(entityfish); +@@ -209,7 +209,15 @@ public abstract class EntityFish extends EntityWaterAnimal { + } + + @Override +- public void a() { ++ // Purpur start ++ public void tick(EntityHuman rider) { ++ super.tick(rider); ++ getFish().setMot(getFish().getMot().add(0.0D, 0.005D, 0.0D)); ++ } ++ ++ @Override ++ public void tick() { ++ // Purpur end + if (this.i.a((Tag) TagsFluid.WATER)) { + this.i.setMot(this.i.getMot().add(0.0D, 0.005D, 0.0D)); + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFishSchool.java b/src/main/java/net/minecraft/world/entity/animal/EntityFishSchool.java +index 21780f5dbcd4384649f08161f0812202ee94c96d..a03b0ed0a3f74ccb7572e1c4fa8e345a9e9bc49f 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityFishSchool.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityFishSchool.java +@@ -25,7 +25,7 @@ public abstract class EntityFishSchool extends EntityFish { + @Override + protected void initPathfinder() { + super.initPathfinder(); +- this.goalSelector.a(5, new PathfinderGoalFishSchool(this)); ++ this.goalSelector.a(6, new PathfinderGoalFishSchool(this)); // Purpur + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java +index cea46348c0876e168376061fbaf258048e9358cb..0c1151b598aa681e63ddaac29e4a589f917fd03b 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java +@@ -21,6 +21,7 @@ import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; + import net.minecraft.resources.ResourceKey; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; +@@ -127,6 +128,39 @@ public class EntityFox extends EntityAnimal { + this.setCanPickupLoot(true); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.foxRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.foxRidableInWater; ++ } ++ ++ @Override ++ public float getJumpHeight() { ++ return !hasRider() ? super.getJumpHeight() : 0.5F; ++ } ++ ++ @Override ++ public void onMount(EntityHuman entityhuman) { ++ super.onMount(entityhuman); ++ setCanPickupLoot(false); ++ stopActions(); ++ setChasing(false); ++ spit(getEquipment(EnumItemSlot.MAINHAND)); ++ setSlot(EnumItemSlot.MAINHAND, ItemStack.NULL_ITEM); ++ } ++ ++ @Override ++ public void onDismount(EntityHuman entityhuman) { ++ super.onDismount(entityhuman); ++ setCanPickupLoot(true); ++ } ++ // Purpur end ++ + @Override + protected void initDatawatcher() { + super.initDatawatcher(); +@@ -146,6 +180,7 @@ public class EntityFox extends EntityAnimal { + return entityliving instanceof EntityFishSchool; + }); + this.goalSelector.a(0, new EntityFox.g()); ++ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.goalSelector.a(1, new EntityFox.b()); + this.goalSelector.a(2, new EntityFox.n(2.2D)); + this.goalSelector.a(3, new EntityFox.e(1.0D)); +@@ -171,6 +206,7 @@ public class EntityFox extends EntityAnimal { + this.goalSelector.a(11, new EntityFox.p()); + this.goalSelector.a(12, new EntityFox.j(this, EntityHuman.class, 24.0F)); + this.goalSelector.a(13, new EntityFox.r()); ++ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.targetSelector.a(3, new EntityFox.a(EntityLiving.class, false, false, (entityliving) -> { + return EntityFox.bt.test(entityliving) && !this.c(entityliving.getUniqueID()); + })); +@@ -458,6 +494,7 @@ public class EntityFox extends EntityAnimal { + return itemstack1.isEmpty() || this.bD > 0 && item.isFood() && !itemstack1.getItem().isFood(); + } + ++ public void spit(ItemStack itemstack) { m(itemstack); } // Purpur - OBFHELPER + private void m(ItemStack itemstack) { + if (!itemstack.isEmpty() && !this.world.isClientSide) { + EntityItem entityitem = new EntityItem(this.world, this.locX() + this.getLookDirection().x, this.locY() + 1.0D, this.locZ() + this.getLookDirection().z, itemstack); +@@ -553,6 +590,7 @@ public class EntityFox extends EntityAnimal { + return this.t(16); + } + ++ public void setChasing(boolean flag) { u(flag); } // Purpur - OBFHELPER + public void u(boolean flag) { + this.d(16, flag); + } +@@ -595,6 +633,7 @@ public class EntityFox extends EntityAnimal { + this.setSleeping(false); + } + ++ public void stopActions() { fd(); } // Purpur - OBFHELPER + private void fd() { + this.w(false); + this.setCrouching(false); +@@ -760,16 +799,16 @@ public class EntityFox extends EntityAnimal { + } + } + +- public class k extends ControllerLook { ++ public class k extends net.pl3x.purpur.controller.ControllerLookWASD { // Purpur + + public k() { + super(EntityFox.this); + } + + @Override +- public void a() { ++ public void tick() { // Purpur + if (!EntityFox.this.isSleeping()) { +- super.a(); ++ super.tick(); // Purpur + } + + } +@@ -1439,16 +1478,16 @@ public class EntityFox extends EntityAnimal { + } + } + +- class m extends ControllerMove { ++ class m extends net.pl3x.purpur.controller.ControllerMoveWASD { // Purpur + + public m() { + super(EntityFox.this); + } + + @Override +- public void a() { ++ public void tick() { // Purpur + if (EntityFox.this.fe()) { +- super.a(); ++ super.tick(); // Purpur + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java b/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java +index 62cff5faafa076d05ebc59ad5c4fb020bea0509e..23e614f0c3cf1178acff8e72e0441c42c658e76b 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java +@@ -14,6 +14,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -69,9 +70,22 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable { + this.G = 1.0F; + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.ironGolemRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.ironGolemRidableInWater; ++ } ++ // Purpur end ++ + @Override + protected void initPathfinder() { + if (world.purpurConfig.ironGolemCanSwim) this.goalSelector.a(0, new PathfinderGoalFloat(this)); // Purpur ++ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.goalSelector.a(1, new PathfinderGoalMeleeAttack(this, 1.0D, true)); + this.goalSelector.a(2, new PathfinderGoalMoveTowardsTarget(this, 0.9D, 32.0F)); + this.goalSelector.a(2, new PathfinderGoalStrollVillage(this, 0.6D, false)); +@@ -79,6 +93,7 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable { + this.goalSelector.a(5, new PathfinderGoalOfferFlower(this)); + this.goalSelector.a(7, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F)); + this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this)); ++ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.targetSelector.a(1, new PathfinderGoalDefendVillage(this)); + this.targetSelector.a(2, new PathfinderGoalHurtByTarget(this, new Class[0])); + this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, this::a_)); +@@ -248,13 +263,13 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable { + Item item = itemstack.getItem(); + + if (item != Items.IRON_INGOT) { +- return EnumInteractionResult.PASS; ++ return tryRide(entityhuman, enumhand); // Purpur + } else { + float f = this.getHealth(); + + this.heal(25.0F); + if (this.getHealth() == f) { +- return EnumInteractionResult.PASS; ++ return tryRide(entityhuman, enumhand); // Purpur + } else { + float f1 = 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F; + +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java b/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java +index d28d4d2c1eff2c130f49c2bce3c19da212dba5dc..815e907e8db721f2a6f0f831b69c44a9573b5c9b 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java +@@ -57,6 +57,18 @@ public class EntityMushroomCow extends EntityCow implements IShearable { + super(entitytypes, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.mooshroomRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.mooshroomRidableInWater; ++ } ++ // Purpur end ++ + @Override + public float a(BlockPosition blockposition, IWorldReader iworldreader) { + return iworldreader.getType(blockposition.down()).a(Blocks.MYCELIUM) ? 10.0F : iworldreader.y(blockposition) - 0.5F; +@@ -118,7 +130,7 @@ public class EntityMushroomCow extends EntityCow implements IShearable { + } else if (itemstack.getItem() == Items.SHEARS && this.canShear()) { + // CraftBukkit start + if (!CraftEventFactory.handlePlayerShearEntityEvent(entityhuman, this, itemstack, enumhand)) { +- return EnumInteractionResult.PASS; ++ return tryRide(entityhuman, enumhand); // Purpur + } + // CraftBukkit end + this.shear(SoundCategory.PLAYERS); +@@ -138,7 +150,7 @@ public class EntityMushroomCow extends EntityCow implements IShearable { + Optional> optional = this.l(itemstack); + + if (!optional.isPresent()) { +- return EnumInteractionResult.PASS; ++ return tryRide(entityhuman, enumhand); // Purpur + } + + Pair pair = (Pair) optional.get(); +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java b/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java +index f3e9c73f28584bcccd6f82d8974eabe4b4a892fa..d7938ff0dca305f1d47fdfdbc57648892debe367 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java +@@ -10,6 +10,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -63,6 +64,18 @@ public class EntityOcelot extends EntityAnimal { + this.eL(); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.ocelotRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.ocelotRidableInWater; ++ } ++ // Purpur end ++ + private boolean isTrusting() { + return (Boolean) this.datawatcher.get(EntityOcelot.bp); + } +@@ -94,12 +107,14 @@ public class EntityOcelot extends EntityAnimal { + protected void initPathfinder() { + this.br = new EntityOcelot.b(this, 0.6D, EntityOcelot.bo, true); + this.goalSelector.a(1, new PathfinderGoalFloat(this)); ++ this.goalSelector.a(1, new PathfinderGoalHasRider(this)); // Purpur + this.goalSelector.a(3, this.br); + this.goalSelector.a(7, new PathfinderGoalLeapAtTarget(this, 0.3F)); + this.goalSelector.a(8, new PathfinderGoalOcelotAttack(this)); + this.goalSelector.a(9, new PathfinderGoalBreed(this, 0.8D)); + this.goalSelector.a(10, new PathfinderGoalRandomStrollLand(this, 0.8D, 1.0000001E-5F)); + this.goalSelector.a(11, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 10.0F)); ++ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityChicken.class, false)); + this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityTurtle.class, 10, false, false, EntityTurtle.bo)); + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java b/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java +index 711b322007a0973ff0aebf3c25efbae8fc7741d0..0d912399e1975d9c0d5525f5b89049f40e7efcc0 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java +@@ -16,6 +16,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -101,6 +102,27 @@ public class EntityPanda extends EntityAnimal { + + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.pandaRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.pandaRidableInWater; ++ } ++ ++ @Override ++ public void onMount(EntityHuman entityhuman) { ++ super.onMount(entityhuman); ++ this.setForwardSpeed(0.0F); ++ this.setScared(false); ++ this.setEating(false); ++ this.setLayingOnBack(false); ++ } ++ // Purpur end ++ + @Override + public boolean e(ItemStack itemstack) { + EnumItemSlot enumitemslot = EntityInsentient.j(itemstack); +@@ -124,6 +146,7 @@ public class EntityPanda extends EntityAnimal { + return this.w(8); + } + ++ public void setScared(boolean scared) { this.t(scared); } // Purpur - OBFHELPER + public void t(boolean flag) { + this.d(8, flag); + } +@@ -132,6 +155,7 @@ public class EntityPanda extends EntityAnimal { + return this.w(16); + } + ++ public void setLayingOnBack(boolean layingOnBack) { this.u(layingOnBack); } // Purpur - OBFHELPER + public void u(boolean flag) { + this.d(16, flag); + } +@@ -148,6 +172,7 @@ public class EntityPanda extends EntityAnimal { + return (Integer) this.datawatcher.get(EntityPanda.br); + } + ++ public void setEating(boolean eating) { this.v(eating); } // Purpur - OBFHELPER + private void v(int i) { + this.datawatcher.set(EntityPanda.br, i); + } +@@ -256,6 +281,7 @@ public class EntityPanda extends EntityAnimal { + @Override + protected void initPathfinder() { + this.goalSelector.a(0, new PathfinderGoalFloat(this)); ++ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.goalSelector.a(2, new EntityPanda.i(this, 2.0D)); + this.goalSelector.a(2, new EntityPanda.d(this, 1.0D)); + this.goalSelector.a(3, new EntityPanda.b(this, 1.2000000476837158D, true)); +@@ -271,6 +297,7 @@ public class EntityPanda extends EntityAnimal { + this.goalSelector.a(12, new EntityPanda.j(this)); + this.goalSelector.a(13, new PathfinderGoalFollowParent(this, 1.25D)); + this.goalSelector.a(14, new PathfinderGoalRandomStrollLand(this, 1.0D)); ++ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.targetSelector.a(1, (new EntityPanda.e(this, new Class[0])).a(new Class[0])); + } + +@@ -591,7 +618,7 @@ public class EntityPanda extends EntityAnimal { + ItemStack itemstack = entityhuman.b(enumhand); + + if (this.ff()) { +- return EnumInteractionResult.PASS; ++ return tryRide(entityhuman, enumhand); // Purpur + } else if (this.eN()) { + this.u(false); + return EnumInteractionResult.a(this.world.isClientSide); +@@ -608,7 +635,7 @@ public class EntityPanda extends EntityAnimal { + this.g(entityhuman); + } else { + if (this.world.isClientSide || this.eM() || this.isInWater()) { +- return EnumInteractionResult.PASS; ++ return tryRide(entityhuman, enumhand); // Purpur + } + + this.ft(); +@@ -625,7 +652,7 @@ public class EntityPanda extends EntityAnimal { + + return EnumInteractionResult.SUCCESS; + } else { +- return EnumInteractionResult.PASS; ++ return tryRide(entityhuman, enumhand); // Purpur + } + } + +@@ -738,6 +765,7 @@ public class EntityPanda extends EntityAnimal { + + public f(EntityPanda entitypanda) { + this.a = entitypanda; ++ this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - lay on back + } + + @Override +@@ -901,6 +929,7 @@ public class EntityPanda extends EntityAnimal { + + public l(EntityPanda entitypanda) { + this.a = entitypanda; ++ this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - sneeze + } + + @Override +@@ -1030,7 +1059,7 @@ public class EntityPanda extends EntityAnimal { + } + } + +- static class h extends ControllerMove { ++ static class h extends net.pl3x.purpur.controller.ControllerMoveWASD { // Purpur + + private final EntityPanda i; + +@@ -1040,9 +1069,9 @@ public class EntityPanda extends EntityAnimal { + } + + @Override +- public void a() { ++ public void tick() { // Purpur + if (this.i.fh()) { +- super.a(); ++ super.tick(); // Purpur + } + } + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java +index 699dd0ac1f8d0d340ab1a560106336fc7cc95d5b..5c26eea7e3e93dc7bcd8b86519e84db58b70cecb 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java +@@ -16,6 +16,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundCategory; + import net.minecraft.sounds.SoundEffect; +@@ -38,6 +39,7 @@ import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySize; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.ai.attributes.AttributeProvider; + import net.minecraft.world.entity.ai.attributes.GenericAttributes; +@@ -119,12 +121,58 @@ public class EntityParrot extends EntityPerchable implements EntityBird { + + public EntityParrot(EntityTypes entitytypes, World world) { + super(entitytypes, world); +- this.moveController = new ControllerMoveFlying(this, 10, false); ++ // Purpur start ++ final net.pl3x.purpur.controller.ControllerMoveWASDFlyingWithSpacebar flyingController = new net.pl3x.purpur.controller.ControllerMoveWASDFlyingWithSpacebar(this, 0.3F); ++ this.moveController = new ControllerMoveFlying(this, 10, false) { ++ @Override ++ public void a() { // tick ++ if (getEntity().hasRider()) { ++ flyingController.tick(getEntity().getRider()); ++ } else { ++ tick(); ++ } ++ } ++ ++ @Override ++ public boolean b() { // isUpdating ++ return getEntity().hasRider() ? getForward() != 0 || getStrafe() != 0 : super.b(); ++ } ++ }; ++ // Purpur end + this.a(PathType.DANGER_FIRE, -1.0F); + this.a(PathType.DAMAGE_FIRE, -1.0F); + this.a(PathType.COCOA, -1.0F); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.parrotRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.parrotRidableInWater; ++ } ++ ++ @Override ++ public double getMaxY() { ++ return world.purpurConfig.parrotMaxY; ++ } ++ ++ @Override ++ public void g(Vec3D vec3d) { ++ super.g(vec3d); ++ if (hasRider() && !onGround) { ++ float speed = (float) getAttributeInstance(GenericAttributes.FLYING_SPEED).getValue() * 2; ++ setSpeed(speed); ++ Vec3D mot = getMot(); ++ move(EnumMoveType.SELF, mot.multiply(speed, 0.25, speed)); ++ setMot(mot.a(0.9D)); ++ } ++ } ++ // Purpur end ++ + @Nullable + @Override + public GroupDataEntity prepare(WorldAccess worldaccess, DifficultyDamageScaler difficultydamagescaler, EnumMobSpawn enummobspawn, @Nullable GroupDataEntity groupdataentity, @Nullable NBTTagCompound nbttagcompound) { +@@ -143,8 +191,10 @@ public class EntityParrot extends EntityPerchable implements EntityBird { + + @Override + protected void initPathfinder() { +- this.goalSelector.a(0, new PathfinderGoalPanic(this, 1.25D)); ++ // this.goalSelector.a(0, new PathfinderGoalPanic(this, 1.25D)); // Purpur - move down + this.goalSelector.a(0, new PathfinderGoalFloat(this)); ++ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur ++ this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.25D)); // Purpur + this.goalSelector.a(1, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); + this.goalSelector.a(2, new PathfinderGoalSit(this)); + this.goalSelector.a(2, new PathfinderGoalFollowOwner(this, 1.0D, 5.0F, 1.0F, true)); +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java +index 1a540e41e6161d011ca4ed30c68ae9df4567b8db..cef69f99d7bc9b6605b9654c50f43a1ebc1a8509 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java +@@ -9,6 +9,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundCategory; + import net.minecraft.sounds.SoundEffect; +@@ -66,9 +67,22 @@ public class EntityPig extends EntityAnimal implements ISteerable, ISaddleable { + this.saddleStorage = new SaddleStorage(this.datawatcher, EntityPig.bp, EntityPig.bo); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.pigRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.pigRidableInWater; ++ } ++ // Purpur end ++ + @Override + protected void initPathfinder() { + this.goalSelector.a(0, new PathfinderGoalFloat(this)); ++ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.25D)); + this.goalSelector.a(3, new PathfinderGoalBreed(this, 1.0D)); + this.goalSelector.a(4, new PathfinderGoalTempt(this, 1.2D, RecipeItemStack.a(Items.CARROT_ON_A_STICK), false)); +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java b/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java +index f25f5ced218555af0d62844a78842cfc7599d608..e686491a469573a3fc466c46be1b7430ff02ba53 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java +@@ -14,6 +14,7 @@ import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; + import net.minecraft.resources.ResourceKey; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -66,12 +67,34 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { + private static final IntRange bs = TimeRange.a(20, 39); + private int bt; + private UUID bu; ++ private int standTimer = 0; // Purpur + + public EntityPolarBear(EntityTypes entitytypes, World world) { + super(entitytypes, world); + } + + // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.polarBearRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.polarBearRidableInWater; ++ } ++ ++ @Override ++ public boolean onSpacebar() { ++ if (!isStanding()) { ++ if (hasRider() && getRider().getForward() == 0 && getRider().getStrafe() == 0) { ++ setStanding(true); ++ playSound(SoundEffects.ENTITY_POLAR_BEAR_WARNING, 1.0F, 1.0F); ++ } ++ } ++ return false; ++ } ++ + @Override + public boolean mate(EntityAnimal entityanimal) { + if (entityanimal == this) { +@@ -109,6 +132,7 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { + protected void initPathfinder() { + super.initPathfinder(); + this.goalSelector.a(0, new PathfinderGoalFloat(this)); ++ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.goalSelector.a(1, new EntityPolarBear.c()); + this.goalSelector.a(1, new EntityPolarBear.d()); + // Purpur start +@@ -121,6 +145,7 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { + this.goalSelector.a(5, new PathfinderGoalRandomStroll(this, 1.0D)); + this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F)); + this.goalSelector.a(7, new PathfinderGoalRandomLookaround(this)); ++ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.targetSelector.a(1, new EntityPolarBear.b()); + this.targetSelector.a(2, new EntityPolarBear.a()); + this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, this::a_)); +@@ -233,6 +258,11 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { + this.a((WorldServer) this.world, true); + } + ++ // Purpur start ++ if (isStanding() && --standTimer <= 0) { ++ setStanding(false); ++ } ++ // Purpur end + } + + @Override +@@ -266,6 +296,7 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { + public void setStanding(boolean standing) { t(standing); } // Purpur - OBFHELPER + public void t(boolean flag) { + this.datawatcher.set(EntityPolarBear.bo, flag); ++ standTimer = flag ? 20 : -1; // Purpur + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java b/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java +index e9f20d387ccdacfbb1a48dc31e2a6cd4843a0d7b..38fe79872b4b7f4ad4a030fbdf505efbc0352fc0 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java +@@ -39,6 +39,18 @@ public class EntityPufferFish extends EntityFish { + super(entitytypes, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.pufferfishRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return true; ++ } ++ // Purpur end ++ + @Override + protected void initDatawatcher() { + super.initDatawatcher(); +@@ -82,7 +94,7 @@ public class EntityPufferFish extends EntityFish { + @Override + protected void initPathfinder() { + super.initPathfinder(); +- this.goalSelector.a(1, new EntityPufferFish.a(this)); ++ this.goalSelector.a(2, new EntityPufferFish.a(this)); // Purpur + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java b/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java +index 180fc927074dc683ad4d482a00dd4e04ff7923d0..fff6bcff9d44c7d49cd2d0c334ea702531c74ea1 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java +@@ -10,6 +10,7 @@ import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; + import net.minecraft.resources.MinecraftKey; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundCategory; + import net.minecraft.sounds.SoundEffect; +@@ -75,6 +76,18 @@ public class EntityRabbit extends EntityAnimal { + this.initializePathFinderGoals(); // CraftBukkit - moved code + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.rabbitRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.rabbitRidableInWater; ++ } ++ // Purpur end ++ + // CraftBukkit start - code from constructor + public void initializePathFinderGoals(){ + this.i(0.0D); +@@ -83,7 +96,8 @@ public class EntityRabbit extends EntityAnimal { + + @Override + public void initPathfinder() { +- this.goalSelector.a(1, new PathfinderGoalFloat(this)); ++ this.goalSelector.a(0, new PathfinderGoalFloat(this)); // Purpur ++ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.goalSelector.a(1, new EntityRabbit.PathfinderGoalRabbitPanic(this, 2.2D)); + this.goalSelector.a(2, new PathfinderGoalBreed(this, 0.8D)); + this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.0D, RecipeItemStack.a(Items.CARROT, Items.GOLDEN_CARROT, Blocks.DANDELION), false)); +@@ -96,7 +110,15 @@ public class EntityRabbit extends EntityAnimal { + } + + @Override +- protected float dJ() { ++ // Purpur start ++ public float getJumpHeight() { ++ if (hasRider()) { ++ if (getForward() < 0) { ++ setSpeed(getForward() * 2F); ++ } ++ return actualJump ? 0.5F : 0.3F; ++ } ++ // Purpur end + if (!this.positionChanged && (!this.moveController.b() || this.moveController.e() <= this.locY() + 0.5D)) { + PathEntity pathentity = this.navigation.k(); + +@@ -115,7 +137,7 @@ public class EntityRabbit extends EntityAnimal { + } + + @Override +- protected void jump() { ++ public void jump() { // Purpur - protected -> public + super.jump(); + double d0 = this.moveController.c(); + +@@ -147,6 +169,7 @@ public class EntityRabbit extends EntityAnimal { + + } + ++ public void startJumping() { eK(); } // Purpur - OBFHELPER + public void eK() { + this.setJumping(true); + this.br = 10; +@@ -161,6 +184,13 @@ public class EntityRabbit extends EntityAnimal { + + @Override + public void mobTick() { ++ // Purpur start ++ if (hasRider()) { ++ handleJumping(); ++ return; ++ } ++ // Purpur end ++ + if (this.bt > 0) { + --this.bt; + } +@@ -211,6 +241,39 @@ public class EntityRabbit extends EntityAnimal { + this.bs = this.onGround; + } + ++ // Purpur start ++ private boolean wasOnGround; ++ private boolean actualJump; ++ ++ private void handleJumping() { ++ if (onGround) { ++ ControllerJumpRabbit jumpController = (ControllerJumpRabbit) getJumpController(); ++ if (!wasOnGround) { ++ setJumping(false); ++ jumpController.setCanJump(false); ++ } ++ if (!jumpController.isJumping()) { ++ if (moveController.b()) { // isUpdating ++ startJumping(); ++ } ++ } else if (!jumpController.canJump()) { ++ jumpController.setCanJump(true); ++ } ++ } ++ wasOnGround = onGround; ++ } ++ ++ @Override ++ public boolean onSpacebar() { ++ if (onGround) { ++ actualJump = true; ++ jump(); ++ actualJump = false; ++ } ++ return true; ++ } ++ // Purpur end ++ + @Override + public boolean aO() { + return false; +@@ -540,7 +603,7 @@ public class EntityRabbit extends EntityAnimal { + } + } + +- static class ControllerMoveRabbit extends ControllerMove { ++ static class ControllerMoveRabbit extends net.pl3x.purpur.controller.ControllerMoveWASD { // Purpur + + private final EntityRabbit i; + private double j; +@@ -551,14 +614,14 @@ public class EntityRabbit extends EntityAnimal { + } + + @Override +- public void a() { ++ public void tick() { // Purpur + if (this.i.onGround && !this.i.jumping && !((EntityRabbit.ControllerJumpRabbit) this.i.bi).c()) { + this.i.i(0.0D); + } else if (this.b()) { + this.i.i(this.j); + } + +- super.a(); ++ super.tick(); // Purpur + } + + @Override +@@ -585,14 +648,17 @@ public class EntityRabbit extends EntityAnimal { + this.c = entityrabbit; + } + ++ public boolean isJumping() { return c(); } // Purpur - OBFHELPER + public boolean c() { + return this.a; + } + ++ public boolean canJump() { return d(); } // Purpur - OBFHELPER + public boolean d() { + return this.d; + } + ++ public void setCanJump(boolean canJump) { a(canJump); } // Purpur - OBFHELPER + public void a(boolean flag) { + this.d = flag; + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySalmon.java b/src/main/java/net/minecraft/world/entity/animal/EntitySalmon.java +index ca125342f189d5db95ebd04043a2d11e5fbfd3fd..bf565671c167162b3d935447961f0d44ed4a2779 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntitySalmon.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntitySalmon.java +@@ -14,6 +14,18 @@ public class EntitySalmon extends EntityFishSchool { + super(entitytypes, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.salmonRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return true; ++ } ++ // Purpur end ++ + @Override + public int eN() { + return 5; +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java b/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java +index 88bed962bc17242ee6a9c93b7e0fec8bc578b35f..8f3296031f220dd7bb3ae9fe2443e479954ebad3 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java +@@ -14,6 +14,7 @@ import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; + import net.minecraft.resources.MinecraftKey; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundCategory; + import net.minecraft.sounds.SoundEffect; +@@ -110,10 +111,23 @@ public class EntitySheep extends EntityAnimal implements IShearable { + super(entitytypes, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.sheepRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.sheepRidableInWater; ++ } ++ // Purpur end ++ + @Override + protected void initPathfinder() { + this.bs = new PathfinderGoalEatTile(this); + this.goalSelector.a(0, new PathfinderGoalFloat(this)); ++ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.25D)); + this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D)); + this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.1D, RecipeItemStack.a(Items.WHEAT), false)); +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java b/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java +index 44119f52a4f169ffcea53fb69393bfedfd1a62a7..cfcf67e99ae345f77a55771e6a25bdcdb4a9740a 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java +@@ -6,6 +6,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.sounds.SoundCategory; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -50,12 +51,26 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt + super(entitytypes, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.snowGolemRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.snowGolemRidableInWater; ++ } ++ // Purpur end ++ + @Override + protected void initPathfinder() { ++ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.goalSelector.a(1, new PathfinderGoalArrowAttack(this, 1.25D, 20, 10.0F)); + this.goalSelector.a(2, new PathfinderGoalRandomStrollLand(this, 1.0D, 1.0000001E-5F)); + this.goalSelector.a(3, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F)); + this.goalSelector.a(4, new PathfinderGoalRandomLookaround(this)); ++ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityInsentient.class, 10, true, false, (entityliving) -> { + return entityliving instanceof IMonster; + })); +@@ -107,6 +122,7 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt + return; + } + ++ if (hasRider() && !world.purpurConfig.snowGolemLeaveTrailWhenRidden) return; // Purpur - don't leave snow trail when being ridden + IBlockData iblockdata = Blocks.SNOW.getBlockData(); + + for (int l = 0; l < 4; ++l) { +@@ -149,7 +165,7 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt + if (itemstack.getItem() == Items.SHEARS && this.canShear()) { + // CraftBukkit start + if (!CraftEventFactory.handlePlayerShearEntityEvent(entityhuman, this, itemstack, enumhand)) { +- return EnumInteractionResult.PASS; ++ return tryRide(entityhuman, enumhand); // Purpur + } + // CraftBukkit end + this.shear(SoundCategory.PLAYERS); +@@ -169,7 +185,7 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt + return EnumInteractionResult.SUCCESS; + // Purpur end + } else { +- return EnumInteractionResult.PASS; ++ return tryRide(entityhuman, enumhand); // Purpur + } + } + +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java +index 081929990a8208f643d298a885acc4ddfa401bfb..10e228a36b213a87e17f26a633adfca18a006e94 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java +@@ -3,6 +3,7 @@ package net.minecraft.world.entity.animal; + import java.util.Random; + import net.minecraft.core.BlockPosition; + import net.minecraft.core.particles.Particles; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -22,6 +23,7 @@ import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.ai.attributes.AttributeProvider; + import net.minecraft.world.entity.ai.attributes.GenericAttributes; + import net.minecraft.world.entity.ai.goal.PathfinderGoal; ++import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.level.GeneratorAccess; + import net.minecraft.world.level.World; + import net.minecraft.world.level.block.state.IBlockData; +@@ -53,17 +55,38 @@ public class EntitySquid extends EntityWaterAnimal { + } + + // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.squidRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return true; ++ } ++ + @Override + public AxisAlignedBB getAxisForFluidCheck() { + // Stops squids from floating just over the water + return this.getBoundingBox().shrink(0.001D).offsetY(world.purpurConfig.squidOffsetWaterCheck); + } ++ ++ private void rotateVectorAroundY(org.bukkit.util.Vector vector, double degrees) { ++ double rad = Math.toRadians(degrees); ++ double cos = Math.cos(rad); ++ double sine = Math.sin(rad); ++ double x = vector.getX(); ++ double z = vector.getZ(); ++ vector.setX(cos * x - sine * z); ++ vector.setZ(sine * x + cos * z); ++ } + // Purpur end + + @Override + protected void initPathfinder() { + this.goalSelector.a(0, new EntitySquid.PathfinderGoalSquid(this)); +- this.goalSelector.a(1, new EntitySquid.a()); ++ this.goalSelector.a(1, new PathfinderGoalHasRider(this)); // Purpur ++ this.goalSelector.a(2, new EntitySquid.a()); // Purpur + } + + public static AttributeProvider.Builder m() { +@@ -208,6 +231,7 @@ public class EntitySquid extends EntityWaterAnimal { + return blockposition.getY() > generatoraccess.getMinecraftWorld().spigotConfig.squidSpawnRangeMin && blockposition.getY() < maxHeight; // Spigot // Paper + } + ++ public void setMovementVector(float x, float y, float z) { a(x, y, z); } // Purpur - OBFHELPER + public void a(float f, float f1, float f2) { + this.bw = f; + this.bx = f1; +@@ -279,7 +303,7 @@ public class EntitySquid extends EntityWaterAnimal { + + class PathfinderGoalSquid extends PathfinderGoal { + +- private final EntitySquid b; ++ private final EntitySquid b; public EntitySquid getSquid() { return b; } // Purpur - OBFHELPER + + public PathfinderGoalSquid(EntitySquid entitysquid) { + this.b = entitysquid; +@@ -292,6 +316,38 @@ public class EntitySquid extends EntityWaterAnimal { + + @Override + public void e() { ++ // Purpur start ++ EntitySquid squid = getSquid(); ++ EntityHuman rider = squid.getRider(); ++ if (rider != null) { ++ if (rider.jumping) { ++ squid.onSpacebar(); ++ } ++ float forward = rider.getForward(); ++ float strafe = rider.getStrafe(); ++ float speed = (float) squid.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getValue() * 10F; ++ if (forward < 0.0F) { ++ speed *= -0.5; ++ } ++ org.bukkit.util.Vector dir = rider.getBukkitEntity().getEyeLocation().getDirection().normalize().multiply(speed / 20.0F); ++ if (strafe != 0.0F) { ++ if (forward == 0.0F) { ++ dir.setY(0); ++ rotateVectorAroundY(dir, strafe > 0.0F ? -90 : 90); ++ } else if (forward < 0.0F) { ++ rotateVectorAroundY(dir, strafe > 0.0F ? 45 : -45); ++ } else { ++ rotateVectorAroundY(dir, strafe > 0.0F ? -45 : 45); ++ } ++ } ++ if (forward != 0.0F || strafe != 0.0F) { ++ squid.setMovementVector((float) dir.getX(), (float) dir.getY(), (float) dir.getZ()); ++ } else { ++ squid.setMovementVector(0.0F, 0.0F, 0.0F); ++ } ++ return; ++ } ++ // Purpur end + int i = this.b.dd(); + + if (i > 100) { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTropicalFish.java b/src/main/java/net/minecraft/world/entity/animal/EntityTropicalFish.java +index 29f6835da58c73a99fe620d6de7d86fede6ac893..478e55475ccc1410a442f4e30a1cbc08f479dbda 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityTropicalFish.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityTropicalFish.java +@@ -37,6 +37,18 @@ public class EntityTropicalFish extends EntityFishSchool { + super(entitytypes, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.tropicalFishRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return true; ++ } ++ // Purpur end ++ + @Override + protected void initDatawatcher() { + super.initDatawatcher(); +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java +index ecec8a3c4d4b5d491f79ad60d7ce5a118f30b3db..28d6e673f55fc8fae40dff4a96ac2c2b5eeab9d6 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java +@@ -15,6 +15,7 @@ import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; + import net.minecraft.server.MCUtil; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundCategory; +@@ -90,6 +91,18 @@ public class EntityTurtle extends EntityAnimal { + this.G = 1.0F; + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.turtleRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.turtleRidableInWater; ++ } ++ // Purpur end ++ + public void setHomePos(BlockPosition blockposition) { + this.datawatcher.set(EntityTurtle.bp, blockposition.immutableCopy()); // Paper - called with mutablepos... + } +@@ -198,12 +211,13 @@ public class EntityTurtle extends EntityAnimal { + + @Override + protected void initPathfinder() { +- this.goalSelector.a(0, new EntityTurtle.f(this, 1.2D)); +- this.goalSelector.a(1, new EntityTurtle.a(this, 1.0D)); +- this.goalSelector.a(1, new EntityTurtle.d(this, 1.0D)); +- this.goalSelector.a(2, new EntityTurtle.i(this, 1.1D, Blocks.SEAGRASS.getItem())); +- this.goalSelector.a(3, new EntityTurtle.c(this, 1.0D)); +- this.goalSelector.a(4, new EntityTurtle.b(this, 1.0D)); ++ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur ++ this.goalSelector.a(1, new EntityTurtle.f(this, 1.2D)); // Purpur ++ this.goalSelector.a(2, new EntityTurtle.a(this, 1.0D)); // Purpur ++ this.goalSelector.a(2, new EntityTurtle.d(this, 1.0D)); // Purpur ++ this.goalSelector.a(3, new EntityTurtle.i(this, 1.1D, Blocks.SEAGRASS.getItem())); // Purpur ++ this.goalSelector.a(4, new EntityTurtle.c(this, 1.0D)); // Purpur ++ this.goalSelector.a(5, new EntityTurtle.b(this, 1.0D)); // Purpur + this.goalSelector.a(7, new EntityTurtle.j(this, 1.0D)); + this.goalSelector.a(8, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); + this.goalSelector.a(9, new EntityTurtle.h(this, 1.0D, 100)); +@@ -386,13 +400,15 @@ public class EntityTurtle extends EntityAnimal { + } + } + +- static class e extends ControllerMove { ++ static class e extends net.pl3x.purpur.controller.ControllerMoveWASD { // Purpur + +- private final EntityTurtle i; ++ private final EntityTurtle i; public EntityTurtle getTurtle() { return i; } // Purpur - OBFHELPER ++ private final net.pl3x.purpur.controller.ControllerMoveWASDWater waterController; // Purpur + + e(EntityTurtle entityturtle) { +- super(entityturtle); ++ super(entityturtle, 0.1D); // Purpur + this.i = entityturtle; ++ waterController = new net.pl3x.purpur.controller.ControllerMoveWASDWater(entityturtle, 0.25D); // Purpur + } + + private void g() { +@@ -412,7 +428,18 @@ public class EntityTurtle extends EntityAnimal { + } + + @Override +- public void a() { ++ // Purpur start ++ public void tick(EntityHuman rider) { ++ if (getTurtle().isInWater()) { ++ waterController.tick(rider); ++ } else { ++ super.tick(rider); ++ } ++ } ++ ++ @Override ++ public void tick() { ++ // Purpur end + this.g(); + if (this.h == ControllerMove.Operation.MOVE_TO && !this.i.getNavigation().m()) { + double d0 = this.b - this.i.locX(); +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java b/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java +index b44b1544f401c1a5127bed3239bfd60420d17329..3fbd8f9122d7a5ac23af4d872f877030644ef86a 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java +@@ -9,6 +9,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -91,9 +92,27 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable + this.setTamed(false); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.wolfRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.wolfRidableInWater; ++ } ++ ++ public void onMount(EntityHuman entityhuman) { ++ super.onMount(entityhuman); ++ setSitting(false); ++ } ++ // Purpur end ++ + @Override + protected void initPathfinder() { + this.goalSelector.a(1, new PathfinderGoalFloat(this)); ++ this.goalSelector.a(1, new PathfinderGoalHasRider(this)); // Purpur + this.goalSelector.a(2, new PathfinderGoalSit(this)); + this.goalSelector.a(3, new EntityWolf.a<>(this, EntityLlama.class, 24.0F, 1.5D, 1.5D)); + this.goalSelector.a(4, new PathfinderGoalLeapAtTarget(this, 0.4F)); +@@ -104,6 +123,7 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable + this.goalSelector.a(9, new PathfinderGoalBeg(this, 8.0F)); + this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); + this.goalSelector.a(10, new PathfinderGoalRandomLookaround(this)); ++ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.targetSelector.a(1, new PathfinderGoalOwnerHurtByTarget(this)); + this.targetSelector.a(2, new PathfinderGoalOwnerHurtTarget(this)); + this.targetSelector.a(3, (new PathfinderGoalHurtByTarget(this, new Class[0])).a(new Class[0])); // CraftBukkit - decompile error +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java +index 48f67652a0a6797e217ce1f6040b5dc0f7a74938..650f13b1133e4c61f71b36f3f91a9d2913996435 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java +@@ -41,6 +41,13 @@ public class EntityHorse extends EntityHorseAbstract { + super(entitytypes, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.horseRidableInWater; ++ } ++ // Purpur end ++ + @Override + protected void eK() { + this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue((double) this.fp()); +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java +index cb6e2053d1315b65812e7bff8a17988b5b8ab0e4..d4556fa190c754406d0c65baae941fb23af3f81f 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java +@@ -14,6 +14,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHorseHasRider; + import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.WorldServer; + import net.minecraft.server.players.NameReferencingFileConverter; +@@ -43,6 +44,8 @@ import net.minecraft.world.entity.IJumpable; + import net.minecraft.world.entity.ISaddleable; + import net.minecraft.world.entity.ai.attributes.AttributeProvider; + import net.minecraft.world.entity.ai.attributes.GenericAttributes; ++import net.minecraft.world.entity.ai.control.ControllerLook; ++import net.minecraft.world.entity.ai.control.ControllerMove; + import net.minecraft.world.entity.ai.goal.PathfinderGoalBreed; + import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat; + import net.minecraft.world.entity.ai.goal.PathfinderGoalFollowParent; +@@ -101,12 +104,27 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven + + protected EntityHorseAbstract(EntityTypes entitytypes, World world) { + super(entitytypes, world); ++ this.moveController = new ControllerMove(this); // Purpur - use vanilla controller ++ this.lookController = new ControllerLook(this); // Purpur - use vanilla controller + this.G = 1.0F; + this.loadChest(); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return false; // vanilla handles ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return false; ++ } ++ // Purpur end ++ + @Override + protected void initPathfinder() { ++ this.goalSelector.a(0, new PathfinderGoalHorseHasRider(this)); // Purpur + this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.2D)); + this.goalSelector.a(1, new PathfinderGoalTame(this, 1.2D)); + this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D, EntityHorseAbstract.class)); +@@ -114,6 +132,7 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven + this.goalSelector.a(6, new PathfinderGoalRandomStrollLand(this, 0.7D)); + this.goalSelector.a(7, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F)); + this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this)); ++ this.targetSelector.a(0, new PathfinderGoalHorseHasRider(this)); // Purpur + this.eV(); + } + +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java +index d9c87411f5c636bee3f28b724abf665826788be4..50700bf85a296b87fe3155651f869e2bbdb0875d 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java +@@ -16,6 +16,13 @@ public class EntityHorseDonkey extends EntityHorseChestedAbstract { + super(entitytypes, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.donkeyRidableInWater; ++ } ++ // Purpur end ++ + @Override + protected SoundEffect getSoundAmbient() { + super.getSoundAmbient(); +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java +index 7a5c14c1e80bde623473a39acb01b78b79d593e4..b6385a23050296611dbc8864b92d2cdd8321a1d0 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java +@@ -15,6 +15,12 @@ public class EntityHorseMule extends EntityHorseChestedAbstract { + super(entitytypes, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.muleRidableInWater; ++ } ++ // Purpur end + @Override + protected SoundEffect getSoundAmbient() { + super.getSoundAmbient(); +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java +index da5365372e89b847d626e52c5541544467f14702..d21399fbb6ddc4f26a7509ce547f8c4ad6458089 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java +@@ -17,6 +17,7 @@ import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.ai.attributes.AttributeProvider; + import net.minecraft.world.entity.ai.attributes.GenericAttributes; + import net.minecraft.world.entity.ai.goal.PathfinderGoal; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +@@ -32,6 +33,18 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { + super(entitytypes, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.skeletonHorseRidableInWater; ++ } ++ ++ @Override ++ public boolean isTamed() { ++ return true; ++ } ++ // Purpur end ++ + public static AttributeProvider.Builder eL() { + return fi().a(GenericAttributes.MAX_HEALTH, 15.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.20000000298023224D); + } +@@ -42,7 +55,7 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { + } + + @Override +- protected void eV() {} ++ protected void eV() { if (world.purpurConfig.skeletonHorseCanSwim) goalSelector.a(0, new PathfinderGoalFloat(this)); } // Purpur + + @Override + protected SoundEffect getSoundAmbient() { +@@ -137,7 +150,7 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { + + @Override + public boolean bt() { +- return true; ++ return super.bt(); // Purpur + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java +index 2e448a40dbf2fa5b4df4493f14738210615bab38..d57e7c02268e5d8a00b0b5897fa03dcee10cd2e0 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java +@@ -13,6 +13,7 @@ import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.ai.attributes.AttributeProvider; + import net.minecraft.world.entity.ai.attributes.GenericAttributes; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +@@ -24,6 +25,18 @@ public class EntityHorseZombie extends EntityHorseAbstract { + super(entitytypes, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.zombieHorseRidableInWater; ++ } ++ ++ @Override ++ public boolean isTamed() { ++ return true; ++ } ++ // Purpur end ++ + public static AttributeProvider.Builder eL() { + return fi().a(GenericAttributes.MAX_HEALTH, 15.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.20000000298023224D); + } +@@ -95,5 +108,5 @@ public class EntityHorseZombie extends EntityHorseAbstract { + } + + @Override +- protected void eV() {} ++ protected void eV() { if (world.purpurConfig.zombieHorseCanSwim) goalSelector.a(0, new PathfinderGoalFloat(this)); } // Purpur + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java +index 1c6435bf2cd870b795f87368057d8dfc1e1c938a..d1bd7b9a6a8cfb6b609db4229b2f42a40b8b484f 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java +@@ -8,6 +8,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHorseHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -68,7 +69,46 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn + + public EntityLlama(EntityTypes entitytypes, World world) { + super(entitytypes, world); ++ // Purpur start ++ this.moveController = new net.pl3x.purpur.controller.ControllerMoveWASD(this) { ++ @Override ++ public void a() { // tick ++ if (entity.hasRider() && hasSaddle()) { ++ tick(entity.getRider()); ++ } else { ++ tick(); ++ } ++ } ++ }; ++ this.lookController = new net.pl3x.purpur.controller.ControllerLookWASD(this) { ++ @Override ++ public void a() { // tick ++ if (entity.hasRider() && hasSaddle()) { ++ tick(entity.getRider()); ++ } else { ++ tick(); ++ } ++ } ++ }; ++ // Purpur end ++ } ++ ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.llamaRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.llamaRidableInWater; ++ } ++ ++ @Override ++ public boolean hasSaddle() { ++ return super.hasSaddle() || (isTamed() && getColor() != null); + } ++ // Purpur end + + public void setStrength(int i) { + this.datawatcher.set(EntityLlama.bx, Math.max(1, Math.min(5, i))); +@@ -116,6 +156,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn + @Override + protected void initPathfinder() { + this.goalSelector.a(0, new PathfinderGoalFloat(this)); ++ this.goalSelector.a(0, new PathfinderGoalHorseHasRider(this)); // Purpur + this.goalSelector.a(1, new PathfinderGoalTame(this, 1.2D)); + this.goalSelector.a(2, new PathfinderGoalLlamaFollow(this, 2.0999999046325684D)); + this.goalSelector.a(3, new PathfinderGoalArrowAttack(this, 1.25D, 40, 20.0F)); +@@ -125,6 +166,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn + this.goalSelector.a(6, new PathfinderGoalRandomStrollLand(this, 0.7D)); + this.goalSelector.a(7, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F)); + this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this)); ++ this.targetSelector.a(0, new PathfinderGoalHorseHasRider(this)); // Purpur + this.targetSelector.a(1, new EntityLlama.c(this)); + this.targetSelector.a(2, new EntityLlama.a(this)); + } +@@ -362,7 +404,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn + } + + @Nullable +- public EnumColor fy() { ++ public EnumColor fy() { return getColor(); } public EnumColor getColor() { // Purpur - OBFHELPER + int i = (Integer) this.datawatcher.get(EntityLlama.by); + + return i == -1 ? null : EnumColor.fromColorIndex(i); +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.java +index f761e37f7329342f01f04df5602573a51c0aca4e..0fb651bcde1109b0eb30b60226d3512648dceb41 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.java +@@ -27,6 +27,23 @@ public class EntityLlamaTrader extends EntityLlama { + super(entitytypes, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.llamaTraderRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.llamaTraderRidableInWater; ++ } ++ ++ @Override ++ public boolean hasSaddle() { ++ return super.hasSaddle() || isTamed(); ++ } ++ // Purpur end ++ + @Override + protected EntityLlama fz() { + return (EntityLlama) EntityTypes.TRADER_LLAMA.a(this.world); +diff --git a/src/main/java/net/minecraft/world/entity/boss/EntityComplexPart.java b/src/main/java/net/minecraft/world/entity/boss/EntityComplexPart.java +index f1065c2a37835d760fb57194f7edfd029f426b48..3f2065e2939be54639f44501f7aa8ee5500dfc84 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/EntityComplexPart.java ++++ b/src/main/java/net/minecraft/world/entity/boss/EntityComplexPart.java +@@ -2,11 +2,14 @@ package net.minecraft.world.entity.boss; + + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.protocol.Packet; ++import net.minecraft.world.EnumHand; ++import net.minecraft.world.EnumInteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySize; + import net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon; ++import net.minecraft.world.entity.player.EntityHuman; + + public class EntityComplexPart extends Entity { + +@@ -55,4 +58,11 @@ public class EntityComplexPart extends Entity { + public EntitySize a(EntityPose entitypose) { + return this.d; + } ++ ++ // Purpur start ++ @Override ++ public EnumInteractionResult a(EntityHuman entityhuman, EnumHand enumhand) { ++ return owner.isAlive() ? owner.tryRide(entityhuman, enumhand) : EnumInteractionResult.PASS; ++ } ++ // Purpur end + } +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +index 3fff101637708a1a12f9a457bd3512ae94a8f884..7f583c6c15f0191219eb911d901ea28d86c11489 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +@@ -23,6 +23,7 @@ import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityExperienceOrb; + import net.minecraft.world.entity.EntityInsentient; + import net.minecraft.world.entity.EntityLiving; ++import net.minecraft.world.entity.EntitySize; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.IEntitySelector; +@@ -95,6 +96,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { + private final int[] bK = new int[24]; + private final Path bL = new Path(); + private Explosion explosionSource = new Explosion(null, this, null, null, Double.NaN, Double.NaN, Double.NaN, Float.NaN, true, Explosion.Effect.DESTROY); // CraftBukkit - reusable source for CraftTNTPrimed.getSource() ++ private boolean hadRider; // Purpur + + public EntityEnderDragon(EntityTypes entitytypes, World world) { + super(EntityTypes.ENDER_DRAGON, world); +@@ -109,8 +111,44 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { + } + + this.bG = new DragonControllerManager(this); ++ // Purpur start ++ this.moveController = new net.pl3x.purpur.controller.ControllerMoveWASDFlying(this) { ++ @Override ++ public void tick() { ++ // dragon doesn't use the controller. do nothing ++ } ++ }; ++ this.lookController = new net.pl3x.purpur.controller.ControllerLookWASD(this) { ++ @Override ++ public void tick() { ++ // dragon doesn't use the controller. do nothing ++ } ++ ++ @Override ++ public void tick(EntityHuman rider) { ++ setYawPitch(rider.yaw - 180F, rider.pitch * 0.5F); ++ } ++ }; ++ // Purpur end ++ } ++ ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.enderDragonRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.enderDragonRidableInWater; + } + ++ @Override ++ public double getMaxY() { ++ return world.purpurConfig.enderDragonMaxY; ++ } ++ // Purpur end ++ + public static AttributeProvider.Builder m() { + return EntityInsentient.p().a(GenericAttributes.MAX_HEALTH, 200.0D); + } +@@ -143,6 +181,37 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { + + @Override + public void movementTick() { ++ // Purpur start ++ boolean hasRider = getRider() != null; ++ if (hasRider) { ++ if (!hadRider) { ++ hadRider = true; ++ noclip = false; ++ this.size = EntitySize.b(4.0F, 2.0F); ++ } ++ ++ // dragon doesn't use controllers, so must tick manually ++ moveController.a(); ++ lookController.a(); ++ ++ moveRelative((float) getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getValue() * 0.1F, new Vec3D(-getStrafe(), getVertical(), -getForward())); ++ Vec3D mot = getMot(); ++ setMot(mot); ++ move(EnumMoveType.PLAYER, mot); ++ ++ mot = mot.multiply(0.9F, 0.9F, 0.9F); ++ setMot(mot); ++ ++ // control wing flap speed on client ++ getDragonControllerManager().setControllerPhase(mot.getX() * mot.getX() + mot.getZ() * mot.getZ() < 0.005F ? DragonControllerPhase.HOVER : DragonControllerPhase.HOLDING_PATTERN); ++ } else if (hadRider) { ++ hadRider = false; ++ noclip = true; ++ this.size = EntitySize.b(16.0F, 8.0F); ++ getDragonControllerManager().setControllerPhase(DragonControllerPhase.HOLDING_PATTERN); // HoldingPattern ++ } ++ // Purpur end ++ + float f; + float f1; + +@@ -164,6 +233,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { + + this.bp = this.bq; + if (this.dl()) { ++ if (hasRider) ejectPassengers(); // Purpur + f = (this.random.nextFloat() - 0.5F) * 8.0F; + f1 = (this.random.nextFloat() - 0.5F) * 4.0F; + float f2 = (this.random.nextFloat() - 0.5F) * 8.0F; +@@ -175,9 +245,9 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { + + f1 = 0.2F / (MathHelper.sqrt(c(vec3d)) * 10.0F + 1.0F); + f1 *= (float) Math.pow(2.0D, vec3d.y); +- if (this.bG.a().a()) { ++ if (!hasRider && this.bG.a().a()) { // Purpur + this.bq += 0.1F; +- } else if (this.br) { ++ } else if (!hasRider && this.br) { // Purpur + this.bq += f1 * 0.5F; + } else { + this.bq += f1; +@@ -221,7 +291,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { + } + + this.bG.a().b(); +- } else { ++ } else if (!hasRider) { // Purpur + IDragonController idragoncontroller = this.bG.a(); + + idragoncontroller.c(); +@@ -288,7 +358,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { + this.a(this.bz, (double) (f11 * 0.5F), 0.0D, (double) (-f12 * 0.5F)); + this.a(this.bD, (double) (f12 * 4.5F), 2.0D, (double) (f11 * 4.5F)); + this.a(this.bE, (double) (f12 * -4.5F), 2.0D, (double) (f11 * -4.5F)); +- if (!this.world.isClientSide && this.hurtTicks == 0) { ++ if (!hasRider && !this.world.isClientSide && this.hurtTicks == 0) { // Purpur + this.a(this.world.getEntities(this, this.bD.getBoundingBox().grow(4.0D, 2.0D, 4.0D).d(0.0D, -2.0D, 0.0D), IEntitySelector.e)); + this.a(this.world.getEntities(this, this.bE.getBoundingBox().grow(4.0D, 2.0D, 4.0D).d(0.0D, -2.0D, 0.0D), IEntitySelector.e)); + this.b(this.world.getEntities(this, this.bo.getBoundingBox().g(1.0D), IEntitySelector.e)); +@@ -331,7 +401,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { + } + + if (!this.world.isClientSide) { +- this.br = this.b(this.bo.getBoundingBox()) | this.b(this.by.getBoundingBox()) | this.b(this.bz.getBoundingBox()); ++ this.br = !hasRider && this.b(this.bo.getBoundingBox()) | this.b(this.by.getBoundingBox()) | this.b(this.bz.getBoundingBox()); // Purpur + if (this.bF != null) { + this.bF.b(this); + } +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java +index 930fc752ec0a988b17bc556cd428161638a14f27..4c0a555cdb5bc34c73040b9533beaee56cbce70a 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java +@@ -12,6 +12,7 @@ import net.minecraft.network.chat.IChatBaseComponent; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.BossBattleServer; + import net.minecraft.server.level.EntityPlayer; + import net.minecraft.sounds.SoundEffect; +@@ -20,6 +21,7 @@ import net.minecraft.tags.TagsBlock; + import net.minecraft.util.MathHelper; + import net.minecraft.world.BossBattle; + import net.minecraft.world.EnumDifficulty; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.effect.MobEffect; + import net.minecraft.world.effect.MobEffects; +@@ -28,6 +30,7 @@ import net.minecraft.world.entity.EntityInsentient; + import net.minecraft.world.entity.EntityLiving; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.EnumMonsterType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.ai.attributes.AttributeProvider; + import net.minecraft.world.entity.ai.attributes.GenericAttributes; + import net.minecraft.world.entity.ai.goal.PathfinderGoal; +@@ -48,8 +51,12 @@ import net.minecraft.world.item.Items; + import net.minecraft.world.level.Explosion; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.IMaterial; ++import net.minecraft.world.level.RayTrace; + import net.minecraft.world.level.World; + import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.phys.MovingObjectPosition; ++import net.minecraft.world.phys.MovingObjectPositionBlock; ++import net.minecraft.world.phys.MovingObjectPositionEntity; + import net.minecraft.world.phys.Vec3D; + + // CraftBukkit start +@@ -82,6 +89,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { + return entityliving.getMonsterType() != EnumMonsterType.UNDEAD && entityliving.ei(); + }; + private static final PathfinderTargetCondition bz = (new PathfinderTargetCondition()).a(20.0D).a(EntityWither.by); ++ private int shootCooldown = 0; // Purpur + // Paper start + private boolean canPortal = false; + +@@ -94,15 +102,122 @@ public class EntityWither extends EntityMonster implements IRangedEntity { + this.setHealth(this.getMaxHealth()); + this.getNavigation().d(true); + this.f = 50; ++ this.moveController = new net.pl3x.purpur.controller.ControllerMoveWASDFlyingWithSpacebar(this, 0.1F); // Purpur + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.witherRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.witherRidableInWater; ++ } ++ ++ @Override ++ public double getMaxY() { ++ return world.purpurConfig.witherMaxY; ++ } ++ ++ @Override ++ public void g(Vec3D vec3d) { ++ super.g(vec3d); ++ if (hasRider() && !onGround) { ++ float speed = (float) getAttributeInstance(GenericAttributes.FLYING_SPEED).getValue() * 5F; ++ setSpeed(speed); ++ Vec3D mot = getMot(); ++ move(EnumMoveType.SELF, mot.multiply(speed, 0.5, speed)); ++ setMot(mot.a(0.9D)); ++ } ++ } ++ ++ @Override ++ public void onMount(EntityHuman entityhuman) { ++ super.onMount(entityhuman); ++ this.datawatcher.set(bo.get(0), 0); ++ this.datawatcher.set(bo.get(1), 0); ++ this.datawatcher.set(bo.get(2), 0); ++ getNavigation().stopPathfinding(); ++ shootCooldown = 20; ++ } ++ ++ @Override ++ public boolean onClick(EnumHand hand) { ++ return shoot(getRider(), hand == EnumHand.MAIN_HAND ? new int[]{1} : new int[]{2}); ++ } ++ ++ public boolean shoot(EntityHuman rider, int[] heads) { ++ if (shootCooldown > 0) { ++ return false; ++ } ++ ++ shootCooldown = 20; ++ if (rider == null) { ++ return false; ++ } ++ ++ org.bukkit.craftbukkit.entity.CraftHumanEntity player = rider.getBukkitEntity(); ++ if (!player.hasPermission("allow.special.wither")) { ++ return false; ++ } ++ ++ MovingObjectPosition rayTrace = getRayTrace(120, RayTrace.FluidCollisionOption.NONE); ++ if (rayTrace == null) { ++ return false; ++ } ++ ++ Vec3D loc; ++ if (rayTrace.getType() == MovingObjectPosition.EnumMovingObjectType.BLOCK) { ++ BlockPosition pos = ((MovingObjectPositionBlock) rayTrace).getBlockPosition(); ++ loc = new Vec3D(pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D); ++ } else if (rayTrace.getType() == MovingObjectPosition.EnumMovingObjectType.ENTITY) { ++ Entity target = ((MovingObjectPositionEntity) rayTrace).getEntity(); ++ loc = new Vec3D(target.locX(), target.locY() + (target.getHeadHeight() / 2), target.locZ()); ++ } else { ++ org.bukkit.block.Block block = player.getTargetBlock(null, 120); ++ loc = new Vec3D(block.getX() + 0.5D, block.getY() + 0.5D, block.getZ() + 0.5D); ++ } ++ ++ for (int head : heads) { ++ shoot(head, loc.getX(), loc.getY(), loc.getZ(), rider); ++ } ++ ++ return true; // handled ++ } ++ ++ public void shoot(int head, double x, double y, double z, EntityHuman rider) { ++ world.playEvent(null, 1024, getChunkCoordinates(), 0); ++ double headX = getHeadX(head); ++ double headY = getHeadY(head); ++ double headZ = getHeadZ(head); ++ EntityWitherSkull skull = new EntityWitherSkull(world, this, x - headX, y - headY, z - headZ) { ++ @Override ++ public boolean canSaveToDisk() { ++ return false; ++ } ++ ++ @Override ++ public boolean hitPredicate(Entity target) { ++ // do not hit rider ++ return target != rider && super.hitPredicate(target); ++ } ++ }; ++ skull.setPositionRaw(headX, headY, headZ); ++ world.addEntity(skull); ++ } ++ // Purpur end ++ + @Override + protected void initPathfinder() { +- this.goalSelector.a(0, new EntityWither.a()); ++ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur ++ this.goalSelector.a(1, new EntityWither.a()); // Purpur + this.goalSelector.a(2, new PathfinderGoalArrowAttack(this, 1.0D, 40, 20.0F)); + this.goalSelector.a(5, new PathfinderGoalRandomStrollLand(this, 1.0D)); + this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); + this.goalSelector.a(7, new PathfinderGoalRandomLookaround(this)); ++ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, new Class[0])); + if(this.world.paperConfig.fixWitherTargetingBug) this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 0, false, false, null)); // Paper - Fix MC-29274 + this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityInsentient.class, 0, false, false, EntityWither.by)); +@@ -245,6 +360,16 @@ public class EntityWither extends EntityMonster implements IRangedEntity { + + @Override + protected void mobTick() { ++ // Purpur start ++ if (hasRider()) { ++ Vec3D mot = getMot(); ++ setMot(mot.x, mot.y + (getVertical() > 0 ? 0.07D : 0.0D), mot.z); ++ } ++ if (shootCooldown > 0) { ++ shootCooldown--; ++ } ++ // Purpur end ++ + int i; + + if (this.getInvul() > 0) { +@@ -428,7 +553,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { + this.bossBattle.removePlayer(entityplayer); + } + +- private double u(int i) { ++ private double u(int i) { return getHeadX(i); } private double getHeadX(int i) { // Purpur - OBFHELPER + if (i <= 0) { + return this.locX(); + } else { +@@ -439,11 +564,11 @@ public class EntityWither extends EntityMonster implements IRangedEntity { + } + } + +- private double v(int i) { ++ private double v(int i) { return getHeadY(i); } private double getHeadY(int i) { // Purpur - OBFHELPER + return i <= 0 ? this.locY() + 3.0D : this.locY() + 2.2D; + } + +- private double w(int i) { ++ private double w(int i) { return getHeadZ(i); } private double getHeadZ(int i) { // Purpur - OBFHELPER + if (i <= 0) { + return this.locZ(); + } else { +@@ -567,7 +692,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { + } + + public static AttributeProvider.Builder eK() { +- return EntityMonster.eR().a(GenericAttributes.MAX_HEALTH, 300.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.6000000238418579D).a(GenericAttributes.FOLLOW_RANGE, 40.0D).a(GenericAttributes.ARMOR, 4.0D); ++ return EntityMonster.eR().a(GenericAttributes.MAX_HEALTH, 300.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.6000000238418579D).a(GenericAttributes.FOLLOW_RANGE, 40.0D).a(GenericAttributes.ARMOR, 4.0D).a(GenericAttributes.FLYING_SPEED, 0.6D); // Purpur + } + + public int getInvul() { +@@ -579,11 +704,11 @@ public class EntityWither extends EntityMonster implements IRangedEntity { + } + + public int getHeadTarget(int i) { +- return (Integer) this.datawatcher.get((DataWatcherObject) EntityWither.bo.get(i)); ++ return hasRider() ? 0 : this.datawatcher.get(EntityWither.bo.get(i)); // Purpur + } + + public void setHeadTarget(int i, int j) { +- this.datawatcher.set((DataWatcherObject) EntityWither.bo.get(i), j); ++ if (!hasRider()) this.datawatcher.set(EntityWither.bo.get(i), j); // Purpur + } + + public final boolean isPowered() { return this.S_(); } // Paper - OBFHELPER +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java b/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java +index 88a4dcf9feaa5f66da1394c139b795582c00a8ac..9a109ed062e5abedaad295383aca6441321da276 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java +@@ -5,6 +5,7 @@ import net.minecraft.core.particles.Particles; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.util.MathHelper; +@@ -12,6 +13,7 @@ import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityLiving; + import net.minecraft.world.entity.EntityTypes; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.ai.attributes.AttributeProvider; + import net.minecraft.world.entity.ai.attributes.GenericAttributes; + import net.minecraft.world.entity.ai.goal.PathfinderGoal; +@@ -35,6 +37,7 @@ public class EntityBlaze extends EntityMonster { public EntityBlaze(EntityTypes entitytypes, World world) { super(entitytypes, world); @@ -536,7 +3326,7 @@ index 74082136b38491a0a50d152c455edfa61a6afb9f..dcfad16e06450068d5801fc002c96501 this.a(PathType.WATER, -1.0F); this.a(PathType.LAVA, 8.0F); this.a(PathType.DANGER_FIRE, 0.0F); -@@ -17,19 +18,50 @@ public class EntityBlaze extends EntityMonster { +@@ -42,19 +45,50 @@ public class EntityBlaze extends EntityMonster { this.f = 10; } @@ -589,7 +3379,7 @@ index 74082136b38491a0a50d152c455edfa61a6afb9f..dcfad16e06450068d5801fc002c96501 } @Override -@@ -84,6 +116,14 @@ public class EntityBlaze extends EntityMonster { +@@ -109,6 +143,14 @@ public class EntityBlaze extends EntityMonster { @Override protected void mobTick() { @@ -604,91 +3394,11 @@ index 74082136b38491a0a50d152c455edfa61a6afb9f..dcfad16e06450068d5801fc002c96501 --this.c; if (this.c <= 0) { this.c = 100; -diff --git a/src/main/java/net/minecraft/server/EntityCat.java b/src/main/java/net/minecraft/server/EntityCat.java -index 675083e3952779e43bf8cc3175ad70458a79e49c..0e6552d77adb95c94cb06b6f9289c4c12e6955bb 100644 ---- a/src/main/java/net/minecraft/server/EntityCat.java -+++ b/src/main/java/net/minecraft/server/EntityCat.java -@@ -41,6 +41,25 @@ public class EntityCat extends EntityTameableAnimal { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.catRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.catRidableInWater; -+ } -+ -+ public void onMount(EntityHuman entityhuman) { -+ super.onMount(entityhuman); -+ setSitting(false); -+ setSleepingWithOwner(false); -+ setHeadDown(false); -+ } -+ // Purpur end -+ - public MinecraftKey eU() { - return (MinecraftKey) EntityCat.bq.getOrDefault(this.getCatType(), EntityCat.bq.get(0)); - } -@@ -48,7 +67,8 @@ public class EntityCat extends EntityTameableAnimal { - @Override - protected void initPathfinder() { - this.bx = new EntityCat.PathfinderGoalTemptChance(this, 0.6D, EntityCat.br, true); -- this.goalSelector.a(1, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalFloat(this)); // Purpur -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new PathfinderGoalSit(this)); - this.goalSelector.a(2, new EntityCat.b(this)); - this.goalSelector.a(3, this.bx); -@@ -60,6 +80,7 @@ public class EntityCat extends EntityTameableAnimal { - this.goalSelector.a(10, new PathfinderGoalBreed(this, 0.8D)); - this.goalSelector.a(11, new PathfinderGoalRandomStrollLand(this, 0.8D, 1.0000001E-5F)); - this.goalSelector.a(12, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 10.0F)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new PathfinderGoalRandomTargetNonTamed<>(this, EntityRabbit.class, false, (Predicate) null)); - this.targetSelector.a(1, new PathfinderGoalRandomTargetNonTamed<>(this, EntityTurtle.class, false, EntityTurtle.bo)); - } -@@ -76,6 +97,7 @@ public class EntityCat extends EntityTameableAnimal { - this.datawatcher.set(EntityCat.bs, i); - } - -+ public void setSleepingWithOwner(boolean flag) { x(flag); } // Purpur - OBFHELPER - public void x(boolean flag) { - this.datawatcher.set(EntityCat.bt, flag); - } -@@ -84,6 +106,7 @@ public class EntityCat extends EntityTameableAnimal { - return (Boolean) this.datawatcher.get(EntityCat.bt); - } - -+ public void setHeadDown(boolean flag) { y(flag); } // Purpur - OBFHELPER - public void y(boolean flag) { - this.datawatcher.set(EntityCat.bu, flag); - } -@@ -302,6 +325,7 @@ public class EntityCat extends EntityTameableAnimal { - - @Override - public EnumInteractionResult b(EntityHuman entityhuman, EnumHand enumhand) { -+ if (hasRider()) return EnumInteractionResult.PASS; // Purpur - ItemStack itemstack = entityhuman.b(enumhand); - Item item = itemstack.getItem(); - -@@ -399,6 +423,7 @@ public class EntityCat extends EntityTameableAnimal { - - public b(EntityCat entitycat) { - this.a = entitycat; -+ this.a(java.util.EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - lay on owner - } - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityCaveSpider.java b/src/main/java/net/minecraft/server/EntityCaveSpider.java -index 776f3d25a6eeb5e97667dd06c062d1045d1afa81..2e1f2dec17e7761b6534f29bbec813d135250e4f 100644 ---- a/src/main/java/net/minecraft/server/EntityCaveSpider.java -+++ b/src/main/java/net/minecraft/server/EntityCaveSpider.java -@@ -8,6 +8,18 @@ public class EntityCaveSpider extends EntitySpider { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCaveSpider.java b/src/main/java/net/minecraft/world/entity/monster/EntityCaveSpider.java +index 65d0027186f19f10292ea64976ebb93c12b98394..27baf5cde99d8f25b1e7583c30339fcc71a3786f 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityCaveSpider.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityCaveSpider.java +@@ -24,6 +24,18 @@ public class EntityCaveSpider extends EntitySpider { super(entitytypes, world); } @@ -707,171 +3417,19 @@ index 776f3d25a6eeb5e97667dd06c062d1045d1afa81..2e1f2dec17e7761b6534f29bbec813d1 public static AttributeProvider.Builder m() { return EntitySpider.eK().a(GenericAttributes.MAX_HEALTH, 12.0D); } -diff --git a/src/main/java/net/minecraft/server/EntityChicken.java b/src/main/java/net/minecraft/server/EntityChicken.java -index 8fb5d5c75e79a81ab46af3fbb96ebc41804113c4..ee59a9f272a9caebec8f2329e1e4b22ddd27a0f9 100644 ---- a/src/main/java/net/minecraft/server/EntityChicken.java -+++ b/src/main/java/net/minecraft/server/EntityChicken.java -@@ -18,6 +18,16 @@ public class EntityChicken extends EntityAnimal { - } - - // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.chickenRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.chickenRidableInWater; -+ } -+ - @Override - protected void initAttributes() { - if (world.purpurConfig.chickenRetaliate) { -@@ -29,6 +39,7 @@ public class EntityChicken extends EntityAnimal { - @Override - protected void initPathfinder() { - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - //this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.4D)); // Purpur - moved down - this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D)); - this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.0D, false, EntityChicken.bv)); -@@ -39,6 +50,7 @@ public class EntityChicken extends EntityAnimal { - // Purpur start - if (world.purpurConfig.chickenRetaliate) { - this.goalSelector.a(1, new PathfinderGoalMeleeAttack(this, 1.0D, false)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this)); - } else { - this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.4D)); -diff --git a/src/main/java/net/minecraft/server/EntityCod.java b/src/main/java/net/minecraft/server/EntityCod.java -index 9a99af6e9cec9679af07ab6017f9beb427fa88ad..039fae4c29648afa85ea1b27d82cfe51c4165315 100644 ---- a/src/main/java/net/minecraft/server/EntityCod.java -+++ b/src/main/java/net/minecraft/server/EntityCod.java -@@ -6,6 +6,18 @@ public class EntityCod extends EntityFishSchool { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.codRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return true; -+ } -+ // Purpur end -+ - @Override - protected ItemStack eK() { - return new ItemStack(Items.COD_BUCKET); -diff --git a/src/main/java/net/minecraft/server/EntityComplexPart.java b/src/main/java/net/minecraft/server/EntityComplexPart.java -index c1b1bd123e7a18d37fd55cacc29ebca32030e5f0..26ff230ef774999bfe37b3327a7cf711799cbf2f 100644 ---- a/src/main/java/net/minecraft/server/EntityComplexPart.java -+++ b/src/main/java/net/minecraft/server/EntityComplexPart.java -@@ -47,4 +47,11 @@ public class EntityComplexPart extends Entity { - public EntitySize a(EntityPose entitypose) { - return this.d; - } -+ -+ // Purpur start -+ @Override -+ public EnumInteractionResult a(EntityHuman entityhuman, EnumHand enumhand) { -+ return owner.isAlive() ? owner.tryRide(entityhuman, enumhand) : EnumInteractionResult.PASS; -+ } -+ // Purpur end - } -diff --git a/src/main/java/net/minecraft/server/EntityCow.java b/src/main/java/net/minecraft/server/EntityCow.java -index cfb009c811bd2908d38da1b0007cb7aaed4e42c3..1219b0aa9c62bc9a1bda45cc9e9a27f14a28fe2e 100644 ---- a/src/main/java/net/minecraft/server/EntityCow.java -+++ b/src/main/java/net/minecraft/server/EntityCow.java -@@ -11,9 +11,22 @@ public class EntityCow extends EntityAnimal { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.cowRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.cowRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new PathfinderGoalPanic(this, 2.0D)); - this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D)); - if (world.purpurConfig.cowFeedMushrooms > 0) this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.25D, RecipeItemStack.a(Items.WHEAT, Blocks.RED_MUSHROOM.getItem(), Blocks.BROWN_MUSHROOM.getItem()), false)); else // Purpur -@@ -55,6 +68,7 @@ public class EntityCow extends EntityAnimal { - - @Override - public EnumInteractionResult b(EntityHuman entityhuman, EnumHand enumhand) { -+ if (hasRider()) return EnumInteractionResult.PASS; // Purpur - ItemStack itemstack = entityhuman.b(enumhand); - - if (itemstack.getItem() == Items.BUCKET && !this.isBaby()) { -@@ -62,7 +76,7 @@ public class EntityCow extends EntityAnimal { - org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) entityhuman.world, entityhuman, this.getChunkCoordinates(), this.getChunkCoordinates(), null, itemstack, Items.MILK_BUCKET, enumhand); // Paper - add enumHand - - if (event.isCancelled()) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); // Purpur - } - // CraftBukkit end - -@@ -73,7 +87,7 @@ public class EntityCow extends EntityAnimal { - return EnumInteractionResult.a(this.world.isClientSide); - // Purpur start - feed mushroom to change to mooshroom - } else if (world.purpurConfig.cowFeedMushrooms > 0 && getEntityType() != EntityTypes.MOOSHROOM && isMushroom(itemstack)) { -- return feedMushroom(entityhuman, itemstack); -+ return feedMushroom(entityhuman, enumhand, itemstack); - // Purpur end - } else { - return super.b(entityhuman, enumhand); -@@ -96,7 +110,7 @@ public class EntityCow extends EntityAnimal { - } - } - -- private EnumInteractionResult feedMushroom(EntityHuman entityhuman, ItemStack itemstack) { -+ private EnumInteractionResult feedMushroom(EntityHuman entityhuman, EnumHand enumhand, ItemStack itemstack) { - world.broadcastEntityEffect(this, (byte) 18); // hearts - playSound(SoundEffects.ENTITY_COW_MILK, 1.0F, 1.0F); - if (incrementFeedCount(itemstack) < world.purpurConfig.cowFeedMushrooms) { -@@ -107,7 +121,7 @@ public class EntityCow extends EntityAnimal { - } - EntityMushroomCow mooshroom = EntityTypes.MOOSHROOM.create(world); - if (mooshroom == null) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); - } - if (itemstack.getItem() == Blocks.BROWN_MUSHROOM.getItem()) { - mooshroom.setVariant(EntityMushroomCow.Type.BROWN); -@@ -126,10 +140,10 @@ public class EntityCow extends EntityAnimal { - mooshroom.setCustomName(this.getCustomName()); - } - if (CraftEventFactory.callEntityTransformEvent(this, mooshroom, org.bukkit.event.entity.EntityTransformEvent.TransformReason.INFECTION).isCancelled()) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); - } - if (!new com.destroystokyo.paper.event.entity.EntityTransformedEvent(this.getBukkitEntity(), mooshroom.getBukkitEntity(), com.destroystokyo.paper.event.entity.EntityTransformedEvent.TransformedReason.INFECTED).callEvent()) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); - } - this.world.addEntity(mooshroom); - this.die(); -diff --git a/src/main/java/net/minecraft/server/EntityCreeper.java b/src/main/java/net/minecraft/server/EntityCreeper.java -index 36bf307985624a3567eb1196e034470bd7002e1e..7e5ede0f644a6e303be36ab0915d346a02760daa 100644 ---- a/src/main/java/net/minecraft/server/EntityCreeper.java -+++ b/src/main/java/net/minecraft/server/EntityCreeper.java -@@ -19,12 +19,27 @@ public class EntityCreeper extends EntityMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java +index f1ff9a323eaa636b21e64860d2a83a2ba6c164ea..e29bba9143f027077c1051d61296df219cd45861 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java +@@ -6,6 +6,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -58,12 +59,27 @@ public class EntityCreeper extends EntityMonster { public int maxFuseTicks = 30; public int explosionRadius = 3; private int bs; @@ -899,7 +3457,7 @@ index 36bf307985624a3567eb1196e034470bd7002e1e..7e5ede0f644a6e303be36ab0915d346a @Override public GroupDataEntity prepare(WorldAccess worldaccess, DifficultyDamageScaler difficultydamagescaler, EnumMobSpawn enummobspawn, @javax.annotation.Nullable GroupDataEntity groupdataentity, @javax.annotation.Nullable NBTTagCompound nbttagcompound) { double chance = worldaccess.getMinecraftWorld().purpurConfig.creeperChargedChance; -@@ -33,18 +48,69 @@ public class EntityCreeper extends EntityMonster { +@@ -72,18 +88,69 @@ public class EntityCreeper extends EntityMonster { } return super.prepare(worldaccess, difficultydamagescaler, enummobspawn, groupdataentity, nbttagcompound); } @@ -969,7 +3527,7 @@ index 36bf307985624a3567eb1196e034470bd7002e1e..7e5ede0f644a6e303be36ab0915d346a this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); this.targetSelector.a(2, new PathfinderGoalHurtByTarget(this, new Class[0])); } -@@ -175,6 +241,7 @@ public class EntityCreeper extends EntityMonster { +@@ -214,6 +281,7 @@ public class EntityCreeper extends EntityMonster { return (Integer) this.datawatcher.get(EntityCreeper.b); } @@ -977,7 +3535,7 @@ index 36bf307985624a3567eb1196e034470bd7002e1e..7e5ede0f644a6e303be36ab0915d346a public void a(int i) { this.datawatcher.set(EntityCreeper.b, i); } -@@ -275,6 +342,7 @@ public class EntityCreeper extends EntityMonster { +@@ -314,6 +382,7 @@ public class EntityCreeper extends EntityMonster { com.destroystokyo.paper.event.entity.CreeperIgniteEvent event = new com.destroystokyo.paper.event.entity.CreeperIgniteEvent((org.bukkit.entity.Creeper) getBukkitEntity(), ignited); if (event.callEvent()) { this.datawatcher.set(EntityCreeper.d, event.isIgnited()); @@ -985,144 +3543,11 @@ index 36bf307985624a3567eb1196e034470bd7002e1e..7e5ede0f644a6e303be36ab0915d346a } } // Paper end -diff --git a/src/main/java/net/minecraft/server/EntityDolphin.java b/src/main/java/net/minecraft/server/EntityDolphin.java -index 664f9693368852bfb06a7a3bd0862a10cbc81747..9d5d143a997b74e0777bb79bf14d341ad5340db9 100644 ---- a/src/main/java/net/minecraft/server/EntityDolphin.java -+++ b/src/main/java/net/minecraft/server/EntityDolphin.java -@@ -17,6 +17,7 @@ public class EntityDolphin extends EntityWaterAnimal { - public static final Predicate b = (entityitem) -> { - return !entityitem.p() && entityitem.isAlive() && entityitem.isInWater(); - }; -+ private int spitCooldown; // Purpur - - public EntityDolphin(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -25,6 +26,45 @@ public class EntityDolphin extends EntityWaterAnimal { - this.setCanPickupLoot(true); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.dolphinRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return true; -+ } -+ -+ @Override -+ public boolean onSpacebar() { -+ if (spitCooldown == 0 && hasRider()) { -+ spitCooldown = world.purpurConfig.dolphinSpitCooldown; -+ if (!hasRider()) { -+ return false; -+ } -+ -+ org.bukkit.craftbukkit.entity.CraftPlayer player = (org.bukkit.craftbukkit.entity.CraftPlayer) getRider().getBukkitEntity(); -+ if (!player.hasPermission("allow.special.dolphin")) { -+ return false; -+ } -+ -+ org.bukkit.Location loc = player.getEyeLocation(); -+ loc.setPitch(loc.getPitch() - 10); -+ org.bukkit.util.Vector target = loc.getDirection().normalize().multiply(10).add(loc.toVector()); -+ -+ net.pl3x.purpur.entity.DolphinSpit spit = new net.pl3x.purpur.entity.DolphinSpit(world, this); -+ spit.shoot(target.getX() - locX(), target.getY() - locY(), target.getZ() - locZ(), world.purpurConfig.dolphinSpitSpeed, 5.0F); -+ -+ world.addEntity(spit); -+ playSound(SoundEffects.ENTITY_DOLPHIN_ATTACK, 1.0F, 1.0F + (random.nextFloat() - random.nextFloat()) * 0.2F); -+ return true; -+ } -+ return false; -+ } -+ // Purpur end -+ - @Nullable - @Override - public GroupDataEntity prepare(WorldAccess worldaccess, DifficultyDamageScaler difficultydamagescaler, EnumMobSpawn enummobspawn, @Nullable GroupDataEntity groupdataentity, @Nullable NBTTagCompound nbttagcompound) { -@@ -99,6 +139,7 @@ public class EntityDolphin extends EntityWaterAnimal { - protected void initPathfinder() { - this.goalSelector.a(0, new PathfinderGoalBreath(this)); - this.goalSelector.a(0, new PathfinderGoalWater(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new EntityDolphin.b(this)); - this.goalSelector.a(2, new EntityDolphin.c(this, 4.0D)); - this.goalSelector.a(4, new PathfinderGoalRandomSwim(this, 1.0D, 10)); -@@ -109,6 +150,7 @@ public class EntityDolphin extends EntityWaterAnimal { - this.goalSelector.a(8, new EntityDolphin.d()); - this.goalSelector.a(8, new PathfinderGoalFollowBoat(this)); - this.goalSelector.a(9, new PathfinderGoalAvoidTarget<>(this, EntityGuardian.class, 8.0F, 1.0D, 1.0D)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityGuardian.class})).a(new Class[0])); // CraftBukkit - decompile error - } - -@@ -160,7 +202,7 @@ public class EntityDolphin extends EntityWaterAnimal { - - @Override - protected boolean n(Entity entity) { -- return true; -+ return getRideCooldown() <= 0; // Purpur - make dolphin honor ride cooldown like all other non-boss mobs - } - - @Override -@@ -195,6 +237,9 @@ public class EntityDolphin extends EntityWaterAnimal { - @Override - public void tick() { - super.tick(); -+ if (spitCooldown > 0) { -+ spitCooldown--; -+ } - if (this.isNoAI()) { - this.setAirTicks(this.bH()); - } else { -@@ -468,7 +513,7 @@ public class EntityDolphin extends EntityWaterAnimal { - - private int b; - -- private d() {} -+ private d() { this.a(java.util.EnumSet.of(PathfinderGoal.Type.MOVE)); } // Purpur - play with item - - @Override - public boolean a() { -@@ -536,7 +581,7 @@ public class EntityDolphin extends EntityWaterAnimal { - } - } - -- static class a extends ControllerMove { -+ static class a extends net.pl3x.purpur.controller.ControllerMoveWASDWater { // Purpur - - private final EntityDolphin i; - -@@ -546,7 +591,20 @@ public class EntityDolphin extends EntityWaterAnimal { - } - - @Override -- public void a() { -+ // Purpur start -+ public void tick(EntityHuman rider) { -+ if (this.i.getAirTicks() < 150) { -+ // if drowning override player WASD controls to find air -+ tick(); -+ } else { -+ super.tick(rider); -+ this.i.setMot(this.i.getMot().add(0.0D, 0.005D, 0.0D)); -+ } -+ } -+ -+ @Override -+ public void tick() { -+ // Purpur end - if (this.i.isInWater()) { - this.i.setMot(this.i.getMot().add(0.0D, 0.005D, 0.0D)); - } -diff --git a/src/main/java/net/minecraft/server/EntityDrowned.java b/src/main/java/net/minecraft/server/EntityDrowned.java -index 1a102816921fa3b40f6d364bb826db4459f68eb2..125eab60f2b4657e52a71eddf7586c574945252e 100644 ---- a/src/main/java/net/minecraft/server/EntityDrowned.java -+++ b/src/main/java/net/minecraft/server/EntityDrowned.java -@@ -22,6 +22,16 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java b/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java +index ea776755767f29e49de2792afa30f79420d0fa4c..1d4039d61a2c77a38a31947010cee26f41c0becd 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java +@@ -73,6 +73,16 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { } // Purpur start @@ -1139,7 +3564,7 @@ index 1a102816921fa3b40f6d364bb826db4459f68eb2..125eab60f2b4657e52a71eddf7586c57 @Override public boolean jockeyOnlyBaby() { return world.purpurConfig.drownedJockeyOnlyBaby; -@@ -219,7 +229,7 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { +@@ -270,7 +280,7 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { this.d = flag; } @@ -1148,7 +3573,7 @@ index 1a102816921fa3b40f6d364bb826db4459f68eb2..125eab60f2b4657e52a71eddf7586c57 private final EntityDrowned i; -@@ -229,7 +239,7 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { +@@ -280,7 +290,7 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { } @Override @@ -1157,7 +3582,7 @@ index 1a102816921fa3b40f6d364bb826db4459f68eb2..125eab60f2b4657e52a71eddf7586c57 EntityLiving entityliving = this.i.getGoalTarget(); if (this.i.eW() && this.i.isInWater()) { -@@ -262,7 +272,7 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { +@@ -313,7 +323,7 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { this.i.setMot(this.i.getMot().add(0.0D, -0.008D, 0.0D)); } @@ -1166,7 +3591,7 @@ index 1a102816921fa3b40f6d364bb826db4459f68eb2..125eab60f2b4657e52a71eddf7586c57 } } -@@ -401,6 +411,7 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { +@@ -452,6 +462,7 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { this.a = entitydrowned; this.b = d0; this.c = i; @@ -1174,153 +3599,19 @@ index 1a102816921fa3b40f6d364bb826db4459f68eb2..125eab60f2b4657e52a71eddf7586c57 } @Override -diff --git a/src/main/java/net/minecraft/server/EntityEnderDragon.java b/src/main/java/net/minecraft/server/EntityEnderDragon.java -index de025a48c7ca08d8ae71d2d9239121dc4a86a339..81e63fe1b8252e2b5abcbf9051190cd0214b534c 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/server/EntityEnderDragon.java -@@ -46,6 +46,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - private final int[] bK = new int[24]; - private final Path bL = new Path(); - private Explosion explosionSource = new Explosion(null, this, null, null, Double.NaN, Double.NaN, Double.NaN, Float.NaN, true, Explosion.Effect.DESTROY); // CraftBukkit - reusable source for CraftTNTPrimed.getSource() -+ private boolean hadRider; // Purpur - - public EntityEnderDragon(EntityTypes entitytypes, World world) { - super(EntityTypes.ENDER_DRAGON, world); -@@ -60,8 +61,44 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - } - - this.bG = new DragonControllerManager(this); -+ // Purpur start -+ this.moveController = new net.pl3x.purpur.controller.ControllerMoveWASDFlying(this) { -+ @Override -+ public void tick() { -+ // dragon doesn't use the controller. do nothing -+ } -+ }; -+ this.lookController = new net.pl3x.purpur.controller.ControllerLookWASD(this) { -+ @Override -+ public void tick() { -+ // dragon doesn't use the controller. do nothing -+ } -+ -+ @Override -+ public void tick(EntityHuman rider) { -+ setYawPitch(rider.yaw - 180F, rider.pitch * 0.5F); -+ } -+ }; -+ // Purpur end -+ } -+ -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.enderDragonRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.enderDragonRidableInWater; - } - -+ @Override -+ public double getMaxY() { -+ return world.purpurConfig.enderDragonMaxY; -+ } -+ // Purpur end -+ - public static AttributeProvider.Builder m() { - return EntityInsentient.p().a(GenericAttributes.MAX_HEALTH, 200.0D); - } -@@ -94,6 +131,37 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - - @Override - public void movementTick() { -+ // Purpur start -+ boolean hasRider = getRider() != null; -+ if (hasRider) { -+ if (!hadRider) { -+ hadRider = true; -+ noclip = false; -+ this.size = EntitySize.b(4.0F, 2.0F); -+ } -+ -+ // dragon doesn't use controllers, so must tick manually -+ moveController.a(); -+ lookController.a(); -+ -+ moveRelative((float) getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getValue() * 0.1F, new Vec3D(-getStrafe(), getVertical(), -getForward())); -+ Vec3D mot = getMot(); -+ setMot(mot); -+ move(EnumMoveType.PLAYER, mot); -+ -+ mot = mot.multiply(0.9F, 0.9F, 0.9F); -+ setMot(mot); -+ -+ // control wing flap speed on client -+ getDragonControllerManager().setControllerPhase(mot.getX() * mot.getX() + mot.getZ() * mot.getZ() < 0.005F ? DragonControllerPhase.HOVER : DragonControllerPhase.HOLDING_PATTERN); -+ } else if (hadRider) { -+ hadRider = false; -+ noclip = true; -+ this.size = EntitySize.b(16.0F, 8.0F); -+ getDragonControllerManager().setControllerPhase(DragonControllerPhase.HOLDING_PATTERN); // HoldingPattern -+ } -+ // Purpur end -+ - float f; - float f1; - -@@ -115,6 +183,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - - this.bp = this.bq; - if (this.dl()) { -+ if (hasRider) ejectPassengers(); // Purpur - f = (this.random.nextFloat() - 0.5F) * 8.0F; - f1 = (this.random.nextFloat() - 0.5F) * 4.0F; - float f2 = (this.random.nextFloat() - 0.5F) * 8.0F; -@@ -126,9 +195,9 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - - f1 = 0.2F / (MathHelper.sqrt(c(vec3d)) * 10.0F + 1.0F); - f1 *= (float) Math.pow(2.0D, vec3d.y); -- if (this.bG.a().a()) { -+ if (!hasRider && this.bG.a().a()) { // Purpur - this.bq += 0.1F; -- } else if (this.br) { -+ } else if (!hasRider && this.br) { // Purpur - this.bq += f1 * 0.5F; - } else { - this.bq += f1; -@@ -172,7 +241,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - } - - this.bG.a().b(); -- } else { -+ } else if (!hasRider) { // Purpur - IDragonController idragoncontroller = this.bG.a(); - - idragoncontroller.c(); -@@ -239,7 +308,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - this.a(this.bz, (double) (f11 * 0.5F), 0.0D, (double) (-f12 * 0.5F)); - this.a(this.bD, (double) (f12 * 4.5F), 2.0D, (double) (f11 * 4.5F)); - this.a(this.bE, (double) (f12 * -4.5F), 2.0D, (double) (f11 * -4.5F)); -- if (!this.world.isClientSide && this.hurtTicks == 0) { -+ if (!hasRider && !this.world.isClientSide && this.hurtTicks == 0) { // Purpur - this.a(this.world.getEntities(this, this.bD.getBoundingBox().grow(4.0D, 2.0D, 4.0D).d(0.0D, -2.0D, 0.0D), IEntitySelector.e)); - this.a(this.world.getEntities(this, this.bE.getBoundingBox().grow(4.0D, 2.0D, 4.0D).d(0.0D, -2.0D, 0.0D), IEntitySelector.e)); - this.b(this.world.getEntities(this, this.bo.getBoundingBox().g(1.0D), IEntitySelector.e)); -@@ -282,7 +351,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - } - - if (!this.world.isClientSide) { -- this.br = this.b(this.bo.getBoundingBox()) | this.b(this.by.getBoundingBox()) | this.b(this.bz.getBoundingBox()); -+ this.br = !hasRider && this.b(this.bo.getBoundingBox()) | this.b(this.by.getBoundingBox()) | this.b(this.bz.getBoundingBox()); // Purpur - if (this.bF != null) { - this.bF.b(this); - } -diff --git a/src/main/java/net/minecraft/server/EntityEnderman.java b/src/main/java/net/minecraft/server/EntityEnderman.java -index 9728f5eb59d31535dd9cda6083172cb2ddd20a8e..a930cfe4ec08ee5414f03e420ad79ab110d84129 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderman.java -+++ b/src/main/java/net/minecraft/server/EntityEnderman.java -@@ -30,9 +30,22 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +index 52aa47036acee2ec21ae2d6f4df634ecbf04b3b0..03fa2cfc1d5bc27e03e9979b3f33d88362c19066 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +@@ -16,6 +16,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -85,9 +86,22 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { this.a(PathType.WATER, -1.0F); } @@ -1343,7 +3634,7 @@ index 9728f5eb59d31535dd9cda6083172cb2ddd20a8e..a930cfe4ec08ee5414f03e420ad79ab1 this.goalSelector.a(1, new EntityEnderman.a(this)); this.goalSelector.a(2, new PathfinderGoalMeleeAttack(this, 1.0D, false)); this.goalSelector.a(7, new PathfinderGoalRandomStrollLand(this, 1.0D, 0.0F)); -@@ -40,6 +53,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { +@@ -95,6 +109,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this)); this.goalSelector.a(10, new EntityEnderman.PathfinderGoalEndermanPlaceBlock(this)); this.goalSelector.a(11, new EntityEnderman.PathfinderGoalEndermanPickupBlock(this)); @@ -1351,7 +3642,7 @@ index 9728f5eb59d31535dd9cda6083172cb2ddd20a8e..a930cfe4ec08ee5414f03e420ad79ab1 this.targetSelector.a(1, new EntityEnderman.PathfinderGoalPlayerWhoLookedAtTarget(this, this::a_)); this.targetSelector.a(2, new PathfinderGoalHurtByTarget(this, new Class[0])); this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityEndermite.class, 10, true, false, EntityEnderman.bq)); -@@ -220,7 +234,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { +@@ -275,7 +290,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { @Override protected void mobTick() { @@ -1360,7 +3651,7 @@ index 9728f5eb59d31535dd9cda6083172cb2ddd20a8e..a930cfe4ec08ee5414f03e420ad79ab1 float f = this.aR(); if (f > 0.5F && this.world.e(this.getChunkCoordinates()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.tryEscape(EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper -@@ -329,6 +343,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { +@@ -384,6 +399,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { if (this.isInvulnerable(damagesource)) { return false; } else if (net.pl3x.purpur.PurpurConfig.endermanShortHeight && damagesource == DamageSource.STUCK) { return false; // Purpur - no suffocation damage if short height @@ -1368,7 +3659,7 @@ index 9728f5eb59d31535dd9cda6083172cb2ddd20a8e..a930cfe4ec08ee5414f03e420ad79ab1 } else if (damagesource instanceof EntityDamageSourceIndirect) { if (this.tryEscape(EndermanEscapeEvent.Reason.INDIRECT)) { // Paper start for (int i = 0; i < 64; ++i) { -@@ -373,6 +388,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { +@@ -428,6 +444,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { public PathfinderGoalEndermanPickupBlock(EntityEnderman entityenderman) { this.enderman = entityenderman; @@ -1376,7 +3667,7 @@ index 9728f5eb59d31535dd9cda6083172cb2ddd20a8e..a930cfe4ec08ee5414f03e420ad79ab1 } @Override -@@ -415,6 +431,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { +@@ -470,6 +487,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { public PathfinderGoalEndermanPlaceBlock(EntityEnderman entityenderman) { this.a = entityenderman; @@ -1384,11 +3675,19 @@ index 9728f5eb59d31535dd9cda6083172cb2ddd20a8e..a930cfe4ec08ee5414f03e420ad79ab1 } @Override -diff --git a/src/main/java/net/minecraft/server/EntityEndermite.java b/src/main/java/net/minecraft/server/EntityEndermite.java -index fcebf36312c95df876652d18cf27bf1cc6589226..7eef7f523a17434b38492006526920a955fc9120 100644 ---- a/src/main/java/net/minecraft/server/EntityEndermite.java -+++ b/src/main/java/net/minecraft/server/EntityEndermite.java -@@ -12,14 +12,28 @@ public class EntityEndermite extends EntityMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEndermite.java b/src/main/java/net/minecraft/world/entity/monster/EntityEndermite.java +index 906ac1f861241a184819b4b113abe56625ff5e60..1c87bea9de812e57f8ccd3c9aa85330af87ed240 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityEndermite.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityEndermite.java +@@ -4,6 +4,7 @@ import java.util.Random; + import net.minecraft.core.BlockPosition; + import net.minecraft.core.particles.Particles; + import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.world.damagesource.DamageSource; +@@ -36,14 +37,28 @@ public class EntityEndermite extends EntityMonster { this.f = 3; } @@ -1418,11 +3717,27 @@ index fcebf36312c95df876652d18cf27bf1cc6589226..7eef7f523a17434b38492006526920a9 this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); } -diff --git a/src/main/java/net/minecraft/server/EntityEvoker.java b/src/main/java/net/minecraft/server/EntityEvoker.java -index f40fbef32f2fc1f37f2065ad598f013766cf12f2..c75dc75611991028e9de6db7c57304e913251a6b 100644 ---- a/src/main/java/net/minecraft/server/EntityEvoker.java -+++ b/src/main/java/net/minecraft/server/EntityEvoker.java -@@ -12,10 +12,23 @@ public class EntityEvoker extends EntityIllagerWizard { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java b/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java +index 2aa6b6ca93c25c59ad224348aad1bb34d9bbc6a3..55607910183155080e3d96296421438d17f19c8f 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java +@@ -5,6 +5,7 @@ import javax.annotation.Nullable; + import net.minecraft.core.BlockPosition; + import net.minecraft.core.EnumDirection; + import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -19,6 +20,7 @@ import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.ai.attributes.AttributeProvider; + import net.minecraft.world.entity.ai.attributes.GenericAttributes; ++import net.minecraft.world.entity.ai.goal.PathfinderGoal; + import net.minecraft.world.entity.ai.goal.PathfinderGoalAvoidTarget; + import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat; + import net.minecraft.world.entity.ai.goal.PathfinderGoalLookAtPlayer; +@@ -47,10 +49,23 @@ public class EntityEvoker extends EntityIllagerWizard { this.f = 10; } @@ -1446,7 +3761,7 @@ index f40fbef32f2fc1f37f2065ad598f013766cf12f2..c75dc75611991028e9de6db7c57304e9 this.goalSelector.a(1, new EntityEvoker.b()); this.goalSelector.a(2, new PathfinderGoalAvoidTarget<>(this, EntityHuman.class, 8.0F, 0.6D, 1.0D)); this.goalSelector.a(4, new EntityEvoker.c()); -@@ -24,6 +37,7 @@ public class EntityEvoker extends EntityIllagerWizard { +@@ -59,6 +74,7 @@ public class EntityEvoker extends EntityIllagerWizard { this.goalSelector.a(8, new PathfinderGoalRandomStroll(this, 0.6D)); this.goalSelector.a(9, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 3.0F, 1.0F)); this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 8.0F)); @@ -1454,7 +3769,7 @@ index f40fbef32f2fc1f37f2065ad598f013766cf12f2..c75dc75611991028e9de6db7c57304e9 this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // Paper - decompile fix this.targetSelector.a(2, (new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)).a(300)); this.targetSelector.a(3, (new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)).a(300)); -@@ -104,6 +118,7 @@ public class EntityEvoker extends EntityIllagerWizard { +@@ -139,6 +155,7 @@ public class EntityEvoker extends EntityIllagerWizard { public d() { super(); @@ -1462,7 +3777,7 @@ index f40fbef32f2fc1f37f2065ad598f013766cf12f2..c75dc75611991028e9de6db7c57304e9 } @Override -@@ -182,6 +197,7 @@ public class EntityEvoker extends EntityIllagerWizard { +@@ -217,6 +234,7 @@ public class EntityEvoker extends EntityIllagerWizard { private c() { super(); this.e = (new PathfinderTargetCondition()).a(16.0D).c().e().a().b(); @@ -1470,7 +3785,7 @@ index f40fbef32f2fc1f37f2065ad598f013766cf12f2..c75dc75611991028e9de6db7c57304e9 } @Override -@@ -238,6 +254,7 @@ public class EntityEvoker extends EntityIllagerWizard { +@@ -273,6 +291,7 @@ public class EntityEvoker extends EntityIllagerWizard { private a() { super(); @@ -1478,210 +3793,27 @@ index f40fbef32f2fc1f37f2065ad598f013766cf12f2..c75dc75611991028e9de6db7c57304e9 } @Override -diff --git a/src/main/java/net/minecraft/server/EntityFish.java b/src/main/java/net/minecraft/server/EntityFish.java -index 9b84564401e30a7a2aafae023a1eb3b2eda3f112..668f9d61b72cf0d8e7bb0d1cd985ae653a587466 100644 ---- a/src/main/java/net/minecraft/server/EntityFish.java -+++ b/src/main/java/net/minecraft/server/EntityFish.java -@@ -70,13 +70,12 @@ public abstract class EntityFish extends EntityWaterAnimal { - @Override - protected void initPathfinder() { - super.initPathfinder(); -- this.goalSelector.a(0, new PathfinderGoalPanic(this, 1.25D)); -- PathfinderGoalSelector pathfindergoalselector = this.goalSelector; -- Predicate predicate = IEntitySelector.g; -- -- predicate.getClass(); -- pathfindergoalselector.a(2, new PathfinderGoalAvoidTarget<>(this, EntityHuman.class, 8.0F, 1.6D, 1.4D, predicate::test)); -- this.goalSelector.a(4, new EntityFish.b(this)); -+ // Purpur start -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur -+ this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.25D)); -+ this.goalSelector.a(3, new PathfinderGoalAvoidTarget<>(this, EntityHuman.class, 8.0F, 1.6D, 1.4D, IEntitySelector.g::test)); // Purpur - decompile error -+ this.goalSelector.a(5, new EntityFish.b(this)); -+ // Purpur end - } - - @Override -@@ -87,7 +86,7 @@ public abstract class EntityFish extends EntityWaterAnimal { - @Override - public void g(Vec3D vec3d) { - if (this.doAITick() && this.isInWater()) { -- this.a(0.01F, vec3d); -+ this.a(hasRider() ? getSpeed() : 0.01F, vec3d); // Purpur - this.move(EnumMoveType.SELF, this.getMot()); - this.setMot(this.getMot().a(0.9D)); - if (this.getGoalTarget() == null) { -@@ -161,9 +160,9 @@ public abstract class EntityFish extends EntityWaterAnimal { - @Override - protected void b(BlockPosition blockposition, IBlockData iblockdata) {} - -- static class a extends ControllerMove { -+ static class a extends net.pl3x.purpur.controller.ControllerMoveWASDWater { // Purpur - -- private final EntityFish i; -+ private final EntityFish i; public EntityFish getFish() { return i; } // Purpur - OBFHELPER - - a(EntityFish entityfish) { - super(entityfish); -@@ -171,7 +170,15 @@ public abstract class EntityFish extends EntityWaterAnimal { - } - - @Override -- public void a() { -+ // Purpur start -+ public void tick(EntityHuman rider) { -+ super.tick(rider); -+ getFish().setMot(getFish().getMot().add(0.0D, 0.005D, 0.0D)); -+ } -+ -+ @Override -+ public void tick() { -+ // Purpur end - if (this.i.a((Tag) TagsFluid.WATER)) { - this.i.setMot(this.i.getMot().add(0.0D, 0.005D, 0.0D)); - } -diff --git a/src/main/java/net/minecraft/server/EntityFishSchool.java b/src/main/java/net/minecraft/server/EntityFishSchool.java -index 08372b72262f2ef6e6c95f34e889e04faf731329..6a8e15f01606024aba43d57d270e09db307a9c3f 100644 ---- a/src/main/java/net/minecraft/server/EntityFishSchool.java -+++ b/src/main/java/net/minecraft/server/EntityFishSchool.java -@@ -16,7 +16,7 @@ public abstract class EntityFishSchool extends EntityFish { - @Override - protected void initPathfinder() { - super.initPathfinder(); -- this.goalSelector.a(5, new PathfinderGoalFishSchool(this)); -+ this.goalSelector.a(6, new PathfinderGoalFishSchool(this)); // Purpur - } - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityFox.java b/src/main/java/net/minecraft/server/EntityFox.java -index 8845afd83d47902d5192ec1a9146b6f20c5667d3..f5defe4713c6be7d32fb2116110516717460284e 100644 ---- a/src/main/java/net/minecraft/server/EntityFox.java -+++ b/src/main/java/net/minecraft/server/EntityFox.java -@@ -55,6 +55,39 @@ public class EntityFox extends EntityAnimal { - this.setCanPickupLoot(true); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.foxRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.foxRidableInWater; -+ } -+ -+ @Override -+ public float getJumpHeight() { -+ return !hasRider() ? super.getJumpHeight() : 0.5F; -+ } -+ -+ @Override -+ public void onMount(EntityHuman entityhuman) { -+ super.onMount(entityhuman); -+ setCanPickupLoot(false); -+ stopActions(); -+ setChasing(false); -+ spit(getEquipment(EnumItemSlot.MAINHAND)); -+ setSlot(EnumItemSlot.MAINHAND, ItemStack.NULL_ITEM); -+ } -+ -+ @Override -+ public void onDismount(EntityHuman entityhuman) { -+ super.onDismount(entityhuman); -+ setCanPickupLoot(true); -+ } -+ // Purpur end -+ - @Override - protected void initDatawatcher() { - super.initDatawatcher(); -@@ -74,6 +107,7 @@ public class EntityFox extends EntityAnimal { - return entityliving instanceof EntityFishSchool; - }); - this.goalSelector.a(0, new EntityFox.g()); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new EntityFox.b()); - this.goalSelector.a(2, new EntityFox.n(2.2D)); - this.goalSelector.a(3, new EntityFox.e(1.0D)); -@@ -99,6 +133,7 @@ public class EntityFox extends EntityAnimal { - this.goalSelector.a(11, new EntityFox.p()); - this.goalSelector.a(12, new EntityFox.j(this, EntityHuman.class, 24.0F)); - this.goalSelector.a(13, new EntityFox.r()); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(3, new EntityFox.a(EntityLiving.class, false, false, (entityliving) -> { - return EntityFox.bt.test(entityliving) && !this.c(entityliving.getUniqueID()); - })); -@@ -386,6 +421,7 @@ public class EntityFox extends EntityAnimal { - return itemstack1.isEmpty() || this.bD > 0 && item.isFood() && !itemstack1.getItem().isFood(); - } - -+ public void spit(ItemStack itemstack) { m(itemstack); } // Purpur - OBFHELPER - private void m(ItemStack itemstack) { - if (!itemstack.isEmpty() && !this.world.isClientSide) { - EntityItem entityitem = new EntityItem(this.world, this.locX() + this.getLookDirection().x, this.locY() + 1.0D, this.locZ() + this.getLookDirection().z, itemstack); -@@ -481,6 +517,7 @@ public class EntityFox extends EntityAnimal { - return this.t(16); - } - -+ public void setChasing(boolean flag) { u(flag); } // Purpur - OBFHELPER - public void u(boolean flag) { - this.d(16, flag); - } -@@ -523,6 +560,7 @@ public class EntityFox extends EntityAnimal { - this.setSleeping(false); - } - -+ public void stopActions() { fd(); } // Purpur - OBFHELPER - private void fd() { - this.w(false); - this.setCrouching(false); -@@ -688,16 +726,16 @@ public class EntityFox extends EntityAnimal { - } - } - -- public class k extends ControllerLook { -+ public class k extends net.pl3x.purpur.controller.ControllerLookWASD { // Purpur - - public k() { - super(EntityFox.this); - } - - @Override -- public void a() { -+ public void tick() { // Purpur - if (!EntityFox.this.isSleeping()) { -- super.a(); -+ super.tick(); // Purpur - } - - } -@@ -1367,16 +1405,16 @@ public class EntityFox extends EntityAnimal { - } - } - -- class m extends ControllerMove { -+ class m extends net.pl3x.purpur.controller.ControllerMoveWASD { // Purpur - - public m() { - super(EntityFox.this); - } - - @Override -- public void a() { -+ public void tick() { // Purpur - if (EntityFox.this.fe()) { -- super.a(); -+ super.tick(); // Purpur - } - - } -diff --git a/src/main/java/net/minecraft/server/EntityGhast.java b/src/main/java/net/minecraft/server/EntityGhast.java -index a67611c4f9271c116a795ee598412f25396fee88..216506a7b1f97b776ecd4e24f5b2afaf5b79ec2d 100644 ---- a/src/main/java/net/minecraft/server/EntityGhast.java -+++ b/src/main/java/net/minecraft/server/EntityGhast.java -@@ -14,11 +14,42 @@ public class EntityGhast extends EntityFlying implements IMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java b/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java +index a3e3f6e07674c54c2d2a02661ce4342b43aafe44..8784647f512d280ee0a092ecd406321268359314 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java +@@ -7,6 +7,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.sounds.SoundCategory; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -21,6 +22,7 @@ import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySize; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.ai.attributes.AttributeProvider; + import net.minecraft.world.entity.ai.attributes.GenericAttributes; + import net.minecraft.world.entity.ai.control.ControllerMove; +@@ -44,11 +46,42 @@ public class EntityGhast extends EntityFlying implements IMonster { this.moveController = new EntityGhast.ControllerGhast(this); } @@ -1724,7 +3856,7 @@ index a67611c4f9271c116a795ee598412f25396fee88..216506a7b1f97b776ecd4e24f5b2afaf this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, (entityliving) -> { return Math.abs(entityliving.locY() - this.locY()) <= 4.0D; })); -@@ -56,7 +87,7 @@ public class EntityGhast extends EntityFlying implements IMonster { +@@ -86,7 +119,7 @@ public class EntityGhast extends EntityFlying implements IMonster { } public static AttributeProvider.Builder eJ() { @@ -1733,7 +3865,7 @@ index a67611c4f9271c116a795ee598412f25396fee88..216506a7b1f97b776ecd4e24f5b2afaf } @Override -@@ -255,7 +286,7 @@ public class EntityGhast extends EntityFlying implements IMonster { +@@ -285,7 +318,7 @@ public class EntityGhast extends EntityFlying implements IMonster { } } @@ -1742,7 +3874,7 @@ index a67611c4f9271c116a795ee598412f25396fee88..216506a7b1f97b776ecd4e24f5b2afaf private final EntityGhast i; private int j; -@@ -266,7 +297,7 @@ public class EntityGhast extends EntityFlying implements IMonster { +@@ -296,7 +329,7 @@ public class EntityGhast extends EntityFlying implements IMonster { } @Override @@ -1751,11 +3883,19 @@ index a67611c4f9271c116a795ee598412f25396fee88..216506a7b1f97b776ecd4e24f5b2afaf if (this.h == ControllerMove.Operation.MOVE_TO) { if (this.j-- <= 0) { this.j += this.i.getRandom().nextInt(5) + 2; -diff --git a/src/main/java/net/minecraft/server/EntityGiantZombie.java b/src/main/java/net/minecraft/server/EntityGiantZombie.java -index 565c938d879940d8e12fe320ea8524d2cf679c1f..5e99767f45f7ba7db80f5b51810689e059b5cef5 100644 ---- a/src/main/java/net/minecraft/server/EntityGiantZombie.java -+++ b/src/main/java/net/minecraft/server/EntityGiantZombie.java -@@ -11,16 +11,28 @@ public class EntityGiantZombie extends EntityMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGiantZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityGiantZombie.java +index a188a89143cb1b0243dacdec33c446ca4120219f..7395fa90198a9138b2c33273d8f3540355300029 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityGiantZombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityGiantZombie.java +@@ -2,6 +2,7 @@ package net.minecraft.world.entity.monster; + + import net.minecraft.core.BlockPosition; + import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.world.DifficultyDamageScaler; + import net.minecraft.world.EnumDifficulty; + import net.minecraft.world.entity.EntityPose; +@@ -41,16 +42,28 @@ public class EntityGiantZombie extends EntityMonster { } // Purpur start @@ -1784,11 +3924,19 @@ index 565c938d879940d8e12fe320ea8524d2cf679c1f..5e99767f45f7ba7db80f5b51810689e0 this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this).a(EntityPigZombie.class)); this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillager.class, false)); -diff --git a/src/main/java/net/minecraft/server/EntityGuardian.java b/src/main/java/net/minecraft/server/EntityGuardian.java -index 27ec46c0b2e7df985ed4c68a973db18f81caac89..0a7f51a2a1cb10438c9364faf3e4adc6322fc787 100644 ---- a/src/main/java/net/minecraft/server/EntityGuardian.java -+++ b/src/main/java/net/minecraft/server/EntityGuardian.java -@@ -24,15 +24,36 @@ public class EntityGuardian extends EntityMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGuardian.java b/src/main/java/net/minecraft/world/entity/monster/EntityGuardian.java +index d53e2a9d27f9976d1fd8ea30b88a0da089aec7b6..6980b6988549b37a33d204a6e84c9e81d384a57a 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityGuardian.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityGuardian.java +@@ -9,6 +9,7 @@ import net.minecraft.core.particles.Particles; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.tags.Tag; +@@ -63,15 +64,36 @@ public class EntityGuardian extends EntityMonster { this.f = 10; this.a(PathType.WATER, 0.0F); this.moveController = new EntityGuardian.ControllerMoveGuardian(this); @@ -1825,7 +3973,7 @@ index 27ec46c0b2e7df985ed4c68a973db18f81caac89..0a7f51a2a1cb10438c9364faf3e4adc6 this.goalSelector.a(4, new EntityGuardian.PathfinderGoalGuardianAttack(this)); this.goalSelector.a(5, pathfindergoalmovetowardsrestriction); this.goalSelector.a(7, this.goalRandomStroll); -@@ -41,6 +62,7 @@ public class EntityGuardian extends EntityMonster { +@@ -80,6 +102,7 @@ public class EntityGuardian extends EntityMonster { this.goalSelector.a(9, new PathfinderGoalRandomLookaround(this)); this.goalRandomStroll.a(EnumSet.of(PathfinderGoal.Type.MOVE, PathfinderGoal.Type.LOOK)); pathfindergoalmovetowardsrestriction.a(EnumSet.of(PathfinderGoal.Type.MOVE, PathfinderGoal.Type.LOOK)); @@ -1833,7 +3981,7 @@ index 27ec46c0b2e7df985ed4c68a973db18f81caac89..0a7f51a2a1cb10438c9364faf3e4adc6 this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityLiving.class, 10, true, false, new EntityGuardian.EntitySelectorGuardianTargetHumanSquid(this))); } -@@ -74,6 +96,7 @@ public class EntityGuardian extends EntityMonster { +@@ -113,6 +136,7 @@ public class EntityGuardian extends EntityMonster { return (Boolean) this.datawatcher.get(EntityGuardian.b); } @@ -1841,7 +3989,7 @@ index 27ec46c0b2e7df985ed4c68a973db18f81caac89..0a7f51a2a1cb10438c9364faf3e4adc6 private void t(boolean flag) { this.datawatcher.set(EntityGuardian.b, flag); } -@@ -288,7 +311,7 @@ public class EntityGuardian extends EntityMonster { +@@ -327,7 +351,7 @@ public class EntityGuardian extends EntityMonster { @Override public void g(Vec3D vec3d) { if (this.doAITick() && this.isInWater()) { @@ -1850,7 +3998,7 @@ index 27ec46c0b2e7df985ed4c68a973db18f81caac89..0a7f51a2a1cb10438c9364faf3e4adc6 this.move(EnumMoveType.SELF, this.getMot()); this.setMot(this.getMot().a(0.9D)); if (!this.eN() && this.getGoalTarget() == null) { -@@ -300,17 +323,26 @@ public class EntityGuardian extends EntityMonster { +@@ -339,17 +363,26 @@ public class EntityGuardian extends EntityMonster { } @@ -1880,11 +4028,11 @@ index 27ec46c0b2e7df985ed4c68a973db18f81caac89..0a7f51a2a1cb10438c9364faf3e4adc6 if (this.h == ControllerMove.Operation.MOVE_TO && !this.i.getNavigation().m()) { Vec3D vec3d = new Vec3D(this.b - this.i.locX(), this.c - this.i.locY(), this.d - this.i.locZ()); double d0 = vec3d.f(); -diff --git a/src/main/java/net/minecraft/server/EntityGuardianElder.java b/src/main/java/net/minecraft/server/EntityGuardianElder.java -index b691e844953bcc2853a806a3bbf9cb7338e98266..f6f882746940c9e049106aa9b41591ba27a608ce 100644 ---- a/src/main/java/net/minecraft/server/EntityGuardianElder.java -+++ b/src/main/java/net/minecraft/server/EntityGuardianElder.java -@@ -16,6 +16,18 @@ public class EntityGuardianElder extends EntityGuardian { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java b/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java +index 9bd6f5d988c1e50e1bb729c407178b9cbcc62115..16b8606be2835dccdfa75f29827be4b88aaa1810 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java +@@ -30,6 +30,18 @@ public class EntityGuardianElder extends EntityGuardian { } @@ -1903,226 +4051,19 @@ index b691e844953bcc2853a806a3bbf9cb7338e98266..f6f882746940c9e049106aa9b41591ba public static AttributeProvider.Builder m() { return EntityGuardian.eM().a(GenericAttributes.MOVEMENT_SPEED, 0.30000001192092896D).a(GenericAttributes.ATTACK_DAMAGE, 8.0D).a(GenericAttributes.MAX_HEALTH, 80.0D); } -diff --git a/src/main/java/net/minecraft/server/EntityHoglin.java b/src/main/java/net/minecraft/server/EntityHoglin.java -index 7bd22c81d75368697113915a97c7fbe55ed2a268..f98ac9edf3ba3f3bee2e626a76a5e0e4013514ad 100644 ---- a/src/main/java/net/minecraft/server/EntityHoglin.java -+++ b/src/main/java/net/minecraft/server/EntityHoglin.java -@@ -20,6 +20,18 @@ public class EntityHoglin extends EntityAnimal implements IMonster, IOglin { - this.f = 5; - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.hoglinRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.hoglinRidableInWater; -+ } -+ // Purpur end -+ - @Override - public boolean a(EntityHuman entityhuman) { - return !this.isLeashed(); -@@ -86,6 +98,7 @@ public class EntityHoglin extends EntityAnimal implements IMonster, IOglin { - // Airplane - dynamic tick - if (!gg.airplane.AirplaneConfig.dynamicHoglinBehavior || this.behaviorTick++ % this.activatedPriority == 0) { - this.world.getMethodProfiler().enter("hoglinBrain"); -+ if (getRider() == null) // Purpur - only use brain if no rider - this.getBehaviorController().a((WorldServer) this.world, (EntityHoglin) this); // Airplane - decompile error - this.world.getMethodProfiler().exit(); - HoglinAI.a(this); -diff --git a/src/main/java/net/minecraft/server/EntityHorse.java b/src/main/java/net/minecraft/server/EntityHorse.java -index f958751b16abcc36910bb0b655ff2360459e2e4c..4ffc61acdff8c51dc9b111e3024c828fb5386118 100644 ---- a/src/main/java/net/minecraft/server/EntityHorse.java -+++ b/src/main/java/net/minecraft/server/EntityHorse.java -@@ -12,6 +12,13 @@ public class EntityHorse extends EntityHorseAbstract { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.horseRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void eK() { - this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue((double) this.fp()); -diff --git a/src/main/java/net/minecraft/server/EntityHorseAbstract.java b/src/main/java/net/minecraft/server/EntityHorseAbstract.java -index 784819d252d94e8040a87f53431fcf2c7a19d1a7..8fde406273bbea0b9d2dea2362cf6372b7a5c9ae 100644 ---- a/src/main/java/net/minecraft/server/EntityHorseAbstract.java -+++ b/src/main/java/net/minecraft/server/EntityHorseAbstract.java -@@ -40,12 +40,27 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven - - protected EntityHorseAbstract(EntityTypes entitytypes, World world) { - super(entitytypes, world); -+ this.moveController = new ControllerMove(this); // Purpur - use vanilla controller -+ this.lookController = new ControllerLook(this); // Purpur - use vanilla controller - this.G = 1.0F; - this.loadChest(); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return false; // vanilla handles -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return false; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { -+ this.goalSelector.a(0, new PathfinderGoalHorseHasRider(this)); // Purpur - this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.2D)); - this.goalSelector.a(1, new PathfinderGoalTame(this, 1.2D)); - this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D, EntityHorseAbstract.class)); -@@ -53,6 +68,7 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven - this.goalSelector.a(6, new PathfinderGoalRandomStrollLand(this, 0.7D)); - this.goalSelector.a(7, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F)); - this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this)); -+ this.targetSelector.a(0, new PathfinderGoalHorseHasRider(this)); // Purpur - this.eV(); - } - -diff --git a/src/main/java/net/minecraft/server/EntityHorseDonkey.java b/src/main/java/net/minecraft/server/EntityHorseDonkey.java -index 767d18d5a0417813c514d0341b318d6321f6f7a5..cb8aee5691ff4ecaa6ae60f1637b1852d3b6c162 100644 ---- a/src/main/java/net/minecraft/server/EntityHorseDonkey.java -+++ b/src/main/java/net/minecraft/server/EntityHorseDonkey.java -@@ -8,6 +8,13 @@ public class EntityHorseDonkey extends EntityHorseChestedAbstract { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.donkeyRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected SoundEffect getSoundAmbient() { - super.getSoundAmbient(); -diff --git a/src/main/java/net/minecraft/server/EntityHorseMule.java b/src/main/java/net/minecraft/server/EntityHorseMule.java -index 3dd4d4f0f35e2b12686e1a257250934e5678e397..243aeb736e350418e9476819bbfec0e7ab59f92f 100644 ---- a/src/main/java/net/minecraft/server/EntityHorseMule.java -+++ b/src/main/java/net/minecraft/server/EntityHorseMule.java -@@ -8,6 +8,12 @@ public class EntityHorseMule extends EntityHorseChestedAbstract { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.muleRidableInWater; -+ } -+ // Purpur end - @Override - protected SoundEffect getSoundAmbient() { - super.getSoundAmbient(); -diff --git a/src/main/java/net/minecraft/server/EntityHorseSkeleton.java b/src/main/java/net/minecraft/server/EntityHorseSkeleton.java -index a53d335f3af9df80bec3f94f81fb5ff0e0e5ebb5..e2c6a5807a4554a7eebb148e40f1f8a1d979df5e 100644 ---- a/src/main/java/net/minecraft/server/EntityHorseSkeleton.java -+++ b/src/main/java/net/minecraft/server/EntityHorseSkeleton.java -@@ -12,6 +12,18 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.skeletonHorseRidableInWater; -+ } -+ -+ @Override -+ public boolean isTamed() { -+ return true; -+ } -+ // Purpur end -+ - public static AttributeProvider.Builder eL() { - return fi().a(GenericAttributes.MAX_HEALTH, 15.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.20000000298023224D); - } -@@ -22,7 +34,7 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { - } - - @Override -- protected void eV() {} -+ protected void eV() { if (world.purpurConfig.skeletonHorseCanSwim) goalSelector.a(0, new PathfinderGoalFloat(this)); } // Purpur - - @Override - protected SoundEffect getSoundAmbient() { -@@ -117,7 +129,7 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { - - @Override - public boolean bt() { -- return true; -+ return super.bt(); // Purpur - } - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityHorseZombie.java b/src/main/java/net/minecraft/server/EntityHorseZombie.java -index 0e98173607c810e0e74552a2ba8febf292357c39..559ba50977147b8e2a0e7c1e7dc281faabd7f292 100644 ---- a/src/main/java/net/minecraft/server/EntityHorseZombie.java -+++ b/src/main/java/net/minecraft/server/EntityHorseZombie.java -@@ -8,6 +8,18 @@ public class EntityHorseZombie extends EntityHorseAbstract { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.zombieHorseRidableInWater; -+ } -+ -+ @Override -+ public boolean isTamed() { -+ return true; -+ } -+ // Purpur end -+ - public static AttributeProvider.Builder eL() { - return fi().a(GenericAttributes.MAX_HEALTH, 15.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.20000000298023224D); - } -@@ -79,5 +91,5 @@ public class EntityHorseZombie extends EntityHorseAbstract { - } - - @Override -- protected void eV() {} -+ protected void eV() { if (world.purpurConfig.zombieHorseCanSwim) goalSelector.a(0, new PathfinderGoalFloat(this)); } // Purpur - } -diff --git a/src/main/java/net/minecraft/server/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java -index 0f7b60642c44630000d47f0e1fdebad15e14a810..fc51d6f9cd8c6ca61ae70b07cff817c5d871ab48 100644 ---- a/src/main/java/net/minecraft/server/EntityHuman.java -+++ b/src/main/java/net/minecraft/server/EntityHuman.java -@@ -2161,4 +2161,15 @@ public abstract class EntityHuman extends EntityLiving { - return this.g; - } - } -+ -+ // Purpur start -+ @Override -+ public boolean processClick(EnumHand hand) { -+ Entity vehicle = getRootVehicle(); -+ if (vehicle != null && vehicle.getRider() == this) { -+ return vehicle.onClick(hand); -+ } -+ return false; -+ } -+ // Purpur end - } -diff --git a/src/main/java/net/minecraft/server/EntityIllagerIllusioner.java b/src/main/java/net/minecraft/server/EntityIllagerIllusioner.java -index c57bf5091430709778dc21d70c8a32819c9d6639..b0a5c36d1132e2558a1fefbd9f8dd26448400086 100644 ---- a/src/main/java/net/minecraft/server/EntityIllagerIllusioner.java -+++ b/src/main/java/net/minecraft/server/EntityIllagerIllusioner.java -@@ -20,6 +20,16 @@ public class EntityIllagerIllusioner extends EntityIllagerWizard implements IRan +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java b/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java +index cb092bee9d6827d4b0276bfa9b033cf7ca86ead4..5186d9957c94be359da5b08fd821e9471c159f03 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java +@@ -3,6 +3,7 @@ package net.minecraft.world.entity.monster; + import javax.annotation.Nullable; + import net.minecraft.core.particles.Particles; + import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.util.MathHelper; +@@ -57,6 +58,16 @@ public class EntityIllagerIllusioner extends EntityIllagerWizard implements IRan } // Purpur start @@ -2139,7 +4080,7 @@ index c57bf5091430709778dc21d70c8a32819c9d6639..b0a5c36d1132e2558a1fefbd9f8dd264 @Override protected void initAttributes() { this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue(this.world.purpurConfig.illusionerMovementSpeed); -@@ -32,6 +42,7 @@ public class EntityIllagerIllusioner extends EntityIllagerWizard implements IRan +@@ -69,6 +80,7 @@ public class EntityIllagerIllusioner extends EntityIllagerWizard implements IRan protected void initPathfinder() { super.initPathfinder(); this.goalSelector.a(0, new PathfinderGoalFloat(this)); @@ -2147,7 +4088,7 @@ index c57bf5091430709778dc21d70c8a32819c9d6639..b0a5c36d1132e2558a1fefbd9f8dd264 this.goalSelector.a(1, new EntityIllagerWizard.b()); this.goalSelector.a(4, new EntityIllagerIllusioner.b()); this.goalSelector.a(5, new EntityIllagerIllusioner.a()); -@@ -39,6 +50,7 @@ public class EntityIllagerIllusioner extends EntityIllagerWizard implements IRan +@@ -76,6 +88,7 @@ public class EntityIllagerIllusioner extends EntityIllagerWizard implements IRan this.goalSelector.a(8, new PathfinderGoalRandomStroll(this, 0.6D)); this.goalSelector.a(9, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 3.0F, 1.0F)); this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 8.0F)); @@ -2155,343 +4096,11 @@ index c57bf5091430709778dc21d70c8a32819c9d6639..b0a5c36d1132e2558a1fefbd9f8dd264 this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // CraftBukkit - decompile error this.targetSelector.a(2, (new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)).a(300)); this.targetSelector.a(3, (new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)).a(300)); -diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java -index 37902ee004a7c5aa18165237e75c77117c2eec81..3b6b388515818139cf4b4815b65915cedda67af7 100644 ---- a/src/main/java/net/minecraft/server/EntityInsentient.java -+++ b/src/main/java/net/minecraft/server/EntityInsentient.java -@@ -30,7 +30,7 @@ public abstract class EntityInsentient extends EntityLiving { - protected int f; - protected ControllerLook lookController; - protected ControllerMove moveController; -- protected ControllerJump bi; -+ protected ControllerJump bi; public ControllerJump getJumpController() { return bi; } // Purpur - OBFHELPER - private final EntityAIBodyControl c; - protected NavigationAbstract navigation; - public PathfinderGoalSelector goalSelector; -@@ -68,8 +68,8 @@ public abstract class EntityInsentient extends EntityLiving { - this.bA = -1.0F; - this.goalSelector = new PathfinderGoalSelector(world.getMethodProfilerSupplier()); - this.targetSelector = new PathfinderGoalSelector(world.getMethodProfilerSupplier()); -- this.lookController = new ControllerLook(this); -- this.moveController = new ControllerMove(this); -+ this.lookController = new net.pl3x.purpur.controller.ControllerLookWASD(this); // Purpur -+ this.moveController = new net.pl3x.purpur.controller.ControllerMoveWASD(this); // Purpur - this.bi = new ControllerJump(this); - this.c = this.r(); - this.navigation = this.b(world); -@@ -258,10 +258,10 @@ public abstract class EntityInsentient extends EntityLiving { - // Purpur start - private void incrementTicksSinceLastInteraction() { - ++ticksSinceLastInteraction; -- //if (hasRider()) { -- // ticksSinceLastInteraction = 0; -- // return; -- //} -+ if (hasRider()) { -+ ticksSinceLastInteraction = 0; -+ return; -+ } - if (world.purpurConfig.entityLifeSpan <= 0) { - return; // feature disabled - } -@@ -556,14 +556,17 @@ public abstract class EntityInsentient extends EntityLiving { - return super.dp(); - } - -+ public void setForwardSpeed(float speed) { this.t(speed); } // Purpur - OBFHELPER - public void t(float f) { - this.aT = f; - } - -+ public void setVerticalSpeed(float speed) { this.u(speed); } // Purpur - OBFHELPER - public void u(float f) { - this.aS = f; - } - -+ public void setStrafeSpeed(float speed) { this.v(speed); } // Purpur - OBFHELPER - public void v(float f) { - this.aR = f; - } -@@ -1255,7 +1258,7 @@ public abstract class EntityInsentient extends EntityLiving { - protected void a(EntityHuman entityhuman, EntityInsentient entityinsentient) {} - - protected EnumInteractionResult b(EntityHuman entityhuman, EnumHand enumhand) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); // Purpur - } - - public boolean ev() { -@@ -1636,4 +1639,54 @@ public abstract class EntityInsentient extends EntityLiving { - this.unleash(true, event.isDropLeash()); - // Paper end - } -+ -+ // Purpur start -+ public double getMaxY() { -+ return world.getHeight(); -+ } -+ -+ public EnumInteractionResult tryRide(EntityHuman entityhuman, EnumHand enumhand) { -+ if (!isRidable()) { -+ return EnumInteractionResult.PASS; -+ } -+ if (enumhand != EnumHand.MAIN_HAND) { -+ return EnumInteractionResult.PASS; -+ } -+ if (entityhuman.isSneaking()) { -+ return EnumInteractionResult.PASS; -+ } -+ if (!entityhuman.getItemInHand(enumhand).isEmpty()) { -+ return EnumInteractionResult.PASS; -+ } -+ if (!passengers.isEmpty() || entityhuman.isPassenger()) { -+ return EnumInteractionResult.PASS; -+ } -+ if (this instanceof EntityTameableAnimal) { -+ EntityTameableAnimal tameable = (EntityTameableAnimal) this; -+ if (tameable.isTamed() && !tameable.isOwner(entityhuman)) { -+ return EnumInteractionResult.PASS; -+ } -+ if (!tameable.isTamed() && !world.purpurConfig.untamedTamablesAreRidable) { -+ return EnumInteractionResult.PASS; -+ } -+ } -+ if (this instanceof EntityAgeable) { -+ EntityAgeable ageable = (EntityAgeable) this; -+ if (ageable.isBaby() && !world.purpurConfig.babiesAreRidable) { -+ return EnumInteractionResult.PASS; -+ } -+ } -+ if (!entityhuman.getBukkitEntity().hasPermission("allow.ride." + getEntityType().getName())) { -+ entityhuman.sendMessage(net.pl3x.purpur.PurpurConfig.cannotRideMob); -+ return EnumInteractionResult.PASS; -+ } -+ entityhuman.yaw = this.yaw; -+ entityhuman.pitch = this.pitch; -+ if (entityhuman.startRiding(this)) { -+ return EnumInteractionResult.SUCCESS; -+ } else { -+ return EnumInteractionResult.PASS; -+ } -+ } -+ // Purpur end - } -diff --git a/src/main/java/net/minecraft/server/EntityIronGolem.java b/src/main/java/net/minecraft/server/EntityIronGolem.java -index bdff2368836dca230a6622a205d5772834afc6ee..9ee03b233b71d1b4b85a9a5e1f0ea9feb55dfe43 100644 ---- a/src/main/java/net/minecraft/server/EntityIronGolem.java -+++ b/src/main/java/net/minecraft/server/EntityIronGolem.java -@@ -22,9 +22,22 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable { - this.G = 1.0F; - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.ironGolemRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.ironGolemRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { - if (world.purpurConfig.ironGolemCanSwim) this.goalSelector.a(0, new PathfinderGoalFloat(this)); // Purpur -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new PathfinderGoalMeleeAttack(this, 1.0D, true)); - this.goalSelector.a(2, new PathfinderGoalMoveTowardsTarget(this, 0.9D, 32.0F)); - this.goalSelector.a(2, new PathfinderGoalStrollVillage(this, 0.6D, false)); -@@ -32,6 +45,7 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable { - this.goalSelector.a(5, new PathfinderGoalOfferFlower(this)); - this.goalSelector.a(7, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F)); - this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new PathfinderGoalDefendVillage(this)); - this.targetSelector.a(2, new PathfinderGoalHurtByTarget(this, new Class[0])); - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, this::a_)); -@@ -201,13 +215,13 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable { - Item item = itemstack.getItem(); - - if (item != Items.IRON_INGOT) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); // Purpur - } else { - float f = this.getHealth(); - - this.heal(25.0F); - if (this.getHealth() == f) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); // Purpur - } else { - float f1 = 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F; - -diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index bd89fa598b7dda7272cc512862fda33b64e2af99..a84150b22adb090309192c21459967a571e86b0a 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -463,7 +463,7 @@ public abstract class EntityLiving extends Entity { - - @Override - public boolean bt() { -- return false; -+ return isRidableInWater(); // Purpur - } - - protected void cU() { -@@ -2204,7 +2204,7 @@ public abstract class EntityLiving extends Entity { - return 0.42F * this.getBlockJumpFactor(); - } - -- protected void jump() { -+ public void jump() { // Purpur - protected -> public - float f = this.dJ(); - - if (this.hasEffect(MobEffects.JUMP)) { -@@ -2453,10 +2453,12 @@ public abstract class EntityLiving extends Entity { - return this.onGround ? this.dN() * (0.21600002F / (f * f * f)) : this.aE; - } - -+ public float getSpeed() { return dN(); } // Purpur - OBFHELPER - public float dN() { - return this.bu; - } - -+ public void setSpeed(float speed) { q(speed); } // Purpur - OBFHELPER - public void q(float f) { - this.bu = f; - } -@@ -2855,6 +2857,20 @@ public abstract class EntityLiving extends Entity { - } - } - // Paper end -+ // Purpur start -+ if (hasRider() && ((WorldServer) world).hasRidableMoveEvent && this instanceof EntityInsentient) { -+ if (lastX != locX() || lastY != locY() || lastZ != locZ() || lastYaw != yaw || lastPitch != pitch) { -+ Location from = new Location(world.getWorld(), lastX, lastY, lastZ, lastYaw, lastPitch); -+ Location to = new Location (world.getWorld(), locX(), locY(), locZ(), yaw, pitch); -+ net.pl3x.purpur.event.entity.RidableMoveEvent event = new net.pl3x.purpur.event.entity.RidableMoveEvent((org.bukkit.entity.Mob) getBukkitLivingEntity(), (Player) getRider().getBukkitEntity(), from, to.clone()); -+ if (!event.callEvent()) { -+ setLocation(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch()); -+ } else if (!to.equals(event.getTo())) { -+ setLocation(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch()); -+ } -+ } -+ } -+ // Purpur end - if (!this.world.isClientSide && this.dO() && this.aG()) { - this.damageEntity(DamageSource.DROWN, 1.0F); - } -diff --git a/src/main/java/net/minecraft/server/EntityLlama.java b/src/main/java/net/minecraft/server/EntityLlama.java -index e61f53816cbf09e775762403d97e9c591fb405a6..1099277868f92fdaf4b0ec3a982f26f20ead7369 100644 ---- a/src/main/java/net/minecraft/server/EntityLlama.java -+++ b/src/main/java/net/minecraft/server/EntityLlama.java -@@ -18,7 +18,46 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn - - public EntityLlama(EntityTypes entitytypes, World world) { - super(entitytypes, world); -+ // Purpur start -+ this.moveController = new net.pl3x.purpur.controller.ControllerMoveWASD(this) { -+ @Override -+ public void a() { // tick -+ if (entity.hasRider() && hasSaddle()) { -+ tick(entity.getRider()); -+ } else { -+ tick(); -+ } -+ } -+ }; -+ this.lookController = new net.pl3x.purpur.controller.ControllerLookWASD(this) { -+ @Override -+ public void a() { // tick -+ if (entity.hasRider() && hasSaddle()) { -+ tick(entity.getRider()); -+ } else { -+ tick(); -+ } -+ } -+ }; -+ // Purpur end -+ } -+ -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.llamaRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.llamaRidableInWater; -+ } -+ -+ @Override -+ public boolean hasSaddle() { -+ return super.hasSaddle() || (isTamed() && getColor() != null); - } -+ // Purpur end - - public void setStrength(int i) { - this.datawatcher.set(EntityLlama.bx, Math.max(1, Math.min(5, i))); -@@ -66,6 +105,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn - @Override - protected void initPathfinder() { - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHorseHasRider(this)); // Purpur - this.goalSelector.a(1, new PathfinderGoalTame(this, 1.2D)); - this.goalSelector.a(2, new PathfinderGoalLlamaFollow(this, 2.0999999046325684D)); - this.goalSelector.a(3, new PathfinderGoalArrowAttack(this, 1.25D, 40, 20.0F)); -@@ -75,6 +115,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn - this.goalSelector.a(6, new PathfinderGoalRandomStrollLand(this, 0.7D)); - this.goalSelector.a(7, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F)); - this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this)); -+ this.targetSelector.a(0, new PathfinderGoalHorseHasRider(this)); // Purpur - this.targetSelector.a(1, new EntityLlama.c(this)); - this.targetSelector.a(2, new EntityLlama.a(this)); - } -@@ -312,7 +353,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn - } - - @Nullable -- public EnumColor fy() { -+ public EnumColor fy() { return getColor(); } public EnumColor getColor() { // Purpur - OBFHELPER - int i = (Integer) this.datawatcher.get(EntityLlama.by); - - return i == -1 ? null : EnumColor.fromColorIndex(i); -diff --git a/src/main/java/net/minecraft/server/EntityLlamaTrader.java b/src/main/java/net/minecraft/server/EntityLlamaTrader.java -index 7d30e5c2378a2b8c540d1a1a13ec0ae97367bb9a..b6aae5cdee1f8bb842ab8e06c47fb497576b464f 100644 ---- a/src/main/java/net/minecraft/server/EntityLlamaTrader.java -+++ b/src/main/java/net/minecraft/server/EntityLlamaTrader.java -@@ -11,6 +11,23 @@ public class EntityLlamaTrader extends EntityLlama { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.llamaTraderRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.llamaTraderRidableInWater; -+ } -+ -+ @Override -+ public boolean hasSaddle() { -+ return super.hasSaddle() || isTamed(); -+ } -+ // Purpur end -+ - @Override - protected EntityLlama fz() { - return (EntityLlama) EntityTypes.TRADER_LLAMA.a(this.world); -diff --git a/src/main/java/net/minecraft/server/EntityMagmaCube.java b/src/main/java/net/minecraft/server/EntityMagmaCube.java -index 874dd39825b41f4e2b366446359920989961f084..cd28463e2bf944d94c121c8f8d6e37221754c168 100644 ---- a/src/main/java/net/minecraft/server/EntityMagmaCube.java -+++ b/src/main/java/net/minecraft/server/EntityMagmaCube.java -@@ -8,6 +8,23 @@ public class EntityMagmaCube extends EntitySlime { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityMagmaCube.java b/src/main/java/net/minecraft/world/entity/monster/EntityMagmaCube.java +index fe80e93b00f3bb2f297c6528c3951313fa3c08c7..15ed51a2746c09538a425fce25fa25f2619b7033 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityMagmaCube.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityMagmaCube.java +@@ -29,6 +29,23 @@ public class EntityMagmaCube extends EntitySlime { super(entitytypes, world); } @@ -2515,7 +4124,7 @@ index 874dd39825b41f4e2b366446359920989961f084..cd28463e2bf944d94c121c8f8d6e3722 public static AttributeProvider.Builder m() { return EntityMonster.eR().a(GenericAttributes.MOVEMENT_SPEED, 0.20000000298023224D); } -@@ -58,11 +75,12 @@ public class EntityMagmaCube extends EntitySlime { +@@ -79,11 +96,12 @@ public class EntityMagmaCube extends EntitySlime { } @Override @@ -2529,302 +4138,33 @@ index 874dd39825b41f4e2b366446359920989961f084..cd28463e2bf944d94c121c8f8d6e3722 } @Override -diff --git a/src/main/java/net/minecraft/server/EntityMushroomCow.java b/src/main/java/net/minecraft/server/EntityMushroomCow.java -index 91cfe60f764a573e3724b48a9ae02e806c1e4fb8..e38d165fefb4d552ded2198536a6663a5688070d 100644 ---- a/src/main/java/net/minecraft/server/EntityMushroomCow.java -+++ b/src/main/java/net/minecraft/server/EntityMushroomCow.java -@@ -21,6 +21,18 @@ public class EntityMushroomCow extends EntityCow implements IShearable { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.mooshroomRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.mooshroomRidableInWater; -+ } -+ // Purpur end -+ - @Override - public float a(BlockPosition blockposition, IWorldReader iworldreader) { - return iworldreader.getType(blockposition.down()).a(Blocks.MYCELIUM) ? 10.0F : iworldreader.y(blockposition) - 0.5F; -@@ -82,7 +94,7 @@ public class EntityMushroomCow extends EntityCow implements IShearable { - } else if (itemstack.getItem() == Items.SHEARS && this.canShear()) { - // CraftBukkit start - if (!CraftEventFactory.handlePlayerShearEntityEvent(entityhuman, this, itemstack, enumhand)) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); // Purpur - } - // CraftBukkit end - this.shear(SoundCategory.PLAYERS); -@@ -102,7 +114,7 @@ public class EntityMushroomCow extends EntityCow implements IShearable { - Optional> optional = this.l(itemstack); - - if (!optional.isPresent()) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); // Purpur - } - - Pair pair = (Pair) optional.get(); -diff --git a/src/main/java/net/minecraft/server/EntityOcelot.java b/src/main/java/net/minecraft/server/EntityOcelot.java -index 7bd3fea6e0e478337c7f6400a941675eebba517b..2f8275cd6b3cde0d3f949219f67ba7f0e0031dc3 100644 ---- a/src/main/java/net/minecraft/server/EntityOcelot.java -+++ b/src/main/java/net/minecraft/server/EntityOcelot.java -@@ -16,6 +16,18 @@ public class EntityOcelot extends EntityAnimal { - this.eL(); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.ocelotRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.ocelotRidableInWater; -+ } -+ // Purpur end -+ - private boolean isTrusting() { - return (Boolean) this.datawatcher.get(EntityOcelot.bp); - } -@@ -47,12 +59,14 @@ public class EntityOcelot extends EntityAnimal { - protected void initPathfinder() { - this.br = new EntityOcelot.b(this, 0.6D, EntityOcelot.bo, true); - this.goalSelector.a(1, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(1, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(3, this.br); - this.goalSelector.a(7, new PathfinderGoalLeapAtTarget(this, 0.3F)); - this.goalSelector.a(8, new PathfinderGoalOcelotAttack(this)); - this.goalSelector.a(9, new PathfinderGoalBreed(this, 0.8D)); - this.goalSelector.a(10, new PathfinderGoalRandomStrollLand(this, 0.8D, 1.0000001E-5F)); - this.goalSelector.a(11, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 10.0F)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityChicken.class, false)); - this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityTurtle.class, 10, false, false, EntityTurtle.bo)); - } -diff --git a/src/main/java/net/minecraft/server/EntityPanda.java b/src/main/java/net/minecraft/server/EntityPanda.java -index b36cc95168c6e6fbf668ebe15c1fa10b54e570d3..eafae5516b9b5d51aa943796557926cf61476d2b 100644 ---- a/src/main/java/net/minecraft/server/EntityPanda.java -+++ b/src/main/java/net/minecraft/server/EntityPanda.java -@@ -46,6 +46,27 @@ public class EntityPanda extends EntityAnimal { - - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.pandaRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.pandaRidableInWater; -+ } -+ -+ @Override -+ public void onMount(EntityHuman entityhuman) { -+ super.onMount(entityhuman); -+ this.setForwardSpeed(0.0F); -+ this.setScared(false); -+ this.setEating(false); -+ this.setLayingOnBack(false); -+ } -+ // Purpur end -+ - @Override - public boolean e(ItemStack itemstack) { - EnumItemSlot enumitemslot = EntityInsentient.j(itemstack); -@@ -69,6 +90,7 @@ public class EntityPanda extends EntityAnimal { - return this.w(8); - } - -+ public void setScared(boolean scared) { this.t(scared); } // Purpur - OBFHELPER - public void t(boolean flag) { - this.d(8, flag); - } -@@ -77,6 +99,7 @@ public class EntityPanda extends EntityAnimal { - return this.w(16); - } - -+ public void setLayingOnBack(boolean layingOnBack) { this.u(layingOnBack); } // Purpur - OBFHELPER - public void u(boolean flag) { - this.d(16, flag); - } -@@ -93,6 +116,7 @@ public class EntityPanda extends EntityAnimal { - return (Integer) this.datawatcher.get(EntityPanda.br); - } - -+ public void setEating(boolean eating) { this.v(eating); } // Purpur - OBFHELPER - private void v(int i) { - this.datawatcher.set(EntityPanda.br, i); - } -@@ -201,6 +225,7 @@ public class EntityPanda extends EntityAnimal { - @Override - protected void initPathfinder() { - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(2, new EntityPanda.i(this, 2.0D)); - this.goalSelector.a(2, new EntityPanda.d(this, 1.0D)); - this.goalSelector.a(3, new EntityPanda.b(this, 1.2000000476837158D, true)); -@@ -216,6 +241,7 @@ public class EntityPanda extends EntityAnimal { - this.goalSelector.a(12, new EntityPanda.j(this)); - this.goalSelector.a(13, new PathfinderGoalFollowParent(this, 1.25D)); - this.goalSelector.a(14, new PathfinderGoalRandomStrollLand(this, 1.0D)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, (new EntityPanda.e(this, new Class[0])).a(new Class[0])); - } - -@@ -536,7 +562,7 @@ public class EntityPanda extends EntityAnimal { - ItemStack itemstack = entityhuman.b(enumhand); - - if (this.ff()) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); // Purpur - } else if (this.eN()) { - this.u(false); - return EnumInteractionResult.a(this.world.isClientSide); -@@ -553,7 +579,7 @@ public class EntityPanda extends EntityAnimal { - this.g(entityhuman); - } else { - if (this.world.isClientSide || this.eM() || this.isInWater()) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); // Purpur - } - - this.ft(); -@@ -570,7 +596,7 @@ public class EntityPanda extends EntityAnimal { - - return EnumInteractionResult.SUCCESS; - } else { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); // Purpur - } - } - -@@ -683,6 +709,7 @@ public class EntityPanda extends EntityAnimal { - - public f(EntityPanda entitypanda) { - this.a = entitypanda; -+ this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - lay on back - } - - @Override -@@ -846,6 +873,7 @@ public class EntityPanda extends EntityAnimal { - - public l(EntityPanda entitypanda) { - this.a = entitypanda; -+ this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - sneeze - } - - @Override -@@ -975,7 +1003,7 @@ public class EntityPanda extends EntityAnimal { - } - } - -- static class h extends ControllerMove { -+ static class h extends net.pl3x.purpur.controller.ControllerMoveWASD { // Purpur - - private final EntityPanda i; - -@@ -985,9 +1013,9 @@ public class EntityPanda extends EntityAnimal { - } - - @Override -- public void a() { -+ public void tick() { // Purpur - if (this.i.fh()) { -- super.a(); -+ super.tick(); // Purpur - } - } - } -diff --git a/src/main/java/net/minecraft/server/EntityParrot.java b/src/main/java/net/minecraft/server/EntityParrot.java -index 0af6c9395b5d98e6bfa162f651d0e8cb89035afd..e402d4a77b57b8b12b7575a9793c30d7acfa7fb0 100644 ---- a/src/main/java/net/minecraft/server/EntityParrot.java -+++ b/src/main/java/net/minecraft/server/EntityParrot.java -@@ -65,12 +65,58 @@ public class EntityParrot extends EntityPerchable implements EntityBird { - - public EntityParrot(EntityTypes entitytypes, World world) { - super(entitytypes, world); -- this.moveController = new ControllerMoveFlying(this, 10, false); -+ // Purpur start -+ final net.pl3x.purpur.controller.ControllerMoveWASDFlyingWithSpacebar flyingController = new net.pl3x.purpur.controller.ControllerMoveWASDFlyingWithSpacebar(this, 0.3F); -+ this.moveController = new ControllerMoveFlying(this, 10, false) { -+ @Override -+ public void a() { // tick -+ if (getEntity().hasRider()) { -+ flyingController.tick(getEntity().getRider()); -+ } else { -+ tick(); -+ } -+ } -+ -+ @Override -+ public boolean b() { // isUpdating -+ return getEntity().hasRider() ? getForward() != 0 || getStrafe() != 0 : super.b(); -+ } -+ }; -+ // Purpur end - this.a(PathType.DANGER_FIRE, -1.0F); - this.a(PathType.DAMAGE_FIRE, -1.0F); - this.a(PathType.COCOA, -1.0F); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.parrotRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.parrotRidableInWater; -+ } -+ -+ @Override -+ public double getMaxY() { -+ return world.purpurConfig.parrotMaxY; -+ } -+ -+ @Override -+ public void g(Vec3D vec3d) { -+ super.g(vec3d); -+ if (hasRider() && !onGround) { -+ float speed = (float) getAttributeInstance(GenericAttributes.FLYING_SPEED).getValue() * 2; -+ setSpeed(speed); -+ Vec3D mot = getMot(); -+ move(EnumMoveType.SELF, mot.multiply(speed, 0.25, speed)); -+ setMot(mot.a(0.9D)); -+ } -+ } -+ // Purpur end -+ - @Nullable - @Override - public GroupDataEntity prepare(WorldAccess worldaccess, DifficultyDamageScaler difficultydamagescaler, EnumMobSpawn enummobspawn, @Nullable GroupDataEntity groupdataentity, @Nullable NBTTagCompound nbttagcompound) { -@@ -89,8 +135,10 @@ public class EntityParrot extends EntityPerchable implements EntityBird { - - @Override - protected void initPathfinder() { -- this.goalSelector.a(0, new PathfinderGoalPanic(this, 1.25D)); -+ // this.goalSelector.a(0, new PathfinderGoalPanic(this, 1.25D)); // Purpur - move down - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur -+ this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.25D)); // Purpur - this.goalSelector.a(1, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(2, new PathfinderGoalSit(this)); - this.goalSelector.a(2, new PathfinderGoalFollowOwner(this, 1.0D, 5.0F, 1.0F, true)); -diff --git a/src/main/java/net/minecraft/server/EntityPhantom.java b/src/main/java/net/minecraft/server/EntityPhantom.java -index bdfe073dcd255a7359127f9ae3a962642be5526d..c70281fddcbe5a97a1eb176def99cdf31de37579 100644 ---- a/src/main/java/net/minecraft/server/EntityPhantom.java -+++ b/src/main/java/net/minecraft/server/EntityPhantom.java -@@ -25,6 +25,59 @@ public class EntityPhantom extends EntityFlying implements IMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java +index 07ede7b75a65a5815f1ae1ebf03ec0fdb4621afb..a836839b17cbda8ac269f032b141ba448e3bab8c 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java +@@ -13,6 +13,7 @@ import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; + import net.minecraft.server.level.WorldServer; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.sounds.SoundCategory; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -29,11 +30,11 @@ import net.minecraft.world.entity.EntitySize; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EnumMonsterType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.IEntitySelector; ++import net.minecraft.world.entity.ai.attributes.AttributeProvider; + import net.minecraft.world.entity.ai.attributes.GenericAttributes; +-import net.minecraft.world.entity.ai.control.ControllerLook; +-import net.minecraft.world.entity.ai.control.ControllerMove; + import net.minecraft.world.entity.ai.control.EntityAIBodyControl; + import net.minecraft.world.entity.ai.goal.PathfinderGoal; + import net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition; +@@ -68,6 +69,59 @@ public class EntityPhantom extends EntityFlying implements IMonster { this.lookController = new EntityPhantom.f(this); } @@ -2884,7 +4224,7 @@ index bdfe073dcd255a7359127f9ae3a962642be5526d..c70281fddcbe5a97a1eb176def99cdf3 @Override protected EntityAIBodyControl r() { return new EntityPhantom.d(this); -@@ -33,6 +86,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { +@@ -76,6 +130,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { @Override protected void initPathfinder() { // Purpur start @@ -2892,7 +4232,7 @@ index bdfe073dcd255a7359127f9ae3a962642be5526d..c70281fddcbe5a97a1eb176def99cdf3 if (world.purpurConfig.phantomOrbitCrystalRadius > 0) { this.goalSelector.a(1, new FindCrystalGoal(this)); this.goalSelector.a(2, new OrbitCrystalGoal(this)); -@@ -40,6 +94,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { +@@ -83,6 +138,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { this.goalSelector.a(3, new EntityPhantom.c()); // PickAttackGoal this.goalSelector.a(4, new EntityPhantom.i()); // SweepAttackGoal this.goalSelector.a(5, new EntityPhantom.e()); // OrbitPointGoal @@ -2900,7 +4240,7 @@ index bdfe073dcd255a7359127f9ae3a962642be5526d..c70281fddcbe5a97a1eb176def99cdf3 this.targetSelector.a(1, new EntityPhantom.b()); // AttackPlayer Goal // Purpur end } -@@ -126,7 +181,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { +@@ -169,7 +225,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { @Override public void movementTick() { @@ -2909,7 +4249,7 @@ index bdfe073dcd255a7359127f9ae3a962642be5526d..c70281fddcbe5a97a1eb176def99cdf3 this.setOnFire(8); } -@@ -368,7 +423,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { +@@ -412,7 +468,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { @Override public boolean a() { @@ -2918,7 +4258,7 @@ index bdfe073dcd255a7359127f9ae3a962642be5526d..c70281fddcbe5a97a1eb176def99cdf3 if (this.c > 0) { --this.c; return false; -@@ -397,7 +452,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { +@@ -441,7 +497,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { @Override public boolean b() { @@ -2927,7 +4267,7 @@ index bdfe073dcd255a7359127f9ae3a962642be5526d..c70281fddcbe5a97a1eb176def99cdf3 EntityLiving entityliving = EntityPhantom.this.getGoalTarget(); return entityliving != null ? EntityPhantom.this.a(entityliving, PathfinderTargetCondition.a) : false; -@@ -412,7 +467,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { +@@ -456,7 +512,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { @Override public boolean a() { @@ -2936,7 +4276,7 @@ index bdfe073dcd255a7359127f9ae3a962642be5526d..c70281fddcbe5a97a1eb176def99cdf3 EntityLiving entityliving = EntityPhantom.this.getGoalTarget(); return entityliving != null ? EntityPhantom.this.a(EntityPhantom.this.getGoalTarget(), PathfinderTargetCondition.a) : false; -@@ -610,14 +665,23 @@ public class EntityPhantom extends EntityFlying implements IMonster { +@@ -654,14 +710,23 @@ public class EntityPhantom extends EntityFlying implements IMonster { } } @@ -2962,7 +4302,7 @@ index bdfe073dcd255a7359127f9ae3a962642be5526d..c70281fddcbe5a97a1eb176def99cdf3 } class d extends EntityAIBodyControl { -@@ -633,7 +697,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { +@@ -677,7 +742,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { } } @@ -2971,7 +4311,7 @@ index bdfe073dcd255a7359127f9ae3a962642be5526d..c70281fddcbe5a97a1eb176def99cdf3 private float j = 0.1F; -@@ -642,7 +706,19 @@ public class EntityPhantom extends EntityFlying implements IMonster { +@@ -686,7 +751,19 @@ public class EntityPhantom extends EntityFlying implements IMonster { } @Override @@ -2992,38 +4332,11 @@ index bdfe073dcd255a7359127f9ae3a962642be5526d..c70281fddcbe5a97a1eb176def99cdf3 if (EntityPhantom.this.positionChanged) { EntityPhantom.this.yaw += 180.0F; this.j = 0.1F; -diff --git a/src/main/java/net/minecraft/server/EntityPig.java b/src/main/java/net/minecraft/server/EntityPig.java -index 6ea3e4ffc3f42f4282adf3554944f24d92ca2079..bf7ecd7a7d805cc8f1314a348d7b13f848da46b5 100644 ---- a/src/main/java/net/minecraft/server/EntityPig.java -+++ b/src/main/java/net/minecraft/server/EntityPig.java -@@ -19,9 +19,22 @@ public class EntityPig extends EntityAnimal implements ISteerable, ISaddleable { - this.saddleStorage = new SaddleStorage(this.datawatcher, EntityPig.bp, EntityPig.bo); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.pigRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.pigRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.25D)); - this.goalSelector.a(3, new PathfinderGoalBreed(this, 1.0D)); - this.goalSelector.a(4, new PathfinderGoalTempt(this, 1.2D, RecipeItemStack.a(Items.CARROT_ON_A_STICK), false)); -diff --git a/src/main/java/net/minecraft/server/EntityPigZombie.java b/src/main/java/net/minecraft/server/EntityPigZombie.java -index 32b75f710b12efbcecec2c8d72d4d8cb725870fe..3327dbbf87d8f43cbc7cd728df2f4c6a33dae40d 100644 ---- a/src/main/java/net/minecraft/server/EntityPigZombie.java -+++ b/src/main/java/net/minecraft/server/EntityPigZombie.java -@@ -22,6 +22,16 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java +index af00a4245ca39f208810d1ec758e512cbf5648f3..816a2bd7438f66a5d7ff761b8fcf8b42483561c7 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java +@@ -56,6 +56,16 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { } // Purpur start @@ -3040,84 +4353,19 @@ index 32b75f710b12efbcecec2c8d72d4d8cb725870fe..3327dbbf87d8f43cbc7cd728df2f4c6a @Override public boolean jockeyOnlyBaby() { return world.purpurConfig.zombifiedPiglinJockeyOnlyBaby; -diff --git a/src/main/java/net/minecraft/server/EntityPiglin.java b/src/main/java/net/minecraft/server/EntityPiglin.java -index 682b241ae0e2859aa57faea8a4521c1c07192b7d..29ecfd09f0bed3dc64b14b90875a111253599958 100644 ---- a/src/main/java/net/minecraft/server/EntityPiglin.java -+++ b/src/main/java/net/minecraft/server/EntityPiglin.java -@@ -25,6 +25,18 @@ public class EntityPiglin extends EntityPiglinAbstract implements ICrossbow { - this.f = 5; - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.piglinRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.piglinRidableInWater; -+ } -+ // Purpur end -+ - @Override - public void saveData(NBTTagCompound nbttagcompound) { - super.saveData(nbttagcompound); -@@ -205,6 +217,7 @@ public class EntityPiglin extends EntityPiglinAbstract implements ICrossbow { - // Airplane - dynamic tick - if (!gg.airplane.AirplaneConfig.dynamicPiglinBehavior || this.behaviorTick++ % this.activatedPriority == 0) { - this.world.getMethodProfiler().enter("piglinBrain"); -+ if (getRider() == null) // Purpur - only use brain if no rider - this.getBehaviorController().a((WorldServer) this.world, (EntityPiglin) this); // Airplane - compile error - this.world.getMethodProfiler().exit(); - PiglinAI.b(this); -diff --git a/src/main/java/net/minecraft/server/EntityPiglinBrute.java b/src/main/java/net/minecraft/server/EntityPiglinBrute.java -index 3e9a4af09d0a4af89584ce26428c38f59ff1ff11..f6b170811159544dc10b91226e4e54b349472c46 100644 ---- a/src/main/java/net/minecraft/server/EntityPiglinBrute.java -+++ b/src/main/java/net/minecraft/server/EntityPiglinBrute.java -@@ -15,6 +15,18 @@ public class EntityPiglinBrute extends EntityPiglinAbstract { - this.f = 20; - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.piglinBruteRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.piglinBruteRidableInWater; -+ } -+ // Purpur end -+ - public static AttributeProvider.Builder eS() { - return EntityMonster.eR().a(GenericAttributes.MAX_HEALTH, 50.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.3499999940395355D).a(GenericAttributes.ATTACK_DAMAGE, 7.0D); - } -@@ -44,7 +56,7 @@ public class EntityPiglinBrute extends EntityPiglinAbstract { - - @Override - public BehaviorController getBehaviorController() { -- return super.getBehaviorController(); -+ return (BehaviorController) super.getBehaviorController(); // Purpur - decompile error - } - - @Override -@@ -60,7 +72,8 @@ public class EntityPiglinBrute extends EntityPiglinAbstract { - @Override - protected void mobTick() { - this.world.getMethodProfiler().enter("piglinBruteBrain"); -- this.getBehaviorController().a((WorldServer) this.world, (EntityLiving) this); -+ if (getRider() == null) // Purpur - only use brain if no rider -+ this.getBehaviorController().a((WorldServer) this.world, this); // Purpur - decompile error - this.world.getMethodProfiler().exit(); - PiglinBruteAI.b(this); - PiglinBruteAI.c(this); -diff --git a/src/main/java/net/minecraft/server/EntityPillager.java b/src/main/java/net/minecraft/server/EntityPillager.java -index a3a428da99574c485fcf2b8c7944e0d8354146ee..cf7de0127166f6175a6246062c8664e64959edeb 100644 ---- a/src/main/java/net/minecraft/server/EntityPillager.java -+++ b/src/main/java/net/minecraft/server/EntityPillager.java -@@ -13,15 +13,29 @@ public class EntityPillager extends EntityIllagerAbstract implements ICrossbow { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPillager.java b/src/main/java/net/minecraft/world/entity/monster/EntityPillager.java +index ea105fb86553f5212d616c976eaf2a16bf5b6561..2a4ac6e608650d56cc2b564e715b7b685e7f3f62 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityPillager.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityPillager.java +@@ -9,6 +9,7 @@ import net.minecraft.nbt.NBTTagList; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.world.DifficultyDamageScaler; +@@ -61,15 +62,29 @@ public class EntityPillager extends EntityIllagerAbstract implements ICrossbow { super(entitytypes, world); } @@ -3147,303 +4395,19 @@ index a3a428da99574c485fcf2b8c7944e0d8354146ee..cf7de0127166f6175a6246062c8664e6 this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // CraftBukkit - decompile error this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)); -diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index c69ff970f4afe5c860fa8794b9be1f6b818ac395..da4943389fee9b8a8d03ad5c518806d85cc639db 100644 ---- a/src/main/java/net/minecraft/server/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/EntityPlayer.java -@@ -512,6 +512,15 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - - this.advancementDataPlayer.b(this); -+ -+ // Purpur start -+ if (this.world.purpurConfig.useNightVisionWhenRiding && this.getVehicle() != null && this.getVehicle().getRider() == this && world.getTime() % 100 == 0) { // 5 seconds -+ MobEffect nightVision = this.getEffect(MobEffects.NIGHT_VISION); -+ if (nightVision == null || nightVision.getDuration() <= 300) { // 15 seconds -+ this.addEffect(new MobEffect(MobEffects.NIGHT_VISION, 400, 0)); // 20 seconds -+ } -+ } -+ // Purpur end - } - - public void playerTick() { -diff --git a/src/main/java/net/minecraft/server/EntityPolarBear.java b/src/main/java/net/minecraft/server/EntityPolarBear.java -index 99f0bd8f82520778d469ec51745034e6ebd3238a..3d649843f565d2c8820b525c199bd2b9f9120cc7 100644 ---- a/src/main/java/net/minecraft/server/EntityPolarBear.java -+++ b/src/main/java/net/minecraft/server/EntityPolarBear.java -@@ -18,12 +18,34 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { - private static final IntRange bs = TimeRange.a(20, 39); - private int bt; - private UUID bu; -+ private int standTimer = 0; // Purpur - - public EntityPolarBear(EntityTypes entitytypes, World world) { - super(entitytypes, world); - } - - // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.polarBearRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.polarBearRidableInWater; -+ } -+ -+ @Override -+ public boolean onSpacebar() { -+ if (!isStanding()) { -+ if (hasRider() && getRider().getForward() == 0 && getRider().getStrafe() == 0) { -+ setStanding(true); -+ playSound(SoundEffects.ENTITY_POLAR_BEAR_WARNING, 1.0F, 1.0F); -+ } -+ } -+ return false; -+ } -+ - @Override - public boolean mate(EntityAnimal entityanimal) { - if (entityanimal == this) { -@@ -61,6 +83,7 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { - protected void initPathfinder() { - super.initPathfinder(); - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new EntityPolarBear.c()); - this.goalSelector.a(1, new EntityPolarBear.d()); - // Purpur start -@@ -73,6 +96,7 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { - this.goalSelector.a(5, new PathfinderGoalRandomStroll(this, 1.0D)); - this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F)); - this.goalSelector.a(7, new PathfinderGoalRandomLookaround(this)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new EntityPolarBear.b()); - this.targetSelector.a(2, new EntityPolarBear.a()); - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, this::a_)); -@@ -185,6 +209,11 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { - this.a((WorldServer) this.world, true); - } - -+ // Purpur start -+ if (isStanding() && --standTimer <= 0) { -+ setStanding(false); -+ } -+ // Purpur end - } - - @Override -@@ -218,6 +247,7 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { - public void setStanding(boolean standing) { t(standing); } // Purpur - OBFHELPER - public void t(boolean flag) { - this.datawatcher.set(EntityPolarBear.bo, flag); -+ standTimer = flag ? 20 : -1; // Purpur - } - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityPufferFish.java b/src/main/java/net/minecraft/server/EntityPufferFish.java -index 330ec38d09636232250d97baad0cef7a9305d614..16a4df27c557e2d4a0fd4f48317307b884c2688c 100644 ---- a/src/main/java/net/minecraft/server/EntityPufferFish.java -+++ b/src/main/java/net/minecraft/server/EntityPufferFish.java -@@ -17,6 +17,18 @@ public class EntityPufferFish extends EntityFish { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.pufferfishRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return true; -+ } -+ // Purpur end -+ - @Override - protected void initDatawatcher() { - super.initDatawatcher(); -@@ -60,7 +72,7 @@ public class EntityPufferFish extends EntityFish { - @Override - protected void initPathfinder() { - super.initPathfinder(); -- this.goalSelector.a(1, new EntityPufferFish.a(this)); -+ this.goalSelector.a(2, new EntityPufferFish.a(this)); // Purpur - } - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityRabbit.java b/src/main/java/net/minecraft/server/EntityRabbit.java -index 25a9b7906be35e981566610c7d08aa8df5050d74..b766a27e98e19bffd3fe8f81f750750ae7681d02 100644 ---- a/src/main/java/net/minecraft/server/EntityRabbit.java -+++ b/src/main/java/net/minecraft/server/EntityRabbit.java -@@ -20,6 +20,18 @@ public class EntityRabbit extends EntityAnimal { - this.initializePathFinderGoals(); // CraftBukkit - moved code - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.rabbitRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.rabbitRidableInWater; -+ } -+ // Purpur end -+ - // CraftBukkit start - code from constructor - public void initializePathFinderGoals(){ - this.i(0.0D); -@@ -28,7 +40,8 @@ public class EntityRabbit extends EntityAnimal { - - @Override - public void initPathfinder() { -- this.goalSelector.a(1, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalFloat(this)); // Purpur -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new EntityRabbit.PathfinderGoalRabbitPanic(this, 2.2D)); - this.goalSelector.a(2, new PathfinderGoalBreed(this, 0.8D)); - this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.0D, RecipeItemStack.a(Items.CARROT, Items.GOLDEN_CARROT, Blocks.DANDELION), false)); -@@ -41,7 +54,15 @@ public class EntityRabbit extends EntityAnimal { - } - - @Override -- protected float dJ() { -+ // Purpur start -+ public float getJumpHeight() { -+ if (hasRider()) { -+ if (getForward() < 0) { -+ setSpeed(getForward() * 2F); -+ } -+ return actualJump ? 0.5F : 0.3F; -+ } -+ // Purpur end - if (!this.positionChanged && (!this.moveController.b() || this.moveController.e() <= this.locY() + 0.5D)) { - PathEntity pathentity = this.navigation.k(); - -@@ -60,7 +81,7 @@ public class EntityRabbit extends EntityAnimal { - } - - @Override -- protected void jump() { -+ public void jump() { // Purpur - protected -> public - super.jump(); - double d0 = this.moveController.c(); - -@@ -92,6 +113,7 @@ public class EntityRabbit extends EntityAnimal { - - } - -+ public void startJumping() { eK(); } // Purpur - OBFHELPER - public void eK() { - this.setJumping(true); - this.br = 10; -@@ -106,6 +128,13 @@ public class EntityRabbit extends EntityAnimal { - - @Override - public void mobTick() { -+ // Purpur start -+ if (hasRider()) { -+ handleJumping(); -+ return; -+ } -+ // Purpur end -+ - if (this.bt > 0) { - --this.bt; - } -@@ -156,6 +185,39 @@ public class EntityRabbit extends EntityAnimal { - this.bs = this.onGround; - } - -+ // Purpur start -+ private boolean wasOnGround; -+ private boolean actualJump; -+ -+ private void handleJumping() { -+ if (onGround) { -+ ControllerJumpRabbit jumpController = (ControllerJumpRabbit) getJumpController(); -+ if (!wasOnGround) { -+ setJumping(false); -+ jumpController.setCanJump(false); -+ } -+ if (!jumpController.isJumping()) { -+ if (moveController.b()) { // isUpdating -+ startJumping(); -+ } -+ } else if (!jumpController.canJump()) { -+ jumpController.setCanJump(true); -+ } -+ } -+ wasOnGround = onGround; -+ } -+ -+ @Override -+ public boolean onSpacebar() { -+ if (onGround) { -+ actualJump = true; -+ jump(); -+ actualJump = false; -+ } -+ return true; -+ } -+ // Purpur end -+ - @Override - public boolean aO() { - return false; -@@ -485,7 +547,7 @@ public class EntityRabbit extends EntityAnimal { - } - } - -- static class ControllerMoveRabbit extends ControllerMove { -+ static class ControllerMoveRabbit extends net.pl3x.purpur.controller.ControllerMoveWASD { // Purpur - - private final EntityRabbit i; - private double j; -@@ -496,14 +558,14 @@ public class EntityRabbit extends EntityAnimal { - } - - @Override -- public void a() { -+ public void tick() { // Purpur - if (this.i.onGround && !this.i.jumping && !((EntityRabbit.ControllerJumpRabbit) this.i.bi).c()) { - this.i.i(0.0D); - } else if (this.b()) { - this.i.i(this.j); - } - -- super.a(); -+ super.tick(); // Purpur - } - - @Override -@@ -530,14 +592,17 @@ public class EntityRabbit extends EntityAnimal { - this.c = entityrabbit; - } - -+ public boolean isJumping() { return c(); } // Purpur - OBFHELPER - public boolean c() { - return this.a; - } - -+ public boolean canJump() { return d(); } // Purpur - OBFHELPER - public boolean d() { - return this.d; - } - -+ public void setCanJump(boolean canJump) { a(canJump); } // Purpur - OBFHELPER - public void a(boolean flag) { - this.d = flag; - } -diff --git a/src/main/java/net/minecraft/server/EntityRavager.java b/src/main/java/net/minecraft/server/EntityRavager.java -index e78f158d9c682c60d42c17e0f171d492552e4079..9d0a462bfc56994ee35478cc9e565123620a9f08 100644 ---- a/src/main/java/net/minecraft/server/EntityRavager.java -+++ b/src/main/java/net/minecraft/server/EntityRavager.java -@@ -20,14 +20,37 @@ public class EntityRavager extends EntityRaider { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java b/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java +index 16d5cae64887b82e67eeb61ccb714e6125ff0c09..dc1ca7b334e89b4d0be775b6f6e6f4222ea02dcc 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java +@@ -7,6 +7,7 @@ import javax.annotation.Nullable; + import net.minecraft.core.BlockPosition; + import net.minecraft.core.particles.Particles; + import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.tags.Tag; +@@ -61,14 +62,37 @@ public class EntityRavager extends EntityRaider { this.f = 20; } @@ -3481,7 +4445,7 @@ index e78f158d9c682c60d42c17e0f171d492552e4079..9d0a462bfc56994ee35478cc9e565123 this.targetSelector.a(2, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // CraftBukkit - decompile error this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); this.targetSelector.a(4, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, true)); -@@ -99,7 +122,7 @@ public class EntityRavager extends EntityRaider { +@@ -140,7 +164,7 @@ public class EntityRavager extends EntityRaider { @Override public void movementTick() { super.movementTick(); @@ -3490,62 +4454,19 @@ index e78f158d9c682c60d42c17e0f171d492552e4079..9d0a462bfc56994ee35478cc9e565123 if (this.isFrozen()) { this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue(0.0D); } else { -diff --git a/src/main/java/net/minecraft/server/EntitySalmon.java b/src/main/java/net/minecraft/server/EntitySalmon.java -index 51ec63413306cf9dcd685870ccbd4e5440ab2e7a..6dfcee2c9b658c2c9ee1179e412389934c066d48 100644 ---- a/src/main/java/net/minecraft/server/EntitySalmon.java -+++ b/src/main/java/net/minecraft/server/EntitySalmon.java -@@ -6,6 +6,18 @@ public class EntitySalmon extends EntityFishSchool { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.salmonRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return true; -+ } -+ // Purpur end -+ - @Override - public int eN() { - return 5; -diff --git a/src/main/java/net/minecraft/server/EntitySheep.java b/src/main/java/net/minecraft/server/EntitySheep.java -index 2908e9cc47947daad19391d38da3c2a300f67fe5..a151d4295c02930687a23212647de60cce5405ca 100644 ---- a/src/main/java/net/minecraft/server/EntitySheep.java -+++ b/src/main/java/net/minecraft/server/EntitySheep.java -@@ -56,10 +56,23 @@ public class EntitySheep extends EntityAnimal implements IShearable { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.sheepRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.sheepRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { - this.bs = new PathfinderGoalEatTile(this); - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.25D)); - this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D)); - this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.1D, RecipeItemStack.a(Items.WHEAT), false)); -diff --git a/src/main/java/net/minecraft/server/EntityShulker.java b/src/main/java/net/minecraft/server/EntityShulker.java -index 49f6ee064fa7b79c7a9fd7a3344ed2334ce1f9f6..11a6b939ebb51cdda907531d30b7beb3a8562673 100644 ---- a/src/main/java/net/minecraft/server/EntityShulker.java -+++ b/src/main/java/net/minecraft/server/EntityShulker.java -@@ -30,12 +30,26 @@ public class EntityShulker extends EntityGolem implements IMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityShulker.java b/src/main/java/net/minecraft/world/entity/monster/EntityShulker.java +index bfecaa56c3d93436d71082f1398e0ceb12336e38..0294ab119407dc45a40c8444fb5a91e154017234 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityShulker.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityShulker.java +@@ -12,6 +12,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.sounds.SoundCategory; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -71,12 +72,26 @@ public class EntityShulker extends EntityGolem implements IMonster { this.f = 5; } @@ -3572,7 +4493,7 @@ index 49f6ee064fa7b79c7a9fd7a3344ed2334ce1f9f6..11a6b939ebb51cdda907531d30b7beb3 this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[0])).a(new Class[0])); // CraftBukkit - decompile error this.targetSelector.a(2, new EntityShulker.d(this)); this.targetSelector.a(3, new EntityShulker.c(this)); -@@ -519,7 +533,7 @@ public class EntityShulker extends EntityGolem implements IMonster { +@@ -560,7 +575,7 @@ public class EntityShulker extends EntityGolem implements IMonster { private int b; @@ -3581,11 +4502,19 @@ index 49f6ee064fa7b79c7a9fd7a3344ed2334ce1f9f6..11a6b939ebb51cdda907531d30b7beb3 @Override public boolean a() { -diff --git a/src/main/java/net/minecraft/server/EntitySilverfish.java b/src/main/java/net/minecraft/server/EntitySilverfish.java -index 28b490cc14f5881eb83acfbd6f30f9163ffe1926..ad428e090089a461283445022b33313520585ac5 100644 ---- a/src/main/java/net/minecraft/server/EntitySilverfish.java -+++ b/src/main/java/net/minecraft/server/EntitySilverfish.java -@@ -11,13 +11,27 @@ public class EntitySilverfish extends EntityMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java b/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java +index e1fcb1be102822e87eaf7757fbd64a516b2f58ac..c0601af022d85c7b03463f0df975d713c0366b2c 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java +@@ -4,6 +4,7 @@ import java.util.EnumSet; + import java.util.Random; + import net.minecraft.core.BlockPosition; + import net.minecraft.core.EnumDirection; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.world.damagesource.DamageSource; +@@ -38,13 +39,27 @@ public class EntitySilverfish extends EntityMonster { super(entitytypes, world); } @@ -3613,7 +4542,7 @@ index 28b490cc14f5881eb83acfbd6f30f9163ffe1926..ad428e090089a461283445022b333135 this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[0])).a(new Class[0])); // CraftBukkit - decompile error this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); } -@@ -177,6 +191,7 @@ public class EntitySilverfish extends EntityMonster { +@@ -204,6 +219,7 @@ public class EntitySilverfish extends EntityMonster { public PathfinderGoalSilverfishWakeOthers(EntitySilverfish entitysilverfish) { this.silverfish = entitysilverfish; @@ -3621,11 +4550,11 @@ index 28b490cc14f5881eb83acfbd6f30f9163ffe1926..ad428e090089a461283445022b333135 } public void g() { -diff --git a/src/main/java/net/minecraft/server/EntitySkeleton.java b/src/main/java/net/minecraft/server/EntitySkeleton.java -index 7c39bec8314a3db63a90ccc9f040b82d754705e2..3f130e03bf8b235360385fd169d4886ffcfa626a 100644 ---- a/src/main/java/net/minecraft/server/EntitySkeleton.java -+++ b/src/main/java/net/minecraft/server/EntitySkeleton.java -@@ -6,6 +6,18 @@ public class EntitySkeleton extends EntitySkeletonAbstract { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeleton.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeleton.java +index 342bc9b586ef835e865d6f84bf66f1069ab10f00..0b8517d4e83d14ddf8b6d1f1cf4c538f9e4cc68f 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeleton.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeleton.java +@@ -15,6 +15,18 @@ public class EntitySkeleton extends EntitySkeletonAbstract { super(entitytypes, world); } @@ -3644,11 +4573,19 @@ index 7c39bec8314a3db63a90ccc9f040b82d754705e2..3f130e03bf8b235360385fd169d4886f @Override protected SoundEffect getSoundAmbient() { return SoundEffects.ENTITY_SKELETON_AMBIENT; -diff --git a/src/main/java/net/minecraft/server/EntitySkeletonAbstract.java b/src/main/java/net/minecraft/server/EntitySkeletonAbstract.java -index f73304240a626f3f7d9355e6e5f2963a06c4bb7d..ee4c26de15a5c304889f38f49f4584e8d4ccc5fe 100644 ---- a/src/main/java/net/minecraft/server/EntitySkeletonAbstract.java -+++ b/src/main/java/net/minecraft/server/EntitySkeletonAbstract.java -@@ -28,12 +28,14 @@ public abstract class EntitySkeletonAbstract extends EntityMonster implements IR +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java +index 06d50b22ede102556fdb3e2a6f1424f7ff13f120..7ec60987229927e5fe7164f1d4eae8222832e920 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java +@@ -5,6 +5,7 @@ import java.time.temporal.ChronoField; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPosition; + import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.util.MathHelper; +@@ -70,12 +71,14 @@ public abstract class EntitySkeletonAbstract extends EntityMonster implements IR @Override protected void initPathfinder() { @@ -3663,11 +4600,11 @@ index f73304240a626f3f7d9355e6e5f2963a06c4bb7d..ee4c26de15a5c304889f38f49f4584e8 this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, new Class[0])); this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityIronGolem.class, true)); -diff --git a/src/main/java/net/minecraft/server/EntitySkeletonStray.java b/src/main/java/net/minecraft/server/EntitySkeletonStray.java -index f985caada082eff6183d7bc9868b1782f9529eaf..d123fb82b635d5271bea9b238554a3011858eeae 100644 ---- a/src/main/java/net/minecraft/server/EntitySkeletonStray.java -+++ b/src/main/java/net/minecraft/server/EntitySkeletonStray.java -@@ -8,6 +8,18 @@ public class EntitySkeletonStray extends EntitySkeletonAbstract { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonStray.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonStray.java +index 8481b8fffed3f1f60e2e72e115e79e9ae1aaa635..8484000a1b0d9c252d6fab205b1e316e3f6f33bd 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonStray.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonStray.java +@@ -21,6 +21,18 @@ public class EntitySkeletonStray extends EntitySkeletonAbstract { super(entitytypes, world); } @@ -3686,11 +4623,11 @@ index f985caada082eff6183d7bc9868b1782f9529eaf..d123fb82b635d5271bea9b238554a301 public static boolean a(EntityTypes entitytypes, WorldAccess worldaccess, EnumMobSpawn enummobspawn, BlockPosition blockposition, Random random) { return b(entitytypes, worldaccess, enummobspawn, blockposition, random) && (enummobspawn == EnumMobSpawn.SPAWNER || worldaccess.e(blockposition)); } -diff --git a/src/main/java/net/minecraft/server/EntitySkeletonWither.java b/src/main/java/net/minecraft/server/EntitySkeletonWither.java -index c872be77a6cd767520d5412b38ec4ed4fa87ac2f..96cb080d940db22330598a8806726088b79a53c1 100644 ---- a/src/main/java/net/minecraft/server/EntitySkeletonWither.java -+++ b/src/main/java/net/minecraft/server/EntitySkeletonWither.java -@@ -9,6 +9,18 @@ public class EntitySkeletonWither extends EntitySkeletonAbstract { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java +index a90ac635ef7aef5289d21f948db7b170b23160d3..cb52c4e63ac487d55dc16accca6976f44f904112 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java +@@ -34,6 +34,18 @@ public class EntitySkeletonWither extends EntitySkeletonAbstract { this.a(PathType.LAVA, 8.0F); } @@ -3709,11 +4646,19 @@ index c872be77a6cd767520d5412b38ec4ed4fa87ac2f..96cb080d940db22330598a8806726088 @Override protected void initPathfinder() { this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityPiglinAbstract.class, true)); -diff --git a/src/main/java/net/minecraft/server/EntitySlime.java b/src/main/java/net/minecraft/server/EntitySlime.java -index 80fab9290479f876fd78997c1bd55fe6b00aac45..7f3d57a9399f60465fae27f03fc57df625f5016d 100644 ---- a/src/main/java/net/minecraft/server/EntitySlime.java -+++ b/src/main/java/net/minecraft/server/EntitySlime.java -@@ -35,12 +35,45 @@ public class EntitySlime extends EntityInsentient implements IMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java +index 0af0b232ff1b6f1d58cf3fb543d32bd108be0af7..0cbe3032fd3b048b0eb8ec3d8592a662c69c9e30 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java +@@ -14,6 +14,7 @@ import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; + import net.minecraft.resources.MinecraftKey; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.util.MathHelper; +@@ -74,12 +75,45 @@ public class EntitySlime extends EntityInsentient implements IMonster { this.moveController = new EntitySlime.ControllerMoveSlime(this); } @@ -3759,7 +4704,7 @@ index 80fab9290479f876fd78997c1bd55fe6b00aac45..7f3d57a9399f60465fae27f03fc57df6 this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, (entityliving) -> { return Math.abs(entityliving.locY() - this.locY()) <= 4.0D; })); -@@ -326,11 +359,12 @@ public class EntitySlime extends EntityInsentient implements IMonster { +@@ -365,11 +399,12 @@ public class EntitySlime extends EntityInsentient implements IMonster { } @Override @@ -3773,7 +4718,7 @@ index 80fab9290479f876fd78997c1bd55fe6b00aac45..7f3d57a9399f60465fae27f03fc57df6 } @Nullable -@@ -499,10 +533,10 @@ public class EntitySlime extends EntityInsentient implements IMonster { +@@ -538,10 +573,10 @@ public class EntitySlime extends EntityInsentient implements IMonster { // Paper end } @@ -3786,7 +4731,7 @@ index 80fab9290479f876fd78997c1bd55fe6b00aac45..7f3d57a9399f60465fae27f03fc57df6 private final EntitySlime k; private boolean l; -@@ -524,15 +558,27 @@ public class EntitySlime extends EntityInsentient implements IMonster { +@@ -563,15 +598,27 @@ public class EntitySlime extends EntityInsentient implements IMonster { @Override public void a() { @@ -3816,7 +4761,7 @@ index 80fab9290479f876fd78997c1bd55fe6b00aac45..7f3d57a9399f60465fae27f03fc57df6 if (this.j-- <= 0) { this.j = this.k.eJ(); if (this.l) { -@@ -549,7 +595,7 @@ public class EntitySlime extends EntityInsentient implements IMonster { +@@ -588,7 +635,7 @@ public class EntitySlime extends EntityInsentient implements IMonster { this.a.q(0.0F); } } else { @@ -3825,68 +4770,19 @@ index 80fab9290479f876fd78997c1bd55fe6b00aac45..7f3d57a9399f60465fae27f03fc57df6 } } -diff --git a/src/main/java/net/minecraft/server/EntitySnowman.java b/src/main/java/net/minecraft/server/EntitySnowman.java -index c39f3c06eb199a24f32a5c581e877073b580502c..e370de0ade49ac81d746588bf0991101eba0ce2d 100644 ---- a/src/main/java/net/minecraft/server/EntitySnowman.java -+++ b/src/main/java/net/minecraft/server/EntitySnowman.java -@@ -14,12 +14,26 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.snowGolemRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.snowGolemRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new PathfinderGoalArrowAttack(this, 1.25D, 20, 10.0F)); - this.goalSelector.a(2, new PathfinderGoalRandomStrollLand(this, 1.0D, 1.0000001E-5F)); - this.goalSelector.a(3, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F)); - this.goalSelector.a(4, new PathfinderGoalRandomLookaround(this)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityInsentient.class, 10, true, false, (entityliving) -> { - return entityliving instanceof IMonster; - })); -@@ -71,6 +85,7 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt - return; - } - -+ if (hasRider() && !world.purpurConfig.snowGolemLeaveTrailWhenRidden) return; // Purpur - don't leave snow trail when being ridden - IBlockData iblockdata = Blocks.SNOW.getBlockData(); - - for (int l = 0; l < 4; ++l) { -@@ -113,7 +128,7 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt - if (itemstack.getItem() == Items.SHEARS && this.canShear()) { - // CraftBukkit start - if (!CraftEventFactory.handlePlayerShearEntityEvent(entityhuman, this, itemstack, enumhand)) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); // Purpur - } - // CraftBukkit end - this.shear(SoundCategory.PLAYERS); -@@ -133,7 +148,7 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt - return EnumInteractionResult.SUCCESS; - // Purpur end - } else { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); // Purpur - } - } - -diff --git a/src/main/java/net/minecraft/server/EntitySpider.java b/src/main/java/net/minecraft/server/EntitySpider.java -index bf68efd52f607ae353d6f84d4896926e16740523..92d74137877d096970bf9d1b4fc91beabb862b9d 100644 ---- a/src/main/java/net/minecraft/server/EntitySpider.java -+++ b/src/main/java/net/minecraft/server/EntitySpider.java -@@ -11,14 +11,28 @@ public class EntitySpider extends EntityMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySpider.java b/src/main/java/net/minecraft/world/entity/monster/EntitySpider.java +index c7b443623f3dd90741e52216199d8ed90bcea6b3..fbf7c31f57f6dbfac997480eb7db55efc15ef4cc 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySpider.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySpider.java +@@ -7,6 +7,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.world.DifficultyDamageScaler; +@@ -50,14 +51,28 @@ public class EntitySpider extends EntityMonster { super(entitytypes, world); } @@ -3915,111 +4811,19 @@ index bf68efd52f607ae353d6f84d4896926e16740523..92d74137877d096970bf9d1b4fc91bea this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, new Class[0])); this.targetSelector.a(2, new EntitySpider.PathfinderGoalSpiderNearestAttackableTarget<>(this, EntityHuman.class)); this.targetSelector.a(3, new EntitySpider.PathfinderGoalSpiderNearestAttackableTarget<>(this, EntityIronGolem.class)); -diff --git a/src/main/java/net/minecraft/server/EntitySquid.java b/src/main/java/net/minecraft/server/EntitySquid.java -index 148e4b158734f136832e5c17bdc69634c0f294aa..70b952f10a2af547f58069977ee135469d02f84d 100644 ---- a/src/main/java/net/minecraft/server/EntitySquid.java -+++ b/src/main/java/net/minecraft/server/EntitySquid.java -@@ -26,17 +26,38 @@ public class EntitySquid extends EntityWaterAnimal { - } - - // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.squidRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return true; -+ } -+ - @Override - public AxisAlignedBB getAxisForFluidCheck() { - // Stops squids from floating just over the water - return this.getBoundingBox().shrink(0.001D).offsetY(world.purpurConfig.squidOffsetWaterCheck); - } -+ -+ private void rotateVectorAroundY(org.bukkit.util.Vector vector, double degrees) { -+ double rad = Math.toRadians(degrees); -+ double cos = Math.cos(rad); -+ double sine = Math.sin(rad); -+ double x = vector.getX(); -+ double z = vector.getZ(); -+ vector.setX(cos * x - sine * z); -+ vector.setZ(sine * x + cos * z); -+ } - // Purpur end - - @Override - protected void initPathfinder() { - this.goalSelector.a(0, new EntitySquid.PathfinderGoalSquid(this)); -- this.goalSelector.a(1, new EntitySquid.a()); -+ this.goalSelector.a(1, new PathfinderGoalHasRider(this)); // Purpur -+ this.goalSelector.a(2, new EntitySquid.a()); // Purpur - } - - public static AttributeProvider.Builder m() { -@@ -181,6 +202,7 @@ public class EntitySquid extends EntityWaterAnimal { - return blockposition.getY() > generatoraccess.getMinecraftWorld().spigotConfig.squidSpawnRangeMin && blockposition.getY() < maxHeight; // Spigot // Paper - } - -+ public void setMovementVector(float x, float y, float z) { a(x, y, z); } // Purpur - OBFHELPER - public void a(float f, float f1, float f2) { - this.bw = f; - this.bx = f1; -@@ -252,7 +274,7 @@ public class EntitySquid extends EntityWaterAnimal { - - class PathfinderGoalSquid extends PathfinderGoal { - -- private final EntitySquid b; -+ private final EntitySquid b; public EntitySquid getSquid() { return b; } // Purpur - OBFHELPER - - public PathfinderGoalSquid(EntitySquid entitysquid) { - this.b = entitysquid; -@@ -265,6 +287,38 @@ public class EntitySquid extends EntityWaterAnimal { - - @Override - public void e() { -+ // Purpur start -+ EntitySquid squid = getSquid(); -+ EntityHuman rider = squid.getRider(); -+ if (rider != null) { -+ if (rider.jumping) { -+ squid.onSpacebar(); -+ } -+ float forward = rider.getForward(); -+ float strafe = rider.getStrafe(); -+ float speed = (float) squid.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getValue() * 10F; -+ if (forward < 0.0F) { -+ speed *= -0.5; -+ } -+ org.bukkit.util.Vector dir = rider.getBukkitEntity().getEyeLocation().getDirection().normalize().multiply(speed / 20.0F); -+ if (strafe != 0.0F) { -+ if (forward == 0.0F) { -+ dir.setY(0); -+ rotateVectorAroundY(dir, strafe > 0.0F ? -90 : 90); -+ } else if (forward < 0.0F) { -+ rotateVectorAroundY(dir, strafe > 0.0F ? 45 : -45); -+ } else { -+ rotateVectorAroundY(dir, strafe > 0.0F ? -45 : 45); -+ } -+ } -+ if (forward != 0.0F || strafe != 0.0F) { -+ squid.setMovementVector((float) dir.getX(), (float) dir.getY(), (float) dir.getZ()); -+ } else { -+ squid.setMovementVector(0.0F, 0.0F, 0.0F); -+ } -+ return; -+ } -+ // Purpur end - int i = this.b.dd(); - - if (i > 100) { -diff --git a/src/main/java/net/minecraft/server/EntityStrider.java b/src/main/java/net/minecraft/server/EntityStrider.java -index f35203a5074f520f617f7756bbbc9eecdda08937..56b72132595db5bc9addf31aecde5c13c5fd44c2 100644 ---- a/src/main/java/net/minecraft/server/EntityStrider.java -+++ b/src/main/java/net/minecraft/server/EntityStrider.java -@@ -28,6 +28,18 @@ public class EntityStrider extends EntityAnimal implements ISteerable, ISaddleab +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java b/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java +index 5ce50c6fe788fbd6db95f6406bacbf218b7e691c..14dda6743ed9e6f4880bc560f7ba8892d8e84afe 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java +@@ -13,6 +13,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundCategory; + import net.minecraft.sounds.SoundEffect; +@@ -94,6 +95,18 @@ public class EntityStrider extends EntityAnimal implements ISteerable, ISaddleab this.a(PathType.DAMAGE_FIRE, 0.0F); } @@ -4038,7 +4842,7 @@ index f35203a5074f520f617f7756bbbc9eecdda08937..56b72132595db5bc9addf31aecde5c13 public static boolean c(EntityTypes entitytypes, GeneratorAccess generatoraccess, EnumMobSpawn enummobspawn, BlockPosition blockposition, Random random) { BlockPosition.MutableBlockPosition blockposition_mutableblockposition = blockposition.i(); -@@ -89,6 +101,7 @@ public class EntityStrider extends EntityAnimal implements ISteerable, ISaddleab +@@ -155,6 +168,7 @@ public class EntityStrider extends EntityAnimal implements ISteerable, ISaddleab @Override protected void initPathfinder() { this.bv = new PathfinderGoalPanic(this, 1.65D); @@ -4046,7 +4850,7 @@ index f35203a5074f520f617f7756bbbc9eecdda08937..56b72132595db5bc9addf31aecde5c13 this.goalSelector.a(1, this.bv); this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D)); this.bu = new PathfinderGoalTempt(this, 1.4D, false, EntityStrider.bp); -@@ -368,7 +381,7 @@ public class EntityStrider extends EntityAnimal implements ISteerable, ISaddleab +@@ -434,7 +448,7 @@ public class EntityStrider extends EntityAnimal implements ISteerable, ISaddleab if (!enuminteractionresult.a()) { ItemStack itemstack = entityhuman.b(enumhand); @@ -4055,128 +4859,19 @@ index f35203a5074f520f617f7756bbbc9eecdda08937..56b72132595db5bc9addf31aecde5c13 } else { if (flag && !this.isSilent()) { this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_STRIDER_EAT, this.getSoundCategory(), 1.0F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F); -diff --git a/src/main/java/net/minecraft/server/EntityTameableAnimal.java b/src/main/java/net/minecraft/server/EntityTameableAnimal.java -index 9e008d56bb88550f399008095734436a5ab768c7..8f227678dc4ab1b7369a0c76173b3f695a570620 100644 ---- a/src/main/java/net/minecraft/server/EntityTameableAnimal.java -+++ b/src/main/java/net/minecraft/server/EntityTameableAnimal.java -@@ -130,6 +130,7 @@ public abstract class EntityTameableAnimal extends EntityAnimal { - return this.i(entityliving) ? false : super.c(entityliving); - } - -+ public boolean isOwner(EntityLiving entityLiving) { return i(entityLiving); } // Purpur - OBFHELPER - public boolean i(EntityLiving entityliving) { - return entityliving == this.getOwner(); - } -diff --git a/src/main/java/net/minecraft/server/EntityTropicalFish.java b/src/main/java/net/minecraft/server/EntityTropicalFish.java -index 495c28ccb86a5645459c9265c90dfffb6972d604..2c9df356e685ea6f71653023fadcf7e287dcd46e 100644 ---- a/src/main/java/net/minecraft/server/EntityTropicalFish.java -+++ b/src/main/java/net/minecraft/server/EntityTropicalFish.java -@@ -19,6 +19,18 @@ public class EntityTropicalFish extends EntityFishSchool { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.tropicalFishRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return true; -+ } -+ // Purpur end -+ - @Override - protected void initDatawatcher() { - super.initDatawatcher(); -diff --git a/src/main/java/net/minecraft/server/EntityTurtle.java b/src/main/java/net/minecraft/server/EntityTurtle.java -index 4ad393bc99881d813e2b349fb929fc8e69631723..2b34e6cf3b86319bd2875d92b63902889fec32a8 100644 ---- a/src/main/java/net/minecraft/server/EntityTurtle.java -+++ b/src/main/java/net/minecraft/server/EntityTurtle.java -@@ -27,6 +27,18 @@ public class EntityTurtle extends EntityAnimal { - this.G = 1.0F; - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.turtleRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.turtleRidableInWater; -+ } -+ // Purpur end -+ - public void setHomePos(BlockPosition blockposition) { - this.datawatcher.set(EntityTurtle.bp, blockposition.immutableCopy()); // Paper - called with mutablepos... - } -@@ -135,12 +147,13 @@ public class EntityTurtle extends EntityAnimal { - - @Override - protected void initPathfinder() { -- this.goalSelector.a(0, new EntityTurtle.f(this, 1.2D)); -- this.goalSelector.a(1, new EntityTurtle.a(this, 1.0D)); -- this.goalSelector.a(1, new EntityTurtle.d(this, 1.0D)); -- this.goalSelector.a(2, new EntityTurtle.i(this, 1.1D, Blocks.SEAGRASS.getItem())); -- this.goalSelector.a(3, new EntityTurtle.c(this, 1.0D)); -- this.goalSelector.a(4, new EntityTurtle.b(this, 1.0D)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur -+ this.goalSelector.a(1, new EntityTurtle.f(this, 1.2D)); // Purpur -+ this.goalSelector.a(2, new EntityTurtle.a(this, 1.0D)); // Purpur -+ this.goalSelector.a(2, new EntityTurtle.d(this, 1.0D)); // Purpur -+ this.goalSelector.a(3, new EntityTurtle.i(this, 1.1D, Blocks.SEAGRASS.getItem())); // Purpur -+ this.goalSelector.a(4, new EntityTurtle.c(this, 1.0D)); // Purpur -+ this.goalSelector.a(5, new EntityTurtle.b(this, 1.0D)); // Purpur - this.goalSelector.a(7, new EntityTurtle.j(this, 1.0D)); - this.goalSelector.a(8, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(9, new EntityTurtle.h(this, 1.0D, 100)); -@@ -323,13 +336,15 @@ public class EntityTurtle extends EntityAnimal { - } - } - -- static class e extends ControllerMove { -+ static class e extends net.pl3x.purpur.controller.ControllerMoveWASD { // Purpur - -- private final EntityTurtle i; -+ private final EntityTurtle i; public EntityTurtle getTurtle() { return i; } // Purpur - OBFHELPER -+ private final net.pl3x.purpur.controller.ControllerMoveWASDWater waterController; // Purpur - - e(EntityTurtle entityturtle) { -- super(entityturtle); -+ super(entityturtle, 0.1D); // Purpur - this.i = entityturtle; -+ waterController = new net.pl3x.purpur.controller.ControllerMoveWASDWater(entityturtle, 0.25D); // Purpur - } - - private void g() { -@@ -349,7 +364,18 @@ public class EntityTurtle extends EntityAnimal { - } - - @Override -- public void a() { -+ // Purpur start -+ public void tick(EntityHuman rider) { -+ if (getTurtle().isInWater()) { -+ waterController.tick(rider); -+ } else { -+ super.tick(rider); -+ } -+ } -+ -+ @Override -+ public void tick() { -+ // Purpur end - this.g(); - if (this.h == ControllerMove.Operation.MOVE_TO && !this.i.getNavigation().m()) { - double d0 = this.b - this.i.locX(); -diff --git a/src/main/java/net/minecraft/server/EntityVex.java b/src/main/java/net/minecraft/server/EntityVex.java -index 9a33866e7529e1636c228bab01205737bc678b47..9336fbbd46c7c6ac11adf8e4cc2735f81c9ed639 100644 ---- a/src/main/java/net/minecraft/server/EntityVex.java -+++ b/src/main/java/net/minecraft/server/EntityVex.java -@@ -18,6 +18,45 @@ public class EntityVex extends EntityMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java +index 9645d052069957311478a1ceca42ad52f7a9aa0b..4301ece0a04f3f2b4d198a684d0ca314deef2aef 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java +@@ -7,6 +7,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.util.MathHelper; +@@ -54,6 +55,45 @@ public class EntityVex extends EntityMonster { this.f = 3; } @@ -4222,7 +4917,7 @@ index 9a33866e7529e1636c228bab01205737bc678b47..9336fbbd46c7c6ac11adf8e4cc2735f8 @Override public void move(EnumMoveType enummovetype, Vec3D vec3d) { super.move(enummovetype, vec3d); -@@ -26,7 +65,7 @@ public class EntityVex extends EntityMonster { +@@ -62,7 +102,7 @@ public class EntityVex extends EntityMonster { @Override public void tick() { @@ -4231,7 +4926,7 @@ index 9a33866e7529e1636c228bab01205737bc678b47..9336fbbd46c7c6ac11adf8e4cc2735f8 super.tick(); this.noclip = false; this.setNoGravity(true); -@@ -41,17 +80,19 @@ public class EntityVex extends EntityMonster { +@@ -77,17 +117,19 @@ public class EntityVex extends EntityMonster { protected void initPathfinder() { super.initPathfinder(); this.goalSelector.a(0, new PathfinderGoalFloat(this)); @@ -4252,7 +4947,7 @@ index 9a33866e7529e1636c228bab01205737bc678b47..9336fbbd46c7c6ac11adf8e4cc2735f8 } @Override -@@ -283,14 +324,14 @@ public class EntityVex extends EntityMonster { +@@ -319,14 +361,14 @@ public class EntityVex extends EntityMonster { } } @@ -4269,95 +4964,19 @@ index 9a33866e7529e1636c228bab01205737bc678b47..9336fbbd46c7c6ac11adf8e4cc2735f8 if (this.h == ControllerMove.Operation.MOVE_TO) { Vec3D vec3d = new Vec3D(this.b - EntityVex.this.locX(), this.c - EntityVex.this.locY(), this.d - EntityVex.this.locZ()); double d0 = vec3d.f(); -diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java -index 40085497e61c55789f3888a8a642c44cabed3466..00e3ed9374f9962ea619a104892a4c32b2638876 100644 ---- a/src/main/java/net/minecraft/server/EntityVillager.java -+++ b/src/main/java/net/minecraft/server/EntityVillager.java -@@ -73,8 +73,19 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - } - - // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.villagerRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.villagerRidableInWater; -+ } -+ - @Override - protected void initPathfinder() { -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - if (world.purpurConfig.villagerFollowEmeraldBlock) this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.0D, false, TEMPT_ITEMS)); - } - -@@ -245,7 +256,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - if (itemstack.getItem() != Items.VILLAGER_SPAWN_EGG && this.isAlive() && !this.eN() && !this.isSleeping()) { - if (this.isBaby()) { - this.fk(); -- return EnumInteractionResult.a(this.world.isClientSide); -+ return super.b(entityhuman, enumhand); // Purpur - } else { - boolean flag = this.getOffers().isEmpty(); - -@@ -258,8 +269,9 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - } - - if (flag) { -- return EnumInteractionResult.a(this.world.isClientSide); -+ return tryRide(entityhuman, enumhand); // Purpur - } else { -+ if (world.purpurConfig.villagerRidable && itemstack.isEmpty()) return tryRide(entityhuman, enumhand); // Purpur - if (!this.world.isClientSide && !this.trades.isEmpty()) { - this.h(entityhuman); - } -diff --git a/src/main/java/net/minecraft/server/EntityVillagerTrader.java b/src/main/java/net/minecraft/server/EntityVillagerTrader.java -index 432956d9d5f2706014d67232b88e6b86011484f3..b9418fac0a05d4bb5f8f215a5704bba332e3f7cb 100644 ---- a/src/main/java/net/minecraft/server/EntityVillagerTrader.java -+++ b/src/main/java/net/minecraft/server/EntityVillagerTrader.java -@@ -25,6 +25,7 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { - @Override - protected void initPathfinder() { - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(0, new PathfinderGoalUseItem<>(this, PotionUtil.a(new ItemStack(Items.POTION), Potions.INVISIBILITY), SoundEffects.ENTITY_WANDERING_TRADER_DISAPPEARED, (entityvillagertrader) -> { - return this.world.isNight() && !entityvillagertrader.isInvisible(); - })); -@@ -50,6 +51,16 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { - } - - // Purpur - start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.villagerTraderRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.villagerTraderRidableInWater; -+ } -+ - @Override - public boolean a(EntityHuman entityhuman) { - return world.purpurConfig.villagerTraderCanBeLeashed && !this.isLeashed(); -@@ -77,8 +88,9 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { - } - - if (this.getOffers().isEmpty()) { -- return EnumInteractionResult.a(this.world.isClientSide); -+ return tryRide(entityhuman, enumhand); // Purpur - } else { -+ if (world.purpurConfig.villagerTraderRidable && itemstack.isEmpty()) return tryRide(entityhuman, enumhand); // Purpur - if (!this.world.isClientSide) { - this.setTradingPlayer(entityhuman); - this.openTrade(entityhuman, this.getScoreboardDisplayName(), 1); -diff --git a/src/main/java/net/minecraft/server/EntityVindicator.java b/src/main/java/net/minecraft/server/EntityVindicator.java -index 23b350f793539672b6990327ed52e9bb3bdbf54e..f1bc6a4199d788215c2e7d5a835211d16603a6d9 100644 ---- a/src/main/java/net/minecraft/server/EntityVindicator.java -+++ b/src/main/java/net/minecraft/server/EntityVindicator.java -@@ -18,14 +18,28 @@ public class EntityVindicator extends EntityIllagerAbstract { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java +index fe84d6d2b74b6ae00c4c66682107296a40b69adc..28d345e87f45fa839bc3bd758f79f34aba546db7 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java +@@ -8,6 +8,7 @@ import javax.annotation.Nullable; + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.chat.ChatMessage; + import net.minecraft.network.chat.IChatBaseComponent; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -59,14 +60,28 @@ public class EntityVindicator extends EntityIllagerAbstract { super(entitytypes, world); } @@ -4386,11 +5005,19 @@ index 23b350f793539672b6990327ed52e9bb3bdbf54e..f1bc6a4199d788215c2e7d5a835211d1 this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // Paper - decompile fix this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, true)); -diff --git a/src/main/java/net/minecraft/server/EntityWitch.java b/src/main/java/net/minecraft/server/EntityWitch.java -index ca3c5150bcfe2a92b49ad5a27c23dd37a7054fbb..323d79a99402b0f6952b4fb873170069f3428953 100644 ---- a/src/main/java/net/minecraft/server/EntityWitch.java -+++ b/src/main/java/net/minecraft/server/EntityWitch.java -@@ -24,6 +24,18 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java +index 63fb08e7b4290353e5148d1acb58f091dc5b08be..c4663c5b02363bd1499ce1f3b50027f8aa7c68e7 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java +@@ -2,6 +2,7 @@ package net.minecraft.world.entity.monster; + + // Paper start + import com.destroystokyo.paper.event.entity.WitchReadyPotionEvent; ++import net.minecraft.server.PathfinderGoalHasRider; + import org.bukkit.craftbukkit.inventory.CraftItemStack; + import org.bukkit.entity.Witch; + // Paper end +@@ -63,6 +64,18 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { super(entitytypes, world); } @@ -4409,7 +5036,7 @@ index ca3c5150bcfe2a92b49ad5a27c23dd37a7054fbb..323d79a99402b0f6952b4fb873170069 @Override protected void initPathfinder() { super.initPathfinder(); -@@ -32,10 +44,12 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { +@@ -71,10 +84,12 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { }); this.bs = new PathfinderGoalNearestAttackableTargetWitch<>(this, EntityHuman.class, 10, true, false, (Predicate) null); this.goalSelector.a(1, new PathfinderGoalFloat(this)); @@ -4422,250 +5049,11 @@ index ca3c5150bcfe2a92b49ad5a27c23dd37a7054fbb..323d79a99402b0f6952b4fb873170069 this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})); this.targetSelector.a(2, this.br); this.targetSelector.a(3, this.bs); -diff --git a/src/main/java/net/minecraft/server/EntityWither.java b/src/main/java/net/minecraft/server/EntityWither.java -index 3230c5454ccc39a2e3c89fdf8ca015cf7a15f380..87b7d52bdba357fa59c7b6397cb49286fd8cc8ec 100644 ---- a/src/main/java/net/minecraft/server/EntityWither.java -+++ b/src/main/java/net/minecraft/server/EntityWither.java -@@ -32,6 +32,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - return entityliving.getMonsterType() != EnumMonsterType.UNDEAD && entityliving.ei(); - }; - private static final PathfinderTargetCondition bz = (new PathfinderTargetCondition()).a(20.0D).a(EntityWither.by); -+ private int shootCooldown = 0; // Purpur - // Paper start - private boolean canPortal = false; - -@@ -44,15 +45,122 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - this.setHealth(this.getMaxHealth()); - this.getNavigation().d(true); - this.f = 50; -+ this.moveController = new net.pl3x.purpur.controller.ControllerMoveWASDFlyingWithSpacebar(this, 0.1F); // Purpur - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.witherRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.witherRidableInWater; -+ } -+ -+ @Override -+ public double getMaxY() { -+ return world.purpurConfig.witherMaxY; -+ } -+ -+ @Override -+ public void g(Vec3D vec3d) { -+ super.g(vec3d); -+ if (hasRider() && !onGround) { -+ float speed = (float) getAttributeInstance(GenericAttributes.FLYING_SPEED).getValue() * 5F; -+ setSpeed(speed); -+ Vec3D mot = getMot(); -+ move(EnumMoveType.SELF, mot.multiply(speed, 0.5, speed)); -+ setMot(mot.a(0.9D)); -+ } -+ } -+ -+ @Override -+ public void onMount(EntityHuman entityhuman) { -+ super.onMount(entityhuman); -+ this.datawatcher.set(bo.get(0), 0); -+ this.datawatcher.set(bo.get(1), 0); -+ this.datawatcher.set(bo.get(2), 0); -+ getNavigation().stopPathfinding(); -+ shootCooldown = 20; -+ } -+ -+ @Override -+ public boolean onClick(EnumHand hand) { -+ return shoot(getRider(), hand == EnumHand.MAIN_HAND ? new int[]{1} : new int[]{2}); -+ } -+ -+ public boolean shoot(EntityHuman rider, int[] heads) { -+ if (shootCooldown > 0) { -+ return false; -+ } -+ -+ shootCooldown = 20; -+ if (rider == null) { -+ return false; -+ } -+ -+ org.bukkit.craftbukkit.entity.CraftHumanEntity player = rider.getBukkitEntity(); -+ if (!player.hasPermission("allow.special.wither")) { -+ return false; -+ } -+ -+ MovingObjectPosition rayTrace = getRayTrace(120, RayTrace.FluidCollisionOption.NONE); -+ if (rayTrace == null) { -+ return false; -+ } -+ -+ Vec3D loc; -+ if (rayTrace.getType() == MovingObjectPosition.EnumMovingObjectType.BLOCK) { -+ BlockPosition pos = ((MovingObjectPositionBlock) rayTrace).getBlockPosition(); -+ loc = new Vec3D(pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D); -+ } else if (rayTrace.getType() == MovingObjectPosition.EnumMovingObjectType.ENTITY) { -+ Entity target = ((MovingObjectPositionEntity) rayTrace).getEntity(); -+ loc = new Vec3D(target.locX(), target.locY() + (target.getHeadHeight() / 2), target.locZ()); -+ } else { -+ org.bukkit.block.Block block = player.getTargetBlock(null, 120); -+ loc = new Vec3D(block.getX() + 0.5D, block.getY() + 0.5D, block.getZ() + 0.5D); -+ } -+ -+ for (int head : heads) { -+ shoot(head, loc.getX(), loc.getY(), loc.getZ(), rider); -+ } -+ -+ return true; // handled -+ } -+ -+ public void shoot(int head, double x, double y, double z, EntityHuman rider) { -+ world.playEvent(null, 1024, getChunkCoordinates(), 0); -+ double headX = getHeadX(head); -+ double headY = getHeadY(head); -+ double headZ = getHeadZ(head); -+ EntityWitherSkull skull = new EntityWitherSkull(world, this, x - headX, y - headY, z - headZ) { -+ @Override -+ public boolean canSaveToDisk() { -+ return false; -+ } -+ -+ @Override -+ public boolean hitPredicate(Entity target) { -+ // do not hit rider -+ return target != rider && super.hitPredicate(target); -+ } -+ }; -+ skull.setPositionRaw(headX, headY, headZ); -+ world.addEntity(skull); -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { -- this.goalSelector.a(0, new EntityWither.a()); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur -+ this.goalSelector.a(1, new EntityWither.a()); // Purpur - this.goalSelector.a(2, new PathfinderGoalArrowAttack(this, 1.0D, 40, 20.0F)); - this.goalSelector.a(5, new PathfinderGoalRandomStrollLand(this, 1.0D)); - this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(7, new PathfinderGoalRandomLookaround(this)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, new Class[0])); - if(this.world.paperConfig.fixWitherTargetingBug) this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 0, false, false, null)); // Paper - Fix MC-29274 - this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityInsentient.class, 0, false, false, EntityWither.by)); -@@ -195,6 +303,16 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - - @Override - protected void mobTick() { -+ // Purpur start -+ if (hasRider()) { -+ Vec3D mot = getMot(); -+ setMot(mot.x, mot.y + (getVertical() > 0 ? 0.07D : 0.0D), mot.z); -+ } -+ if (shootCooldown > 0) { -+ shootCooldown--; -+ } -+ // Purpur end -+ - int i; - - if (this.getInvul() > 0) { -@@ -378,7 +496,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - this.bossBattle.removePlayer(entityplayer); - } - -- private double u(int i) { -+ private double u(int i) { return getHeadX(i); } private double getHeadX(int i) { // Purpur - OBFHELPER - if (i <= 0) { - return this.locX(); - } else { -@@ -389,11 +507,11 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - } - } - -- private double v(int i) { -+ private double v(int i) { return getHeadY(i); } private double getHeadY(int i) { // Purpur - OBFHELPER - return i <= 0 ? this.locY() + 3.0D : this.locY() + 2.2D; - } - -- private double w(int i) { -+ private double w(int i) { return getHeadZ(i); } private double getHeadZ(int i) { // Purpur - OBFHELPER - if (i <= 0) { - return this.locZ(); - } else { -@@ -517,7 +635,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - } - - public static AttributeProvider.Builder eK() { -- return EntityMonster.eR().a(GenericAttributes.MAX_HEALTH, 300.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.6000000238418579D).a(GenericAttributes.FOLLOW_RANGE, 40.0D).a(GenericAttributes.ARMOR, 4.0D); -+ return EntityMonster.eR().a(GenericAttributes.MAX_HEALTH, 300.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.6000000238418579D).a(GenericAttributes.FOLLOW_RANGE, 40.0D).a(GenericAttributes.ARMOR, 4.0D).a(GenericAttributes.FLYING_SPEED, 0.6D); // Purpur - } - - public int getInvul() { -@@ -529,11 +647,11 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - } - - public int getHeadTarget(int i) { -- return (Integer) this.datawatcher.get((DataWatcherObject) EntityWither.bo.get(i)); -+ return hasRider() ? 0 : this.datawatcher.get(EntityWither.bo.get(i)); // Purpur - } - - public void setHeadTarget(int i, int j) { -- this.datawatcher.set((DataWatcherObject) EntityWither.bo.get(i), j); -+ if (!hasRider()) this.datawatcher.set(EntityWither.bo.get(i), j); // Purpur - } - - public final boolean isPowered() { return this.S_(); } // Paper - OBFHELPER -diff --git a/src/main/java/net/minecraft/server/EntityWolf.java b/src/main/java/net/minecraft/server/EntityWolf.java -index dcbb34313fedb21e180a0b76610a787e6419d404..9ae7168595dd66860e09ef87f946b18b010e54b1 100644 ---- a/src/main/java/net/minecraft/server/EntityWolf.java -+++ b/src/main/java/net/minecraft/server/EntityWolf.java -@@ -33,9 +33,27 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable - this.setTamed(false); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.wolfRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.wolfRidableInWater; -+ } -+ -+ public void onMount(EntityHuman entityhuman) { -+ super.onMount(entityhuman); -+ setSitting(false); -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { - this.goalSelector.a(1, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(1, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(2, new PathfinderGoalSit(this)); - this.goalSelector.a(3, new EntityWolf.a<>(this, EntityLlama.class, 24.0F, 1.5D, 1.5D)); - this.goalSelector.a(4, new PathfinderGoalLeapAtTarget(this, 0.4F)); -@@ -46,6 +64,7 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable - this.goalSelector.a(9, new PathfinderGoalBeg(this, 8.0F)); - this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(10, new PathfinderGoalRandomLookaround(this)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new PathfinderGoalOwnerHurtByTarget(this)); - this.targetSelector.a(2, new PathfinderGoalOwnerHurtTarget(this)); - this.targetSelector.a(3, (new PathfinderGoalHurtByTarget(this, new Class[0])).a(new Class[0])); // CraftBukkit - decompile error -diff --git a/src/main/java/net/minecraft/server/EntityZoglin.java b/src/main/java/net/minecraft/server/EntityZoglin.java -index e76e6ebde73b93dc06e76b71cdf6371c3654160a..d92fe8013fb3b43cb7eabdf1c624291b7e881889 100644 ---- a/src/main/java/net/minecraft/server/EntityZoglin.java -+++ b/src/main/java/net/minecraft/server/EntityZoglin.java -@@ -21,6 +21,18 @@ public class EntityZoglin extends EntityMonster implements IMonster, IOglin { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZoglin.java b/src/main/java/net/minecraft/world/entity/monster/EntityZoglin.java +index aed585e2c1c88a4d09318c6be7ebe7168eac3631..c5b1ce9268d6e6f3ec26eda4b5d8e7ae2a2ea672 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityZoglin.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityZoglin.java +@@ -62,6 +62,18 @@ public class EntityZoglin extends EntityMonster implements IMonster, IOglin { this.f = 5; } @@ -4684,7 +5072,7 @@ index e76e6ebde73b93dc06e76b71cdf6371c3654160a..d92fe8013fb3b43cb7eabdf1c624291b @Override protected BehaviorController.b cK() { return BehaviorController.a((Collection) EntityZoglin.c, (Collection) EntityZoglin.b); -@@ -52,10 +64,10 @@ public class EntityZoglin extends EntityMonster implements IMonster, IOglin { +@@ -93,10 +105,10 @@ public class EntityZoglin extends EntityMonster implements IMonster, IOglin { } private Optional eO() { @@ -4697,7 +5085,7 @@ index e76e6ebde73b93dc06e76b71cdf6371c3654160a..d92fe8013fb3b43cb7eabdf1c624291b EntityTypes entitytypes = entityliving.getEntityType(); return entitytypes != EntityTypes.ZOGLIN && entitytypes != EntityTypes.CREEPER && IEntitySelector.f.test(entityliving); -@@ -140,14 +152,14 @@ public class EntityZoglin extends EntityMonster implements IMonster, IOglin { +@@ -181,14 +193,14 @@ public class EntityZoglin extends EntityMonster implements IMonster, IOglin { @Override public BehaviorController getBehaviorController() { @@ -4715,7 +5103,7 @@ index e76e6ebde73b93dc06e76b71cdf6371c3654160a..d92fe8013fb3b43cb7eabdf1c624291b if (activity1 == Activity.FLIGHT && activity != Activity.FLIGHT) { this.eN(); -@@ -159,7 +171,8 @@ public class EntityZoglin extends EntityMonster implements IMonster, IOglin { +@@ -200,7 +212,8 @@ public class EntityZoglin extends EntityMonster implements IMonster, IOglin { @Override protected void mobTick() { this.world.getMethodProfiler().enter("zoglinBrain"); @@ -4725,11 +5113,19 @@ index e76e6ebde73b93dc06e76b71cdf6371c3654160a..d92fe8013fb3b43cb7eabdf1c624291b this.world.getMethodProfiler().exit(); this.eL(); } -diff --git a/src/main/java/net/minecraft/server/EntityZombie.java b/src/main/java/net/minecraft/server/EntityZombie.java -index 291748b3436c18653fa959cfd8c92240aa17508c..2076fe3e467c16bb400a75f9ea82f5b0773126be 100644 ---- a/src/main/java/net/minecraft/server/EntityZombie.java -+++ b/src/main/java/net/minecraft/server/EntityZombie.java -@@ -46,6 +46,16 @@ public class EntityZombie extends EntityMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +index 5ac950614fc90d02a568bb38f71faee124584c16..901fe8d224130c67bad00636b065bc798859a18e 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +@@ -16,6 +16,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundCategory; + import net.minecraft.sounds.SoundEffect; +@@ -108,6 +109,16 @@ public class EntityZombie extends EntityMonster { } // Purpur start @@ -4746,7 +5142,7 @@ index 291748b3436c18653fa959cfd8c92240aa17508c..2076fe3e467c16bb400a75f9ea82f5b0 public boolean jockeyOnlyBaby() { return world.purpurConfig.zombieJockeyOnlyBaby; } -@@ -61,9 +71,11 @@ public class EntityZombie extends EntityMonster { +@@ -123,9 +134,11 @@ public class EntityZombie extends EntityMonster { @Override protected void initPathfinder() { @@ -4758,11 +5154,11 @@ index 291748b3436c18653fa959cfd8c92240aa17508c..2076fe3e467c16bb400a75f9ea82f5b0 this.m(); } -diff --git a/src/main/java/net/minecraft/server/EntityZombieHusk.java b/src/main/java/net/minecraft/server/EntityZombieHusk.java -index ce6d79780197eb9300130036a8ed84648a17f9cf..02b0ae550a0ed33b5b43beedf3b1405985c58c13 100644 ---- a/src/main/java/net/minecraft/server/EntityZombieHusk.java -+++ b/src/main/java/net/minecraft/server/EntityZombieHusk.java -@@ -9,6 +9,16 @@ public class EntityZombieHusk extends EntityZombie { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java +index 5d3e5873f19aaf8389eb5525693b9378ea9f94ee..ad801fc394fbb83cf280ee96f962e7f311615d72 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java +@@ -23,6 +23,16 @@ public class EntityZombieHusk extends EntityZombie { } // Purpur start @@ -4779,11 +5175,11 @@ index ce6d79780197eb9300130036a8ed84648a17f9cf..02b0ae550a0ed33b5b43beedf3b14059 @Override public boolean jockeyOnlyBaby() { return world.purpurConfig.huskJockeyOnlyBaby; -diff --git a/src/main/java/net/minecraft/server/EntityZombieVillager.java b/src/main/java/net/minecraft/server/EntityZombieVillager.java -index 5a71381c9f1832710001b6bfa63d6815c3cd1ab0..5b6ed77fb2b92b5bf701de436c8d7235bfe82685 100644 ---- a/src/main/java/net/minecraft/server/EntityZombieVillager.java -+++ b/src/main/java/net/minecraft/server/EntityZombieVillager.java -@@ -29,6 +29,16 @@ public class EntityZombieVillager extends EntityZombie implements VillagerDataHo +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java +index 167ea96ec4072a9415a2ae9d7a0db118bfb94e19..6b2fd555122ba1af0adae3e479540e0da767a99d 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java +@@ -71,6 +71,16 @@ public class EntityZombieVillager extends EntityZombie implements VillagerDataHo } // Purpur start @@ -4800,23 +5196,235 @@ index 5a71381c9f1832710001b6bfa63d6815c3cd1ab0..5b6ed77fb2b92b5bf701de436c8d7235 @Override public boolean jockeyOnlyBaby() { return world.purpurConfig.zombieVillagerJockeyOnlyBaby; -diff --git a/src/main/java/net/minecraft/server/GeneratorAccess.java b/src/main/java/net/minecraft/server/GeneratorAccess.java -index cbc0b8bc854ab1b0ba95fa0a2041385f440718d9..89d64ea0d1e61dfce622df026209af129efd5773 100644 ---- a/src/main/java/net/minecraft/server/GeneratorAccess.java -+++ b/src/main/java/net/minecraft/server/GeneratorAccess.java -@@ -37,6 +37,7 @@ public interface GeneratorAccess extends ICombinedAccess, IWorldTime { +diff --git a/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java b/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java +index 9aa4850e021076fde306eea7eec104c31086c57f..64253428ef66145d07f74f8d0e5bdeb5aa5fe02b 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java ++++ b/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java +@@ -61,6 +61,18 @@ public class EntityHoglin extends EntityAnimal implements IMonster, IOglin { + this.f = 5; + } - void addParticle(ParticleParam particleparam, double d0, double d1, double d2, double d3, double d4, double d5); ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.hoglinRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.hoglinRidableInWater; ++ } ++ // Purpur end ++ + @Override + public boolean a(EntityHuman entityhuman) { + return !this.isLeashed(); +@@ -127,6 +139,7 @@ public class EntityHoglin extends EntityAnimal implements IMonster, IOglin { + // Airplane - dynamic tick + if (!gg.airplane.AirplaneConfig.dynamicHoglinBehavior || this.behaviorTick++ % this.activatedPriority == 0) { + this.world.getMethodProfiler().enter("hoglinBrain"); ++ if (getRider() == null) // Purpur - only use brain if no rider + this.getBehaviorController().a((WorldServer) this.world, (EntityHoglin) this); // Airplane - decompile error + this.world.getMethodProfiler().exit(); + HoglinAI.a(this); +diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java +index 48acef830eb1d919499e9b79dc6a9af4bdf8a17b..8c6f5273ed2ab4ec63b7854e290f790b2eca8c2f 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java ++++ b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java +@@ -70,6 +70,18 @@ public class EntityPiglin extends EntityPiglinAbstract implements ICrossbow { + this.f = 5; + } -+ default void playEvent(@Nullable EntityHuman entityhuman, int i, BlockPosition blockposition, int j) { a(entityhuman, i, blockposition, j); } // Purpur - OBFHELPER - void a(@Nullable EntityHuman entityhuman, int i, BlockPosition blockposition, int j); ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.piglinRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.piglinRidableInWater; ++ } ++ // Purpur end ++ + @Override + public void saveData(NBTTagCompound nbttagcompound) { + super.saveData(nbttagcompound); +@@ -250,6 +262,7 @@ public class EntityPiglin extends EntityPiglinAbstract implements ICrossbow { + // Airplane - dynamic tick + if (!gg.airplane.AirplaneConfig.dynamicPiglinBehavior || this.behaviorTick++ % this.activatedPriority == 0) { + this.world.getMethodProfiler().enter("piglinBrain"); ++ if (getRider() == null) // Purpur - only use brain if no rider + this.getBehaviorController().a((WorldServer) this.world, (EntityPiglin) this); // Airplane - compile error + this.world.getMethodProfiler().exit(); + PiglinAI.b(this); +diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglinBrute.java b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglinBrute.java +index 3d85501791fce621335f34bf508becb74b80210d..da2220b08a9cd9c2d7d3fd06702e6690e12f095e 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglinBrute.java ++++ b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglinBrute.java +@@ -39,6 +39,18 @@ public class EntityPiglinBrute extends EntityPiglinAbstract { + this.f = 20; + } - default int getHeight() { -diff --git a/src/main/java/net/minecraft/server/IProjectile.java b/src/main/java/net/minecraft/server/IProjectile.java -index dc9f2a1a132b3a7925bd62aa1da0512afd90b8b1..b7e540dfeeabb13227596ecfc6eddabf3cfde537 100644 ---- a/src/main/java/net/minecraft/server/IProjectile.java -+++ b/src/main/java/net/minecraft/server/IProjectile.java -@@ -12,7 +12,7 @@ public abstract class IProjectile extends Entity { ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.piglinBruteRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.piglinBruteRidableInWater; ++ } ++ // Purpur end ++ + public static AttributeProvider.Builder eS() { + return EntityMonster.eR().a(GenericAttributes.MAX_HEALTH, 50.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.3499999940395355D).a(GenericAttributes.ATTACK_DAMAGE, 7.0D); + } +@@ -68,7 +80,7 @@ public class EntityPiglinBrute extends EntityPiglinAbstract { + + @Override + public BehaviorController getBehaviorController() { +- return super.getBehaviorController(); ++ return (BehaviorController) super.getBehaviorController(); // Purpur - decompile error + } + + @Override +@@ -84,7 +96,8 @@ public class EntityPiglinBrute extends EntityPiglinAbstract { + @Override + protected void mobTick() { + this.world.getMethodProfiler().enter("piglinBruteBrain"); +- this.getBehaviorController().a((WorldServer) this.world, (EntityLiving) this); ++ if (getRider() == null) // Purpur - only use brain if no rider ++ this.getBehaviorController().a((WorldServer) this.world, this); // Purpur - decompile error + this.world.getMethodProfiler().exit(); + PiglinBruteAI.b(this); + PiglinBruteAI.c(this); +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +index d3032682af94428419daa02f55b6040090d8df73..a0f0d5e0909da5cfe87078d4722b030635cfeadd 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +@@ -32,6 +32,7 @@ import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; + import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -145,8 +146,19 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + } + + // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.villagerRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.villagerRidableInWater; ++ } ++ + @Override + protected void initPathfinder() { ++ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + if (world.purpurConfig.villagerFollowEmeraldBlock) this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.0D, false, TEMPT_ITEMS)); + } + +@@ -317,7 +329,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + if (itemstack.getItem() != Items.VILLAGER_SPAWN_EGG && this.isAlive() && !this.eN() && !this.isSleeping()) { + if (this.isBaby()) { + this.fk(); +- return EnumInteractionResult.a(this.world.isClientSide); ++ return super.b(entityhuman, enumhand); // Purpur + } else { + boolean flag = this.getOffers().isEmpty(); + +@@ -330,8 +342,9 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + } + + if (flag) { +- return EnumInteractionResult.a(this.world.isClientSide); ++ return tryRide(entityhuman, enumhand); // Purpur + } else { ++ if (world.purpurConfig.villagerRidable && itemstack.isEmpty()) return tryRide(entityhuman, enumhand); // Purpur + if (!this.world.isClientSide && !this.trades.isEmpty()) { + this.h(entityhuman); + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java +index e0324cdb2d4c85714eaad490a7a5c826b38e6b16..90cbef7fe8803295f82bddd6709fdf303aedcaba 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java +@@ -6,6 +6,7 @@ import net.minecraft.core.BlockPosition; + import net.minecraft.core.IPosition; + import net.minecraft.nbt.GameProfileSerializer; + import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.server.PathfinderGoalHasRider; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -69,6 +70,7 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { + @Override + protected void initPathfinder() { + this.goalSelector.a(0, new PathfinderGoalFloat(this)); ++ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + this.goalSelector.a(0, new PathfinderGoalUseItem<>(this, PotionUtil.a(new ItemStack(Items.POTION), Potions.INVISIBILITY), SoundEffects.ENTITY_WANDERING_TRADER_DISAPPEARED, (entityvillagertrader) -> { + return this.world.isNight() && !entityvillagertrader.isInvisible(); + })); +@@ -94,6 +96,16 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { + } + + // Purpur - start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.villagerTraderRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.villagerTraderRidableInWater; ++ } ++ + @Override + public boolean a(EntityHuman entityhuman) { + return world.purpurConfig.villagerTraderCanBeLeashed && !this.isLeashed(); +@@ -121,8 +133,9 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { + } + + if (this.getOffers().isEmpty()) { +- return EnumInteractionResult.a(this.world.isClientSide); ++ return tryRide(entityhuman, enumhand); // Purpur + } else { ++ if (world.purpurConfig.villagerTraderRidable && itemstack.isEmpty()) return tryRide(entityhuman, enumhand); // Purpur + if (!this.world.isClientSide) { + this.setTradingPlayer(entityhuman); + this.openTrade(entityhuman, this.getScoreboardDisplayName(), 1); +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index 2ee7daa155d812af8f84ba646106d801d2fb0fec..1062317c22171bccee78a2db1841e0fd2b3023d7 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -2258,4 +2258,15 @@ public abstract class EntityHuman extends EntityLiving { + return this.g; + } + } ++ ++ // Purpur start ++ @Override ++ public boolean processClick(EnumHand hand) { ++ Entity vehicle = getRootVehicle(); ++ if (vehicle != null && vehicle.getRider() == this) { ++ return vehicle.onClick(hand); ++ } ++ return false; ++ } ++ // Purpur end + } +diff --git a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java +index 2e2e4ee98619cfbeaecffa1ebae78ccc1d7666ca..3914081629669aea19d50530db996728bbfa607f 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java +@@ -24,7 +24,7 @@ public abstract class IProjectile extends Entity { private UUID shooter; private int c; @@ -4825,7 +5433,7 @@ index dc9f2a1a132b3a7925bd62aa1da0512afd90b8b1..b7e540dfeeabb13227596ecfc6eddabf IProjectile(EntityTypes entitytypes, World world) { super(entitytypes, world); -@@ -74,6 +74,7 @@ public abstract class IProjectile extends Entity { +@@ -86,6 +86,7 @@ public abstract class IProjectile extends Entity { super.tick(); } @@ -4833,7 +5441,7 @@ index dc9f2a1a132b3a7925bd62aa1da0512afd90b8b1..b7e540dfeeabb13227596ecfc6eddabf private boolean h() { Entity entity = this.getShooter(); -@@ -137,7 +138,7 @@ public abstract class IProjectile extends Entity { +@@ -149,7 +150,7 @@ public abstract class IProjectile extends Entity { iblockdata.a(this.world, iblockdata, movingobjectpositionblock, this); } @@ -4842,82 +5450,11 @@ index dc9f2a1a132b3a7925bd62aa1da0512afd90b8b1..b7e540dfeeabb13227596ecfc6eddabf if (!entity.isSpectator() && entity.isAlive() && entity.isInteractable()) { Entity entity1 = this.getShooter(); // Paper start - Cancel hit for vanished players -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index e46705e7ab5d5c69e5d2bdd29d5066c4b2d60675..4f589ca6cfc770bd26d0046736f7100272d7e48e 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1418,6 +1418,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0; // Paper - worldserver.hasEntityMoveEvent = EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper -+ worldserver.hasRidableMoveEvent = net.pl3x.purpur.event.entity.RidableMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Purpur - TileEntityHopper.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - - this.methodProfiler.a(() -> { -diff --git a/src/main/java/net/minecraft/server/PathfinderGoalHasRider.java b/src/main/java/net/minecraft/server/PathfinderGoalHasRider.java -new file mode 100644 -index 0000000000000000000000000000000000000000..da18e1235eed1988052fbd761c11f77efd7afc5e ---- /dev/null -+++ b/src/main/java/net/minecraft/server/PathfinderGoalHasRider.java -@@ -0,0 +1,18 @@ -+package net.minecraft.server; -+ -+import java.util.EnumSet; -+ -+public class PathfinderGoalHasRider extends PathfinderGoal { -+ public final EntityInsentient entity; -+ -+ public PathfinderGoalHasRider(EntityInsentient entity) { -+ this.entity = entity; -+ setTypes(EnumSet.of(Type.JUMP, Type.MOVE, Type.LOOK, Type.TARGET, Type.UNKNOWN_BEHAVIOR)); -+ } -+ -+ // shouldExecute -+ @Override -+ public boolean a() { -+ return entity.hasRider(); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/PathfinderGoalHorseHasRider.java b/src/main/java/net/minecraft/server/PathfinderGoalHorseHasRider.java -new file mode 100644 -index 0000000000000000000000000000000000000000..44929182dfd7ad847d9657c324f440cbf29abadf ---- /dev/null -+++ b/src/main/java/net/minecraft/server/PathfinderGoalHorseHasRider.java -@@ -0,0 +1,16 @@ -+package net.minecraft.server; -+ -+public class PathfinderGoalHorseHasRider extends PathfinderGoalHasRider { -+ private final EntityHorseAbstract horse; -+ -+ public PathfinderGoalHorseHasRider(EntityHorseAbstract entity) { -+ super(entity); -+ this.horse = entity; -+ } -+ -+ // shouldExecute -+ @Override -+ public boolean a() { -+ return super.a() && horse.hasSaddle(); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 48d032ed74effcfd66e1ab01548913964bca4d19..7be03bb416a5723ce65411ba5d0b967040e8033c 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -2307,6 +2307,8 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - this.server.getPluginManager().callEvent(event); - -+ player.processClick(enumhand); // Purpur -+ - // Fish bucket - SPIGOT-4048 - if ((entity instanceof EntityFish && origItem != null && origItem.getItem() == Items.WATER_BUCKET) && (event.isCancelled() || this.player.inventory.getItemInHand() == null || this.player.inventory.getItemInHand().getItem() != origItem)) { - this.sendPacket(new PacketPlayOutSpawnEntityLiving((EntityFish) entity)); -diff --git a/src/main/java/net/minecraft/server/ProjectileHelper.java b/src/main/java/net/minecraft/server/ProjectileHelper.java -index b2c64b31440389db5abe2322f7e31b328f590f6c..515ba50aec81497d27297e4b6c642e86b7de53ca 100644 ---- a/src/main/java/net/minecraft/server/ProjectileHelper.java -+++ b/src/main/java/net/minecraft/server/ProjectileHelper.java -@@ -7,6 +7,7 @@ import javax.annotation.Nullable; +diff --git a/src/main/java/net/minecraft/world/entity/projectile/ProjectileHelper.java b/src/main/java/net/minecraft/world/entity/projectile/ProjectileHelper.java +index 75889ac851d1c2b26c0b57bea6b75c1b65c2309f..80834537eba8bd33a0688e19d0aa9b963de4398a 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/ProjectileHelper.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/ProjectileHelper.java +@@ -21,6 +21,7 @@ import net.minecraft.world.phys.Vec3D; public final class ProjectileHelper { @@ -4925,39 +5462,23 @@ index b2c64b31440389db5abe2322f7e31b328f590f6c..515ba50aec81497d27297e4b6c642e86 public static MovingObjectPosition a(Entity entity, Predicate predicate) { Vec3D vec3d = entity.getMot(); World world = entity.world; -diff --git a/src/main/java/net/minecraft/server/Vec3D.java b/src/main/java/net/minecraft/server/Vec3D.java -index 7190316a38e6b4edf5501bfedbb12be79e990797..4469fdc932d725b8e6fa4f8e3ec15c22a88ca5e7 100644 ---- a/src/main/java/net/minecraft/server/Vec3D.java -+++ b/src/main/java/net/minecraft/server/Vec3D.java -@@ -45,6 +45,7 @@ public class Vec3D implements IPosition { - return new Vec3D(vec3d.x - this.x, vec3d.y - this.y, vec3d.z - this.z); - } +diff --git a/src/main/java/net/minecraft/world/level/GeneratorAccess.java b/src/main/java/net/minecraft/world/level/GeneratorAccess.java +index 96efd974f1eb9c1e7c70e576e51ed69e15aacb99..fc86ef53c48503139667f7703019a07c40814fd4 100644 +--- a/src/main/java/net/minecraft/world/level/GeneratorAccess.java ++++ b/src/main/java/net/minecraft/world/level/GeneratorAccess.java +@@ -48,6 +48,7 @@ public interface GeneratorAccess extends ICombinedAccess, IWorldTime { -+ public Vec3D normalize() { return d(); } // Purpur - OBFHELPER - public Vec3D d() { - double d0 = (double) MathHelper.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); + void addParticle(ParticleParam particleparam, double d0, double d1, double d2, double d3, double d4, double d5); -@@ -104,6 +105,7 @@ public class Vec3D implements IPosition { - return d3 * d3 + d4 * d4 + d5 * d5; - } ++ default void playEvent(@Nullable EntityHuman entityhuman, int i, BlockPosition blockposition, int j) { a(entityhuman, i, blockposition, j); } // Purpur - OBFHELPER + void a(@Nullable EntityHuman entityhuman, int i, BlockPosition blockposition, int j); -+ public Vec3D scale(double scale) { return a(scale); } // Purpur - OBFHELPER - public Vec3D a(double d0) { - return this.d(d0, d0, d0); - } -@@ -112,6 +114,7 @@ public class Vec3D implements IPosition { - return this.d(vec3d.x, vec3d.y, vec3d.z); - } - -+ public Vec3D multiply (double x, double y, double z) { return d(x, y, z); } // Purpur - OBFHELPER - public Vec3D d(double d0, double d1, double d2) { - return new Vec3D(this.x * d0, this.y * d1, this.z * d2); - } -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 404fcc307454e7f00dcc180dda53677c5a0f43e8..bb7cf83027ad0d0679fb208147f3481dbe280a82 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -1771,5 +1771,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + default int getHeight() { +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 93cbdcd641762e3ab00258fd94ac381ebe47fb79..c75b1b1e8d99157336065f561d40ac803239c6b7 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -1833,5 +1833,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable { public boolean isTheEnd() { return getWorld().getEnvironment() == org.bukkit.World.Environment.THE_END; } @@ -4968,23 +5489,39 @@ index 404fcc307454e7f00dcc180dda53677c5a0f43e8..bb7cf83027ad0d0679fb208147f3481d + } // Purpur end } -diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index 03e3c0250c399b29817285fb4f2db5714f5f66dc..dbeded3f0ede57877dc4ba01990760baa7c6b5bd 100644 ---- a/src/main/java/net/minecraft/server/WorldServer.java -+++ b/src/main/java/net/minecraft/server/WorldServer.java -@@ -102,6 +102,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - public final UUID uuid; - boolean hasPhysicsEvent = true; // Paper - boolean hasEntityMoveEvent = false; // Paper -+ boolean hasRidableMoveEvent = false; // Purpur - private static Throwable getAddToWorldStackTrace(Entity entity) { - return new Throwable(entity + " Added to world at " + new java.util.Date()); +diff --git a/src/main/java/net/minecraft/world/phys/Vec3D.java b/src/main/java/net/minecraft/world/phys/Vec3D.java +index a19a26a88f247d359354902efeece9923f3e0e0b..1119f60890784d953c2cd4e0078af4d04d10d557 100644 +--- a/src/main/java/net/minecraft/world/phys/Vec3D.java ++++ b/src/main/java/net/minecraft/world/phys/Vec3D.java +@@ -50,6 +50,7 @@ public class Vec3D implements IPosition { + return new Vec3D(vec3d.x - this.x, vec3d.y - this.y, vec3d.z - this.z); + } + ++ public Vec3D normalize() { return d(); } // Purpur - OBFHELPER + public Vec3D d() { + double d0 = (double) MathHelper.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); + +@@ -109,6 +110,7 @@ public class Vec3D implements IPosition { + return d3 * d3 + d4 * d4 + d5 * d5; + } + ++ public Vec3D scale(double scale) { return a(scale); } // Purpur - OBFHELPER + public Vec3D a(double d0) { + return this.d(d0, d0, d0); + } +@@ -117,6 +119,7 @@ public class Vec3D implements IPosition { + return this.d(vec3d.x, vec3d.y, vec3d.z); + } + ++ public Vec3D multiply (double x, double y, double z) { return d(x, y, z); } // Purpur - OBFHELPER + public Vec3D d(double d0, double d1, double d2) { + return new Vec3D(this.x * d0, this.y * d1, this.z * d2); } diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index c314a8c9a921a95cea43b748e2037521d948e1e7..59f3122aab9940cb3c3c1efb2664ab0835656d48 100644 +index bfae3043ef6bf402011045bd9682117aa3021468..2e9cec2d70ab4af5603552ebf8f0c0fa52ccfbe5 100644 --- a/src/main/java/net/pl3x/purpur/PurpurConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java -@@ -136,11 +136,13 @@ public class PurpurConfig { +@@ -137,11 +137,13 @@ public class PurpurConfig { public static String afkBroadcastBack = "§e§o%s is no longer AFK"; public static String afkTabListPrefix = "[AFK] "; public static String pingCommandOutput = "§a%s's ping is %sms"; @@ -4999,7 +5536,7 @@ index c314a8c9a921a95cea43b748e2037521d948e1e7..59f3122aab9940cb3c3c1efb2664ab08 public static int dungeonSeed = -1; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 637cac2758a44e72794953b9fbca2accb7d86b6a..d8b5e091047210a8eff45e493f07d30ffa6d9f81 100644 +index 4f5b815f22a906d8438c82204d24417e5d1cc66c..8b0afe5ef5d82bf9171a91521681e3ff4e61dffc 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -42,11 +42,6 @@ public class PurpurWorldConfig { @@ -5654,17 +6191,17 @@ index 637cac2758a44e72794953b9fbca2accb7d86b6a..d8b5e091047210a8eff45e493f07d30f zombieVillagerJockeyTryExistingChickens = getBoolean("mobs.zombie_villager.jockey.try-existing-chickens", zombieVillagerJockeyTryExistingChickens); diff --git a/src/main/java/net/pl3x/purpur/controller/ControllerLookWASD.java b/src/main/java/net/pl3x/purpur/controller/ControllerLookWASD.java new file mode 100644 -index 0000000000000000000000000000000000000000..868c1ce1952193cba5ff0ce35e9d607478df7a53 +index 0000000000000000000000000000000000000000..292821f039d99a03ba4daeb3a941616ef5f6287e --- /dev/null +++ b/src/main/java/net/pl3x/purpur/controller/ControllerLookWASD.java @@ -0,0 +1,76 @@ +package net.pl3x.purpur.controller; + -+import net.minecraft.server.ControllerLook; -+import net.minecraft.server.EntityHuman; -+import net.minecraft.server.EntityInsentient; -+import net.minecraft.server.MathHelper; -+import net.minecraft.server.PacketPlayOutEntity; ++import net.minecraft.network.protocol.game.PacketPlayOutEntity; ++import net.minecraft.world.entity.ai.control.ControllerLook; ++import net.minecraft.world.entity.EntityInsentient; ++import net.minecraft.util.MathHelper; ++import net.minecraft.world.entity.player.EntityHuman; + +public class ControllerLookWASD extends ControllerLook { + protected final EntityInsentient entity; @@ -5736,17 +6273,17 @@ index 0000000000000000000000000000000000000000..868c1ce1952193cba5ff0ce35e9d6074 +} diff --git a/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASD.java b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASD.java new file mode 100644 -index 0000000000000000000000000000000000000000..426688b3a6dc197b41ddc4d1efed0405614f0f3b +index 0000000000000000000000000000000000000000..266e734e8c20d6e414bd4a453118ad75fa4f97e5 --- /dev/null +++ b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASD.java @@ -0,0 +1,92 @@ +package net.pl3x.purpur.controller; + -+import net.minecraft.server.ControllerMove; -+import net.minecraft.server.Entity; -+import net.minecraft.server.EntityHuman; -+import net.minecraft.server.EntityInsentient; -+import net.minecraft.server.GenericAttributes; ++import net.minecraft.world.entity.ai.control.ControllerMove; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EntityInsentient; ++import net.minecraft.world.entity.ai.attributes.GenericAttributes; ++import net.minecraft.world.entity.player.EntityHuman; +import net.pl3x.purpur.event.entity.RidableSpacebarEvent; + +public class ControllerMoveWASD extends ControllerMove { @@ -5834,15 +6371,15 @@ index 0000000000000000000000000000000000000000..426688b3a6dc197b41ddc4d1efed0405 +} diff --git a/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDFlying.java b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDFlying.java new file mode 100644 -index 0000000000000000000000000000000000000000..33c51460ab9556e5574c99232e9e3ff843c6ccc9 +index 0000000000000000000000000000000000000000..7737e87048e88b40c0b6b4a1093e2256ae252802 --- /dev/null +++ b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDFlying.java @@ -0,0 +1,61 @@ +package net.pl3x.purpur.controller; + -+import net.minecraft.server.EntityHuman; -+import net.minecraft.server.EntityInsentient; -+import net.minecraft.server.GenericAttributes; ++import net.minecraft.world.entity.EntityInsentient; ++import net.minecraft.world.entity.ai.attributes.GenericAttributes; ++import net.minecraft.world.entity.player.EntityHuman; + +public class ControllerMoveWASDFlying extends ControllerMoveWASD { + protected final float groundSpeedModifier; @@ -5901,16 +6438,16 @@ index 0000000000000000000000000000000000000000..33c51460ab9556e5574c99232e9e3ff8 +} diff --git a/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDFlyingWithSpacebar.java b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDFlyingWithSpacebar.java new file mode 100644 -index 0000000000000000000000000000000000000000..f7537593619a68eb3898f28034192fab8548655c +index 0000000000000000000000000000000000000000..cdd32aa66b6bd9c01854e3d9baf25757c7e2a707 --- /dev/null +++ b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDFlyingWithSpacebar.java @@ -0,0 +1,61 @@ +package net.pl3x.purpur.controller; + -+import net.minecraft.server.EntityHuman; -+import net.minecraft.server.EntityInsentient; -+import net.minecraft.server.GenericAttributes; -+import net.minecraft.server.Vec3D; ++import net.minecraft.world.entity.EntityInsentient; ++import net.minecraft.world.entity.ai.attributes.GenericAttributes; ++import net.minecraft.world.entity.player.EntityHuman; ++import net.minecraft.world.phys.Vec3D; + +public class ControllerMoveWASDFlyingWithSpacebar extends ControllerMoveWASDFlying { + public ControllerMoveWASDFlyingWithSpacebar(EntityInsentient entity) { @@ -5968,15 +6505,15 @@ index 0000000000000000000000000000000000000000..f7537593619a68eb3898f28034192fab +} diff --git a/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDWater.java b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDWater.java new file mode 100644 -index 0000000000000000000000000000000000000000..1b08a0905b296b989e0ef0ea3b15169759b5f2fe +index 0000000000000000000000000000000000000000..aa7eb0b3bd7be8d1992e99bf156dbad167e571aa --- /dev/null +++ b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDWater.java @@ -0,0 +1,50 @@ +package net.pl3x.purpur.controller; + -+import net.minecraft.server.EntityHuman; -+import net.minecraft.server.EntityInsentient; -+import net.minecraft.server.GenericAttributes; ++import net.minecraft.world.entity.EntityInsentient; ++import net.minecraft.world.entity.ai.attributes.GenericAttributes; ++import net.minecraft.world.entity.player.EntityHuman; + +public class ControllerMoveWASDWater extends ControllerMoveWASD { + private final double speedModifier; @@ -6024,29 +6561,28 @@ index 0000000000000000000000000000000000000000..1b08a0905b296b989e0ef0ea3b151697 +} diff --git a/src/main/java/net/pl3x/purpur/entity/DolphinSpit.java b/src/main/java/net/pl3x/purpur/entity/DolphinSpit.java new file mode 100644 -index 0000000000000000000000000000000000000000..a01524c6abaec13d7249d7aba6da9e4bc39f8b99 +index 0000000000000000000000000000000000000000..7c7b1cb54bf0d64ae71d50532b61bb648396b2dc --- /dev/null +++ b/src/main/java/net/pl3x/purpur/entity/DolphinSpit.java -@@ -0,0 +1,120 @@ +@@ -0,0 +1,119 @@ +package net.pl3x.purpur.entity; + -+import net.minecraft.server.BlockBase; -+import net.minecraft.server.DamageSource; -+import net.minecraft.server.Entity; -+import net.minecraft.server.EntityDolphin; -+import net.minecraft.server.EntityLiving; -+import net.minecraft.server.EntityLlamaSpit; -+import net.minecraft.server.EntityTypes; -+import net.minecraft.server.IBlockData; -+import net.minecraft.server.MathHelper; -+import net.minecraft.server.MovingObjectPosition; -+import net.minecraft.server.MovingObjectPositionBlock; -+import net.minecraft.server.MovingObjectPositionEntity; -+import net.minecraft.server.Particles; -+import net.minecraft.server.ProjectileHelper; -+import net.minecraft.server.Vec3D; -+import net.minecraft.server.World; -+import net.minecraft.server.WorldServer; ++import net.minecraft.world.entity.animal.EntityDolphin; ++import net.minecraft.world.entity.projectile.EntityLlamaSpit; ++import net.minecraft.world.damagesource.DamageSource; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EntityLiving; ++import net.minecraft.world.entity.EntityTypes; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.util.MathHelper; ++import net.minecraft.world.phys.MovingObjectPosition; ++import net.minecraft.world.phys.MovingObjectPositionBlock; ++import net.minecraft.world.phys.MovingObjectPositionEntity; ++import net.minecraft.core.particles.Particles; ++import net.minecraft.world.entity.projectile.ProjectileHelper; ++import net.minecraft.world.phys.Vec3D; ++import net.minecraft.world.level.World; ++import net.minecraft.server.level.WorldServer; +import org.bukkit.craftbukkit.event.CraftEventFactory; + +public class DolphinSpit extends EntityLlamaSpit { @@ -6150,30 +6686,30 @@ index 0000000000000000000000000000000000000000..a01524c6abaec13d7249d7aba6da9e4b +} diff --git a/src/main/java/net/pl3x/purpur/entity/PhantomFlames.java b/src/main/java/net/pl3x/purpur/entity/PhantomFlames.java new file mode 100644 -index 0000000000000000000000000000000000000000..9a9e46d7ee247f9e43ae5c697f10e4665fd6e4e6 +index 0000000000000000000000000000000000000000..3d83a495cbe08e2f129a583ec2760391edb819ba --- /dev/null +++ b/src/main/java/net/pl3x/purpur/entity/PhantomFlames.java @@ -0,0 +1,140 @@ +package net.pl3x.purpur.entity; + -+import net.minecraft.server.BlockBase; -+import net.minecraft.server.DamageSource; -+import net.minecraft.server.Entity; -+import net.minecraft.server.EntityArmorStand; -+import net.minecraft.server.EntityLiving; -+import net.minecraft.server.EntityLlamaSpit; -+import net.minecraft.server.EntityPhantom; -+import net.minecraft.server.EntityTypes; -+import net.minecraft.server.IBlockData; -+import net.minecraft.server.MathHelper; -+import net.minecraft.server.MovingObjectPosition; -+import net.minecraft.server.MovingObjectPositionBlock; -+import net.minecraft.server.MovingObjectPositionEntity; -+import net.minecraft.server.Particles; -+import net.minecraft.server.ProjectileHelper; -+import net.minecraft.server.Vec3D; -+import net.minecraft.server.World; -+import net.minecraft.server.WorldServer; ++import net.minecraft.world.damagesource.DamageSource; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EntityLiving; ++import net.minecraft.world.entity.EntityTypes; ++import net.minecraft.world.entity.decoration.EntityArmorStand; ++import net.minecraft.world.entity.monster.EntityPhantom; ++import net.minecraft.world.entity.projectile.EntityLlamaSpit; ++import net.minecraft.world.level.block.state.BlockBase; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.util.MathHelper; ++import net.minecraft.world.phys.MovingObjectPosition; ++import net.minecraft.world.phys.MovingObjectPositionBlock; ++import net.minecraft.world.phys.MovingObjectPositionEntity; ++import net.minecraft.core.particles.Particles; ++import net.minecraft.world.entity.projectile.ProjectileHelper; ++import net.minecraft.world.phys.Vec3D; ++import net.minecraft.world.level.World; ++import net.minecraft.server.level.WorldServer; +import org.bukkit.craftbukkit.event.CraftEventFactory; + +public class PhantomFlames extends EntityLlamaSpit { @@ -6295,10 +6831,10 @@ index 0000000000000000000000000000000000000000..9a9e46d7ee247f9e43ae5c697f10e466 + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 2af3bee540ee25ea32a7548fd0d64dea16a0a268..5471422d23d261a06c67f9374cae933430ec03a0 100644 +index dee4d12a49468d38f077784b219199f0070786f2..c524a0994f1c9ef1d0534403efa4e4481955b2f3 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1174,4 +1174,26 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -1175,4 +1175,26 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { return getHandle().isTicking(); } // Paper end @@ -6326,10 +6862,10 @@ index 2af3bee540ee25ea32a7548fd0d64dea16a0a268..5471422d23d261a06c67f9374cae9334 + // Purpur end } diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 82e36ba35c0bd4d5b3e13281bad1a0664c25c6e0..c4d0082bb0d310ad16de36df03dd99225c5cadb0 100644 +index 926440e846eff2c1aaa262aa2b3975b7dd225332..9a6c4f292940b1cef2f4ef87c2e47d82ba5cb60f 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -528,6 +528,18 @@ public class CraftEventFactory { +@@ -530,6 +530,18 @@ public class CraftEventFactory { } craftServer.getPluginManager().callEvent(event); @@ -6348,7 +6884,7 @@ index 82e36ba35c0bd4d5b3e13281bad1a0664c25c6e0..c4d0082bb0d310ad16de36df03dd9922 return event; } -@@ -928,6 +940,7 @@ public class CraftEventFactory { +@@ -930,6 +942,7 @@ public class CraftEventFactory { damageCause = DamageCause.ENTITY_EXPLOSION; } event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), entity.getBukkitEntity(), damageCause, modifiers, modifierFunctions); @@ -6356,7 +6892,7 @@ index 82e36ba35c0bd4d5b3e13281bad1a0664c25c6e0..c4d0082bb0d310ad16de36df03dd9922 } event.setCancelled(cancelled); -@@ -1012,6 +1025,7 @@ public class CraftEventFactory { +@@ -1014,6 +1027,7 @@ public class CraftEventFactory { if (!event.isCancelled()) { event.getEntity().setLastDamageCause(event); } @@ -6364,7 +6900,7 @@ index 82e36ba35c0bd4d5b3e13281bad1a0664c25c6e0..c4d0082bb0d310ad16de36df03dd9922 return event; } -@@ -1061,6 +1075,7 @@ public class CraftEventFactory { +@@ -1063,6 +1077,7 @@ public class CraftEventFactory { EntityDamageEvent event; if (damager != null) { event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), damagee.getBukkitEntity(), cause, modifiers, modifierFunctions); diff --git a/patches/server/0104-Use-configured-height-for-nether-surface-builders.patch b/patches/server/0104-Use-configured-height-for-nether-surface-builders.patch index fb5a5fb7e..a1b1edd84 100644 --- a/patches/server/0104-Use-configured-height-for-nether-surface-builders.patch +++ b/patches/server/0104-Use-configured-height-for-nether-surface-builders.patch @@ -4,11 +4,11 @@ Date: Sat, 15 Aug 2020 06:51:46 -0500 Subject: [PATCH] Use configured height for nether surface builders -diff --git a/src/main/java/net/minecraft/server/WorldGenSurfaceNetherAbstract.java b/src/main/java/net/minecraft/server/WorldGenSurfaceNetherAbstract.java -index 462f0b2baea4207d7d82f2d4e043a5a7999a1f42..f418a71ca8ec5e1417778d33c9020dc002a611cc 100644 ---- a/src/main/java/net/minecraft/server/WorldGenSurfaceNetherAbstract.java -+++ b/src/main/java/net/minecraft/server/WorldGenSurfaceNetherAbstract.java -@@ -35,7 +35,7 @@ public abstract class WorldGenSurfaceNetherAbstract extends WorldGenSurface { @@ -42,10 +42,10 @@ index 6ef81aeb4c63bc6c23163796dbd977602ca2f540..9ea3c30b679da4e77b86d96d0cc47673 private final GeneratorAccess b; private final EnumDirection.EnumAxis c; diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index 59f3122aab9940cb3c3c1efb2664ab0835656d48..a5febd7671ae1818edb18955d5e8176303c92c93 100644 +index 2e9cec2d70ab4af5603552ebf8f0c0fa52ccfbe5..c61595aa6e42a4cc096bda9126d23c465f8bd3de 100644 --- a/src/main/java/net/pl3x/purpur/PurpurConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java -@@ -179,6 +179,7 @@ public class PurpurConfig { +@@ -180,6 +180,7 @@ public class PurpurConfig { public static boolean barrelSixRows = false; public static boolean enderChestSixRows = false; public static boolean enderChestPermissionRows = false; @@ -53,7 +53,7 @@ index 59f3122aab9940cb3c3c1efb2664ab0835656d48..a5febd7671ae1818edb18955d5e81763 private static void blockSettings() { if (version < 3) { boolean oldValue = getBoolean("settings.barrel.packed-barrels", true); -@@ -193,6 +194,7 @@ public class PurpurConfig { +@@ -194,6 +195,7 @@ public class PurpurConfig { enderChestSixRows = getBoolean("settings.blocks.ender_chest.six-rows", enderChestSixRows); InventoryType.ENDER_CHEST.setDefaultSize(enderChestSixRows ? 54 : 27); enderChestPermissionRows = getBoolean("settings.blocks.ender_chest.use-permissions-for-rows", enderChestPermissionRows); diff --git a/patches/server/0106-Entities-can-use-portals-configuration.patch b/patches/server/0106-Entities-can-use-portals-configuration.patch index 23829f2ca..739bcc60d 100644 --- a/patches/server/0106-Entities-can-use-portals-configuration.patch +++ b/patches/server/0106-Entities-can-use-portals-configuration.patch @@ -4,11 +4,11 @@ Date: Mon, 17 Aug 2020 19:32:05 -0500 Subject: [PATCH] Entities can use portals configuration -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index bcae44f59b3f90b3f2c3f0680b13ce58688ed77b..82176fe047f93ccf549deb645568b3ee5dc21b5e 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -2430,7 +2430,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index d1bbf4127a2e0836bedb33a81e3fd18a8e8eb962..4b4c6477122c51871ce98f34c6e5874048eaa227 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2523,7 +2523,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne public void d(BlockPosition blockposition) { if (this.ai()) { this.resetPortalCooldown(); @@ -17,7 +17,7 @@ index bcae44f59b3f90b3f2c3f0680b13ce58688ed77b..82176fe047f93ccf549deb645568b3ee if (!this.world.isClientSide && !blockposition.equals(this.ac)) { this.ac = blockposition.immutableCopy(); } -@@ -3010,7 +3010,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +@@ -3103,7 +3103,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne } public boolean canPortal() { @@ -27,7 +27,7 @@ index bcae44f59b3f90b3f2c3f0680b13ce58688ed77b..82176fe047f93ccf549deb645568b3ee public float a(Explosion explosion, IBlockAccess iblockaccess, BlockPosition blockposition, IBlockData iblockdata, Fluid fluid, float f) { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index d8b5e091047210a8eff45e493f07d30ffa6d9f81..cf4ac765fdbaf961e913ca028edc084373eba978 100644 +index 8b0afe5ef5d82bf9171a91521681e3ff4e61dffc..c7c33906466a28f65a6f8252a959a6651bd1074e 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -158,6 +158,7 @@ public class PurpurWorldConfig { diff --git a/patches/server/0107-LivingEntity-broadcastItemBreak.patch b/patches/server/0107-LivingEntity-broadcastItemBreak.patch index 75d1de0ed..209b879f1 100644 --- a/patches/server/0107-LivingEntity-broadcastItemBreak.patch +++ b/patches/server/0107-LivingEntity-broadcastItemBreak.patch @@ -5,10 +5,10 @@ Subject: [PATCH] LivingEntity#broadcastItemBreak diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 84aeffac2c2c12d98e9cec05314668a93bb5ed91..6a15b0d5e8446ab2a5e5bd11020a4f812b6c7877 100644 +index b5040de9885556561416bf3282476f3b33925a62..f0631331afc16576a21310f5575b56ae7663f399 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -844,5 +844,11 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { +@@ -854,5 +854,11 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { public void setSafeFallDistance(float safeFallDistance) { getHandle().safeFallDistance = safeFallDistance; } diff --git a/patches/server/0108-Customizable-wither-health-and-healing.patch b/patches/server/0108-Customizable-wither-health-and-healing.patch index f880f1ef6..15d977e1c 100644 --- a/patches/server/0108-Customizable-wither-health-and-healing.patch +++ b/patches/server/0108-Customizable-wither-health-and-healing.patch @@ -5,11 +5,11 @@ Subject: [PATCH] Customizable wither health and healing Adds the ability to customize the health of the wither, as well as the amount that it heals, and how often. -diff --git a/src/main/java/net/minecraft/server/EntityWither.java b/src/main/java/net/minecraft/server/EntityWither.java -index 87b7d52bdba357fa59c7b6397cb49286fd8cc8ec..edc58c5cb178ea9a53f960bd4a460f394b13ab64 100644 ---- a/src/main/java/net/minecraft/server/EntityWither.java -+++ b/src/main/java/net/minecraft/server/EntityWither.java -@@ -150,6 +150,11 @@ public class EntityWither extends EntityMonster implements IRangedEntity { +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java +index 4c0a555cdb5bc34c73040b9533beaee56cbce70a..beb4d59faf4bd7501468b2eaa0e866613625e963 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java +@@ -207,6 +207,11 @@ public class EntityWither extends EntityMonster implements IRangedEntity { skull.setPositionRaw(headX, headY, headZ); world.addEntity(skull); } @@ -21,7 +21,7 @@ index 87b7d52bdba357fa59c7b6397cb49286fd8cc8ec..edc58c5cb178ea9a53f960bd4a460f39 // Purpur end @Override -@@ -354,7 +359,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { +@@ -411,7 +416,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { this.setInvul(i); if (this.ticksLived % 10 == 0) { @@ -30,7 +30,7 @@ index 87b7d52bdba357fa59c7b6397cb49286fd8cc8ec..edc58c5cb178ea9a53f960bd4a460f39 } } else { -@@ -463,8 +468,10 @@ public class EntityWither extends EntityMonster implements IRangedEntity { +@@ -520,8 +525,10 @@ public class EntityWither extends EntityMonster implements IRangedEntity { } } @@ -44,7 +44,7 @@ index 87b7d52bdba357fa59c7b6397cb49286fd8cc8ec..edc58c5cb178ea9a53f960bd4a460f39 //this.bossBattle.setProgress(this.getHealth() / this.getMaxHealth()); // Paper - Moved down diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index cf4ac765fdbaf961e913ca028edc084373eba978..94a870113dc45201379c1efc7e83162c303573df 100644 +index c7c33906466a28f65a6f8252a959a6651bd1074e..3e1b97a4003cea3af511ed9b7f13f8a5373f9a20 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -921,10 +921,21 @@ public class PurpurWorldConfig { diff --git a/patches/server/0109-Allow-toggling-special-MobSpawners-per-world.patch b/patches/server/0109-Allow-toggling-special-MobSpawners-per-world.patch index 458caea14..7fe16bbc2 100644 --- a/patches/server/0109-Allow-toggling-special-MobSpawners-per-world.patch +++ b/patches/server/0109-Allow-toggling-special-MobSpawners-per-world.patch @@ -5,47 +5,37 @@ Subject: [PATCH] Allow toggling special MobSpawners per world In vanilla, these are all hardcoded on for world type 0 (overworld) and hardcoded off for every other world type. Default config behaviour matches this. -diff --git a/src/main/java/net/minecraft/server/MobSpawnerTrader.java b/src/main/java/net/minecraft/server/MobSpawnerTrader.java -index 341af7474690b929cfa3e35cd464bbbbacb6685e..ad00ff2bd525768e4f06631d16b912c61c8eee28 100644 ---- a/src/main/java/net/minecraft/server/MobSpawnerTrader.java -+++ b/src/main/java/net/minecraft/server/MobSpawnerTrader.java -@@ -132,7 +132,17 @@ public class MobSpawnerTrader implements MobSpawner { - int k = blockposition.getX() + this.a.nextInt(i * 2) - i; - int l = blockposition.getZ() + this.a.nextInt(i * 2) - i; - int i1 = iworldreader.a(HeightMap.Type.WORLD_SURFACE, k, l); -- BlockPosition blockposition2 = new BlockPosition(k, i1, l); -+ // Purpur start - allow traders to spawn below nether roof -+ BlockPosition.MutableBlockPosition blockposition2 = new BlockPosition.MutableBlockPosition(k, i1, l); -+ if (iworldreader.getDimensionManager().hasCeiling()) { -+ do { -+ blockposition2.c(EnumDirection.DOWN); -+ } while (!iworldreader.getType(blockposition2).isAir()); -+ do { -+ blockposition2.c(EnumDirection.DOWN); -+ } while (iworldreader.getType(blockposition2).isAir() && blockposition2.getY() > 0); -+ } -+ // Purpur end - - if (SpawnerCreature.a(EntityPositionTypes.Surface.ON_GROUND, iworldreader, blockposition2, EntityTypes.WANDERING_TRADER)) { - blockposition1 = blockposition2; -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index bb7cf83027ad0d0679fb208147f3481dbe280a82..42e06121f20b5366627b9612994187066c73328f 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -187,7 +187,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((WorldDataServer) worlddatamutable).getName()); // Spigot - this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper - this.tuinityConfig = new com.tuinity.tuinity.config.TuinityConfig.WorldConfig(((WorldDataServer)worlddatamutable).getName()); // Tuinity - Server Config -- this.purpurConfig = new net.pl3x.purpur.PurpurWorldConfig((((WorldDataServer)worlddatamutable).getName())); // Purpur -+ this.purpurConfig = new net.pl3x.purpur.PurpurWorldConfig(((WorldDataServer) worlddatamutable).getName(), env); // Purpur - this.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this, executor) : ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray - this.generator = gen; - this.world = new CraftWorld((WorldServer) this, gen, env); -diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index dbeded3f0ede57877dc4ba01990760baa7c6b5bd..f2bbc31540224424dc224bbfc86c61ccf2d0e629 100644 ---- a/src/main/java/net/minecraft/server/WorldServer.java -+++ b/src/main/java/net/minecraft/server/WorldServer.java -@@ -436,7 +436,24 @@ public class WorldServer extends World implements GeneratorAccessSeed { +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index dd1a0cffedc434d570c1b03fa8cf55d90de1f324..c74e82feb007764d77f8f9b7f910f7b113e3bf40 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -92,6 +92,7 @@ import net.minecraft.world.entity.EnumCreatureType; + import net.minecraft.world.entity.ReputationHandler; + import net.minecraft.world.entity.ai.navigation.NavigationAbstract; + import net.minecraft.world.entity.ai.village.ReputationEvent; ++import net.minecraft.world.entity.ai.village.VillageSiege; + import net.minecraft.world.entity.ai.village.poi.VillagePlace; + import net.minecraft.world.entity.ai.village.poi.VillagePlaceType; + import net.minecraft.world.entity.animal.EntityAnimal; +@@ -101,6 +102,8 @@ import net.minecraft.world.entity.animal.horse.EntityHorseSkeleton; + import net.minecraft.world.entity.boss.EntityComplexPart; + import net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon; + import net.minecraft.world.entity.item.EntityItem; ++import net.minecraft.world.entity.npc.MobSpawnerCat; ++import net.minecraft.world.entity.npc.MobSpawnerTrader; + import net.minecraft.world.entity.npc.NPC; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.entity.raid.PersistentRaid; +@@ -133,6 +136,8 @@ import net.minecraft.world.level.chunk.storage.RegionFile; + import net.minecraft.world.level.dimension.DimensionManager; + import net.minecraft.world.level.dimension.end.EnderDragonBattle; + import net.minecraft.world.level.levelgen.HeightMap; ++import net.minecraft.world.level.levelgen.MobSpawnerPatrol; ++import net.minecraft.world.level.levelgen.MobSpawnerPhantom; + import net.minecraft.world.level.levelgen.feature.StructureGenerator; + import net.minecraft.world.level.levelgen.structure.StructureBoundingBox; + import net.minecraft.world.level.levelgen.structure.StructureStart; +@@ -550,7 +555,24 @@ public class WorldServer extends World implements GeneratorAccessSeed { this.L = new ObjectLinkedOpenHashSet(); this.Q = flag1; this.server = minecraftserver; @@ -71,16 +61,60 @@ index dbeded3f0ede57877dc4ba01990760baa7c6b5bd..f2bbc31540224424dc224bbfc86c61cc // CraftBukkit start this.worldDataServer = (WorldDataServer) iworlddataserver; worldDataServer.world = this; +diff --git a/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java b/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java +index 7c8a2151be8a0f48cba1c15d231d5dbdb500b4d6..361771fc4fcf16b1b013c550734019535cef2924 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java ++++ b/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java +@@ -5,6 +5,7 @@ import java.util.Optional; + import java.util.Random; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPosition; ++import net.minecraft.core.EnumDirection; + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.chat.IChatBaseComponent; + import net.minecraft.server.level.EntityPlayer; +@@ -153,7 +154,17 @@ public class MobSpawnerTrader implements MobSpawner { + int k = blockposition.getX() + this.a.nextInt(i * 2) - i; + int l = blockposition.getZ() + this.a.nextInt(i * 2) - i; + int i1 = iworldreader.a(HeightMap.Type.WORLD_SURFACE, k, l); +- BlockPosition blockposition2 = new BlockPosition(k, i1, l); ++ // Purpur start - allow traders to spawn below nether roof ++ BlockPosition.MutableBlockPosition blockposition2 = new BlockPosition.MutableBlockPosition(k, i1, l); ++ if (iworldreader.getDimensionManager().hasCeiling()) { ++ do { ++ blockposition2.c(EnumDirection.DOWN); ++ } while (!iworldreader.getType(blockposition2).isAir()); ++ do { ++ blockposition2.c(EnumDirection.DOWN); ++ } while (iworldreader.getType(blockposition2).isAir() && blockposition2.getY() > 0); ++ } ++ // Purpur end + + if (SpawnerCreature.a(EntityPositionTypes.Surface.ON_GROUND, iworldreader, blockposition2, EntityTypes.WANDERING_TRADER)) { + blockposition1 = blockposition2; +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index c75b1b1e8d99157336065f561d40ac803239c6b7..06ecb1ec2b92f0978c57de6353f63a02e6e363da 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -250,7 +250,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper + this.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this, executor) : ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray + this.tuinityConfig = new com.tuinity.tuinity.config.TuinityConfig.WorldConfig(((net.minecraft.world.level.storage.WorldDataServer)worlddatamutable).getName()); // Tuinity - Server Config +- this.purpurConfig = new net.pl3x.purpur.PurpurWorldConfig((((net.minecraft.world.level.storage.WorldDataServer)worlddatamutable).getName())); // Purpur ++ this.purpurConfig = new net.pl3x.purpur.PurpurWorldConfig((((net.minecraft.world.level.storage.WorldDataServer)worlddatamutable).getName()), env); // Purpur + this.generator = gen; + this.world = new CraftWorld((WorldServer) this, gen, env); + this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 94a870113dc45201379c1efc7e83162c303573df..c8666ce6bdf2e61dd3ccc7ff6cc0810559ce3f5b 100644 +index 3e1b97a4003cea3af511ed9b7f13f8a5373f9a20..1d144ed296120eccee1001fd1299ead48351cbfa 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -7,6 +7,8 @@ import net.minecraft.server.IRegistry; - import net.minecraft.server.Item; - import net.minecraft.server.Items; - import net.minecraft.server.MinecraftKey; -+import org.apache.commons.lang.BooleanUtils; -+import org.bukkit.World.Environment; +@@ -7,6 +7,8 @@ import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.Items; + import net.minecraft.resources.MinecraftKey; ++import org.apache.commons.lang3.BooleanUtils; ++import org.bukkit.World; import org.bukkit.configuration.ConfigurationSection; import java.util.ArrayList; @@ -96,10 +130,10 @@ index 94a870113dc45201379c1efc7e83162c303573df..c8666ce6bdf2e61dd3ccc7ff6cc08105 public class PurpurWorldConfig { private final String worldName; -+ private final Environment environment; ++ private final World.Environment environment; - public PurpurWorldConfig(String worldName) { -+ public PurpurWorldConfig(String worldName, Environment environment) { ++ public PurpurWorldConfig(String worldName, World.Environment environment) { this.worldName = worldName; + this.environment = environment; init(); @@ -129,7 +163,7 @@ index 94a870113dc45201379c1efc7e83162c303573df..c8666ce6bdf2e61dd3ccc7ff6cc08105 + public boolean villageSiegeSpawning; + private void mobSpawnerSettings() { + // values of "default" or null will default to true only if the world environment is normal (aka overworld) -+ Predicate predicate = (bool) -> (bool != null && bool) || (bool == null && environment == Environment.NORMAL); ++ Predicate predicate = (bool) -> (bool != null && bool) || (bool == null && environment == World.Environment.NORMAL); + catSpawning = getBoolean("gameplay-mechanics.mob-spawning.village-cats", predicate); + patrolSpawning = getBoolean("gameplay-mechanics.mob-spawning.raid-patrols", predicate); + phantomSpawning = getBoolean("gameplay-mechanics.mob-spawning.phantoms", predicate); diff --git a/patches/server/0110-Raid-cooldown-setting.patch b/patches/server/0110-Raid-cooldown-setting.patch index e7504aee8..ac3b1f616 100644 --- a/patches/server/0110-Raid-cooldown-setting.patch +++ b/patches/server/0110-Raid-cooldown-setting.patch @@ -4,11 +4,11 @@ Date: Thu, 27 Aug 2020 13:48:52 -0700 Subject: [PATCH] Raid cooldown setting -diff --git a/src/main/java/net/minecraft/server/PersistentRaid.java b/src/main/java/net/minecraft/server/PersistentRaid.java -index 826dcf9f7eedc3664d66170b97b2a19552a0dc60..807910c60e6cad58b91474b0477e6fc109eaf281 100644 ---- a/src/main/java/net/minecraft/server/PersistentRaid.java -+++ b/src/main/java/net/minecraft/server/PersistentRaid.java -@@ -9,6 +9,7 @@ import javax.annotation.Nullable; +diff --git a/src/main/java/net/minecraft/world/entity/raid/PersistentRaid.java b/src/main/java/net/minecraft/world/entity/raid/PersistentRaid.java +index c939ca087af4588e14669a2d53d7c116dcb59f16..11271762dcf5783c3179de1afc6a882c5330b4dd 100644 +--- a/src/main/java/net/minecraft/world/entity/raid/PersistentRaid.java ++++ b/src/main/java/net/minecraft/world/entity/raid/PersistentRaid.java +@@ -27,6 +27,7 @@ import net.minecraft.world.phys.Vec3D; public class PersistentRaid extends PersistentBase { @@ -16,7 +16,7 @@ index 826dcf9f7eedc3664d66170b97b2a19552a0dc60..807910c60e6cad58b91474b0477e6fc1 public final Map raids = Maps.newHashMap(); private final WorldServer b; private int c; -@@ -27,6 +28,17 @@ public class PersistentRaid extends PersistentBase { +@@ -45,6 +46,17 @@ public class PersistentRaid extends PersistentBase { public void a() { ++this.d; @@ -34,7 +34,7 @@ index 826dcf9f7eedc3664d66170b97b2a19552a0dc60..807910c60e6cad58b91474b0477e6fc1 Iterator iterator = this.raids.values().iterator(); while (iterator.hasNext()) { -@@ -110,10 +122,15 @@ public class PersistentRaid extends PersistentBase { +@@ -128,10 +140,15 @@ public class PersistentRaid extends PersistentBase { if (flag) { // CraftBukkit start @@ -52,7 +52,7 @@ index 826dcf9f7eedc3664d66170b97b2a19552a0dc60..807910c60e6cad58b91474b0477e6fc1 if (!this.raids.containsKey(raid.getId())) { this.raids.put(raid.getId(), raid); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index c8666ce6bdf2e61dd3ccc7ff6cc0810559ce3f5b..1c9db2dc3d5577906aa1ac208aad3c6865040381 100644 +index 1d144ed296120eccee1001fd1299ead48351cbfa..9dcc2f52641e9196487744f4a1e8ae0f312aaff8 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -173,6 +173,7 @@ public class PurpurWorldConfig { diff --git a/patches/server/0111-Despawn-rate-config-options-per-projectile-type.patch b/patches/server/0111-Despawn-rate-config-options-per-projectile-type.patch index 44a5d762a..0e27c10f7 100644 --- a/patches/server/0111-Despawn-rate-config-options-per-projectile-type.patch +++ b/patches/server/0111-Despawn-rate-config-options-per-projectile-type.patch @@ -5,11 +5,11 @@ Subject: [PATCH] Despawn rate config options per projectile type Default values of -1 respect vanilla behaviour. -diff --git a/src/main/java/net/minecraft/server/EntityArrow.java b/src/main/java/net/minecraft/server/EntityArrow.java -index 7532e4e6fc561645e7e7a4f703025af77825b0bd..ee24500e63830b34dd575feed4ef8ecb021d3501 100644 ---- a/src/main/java/net/minecraft/server/EntityArrow.java -+++ b/src/main/java/net/minecraft/server/EntityArrow.java -@@ -23,7 +23,7 @@ public abstract class EntityArrow extends IProjectile { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java +index e440d26c920c4efddf958c61bfdfa508273062cc..3ee404effe339a5742926255da6a9c41d1bc9367 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java +@@ -61,7 +61,7 @@ public abstract class EntityArrow extends IProjectile { protected int c; public EntityArrow.PickupStatus fromPlayer; public int shake; @@ -18,7 +18,7 @@ index 7532e4e6fc561645e7e7a4f703025af77825b0bd..ee24500e63830b34dd575feed4ef8ecb private double damage; public int knockbackStrength; private SoundEffect ak; -@@ -257,13 +257,23 @@ public abstract class EntityArrow extends IProjectile { +@@ -295,13 +295,23 @@ public abstract class EntityArrow extends IProjectile { } @@ -47,11 +47,11 @@ index 7532e4e6fc561645e7e7a4f703025af77825b0bd..ee24500e63830b34dd575feed4ef8ecb } private void A() { -diff --git a/src/main/java/net/minecraft/server/EntityDragonFireball.java b/src/main/java/net/minecraft/server/EntityDragonFireball.java -index 27032abad4f3da1d1b28a3cec49e3fc079deadb9..9d2d5be5eedc60749e276434be9be6ab41f2289d 100644 ---- a/src/main/java/net/minecraft/server/EntityDragonFireball.java -+++ b/src/main/java/net/minecraft/server/EntityDragonFireball.java -@@ -75,4 +75,11 @@ public class EntityDragonFireball extends EntityFireball { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityDragonFireball.java b/src/main/java/net/minecraft/world/entity/projectile/EntityDragonFireball.java +index 27853f510e15e40c66da2cb4905c43f5e8f99d3d..98dcfedc8826ebb067438be713549e2cfb19ebb0 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityDragonFireball.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityDragonFireball.java +@@ -87,4 +87,11 @@ public class EntityDragonFireball extends EntityFireball { protected boolean W_() { return false; } @@ -63,11 +63,11 @@ index 27032abad4f3da1d1b28a3cec49e3fc079deadb9..9d2d5be5eedc60749e276434be9be6ab + } + // Purpur end } -diff --git a/src/main/java/net/minecraft/server/EntityEgg.java b/src/main/java/net/minecraft/server/EntityEgg.java -index edce89169b3ca2894852087b83a6bf035ba43c3f..4951abdfa13d170b7075a0223dd0096d77dec6ea 100644 ---- a/src/main/java/net/minecraft/server/EntityEgg.java -+++ b/src/main/java/net/minecraft/server/EntityEgg.java -@@ -87,4 +87,11 @@ public class EntityEgg extends EntityProjectileThrowable { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityEgg.java b/src/main/java/net/minecraft/world/entity/projectile/EntityEgg.java +index dc2e51718395494f60b0376d65d496daf2f76e71..d97511c27ff376b2dd0fbedb227f9a0c337a1264 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityEgg.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityEgg.java +@@ -99,4 +99,11 @@ public class EntityEgg extends EntityProjectileThrowable { protected Item getDefaultItem() { return Items.EGG; } @@ -79,11 +79,11 @@ index edce89169b3ca2894852087b83a6bf035ba43c3f..4951abdfa13d170b7075a0223dd0096d + } + // Purpur end } -diff --git a/src/main/java/net/minecraft/server/EntityEnderPearl.java b/src/main/java/net/minecraft/server/EntityEnderPearl.java -index e42dd066e76a3d2bc3270774f48bb8c8fd47cc38..44dbe818b19c927098c1e6b2bcb556378be5637c 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderPearl.java -+++ b/src/main/java/net/minecraft/server/EntityEnderPearl.java -@@ -107,4 +107,11 @@ public class EntityEnderPearl extends EntityProjectileThrowable { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityEnderPearl.java b/src/main/java/net/minecraft/world/entity/projectile/EntityEnderPearl.java +index efdf5bc4f07231690c680429b3f77bd07970eee0..cf2c691357c41a7e7044f7a719144db2ffab5dbe 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityEnderPearl.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityEnderPearl.java +@@ -122,4 +122,11 @@ public class EntityEnderPearl extends EntityProjectileThrowable { return super.b(worldserver); } @@ -95,11 +95,11 @@ index e42dd066e76a3d2bc3270774f48bb8c8fd47cc38..44dbe818b19c927098c1e6b2bcb55637 + } + // Purpur end } -diff --git a/src/main/java/net/minecraft/server/EntityFireworks.java b/src/main/java/net/minecraft/server/EntityFireworks.java -index 7ec62d734542d64809c71776eb865ff8ca51dc7f..dad470dacd6a94d2b37ee1aff6c0d7f54fa61794 100644 ---- a/src/main/java/net/minecraft/server/EntityFireworks.java -+++ b/src/main/java/net/minecraft/server/EntityFireworks.java -@@ -301,4 +301,11 @@ public class EntityFireworks extends IProjectile { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java +index f9a355c847d778a9aad1987882fc816af92450ba..9b4b8b1a0f7654c9c30ca614cac6f485f82db5ef 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java +@@ -325,4 +325,11 @@ public class EntityFireworks extends IProjectile { public Packet P() { return new PacketPlayOutSpawnEntity(this); } @@ -111,11 +111,11 @@ index 7ec62d734542d64809c71776eb865ff8ca51dc7f..dad470dacd6a94d2b37ee1aff6c0d7f5 + } + // Purpur end } -diff --git a/src/main/java/net/minecraft/server/EntityFishingHook.java b/src/main/java/net/minecraft/server/EntityFishingHook.java -index 9841c7c27cd296a5156ba79ab734d45922bacaf7..f0502c7f5419f637641b48d8c87f5df206e4f922 100644 ---- a/src/main/java/net/minecraft/server/EntityFishingHook.java -+++ b/src/main/java/net/minecraft/server/EntityFishingHook.java -@@ -579,4 +579,11 @@ public class EntityFishingHook extends IProjectile { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java +index dc6d279766ccc83a8f450028a09491b1c88f524c..5a5773209183331d849368c6b300367ac0ebe203 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java +@@ -617,4 +617,11 @@ public class EntityFishingHook extends IProjectile { private HookState() {} } @@ -127,11 +127,11 @@ index 9841c7c27cd296a5156ba79ab734d45922bacaf7..f0502c7f5419f637641b48d8c87f5df2 + } + // Purpur end } -diff --git a/src/main/java/net/minecraft/server/EntityLargeFireball.java b/src/main/java/net/minecraft/server/EntityLargeFireball.java -index b4b0dfbc70f91f74f9792b835ec2f8d5af41c311..d12de20cf4bb2345c616d3cc0b9f50bddb5135ee 100644 ---- a/src/main/java/net/minecraft/server/EntityLargeFireball.java -+++ b/src/main/java/net/minecraft/server/EntityLargeFireball.java -@@ -66,4 +66,11 @@ public class EntityLargeFireball extends EntityFireballFireball { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityLargeFireball.java b/src/main/java/net/minecraft/world/entity/projectile/EntityLargeFireball.java +index cf2663d9883654f53b327246d85ee63c3990cd71..e860737bacfea0a1d728dbaaf41d62165658ad89 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityLargeFireball.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityLargeFireball.java +@@ -77,4 +77,11 @@ public class EntityLargeFireball extends EntityFireballFireball { } } @@ -143,11 +143,11 @@ index b4b0dfbc70f91f74f9792b835ec2f8d5af41c311..d12de20cf4bb2345c616d3cc0b9f50bd + } + // Purpur end } -diff --git a/src/main/java/net/minecraft/server/EntityLlamaSpit.java b/src/main/java/net/minecraft/server/EntityLlamaSpit.java -index 480a02a8f6ec7110f9af8f2037fdc09a7a54ef01..aa9afb60808a9988b38cf588ec9f649ee09c728e 100644 ---- a/src/main/java/net/minecraft/server/EntityLlamaSpit.java -+++ b/src/main/java/net/minecraft/server/EntityLlamaSpit.java -@@ -73,4 +73,11 @@ public class EntityLlamaSpit extends IProjectile { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityLlamaSpit.java b/src/main/java/net/minecraft/world/entity/projectile/EntityLlamaSpit.java +index 8aef834a6e8fcf5d44986745affb8f27bc3dfd6b..0bfb80331cea6bd2cf85a9475b6416691edd8b0b 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityLlamaSpit.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityLlamaSpit.java +@@ -88,4 +88,11 @@ public class EntityLlamaSpit extends IProjectile { public Packet P() { return new PacketPlayOutSpawnEntity(this); } @@ -159,11 +159,11 @@ index 480a02a8f6ec7110f9af8f2037fdc09a7a54ef01..aa9afb60808a9988b38cf588ec9f649e + } + // Purpur end } -diff --git a/src/main/java/net/minecraft/server/EntityPotion.java b/src/main/java/net/minecraft/server/EntityPotion.java -index b338cb771aa8ba7a810b8129ca04640d115b68ba..dfc0538cc8cb8015fe79978ee360c86127118330 100644 ---- a/src/main/java/net/minecraft/server/EntityPotion.java -+++ b/src/main/java/net/minecraft/server/EntityPotion.java -@@ -241,4 +241,11 @@ public class EntityPotion extends EntityProjectileThrowable { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityPotion.java b/src/main/java/net/minecraft/world/entity/projectile/EntityPotion.java +index dbc0afc5fb9e358a3e6d596692f57fb28303c4da..a3344719bcf178df5b63cda6f6a854c2df174fa5 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityPotion.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityPotion.java +@@ -270,4 +270,11 @@ public class EntityPotion extends EntityProjectileThrowable { } } @@ -175,11 +175,11 @@ index b338cb771aa8ba7a810b8129ca04640d115b68ba..dfc0538cc8cb8015fe79978ee360c861 + } + // Purpur end } -diff --git a/src/main/java/net/minecraft/server/EntityShulkerBullet.java b/src/main/java/net/minecraft/server/EntityShulkerBullet.java -index a4d94385ede0303417d676155c2c0b226681cc59..da38bdd6055d06005cfee3e73c32230ad7b480ff 100644 ---- a/src/main/java/net/minecraft/server/EntityShulkerBullet.java -+++ b/src/main/java/net/minecraft/server/EntityShulkerBullet.java -@@ -313,4 +313,11 @@ public class EntityShulkerBullet extends IProjectile { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityShulkerBullet.java b/src/main/java/net/minecraft/world/entity/projectile/EntityShulkerBullet.java +index 1ae528ccd09a6536b3aac320e6218f03c274d6a9..cfc1376bfed9399daa6f27f54780ccf8e05753c6 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityShulkerBullet.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityShulkerBullet.java +@@ -337,4 +337,11 @@ public class EntityShulkerBullet extends IProjectile { public Packet P() { return new PacketPlayOutSpawnEntity(this); } @@ -191,11 +191,11 @@ index a4d94385ede0303417d676155c2c0b226681cc59..da38bdd6055d06005cfee3e73c32230a + } + // Purpur end } -diff --git a/src/main/java/net/minecraft/server/EntitySmallFireball.java b/src/main/java/net/minecraft/server/EntitySmallFireball.java -index 350e92ac99fe48ba046a51e1db4b977dd9bfc20a..4ed7a20bfed267776628457a4b33178bac7d1972 100644 ---- a/src/main/java/net/minecraft/server/EntitySmallFireball.java -+++ b/src/main/java/net/minecraft/server/EntitySmallFireball.java -@@ -86,4 +86,11 @@ public class EntitySmallFireball extends EntityFireballFireball { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntitySmallFireball.java b/src/main/java/net/minecraft/world/entity/projectile/EntitySmallFireball.java +index d139c5806e5971e82865c2ce627e87c631e42d7a..bf747cbf6e1ef9ea9d1d41d0441b29a46ce874c0 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntitySmallFireball.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntitySmallFireball.java +@@ -100,4 +100,11 @@ public class EntitySmallFireball extends EntityFireballFireball { public boolean damageEntity(DamageSource damagesource, float f) { return false; } @@ -207,11 +207,11 @@ index 350e92ac99fe48ba046a51e1db4b977dd9bfc20a..4ed7a20bfed267776628457a4b33178b + } + // Purpur end } -diff --git a/src/main/java/net/minecraft/server/EntitySnowball.java b/src/main/java/net/minecraft/server/EntitySnowball.java -index e44249f59b742d16f08643ee2a83fdcd0bed9590..34a5f481e6ed1357861dca15fb4013ec8484a292 100644 ---- a/src/main/java/net/minecraft/server/EntitySnowball.java -+++ b/src/main/java/net/minecraft/server/EntitySnowball.java -@@ -14,6 +14,12 @@ public class EntitySnowball extends EntityProjectileThrowable { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntitySnowball.java b/src/main/java/net/minecraft/world/entity/projectile/EntitySnowball.java +index 3ec380ec35fade3bcc61c5f45cee651eb45ae073..0d3b9c81e47eef645335e49a1d6d88db7338aa4b 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntitySnowball.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntitySnowball.java +@@ -25,6 +25,12 @@ public class EntitySnowball extends EntityProjectileThrowable { super(EntityTypes.SNOWBALL, d0, d1, d2, world); } @@ -224,11 +224,11 @@ index e44249f59b742d16f08643ee2a83fdcd0bed9590..34a5f481e6ed1357861dca15fb4013ec @Override protected Item getDefaultItem() { return Items.SNOWBALL; -diff --git a/src/main/java/net/minecraft/server/EntityThrownExpBottle.java b/src/main/java/net/minecraft/server/EntityThrownExpBottle.java -index 2d3ca8c424f2088027d51066d634c48723e96214..1d32518bd7982f20574d56f2f2ea4142ea1e015d 100644 ---- a/src/main/java/net/minecraft/server/EntityThrownExpBottle.java -+++ b/src/main/java/net/minecraft/server/EntityThrownExpBottle.java -@@ -51,4 +51,11 @@ public class EntityThrownExpBottle extends EntityProjectileThrowable { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityThrownExpBottle.java b/src/main/java/net/minecraft/world/entity/projectile/EntityThrownExpBottle.java +index e07353a6b34196e3d275ba482fbef7e4d209c31d..6ef87bd6969603a51f09034ad87b89ab8a25eadb 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityThrownExpBottle.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityThrownExpBottle.java +@@ -61,4 +61,11 @@ public class EntityThrownExpBottle extends EntityProjectileThrowable { } } @@ -240,11 +240,11 @@ index 2d3ca8c424f2088027d51066d634c48723e96214..1d32518bd7982f20574d56f2f2ea4142 + } + // Purpur end } -diff --git a/src/main/java/net/minecraft/server/EntityWitherSkull.java b/src/main/java/net/minecraft/server/EntityWitherSkull.java -index 2c02e114cce1f49b643e75e7ab3c05be716d7dba..4a97a7517dc1a2a25c578d9e168240cc19ab0831 100644 ---- a/src/main/java/net/minecraft/server/EntityWitherSkull.java -+++ b/src/main/java/net/minecraft/server/EntityWitherSkull.java -@@ -116,4 +116,11 @@ public class EntityWitherSkull extends EntityFireball { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityWitherSkull.java b/src/main/java/net/minecraft/world/entity/projectile/EntityWitherSkull.java +index 021a7e31dc3650c0c404a893374528e6a63dfbad..2fe0e32a1158cccb3060f5a986c9fc41a0237aa8 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityWitherSkull.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityWitherSkull.java +@@ -137,4 +137,11 @@ public class EntityWitherSkull extends EntityFireball { protected boolean W_() { return false; } @@ -256,11 +256,11 @@ index 2c02e114cce1f49b643e75e7ab3c05be716d7dba..4a97a7517dc1a2a25c578d9e168240cc + } + // Purpur end } -diff --git a/src/main/java/net/minecraft/server/IProjectile.java b/src/main/java/net/minecraft/server/IProjectile.java -index b7e540dfeeabb13227596ecfc6eddabf3cfde537..56adefabdfbf444e87129715f107c6d3aafe4ca7 100644 ---- a/src/main/java/net/minecraft/server/IProjectile.java -+++ b/src/main/java/net/minecraft/server/IProjectile.java -@@ -13,11 +13,25 @@ public abstract class IProjectile extends Entity { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java +index 3914081629669aea19d50530db996728bbfa607f..62fa5be9090c8789e91bf9b9f614e74a4a6babdd 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java +@@ -25,11 +25,25 @@ public abstract class IProjectile extends Entity { private UUID shooter; private int c; private boolean d; public boolean leftOwner() { return d; } public void setLeftOwner(boolean leftOwner) { this.d = leftOwner; } // Purpur - OBFHELPER @@ -286,7 +286,7 @@ index b7e540dfeeabb13227596ecfc6eddabf3cfde537..56adefabdfbf444e87129715f107c6d3 public void setShooter(@Nullable Entity entity) { if (entity != null) { this.shooter = entity.getUniqueID(); -@@ -72,6 +86,12 @@ public abstract class IProjectile extends Entity { +@@ -84,6 +98,12 @@ public abstract class IProjectile extends Entity { } super.tick(); @@ -300,7 +300,7 @@ index b7e540dfeeabb13227596ecfc6eddabf3cfde537..56adefabdfbf444e87129715f107c6d3 public boolean checkIfLeftOwner() { return this.h(); } // Purpur - OBFHELPER diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 1c9db2dc3d5577906aa1ac208aad3c6865040381..c9884c382e3e16db0d4c1b7d0d804aafbd6a3fa8 100644 +index 9dcc2f52641e9196487744f4a1e8ae0f312aaff8..43b11c9e8af513002318e11ed58a3f2afa1c7a89 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -165,6 +165,35 @@ public class PurpurWorldConfig { diff --git a/patches/server/0112-Add-option-to-disable-zombie-aggressiveness-towards-.patch b/patches/server/0112-Add-option-to-disable-zombie-aggressiveness-towards-.patch index d44ee2058..01573bd6c 100644 --- a/patches/server/0112-Add-option-to-disable-zombie-aggressiveness-towards-.patch +++ b/patches/server/0112-Add-option-to-disable-zombie-aggressiveness-towards-.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add option to disable zombie aggressiveness towards villagers diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java -index 89b56de7567ae54be75e0735b712e4dd713f1bf4..ded483ace0e93b695a5078391582c1654b6d139a 100644 +index f62d0ee49ebda2b0c7a136562b24ee038502d048..995ccf9abfd91780168091da95c9af758f177b98 100644 --- a/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java +++ b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java -@@ -131,6 +131,10 @@ public class MobGoalHelper { +@@ -305,6 +305,10 @@ public class MobGoalHelper { deobfuscationMap.put("wither_a", "wither_do_nothing"); deobfuscationMap.put("wolf_a", "wolf_avoid_entity"); deobfuscationMap.put("zombie_a", "zombie_attack_turtle_egg"); @@ -20,11 +20,11 @@ index 89b56de7567ae54be75e0735b712e4dd713f1bf4..ded483ace0e93b695a5078391582c165 ignored.add("selector_1"); ignored.add("selector_2"); -diff --git a/src/main/java/net/minecraft/server/EntityDrowned.java b/src/main/java/net/minecraft/server/EntityDrowned.java -index 125eab60f2b4657e52a71eddf7586c574945252e..638efc67d66001ee085957d4698f51a7daac77fc 100644 ---- a/src/main/java/net/minecraft/server/EntityDrowned.java -+++ b/src/main/java/net/minecraft/server/EntityDrowned.java -@@ -58,7 +58,18 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java b/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java +index 1d4039d61a2c77a38a31947010cee26f41c0becd..93946f4e3cad07e20189a44ce512682b4cbc163b 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java +@@ -109,7 +109,18 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { this.goalSelector.a(7, new PathfinderGoalRandomStroll(this, 1.0D)); this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityDrowned.class})).a(EntityPigZombie.class)); this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, this::i)); @@ -44,11 +44,11 @@ index 125eab60f2b4657e52a71eddf7586c574945252e..638efc67d66001ee085957d4698f51a7 this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityIronGolem.class, true)); this.targetSelector.a(5, new PathfinderGoalNearestAttackableTarget<>(this, EntityTurtle.class, 10, true, false, EntityTurtle.bo)); } -diff --git a/src/main/java/net/minecraft/server/EntityZombie.java b/src/main/java/net/minecraft/server/EntityZombie.java -index 2076fe3e467c16bb400a75f9ea82f5b0773126be..e4de6e2f8b72c0ede3ad34666a5dfde5c5363b56 100644 ---- a/src/main/java/net/minecraft/server/EntityZombie.java -+++ b/src/main/java/net/minecraft/server/EntityZombie.java -@@ -85,7 +85,18 @@ public class EntityZombie extends EntityMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +index 901fe8d224130c67bad00636b065bc798859a18e..88264b7b2c21a377f4b0dd857065e40165f0acde 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +@@ -148,7 +148,18 @@ public class EntityZombie extends EntityMonster { this.goalSelector.a(7, new PathfinderGoalRandomStrollLand(this, 1.0D)); this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[0])).a(EntityPigZombie.class)); this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); @@ -69,7 +69,7 @@ index 2076fe3e467c16bb400a75f9ea82f5b0773126be..e4de6e2f8b72c0ede3ad34666a5dfde5 this.targetSelector.a(5, new PathfinderGoalNearestAttackableTarget<>(this, EntityTurtle.class, 10, true, false, EntityTurtle.bo)); } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index c9884c382e3e16db0d4c1b7d0d804aafbd6a3fa8..6d0d43e77bbf6f792257eb368e572b1bfade3266 100644 +index 43b11c9e8af513002318e11ed58a3f2afa1c7a89..22aa4709d1db75eb901a6145b75689bd766bf10b 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -1023,12 +1023,14 @@ public class PurpurWorldConfig { diff --git a/patches/server/0113-Persistent-TileEntity-Lore-and-DisplayName.patch b/patches/server/0113-Persistent-TileEntity-Lore-and-DisplayName.patch index 6fdf68dc1..43a3360ef 100644 --- a/patches/server/0113-Persistent-TileEntity-Lore-and-DisplayName.patch +++ b/patches/server/0113-Persistent-TileEntity-Lore-and-DisplayName.patch @@ -6,11 +6,81 @@ Subject: [PATCH] Persistent TileEntity Lore and DisplayName Makes it so that when a TileEntity is placed in the world and then broken, the dropped ItemStack retains any original custom display name/lore. -diff --git a/src/main/java/net/minecraft/server/Block.java b/src/main/java/net/minecraft/server/Block.java -index d3026d8911c73e23315a545b9eb0753306c0e825..2c8d7024879392f37e53dfb72cc07971c7b4f27c 100644 ---- a/src/main/java/net/minecraft/server/Block.java -+++ b/src/main/java/net/minecraft/server/Block.java -@@ -207,7 +207,7 @@ public class Block extends BlockBase implements IMaterial { +diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityPainting.java b/src/main/java/net/minecraft/world/entity/decoration/EntityPainting.java +index 9c01ec42342cf0420bf5215604c24fbc89c1361b..3de0f21648ca60bdfcbc078bca896d51bf84e207 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/EntityPainting.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/EntityPainting.java +@@ -15,6 +15,7 @@ import net.minecraft.sounds.SoundEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.player.EntityHuman; ++import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.IMaterial; +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java +index 01839c7319e175477ded7001e00e5937734ff516..e5cda8c040c93639211dacbf5b0c7cd6a9df9e6d 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java +@@ -34,6 +34,7 @@ import net.minecraft.world.entity.animal.EntityAnimal; + import net.minecraft.world.entity.animal.EntityWaterAnimal; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.Item; ++import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.IMaterial; +diff --git a/src/main/java/net/minecraft/world/item/ItemBlock.java b/src/main/java/net/minecraft/world/item/ItemBlock.java +index 59d52c252b2e59923b8e513dd4d2e1ec9ce34dc7..4be1c8ee85f411a8b01be50b8cc3dc3835f80a2e 100644 +--- a/src/main/java/net/minecraft/world/item/ItemBlock.java ++++ b/src/main/java/net/minecraft/world/item/ItemBlock.java +@@ -119,7 +119,24 @@ public class ItemBlock extends Item { + } + + protected boolean a(BlockPosition blockposition, World world, @Nullable EntityHuman entityhuman, ItemStack itemstack, IBlockData iblockdata) { +- return a(world, entityhuman, blockposition, itemstack); ++ // Purpur start ++ boolean handled = a(world, entityhuman, blockposition, itemstack); ++ if (world.purpurConfig.persistentTileEntityDisplayNames && itemstack.hasTag()) { ++ NBTTagCompound display = itemstack.getSubTag("display"); ++ if (display != null) { ++ TileEntity tile = world.getTileEntity(blockposition); ++ if (tile != null) { ++ if (display.hasKeyOfType("Name", 8)) { ++ tile.setPersistentDisplayName(display.getString("Name")); ++ } ++ if (display.hasKeyOfType("Lore", 9)) { ++ tile.setPersistentLore(display.getList("Lore", 8)); ++ } ++ } ++ } ++ } ++ return handled; ++ // Purpur end + } + + @Nullable +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index 97eb81338207c93125bea082256384946a8305bb..eecb17e887bf0d1680a5fb5198a8b4246c14e548 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -15,10 +15,15 @@ import net.minecraft.core.EnumDirection; + import net.minecraft.core.IRegistry; + import net.minecraft.core.NonNullList; + import net.minecraft.core.RegistryBlockID; ++import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.nbt.NBTTagList; ++import net.minecraft.nbt.NBTTagString; ++import net.minecraft.network.chat.IChatBaseComponent; + import net.minecraft.server.level.WorldServer; + import net.minecraft.stats.StatisticList; + import net.minecraft.tags.Tag; + import net.minecraft.tags.TagsBlock; ++import net.minecraft.world.INamableTileEntity; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityExperienceOrb; + import net.minecraft.world.entity.EntityLiving; +@@ -248,7 +253,7 @@ public class Block extends BlockBase implements IMaterial { public static void a(IBlockData iblockdata, GeneratorAccess generatoraccess, BlockPosition blockposition, @Nullable TileEntity tileentity) { if (generatoraccess instanceof WorldServer) { a(iblockdata, (WorldServer) generatoraccess, blockposition, tileentity).forEach((itemstack) -> { @@ -19,7 +89,7 @@ index d3026d8911c73e23315a545b9eb0753306c0e825..2c8d7024879392f37e53dfb72cc07971 }); iblockdata.dropNaturally((WorldServer) generatoraccess, blockposition, ItemStack.b); } -@@ -216,14 +216,56 @@ public class Block extends BlockBase implements IMaterial { +@@ -257,14 +262,56 @@ public class Block extends BlockBase implements IMaterial { public static void dropItems(IBlockData iblockdata, World world, BlockPosition blockposition, @Nullable TileEntity tileentity, Entity entity, ItemStack itemstack) { if (world instanceof WorldServer) { @@ -78,41 +148,20 @@ index d3026d8911c73e23315a545b9eb0753306c0e825..2c8d7024879392f37e53dfb72cc07971 public static void a(World world, BlockPosition blockposition, ItemStack itemstack) { dropItem(world, blockposition, itemstack); } public static void dropItem(World world, BlockPosition blockposition, ItemStack itemstack) { // Paper - OBFHELPER if (!world.isClientSide && !itemstack.isEmpty() && world.getGameRules().getBoolean(GameRules.DO_TILE_DROPS)) { float f = 0.5F; -diff --git a/src/main/java/net/minecraft/server/ItemBlock.java b/src/main/java/net/minecraft/server/ItemBlock.java -index ae2ad70699347e169d941266ec3ad1af4c9b3786..e4aea92040b58a5c87258ac6fd735f21709a45a3 100644 ---- a/src/main/java/net/minecraft/server/ItemBlock.java -+++ b/src/main/java/net/minecraft/server/ItemBlock.java -@@ -97,7 +97,24 @@ public class ItemBlock extends Item { - } - - protected boolean a(BlockPosition blockposition, World world, @Nullable EntityHuman entityhuman, ItemStack itemstack, IBlockData iblockdata) { -- return a(world, entityhuman, blockposition, itemstack); -+ // Purpur start -+ boolean handled = a(world, entityhuman, blockposition, itemstack); -+ if (world.purpurConfig.persistentTileEntityDisplayNames && itemstack.hasTag()) { -+ NBTTagCompound display = itemstack.getSubTag("display"); -+ if (display != null) { -+ TileEntity tile = world.getTileEntity(blockposition); -+ if (tile != null) { -+ if (display.hasKeyOfType("Name", 8)) { -+ tile.setPersistentDisplayName(display.getString("Name")); -+ } -+ if (display.hasKeyOfType("Lore", 9)) { -+ tile.setPersistentLore(display.getList("Lore", 8)); -+ } -+ } -+ } -+ } -+ return handled; -+ // Purpur end - } - - @Nullable -diff --git a/src/main/java/net/minecraft/server/TileEntity.java b/src/main/java/net/minecraft/server/TileEntity.java -index 060c1206e4b5da6be50fff605894fb2a46f57c1b..c0d465749093b1a18bd5179eb28ae06a00850185 100644 ---- a/src/main/java/net/minecraft/server/TileEntity.java -+++ b/src/main/java/net/minecraft/server/TileEntity.java -@@ -93,9 +93,25 @@ public abstract class TileEntity implements KeyedObject { // Paper +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java +index f1e586754396439dfb70a4d63e3b8b34fb36ebf4..8a049d3de8937a6c8afe178ccd134e2511fb3baf 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java +@@ -5,6 +5,8 @@ import net.minecraft.CrashReportSystemDetails; + import net.minecraft.core.BlockPosition; + import net.minecraft.core.IRegistry; + import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.nbt.NBTTagList; ++import net.minecraft.nbt.NBTTagString; + import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData; + import net.minecraft.resources.MinecraftKey; + import net.minecraft.world.level.World; +@@ -104,9 +106,25 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / this.persistentDataContainer.putAll((NBTTagCompound) persistentDataTag); } // CraftBukkit end @@ -138,7 +187,7 @@ index 060c1206e4b5da6be50fff605894fb2a46f57c1b..c0d465749093b1a18bd5179eb28ae06a return this.b(nbttagcompound); } -@@ -256,4 +272,25 @@ public abstract class TileEntity implements KeyedObject { // Paper +@@ -267,4 +285,25 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / return null; } // CraftBukkit end @@ -165,7 +214,7 @@ index 060c1206e4b5da6be50fff605894fb2a46f57c1b..c0d465749093b1a18bd5179eb28ae06a + // Purpur end } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 6d0d43e77bbf6f792257eb368e572b1bfade3266..4515c95a195ab962513ddc6868f9cdfd47f61d68 100644 +index 22aa4709d1db75eb901a6145b75689bd766bf10b..4843d4a0794e05386d6cdf05a7059598291aafe7 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -200,6 +200,7 @@ public class PurpurWorldConfig { diff --git a/patches/server/0114-Add-predicate-to-recipe-s-ExactChoice-ingredient.patch b/patches/server/0114-Add-predicate-to-recipe-s-ExactChoice-ingredient.patch index 3cb204733..2e1d8f600 100644 --- a/patches/server/0114-Add-predicate-to-recipe-s-ExactChoice-ingredient.patch +++ b/patches/server/0114-Add-predicate-to-recipe-s-ExactChoice-ingredient.patch @@ -4,11 +4,11 @@ Date: Sat, 3 Oct 2020 17:40:52 -0500 Subject: [PATCH] Add predicate to recipe's ExactChoice ingredient -diff --git a/src/main/java/net/minecraft/server/RecipeItemStack.java b/src/main/java/net/minecraft/server/RecipeItemStack.java -index 0f96abd0ca78e9c78306fed69684dee71be37703..f6d92949409b66d5d0c578e010aebd058903c6fa 100644 ---- a/src/main/java/net/minecraft/server/RecipeItemStack.java -+++ b/src/main/java/net/minecraft/server/RecipeItemStack.java -@@ -26,6 +26,7 @@ public final class RecipeItemStack implements Predicate { +diff --git a/src/main/java/net/minecraft/world/item/crafting/RecipeItemStack.java b/src/main/java/net/minecraft/world/item/crafting/RecipeItemStack.java +index 63274908bc7552321a4db3d4e0eec0f55ee34786..c7f6dc5a933873a6118a5674e4ce04cfa1664f60 100644 +--- a/src/main/java/net/minecraft/world/item/crafting/RecipeItemStack.java ++++ b/src/main/java/net/minecraft/world/item/crafting/RecipeItemStack.java +@@ -36,6 +36,7 @@ public final class RecipeItemStack implements Predicate { public ItemStack[] choices; private IntList d; public boolean exact; // CraftBukkit @@ -16,7 +16,7 @@ index 0f96abd0ca78e9c78306fed69684dee71be37703..f6d92949409b66d5d0c578e010aebd05 public RecipeItemStack(Stream stream) { this.b = (RecipeItemStack.Provider[]) stream.toArray((i) -> { -@@ -52,6 +53,12 @@ public final class RecipeItemStack implements Predicate { +@@ -62,6 +63,12 @@ public final class RecipeItemStack implements Predicate { if (this.choices.length == 0) { return itemstack.isEmpty(); } else { @@ -30,12 +30,12 @@ index 0f96abd0ca78e9c78306fed69684dee71be37703..f6d92949409b66d5d0c578e010aebd05 int i = aitemstack.length; diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java -index ef29599a89bc630899c65df9a7004f836787d95e..18413e6327458c6d60d2a0ca8167fc5d75389934 100644 +index b7e8c3798628229be56289818caa3024014640d6..43c50c2c54444c67e4a875be4880afe97c32412c 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java @@ -22,6 +22,7 @@ public interface CraftRecipe extends Recipe { } else if (bukkit instanceof RecipeChoice.ExactChoice) { - stack = new RecipeItemStack(((RecipeChoice.ExactChoice) bukkit).getChoices().stream().map((mat) -> new net.minecraft.server.RecipeItemStack.StackProvider(CraftItemStack.asNMSCopy(mat)))); + stack = new RecipeItemStack(((RecipeChoice.ExactChoice) bukkit).getChoices().stream().map((mat) -> new net.minecraft.world.item.crafting.RecipeItemStack.StackProvider(CraftItemStack.asNMSCopy(mat)))); stack.exact = true; + stack.predicate = ((RecipeChoice.ExactChoice) bukkit).getPredicate(); // Purpur } else { diff --git a/patches/server/0115-Flying-squids-Oh-my.patch b/patches/server/0115-Flying-squids-Oh-my.patch index cc82d9481..f2b5e6f13 100644 --- a/patches/server/0115-Flying-squids-Oh-my.patch +++ b/patches/server/0115-Flying-squids-Oh-my.patch @@ -4,11 +4,11 @@ Date: Sun, 4 Oct 2020 12:00:42 -0500 Subject: [PATCH] Flying squids! Oh my! -diff --git a/src/main/java/net/minecraft/server/EntitySquid.java b/src/main/java/net/minecraft/server/EntitySquid.java -index 70b952f10a2af547f58069977ee135469d02f84d..cee226501690e1c00983a01ac82bc7384f233c3c 100644 ---- a/src/main/java/net/minecraft/server/EntitySquid.java -+++ b/src/main/java/net/minecraft/server/EntitySquid.java -@@ -51,6 +51,11 @@ public class EntitySquid extends EntityWaterAnimal { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java +index 10e228a36b213a87e17f26a633adfca18a006e94..07b1db0e1fff1beffe464a3984716d5d84ea1873 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java +@@ -80,6 +80,11 @@ public class EntitySquid extends EntityWaterAnimal { vector.setX(cos * x - sine * z); vector.setZ(sine * x + cos * z); } @@ -20,7 +20,7 @@ index 70b952f10a2af547f58069977ee135469d02f84d..cee226501690e1c00983a01ac82bc738 // Purpur end @Override -@@ -116,6 +121,7 @@ public class EntitySquid extends EntityWaterAnimal { +@@ -145,6 +150,7 @@ public class EntitySquid extends EntityWaterAnimal { } if (this.aH()) { @@ -28,7 +28,7 @@ index 70b952f10a2af547f58069977ee135469d02f84d..cee226501690e1c00983a01ac82bc738 if (this.bp < 3.1415927F) { float f = this.bp / 3.1415927F; -@@ -323,7 +329,7 @@ public class EntitySquid extends EntityWaterAnimal { +@@ -352,7 +358,7 @@ public class EntitySquid extends EntityWaterAnimal { if (i > 100) { this.b.a(0.0F, 0.0F, 0.0F); @@ -38,7 +38,7 @@ index 70b952f10a2af547f58069977ee135469d02f84d..cee226501690e1c00983a01ac82bc738 float f1 = MathHelper.cos(f) * 0.2F; float f2 = -0.1F + this.b.getRandom().nextFloat() * 0.2F; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 4515c95a195ab962513ddc6868f9cdfd47f61d68..39f25fe85d8d2c8cd48ba0f5988b1839d3d331aa 100644 +index 4843d4a0794e05386d6cdf05a7059598291aafe7..a9f3cec879329101794afa3561bcff63a6db22bf 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -879,10 +879,12 @@ public class PurpurWorldConfig { diff --git a/patches/server/0116-Infinity-bow-settings.patch b/patches/server/0116-Infinity-bow-settings.patch index e7a9d8a2f..f332d7987 100644 --- a/patches/server/0116-Infinity-bow-settings.patch +++ b/patches/server/0116-Infinity-bow-settings.patch @@ -4,11 +4,11 @@ Date: Sun, 4 Oct 2020 19:08:53 -0500 Subject: [PATCH] Infinity bow settings -diff --git a/src/main/java/net/minecraft/server/ItemBow.java b/src/main/java/net/minecraft/server/ItemBow.java -index dd6a93dc78a4589f2c65d1738c432def1285f3e2..8241f3dafa5852bed7a3967e7260b36f47198dba 100644 ---- a/src/main/java/net/minecraft/server/ItemBow.java -+++ b/src/main/java/net/minecraft/server/ItemBow.java -@@ -24,7 +24,7 @@ public class ItemBow extends ItemProjectileWeapon implements ItemVanishable { +diff --git a/src/main/java/net/minecraft/world/item/ItemBow.java b/src/main/java/net/minecraft/world/item/ItemBow.java +index 015f4d71f35a9d512814389b6e6cab74c0daf116..c7e20b25b4d09463fa54c66e62208e90515013e2 100644 +--- a/src/main/java/net/minecraft/world/item/ItemBow.java ++++ b/src/main/java/net/minecraft/world/item/ItemBow.java +@@ -35,7 +35,7 @@ public class ItemBow extends ItemProjectileWeapon implements ItemVanishable { float f = a(j); if ((double) f >= 0.1D) { @@ -17,7 +17,7 @@ index dd6a93dc78a4589f2c65d1738c432def1285f3e2..8241f3dafa5852bed7a3967e7260b36f if (!world.isClientSide) { ItemArrow itemarrow = (ItemArrow) ((ItemArrow) (itemstack1.getItem() instanceof ItemArrow ? itemstack1.getItem() : Items.ARROW)); -@@ -85,6 +85,7 @@ public class ItemBow extends ItemProjectileWeapon implements ItemVanishable { +@@ -96,6 +96,7 @@ public class ItemBow extends ItemProjectileWeapon implements ItemVanishable { entityhuman.inventory.f(itemstack1); } } @@ -26,7 +26,7 @@ index dd6a93dc78a4589f2c65d1738c432def1285f3e2..8241f3dafa5852bed7a3967e7260b36f entityhuman.b(StatisticList.ITEM_USED.b(this)); } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 39f25fe85d8d2c8cd48ba0f5988b1839d3d331aa..3d6e1eb623b66d9157ca33f64483e857e3b6b39e 100644 +index a9f3cec879329101794afa3561bcff63a6db22bf..bc4caba06f469f700c89e96f1e70c7b2948329ad 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -165,6 +165,15 @@ public class PurpurWorldConfig { diff --git a/patches/server/0117-Stonecutter-damage.patch b/patches/server/0117-Stonecutter-damage.patch index a5bdec3ed..6f3925169 100644 --- a/patches/server/0117-Stonecutter-damage.patch +++ b/patches/server/0117-Stonecutter-damage.patch @@ -4,11 +4,21 @@ Date: Mon, 5 Oct 2020 12:15:14 -0500 Subject: [PATCH] Stonecutter damage -diff --git a/src/main/java/net/minecraft/server/BlockStonecutter.java b/src/main/java/net/minecraft/server/BlockStonecutter.java -index 3e57abd33ee61d78f6d895ec710adb5e5983d42c..08ba9e1c4e916ee09df1bd397b8fc36b4780b9b5 100644 ---- a/src/main/java/net/minecraft/server/BlockStonecutter.java -+++ b/src/main/java/net/minecraft/server/BlockStonecutter.java -@@ -71,4 +71,16 @@ public class BlockStonecutter extends Block { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockStonecutter.java b/src/main/java/net/minecraft/world/level/block/BlockStonecutter.java +index 54c9586cd7f8c9691a1c7ded9c9c96b0f316b0b6..988204918854e982e334eb2417b83914b58cbcf6 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockStonecutter.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockStonecutter.java +@@ -10,6 +10,9 @@ import net.minecraft.world.EnumHand; + import net.minecraft.world.EnumInteractionResult; + import net.minecraft.world.ITileInventory; + import net.minecraft.world.TileInventory; ++import net.minecraft.world.damagesource.DamageSource; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EntityLiving; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.inventory.ContainerAccess; + import net.minecraft.world.inventory.ContainerStonecutter; +@@ -94,4 +97,16 @@ public class BlockStonecutter extends Block { public boolean a(IBlockData iblockdata, IBlockAccess iblockaccess, BlockPosition blockposition, PathMode pathmode) { return false; } @@ -25,11 +35,11 @@ index 3e57abd33ee61d78f6d895ec710adb5e5983d42c..08ba9e1c4e916ee09df1bd397b8fc36b + } + // Purpur end } -diff --git a/src/main/java/net/minecraft/server/PathfinderNormal.java b/src/main/java/net/minecraft/server/PathfinderNormal.java -index 33804e68931e8b4145b896eedeab79bde78779f2..fabadcd7a21b0e4ad0e2eeadcd8926dfad6c4b7a 100644 ---- a/src/main/java/net/minecraft/server/PathfinderNormal.java -+++ b/src/main/java/net/minecraft/server/PathfinderNormal.java -@@ -480,7 +480,7 @@ public class PathfinderNormal extends PathfinderAbstract { +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java +index 7b92a54cfb64fb77af99e6bf66eacbdb9e769dc1..9d08094165cf18d99116b5c721fff888f3cb42e2 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java +@@ -503,7 +503,7 @@ public class PathfinderNormal extends PathfinderAbstract { return iblockdata.neighbourOverridePathType = PathType.DANGER_CACTUS; // Tuinity - reduce pathfinder branching } @@ -39,7 +49,7 @@ index 33804e68931e8b4145b896eedeab79bde78779f2..fabadcd7a21b0e4ad0e2eeadcd8926df } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 3d6e1eb623b66d9157ca33f64483e857e3b6b39e..95d14d82d6f8bce762ef70645f0f8eae3093914c 100644 +index bc4caba06f469f700c89e96f1e70c7b2948329ad..fdd44288c3d962df02cb65a5de5ac75d3dd4c5b9 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -383,6 +383,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0118-Configurable-daylight-cycle.patch b/patches/server/0118-Configurable-daylight-cycle.patch index ee1ec7ef9..54a64c91d 100644 --- a/patches/server/0118-Configurable-daylight-cycle.patch +++ b/patches/server/0118-Configurable-daylight-cycle.patch @@ -4,11 +4,11 @@ Date: Sat, 10 Oct 2020 14:29:55 -0500 Subject: [PATCH] Configurable daylight cycle -diff --git a/src/main/java/net/minecraft/server/PacketPlayOutUpdateTime.java b/src/main/java/net/minecraft/server/PacketPlayOutUpdateTime.java -index 1b9b43ee696575d986c25cafec07d863acb951a7..e837db171545ceacbc84a2b360cf0d95347145d0 100644 ---- a/src/main/java/net/minecraft/server/PacketPlayOutUpdateTime.java -+++ b/src/main/java/net/minecraft/server/PacketPlayOutUpdateTime.java -@@ -5,7 +5,7 @@ import java.io.IOException; +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutUpdateTime.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutUpdateTime.java +index 3086ee023685781d94e2fb99fc8dff5264f01165..74c1047305cac5673e274096709c757ede4605f4 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutUpdateTime.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutUpdateTime.java +@@ -7,7 +7,7 @@ import net.minecraft.network.protocol.Packet; public class PacketPlayOutUpdateTime implements Packet { private long a; private final void setWorldAge(final long age) { this.a = age; } private final long getWorldAge() { return this.a; } // Paper - OBFHELPER @@ -17,11 +17,19 @@ index 1b9b43ee696575d986c25cafec07d863acb951a7..e837db171545ceacbc84a2b360cf0d95 public PacketPlayOutUpdateTime() {} -diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index f2bbc31540224424dc224bbfc86c61ccf2d0e629..8146e86aacfac80f06906c8d421899fcca2be50a 100644 ---- a/src/main/java/net/minecraft/server/WorldServer.java -+++ b/src/main/java/net/minecraft/server/WorldServer.java -@@ -94,6 +94,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index c74e82feb007764d77f8f9b7f910f7b113e3bf40..63b22bd2dc828f4b5be45f8162745b4cc214382b 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -64,6 +64,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutExplosion; + import net.minecraft.network.protocol.game.PacketPlayOutGameStateChange; + import net.minecraft.network.protocol.game.PacketPlayOutNamedSoundEffect; + import net.minecraft.network.protocol.game.PacketPlayOutSpawnPosition; ++import net.minecraft.network.protocol.game.PacketPlayOutUpdateTime; + import net.minecraft.network.protocol.game.PacketPlayOutWorldEvent; + import net.minecraft.network.protocol.game.PacketPlayOutWorldParticles; + import net.minecraft.resources.MinecraftKey; +@@ -213,6 +214,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { private final EnderDragonBattle dragonBattle; private final StructureManager structureManager; private final boolean Q; @@ -29,7 +37,7 @@ index f2bbc31540224424dc224bbfc86c61ccf2d0e629..8146e86aacfac80f06906c8d421899fc // CraftBukkit start -@@ -485,6 +486,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -604,6 +606,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { this.getServer().addWorld(this.getWorld()); // CraftBukkit this.asyncChunkTaskManager = new com.destroystokyo.paper.io.chunk.ChunkTaskManager(this); // Paper @@ -37,7 +45,7 @@ index f2bbc31540224424dc224bbfc86c61ccf2d0e629..8146e86aacfac80f06906c8d421899fc } // Tuinity start - optimise collision -@@ -1091,7 +1093,21 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -1210,7 +1213,21 @@ public class WorldServer extends World implements GeneratorAccessSeed { this.nextTickListBlock.nextTick(); // Paper this.nextTickListFluid.nextTick(); // Paper this.worldDataServer.u().a(this.server, i); @@ -60,7 +68,7 @@ index f2bbc31540224424dc224bbfc86c61ccf2d0e629..8146e86aacfac80f06906c8d421899fc this.setDayTime(this.worldData.getDayTime() + 1L); } -@@ -1100,6 +1116,12 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -1219,6 +1236,12 @@ public class WorldServer extends World implements GeneratorAccessSeed { public void setDayTime(long i) { this.worldDataServer.setDayTime(i); @@ -74,7 +82,7 @@ index f2bbc31540224424dc224bbfc86c61ccf2d0e629..8146e86aacfac80f06906c8d421899fc public void doMobSpawning(boolean flag, boolean flag1) { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 95d14d82d6f8bce762ef70645f0f8eae3093914c..0b58a2e99a2f89d450d7980eb4837172e8a10dba 100644 +index fdd44288c3d962df02cb65a5de5ac75d3dd4c5b9..ae1202142600a15566c4c3d77487ff65c1f06087 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -116,6 +116,13 @@ public class PurpurWorldConfig { diff --git a/patches/server/0119-Allow-infinite-and-mending-enchantments-together.patch b/patches/server/0119-Allow-infinite-and-mending-enchantments-together.patch index 30dc5086f..a451c2463 100644 --- a/patches/server/0119-Allow-infinite-and-mending-enchantments-together.patch +++ b/patches/server/0119-Allow-infinite-and-mending-enchantments-together.patch @@ -4,11 +4,11 @@ Date: Tue, 13 Oct 2020 20:04:33 -0500 Subject: [PATCH] Allow infinite and mending enchantments together -diff --git a/src/main/java/net/minecraft/server/EnchantmentInfiniteArrows.java b/src/main/java/net/minecraft/server/EnchantmentInfiniteArrows.java -index 408cfa460920f74e0394ab27101ecb12cceb9c43..3d4e34f7070a48c436284ba7744a94aeacbb7651 100644 ---- a/src/main/java/net/minecraft/server/EnchantmentInfiniteArrows.java -+++ b/src/main/java/net/minecraft/server/EnchantmentInfiniteArrows.java -@@ -23,6 +23,6 @@ public class EnchantmentInfiniteArrows extends Enchantment { +diff --git a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentInfiniteArrows.java b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentInfiniteArrows.java +index bf9d6d0e593951aa5abc9aef6cf4803430ea18e5..29bebbccf8dd6ff8976d1bfdb4c2ddcfc9de57dc 100644 +--- a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentInfiniteArrows.java ++++ b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentInfiniteArrows.java +@@ -25,6 +25,6 @@ public class EnchantmentInfiniteArrows extends Enchantment { @Override public boolean a(Enchantment enchantment) { @@ -17,10 +17,10 @@ index 408cfa460920f74e0394ab27101ecb12cceb9c43..3d4e34f7070a48c436284ba7744a94ae } } diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index a5febd7671ae1818edb18955d5e8176303c92c93..a20d7ac486a915fae2c6c7d42aa07d44f42438db 100644 +index c61595aa6e42a4cc096bda9126d23c465f8bd3de..44d3b46fc9fa9852187bacc71beeecaf53040c11 100644 --- a/src/main/java/net/pl3x/purpur/PurpurConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java -@@ -197,6 +197,16 @@ public class PurpurConfig { +@@ -198,6 +198,16 @@ public class PurpurConfig { cryingObsidianValidForPortalFrame = getBoolean("settings.blocks.crying_obsidian.valid-for-portal-frame", cryingObsidianValidForPortalFrame); } diff --git a/patches/server/0120-Infinite-fuel-furnace.patch b/patches/server/0120-Infinite-fuel-furnace.patch index b18d6d134..c088f8ecf 100644 --- a/patches/server/0120-Infinite-fuel-furnace.patch +++ b/patches/server/0120-Infinite-fuel-furnace.patch @@ -4,11 +4,27 @@ Date: Mon, 19 Oct 2020 15:14:01 -0500 Subject: [PATCH] Infinite fuel furnace -diff --git a/src/main/java/net/minecraft/server/TileEntityFurnace.java b/src/main/java/net/minecraft/server/TileEntityFurnace.java -index 935c7f111a7d7b9cc7c8e384d43e7ab6092cfc5f..48359a7e79b64026e38e7cd17505d8944106e089 100644 ---- a/src/main/java/net/minecraft/server/TileEntityFurnace.java -+++ b/src/main/java/net/minecraft/server/TileEntityFurnace.java -@@ -279,6 +279,22 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java +index 1997139fb87dc1947acfdf02e1f116577c3fa943..cd7bcedf8474dcb565b5b1157e167706c031a7f1 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java +@@ -12,6 +12,7 @@ import java.util.Map; + import javax.annotation.Nullable; + import net.minecraft.SharedConstants; + import net.minecraft.SystemUtils; ++import net.minecraft.core.BlockPosition; + import net.minecraft.core.EnumDirection; + import net.minecraft.core.NonNullList; + import net.minecraft.nbt.NBTTagCompound; +@@ -38,6 +39,7 @@ import net.minecraft.world.level.World; + import net.minecraft.world.level.block.BlockFurnace; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.phys.Vec3D; + + // CraftBukkit start +@@ -308,6 +310,22 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I if (!this.world.isClientSide) { ItemStack itemstack = (ItemStack) this.items.get(1); @@ -31,7 +47,7 @@ index 935c7f111a7d7b9cc7c8e384d43e7ab6092cfc5f..48359a7e79b64026e38e7cd17505d894 if (!this.isBurning() && (itemstack.isEmpty() || ((ItemStack) this.items.get(0)).isEmpty())) { if (!this.isBurning() && this.cookTime > 0) { this.cookTime = MathHelper.clamp(this.cookTime - 2, 0, this.cookTimeTotal); -@@ -332,6 +348,8 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I +@@ -361,6 +379,8 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I flag1 = true; this.world.setTypeAndData(this.position, (IBlockData) this.world.getType(this.position).set(BlockFurnace.LIT, this.isBurning()), 3); } @@ -41,7 +57,7 @@ index 935c7f111a7d7b9cc7c8e384d43e7ab6092cfc5f..48359a7e79b64026e38e7cd17505d894 if (flag1) { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 0b58a2e99a2f89d450d7980eb4837172e8a10dba..0cae636df21d73f88acc4dbbf7563cf8a44c5a58 100644 +index ae1202142600a15566c4c3d77487ff65c1f06087..c9a6261e988c85874d24ed78890e668637aaf6d6 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -351,6 +351,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0121-Arrows-should-not-reset-despawn-counter.patch b/patches/server/0121-Arrows-should-not-reset-despawn-counter.patch index e54675a87..7074af8b9 100644 --- a/patches/server/0121-Arrows-should-not-reset-despawn-counter.patch +++ b/patches/server/0121-Arrows-should-not-reset-despawn-counter.patch @@ -6,11 +6,11 @@ Subject: [PATCH] Arrows should not reset despawn counter This prevents keeping arrows alive indefinitely (such as when the block the arrow is stuck in gets removed, like a piston head going up/down) -diff --git a/src/main/java/net/minecraft/server/EntityArrow.java b/src/main/java/net/minecraft/server/EntityArrow.java -index ee24500e63830b34dd575feed4ef8ecb021d3501..1c2cf3ca08671872b5641ab0b3469f947c229e41 100644 ---- a/src/main/java/net/minecraft/server/EntityArrow.java -+++ b/src/main/java/net/minecraft/server/EntityArrow.java -@@ -245,7 +245,7 @@ public abstract class EntityArrow extends IProjectile { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java +index 3ee404effe339a5742926255da6a9c41d1bc9367..6f0a306449844dc50426202262219d0e952459cc 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java +@@ -283,7 +283,7 @@ public abstract class EntityArrow extends IProjectile { Vec3D vec3d = this.getMot(); this.setMot(vec3d.d((double) (this.random.nextFloat() * 0.2F), (double) (this.random.nextFloat() * 0.2F), (double) (this.random.nextFloat() * 0.2F))); diff --git a/patches/server/0122-Add-tablist-suffix-option-for-afk.patch b/patches/server/0122-Add-tablist-suffix-option-for-afk.patch index 6ec20715d..66282d790 100644 --- a/patches/server/0122-Add-tablist-suffix-option-for-afk.patch +++ b/patches/server/0122-Add-tablist-suffix-option-for-afk.patch @@ -4,11 +4,11 @@ Date: Thu, 12 Nov 2020 11:02:50 +0100 Subject: [PATCH] Add tablist suffix option for afk -diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index da4943389fee9b8a8d03ad5c518806d85cc639db..f4e0a0714fa17c370202f6ea02412dc7afb0af97 100644 ---- a/src/main/java/net/minecraft/server/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/EntityPlayer.java -@@ -1991,7 +1991,11 @@ public class EntityPlayer extends EntityHuman implements ICrafting { +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index e1a6e4a359eb2aa484d479fde398473c349a63ba..9ec4008f2195908130410d2c36fb5bf21b26b991 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -2122,7 +2122,11 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } if (world.purpurConfig.idleTimeoutUpdateTabList) { @@ -22,10 +22,10 @@ index da4943389fee9b8a8d03ad5c518806d85cc639db..f4e0a0714fa17c370202f6ea02412dc7 ((WorldServer) world).everyoneSleeping(); diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index a20d7ac486a915fae2c6c7d42aa07d44f42438db..767715963a79b06c8a0988b65bc589dc9c351138 100644 +index 44d3b46fc9fa9852187bacc71beeecaf53040c11..cc354e420befd531a8c1e778fd97e9b7c4c26f90 100644 --- a/src/main/java/net/pl3x/purpur/PurpurConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java -@@ -135,12 +135,14 @@ public class PurpurConfig { +@@ -136,12 +136,14 @@ public class PurpurConfig { public static String afkBroadcastAway = "§e§o%s is now AFK"; public static String afkBroadcastBack = "§e§o%s is no longer AFK"; public static String afkTabListPrefix = "[AFK] "; diff --git a/patches/server/0123-Ability-to-re-add-farmland-mechanics-from-Alpha.patch b/patches/server/0123-Ability-to-re-add-farmland-mechanics-from-Alpha.patch index b7361f011..377a4b731 100644 --- a/patches/server/0123-Ability-to-re-add-farmland-mechanics-from-Alpha.patch +++ b/patches/server/0123-Ability-to-re-add-farmland-mechanics-from-Alpha.patch @@ -4,11 +4,11 @@ Date: Sat, 14 Nov 2020 08:06:20 -0800 Subject: [PATCH] Ability to re-add farmland mechanics from Alpha -diff --git a/src/main/java/net/minecraft/server/BlockSoil.java b/src/main/java/net/minecraft/server/BlockSoil.java -index 8dd48669c29dd51ed4d535dad0b0319f4bb2250c..099e0d3df219408ebe2a741a02e53eb9f7def28e 100644 ---- a/src/main/java/net/minecraft/server/BlockSoil.java -+++ b/src/main/java/net/minecraft/server/BlockSoil.java -@@ -90,6 +90,14 @@ public class BlockSoil extends Block { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockSoil.java b/src/main/java/net/minecraft/world/level/block/BlockSoil.java +index 2bbaa2fb426869223a9b2f07406496c1b0daff3f..3e8893bf76b8ffda4c595c81086556ea929beaa4 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockSoil.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockSoil.java +@@ -113,6 +113,14 @@ public class BlockSoil extends Block { return; } @@ -24,7 +24,7 @@ index 8dd48669c29dd51ed4d535dad0b0319f4bb2250c..099e0d3df219408ebe2a741a02e53eb9 return; } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 0cae636df21d73f88acc4dbbf7563cf8a44c5a58..9f8d9b65b151149720ce2d69299ddd0bbe0045d1 100644 +index c9a6261e988c85874d24ed78890e668637aaf6d6..f774572a14c0d997aabeab902dca9764a5f1411e 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -347,8 +347,10 @@ public class PurpurWorldConfig { diff --git a/patches/server/0124-Add-adjustable-breeding-cooldown-to-config.patch b/patches/server/0124-Add-adjustable-breeding-cooldown-to-config.patch index 03fc2378d..434b3dd22 100644 --- a/patches/server/0124-Add-adjustable-breeding-cooldown-to-config.patch +++ b/patches/server/0124-Add-adjustable-breeding-cooldown-to-config.patch @@ -4,11 +4,11 @@ Date: Fri, 13 Nov 2020 17:52:40 +0100 Subject: [PATCH] Add adjustable breeding cooldown to config -diff --git a/src/main/java/net/minecraft/server/EntityAnimal.java b/src/main/java/net/minecraft/server/EntityAnimal.java -index b290218e506d5e4ddd1af17f91de19a588bbcfbd..cf9be4be18e913e49e9150358c66138b64319ed8 100644 ---- a/src/main/java/net/minecraft/server/EntityAnimal.java -+++ b/src/main/java/net/minecraft/server/EntityAnimal.java -@@ -121,7 +121,7 @@ public abstract class EntityAnimal extends EntityAgeable { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java b/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java +index 28dd42921961c6a47f2d85a5f93b8298f2c228d3..6ae5fafd379863bf23df3580d3dbc7a5ba63b545 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java +@@ -145,7 +145,7 @@ public abstract class EntityAnimal extends EntityAgeable { if (this.k(itemstack)) { int i = this.getAge(); @@ -17,7 +17,7 @@ index b290218e506d5e4ddd1af17f91de19a588bbcfbd..cf9be4be18e913e49e9150358c66138b this.a(entityhuman, itemstack); this.g(entityhuman); return EnumInteractionResult.SUCCESS; -@@ -213,6 +213,14 @@ public abstract class EntityAnimal extends EntityAgeable { +@@ -237,6 +237,14 @@ public abstract class EntityAnimal extends EntityAgeable { if (entityplayer == null && entityanimal.getBreedCause() != null) { entityplayer = entityanimal.getBreedCause(); } @@ -32,11 +32,19 @@ index b290218e506d5e4ddd1af17f91de19a588bbcfbd..cf9be4be18e913e49e9150358c66138b // CraftBukkit start - call EntityBreedEvent int experience = this.getRandom().nextInt(7) + 1; org.bukkit.event.entity.EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(entityageable, this, entityanimal, entityplayer, this.breedItem, experience); -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 42e06121f20b5366627b9612994187066c73328f..e13c5c97b91994c86161c86e5f03aca1545af676 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -104,6 +104,48 @@ public abstract class World implements GeneratorAccess, AutoCloseable { +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 06ecb1ec2b92f0978c57de6353f63a02e6e363da..266240b2fa9f22c5bff094fdb003a73a50ef1a81 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -41,6 +41,7 @@ import net.minecraft.world.DifficultyDamageScaler; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityTypes; ++import net.minecraft.world.entity.animal.EntityAnimal; + import net.minecraft.world.entity.decoration.EntityArmorStand; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.ItemStack; +@@ -166,6 +167,48 @@ public abstract class World implements GeneratorAccess, AutoCloseable { private int tileTickPosition; public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here @@ -51,11 +59,11 @@ index 42e06121f20b5366627b9612994187066c73328f..e13c5c97b91994c86161c86e5f03aca1 + this.playerBreedingCooldowns = this.getNewBreedingCooldownCache(); + } + -+ boolean hasBreedingCooldown(java.util.UUID player, Class animalType) { ++ public boolean hasBreedingCooldown(java.util.UUID player, Class animalType) { // Purpur + return this.playerBreedingCooldowns.getIfPresent(new BreedingCooldownPair(player, animalType)) != null; + } + -+ void addBreedingCooldown(java.util.UUID player, Class animalType) { ++ public void addBreedingCooldown(java.util.UUID player, Class animalType) { + this.playerBreedingCooldowns.put(new BreedingCooldownPair(player, animalType), new Object()); + } + @@ -85,16 +93,16 @@ index 42e06121f20b5366627b9612994187066c73328f..e13c5c97b91994c86161c86e5f03aca1 public CraftWorld getWorld() { return this.world; -@@ -188,6 +230,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper - this.tuinityConfig = new com.tuinity.tuinity.config.TuinityConfig.WorldConfig(((WorldDataServer)worlddatamutable).getName()); // Tuinity - Server Config - this.purpurConfig = new net.pl3x.purpur.PurpurWorldConfig(((WorldDataServer) worlddatamutable).getName(), env); // Purpur -+ this.playerBreedingCooldowns = this.getNewBreedingCooldownCache(); // Purpur +@@ -251,6 +294,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { this.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this, executor) : ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray + this.tuinityConfig = new com.tuinity.tuinity.config.TuinityConfig.WorldConfig(((net.minecraft.world.level.storage.WorldDataServer)worlddatamutable).getName()); // Tuinity - Server Config + this.purpurConfig = new net.pl3x.purpur.PurpurWorldConfig((((net.minecraft.world.level.storage.WorldDataServer)worlddatamutable).getName()), env); // Purpur ++ this.playerBreedingCooldowns = this.getNewBreedingCooldownCache(); // Purpur this.generator = gen; this.world = new CraftWorld((WorldServer) this, gen, env); + this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 9f8d9b65b151149720ce2d69299ddd0bbe0045d1..84b2b8618162f81369dac9e8341374447d9b1737 100644 +index f774572a14c0d997aabeab902dca9764a5f1411e..23b4593ff14b7a74839f199b1b1056214a6943a0 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -220,6 +220,7 @@ public class PurpurWorldConfig { @@ -114,7 +122,7 @@ index 9f8d9b65b151149720ce2d69299ddd0bbe0045d1..84b2b8618162f81369dac9e834137444 public boolean catSpawning; diff --git a/src/main/java/net/pl3x/purpur/command/PurpurCommand.java b/src/main/java/net/pl3x/purpur/command/PurpurCommand.java -index 4904be939c7a4b1d1583fd7b6232c930b79caba6..860d07cd686e0a6e3eebf2deaf6bcecc1fb9dfd2 100644 +index 536955124afaec5c8a070249c7432cb99bf43d67..0c35b1dd5147cf86c7ee743b98528e8f4bc0b5e9 100644 --- a/src/main/java/net/pl3x/purpur/command/PurpurCommand.java +++ b/src/main/java/net/pl3x/purpur/command/PurpurCommand.java @@ -49,6 +49,7 @@ public class PurpurCommand extends Command { diff --git a/patches/server/0125-Make-entity-breeding-times-configurable.patch b/patches/server/0125-Make-entity-breeding-times-configurable.patch index c15efc643..ef55ae9f1 100644 --- a/patches/server/0125-Make-entity-breeding-times-configurable.patch +++ b/patches/server/0125-Make-entity-breeding-times-configurable.patch @@ -4,11 +4,11 @@ Date: Sun, 15 Nov 2020 02:18:15 -0800 Subject: [PATCH] Make entity breeding times configurable -diff --git a/src/main/java/net/minecraft/server/BehaviorMakeLove.java b/src/main/java/net/minecraft/server/BehaviorMakeLove.java -index 7bdcc7bb26a1f7c8fc2562016af8598b9a7b4de3..d22b1742e2bf9c390590851de45b2e66f1444b47 100644 ---- a/src/main/java/net/minecraft/server/BehaviorMakeLove.java -+++ b/src/main/java/net/minecraft/server/BehaviorMakeLove.java -@@ -102,8 +102,10 @@ public class BehaviorMakeLove extends Behavior { +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorMakeLove.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorMakeLove.java +index a68428554b93f4aba9f0cb0b3af03985896830b7..c1e8b9562eb37cee3d47034b93d4ef0c998eb52f 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorMakeLove.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorMakeLove.java +@@ -115,8 +115,10 @@ public class BehaviorMakeLove extends Behavior { if (entityvillager2 == null) { return Optional.empty(); } else { @@ -21,19 +21,19 @@ index 7bdcc7bb26a1f7c8fc2562016af8598b9a7b4de3..d22b1742e2bf9c390590851de45b2e66 entityvillager2.setAgeRaw(-24000); entityvillager2.setPositionRotation(entityvillager.locX(), entityvillager.locY(), entityvillager.locZ(), 0.0F, 0.0F); worldserver.addAllEntities(entityvillager2, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - added SpawnReason -diff --git a/src/main/java/net/minecraft/server/EntityAnimal.java b/src/main/java/net/minecraft/server/EntityAnimal.java -index cf9be4be18e913e49e9150358c66138b64319ed8..c1d2b12418464203c1da8af8da61a9cc9305bb65 100644 ---- a/src/main/java/net/minecraft/server/EntityAnimal.java -+++ b/src/main/java/net/minecraft/server/EntityAnimal.java -@@ -14,6 +14,7 @@ public abstract class EntityAnimal extends EntityAgeable { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java b/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java +index 6ae5fafd379863bf23df3580d3dbc7a5ba63b545..38a4072a5df3abd3d1d9929f6402b3edfdd6c197 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java +@@ -38,6 +38,7 @@ public abstract class EntityAnimal extends EntityAgeable { public int loveTicks; public UUID breedCause; public ItemStack breedItem; // CraftBukkit - Add breedItem variable -+ abstract int getPurpurBreedTime(); // Purpur ++ public abstract int getPurpurBreedTime(); // Purpur protected EntityAnimal(EntityTypes entitytypes, World world) { super(entitytypes, world); -@@ -235,8 +236,10 @@ public abstract class EntityAnimal extends EntityAgeable { +@@ -259,8 +260,10 @@ public abstract class EntityAnimal extends EntityAgeable { CriterionTriggers.o.a(entityplayer, this, entityanimal, entityageable); } @@ -46,87 +46,87 @@ index cf9be4be18e913e49e9150358c66138b64319ed8..c1d2b12418464203c1da8af8da61a9cc this.resetLove(); entityanimal.resetLove(); entityageable.setBaby(true); -diff --git a/src/main/java/net/minecraft/server/EntityBee.java b/src/main/java/net/minecraft/server/EntityBee.java -index d8354ec4d19fc3fbddc2551ee217acb137482e63..ded4e10f5082fb5aa25368d9035affba287c3345 100644 ---- a/src/main/java/net/minecraft/server/EntityBee.java -+++ b/src/main/java/net/minecraft/server/EntityBee.java -@@ -100,6 +100,11 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java +index 0c6d3dae70eeea844a31f9edf54410db13e0b04b..9e40fd6585592ccd1deff1d8319c57660474c053 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java +@@ -176,6 +176,11 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB setMot(mot.a(0.9D)); } } + + @Override -+ int getPurpurBreedTime() { ++ public int getPurpurBreedTime() { + return this.world.purpurConfig.beeBreedingTicks; + } // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityCat.java b/src/main/java/net/minecraft/server/EntityCat.java -index 0e6552d77adb95c94cb06b6f9289c4c12e6955bb..437a7b8ffb40c461f1778d91591fa6c4dcf36834 100644 ---- a/src/main/java/net/minecraft/server/EntityCat.java -+++ b/src/main/java/net/minecraft/server/EntityCat.java -@@ -58,6 +58,11 @@ public class EntityCat extends EntityTameableAnimal { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCat.java b/src/main/java/net/minecraft/world/entity/animal/EntityCat.java +index 3efb010d0e045d14051a33bd7465669e415c26bd..079b95ef465f7155f426a2c87a4a50f8369d0a18 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityCat.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityCat.java +@@ -122,6 +122,11 @@ public class EntityCat extends EntityTameableAnimal { setSleepingWithOwner(false); setHeadDown(false); } + + @Override -+ int getPurpurBreedTime() { ++ public int getPurpurBreedTime() { + return this.world.purpurConfig.catBreedingTicks; + } // Purpur end public MinecraftKey eU() { -diff --git a/src/main/java/net/minecraft/server/EntityChicken.java b/src/main/java/net/minecraft/server/EntityChicken.java -index ee59a9f272a9caebec8f2329e1e4b22ddd27a0f9..2e1dc047459889aea85a79eaa04e8fe1a80e5b9e 100644 ---- a/src/main/java/net/minecraft/server/EntityChicken.java -+++ b/src/main/java/net/minecraft/server/EntityChicken.java -@@ -34,6 +34,11 @@ public class EntityChicken extends EntityAnimal { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java b/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java +index 5c744f1eac19e144c39a2c146d312f0547d6e589..ab54e809f735cea7d84366d2bc205351f8992bef 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java +@@ -71,6 +71,11 @@ public class EntityChicken extends EntityAnimal { this.getAttributeInstance(GenericAttributes.ATTACK_DAMAGE).setValue(2.0D); } } + + @Override -+ int getPurpurBreedTime() { ++ public int getPurpurBreedTime() { + return this.world.purpurConfig.chickenBreedingTicks; + } // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityCow.java b/src/main/java/net/minecraft/server/EntityCow.java -index 1219b0aa9c62bc9a1bda45cc9e9a27f14a28fe2e..63497ca0266073dc0a16b7dc22641d08c3eaf400 100644 ---- a/src/main/java/net/minecraft/server/EntityCow.java -+++ b/src/main/java/net/minecraft/server/EntityCow.java -@@ -21,6 +21,11 @@ public class EntityCow extends EntityAnimal { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCow.java b/src/main/java/net/minecraft/world/entity/animal/EntityCow.java +index cad256514c7df92847522c8d7ddf45ebe02658c4..93589a2b86e6663d93f6b536b853996c08db549a 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityCow.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityCow.java +@@ -54,6 +54,11 @@ public class EntityCow extends EntityAnimal { public boolean isRidableInWater() { return world.purpurConfig.cowRidableInWater; } + + @Override -+ int getPurpurBreedTime() { ++ public int getPurpurBreedTime() { + return this.world.purpurConfig.cowBreedingTicks; + } // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityFox.java b/src/main/java/net/minecraft/server/EntityFox.java -index f5defe4713c6be7d32fb2116110516717460284e..b5f036af81ddd3c1b0e388a28383f0b6a63d128c 100644 ---- a/src/main/java/net/minecraft/server/EntityFox.java -+++ b/src/main/java/net/minecraft/server/EntityFox.java -@@ -86,6 +86,11 @@ public class EntityFox extends EntityAnimal { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java +index 0c1151b598aa681e63ddaac29e4a589f917fd03b..7bf546a1b2a80179962ed08a35d86f0a28eda3c2 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java +@@ -159,6 +159,11 @@ public class EntityFox extends EntityAnimal { super.onDismount(entityhuman); setCanPickupLoot(true); } + + @Override -+ int getPurpurBreedTime() { ++ public int getPurpurBreedTime() { + return this.world.purpurConfig.foxBreedingTicks; + } // Purpur end @Override -@@ -1300,8 +1305,10 @@ public class EntityFox extends EntityAnimal { +@@ -1373,8 +1378,10 @@ public class EntityFox extends EntityAnimal { CriterionTriggers.o.a(entityplayer2, this.animal, this.partner, (EntityAgeable) entityfox); } @@ -139,296 +139,296 @@ index f5defe4713c6be7d32fb2116110516717460284e..b5f036af81ddd3c1b0e388a28383f0b6 this.animal.resetLove(); this.partner.resetLove(); entityfox.setAgeRaw(-24000); -diff --git a/src/main/java/net/minecraft/server/EntityHoglin.java b/src/main/java/net/minecraft/server/EntityHoglin.java -index f98ac9edf3ba3f3bee2e626a76a5e0e4013514ad..96cad9471d316e26b5daa9d217e172efcc77e0cc 100644 ---- a/src/main/java/net/minecraft/server/EntityHoglin.java -+++ b/src/main/java/net/minecraft/server/EntityHoglin.java -@@ -30,6 +30,11 @@ public class EntityHoglin extends EntityAnimal implements IMonster, IOglin { - public boolean isRidableInWater() { - return world.purpurConfig.hoglinRidableInWater; - } -+ -+ @Override -+ int getPurpurBreedTime() { -+ return this.world.purpurConfig.hoglinBreedingTicks; -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityHorse.java b/src/main/java/net/minecraft/server/EntityHorse.java -index 4ffc61acdff8c51dc9b111e3024c828fb5386118..669bce5d9806c80bddc247fe103ff20dc6aaa8a5 100644 ---- a/src/main/java/net/minecraft/server/EntityHorse.java -+++ b/src/main/java/net/minecraft/server/EntityHorse.java -@@ -17,6 +17,11 @@ public class EntityHorse extends EntityHorseAbstract { - public boolean isRidableInWater() { - return world.purpurConfig.horseRidableInWater; - } -+ -+ @Override -+ int getPurpurBreedTime() { -+ return this.world.purpurConfig.horseBreedingTicks; -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityHorseDonkey.java b/src/main/java/net/minecraft/server/EntityHorseDonkey.java -index cb8aee5691ff4ecaa6ae60f1637b1852d3b6c162..f6421bb45c5e6adf39fdc085efe2b2f500b76c0c 100644 ---- a/src/main/java/net/minecraft/server/EntityHorseDonkey.java -+++ b/src/main/java/net/minecraft/server/EntityHorseDonkey.java -@@ -13,6 +13,11 @@ public class EntityHorseDonkey extends EntityHorseChestedAbstract { - public boolean isRidableInWater() { - return world.purpurConfig.donkeyRidableInWater; - } -+ -+ @Override -+ int getPurpurBreedTime() { -+ return this.world.purpurConfig.donkeyBreedingTicks; -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityHorseMule.java b/src/main/java/net/minecraft/server/EntityHorseMule.java -index 243aeb736e350418e9476819bbfec0e7ab59f92f..30cbc505d2b0f4d3247edfd271de8daab023eb2a 100644 ---- a/src/main/java/net/minecraft/server/EntityHorseMule.java -+++ b/src/main/java/net/minecraft/server/EntityHorseMule.java -@@ -13,6 +13,11 @@ public class EntityHorseMule extends EntityHorseChestedAbstract { - public boolean isRidableInWater() { - return world.purpurConfig.muleRidableInWater; - } -+ -+ @Override -+ int getPurpurBreedTime() { -+ return this.world.purpurConfig.muleBreedingTicks; -+ } - // Purpur end - @Override - protected SoundEffect getSoundAmbient() { -diff --git a/src/main/java/net/minecraft/server/EntityHorseSkeleton.java b/src/main/java/net/minecraft/server/EntityHorseSkeleton.java -index e2c6a5807a4554a7eebb148e40f1f8a1d979df5e..408db52cacbdfbca8af0a6a8e913b0128a3f5a76 100644 ---- a/src/main/java/net/minecraft/server/EntityHorseSkeleton.java -+++ b/src/main/java/net/minecraft/server/EntityHorseSkeleton.java -@@ -22,6 +22,11 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { - public boolean isTamed() { - return true; - } -+ -+ @Override -+ int getPurpurBreedTime() { -+ return 6000; -+ } - // Purpur end - - public static AttributeProvider.Builder eL() { -diff --git a/src/main/java/net/minecraft/server/EntityHorseZombie.java b/src/main/java/net/minecraft/server/EntityHorseZombie.java -index 559ba50977147b8e2a0e7c1e7dc281faabd7f292..2121a6c979ba2ea7cb596ca6081750d2f8c7df9f 100644 ---- a/src/main/java/net/minecraft/server/EntityHorseZombie.java -+++ b/src/main/java/net/minecraft/server/EntityHorseZombie.java -@@ -18,6 +18,11 @@ public class EntityHorseZombie extends EntityHorseAbstract { - public boolean isTamed() { - return true; - } -+ -+ @Override -+ int getPurpurBreedTime() { -+ return 6000; -+ } - // Purpur end - - public static AttributeProvider.Builder eL() { -diff --git a/src/main/java/net/minecraft/server/EntityLlama.java b/src/main/java/net/minecraft/server/EntityLlama.java -index 1099277868f92fdaf4b0ec3a982f26f20ead7369..3bc6e6df9e0107debe5b15f5f7aad97ad336f304 100644 ---- a/src/main/java/net/minecraft/server/EntityLlama.java -+++ b/src/main/java/net/minecraft/server/EntityLlama.java -@@ -57,6 +57,11 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn - public boolean hasSaddle() { - return super.hasSaddle() || (isTamed() && getColor() != null); - } -+ -+ @Override -+ int getPurpurBreedTime() { -+ return this.world.purpurConfig.llamaBreedingTicks; -+ } - // Purpur end - - public void setStrength(int i) { -diff --git a/src/main/java/net/minecraft/server/EntityMushroomCow.java b/src/main/java/net/minecraft/server/EntityMushroomCow.java -index e38d165fefb4d552ded2198536a6663a5688070d..46d031ef3cebfe30e07840ef1c9d60a97a24cd1b 100644 ---- a/src/main/java/net/minecraft/server/EntityMushroomCow.java -+++ b/src/main/java/net/minecraft/server/EntityMushroomCow.java -@@ -31,6 +31,11 @@ public class EntityMushroomCow extends EntityCow implements IShearable { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java b/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java +index 815e907e8db721f2a6f0f831b69c44a9573b5c9b..ab4a8ee6e1912f230cbf3353eb42c3bc8a9db58e 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java +@@ -67,6 +67,11 @@ public class EntityMushroomCow extends EntityCow implements IShearable { public boolean isRidableInWater() { return world.purpurConfig.mooshroomRidableInWater; } + + @Override -+ int getPurpurBreedTime() { ++ public int getPurpurBreedTime() { + return this.world.purpurConfig.mooshroomBreedingTicks; + } // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityOcelot.java b/src/main/java/net/minecraft/server/EntityOcelot.java -index 2f8275cd6b3cde0d3f949219f67ba7f0e0031dc3..a5be10dfb0de08b0d97265278b1f11ad1e94b821 100644 ---- a/src/main/java/net/minecraft/server/EntityOcelot.java -+++ b/src/main/java/net/minecraft/server/EntityOcelot.java -@@ -26,6 +26,11 @@ public class EntityOcelot extends EntityAnimal { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java b/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java +index d7938ff0dca305f1d47fdfdbc57648892debe367..cff2ff5a8beef739f0515832e072e7e390ac388f 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java +@@ -74,6 +74,11 @@ public class EntityOcelot extends EntityAnimal { public boolean isRidableInWater() { return world.purpurConfig.ocelotRidableInWater; } + + @Override -+ int getPurpurBreedTime() { ++ public int getPurpurBreedTime() { + return this.world.purpurConfig.ocelotBreedingTicks; + } // Purpur end private boolean isTrusting() { -diff --git a/src/main/java/net/minecraft/server/EntityPanda.java b/src/main/java/net/minecraft/server/EntityPanda.java -index eafae5516b9b5d51aa943796557926cf61476d2b..c70180fddb829419b9cc5188766e9130f9b8a94a 100644 ---- a/src/main/java/net/minecraft/server/EntityPanda.java -+++ b/src/main/java/net/minecraft/server/EntityPanda.java -@@ -65,6 +65,11 @@ public class EntityPanda extends EntityAnimal { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java b/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java +index 0d912399e1975d9c0d5525f5b89049f40e7efcc0..e6952c0a8d90eb4b133c517d97299f2c3db7e329 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java +@@ -121,6 +121,11 @@ public class EntityPanda extends EntityAnimal { this.setEating(false); this.setLayingOnBack(false); } + + @Override -+ int getPurpurBreedTime() { ++ public int getPurpurBreedTime() { + return this.world.purpurConfig.pandaBreedingTicks; + } // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityParrot.java b/src/main/java/net/minecraft/server/EntityParrot.java -index e402d4a77b57b8b12b7575a9793c30d7acfa7fb0..398e92bf7053c411bd98626efe4261e15256d3ee 100644 ---- a/src/main/java/net/minecraft/server/EntityParrot.java -+++ b/src/main/java/net/minecraft/server/EntityParrot.java -@@ -115,6 +115,11 @@ public class EntityParrot extends EntityPerchable implements EntityBird { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java +index 5c26eea7e3e93dc7bcd8b86519e84db58b70cecb..5463e1779422ff19499727a000fdfbbfc38809a8 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java +@@ -171,6 +171,11 @@ public class EntityParrot extends EntityPerchable implements EntityBird { setMot(mot.a(0.9D)); } } + + @Override -+ int getPurpurBreedTime() { ++ public int getPurpurBreedTime() { + return 6000; + } // Purpur end @Nullable -diff --git a/src/main/java/net/minecraft/server/EntityPig.java b/src/main/java/net/minecraft/server/EntityPig.java -index bf7ecd7a7d805cc8f1314a348d7b13f848da46b5..eae841eeac75a35a9dc5a53c57538ac5264ece68 100644 ---- a/src/main/java/net/minecraft/server/EntityPig.java -+++ b/src/main/java/net/minecraft/server/EntityPig.java -@@ -29,6 +29,11 @@ public class EntityPig extends EntityAnimal implements ISteerable, ISaddleable { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java +index cef69f99d7bc9b6605b9654c50f43a1ebc1a8509..5aa8806063186bec36b38adc51e2ea82bf6ff21a 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java +@@ -77,6 +77,11 @@ public class EntityPig extends EntityAnimal implements ISteerable, ISaddleable { public boolean isRidableInWater() { return world.purpurConfig.pigRidableInWater; } + + @Override -+ int getPurpurBreedTime() { ++ public int getPurpurBreedTime() { + return this.world.purpurConfig.pigBreedingTicks; + } // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityPolarBear.java b/src/main/java/net/minecraft/server/EntityPolarBear.java -index 3d649843f565d2c8820b525c199bd2b9f9120cc7..40395dd7ea515e51a189d014a3274d15dc1d8ee6 100644 ---- a/src/main/java/net/minecraft/server/EntityPolarBear.java -+++ b/src/main/java/net/minecraft/server/EntityPolarBear.java -@@ -67,6 +67,11 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java b/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java +index e686491a469573a3fc466c46be1b7430ff02ba53..2306abb72ea76a52fd6f27648c4815ad99f8f005 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java +@@ -116,6 +116,11 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { return this.isInLove() && polarbear.isInLove(); } } + + @Override -+ int getPurpurBreedTime() { ++ public int getPurpurBreedTime() { + return this.world.purpurConfig.polarBearBreedingTicks; + } // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityRabbit.java b/src/main/java/net/minecraft/server/EntityRabbit.java -index b766a27e98e19bffd3fe8f81f750750ae7681d02..654cd036a8e4aa4499f10f528b684e003c469c9a 100644 ---- a/src/main/java/net/minecraft/server/EntityRabbit.java -+++ b/src/main/java/net/minecraft/server/EntityRabbit.java -@@ -30,6 +30,11 @@ public class EntityRabbit extends EntityAnimal { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java b/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java +index fff6bcff9d44c7d49cd2d0c334ea702531c74ea1..0b706404895b69fbca79502a327ec20b47ed99f0 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java +@@ -86,6 +86,11 @@ public class EntityRabbit extends EntityAnimal { public boolean isRidableInWater() { return world.purpurConfig.rabbitRidableInWater; } + + @Override -+ int getPurpurBreedTime() { ++ public int getPurpurBreedTime() { + return this.world.purpurConfig.rabbitBreedingTicks; + } // Purpur end // CraftBukkit start - code from constructor -diff --git a/src/main/java/net/minecraft/server/EntitySheep.java b/src/main/java/net/minecraft/server/EntitySheep.java -index a151d4295c02930687a23212647de60cce5405ca..32130c0681501e3e5a47b199f0bb39daac416ed3 100644 ---- a/src/main/java/net/minecraft/server/EntitySheep.java -+++ b/src/main/java/net/minecraft/server/EntitySheep.java -@@ -66,6 +66,11 @@ public class EntitySheep extends EntityAnimal implements IShearable { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java b/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java +index 8f3296031f220dd7bb3ae9fe2443e479954ebad3..ff6fc821085e4430a3b1008140b0b7fcacc59d2e 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java +@@ -121,6 +121,11 @@ public class EntitySheep extends EntityAnimal implements IShearable { public boolean isRidableInWater() { return world.purpurConfig.sheepRidableInWater; } + + @Override -+ int getPurpurBreedTime() { ++ public int getPurpurBreedTime() { + return this.world.purpurConfig.sheepBreedingTicks; + } // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityStrider.java b/src/main/java/net/minecraft/server/EntityStrider.java -index 56b72132595db5bc9addf31aecde5c13c5fd44c2..5c960365901b6ebd74134dac2e90c6aa81d33351 100644 ---- a/src/main/java/net/minecraft/server/EntityStrider.java -+++ b/src/main/java/net/minecraft/server/EntityStrider.java -@@ -38,6 +38,11 @@ public class EntityStrider extends EntityAnimal implements ISteerable, ISaddleab - public boolean isRidableInWater() { - return world.purpurConfig.striderRidableInWater; - } -+ -+ @Override -+ int getPurpurBreedTime() { -+ return this.world.purpurConfig.striderBreedingTicks; -+ } - // Purpur end - - public static boolean c(EntityTypes entitytypes, GeneratorAccess generatoraccess, EnumMobSpawn enummobspawn, BlockPosition blockposition, Random random) { -diff --git a/src/main/java/net/minecraft/server/EntityTurtle.java b/src/main/java/net/minecraft/server/EntityTurtle.java -index 2b34e6cf3b86319bd2875d92b63902889fec32a8..067f7f28b02b388d56b93b1ed8274799757196e6 100644 ---- a/src/main/java/net/minecraft/server/EntityTurtle.java -+++ b/src/main/java/net/minecraft/server/EntityTurtle.java -@@ -37,6 +37,11 @@ public class EntityTurtle extends EntityAnimal { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java +index 28d6e673f55fc8fae40dff4a96ac2c2b5eeab9d6..a16f586934f24e599d00bf793f06d3f9134ed29d 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java +@@ -101,6 +101,11 @@ public class EntityTurtle extends EntityAnimal { public boolean isRidableInWater() { return world.purpurConfig.turtleRidableInWater; } + + @Override -+ int getPurpurBreedTime() { ++ public int getPurpurBreedTime() { + return this.world.purpurConfig.turtleBreedingTicks; + } // Purpur end public void setHomePos(BlockPosition blockposition) { -diff --git a/src/main/java/net/minecraft/server/EntityWolf.java b/src/main/java/net/minecraft/server/EntityWolf.java -index 9ae7168595dd66860e09ef87f946b18b010e54b1..6c25f667eecdf345289a0dbf885c9d71c6a26958 100644 ---- a/src/main/java/net/minecraft/server/EntityWolf.java -+++ b/src/main/java/net/minecraft/server/EntityWolf.java -@@ -48,6 +48,11 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java b/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java +index 3fbd8f9122d7a5ac23af4d872f877030644ef86a..dd3c7ad7701ad18ccaf86d73fde7051090ed3d57 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java +@@ -107,6 +107,11 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable super.onMount(entityhuman); setSitting(false); } + + @Override -+ int getPurpurBreedTime() { ++ public int getPurpurBreedTime() { + return this.world.purpurConfig.wolfBreedingTicks; + } // Purpur end + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java +index 650f13b1133e4c61f71b36f3f91a9d2913996435..c830bf6e5e38f5ebacc07673c3d67e4157c8c2b5 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java +@@ -46,6 +46,11 @@ public class EntityHorse extends EntityHorseAbstract { + public boolean isRidableInWater() { + return world.purpurConfig.horseRidableInWater; + } ++ ++ @Override ++ public int getPurpurBreedTime() { ++ return this.world.purpurConfig.horseBreedingTicks; ++ } + // Purpur end + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java +index 50700bf85a296b87fe3155651f869e2bbdb0875d..3b44394dcba8e9905aca46e6e585ee6d7a87de44 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java +@@ -21,6 +21,11 @@ public class EntityHorseDonkey extends EntityHorseChestedAbstract { + public boolean isRidableInWater() { + return world.purpurConfig.donkeyRidableInWater; + } ++ ++ @Override ++ public int getPurpurBreedTime() { ++ return this.world.purpurConfig.donkeyBreedingTicks; ++ } + // Purpur end + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java +index b6385a23050296611dbc8864b92d2cdd8321a1d0..0536112357e0321dbb902331467b847894a4c11b 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java +@@ -20,6 +20,11 @@ public class EntityHorseMule extends EntityHorseChestedAbstract { + public boolean isRidableInWater() { + return world.purpurConfig.muleRidableInWater; + } ++ ++ @Override ++ public int getPurpurBreedTime() { ++ return this.world.purpurConfig.muleBreedingTicks; ++ } + // Purpur end + @Override + protected SoundEffect getSoundAmbient() { +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java +index d21399fbb6ddc4f26a7509ce547f8c4ad6458089..28c6e3745c61d0670bf7f3a324169472250e25f4 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java +@@ -43,6 +43,11 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { + public boolean isTamed() { + return true; + } ++ ++ @Override ++ public int getPurpurBreedTime() { ++ return 6000; ++ } + // Purpur end + + public static AttributeProvider.Builder eL() { +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java +index d57e7c02268e5d8a00b0b5897fa03dcee10cd2e0..c776f18722d1aa73f53da66ef6b37564eeaddd2a 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java +@@ -35,6 +35,11 @@ public class EntityHorseZombie extends EntityHorseAbstract { + public boolean isTamed() { + return true; + } ++ ++ @Override ++ public int getPurpurBreedTime() { ++ return 6000; ++ } + // Purpur end + + public static AttributeProvider.Builder eL() { +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java +index d1bd7b9a6a8cfb6b609db4229b2f42a40b8b484f..b3d51abc9bad9cad6fdc5dbdc2bf09d43a565f98 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java +@@ -108,6 +108,11 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn + public boolean hasSaddle() { + return super.hasSaddle() || (isTamed() && getColor() != null); + } ++ ++ @Override ++ public int getPurpurBreedTime() { ++ return this.world.purpurConfig.llamaBreedingTicks; ++ } + // Purpur end + + public void setStrength(int i) { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java b/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java +index 14dda6743ed9e6f4880bc560f7ba8892d8e84afe..cba66a08feceeeaf7c123da595fc7b12c5749783 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java +@@ -105,6 +105,11 @@ public class EntityStrider extends EntityAnimal implements ISteerable, ISaddleab + public boolean isRidableInWater() { + return world.purpurConfig.striderRidableInWater; + } ++ ++ @Override ++ public int getPurpurBreedTime() { ++ return this.world.purpurConfig.striderBreedingTicks; ++ } + // Purpur end + + public static boolean c(EntityTypes entitytypes, GeneratorAccess generatoraccess, EnumMobSpawn enummobspawn, BlockPosition blockposition, Random random) { +diff --git a/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java b/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java +index 64253428ef66145d07f74f8d0e5bdeb5aa5fe02b..828d01abe8202a246ce07c1c652a17cbc829d904 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java ++++ b/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java +@@ -71,6 +71,11 @@ public class EntityHoglin extends EntityAnimal implements IMonster, IOglin { + public boolean isRidableInWater() { + return world.purpurConfig.hoglinRidableInWater; + } ++ ++ @Override ++ public int getPurpurBreedTime() { ++ return this.world.purpurConfig.hoglinBreedingTicks; ++ } + // Purpur end + @Override diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 84b2b8618162f81369dac9e8341374447d9b1737..abc9b4fc27fdef37e3444cc3d885acab9f4d3f23 100644 +index 23b4593ff14b7a74839f199b1b1056214a6943a0..2d4dea3c432fcf52dffd126f8bd910be03c20b1c 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -434,10 +434,12 @@ public class PurpurWorldConfig { diff --git a/patches/server/0126-Apply-display-names-from-item-forms-of-entities-to-e.patch b/patches/server/0126-Apply-display-names-from-item-forms-of-entities-to-e.patch index e23a64a77..9afc31054 100644 --- a/patches/server/0126-Apply-display-names-from-item-forms-of-entities-to-e.patch +++ b/patches/server/0126-Apply-display-names-from-item-forms-of-entities-to-e.patch @@ -5,11 +5,11 @@ Subject: [PATCH] Apply display names from item forms of entities to entities and vice versa -diff --git a/src/main/java/net/minecraft/server/EntityArmorStand.java b/src/main/java/net/minecraft/server/EntityArmorStand.java -index 9e37bf25689691f9640b294c482978e8e3b6e627..759a8f95038778aead2f33a65a2d8f2d6b26a765 100644 ---- a/src/main/java/net/minecraft/server/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/server/EntityArmorStand.java -@@ -553,7 +553,13 @@ public class EntityArmorStand extends EntityLiving { +diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java +index 89d3734489b65245e815376edf4e2d9baea1563a..43dc0925887e2e9e86445cccff57be7994ca0d58 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java +@@ -588,7 +588,13 @@ public class EntityArmorStand extends EntityLiving { } private void f(DamageSource damagesource) { @@ -24,30 +24,11 @@ index 9e37bf25689691f9640b294c482978e8e3b6e627..759a8f95038778aead2f33a65a2d8f2d this.g(damagesource); } -diff --git a/src/main/java/net/minecraft/server/EntityBoat.java b/src/main/java/net/minecraft/server/EntityBoat.java -index 05c702bbdb8addea5c69faa0479609e8959945f1..fcb4936e78d56907b0e56d0aaf7f8361513d0a4e 100644 ---- a/src/main/java/net/minecraft/server/EntityBoat.java -+++ b/src/main/java/net/minecraft/server/EntityBoat.java -@@ -155,7 +155,13 @@ public class EntityBoat extends Entity { - } - // CraftBukkit end - if (!flag && this.world.getGameRules().getBoolean(GameRules.DO_ENTITY_DROPS)) { -- this.a((IMaterial) this.g()); -+ // Purpur start -+ final ItemStack boat = new ItemStack(this.getBoatItem()); -+ if (this.world.purpurConfig.persistentDroppableEntityDisplayNames && this.hasCustomName()) { -+ boat.setName(this.getCustomName()); -+ } -+ this.dropItem(boat); -+ // Purpur end - } - - this.die(); -diff --git a/src/main/java/net/minecraft/server/EntityItemFrame.java b/src/main/java/net/minecraft/server/EntityItemFrame.java -index 8a95e698d5caa3730954ce1135b0ec37a389dd70..372be937f1cf95775e37931f326f6a77836968f3 100644 ---- a/src/main/java/net/minecraft/server/EntityItemFrame.java -+++ b/src/main/java/net/minecraft/server/EntityItemFrame.java -@@ -199,7 +199,13 @@ public class EntityItemFrame extends EntityHanging { +diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityItemFrame.java b/src/main/java/net/minecraft/world/entity/decoration/EntityItemFrame.java +index 43152a6c70c9433d627a58051101530ddd693307..eb07db442c5a0da73249f4a02be7dacae0ff0e45 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/EntityItemFrame.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/EntityItemFrame.java +@@ -229,7 +229,13 @@ public class EntityItemFrame extends EntityHanging { } if (flag) { @@ -62,11 +43,11 @@ index 8a95e698d5caa3730954ce1135b0ec37a389dd70..372be937f1cf95775e37931f326f6a77 } if (!itemstack.isEmpty()) { -diff --git a/src/main/java/net/minecraft/server/EntityPainting.java b/src/main/java/net/minecraft/server/EntityPainting.java -index 4b7cd7c59fefbd56d38e0301b08d06ce92c9d8a2..d01fc8b11026536be30c8149aca253280524811f 100644 ---- a/src/main/java/net/minecraft/server/EntityPainting.java -+++ b/src/main/java/net/minecraft/server/EntityPainting.java -@@ -92,7 +92,13 @@ public class EntityPainting extends EntityHanging { +diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityPainting.java b/src/main/java/net/minecraft/world/entity/decoration/EntityPainting.java +index 3de0f21648ca60bdfcbc078bca896d51bf84e207..7517e861301e0c329c70aa6f2bf5aa40114b6589 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/EntityPainting.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/EntityPainting.java +@@ -108,7 +108,13 @@ public class EntityPainting extends EntityHanging { } } @@ -81,11 +62,30 @@ index 4b7cd7c59fefbd56d38e0301b08d06ce92c9d8a2..d01fc8b11026536be30c8149aca25328 } } -diff --git a/src/main/java/net/minecraft/server/ItemArmorStand.java b/src/main/java/net/minecraft/server/ItemArmorStand.java -index c9a5d3b583076cf8f2f32b12c142beb3f5e22dc0..315faee9e35d27071a62ea1d335dfbe5351582ca 100644 ---- a/src/main/java/net/minecraft/server/ItemArmorStand.java -+++ b/src/main/java/net/minecraft/server/ItemArmorStand.java -@@ -43,6 +43,14 @@ public class ItemArmorStand extends Item { +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java +index e5cda8c040c93639211dacbf5b0c7cd6a9df9e6d..9cd1a2a2a8db1d8daf7c712d6bd03fad1b048485 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java +@@ -201,7 +201,13 @@ public class EntityBoat extends Entity { + } + // CraftBukkit end + if (!flag && this.world.getGameRules().getBoolean(GameRules.DO_ENTITY_DROPS)) { +- this.a((IMaterial) this.g()); ++ // Purpur start ++ final ItemStack boat = new ItemStack(this.getBoatItem()); ++ if (this.world.purpurConfig.persistentDroppableEntityDisplayNames && this.hasCustomName()) { ++ boat.setName(this.getCustomName()); ++ } ++ this.dropItem(boat); ++ // Purpur end + } + + this.die(); +diff --git a/src/main/java/net/minecraft/world/item/ItemArmorStand.java b/src/main/java/net/minecraft/world/item/ItemArmorStand.java +index cd46df5485ebfd597ea72360a27872d46174ee19..245d3fe09feb9dc27b097642d40664a9f2377581 100644 +--- a/src/main/java/net/minecraft/world/item/ItemArmorStand.java ++++ b/src/main/java/net/minecraft/world/item/ItemArmorStand.java +@@ -63,6 +63,14 @@ public class ItemArmorStand extends Item { return EnumInteractionResult.FAIL; } // CraftBukkit end @@ -100,11 +100,11 @@ index c9a5d3b583076cf8f2f32b12c142beb3f5e22dc0..315faee9e35d27071a62ea1d335dfbe5 worldserver.addAllEntities(entityarmorstand); // Paper - moved down world.playSound((EntityHuman) null, entityarmorstand.locX(), entityarmorstand.locY(), entityarmorstand.locZ(), SoundEffects.ENTITY_ARMOR_STAND_PLACE, SoundCategory.BLOCKS, 0.75F, 0.8F); } -diff --git a/src/main/java/net/minecraft/server/ItemBoat.java b/src/main/java/net/minecraft/server/ItemBoat.java -index 0580ce55ec945b5bc6ce8c5d0cee13b03ccc7d1a..6183da7ad2a458f4ada288ec82fdaf097d771122 100644 ---- a/src/main/java/net/minecraft/server/ItemBoat.java -+++ b/src/main/java/net/minecraft/server/ItemBoat.java -@@ -52,6 +52,11 @@ public class ItemBoat extends Item { +diff --git a/src/main/java/net/minecraft/world/item/ItemBoat.java b/src/main/java/net/minecraft/world/item/ItemBoat.java +index 1d812b3e27f87213afc3e441eb20ca984458ce2a..636a8bc76d436fc770b4e05a93f1991210b64230 100644 +--- a/src/main/java/net/minecraft/world/item/ItemBoat.java ++++ b/src/main/java/net/minecraft/world/item/ItemBoat.java +@@ -65,6 +65,11 @@ public class ItemBoat extends Item { entityboat.setType(this.b); entityboat.yaw = entityhuman.yaw; @@ -116,11 +116,11 @@ index 0580ce55ec945b5bc6ce8c5d0cee13b03ccc7d1a..6183da7ad2a458f4ada288ec82fdaf09 if (!world.getCubes(entityboat, entityboat.getBoundingBox().g(-0.1D))) { return InteractionResultWrapper.fail(itemstack); } else { -diff --git a/src/main/java/net/minecraft/server/ItemHanging.java b/src/main/java/net/minecraft/server/ItemHanging.java -index a3eaeeda875d96fe4b047bd6bf993018722c96b9..f2f800087adb0238b4b672b9f6f4c8c4836f2891 100644 ---- a/src/main/java/net/minecraft/server/ItemHanging.java -+++ b/src/main/java/net/minecraft/server/ItemHanging.java -@@ -26,7 +26,7 @@ public class ItemHanging extends Item { +diff --git a/src/main/java/net/minecraft/world/item/ItemHanging.java b/src/main/java/net/minecraft/world/item/ItemHanging.java +index bbd3bb2d12e500d15485598783d39b0cb63a6d83..8e4c3304779cfccf7d45d4843f9c15bffce8ba07 100644 +--- a/src/main/java/net/minecraft/world/item/ItemHanging.java ++++ b/src/main/java/net/minecraft/world/item/ItemHanging.java +@@ -39,7 +39,7 @@ public class ItemHanging extends Item { return EnumInteractionResult.FAIL; } else { World world = itemactioncontext.getWorld(); @@ -129,7 +129,7 @@ index a3eaeeda875d96fe4b047bd6bf993018722c96b9..f2f800087adb0238b4b672b9f6f4c8c4 if (this.a == EntityTypes.PAINTING) { object = new EntityPainting(world, blockposition1, enumdirection); -@@ -42,6 +42,11 @@ public class ItemHanging extends Item { +@@ -55,6 +55,11 @@ public class ItemHanging extends Item { if (nbttagcompound != null) { EntityTypes.a(world, entityhuman, (Entity) object, nbttagcompound); @@ -141,11 +141,11 @@ index a3eaeeda875d96fe4b047bd6bf993018722c96b9..f2f800087adb0238b4b672b9f6f4c8c4 } if (((EntityHanging) object).survives()) { -diff --git a/src/main/java/net/minecraft/server/ItemStack.java b/src/main/java/net/minecraft/server/ItemStack.java -index a4edfb02fd350433020b0f3699726b6127ab9933..3f9062d8eca3ce53c0fb9e9e40330aa4e3296c9a 100644 ---- a/src/main/java/net/minecraft/server/ItemStack.java -+++ b/src/main/java/net/minecraft/server/ItemStack.java -@@ -733,6 +733,7 @@ public final class ItemStack { +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 81e2ccfa4f6cf6a4ad9236cf0ce94df8dc3ec5b6..132972755ac74838f3386e0fac5033380b71fce5 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -788,6 +788,7 @@ public final class ItemStack { return this.getItem().h(this); } @@ -154,7 +154,7 @@ index a4edfb02fd350433020b0f3699726b6127ab9933..3f9062d8eca3ce53c0fb9e9e40330aa4 NBTTagCompound nbttagcompound = this.a("display"); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index abc9b4fc27fdef37e3444cc3d885acab9f4d3f23..7915a0204597a3711c1f177cf504a1c3c603e91e 100644 +index 2d4dea3c432fcf52dffd126f8bd910be03c20b1c..e1af622206f28186e7eebf135f3786c7a771b337 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -83,8 +83,10 @@ public class PurpurWorldConfig { diff --git a/patches/server/0127-Set-name-visible-when-using-a-Name-Tag-on-an-Armor-S.patch b/patches/server/0127-Set-name-visible-when-using-a-Name-Tag-on-an-Armor-S.patch index e9c069961..5044d12a1 100644 --- a/patches/server/0127-Set-name-visible-when-using-a-Name-Tag-on-an-Armor-S.patch +++ b/patches/server/0127-Set-name-visible-when-using-a-Name-Tag-on-an-Armor-S.patch @@ -4,11 +4,19 @@ Date: Tue, 17 Nov 2020 13:12:09 -0800 Subject: [PATCH] Set name visible when using a Name Tag on an Armor Stand -diff --git a/src/main/java/net/minecraft/server/ItemNameTag.java b/src/main/java/net/minecraft/server/ItemNameTag.java -index a34772e329df62d9176b0aa392197e2771c69da4..facaca3622e028e315b822a61ed40ba518de2720 100644 ---- a/src/main/java/net/minecraft/server/ItemNameTag.java -+++ b/src/main/java/net/minecraft/server/ItemNameTag.java -@@ -20,6 +20,11 @@ public class ItemNameTag extends Item { +diff --git a/src/main/java/net/minecraft/world/item/ItemNameTag.java b/src/main/java/net/minecraft/world/item/ItemNameTag.java +index b9b2b27e534ba87a1aae3c521f393a066a18a199..4f4e9ebb9af4970fe920a540d40dbc56682efd57 100644 +--- a/src/main/java/net/minecraft/world/item/ItemNameTag.java ++++ b/src/main/java/net/minecraft/world/item/ItemNameTag.java +@@ -5,6 +5,7 @@ import net.minecraft.world.EnumHand; + import net.minecraft.world.EnumInteractionResult; + import net.minecraft.world.entity.EntityInsentient; + import net.minecraft.world.entity.EntityLiving; ++import net.minecraft.world.entity.decoration.EntityArmorStand; + import net.minecraft.world.entity.player.EntityHuman; + + // Paper start +@@ -27,6 +28,11 @@ public class ItemNameTag extends Item { if (!event.callEvent()) return EnumInteractionResult.PASS; EntityLiving newEntityLiving = ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getEntity()).getHandle(); newEntityLiving.setCustomName(event.getName() != null ? PaperAdventure.asVanilla(event.getName()) : null); @@ -21,7 +29,7 @@ index a34772e329df62d9176b0aa392197e2771c69da4..facaca3622e028e315b822a61ed40ba5 ((EntityInsentient) newEntityLiving).setPersistent(); } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 7915a0204597a3711c1f177cf504a1c3c603e91e..9a419e2e591113015bd122202aba2a8aa8494f63 100644 +index e1af622206f28186e7eebf135f3786c7a771b337..43d23f55283ad8a611073bceaea554368775f483 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -84,9 +84,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0128-Add-twisting-and-weeping-vines-growth-rates.patch b/patches/server/0128-Add-twisting-and-weeping-vines-growth-rates.patch index e2de87ecb..147611762 100644 --- a/patches/server/0128-Add-twisting-and-weeping-vines-growth-rates.patch +++ b/patches/server/0128-Add-twisting-and-weeping-vines-growth-rates.patch @@ -4,11 +4,11 @@ Date: Sun, 22 Nov 2020 06:02:32 -0600 Subject: [PATCH] Add twisting and weeping vines growth rates -diff --git a/src/main/java/net/minecraft/server/BlockGrowingTop.java b/src/main/java/net/minecraft/server/BlockGrowingTop.java -index 7963411be990fed8eb0ffca3eba35d15a9b8d7bd..6c084ad5cda41425eed04465d942f6a73968cd61 100644 ---- a/src/main/java/net/minecraft/server/BlockGrowingTop.java -+++ b/src/main/java/net/minecraft/server/BlockGrowingTop.java -@@ -23,9 +23,11 @@ public abstract class BlockGrowingTop extends BlockGrowingAbstract implements IB +diff --git a/src/main/java/net/minecraft/world/level/block/BlockGrowingTop.java b/src/main/java/net/minecraft/world/level/block/BlockGrowingTop.java +index 84bd1fa9edb59b8515685a47783ed5e6abe7333f..546c7877647bac41753a600bd25c630a0510be56 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockGrowingTop.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockGrowingTop.java +@@ -38,9 +38,11 @@ public abstract class BlockGrowingTop extends BlockGrowingAbstract implements IB return (Integer) iblockdata.get(BlockGrowingTop.d) < 25; } @@ -21,11 +21,19 @@ index 7963411be990fed8eb0ffca3eba35d15a9b8d7bd..6c084ad5cda41425eed04465d942f6a7 BlockPosition blockposition1 = blockposition.shift(this.a); if (this.h(worldserver.getType(blockposition1))) { -diff --git a/src/main/java/net/minecraft/server/BlockKelp.java b/src/main/java/net/minecraft/server/BlockKelp.java -index a243aaed58454ae304c988df8a8a090a8236075e..2a7a6e5943f2ff87815c398ffec01bb78d320690 100644 ---- a/src/main/java/net/minecraft/server/BlockKelp.java -+++ b/src/main/java/net/minecraft/server/BlockKelp.java -@@ -53,4 +53,10 @@ public class BlockKelp extends BlockGrowingTop implements IFluidContainer { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockKelp.java b/src/main/java/net/minecraft/world/level/block/BlockKelp.java +index 424b9b3c1263910eb6113f19efc14607dd2bf638..27f1cbe8786d7c37d62193a21baf0a2bdc6f0294 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockKelp.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockKelp.java +@@ -4,6 +4,7 @@ import java.util.Random; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPosition; + import net.minecraft.core.EnumDirection; ++import net.minecraft.server.level.WorldServer; + import net.minecraft.tags.Tag; + import net.minecraft.tags.TagsFluid; + import net.minecraft.world.item.context.BlockActionContext; +@@ -66,4 +67,10 @@ public class BlockKelp extends BlockGrowingTop implements IFluidContainer { public Fluid d(IBlockData iblockdata) { return FluidTypes.WATER.a(false); } @@ -36,11 +44,19 @@ index a243aaed58454ae304c988df8a8a090a8236075e..2a7a6e5943f2ff87815c398ffec01bb7 + } + // Purpur end } -diff --git a/src/main/java/net/minecraft/server/BlockTwistingVines.java b/src/main/java/net/minecraft/server/BlockTwistingVines.java -index be381674632c49d7465dd7d52084b52f45194b54..146638111c56ec81ab46b514d45a7cc8aac2b36a 100644 ---- a/src/main/java/net/minecraft/server/BlockTwistingVines.java -+++ b/src/main/java/net/minecraft/server/BlockTwistingVines.java -@@ -24,4 +24,10 @@ public class BlockTwistingVines extends BlockGrowingTop { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockTwistingVines.java b/src/main/java/net/minecraft/world/level/block/BlockTwistingVines.java +index 2cfa96f144391e664207ac8e8bdd3f11bfed4dff..3a8d08a1ee8f066cea36e6acff492e5af62993c5 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockTwistingVines.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockTwistingVines.java +@@ -2,6 +2,7 @@ package net.minecraft.world.level.block; + + import java.util.Random; + import net.minecraft.core.EnumDirection; ++import net.minecraft.server.level.WorldServer; + import net.minecraft.world.level.block.state.BlockBase; + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.shapes.VoxelShape; +@@ -28,4 +29,10 @@ public class BlockTwistingVines extends BlockGrowingTop { protected boolean h(IBlockData iblockdata) { return BlockNetherVinesUtil.a(iblockdata); } @@ -51,11 +67,19 @@ index be381674632c49d7465dd7d52084b52f45194b54..146638111c56ec81ab46b514d45a7cc8 + } + // Purpur end } -diff --git a/src/main/java/net/minecraft/server/BlockWeepingVines.java b/src/main/java/net/minecraft/server/BlockWeepingVines.java -index 23dca1940375d243531fc4a891f04e937ae2f48f..94ffadb91fec65a721cf0c8fa98bad708a2ca269 100644 ---- a/src/main/java/net/minecraft/server/BlockWeepingVines.java -+++ b/src/main/java/net/minecraft/server/BlockWeepingVines.java -@@ -24,4 +24,10 @@ public class BlockWeepingVines extends BlockGrowingTop { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockWeepingVines.java b/src/main/java/net/minecraft/world/level/block/BlockWeepingVines.java +index 2552631084926c2fad40b3f21ae479c0e1cfdb77..198bd8857571872ed3f7437529c330dceeb825db 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockWeepingVines.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockWeepingVines.java +@@ -2,6 +2,7 @@ package net.minecraft.world.level.block; + + import java.util.Random; + import net.minecraft.core.EnumDirection; ++import net.minecraft.server.level.WorldServer; + import net.minecraft.world.level.block.state.BlockBase; + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.shapes.VoxelShape; +@@ -28,4 +29,10 @@ public class BlockWeepingVines extends BlockGrowingTop { protected boolean h(IBlockData iblockdata) { return BlockNetherVinesUtil.a(iblockdata); } @@ -67,7 +91,7 @@ index 23dca1940375d243531fc4a891f04e937ae2f48f..94ffadb91fec65a721cf0c8fa98bad70 + // Purpur end } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 9a419e2e591113015bd122202aba2a8aa8494f63..8f59e8412c2d82211274abdc9fc9bb94f117960d 100644 +index 43d23f55283ad8a611073bceaea554368775f483..a7a368a0a4e59800b4ba9191ab24cca9ea636ff0 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -419,6 +419,16 @@ public class PurpurWorldConfig { diff --git a/patches/server/0129-Kelp-weeping-and-twisting-vines-configurable-max-gro.patch b/patches/server/0129-Kelp-weeping-and-twisting-vines-configurable-max-gro.patch index 2391f3b11..4edef9f04 100644 --- a/patches/server/0129-Kelp-weeping-and-twisting-vines-configurable-max-gro.patch +++ b/patches/server/0129-Kelp-weeping-and-twisting-vines-configurable-max-gro.patch @@ -4,11 +4,11 @@ Date: Sun, 22 Nov 2020 20:13:27 -0600 Subject: [PATCH] Kelp weeping and twisting vines configurable max growth age -diff --git a/src/main/java/net/minecraft/server/BlockGrowingTop.java b/src/main/java/net/minecraft/server/BlockGrowingTop.java -index 6c084ad5cda41425eed04465d942f6a73968cd61..6d49422c3358b06369e1a31ee5580ff4a0057c5f 100644 ---- a/src/main/java/net/minecraft/server/BlockGrowingTop.java -+++ b/src/main/java/net/minecraft/server/BlockGrowingTop.java -@@ -15,7 +15,7 @@ public abstract class BlockGrowingTop extends BlockGrowingAbstract implements IB +diff --git a/src/main/java/net/minecraft/world/level/block/BlockGrowingTop.java b/src/main/java/net/minecraft/world/level/block/BlockGrowingTop.java +index 546c7877647bac41753a600bd25c630a0510be56..3d6a1131a138114424b683a81d04478e92d05544 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockGrowingTop.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockGrowingTop.java +@@ -30,7 +30,7 @@ public abstract class BlockGrowingTop extends BlockGrowingAbstract implements IB @Override public IBlockData a(GeneratorAccess generatoraccess) { @@ -17,7 +17,7 @@ index 6c084ad5cda41425eed04465d942f6a73968cd61..6d49422c3358b06369e1a31ee5580ff4 } @Override -@@ -25,9 +25,11 @@ public abstract class BlockGrowingTop extends BlockGrowingAbstract implements IB +@@ -40,9 +40,11 @@ public abstract class BlockGrowingTop extends BlockGrowingAbstract implements IB public abstract double getGrowthModifier(WorldServer worldserver); // Purpur @@ -30,7 +30,7 @@ index 6c084ad5cda41425eed04465d942f6a73968cd61..6d49422c3358b06369e1a31ee5580ff4 BlockPosition blockposition1 = blockposition.shift(this.a); if (this.h(worldserver.getType(blockposition1))) { -@@ -72,13 +74,13 @@ public abstract class BlockGrowingTop extends BlockGrowingAbstract implements IB +@@ -87,13 +89,13 @@ public abstract class BlockGrowingTop extends BlockGrowingAbstract implements IB @Override public void a(WorldServer worldserver, Random random, BlockPosition blockposition, IBlockData iblockdata) { BlockPosition blockposition1 = blockposition.shift(this.a); @@ -46,11 +46,11 @@ index 6c084ad5cda41425eed04465d942f6a73968cd61..6d49422c3358b06369e1a31ee5580ff4 } } -diff --git a/src/main/java/net/minecraft/server/BlockKelp.java b/src/main/java/net/minecraft/server/BlockKelp.java -index 2a7a6e5943f2ff87815c398ffec01bb78d320690..b35c115e34cf5f7a24cd26ca31c19a63c82e0080 100644 ---- a/src/main/java/net/minecraft/server/BlockKelp.java -+++ b/src/main/java/net/minecraft/server/BlockKelp.java -@@ -58,5 +58,9 @@ public class BlockKelp extends BlockGrowingTop implements IFluidContainer { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockKelp.java b/src/main/java/net/minecraft/world/level/block/BlockKelp.java +index 27f1cbe8786d7c37d62193a21baf0a2bdc6f0294..90ad39d40e4f979126d80c70df292e01e07ed793 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockKelp.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockKelp.java +@@ -72,5 +72,9 @@ public class BlockKelp extends BlockGrowingTop implements IFluidContainer { public double getGrowthModifier(WorldServer worldserver) { return worldserver.spigotConfig.kelpModifier; } @@ -60,11 +60,11 @@ index 2a7a6e5943f2ff87815c398ffec01bb78d320690..b35c115e34cf5f7a24cd26ca31c19a63 + } // Purpur end } -diff --git a/src/main/java/net/minecraft/server/BlockTwistingVines.java b/src/main/java/net/minecraft/server/BlockTwistingVines.java -index 146638111c56ec81ab46b514d45a7cc8aac2b36a..71b9b7183df5702f2753c7372d0c491b2230b365 100644 ---- a/src/main/java/net/minecraft/server/BlockTwistingVines.java -+++ b/src/main/java/net/minecraft/server/BlockTwistingVines.java -@@ -29,5 +29,9 @@ public class BlockTwistingVines extends BlockGrowingTop { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockTwistingVines.java b/src/main/java/net/minecraft/world/level/block/BlockTwistingVines.java +index 3a8d08a1ee8f066cea36e6acff492e5af62993c5..d95151d50d2652e5f1b215267c898402f0b28829 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockTwistingVines.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockTwistingVines.java +@@ -34,5 +34,9 @@ public class BlockTwistingVines extends BlockGrowingTop { public double getGrowthModifier(WorldServer worldserver) { return worldserver.purpurConfig.twistingVinesGrowthModifier; } @@ -74,11 +74,11 @@ index 146638111c56ec81ab46b514d45a7cc8aac2b36a..71b9b7183df5702f2753c7372d0c491b + } // Purpur end } -diff --git a/src/main/java/net/minecraft/server/BlockWeepingVines.java b/src/main/java/net/minecraft/server/BlockWeepingVines.java -index 94ffadb91fec65a721cf0c8fa98bad708a2ca269..067df63ab27ecb9fe0a0d012b16efbd546fdfff7 100644 ---- a/src/main/java/net/minecraft/server/BlockWeepingVines.java -+++ b/src/main/java/net/minecraft/server/BlockWeepingVines.java -@@ -29,5 +29,9 @@ public class BlockWeepingVines extends BlockGrowingTop { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockWeepingVines.java b/src/main/java/net/minecraft/world/level/block/BlockWeepingVines.java +index 198bd8857571872ed3f7437529c330dceeb825db..a71f97e87ee7210f3246e542dd768403905f7679 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockWeepingVines.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockWeepingVines.java +@@ -34,5 +34,9 @@ public class BlockWeepingVines extends BlockGrowingTop { public double getGrowthModifier(WorldServer worldserver) { return worldserver.purpurConfig.weepingVinesGrowthModifier; } @@ -89,7 +89,7 @@ index 94ffadb91fec65a721cf0c8fa98bad708a2ca269..067df63ab27ecb9fe0a0d012b16efbd5 // Purpur end } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 8f59e8412c2d82211274abdc9fc9bb94f117960d..84172893cb5dd9aa61296d9bfb4cf0ea1ff91e9d 100644 +index a7a368a0a4e59800b4ba9191ab24cca9ea636ff0..27863bdfc41fd27a9dbf9e8f9673fcb65b9dc5a4 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -366,6 +366,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0130-Add-config-for-allowing-Endermen-to-despawn-even-whi.patch b/patches/server/0130-Add-config-for-allowing-Endermen-to-despawn-even-whi.patch index 1d76e9252..2836a48af 100644 --- a/patches/server/0130-Add-config-for-allowing-Endermen-to-despawn-even-whi.patch +++ b/patches/server/0130-Add-config-for-allowing-Endermen-to-despawn-even-whi.patch @@ -7,11 +7,11 @@ Subject: [PATCH] Add config for allowing Endermen to despawn even while This should help to reduce the amount of dirt, gravel, grass, and etc. that Endermen like to randomly place all over the world. -diff --git a/src/main/java/net/minecraft/server/EntityEnderman.java b/src/main/java/net/minecraft/server/EntityEnderman.java -index a930cfe4ec08ee5414f03e420ad79ab110d84129..0a9bd0dbd2f90aa968db0f8a14cde7e58d18652e 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderman.java -+++ b/src/main/java/net/minecraft/server/EntityEnderman.java -@@ -379,7 +379,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +index 03fa2cfc1d5bc27e03e9979b3f33d88362c19066..18b3f8d1fadd1424327261d92b49977a35c4948c 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +@@ -435,7 +435,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { @Override public boolean isSpecialPersistence() { @@ -21,7 +21,7 @@ index a930cfe4ec08ee5414f03e420ad79ab110d84129..0a9bd0dbd2f90aa968db0f8a14cde7e5 static class PathfinderGoalEndermanPickupBlock extends PathfinderGoal { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 84172893cb5dd9aa61296d9bfb4cf0ea1ff91e9d..6c7e898dd42e958553d929b94ce5ddb9542001ee 100644 +index 27863bdfc41fd27a9dbf9e8f9673fcb65b9dc5a4..3a7d060263da6a31f65870833bbb82893700022d 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -588,10 +588,12 @@ public class PurpurWorldConfig { diff --git a/patches/server/0131-Add-critical-hit-check-to-EntityDamagedByEntityEvent.patch b/patches/server/0131-Add-critical-hit-check-to-EntityDamagedByEntityEvent.patch index 65f802a10..df2c2a109 100644 --- a/patches/server/0131-Add-critical-hit-check-to-EntityDamagedByEntityEvent.patch +++ b/patches/server/0131-Add-critical-hit-check-to-EntityDamagedByEntityEvent.patch @@ -4,11 +4,11 @@ Date: Tue, 24 Nov 2020 04:30:46 -0600 Subject: [PATCH] Add critical hit check to EntityDamagedByEntityEvent -diff --git a/src/main/java/net/minecraft/server/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java -index fc51d6f9cd8c6ca61ae70b07cff817c5d871ab48..84fdb4710331791dfb180ce401f1da6962635b54 100644 ---- a/src/main/java/net/minecraft/server/EntityHuman.java -+++ b/src/main/java/net/minecraft/server/EntityHuman.java -@@ -74,6 +74,7 @@ public abstract class EntityHuman extends EntityLiving { +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index 1062317c22171bccee78a2db1841e0fd2b3023d7..907bfe42bd866188639f7d25150fcde039c1e5f7 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -171,6 +171,7 @@ public abstract class EntityHuman extends EntityLiving { // Paper start public boolean affectsSpawning = true; // Paper end @@ -16,7 +16,7 @@ index fc51d6f9cd8c6ca61ae70b07cff817c5d871ab48..84fdb4710331791dfb180ce401f1da69 // CraftBukkit start public boolean fauxSleeping; -@@ -1067,6 +1068,7 @@ public abstract class EntityHuman extends EntityLiving { +@@ -1164,6 +1165,7 @@ public abstract class EntityHuman extends EntityLiving { flag2 = flag2 && !world.paperConfig.disablePlayerCrits; // Paper flag2 = flag2 && !this.isSprinting(); if (flag2) { @@ -24,7 +24,7 @@ index fc51d6f9cd8c6ca61ae70b07cff817c5d871ab48..84fdb4710331791dfb180ce401f1da69 f *= 1.5F; } -@@ -1103,6 +1105,7 @@ public abstract class EntityHuman extends EntityLiving { +@@ -1200,6 +1202,7 @@ public abstract class EntityHuman extends EntityLiving { Vec3D vec3d = entity.getMot(); boolean flag5 = entity.damageEntity(DamageSource.playerAttack(this), f); @@ -33,10 +33,10 @@ index fc51d6f9cd8c6ca61ae70b07cff817c5d871ab48..84fdb4710331791dfb180ce401f1da69 if (flag5) { if (i > 0) { diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index c4d0082bb0d310ad16de36df03dd99225c5cadb0..22aaa4efd0f5e89f66abf6a9054b595f52e7129b 100644 +index 9a6c4f292940b1cef2f4ef87c2e47d82ba5cb60f..b068e08e3922536b4de8a54e7d63a1ec943602f3 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1074,7 +1074,7 @@ public class CraftEventFactory { +@@ -1076,7 +1076,7 @@ public class CraftEventFactory { private static EntityDamageEvent callEntityDamageEvent(Entity damager, Entity damagee, DamageCause cause, Map modifiers, Map> modifierFunctions, boolean cancelled) { EntityDamageEvent event; if (damager != null) { diff --git a/patches/server/0132-Add-configurable-snowball-damage.patch b/patches/server/0132-Add-configurable-snowball-damage.patch index 18bcc048f..879506e15 100644 --- a/patches/server/0132-Add-configurable-snowball-damage.patch +++ b/patches/server/0132-Add-configurable-snowball-damage.patch @@ -4,11 +4,11 @@ Date: Tue, 24 Nov 2020 05:32:02 -0600 Subject: [PATCH] Add configurable snowball damage -diff --git a/src/main/java/net/minecraft/server/EntitySnowball.java b/src/main/java/net/minecraft/server/EntitySnowball.java -index 34a5f481e6ed1357861dca15fb4013ec8484a292..d7bab4446a5a8eef98c10b1f6eb89de90365dfeb 100644 ---- a/src/main/java/net/minecraft/server/EntitySnowball.java -+++ b/src/main/java/net/minecraft/server/EntitySnowball.java -@@ -29,7 +29,7 @@ public class EntitySnowball extends EntityProjectileThrowable { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntitySnowball.java b/src/main/java/net/minecraft/world/entity/projectile/EntitySnowball.java +index 0d3b9c81e47eef645335e49a1d6d88db7338aa4b..6bfd3f57e6c04ed426870d6dbf068bf324f22d6e 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntitySnowball.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntitySnowball.java +@@ -40,7 +40,7 @@ public class EntitySnowball extends EntityProjectileThrowable { protected void a(MovingObjectPositionEntity movingobjectpositionentity) { super.a(movingobjectpositionentity); Entity entity = movingobjectpositionentity.getEntity(); @@ -18,7 +18,7 @@ index 34a5f481e6ed1357861dca15fb4013ec8484a292..d7bab4446a5a8eef98c10b1f6eb89de9 entity.damageEntity(DamageSource.projectile(this, this.getShooter()), (float) i); } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 6c7e898dd42e958553d929b94ce5ddb9542001ee..9dcbce33274f599e4846588afc6d38b8353d6422 100644 +index 3a7d060263da6a31f65870833bbb82893700022d..2b6e29463ec6b1d67a0100c650c218f340f72940 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -214,6 +214,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0133-Zombie-break-door-minimum-difficulty-option.patch b/patches/server/0133-Zombie-break-door-minimum-difficulty-option.patch index f2a946933..d3cf1d168 100644 --- a/patches/server/0133-Zombie-break-door-minimum-difficulty-option.patch +++ b/patches/server/0133-Zombie-break-door-minimum-difficulty-option.patch @@ -4,11 +4,21 @@ Date: Fri, 27 Nov 2020 10:33:33 -0600 Subject: [PATCH] Zombie break door minimum difficulty option -diff --git a/src/main/java/net/minecraft/server/PathfinderGoalBreakDoor.java b/src/main/java/net/minecraft/server/PathfinderGoalBreakDoor.java -index 7488a12926c5ee4adc3bc1fa3973988350381544..23870a271b759a953a095df835e08ea2a09f4218 100644 ---- a/src/main/java/net/minecraft/server/PathfinderGoalBreakDoor.java -+++ b/src/main/java/net/minecraft/server/PathfinderGoalBreakDoor.java -@@ -13,7 +13,7 @@ public class PathfinderGoalBreakDoor extends PathfinderGoalDoorInteract { +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalBreakDoor.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalBreakDoor.java +index 10ee8a0a717354f50b29e7ebeab0ee2aa7bf42f7..d785066e2a52699c18315f7244d80db6cab0c736 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalBreakDoor.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalBreakDoor.java +@@ -3,7 +3,9 @@ package net.minecraft.world.entity.ai.goal; + import java.util.function.Predicate; + import net.minecraft.core.IPosition; + import net.minecraft.world.EnumDifficulty; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityInsentient; ++import net.minecraft.world.entity.monster.EntityZombie; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.block.Block; + +@@ -18,7 +20,7 @@ public class PathfinderGoalBreakDoor extends PathfinderGoalDoorInteract { super(entityinsentient); this.b = -1; this.c = -1; @@ -17,7 +27,7 @@ index 7488a12926c5ee4adc3bc1fa3973988350381544..23870a271b759a953a095df835e08ea2 } public PathfinderGoalBreakDoor(EntityInsentient entityinsentient, int i, Predicate predicate) { -@@ -82,4 +82,21 @@ public class PathfinderGoalBreakDoor extends PathfinderGoalDoorInteract { +@@ -87,4 +89,21 @@ public class PathfinderGoalBreakDoor extends PathfinderGoalDoorInteract { private boolean a(EnumDifficulty enumdifficulty) { return this.g.test(enumdifficulty); } @@ -40,17 +50,17 @@ index 7488a12926c5ee4adc3bc1fa3973988350381544..23870a271b759a953a095df835e08ea2 + // Purpur end } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 9dcbce33274f599e4846588afc6d38b8353d6422..4801be1715f70655ee3aed53e5db10ac18dc7a82 100644 +index 2b6e29463ec6b1d67a0100c650c218f340f72940..65de687319e9759630c7114dfe5c70455bb9957a 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -2,6 +2,7 @@ package net.pl3x.purpur; +@@ -1,6 +1,7 @@ + package net.pl3x.purpur; - import net.minecraft.server.Block; - import net.minecraft.server.Blocks; -+import net.minecraft.server.EnumDifficulty; - import net.minecraft.server.Explosion; - import net.minecraft.server.IRegistry; - import net.minecraft.server.Item; + import net.minecraft.core.IRegistry; ++import net.minecraft.world.EnumDifficulty; + import net.minecraft.world.level.Explosion; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; @@ -1132,6 +1133,7 @@ public class PurpurWorldConfig { public double zombieJockeyChance = 0.05D; public boolean zombieJockeyTryExistingChickens = true; diff --git a/patches/server/0134-Add-demo-command.patch b/patches/server/0134-Add-demo-command.patch index 11cbaa41b..4ccc5a1a7 100644 --- a/patches/server/0134-Add-demo-command.patch +++ b/patches/server/0134-Add-demo-command.patch @@ -4,11 +4,11 @@ Date: Mon, 30 Nov 2020 03:12:04 -0600 Subject: [PATCH] Add demo command -diff --git a/src/main/java/net/minecraft/server/CommandDispatcher.java b/src/main/java/net/minecraft/server/CommandDispatcher.java -index d080bf58ebc9c1dc9d41fae7d515547bc3f26d54..b5cc099746e9f05ea69bc438bda22a5ac3ebc3c5 100644 ---- a/src/main/java/net/minecraft/server/CommandDispatcher.java -+++ b/src/main/java/net/minecraft/server/CommandDispatcher.java -@@ -107,6 +107,7 @@ public class CommandDispatcher { +diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java +index e8fe4984fdc67536561a1ad08b328a30b30b8717..a551636c2c59e68a5abb1cd5611c1d5c7e36f514 100644 +--- a/src/main/java/net/minecraft/commands/CommandDispatcher.java ++++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java +@@ -191,6 +191,7 @@ public class CommandDispatcher { CommandIdleTimeout.a(this.b); CommandStop.a(this.b); CommandWhitelist.a(this.b); @@ -16,11 +16,11 @@ index d080bf58ebc9c1dc9d41fae7d515547bc3f26d54..b5cc099746e9f05ea69bc438bda22a5a net.pl3x.purpur.command.PingCommand.register(getDispatcher()); // Purpur } -diff --git a/src/main/java/net/minecraft/server/PacketPlayOutGameStateChange.java b/src/main/java/net/minecraft/server/PacketPlayOutGameStateChange.java -index 08cbc787e2bf6587878bdeffa7248e5d23cdcf98..57d39ed441ec7be933f4fce48225f527db7e6a3c 100644 ---- a/src/main/java/net/minecraft/server/PacketPlayOutGameStateChange.java -+++ b/src/main/java/net/minecraft/server/PacketPlayOutGameStateChange.java -@@ -11,7 +11,7 @@ public class PacketPlayOutGameStateChange implements Packet> { +diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java +index e101b1dccec98d5c7b9ee9a2c8aa2e3b911de652..2214b116d1e548eca3c2e70e8b23d7c7913c361d 100644 +--- a/src/main/java/net/minecraft/network/NetworkManager.java ++++ b/src/main/java/net/minecraft/network/NetworkManager.java +@@ -435,9 +435,9 @@ public class NetworkManager extends SimpleChannelInboundHandler> { // note: since the type is not dynamic here, we need to actually copy the old executor code // into two branches. On conflict, just re-copy - no changes were made inside the executor code. if (flush) { @@ -20,7 +20,7 @@ index d93634391501da01cb1afe70fedd5247c654e8fc..53b5063b43e42f09c2ef335251c91d20 } // Paper start -@@ -428,7 +428,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { +@@ -447,7 +447,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { } try { // Paper end @@ -29,7 +29,7 @@ index d93634391501da01cb1afe70fedd5247c654e8fc..53b5063b43e42f09c2ef335251c91d20 if (genericfuturelistener != null) { -@@ -448,12 +448,12 @@ public class NetworkManager extends SimpleChannelInboundHandler> { +@@ -467,12 +467,12 @@ public class NetworkManager extends SimpleChannelInboundHandler> { packet.onPacketDispatchFinish(player, null); } // Paper end @@ -45,7 +45,7 @@ index d93634391501da01cb1afe70fedd5247c654e8fc..53b5063b43e42f09c2ef335251c91d20 } // Paper start -@@ -463,7 +463,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { +@@ -482,7 +482,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { } try { // Paper end @@ -54,7 +54,7 @@ index d93634391501da01cb1afe70fedd5247c654e8fc..53b5063b43e42f09c2ef335251c91d20 if (genericfuturelistener != null) { -@@ -483,7 +483,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { +@@ -502,7 +502,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { packet.onPacketDispatchFinish(player, null); } // Paper end diff --git a/patches/server/0137-Changeable-Mob-Left-Handed-Chance.patch b/patches/server/0137-Changeable-Mob-Left-Handed-Chance.patch index a26107625..e6e20baa8 100644 --- a/patches/server/0137-Changeable-Mob-Left-Handed-Chance.patch +++ b/patches/server/0137-Changeable-Mob-Left-Handed-Chance.patch @@ -4,11 +4,11 @@ Date: Mon, 30 Nov 2020 11:40:11 -0500 Subject: [PATCH] Changeable Mob Left Handed Chance -diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java -index 3b6b388515818139cf4b4815b65915cedda67af7..679b6a4b408f01ae578803dac8bf562fbfdd2600 100644 ---- a/src/main/java/net/minecraft/server/EntityInsentient.java -+++ b/src/main/java/net/minecraft/server/EntityInsentient.java -@@ -1139,7 +1139,7 @@ public abstract class EntityInsentient extends EntityLiving { +diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +index 8b7f840bb1b24996b40c9bef85f4c1e98e39caec..63d93060b350069040876aaacb91c853d674ea7b 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java ++++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +@@ -1209,7 +1209,7 @@ public abstract class EntityInsentient extends EntityLiving { @Nullable public GroupDataEntity prepare(WorldAccess worldaccess, DifficultyDamageScaler difficultydamagescaler, EnumMobSpawn enummobspawn, @Nullable GroupDataEntity groupdataentity, @Nullable NBTTagCompound nbttagcompound) { this.getAttributeInstance(GenericAttributes.FOLLOW_RANGE).addModifier(new AttributeModifier("Random spawn bonus", this.random.nextGaussian() * 0.05D, AttributeModifier.Operation.MULTIPLY_BASE)); @@ -18,7 +18,7 @@ index 3b6b388515818139cf4b4815b65915cedda67af7..679b6a4b408f01ae578803dac8bf562f } else { this.setLeftHanded(false); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 4801be1715f70655ee3aed53e5db10ac18dc7a82..f9c43a764a609e8c4339868cb0088b3c09ec29f4 100644 +index 65de687319e9759630c7114dfe5c70455bb9957a..6b0b132ce3924722adbd8cb0beb45af446385fe6 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -129,8 +129,10 @@ public class PurpurWorldConfig { diff --git a/patches/server/0138-Add-boat-fall-damage-config.patch b/patches/server/0138-Add-boat-fall-damage-config.patch index 84f5819ce..a03ea82a0 100644 --- a/patches/server/0138-Add-boat-fall-damage-config.patch +++ b/patches/server/0138-Add-boat-fall-damage-config.patch @@ -4,11 +4,19 @@ Date: Mon, 30 Nov 2020 19:36:35 -0600 Subject: [PATCH] Add boat fall damage config -diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index f4e0a0714fa17c370202f6ea02412dc7afb0af97..5a602de5b9ff436e7cfb70c39475be34beddfb8d 100644 ---- a/src/main/java/net/minecraft/server/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/EntityPlayer.java -@@ -1011,7 +1011,16 @@ public class EntityPlayer extends EntityHuman implements ICrafting { +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 9ec4008f2195908130410d2c36fb5bf21b26b991..f942c3ab757b768fbd1d459752b7f29094471c56 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -106,6 +106,7 @@ import net.minecraft.world.entity.monster.EntityMonster; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.entity.player.EnumChatVisibility; + import net.minecraft.world.entity.projectile.EntityArrow; ++import net.minecraft.world.entity.vehicle.EntityBoat; + import net.minecraft.world.entity.vehicle.EntityMinecartAbstract; + import net.minecraft.world.inventory.Container; + import net.minecraft.world.inventory.ContainerHorse; +@@ -1142,7 +1143,16 @@ public class EntityPlayer extends EntityHuman implements ICrafting { if (this.isInvulnerable(damagesource)) { return false; } else { @@ -27,7 +35,7 @@ index f4e0a0714fa17c370202f6ea02412dc7afb0af97..5a602de5b9ff436e7cfb70c39475be34 if (!flag && isSpawnInvulnerable() && damagesource != DamageSource.OUT_OF_WORLD) { // Purpur diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index f9c43a764a609e8c4339868cb0088b3c09ec29f4..684a2fa594176a5f456d5f203a47aba15469c727 100644 +index 6b0b132ce3924722adbd8cb0beb45af446385fe6..34feb9f133044232846cd04f10268235d3076501 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -224,6 +224,7 @@ public class PurpurWorldConfig { diff --git a/patches/server/0139-Config-migration-disable-saving-projectiles-to-disk-.patch b/patches/server/0139-Config-migration-disable-saving-projectiles-to-disk-.patch index 8fc65175c..a55beecc5 100644 --- a/patches/server/0139-Config-migration-disable-saving-projectiles-to-disk-.patch +++ b/patches/server/0139-Config-migration-disable-saving-projectiles-to-disk-.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Config migration: disable saving projectiles to disk -> diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index fa03879f52f89988d1f43a6cab9e202c88ff6d8d..d25d2e43c2dc3588b98b1d76f84ab10c957f2104 100644 +index d61a0e028135486b86ce1d0984eae3aea45e8a9a..b43d6d08d1eb2d77a4c8288d5c5f2a76efcab8db 100644 --- a/src/main/java/net/pl3x/purpur/PurpurConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java @@ -1,6 +1,7 @@ @@ -15,9 +15,9 @@ index fa03879f52f89988d1f43a6cab9e202c88ff6d8d..d25d2e43c2dc3588b98b1d76f84ab10c import co.aikar.timings.TimingsManager; +import com.destroystokyo.paper.PaperConfig; import com.google.common.base.Throwables; - import net.minecraft.server.EntitySize; - import net.minecraft.server.EntityTypes; -@@ -132,6 +133,17 @@ public class PurpurConfig { + import net.minecraft.locale.LocaleLanguage; + import net.minecraft.server.MinecraftServer; +@@ -133,6 +134,17 @@ public class PurpurConfig { return config.getString(path, config.getString(path)); } @@ -36,16 +36,16 @@ index fa03879f52f89988d1f43a6cab9e202c88ff6d8d..d25d2e43c2dc3588b98b1d76f84ab10c public static String afkBroadcastBack = "§e§o%s is no longer AFK"; public static String afkTabListPrefix = "[AFK] "; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 684a2fa594176a5f456d5f203a47aba15469c727..6d64e78e2a06dbc40863b34de6bdb8d019334f7f 100644 +index 34feb9f133044232846cd04f10268235d3076501..15dc2dcbb4bec56efd6e069b1848d6c55a3ffa32 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -1,5 +1,6 @@ package net.pl3x.purpur; +import com.destroystokyo.paper.PaperConfig; - import net.minecraft.server.Block; - import net.minecraft.server.Blocks; - import net.minecraft.server.EnumDifficulty; + import net.minecraft.core.IRegistry; + import net.minecraft.world.EnumDifficulty; + import net.minecraft.world.level.Explosion; @@ -84,6 +85,17 @@ public class PurpurWorldConfig { return PurpurConfig.config.getString("world-settings." + worldName + "." + path, PurpurConfig.config.getString("world-settings.default." + path)); } diff --git a/patches/server/0140-Snow-Golem-rate-of-fire-config.patch b/patches/server/0140-Snow-Golem-rate-of-fire-config.patch index 783ca2f11..a4e705668 100644 --- a/patches/server/0140-Snow-Golem-rate-of-fire-config.patch +++ b/patches/server/0140-Snow-Golem-rate-of-fire-config.patch @@ -9,11 +9,11 @@ The formula used to determine the amount of ticks between shots is: If min-shoot-interval-ticks and max-shoot-interval-ticks are both set to 0, snow golems won't shoot any snowballs. -diff --git a/src/main/java/net/minecraft/server/EntitySnowman.java b/src/main/java/net/minecraft/server/EntitySnowman.java -index e370de0ade49ac81d746588bf0991101eba0ce2d..338c78efe43641686be0d6b3a241865ec5fe56bd 100644 ---- a/src/main/java/net/minecraft/server/EntitySnowman.java -+++ b/src/main/java/net/minecraft/server/EntitySnowman.java -@@ -29,7 +29,7 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java b/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java +index cfcf67e99ae345f77a55771e6a25bdcdb4a9740a..28b5c22ecfe573ac9d91b74e54ebd3e3c5e6373f 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java +@@ -66,7 +66,7 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt @Override protected void initPathfinder() { this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur @@ -23,7 +23,7 @@ index e370de0ade49ac81d746588bf0991101eba0ce2d..338c78efe43641686be0d6b3a241865e this.goalSelector.a(3, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F)); this.goalSelector.a(4, new PathfinderGoalRandomLookaround(this)); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 6d64e78e2a06dbc40863b34de6bdb8d019334f7f..c51cca18eb13a0743d9c7748c58a3669d6178216 100644 +index 15dc2dcbb4bec56efd6e069b1848d6c55a3ffa32..3387b3af053cc6a79e89b6273b9121ca2734b81e 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -981,12 +981,20 @@ public class PurpurWorldConfig { diff --git a/patches/server/0141-PaperPR-Config-option-for-Piglins-guarding-chests.patch b/patches/server/0141-PaperPR-Config-option-for-Piglins-guarding-chests.patch index 3f5e7ab55..8e9824b43 100644 --- a/patches/server/0141-PaperPR-Config-option-for-Piglins-guarding-chests.patch +++ b/patches/server/0141-PaperPR-Config-option-for-Piglins-guarding-chests.patch @@ -5,7 +5,7 @@ Subject: [PATCH] PaperPR - Config option for Piglins guarding chests diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index fd675585c61387156892b179af593ad640873d45..9f5edd3285bd477a73e18cfe3af51b441b3eeae1 100644 +index 921253a06daa414aed7dc6824effc65db09ea7a5..319e12c843305e62c34b1b6e2fd198d02491ca12 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -704,6 +704,11 @@ public class PaperWorldConfig { @@ -20,11 +20,11 @@ index fd675585c61387156892b179af593ad640873d45..9f5edd3285bd477a73e18cfe3af51b44 public boolean useEigencraftRedstone = false; private void useEigencraftRedstone() { useEigencraftRedstone = this.getBoolean("use-faster-eigencraft-redstone", false); -diff --git a/src/main/java/net/minecraft/server/PiglinAI.java b/src/main/java/net/minecraft/server/PiglinAI.java -index 0407fa1751d89a037da8cb01f5ceef9b9833dd18..df5aafec9a5844a1ae3e948d8a787051a8903bce 100644 ---- a/src/main/java/net/minecraft/server/PiglinAI.java -+++ b/src/main/java/net/minecraft/server/PiglinAI.java -@@ -357,6 +357,7 @@ public class PiglinAI { +diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAI.java b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAI.java +index 490e749db3fc60a06fbb51347491b1ed29f3eaa0..39451d6d7a5b8cb4a29c6b3a4787979d40144cd9 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAI.java ++++ b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAI.java +@@ -419,6 +419,7 @@ public class PiglinAI { } public static void a(EntityHuman entityhuman, boolean flag) { diff --git a/patches/server/0142-EMC-Configurable-disable-give-dropping.patch b/patches/server/0142-EMC-Configurable-disable-give-dropping.patch index f96044a63..e33114593 100644 --- a/patches/server/0142-EMC-Configurable-disable-give-dropping.patch +++ b/patches/server/0142-EMC-Configurable-disable-give-dropping.patch @@ -7,11 +7,11 @@ Modified version of a patch by Aikar from EMC. Adds a config option in purpur.yml to disable the /give command from dropping items on the floor when a player's inventory is full. -diff --git a/src/main/java/net/minecraft/server/CommandGive.java b/src/main/java/net/minecraft/server/CommandGive.java -index 1d22c45af884a917e77e02c272fcbae74794200c..7bf90f27fdc48440ef229cca0e100d2c5c0ebef7 100644 ---- a/src/main/java/net/minecraft/server/CommandGive.java -+++ b/src/main/java/net/minecraft/server/CommandGive.java -@@ -35,6 +35,7 @@ public class CommandGive { +diff --git a/src/main/java/net/minecraft/server/commands/CommandGive.java b/src/main/java/net/minecraft/server/commands/CommandGive.java +index 6685bf1757458d908e32d4069f7a8a22a28c28d7..82d663d3b8bbbb020c3467ea93b54729c3053f9e 100644 +--- a/src/main/java/net/minecraft/server/commands/CommandGive.java ++++ b/src/main/java/net/minecraft/server/commands/CommandGive.java +@@ -47,6 +47,7 @@ public class CommandGive { boolean flag = entityplayer.inventory.pickup(itemstack); EntityItem entityitem; @@ -20,18 +20,18 @@ index 1d22c45af884a917e77e02c272fcbae74794200c..7bf90f27fdc48440ef229cca0e100d2c itemstack.setCount(1); entityitem = entityplayer.drop(itemstack, false); diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index d25d2e43c2dc3588b98b1d76f84ab10c957f2104..12196850591679cae87575ad25d4d061af65848b 100644 +index b43d6d08d1eb2d77a4c8288d5c5f2a76efcab8db..3836602aba80a1e23bbec451d6948159b10dd24d 100644 --- a/src/main/java/net/pl3x/purpur/PurpurConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java -@@ -191,6 +191,11 @@ public class PurpurConfig { - private static void useAlternateKeepAlive() { +@@ -193,6 +193,11 @@ public class PurpurConfig { useAlternateKeepAlive = getBoolean("settings.use-alternate-keepalive", useAlternateKeepAlive); } -+ + + public static boolean disableGiveCommandDrops = false; + private static void disableGiveCommandDrops() { + disableGiveCommandDrops = getBoolean("settings.disable-give-dropping", disableGiveCommandDrops); + } - ++ public static boolean barrelSixRows = false; public static boolean enderChestSixRows = false; + public static boolean enderChestPermissionRows = false; diff --git a/patches/server/0143-Config-migration-climbing-should-not-bypass-cramming.patch b/patches/server/0143-Config-migration-climbing-should-not-bypass-cramming.patch index 6952ea14d..d563b070e 100644 --- a/patches/server/0143-Config-migration-climbing-should-not-bypass-cramming.patch +++ b/patches/server/0143-Config-migration-climbing-should-not-bypass-cramming.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Config migration: climbing should not bypass cramming diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index 12196850591679cae87575ad25d4d061af65848b..5d75481660d5e11abe263f2a6343b87c75cca090 100644 +index 3836602aba80a1e23bbec451d6948159b10dd24d..322cecf1a7316fb8fe00ff538fe3a2dd21708819 100644 --- a/src/main/java/net/pl3x/purpur/PurpurConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java -@@ -144,6 +144,17 @@ public class PurpurConfig { +@@ -145,6 +145,17 @@ public class PurpurConfig { } } @@ -28,7 +28,7 @@ index 12196850591679cae87575ad25d4d061af65848b..5d75481660d5e11abe263f2a6343b87c public static String afkBroadcastBack = "§e§o%s is no longer AFK"; public static String afkTabListPrefix = "[AFK] "; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index c51cca18eb13a0743d9c7748c58a3669d6178216..4b291b6bd8e74a4affd6a6ea7e1ace50d78ff7eb 100644 +index 3387b3af053cc6a79e89b6273b9121ca2734b81e..5ad9b63e50137163ec7bab48560f618f165d676f 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -96,6 +96,17 @@ public class PurpurWorldConfig { diff --git a/patches/server/0144-Lobotomize-stuck-villagers.patch b/patches/server/0144-Lobotomize-stuck-villagers.patch index 7285fd4d5..17ea4f7c9 100644 --- a/patches/server/0144-Lobotomize-stuck-villagers.patch +++ b/patches/server/0144-Lobotomize-stuck-villagers.patch @@ -4,11 +4,11 @@ Date: Thu, 3 Dec 2020 17:56:18 -0600 Subject: [PATCH] Lobotomize stuck villagers -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 82176fe047f93ccf549deb645568b3ee5dc21b5e..6fa2e0b2ee62212ab315a16803457efc8001d6d0 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -114,7 +114,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 4b4c6477122c51871ce98f34c6e5874048eaa227..904bca540a42204a9856765e333eee6c5de6a960 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -207,7 +207,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne public double lastY; public double lastZ; private Vec3D loc; @@ -17,11 +17,31 @@ index 82176fe047f93ccf549deb645568b3ee5dc21b5e..6fa2e0b2ee62212ab315a16803457efc private Vec3D mot; public float yaw; public float pitch; -diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java -index 00e3ed9374f9962ea619a104892a4c32b2638876..b4719669d5dcfbc34dd37595be403e18184fea4f 100644 ---- a/src/main/java/net/minecraft/server/EntityVillager.java -+++ b/src/main/java/net/minecraft/server/EntityVillager.java -@@ -187,11 +187,32 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java +index 48e6a4c588ef39a4bde067d79b96a656c68750ce..ac7bad10697c6fde7d512753992d59710aa1e032 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java +@@ -123,6 +123,7 @@ public abstract class NavigationAbstract { + } + + @Nullable ++ public PathEntity calculateDestination(BlockPosition blockposition, int i) { return a(blockposition, i); } // Purpur - OBFHELPER + public PathEntity a(BlockPosition blockposition, int i) { + // Paper start - add target parameter + return this.a(blockposition, null, i); +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +index a0f0d5e0909da5cfe87078d4722b030635cfeadd..bc14e242f97f9f6d8e581d12319c95ae5f70f250 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +@@ -89,6 +89,7 @@ import net.minecraft.world.level.IWorldReader; + import net.minecraft.world.level.World; + import net.minecraft.world.level.WorldAccess; + import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.pathfinder.PathEntity; + import net.minecraft.world.phys.AxisAlignedBB; + import org.apache.logging.log4j.Logger; + +@@ -260,11 +261,32 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation private int behaviorTick = 0; @@ -54,7 +74,7 @@ index 00e3ed9374f9962ea619a104892a4c32b2638876..b4719669d5dcfbc34dd37595be403e18 boolean tick = (world.getTime() + brainTickOffset) % world.purpurConfig.villagerBrainTicks == 0; if (((WorldServer) world).getMinecraftServer().lagging ? tick : world.purpurConfig.villagerUseBrainTicksOnlyWhenLagging || tick) // Purpur end -@@ -200,6 +221,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation +@@ -273,6 +295,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error // Paper } } @@ -62,7 +82,7 @@ index 00e3ed9374f9962ea619a104892a4c32b2638876..b4719669d5dcfbc34dd37595be403e18 this.world.getMethodProfiler().exit(); if (this.bF) { this.bF = false; -@@ -331,6 +353,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation +@@ -404,6 +427,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation return true; } @@ -70,7 +90,7 @@ index 00e3ed9374f9962ea619a104892a4c32b2638876..b4719669d5dcfbc34dd37595be403e18 public void fb() { this.fp(); Iterator iterator = this.getOffers().iterator(); -@@ -365,6 +388,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation +@@ -438,6 +462,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation return this.bD == 0 || this.bD < 2 && this.world.getTime() > this.bC + 2400L; } @@ -78,20 +98,8 @@ index 00e3ed9374f9962ea619a104892a4c32b2638876..b4719669d5dcfbc34dd37595be403e18 public boolean fc() { long i = this.bC + 12000L; long j = this.world.getTime(); -diff --git a/src/main/java/net/minecraft/server/NavigationAbstract.java b/src/main/java/net/minecraft/server/NavigationAbstract.java -index be243d411abf68686e75d46023c93fb8bb5c84e0..88368ae1633cf8bfb845d52b38110a6828fcf699 100644 ---- a/src/main/java/net/minecraft/server/NavigationAbstract.java -+++ b/src/main/java/net/minecraft/server/NavigationAbstract.java -@@ -101,6 +101,7 @@ public abstract class NavigationAbstract { - } - - @Nullable -+ public PathEntity calculateDestination(BlockPosition blockposition, int i) { return a(blockposition, i); } // Purpur - OBFHELPER - public PathEntity a(BlockPosition blockposition, int i) { - // Paper start - add target parameter - return this.a(blockposition, null, i); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 4b291b6bd8e74a4affd6a6ea7e1ace50d78ff7eb..dd8c9cd8e45b49bcee4825abb4e30537ef3dafd4 100644 +index 5ad9b63e50137163ec7bab48560f618f165d676f..b2e4404e05ba304423803779321321292b306255 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -1076,6 +1076,8 @@ public class PurpurWorldConfig { diff --git a/patches/server/0145-Option-for-Villager-Clerics-to-farm-Nether-Wart.patch b/patches/server/0145-Option-for-Villager-Clerics-to-farm-Nether-Wart.patch index a1ad3df57..a914db5c2 100644 --- a/patches/server/0145-Option-for-Villager-Clerics-to-farm-Nether-Wart.patch +++ b/patches/server/0145-Option-for-Villager-Clerics-to-farm-Nether-Wart.patch @@ -7,11 +7,39 @@ Adds an option so that Villagers with the Cleric profession are able to farm Nether Wart. Reimplemented based on a feature of the carpet-extra mod. -diff --git a/src/main/java/net/minecraft/server/BehaviorFarm.java b/src/main/java/net/minecraft/server/BehaviorFarm.java -index 0ff202c0d77681f7e0d55d57c69dd0e455336eba..b9c6011c8dcab1a328260871f46d0216bce1818f 100644 ---- a/src/main/java/net/minecraft/server/BehaviorFarm.java -+++ b/src/main/java/net/minecraft/server/BehaviorFarm.java -@@ -12,6 +12,7 @@ public class BehaviorFarm extends Behavior { +diff --git a/src/main/java/net/minecraft/world/IInventory.java b/src/main/java/net/minecraft/world/IInventory.java +index 774ba6a923f7e329f6af5efc17e1c46e87ed2d77..b8c73cd0ba916b7bf166a6d2f6b7ab68cd9c939b 100644 +--- a/src/main/java/net/minecraft/world/IInventory.java ++++ b/src/main/java/net/minecraft/world/IInventory.java +@@ -38,6 +38,7 @@ public interface IInventory extends Clearable { + return true; + } + ++ default int getAmount(Item item) { return this.a(item); } // Purpur - OBFHELPER + default int a(Item item) { + int i = 0; + +@@ -52,6 +53,7 @@ public interface IInventory extends Clearable { + return i; + } + ++ default boolean containsAny(Set itemSet) { return a(itemSet); } // Purpur - OBFHELPER + default boolean a(Set set) { + for (int i = 0; i < this.getSize(); ++i) { + ItemStack itemstack = this.getItem(i); +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFarm.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFarm.java +index 42c70a6c2972ac38e889a6d42fe2d7d4f6017d57..751f2b2f7d0e87212a6bd813d4f85cefd5bb2b50 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFarm.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFarm.java +@@ -21,6 +21,7 @@ import net.minecraft.world.item.Items; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.BlockCrops; ++import net.minecraft.world.level.block.BlockNetherWart; + import net.minecraft.world.level.block.BlockSoil; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.IBlockData; +@@ -32,6 +33,7 @@ public class BehaviorFarm extends Behavior { private long c; private int d; private final List e = Lists.newArrayList(); @@ -19,7 +47,7 @@ index 0ff202c0d77681f7e0d55d57c69dd0e455336eba..b9c6011c8dcab1a328260871f46d0216 public BehaviorFarm() { super(ImmutableMap.of(MemoryModuleType.LOOK_TARGET, MemoryStatus.VALUE_ABSENT, MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT, MemoryModuleType.SECONDARY_JOB_SITE, MemoryStatus.VALUE_PRESENT)); -@@ -20,9 +21,14 @@ public class BehaviorFarm extends Behavior { +@@ -40,9 +42,14 @@ public class BehaviorFarm extends Behavior { protected boolean a(WorldServer worldserver, EntityVillager entityvillager) { if (!worldserver.getGameRules().getBoolean(GameRules.MOB_GRIEFING) && !worldserver.purpurConfig.villagerFarmingBypassMobGriefing) { // Purpur return false; @@ -35,7 +63,7 @@ index 0ff202c0d77681f7e0d55d57c69dd0e455336eba..b9c6011c8dcab1a328260871f46d0216 BlockPosition.MutableBlockPosition blockposition_mutableblockposition = entityvillager.getChunkCoordinates().i(); this.e.clear(); -@@ -53,6 +59,11 @@ public class BehaviorFarm extends Behavior { +@@ -73,6 +80,11 @@ public class BehaviorFarm extends Behavior { Block block = iblockdata.getBlock(); Block block1 = worldserver.getType(blockposition.down()).getBlock(); @@ -47,7 +75,7 @@ index 0ff202c0d77681f7e0d55d57c69dd0e455336eba..b9c6011c8dcab1a328260871f46d0216 return block instanceof BlockCrops && ((BlockCrops) block).isRipe(iblockdata) || iblockdata.isAir() && block1 instanceof BlockSoil; } -@@ -78,7 +89,7 @@ public class BehaviorFarm extends Behavior { +@@ -98,7 +110,7 @@ public class BehaviorFarm extends Behavior { Block block = iblockdata.getBlock(); Block block1 = worldserver.getType(this.farmBlock.down()).getBlock(); @@ -56,7 +84,7 @@ index 0ff202c0d77681f7e0d55d57c69dd0e455336eba..b9c6011c8dcab1a328260871f46d0216 // CraftBukkit start if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entityvillager, this.farmBlock, Blocks.AIR.getBlockData()).isCancelled()) { worldserver.a(this.farmBlock, true, entityvillager); -@@ -86,7 +97,7 @@ public class BehaviorFarm extends Behavior { +@@ -106,7 +118,7 @@ public class BehaviorFarm extends Behavior { // CraftBukkit end } @@ -65,7 +93,7 @@ index 0ff202c0d77681f7e0d55d57c69dd0e455336eba..b9c6011c8dcab1a328260871f46d0216 InventorySubcontainer inventorysubcontainer = entityvillager.getInventory(); for (int j = 0; j < inventorysubcontainer.getSize(); ++j) { -@@ -109,6 +120,12 @@ public class BehaviorFarm extends Behavior { +@@ -129,6 +141,12 @@ public class BehaviorFarm extends Behavior { planted = Blocks.BEETROOTS; flag = true; } @@ -78,7 +106,7 @@ index 0ff202c0d77681f7e0d55d57c69dd0e455336eba..b9c6011c8dcab1a328260871f46d0216 if (planted != null && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entityvillager, this.farmBlock, planted.getBlockData()).isCancelled()) { worldserver.setTypeAndData(this.farmBlock, planted.getBlockData(), 3); -@@ -119,7 +136,7 @@ public class BehaviorFarm extends Behavior { +@@ -139,7 +157,7 @@ public class BehaviorFarm extends Behavior { } if (flag) { @@ -87,11 +115,11 @@ index 0ff202c0d77681f7e0d55d57c69dd0e455336eba..b9c6011c8dcab1a328260871f46d0216 itemstack.subtract(1); if (itemstack.isEmpty()) { inventorysubcontainer.setItem(j, ItemStack.b); -diff --git a/src/main/java/net/minecraft/server/BehaviorTradeVillager.java b/src/main/java/net/minecraft/server/BehaviorTradeVillager.java -index ad26ecd7fe6b6eedc743f2fab687bd0c6a62a46a..6d8b6951c3c07f71dc89131842d815099c62030f 100644 ---- a/src/main/java/net/minecraft/server/BehaviorTradeVillager.java -+++ b/src/main/java/net/minecraft/server/BehaviorTradeVillager.java -@@ -41,6 +41,11 @@ public class BehaviorTradeVillager extends Behavior { +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorTradeVillager.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorTradeVillager.java +index 71ea6c43d76bf1abe6b08dadb20ea4708b0ecfc7..c73b4475182541fa8261bec44f1eeeef21c22f42 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorTradeVillager.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorTradeVillager.java +@@ -53,6 +53,11 @@ public class BehaviorTradeVillager extends Behavior { if (entityvillager1.getVillagerData().getProfession() == VillagerProfession.FARMER && entityvillager.getInventory().a(Items.WHEAT) > Items.WHEAT.getMaxStackSize() / 2) { a(entityvillager, ImmutableSet.of(Items.WHEAT), entityvillager1); } @@ -103,7 +131,7 @@ index ad26ecd7fe6b6eedc743f2fab687bd0c6a62a46a..6d8b6951c3c07f71dc89131842d81509 if (!this.b.isEmpty() && entityvillager.getInventory().a(this.b)) { a(entityvillager, this.b, entityvillager1); -@@ -62,6 +67,7 @@ public class BehaviorTradeVillager extends Behavior { +@@ -74,6 +79,7 @@ public class BehaviorTradeVillager extends Behavior { }).collect(Collectors.toSet()); } @@ -111,11 +139,11 @@ index ad26ecd7fe6b6eedc743f2fab687bd0c6a62a46a..6d8b6951c3c07f71dc89131842d81509 private static void a(EntityVillager entityvillager, Set set, EntityLiving entityliving) { InventorySubcontainer inventorysubcontainer = entityvillager.getInventory(); ItemStack itemstack = ItemStack.b; -diff --git a/src/main/java/net/minecraft/server/Behaviors.java b/src/main/java/net/minecraft/server/Behaviors.java -index 2d91869660c36b4cd7bfe887956a26802cce7f8a..e376306bc2555620d1a61af2296f3dd8abc6ce0e 100644 ---- a/src/main/java/net/minecraft/server/Behaviors.java -+++ b/src/main/java/net/minecraft/server/Behaviors.java -@@ -12,10 +12,13 @@ public class Behaviors { +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/Behaviors.java b/src/main/java/net/minecraft/world/entity/ai/behavior/Behaviors.java +index df12193e1a2e449193a3feab53fc684a2571ae3a..4a8217862a98488ce71ce577b5fa9d6a0f9c898a 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/Behaviors.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/Behaviors.java +@@ -21,10 +21,13 @@ public class Behaviors { return ImmutableList.of(Pair.of(0, new BehaviorSwim(0.8F)), Pair.of(0, new BehaviorInteractDoor()), Pair.of(0, new BehaviorLook(45, 90)), Pair.of(0, new BehaviorPanic()), Pair.of(0, new BehaviorWake()), Pair.of(0, new BehaviorBellAlert()), Pair.of(0, new BehaviorRaid()), Pair.of(0, new BehaviorPositionValidate(villagerprofession.b(), MemoryModuleType.JOB_SITE)), Pair.of(0, new BehaviorPositionValidate(villagerprofession.b(), MemoryModuleType.POTENTIAL_JOB_SITE)), Pair.of(1, new BehavorMove()), Pair.of(2, new BehaviorBetterJob(villagerprofession)), Pair.of(3, new BehaviorInteractPlayer(f)), new Pair[]{Pair.of(5, new BehaviorFindAdmirableItem<>(f, false, 4)), Pair.of(6, new BehaviorFindPosition(villagerprofession.b(), MemoryModuleType.JOB_SITE, MemoryModuleType.POTENTIAL_JOB_SITE, true, Optional.empty())), Pair.of(7, new BehaviorPotentialJobSite(f)), Pair.of(8, new BehaviorLeaveJob(f)), Pair.of(10, new BehaviorFindPosition(VillagePlaceType.r, MemoryModuleType.HOME, false, Optional.of((byte) 14))), Pair.of(10, new BehaviorFindPosition(VillagePlaceType.s, MemoryModuleType.MEETING_POINT, true, Optional.of((byte) 14))), Pair.of(10, new BehaviorCareer()), Pair.of(10, new BehaviorProfession())}); } @@ -132,68 +160,19 @@ index 2d91869660c36b4cd7bfe887956a26802cce7f8a..e376306bc2555620d1a61af2296f3dd8 object = new BehaviorWorkComposter(); } else { object = new BehaviorWork(); -diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java -index b4719669d5dcfbc34dd37595be403e18184fea4f..d2112fb2424f19b2fb65ce635aa0fe24807a311e 100644 ---- a/src/main/java/net/minecraft/server/EntityVillager.java -+++ b/src/main/java/net/minecraft/server/EntityVillager.java -@@ -129,7 +129,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - behaviorcontroller.a(Activity.PLAY, Behaviors.a(0.5F)); - } else { - behaviorcontroller.setSchedule(Schedule.VILLAGER_DEFAULT); -- behaviorcontroller.a(Activity.WORK, Behaviors.b(villagerprofession, 0.5F), (Set) ImmutableSet.of(Pair.of(MemoryModuleType.JOB_SITE, MemoryStatus.VALUE_PRESENT))); -+ behaviorcontroller.a(Activity.WORK, Behaviors.createWorkTask(villagerprofession, 0.5F, this.world.purpurConfig.villagerClericsFarmWarts), (Set) ImmutableSet.of(Pair.of(MemoryModuleType.JOB_SITE, MemoryStatus.VALUE_PRESENT))); // Purpur - } +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorSecondaryPlaces.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorSecondaryPlaces.java +index 25c10973c74f98224dd1d2ae5e7178b9781374aa..78df1ded72a625c676faf4d704e9e44cec2bc054 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorSecondaryPlaces.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorSecondaryPlaces.java +@@ -11,6 +11,7 @@ import net.minecraft.server.level.WorldServer; + import net.minecraft.world.entity.ai.BehaviorController; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + import net.minecraft.world.entity.npc.EntityVillager; ++import net.minecraft.world.entity.npc.VillagerProfession; + import net.minecraft.world.level.World; - behaviorcontroller.a(Activity.CORE, Behaviors.a(villagerprofession, 0.5F)); -@@ -849,6 +849,11 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - @Override - public boolean i(ItemStack itemstack) { - Item item = itemstack.getItem(); -+ // Purpur start -+ if (this.world.purpurConfig.villagerClericsFarmWarts && item.getItem() == Items.NETHER_WART && this.getVillagerData().getProfession() == VillagerProfession.CLERIC) { -+ return true; -+ } -+ // Purpur end - - return (EntityVillager.bs.contains(item) || this.getVillagerData().getProfession().c().contains(item)) && this.getInventory().b(itemstack); - } -@@ -870,6 +875,11 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - } - - public boolean canPlant() { -+ // Purpur start -+ if (this.world.purpurConfig.villagerClericsFarmWarts && this.getVillagerData().getProfession() == VillagerProfession.CLERIC) { -+ return this.getInventory().containsAny(ImmutableSet.of(Items.NETHER_WART)); -+ } -+ // Purpur end - return this.getInventory().a((Set) ImmutableSet.of(Items.WHEAT_SEEDS, Items.POTATO, Items.CARROT, Items.BEETROOT_SEEDS)); - } - -diff --git a/src/main/java/net/minecraft/server/IInventory.java b/src/main/java/net/minecraft/server/IInventory.java -index 317349bf382ee6671066fd5556ee339179165ff0..26094ed0089982ed60e28d7c110884cff793108d 100644 ---- a/src/main/java/net/minecraft/server/IInventory.java -+++ b/src/main/java/net/minecraft/server/IInventory.java -@@ -32,6 +32,7 @@ public interface IInventory extends Clearable { - return true; - } - -+ default int getAmount(Item item) { return this.a(item); } // Purpur - OBFHELPER - default int a(Item item) { - int i = 0; - -@@ -46,6 +47,7 @@ public interface IInventory extends Clearable { - return i; - } - -+ default boolean containsAny(Set itemSet) { return a(itemSet); } // Purpur - OBFHELPER - default boolean a(Set set) { - for (int i = 0; i < this.getSize(); ++i) { - ItemStack itemstack = this.getItem(i); -diff --git a/src/main/java/net/minecraft/server/SensorSecondaryPlaces.java b/src/main/java/net/minecraft/server/SensorSecondaryPlaces.java -index 24173f0d3a6c2c9a4a564de6cd828bdef9afec90..2d8e3e77710b59967b7b18006194d73761df6c56 100644 ---- a/src/main/java/net/minecraft/server/SensorSecondaryPlaces.java -+++ b/src/main/java/net/minecraft/server/SensorSecondaryPlaces.java -@@ -12,6 +12,13 @@ public class SensorSecondaryPlaces extends Sensor { + public class SensorSecondaryPlaces extends Sensor { +@@ -20,6 +21,13 @@ public class SensorSecondaryPlaces extends Sensor { } protected void a(WorldServer worldserver, EntityVillager entityvillager) { @@ -207,7 +186,7 @@ index 24173f0d3a6c2c9a4a564de6cd828bdef9afec90..2d8e3e77710b59967b7b18006194d737 ResourceKey resourcekey = worldserver.getDimensionKey(); BlockPosition blockposition = entityvillager.getChunkCoordinates(); List list = Lists.newArrayList(); -@@ -29,10 +36,10 @@ public class SensorSecondaryPlaces extends Sensor { +@@ -37,10 +45,10 @@ public class SensorSecondaryPlaces extends Sensor { } } @@ -220,11 +199,48 @@ index 24173f0d3a6c2c9a4a564de6cd828bdef9afec90..2d8e3e77710b59967b7b18006194d737 } else { behaviorcontroller.removeMemory(MemoryModuleType.SECONDARY_JOB_SITE); } -diff --git a/src/main/java/net/minecraft/server/VillagerProfession.java b/src/main/java/net/minecraft/server/VillagerProfession.java -index 3c60da7ac6faebe9d964e893974e42613c59b4c1..6493f220a0cf627e82e5f3f3c85e9934d9a9ebae 100644 ---- a/src/main/java/net/minecraft/server/VillagerProfession.java -+++ b/src/main/java/net/minecraft/server/VillagerProfession.java -@@ -9,7 +9,7 @@ public class VillagerProfession { +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +index bc14e242f97f9f6d8e581d12319c95ae5f70f250..77a5be6f5fc51689a74f853b5dfcef5e772e2c84 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +@@ -203,7 +203,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + behaviorcontroller.a(Activity.PLAY, Behaviors.a(0.5F)); + } else { + behaviorcontroller.setSchedule(Schedule.VILLAGER_DEFAULT); +- behaviorcontroller.a(Activity.WORK, Behaviors.b(villagerprofession, 0.5F), (Set) ImmutableSet.of(Pair.of(MemoryModuleType.JOB_SITE, MemoryStatus.VALUE_PRESENT))); ++ behaviorcontroller.a(Activity.WORK, Behaviors.createWorkTask(villagerprofession, 0.5F, this.world.purpurConfig.villagerClericsFarmWarts), (Set) ImmutableSet.of(Pair.of(MemoryModuleType.JOB_SITE, MemoryStatus.VALUE_PRESENT))); // Purpur + } + + behaviorcontroller.a(Activity.CORE, Behaviors.a(villagerprofession, 0.5F)); +@@ -923,6 +923,11 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + @Override + public boolean i(ItemStack itemstack) { + Item item = itemstack.getItem(); ++ // Purpur start ++ if (this.world.purpurConfig.villagerClericsFarmWarts && item.getItem() == Items.NETHER_WART && this.getVillagerData().getProfession() == VillagerProfession.CLERIC) { ++ return true; ++ } ++ // Purpur end + + return (EntityVillager.bs.contains(item) || this.getVillagerData().getProfession().c().contains(item)) && this.getInventory().b(itemstack); + } +@@ -944,6 +949,11 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + } + + public boolean canPlant() { ++ // Purpur start ++ if (this.world.purpurConfig.villagerClericsFarmWarts && this.getVillagerData().getProfession() == VillagerProfession.CLERIC) { ++ return this.getInventory().containsAny(ImmutableSet.of(Items.NETHER_WART)); ++ } ++ // Purpur end + return this.getInventory().a((Set) ImmutableSet.of(Items.WHEAT_SEEDS, Items.POTATO, Items.CARROT, Items.BEETROOT_SEEDS)); + } + +diff --git a/src/main/java/net/minecraft/world/entity/npc/VillagerProfession.java b/src/main/java/net/minecraft/world/entity/npc/VillagerProfession.java +index 69de7588eebba7557cdaec129f19ec1fc2c675c5..dd9b678481620856fb7eaaa04c3b812c861e892a 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/VillagerProfession.java ++++ b/src/main/java/net/minecraft/world/entity/npc/VillagerProfession.java +@@ -18,7 +18,7 @@ public class VillagerProfession { public static final VillagerProfession ARMORER = a("armorer", VillagePlaceType.d, SoundEffects.ENTITY_VILLAGER_WORK_ARMORER); public static final VillagerProfession BUTCHER = a("butcher", VillagePlaceType.e, SoundEffects.ENTITY_VILLAGER_WORK_BUTCHER); public static final VillagerProfession CARTOGRAPHER = a("cartographer", VillagePlaceType.f, SoundEffects.ENTITY_VILLAGER_WORK_CARTOGRAPHER); @@ -234,7 +250,7 @@ index 3c60da7ac6faebe9d964e893974e42613c59b4c1..6493f220a0cf627e82e5f3f3c85e9934 public static final VillagerProfession FISHERMAN = a("fisherman", VillagePlaceType.i, SoundEffects.ENTITY_VILLAGER_WORK_FISHERMAN); public static final VillagerProfession FLETCHER = a("fletcher", VillagePlaceType.j, SoundEffects.ENTITY_VILLAGER_WORK_FLETCHER); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index dd8c9cd8e45b49bcee4825abb4e30537ef3dafd4..12c54e4874d8cd687c1680e9184a3f01fab11b39 100644 +index b2e4404e05ba304423803779321321292b306255..6f0fa3d581fcb1897bc8e591d596a7e1388a667d 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -1078,6 +1078,8 @@ public class PurpurWorldConfig { diff --git a/patches/server/0146-Toggle-for-Zombified-Piglin-death-always-counting-as.patch b/patches/server/0146-Toggle-for-Zombified-Piglin-death-always-counting-as.patch index 75b428a56..17d122d3e 100644 --- a/patches/server/0146-Toggle-for-Zombified-Piglin-death-always-counting-as.patch +++ b/patches/server/0146-Toggle-for-Zombified-Piglin-death-always-counting-as.patch @@ -12,11 +12,11 @@ to the Piglin being angry, even though the player never hit them. This patch adds a toggle to disable this behavior. -diff --git a/src/main/java/net/minecraft/server/EntityPigZombie.java b/src/main/java/net/minecraft/server/EntityPigZombie.java -index 3327dbbf87d8f43cbc7cd728df2f4c6a33dae40d..57f3358b8dfd53f5b1d2e976d64b809f74bc3ce3 100644 ---- a/src/main/java/net/minecraft/server/EntityPigZombie.java -+++ b/src/main/java/net/minecraft/server/EntityPigZombie.java -@@ -95,7 +95,7 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java +index 816a2bd7438f66a5d7ff761b8fcf8b42483561c7..8db9c62093b2f075face65030cb91c24fb6c2dbf 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java +@@ -129,7 +129,7 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { this.eY(); } @@ -25,7 +25,7 @@ index 3327dbbf87d8f43cbc7cd728df2f4c6a33dae40d..57f3358b8dfd53f5b1d2e976d64b809f this.lastDamageByPlayerTime = this.ticksLived; } -@@ -150,7 +150,7 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { +@@ -184,7 +184,7 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { this.bt = EntityPigZombie.bs.a(this.random); } @@ -35,7 +35,7 @@ index 3327dbbf87d8f43cbc7cd728df2f4c6a33dae40d..57f3358b8dfd53f5b1d2e976d64b809f } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 12c54e4874d8cd687c1680e9184a3f01fab11b39..f7ccf7ce209c047dbfe18539fba6a12ca3765c78 100644 +index 6f0fa3d581fcb1897bc8e591d596a7e1388a667d..6c59bd1a0ab69b382b9482d12987828c734dbbb1 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -1210,12 +1210,14 @@ public class PurpurWorldConfig { diff --git a/patches/server/0147-Spread-out-and-optimise-player-list-ticks.patch b/patches/server/0147-Spread-out-and-optimise-player-list-ticks.patch index 6216ea814..a66b41320 100644 --- a/patches/server/0147-Spread-out-and-optimise-player-list-ticks.patch +++ b/patches/server/0147-Spread-out-and-optimise-player-list-ticks.patch @@ -4,11 +4,11 @@ Date: Mon, 7 Dec 2020 17:52:36 +0000 Subject: [PATCH] Spread out and optimise player list ticks -diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java -index f9043744ad0a622c6aa5e5bd3986fb9f60cab4c3..4415d081983d46bcece9b80bad6f3b5cdc624a4e 100644 ---- a/src/main/java/net/minecraft/server/PlayerList.java -+++ b/src/main/java/net/minecraft/server/PlayerList.java -@@ -68,7 +68,7 @@ public abstract class PlayerList { +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 54e009ee763a689125eb521f9144951aac53a4c0..fbc8f7746fc92def73c244b3c12da990741d4bd5 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -150,7 +150,7 @@ public abstract class PlayerList { private int viewDistance; private EnumGamemode u; private boolean v; @@ -17,7 +17,7 @@ index f9043744ad0a622c6aa5e5bd3986fb9f60cab4c3..4415d081983d46bcece9b80bad6f3b5c // CraftBukkit start private CraftServer cserver; -@@ -928,22 +928,23 @@ public abstract class PlayerList { +@@ -1012,22 +1012,23 @@ public abstract class PlayerList { } public void tick() { @@ -56,10 +56,10 @@ index f9043744ad0a622c6aa5e5bd3986fb9f60cab4c3..4415d081983d46bcece9b80bad6f3b5c public void sendAll(Packet packet) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 8bf29aca4b5aa0d51ed3cda25b37d30e6c986848..7b5ffe92430121eebe2866ac33b37a840eed90f1 100644 +index 1ff48eae5e5b732fbd1e720c55e08a30669bebfa..ca465a53a0c6232f912287704fc63cdcc59a28bd 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1435,7 +1435,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1444,7 +1444,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public boolean canSee(Player player) { diff --git a/patches/server/0148-Configurable-chance-for-wolves-to-spawn-rabid.patch b/patches/server/0148-Configurable-chance-for-wolves-to-spawn-rabid.patch index 9ca848339..7151225bf 100644 --- a/patches/server/0148-Configurable-chance-for-wolves-to-spawn-rabid.patch +++ b/patches/server/0148-Configurable-chance-for-wolves-to-spawn-rabid.patch @@ -6,11 +6,11 @@ Subject: [PATCH] Configurable chance for wolves to spawn rabid Configurable chance to spawn a wolf that is rabid. Rabid wolves attack all players, mobs, and animals. -diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index a84150b22adb090309192c21459967a571e86b0a..96e9be81429aa7bf215d2c2cdf865606e3a2707c 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -2104,6 +2104,7 @@ public abstract class EntityLiving extends Entity { +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 617657ff7f27996ed7d97801dc49c9a39f59a240..f3f528065eb9ee2f385edbaceeeddef39552485c 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -2200,6 +2200,7 @@ public abstract class EntityLiving extends Entity { } } @@ -18,11 +18,79 @@ index a84150b22adb090309192c21459967a571e86b0a..96e9be81429aa7bf215d2c2cdf865606 public void a(EnumHand enumhand, ItemStack itemstack) { if (enumhand == EnumHand.MAIN_HAND) { this.setSlot(EnumItemSlot.MAINHAND, itemstack); -diff --git a/src/main/java/net/minecraft/server/EntityWolf.java b/src/main/java/net/minecraft/server/EntityWolf.java -index 6c25f667eecdf345289a0dbf885c9d71c6a26958..5fe2e9f4bfbdc08690eacd6196e59529dc7953e8 100644 ---- a/src/main/java/net/minecraft/server/EntityWolf.java -+++ b/src/main/java/net/minecraft/server/EntityWolf.java -@@ -14,11 +14,42 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalAvoidTarget.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalAvoidTarget.java +index 5115c56487a12f904ff836355375f66a16098790..35502bd2f7d9cebf5cfe1060e300a5032dbe6a5d 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalAvoidTarget.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalAvoidTarget.java +@@ -17,7 +17,7 @@ public class PathfinderGoalAvoidTarget extends Pathfinde + protected final EntityCreature a; + private final double i; + private final double j; +- protected T b; ++ protected T b; protected T getTarget() { return this.b; } // Purpur - OBFHELPER + protected final float c; + protected PathEntity d; + protected final NavigationAbstract e; +@@ -27,12 +27,7 @@ public class PathfinderGoalAvoidTarget extends Pathfinde + private final PathfinderTargetCondition k; + + public PathfinderGoalAvoidTarget(EntityCreature entitycreature, Class oclass, float f, double d0, double d1) { +- Predicate predicate = (entityliving) -> { +- return true; +- }; +- Predicate predicate1 = IEntitySelector.e; +- +- this(entitycreature, oclass, predicate, f, d0, d1, predicate1::test); ++ this(entitycreature, oclass, entityliving -> true, f, d0, d1, IEntitySelector.e::test); // Purpur - decompile fix + } + + public PathfinderGoalAvoidTarget(EntityCreature entitycreature, Class oclass, Predicate predicate, float f, double d0, double d1, Predicate predicate1) { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java b/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java +index dd3c7ad7701ad18ccaf86d73fde7051090ed3d57..e8c6aca70db693250224d1c162e3c2684687ea41 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java +@@ -10,15 +10,19 @@ import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; + import net.minecraft.server.PathfinderGoalHasRider; ++import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.util.IntRange; + import net.minecraft.util.MathHelper; + import net.minecraft.util.TimeRange; ++import net.minecraft.world.DifficultyDamageScaler; + import net.minecraft.world.EnumHand; + import net.minecraft.world.EnumInteractionResult; + import net.minecraft.world.damagesource.DamageSource; ++import net.minecraft.world.effect.MobEffect; ++import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityAgeable; + import net.minecraft.world.entity.EntityInsentient; +@@ -27,9 +31,12 @@ import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySize; + import net.minecraft.world.entity.EntityTameableAnimal; + import net.minecraft.world.entity.EntityTypes; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.IEntityAngerable; + import net.minecraft.world.entity.ai.attributes.AttributeProvider; + import net.minecraft.world.entity.ai.attributes.GenericAttributes; ++import net.minecraft.world.entity.ai.goal.PathfinderGoal; + import net.minecraft.world.entity.ai.goal.PathfinderGoalAvoidTarget; + import net.minecraft.world.entity.ai.goal.PathfinderGoalBeg; + import net.minecraft.world.entity.ai.goal.PathfinderGoalBreed; +@@ -60,6 +67,7 @@ import net.minecraft.world.item.ItemDye; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.World; ++import net.minecraft.world.level.WorldAccess; + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3D; + +@@ -73,11 +81,42 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable private static final DataWatcherObject br = DataWatcher.a(EntityWolf.class, DataWatcherRegistry.i); private static final DataWatcherObject bs = DataWatcher.a(EntityWolf.class, DataWatcherRegistry.b); private static final DataWatcherObject bt = DataWatcher.a(EntityWolf.class, DataWatcherRegistry.b); @@ -66,8 +134,8 @@ index 6c25f667eecdf345289a0dbf885c9d71c6a26958..5fe2e9f4bfbdc08690eacd6196e59529 private float bu; private float bv; private boolean bw; -@@ -53,6 +84,37 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable - int getPurpurBreedTime() { +@@ -112,6 +151,37 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable + public int getPurpurBreedTime() { return this.world.purpurConfig.wolfBreedingTicks; } + @@ -104,7 +172,7 @@ index 6c25f667eecdf345289a0dbf885c9d71c6a26958..5fe2e9f4bfbdc08690eacd6196e59529 // Purpur end @Override -@@ -61,6 +123,7 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable +@@ -120,6 +190,7 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable this.goalSelector.a(1, new PathfinderGoalHasRider(this)); // Purpur this.goalSelector.a(2, new PathfinderGoalSit(this)); this.goalSelector.a(3, new EntityWolf.a<>(this, EntityLlama.class, 24.0F, 1.5D, 1.5D)); @@ -112,7 +180,7 @@ index 6c25f667eecdf345289a0dbf885c9d71c6a26958..5fe2e9f4bfbdc08690eacd6196e59529 this.goalSelector.a(4, new PathfinderGoalLeapAtTarget(this, 0.4F)); this.goalSelector.a(5, new PathfinderGoalMeleeAttack(this, 1.0D, true)); this.goalSelector.a(6, new PathfinderGoalFollowOwner(this, 1.0D, 10.0F, 2.0F, false)); -@@ -74,7 +137,7 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable +@@ -133,7 +204,7 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable this.targetSelector.a(2, new PathfinderGoalOwnerHurtTarget(this)); this.targetSelector.a(3, (new PathfinderGoalHurtByTarget(this, new Class[0])).a(new Class[0])); // CraftBukkit - decompile error this.targetSelector.a(4, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, this::a_)); @@ -121,7 +189,7 @@ index 6c25f667eecdf345289a0dbf885c9d71c6a26958..5fe2e9f4bfbdc08690eacd6196e59529 this.targetSelector.a(6, new PathfinderGoalRandomTargetNonTamed<>(this, EntityTurtle.class, false, EntityTurtle.bo)); this.targetSelector.a(7, new PathfinderGoalNearestAttackableTarget<>(this, EntitySkeletonAbstract.class, false)); this.targetSelector.a(8, new PathfinderGoalUniversalAngerReset<>(this, true)); -@@ -119,6 +182,7 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable +@@ -178,6 +249,7 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable public void saveData(NBTTagCompound nbttagcompound) { super.saveData(nbttagcompound); nbttagcompound.setByte("CollarColor", (byte) this.getCollarColor().getColorIndex()); @@ -129,7 +197,7 @@ index 6c25f667eecdf345289a0dbf885c9d71c6a26958..5fe2e9f4bfbdc08690eacd6196e59529 this.c(nbttagcompound); } -@@ -128,6 +192,10 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable +@@ -187,6 +259,10 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable if (nbttagcompound.hasKeyOfType("CollarColor", 99)) { this.setCollarColor(EnumColor.fromColorIndex(nbttagcompound.getInt("CollarColor"))); } @@ -140,7 +208,7 @@ index 6c25f667eecdf345289a0dbf885c9d71c6a26958..5fe2e9f4bfbdc08690eacd6196e59529 this.a((WorldServer) this.world, nbttagcompound); } -@@ -172,6 +240,11 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable +@@ -231,6 +307,11 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable public void tick() { super.tick(); if (this.isAlive()) { @@ -152,7 +220,7 @@ index 6c25f667eecdf345289a0dbf885c9d71c6a26958..5fe2e9f4bfbdc08690eacd6196e59529 this.bv = this.bu; if (this.eY()) { this.bu += (1.0F - this.bu) * 0.4F; -@@ -343,6 +416,20 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable +@@ -402,6 +483,20 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable return EnumInteractionResult.SUCCESS; } @@ -173,35 +241,8 @@ index 6c25f667eecdf345289a0dbf885c9d71c6a26958..5fe2e9f4bfbdc08690eacd6196e59529 return super.b(entityhuman, enumhand); } -diff --git a/src/main/java/net/minecraft/server/PathfinderGoalAvoidTarget.java b/src/main/java/net/minecraft/server/PathfinderGoalAvoidTarget.java -index 9a4819815c7a4bf2fd4a92c4169ace35f2261704..da29898574d30d5fecc5a44ad7b365564fa686e1 100644 ---- a/src/main/java/net/minecraft/server/PathfinderGoalAvoidTarget.java -+++ b/src/main/java/net/minecraft/server/PathfinderGoalAvoidTarget.java -@@ -8,7 +8,7 @@ public class PathfinderGoalAvoidTarget extends Pathfinde - protected final EntityCreature a; - private final double i; - private final double j; -- protected T b; -+ protected T b; protected T getTarget() { return this.b; } // Purpur - OBFHELPER - protected final float c; - protected PathEntity d; - protected final NavigationAbstract e; -@@ -18,12 +18,7 @@ public class PathfinderGoalAvoidTarget extends Pathfinde - private final PathfinderTargetCondition k; - - public PathfinderGoalAvoidTarget(EntityCreature entitycreature, Class oclass, float f, double d0, double d1) { -- Predicate predicate = (entityliving) -> { -- return true; -- }; -- Predicate predicate1 = IEntitySelector.e; -- -- this(entitycreature, oclass, predicate, f, d0, d1, predicate1::test); -+ this(entitycreature, oclass, entityliving -> true, f, d0, d1, IEntitySelector.e::test); // Purpur - decompile fix - } - - public PathfinderGoalAvoidTarget(EntityCreature entitycreature, Class oclass, Predicate predicate, float f, double d0, double d1, Predicate predicate1) { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index f7ccf7ce209c047dbfe18539fba6a12ca3765c78..aea3e3ae09d2df797d284104eafb957e8f11a109 100644 +index 6c59bd1a0ab69b382b9482d12987828c734dbbb1..ecedeb10196b05f0d919f744cdf2e9556eff0a8d 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -1161,10 +1161,14 @@ public class PurpurWorldConfig { @@ -220,7 +261,7 @@ index f7ccf7ce209c047dbfe18539fba6a12ca3765c78..aea3e3ae09d2df797d284104eafb957e } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java -index 5f3314febb2300a9b4f3a7c143cb65811e1d5320..507857ba247d0988e0011d215ea38a3622e78e05 100644 +index dc5ba91ebdef25d633205a65148b62f1853b4da5..71e5b36b7d0bb92ef6e94759318a4a82a19e729a 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java @@ -45,4 +45,16 @@ public class CraftWolf extends CraftTameableAnimal implements Wolf { diff --git a/patches/server/0149-Configurable-default-wolf-collar-color.patch b/patches/server/0149-Configurable-default-wolf-collar-color.patch index 121be503d..68ba28357 100644 --- a/patches/server/0149-Configurable-default-wolf-collar-color.patch +++ b/patches/server/0149-Configurable-default-wolf-collar-color.patch @@ -6,11 +6,11 @@ Subject: [PATCH] Configurable default wolf collar color This allows for the server to set a default collar color when a wolf is tamed. Resets to RED when the value is invalid. -diff --git a/src/main/java/net/minecraft/server/EntityWolf.java b/src/main/java/net/minecraft/server/EntityWolf.java -index 5fe2e9f4bfbdc08690eacd6196e59529dc7953e8..fd62dc51258876275adbe02f750fd88107c38a6b 100644 ---- a/src/main/java/net/minecraft/server/EntityWolf.java -+++ b/src/main/java/net/minecraft/server/EntityWolf.java -@@ -115,6 +115,12 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java b/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java +index e8c6aca70db693250224d1c162e3c2684687ea41..e33aadead6e6c5e0a7b39ef95e7aeb0f0092a94e 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java +@@ -182,6 +182,12 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable this.updatePathfinders(false); return super.prepare(worldaccess, difficultydamagescaler, enummobspawn, groupdataentity, nbttagcompound); } @@ -24,17 +24,17 @@ index 5fe2e9f4bfbdc08690eacd6196e59529dc7953e8..fd62dc51258876275adbe02f750fd881 @Override diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index aea3e3ae09d2df797d284104eafb957e8f11a109..3790fcea3a556a979eacaf5b03e5ebc4c3a02925 100644 +index ecedeb10196b05f0d919f744cdf2e9556eff0a8d..5c5aa1ab859c836945294cfdb06589639006a307 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -3,6 +3,7 @@ package net.pl3x.purpur; import com.destroystokyo.paper.PaperConfig; - import net.minecraft.server.Block; - import net.minecraft.server.Blocks; -+import net.minecraft.server.EnumColor; - import net.minecraft.server.EnumDifficulty; - import net.minecraft.server.Explosion; - import net.minecraft.server.IRegistry; + import net.minecraft.core.IRegistry; + import net.minecraft.world.EnumDifficulty; ++import net.minecraft.world.item.EnumColor; + import net.minecraft.world.level.Explosion; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; @@ -1161,12 +1162,18 @@ public class PurpurWorldConfig { public boolean wolfRidable = false; diff --git a/patches/server/0150-Configurable-entity-base-attributes.patch b/patches/server/0150-Configurable-entity-base-attributes.patch index c8848d0f9..25f358c7c 100644 --- a/patches/server/0150-Configurable-entity-base-attributes.patch +++ b/patches/server/0150-Configurable-entity-base-attributes.patch @@ -4,11 +4,11 @@ Date: Thu, 10 Dec 2020 16:44:54 -0600 Subject: [PATCH] Configurable entity base attributes -diff --git a/src/main/java/net/minecraft/server/EntityBat.java b/src/main/java/net/minecraft/server/EntityBat.java -index 7a18c59689b84fa277709ad11c39a72d77df4afb..da4ce323b9a2e0de0d1ed242f102a1601c6891d2 100644 ---- a/src/main/java/net/minecraft/server/EntityBat.java -+++ b/src/main/java/net/minecraft/server/EntityBat.java -@@ -55,6 +55,18 @@ public class EntityBat extends EntityAmbient { +diff --git a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java +index eed98fd7e84b4f390b8b356258f5011da561a343..88a0d51f78bee9a1b0762b46db4d91a9f8f8c75d 100644 +--- a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java ++++ b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java +@@ -82,6 +82,18 @@ public class EntityBat extends EntityAmbient { setMot(mot.a(0.9D)); } } @@ -27,12 +27,12 @@ index 7a18c59689b84fa277709ad11c39a72d77df4afb..da4ce323b9a2e0de0d1ed242f102a160 // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityBee.java b/src/main/java/net/minecraft/server/EntityBee.java -index ded4e10f5082fb5aa25368d9035affba287c3345..bef806bfc60792a990209b57f3cd4b9da0c24acc 100644 ---- a/src/main/java/net/minecraft/server/EntityBee.java -+++ b/src/main/java/net/minecraft/server/EntityBee.java -@@ -105,6 +105,11 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - int getPurpurBreedTime() { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java +index 9e40fd6585592ccd1deff1d8319c57660474c053..c39a7a6d7f391debd632a199eeec8ded6189ad76 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java +@@ -181,6 +181,11 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB + public int getPurpurBreedTime() { return this.world.purpurConfig.beeBreedingTicks; } + @@ -43,28 +43,12 @@ index ded4e10f5082fb5aa25368d9035affba287c3345..bef806bfc60792a990209b57f3cd4b9d // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityBlaze.java b/src/main/java/net/minecraft/server/EntityBlaze.java -index dcfad16e06450068d5801fc002c9650102dbf995..90b90fa33b39020189a1d4a5826fa3ab720488cd 100644 ---- a/src/main/java/net/minecraft/server/EntityBlaze.java -+++ b/src/main/java/net/minecraft/server/EntityBlaze.java -@@ -45,6 +45,11 @@ public class EntityBlaze extends EntityMonster { - setMot(mot.a(0.9D)); - } - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.blazeMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityCat.java b/src/main/java/net/minecraft/server/EntityCat.java -index 437a7b8ffb40c461f1778d91591fa6c4dcf36834..f973408b1f098c8a090401205f809e95fdcf2f62 100644 ---- a/src/main/java/net/minecraft/server/EntityCat.java -+++ b/src/main/java/net/minecraft/server/EntityCat.java -@@ -63,6 +63,11 @@ public class EntityCat extends EntityTameableAnimal { - int getPurpurBreedTime() { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCat.java b/src/main/java/net/minecraft/world/entity/animal/EntityCat.java +index 079b95ef465f7155f426a2c87a4a50f8369d0a18..7143b0801be7877762e41da336ea5e4e57f2e463 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityCat.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityCat.java +@@ -127,6 +127,11 @@ public class EntityCat extends EntityTameableAnimal { + public int getPurpurBreedTime() { return this.world.purpurConfig.catBreedingTicks; } + @@ -75,27 +59,11 @@ index 437a7b8ffb40c461f1778d91591fa6c4dcf36834..f973408b1f098c8a090401205f809e95 // Purpur end public MinecraftKey eU() { -diff --git a/src/main/java/net/minecraft/server/EntityCaveSpider.java b/src/main/java/net/minecraft/server/EntityCaveSpider.java -index 2e1f2dec17e7761b6534f29bbec813d135250e4f..adbd665d455dfc1672a5bdf1b3b380d535835cd7 100644 ---- a/src/main/java/net/minecraft/server/EntityCaveSpider.java -+++ b/src/main/java/net/minecraft/server/EntityCaveSpider.java -@@ -18,6 +18,11 @@ public class EntityCaveSpider extends EntitySpider { - public boolean isRidableInWater() { - return world.purpurConfig.caveSpiderRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.caveSpiderMaxHealth); -+ } - // Purpur end - - public static AttributeProvider.Builder m() { -diff --git a/src/main/java/net/minecraft/server/EntityChicken.java b/src/main/java/net/minecraft/server/EntityChicken.java -index 2e1dc047459889aea85a79eaa04e8fe1a80e5b9e..18aed81061a4033627214a65d38cd9509ed0f8e9 100644 ---- a/src/main/java/net/minecraft/server/EntityChicken.java -+++ b/src/main/java/net/minecraft/server/EntityChicken.java -@@ -33,6 +33,7 @@ public class EntityChicken extends EntityAnimal { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java b/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java +index ab54e809f735cea7d84366d2bc205351f8992bef..51fd3d955c866cc09bb09abe1b6d23caad2d7e85 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java +@@ -70,6 +70,7 @@ public class EntityChicken extends EntityAnimal { if (world.purpurConfig.chickenRetaliate) { this.getAttributeInstance(GenericAttributes.ATTACK_DAMAGE).setValue(2.0D); } @@ -103,11 +71,19 @@ index 2e1dc047459889aea85a79eaa04e8fe1a80e5b9e..18aed81061a4033627214a65d38cd950 } @Override -diff --git a/src/main/java/net/minecraft/server/EntityCod.java b/src/main/java/net/minecraft/server/EntityCod.java -index 039fae4c29648afa85ea1b27d82cfe51c4165315..024a5ffa878d6e6749c1dd95e94ec6d65cf1d629 100644 ---- a/src/main/java/net/minecraft/server/EntityCod.java -+++ b/src/main/java/net/minecraft/server/EntityCod.java -@@ -16,6 +16,11 @@ public class EntityCod extends EntityFishSchool { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCod.java b/src/main/java/net/minecraft/world/entity/animal/EntityCod.java +index 897e0d5ca44a0c475634f08e7d4fcf129ee197ab..07c6dc6a1b9af7b9662f4dd4b4a2ddfcbe600c34 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityCod.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityCod.java +@@ -4,6 +4,7 @@ import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.EntityTypes; ++import net.minecraft.world.entity.ai.attributes.GenericAttributes; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.World; +@@ -24,6 +25,11 @@ public class EntityCod extends EntityFishSchool { public boolean isRidableInWater() { return true; } @@ -119,12 +95,12 @@ index 039fae4c29648afa85ea1b27d82cfe51c4165315..024a5ffa878d6e6749c1dd95e94ec6d6 // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityCow.java b/src/main/java/net/minecraft/server/EntityCow.java -index 63497ca0266073dc0a16b7dc22641d08c3eaf400..951531d65709ee3064371cbf4b3a9831a47b12aa 100644 ---- a/src/main/java/net/minecraft/server/EntityCow.java -+++ b/src/main/java/net/minecraft/server/EntityCow.java -@@ -26,6 +26,11 @@ public class EntityCow extends EntityAnimal { - int getPurpurBreedTime() { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCow.java b/src/main/java/net/minecraft/world/entity/animal/EntityCow.java +index 93589a2b86e6663d93f6b536b853996c08db549a..2a8c0537fbb68577a3da3f8d07c16e9ca18b224d 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityCow.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityCow.java +@@ -59,6 +59,11 @@ public class EntityCow extends EntityAnimal { + public int getPurpurBreedTime() { return this.world.purpurConfig.cowBreedingTicks; } + @@ -135,27 +111,11 @@ index 63497ca0266073dc0a16b7dc22641d08c3eaf400..951531d65709ee3064371cbf4b3a9831 // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityCreeper.java b/src/main/java/net/minecraft/server/EntityCreeper.java -index 7e5ede0f644a6e303be36ab0915d346a02760daa..523988bcc0607198dfb73afca5932ed6dd82cca1 100644 ---- a/src/main/java/net/minecraft/server/EntityCreeper.java -+++ b/src/main/java/net/minecraft/server/EntityCreeper.java -@@ -97,6 +97,11 @@ public class EntityCreeper extends EntityMonster { - } - return getForward() == 0 && getStrafe() == 0; // do not jump if standing still - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.creeperMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityDolphin.java b/src/main/java/net/minecraft/server/EntityDolphin.java -index 9d5d143a997b74e0777bb79bf14d341ad5340db9..82021ba825d6a36191174acf83d109a5c74f6db8 100644 ---- a/src/main/java/net/minecraft/server/EntityDolphin.java -+++ b/src/main/java/net/minecraft/server/EntityDolphin.java -@@ -63,6 +63,11 @@ public class EntityDolphin extends EntityWaterAnimal { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java b/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java +index 880c3aaf4e684209879dc921480619e7c61ee4a0..6b32b3e4877efa64942838a07af5d48cd4e33a80 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java +@@ -128,6 +128,11 @@ public class EntityDolphin extends EntityWaterAnimal { } return false; } @@ -167,96 +127,12 @@ index 9d5d143a997b74e0777bb79bf14d341ad5340db9..82021ba825d6a36191174acf83d109a5 // Purpur end @Nullable -diff --git a/src/main/java/net/minecraft/server/EntityDrowned.java b/src/main/java/net/minecraft/server/EntityDrowned.java -index 638efc67d66001ee085957d4698f51a7daac77fc..a766910663e47b05d1e38908b5db7471199993c7 100644 ---- a/src/main/java/net/minecraft/server/EntityDrowned.java -+++ b/src/main/java/net/minecraft/server/EntityDrowned.java -@@ -46,6 +46,15 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { - public boolean jockeyTryExistingChickens() { - return world.purpurConfig.drownedJockeyTryExistingChickens; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.drownedMaxHealth); -+ } -+ -+ protected void generateReinforcementsChance() { -+ this.getAttributeInstance(GenericAttributes.SPAWN_REINFORCEMENTS).setValue(this.random.nextDouble() * this.world.purpurConfig.drownedSpawnReinforcements); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityEnderDragon.java b/src/main/java/net/minecraft/server/EntityEnderDragon.java -index 81e63fe1b8252e2b5abcbf9051190cd0214b534c..75e834caaf7bb64a3d51d793e86aa702f6ccb0ae 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/server/EntityEnderDragon.java -@@ -97,6 +97,11 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - public double getMaxY() { - return world.purpurConfig.enderDragonMaxY; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.enderDragonMaxHealth); -+ } - // Purpur end - - public static AttributeProvider.Builder m() { -diff --git a/src/main/java/net/minecraft/server/EntityEnderman.java b/src/main/java/net/minecraft/server/EntityEnderman.java -index 0a9bd0dbd2f90aa968db0f8a14cde7e58d18652e..c03232ac1e2b450b64430f8d56bfebd30fa37155 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderman.java -+++ b/src/main/java/net/minecraft/server/EntityEnderman.java -@@ -40,6 +40,11 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - public boolean isRidableInWater() { - return world.purpurConfig.endermanRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.endermanMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityEndermite.java b/src/main/java/net/minecraft/server/EntityEndermite.java -index 7eef7f523a17434b38492006526920a955fc9120..3f34ebc1c4ac6f6f0b883c3e4c768007c24fc194 100644 ---- a/src/main/java/net/minecraft/server/EntityEndermite.java -+++ b/src/main/java/net/minecraft/server/EntityEndermite.java -@@ -22,6 +22,11 @@ public class EntityEndermite extends EntityMonster { - public boolean isRidableInWater() { - return world.purpurConfig.endermiteRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.endermiteMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityEvoker.java b/src/main/java/net/minecraft/server/EntityEvoker.java -index c75dc75611991028e9de6db7c57304e913251a6b..f0ecc6e6ef5843714a6423af5d6619856ef23977 100644 ---- a/src/main/java/net/minecraft/server/EntityEvoker.java -+++ b/src/main/java/net/minecraft/server/EntityEvoker.java -@@ -22,6 +22,11 @@ public class EntityEvoker extends EntityIllagerWizard { - public boolean isRidableInWater() { - return world.purpurConfig.evokerRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.evokerMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityFox.java b/src/main/java/net/minecraft/server/EntityFox.java -index b5f036af81ddd3c1b0e388a28383f0b6a63d128c..7a3fb7a41e987adee675fbfd11f2648cf5de3e53 100644 ---- a/src/main/java/net/minecraft/server/EntityFox.java -+++ b/src/main/java/net/minecraft/server/EntityFox.java -@@ -91,6 +91,11 @@ public class EntityFox extends EntityAnimal { - int getPurpurBreedTime() { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java +index 7bf546a1b2a80179962ed08a35d86f0a28eda3c2..b8b0ee65798dc94d707fa64bd53fdda5506331d9 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java +@@ -164,6 +164,11 @@ public class EntityFox extends EntityAnimal { + public int getPurpurBreedTime() { return this.world.purpurConfig.foxBreedingTicks; } + @@ -267,76 +143,324 @@ index b5f036af81ddd3c1b0e388a28383f0b6a63d128c..7a3fb7a41e987adee675fbfd11f2648c // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityGhast.java b/src/main/java/net/minecraft/server/EntityGhast.java -index 216506a7b1f97b776ecd4e24f5b2afaf5b79ec2d..2c0148229283f95bed3c8f33cc02a31d6f682191 100644 ---- a/src/main/java/net/minecraft/server/EntityGhast.java -+++ b/src/main/java/net/minecraft/server/EntityGhast.java -@@ -41,6 +41,11 @@ public class EntityGhast extends EntityFlying implements IMonster { - setMot(mot.a(0.9D)); +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java b/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java +index 23e614f0c3cf1178acff8e72e0441c42c658e76b..9ee82c908008190e31034e614c241fc7a66248e1 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java +@@ -80,6 +80,11 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable { + public boolean isRidableInWater() { + return world.purpurConfig.ironGolemRidableInWater; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.ironGolemMaxHealth); ++ } + // Purpur end + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java b/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java +index ab4a8ee6e1912f230cbf3353eb42c3bc8a9db58e..4b7e21a611d87410805722c30c9ee77212b33348 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java +@@ -24,6 +24,7 @@ import net.minecraft.world.entity.EntityLightning; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.IShearable; ++import net.minecraft.world.entity.ai.attributes.GenericAttributes; + import net.minecraft.world.entity.item.EntityItem; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.Item; +@@ -72,6 +73,11 @@ public class EntityMushroomCow extends EntityCow implements IShearable { + public int getPurpurBreedTime() { + return this.world.purpurConfig.mooshroomBreedingTicks; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.mooshroomMaxHealth); ++ } + // Purpur end + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java b/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java +index cff2ff5a8beef739f0515832e072e7e390ac388f..12534673afe0b05868a5f400c9e59c22dfcf12d6 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java +@@ -79,6 +79,11 @@ public class EntityOcelot extends EntityAnimal { + public int getPurpurBreedTime() { + return this.world.purpurConfig.ocelotBreedingTicks; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.ocelotMaxHealth); ++ } + // Purpur end + + private boolean isTrusting() { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java b/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java +index e6952c0a8d90eb4b133c517d97299f2c3db7e329..94141b8c1ad62e6d187726734d25dd0ee5535618 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java +@@ -34,6 +34,7 @@ import net.minecraft.world.entity.EnumItemSlot; + import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.IEntitySelector; ++import net.minecraft.world.entity.ai.attributes.AttributeModifiable; + import net.minecraft.world.entity.ai.attributes.AttributeProvider; + import net.minecraft.world.entity.ai.attributes.GenericAttributes; + import net.minecraft.world.entity.ai.control.ControllerMove; +@@ -126,6 +127,12 @@ public class EntityPanda extends EntityAnimal { + public int getPurpurBreedTime() { + return this.world.purpurConfig.pandaBreedingTicks; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.pandaMaxHealth); ++ updateAttributes(); ++ } + // Purpur end + + @Override +@@ -598,9 +605,12 @@ public class EntityPanda extends EntityAnimal { + return this.random.nextBoolean() ? this.getMainGene() : this.getHiddenGene(); + } + +- public void fg() { ++ public void fg() { updateAttributes(); } public void updateAttributes() { // Purpur - OBFHELPER + if (this.isWeak()) { +- this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(10.0D); ++ // Purpur start ++ AttributeModifiable maxHealth = this.getAttributeInstance(GenericAttributes.MAX_HEALTH); ++ maxHealth.setValue(maxHealth.getValue() / 2); ++ // Purpur end } + + if (this.isLazy()) { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java +index 5463e1779422ff19499727a000fdfbbfc38809a8..efa4318989893c946e9d7671d0dead6c4a6e315f 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java +@@ -176,6 +176,11 @@ public class EntityParrot extends EntityPerchable implements EntityBird { + public int getPurpurBreedTime() { + return 6000; } + + @Override + public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.ghastMaxHealth); ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.parrotMaxHealth); ++ } + // Purpur end + + @Nullable +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java +index 5aa8806063186bec36b38adc51e2ea82bf6ff21a..8d24855f230a5ca6280f885d5b1c26ecf5b91395 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java +@@ -82,6 +82,11 @@ public class EntityPig extends EntityAnimal implements ISteerable, ISaddleable { + public int getPurpurBreedTime() { + return this.world.purpurConfig.pigBreedingTicks; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.pigMaxHealth); + } // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityGuardian.java b/src/main/java/net/minecraft/server/EntityGuardian.java -index 0a7f51a2a1cb10438c9364faf3e4adc6322fc787..476f692df79e98779271cc5a395276ab9c755a58 100644 ---- a/src/main/java/net/minecraft/server/EntityGuardian.java -+++ b/src/main/java/net/minecraft/server/EntityGuardian.java -@@ -46,6 +46,11 @@ public class EntityGuardian extends EntityMonster { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java b/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java +index 2306abb72ea76a52fd6f27648c4815ad99f8f005..5a496d55b40f98609b0a9aac25929f6b5c0311ba 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java +@@ -121,6 +121,11 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { + public int getPurpurBreedTime() { + return this.world.purpurConfig.polarBearBreedingTicks; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.polarBearMaxHealth); ++ } + // Purpur end + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java b/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java +index 38fe79872b4b7f4ad4a030fbdf505efbc0352fc0..0d32590cf4cfdd95da6aceac5190d42c8e966ce7 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java +@@ -20,6 +20,7 @@ import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySize; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.EnumMonsterType; ++import net.minecraft.world.entity.ai.attributes.GenericAttributes; + import net.minecraft.world.entity.ai.goal.PathfinderGoal; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.ItemStack; +@@ -49,6 +50,11 @@ public class EntityPufferFish extends EntityFish { public boolean isRidableInWater() { return true; } + + @Override + public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.guardianMaxHealth); ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.pufferfishMaxHealth); + } // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityGuardianElder.java b/src/main/java/net/minecraft/server/EntityGuardianElder.java -index f6f882746940c9e049106aa9b41591ba27a608ce..7afba8136f9a809e779d9af8c93cda7c0765c095 100644 ---- a/src/main/java/net/minecraft/server/EntityGuardianElder.java -+++ b/src/main/java/net/minecraft/server/EntityGuardianElder.java -@@ -26,6 +26,11 @@ public class EntityGuardianElder extends EntityGuardian { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java b/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java +index 0b706404895b69fbca79502a327ec20b47ed99f0..284c52276b2fd816990c23b7b8a9ee50e70ab005 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java +@@ -91,6 +91,11 @@ public class EntityRabbit extends EntityAnimal { + public int getPurpurBreedTime() { + return this.world.purpurConfig.rabbitBreedingTicks; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.rabbitMaxHealth); ++ } + // Purpur end + + // CraftBukkit start - code from constructor +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySalmon.java b/src/main/java/net/minecraft/world/entity/animal/EntitySalmon.java +index bf565671c167162b3d935447961f0d44ed4a2779..36e60360193cb0cfd8fef03f964e0fa90002f8bc 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntitySalmon.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntitySalmon.java +@@ -4,6 +4,7 @@ import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.EntityTypes; ++import net.minecraft.world.entity.ai.attributes.GenericAttributes; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.World; +@@ -24,6 +25,11 @@ public class EntitySalmon extends EntityFishSchool { public boolean isRidableInWater() { return true; } + + @Override + public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.elderGuardianMaxHealth); -+ } - // Purpur end - - public static AttributeProvider.Builder m() { -diff --git a/src/main/java/net/minecraft/server/EntityHoglin.java b/src/main/java/net/minecraft/server/EntityHoglin.java -index 96cad9471d316e26b5daa9d217e172efcc77e0cc..f669fe47801cf21624ba4be3ad86ebc7ab66cf98 100644 ---- a/src/main/java/net/minecraft/server/EntityHoglin.java -+++ b/src/main/java/net/minecraft/server/EntityHoglin.java -@@ -35,6 +35,11 @@ public class EntityHoglin extends EntityAnimal implements IMonster, IOglin { - int getPurpurBreedTime() { - return this.world.purpurConfig.hoglinBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.hoglinMaxHealth); ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.salmonMaxHealth); + } // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityHorse.java b/src/main/java/net/minecraft/server/EntityHorse.java -index 669bce5d9806c80bddc247fe103ff20dc6aaa8a5..e78e89d187f923239f23e37d5141e2e69b056360 100644 ---- a/src/main/java/net/minecraft/server/EntityHorse.java -+++ b/src/main/java/net/minecraft/server/EntityHorse.java -@@ -22,6 +22,21 @@ public class EntityHorse extends EntityHorseAbstract { - int getPurpurBreedTime() { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java b/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java +index ff6fc821085e4430a3b1008140b0b7fcacc59d2e..365f70117a287fab2fbf63ee8d89a10ac70b2f1b 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java +@@ -126,6 +126,11 @@ public class EntitySheep extends EntityAnimal implements IShearable { + public int getPurpurBreedTime() { + return this.world.purpurConfig.sheepBreedingTicks; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.sheepMaxHealth); ++ } + // Purpur end + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java b/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java +index 28b5c22ecfe573ac9d91b74e54ebd3e3c5e6373f..88db8ff8cb415b84ab98cc0550c705d5a472230c 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java +@@ -61,6 +61,11 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt + public boolean isRidableInWater() { + return world.purpurConfig.snowGolemRidableInWater; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.snowGolemMaxHealth); ++ } + // Purpur end + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java +index 07b1db0e1fff1beffe464a3984716d5d84ea1873..2d2a3fc083bff18cdf50b1ef49b198f8253987ec 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java +@@ -85,6 +85,11 @@ public class EntitySquid extends EntityWaterAnimal { + public boolean isInWater() { + return this.inWater || world.purpurConfig.squidsCanFly; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.squidMaxHealth); ++ } + // Purpur end + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTropicalFish.java b/src/main/java/net/minecraft/world/entity/animal/EntityTropicalFish.java +index 478e55475ccc1410a442f4e30a1cbc08f479dbda..7d0982b8756b9e6c12cf4acae765ff651b846250 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityTropicalFish.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityTropicalFish.java +@@ -14,6 +14,7 @@ import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.GroupDataEntity; ++import net.minecraft.world.entity.ai.attributes.GenericAttributes; + import net.minecraft.world.item.EnumColor; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +@@ -47,6 +48,11 @@ public class EntityTropicalFish extends EntityFishSchool { + public boolean isRidableInWater() { + return true; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.tropicalFishMaxHealth); ++ } + // Purpur end + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java +index a16f586934f24e599d00bf793f06d3f9134ed29d..2da43c75c5767973c43e42af37c0d0d9d3a27859 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java +@@ -106,6 +106,11 @@ public class EntityTurtle extends EntityAnimal { + public int getPurpurBreedTime() { + return this.world.purpurConfig.turtleBreedingTicks; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.turtleMaxHealth); ++ } + // Purpur end + + public void setHomePos(BlockPosition blockposition) { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java b/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java +index e33aadead6e6c5e0a7b39ef95e7aeb0f0092a94e..090903fbc8f6cd1522c7afb358f708f5ae3395f4 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java +@@ -188,6 +188,11 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable + setCollarColor(world.purpurConfig.wolfDefaultCollarColor); + super.tame(entityhuman); + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.wolfMaxHealth); ++ } + // Purpur end + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java +index c830bf6e5e38f5ebacc07673c3d67e4157c8c2b5..c6e39fe54cc402869b2e9eaea1830ba1ccc9ffc1 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java +@@ -51,6 +51,21 @@ public class EntityHorse extends EntityHorseAbstract { + public int getPurpurBreedTime() { return this.world.purpurConfig.horseBreedingTicks; } + @@ -357,11 +481,11 @@ index 669bce5d9806c80bddc247fe103ff20dc6aaa8a5..e78e89d187f923239f23e37d5141e2e6 // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityHorseAbstract.java b/src/main/java/net/minecraft/server/EntityHorseAbstract.java -index 8fde406273bbea0b9d2dea2362cf6372b7a5c9ae..2bed0a08eaad5fee5d5e85ba6cb3d3e8e1be1c2c 100644 ---- a/src/main/java/net/minecraft/server/EntityHorseAbstract.java -+++ b/src/main/java/net/minecraft/server/EntityHorseAbstract.java -@@ -56,6 +56,32 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java +index d4556fa190c754406d0c65baae941fb23af3f81f..1d938f324bc08c05b44c72b5a2927016ed599cf2 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java +@@ -120,6 +120,32 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven public boolean isRidableInWater() { return false; } @@ -394,7 +518,7 @@ index 8fde406273bbea0b9d2dea2362cf6372b7a5c9ae..2bed0a08eaad5fee5d5e85ba6cb3d3e8 // Purpur end @Override -@@ -864,15 +890,15 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven +@@ -928,15 +954,15 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven } @@ -413,7 +537,7 @@ index 8fde406273bbea0b9d2dea2362cf6372b7a5c9ae..2bed0a08eaad5fee5d5e85ba6cb3d3e8 return (0.44999998807907104D + this.random.nextDouble() * 0.3D + this.random.nextDouble() * 0.3D + this.random.nextDouble() * 0.3D) * 0.25D; } -@@ -995,7 +1021,7 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven +@@ -1059,7 +1085,7 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven groupdataentity = new EntityAgeable.a(0.2F); } @@ -422,12 +546,12 @@ index 8fde406273bbea0b9d2dea2362cf6372b7a5c9ae..2bed0a08eaad5fee5d5e85ba6cb3d3e8 return super.prepare(worldaccess, difficultydamagescaler, enummobspawn, (GroupDataEntity) groupdataentity, nbttagcompound); } } -diff --git a/src/main/java/net/minecraft/server/EntityHorseDonkey.java b/src/main/java/net/minecraft/server/EntityHorseDonkey.java -index f6421bb45c5e6adf39fdc085efe2b2f500b76c0c..5b7c0e9c6cce440ed54a97803a4275eea497935a 100644 ---- a/src/main/java/net/minecraft/server/EntityHorseDonkey.java -+++ b/src/main/java/net/minecraft/server/EntityHorseDonkey.java -@@ -18,6 +18,21 @@ public class EntityHorseDonkey extends EntityHorseChestedAbstract { - int getPurpurBreedTime() { +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java +index 3b44394dcba8e9905aca46e6e585ee6d7a87de44..589986b36c12dd2774a87e1d22aafd6d3052f123 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java +@@ -26,6 +26,21 @@ public class EntityHorseDonkey extends EntityHorseChestedAbstract { + public int getPurpurBreedTime() { return this.world.purpurConfig.donkeyBreedingTicks; } + @@ -448,12 +572,12 @@ index f6421bb45c5e6adf39fdc085efe2b2f500b76c0c..5b7c0e9c6cce440ed54a97803a4275ee // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityHorseMule.java b/src/main/java/net/minecraft/server/EntityHorseMule.java -index 30cbc505d2b0f4d3247edfd271de8daab023eb2a..a32c5347e4d77f5641e4eb3ea4a6ad63d0258bc3 100644 ---- a/src/main/java/net/minecraft/server/EntityHorseMule.java -+++ b/src/main/java/net/minecraft/server/EntityHorseMule.java -@@ -18,7 +18,23 @@ public class EntityHorseMule extends EntityHorseChestedAbstract { - int getPurpurBreedTime() { +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java +index 0536112357e0321dbb902331467b847894a4c11b..9cc1a371dfbb0305fa47e69665a12a6901224edc 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java +@@ -25,7 +25,23 @@ public class EntityHorseMule extends EntityHorseChestedAbstract { + public int getPurpurBreedTime() { return this.world.purpurConfig.muleBreedingTicks; } + @@ -476,12 +600,12 @@ index 30cbc505d2b0f4d3247edfd271de8daab023eb2a..a32c5347e4d77f5641e4eb3ea4a6ad63 @Override protected SoundEffect getSoundAmbient() { super.getSoundAmbient(); -diff --git a/src/main/java/net/minecraft/server/EntityHorseSkeleton.java b/src/main/java/net/minecraft/server/EntityHorseSkeleton.java -index 408db52cacbdfbca8af0a6a8e913b0128a3f5a76..9eac8f39ddfb598f7dfb90625829e2b10d7ec140 100644 ---- a/src/main/java/net/minecraft/server/EntityHorseSkeleton.java -+++ b/src/main/java/net/minecraft/server/EntityHorseSkeleton.java -@@ -27,6 +27,21 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { - int getPurpurBreedTime() { +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java +index 28c6e3745c61d0670bf7f3a324169472250e25f4..0fe21fde809aa72305b1145b994a7aafe3f03112 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java +@@ -48,6 +48,21 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { + public int getPurpurBreedTime() { return 6000; } + @@ -502,12 +626,12 @@ index 408db52cacbdfbca8af0a6a8e913b0128a3f5a76..9eac8f39ddfb598f7dfb90625829e2b1 // Purpur end public static AttributeProvider.Builder eL() { -diff --git a/src/main/java/net/minecraft/server/EntityHorseZombie.java b/src/main/java/net/minecraft/server/EntityHorseZombie.java -index 2121a6c979ba2ea7cb596ca6081750d2f8c7df9f..c2dc8211b05b4ee2a2b42435f866f8e55295162d 100644 ---- a/src/main/java/net/minecraft/server/EntityHorseZombie.java -+++ b/src/main/java/net/minecraft/server/EntityHorseZombie.java -@@ -23,6 +23,21 @@ public class EntityHorseZombie extends EntityHorseAbstract { - int getPurpurBreedTime() { +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java +index c776f18722d1aa73f53da66ef6b37564eeaddd2a..1820c2d225d1fa919de2b1c0593370a8a17b4b6a 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java +@@ -40,6 +40,21 @@ public class EntityHorseZombie extends EntityHorseAbstract { + public int getPurpurBreedTime() { return 6000; } + @@ -528,28 +652,12 @@ index 2121a6c979ba2ea7cb596ca6081750d2f8c7df9f..c2dc8211b05b4ee2a2b42435f866f8e5 // Purpur end public static AttributeProvider.Builder eL() { -diff --git a/src/main/java/net/minecraft/server/EntityIronGolem.java b/src/main/java/net/minecraft/server/EntityIronGolem.java -index 9ee03b233b71d1b4b85a9a5e1f0ea9feb55dfe43..3e224eeb7bdcd0d1c6bd46012366c9d9878dd2a2 100644 ---- a/src/main/java/net/minecraft/server/EntityIronGolem.java -+++ b/src/main/java/net/minecraft/server/EntityIronGolem.java -@@ -32,6 +32,11 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable { - public boolean isRidableInWater() { - return world.purpurConfig.ironGolemRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.ironGolemMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityLlama.java b/src/main/java/net/minecraft/server/EntityLlama.java -index 3bc6e6df9e0107debe5b15f5f7aad97ad336f304..f46a7cfe832c8cca83738b71882ff0a9819a7f41 100644 ---- a/src/main/java/net/minecraft/server/EntityLlama.java -+++ b/src/main/java/net/minecraft/server/EntityLlama.java -@@ -62,6 +62,21 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn - int getPurpurBreedTime() { +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java +index b3d51abc9bad9cad6fdc5dbdc2bf09d43a565f98..762fed5ba27474951c1962e6f034e8494b1035d6 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java +@@ -113,6 +113,21 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn + public int getPurpurBreedTime() { return this.world.purpurConfig.llamaBreedingTicks; } + @@ -570,11 +678,11 @@ index 3bc6e6df9e0107debe5b15f5f7aad97ad336f304..f46a7cfe832c8cca83738b71882ff0a9 // Purpur end public void setStrength(int i) { -diff --git a/src/main/java/net/minecraft/server/EntityLlamaTrader.java b/src/main/java/net/minecraft/server/EntityLlamaTrader.java -index b6aae5cdee1f8bb842ab8e06c47fb497576b464f..665de0c28e052d195bb30ca13e1b129245eff11c 100644 ---- a/src/main/java/net/minecraft/server/EntityLlamaTrader.java -+++ b/src/main/java/net/minecraft/server/EntityLlamaTrader.java -@@ -26,6 +26,21 @@ public class EntityLlamaTrader extends EntityLlama { +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.java +index 0fb651bcde1109b0eb30b60226d3512648dceb41..73f59982d70093d308c6dc6a9a5693347c2699b7 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.java +@@ -42,6 +42,21 @@ public class EntityLlamaTrader extends EntityLlama { public boolean hasSaddle() { return super.hasSaddle() || isTamed(); } @@ -596,11 +704,191 @@ index b6aae5cdee1f8bb842ab8e06c47fb497576b464f..665de0c28e052d195bb30ca13e1b1292 // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityMagmaCube.java b/src/main/java/net/minecraft/server/EntityMagmaCube.java -index cd28463e2bf944d94c121c8f8d6e37221754c168..ac24a9de3b2b24bc8afebf54ea0a947fbdac2157 100644 ---- a/src/main/java/net/minecraft/server/EntityMagmaCube.java -+++ b/src/main/java/net/minecraft/server/EntityMagmaCube.java -@@ -23,6 +23,15 @@ public class EntityMagmaCube extends EntitySlime { +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +index 7f583c6c15f0191219eb911d901ea28d86c11489..999a6d17eccd6305c0063e1558abfe70d72c39fe 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +@@ -147,6 +147,11 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { + public double getMaxY() { + return world.purpurConfig.enderDragonMaxY; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.enderDragonMaxHealth); ++ } + // Purpur end + + public static AttributeProvider.Builder m() { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java b/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java +index 9a109ed062e5abedaad295383aca6441321da276..45e69d2f8da4c5babfd2e67055cc0a4c6d3baac7 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java +@@ -72,6 +72,11 @@ public class EntityBlaze extends EntityMonster { + setMot(mot.a(0.9D)); + } + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.blazeMaxHealth); ++ } + // Purpur end + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCaveSpider.java b/src/main/java/net/minecraft/world/entity/monster/EntityCaveSpider.java +index 27baf5cde99d8f25b1e7583c30339fcc71a3786f..72b298642f17c13f0f5959034e345a47f1e7ae26 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityCaveSpider.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityCaveSpider.java +@@ -34,6 +34,11 @@ public class EntityCaveSpider extends EntitySpider { + public boolean isRidableInWater() { + return world.purpurConfig.caveSpiderRidableInWater; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.caveSpiderMaxHealth); ++ } + // Purpur end + + public static AttributeProvider.Builder m() { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java +index e29bba9143f027077c1051d61296df219cd45861..6461e09e05f9255a399a6ce65d8fb90789a2fd7f 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java +@@ -137,6 +137,11 @@ public class EntityCreeper extends EntityMonster { + } + return getForward() == 0 && getStrafe() == 0; // do not jump if standing still + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.creeperMaxHealth); ++ } + // Purpur end + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java b/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java +index 93946f4e3cad07e20189a44ce512682b4cbc163b..926a38adb52b7d99ce2a9fcc52eb4878a2abdbcf 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java +@@ -97,6 +97,15 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { + public boolean jockeyTryExistingChickens() { + return world.purpurConfig.drownedJockeyTryExistingChickens; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.drownedMaxHealth); ++ } ++ ++ protected void generateReinforcementsChance() { ++ this.getAttributeInstance(GenericAttributes.SPAWN_REINFORCEMENTS).setValue(this.random.nextDouble() * this.world.purpurConfig.drownedSpawnReinforcements); ++ } + // Purpur end + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +index 18b3f8d1fadd1424327261d92b49977a35c4948c..478ac5bfdc69b5c3e24906bb5e0ea1dff81cea98 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +@@ -96,6 +96,11 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { + public boolean isRidableInWater() { + return world.purpurConfig.endermanRidableInWater; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.endermanMaxHealth); ++ } + // Purpur end + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEndermite.java b/src/main/java/net/minecraft/world/entity/monster/EntityEndermite.java +index 1c87bea9de812e57f8ccd3c9aa85330af87ed240..0e1d60a744fb41d2c31950572720b8899281df47 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityEndermite.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityEndermite.java +@@ -47,6 +47,11 @@ public class EntityEndermite extends EntityMonster { + public boolean isRidableInWater() { + return world.purpurConfig.endermiteRidableInWater; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.endermiteMaxHealth); ++ } + // Purpur end + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java b/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java +index 55607910183155080e3d96296421438d17f19c8f..8d7b8d2ac9a7340e2cfd0d1b8963e4e4d97e8bc8 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java +@@ -59,6 +59,11 @@ public class EntityEvoker extends EntityIllagerWizard { + public boolean isRidableInWater() { + return world.purpurConfig.evokerRidableInWater; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.evokerMaxHealth); ++ } + // Purpur end + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java b/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java +index 8784647f512d280ee0a092ecd406321268359314..5c39a9aec865d25a9aa5edcfd3a0fd6d1166cbd1 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java +@@ -73,6 +73,11 @@ public class EntityGhast extends EntityFlying implements IMonster { + setMot(mot.a(0.9D)); + } + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.ghastMaxHealth); ++ } + // Purpur end + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGuardian.java b/src/main/java/net/minecraft/world/entity/monster/EntityGuardian.java +index 6980b6988549b37a33d204a6e84c9e81d384a57a..248c64ea21de214bfbb2fa39f289382fd4f76202 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityGuardian.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityGuardian.java +@@ -86,6 +86,11 @@ public class EntityGuardian extends EntityMonster { + public boolean isRidableInWater() { + return true; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.guardianMaxHealth); ++ } + // Purpur end + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java b/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java +index 16b8606be2835dccdfa75f29827be4b88aaa1810..b06897c3d9dfc4612b0711eee5f225224e07ae91 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java +@@ -40,6 +40,11 @@ public class EntityGuardianElder extends EntityGuardian { + public boolean isRidableInWater() { + return true; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.elderGuardianMaxHealth); ++ } + // Purpur end + + public static AttributeProvider.Builder m() { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityMagmaCube.java b/src/main/java/net/minecraft/world/entity/monster/EntityMagmaCube.java +index 15ed51a2746c09538a425fce25fa25f2619b7033..626a207cdb727866cb75f4e53a6880867c1ca195 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityMagmaCube.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityMagmaCube.java +@@ -44,6 +44,15 @@ public class EntityMagmaCube extends EntitySlime { public float getJumpHeight() { return 0.42F * this.getBlockJumpFactor(); // from EntityLiving } @@ -616,91 +904,11 @@ index cd28463e2bf944d94c121c8f8d6e37221754c168..ac24a9de3b2b24bc8afebf54ea0a947f // Purpur end public static AttributeProvider.Builder m() { -diff --git a/src/main/java/net/minecraft/server/EntityMushroomCow.java b/src/main/java/net/minecraft/server/EntityMushroomCow.java -index 46d031ef3cebfe30e07840ef1c9d60a97a24cd1b..c97dac30010c7d574aa7087f3a84581bfc386473 100644 ---- a/src/main/java/net/minecraft/server/EntityMushroomCow.java -+++ b/src/main/java/net/minecraft/server/EntityMushroomCow.java -@@ -36,6 +36,11 @@ public class EntityMushroomCow extends EntityCow implements IShearable { - int getPurpurBreedTime() { - return this.world.purpurConfig.mooshroomBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.mooshroomMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityOcelot.java b/src/main/java/net/minecraft/server/EntityOcelot.java -index a5be10dfb0de08b0d97265278b1f11ad1e94b821..b8368cf397c26d06f2827a1a786e1f241b810cce 100644 ---- a/src/main/java/net/minecraft/server/EntityOcelot.java -+++ b/src/main/java/net/minecraft/server/EntityOcelot.java -@@ -31,6 +31,11 @@ public class EntityOcelot extends EntityAnimal { - int getPurpurBreedTime() { - return this.world.purpurConfig.ocelotBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.ocelotMaxHealth); -+ } - // Purpur end - - private boolean isTrusting() { -diff --git a/src/main/java/net/minecraft/server/EntityPanda.java b/src/main/java/net/minecraft/server/EntityPanda.java -index c70180fddb829419b9cc5188766e9130f9b8a94a..d202624853a1a0a0562b62ad5f3792db0916ae03 100644 ---- a/src/main/java/net/minecraft/server/EntityPanda.java -+++ b/src/main/java/net/minecraft/server/EntityPanda.java -@@ -70,6 +70,12 @@ public class EntityPanda extends EntityAnimal { - int getPurpurBreedTime() { - return this.world.purpurConfig.pandaBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.pandaMaxHealth); -+ updateAttributes(); -+ } - // Purpur end - - @Override -@@ -542,9 +548,12 @@ public class EntityPanda extends EntityAnimal { - return this.random.nextBoolean() ? this.getMainGene() : this.getHiddenGene(); - } - -- public void fg() { -+ public void fg() { updateAttributes(); } public void updateAttributes() { // Purpur - OBFHELPER - if (this.isWeak()) { -- this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(10.0D); -+ // Purpur start -+ AttributeModifiable maxHealth = this.getAttributeInstance(GenericAttributes.MAX_HEALTH); -+ maxHealth.setValue(maxHealth.getValue() / 2); -+ // Purpur end - } - - if (this.isLazy()) { -diff --git a/src/main/java/net/minecraft/server/EntityParrot.java b/src/main/java/net/minecraft/server/EntityParrot.java -index 398e92bf7053c411bd98626efe4261e15256d3ee..d19f8dda87c97de594ad051a6791d99eec581e95 100644 ---- a/src/main/java/net/minecraft/server/EntityParrot.java -+++ b/src/main/java/net/minecraft/server/EntityParrot.java -@@ -120,6 +120,11 @@ public class EntityParrot extends EntityPerchable implements EntityBird { - int getPurpurBreedTime() { - return 6000; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.parrotMaxHealth); -+ } - // Purpur end - - @Nullable -diff --git a/src/main/java/net/minecraft/server/EntityPhantom.java b/src/main/java/net/minecraft/server/EntityPhantom.java -index c70281fddcbe5a97a1eb176def99cdf31de37579..80cc4467d601b653583e387eb4be6f3b739058e6 100644 ---- a/src/main/java/net/minecraft/server/EntityPhantom.java -+++ b/src/main/java/net/minecraft/server/EntityPhantom.java -@@ -76,6 +76,11 @@ public class EntityPhantom extends EntityFlying implements IMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java +index a836839b17cbda8ac269f032b141ba448e3bab8c..902b26d609aef8dd46e8875cb7c06f187511e8d5 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java +@@ -120,6 +120,11 @@ public class EntityPhantom extends EntityFlying implements IMonster { world.addEntity(flames); return true; } @@ -712,27 +920,11 @@ index c70281fddcbe5a97a1eb176def99cdf31de37579..80cc4467d601b653583e387eb4be6f3b // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityPig.java b/src/main/java/net/minecraft/server/EntityPig.java -index eae841eeac75a35a9dc5a53c57538ac5264ece68..9cf07531c674402e3ecc87229638578989340a13 100644 ---- a/src/main/java/net/minecraft/server/EntityPig.java -+++ b/src/main/java/net/minecraft/server/EntityPig.java -@@ -34,6 +34,11 @@ public class EntityPig extends EntityAnimal implements ISteerable, ISaddleable { - int getPurpurBreedTime() { - return this.world.purpurConfig.pigBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.pigMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityPigZombie.java b/src/main/java/net/minecraft/server/EntityPigZombie.java -index 57f3358b8dfd53f5b1d2e976d64b809f74bc3ce3..4c050c841f9846cc74fef51d5eb69f4cbb737ef1 100644 ---- a/src/main/java/net/minecraft/server/EntityPigZombie.java -+++ b/src/main/java/net/minecraft/server/EntityPigZombie.java -@@ -46,6 +46,15 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java +index 8db9c62093b2f075face65030cb91c24fb6c2dbf..736c45bae020158866514bc760c05a929f47c531 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java +@@ -80,6 +80,15 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { public boolean jockeyTryExistingChickens() { return world.purpurConfig.zombifiedPiglinJockeyTryExistingChickens; } @@ -748,7 +940,7 @@ index 57f3358b8dfd53f5b1d2e976d64b809f74bc3ce3..4c050c841f9846cc74fef51d5eb69f4c // Purpur end @Override -@@ -234,7 +243,7 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { +@@ -268,7 +277,7 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { @Override protected void eV() { @@ -757,43 +949,11 @@ index 57f3358b8dfd53f5b1d2e976d64b809f74bc3ce3..4c050c841f9846cc74fef51d5eb69f4c } @Override -diff --git a/src/main/java/net/minecraft/server/EntityPiglin.java b/src/main/java/net/minecraft/server/EntityPiglin.java -index 29ecfd09f0bed3dc64b14b90875a111253599958..20b6a4faae21e6969eb8bb4377c6cbe0b1f80fa0 100644 ---- a/src/main/java/net/minecraft/server/EntityPiglin.java -+++ b/src/main/java/net/minecraft/server/EntityPiglin.java -@@ -35,6 +35,11 @@ public class EntityPiglin extends EntityPiglinAbstract implements ICrossbow { - public boolean isRidableInWater() { - return world.purpurConfig.piglinRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.piglinMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityPiglinBrute.java b/src/main/java/net/minecraft/server/EntityPiglinBrute.java -index f6b170811159544dc10b91226e4e54b349472c46..50e42cd8ccd48efe6251a37762953f7f55d18277 100644 ---- a/src/main/java/net/minecraft/server/EntityPiglinBrute.java -+++ b/src/main/java/net/minecraft/server/EntityPiglinBrute.java -@@ -25,6 +25,11 @@ public class EntityPiglinBrute extends EntityPiglinAbstract { - public boolean isRidableInWater() { - return world.purpurConfig.piglinBruteRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.piglinBruteMaxHealth); -+ } - // Purpur end - - public static AttributeProvider.Builder eS() { -diff --git a/src/main/java/net/minecraft/server/EntityPillager.java b/src/main/java/net/minecraft/server/EntityPillager.java -index cf7de0127166f6175a6246062c8664e64959edeb..99b2d50d3958a9341d01108000f2719d271bdfd5 100644 ---- a/src/main/java/net/minecraft/server/EntityPillager.java -+++ b/src/main/java/net/minecraft/server/EntityPillager.java -@@ -23,6 +23,11 @@ public class EntityPillager extends EntityIllagerAbstract implements ICrossbow { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPillager.java b/src/main/java/net/minecraft/world/entity/monster/EntityPillager.java +index 2a4ac6e608650d56cc2b564e715b7b685e7f3f62..43a1a31db5ddfd30b66c63c6b2cceb1dcf62e412 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityPillager.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityPillager.java +@@ -72,6 +72,11 @@ public class EntityPillager extends EntityIllagerAbstract implements ICrossbow { public boolean isRidableInWater() { return world.purpurConfig.pillagerRidableInWater; } @@ -805,59 +965,11 @@ index cf7de0127166f6175a6246062c8664e64959edeb..99b2d50d3958a9341d01108000f2719d // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityPolarBear.java b/src/main/java/net/minecraft/server/EntityPolarBear.java -index 40395dd7ea515e51a189d014a3274d15dc1d8ee6..f72a72e6f76c3896a80a75aae255081e2f8bb507 100644 ---- a/src/main/java/net/minecraft/server/EntityPolarBear.java -+++ b/src/main/java/net/minecraft/server/EntityPolarBear.java -@@ -72,6 +72,11 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { - int getPurpurBreedTime() { - return this.world.purpurConfig.polarBearBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.polarBearMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityPufferFish.java b/src/main/java/net/minecraft/server/EntityPufferFish.java -index 16a4df27c557e2d4a0fd4f48317307b884c2688c..815ba3062e0cbc4400f4dae9f80ce8f6745816f5 100644 ---- a/src/main/java/net/minecraft/server/EntityPufferFish.java -+++ b/src/main/java/net/minecraft/server/EntityPufferFish.java -@@ -27,6 +27,11 @@ public class EntityPufferFish extends EntityFish { - public boolean isRidableInWater() { - return true; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.pufferfishMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityRabbit.java b/src/main/java/net/minecraft/server/EntityRabbit.java -index 654cd036a8e4aa4499f10f528b684e003c469c9a..75f42e91449de71e154e2169ea986ff09224e2f0 100644 ---- a/src/main/java/net/minecraft/server/EntityRabbit.java -+++ b/src/main/java/net/minecraft/server/EntityRabbit.java -@@ -35,6 +35,11 @@ public class EntityRabbit extends EntityAnimal { - int getPurpurBreedTime() { - return this.world.purpurConfig.rabbitBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.rabbitMaxHealth); -+ } - // Purpur end - - // CraftBukkit start - code from constructor -diff --git a/src/main/java/net/minecraft/server/EntityRavager.java b/src/main/java/net/minecraft/server/EntityRavager.java -index 9d0a462bfc56994ee35478cc9e565123620a9f08..820938c76e787fac6c65eb000491232d5b749dee 100644 ---- a/src/main/java/net/minecraft/server/EntityRavager.java -+++ b/src/main/java/net/minecraft/server/EntityRavager.java -@@ -39,6 +39,11 @@ public class EntityRavager extends EntityRaider { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java b/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java +index dc1ca7b334e89b4d0be775b6f6e6f4222ea02dcc..80c3cd540a46e249e85586e8d7a2f0f6226091fc 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java +@@ -81,6 +81,11 @@ public class EntityRavager extends EntityRaider { double speed = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getBaseValue(); getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue(speed); } @@ -869,43 +981,11 @@ index 9d0a462bfc56994ee35478cc9e565123620a9f08..820938c76e787fac6c65eb000491232d // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntitySalmon.java b/src/main/java/net/minecraft/server/EntitySalmon.java -index 6dfcee2c9b658c2c9ee1179e412389934c066d48..475c375bebe2c7211869af28d23db3107b39fe51 100644 ---- a/src/main/java/net/minecraft/server/EntitySalmon.java -+++ b/src/main/java/net/minecraft/server/EntitySalmon.java -@@ -16,6 +16,11 @@ public class EntitySalmon extends EntityFishSchool { - public boolean isRidableInWater() { - return true; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.salmonMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/server/EntitySheep.java b/src/main/java/net/minecraft/server/EntitySheep.java -index 32130c0681501e3e5a47b199f0bb39daac416ed3..d9fe8cf00088dba516ea2bfd7e9590d95c7e7939 100644 ---- a/src/main/java/net/minecraft/server/EntitySheep.java -+++ b/src/main/java/net/minecraft/server/EntitySheep.java -@@ -71,6 +71,11 @@ public class EntitySheep extends EntityAnimal implements IShearable { - int getPurpurBreedTime() { - return this.world.purpurConfig.sheepBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.sheepMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityShulker.java b/src/main/java/net/minecraft/server/EntityShulker.java -index 11a6b939ebb51cdda907531d30b7beb3a8562673..3f1cb739709cc16a9f7073ec8fafb448b734a948 100644 ---- a/src/main/java/net/minecraft/server/EntityShulker.java -+++ b/src/main/java/net/minecraft/server/EntityShulker.java -@@ -40,6 +40,11 @@ public class EntityShulker extends EntityGolem implements IMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityShulker.java b/src/main/java/net/minecraft/world/entity/monster/EntityShulker.java +index 0294ab119407dc45a40c8444fb5a91e154017234..a735ac7644f8fe6924349fbd9e8984f678d0b9c2 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityShulker.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityShulker.java +@@ -82,6 +82,11 @@ public class EntityShulker extends EntityGolem implements IMonster { public boolean isRidableInWater() { return world.purpurConfig.shulkerRidableInWater; } @@ -917,11 +997,11 @@ index 11a6b939ebb51cdda907531d30b7beb3a8562673..3f1cb739709cc16a9f7073ec8fafb448 // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntitySilverfish.java b/src/main/java/net/minecraft/server/EntitySilverfish.java -index ad428e090089a461283445022b33313520585ac5..6bd00f0b5735d694e370cf85fdbf508c31fc7c27 100644 ---- a/src/main/java/net/minecraft/server/EntitySilverfish.java -+++ b/src/main/java/net/minecraft/server/EntitySilverfish.java -@@ -21,6 +21,11 @@ public class EntitySilverfish extends EntityMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java b/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java +index c0601af022d85c7b03463f0df975d713c0366b2c..a0a1e5977a3cbc8e9befd827dd1e15352a2c0c39 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java +@@ -49,6 +49,11 @@ public class EntitySilverfish extends EntityMonster { public boolean isRidableInWater() { return world.purpurConfig.silverfishRidableInWater; } @@ -933,11 +1013,19 @@ index ad428e090089a461283445022b33313520585ac5..6bd00f0b5735d694e370cf85fdbf508c // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntitySkeleton.java b/src/main/java/net/minecraft/server/EntitySkeleton.java -index 3f130e03bf8b235360385fd169d4886ffcfa626a..a78e593cbdfa4a74d07fd53c9481534c856d01e6 100644 ---- a/src/main/java/net/minecraft/server/EntitySkeleton.java -+++ b/src/main/java/net/minecraft/server/EntitySkeleton.java -@@ -16,6 +16,11 @@ public class EntitySkeleton extends EntitySkeletonAbstract { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeleton.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeleton.java +index 0b8517d4e83d14ddf8b6d1f1cf4c538f9e4cc68f..8ee51897af1199b9bed05ddf90fe914a7b214b91 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeleton.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeleton.java +@@ -5,6 +5,7 @@ import net.minecraft.sounds.SoundEffects; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityTypes; ++import net.minecraft.world.entity.ai.attributes.GenericAttributes; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.World; +@@ -25,6 +26,11 @@ public class EntitySkeleton extends EntitySkeletonAbstract { public boolean isRidableInWater() { return world.purpurConfig.skeletonRidableInWater; } @@ -949,11 +1037,19 @@ index 3f130e03bf8b235360385fd169d4886ffcfa626a..a78e593cbdfa4a74d07fd53c9481534c // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntitySkeletonStray.java b/src/main/java/net/minecraft/server/EntitySkeletonStray.java -index d123fb82b635d5271bea9b238554a3011858eeae..e34ab9eda7f610456193bdc0495c2ba478917625 100644 ---- a/src/main/java/net/minecraft/server/EntitySkeletonStray.java -+++ b/src/main/java/net/minecraft/server/EntitySkeletonStray.java -@@ -18,6 +18,11 @@ public class EntitySkeletonStray extends EntitySkeletonAbstract { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonStray.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonStray.java +index 8484000a1b0d9c252d6fab205b1e316e3f6f33bd..a75a7785406143325b0364737dd1667aad464018 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonStray.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonStray.java +@@ -9,6 +9,7 @@ import net.minecraft.world.effect.MobEffect; + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.ai.attributes.GenericAttributes; + import net.minecraft.world.entity.projectile.EntityArrow; + import net.minecraft.world.entity.projectile.EntityTippedArrow; + import net.minecraft.world.item.ItemStack; +@@ -31,6 +32,11 @@ public class EntitySkeletonStray extends EntitySkeletonAbstract { public boolean isRidableInWater() { return world.purpurConfig.strayRidableInWater; } @@ -965,11 +1061,11 @@ index d123fb82b635d5271bea9b238554a3011858eeae..e34ab9eda7f610456193bdc0495c2ba4 // Purpur end public static boolean a(EntityTypes entitytypes, WorldAccess worldaccess, EnumMobSpawn enummobspawn, BlockPosition blockposition, Random random) { -diff --git a/src/main/java/net/minecraft/server/EntitySkeletonWither.java b/src/main/java/net/minecraft/server/EntitySkeletonWither.java -index 96cb080d940db22330598a8806726088b79a53c1..ee7805dccac9c4dcdf4fa83ab8041953dccdc83b 100644 ---- a/src/main/java/net/minecraft/server/EntitySkeletonWither.java -+++ b/src/main/java/net/minecraft/server/EntitySkeletonWither.java -@@ -19,6 +19,11 @@ public class EntitySkeletonWither extends EntitySkeletonAbstract { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java +index cb52c4e63ac487d55dc16accca6976f44f904112..62f1808a456f46a6c7fbb5e030d9ed6546676a3d 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java +@@ -44,6 +44,11 @@ public class EntitySkeletonWither extends EntitySkeletonAbstract { public boolean isRidableInWater() { return world.purpurConfig.witherSkeletonRidableInWater; } @@ -981,11 +1077,11 @@ index 96cb080d940db22330598a8806726088b79a53c1..ee7805dccac9c4dcdf4fa83ab8041953 // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntitySlime.java b/src/main/java/net/minecraft/server/EntitySlime.java -index 7f3d57a9399f60465fae27f03fc57df625f5016d..c3737457c521715b640b138dc41863dfba6e4ae8 100644 ---- a/src/main/java/net/minecraft/server/EntitySlime.java -+++ b/src/main/java/net/minecraft/server/EntitySlime.java -@@ -11,6 +11,7 @@ import com.destroystokyo.paper.event.entity.SlimeChangeDirectionEvent; +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java +index 0cbe3032fd3b048b0eb8ec3d8592a662c69c9e30..b80b426acd8aec61c5e970ca039c8c47bc97f9e4 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java +@@ -51,6 +51,7 @@ import com.destroystokyo.paper.event.entity.SlimeChangeDirectionEvent; import com.destroystokyo.paper.event.entity.SlimeSwimEvent; import com.destroystokyo.paper.event.entity.SlimeTargetLivingEntityEvent; import com.destroystokyo.paper.event.entity.SlimeWanderEvent; @@ -993,7 +1089,7 @@ index 7f3d57a9399f60465fae27f03fc57df625f5016d..c3737457c521715b640b138dc41863df import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Slime; // Paper end -@@ -25,6 +26,7 @@ import org.bukkit.event.entity.SlimeSplitEvent; +@@ -65,6 +66,7 @@ import org.bukkit.event.entity.SlimeSplitEvent; public class EntitySlime extends EntityInsentient implements IMonster { private static final DataWatcherObject bo = DataWatcher.a(EntitySlime.class, DataWatcherRegistry.b); @@ -1001,7 +1097,7 @@ index 7f3d57a9399f60465fae27f03fc57df625f5016d..c3737457c521715b640b138dc41863df public float b; public float c; public float d; -@@ -64,6 +66,25 @@ public class EntitySlime extends EntityInsentient implements IMonster { +@@ -104,6 +106,25 @@ public class EntitySlime extends EntityInsentient implements IMonster { } return true; // do not jump() in wasd controller, let vanilla controller handle } @@ -1027,7 +1123,7 @@ index 7f3d57a9399f60465fae27f03fc57df625f5016d..c3737457c521715b640b138dc41863df // Purpur end @Override -@@ -90,7 +111,7 @@ public class EntitySlime extends EntityInsentient implements IMonster { +@@ -130,7 +151,7 @@ public class EntitySlime extends EntityInsentient implements IMonster { this.datawatcher.set(EntitySlime.bo, i); this.af(); this.updateSize(); @@ -1036,27 +1132,11 @@ index 7f3d57a9399f60465fae27f03fc57df625f5016d..c3737457c521715b640b138dc41863df this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue((double) (0.2F + 0.1F * (float) i)); this.getAttributeInstance(GenericAttributes.ATTACK_DAMAGE).setValue((double) i); if (flag) { -diff --git a/src/main/java/net/minecraft/server/EntitySnowman.java b/src/main/java/net/minecraft/server/EntitySnowman.java -index 338c78efe43641686be0d6b3a241865ec5fe56bd..1dd13dfea91a05b1e83b065328092a17d41a605f 100644 ---- a/src/main/java/net/minecraft/server/EntitySnowman.java -+++ b/src/main/java/net/minecraft/server/EntitySnowman.java -@@ -24,6 +24,11 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt - public boolean isRidableInWater() { - return world.purpurConfig.snowGolemRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.snowGolemMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/server/EntitySpider.java b/src/main/java/net/minecraft/server/EntitySpider.java -index 92d74137877d096970bf9d1b4fc91beabb862b9d..9001ca50b8d9f77b0d997511b70c39b2712df67a 100644 ---- a/src/main/java/net/minecraft/server/EntitySpider.java -+++ b/src/main/java/net/minecraft/server/EntitySpider.java -@@ -21,6 +21,11 @@ public class EntitySpider extends EntityMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySpider.java b/src/main/java/net/minecraft/world/entity/monster/EntitySpider.java +index fbf7c31f57f6dbfac997480eb7db55efc15ef4cc..9b596aa061aa1d4ddfd66361d5277089c3e18246 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySpider.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySpider.java +@@ -61,6 +61,11 @@ public class EntitySpider extends EntityMonster { public boolean isRidableInWater() { return world.purpurConfig.spiderRidableInWater; } @@ -1068,28 +1148,12 @@ index 92d74137877d096970bf9d1b4fc91beabb862b9d..9001ca50b8d9f77b0d997511b70c39b2 // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntitySquid.java b/src/main/java/net/minecraft/server/EntitySquid.java -index cee226501690e1c00983a01ac82bc7384f233c3c..918cd774bc7e9f84ddbc1e65b4cb4d661eb127a5 100644 ---- a/src/main/java/net/minecraft/server/EntitySquid.java -+++ b/src/main/java/net/minecraft/server/EntitySquid.java -@@ -56,6 +56,11 @@ public class EntitySquid extends EntityWaterAnimal { - public boolean isInWater() { - return this.inWater || world.purpurConfig.squidsCanFly; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.squidMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityStrider.java b/src/main/java/net/minecraft/server/EntityStrider.java -index 5c960365901b6ebd74134dac2e90c6aa81d33351..1bca386b7dea01af88a6c8d8e87ff11a0b21cc7a 100644 ---- a/src/main/java/net/minecraft/server/EntityStrider.java -+++ b/src/main/java/net/minecraft/server/EntityStrider.java -@@ -43,6 +43,11 @@ public class EntityStrider extends EntityAnimal implements ISteerable, ISaddleab - int getPurpurBreedTime() { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java b/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java +index cba66a08feceeeaf7c123da595fc7b12c5749783..892aa844a98ae0d192737c6fc6df0a219256a47b 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java +@@ -110,6 +110,11 @@ public class EntityStrider extends EntityAnimal implements ISteerable, ISaddleab + public int getPurpurBreedTime() { return this.world.purpurConfig.striderBreedingTicks; } + @@ -1100,43 +1164,11 @@ index 5c960365901b6ebd74134dac2e90c6aa81d33351..1bca386b7dea01af88a6c8d8e87ff11a // Purpur end public static boolean c(EntityTypes entitytypes, GeneratorAccess generatoraccess, EnumMobSpawn enummobspawn, BlockPosition blockposition, Random random) { -diff --git a/src/main/java/net/minecraft/server/EntityTropicalFish.java b/src/main/java/net/minecraft/server/EntityTropicalFish.java -index 2c9df356e685ea6f71653023fadcf7e287dcd46e..4bf7b697c18f3d3a1987471571d665ed823c5c77 100644 ---- a/src/main/java/net/minecraft/server/EntityTropicalFish.java -+++ b/src/main/java/net/minecraft/server/EntityTropicalFish.java -@@ -29,6 +29,11 @@ public class EntityTropicalFish extends EntityFishSchool { - public boolean isRidableInWater() { - return true; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.tropicalFishMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityTurtle.java b/src/main/java/net/minecraft/server/EntityTurtle.java -index 067f7f28b02b388d56b93b1ed8274799757196e6..0233b65a996111af7bdc10e4da2d70e541411c09 100644 ---- a/src/main/java/net/minecraft/server/EntityTurtle.java -+++ b/src/main/java/net/minecraft/server/EntityTurtle.java -@@ -42,6 +42,11 @@ public class EntityTurtle extends EntityAnimal { - int getPurpurBreedTime() { - return this.world.purpurConfig.turtleBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.turtleMaxHealth); -+ } - // Purpur end - - public void setHomePos(BlockPosition blockposition) { -diff --git a/src/main/java/net/minecraft/server/EntityVex.java b/src/main/java/net/minecraft/server/EntityVex.java -index 9336fbbd46c7c6ac11adf8e4cc2735f81c9ed639..3fcbfc7cdf78f71d23b2e2b2990c21db6f493f31 100644 ---- a/src/main/java/net/minecraft/server/EntityVex.java -+++ b/src/main/java/net/minecraft/server/EntityVex.java -@@ -55,6 +55,11 @@ public class EntityVex extends EntityMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java +index 4301ece0a04f3f2b4d198a684d0ca314deef2aef..69d47697442fa80fbed08a11bb9e66057d059101 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java +@@ -92,6 +92,11 @@ public class EntityVex extends EntityMonster { public boolean b(float f, float f1) { return false; // no fall damage please } @@ -1148,43 +1180,11 @@ index 9336fbbd46c7c6ac11adf8e4cc2735f81c9ed639..3fcbfc7cdf78f71d23b2e2b2990c21db // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java -index d2112fb2424f19b2fb65ce635aa0fe24807a311e..4f5ad3836d39ccb88923a38f2fd556cb88ec241a 100644 ---- a/src/main/java/net/minecraft/server/EntityVillager.java -+++ b/src/main/java/net/minecraft/server/EntityVillager.java -@@ -93,6 +93,11 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - public boolean a(EntityHuman entityhuman) { - return world.purpurConfig.villagerCanBeLeashed && !this.isLeashed(); - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.villagerMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityVillagerTrader.java b/src/main/java/net/minecraft/server/EntityVillagerTrader.java -index b9418fac0a05d4bb5f8f215a5704bba332e3f7cb..a37aee151bce19ee74e6eae6b67e522a4b28f5a8 100644 ---- a/src/main/java/net/minecraft/server/EntityVillagerTrader.java -+++ b/src/main/java/net/minecraft/server/EntityVillagerTrader.java -@@ -65,6 +65,11 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { - public boolean a(EntityHuman entityhuman) { - return world.purpurConfig.villagerTraderCanBeLeashed && !this.isLeashed(); - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.villagerTraderMaxHealth); -+ } - // Purpur - end - - @Nullable -diff --git a/src/main/java/net/minecraft/server/EntityVindicator.java b/src/main/java/net/minecraft/server/EntityVindicator.java -index f1bc6a4199d788215c2e7d5a835211d16603a6d9..2a137a90828f84de15a7184203c7d0dccc0851b4 100644 ---- a/src/main/java/net/minecraft/server/EntityVindicator.java -+++ b/src/main/java/net/minecraft/server/EntityVindicator.java -@@ -28,6 +28,11 @@ public class EntityVindicator extends EntityIllagerAbstract { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java +index 28d345e87f45fa839bc3bd758f79f34aba546db7..caaa27248637255ad9e8db20ca839a980e01bfb6 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java +@@ -70,6 +70,11 @@ public class EntityVindicator extends EntityIllagerAbstract { public boolean isRidableInWater() { return world.purpurConfig.vindicatorRidableInWater; } @@ -1196,11 +1196,11 @@ index f1bc6a4199d788215c2e7d5a835211d16603a6d9..2a137a90828f84de15a7184203c7d0dc // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityWitch.java b/src/main/java/net/minecraft/server/EntityWitch.java -index 323d79a99402b0f6952b4fb873170069f3428953..dc846e7bda587a47b1cce9054e587a734179e7fe 100644 ---- a/src/main/java/net/minecraft/server/EntityWitch.java -+++ b/src/main/java/net/minecraft/server/EntityWitch.java -@@ -34,6 +34,11 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java +index c4663c5b02363bd1499ce1f3b50027f8aa7c68e7..a119923ee8d8ac00892f594a8af6d392f818b59c 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java +@@ -74,6 +74,11 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { public boolean isRidableInWater() { return world.purpurConfig.witchRidableInWater; } @@ -1212,27 +1212,11 @@ index 323d79a99402b0f6952b4fb873170069f3428953..dc846e7bda587a47b1cce9054e587a73 // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityWolf.java b/src/main/java/net/minecraft/server/EntityWolf.java -index fd62dc51258876275adbe02f750fd88107c38a6b..03bcbf7c280476ef0e6fe87e3a96edb75544bddb 100644 ---- a/src/main/java/net/minecraft/server/EntityWolf.java -+++ b/src/main/java/net/minecraft/server/EntityWolf.java -@@ -121,6 +121,11 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable - setCollarColor(world.purpurConfig.wolfDefaultCollarColor); - super.tame(entityhuman); - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.wolfMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityZoglin.java b/src/main/java/net/minecraft/server/EntityZoglin.java -index d92fe8013fb3b43cb7eabdf1c624291b7e881889..bcc4aa1d3f09e43016d0009cd04dd6b797dcfeca 100644 ---- a/src/main/java/net/minecraft/server/EntityZoglin.java -+++ b/src/main/java/net/minecraft/server/EntityZoglin.java -@@ -31,6 +31,11 @@ public class EntityZoglin extends EntityMonster implements IMonster, IOglin { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZoglin.java b/src/main/java/net/minecraft/world/entity/monster/EntityZoglin.java +index c5b1ce9268d6e6f3ec26eda4b5d8e7ae2a2ea672..17c96e8eaa5cde028024f5ad4b853e3399a942d5 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityZoglin.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityZoglin.java +@@ -72,6 +72,11 @@ public class EntityZoglin extends EntityMonster implements IMonster, IOglin { public boolean isRidableInWater() { return world.purpurConfig.zoglinRidableInWater; } @@ -1244,11 +1228,11 @@ index d92fe8013fb3b43cb7eabdf1c624291b7e881889..bcc4aa1d3f09e43016d0009cd04dd6b7 // Purpur end @Override -diff --git a/src/main/java/net/minecraft/server/EntityZombie.java b/src/main/java/net/minecraft/server/EntityZombie.java -index e4de6e2f8b72c0ede3ad34666a5dfde5c5363b56..c87f05f2d511a135fe67943f96fe41d06882e57b 100644 ---- a/src/main/java/net/minecraft/server/EntityZombie.java -+++ b/src/main/java/net/minecraft/server/EntityZombie.java -@@ -67,6 +67,15 @@ public class EntityZombie extends EntityMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +index 88264b7b2c21a377f4b0dd857065e40165f0acde..7112db516e62ca75a445482005c524129b84f54c 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +@@ -130,6 +130,15 @@ public class EntityZombie extends EntityMonster { public boolean jockeyTryExistingChickens() { return world.purpurConfig.zombieJockeyTryExistingChickens; } @@ -1264,7 +1248,7 @@ index e4de6e2f8b72c0ede3ad34666a5dfde5c5363b56..c87f05f2d511a135fe67943f96fe41d0 // Purpur end @Override -@@ -549,7 +558,7 @@ public class EntityZombie extends EntityMonster { +@@ -612,7 +621,7 @@ public class EntityZombie extends EntityMonster { } protected void eV() { @@ -1273,11 +1257,19 @@ index e4de6e2f8b72c0ede3ad34666a5dfde5c5363b56..c87f05f2d511a135fe67943f96fe41d0 } @Override -diff --git a/src/main/java/net/minecraft/server/EntityZombieHusk.java b/src/main/java/net/minecraft/server/EntityZombieHusk.java -index 02b0ae550a0ed33b5b43beedf3b1405985c58c13..966a14b4122b5ca43832a57fcbc162147f903a21 100644 ---- a/src/main/java/net/minecraft/server/EntityZombieHusk.java -+++ b/src/main/java/net/minecraft/server/EntityZombieHusk.java -@@ -33,6 +33,15 @@ public class EntityZombieHusk extends EntityZombie { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java +index ad801fc394fbb83cf280ee96f962e7f311615d72..c060d93d9f3332b514a1400dec14f2035c058e48 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java +@@ -11,6 +11,7 @@ import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityLiving; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.ai.attributes.GenericAttributes; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.World; +@@ -47,6 +48,15 @@ public class EntityZombieHusk extends EntityZombie { public boolean jockeyTryExistingChickens() { return world.purpurConfig.huskJockeyTryExistingChickens; } @@ -1293,11 +1285,19 @@ index 02b0ae550a0ed33b5b43beedf3b1405985c58c13..966a14b4122b5ca43832a57fcbc16214 // Purpur end public static boolean a(EntityTypes entitytypes, WorldAccess worldaccess, EnumMobSpawn enummobspawn, BlockPosition blockposition, Random random) { -diff --git a/src/main/java/net/minecraft/server/EntityZombieVillager.java b/src/main/java/net/minecraft/server/EntityZombieVillager.java -index 5b6ed77fb2b92b5bf701de436c8d7235bfe82685..48e501130dea326ffc6503bc2e9306dffd8797f9 100644 ---- a/src/main/java/net/minecraft/server/EntityZombieVillager.java -+++ b/src/main/java/net/minecraft/server/EntityZombieVillager.java -@@ -53,6 +53,15 @@ public class EntityZombieVillager extends EntityZombie implements VillagerDataHo +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java +index 6b2fd555122ba1af0adae3e479540e0da767a99d..280d716f3625c859c04c782fcf2b126068cb3c84 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java +@@ -29,6 +29,7 @@ import net.minecraft.world.entity.EnumItemSlot; + import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.ReputationHandler; ++import net.minecraft.world.entity.ai.attributes.GenericAttributes; + import net.minecraft.world.entity.ai.village.ReputationEvent; + import net.minecraft.world.entity.npc.EntityVillager; + import net.minecraft.world.entity.npc.VillagerData; +@@ -95,6 +96,15 @@ public class EntityZombieVillager extends EntityZombie implements VillagerDataHo public boolean jockeyTryExistingChickens() { return world.purpurConfig.zombieVillagerJockeyTryExistingChickens; } @@ -1313,8 +1313,96 @@ index 5b6ed77fb2b92b5bf701de436c8d7235bfe82685..48e501130dea326ffc6503bc2e9306df // Purpur end @Override +diff --git a/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java b/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java +index 828d01abe8202a246ce07c1c652a17cbc829d904..b271df48d04f12a68e0b7abf2f1375749a9a0f08 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java ++++ b/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java +@@ -76,6 +76,11 @@ public class EntityHoglin extends EntityAnimal implements IMonster, IOglin { + public int getPurpurBreedTime() { + return this.world.purpurConfig.hoglinBreedingTicks; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.hoglinMaxHealth); ++ } + // Purpur end + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java +index 8c6f5273ed2ab4ec63b7854e290f790b2eca8c2f..99fc16aae085da564c5236e68925a8a2225f5c27 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java ++++ b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java +@@ -80,6 +80,11 @@ public class EntityPiglin extends EntityPiglinAbstract implements ICrossbow { + public boolean isRidableInWater() { + return world.purpurConfig.piglinRidableInWater; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.piglinMaxHealth); ++ } + // Purpur end + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglinBrute.java b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglinBrute.java +index da2220b08a9cd9c2d7d3fd06702e6690e12f095e..c441d6b2ce29d914a29c2f39d70adb14e9ab31a6 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglinBrute.java ++++ b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglinBrute.java +@@ -49,6 +49,11 @@ public class EntityPiglinBrute extends EntityPiglinAbstract { + public boolean isRidableInWater() { + return world.purpurConfig.piglinBruteRidableInWater; + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.piglinBruteMaxHealth); ++ } + // Purpur end + + public static AttributeProvider.Builder eS() { +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +index 77a5be6f5fc51689a74f853b5dfcef5e772e2c84..6ad608a795e85daf7425f26041b5e4a86cadc033 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +@@ -167,6 +167,11 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + public boolean a(EntityHuman entityhuman) { + return world.purpurConfig.villagerCanBeLeashed && !this.isLeashed(); + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.villagerMaxHealth); ++ } + // Purpur end + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java +index 90cbef7fe8803295f82bddd6709fdf303aedcaba..b84916c0c58fd208ef5547299f8db8462d1c42fe 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java +@@ -18,6 +18,7 @@ import net.minecraft.world.entity.EntityAgeable; + import net.minecraft.world.entity.EntityExperienceOrb; + import net.minecraft.world.entity.EntityInsentient; + import net.minecraft.world.entity.EntityTypes; ++import net.minecraft.world.entity.ai.attributes.GenericAttributes; + import net.minecraft.world.entity.ai.goal.PathfinderGoal; + import net.minecraft.world.entity.ai.goal.PathfinderGoalAvoidTarget; + import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat; +@@ -110,6 +111,11 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { + public boolean a(EntityHuman entityhuman) { + return world.purpurConfig.villagerTraderCanBeLeashed && !this.isLeashed(); + } ++ ++ @Override ++ public void initAttributes() { ++ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.villagerTraderMaxHealth); ++ } + // Purpur - end + + @Nullable diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 3790fcea3a556a979eacaf5b03e5ebc4c3a02925..31114da5cc21c5f3b59ea97e34bddfd09c2a5198 100644 +index 5c5aa1ab859c836945294cfdb06589639006a307..d0473f64fbb743f12eb7c98a59231b3fb7d20ccc 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -484,30 +484,58 @@ public class PurpurWorldConfig { diff --git a/patches/server/0151-Phantom-flames-on-swoop.patch b/patches/server/0151-Phantom-flames-on-swoop.patch index 1f996c38b..387f77acb 100644 --- a/patches/server/0151-Phantom-flames-on-swoop.patch +++ b/patches/server/0151-Phantom-flames-on-swoop.patch @@ -4,11 +4,11 @@ Date: Sat, 12 Dec 2020 09:10:59 -0600 Subject: [PATCH] Phantom flames on swoop -diff --git a/src/main/java/net/minecraft/server/EntityPhantom.java b/src/main/java/net/minecraft/server/EntityPhantom.java -index 80cc4467d601b653583e387eb4be6f3b739058e6..52a3ae1eda874b41e5d71c16b8ab24d3c9f17470 100644 ---- a/src/main/java/net/minecraft/server/EntityPhantom.java -+++ b/src/main/java/net/minecraft/server/EntityPhantom.java -@@ -182,6 +182,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java +index 902b26d609aef8dd46e8875cb7c06f187511e8d5..4f3d4f2596c69881f0653bddcc3bf2b9ede3ca8f 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java +@@ -226,6 +226,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { this.world.addParticle(Particles.MYCELIUM, this.locX() - (double) f2, this.locY() + (double) f4, this.locZ() - (double) f3, 0.0D, 0.0D, 0.0D); } @@ -17,7 +17,7 @@ index 80cc4467d601b653583e387eb4be6f3b739058e6..52a3ae1eda874b41e5d71c16b8ab24d3 @Override diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 31114da5cc21c5f3b59ea97e34bddfd09c2a5198..b630887b4ba9288e9724e97658d903ab334c3f8b 100644 +index d0473f64fbb743f12eb7c98a59231b3fb7d20ccc..b22344e942a212a204dd0935d3c6d55a37c23477 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -1148,6 +1148,7 @@ public class PurpurWorldConfig { diff --git a/patches/server/0152-Option-for-chests-to-open-even-with-a-solid-block-on.patch b/patches/server/0152-Option-for-chests-to-open-even-with-a-solid-block-on.patch index a30732549..cd1d4b935 100644 --- a/patches/server/0152-Option-for-chests-to-open-even-with-a-solid-block-on.patch +++ b/patches/server/0152-Option-for-chests-to-open-even-with-a-solid-block-on.patch @@ -4,11 +4,11 @@ Date: Sat, 12 Dec 2020 14:34:18 -0800 Subject: [PATCH] Option for chests to open even with a solid block on top -diff --git a/src/main/java/net/minecraft/server/BlockChest.java b/src/main/java/net/minecraft/server/BlockChest.java -index c4ff93a6b908c1bd157c7fe45b504909b189d09c..71a32a317e38b9c8f802fd5dd9ae546fb46eb020 100644 ---- a/src/main/java/net/minecraft/server/BlockChest.java -+++ b/src/main/java/net/minecraft/server/BlockChest.java -@@ -262,6 +262,7 @@ public class BlockChest extends BlockChestAbstract implements I +diff --git a/src/main/java/net/minecraft/world/level/block/BlockChest.java b/src/main/java/net/minecraft/world/level/block/BlockChest.java +index a45ee959f41e7f349ff2c309f21fa44ec671cb87..cddf8e3d34385eb264cd28ba6b4392d682df0360 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockChest.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockChest.java +@@ -306,6 +306,7 @@ public class BlockChest extends BlockChestAbstract implements I } private static boolean a(IBlockAccess iblockaccess, BlockPosition blockposition) { @@ -17,7 +17,7 @@ index c4ff93a6b908c1bd157c7fe45b504909b189d09c..71a32a317e38b9c8f802fd5dd9ae546f return iblockaccess.getType(blockposition1).isOccluding(iblockaccess, blockposition1); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index b630887b4ba9288e9724e97658d903ab334c3f8b..98211b159564f1674c84a5ec7cce37a1f077af5e 100644 +index b22344e942a212a204dd0935d3c6d55a37c23477..06af8583af105765e758ca4f6c81babbfe199e25 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -381,6 +381,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0153-Implement-TPSBar.patch b/patches/server/0153-Implement-TPSBar.patch index 408b753ad..19040b325 100644 --- a/patches/server/0153-Implement-TPSBar.patch +++ b/patches/server/0153-Implement-TPSBar.patch @@ -4,11 +4,11 @@ Date: Sat, 12 Dec 2020 21:19:05 -0600 Subject: [PATCH] Implement TPSBar -diff --git a/src/main/java/net/minecraft/server/CommandDispatcher.java b/src/main/java/net/minecraft/server/CommandDispatcher.java -index b5cc099746e9f05ea69bc438bda22a5ac3ebc3c5..bbd17231a4f7ad0ddde6eb5e589a6c403366cc36 100644 ---- a/src/main/java/net/minecraft/server/CommandDispatcher.java -+++ b/src/main/java/net/minecraft/server/CommandDispatcher.java -@@ -109,6 +109,7 @@ public class CommandDispatcher { +diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java +index a551636c2c59e68a5abb1cd5611c1d5c7e36f514..b7663a3d64ae5202abb93eabba6ec013bae96334 100644 +--- a/src/main/java/net/minecraft/commands/CommandDispatcher.java ++++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java +@@ -193,6 +193,7 @@ public class CommandDispatcher { CommandWhitelist.a(this.b); net.pl3x.purpur.command.DemoCommand.register(getDispatcher()); // Purpur net.pl3x.purpur.command.PingCommand.register(getDispatcher()); // Purpur @@ -17,10 +17,10 @@ index b5cc099746e9f05ea69bc438bda22a5ac3ebc3c5..bbd17231a4f7ad0ddde6eb5e589a6c40 if (commanddispatcher_servertype.d) { diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 4f589ca6cfc770bd26d0046736f7100272d7e48e..c8c4c4e7acd05768d2dc7dc3096cb208abcda0f3 100644 +index 5de12553875af626fa597ca440e52682624e35c8..e8146dad220330bdcc46e563172b40a66931d17c 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -472,6 +472,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 100) { PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send a book with too many pages"); @@ -16,7 +16,7 @@ index 7be03bb416a5723ce65411ba5d0b967040e8033c..9ff35aa827cf5b937b8dcbcabafd2730 minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); return; } -@@ -982,6 +983,7 @@ public class PlayerConnection implements PacketListenerPlayIn { +@@ -1127,6 +1128,7 @@ public class PlayerConnection implements PacketListenerPlayIn { int byteLength = testString.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; if (byteLength > 256 * 4) { PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send a book with with a page too large!"); @@ -24,7 +24,7 @@ index 7be03bb416a5723ce65411ba5d0b967040e8033c..9ff35aa827cf5b937b8dcbcabafd2730 minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); return; } -@@ -1005,6 +1007,7 @@ public class PlayerConnection implements PacketListenerPlayIn { +@@ -1150,6 +1152,7 @@ public class PlayerConnection implements PacketListenerPlayIn { if (byteTotal > byteAllowed) { PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send too large of a book. Book Size: " + byteTotal + " - Allowed: "+ byteAllowed + " - Pages: " + pageList.size()); diff --git a/patches/server/0156-Full-netherite-armor-grants-fire-resistance.patch b/patches/server/0156-Full-netherite-armor-grants-fire-resistance.patch index c08354304..3ade642f1 100644 --- a/patches/server/0156-Full-netherite-armor-grants-fire-resistance.patch +++ b/patches/server/0156-Full-netherite-armor-grants-fire-resistance.patch @@ -4,11 +4,11 @@ Date: Thu, 24 Dec 2020 11:00:15 -0600 Subject: [PATCH] Full netherite armor grants fire resistance -diff --git a/src/main/java/net/minecraft/server/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java -index 84fdb4710331791dfb180ce401f1da6962635b54..708f9c5d0b6e30512b3d3ea45ec2b2baf9482669 100644 ---- a/src/main/java/net/minecraft/server/EntityHuman.java -+++ b/src/main/java/net/minecraft/server/EntityHuman.java -@@ -237,6 +237,16 @@ public abstract class EntityHuman extends EntityLiving { +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index 907bfe42bd866188639f7d25150fcde039c1e5f7..b63019f40b28a2e543528a7919bbc08a4ccc8f07 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -334,6 +334,16 @@ public abstract class EntityHuman extends EntityLiving { this.addEffect(new MobEffect(MobEffects.WATER_BREATHING, 200, 0, false, false, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TURTLE_HELMET); // CraftBukkit } @@ -26,7 +26,7 @@ index 84fdb4710331791dfb180ce401f1da6962635b54..708f9c5d0b6e30512b3d3ea45ec2b2ba protected ItemCooldown i() { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index f19da65bcc79bd70bf9b5ac33867e49b6838cb7d..af33ee28276ac9848805765af6d51bf4b9f3c372 100644 +index 6afdcad6b6ab47f77dba3dcc97c2b6580b774e1c..73213bf975ffe38ff6ee9b05c5a48b232f767727 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -310,6 +310,19 @@ public class PurpurWorldConfig { diff --git a/patches/server/0157-Fix-rotating-UP-DOWN-CW-and-CCW.patch b/patches/server/0157-Fix-rotating-UP-DOWN-CW-and-CCW.patch index febdd94f1..187d93067 100644 --- a/patches/server/0157-Fix-rotating-UP-DOWN-CW-and-CCW.patch +++ b/patches/server/0157-Fix-rotating-UP-DOWN-CW-and-CCW.patch @@ -4,11 +4,11 @@ Date: Wed, 6 Jan 2021 02:19:29 -0600 Subject: [PATCH] Fix rotating UP/DOWN CW and CCW -diff --git a/src/main/java/net/minecraft/server/EnumDirection.java b/src/main/java/net/minecraft/server/EnumDirection.java -index 23796bd657f071a337fdf76d777e33c207baf7a7..814b168eaa4b74dce2b83bc8aa557b33aebf35fa 100644 ---- a/src/main/java/net/minecraft/server/EnumDirection.java -+++ b/src/main/java/net/minecraft/server/EnumDirection.java -@@ -123,6 +123,12 @@ public enum EnumDirection implements INamable { +diff --git a/src/main/java/net/minecraft/core/EnumDirection.java b/src/main/java/net/minecraft/core/EnumDirection.java +index 29d747f7fc5824a222755ebf96dfe053896d43d0..9f1ea11d0bc15b8b0069fcf46ea2f6751c5e3064 100644 +--- a/src/main/java/net/minecraft/core/EnumDirection.java ++++ b/src/main/java/net/minecraft/core/EnumDirection.java +@@ -127,6 +127,12 @@ public enum EnumDirection implements INamable { return EnumDirection.NORTH; case EAST: return EnumDirection.SOUTH; @@ -21,7 +21,7 @@ index 23796bd657f071a337fdf76d777e33c207baf7a7..814b168eaa4b74dce2b83bc8aa557b33 default: throw new IllegalStateException("Unable to get Y-rotated facing of " + this); } -@@ -139,6 +145,12 @@ public enum EnumDirection implements INamable { +@@ -143,6 +149,12 @@ public enum EnumDirection implements INamable { return EnumDirection.SOUTH; case EAST: return EnumDirection.NORTH; diff --git a/patches/server/0158-Add-MC-4-fix-back.patch b/patches/server/0158-Add-MC-4-fix-back.patch index 01048de81..c3d1fe8bf 100644 --- a/patches/server/0158-Add-MC-4-fix-back.patch +++ b/patches/server/0158-Add-MC-4-fix-back.patch @@ -4,11 +4,11 @@ Date: Thu, 7 Jan 2021 07:51:25 -0600 Subject: [PATCH] Add MC-4 fix back -diff --git a/src/main/java/net/minecraft/server/EntityItem.java b/src/main/java/net/minecraft/server/EntityItem.java -index c25dce9a75b0e79f9b59f31892d863f46e2565e9..14aa48759c78cd61574a25d7377d8e35d8559599 100644 ---- a/src/main/java/net/minecraft/server/EntityItem.java -+++ b/src/main/java/net/minecraft/server/EntityItem.java -@@ -543,7 +543,7 @@ public class EntityItem extends Entity { +diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +index 3b84039a76843a0784e2d71bb66dc322450c2cab..8640472dba341285a37edb086e1bea387204fd04 100644 +--- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java ++++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +@@ -571,7 +571,7 @@ public class EntityItem extends Entity { // Paper start - fix MC-4 public void setPositionRaw(double x, double y, double z) { diff --git a/patches/server/0159-Add-mobGriefing-bypass-to-everything-affected.patch b/patches/server/0159-Add-mobGriefing-bypass-to-everything-affected.patch index de928e0a4..18babc0fd 100644 --- a/patches/server/0159-Add-mobGriefing-bypass-to-everything-affected.patch +++ b/patches/server/0159-Add-mobGriefing-bypass-to-everything-affected.patch @@ -5,111 +5,81 @@ Subject: [PATCH] Add mobGriefing bypass to everything affected This adds the "bypass-mob-griefing" world config option to everything that is affected by the gamerule. -diff --git a/src/main/java/net/minecraft/server/BlockCampfire.java b/src/main/java/net/minecraft/server/BlockCampfire.java -index 99decab11b3561edb0fea8964bfb97ccc997b772..e4cc567d28a5368f975e29c7d18dba007d914584 100644 ---- a/src/main/java/net/minecraft/server/BlockCampfire.java -+++ b/src/main/java/net/minecraft/server/BlockCampfire.java -@@ -139,7 +139,7 @@ public class BlockCampfire extends BlockTileEntity implements IBlockWaterlogged - public void a(World world, IBlockData iblockdata, MovingObjectPositionBlock movingobjectpositionblock, IProjectile iprojectile) { - if (!world.isClientSide && iprojectile.isBurning()) { - Entity entity = iprojectile.getShooter(); -- boolean flag = entity == null || entity instanceof EntityHuman || world.getGameRules().getBoolean(GameRules.MOB_GRIEFING); -+ boolean flag = entity == null || entity instanceof EntityHuman || world.purpurConfig.fireballsBypassMobGriefing || world.getGameRules().getBoolean(GameRules.MOB_GRIEFING); // Purpur +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index f3f528065eb9ee2f385edbaceeeddef39552485c..1e57358c02e67a6b062149926ada46696da24487 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -1571,7 +1571,7 @@ public abstract class EntityLiving extends Entity { + boolean flag = false; - if (flag && !(Boolean) iblockdata.get(BlockCampfire.LIT) && !(Boolean) iblockdata.get(BlockCampfire.d)) { - BlockPosition blockposition = movingobjectpositionblock.getBlockPosition(); -diff --git a/src/main/java/net/minecraft/server/BlockCrops.java b/src/main/java/net/minecraft/server/BlockCrops.java -index 0fdc960fa3bbe6506185480a7a86d5009d70b385..d49c309d7c31b3be0a21544ba23c0fd663f3317b 100644 ---- a/src/main/java/net/minecraft/server/BlockCrops.java -+++ b/src/main/java/net/minecraft/server/BlockCrops.java -@@ -144,7 +144,7 @@ public class BlockCrops extends BlockPlant implements IBlockFragilePlantElement + if (this.killed && entityliving instanceof EntityWither) { // Paper +- if (this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { ++ if (this.world.purpurConfig.witherBypassMobGriefing || this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { // Purpur + BlockPosition blockposition = this.getChunkCoordinates(); + IBlockData iblockdata = Blocks.WITHER_ROSE.getBlockData(); + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalBreakDoor.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalBreakDoor.java +index d785066e2a52699c18315f7244d80db6cab0c736..6c40b070c674f2b120b860b78a63d0a6635d2f5b 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalBreakDoor.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalBreakDoor.java +@@ -34,7 +34,7 @@ public class PathfinderGoalBreakDoor extends PathfinderGoalDoorInteract { @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -- if (entity instanceof EntityRavager && !CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, Blocks.AIR.getBlockData(), !world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)).isCancelled()) { // CraftBukkit -+ if (entity instanceof EntityRavager && !CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, Blocks.AIR.getBlockData(), (!world.purpurConfig.ravagerBypassMobGriefing && !world.getGameRules().getBoolean(GameRules.MOB_GRIEFING))).isCancelled()) { // CraftBukkit // Purpur - world.a(blockposition, true, entity); - } + public boolean a() { +- return !super.a() ? false : (!this.entity.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) ? false : this.a(this.entity.world.getDifficulty()) && !this.g()); ++ return !super.a() ? false : ((!this.entity.world.purpurConfig.zombieBypassMobGriefing && !this.entity.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) ? false : this.a(this.entity.world.getDifficulty()) && !this.g()); // Purpur + } -diff --git a/src/main/java/net/minecraft/server/BlockSoil.java b/src/main/java/net/minecraft/server/BlockSoil.java -index 099e0d3df219408ebe2a741a02e53eb9f7def28e..73dc0f499c456c21d298013fbab8c79ebcdecd6b 100644 ---- a/src/main/java/net/minecraft/server/BlockSoil.java -+++ b/src/main/java/net/minecraft/server/BlockSoil.java -@@ -76,7 +76,7 @@ public class BlockSoil extends Block { @Override - public void fallOn(World world, BlockPosition blockposition, Entity entity, float f) { - super.fallOn(world, blockposition, entity, f); // CraftBukkit - moved here as game rules / events shouldn't affect fall damage. -- if (!world.isClientSide && world.random.nextFloat() < f - 0.5F && entity instanceof EntityLiving && (entity instanceof EntityHuman || world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) && entity.getWidth() * entity.getWidth() * entity.getHeight() > 0.512F) { -+ if (!world.isClientSide && world.random.nextFloat() < f - 0.5F && entity instanceof EntityLiving && (entity instanceof EntityHuman || world.purpurConfig.farmlandBypassMobGriefing || world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) && entity.getWidth() * entity.getWidth() * entity.getHeight() > 0.512F) { // Purpur - // CraftBukkit start - Interact soil - org.bukkit.event.Cancellable cancellable; - if (entity instanceof EntityHuman) { -diff --git a/src/main/java/net/minecraft/server/BlockTurtleEgg.java b/src/main/java/net/minecraft/server/BlockTurtleEgg.java -index 0f147dc938cef428452bd3137c68b52a78f9fbde..276aac9afd5d987cf388a87718453c4737049073 100644 ---- a/src/main/java/net/minecraft/server/BlockTurtleEgg.java -+++ b/src/main/java/net/minecraft/server/BlockTurtleEgg.java -@@ -177,7 +177,7 @@ public class BlockTurtleEgg extends Block { +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalEatTile.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalEatTile.java +index 6737dd77c8f46edf353f951b5adb4399142a1753..06dbce54602d02382e9d47b7e6925cfc686d26f6 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalEatTile.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalEatTile.java +@@ -19,7 +19,7 @@ public class PathfinderGoalEatTile extends PathfinderGoal { + + private static final Predicate a = BlockStatePredicate.a(Blocks.GRASS); + private final EntityInsentient b; +- private final World c; ++ private final World c; private final World getWorld() { return c; } // Purpur - OBFHELPER + private int d; + + public PathfinderGoalEatTile(EntityInsentient entityinsentient) { +@@ -68,7 +68,7 @@ public class PathfinderGoalEatTile extends PathfinderGoal { + + if (PathfinderGoalEatTile.a.test(this.c.getType(blockposition))) { + // CraftBukkit +- if (!CraftEventFactory.callEntityChangeBlockEvent(this.b, blockposition, Blocks.AIR.getBlockData(), !this.c.getGameRules().getBoolean(GameRules.MOB_GRIEFING)).isCancelled()) { ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.b, blockposition, Blocks.AIR.getBlockData(), !this.getWorld().purpurConfig.sheepBypassMobGriefing && !this.c.getGameRules().getBoolean(GameRules.MOB_GRIEFING)).isCancelled()) { // Purpur + this.c.b(blockposition, false); + } + +@@ -78,7 +78,7 @@ public class PathfinderGoalEatTile extends PathfinderGoal { + + if (this.c.getType(blockposition1).a(Blocks.GRASS_BLOCK)) { + // CraftBukkit +- if (!CraftEventFactory.callEntityChangeBlockEvent(this.b, blockposition, Blocks.AIR.getBlockData(), !this.c.getGameRules().getBoolean(GameRules.MOB_GRIEFING)).isCancelled()) { ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.b, blockposition, Blocks.AIR.getBlockData(), !this.getWorld().purpurConfig.sheepBypassMobGriefing && !this.c.getGameRules().getBoolean(GameRules.MOB_GRIEFING)).isCancelled()) { // Purpur + this.c.triggerEffect(2001, blockposition1, Block.getCombinedId(Blocks.GRASS_BLOCK.getBlockData())); + this.c.setTypeAndData(blockposition1, Blocks.DIRT.getBlockData(), 2); + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.java +index 61a62c093b24c43064f116630d85096159e082d3..2519a78f7e5dd759680a1f47a1047885d4ad32f1 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.java +@@ -41,7 +41,7 @@ public class PathfinderGoalRemoveBlock extends PathfinderGoalGotoTarget { + + @Override + public boolean a() { +- if (!this.entity.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { ++ if (!this.entity.world.purpurConfig.zombieBypassMobGriefing && !this.entity.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { // Purpur return false; - } - if (entity instanceof EntityLiving && !(entity instanceof EntityHuman)) { -- return world.getGameRules().getBoolean(GameRules.MOB_GRIEFING); -+ return world.purpurConfig.turtleEggsBypassMobGriefing || world.getGameRules().getBoolean(GameRules.MOB_GRIEFING); // Purpur - } - return true; - // Purpur end -diff --git a/src/main/java/net/minecraft/server/EntityEnderDragon.java b/src/main/java/net/minecraft/server/EntityEnderDragon.java -index 75e834caaf7bb64a3d51d793e86aa702f6ccb0ae..e2377c6e8a98be431953533bf0b2060028caad45 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/server/EntityEnderDragon.java -@@ -489,7 +489,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - Block block = iblockdata.getBlock(); - - if (!iblockdata.isAir() && iblockdata.getMaterial() != Material.FIRE) { -- if (this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) && !TagsBlock.DRAGON_IMMUNE.isTagged(block)) { -+ if ((this.world.purpurConfig.enderDragonBypassMobGriefing || this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) && !TagsBlock.DRAGON_IMMUNE.isTagged(block)) { // Purpur - // CraftBukkit start - Add blocks to list rather than destroying them - // flag1 = this.world.a(blockposition, false) || flag1; - flag1 = true; -diff --git a/src/main/java/net/minecraft/server/EntityEnderman.java b/src/main/java/net/minecraft/server/EntityEnderman.java -index c03232ac1e2b450b64430f8d56bfebd30fa37155..4d575d29cd446cd65cea7cdeb2541e0c3112d660 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderman.java -+++ b/src/main/java/net/minecraft/server/EntityEnderman.java -@@ -399,7 +399,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - @Override - public boolean a() { - if (!enderman.world.purpurConfig.endermanAllowGriefing) return false; // Purpur -- return this.enderman.getCarried() != null ? false : (!this.enderman.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) ? false : this.enderman.getRandom().nextInt(20) == 0); -+ return this.enderman.getCarried() != null ? false : (!this.enderman.world.purpurConfig.endermanBypassMobGriefing && !this.enderman.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) ? false : this.enderman.getRandom().nextInt(20) == 0); // Purpur - } - - @Override -@@ -442,7 +442,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - @Override - public boolean a() { - if (!getEnderman().world.purpurConfig.endermanAllowGriefing) return false; // Purpur -- return this.a.getCarried() == null ? false : (!this.a.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) ? false : this.a.getRandom().nextInt(2000) == 0); -+ return this.a.getCarried() == null ? false : (!this.a.world.purpurConfig.endermanBypassMobGriefing && !this.a.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) ? false : this.a.getRandom().nextInt(2000) == 0); // Purpur - } - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityEvoker.java b/src/main/java/net/minecraft/server/EntityEvoker.java -index f0ecc6e6ef5843714a6423af5d6619856ef23977..5f24c36bf45a656e220475449113786732a47c56 100644 ---- a/src/main/java/net/minecraft/server/EntityEvoker.java -+++ b/src/main/java/net/minecraft/server/EntityEvoker.java -@@ -134,7 +134,7 @@ public class EntityEvoker extends EntityIllagerWizard { - return false; - } else if (EntityEvoker.this.ticksLived < this.c) { - return false; -- } else if (!EntityEvoker.this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { -+ } else if (!EntityEvoker.this.world.purpurConfig.evokerBypassMobGriefing && !EntityEvoker.this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { // Purpur - return false; - } else { - List list = EntityEvoker.this.world.a(EntitySheep.class, this.e, EntityEvoker.this, EntityEvoker.this.getBoundingBox().grow(16.0D, 4.0D, 16.0D)); -diff --git a/src/main/java/net/minecraft/server/EntityFox.java b/src/main/java/net/minecraft/server/EntityFox.java -index 7a3fb7a41e987adee675fbfd11f2648cf5de3e53..ff78bd607f19a1b9f37281946db3f705c844f7cc 100644 ---- a/src/main/java/net/minecraft/server/EntityFox.java -+++ b/src/main/java/net/minecraft/server/EntityFox.java -@@ -1002,7 +1002,7 @@ public class EntityFox extends EntityAnimal { + } else if (this.c > 0) { + --this.c; +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java +index b8b0ee65798dc94d707fa64bd53fdda5506331d9..355735c2efbba62481d059b8e733c9c70e834be1 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java +@@ -1075,7 +1075,7 @@ public class EntityFox extends EntityAnimal { } protected void n() { @@ -118,11 +88,142 @@ index 7a3fb7a41e987adee675fbfd11f2648cf5de3e53..ff78bd607f19a1b9f37281946db3f705 IBlockData iblockdata = EntityFox.this.world.getType(this.e); if (iblockdata.a(Blocks.SWEET_BERRY_BUSH)) { -diff --git a/src/main/java/net/minecraft/server/EntityLargeFireball.java b/src/main/java/net/minecraft/server/EntityLargeFireball.java -index d12de20cf4bb2345c616d3cc0b9f50bddb5135ee..3f3be1b2ded6ad118ae7860c1231c7affc0715b6 100644 ---- a/src/main/java/net/minecraft/server/EntityLargeFireball.java -+++ b/src/main/java/net/minecraft/server/EntityLargeFireball.java -@@ -8,19 +8,19 @@ public class EntityLargeFireball extends EntityFireballFireball { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java b/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java +index 284c52276b2fd816990c23b7b8a9ee50e70ab005..acb4c79b23fada090c5605cd352a573bdb0667bf 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java +@@ -518,7 +518,7 @@ public class EntityRabbit extends EntityAnimal { + @Override + public boolean a() { + if (this.c <= 0) { +- if (!this.entity.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { ++ if (!this.entity.world.purpurConfig.rabbitBypassMobGriefing && !this.entity.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { // Purpur + return false; + } + +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java b/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java +index 88db8ff8cb415b84ab98cc0550c705d5a472230c..17f27d2bf5be746a0fa0e1e0fecab8158b2b3587 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java +@@ -123,7 +123,7 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt + this.damageEntity(CraftEventFactory.MELTING, 1.0F); // CraftBukkit - DamageSource.BURN -> CraftEventFactory.MELTING + } + +- if (!this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { ++ if (!this.world.purpurConfig.snowGolemBypassMobGriefing && !this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { // Purpur + return; + } + +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +index 999a6d17eccd6305c0063e1558abfe70d72c39fe..a81d782877ff6116477792fa4cec0846e56ed384 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +@@ -539,7 +539,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { + Block block = iblockdata.getBlock(); + + if (!iblockdata.isAir() && iblockdata.getMaterial() != Material.FIRE) { +- if (this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) && !TagsBlock.DRAGON_IMMUNE.isTagged(block)) { ++ if ((this.world.purpurConfig.enderDragonBypassMobGriefing || this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) && !TagsBlock.DRAGON_IMMUNE.isTagged(block)) { // Purpur + // CraftBukkit start - Add blocks to list rather than destroying them + // flag1 = this.world.a(blockposition, false) || flag1; + flag1 = true; +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java +index beb4d59faf4bd7501468b2eaa0e866613625e963..fa6b72c7a12b20f8ccffa360a3895e4d8f4277e4 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java +@@ -380,7 +380,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { + if (this.getInvul() > 0) { + i = this.getInvul() - 1; + if (i <= 0) { +- Explosion.Effect explosion_effect = this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) ? Explosion.Effect.DESTROY : Explosion.Effect.NONE; ++ Explosion.Effect explosion_effect = (this.world.purpurConfig.witherBypassMobGriefing || this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) ? Explosion.Effect.DESTROY : Explosion.Effect.NONE; // Purpur + // CraftBukkit start + // this.world.createExplosion(this, this.locX(), this.getHeadY(), this.locZ(), 7.0F, false, explosion_effect); + ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), 7.0F, false); +@@ -492,7 +492,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { + + if (this.bw > 0) { + --this.bw; +- if (this.bw == 0 && this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { ++ if (this.bw == 0 && (this.world.purpurConfig.witherBypassMobGriefing || this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING))) { // Purpur + i = MathHelper.floor(this.locY()); + j = MathHelper.floor(this.locX()); + int j1 = MathHelper.floor(this.locZ()); +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +index 478ac5bfdc69b5c3e24906bb5e0ea1dff81cea98..ea500a6080f73dcc35d83a3b5a170f57dedaa431 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +@@ -455,7 +455,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { + @Override + public boolean a() { + if (!enderman.world.purpurConfig.endermanAllowGriefing) return false; // Purpur +- return this.enderman.getCarried() != null ? false : (!this.enderman.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) ? false : this.enderman.getRandom().nextInt(20) == 0); ++ return this.enderman.getCarried() != null ? false : (!this.enderman.world.purpurConfig.endermanBypassMobGriefing && !this.enderman.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) ? false : this.enderman.getRandom().nextInt(20) == 0); // Purpur + } + + @Override +@@ -498,7 +498,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { + @Override + public boolean a() { + if (!getEnderman().world.purpurConfig.endermanAllowGriefing) return false; // Purpur +- return this.a.getCarried() == null ? false : (!this.a.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) ? false : this.a.getRandom().nextInt(2000) == 0); ++ return this.a.getCarried() == null ? false : (!this.a.world.purpurConfig.endermanBypassMobGriefing && !this.a.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) ? false : this.a.getRandom().nextInt(2000) == 0); // Purpur + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java b/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java +index 8d7b8d2ac9a7340e2cfd0d1b8963e4e4d97e8bc8..8a219ac18307c715913f5c2a80b1ff35a2ea8b93 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java +@@ -171,7 +171,7 @@ public class EntityEvoker extends EntityIllagerWizard { + return false; + } else if (EntityEvoker.this.ticksLived < this.c) { + return false; +- } else if (!EntityEvoker.this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { ++ } else if (!EntityEvoker.this.world.purpurConfig.evokerBypassMobGriefing && !EntityEvoker.this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { // Purpur + return false; + } else { + List list = EntityEvoker.this.world.a(EntitySheep.class, this.e, EntityEvoker.this, EntityEvoker.this.getBoundingBox().grow(16.0D, 4.0D, 16.0D)); +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java b/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java +index 80c3cd540a46e249e85586e8d7a2f0f6226091fc..6809c93fe435d183a27204fb4460fd68a86aa04f 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java +@@ -179,7 +179,7 @@ public class EntityRavager extends EntityRaider { + this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue(MathHelper.d(0.1D, d1, d0)); + } + +- if (this.positionChanged && this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { ++ if (this.positionChanged && (this.world.purpurConfig.ravagerBypassMobGriefing || this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING))) { // Purpur + boolean flag = false; + AxisAlignedBB axisalignedbb = this.getBoundingBox().g(0.2D); + Iterator iterator = BlockPosition.b(MathHelper.floor(axisalignedbb.minX), MathHelper.floor(axisalignedbb.minY), MathHelper.floor(axisalignedbb.minZ), MathHelper.floor(axisalignedbb.maxX), MathHelper.floor(axisalignedbb.maxY), MathHelper.floor(axisalignedbb.maxZ)).iterator(); +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java b/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java +index a0a1e5977a3cbc8e9befd827dd1e15352a2c0c39..cbdb512c924ac54e925f8c52558d24d3286d31ce 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java +@@ -172,7 +172,7 @@ public class EntitySilverfish extends EntityMonster { + } else { + Random random = this.a.getRandom(); + +- if (this.a.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) && random.nextInt(10) == 0) { ++ if ((this.a.world.purpurConfig.silverfishBypassMobGriefing || this.a.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) && random.nextInt(10) == 0) { // Purpur + this.h = EnumDirection.a(random); + BlockPosition blockposition = (new BlockPosition(this.a.locX(), this.a.locY() + 0.5D, this.a.locZ())).shift(this.h); + IBlockData iblockdata = this.a.world.getType(blockposition); +@@ -260,7 +260,7 @@ public class EntitySilverfish extends EntityMonster { + continue; + } + // CraftBukkit end +- if (world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { ++ if (world.purpurConfig.silverfishBypassMobGriefing || world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { // Purpur + world.a(blockposition1, true, this.silverfish); + } else { + world.setTypeAndData(blockposition1, ((BlockMonsterEggs) block).c().getBlockData(), 3); +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityLargeFireball.java b/src/main/java/net/minecraft/world/entity/projectile/EntityLargeFireball.java +index e860737bacfea0a1d728dbaaf41d62165658ad89..61f06eacb4ea4ef869b60c9014cc23b25583eead 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityLargeFireball.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityLargeFireball.java +@@ -19,19 +19,19 @@ public class EntityLargeFireball extends EntityFireballFireball { public EntityLargeFireball(EntityTypes entitytypes, World world) { super(entitytypes, world); @@ -145,85 +246,11 @@ index d12de20cf4bb2345c616d3cc0b9f50bddb5135ee..3f3be1b2ded6ad118ae7860c1231c7af // CraftBukkit start - fire ExplosionPrimeEvent ExplosionPrimeEvent event = new ExplosionPrimeEvent((org.bukkit.entity.Explosive) this.getBukkitEntity()); -diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index 96e9be81429aa7bf215d2c2cdf865606e3a2707c..8b8e6b8cfbdc591eb8681bc672975ae6198ef263 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -1475,7 +1475,7 @@ public abstract class EntityLiving extends Entity { - boolean flag = false; - - if (this.killed && entityliving instanceof EntityWither) { // Paper -- if (this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { -+ if (this.world.purpurConfig.witherBypassMobGriefing || this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { // Purpur - BlockPosition blockposition = this.getChunkCoordinates(); - IBlockData iblockdata = Blocks.WITHER_ROSE.getBlockData(); - -diff --git a/src/main/java/net/minecraft/server/EntityRabbit.java b/src/main/java/net/minecraft/server/EntityRabbit.java -index 75f42e91449de71e154e2169ea986ff09224e2f0..9017e56d4ecff810b07271362dce1c1354a3404d 100644 ---- a/src/main/java/net/minecraft/server/EntityRabbit.java -+++ b/src/main/java/net/minecraft/server/EntityRabbit.java -@@ -462,7 +462,7 @@ public class EntityRabbit extends EntityAnimal { - @Override - public boolean a() { - if (this.c <= 0) { -- if (!this.entity.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { -+ if (!this.entity.world.purpurConfig.rabbitBypassMobGriefing && !this.entity.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { // Purpur - return false; - } - -diff --git a/src/main/java/net/minecraft/server/EntityRaider.java b/src/main/java/net/minecraft/server/EntityRaider.java -index ad2a2c27f0ef064064ded28cc049a6856d476808..e07f224289a937689a26d58639899abbfd6a6302 100644 ---- a/src/main/java/net/minecraft/server/EntityRaider.java -+++ b/src/main/java/net/minecraft/server/EntityRaider.java -@@ -496,7 +496,7 @@ public abstract class EntityRaider extends EntityMonsterPatrolling { - - @Override - public boolean a() { -- if (!getRaider().world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) || !getRaider().canPickupLoot()) return false; // Paper - respect game and entity rules for picking up items -+ if ((!getRaider().world.purpurConfig.pillagerBypassMobGriefing && !getRaider().world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) || !getRaider().canPickupLoot()) return false; // Paper - respect game and entity rules for picking up items // Purpur - Raid raid = this.b.fa(); - - if (this.b.fb() && !this.b.fa().a() && this.b.eN() && !ItemStack.matches(this.b.getEquipment(EnumItemSlot.HEAD), Raid.s())) { -diff --git a/src/main/java/net/minecraft/server/EntityRavager.java b/src/main/java/net/minecraft/server/EntityRavager.java -index 820938c76e787fac6c65eb000491232d5b749dee..3606440e41ab3193fadebb455c0967dbc0ccbb63 100644 ---- a/src/main/java/net/minecraft/server/EntityRavager.java -+++ b/src/main/java/net/minecraft/server/EntityRavager.java -@@ -137,7 +137,7 @@ public class EntityRavager extends EntityRaider { - this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue(MathHelper.d(0.1D, d1, d0)); - } - -- if (this.positionChanged && this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { -+ if (this.positionChanged && (this.world.purpurConfig.ravagerBypassMobGriefing || this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING))) { // Purpur - boolean flag = false; - AxisAlignedBB axisalignedbb = this.getBoundingBox().g(0.2D); - Iterator iterator = BlockPosition.b(MathHelper.floor(axisalignedbb.minX), MathHelper.floor(axisalignedbb.minY), MathHelper.floor(axisalignedbb.minZ), MathHelper.floor(axisalignedbb.maxX), MathHelper.floor(axisalignedbb.maxY), MathHelper.floor(axisalignedbb.maxZ)).iterator(); -diff --git a/src/main/java/net/minecraft/server/EntitySilverfish.java b/src/main/java/net/minecraft/server/EntitySilverfish.java -index 6bd00f0b5735d694e370cf85fdbf508c31fc7c27..9ccb7a805adf8c1e429f3fab2bc261c4dad5eda8 100644 ---- a/src/main/java/net/minecraft/server/EntitySilverfish.java -+++ b/src/main/java/net/minecraft/server/EntitySilverfish.java -@@ -144,7 +144,7 @@ public class EntitySilverfish extends EntityMonster { - } else { - Random random = this.a.getRandom(); - -- if (this.a.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) && random.nextInt(10) == 0) { -+ if ((this.a.world.purpurConfig.silverfishBypassMobGriefing || this.a.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) && random.nextInt(10) == 0) { // Purpur - this.h = EnumDirection.a(random); - BlockPosition blockposition = (new BlockPosition(this.a.locX(), this.a.locY() + 0.5D, this.a.locZ())).shift(this.h); - IBlockData iblockdata = this.a.world.getType(blockposition); -@@ -232,7 +232,7 @@ public class EntitySilverfish extends EntityMonster { - continue; - } - // CraftBukkit end -- if (world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { -+ if (world.purpurConfig.silverfishBypassMobGriefing || world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { // Purpur - world.a(blockposition1, true, this.silverfish); - } else { - world.setTypeAndData(blockposition1, ((BlockMonsterEggs) block).c().getBlockData(), 3); -diff --git a/src/main/java/net/minecraft/server/EntitySmallFireball.java b/src/main/java/net/minecraft/server/EntitySmallFireball.java -index 4ed7a20bfed267776628457a4b33178bac7d1972..e7e12ce2338102b875444c3f3cc767858de38dca 100644 ---- a/src/main/java/net/minecraft/server/EntitySmallFireball.java -+++ b/src/main/java/net/minecraft/server/EntitySmallFireball.java -@@ -12,7 +12,7 @@ public class EntitySmallFireball extends EntityFireballFireball { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntitySmallFireball.java b/src/main/java/net/minecraft/world/entity/projectile/EntitySmallFireball.java +index bf747cbf6e1ef9ea9d1d41d0441b29a46ce874c0..53e02e512b8bcebac105e421991b3554a7ad699a 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntitySmallFireball.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntitySmallFireball.java +@@ -26,7 +26,7 @@ public class EntitySmallFireball extends EntityFireballFireball { super(EntityTypes.SMALL_FIREBALL, entityliving, d0, d1, d2, world); // CraftBukkit start if (this.getShooter() != null && this.getShooter() instanceof EntityInsentient) { @@ -232,46 +259,11 @@ index 4ed7a20bfed267776628457a4b33178bac7d1972..e7e12ce2338102b875444c3f3cc76785 } // CraftBukkit end } -diff --git a/src/main/java/net/minecraft/server/EntitySnowman.java b/src/main/java/net/minecraft/server/EntitySnowman.java -index 1dd13dfea91a05b1e83b065328092a17d41a605f..eb6344a5671408ae9fdd6013774baa13addf304b 100644 ---- a/src/main/java/net/minecraft/server/EntitySnowman.java -+++ b/src/main/java/net/minecraft/server/EntitySnowman.java -@@ -86,7 +86,7 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt - this.damageEntity(CraftEventFactory.MELTING, 1.0F); // CraftBukkit - DamageSource.BURN -> CraftEventFactory.MELTING - } - -- if (!this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { -+ if (!this.world.purpurConfig.snowGolemBypassMobGriefing && !this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { // Purpur - return; - } - -diff --git a/src/main/java/net/minecraft/server/EntityWither.java b/src/main/java/net/minecraft/server/EntityWither.java -index edc58c5cb178ea9a53f960bd4a460f394b13ab64..27bfef57cfa1386e81c6409be49ea6898057e631 100644 ---- a/src/main/java/net/minecraft/server/EntityWither.java -+++ b/src/main/java/net/minecraft/server/EntityWither.java -@@ -323,7 +323,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - if (this.getInvul() > 0) { - i = this.getInvul() - 1; - if (i <= 0) { -- Explosion.Effect explosion_effect = this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) ? Explosion.Effect.DESTROY : Explosion.Effect.NONE; -+ Explosion.Effect explosion_effect = (this.world.purpurConfig.witherBypassMobGriefing || this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) ? Explosion.Effect.DESTROY : Explosion.Effect.NONE; // Purpur - // CraftBukkit start - // this.world.createExplosion(this, this.locX(), this.getHeadY(), this.locZ(), 7.0F, false, explosion_effect); - ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), 7.0F, false); -@@ -435,7 +435,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - - if (this.bw > 0) { - --this.bw; -- if (this.bw == 0 && this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { -+ if (this.bw == 0 && (this.world.purpurConfig.witherBypassMobGriefing || this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING))) { // Purpur - i = MathHelper.floor(this.locY()); - j = MathHelper.floor(this.locX()); - int j1 = MathHelper.floor(this.locZ()); -diff --git a/src/main/java/net/minecraft/server/EntityWitherSkull.java b/src/main/java/net/minecraft/server/EntityWitherSkull.java -index 4a97a7517dc1a2a25c578d9e168240cc19ab0831..fedc78e4111864d1413e6fcd588b9951595b463a 100644 ---- a/src/main/java/net/minecraft/server/EntityWitherSkull.java -+++ b/src/main/java/net/minecraft/server/EntityWitherSkull.java -@@ -73,7 +73,7 @@ public class EntityWitherSkull extends EntityFireball { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityWitherSkull.java b/src/main/java/net/minecraft/world/entity/projectile/EntityWitherSkull.java +index 2fe0e32a1158cccb3060f5a986c9fc41a0237aa8..616b5267d1d94b2be37ec48983b45e4478502fb5 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityWitherSkull.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityWitherSkull.java +@@ -94,7 +94,7 @@ public class EntityWitherSkull extends EntityFireball { protected void a(MovingObjectPosition movingobjectposition) { super.a(movingobjectposition); if (!this.world.isClientSide) { @@ -280,65 +272,73 @@ index 4a97a7517dc1a2a25c578d9e168240cc19ab0831..fedc78e4111864d1413e6fcd588b9951 // CraftBukkit start // this.world.createExplosion(this, this.locX(), this.locY(), this.locZ(), 1.0F, false, explosion_effect); -diff --git a/src/main/java/net/minecraft/server/PathfinderGoalBreakDoor.java b/src/main/java/net/minecraft/server/PathfinderGoalBreakDoor.java -index 23870a271b759a953a095df835e08ea2a09f4218..c31bacf786ea750e922c938c042656515d8b0041 100644 ---- a/src/main/java/net/minecraft/server/PathfinderGoalBreakDoor.java -+++ b/src/main/java/net/minecraft/server/PathfinderGoalBreakDoor.java -@@ -27,7 +27,7 @@ public class PathfinderGoalBreakDoor extends PathfinderGoalDoorInteract { +diff --git a/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java b/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java +index ff41ee884e3e46af1b1e9fb550f0abc6998fd031..8eec32af12c69e1963dcd304a25ec4811b2f1f5a 100644 +--- a/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java ++++ b/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java +@@ -532,7 +532,7 @@ public abstract class EntityRaider extends EntityMonsterPatrolling { + + @Override + public boolean a() { +- if (!getRaider().world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) || !getRaider().canPickupLoot()) return false; // Paper - respect game and entity rules for picking up items ++ if ((!getRaider().world.purpurConfig.pillagerBypassMobGriefing && !getRaider().world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) || !getRaider().canPickupLoot()) return false; // Paper - respect game and entity rules for picking up items // Purpur + Raid raid = this.b.fa(); + + if (this.b.fb() && !this.b.fa().a() && this.b.eN() && !ItemStack.matches(this.b.getEquipment(EnumItemSlot.HEAD), Raid.s())) { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockCampfire.java b/src/main/java/net/minecraft/world/level/block/BlockCampfire.java +index 21baa8fb99b0587da503e14e2b04abf3134d03bc..3f816358758165bf5e346eaffcb3edc46c48dd40 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockCampfire.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockCampfire.java +@@ -181,7 +181,7 @@ public class BlockCampfire extends BlockTileEntity implements IBlockWaterlogged + public void a(World world, IBlockData iblockdata, MovingObjectPositionBlock movingobjectpositionblock, IProjectile iprojectile) { + if (!world.isClientSide && iprojectile.isBurning()) { + Entity entity = iprojectile.getShooter(); +- boolean flag = entity == null || entity instanceof EntityHuman || world.getGameRules().getBoolean(GameRules.MOB_GRIEFING); ++ boolean flag = entity == null || entity instanceof EntityHuman || world.purpurConfig.fireballsBypassMobGriefing || world.getGameRules().getBoolean(GameRules.MOB_GRIEFING); // Purpur + + if (flag && !(Boolean) iblockdata.get(BlockCampfire.LIT) && !(Boolean) iblockdata.get(BlockCampfire.d)) { + BlockPosition blockposition = movingobjectpositionblock.getBlockPosition(); +diff --git a/src/main/java/net/minecraft/world/level/block/BlockCrops.java b/src/main/java/net/minecraft/world/level/block/BlockCrops.java +index 09f15d9087f1c40e5d50cb56f8c764ddaa992e41..5f8366beeaac7153a0421554f9bf91fbf265edca 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockCrops.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockCrops.java +@@ -160,7 +160,7 @@ public class BlockCrops extends BlockPlant implements IBlockFragilePlantElement @Override - public boolean a() { -- return !super.a() ? false : (!this.entity.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) ? false : this.a(this.entity.world.getDifficulty()) && !this.g()); -+ return !super.a() ? false : ((!this.entity.world.purpurConfig.zombieBypassMobGriefing && !this.entity.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) ? false : this.a(this.entity.world.getDifficulty()) && !this.g()); // Purpur - } + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { +- if (entity instanceof EntityRavager && !CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, Blocks.AIR.getBlockData(), !world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)).isCancelled()) { // CraftBukkit ++ if (entity instanceof EntityRavager && !CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, Blocks.AIR.getBlockData(), (!world.purpurConfig.ravagerBypassMobGriefing && !world.getGameRules().getBoolean(GameRules.MOB_GRIEFING))).isCancelled()) { // CraftBukkit // Purpur + world.a(blockposition, true, entity); + } +diff --git a/src/main/java/net/minecraft/world/level/block/BlockSoil.java b/src/main/java/net/minecraft/world/level/block/BlockSoil.java +index 3e8893bf76b8ffda4c595c81086556ea929beaa4..d3fd0b418b9088b621e44f5da452db74b433efe8 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockSoil.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockSoil.java +@@ -99,7 +99,7 @@ public class BlockSoil extends Block { @Override -diff --git a/src/main/java/net/minecraft/server/PathfinderGoalEatTile.java b/src/main/java/net/minecraft/server/PathfinderGoalEatTile.java -index b7e1e7e35a33cf6a476b11284ebdb0cdda524af2..9e8f720ee0a39ccc27d671df4ae83ef404788a2f 100644 ---- a/src/main/java/net/minecraft/server/PathfinderGoalEatTile.java -+++ b/src/main/java/net/minecraft/server/PathfinderGoalEatTile.java -@@ -11,7 +11,7 @@ public class PathfinderGoalEatTile extends PathfinderGoal { - - private static final Predicate a = BlockStatePredicate.a(Blocks.GRASS); - private final EntityInsentient b; -- private final World c; -+ private final World c; private final World getWorld() { return c; } // Purpur - OBFHELPER - private int d; - - public PathfinderGoalEatTile(EntityInsentient entityinsentient) { -@@ -60,7 +60,7 @@ public class PathfinderGoalEatTile extends PathfinderGoal { - - if (PathfinderGoalEatTile.a.test(this.c.getType(blockposition))) { - // CraftBukkit -- if (!CraftEventFactory.callEntityChangeBlockEvent(this.b, blockposition, Blocks.AIR.getBlockData(), !this.c.getGameRules().getBoolean(GameRules.MOB_GRIEFING)).isCancelled()) { -+ if (!CraftEventFactory.callEntityChangeBlockEvent(this.b, blockposition, Blocks.AIR.getBlockData(), !this.getWorld().purpurConfig.sheepBypassMobGriefing && !this.c.getGameRules().getBoolean(GameRules.MOB_GRIEFING)).isCancelled()) { // Purpur - this.c.b(blockposition, false); - } - -@@ -70,7 +70,7 @@ public class PathfinderGoalEatTile extends PathfinderGoal { - - if (this.c.getType(blockposition1).a(Blocks.GRASS_BLOCK)) { - // CraftBukkit -- if (!CraftEventFactory.callEntityChangeBlockEvent(this.b, blockposition, Blocks.AIR.getBlockData(), !this.c.getGameRules().getBoolean(GameRules.MOB_GRIEFING)).isCancelled()) { -+ if (!CraftEventFactory.callEntityChangeBlockEvent(this.b, blockposition, Blocks.AIR.getBlockData(), !this.getWorld().purpurConfig.sheepBypassMobGriefing && !this.c.getGameRules().getBoolean(GameRules.MOB_GRIEFING)).isCancelled()) { // Purpur - this.c.triggerEffect(2001, blockposition1, Block.getCombinedId(Blocks.GRASS_BLOCK.getBlockData())); - this.c.setTypeAndData(blockposition1, Blocks.DIRT.getBlockData(), 2); - } -diff --git a/src/main/java/net/minecraft/server/PathfinderGoalRemoveBlock.java b/src/main/java/net/minecraft/server/PathfinderGoalRemoveBlock.java -index 6ea402c603b9b54705e79a2fdc61fe5a254479a3..0119eb85fbb2aa85b402f7e0ff712e83c79880a4 100644 ---- a/src/main/java/net/minecraft/server/PathfinderGoalRemoveBlock.java -+++ b/src/main/java/net/minecraft/server/PathfinderGoalRemoveBlock.java -@@ -24,7 +24,7 @@ public class PathfinderGoalRemoveBlock extends PathfinderGoalGotoTarget { - - @Override - public boolean a() { -- if (!this.entity.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { -+ if (!this.entity.world.purpurConfig.zombieBypassMobGriefing && !this.entity.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { // Purpur + public void fallOn(World world, BlockPosition blockposition, Entity entity, float f) { + super.fallOn(world, blockposition, entity, f); // CraftBukkit - moved here as game rules / events shouldn't affect fall damage. +- if (!world.isClientSide && world.random.nextFloat() < f - 0.5F && entity instanceof EntityLiving && (entity instanceof EntityHuman || world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) && entity.getWidth() * entity.getWidth() * entity.getHeight() > 0.512F) { ++ if (!world.isClientSide && world.random.nextFloat() < f - 0.5F && entity instanceof EntityLiving && (entity instanceof EntityHuman || world.purpurConfig.farmlandBypassMobGriefing || world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) && entity.getWidth() * entity.getWidth() * entity.getHeight() > 0.512F) { // Purpur + // CraftBukkit start - Interact soil + org.bukkit.event.Cancellable cancellable; + if (entity instanceof EntityHuman) { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockTurtleEgg.java b/src/main/java/net/minecraft/world/level/block/BlockTurtleEgg.java +index 04504901b1933ed760b34b8abb994de8ec340a4e..e18be05c9a9230105ec54395d4391c86132e7930 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockTurtleEgg.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockTurtleEgg.java +@@ -206,7 +206,7 @@ public class BlockTurtleEgg extends Block { return false; - } else if (this.c > 0) { - --this.c; + } + if (entity instanceof EntityLiving && !(entity instanceof EntityHuman)) { +- return world.getGameRules().getBoolean(GameRules.MOB_GRIEFING); ++ return world.purpurConfig.turtleEggsBypassMobGriefing || world.getGameRules().getBoolean(GameRules.MOB_GRIEFING); // Purpur + } + return true; + // Purpur end diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index af33ee28276ac9848805765af6d51bf4b9f3c372..f9cd952ebddab8c963a8cc51755e3019c9286bd0 100644 +index 73213bf975ffe38ff6ee9b05c5a48b232f767727..9fae36ee7c25a0cf3a7677223a7aa55617797970 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -252,6 +252,7 @@ public class PurpurWorldConfig { diff --git a/patches/server/0160-Config-to-allow-Note-Block-sounds-when-blocked.patch b/patches/server/0160-Config-to-allow-Note-Block-sounds-when-blocked.patch index 039f187f8..a2a7a8d48 100644 --- a/patches/server/0160-Config-to-allow-Note-Block-sounds-when-blocked.patch +++ b/patches/server/0160-Config-to-allow-Note-Block-sounds-when-blocked.patch @@ -8,11 +8,11 @@ Allows for Note Blocks to ignore whether or not there's air above them to play. Normally, the sounds will only play when the block directly above is air. With this patch enabled, players can place any block above the Note Block and it will still work. -diff --git a/src/main/java/net/minecraft/server/BlockNote.java b/src/main/java/net/minecraft/server/BlockNote.java -index df69d00d3a38417e53f433cd1eb1f6cf3ec9b55b..6bb6e229c8734d7b9f4e3cd3dd1b4b646bca1777 100644 ---- a/src/main/java/net/minecraft/server/BlockNote.java -+++ b/src/main/java/net/minecraft/server/BlockNote.java -@@ -37,7 +37,7 @@ public class BlockNote extends Block { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockNote.java b/src/main/java/net/minecraft/world/level/block/BlockNote.java +index feec1db88b22a4d13ffd3034633da79ed41b94fe..4882046f46c33a8d828d13325af17237ae07cd86 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockNote.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockNote.java +@@ -59,7 +59,7 @@ public class BlockNote extends Block { } private void play(World world, BlockPosition blockposition, IBlockData data) { // CraftBukkit @@ -22,7 +22,7 @@ index df69d00d3a38417e53f433cd1eb1f6cf3ec9b55b..6bb6e229c8734d7b9f4e3cd3dd1b4b64 org.bukkit.event.block.NotePlayEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callNotePlayEvent(world, blockposition, data.get(BlockNote.INSTRUMENT), data.get(BlockNote.NOTE)); if (!event.isCancelled()) { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index f9cd952ebddab8c963a8cc51755e3019c9286bd0..e1b2a39ea8847716c44d265a62492b5e6cbe262d 100644 +index 9fae36ee7c25a0cf3a7677223a7aa55617797970..c992521116d7aadebd43d2793d5ea1875841d51d 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -254,6 +254,7 @@ public class PurpurWorldConfig { diff --git a/patches/server/0161-Add-EntityTeleportHinderedEvent.patch b/patches/server/0161-Add-EntityTeleportHinderedEvent.patch index ac0f32dbd..d584bbf3c 100644 --- a/patches/server/0161-Add-EntityTeleportHinderedEvent.patch +++ b/patches/server/0161-Add-EntityTeleportHinderedEvent.patch @@ -16,23 +16,11 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . -diff --git a/src/main/java/net/minecraft/server/BlockBase.java b/src/main/java/net/minecraft/server/BlockBase.java -index b40f5167d2a9772658c115091f13706fbb4959b7..657885cdaa086293f6b5aa6f3058acd16df0ba35 100644 ---- a/src/main/java/net/minecraft/server/BlockBase.java -+++ b/src/main/java/net/minecraft/server/BlockBase.java -@@ -250,6 +250,7 @@ public abstract class BlockBase { - return 0; - } - -+ @Deprecated public final void collideWithBlock(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { this.a(iblockdata, world, blockposition, entity); } // Purpur - OBFHELPER - @Deprecated - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) {} - -diff --git a/src/main/java/net/minecraft/server/BlockEnderPortal.java b/src/main/java/net/minecraft/server/BlockEnderPortal.java -index e731b6d811d179f07f84278d2cce75e0d98092ab..f0e5c378c4612192c1d4c74aa81e598f9370b8b8 100644 ---- a/src/main/java/net/minecraft/server/BlockEnderPortal.java -+++ b/src/main/java/net/minecraft/server/BlockEnderPortal.java -@@ -25,7 +25,15 @@ public class BlockEnderPortal extends BlockTileEntity { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java b/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java +index fc89b3bf5075497596885548d80e4ed0b800ea89..4900c90597358f7b701b8becd2ac58de11aacc71 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java +@@ -43,7 +43,15 @@ public class BlockEnderPortal extends BlockTileEntity { @Override public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { @@ -49,11 +37,11 @@ index e731b6d811d179f07f84278d2cce75e0d98092ab..f0e5c378c4612192c1d4c74aa81e598f ResourceKey resourcekey = world.getTypeKey() == DimensionManager.THE_END ? World.OVERWORLD : World.THE_END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends WorldServer worldserver = ((WorldServer) world).getMinecraftServer().getWorldServer(resourcekey); -diff --git a/src/main/java/net/minecraft/server/BlockPortal.java b/src/main/java/net/minecraft/server/BlockPortal.java -index bd78d55ee94f1359739a9d790092d07c613eac0f..a574ef929ac60584ff6e1b2c76722456cc3895ff 100644 ---- a/src/main/java/net/minecraft/server/BlockPortal.java -+++ b/src/main/java/net/minecraft/server/BlockPortal.java -@@ -60,7 +60,15 @@ public class BlockPortal extends Block { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockPortal.java b/src/main/java/net/minecraft/world/level/block/BlockPortal.java +index 5f797260eff317409a5039b88b01ad79ee2fdd91..ac5ce96ab62ec210816e7af85a4269073b7a9270 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockPortal.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockPortal.java +@@ -82,7 +82,15 @@ public class BlockPortal extends Block { @Override public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { @@ -70,11 +58,11 @@ index bd78d55ee94f1359739a9d790092d07c613eac0f..a574ef929ac60584ff6e1b2c76722456 // CraftBukkit start - Entity in portal EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), blockposition.getX(), blockposition.getY(), blockposition.getZ())); world.getServer().getPluginManager().callEvent(event); -diff --git a/src/main/java/net/minecraft/server/TileEntityEndGateway.java b/src/main/java/net/minecraft/server/TileEntityEndGateway.java -index e616b3759561e0d6e471f914f3dc843fe7464f2e..4a443827a316415c2c047ca468d965a80fce1fb1 100644 ---- a/src/main/java/net/minecraft/server/TileEntityEndGateway.java -+++ b/src/main/java/net/minecraft/server/TileEntityEndGateway.java -@@ -126,9 +126,18 @@ public class TileEntityEndGateway extends TileEntityEnderPortal implements ITick +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java +index d918194e45953764fa3fd286b715714330a60941..70496562faa89e92da34a4f7b891f845d1d55012 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java +@@ -151,9 +151,18 @@ public class TileEntityEndGateway extends TileEntityEnderPortal implements ITick } } @@ -93,8 +81,20 @@ index e616b3759561e0d6e471f914f3dc843fe7464f2e..4a443827a316415c2c047ca468d965a8 this.c = 100; if (this.exitPortal == null && this.world.getTypeKey() == DimensionManager.THE_END) { // CraftBukkit - work in alternate worlds this.a((WorldServer) this.world); +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java +index 8d21f9451c60873d1524ad64876094e6e21509e4..5e8b3791ebec2f745af2527dc52c792f30f63106 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java +@@ -302,6 +302,7 @@ public abstract class BlockBase { + return 0; + } + ++ @Deprecated public final void collideWithBlock(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { this.a(iblockdata, world, blockposition, entity); } // Purpur - OBFHELPER + @Deprecated + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) {} + diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index e1b2a39ea8847716c44d265a62492b5e6cbe262d..2391e1ddbe062dde5cb9a240b0a6a85ed793e569 100644 +index c992521116d7aadebd43d2793d5ea1875841d51d..61bc3507a9f473e9dc1c948299e3bf11a02b632b 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -1881,4 +1881,9 @@ public class PurpurWorldConfig { @@ -108,10 +108,10 @@ index e1b2a39ea8847716c44d265a62492b5e6cbe262d..2391e1ddbe062dde5cb9a240b0a6a85e + } } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 5471422d23d261a06c67f9374cae933430ec03a0..4c592f6d4d6cbeb4c3225e7794f4b1d6c8d62394 100644 +index c524a0994f1c9ef1d0534403efa4e4481955b2f3..a80f664d2cf713fd751421be3735e2f4779f0056 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -522,6 +522,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -554,6 +554,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { location.checkFinite(); if (entity.isVehicle() || entity.dead) { @@ -123,10 +123,10 @@ index 5471422d23d261a06c67f9374cae933430ec03a0..4c592f6d4d6cbeb4c3225e7794f4b1d6 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 7b5ffe92430121eebe2866ac33b37a840eed90f1..98f4407848347dfc46b70d1c1fe466dce10f54b7 100644 +index ca465a53a0c6232f912287704fc63cdcc59a28bd..37564214c6595dfc07534124f749bf65002325c2 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -117,6 +117,7 @@ import org.bukkit.entity.EntityType; +@@ -126,6 +126,7 @@ import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerRegisterChannelEvent; import org.bukkit.event.player.PlayerTeleportEvent; @@ -134,7 +134,7 @@ index 7b5ffe92430121eebe2866ac33b37a840eed90f1..98f4407848347dfc46b70d1c1fe466dc import org.bukkit.event.player.PlayerUnregisterChannelEvent; import org.bukkit.inventory.InventoryView.Property; import org.bukkit.inventory.ItemStack; -@@ -874,6 +875,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -883,6 +884,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } if (entity.isVehicle()) { diff --git a/patches/server/0162-Add-StructureGenerateEvent.patch b/patches/server/0162-Add-StructureGenerateEvent.patch index 90a1be64a..48b3d1712 100644 --- a/patches/server/0162-Add-StructureGenerateEvent.patch +++ b/patches/server/0162-Add-StructureGenerateEvent.patch @@ -18,11 +18,11 @@ along with this program. If not, see . Co-authored-by: Mariell Hoversholm -diff --git a/src/main/java/net/minecraft/server/ChunkGenerator.java b/src/main/java/net/minecraft/server/ChunkGenerator.java -index 17cf00dfe8b24adf2fb66eca4710ab7888a894e3..6223d1d9048e31fb10cec7f485d1556aec2c7d5e 100644 ---- a/src/main/java/net/minecraft/server/ChunkGenerator.java -+++ b/src/main/java/net/minecraft/server/ChunkGenerator.java -@@ -251,6 +251,14 @@ public abstract class ChunkGenerator { +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java +index 316287af6e405ff224636255c2964f46003215ce..ff98335155c86803b98d8c67f0b40b8d65214890 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java +@@ -287,6 +287,14 @@ public abstract class ChunkGenerator { if (structuresettingsfeature != null) { StructureStart structurestart1 = structurefeature.a(iregistrycustom, this, this.b, definedstructuremanager, i, chunkcoordintpair, biomebase, j, structuresettingsfeature); @@ -37,11 +37,11 @@ index 17cf00dfe8b24adf2fb66eca4710ab7888a894e3..6223d1d9048e31fb10cec7f485d1556a structuremanager.a(SectionPosition.a(ichunkaccess.getPos(), 0), structurefeature.d, structurestart1, ichunkaccess); } -diff --git a/src/main/java/net/minecraft/server/StructureFeature.java b/src/main/java/net/minecraft/server/StructureFeature.java -index 8e3c0c3783b767c2ba603b3b50200ac76a7fc33e..379665ae55e76afb03b20d1b81c57347af1137db 100644 ---- a/src/main/java/net/minecraft/server/StructureFeature.java -+++ b/src/main/java/net/minecraft/server/StructureFeature.java -@@ -11,7 +11,7 @@ public class StructureFeature>> b = RegistryFileCodec.a(IRegistry.av, StructureFeature.a); public static final Codec>>> c = RegistryFileCodec.b(IRegistry.av, StructureFeature.a); @@ -50,11 +50,11 @@ index 8e3c0c3783b767c2ba603b3b50200ac76a7fc33e..379665ae55e76afb03b20d1b81c57347 public final FC e; public StructureFeature(F f0, FC fc) { -diff --git a/src/main/java/net/minecraft/server/StructureGenerator.java b/src/main/java/net/minecraft/server/StructureGenerator.java -index a62c87bceab2c9700a7b3925f208b0ffa2b9b393..8fc283f014783b76afda83097201bb7938a1f9fa 100644 ---- a/src/main/java/net/minecraft/server/StructureGenerator.java -+++ b/src/main/java/net/minecraft/server/StructureGenerator.java -@@ -235,6 +235,7 @@ public abstract class StructureGenerator +diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java +index 6df42ff26ff6e65ec2885122fe53dde857a3d1d2..917d147b06b7045ea69917c81f35fcafdd5098dd 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java +@@ -268,6 +268,7 @@ public abstract class StructureGenerator public abstract StructureGenerator.a a(); diff --git a/patches/server/0163-Farmland-trampling-changes.patch b/patches/server/0163-Farmland-trampling-changes.patch index 2ecf6cc10..cc80f9a58 100644 --- a/patches/server/0163-Farmland-trampling-changes.patch +++ b/patches/server/0163-Farmland-trampling-changes.patch @@ -11,11 +11,29 @@ distance equal to their feather falling level, plus the extra block necessary to trample in the first place. Feather Falling 1 requires you to fall over 3+ blocks to trample. FF 2 requires 4+, etc. -diff --git a/src/main/java/net/minecraft/server/BlockSoil.java b/src/main/java/net/minecraft/server/BlockSoil.java -index 73dc0f499c456c21d298013fbab8c79ebcdecd6b..383a6fa1cbc913c492fea341132bfabf412115c6 100644 ---- a/src/main/java/net/minecraft/server/BlockSoil.java -+++ b/src/main/java/net/minecraft/server/BlockSoil.java -@@ -91,12 +91,19 @@ public class BlockSoil extends Block { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockSoil.java b/src/main/java/net/minecraft/world/level/block/BlockSoil.java +index d3fd0b418b9088b621e44f5da452db74b433efe8..e7e5ee52cb7ac7e406c837db686d0a96dcc13fbc 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockSoil.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockSoil.java +@@ -4,13 +4,17 @@ import java.util.Iterator; + import java.util.Random; + import net.minecraft.core.BlockPosition; + import net.minecraft.core.EnumDirection; ++import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.WorldServer; + import net.minecraft.tags.Tag; + import net.minecraft.tags.TagsFluid; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityLiving; + import net.minecraft.world.entity.player.EntityHuman; ++import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.context.BlockActionContext; ++import net.minecraft.world.item.enchantment.EnchantmentManager; ++import net.minecraft.world.item.enchantment.Enchantments; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.GeneratorAccess; + import net.minecraft.world.level.IBlockAccess; +@@ -114,12 +118,19 @@ public class BlockSoil extends Block { } // Purpur start @@ -36,7 +54,7 @@ index 73dc0f499c456c21d298013fbab8c79ebcdecd6b..383a6fa1cbc913c492fea341132bfabf if (CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, Blocks.DIRT.getBlockData()).isCancelled()) { return; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 2391e1ddbe062dde5cb9a240b0a6a85ed793e569..16e95a3c6edd65d943ebab5d894dc4c6a84623e3 100644 +index 61bc3507a9f473e9dc1c948299e3bf11a02b632b..498abbe8e9324d215b4ac409e1af10a4db5f02d5 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -413,10 +413,16 @@ public class PurpurWorldConfig { diff --git a/patches/server/0164-Movement-options-for-armour-stands.patch b/patches/server/0164-Movement-options-for-armor-stands.patch similarity index 67% rename from patches/server/0164-Movement-options-for-armour-stands.patch rename to patches/server/0164-Movement-options-for-armor-stands.patch index 635d3476b..4d0dc6d9e 100644 --- a/patches/server/0164-Movement-options-for-armour-stands.patch +++ b/patches/server/0164-Movement-options-for-armor-stands.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Mariell Hoversholm Date: Sat, 9 Jan 2021 22:22:59 +0100 -Subject: [PATCH] Movement options for armour stands +Subject: [PATCH] Movement options for armor stands This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,24 +16,32 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 6fa2e0b2ee62212ab315a16803457efc8001d6d0..4b7ab2405a7d49ae085d64e482d4a851f18263d6 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -1376,7 +1376,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 904bca540a42204a9856765e333eee6c5de6a960..ee1f0ccce5c5c920b2595ced9e72fd1544e2459a 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1469,7 +1469,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne return this.isInWater() || flag; } - void aL() { -+ void aL() { // Purpur - diff on change; this is `updateInWaterStateAndDoWaterCurrentPushing()V` ++ public void aL() { updateInWaterStateAndDoWaterCurrentPushing(); } public void updateInWaterStateAndDoWaterCurrentPushing() { // Purpur if (this.getVehicle() instanceof EntityBoat) { this.inWater = false; } else if (this.a((Tag) TagsFluid.WATER, 0.014D)) { -diff --git a/src/main/java/net/minecraft/server/EntityArmorStand.java b/src/main/java/net/minecraft/server/EntityArmorStand.java -index 759a8f95038778aead2f33a65a2d8f2d6b26a765..74fda434ed7beb6612f46ed75fdccad59f394b60 100644 ---- a/src/main/java/net/minecraft/server/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/server/EntityArmorStand.java -@@ -52,10 +52,12 @@ public class EntityArmorStand extends EntityLiving { +diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java +index 43dc0925887e2e9e86445cccff57be7994ca0d58..72869cf01f0cb52260603f5f63855b29778640e9 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java +@@ -36,6 +36,7 @@ import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.World; + import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.BlockFence; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.material.EnumPistonReaction; + import net.minecraft.world.phys.Vec3D; +@@ -87,10 +88,12 @@ public class EntityArmorStand extends EntityLiving { private boolean noTickPoseDirty = false; private boolean noTickEquipmentDirty = false; // Paper end @@ -46,14 +54,14 @@ index 759a8f95038778aead2f33a65a2d8f2d6b26a765..74fda434ed7beb6612f46ed75fdccad5 this.handItems = NonNullList.a(2, ItemStack.b); this.armorItems = NonNullList.a(4, ItemStack.b); this.headPose = EntityArmorStand.bj; -@@ -897,4 +899,18 @@ public class EntityArmorStand extends EntityLiving { +@@ -932,4 +935,18 @@ public class EntityArmorStand extends EntityLiving { return true; } // Paper end + + // Purpur start + @Override -+ void aL() { ++ public void updateInWaterStateAndDoWaterCurrentPushing() { + if (this.world.purpurConfig.armorstandWaterMovement && + (this.world.purpurConfig.armorstandWaterFence || !(world.getType(getBlockLocation().down()).getBlock() instanceof BlockFence))) + super.aL(); @@ -66,7 +74,7 @@ index 759a8f95038778aead2f33a65a2d8f2d6b26a765..74fda434ed7beb6612f46ed75fdccad5 + // Purpur end } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 16e95a3c6edd65d943ebab5d894dc4c6a84623e3..b2770122e67123a3a30feafd24d959b6035d65ae 100644 +index 498abbe8e9324d215b4ac409e1af10a4db5f02d5..01304a630d22a7de1a6d8beb8d9753a36a31fc42 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -111,10 +111,16 @@ public class PurpurWorldConfig { diff --git a/patches/server/0165-Fix-stuck-in-portals.patch b/patches/server/0165-Fix-stuck-in-portals.patch index a77faa785..4c0a1f775 100644 --- a/patches/server/0165-Fix-stuck-in-portals.patch +++ b/patches/server/0165-Fix-stuck-in-portals.patch @@ -4,11 +4,23 @@ Date: Thu, 14 Jan 2021 16:48:10 -0600 Subject: [PATCH] Fix stuck in portals -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 4b7ab2405a7d49ae085d64e482d4a851f18263d6..c27ce317c7acaf7ddd926c982d08e0539e045e28 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -2427,12 +2427,15 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index f942c3ab757b768fbd1d459752b7f29094471c56..ccee67df065dcdee5e0e24ab12476572ca696687 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -1293,6 +1293,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + playerlist.d(this); + worldserver1.removePlayer(this); + this.dead = false; ++ this.portalPos = MCUtil.toBlockPosition(exit); // Purpur + + // CraftBukkit end + this.spawnIn(worldserver); +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index ee1f0ccce5c5c920b2595ced9e72fd1544e2459a..fcbbf100990faf60250357b744cbd58701da0b0c 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2520,12 +2520,15 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne return new Vec2F(this.pitch, this.yaw); } @@ -24,20 +36,8 @@ index 4b7ab2405a7d49ae085d64e482d4a851f18263d6..c27ce317c7acaf7ddd926c982d08e053 } this.inPortal = true; -diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index 5a602de5b9ff436e7cfb70c39475be34beddfb8d..5cf4a2b41d7f088eeb7c8003b8b889f370a4d214 100644 ---- a/src/main/java/net/minecraft/server/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/EntityPlayer.java -@@ -1161,6 +1161,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - playerlist.d(this); - worldserver1.removePlayer(this); - this.dead = false; -+ this.portalPos = MCUtil.toBlockPosition(exit); // Purpur - - // CraftBukkit end - this.spawnIn(worldserver); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index b2770122e67123a3a30feafd24d959b6035d65ae..fef64804d1e4f1de852ec209e0d7ac524896e43e 100644 +index 01304a630d22a7de1a6d8beb8d9753a36a31fc42..82b4ece3c12d8180b7ab275c3f240e94578177fc 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -350,6 +350,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0166-Fix-PlayerEditBookEvent-not-saving-new-book.patch b/patches/server/0166-Fix-PlayerEditBookEvent-not-saving-new-book.patch index 56a2c53b7..952e62f34 100644 --- a/patches/server/0166-Fix-PlayerEditBookEvent-not-saving-new-book.patch +++ b/patches/server/0166-Fix-PlayerEditBookEvent-not-saving-new-book.patch @@ -4,11 +4,11 @@ Date: Mon, 25 Jan 2021 10:22:28 -0600 Subject: [PATCH] Fix PlayerEditBookEvent not saving new book -diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 9ff35aa827cf5b937b8dcbcabafd27301574c35d..f7a031920c68d5d5d505d86ab1b513ac53f5bf84 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -1065,7 +1065,7 @@ public class PlayerConnection implements PacketListenerPlayIn { +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index b81b7a4f7debdb77a9b8906e3d87420be51b8e62..c7c26cd1b99c911efd12e325e0ca09d9ac98c6f4 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -1210,7 +1210,7 @@ public class PlayerConnection implements PacketListenerPlayIn { list.stream().map(s -> s = color(s, hasPerm, false)).map(NBTTagString::a).forEach(nbttaglist::add); // Purpur - edit book ItemStack old = itemstack.cloneItemStack(); // CraftBukkit itemstack.a("pages", (NBTBase) nbttaglist); diff --git a/patches/server/0167-Config-to-use-infinity-bows-without-arrows.patch b/patches/server/0167-Config-to-use-infinity-bows-without-arrows.patch index 2e861354c..f177ccb8a 100644 --- a/patches/server/0167-Config-to-use-infinity-bows-without-arrows.patch +++ b/patches/server/0167-Config-to-use-infinity-bows-without-arrows.patch @@ -6,11 +6,11 @@ Subject: [PATCH] Config to use infinity bows without arrows Allows for bows with infinity to be used without any arrows in the player's inventory. Uses a standard arrow when shot. -diff --git a/src/main/java/net/minecraft/server/ItemBow.java b/src/main/java/net/minecraft/server/ItemBow.java -index 8241f3dafa5852bed7a3967e7260b36f47198dba..edfb09fe673a9a7fe4e0410c0c0eeeda0d164270 100644 ---- a/src/main/java/net/minecraft/server/ItemBow.java -+++ b/src/main/java/net/minecraft/server/ItemBow.java -@@ -119,7 +119,7 @@ public class ItemBow extends ItemProjectileWeapon implements ItemVanishable { +diff --git a/src/main/java/net/minecraft/world/item/ItemBow.java b/src/main/java/net/minecraft/world/item/ItemBow.java +index c7e20b25b4d09463fa54c66e62208e90515013e2..59b803ec4552058f2dda269e9435daf65be10559 100644 +--- a/src/main/java/net/minecraft/world/item/ItemBow.java ++++ b/src/main/java/net/minecraft/world/item/ItemBow.java +@@ -130,7 +130,7 @@ public class ItemBow extends ItemProjectileWeapon implements ItemVanishable { ItemStack itemstack = entityhuman.b(enumhand); boolean flag = !entityhuman.f(itemstack).isEmpty(); @@ -20,7 +20,7 @@ index 8241f3dafa5852bed7a3967e7260b36f47198dba..edfb09fe673a9a7fe4e0410c0c0eeeda } else { entityhuman.c(enumhand); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index fef64804d1e4f1de852ec209e0d7ac524896e43e..bc5c90b21045ed8b405cd7c489b7c8a8d9226cd8 100644 +index 82b4ece3c12d8180b7ab275c3f240e94578177fc..7ba0c16271fccf7609680b1409a93e2653aa0af2 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -209,10 +209,12 @@ public class PurpurWorldConfig { diff --git a/patches/server/0168-Toggle-for-water-sensitive-mob-damage.patch b/patches/server/0168-Toggle-for-water-sensitive-mob-damage.patch index 7cd9d8272..537c2ee29 100644 --- a/patches/server/0168-Toggle-for-water-sensitive-mob-damage.patch +++ b/patches/server/0168-Toggle-for-water-sensitive-mob-damage.patch @@ -4,37 +4,11 @@ Date: Fri, 5 Feb 2021 01:11:22 +0100 Subject: [PATCH] Toggle for water sensitive mob damage -diff --git a/src/main/java/net/minecraft/server/EntityBlaze.java b/src/main/java/net/minecraft/server/EntityBlaze.java -index 90b90fa33b39020189a1d4a5826fa3ab720488cd..b4db9869d172406f4eff84cfb2648b5c6c6d00e2 100644 ---- a/src/main/java/net/minecraft/server/EntityBlaze.java -+++ b/src/main/java/net/minecraft/server/EntityBlaze.java -@@ -116,7 +116,7 @@ public class EntityBlaze extends EntityMonster { - - @Override - public boolean dO() { -- return true; -+ return world.purpurConfig.blazeTakeDamageFromWater; // Purpur - Toggle for water sensitive mob damage - } - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityEnderman.java b/src/main/java/net/minecraft/server/EntityEnderman.java -index 4d575d29cd446cd65cea7cdeb2541e0c3112d660..e20b91b36587d1191f8f9e8dd501607bf085e76d 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderman.java -+++ b/src/main/java/net/minecraft/server/EntityEnderman.java -@@ -234,7 +234,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - - @Override - public boolean dO() { -- return true; -+ return world.purpurConfig.endermanTakeDamageFromWater; // Purpur - Toggle for water sensitive mob damage - } - - @Override -diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java -index 679b6a4b408f01ae578803dac8bf562fbfdd2600..cbebc150700ec5074244c28388e7d32714510b05 100644 ---- a/src/main/java/net/minecraft/server/EntityInsentient.java -+++ b/src/main/java/net/minecraft/server/EntityInsentient.java -@@ -786,7 +786,8 @@ public abstract class EntityInsentient extends EntityLiving { +diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +index 63d93060b350069040876aaacb91c853d674ea7b..e9793954c872baacfe7be80ecf3888e848dc924f 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java ++++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +@@ -856,7 +856,8 @@ public abstract class EntityInsentient extends EntityLiving { if (goalFloat.validConditions()) goalFloat.update(); this.getControllerJump().jumpIfSet(); } @@ -44,11 +18,11 @@ index 679b6a4b408f01ae578803dac8bf562fbfdd2600..cbebc150700ec5074244c28388e7d327 damageEntity(DamageSource.DROWN, 1.0F); } return; -diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index 8b8e6b8cfbdc591eb8681bc672975ae6198ef263..c514ba819e5fc69e67bd370469465a926672c2da 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -2878,6 +2878,7 @@ public abstract class EntityLiving extends Entity { +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 1e57358c02e67a6b062149926ada46696da24487..66f1750172df09f1cbb47ca5a679a77a9ccab282 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -2974,6 +2974,7 @@ public abstract class EntityLiving extends Entity { } @@ -56,11 +30,11 @@ index 8b8e6b8cfbdc591eb8681bc672975ae6198ef263..c514ba819e5fc69e67bd370469465a92 public boolean dO() { return false; } -diff --git a/src/main/java/net/minecraft/server/EntitySnowman.java b/src/main/java/net/minecraft/server/EntitySnowman.java -index eb6344a5671408ae9fdd6013774baa13addf304b..663c6dd23e0aa75266cefc8f0514d2ca9dc51553 100644 ---- a/src/main/java/net/minecraft/server/EntitySnowman.java -+++ b/src/main/java/net/minecraft/server/EntitySnowman.java -@@ -71,7 +71,7 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java b/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java +index 17f27d2bf5be746a0fa0e1e0fecab8158b2b3587..ad30cc92333aabf7d9fb3fb046e7ecb63629ee5b 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java +@@ -108,7 +108,7 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt @Override public boolean dO() { @@ -69,11 +43,37 @@ index eb6344a5671408ae9fdd6013774baa13addf304b..663c6dd23e0aa75266cefc8f0514d2ca } @Override -diff --git a/src/main/java/net/minecraft/server/EntityStrider.java b/src/main/java/net/minecraft/server/EntityStrider.java -index 964956a0027bf0941ff75d658be760b754772fa0..7c5472a5138011a3376b7b6ec2467bdfc1739033 100644 ---- a/src/main/java/net/minecraft/server/EntityStrider.java -+++ b/src/main/java/net/minecraft/server/EntityStrider.java -@@ -338,7 +338,7 @@ public class EntityStrider extends EntityAnimal implements ISteerable, ISaddleab +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java b/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java +index 45e69d2f8da4c5babfd2e67055cc0a4c6d3baac7..f90a0fcd41996cfb6935a2299306e6a4bf19701a 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java +@@ -143,7 +143,7 @@ public class EntityBlaze extends EntityMonster { + + @Override + public boolean dO() { +- return true; ++ return world.purpurConfig.blazeTakeDamageFromWater; // Purpur - Toggle for water sensitive mob damage + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +index ea500a6080f73dcc35d83a3b5a170f57dedaa431..d290787f74579dd4c138eb827e44544814bfe315 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +@@ -290,7 +290,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { + + @Override + public boolean dO() { +- return true; ++ return world.purpurConfig.endermanTakeDamageFromWater; // Purpur - Toggle for water sensitive mob damage + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java b/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java +index 5e4cc99a746d98231bbb71672fbc02431e4fab48..f52ae7446c16d5b8ac51bd2e12bb51d221ca43ca 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java +@@ -405,7 +405,7 @@ public class EntityStrider extends EntityAnimal implements ISteerable, ISaddleab @Override public boolean dO() { @@ -83,7 +83,7 @@ index 964956a0027bf0941ff75d658be760b754772fa0..7c5472a5138011a3376b7b6ec2467bdf @Override diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index bc5c90b21045ed8b405cd7c489b7c8a8d9226cd8..82ec9e47dd7fa4008098ca9bb892c79f30b5fa0a 100644 +index 7ba0c16271fccf7609680b1409a93e2653aa0af2..3c0a9b8e71663ad60cf78d4f66f4fd9960f2c59b 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -571,6 +571,7 @@ public class PurpurWorldConfig { diff --git a/patches/server/0169-Config-to-always-tame-in-Creative.patch b/patches/server/0169-Config-to-always-tame-in-Creative.patch index 0244fd337..f82bbcb26 100644 --- a/patches/server/0169-Config-to-always-tame-in-Creative.patch +++ b/patches/server/0169-Config-to-always-tame-in-Creative.patch @@ -6,50 +6,11 @@ Subject: [PATCH] Config to always tame in Creative Adds a configuration option that ensures a player in Creative always tames a tameable entity. This essentially allows Creative mode players to tame animals on their first try. -diff --git a/src/main/java/net/minecraft/server/EntityCat.java b/src/main/java/net/minecraft/server/EntityCat.java -index f973408b1f098c8a090401205f809e95fdcf2f62..2128d8a9a6fe6bdea81881cfc8ab7b03f448576f 100644 ---- a/src/main/java/net/minecraft/server/EntityCat.java -+++ b/src/main/java/net/minecraft/server/EntityCat.java -@@ -375,7 +375,7 @@ public class EntityCat extends EntityTameableAnimal { - } - } else if (this.k(itemstack)) { - this.a(entityhuman, itemstack); -- if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled()) { // CraftBukkit -+ if ((this.world.purpurConfig.alwaysTameInCreative && entityhuman.abilities.canInstantlyBuild) || (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled())) { // CraftBukkit // Purpur - this.tame(entityhuman); - this.setWillSit(true); - this.world.broadcastEntityEffect(this, (byte) 7); -diff --git a/src/main/java/net/minecraft/server/EntityParrot.java b/src/main/java/net/minecraft/server/EntityParrot.java -index d19f8dda87c97de594ad051a6791d99eec581e95..6d5a56b96c3759c594fe2ee4b7cdd7fa67f3d3fb 100644 ---- a/src/main/java/net/minecraft/server/EntityParrot.java -+++ b/src/main/java/net/minecraft/server/EntityParrot.java -@@ -245,7 +245,7 @@ public class EntityParrot extends EntityPerchable implements EntityBird { - } - - if (!this.world.isClientSide) { -- if (this.random.nextInt(10) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled()) { // CraftBukkit -+ if ((this.world.purpurConfig.alwaysTameInCreative && entityhuman.abilities.canInstantlyBuild) || (this.random.nextInt(10) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled())) { // CraftBukkit // Purpur - this.tame(entityhuman); - this.world.broadcastEntityEffect(this, (byte) 7); - } else { -diff --git a/src/main/java/net/minecraft/server/EntityWolf.java b/src/main/java/net/minecraft/server/EntityWolf.java -index 03bcbf7c280476ef0e6fe87e3a96edb75544bddb..5bf2a3205671a7cb001835ab241c34bcbe47e02c 100644 ---- a/src/main/java/net/minecraft/server/EntityWolf.java -+++ b/src/main/java/net/minecraft/server/EntityWolf.java -@@ -415,7 +415,7 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable - } - - // CraftBukkit - added event call and isCancelled check. -- if (this.random.nextInt(3) == 0 && !CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled()) { -+ if ((this.world.purpurConfig.alwaysTameInCreative && entityhuman.abilities.canInstantlyBuild) || (this.random.nextInt(3) == 0 && !CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled())) { // Purpur - this.tame(entityhuman); - this.navigation.o(); - this.setGoalTarget((EntityLiving) null); -diff --git a/src/main/java/net/minecraft/server/PathfinderGoalTame.java b/src/main/java/net/minecraft/server/PathfinderGoalTame.java -index 8757c6487a433b1fa5c46b50c559aeca82f84b8d..b841f87f9d6b7c9c67e2497607cbd927909c3ddc 100644 ---- a/src/main/java/net/minecraft/server/PathfinderGoalTame.java -+++ b/src/main/java/net/minecraft/server/PathfinderGoalTame.java -@@ -58,7 +58,7 @@ public class PathfinderGoalTame extends PathfinderGoal { +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.java +index d285f5aa66fa81a2f56920c05afb4506cb82fa54..39e348847bcecd91013452e71ef1672994a1bfa7 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.java +@@ -63,7 +63,7 @@ public class PathfinderGoalTame extends PathfinderGoal { int j = this.entity.getMaxDomestication(); // CraftBukkit - fire EntityTameEvent @@ -58,8 +19,47 @@ index 8757c6487a433b1fa5c46b50c559aeca82f84b8d..b841f87f9d6b7c9c67e2497607cbd927 this.entity.i((EntityHuman) entity); return; } +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCat.java b/src/main/java/net/minecraft/world/entity/animal/EntityCat.java +index 7143b0801be7877762e41da336ea5e4e57f2e463..a099d8e0c5a3e4b804c8af978161ec1747ee7fa3 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityCat.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityCat.java +@@ -439,7 +439,7 @@ public class EntityCat extends EntityTameableAnimal { + } + } else if (this.k(itemstack)) { + this.a(entityhuman, itemstack); +- if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled()) { // CraftBukkit ++ if ((this.world.purpurConfig.alwaysTameInCreative && entityhuman.abilities.canInstantlyBuild) || (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled())) { // CraftBukkit // Purpur + this.tame(entityhuman); + this.setWillSit(true); + this.world.broadcastEntityEffect(this, (byte) 7); +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java +index efa4318989893c946e9d7671d0dead6c4a6e315f..b2a8bfc3e53a2071ab7451fbdb3d49d97f0c430a 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java +@@ -301,7 +301,7 @@ public class EntityParrot extends EntityPerchable implements EntityBird { + } + + if (!this.world.isClientSide) { +- if (this.random.nextInt(10) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled()) { // CraftBukkit ++ if ((this.world.purpurConfig.alwaysTameInCreative && entityhuman.abilities.canInstantlyBuild) || (this.random.nextInt(10) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled())) { // CraftBukkit // Purpur + this.tame(entityhuman); + this.world.broadcastEntityEffect(this, (byte) 7); + } else { +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java b/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java +index 090903fbc8f6cd1522c7afb358f708f5ae3395f4..884a3f03c73efb8fb0863976615fba5ec10f716c 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java +@@ -482,7 +482,7 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable + } + + // CraftBukkit - added event call and isCancelled check. +- if (this.random.nextInt(3) == 0 && !CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled()) { ++ if ((this.world.purpurConfig.alwaysTameInCreative && entityhuman.abilities.canInstantlyBuild) || (this.random.nextInt(3) == 0 && !CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled())) { // Purpur + this.tame(entityhuman); + this.navigation.o(); + this.setGoalTarget((EntityLiving) null); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 82ec9e47dd7fa4008098ca9bb892c79f30b5fa0a..8c25e08dfa7f141a6e1616b96625376f3fa10c5f 100644 +index 3c0a9b8e71663ad60cf78d4f66f4fd9960f2c59b..b49a909bf1dcf0bebce3eec03b54d05583af2e43 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -255,6 +255,7 @@ public class PurpurWorldConfig { diff --git a/patches/server/0170-End-crystal-explosion-options.patch b/patches/server/0170-End-crystal-explosion-options.patch index 4d3ff0b68..c54bbc6c2 100644 --- a/patches/server/0170-End-crystal-explosion-options.patch +++ b/patches/server/0170-End-crystal-explosion-options.patch @@ -4,11 +4,11 @@ Date: Sat, 13 Feb 2021 09:28:56 -0500 Subject: [PATCH] End crystal explosion options -diff --git a/src/main/java/net/minecraft/server/EntityEnderCrystal.java b/src/main/java/net/minecraft/server/EntityEnderCrystal.java -index 1942fae27051af79b6eb1d790a219da100bf889e..0e2f9777fe1b62f8da20bf7559150e1dd041febc 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderCrystal.java -+++ b/src/main/java/net/minecraft/server/EntityEnderCrystal.java -@@ -100,6 +100,22 @@ public class EntityEnderCrystal extends Entity { +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java +index 2c983e6a092464d1867fcbe875b2e1461ec8556b..a92c900a6092c07b34711428fac268f446043c90 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java +@@ -118,6 +118,22 @@ public class EntityEnderCrystal extends Entity { phantomDamageCooldown = 0; idleCooldown = 60; } @@ -31,7 +31,7 @@ index 1942fae27051af79b6eb1d790a219da100bf889e..0e2f9777fe1b62f8da20bf7559150e1d // Purpur end @Override -@@ -143,15 +159,17 @@ public class EntityEnderCrystal extends Entity { +@@ -161,15 +177,17 @@ public class EntityEnderCrystal extends Entity { // CraftBukkit end this.die(); if (!damagesource.isExplosion()) { @@ -52,7 +52,7 @@ index 1942fae27051af79b6eb1d790a219da100bf889e..0e2f9777fe1b62f8da20bf7559150e1d this.a(damagesource); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 8c25e08dfa7f141a6e1616b96625376f3fa10c5f..5a48219c214c062fee5a1915227923265febc698 100644 +index b49a909bf1dcf0bebce3eec03b54d05583af2e43..16eac6648c7bb17fb10f5741857ac5e8283aed50 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -1915,4 +1915,33 @@ public class PurpurWorldConfig { diff --git a/patches/server/0171-Add-unsafe-Entity-serialization-API.patch b/patches/server/0171-Add-unsafe-Entity-serialization-API.patch index e27170a0b..2cd8b9297 100644 --- a/patches/server/0171-Add-unsafe-Entity-serialization-API.patch +++ b/patches/server/0171-Add-unsafe-Entity-serialization-API.patch @@ -16,11 +16,11 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . -diff --git a/src/main/java/net/minecraft/server/EntityTypes.java b/src/main/java/net/minecraft/server/EntityTypes.java -index 4de08939f8a5de464e510e47228291fc513b8104..b38e7c40fe9cb56cb37769ce3a8c7969e2ee5372 100644 ---- a/src/main/java/net/minecraft/server/EntityTypes.java -+++ b/src/main/java/net/minecraft/server/EntityTypes.java -@@ -396,6 +396,7 @@ public class EntityTypes { +diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java +index cc963bbc0fa909b3121a25786b511b31ee4b9561..6569f3d07e89383ff3ebed9c2ff5615b81ddd2f5 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityTypes.java ++++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java +@@ -534,6 +534,7 @@ public class EntityTypes { return this.bf.create(this, world); } @@ -29,10 +29,10 @@ index 4de08939f8a5de464e510e47228291fc513b8104..b38e7c40fe9cb56cb37769ce3a8c7969 return SystemUtils.a(a(nbttagcompound).map((entitytypes) -> { return entitytypes.a(world); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 4c592f6d4d6cbeb4c3225e7794f4b1d6c8d62394..b441dac8f31b679aa7e36d23848d34e298e6abba 100644 +index a80f664d2cf713fd751421be3735e2f4779f0056..6c37bf58bd269c2d7e1c84e5791e8245e4c75aea 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1199,5 +1199,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -1200,5 +1200,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { public boolean isRidableInWater() { return getHandle().isRidableInWater(); } @@ -46,7 +46,7 @@ index 4c592f6d4d6cbeb4c3225e7794f4b1d6c8d62394..b441dac8f31b679aa7e36d23848d34e2 // Purpur end } diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 81cff601a5161c30df90de3cefc18d72cd7ee347..980696490709d04741c1617f528357100696d0e5 100644 +index eba28b9c5cb87dea09bf8430d253725f585f87b9..609eda567751b2f1cf74e9f090ca5cb0c1d771cc 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -390,9 +390,14 @@ public final class CraftMagicNumbers implements UnsafeValues { @@ -64,7 +64,7 @@ index 81cff601a5161c30df90de3cefc18d72cd7ee347..980696490709d04741c1617f52835710 - compound.setInt("DataVersion", getDataVersion()); + // Purpur end try { - net.minecraft.server.NBTCompressedStreamTools.writeNBT( + net.minecraft.nbt.NBTCompressedStreamTools.writeNBT( compound, @@ -405,26 +410,58 @@ public final class CraftMagicNumbers implements UnsafeValues { return outputStream.toByteArray(); @@ -79,13 +79,13 @@ index 81cff601a5161c30df90de3cefc18d72cd7ee347..980696490709d04741c1617f52835710 + // Purpur start - rework NBT <-> bytes + NBTTagCompound compound = deserializeNbtFromBytes(data, true); + Dynamic converted = DataConverterRegistry.getDataFixer().update(DataConverterTypes.ITEM_STACK, new Dynamic<>(getDynamicOpsNbtInstance(), compound), compound.getInt("DataVersion"), getDataVersion()); // TODO: obfhelper -+ return net.minecraft.server.ItemStack.fromCompound((NBTTagCompound) converted.getValue()).asBukkitMirror(); ++ return net.minecraft.world.item.ItemStack.fromCompound((NBTTagCompound) converted.getValue()).asBukkitMirror(); + } + + public NBTTagCompound deserializeNbtFromBytes(byte[] data, boolean verifyDataVersion) { + // Purpur end try { - NBTTagCompound compound = net.minecraft.server.NBTCompressedStreamTools.readNBT( + NBTTagCompound compound = net.minecraft.nbt.NBTCompressedStreamTools.readNBT( new java.io.ByteArrayInputStream(data) ); + if (verifyDataVersion) { // Purpur @@ -93,7 +93,7 @@ index 81cff601a5161c30df90de3cefc18d72cd7ee347..980696490709d04741c1617f52835710 Preconditions.checkArgument(dataVersion <= getDataVersion(), "Newer version! Server downgrades are not supported!"); - Dynamic converted = DataConverterRegistry.getDataFixer().update(DataConverterTypes.ITEM_STACK, new Dynamic(DynamicOpsNBT.a, compound), dataVersion, getDataVersion()); -- return CraftItemStack.asCraftMirror(net.minecraft.server.ItemStack.fromCompound((NBTTagCompound) converted.getValue())); +- return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.fromCompound((NBTTagCompound) converted.getValue())); + } // Purpur + return compound; // Purpur } catch (IOException ex) { @@ -118,7 +118,7 @@ index 81cff601a5161c30df90de3cefc18d72cd7ee347..980696490709d04741c1617f52835710 + Dynamic converted = DataConverterRegistry.getDataFixer().update(DataConverterTypes.ENTITY, new Dynamic<>(getDynamicOpsNbtInstance(), compound), compound.getInt("DataVersion"), getDataVersion()); + compound = (NBTTagCompound) converted.getValue(); + compound.remove("UUID"); // Make the server make a new UUID for this entity; makes entities always spawnable. -+ return net.minecraft.server.EntityTypes.loadEntityFixedData(compound, ((org.bukkit.craftbukkit.CraftWorld) world).getHandle()) ++ return net.minecraft.world.entity.EntityTypes.loadEntityFixedData(compound, ((org.bukkit.craftbukkit.CraftWorld) world).getHandle()) + .orElseThrow(() -> new IllegalArgumentException("unknown ID was found for the data; did you downgrade?")) + .getBukkitEntity(); + } diff --git a/patches/server/0172-Add-ghast-allow-griefing-option.patch b/patches/server/0172-Add-ghast-allow-griefing-option.patch index 0ad16c54e..46ee8b506 100644 --- a/patches/server/0172-Add-ghast-allow-griefing-option.patch +++ b/patches/server/0172-Add-ghast-allow-griefing-option.patch @@ -4,11 +4,11 @@ Date: Sat, 13 Feb 2021 14:02:43 -0600 Subject: [PATCH] Add ghast allow-griefing option -diff --git a/src/main/java/net/minecraft/server/EntityGhast.java b/src/main/java/net/minecraft/server/EntityGhast.java -index 2c0148229283f95bed3c8f33cc02a31d6f682191..db96d2bb02dfeea4136eb587a7bd744c9eb30bf3 100644 ---- a/src/main/java/net/minecraft/server/EntityGhast.java -+++ b/src/main/java/net/minecraft/server/EntityGhast.java -@@ -198,6 +198,7 @@ public class EntityGhast extends EntityFlying implements IMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java b/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java +index 5c39a9aec865d25a9aa5edcfd3a0fd6d1166cbd1..4bc8b6ec44a03390ced313e84b03ab6662a3c0a2 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java +@@ -230,6 +230,7 @@ public class EntityGhast extends EntityFlying implements IMonster { } EntityLargeFireball entitylargefireball = new EntityLargeFireball(world, this.ghast, d2, d3, d4); @@ -16,11 +16,11 @@ index 2c0148229283f95bed3c8f33cc02a31d6f682191..db96d2bb02dfeea4136eb587a7bd744c // CraftBukkit - set bukkitYield when setting explosionpower entitylargefireball.bukkitYield = entitylargefireball.yield = this.ghast.getPower(); -diff --git a/src/main/java/net/minecraft/server/EntityLargeFireball.java b/src/main/java/net/minecraft/server/EntityLargeFireball.java -index 3f3be1b2ded6ad118ae7860c1231c7affc0715b6..48174610518af8d053149e609c1b140e1ae6ba61 100644 ---- a/src/main/java/net/minecraft/server/EntityLargeFireball.java -+++ b/src/main/java/net/minecraft/server/EntityLargeFireball.java -@@ -5,6 +5,7 @@ import org.bukkit.event.entity.ExplosionPrimeEvent; // CraftBukkit +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityLargeFireball.java b/src/main/java/net/minecraft/world/entity/projectile/EntityLargeFireball.java +index 61f06eacb4ea4ef869b60c9014cc23b25583eead..627915ee205fdcc93c5424ad7d7ea05783bc07ad 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityLargeFireball.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityLargeFireball.java +@@ -16,6 +16,7 @@ import org.bukkit.event.entity.ExplosionPrimeEvent; // CraftBukkit public class EntityLargeFireball extends EntityFireballFireball { public int yield = 1; @@ -28,7 +28,7 @@ index 3f3be1b2ded6ad118ae7860c1231c7affc0715b6..48174610518af8d053149e609c1b140e public EntityLargeFireball(EntityTypes entitytypes, World world) { super(entitytypes, world); -@@ -20,7 +21,7 @@ public class EntityLargeFireball extends EntityFireballFireball { +@@ -31,7 +32,7 @@ public class EntityLargeFireball extends EntityFireballFireball { protected void a(MovingObjectPosition movingobjectposition) { super.a(movingobjectposition); if (!this.world.isClientSide) { @@ -38,7 +38,7 @@ index 3f3be1b2ded6ad118ae7860c1231c7affc0715b6..48174610518af8d053149e609c1b140e // CraftBukkit start - fire ExplosionPrimeEvent ExplosionPrimeEvent event = new ExplosionPrimeEvent((org.bukkit.entity.Explosive) this.getBukkitEntity()); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 5a48219c214c062fee5a1915227923265febc698..514bcc4af3b9695c17d6e6c1e01e758eb027ab69 100644 +index 16eac6648c7bb17fb10f5741857ac5e8283aed50..ba4377422abe55a6ce98551eb9f8633589f37f4c 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -868,6 +868,7 @@ public class PurpurWorldConfig { diff --git a/patches/server/0173-Configs-for-if-Wither-Ender-Dragon-can-ride-vehicles.patch b/patches/server/0173-Configs-for-if-Wither-Ender-Dragon-can-ride-vehicles.patch index 5882aeab7..afe2118d8 100644 --- a/patches/server/0173-Configs-for-if-Wither-Ender-Dragon-can-ride-vehicles.patch +++ b/patches/server/0173-Configs-for-if-Wither-Ender-Dragon-can-ride-vehicles.patch @@ -4,11 +4,11 @@ Date: Sat, 20 Feb 2021 14:47:08 -0800 Subject: [PATCH] Configs for if Wither/Ender Dragon can ride vehicles -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index c27ce317c7acaf7ddd926c982d08e0539e045e28..426bebc5cd67ffcc72ee56d437cc13f6846e109c 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -2277,7 +2277,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index fcbbf100990faf60250357b744cbd58701da0b0c..d321616b7f726f4ff307b46ced9efce6cc20b82f 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2370,7 +2370,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne } } @@ -17,11 +17,11 @@ index c27ce317c7acaf7ddd926c982d08e0539e045e28..426bebc5cd67ffcc72ee56d437cc13f6 return !this.isSneaking() && this.j <= 0; } -diff --git a/src/main/java/net/minecraft/server/EntityEnderDragon.java b/src/main/java/net/minecraft/server/EntityEnderDragon.java -index e2377c6e8a98be431953533bf0b2060028caad45..a495c14b9f168884a0bba6b95d28c9ecfa9dfdab 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/server/EntityEnderDragon.java -@@ -1023,6 +1023,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +index a81d782877ff6116477792fa4cec0846e56ed384..6b0a71ce1c51e587ee17c8d60aaa52bbc87fb321 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +@@ -1073,6 +1073,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { @Override protected boolean n(Entity entity) { @@ -29,11 +29,11 @@ index e2377c6e8a98be431953533bf0b2060028caad45..a495c14b9f168884a0bba6b95d28c9ec return false; } -diff --git a/src/main/java/net/minecraft/server/EntityWither.java b/src/main/java/net/minecraft/server/EntityWither.java -index 27bfef57cfa1386e81c6409be49ea6898057e631..a8cda33da336f7c24a341f67a88681690d5a29a6 100644 ---- a/src/main/java/net/minecraft/server/EntityWither.java -+++ b/src/main/java/net/minecraft/server/EntityWither.java -@@ -673,6 +673,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java +index fa6b72c7a12b20f8ccffa360a3895e4d8f4277e4..4a3e0f7f59ca4fd64be62a580d08b6ab84649ee8 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java +@@ -730,6 +730,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { @Override protected boolean n(Entity entity) { @@ -42,7 +42,7 @@ index 27bfef57cfa1386e81c6409be49ea6898057e631..a8cda33da336f7c24a341f67a8868169 } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 514bcc4af3b9695c17d6e6c1e01e758eb027ab69..25e5105361a6615da80fe09224f30e14f0e8057b 100644 +index ba4377422abe55a6ce98551eb9f8633589f37f4c..d4f7d0550b499018896964e2528f2481e2245dc6 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -775,6 +775,7 @@ public class PurpurWorldConfig { diff --git a/patches/server/0174-Dont-run-with-scissors.patch b/patches/server/0174-Dont-run-with-scissors.patch index 26e6df4fe..615908136 100644 --- a/patches/server/0174-Dont-run-with-scissors.patch +++ b/patches/server/0174-Dont-run-with-scissors.patch @@ -4,17 +4,17 @@ Date: Fri, 5 Mar 2021 14:23:16 -0500 Subject: [PATCH] Dont run with scissors! -diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index f7a031920c68d5d5d505d86ab1b513ac53f5bf84..100ab4ae37a0d71a0d9bc3202802f705e1260ee1 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -1388,6 +1388,12 @@ public class PlayerConnection implements PacketListenerPlayIn { +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index c7c26cd1b99c911efd12e325e0ca09d9ac98c6f4..bdcc8ced52a858d2dd0bbfaab5a21197327d4dda 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -1533,6 +1533,12 @@ public class PlayerConnection implements PacketListenerPlayIn { this.player.fallDistance = 0.0F; } + // Purpur Start + if (this.player.isSprinting() && this.player.getWorldServer().purpurConfig.dontRunWithScissors && (this.player.getItemInHand(EnumHand.MAIN_HAND).getItem() == Items.SHEARS || this.player.getItemInHand(EnumHand.OFF_HAND).getItem() == Items.SHEARS) && (int) (Math.random() * 10) == 0) { -+ this.player.damageEntity(net.minecraft.server.DamageSource.MAGIC, (float) this.player.getWorldServer().purpurConfig.scissorsRunningDamage); ++ this.player.damageEntity(net.minecraft.world.damagesource.DamageSource.MAGIC, (float) this.player.getWorldServer().purpurConfig.scissorsRunningDamage); + } + // Purpur End + @@ -22,7 +22,7 @@ index f7a031920c68d5d5d505d86ab1b513ac53f5bf84..100ab4ae37a0d71a0d9bc3202802f705 this.o = this.player.locX(); this.p = this.player.locY(); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 25e5105361a6615da80fe09224f30e14f0e8057b..4930af515f7bb3b1bbc067e26d1b33027ccfcf17 100644 +index d4f7d0550b499018896964e2528f2481e2245dc6..7f5383518d45134bc2e3e39de310f8fa4ecf2451 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -168,6 +168,8 @@ public class PurpurWorldConfig { diff --git a/patches/server/0175-One-Punch-Man.patch b/patches/server/0175-One-Punch-Man.patch index 378c4a884..3d3e89b44 100644 --- a/patches/server/0175-One-Punch-Man.patch +++ b/patches/server/0175-One-Punch-Man.patch @@ -4,11 +4,11 @@ Date: Fri, 5 Mar 2021 17:42:35 -0500 Subject: [PATCH] One Punch Man! -diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index c514ba819e5fc69e67bd370469465a926672c2da..c5762aebcdd383ab710d4891308a7b1e815c44fd 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -1923,6 +1923,23 @@ public abstract class EntityLiving extends Entity { +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 66f1750172df09f1cbb47ca5a679a77a9ccab282..659ccc8075945531ca714c43a034f2d5baa5defb 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -2019,6 +2019,23 @@ public abstract class EntityLiving extends Entity { ((EntityPlayer) damagesource.getEntity()).a(StatisticList.DAMAGE_DEALT_ABSORBED, Math.round(f2 * 10.0F)); } @@ -32,11 +32,11 @@ index c514ba819e5fc69e67bd370469465a926672c2da..c5762aebcdd383ab710d4891308a7b1e if (f > 0 || !human) { if (human) { // PAIL: Be sure to drag all this code from the EntityHuman subclass each update. -diff --git a/src/main/java/net/minecraft/server/ItemStack.java b/src/main/java/net/minecraft/server/ItemStack.java -index 3f9062d8eca3ce53c0fb9e9e40330aa4e3296c9a..47e3ac6bcebacd9c424ddcc49774e06e05f02fe2 100644 ---- a/src/main/java/net/minecraft/server/ItemStack.java -+++ b/src/main/java/net/minecraft/server/ItemStack.java -@@ -842,6 +842,7 @@ public final class ItemStack { +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 132972755ac74838f3386e0fac5033380b71fce5..26fff0540e3d8863e83b0a60df2205422d50f1e1 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -897,6 +897,7 @@ public final class ItemStack { this.getOrCreateTag().setInt("RepairCost", i); } @@ -45,7 +45,7 @@ index 3f9062d8eca3ce53c0fb9e9e40330aa4e3296c9a..47e3ac6bcebacd9c424ddcc49774e06e Object object; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 4930af515f7bb3b1bbc067e26d1b33027ccfcf17..9fb065d077cc4282ba44059e8364e99c0238f9c5 100644 +index 7f5383518d45134bc2e3e39de310f8fa4ecf2451..ef75a80793a5a36177dd99879d19a91a52077e95 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -274,6 +274,7 @@ public class PurpurWorldConfig { diff --git a/patches/server/0176-Add-config-for-snow-on-blue-ice.patch b/patches/server/0176-Add-config-for-snow-on-blue-ice.patch index 10cc821cd..4aaeb30a6 100644 --- a/patches/server/0176-Add-config-for-snow-on-blue-ice.patch +++ b/patches/server/0176-Add-config-for-snow-on-blue-ice.patch @@ -4,11 +4,11 @@ Date: Fri, 5 Mar 2021 17:59:05 -0600 Subject: [PATCH] Add config for snow on blue ice -diff --git a/src/main/java/net/minecraft/server/BlockSnow.java b/src/main/java/net/minecraft/server/BlockSnow.java -index 66f188c9eb6431eedfd655a1dd4a35b5141e7196..21fd6689e1e6e837debc3c39d155402bca084595 100644 ---- a/src/main/java/net/minecraft/server/BlockSnow.java -+++ b/src/main/java/net/minecraft/server/BlockSnow.java -@@ -56,7 +56,18 @@ public class BlockSnow extends Block { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockSnow.java b/src/main/java/net/minecraft/world/level/block/BlockSnow.java +index d44b88185ce58346007c6ef70b76f8e0df23e95c..4b7497acc5b26da48375625b4a31fb057805344d 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockSnow.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockSnow.java +@@ -74,7 +74,18 @@ public class BlockSnow extends Block { public boolean canPlace(IBlockData iblockdata, IWorldReader iworldreader, BlockPosition blockposition) { IBlockData iblockdata1 = iworldreader.getType(blockposition.down()); @@ -29,7 +29,7 @@ index 66f188c9eb6431eedfd655a1dd4a35b5141e7196..21fd6689e1e6e837debc3c39d155402b @Override diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 9fb065d077cc4282ba44059e8364e99c0238f9c5..05a041c740c5464d348323064af1a1198c9f6a0e 100644 +index ef75a80793a5a36177dd99879d19a91a52077e95..3e7ec07ab595998b0a13ac9e44f5a5b9d0d45d03 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -419,6 +419,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0177-Configurable-Ender-Pearl-cooldown-damage-and-Endermi.patch b/patches/server/0177-Configurable-Ender-Pearl-cooldown-damage-and-Endermi.patch index 32b248a58..6669ce796 100644 --- a/patches/server/0177-Configurable-Ender-Pearl-cooldown-damage-and-Endermi.patch +++ b/patches/server/0177-Configurable-Ender-Pearl-cooldown-damage-and-Endermi.patch @@ -7,11 +7,11 @@ Subject: [PATCH] Configurable Ender Pearl cooldown, damage, and Endermite RNG - Damage dealt on pearl usage - Endermite spawn chance -diff --git a/src/main/java/net/minecraft/server/EntityEnderPearl.java b/src/main/java/net/minecraft/server/EntityEnderPearl.java -index 44dbe818b19c927098c1e6b2bcb556378be5637c..a1a070e786a7b587d103809957ec4f70f30f999a 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderPearl.java -+++ b/src/main/java/net/minecraft/server/EntityEnderPearl.java -@@ -54,7 +54,7 @@ public class EntityEnderPearl extends EntityProjectileThrowable { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityEnderPearl.java b/src/main/java/net/minecraft/world/entity/projectile/EntityEnderPearl.java +index cf2c691357c41a7e7044f7a719144db2ffab5dbe..d80c1abefe53e6b20dd2a020f60c11e380b57bb1 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityEnderPearl.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityEnderPearl.java +@@ -69,7 +69,7 @@ public class EntityEnderPearl extends EntityProjectileThrowable { Bukkit.getPluginManager().callEvent(teleEvent); if (!teleEvent.isCancelled() && !entityplayer.playerConnection.isDisconnected()) { @@ -20,7 +20,7 @@ index 44dbe818b19c927098c1e6b2bcb556378be5637c..a1a070e786a7b587d103809957ec4f70 EntityEndermite entityendermite = (EntityEndermite) EntityTypes.ENDERMITE.a(this.world); entityendermite.setPlayerSpawned(true); -@@ -69,7 +69,7 @@ public class EntityEnderPearl extends EntityProjectileThrowable { +@@ -84,7 +84,7 @@ public class EntityEnderPearl extends EntityProjectileThrowable { entityplayer.playerConnection.teleport(teleEvent.getTo()); entity.fallDistance = 0.0F; CraftEventFactory.entityDamage = this; @@ -29,21 +29,21 @@ index 44dbe818b19c927098c1e6b2bcb556378be5637c..a1a070e786a7b587d103809957ec4f70 CraftEventFactory.entityDamage = null; } // CraftBukkit end -diff --git a/src/main/java/net/minecraft/server/ItemEnderPearl.java b/src/main/java/net/minecraft/server/ItemEnderPearl.java -index 0e154ee2976694dacf8d41fcd831f21fbbda13af..f2cafb9f9365a3428f8fa0c35e9b6045d5729a8f 100644 ---- a/src/main/java/net/minecraft/server/ItemEnderPearl.java -+++ b/src/main/java/net/minecraft/server/ItemEnderPearl.java -@@ -27,7 +27,7 @@ public class ItemEnderPearl extends Item { +diff --git a/src/main/java/net/minecraft/world/item/ItemEnderPearl.java b/src/main/java/net/minecraft/world/item/ItemEnderPearl.java +index 9896d77381e7fadf1ef2619210713e190c1445d0..61512c6755f29cb2c228ae3e80b1e08348d784a5 100644 +--- a/src/main/java/net/minecraft/world/item/ItemEnderPearl.java ++++ b/src/main/java/net/minecraft/world/item/ItemEnderPearl.java +@@ -36,7 +36,7 @@ public class ItemEnderPearl extends Item { - world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); + world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); entityhuman.b(StatisticList.ITEM_USED.b(this)); - entityhuman.getCooldownTracker().setCooldown(this, 20); + entityhuman.getCooldownTracker().setCooldown(this, entityhuman.abilities.canInstantlyBuild ? world.purpurConfig.enderPearlCooldownCreative : world.purpurConfig.enderPearlCooldown); // Purpur } else { // Paper end - if (entityhuman instanceof EntityPlayer) { + if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 05a041c740c5464d348323064af1a1198c9f6a0e..83941fca744b9d044078029614d59d48af7ce382 100644 +index 3e7ec07ab595998b0a13ac9e44f5a5b9d0d45d03..c5a8f78563abc4dae68254b599b2ee60dee6d416 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -170,6 +170,10 @@ public class PurpurWorldConfig { diff --git a/patches/server/0178-Config-to-ignore-nearby-mobs-when-sleeping.patch b/patches/server/0178-Config-to-ignore-nearby-mobs-when-sleeping.patch index 270f6c024..957ab72b7 100644 --- a/patches/server/0178-Config-to-ignore-nearby-mobs-when-sleeping.patch +++ b/patches/server/0178-Config-to-ignore-nearby-mobs-when-sleeping.patch @@ -4,11 +4,11 @@ Date: Mon, 8 Mar 2021 16:46:54 -0500 Subject: [PATCH] Config to ignore nearby mobs when sleeping -diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index 5cf4a2b41d7f088eeb7c8003b8b889f370a4d214..c3833ea72c34efc9357706dac7afa2dbb768cf6a 100644 ---- a/src/main/java/net/minecraft/server/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/EntityPlayer.java -@@ -1311,7 +1311,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index ccee67df065dcdee5e0e24ab12476572ca696687..b4dbc59faff3fd6ceb74d829762eb68e649975c5 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -1443,7 +1443,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { return entitymonster.f((EntityHuman) this); }); @@ -18,7 +18,7 @@ index 5cf4a2b41d7f088eeb7c8003b8b889f370a4d214..c3833ea72c34efc9357706dac7afa2db } } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 83941fca744b9d044078029614d59d48af7ce382..0e004e67fb625035ab1db458f74beef9a20efc8f 100644 +index c5a8f78563abc4dae68254b599b2ee60dee6d416..fc68963c47d37b9ecec5debc367efe4647d67b2e 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -283,6 +283,7 @@ public class PurpurWorldConfig { diff --git a/patches/server/0179-Config-for-Enderman-to-aggro-spawned-Endermites.patch b/patches/server/0179-Config-for-Enderman-to-aggro-spawned-Endermites.patch index 66297cbf3..c5cfbc69e 100644 --- a/patches/server/0179-Config-for-Enderman-to-aggro-spawned-Endermites.patch +++ b/patches/server/0179-Config-for-Enderman-to-aggro-spawned-Endermites.patch @@ -5,11 +5,11 @@ Subject: [PATCH] Config for Enderman to aggro spawned Endermites By default, Enderman do not attack Endermites unless spawned by an Ender Pearl. -diff --git a/src/main/java/net/minecraft/server/EntityEnderman.java b/src/main/java/net/minecraft/server/EntityEnderman.java -index e20b91b36587d1191f8f9e8dd501607bf085e76d..c9fd8c8e7e36cbab2dcf4b0f5e6d84ede5851a12 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderman.java -+++ b/src/main/java/net/minecraft/server/EntityEnderman.java -@@ -16,7 +16,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +index d290787f74579dd4c138eb827e44544814bfe315..46143a710e057378ebe0ad644de275604b11d886 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +@@ -72,7 +72,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { private static final DataWatcherObject bo = DataWatcher.a(EntityEnderman.class, DataWatcherRegistry.i); private static final DataWatcherObject bp = DataWatcher.a(EntityEnderman.class, DataWatcherRegistry.i); private static final Predicate bq = (entityliving) -> { @@ -19,7 +19,7 @@ index e20b91b36587d1191f8f9e8dd501607bf085e76d..c9fd8c8e7e36cbab2dcf4b0f5e6d84ed private int br = Integer.MIN_VALUE; private int bs; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 0e004e67fb625035ab1db458f74beef9a20efc8f..9a41f45d0ccc019b44c289af16eacfe7960a2053 100644 +index fc68963c47d37b9ecec5debc367efe4647d67b2e..f6d6e57a0dea4d9e0de04caaab530682e3b212d5 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -823,6 +823,7 @@ public class PurpurWorldConfig { diff --git a/patches/server/0180-Config-to-ignore-Dragon-Head-wearers-and-stare-aggro.patch b/patches/server/0180-Config-to-ignore-Dragon-Head-wearers-and-stare-aggro.patch index 385433972..8ab2aac4c 100644 --- a/patches/server/0180-Config-to-ignore-Dragon-Head-wearers-and-stare-aggro.patch +++ b/patches/server/0180-Config-to-ignore-Dragon-Head-wearers-and-stare-aggro.patch @@ -6,11 +6,19 @@ Subject: [PATCH] Config to ignore Dragon Head wearers and stare aggro Prevents Enderman from becoming aggresive towards players that are wearing a Dragon Head. Adds functionality to a useless item! -diff --git a/src/main/java/net/minecraft/server/EntityEnderman.java b/src/main/java/net/minecraft/server/EntityEnderman.java -index c9fd8c8e7e36cbab2dcf4b0f5e6d84ede5851a12..e7568e3df10bc07e9b3b05caa9d41398925cf4d7 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderman.java -+++ b/src/main/java/net/minecraft/server/EntityEnderman.java -@@ -197,7 +197,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +index 46143a710e057378ebe0ad644de275604b11d886..0ed19429c1a9021e636fdfffa582b4e093fbc2e7 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +@@ -50,6 +50,7 @@ import net.minecraft.world.entity.ai.goal.target.PathfinderGoalUniversalAngerRes + import net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.item.Items; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.GeneratorAccess; + import net.minecraft.world.level.IMaterial; +@@ -253,7 +254,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { // Paper end ItemStack itemstack = (ItemStack) entityhuman.inventory.armor.get(3); @@ -20,7 +28,7 @@ index c9fd8c8e7e36cbab2dcf4b0f5e6d84ede5851a12..e7568e3df10bc07e9b3b05caa9d41398 } else { Vec3D vec3d = entityhuman.f(1.0F).d(); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 9a41f45d0ccc019b44c289af16eacfe7960a2053..6c7afd40d1bde770424216f01e78a07d05077670 100644 +index f6d6e57a0dea4d9e0de04caaab530682e3b212d5..fc29c54ee69bd39dec95cc5e877f5b6fb6bba442 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -824,6 +824,8 @@ public class PurpurWorldConfig { diff --git a/patches/server/0182-Tick-fluids-config.patch b/patches/server/0182-Tick-fluids-config.patch index c9fda6d4d..dddf56e11 100644 --- a/patches/server/0182-Tick-fluids-config.patch +++ b/patches/server/0182-Tick-fluids-config.patch @@ -4,11 +4,11 @@ Date: Mon, 15 Mar 2021 03:52:17 -0500 Subject: [PATCH] Tick fluids config -diff --git a/src/main/java/net/minecraft/server/BlockFluids.java b/src/main/java/net/minecraft/server/BlockFluids.java -index 07a9d462abad9a432dd5a153277839feeabad4bf..e470551fd4078924c3269714e7c60449fcecbc4d 100644 ---- a/src/main/java/net/minecraft/server/BlockFluids.java -+++ b/src/main/java/net/minecraft/server/BlockFluids.java -@@ -75,7 +75,7 @@ public class BlockFluids extends Block implements IFluidSource { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockFluids.java b/src/main/java/net/minecraft/world/level/block/BlockFluids.java +index 0ed8d938b8fafdb03e01a00a201ba3f8597ac6e9..0eff89bf9e114271c34c37cad1b98691902529ac 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockFluids.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockFluids.java +@@ -100,7 +100,7 @@ public class BlockFluids extends Block implements IFluidSource { @Override public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { @@ -17,7 +17,7 @@ index 07a9d462abad9a432dd5a153277839feeabad4bf..e470551fd4078924c3269714e7c60449 world.getFluidTickList().a(blockposition, iblockdata.getFluid().getType(), this.getFlowSpeed(world, blockposition)); // Paper } -@@ -100,7 +100,7 @@ public class BlockFluids extends Block implements IFluidSource { +@@ -125,7 +125,7 @@ public class BlockFluids extends Block implements IFluidSource { @Override public IBlockData updateState(IBlockData iblockdata, EnumDirection enumdirection, IBlockData iblockdata1, GeneratorAccess generatoraccess, BlockPosition blockposition, BlockPosition blockposition1) { @@ -26,7 +26,7 @@ index 07a9d462abad9a432dd5a153277839feeabad4bf..e470551fd4078924c3269714e7c60449 generatoraccess.getFluidTickList().a(blockposition, iblockdata.getFluid().getType(), this.b.a((IWorldReader) generatoraccess)); } -@@ -109,7 +109,7 @@ public class BlockFluids extends Block implements IFluidSource { +@@ -134,7 +134,7 @@ public class BlockFluids extends Block implements IFluidSource { @Override public void doPhysics(IBlockData iblockdata, World world, BlockPosition blockposition, Block block, BlockPosition blockposition1, boolean flag) { @@ -36,7 +36,7 @@ index 07a9d462abad9a432dd5a153277839feeabad4bf..e470551fd4078924c3269714e7c60449 } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 6c7afd40d1bde770424216f01e78a07d05077670..e3dccf08a9b931f83e0c0a218f5db60e643f7674 100644 +index fc29c54ee69bd39dec95cc5e877f5b6fb6bba442..ca108b3163c31fddd43112123c1c4cb70ba26bc9 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -261,6 +261,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0183-Config-to-disable-Llama-caravans.patch b/patches/server/0183-Config-to-disable-Llama-caravans.patch index 548386e37..9a97ac712 100644 --- a/patches/server/0183-Config-to-disable-Llama-caravans.patch +++ b/patches/server/0183-Config-to-disable-Llama-caravans.patch @@ -5,24 +5,11 @@ Subject: [PATCH] Config to disable Llama caravans Disables the mechanic where llamas follow leashed llamas. -diff --git a/src/main/java/net/minecraft/server/EntityLlama.java b/src/main/java/net/minecraft/server/EntityLlama.java -index f46a7cfe832c8cca83738b71882ff0a9819a7f41..b2e3f057206eab3a3c1a829b99ab66d3f8e212ad 100644 ---- a/src/main/java/net/minecraft/server/EntityLlama.java -+++ b/src/main/java/net/minecraft/server/EntityLlama.java -@@ -467,7 +467,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn - - public void joinCaravan(EntityLlama entitiyllama) { a(entitiyllama); } // Purpur - OBFHELPER - public void a(EntityLlama entityllama) { -- if (!shouldJoinCaravan || !new net.pl3x.purpur.event.entity.LlamaJoinCaravanEvent((org.bukkit.entity.Llama) getBukkitEntity(), (org.bukkit.entity.Llama) entityllama.getBukkitEntity()).callEvent()) return; // Purpur -+ if (!this.world.purpurConfig.llamaCaravans || !shouldJoinCaravan || !new net.pl3x.purpur.event.entity.LlamaJoinCaravanEvent((org.bukkit.entity.Llama) getBukkitEntity(), (org.bukkit.entity.Llama) entityllama.getBukkitEntity()).callEvent()) return; // Purpur - this.bB = entityllama; - this.bB.bC = this; - } -diff --git a/src/main/java/net/minecraft/server/PathfinderGoalLlamaFollow.java b/src/main/java/net/minecraft/server/PathfinderGoalLlamaFollow.java -index 47ffa669681da7512ee594ecb643f28576dee444..eb5e87b85f9daa392a69830dc4cee59a9b232837 100644 ---- a/src/main/java/net/minecraft/server/PathfinderGoalLlamaFollow.java -+++ b/src/main/java/net/minecraft/server/PathfinderGoalLlamaFollow.java -@@ -18,7 +18,7 @@ public class PathfinderGoalLlamaFollow extends PathfinderGoal { +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalLlamaFollow.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalLlamaFollow.java +index 34a854131dd939693a6df4d52103714ebe373dc3..ea02a78c31ed43220a2b83be4bd2a896500a70b8 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalLlamaFollow.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalLlamaFollow.java +@@ -23,7 +23,7 @@ public class PathfinderGoalLlamaFollow extends PathfinderGoal { @Override public boolean a() { @@ -31,8 +18,21 @@ index 47ffa669681da7512ee594ecb643f28576dee444..eb5e87b85f9daa392a69830dc4cee59a if (!this.a.isLeashed() && !this.a.fC()) { List list = this.a.world.getEntities(this.a, this.a.getBoundingBox().grow(9.0D, 4.0D, 9.0D), (entity) -> { EntityTypes entitytypes = entity.getEntityType(); +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java +index 762fed5ba27474951c1962e6f034e8494b1035d6..567a1da3c167c20ae3fb86c2a1f3608ebb1056b6 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java +@@ -518,7 +518,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn + + public void joinCaravan(EntityLlama entitiyllama) { a(entitiyllama); } // Purpur - OBFHELPER + public void a(EntityLlama entityllama) { +- if (!shouldJoinCaravan || !new net.pl3x.purpur.event.entity.LlamaJoinCaravanEvent((org.bukkit.entity.Llama) getBukkitEntity(), (org.bukkit.entity.Llama) entityllama.getBukkitEntity()).callEvent()) return; // Purpur ++ if (!this.world.purpurConfig.llamaCaravans || !shouldJoinCaravan || !new net.pl3x.purpur.event.entity.LlamaJoinCaravanEvent((org.bukkit.entity.Llama) getBukkitEntity(), (org.bukkit.entity.Llama) entityllama.getBukkitEntity()).callEvent()) return; // Purpur + this.bB = entityllama; + this.bB.bC = this; + } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index e3dccf08a9b931f83e0c0a218f5db60e643f7674..fc584ec761f04dbcc45e7e058d19a0efb110c2c6 100644 +index ca108b3163c31fddd43112123c1c4cb70ba26bc9..886d04393bfbd25d3c0131520e239ac0c3404654 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -1063,6 +1063,7 @@ public class PurpurWorldConfig { diff --git a/patches/server/0184-Config-to-make-Creepers-explode-on-death.patch b/patches/server/0184-Config-to-make-Creepers-explode-on-death.patch index e7adba2e4..768e6a770 100644 --- a/patches/server/0184-Config-to-make-Creepers-explode-on-death.patch +++ b/patches/server/0184-Config-to-make-Creepers-explode-on-death.patch @@ -5,11 +5,19 @@ Subject: [PATCH] Config to make Creepers explode on death Creepers exploded after being killed in the alpha days. This brings that back. -diff --git a/src/main/java/net/minecraft/server/EntityCreeper.java b/src/main/java/net/minecraft/server/EntityCreeper.java -index 523988bcc0607198dfb73afca5932ed6dd82cca1..6b3b1303862cd2ea90b5158e51ce94d3ad81d463 100644 ---- a/src/main/java/net/minecraft/server/EntityCreeper.java -+++ b/src/main/java/net/minecraft/server/EntityCreeper.java -@@ -23,6 +23,7 @@ public class EntityCreeper extends EntityMonster { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java +index 6461e09e05f9255a399a6ce65d8fb90789a2fd7f..5e70746494c5397d4d798d24b7292c57d145aef2 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java +@@ -7,6 +7,7 @@ import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; + import net.minecraft.server.PathfinderGoalHasRider; ++import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -63,6 +64,7 @@ public class EntityCreeper extends EntityMonster { private int spacebarCharge = 0; private int prevSpacebarCharge = 0; private int powerToggleDelay = 0; @@ -17,7 +25,7 @@ index 523988bcc0607198dfb73afca5932ed6dd82cca1..6b3b1303862cd2ea90b5158e51ce94d3 // Purpur end public EntityCreeper(EntityTypes entitytypes, World world) { -@@ -102,6 +103,14 @@ public class EntityCreeper extends EntityMonster { +@@ -142,6 +144,14 @@ public class EntityCreeper extends EntityMonster { public void initAttributes() { this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.creeperMaxHealth); } @@ -32,7 +40,7 @@ index 523988bcc0607198dfb73afca5932ed6dd82cca1..6b3b1303862cd2ea90b5158e51ce94d3 // Purpur end @Override -@@ -287,6 +296,7 @@ public class EntityCreeper extends EntityMonster { +@@ -327,6 +337,7 @@ public class EntityCreeper extends EntityMonster { } public void explode() { @@ -40,7 +48,7 @@ index 523988bcc0607198dfb73afca5932ed6dd82cca1..6b3b1303862cd2ea90b5158e51ce94d3 if (!this.world.isClientSide) { Explosion.Effect explosion_effect = this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) && world.purpurConfig.creeperAllowGriefing ? Explosion.Effect.DESTROY : Explosion.Effect.NONE; // Purpur float f = this.isPowered() ? 2.0F : 1.0F; -@@ -306,6 +316,7 @@ public class EntityCreeper extends EntityMonster { +@@ -346,6 +357,7 @@ public class EntityCreeper extends EntityMonster { // CraftBukkit end } @@ -49,7 +57,7 @@ index 523988bcc0607198dfb73afca5932ed6dd82cca1..6b3b1303862cd2ea90b5158e51ce94d3 private void createEffectCloud() { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index fc584ec761f04dbcc45e7e058d19a0efb110c2c6..4968223d4711e6fea414ee7fba4904f5fc35c074 100644 +index 886d04393bfbd25d3c0131520e239ac0c3404654..d975b08e3ef4921f17fc0aac85cfa7d9febb9054 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -699,12 +699,14 @@ public class PurpurWorldConfig { diff --git a/patches/server/0185-Configurable-ravager-griefable-blocks-list.patch b/patches/server/0185-Configurable-ravager-griefable-blocks-list.patch index 6f7840070..3c8afddc7 100644 --- a/patches/server/0185-Configurable-ravager-griefable-blocks-list.patch +++ b/patches/server/0185-Configurable-ravager-griefable-blocks-list.patch @@ -4,11 +4,24 @@ Date: Wed, 17 Mar 2021 14:54:43 -0500 Subject: [PATCH] Configurable ravager griefable blocks list -diff --git a/src/main/java/net/minecraft/server/BlockCrops.java b/src/main/java/net/minecraft/server/BlockCrops.java -index d49c309d7c31b3be0a21544ba23c0fd663f3317b..0fd8f9c6c77900fd4f46a439bae6a34487678c49 100644 ---- a/src/main/java/net/minecraft/server/BlockCrops.java -+++ b/src/main/java/net/minecraft/server/BlockCrops.java -@@ -144,7 +144,7 @@ public class BlockCrops extends BlockPlant implements IBlockFragilePlantElement +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java b/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java +index 6809c93fe435d183a27204fb4460fd68a86aa04f..aee5e370907d238cb0a0fb55a45341c8f60ed7d0 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java +@@ -189,7 +189,7 @@ public class EntityRavager extends EntityRaider { + IBlockData iblockdata = this.world.getType(blockposition); + Block block = iblockdata.getBlock(); + +- if (block instanceof BlockLeaves && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, net.minecraft.world.level.block.Blocks.AIR.getBlockData()).isCancelled()) { // CraftBukkit ++ if (world.purpurConfig.ravagerGriefableBlocks.contains(block) && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, net.minecraft.world.level.block.Blocks.AIR.getBlockData()).isCancelled()) { // CraftBukkit // Purpur + flag = this.world.a(blockposition, true, this) || flag; + } + } +diff --git a/src/main/java/net/minecraft/world/level/block/BlockCrops.java b/src/main/java/net/minecraft/world/level/block/BlockCrops.java +index 5f8366beeaac7153a0421554f9bf91fbf265edca..7fca4d1713e8061d9de825cdae48401217d4c6b1 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockCrops.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockCrops.java +@@ -160,7 +160,7 @@ public class BlockCrops extends BlockPlant implements IBlockFragilePlantElement @Override public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { @@ -17,21 +30,8 @@ index d49c309d7c31b3be0a21544ba23c0fd663f3317b..0fd8f9c6c77900fd4f46a439bae6a344 world.a(blockposition, true, entity); } -diff --git a/src/main/java/net/minecraft/server/EntityRavager.java b/src/main/java/net/minecraft/server/EntityRavager.java -index 3606440e41ab3193fadebb455c0967dbc0ccbb63..e6d3f705f499d07158b15b2a65235d5c2ff0a4fe 100644 ---- a/src/main/java/net/minecraft/server/EntityRavager.java -+++ b/src/main/java/net/minecraft/server/EntityRavager.java -@@ -147,7 +147,7 @@ public class EntityRavager extends EntityRaider { - IBlockData iblockdata = this.world.getType(blockposition); - Block block = iblockdata.getBlock(); - -- if (block instanceof BlockLeaves && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.getBlockData()).isCancelled()) { // CraftBukkit -+ if (world.purpurConfig.ravagerGriefableBlocks.contains(block) && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.getBlockData()).isCancelled()) { // CraftBukkit // Purpur - flag = this.world.a(blockposition, true, this) || flag; - } - } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 4968223d4711e6fea414ee7fba4904f5fc35c074..0f385273214c469e0f0d8a57b6c9bad9a79d221b 100644 +index d975b08e3ef4921f17fc0aac85cfa7d9febb9054..94f975521e9770577975810bb2c6c40d96303392 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -1404,6 +1404,7 @@ public class PurpurWorldConfig {