diff --git a/Paper b/Paper index d78cbb855..0823d3fdc 160000 --- a/Paper +++ b/Paper @@ -1 +1 @@ -Subproject commit d78cbb85531bd905ffc37691ff31d1f399fd9dfb +Subproject commit 0823d3fdce4cd7f877f7842e8da2f581e82ab596 diff --git a/current-paper b/current-paper index 0a4c73063..5e34fb9ec 100644 --- a/current-paper +++ b/current-paper @@ -1 +1 @@ -1.16.1--9df7694b152e9bdeb20c3f122f82f06d23ddc2dc +1.16.1--6b6bdc9c691dfb9f7ccb8bdb857a31df625170ae diff --git a/patches/api/0001-Tuinity-API-Changes.patch b/patches/api/0001-Tuinity-API-Changes.patch new file mode 100644 index 000000000..1ce59c793 --- /dev/null +++ b/patches/api/0001-Tuinity-API-Changes.patch @@ -0,0 +1,61 @@ +From c666bb03ff971b242661f09f9df8a48efb1145db Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 14 Dec 2018 21:52:29 -0800 +Subject: [PATCH] Tuinity API Changes + +--- + pom.xml | 12 ++++++------ + src/main/java/org/bukkit/Server.java | 8 ++++++++ + 2 files changed, 14 insertions(+), 6 deletions(-) + +diff --git a/pom.xml b/pom.xml +index dfc7c2f3..12a5e929 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -3,18 +3,18 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + +- com.destroystokyo.paper +- paper-parent ++ com.tuinity ++ tuinity-parent + dev-SNAPSHOT ++ ../pom.xml + + +- com.destroystokyo.paper +- paper-api ++ tuinity-api + 1.16.1-R0.1-SNAPSHOT + jar + +- Paper-API +- https://github.com/PaperMC/Paper ++ Tuinity-API ++ https://github.com/Spottedleaf/Tuinity + An enhanced plugin API for Minecraft servers. + + +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index b464cc1a..959e4e7e 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1424,6 +1424,14 @@ public interface Server extends PluginMessageRecipient { + } + // Paper end + ++ // Tuinity start - add config to timings report ++ @NotNull ++ public org.bukkit.configuration.file.YamlConfiguration getTuinityConfig() ++ { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ // Tuinity end - add config to timings report ++ + /** + * Sends the component to the player + * +-- +2.26.2 + diff --git a/patches/api/0001-Rebrand.patch b/patches/api/0002-Rebrand.patch similarity index 68% rename from patches/api/0001-Rebrand.patch rename to patches/api/0002-Rebrand.patch index 50fbcdea7..993efe0ca 100644 --- a/patches/api/0001-Rebrand.patch +++ b/patches/api/0002-Rebrand.patch @@ -1,41 +1,41 @@ -From 236214ae05f55fc6ae1305edf2eb85b1bcc5af66 Mon Sep 17 00:00:00 2001 +From 6cabefe5ac062e259a8ae4edf0f85628593d36a9 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 4 May 2019 00:57:16 -0500 Subject: [PATCH] Rebrand --- - pom.xml | 13 ++++++------- - 1 file changed, 6 insertions(+), 7 deletions(-) + pom.xml | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml -index dfc7c2f35..cb2dea442 100644 +index 12a5e929..84c9870e 100644 --- a/pom.xml +++ b/pom.xml -@@ -3,18 +3,17 @@ +@@ -3,18 +3,18 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 -- com.destroystokyo.paper -- paper-parent +- com.tuinity +- tuinity-parent + net.pl3x.purpur + purpur-parent dev-SNAPSHOT + ../pom.xml -- com.destroystokyo.paper -- paper-api +- tuinity-api + purpur-api 1.16.1-R0.1-SNAPSHOT jar -- Paper-API -- https://github.com/PaperMC/Paper +- Tuinity-API +- https://github.com/Spottedleaf/Tuinity + Purpur-API + https://github.com/pl3xgaming/Purpur An enhanced plugin API for Minecraft servers. -@@ -149,7 +148,7 @@ +@@ -149,7 +149,7 @@ diff --git a/patches/api/0002-Purpur-config-files.patch b/patches/api/0003-Purpur-config-files.patch similarity index 81% rename from patches/api/0002-Purpur-config-files.patch rename to patches/api/0003-Purpur-config-files.patch index 9817d6a9e..3bd79e29d 100644 --- a/patches/api/0002-Purpur-config-files.patch +++ b/patches/api/0003-Purpur-config-files.patch @@ -1,4 +1,4 @@ -From 207d7356ada158abb9151799b2c290cef7e465d0 Mon Sep 17 00:00:00 2001 +From 51909d1294b8a427c02ab0edac37205069b58d78 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Tue, 18 Feb 2020 20:30:03 -0600 Subject: [PATCH] Purpur config files @@ -8,12 +8,12 @@ Subject: [PATCH] Purpur config files 1 file changed, 12 insertions(+) diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index b464cc1a7..1a05a438c 100644 +index 959e4e7e..a5262420 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -1424,6 +1424,18 @@ public interface Server extends PluginMessageRecipient { +@@ -1432,6 +1432,18 @@ public interface Server extends PluginMessageRecipient { } - // Paper end + // Tuinity end - add config to timings report + // Purpur start + @NotNull diff --git a/patches/api/0003-Default-permissions.patch b/patches/api/0004-Default-permissions.patch similarity index 97% rename from patches/api/0003-Default-permissions.patch rename to patches/api/0004-Default-permissions.patch index eea456ab4..c2c66935c 100644 --- a/patches/api/0003-Default-permissions.patch +++ b/patches/api/0004-Default-permissions.patch @@ -1,4 +1,4 @@ -From 77cf864ad36201a94e3c8ac0535064c98e5c175a Mon Sep 17 00:00:00 2001 +From 0105b33898fbefac968bac777201e745d11bdb73 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 5 Jun 2020 23:32:38 -0500 Subject: [PATCH] Default permissions @@ -11,7 +11,7 @@ Subject: [PATCH] Default permissions create mode 100644 src/main/java/org/bukkit/util/permissions/PurpurPermissions.java diff --git a/src/main/java/org/bukkit/util/permissions/CommandPermissions.java b/src/main/java/org/bukkit/util/permissions/CommandPermissions.java -index 7763d6101..d5a42707d 100644 +index 7763d610..d5a42707 100644 --- a/src/main/java/org/bukkit/util/permissions/CommandPermissions.java +++ b/src/main/java/org/bukkit/util/permissions/CommandPermissions.java @@ -18,6 +18,7 @@ public final class CommandPermissions { @@ -23,7 +23,7 @@ index 7763d6101..d5a42707d 100644 commands.recalculatePermissibles(); return commands; diff --git a/src/main/java/org/bukkit/util/permissions/DefaultPermissions.java b/src/main/java/org/bukkit/util/permissions/DefaultPermissions.java -index e1a4ddf2c..8e481e381 100644 +index e1a4ddf2..8e481e38 100644 --- a/src/main/java/org/bukkit/util/permissions/DefaultPermissions.java +++ b/src/main/java/org/bukkit/util/permissions/DefaultPermissions.java @@ -89,6 +89,8 @@ public final class DefaultPermissions { @@ -37,7 +37,7 @@ index e1a4ddf2c..8e481e381 100644 } diff --git a/src/main/java/org/bukkit/util/permissions/PurpurPermissions.java b/src/main/java/org/bukkit/util/permissions/PurpurPermissions.java new file mode 100644 -index 000000000..14cb78e3e +index 00000000..14cb78e3 --- /dev/null +++ b/src/main/java/org/bukkit/util/permissions/PurpurPermissions.java @@ -0,0 +1,69 @@ diff --git a/patches/api/0004-Allow-inventory-resizing.patch b/patches/api/0005-Allow-inventory-resizing.patch similarity index 91% rename from patches/api/0004-Allow-inventory-resizing.patch rename to patches/api/0005-Allow-inventory-resizing.patch index 132d2ef12..35eb0dde6 100644 --- a/patches/api/0004-Allow-inventory-resizing.patch +++ b/patches/api/0005-Allow-inventory-resizing.patch @@ -1,4 +1,4 @@ -From 683682367df0d1ec0605b5d75398d9a3f096ca2a Mon Sep 17 00:00:00 2001 +From 71daaa052b59b70bfdf1d26a1fc7eb85aceda055 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Tue, 23 Jul 2019 06:50:55 -0500 Subject: [PATCH] Allow inventory resizing @@ -8,7 +8,7 @@ Subject: [PATCH] Allow inventory resizing 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/bukkit/event/inventory/InventoryType.java b/src/main/java/org/bukkit/event/inventory/InventoryType.java -index b59fec1ae..e3b77f565 100644 +index b59fec1a..e3b77f56 100644 --- a/src/main/java/org/bukkit/event/inventory/InventoryType.java +++ b/src/main/java/org/bukkit/event/inventory/InventoryType.java @@ -132,7 +132,7 @@ public enum InventoryType { diff --git a/patches/api/0005-Advancement-API.patch b/patches/api/0006-Advancement-API.patch similarity index 96% rename from patches/api/0005-Advancement-API.patch rename to patches/api/0006-Advancement-API.patch index 0db098970..628b0c233 100644 --- a/patches/api/0005-Advancement-API.patch +++ b/patches/api/0006-Advancement-API.patch @@ -1,4 +1,4 @@ -From c43598530aeb734560bda5aa9e33ba4ecc18ed2a Mon Sep 17 00:00:00 2001 +From 187dbb6bb7a7a564c79b2db678c2fd5d9f32d964 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 31 May 2019 21:24:21 -0500 Subject: [PATCH] Advancement API @@ -12,7 +12,7 @@ Subject: [PATCH] Advancement API create mode 100644 src/main/java/org/bukkit/advancement/FrameType.java diff --git a/src/main/java/org/bukkit/advancement/Advancement.java b/src/main/java/org/bukkit/advancement/Advancement.java -index 7c5009974..432caadba 100644 +index 7c500997..432caadb 100644 --- a/src/main/java/org/bukkit/advancement/Advancement.java +++ b/src/main/java/org/bukkit/advancement/Advancement.java @@ -3,6 +3,7 @@ package org.bukkit.advancement; @@ -38,7 +38,7 @@ index 7c5009974..432caadba 100644 } diff --git a/src/main/java/org/bukkit/advancement/AdvancementDisplay.java b/src/main/java/org/bukkit/advancement/AdvancementDisplay.java new file mode 100644 -index 000000000..bca3d112e +index 00000000..bca3d112 --- /dev/null +++ b/src/main/java/org/bukkit/advancement/AdvancementDisplay.java @@ -0,0 +1,53 @@ @@ -97,7 +97,7 @@ index 000000000..bca3d112e +} diff --git a/src/main/java/org/bukkit/advancement/FrameType.java b/src/main/java/org/bukkit/advancement/FrameType.java new file mode 100644 -index 000000000..d1757f3d4 +index 00000000..d1757f3d --- /dev/null +++ b/src/main/java/org/bukkit/advancement/FrameType.java @@ -0,0 +1,27 @@ diff --git a/patches/api/0006-Llama-API.patch b/patches/api/0007-Llama-API.patch similarity index 97% rename from patches/api/0006-Llama-API.patch rename to patches/api/0007-Llama-API.patch index 8ec68ac13..724e5b743 100644 --- a/patches/api/0006-Llama-API.patch +++ b/patches/api/0007-Llama-API.patch @@ -1,4 +1,4 @@ -From 3efaae899100095ab241d17882103707e439d625 Mon Sep 17 00:00:00 2001 +From 6218971b943e4ead4f80712c59d44efb80c0511e Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 18 Oct 2019 22:50:05 -0500 Subject: [PATCH] Llama API @@ -13,7 +13,7 @@ Subject: [PATCH] Llama API diff --git a/src/main/java/net/pl3x/purpur/event/entity/LlamaJoinCaravanEvent.java b/src/main/java/net/pl3x/purpur/event/entity/LlamaJoinCaravanEvent.java new file mode 100644 -index 000000000..6e68c1399 +index 00000000..6e68c139 --- /dev/null +++ b/src/main/java/net/pl3x/purpur/event/entity/LlamaJoinCaravanEvent.java @@ -0,0 +1,61 @@ @@ -80,7 +80,7 @@ index 000000000..6e68c1399 +} diff --git a/src/main/java/net/pl3x/purpur/event/entity/LlamaLeaveCaravanEvent.java b/src/main/java/net/pl3x/purpur/event/entity/LlamaLeaveCaravanEvent.java new file mode 100644 -index 000000000..ec8d978c2 +index 00000000..ec8d978c --- /dev/null +++ b/src/main/java/net/pl3x/purpur/event/entity/LlamaLeaveCaravanEvent.java @@ -0,0 +1,34 @@ @@ -119,7 +119,7 @@ index 000000000..ec8d978c2 + } +} diff --git a/src/main/java/org/bukkit/entity/Llama.java b/src/main/java/org/bukkit/entity/Llama.java -index d23226ccb..1ef9479c9 100644 +index d23226cc..1ef9479c 100644 --- a/src/main/java/org/bukkit/entity/Llama.java +++ b/src/main/java/org/bukkit/entity/Llama.java @@ -3,6 +3,7 @@ package org.bukkit.entity; diff --git a/patches/api/0007-Evoker-API.patch b/patches/api/0008-Evoker-API.patch similarity index 90% rename from patches/api/0007-Evoker-API.patch rename to patches/api/0008-Evoker-API.patch index 3facccd62..c81e694b1 100644 --- a/patches/api/0007-Evoker-API.patch +++ b/patches/api/0008-Evoker-API.patch @@ -1,4 +1,4 @@ -From bbc865bdfdd716cc526fbd7cc57e6eb0841d9926 Mon Sep 17 00:00:00 2001 +From 5f09e991c9555ba836ee891e52acd6881040d345 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 19 Oct 2019 00:28:53 -0500 Subject: [PATCH] Evoker API @@ -8,7 +8,7 @@ Subject: [PATCH] Evoker API 1 file changed, 17 insertions(+) diff --git a/src/main/java/org/bukkit/entity/Evoker.java b/src/main/java/org/bukkit/entity/Evoker.java -index f8d173adc..f2a03f7f8 100644 +index f8d173ad..f2a03f7f 100644 --- a/src/main/java/org/bukkit/entity/Evoker.java +++ b/src/main/java/org/bukkit/entity/Evoker.java @@ -64,4 +64,21 @@ public interface Evoker extends Spellcaster { diff --git a/patches/api/0008-AFK-API.patch b/patches/api/0009-AFK-API.patch similarity index 96% rename from patches/api/0008-AFK-API.patch rename to patches/api/0009-AFK-API.patch index 62f9099f4..8a70f4895 100644 --- a/patches/api/0008-AFK-API.patch +++ b/patches/api/0009-AFK-API.patch @@ -1,4 +1,4 @@ -From b01aba9c3138bfcde84036b1fbed0ec910617913 Mon Sep 17 00:00:00 2001 +From 7fa4a397d97e8bac99b3eed5d995d6696d820ebe Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 10 Aug 2019 22:19:56 -0500 Subject: [PATCH] AFK API @@ -11,7 +11,7 @@ Subject: [PATCH] AFK API diff --git a/src/main/java/net/pl3x/purpur/event/PlayerAFKEvent.java b/src/main/java/net/pl3x/purpur/event/PlayerAFKEvent.java new file mode 100644 -index 000000000..0c8b3e5e4 +index 00000000..0c8b3e5e --- /dev/null +++ b/src/main/java/net/pl3x/purpur/event/PlayerAFKEvent.java @@ -0,0 +1,70 @@ @@ -86,7 +86,7 @@ index 000000000..0c8b3e5e4 + } +} diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 2eb312138..2dca16ac4 100644 +index 2eb31213..2dca16ac 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -1870,4 +1870,25 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM diff --git a/patches/api/0009-Bring-back-server-name.patch b/patches/api/0010-Bring-back-server-name.patch similarity index 87% rename from patches/api/0009-Bring-back-server-name.patch rename to patches/api/0010-Bring-back-server-name.patch index 7516e7ea7..76959e80a 100644 --- a/patches/api/0009-Bring-back-server-name.patch +++ b/patches/api/0010-Bring-back-server-name.patch @@ -1,4 +1,4 @@ -From 964c8bd13a95dd17362e4c9bf98acc1a7662e008 Mon Sep 17 00:00:00 2001 +From 2c69dbc2a73e148723a2011c2b78006ee23e97ae Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 26 May 2019 15:18:40 -0500 Subject: [PATCH] Bring back server name @@ -9,7 +9,7 @@ Subject: [PATCH] Bring back server name 2 files changed, 20 insertions(+) diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 329e2dd1c..4f6f01939 100644 +index 329e2dd1..4f6f0193 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -1749,4 +1749,15 @@ public final class Bukkit { @@ -29,10 +29,10 @@ index 329e2dd1c..4f6f01939 100644 + // Purpur end } diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 1a05a438c..c8b50ec90 100644 +index a5262420..e3808a79 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -1536,4 +1536,13 @@ public interface Server extends PluginMessageRecipient { +@@ -1544,4 +1544,13 @@ public interface Server extends PluginMessageRecipient { @NotNull com.destroystokyo.paper.entity.ai.MobGoals getMobGoals(); // Paper end diff --git a/patches/api/0010-ExecuteCommandEvent.patch b/patches/api/0011-ExecuteCommandEvent.patch similarity index 97% rename from patches/api/0010-ExecuteCommandEvent.patch rename to patches/api/0011-ExecuteCommandEvent.patch index 7650df629..273491d8d 100644 --- a/patches/api/0010-ExecuteCommandEvent.patch +++ b/patches/api/0011-ExecuteCommandEvent.patch @@ -1,4 +1,4 @@ -From c9d8ecde06f4f694ed59d1da743b79b003a55b3c Mon Sep 17 00:00:00 2001 +From 7168d5182318a5a5c35f20bddaf992ecea957763 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 31 May 2019 00:08:28 -0500 Subject: [PATCH] ExecuteCommandEvent @@ -11,7 +11,7 @@ Subject: [PATCH] ExecuteCommandEvent diff --git a/src/main/java/net/pl3x/purpur/event/ExecuteCommandEvent.java b/src/main/java/net/pl3x/purpur/event/ExecuteCommandEvent.java new file mode 100644 -index 000000000..3250bd4dc +index 00000000..3250bd4d --- /dev/null +++ b/src/main/java/net/pl3x/purpur/event/ExecuteCommandEvent.java @@ -0,0 +1,130 @@ @@ -146,7 +146,7 @@ index 000000000..3250bd4dc + } +} diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java -index 460fda05a..1e0eb0999 100644 +index 460fda05..1e0eb099 100644 --- a/src/main/java/org/bukkit/command/SimpleCommandMap.java +++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java @@ -147,6 +147,19 @@ public class SimpleCommandMap implements CommandMap { diff --git a/patches/api/0011-LivingEntity-safeFallDistance.patch b/patches/api/0012-LivingEntity-safeFallDistance.patch similarity index 91% rename from patches/api/0011-LivingEntity-safeFallDistance.patch rename to patches/api/0012-LivingEntity-safeFallDistance.patch index cf1171c05..9c9f8847b 100644 --- a/patches/api/0011-LivingEntity-safeFallDistance.patch +++ b/patches/api/0012-LivingEntity-safeFallDistance.patch @@ -1,4 +1,4 @@ -From 6e3bdc06356d7b63bb206d7319badf594e30d872 Mon Sep 17 00:00:00 2001 +From 148b37f8d2e62b7075b27b0d36dd0470b460e142 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 5 May 2019 12:58:19 -0500 Subject: [PATCH] LivingEntity safeFallDistance @@ -8,7 +8,7 @@ Subject: [PATCH] LivingEntity safeFallDistance 1 file changed, 16 insertions(+) diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index a60523cc9..5b688cd04 100644 +index a60523cc..5b688cd0 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java @@ -753,4 +753,20 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource diff --git a/patches/api/0012-MoonPhase-API.patch b/patches/api/0013-MoonPhase-API.patch similarity index 93% rename from patches/api/0012-MoonPhase-API.patch rename to patches/api/0013-MoonPhase-API.patch index d85256934..9962bc048 100644 --- a/patches/api/0012-MoonPhase-API.patch +++ b/patches/api/0013-MoonPhase-API.patch @@ -1,4 +1,4 @@ -From 28381a87dfb15e899df91a30192d98eb2575dff8 Mon Sep 17 00:00:00 2001 +From 429414ef1d9773c1df37641278660e4a68dea10f Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 1 Feb 2020 22:22:07 -0600 Subject: [PATCH] MoonPhase API @@ -11,7 +11,7 @@ Subject: [PATCH] MoonPhase API diff --git a/src/main/java/net/pl3x/purpur/MoonPhase.java b/src/main/java/net/pl3x/purpur/MoonPhase.java new file mode 100644 -index 000000000..f5ad98c62 +index 00000000..f5ad98c6 --- /dev/null +++ b/src/main/java/net/pl3x/purpur/MoonPhase.java @@ -0,0 +1,36 @@ @@ -52,7 +52,7 @@ index 000000000..f5ad98c62 + } +} diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 75c9225bd..9955d7417 100644 +index 75c9225b..9955d741 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -3450,6 +3450,16 @@ public interface World extends PluginMessageRecipient, Metadatable { diff --git a/patches/api/0013-Lagging-threshold.patch b/patches/api/0014-Lagging-threshold.patch similarity index 86% rename from patches/api/0013-Lagging-threshold.patch rename to patches/api/0014-Lagging-threshold.patch index 4318e2b36..03a0d33a2 100644 --- a/patches/api/0013-Lagging-threshold.patch +++ b/patches/api/0014-Lagging-threshold.patch @@ -1,4 +1,4 @@ -From cc7269c63a9bf44a2ddf6d3e51d3d665d265f271 Mon Sep 17 00:00:00 2001 +From fadc3e9707dd05213bf119aba6d4604696729896 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Tue, 23 Jul 2019 10:07:24 -0500 Subject: [PATCH] Lagging threshold @@ -9,7 +9,7 @@ Subject: [PATCH] Lagging threshold 2 files changed, 16 insertions(+) diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 4f6f01939..4c410f6e1 100644 +index 4f6f0193..4c410f6e 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -1759,5 +1759,14 @@ public final class Bukkit { @@ -28,10 +28,10 @@ index 4f6f01939..4c410f6e1 100644 // Purpur end } diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index c8b50ec90..dc6201365 100644 +index e3808a79..d8c81767 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -1544,5 +1544,12 @@ public interface Server extends PluginMessageRecipient { +@@ -1552,5 +1552,12 @@ public interface Server extends PluginMessageRecipient { */ @NotNull String getServerName(); diff --git a/patches/api/0014-ItemFactory-getMonsterEgg.patch b/patches/api/0015-ItemFactory-getMonsterEgg.patch similarity index 90% rename from patches/api/0014-ItemFactory-getMonsterEgg.patch rename to patches/api/0015-ItemFactory-getMonsterEgg.patch index f490fe151..52e44f911 100644 --- a/patches/api/0014-ItemFactory-getMonsterEgg.patch +++ b/patches/api/0015-ItemFactory-getMonsterEgg.patch @@ -1,4 +1,4 @@ -From 3414a3777cd50ba9f807ed0f83284f7dd88e0137 Mon Sep 17 00:00:00 2001 +From 6a8e9699b7a8d5a40f88f01f62670fd9b74a7b7e Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 5 Jul 2019 16:37:04 -0500 Subject: [PATCH] ItemFactory#getMonsterEgg @@ -8,7 +8,7 @@ Subject: [PATCH] ItemFactory#getMonsterEgg 1 file changed, 11 insertions(+) diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java -index 03ba22659..630c15d23 100644 +index 03ba2265..630c15d2 100644 --- a/src/main/java/org/bukkit/inventory/ItemFactory.java +++ b/src/main/java/org/bukkit/inventory/ItemFactory.java @@ -166,4 +166,15 @@ public interface ItemFactory { diff --git a/patches/api/0015-PlayerSetSpawnerTypeWithEggEvent.patch b/patches/api/0016-PlayerSetSpawnerTypeWithEggEvent.patch similarity index 96% rename from patches/api/0015-PlayerSetSpawnerTypeWithEggEvent.patch rename to patches/api/0016-PlayerSetSpawnerTypeWithEggEvent.patch index 3b6f626b7..f977fd70c 100644 --- a/patches/api/0015-PlayerSetSpawnerTypeWithEggEvent.patch +++ b/patches/api/0016-PlayerSetSpawnerTypeWithEggEvent.patch @@ -1,4 +1,4 @@ -From 793caade58c03633ae3b36b59ced116586950df6 Mon Sep 17 00:00:00 2001 +From 192ebbf530a67ed5a3d0baed103708f95e9aa39f Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 5 Jul 2019 18:21:15 -0500 Subject: [PATCH] PlayerSetSpawnerTypeWithEggEvent @@ -10,7 +10,7 @@ Subject: [PATCH] PlayerSetSpawnerTypeWithEggEvent diff --git a/src/main/java/net/pl3x/purpur/event/PlayerSetSpawnerTypeWithEggEvent.java b/src/main/java/net/pl3x/purpur/event/PlayerSetSpawnerTypeWithEggEvent.java new file mode 100644 -index 000000000..c050b75e9 +index 00000000..c050b75e --- /dev/null +++ b/src/main/java/net/pl3x/purpur/event/PlayerSetSpawnerTypeWithEggEvent.java @@ -0,0 +1,85 @@ diff --git a/patches/api/0016-EMC-MonsterEggSpawnEvent.patch b/patches/api/0017-EMC-MonsterEggSpawnEvent.patch similarity index 96% rename from patches/api/0016-EMC-MonsterEggSpawnEvent.patch rename to patches/api/0017-EMC-MonsterEggSpawnEvent.patch index 830267520..4999f541c 100644 --- a/patches/api/0016-EMC-MonsterEggSpawnEvent.patch +++ b/patches/api/0017-EMC-MonsterEggSpawnEvent.patch @@ -1,4 +1,4 @@ -From 6f446935210fd7f4676937654457d8d6c1faf2ca Mon Sep 17 00:00:00 2001 +From a9021d0f56cb27f4532c44e3ce8400bfad8563a7 Mon Sep 17 00:00:00 2001 From: Aikar Date: Mon, 21 Nov 2016 17:02:11 -0500 Subject: [PATCH] EMC - MonsterEggSpawnEvent @@ -10,7 +10,7 @@ Subject: [PATCH] EMC - MonsterEggSpawnEvent diff --git a/src/main/java/net/pl3x/purpur/event/entity/MonsterEggSpawnEvent.java b/src/main/java/net/pl3x/purpur/event/entity/MonsterEggSpawnEvent.java new file mode 100644 -index 000000000..983d67234 +index 00000000..983d6723 --- /dev/null +++ b/src/main/java/net/pl3x/purpur/event/entity/MonsterEggSpawnEvent.java @@ -0,0 +1,67 @@ diff --git a/patches/api/0017-Villager-resetOffers.patch b/patches/api/0018-Villager-resetOffers.patch similarity index 89% rename from patches/api/0017-Villager-resetOffers.patch rename to patches/api/0018-Villager-resetOffers.patch index 76196e728..4c9c280c2 100644 --- a/patches/api/0017-Villager-resetOffers.patch +++ b/patches/api/0018-Villager-resetOffers.patch @@ -1,4 +1,4 @@ -From 49323476e3d0ca119769a379c1080de43ebd3981 Mon Sep 17 00:00:00 2001 +From 70a13007f8475a226590df7dcd9fdd6c2060de1e Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Mon, 7 Oct 2019 00:15:28 -0500 Subject: [PATCH] Villager#resetOffers @@ -8,7 +8,7 @@ Subject: [PATCH] Villager#resetOffers 1 file changed, 7 insertions(+) diff --git a/src/main/java/org/bukkit/entity/Villager.java b/src/main/java/org/bukkit/entity/Villager.java -index c8777a476..ed703af45 100644 +index c8777a47..ed703af4 100644 --- a/src/main/java/org/bukkit/entity/Villager.java +++ b/src/main/java/org/bukkit/entity/Villager.java @@ -113,6 +113,13 @@ public interface Villager extends AbstractVillager { diff --git a/patches/api/0018-World-getPlacementBlockData.patch b/patches/api/0019-World-getPlacementBlockData.patch similarity index 90% rename from patches/api/0018-World-getPlacementBlockData.patch rename to patches/api/0019-World-getPlacementBlockData.patch index b062e9d8a..6efbabdfb 100644 --- a/patches/api/0018-World-getPlacementBlockData.patch +++ b/patches/api/0019-World-getPlacementBlockData.patch @@ -1,4 +1,4 @@ -From f7b6857340ba29d5877523fa69ad968247143ae7 Mon Sep 17 00:00:00 2001 +From 8eb0a3b8e8fb7dfaef23c02f6f3ce2183461047c Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 19 Oct 2019 00:34:36 -0500 Subject: [PATCH] World#getPlacementBlockData @@ -8,7 +8,7 @@ Subject: [PATCH] World#getPlacementBlockData 1 file changed, 10 insertions(+) diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 9955d7417..950425979 100644 +index 9955d741..95042597 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -3458,6 +3458,16 @@ public interface World extends PluginMessageRecipient, Metadatable { diff --git a/patches/api/0019-LivingEntity-playPickupItemAnimation.patch b/patches/api/0020-LivingEntity-playPickupItemAnimation.patch similarity index 92% rename from patches/api/0019-LivingEntity-playPickupItemAnimation.patch rename to patches/api/0020-LivingEntity-playPickupItemAnimation.patch index 7f7a2f7e9..cfe52336f 100644 --- a/patches/api/0019-LivingEntity-playPickupItemAnimation.patch +++ b/patches/api/0020-LivingEntity-playPickupItemAnimation.patch @@ -1,4 +1,4 @@ -From ee3249840f9b53b10d7df7434088c5be3a1cd1ea Mon Sep 17 00:00:00 2001 +From d5561b9fc5626a9d263d12145c58eb2f39a4bcca Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 19 Oct 2019 02:25:05 -0500 Subject: [PATCH] LivingEntity#playPickupItemAnimation @@ -8,7 +8,7 @@ Subject: [PATCH] LivingEntity#playPickupItemAnimation 1 file changed, 17 insertions(+) diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 5b688cd04..a0db76946 100644 +index 5b688cd0..a0db7694 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java @@ -768,5 +768,22 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource diff --git a/patches/api/0020-SkeletonHorseTrapEvent-getPlayer.patch b/patches/api/0021-SkeletonHorseTrapEvent-getPlayer.patch similarity index 95% rename from patches/api/0020-SkeletonHorseTrapEvent-getPlayer.patch rename to patches/api/0021-SkeletonHorseTrapEvent-getPlayer.patch index a8689b8ca..739aef29a 100644 --- a/patches/api/0020-SkeletonHorseTrapEvent-getPlayer.patch +++ b/patches/api/0021-SkeletonHorseTrapEvent-getPlayer.patch @@ -1,4 +1,4 @@ -From 9dc21420ed45e161850891442fb6f6ab988eb2e8 Mon Sep 17 00:00:00 2001 +From b9d3e5804fc24259bf59943ac14de4a3416a4856 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 19 Oct 2019 02:35:24 -0500 Subject: [PATCH] SkeletonHorseTrapEvent#getPlayer @@ -8,7 +8,7 @@ Subject: [PATCH] SkeletonHorseTrapEvent#getPlayer 1 file changed, 24 insertions(+) diff --git a/src/main/java/com/destroystokyo/paper/event/entity/SkeletonHorseTrapEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/SkeletonHorseTrapEvent.java -index d79dbcd68..1ed3ea8fa 100644 +index d79dbcd6..1ed3ea8f 100644 --- a/src/main/java/com/destroystokyo/paper/event/entity/SkeletonHorseTrapEvent.java +++ b/src/main/java/com/destroystokyo/paper/event/entity/SkeletonHorseTrapEvent.java @@ -1,20 +1,30 @@ diff --git a/patches/api/0021-PaperPR-PlayerItemCooldownEvent.patch b/patches/api/0022-PaperPR-PlayerItemCooldownEvent.patch similarity index 96% rename from patches/api/0021-PaperPR-PlayerItemCooldownEvent.patch rename to patches/api/0022-PaperPR-PlayerItemCooldownEvent.patch index 95326f510..654ce90e5 100644 --- a/patches/api/0021-PaperPR-PlayerItemCooldownEvent.patch +++ b/patches/api/0022-PaperPR-PlayerItemCooldownEvent.patch @@ -1,4 +1,4 @@ -From 585d46d0b381d2dd334997acf9140f505b484bfe Mon Sep 17 00:00:00 2001 +From 855fc3bdef2953107a8e75a953c086a7866eb024 Mon Sep 17 00:00:00 2001 From: KennyTV Date: Mon, 20 Apr 2020 13:57:13 +0200 Subject: [PATCH] PaperPR - PlayerItemCooldownEvent @@ -10,7 +10,7 @@ Subject: [PATCH] PaperPR - PlayerItemCooldownEvent diff --git a/src/main/java/net/pl3x/purpur/event/player/PlayerItemCooldownEvent.java b/src/main/java/net/pl3x/purpur/event/player/PlayerItemCooldownEvent.java new file mode 100644 -index 000000000..2002909f3 +index 00000000..2002909f --- /dev/null +++ b/src/main/java/net/pl3x/purpur/event/player/PlayerItemCooldownEvent.java @@ -0,0 +1,77 @@ diff --git a/patches/api/0022-EntityMoveEvent.patch b/patches/api/0023-EntityMoveEvent.patch similarity index 97% rename from patches/api/0022-EntityMoveEvent.patch rename to patches/api/0023-EntityMoveEvent.patch index 4dddf5be9..a349657a9 100644 --- a/patches/api/0022-EntityMoveEvent.patch +++ b/patches/api/0023-EntityMoveEvent.patch @@ -1,4 +1,4 @@ -From e15332baaee66fbb5134bc7891a9ba0890d24e04 Mon Sep 17 00:00:00 2001 +From 9c6e4fddc16253233e0cca1d093e76d8c4ac64a9 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Tue, 11 Feb 2020 21:56:38 -0600 Subject: [PATCH] EntityMoveEvent @@ -10,7 +10,7 @@ Subject: [PATCH] EntityMoveEvent diff --git a/src/main/java/net/pl3x/purpur/event/entity/EntityMoveEvent.java b/src/main/java/net/pl3x/purpur/event/entity/EntityMoveEvent.java new file mode 100644 -index 000000000..c48c525b8 +index 00000000..c48c525b --- /dev/null +++ b/src/main/java/net/pl3x/purpur/event/entity/EntityMoveEvent.java @@ -0,0 +1,95 @@ diff --git a/patches/api/0023-PaperPR-BellRingEvent.patch b/patches/api/0024-PaperPR-BellRingEvent.patch similarity index 95% rename from patches/api/0023-PaperPR-BellRingEvent.patch rename to patches/api/0024-PaperPR-BellRingEvent.patch index c7296b421..b0acd64a3 100644 --- a/patches/api/0023-PaperPR-BellRingEvent.patch +++ b/patches/api/0024-PaperPR-BellRingEvent.patch @@ -1,4 +1,4 @@ -From b9e5c3e951fb47294a74c6515e6c3f5442a8b8e7 Mon Sep 17 00:00:00 2001 +From 13467a78b38df42ecee499849c1bf9ceb914bfdf Mon Sep 17 00:00:00 2001 From: Eearslya Sleiarion Date: Mon, 24 Jun 2019 21:27:39 -0700 Subject: [PATCH] PaperPR - BellRingEvent @@ -12,7 +12,7 @@ village bell. Passes along the bell block and the player who rang it. diff --git a/src/main/java/com/destroystokyo/paper/event/block/BellRingEvent.java b/src/main/java/com/destroystokyo/paper/event/block/BellRingEvent.java new file mode 100644 -index 000000000..82e0a747b +index 00000000..82e0a747 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/event/block/BellRingEvent.java @@ -0,0 +1,53 @@ diff --git a/patches/api/0024-Player-invulnerabilities.patch b/patches/api/0025-Player-invulnerabilities.patch similarity index 92% rename from patches/api/0024-Player-invulnerabilities.patch rename to patches/api/0025-Player-invulnerabilities.patch index 46bb6fc07..08b357f5d 100644 --- a/patches/api/0024-Player-invulnerabilities.patch +++ b/patches/api/0025-Player-invulnerabilities.patch @@ -1,4 +1,4 @@ -From be009f6bd10975040ad8ff9378eca1569132774b Mon Sep 17 00:00:00 2001 +From 471dd5a530419f3dc9af3601d37ef3f2957291c5 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 2 May 2020 20:55:31 -0500 Subject: [PATCH] Player invulnerabilities @@ -8,7 +8,7 @@ Subject: [PATCH] Player invulnerabilities 1 file changed, 21 insertions(+) diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 2dca16ac4..55edcd54b 100644 +index 2dca16ac..55edcd54 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -1890,5 +1890,26 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM diff --git a/patches/api/0025-Anvil-API.patch b/patches/api/0026-Anvil-API.patch similarity index 96% rename from patches/api/0025-Anvil-API.patch rename to patches/api/0026-Anvil-API.patch index 17fb7298d..360f1b4a6 100644 --- a/patches/api/0025-Anvil-API.patch +++ b/patches/api/0026-Anvil-API.patch @@ -1,4 +1,4 @@ -From 4b4840812bcfe1331263157f9b7b61ec8d79e672 Mon Sep 17 00:00:00 2001 +From 2e6244aec6bbbb3846c4ba2c59998c44e605ace9 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 19 Apr 2020 00:25:09 -0500 Subject: [PATCH] Anvil API @@ -13,7 +13,7 @@ Subject: [PATCH] Anvil API diff --git a/src/main/java/net/pl3x/purpur/event/inventory/AnvilTakeResultEvent.java b/src/main/java/net/pl3x/purpur/event/inventory/AnvilTakeResultEvent.java new file mode 100644 -index 000000000..85663c0a4 +index 00000000..85663c0a --- /dev/null +++ b/src/main/java/net/pl3x/purpur/event/inventory/AnvilTakeResultEvent.java @@ -0,0 +1,52 @@ @@ -71,7 +71,7 @@ index 000000000..85663c0a4 +} diff --git a/src/main/java/net/pl3x/purpur/event/inventory/AnvilUpdateResultEvent.java b/src/main/java/net/pl3x/purpur/event/inventory/AnvilUpdateResultEvent.java new file mode 100644 -index 000000000..2717ad82c +index 00000000..2717ad82 --- /dev/null +++ b/src/main/java/net/pl3x/purpur/event/inventory/AnvilUpdateResultEvent.java @@ -0,0 +1,35 @@ @@ -111,7 +111,7 @@ index 000000000..2717ad82c + } +} diff --git a/src/main/java/org/bukkit/inventory/AnvilInventory.java b/src/main/java/org/bukkit/inventory/AnvilInventory.java -index b95e563b5..435026e53 100644 +index b95e563b..435026e5 100644 --- a/src/main/java/org/bukkit/inventory/AnvilInventory.java +++ b/src/main/java/org/bukkit/inventory/AnvilInventory.java @@ -109,4 +109,14 @@ public interface AnvilInventory extends Inventory { diff --git a/patches/api/0026-ItemStack-convenience-methods.patch b/patches/api/0027-ItemStack-convenience-methods.patch similarity index 99% rename from patches/api/0026-ItemStack-convenience-methods.patch rename to patches/api/0027-ItemStack-convenience-methods.patch index 78bfbd180..75f9f034f 100644 --- a/patches/api/0026-ItemStack-convenience-methods.patch +++ b/patches/api/0027-ItemStack-convenience-methods.patch @@ -1,4 +1,4 @@ -From dc446f6d6e36a6b06f04d8395835257126454d27 Mon Sep 17 00:00:00 2001 +From 90d4f270ec4296b0f0c013e8d3a97a5c4babe79a Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 15 Mar 2020 20:52:12 -0500 Subject: [PATCH] ItemStack convenience methods @@ -9,7 +9,7 @@ Subject: [PATCH] ItemStack convenience methods 2 files changed, 651 insertions(+) diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index 769c65e79..7126e5cba 100644 +index 3a8438fb..e7167d11 100644 --- a/src/main/java/org/bukkit/Material.java +++ b/src/main/java/org/bukkit/Material.java @@ -8636,4 +8636,36 @@ public enum Material implements Keyed { @@ -50,7 +50,7 @@ index 769c65e79..7126e5cba 100644 + // Purpur end } diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index ccd81fca2..c38fd8403 100644 +index ccd81fca..c38fd840 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; diff --git a/patches/api/0027-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch b/patches/api/0028-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch similarity index 92% rename from patches/api/0027-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch rename to patches/api/0028-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch index f247dbe12..3ec82d01a 100644 --- a/patches/api/0027-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch +++ b/patches/api/0028-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch @@ -1,4 +1,4 @@ -From 19065eff8026e396d1bf06bc2f87e7598c322c25 Mon Sep 17 00:00:00 2001 +From 20a60758768a69b9083d1c079b15571860979291 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 28 Jun 2020 21:50:55 -0500 Subject: [PATCH] Phantoms attracted to crystals and crystals shoot phantoms @@ -8,7 +8,7 @@ Subject: [PATCH] Phantoms attracted to crystals and crystals shoot phantoms 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java -index d7f1b2c84..8d25b6f09 100644 +index d7f1b2c8..8d25b6f0 100644 --- a/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java +++ b/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java @@ -205,4 +205,8 @@ public interface VanillaGoal extends Goal { diff --git a/patches/server/0001-Tuinity-Server-Changes.patch b/patches/server/0001-Tuinity-Server-Changes.patch new file mode 100644 index 000000000..7306415b3 --- /dev/null +++ b/patches/server/0001-Tuinity-Server-Changes.patch @@ -0,0 +1,7163 @@ +From cf1df09b2a81a4e2d37f240578d2b4cb330887b7 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 14 Dec 2018 21:53:58 -0800 +Subject: [PATCH] Tuinity Server Changes + +Brand changes + +MC-Dev fixes + +Util patch + +Tuinity Server Config + +Multi-Threaded Server Ticking Vanilla + +This patch is the vanilla server changes + +Currently a placeholder patch. + +Multi-Threaded ticking CraftBukkit + +These are the changes to CB + +Currently a placeholder patch. + +Add soft async catcher + +Must be enabled via -Dtuinity.strict-thread-checks=true + +Delay chunk unloads + +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. + +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. + +Configurable under `delay-chunkunloads-by` in config. + +This patch replaces the paper patch as the paper patch only +affects player loaded chunks, when we want to target all +loads. + +Attempt to recalculate regionfile header if it is corrupt + +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. + +Lag compensate block breaking + +Use time instead of ticks if ticks fall behind + +Update version fetcher repo + +Sets the target github repo to Tuinity in the version checker. Also disables the jenkins build lookups. + +Per World Spawn Limits + +Detail more information in watchdog dumps + +- Dump position, world, velocity, and uuid for currently ticking entities +- Dump player name, player uuid, position, and world for packet handling + +Execute chunk tasks mid-tick + +This will help the server load chunks if tick times are high. + +Change writes to use NORMAL priority rather than LOW + +Should limit build up of I/O tasks, or at least properly +indicate to server owners that I/O is falling behind + +Allow controlled flushing for network manager + +Only make one flush call when emptying the packet queue too + +This patch will be used to optimise out flush calls in later +patches. + +Consolidate flush calls for entity tracker packets + +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. + +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 blockpos allocation from pathfinding + +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. + +Temporary fix for large move vectors + +Check movement distance also based on current position. + +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. + +Optimise getType calls + +Remove the map lookup for converting from Block->Bukkit Material + +Optimise biome conversion + +Avoids the string conversions + map lookup + +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. + +Piston pushable TileEntities + +Configurable under pistons-can-push-tile-entities, globally. +Defaults to false because some redstone machines are going to rely on +TE's not being pushable. + +Explicitly disabled blocks & their reasons can be found under their override +of the function TileEntity#isPushable. +Other disabled blocks are due to the underlying block material not being +pushable (in general, a TE is pushable if its underlying material is). + +Video demonstration: +https://www.youtube.com/watch?v=Q0dYMtZ-a5c + +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 + +Prevent log spam for "Block is water but TE is chest" + +Happens when breaking a waterlogged chest. +Fix is to just not validate the TE while the chest is being removed. +--- + pom.xml | 22 +- + .../co/aikar/timings/MinecraftTimings.java | 2 + + .../java/co/aikar/timings/TimingsExport.java | 3 +- + .../paper/PaperVersionFetcher.java | 11 +- + .../paper/server/ticklist/PaperTickList.java | 9 + + .../chunk/SingleThreadChunkRegionManager.java | 159 ++++++ + .../tuinity/tuinity/config/TuinityConfig.java | 277 ++++++++++ + .../com/tuinity/tuinity/util/CachedLists.java | 53 ++ + .../com/tuinity/tuinity/util/TickThread.java | 41 ++ + .../IteratorSafeOrderedReferenceSet.java | 265 +++++++++ + .../tuinity/tuinity/voxel/AABBVoxelShape.java | 246 +++++++++ + .../net/minecraft/server/AxisAlignedBB.java | 116 ++++ + .../java/net/minecraft/server/BiomeBase.java | 12 + + .../java/net/minecraft/server/BlockBase.java | 1 + + .../java/net/minecraft/server/BlockChest.java | 4 +- + .../net/minecraft/server/BlockPiston.java | 30 +- + .../minecraft/server/BlockPistonMoving.java | 7 +- + src/main/java/net/minecraft/server/Chunk.java | 37 ++ + .../minecraft/server/ChunkMapDistance.java | 93 +++- + .../minecraft/server/ChunkProviderServer.java | 286 ++++++++-- + .../minecraft/server/ChunkRegionLoader.java | 12 +- + .../net/minecraft/server/ChunkSection.java | 1 + + .../net/minecraft/server/ChunkStatus.java | 4 +- + .../minecraft/server/DataPaletteBlock.java | 1 + + .../net/minecraft/server/DedicatedServer.java | 1 + + src/main/java/net/minecraft/server/EULA.java | 2 +- + .../java/net/minecraft/server/Entity.java | 201 ++++++- + .../net/minecraft/server/EntityLiving.java | 9 +- + .../minecraft/server/EntityTrackerEntry.java | 1 + + .../java/net/minecraft/server/HeightMap.java | 5 +- + .../java/net/minecraft/server/IBlockData.java | 13 + + .../net/minecraft/server/IChunkLoader.java | 2 +- + .../minecraft/server/ICollisionAccess.java | 5 + + .../net/minecraft/server/IEntityAccess.java | 1 + + .../minecraft/server/LightEngineStorage.java | 7 +- + .../java/net/minecraft/server/MCUtil.java | 14 + + .../net/minecraft/server/MinecraftServer.java | 108 +++- + .../net/minecraft/server/NetworkManager.java | 59 +- + .../server/PacketPlayOutMapChunk.java | 109 +++- + .../minecraft/server/PathfinderNormal.java | 2 +- + .../net/minecraft/server/PlayerChunk.java | 37 +- + .../net/minecraft/server/PlayerChunkMap.java | 64 ++- + .../minecraft/server/PlayerConnection.java | 34 +- + .../server/PlayerConnectionUtils.java | 26 + + .../server/PlayerInteractManager.java | 53 +- + .../java/net/minecraft/server/ProtoChunk.java | 16 +- + .../java/net/minecraft/server/RegionFile.java | 466 +++++++++++++++- + .../minecraft/server/RegionFileBitSet.java | 26 +- + .../net/minecraft/server/RegionFileCache.java | 52 +- + .../server/RegionFileCompression.java | 7 +- + .../java/net/minecraft/server/Ticket.java | 11 +- + .../java/net/minecraft/server/TicketType.java | 3 +- + .../java/net/minecraft/server/TileEntity.java | 49 +- + .../minecraft/server/TileEntityBeacon.java | 26 +- + .../minecraft/server/TileEntityBeehive.java | 7 + + .../server/TileEntityBrewingStand.java | 26 +- + .../net/minecraft/server/TileEntityChest.java | 16 + + .../minecraft/server/TileEntityConduit.java | 21 +- + .../minecraft/server/TileEntityFurnace.java | 26 +- + .../minecraft/server/TileEntityJukeBox.java | 7 + + .../minecraft/server/TileEntityLectern.java | 51 +- + .../minecraft/server/TileEntityPiston.java | 66 ++- + src/main/java/net/minecraft/server/Vec3D.java | 5 +- + .../net/minecraft/server/VillagePlace.java | 2 +- + .../java/net/minecraft/server/VoxelShape.java | 11 +- + .../net/minecraft/server/VoxelShapeArray.java | 72 +++ + .../net/minecraft/server/VoxelShapes.java | 79 ++- + src/main/java/net/minecraft/server/World.java | 48 +- + .../net/minecraft/server/WorldBorder.java | 38 +- + .../net/minecraft/server/WorldServer.java | 517 +++++++++++++++++- + .../net/minecraft/server/WorldUpgrader.java | 2 +- + .../craftbukkit/CraftChunkSnapshot.java | 2 +- + .../org/bukkit/craftbukkit/CraftServer.java | 17 +- + .../org/bukkit/craftbukkit/CraftWorld.java | 19 +- + .../java/org/bukkit/craftbukkit/Main.java | 9 +- + .../bukkit/craftbukkit/block/CraftBlock.java | 21 +- + .../craftbukkit/block/CraftBlockState.java | 2 +- + .../block/data/CraftBlockData.java | 2 +- + .../craftbukkit/entity/CraftEntity.java | 31 ++ + .../craftbukkit/generator/CraftChunkData.java | 2 +- + .../scoreboard/CraftScoreboardManager.java | 9 + + .../bukkit/craftbukkit/util/UnsafeList.java | 26 + + .../bukkit/craftbukkit/util/Versioning.java | 2 +- + src/main/java/org/spigotmc/AsyncCatcher.java | 2 +- + .../java/org/spigotmc/WatchdogThread.java | 79 +++ + 85 files changed, 3960 insertions(+), 358 deletions(-) + create mode 100644 src/main/java/com/tuinity/tuinity/chunk/SingleThreadChunkRegionManager.java + create mode 100644 src/main/java/com/tuinity/tuinity/config/TuinityConfig.java + create mode 100644 src/main/java/com/tuinity/tuinity/util/CachedLists.java + create mode 100644 src/main/java/com/tuinity/tuinity/util/TickThread.java + create mode 100644 src/main/java/com/tuinity/tuinity/util/maplist/IteratorSafeOrderedReferenceSet.java + create mode 100644 src/main/java/com/tuinity/tuinity/voxel/AABBVoxelShape.java + +diff --git a/pom.xml b/pom.xml +index ef8ee637a..6fd596817 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -1,11 +1,11 @@ +- + 4.0.0 +- paper ++ tuinity + jar + 1.16.1-R0.1-SNAPSHOT +- Paper +- https://papermc.io ++ Tuinity-Server ++ https://github.com/Spottedleaf/Tuinity + + + +@@ -18,16 +18,16 @@ + + + +- com.destroystokyo.paper +- paper-parent ++ com.tuinity ++ tuinity-parent + dev-SNAPSHOT + ../pom.xml + + + + +- com.destroystokyo.paper +- paper-api ++ com.tuinity ++ tuinity-api + ${project.version} + compile + +@@ -164,15 +164,15 @@ + + + +- paper-${minecraft.version} +- clean install ++ tuinity-${minecraft.version} ++ install + + + com.lukegb.mojo + gitdescribe-maven-plugin + 1.3 + +- git-Paper- ++ git-Tuinity- + .. + + +diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java +index dd0722397..2966c5731 100644 +--- a/src/main/java/co/aikar/timings/MinecraftTimings.java ++++ b/src/main/java/co/aikar/timings/MinecraftTimings.java +@@ -43,6 +43,8 @@ public final class MinecraftTimings { + public static final Timing antiXrayUpdateTimer = Timings.ofSafe("anti-xray - update"); + public static final Timing antiXrayObfuscateTimer = Timings.ofSafe("anti-xray - obfuscate"); + ++ public static final Timing scoreboardScoreSearch = Timings.ofSafe("Scoreboard score search"); // Tuinity - add timings for scoreboard search ++ + private static final Map, String> taskNameCache = new MapMaker().weakKeys().makeMap(); + + private MinecraftTimings() {} +diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java +index e33e889c2..5dfa06588 100644 +--- a/src/main/java/co/aikar/timings/TimingsExport.java ++++ b/src/main/java/co/aikar/timings/TimingsExport.java +@@ -229,7 +229,8 @@ public class TimingsExport extends Thread { + parent.put("config", createObject( + pair("spigot", mapAsJSON(Bukkit.spigot().getSpigotConfig(), null)), + pair("bukkit", mapAsJSON(Bukkit.spigot().getBukkitConfig(), null)), +- pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)) ++ pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)), // Tuinity - add config to timings report ++ pair("tuinity", mapAsJSON(Bukkit.spigot().getTuinityConfig(), null)) // Tuinity - add config to timings report + )); + + new TimingsExport(listeners, parent, history).start(); +diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java +index 49a38c660..255bbd6e4 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java ++++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java +@@ -24,8 +24,8 @@ public class PaperVersionFetcher implements VersionFetcher { + @Nonnull + @Override + public String getVersionMessage(@Nonnull String serverVersion) { +- String[] parts = serverVersion.substring("git-Paper-".length()).split("[-\\s]"); +- String updateMessage = getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); ++ String[] parts = serverVersion.substring("git-Tuinity-".length()).split("[-\\s]"); // Tuinity ++ String updateMessage = getUpdateStatusMessage("Spottedleaf/Tuinity", GITHUB_BRANCH_NAME, parts[0]); // Tuinity + String history = getHistory(); + + return history != null ? history + "\n" + updateMessage : updateMessage; +@@ -49,13 +49,10 @@ public class PaperVersionFetcher implements VersionFetcher { + + private static String getUpdateStatusMessage(@Nonnull String repo, @Nonnull String branch, @Nonnull String versionInfo) { + int distance; +- try { +- int jenkinsBuild = Integer.parseInt(versionInfo); +- distance = fetchDistanceFromSiteApi(jenkinsBuild, getMinecraftVersion()); +- } catch (NumberFormatException ignored) { ++ // Tuinity - we don't have jenkins setup + versionInfo = versionInfo.replace("\"", ""); + distance = fetchDistanceFromGitHub(repo, branch, versionInfo); +- } ++ // Tuinity - we don't have jenkins setup + + 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 0692fe33b..4263eb917 100644 +--- a/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java ++++ b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java +@@ -188,6 +188,7 @@ public final class PaperTickList extends TickListServer { // extend to avo + } + + public void onChunkSetTicking(final int chunkX, final int chunkZ) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("async tick list chunk ticking update"); // Tuinity - soft async catcher + final ArrayList> pending = this.pendingChunkTickLoad.remove(MCUtil.getCoordinateKey(chunkX, chunkZ)); + if (pending == null) { + return; +@@ -268,6 +269,7 @@ public final class PaperTickList extends TickListServer { // extend to avo + + @Override + public void tick() { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("async tick list tick"); // Tuinity - soft async catcher + final ChunkProviderServer chunkProvider = this.world.getChunkProvider(); + + this.world.getMethodProfiler().enter("cleaning"); +@@ -296,6 +298,7 @@ public final class PaperTickList extends TickListServer { // extend to avo + if (toTick.tickState == STATE_TICKING) { + toTick.tickState = STATE_TICKED; + } // else it's STATE_CANCELLED_TICK ++ MinecraftServer.getServer().executeMidTickTasks(); // Tuinity - exec chunk tasks during world tick + } else { + // re-schedule eventually + toTick.tickState = STATE_SCHEDULED; +@@ -413,6 +416,7 @@ public final class PaperTickList extends TickListServer { // extend to avo + } + + public void schedule(final BlockPosition pos, final T data, final long targetTick, final TickListPriority priority) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("async tick list schedule"); // Tuinity - soft async catcher + final NextTickListEntry entry = new NextTickListEntry<>(pos, data, targetTick, priority); + if (this.excludeFromScheduling.test(entry.getData())) { + return; +@@ -468,6 +472,7 @@ public final class PaperTickList extends TickListServer { // extend to avo + + @Override + public List> getEntriesInBoundingBox(final StructureBoundingBox structureboundingbox, final boolean removeReturned, final boolean excludeTicked) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("async tick list get in bounding box"); // Tuinity - soft async catcher + if (structureboundingbox.getMinX() == structureboundingbox.getMaxX() || structureboundingbox.getMinZ() == structureboundingbox.getMaxZ()) { + return Collections.emptyList(); // vanilla behaviour, check isBlockInSortof above + } +@@ -524,6 +529,7 @@ public final class PaperTickList extends TickListServer { // extend to avo + + @Override + public void copy(StructureBoundingBox structureboundingbox, BlockPosition blockposition) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("async tick list copy"); // Tuinity - soft async catcher + // start copy from TickListServer // TODO check on update + List> list = this.getEntriesInBoundingBox(structureboundingbox, false, false); + Iterator> iterator = list.iterator(); +@@ -543,6 +549,7 @@ public final class PaperTickList extends TickListServer { // extend to avo + + @Override + public List> getEntriesInChunk(ChunkCoordIntPair chunkPos, boolean removeReturned, boolean excludeTicked) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("async tick list get"); // Tuinity - soft async catcher + // Vanilla DOES get the entries 2 blocks out of the chunk too, but that doesn't matter since we ignore chunks + // not at ticking status, and ticking status requires neighbours loaded + // so with this method we will reduce scheduler churning +@@ -574,6 +581,7 @@ public final class PaperTickList extends TickListServer { // extend to avo + + @Override + public NBTTagList serialize(ChunkCoordIntPair chunkcoordintpair) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("async tick list serialize"); // Tuinity - soft async catcher + // start copy from TickListServer // TODO check on update + List> list = this.getEntriesInChunk(chunkcoordintpair, false, true); + +@@ -583,6 +591,7 @@ public final class PaperTickList extends TickListServer { // extend to avo + + @Override + public int getTotalScheduledEntries() { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("async tick list get size"); // Tuinity - soft async catcher + // good thing this is only used in debug reports // TODO check on update + int ret = 0; + +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 000000000..97c4100c5 +--- /dev/null ++++ b/src/main/java/com/tuinity/tuinity/chunk/SingleThreadChunkRegionManager.java +@@ -0,0 +1,159 @@ ++package com.tuinity.tuinity.chunk; ++ ++import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; ++import it.unimi.dsi.fastutil.longs.LongIterator; ++import it.unimi.dsi.fastutil.longs.LongOpenHashSet; ++import net.minecraft.server.MCUtil; ++import net.minecraft.server.WorldServer; ++import java.util.List; ++ ++public final class SingleThreadChunkRegionManager { ++ ++ static final int REGION_SECTION_MERGE_RADIUS = 1; ++ ++ static final int REGION_SECTION_CHUNK_SIZE = 8; ++ static final int REGION_SECTION_CHUNK_SIZE_SHIFT = 3; ++ ++ final Long2ObjectOpenHashMap regionsBySection = new Long2ObjectOpenHashMap<>(4096, 0.25f); ++ final LongOpenHashSet chunks = new LongOpenHashSet(8192, 0.25f); ++ ++ public final WorldServer world; ++ ++ public SingleThreadChunkRegionManager(final WorldServer world) { ++ this.world = world; ++ } ++ ++ public void addChunk(final int chunkX, final int chunkZ) { ++ this.addChunk(chunkX, chunkZ, true); ++ } ++ ++ void addChunk(final int chunkX, final int chunkZ, boolean addToChunks) { ++ final long coordinate = MCUtil.getCoordinateKey(chunkX, chunkZ); ++ final long sectionPos = MCUtil.getCoordinateKey(chunkX >> REGION_SECTION_CHUNK_SIZE_SHIFT, chunkZ >> REGION_SECTION_CHUNK_SIZE_SHIFT); ++ if (addToChunks) { ++ this.chunks.add(coordinate); ++ } ++ ++ // merge nearby regions first ++ ++ // gather regions to merge ++ ++ SingleThreadChunkRegionManager.ChunkRegion mergeIntoCandidate = null; ++ int mergeCandidateChunkCount = -1; ++ ++ List toMerge = null; ++ ++ final int regionSectionX = chunkX >> REGION_SECTION_CHUNK_SIZE_SHIFT; ++ final int regionSectionZ = chunkZ >> REGION_SECTION_CHUNK_SIZE_SHIFT; ++ ++ final int checkXStart = regionSectionX - REGION_SECTION_MERGE_RADIUS; ++ final int checkZStart = regionSectionZ - REGION_SECTION_MERGE_RADIUS; ++ final int checkXEnd = regionSectionX + REGION_SECTION_MERGE_RADIUS; ++ final int checkZEnd = regionSectionZ + REGION_SECTION_MERGE_RADIUS; ++ ++ // select the ideal region to merge into ++ for (int checkX = checkXStart; checkX <= checkXEnd; ++checkX) { ++ for (int checkZ = checkZStart; checkZ <= checkZEnd; ++checkZ) { ++ final SingleThreadChunkRegionManager.ChunkRegion region = this.regionsBySection.get(MCUtil.getCoordinateKey(checkX, checkZ)); ++ if (region == null) { ++ continue; ++ } ++ ++ final int coordinateSize = region.coordinates.size(); ++ if (coordinateSize > mergeCandidateChunkCount) { ++ mergeIntoCandidate = region; ++ mergeCandidateChunkCount = coordinateSize; ++ } ++ if (toMerge == null) { ++ toMerge = new java.util.ArrayList<>(4); ++ toMerge.add(region); ++ } ++ } ++ } ++ ++ // merge ++ if (toMerge != null) { ++ for (int i = 0, len = toMerge.size(); i < len; ++i) { ++ final SingleThreadChunkRegionManager.ChunkRegion needsMerge = toMerge.get(i); ++ if (needsMerge == mergeIntoCandidate) { ++ continue; ++ } ++ // this function forwards the sections ++ needsMerge.mergeInto(this, mergeIntoCandidate); ++ } ++ } else { ++ mergeIntoCandidate = new ChunkRegion(); ++ } ++ ++ mergeIntoCandidate.addChunk(coordinate); ++ if (mergeIntoCandidate.addSection(sectionPos)) { ++ this.regionsBySection.put(sectionPos, mergeIntoCandidate); ++ } ++ } ++ ++ public void removeChunk(final int chunkX, final int chunkZ) { ++ final long coordinate = MCUtil.getCoordinateKey(chunkX, chunkZ); ++ final long sectionPos = MCUtil.getCoordinateKey(chunkX >> REGION_SECTION_CHUNK_SIZE_SHIFT, chunkZ >> REGION_SECTION_CHUNK_SIZE_SHIFT); ++ this.chunks.remove(coordinate); ++ ++ final SingleThreadChunkRegionManager.ChunkRegion region = this.regionsBySection.get(sectionPos); ++ if (region == null) { ++ throw new IllegalStateException("Cannot remove chunk form no region"); ++ } ++ ++ if (!region.removeChunk(coordinate)) { ++ throw new IllegalStateException("Cannot remove chunk from region, has no chunk"); ++ } ++ } ++ ++ public void recalculateRegions() { ++ this.regionsBySection.clear(); ++ for (final LongIterator iterator = this.chunks.iterator(); iterator.hasNext();) { ++ final long coordinate = iterator.nextLong(); ++ this.addChunk(MCUtil.getCoordinateX(coordinate), MCUtil.getCoordinateZ(coordinate), false); ++ } ++ } ++ ++ static final class ChunkRegion { ++ private final LongOpenHashSet coordinates = new LongOpenHashSet(); ++ private final LongOpenHashSet sections = new LongOpenHashSet(); ++ private boolean dead; ++ ++ public void mergeInto(final SingleThreadChunkRegionManager regionManager, final ChunkRegion region) { ++ if (region.dead) { ++ throw new IllegalStateException("Attempting to merge into a dead region"); ++ } else if (this.dead) { ++ throw new IllegalStateException("Attempting to merge from a dead region"); ++ } ++ ++ for (final LongIterator iterator = this.coordinates.iterator(); iterator.hasNext();) { ++ final long coordinate = iterator.nextLong(); ++ if (!region.addChunk(coordinate)) { ++ throw new IllegalStateException("Regions cannot share chunks"); ++ } ++ } ++ ++ for (final LongIterator iterator = this.sections.iterator(); iterator.hasNext();) { ++ regionManager.regionsBySection.replace(iterator.nextLong(), region); ++ } ++ ++ this.dead = true; ++ } ++ ++ boolean addSection(final long sectionPos) { ++ return this.sections.add(sectionPos); ++ } ++ ++ boolean removeSection(final long sectionPos) { ++ return this.sections.remove(sectionPos); ++ } ++ ++ boolean addChunk(final long coordinate) { ++ return this.coordinates.add(coordinate); ++ } ++ ++ boolean removeChunk(final long coordinate) { ++ return this.coordinates.remove(coordinate); ++ } ++ } ++} +\ No newline at end of file +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 000000000..1ae1fd750 +--- /dev/null ++++ b/src/main/java/com/tuinity/tuinity/config/TuinityConfig.java +@@ -0,0 +1,277 @@ ++package com.tuinity.tuinity.config; ++ ++import com.destroystokyo.paper.util.SneakyThrow; ++import net.minecraft.server.TicketType; ++import org.bukkit.Bukkit; ++import org.bukkit.configuration.ConfigurationSection; ++import org.bukkit.configuration.file.YamlConfiguration; ++import java.io.File; ++import java.lang.reflect.Method; ++import java.lang.reflect.Modifier; ++import java.util.List; ++import java.util.logging.Level; ++ ++public final class TuinityConfig { ++ ++ public static final String CONFIG_HEADER = "Configuration file for Tuinity."; ++ public static final int CURRENT_CONFIG_VERSION = 2; ++ ++ private static final Object[] EMPTY = new Object[0]; ++ ++ private static File configFile; ++ public static YamlConfiguration config; ++ private static int configVersion; ++ ++ public static void init(final File file) { ++ // TODO remove this in the future... ++ final File tuinityConfig = new File(file.getParent(), "tuinity.yml"); ++ if (!tuinityConfig.exists()) { ++ final File oldConfig = new File(file.getParent(), "concrete.yml"); ++ oldConfig.renameTo(tuinityConfig); ++ } ++ TuinityConfig.configFile = file; ++ final YamlConfiguration config = new YamlConfiguration(); ++ config.options().header(CONFIG_HEADER); ++ config.options().copyDefaults(true); ++ ++ if (!file.exists()) { ++ try { ++ file.createNewFile(); ++ } catch (final Exception ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Failure to create tuinity config", ex); ++ } ++ } else { ++ try { ++ config.load(file); ++ } catch (final Exception ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Failure to load tuinity config", ex); ++ SneakyThrow.sneaky(ex); /* Rethrow, this is critical */ ++ throw new RuntimeException(ex); // unreachable ++ } ++ } ++ ++ TuinityConfig.load(config); ++ } ++ ++ public static void load(final YamlConfiguration config) { ++ TuinityConfig.config = config; ++ TuinityConfig.configVersion = TuinityConfig.getInt("config-version-please-do-not-modify-me", CURRENT_CONFIG_VERSION); ++ TuinityConfig.set("config-version-please-do-not-modify-me", CURRENT_CONFIG_VERSION); ++ ++ for (final Method method : TuinityConfig.class.getDeclaredMethods()) { ++ if (method.getReturnType() != void.class || method.getParameterCount() != 0 || ++ !Modifier.isPrivate(method.getModifiers()) || !Modifier.isStatic(method.getModifiers())) { ++ continue; ++ } ++ ++ try { ++ method.setAccessible(true); ++ method.invoke(null, EMPTY); ++ } catch (final Exception ex) { ++ SneakyThrow.sneaky(ex); /* Rethrow, this is critical */ ++ throw new RuntimeException(ex); // unreachable ++ } ++ } ++ ++ /* We re-save to add new options */ ++ try { ++ config.save(TuinityConfig.configFile); ++ } catch (final Exception ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Unable to save tuinity config", ex); ++ } ++ } ++ ++ static void set(final String path, final Object value) { ++ TuinityConfig.config.set(path, value); ++ } ++ ++ static boolean getBoolean(final String path, final boolean dfl) { ++ TuinityConfig.config.addDefault(path, Boolean.valueOf(dfl)); ++ return TuinityConfig.config.getBoolean(path, dfl); ++ } ++ ++ static int getInt(final String path, final int dfl) { ++ TuinityConfig.config.addDefault(path, Integer.valueOf(dfl)); ++ return TuinityConfig.config.getInt(path, dfl); ++ } ++ ++ static long getLong(final String path, final long dfl) { ++ TuinityConfig.config.addDefault(path, Long.valueOf(dfl)); ++ return TuinityConfig.config.getLong(path, dfl); ++ } ++ ++ static double getDouble(final String path, final double dfl) { ++ TuinityConfig.config.addDefault(path, Double.valueOf(dfl)); ++ return TuinityConfig.config.getDouble(path, dfl); ++ } ++ ++ public static boolean tickWorldsInParallel; ++ ++ /** ++ * if tickWorldsInParallel == true, then this value is used as a default only for worlds ++ */ ++ public static int tickThreads; ++ ++ /* ++ private static void worldticking() { ++ 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() { ++ delayChunkUnloadsBy = TuinityConfig.getInt("delay-chunkunloads-by", 1) * 20; ++ if (delayChunkUnloadsBy >= 0) { ++ TicketType.DELAYED_UNLOAD.loadPeriod = delayChunkUnloadsBy; ++ } ++ } ++ ++ public static boolean lagCompensateBlockBreaking; ++ ++ private static void lagCompensateBlockBreaking() { ++ lagCompensateBlockBreaking = TuinityConfig.getBoolean("lag-compensate-block-breaking", true); ++ } ++ ++ public static boolean pistonsCanPushTileEntities; ++ ++ private static void pistonsCanPushTileEntities() { ++ pistonsCanPushTileEntities = TuinityConfig.getBoolean("pistons-can-push-tile-entities", false); ++ } ++ ++ public static final class WorldConfig { ++ ++ public final String worldName; ++ public ConfigurationSection config; ++ ConfigurationSection worldDefaults; ++ ++ public WorldConfig(final String worldName) { ++ this.worldName = worldName; ++ this.init(); ++ } ++ ++ public void init() { ++ this.worldDefaults = TuinityConfig.config.getConfigurationSection("world-settings.default"); ++ if (this.worldDefaults == null) { ++ this.worldDefaults = TuinityConfig.config.createSection("world-settings.default"); ++ } ++ ++ String worldSectionPath = TuinityConfig.configVersion < 1 ? this.worldName : "world-settings.".concat(this.worldName); ++ ConfigurationSection section = TuinityConfig.config.getConfigurationSection(worldSectionPath); ++ if (section == null) { ++ section = TuinityConfig.config.createSection(worldSectionPath); ++ } ++ TuinityConfig.config.set(worldSectionPath, section); ++ ++ this.load(section); ++ } ++ ++ public void load(final ConfigurationSection config) { ++ this.config = config; ++ ++ for (final Method method : TuinityConfig.WorldConfig.class.getDeclaredMethods()) { ++ if (method.getReturnType() != void.class || method.getParameterCount() != 0 || ++ !Modifier.isPrivate(method.getModifiers()) || Modifier.isStatic(method.getModifiers())) { ++ continue; ++ } ++ ++ try { ++ method.setAccessible(true); ++ method.invoke(this, EMPTY); ++ } catch (final Exception ex) { ++ SneakyThrow.sneaky(ex); /* Rethrow, this is critical */ ++ throw new RuntimeException(ex); // unreachable ++ } ++ } ++ ++ if (TuinityConfig.configVersion < 1) { ++ ConfigurationSection oldSection = TuinityConfig.config.getConfigurationSection(this.worldName); ++ TuinityConfig.config.set("world-settings.".concat(this.worldName), oldSection); ++ TuinityConfig.config.set(this.worldName, null); ++ } ++ ++ /* We re-save to add new options */ ++ try { ++ TuinityConfig.config.save(TuinityConfig.configFile); ++ } catch (final Exception ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Unable to save tuinity config", ex); ++ } ++ } ++ ++ /** ++ * update world defaults for the specified path, but also sets this world's config value for the path ++ * if it exists ++ */ ++ void set(final String path, final Object val) { ++ this.worldDefaults.set(path, val); ++ if (this.config.get(path) != null) { ++ this.config.set(path, val); ++ } ++ } ++ ++ boolean getBoolean(final String path, final boolean dfl) { ++ this.worldDefaults.addDefault(path, Boolean.valueOf(dfl)); ++ if (TuinityConfig.configVersion < 1) { ++ if (this.config.getBoolean(path) == dfl) { ++ this.config.set(path, null); ++ } ++ } ++ return this.config.getBoolean(path, this.worldDefaults.getBoolean(path)); ++ } ++ ++ int getInt(final String path, final int dfl) { ++ this.worldDefaults.addDefault(path, Integer.valueOf(dfl)); ++ if (TuinityConfig.configVersion < 1) { ++ if (this.config.getInt(path) == dfl) { ++ this.config.set(path, null); ++ } ++ } ++ return this.config.getInt(path, this.worldDefaults.getInt(path)); ++ } ++ ++ long getLong(final String path, final long dfl) { ++ this.worldDefaults.addDefault(path, Long.valueOf(dfl)); ++ if (TuinityConfig.configVersion < 1) { ++ if (this.config.getLong(path) == dfl) { ++ this.config.set(path, null); ++ } ++ } ++ return this.config.getLong(path, this.worldDefaults.getLong(path)); ++ } ++ ++ double getDouble(final String path, final double dfl) { ++ this.worldDefaults.addDefault(path, Double.valueOf(dfl)); ++ if (TuinityConfig.configVersion < 1) { ++ if (this.config.getDouble(path) == dfl) { ++ this.config.set(path, null); ++ } ++ } ++ return this.config.getDouble(path, this.worldDefaults.getDouble(path)); ++ } ++ ++ /** ignored if {@link TuinityConfig#tickWorldsInParallel} == false */ ++ public int threads; ++ ++ /* ++ private void worldthreading() { ++ final int threads = this.getInt("tick-threads", -1); ++ this.threads = threads == -1 ? TuinityConfig.tickThreads : threads; ++ }*/ ++ ++ public int spawnLimitMonsters; ++ public int spawnLimitAnimals; ++ public int spawnLimitWaterAnimals; ++ public int spawnLimitAmbient; ++ ++ private void perWorldSpawnLimit() { ++ final String path = "spawn-limits"; ++ ++ this.spawnLimitMonsters = this.getInt(path + ".monsters", -1); ++ this.spawnLimitAnimals = this.getInt(path + ".animals", -1); ++ this.spawnLimitWaterAnimals = this.getInt(path + ".water-animals", -1); ++ this.spawnLimitAmbient = this.getInt(path + ".ambient", -1); ++ } ++ ++ } ++ ++} +\ 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 000000000..a54f516ba +--- /dev/null ++++ b/src/main/java/com/tuinity/tuinity/util/CachedLists.java +@@ -0,0 +1,53 @@ ++package com.tuinity.tuinity.util; ++ ++import net.minecraft.server.AxisAlignedBB; ++import net.minecraft.server.Entity; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.util.UnsafeList; ++import java.util.List; ++ ++public class CachedLists { ++ ++ static final UnsafeList TEMP_COLLISION_LIST = new UnsafeList<>(1024); ++ static boolean tempCollisionListInUse; ++ ++ public static List getTempCollisionList() { ++ if (!Bukkit.isPrimaryThread() || tempCollisionListInUse) { ++ return new UnsafeList<>(16); ++ } ++ tempCollisionListInUse = true; ++ return TEMP_COLLISION_LIST; ++ } ++ ++ public static void returnTempCollisionList(List list) { ++ if (list != TEMP_COLLISION_LIST) { ++ return; ++ } ++ ((UnsafeList)list).setSize(0); ++ tempCollisionListInUse = false; ++ } ++ ++ static final UnsafeList TEMP_GET_ENTITIES_LIST = new UnsafeList<>(1024); ++ static boolean tempGetEntitiesListInUse; ++ ++ public static List getTempGetEntitiesList() { ++ if (!Bukkit.isPrimaryThread() || tempGetEntitiesListInUse) { ++ return new UnsafeList<>(16); ++ } ++ tempGetEntitiesListInUse = true; ++ return TEMP_GET_ENTITIES_LIST; ++ } ++ ++ public static void returnTempGetEntitiesList(List list) { ++ if (list != TEMP_GET_ENTITIES_LIST) { ++ return; ++ } ++ ((UnsafeList)list).setSize(0); ++ tempGetEntitiesListInUse = false; ++ } ++ ++ public static void reset() { ++ TEMP_COLLISION_LIST.completeReset(); ++ TEMP_GET_ENTITIES_LIST.completeReset(); ++ } ++} +diff --git a/src/main/java/com/tuinity/tuinity/util/TickThread.java b/src/main/java/com/tuinity/tuinity/util/TickThread.java +new file mode 100644 +index 000000000..08ed24325 +--- /dev/null ++++ b/src/main/java/com/tuinity/tuinity/util/TickThread.java +@@ -0,0 +1,41 @@ ++package com.tuinity.tuinity.util; ++ ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.Bukkit; ++ ++public final class TickThread extends Thread { ++ ++ public static final boolean STRICT_THREAD_CHECKS = Boolean.getBoolean("tuinity.strict-thread-checks"); ++ ++ static { ++ if (STRICT_THREAD_CHECKS) { ++ MinecraftServer.LOGGER.warn("Strict thread checks enabled - performance may suffer"); ++ } ++ } ++ ++ public static void softEnsureTickThread(final String reason) { ++ if (!STRICT_THREAD_CHECKS) { ++ return; ++ } ++ ensureTickThread(reason); ++ } ++ ++ ++ public static void ensureTickThread(final String reason) { ++ if (!Bukkit.isPrimaryThread()) { ++ MinecraftServer.LOGGER.fatal("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable()); ++ throw new IllegalStateException(reason); ++ } ++ } ++ ++ public final int id; /* We don't override getId as the spec requires that it be unique (with respect to all other threads) */ ++ ++ public TickThread(final Runnable run, final String name, final int id) { ++ super(run, name); ++ this.id = id; ++ } ++ ++ public static TickThread getCurrentTickThread() { ++ return (TickThread)Thread.currentThread(); ++ } ++} +\ No newline at end of file +diff --git a/src/main/java/com/tuinity/tuinity/util/maplist/IteratorSafeOrderedReferenceSet.java b/src/main/java/com/tuinity/tuinity/util/maplist/IteratorSafeOrderedReferenceSet.java +new file mode 100644 +index 000000000..e12d09645 +--- /dev/null ++++ b/src/main/java/com/tuinity/tuinity/util/maplist/IteratorSafeOrderedReferenceSet.java +@@ -0,0 +1,265 @@ ++package com.tuinity.tuinity.util.maplist; ++ ++import it.unimi.dsi.fastutil.objects.Reference2IntLinkedOpenHashMap; ++import it.unimi.dsi.fastutil.objects.Reference2IntMap; ++import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet; ++import java.util.Arrays; ++import java.util.NoSuchElementException; ++ ++public final class IteratorSafeOrderedReferenceSet { ++ ++ protected final Reference2IntLinkedOpenHashMap indexMap; ++ protected int firstInvalidIndex = -1; ++ ++ protected final ReferenceLinkedOpenHashSet pendingAdditions; ++ ++ /* list impl */ ++ protected E[] listElements; ++ protected int listSize; ++ ++ protected final double maxFragFactor; ++ ++ protected int iteratorCount; ++ ++ public IteratorSafeOrderedReferenceSet() { ++ this(16, 0.75f, 16, 0.2); ++ } ++ ++ public IteratorSafeOrderedReferenceSet(final int setCapacity, final float setLoadFactor, final int arrayCapacity, final double maxFragFactor) { ++ this.indexMap = new Reference2IntLinkedOpenHashMap<>(setCapacity, setLoadFactor); ++ this.indexMap.defaultReturnValue(-1); ++ this.pendingAdditions = new ReferenceLinkedOpenHashSet<>(); ++ this.maxFragFactor = maxFragFactor; ++ this.listElements = (E[])new Object[arrayCapacity]; ++ } ++ ++ protected final double getFragFactor() { ++ return 1.0 - ((double)this.indexMap.size() / (double)this.listSize); ++ } ++ ++ public int createRawIterator() { ++ ++this.iteratorCount; ++ if (this.indexMap.isEmpty()) { ++ return -1; ++ } else { ++ return this.firstInvalidIndex == 0 ? this.indexMap.getInt(this.indexMap.firstKey()) : 0; ++ } ++ } ++ ++ public int advanceRawIterator(final int index) { ++ final E[] elements = this.listElements; ++ int ret = index + 1; ++ for (int len = this.listSize; ret < len; ++ret) { ++ if (elements[ret] != null) { ++ return ret; ++ } ++ } ++ ++ return -1; ++ } ++ ++ public void finishRawIterator() { ++ if (--this.iteratorCount == 0) { ++ if (this.getFragFactor() >= this.maxFragFactor) { ++ this.defrag(); ++ } ++ if (!this.pendingAdditions.isEmpty()) { ++ int index = this.listSize; ++ int neededLen = index + this.pendingAdditions.size(); ++ ++ if (neededLen < 0) { ++ throw new IllegalStateException("Too large"); ++ } ++ ++ if (neededLen > this.listElements.length) { ++ this.listElements = Arrays.copyOf(this.listElements, neededLen * 2); ++ } ++ ++ final E[] elements = this.listElements; ++ java.util.Iterator iterator = this.pendingAdditions.iterator(); ++ for (int i = index; i < neededLen; ++i) { ++ final E element = iterator.next(); ++ elements[i] = element; ++ this.indexMap.put(element, i); ++ } ++ ++ this.pendingAdditions.clear(); ++ this.listSize = neededLen; ++ } ++ } ++ } ++ ++ public boolean remove(final E element) { ++ final int index = this.indexMap.removeInt(element); ++ if (index >= 0) { ++ if (this.firstInvalidIndex < 0 || index < this.firstInvalidIndex) { ++ this.firstInvalidIndex = index; ++ } ++ this.listElements[index] = null; ++ return true; ++ } else { ++ return this.pendingAdditions.remove(element); ++ } ++ } ++ ++ public boolean add(final E element) { ++ if (this.iteratorCount > 0) { ++ if (this.indexMap.containsKey(element)) { ++ return true; ++ } ++ return this.pendingAdditions.add(element); ++ } else { ++ final int listSize = this.listSize; ++ ++ final int previous = this.indexMap.putIfAbsent(element, listSize); ++ if (previous != -1) { ++ return false; ++ } ++ ++ if (listSize >= this.listElements.length) { ++ this.listElements = Arrays.copyOf(this.listElements, listSize * 2); ++ } ++ this.listElements[listSize] = element; ++ this.listSize = listSize + 1; ++ ++ return true; ++ } ++ } ++ ++ protected void defrag() { ++ if (this.firstInvalidIndex < 0) { ++ return; // nothing to do ++ } ++ ++ if (this.indexMap.isEmpty()) { ++ Arrays.fill(this.listElements, 0, this.listSize, null); ++ this.listSize = 0; ++ this.firstInvalidIndex = -1; ++ return; ++ } ++ ++ final E[] backingArray = this.listElements; ++ ++ int lastValidIndex; ++ java.util.Iterator> iterator; ++ ++ if (this.firstInvalidIndex == 0) { ++ iterator = this.indexMap.reference2IntEntrySet().fastIterator(); ++ lastValidIndex = 0; ++ } else { ++ lastValidIndex = this.firstInvalidIndex; ++ final E key = backingArray[lastValidIndex - 1]; ++ iterator = this.indexMap.reference2IntEntrySet().fastIterator(new Reference2IntMap.Entry() { ++ @Override ++ public int getIntValue() { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public int setValue(int i) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public E getKey() { ++ return key; ++ } ++ }); ++ } ++ ++ while (iterator.hasNext()) { ++ final Reference2IntMap.Entry entry = iterator.next(); ++ ++ final int newIndex = lastValidIndex++; ++ backingArray[newIndex] = entry.getKey(); ++ entry.setValue(newIndex); ++ } ++ ++ // cleanup end ++ Arrays.fill(backingArray, lastValidIndex, this.listSize, null); ++ this.listSize = lastValidIndex; ++ this.firstInvalidIndex = -1; ++ } ++ ++ public E rawGet(final int index) { ++ return this.listElements[index]; ++ } ++ ++ public int size() { ++ // always returns the correct amount - listSize can be different ++ return this.indexMap.size(); ++ } ++ ++ public IteratorSafeOrderedReferenceSet.Iterator iterator() { ++ ++this.iteratorCount; ++ return new BaseIterator<>(this); ++ } ++ ++ public static interface Iterator extends java.util.Iterator { ++ ++ public void finishedIterating(); ++ ++ } ++ ++ protected static final class BaseIterator implements IteratorSafeOrderedReferenceSet.Iterator { ++ ++ protected final IteratorSafeOrderedReferenceSet set; ++ protected int nextIndex; ++ protected E currentValue; ++ protected boolean finished; ++ ++ protected BaseIterator(final IteratorSafeOrderedReferenceSet set) { ++ this.set = set; ++ } ++ ++ @Override ++ public boolean hasNext() { ++ if (this.finished) { ++ return false; ++ } ++ if (this.currentValue != null) { ++ return true; ++ } ++ ++ final E[] elements = this.set.listElements; ++ int index, len; ++ for (index = this.nextIndex, len = this.set.listSize; index < len; ++index) { ++ final E element = elements[index]; ++ if (element != null) { ++ this.currentValue = element; ++ this.nextIndex = index + 1; ++ return true; ++ } ++ } ++ ++ this.nextIndex = index; ++ return false; ++ } ++ ++ @Override ++ public E next() { ++ if (!this.hasNext()) { ++ throw new NoSuchElementException(); ++ } ++ final E ret = this.currentValue; ++ ++ this.currentValue = null; ++ ++ return ret; ++ } ++ ++ @Override ++ public void remove() { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public void finishedIterating() { ++ if (this.finished) { ++ throw new IllegalStateException(); ++ } ++ this.finished = true; ++ this.set.finishRawIterator(); ++ } ++ } ++} +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 000000000..76593df29 +--- /dev/null ++++ b/src/main/java/com/tuinity/tuinity/voxel/AABBVoxelShape.java +@@ -0,0 +1,246 @@ ++package com.tuinity.tuinity.voxel; ++ ++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 java.util.ArrayList; ++import java.util.List; ++ ++public final class AABBVoxelShape extends VoxelShape { ++ ++ public final AxisAlignedBB aabb; ++ private boolean isEmpty; ++ ++ public AABBVoxelShape(AxisAlignedBB aabb) { ++ super(VoxelShapes.getFullUnoptimisedCube().getShape()); ++ this.aabb = aabb; ++ this.isEmpty = (fuzzyEquals(aabb.minX, aabb.maxX) && fuzzyEquals(aabb.minY, aabb.maxY) && fuzzyEquals(aabb.minZ, aabb.maxZ)); ++ } ++ ++ static boolean fuzzyEquals(double d0, double d1) { ++ return Math.abs(d0 - d1) <= 1.0e-7; ++ } ++ ++ @Override ++ public boolean isEmpty() { ++ return this.isEmpty; ++ } ++ ++ @Override ++ public double b(EnumDirection.EnumAxis enumdirection_enumaxis) { // getMin ++ switch (enumdirection_enumaxis.ordinal()) { ++ case 0: ++ return this.aabb.minX; ++ case 1: ++ return this.aabb.minY; ++ case 2: ++ return this.aabb.minZ; ++ default: ++ throw new IllegalStateException("Unknown axis requested"); ++ } ++ } ++ ++ @Override ++ public double c(EnumDirection.EnumAxis enumdirection_enumaxis) { //getMax ++ switch (enumdirection_enumaxis.ordinal()) { ++ case 0: ++ return this.aabb.maxX; ++ case 1: ++ return this.aabb.maxY; ++ case 2: ++ return this.aabb.maxZ; ++ default: ++ throw new IllegalStateException("Unknown axis requested"); ++ } ++ } ++ ++ @Override ++ public AxisAlignedBB getBoundingBox() { // rets bounding box enclosing this entire shape ++ return this.aabb; ++ } ++ ++ // enum direction axis is from 0 -> 2, so we keep the lower bits for direction axis. ++ @Override ++ protected double a(EnumDirection.EnumAxis enumdirection_enumaxis, int i) { // getPointFromIndex ++ switch (enumdirection_enumaxis.ordinal() | (i << 2)) { ++ case (0 | (0 << 2)): ++ return this.aabb.minX; ++ case (1 | (0 << 2)): ++ return this.aabb.minY; ++ case (2 | (0 << 2)): ++ return this.aabb.minZ; ++ case (0 | (1 << 2)): ++ return this.aabb.maxX; ++ case (1 | (1 << 2)): ++ return this.aabb.maxY; ++ case (2 | (1 << 2)): ++ return this.aabb.maxZ; ++ default: ++ throw new IllegalStateException("Unknown axis requested"); ++ } ++ } ++ ++ private DoubleList cachedListX; ++ private DoubleList cachedListY; ++ private DoubleList cachedListZ; ++ ++ @Override ++ protected DoubleList a(EnumDirection.EnumAxis enumdirection_enumaxis) { // getPoints ++ switch (enumdirection_enumaxis.ordinal()) { ++ case 0: ++ return this.cachedListX == null ? this.cachedListX = DoubleArrayList.wrap(new double[] { this.aabb.minX, this.aabb.maxX }) : this.cachedListX; ++ case 1: ++ return this.cachedListY == null ? this.cachedListY = DoubleArrayList.wrap(new double[] { this.aabb.minY, this.aabb.maxY }) : this.cachedListY; ++ case 2: ++ return this.cachedListZ == null ? this.cachedListZ = DoubleArrayList.wrap(new double[] { this.aabb.minZ, this.aabb.maxZ }) : this.cachedListZ; ++ default: ++ throw new IllegalStateException("Unknown axis requested"); ++ } ++ } ++ ++ @Override ++ public VoxelShape a(double d0, double d1, double d2) { // createOffset ++ return new AABBVoxelShape(this.aabb.offset(d0, d1, d2)); ++ } ++ ++ @Override ++ public VoxelShape c() { // simplify ++ return this; ++ } ++ ++ @Override ++ public void b(VoxelShapes.a voxelshapes_a) { // forEachAABB ++ voxelshapes_a.consume(this.aabb.minX, this.aabb.minY, this.aabb.minZ, this.aabb.maxX, this.aabb.maxY, this.aabb.maxZ); ++ } ++ ++ @Override ++ public List d() { // getAABBs ++ List ret = new ArrayList<>(1); ++ ret.add(this.aabb); ++ return ret; ++ } ++ ++ @Override ++ protected int a(EnumDirection.EnumAxis enumdirection_enumaxis, double d0) { // findPointIndexAfterOffset ++ switch (enumdirection_enumaxis.ordinal()) { ++ case 0: ++ return d0 < this.aabb.maxX ? (d0 < this.aabb.minX ? -1 : 0) : 1; ++ case 1: ++ return d0 < this.aabb.maxY ? (d0 < this.aabb.minY ? -1 : 0) : 1; ++ case 2: ++ return d0 < this.aabb.maxZ ? (d0 < this.aabb.minZ ? -1 : 0) : 1; ++ default: ++ throw new IllegalStateException("Unknown axis requested"); ++ } ++ } ++ ++ @Override ++ protected boolean b(double d0, double d1, double d2) { // containsPoint ++ return this.aabb.contains(d0, d1, d2); ++ } ++ ++ @Override ++ public VoxelShape a(EnumDirection enumdirection) { // unknown ++ return super.a(enumdirection); ++ } ++ ++ @Override ++ public double a(EnumDirection.EnumAxis enumdirection_enumaxis, AxisAlignedBB axisalignedbb, double d0) { // collide ++ if (this.isEmpty) { ++ return d0; ++ } ++ if (Math.abs(d0) < 1.0e-7) { ++ return 0.0; ++ } ++ switch (enumdirection_enumaxis.ordinal()) { ++ case 0: ++ return this.collideX(axisalignedbb, d0); ++ case 1: ++ return this.collideY(axisalignedbb, d0); ++ case 2: ++ return this.collideZ(axisalignedbb, d0); ++ default: ++ throw new IllegalStateException("Unknown axis requested"); ++ } ++ } ++ ++ // collideX, collideY, collideZ are copied from 1.12 src and remapped ++ // so the code all belongs to mojang ++ ++ public double collideX(AxisAlignedBB axisalignedbb, double d0) { ++ if (axisalignedbb.maxY > this.aabb.minY && axisalignedbb.minY < this.aabb.maxY ++ && axisalignedbb.maxZ > this.aabb.minZ && axisalignedbb.minZ < this.aabb.maxZ) { ++ double d1; ++ ++ if (d0 > 0.0D && axisalignedbb.maxX <= this.aabb.minX) { ++ d1 = this.aabb.minX - axisalignedbb.maxX; ++ if (d1 < d0) { ++ d0 = d1; ++ } ++ } else if (d0 < 0.0D && axisalignedbb.minX >= this.aabb.maxX) { ++ d1 = this.aabb.maxX - axisalignedbb.minX; ++ if (d1 > d0) { ++ d0 = d1; ++ } ++ } ++ ++ return d0; ++ } else { ++ return d0; ++ } ++ } ++ ++ public double collideY(AxisAlignedBB axisalignedbb, double d0) { ++ if (axisalignedbb.maxX > this.aabb.minX && axisalignedbb.minX < this.aabb.maxX ++ && axisalignedbb.maxZ > this.aabb.minZ && axisalignedbb.minZ < this.aabb.maxZ) { ++ double d1; ++ ++ if (d0 > 0.0D && axisalignedbb.maxY <= this.aabb.minY) { ++ d1 = this.aabb.minY - axisalignedbb.maxY; ++ if (d1 < d0) { ++ d0 = d1; ++ } ++ } else if (d0 < 0.0D && axisalignedbb.minY >= this.aabb.maxY) { ++ d1 = this.aabb.maxY - axisalignedbb.minY; ++ if (d1 > d0) { ++ d0 = d1; ++ } ++ } ++ ++ return d0; ++ } else { ++ return d0; ++ } ++ } ++ ++ public double collideZ(AxisAlignedBB axisalignedbb, double d0) { ++ if (axisalignedbb.maxX > this.aabb.minX && axisalignedbb.minX < this.aabb.maxX ++ && axisalignedbb.maxY > this.aabb.minY && axisalignedbb.minY < this.aabb.maxY) { ++ double d1; ++ ++ if (d0 > 0.0D && axisalignedbb.maxZ <= this.aabb.minZ) { ++ d1 = this.aabb.minZ - axisalignedbb.maxZ; ++ if (d1 < d0) { ++ d0 = d1; ++ } ++ } else if (d0 < 0.0D && axisalignedbb.minZ >= this.aabb.maxZ) { ++ d1 = this.aabb.maxZ - axisalignedbb.minZ; ++ if (d1 > d0) { ++ d0 = d1; ++ } ++ } ++ ++ return d0; ++ } else { ++ return d0; ++ } ++ } ++ ++ @Override ++ public boolean intersects(AxisAlignedBB axisalingedbb) { ++ return this.aabb.intersects(axisalingedbb); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/AxisAlignedBB.java b/src/main/java/net/minecraft/server/AxisAlignedBB.java +index ed9b2f9ad..d54bf7140 100644 +--- a/src/main/java/net/minecraft/server/AxisAlignedBB.java ++++ b/src/main/java/net/minecraft/server/AxisAlignedBB.java +@@ -13,6 +13,119 @@ public class AxisAlignedBB { + public final double maxY; + public final double maxZ; + ++ // Tuinity start ++ public final boolean isEmpty() { ++ return (this.maxX - this.minX) < 1.0E-7 && (this.maxY - this.minY) < 1.0E-7 && (this.maxZ - this.minZ) < 1.0E-7; ++ } ++ ++ 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 - 1.0E-7, 0.0, z - 1.0E-7, x + (16.0 + 1.0E-7), 255.0, z + (16.0 + 1.0E-7), false); ++ } ++ ++ // collideX, collideY, collideZ are copied from 1.12 src ++ // so the code all belongs to mojang ++ public double collideX(AxisAlignedBB axisalignedbb, double d0) { ++ if (axisalignedbb.maxY > this.minY && axisalignedbb.minY < this.maxY ++ && axisalignedbb.maxZ > this.minZ && axisalignedbb.minZ < this.maxZ) { ++ double d1; ++ ++ if (d0 > 0.0D && axisalignedbb.maxX <= this.minX) { ++ d1 = this.minX - axisalignedbb.maxX; ++ if (d1 < d0) { ++ d0 = d1; ++ } ++ } else if (d0 < 0.0D && axisalignedbb.minX >= this.maxX) { ++ d1 = this.maxX - axisalignedbb.minX; ++ if (d1 > d0) { ++ d0 = d1; ++ } ++ } ++ ++ return d0; ++ } else { ++ return d0; ++ } ++ } ++ ++ public double collideY(AxisAlignedBB axisalignedbb, double d0) { ++ if (axisalignedbb.maxX > this.minX && axisalignedbb.minX < this.maxX ++ && axisalignedbb.maxZ > this.minZ && axisalignedbb.minZ < this.maxZ) { ++ double d1; ++ ++ if (d0 > 0.0D && axisalignedbb.maxY <= this.minY) { ++ d1 = this.minY - axisalignedbb.maxY; ++ if (d1 < d0) { ++ d0 = d1; ++ } ++ } else if (d0 < 0.0D && axisalignedbb.minY >= this.maxY) { ++ d1 = this.maxY - axisalignedbb.minY; ++ if (d1 > d0) { ++ d0 = d1; ++ } ++ } ++ ++ return d0; ++ } else { ++ return d0; ++ } ++ } ++ ++ public double collideZ(AxisAlignedBB axisalignedbb, double d0) { ++ if (axisalignedbb.maxX > this.minX && axisalignedbb.minX < this.maxX ++ && axisalignedbb.maxY > this.minY && axisalignedbb.minY < this.maxY) { ++ double d1; ++ ++ if (d0 > 0.0D && axisalignedbb.maxZ <= this.minZ) { ++ d1 = this.minZ - axisalignedbb.maxZ; ++ if (d1 < d0) { ++ d0 = d1; ++ } ++ } else if (d0 < 0.0D && axisalignedbb.minZ >= this.maxZ) { ++ d1 = this.maxZ - axisalignedbb.minZ; ++ if (d1 > d0) { ++ d0 = d1; ++ } ++ } ++ ++ return d0; ++ } else { ++ return d0; ++ } ++ } ++ ++ 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 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 +298,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 +307,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 +327,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/BiomeBase.java b/src/main/java/net/minecraft/server/BiomeBase.java +index db198811d..52ebdfcc0 100644 +--- a/src/main/java/net/minecraft/server/BiomeBase.java ++++ b/src/main/java/net/minecraft/server/BiomeBase.java +@@ -92,6 +92,18 @@ public class BiomeBase { + return new WorldGenCarverWrapper<>(worldgencarverabstract, c0); + } + ++ // Tuinity start - optimise biome conversion ++ private org.bukkit.block.Biome bukkitBiome; ++ ++ public final org.bukkit.block.Biome getBukkitBiome() { ++ if (this.bukkitBiome == null) { ++ this.bukkitBiome = org.bukkit.block.Biome.valueOf(IRegistry.BIOME.getKey(this).getKey().toUpperCase(java.util.Locale.ENGLISH)); ++ } ++ ++ return this.bukkitBiome; ++ } ++ // Tuinity end - optimise biome conversion ++ + protected BiomeBase(BiomeBase.a biomebase_a) { + if (biomebase_a.a != null && biomebase_a.b != null && biomebase_a.c != null && biomebase_a.d != null && biomebase_a.e != null && biomebase_a.f != null && biomebase_a.g != null && biomebase_a.j != null) { + this.m = biomebase_a.a; +diff --git a/src/main/java/net/minecraft/server/BlockBase.java b/src/main/java/net/minecraft/server/BlockBase.java +index ff770a3b0..c4ad88b7e 100644 +--- a/src/main/java/net/minecraft/server/BlockBase.java ++++ b/src/main/java/net/minecraft/server/BlockBase.java +@@ -371,6 +371,7 @@ public abstract class BlockBase { + return this.getBlock().d(this.p(), iblockaccess, blockposition); + } + ++ public final boolean collisionBoxExceedsCube() { return this.d(); } // Tuinity - OBFHELPER + public boolean d() { + return this.a == null || this.a.c; + } +diff --git a/src/main/java/net/minecraft/server/BlockChest.java b/src/main/java/net/minecraft/server/BlockChest.java +index 44b9bfcdc..dba774018 100644 +--- a/src/main/java/net/minecraft/server/BlockChest.java ++++ b/src/main/java/net/minecraft/server/BlockChest.java +@@ -10,7 +10,7 @@ import javax.annotation.Nullable; + public class BlockChest extends BlockChestAbstract implements IBlockWaterlogged { + + public static final BlockStateDirection FACING = BlockFacingHorizontal.FACING; +- public static final BlockStateEnum c = BlockProperties.aF; ++ public static final BlockStateEnum c = BlockProperties.aF; public static final BlockStateEnum getChestTypeEnum() { return BlockChest.c; } // Tuinity - OBFHELPER + public static final BlockStateBoolean d = BlockProperties.C; public static final BlockStateBoolean waterlogged() { return d; } // Paper OBFHELPER + protected static final VoxelShape e = Block.a(1.0D, 0.0D, 0.0D, 15.0D, 14.0D, 15.0D); + protected static final VoxelShape f = Block.a(1.0D, 0.0D, 1.0D, 15.0D, 14.0D, 16.0D); +@@ -195,7 +195,7 @@ public class BlockChest extends BlockChestAbstract implements I + @Override + public void remove(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { + if (!iblockdata.a(iblockdata1.getBlock())) { +- TileEntity tileentity = world.getTileEntity(blockposition); ++ TileEntity tileentity = world.getTileEntity(blockposition, false); // Tuinity - block has since changed. + + if (tileentity instanceof IInventory) { + InventoryUtils.dropInventory(world, blockposition, (IInventory) tileentity); +diff --git a/src/main/java/net/minecraft/server/BlockPiston.java b/src/main/java/net/minecraft/server/BlockPiston.java +index c3133814f..4f10ca5ad 100644 +--- a/src/main/java/net/minecraft/server/BlockPiston.java ++++ b/src/main/java/net/minecraft/server/BlockPiston.java +@@ -270,7 +270,10 @@ public class BlockPiston extends BlockDirectional { + return false; + } + +- return !iblockdata.getBlock().isTileEntity(); ++ // Tuinity start - pushable TE's ++ TileEntity tileEntity; ++ return !iblockdata.getBlock().isTileEntity() || ((tileEntity = world.getTileEntity(blockposition)) != null && tileEntity.isPushable()); ++ // Tuinity end - pushable TE's + } else { + return false; + } +@@ -369,7 +372,7 @@ public class BlockPiston extends BlockDirectional { + + for (k = list.size() - 1; k >= 0; --k) { + // Paper start - fix a variety of piston desync dupes +- boolean allowDesync = com.destroystokyo.paper.PaperConfig.allowPistonDuplication; ++ boolean allowDesync = com.destroystokyo.paper.PaperConfig.allowPistonDuplication && !list1.get(k).getBlock().isTileEntity(); // Tuinity - pushable TE's + BlockPosition oldPos = blockposition3 = (BlockPosition) list.get(k); + iblockdata1 = allowDesync ? world.getType(oldPos) : null; + // Paper end - fix a variety of piston desync dupes +@@ -381,10 +384,29 @@ public class BlockPiston extends BlockDirectional { + iblockdata1 = world.getType(oldPos); + map.replace(oldPos, iblockdata1); + } +- world.setTileEntity(blockposition3, BlockPistonMoving.a(allowDesync ? list1.get(k) : iblockdata1, enumdirection, flag, false)); ++ // Tuinity start - pushable TE's ++ TileEntity tileEntity = world.getTileEntity(oldPos); ++ if (tileEntity != null) { ++ if (!tileEntity.isPushable()) { ++ tileEntity = null; ++ } else { ++ // ensure the death of world tied state ++ if (tileEntity instanceof IInventory) { ++ MCUtil.closeInventory((IInventory)tileEntity, org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); ++ } ++ if (tileEntity instanceof TileEntityLectern) { ++ MCUtil.closeInventory(((TileEntityLectern)tileEntity).inventory, org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); ++ } ++ ++ // now copy ++ tileEntity = tileEntity.createCopyForPush((WorldServer)world, oldPos, blockposition3, iblockdata1); ++ } ++ } ++ // Tuinity end - pushable TE's + if (!allowDesync) { +- world.setTypeAndData(oldPos, Blocks.AIR.getBlockData(), 2 | 4 | 16 | 1024); // set air to prevent later physics updates from seeing this block ++ world.setTypeAndDataRaw(oldPos, Blocks.AIR.getBlockData(), null); // Tuinity - don't fire logic for removing the old block + } ++ world.setTileEntity(blockposition3, BlockPistonMoving.createPistonTile(allowDesync ? list1.get(k) : iblockdata1, enumdirection, flag, false, tileEntity)); // Tuinity - pushable TE's + // Paper end - fix a variety of piston desync dupes + aiblockdata[j++] = iblockdata1; + } +diff --git a/src/main/java/net/minecraft/server/BlockPistonMoving.java b/src/main/java/net/minecraft/server/BlockPistonMoving.java +index 4bf66420f..bf76615d7 100644 +--- a/src/main/java/net/minecraft/server/BlockPistonMoving.java ++++ b/src/main/java/net/minecraft/server/BlockPistonMoving.java +@@ -21,7 +21,12 @@ public class BlockPistonMoving extends BlockTileEntity { + } + + public static TileEntity a(IBlockData iblockdata, EnumDirection enumdirection, boolean flag, boolean flag1) { +- return new TileEntityPiston(iblockdata, enumdirection, flag, flag1); ++ // Tuinity start - add tileEntity parameter ++ return createPistonTile(iblockdata, enumdirection, flag, flag1, null); ++ } ++ public static TileEntity createPistonTile(IBlockData iblockdata, EnumDirection enumdirection, boolean flag, boolean flag1, TileEntity tileEntity) { ++ return new TileEntityPiston(iblockdata, enumdirection, flag, flag1, tileEntity); ++ // Tuinity end - add tileEntity parameter + } + + @Override +diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java +index 84dc89d96..996438b00 100644 +--- a/src/main/java/net/minecraft/server/Chunk.java ++++ b/src/main/java/net/minecraft/server/Chunk.java +@@ -510,8 +510,35 @@ public class Chunk implements IChunkAccess { + return this.setType(blockposition, iblockdata, flag, true); + } + ++ // Tuinity start ++ final void setTypeAndDataRaw(BlockPosition blockposition, IBlockData iblockdata) { ++ // copied from setType ++ int i = blockposition.getX() & 15; ++ int j = blockposition.getY(); ++ int k = blockposition.getZ() & 15; ++ ChunkSection chunksection = this.sections[j >> 4]; ++ ++ if (chunksection == Chunk.a) { ++ if (iblockdata.isAir()) { ++ return; ++ } ++ ++ chunksection = new ChunkSection(j >> 4 << 4, this, this.world, true); // Paper - Anti-Xray - Add parameters ++ this.sections[j >> 4] = chunksection; ++ } ++ ++ chunksection.setType(i, j & 15, k, iblockdata); ++ } ++ // Tuinity end ++ + @Nullable + public IBlockData setType(BlockPosition blockposition, IBlockData iblockdata, boolean flag, boolean doPlace) { ++ // Tuinity start - add tileEntity parameter ++ return this.setType(blockposition, iblockdata, flag, doPlace, null); ++ } ++ @Nullable ++ public IBlockData setType(BlockPosition blockposition, IBlockData iblockdata, boolean flag, boolean doPlace, TileEntity newTileEntity) { ++ // Tuinity end - add tileEntity parameter + // CraftBukkit end + int i = blockposition.getX() & 15; + int j = blockposition.getY(); +@@ -570,6 +597,10 @@ public class Chunk implements IChunkAccess { + } + + if (block instanceof ITileEntity) { ++ // Tuinity start - add tileEntity parameter ++ if (newTileEntity != null) { ++ this.world.setTileEntity(blockposition, newTileEntity); ++ } else { // Tuinity end - add tileEntity parameter + tileentity = this.a(blockposition, Chunk.EnumTileEntityState.CHECK); + if (tileentity == null) { + tileentity = ((ITileEntity) block).createTile(this.world); +@@ -577,6 +608,7 @@ public class Chunk implements IChunkAccess { + } else { + tileentity.invalidateBlockCache(); + } ++ } // Tuinity - add tileEntity parameter + } + + this.s = true; +@@ -592,6 +624,7 @@ public class Chunk implements IChunkAccess { + + @Override + public void a(Entity entity) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Async addEntity call"); // Tuinity + this.q = true; + int i = MathHelper.floor(entity.locX() / 16.0D); + int j = MathHelper.floor(entity.locZ() / 16.0D); +@@ -661,6 +694,7 @@ public class Chunk implements IChunkAccess { + } + + public void a(Entity entity, int i) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Async removeEntity call"); // Tuinity + if (i < 0) { + i = 0; + } +@@ -918,6 +952,7 @@ public class Chunk implements IChunkAccess { + } + + public void a(@Nullable Entity entity, AxisAlignedBB axisalignedbb, List list, @Nullable Predicate predicate) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Async getEntities call"); // Tuinity + int i = MathHelper.floor((axisalignedbb.minY - 2.0D) / 16.0D); + int j = MathHelper.floor((axisalignedbb.maxY + 2.0D) / 16.0D); + +@@ -957,6 +992,7 @@ public class Chunk implements IChunkAccess { + } + + public void a(@Nullable EntityTypes entitytypes, AxisAlignedBB axisalignedbb, List list, Predicate predicate) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Async getEntities call"); // Tuinity + int i = MathHelper.floor((axisalignedbb.minY - 2.0D) / 16.0D); + int j = MathHelper.floor((axisalignedbb.maxY + 2.0D) / 16.0D); + +@@ -987,6 +1023,7 @@ public class Chunk implements IChunkAccess { + } + + public void a(Class oclass, AxisAlignedBB axisalignedbb, List list, @Nullable Predicate predicate) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Async getEntities call"); // Tuinity + int i = MathHelper.floor((axisalignedbb.minY - 2.0D) / 16.0D); + int j = MathHelper.floor((axisalignedbb.maxY + 2.0D) / 16.0D); + +diff --git a/src/main/java/net/minecraft/server/ChunkMapDistance.java b/src/main/java/net/minecraft/server/ChunkMapDistance.java +index 893c0085b..d83d3b54d 100644 +--- a/src/main/java/net/minecraft/server/ChunkMapDistance.java ++++ b/src/main/java/net/minecraft/server/ChunkMapDistance.java +@@ -31,7 +31,7 @@ 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(); +- private final ChunkMapDistance.a ticketLevelTracker = new ChunkMapDistance.a(); ++ private final ChunkMapDistance.a ticketLevelTracker = new ChunkMapDistance.a(); final ChunkMapDistance.a getTicketTracker() { return this.ticketLevelTracker; } // Tuinity - OBFHELPER + public static final int MOB_SPAWN_RANGE = 8; // private final ChunkMapDistance.b f = new ChunkMapDistance.b(8); // Paper - no longer used + private final ChunkMapDistance.c g = new ChunkMapDistance.c(33); + // Paper start use a queue, but still keep unique requirement +@@ -53,6 +53,47 @@ public abstract class ChunkMapDistance { + + PlayerChunkMap chunkMap; // Paper + ++ // Tuinity start - delay chunk unloads ++ private long nextUnloadId; // delay chunk unloads ++ private final Long2ObjectOpenHashMap> delayedChunks = new Long2ObjectOpenHashMap<>(); ++ public final void removeTickets(long chunk, TicketType type) { ++ ArraySetSorted> tickets = this.tickets.get(chunk); ++ if (tickets == null) { ++ return; ++ } ++ if (type == TicketType.DELAYED_UNLOAD) { ++ this.delayedChunks.remove(chunk); ++ } ++ boolean changed = tickets.removeIf((Ticket ticket) -> { ++ return ticket.getTicketType() == type; ++ }); ++ if (changed) { ++ this.getTicketTracker().update(chunk, getLowestTicketLevel(tickets), false); ++ } ++ } ++ ++ private final java.util.function.LongFunction> computeFuntion = (long key) -> { ++ Ticket ret = new Ticket<>(TicketType.DELAYED_UNLOAD, -1, ++ChunkMapDistance.this.nextUnloadId); ++ ret.isCached = true; ++ return ret; ++ }; ++ ++ private void computeDelayedTicketFor(long chunk, int removedLevel, ArraySetSorted> tickets) { ++ int lowestLevel = getLowestTicketLevel(tickets); ++ if (removedLevel > lowestLevel) { ++ return; ++ } ++ final Ticket ticket = this.delayedChunks.computeIfAbsent(chunk, this.computeFuntion); ++ if (ticket.getTicketLevel() != -1) { ++ // since we modify data used in sorting, we need to remove before ++ tickets.remove(ticket); ++ } ++ ticket.setCreationTick(this.currentTick); ++ ticket.setTicketLevel(removedLevel); ++ tickets.add(ticket); // re-add with new expire time and ticket level ++ } ++ // Tuinity end - delay chunk unloads ++ + protected ChunkMapDistance(Executor executor, Executor executor1) { + executor1.getClass(); + Mailbox mailbox = Mailbox.a("player ticket throttler", executor1::execute); +@@ -65,15 +106,34 @@ public abstract class ChunkMapDistance { + } + + protected void purgeTickets() { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Async purge tickets"); // Tuinity + ++this.currentTick; + ObjectIterator objectiterator = this.tickets.long2ObjectEntrySet().fastIterator(); + ++ int[] tempLevel = new int[] { PlayerChunkMap.GOLDEN_TICKET + 1 }; // Tuinity - delay chunk unloads + while (objectiterator.hasNext()) { + Entry>> entry = (Entry) objectiterator.next(); + + if ((entry.getValue()).removeIf((ticket) -> { // CraftBukkit - decompile error +- return ticket.b(this.currentTick); ++ // Tuinity start - delay chunk unloads ++ boolean ret = ticket.isExpired(this.currentTick); ++ if (com.tuinity.tuinity.config.TuinityConfig.delayChunkUnloadsBy <= 0) { ++ return ret; ++ } ++ if (ret && ticket.getTicketType() != TicketType.DELAYED_UNLOAD && ticket.getTicketLevel() < tempLevel[0]) { ++ tempLevel[0] = ticket.getTicketLevel(); ++ } ++ if (ticket.getTicketType() == TicketType.DELAYED_UNLOAD && ticket.isCached) { ++ this.delayedChunks.remove(entry.getLongKey(), ticket); // clean up ticket... ++ } ++ return ret; ++ // Tuinity end - delay chunk unloads + })) { ++ // Tuinity start - delay chunk unloads ++ if (tempLevel[0] < (PlayerChunkMap.GOLDEN_TICKET + 1)) { ++ this.computeDelayedTicketFor(entry.getLongKey(), tempLevel[0], entry.getValue()); ++ } ++ // Tuinity end - delay chunk unloads + this.ticketLevelTracker.update(entry.getLongKey(), getLowestTicketLevel((ArraySetSorted) entry.getValue()), false); + } + +@@ -98,6 +158,7 @@ public abstract class ChunkMapDistance { + protected abstract PlayerChunk a(long i, int j, @Nullable PlayerChunk playerchunk, int k); + + public boolean a(PlayerChunkMap playerchunkmap) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Cannot tick ChunkMapDistance off of the main-thread");// Tuinity + //this.f.a(); // Paper - no longer used + AsyncCatcher.catchOp("DistanceManagerTick"); // Paper + this.g.a(); +@@ -176,27 +237,11 @@ public abstract class ChunkMapDistance { + boolean removed = false; // CraftBukkit + if (arraysetsorted.remove(ticket)) { + removed = true; // CraftBukkit +- // Paper start - delay chunk unloads for player tickets +- long delayChunkUnloadsBy = chunkMap.world.paperConfig.delayChunkUnloadsBy; +- if (ticket.getTicketType() == TicketType.PLAYER && delayChunkUnloadsBy > 0) { +- boolean hasPlayer = false; +- for (Ticket ticket1 : arraysetsorted) { +- if (ticket1.getTicketType() == TicketType.PLAYER) { +- hasPlayer = true; +- break; +- } +- } +- PlayerChunk playerChunk = chunkMap.getUpdatingChunk(i); +- if (!hasPlayer && playerChunk != null && playerChunk.isFullChunkReady()) { +- Ticket delayUnload = new Ticket(TicketType.DELAY_UNLOAD, 33, i); +- delayUnload.delayUnloadBy = delayChunkUnloadsBy; +- delayUnload.setCurrentTick(this.currentTick); +- arraysetsorted.remove(delayUnload); +- // refresh ticket +- arraysetsorted.add(delayUnload); +- } ++ // Tuinity start - delay chunk unloads ++ if (com.tuinity.tuinity.config.TuinityConfig.delayChunkUnloadsBy > 0 && ticket.getTicketType() != TicketType.DELAYED_UNLOAD) { ++ this.computeDelayedTicketFor(i, ticket.getTicketLevel(), arraysetsorted); + } +- // Paper end ++ // Tuinity end - delay chunk unloads + } + + if (arraysetsorted.isEmpty()) { +@@ -370,6 +415,7 @@ public abstract class ChunkMapDistance { + } + + private ArraySetSorted> e(long i) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Async tickets compute"); // Tuinity + return (ArraySetSorted) this.tickets.computeIfAbsent(i, (j) -> { + return ArraySetSorted.a(4); + }); +@@ -387,6 +433,7 @@ public abstract class ChunkMapDistance { + } + + public void a(SectionPosition sectionposition, EntityPlayer entityplayer) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Async player add"); // Tuinity + long i = sectionposition.r().pair(); + + ((ObjectSet) this.c.computeIfAbsent(i, (j) -> { +@@ -397,6 +444,7 @@ public abstract class ChunkMapDistance { + } + + public void b(SectionPosition sectionposition, EntityPlayer entityplayer) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Async player remove"); // Tuinity + long i = sectionposition.r().pair(); + ObjectSet objectset = (ObjectSet) this.c.get(i); + +@@ -446,6 +494,7 @@ public abstract class ChunkMapDistance { + + // CraftBukkit start + public void removeAllTicketsFor(TicketType ticketType, int ticketLevel, T ticketIdentifier) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Async ticket remove"); // Tuinity + Ticket target = new Ticket<>(ticketType, ticketLevel, ticketIdentifier); + + for (java.util.Iterator>>> iterator = this.tickets.long2ObjectEntrySet().fastIterator(); iterator.hasNext();) { +diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java +index ef980f985..507105a2c 100644 +--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java +@@ -120,7 +120,7 @@ public class ChunkProviderServer extends IChunkProvider { + return (Chunk)this.getChunkAt(x, z, ChunkStatus.FULL, true); + } + +- private long chunkFutureAwaitCounter; ++ long chunkFutureAwaitCounter; // Tuinity - private -> package private + + public void getEntityTickingChunkAsync(int x, int z, java.util.function.Consumer onLoad) { + if (Thread.currentThread() != this.serverThread) { +@@ -182,9 +182,9 @@ public class ChunkProviderServer extends IChunkProvider { + + try { + if (onLoad != null) { +- playerChunkMap.callbackExecutor.execute(() -> { ++ // Tuinity - revert incorrect use of callback executor + onLoad.accept(either == null ? null : either.left().orElse(null)); // indicate failure to the callback. +- }); ++ // Tuinity - revert incorrect use of callback executor + } + } catch (Throwable thr) { + if (thr instanceof ThreadDeath) { +@@ -209,6 +209,164 @@ public class ChunkProviderServer extends IChunkProvider { + } + // Paper end - rewrite ticklistserver + ++ // Tuinity start ++ // this will try to avoid chunk neighbours for lighting ++ public final IChunkAccess getFullStatusChunkAt(int chunkX, int chunkZ) { ++ Chunk ifLoaded = this.getChunkAtIfLoadedImmediately(chunkX, chunkZ); ++ if (ifLoaded != null) { ++ return ifLoaded; ++ } ++ ++ IChunkAccess empty = this.getChunkAt(chunkX, chunkZ, ChunkStatus.EMPTY, true); ++ if (empty != null && empty.getChunkStatus() == ChunkStatus.FULL) { ++ return empty; ++ } ++ return this.getChunkAt(chunkX, chunkZ, ChunkStatus.FULL, true); ++ } ++ ++ public final IChunkAccess getFullStatusChunkAtIfLoaded(int chunkX, int chunkZ) { ++ Chunk ifLoaded = this.getChunkAtIfLoadedImmediately(chunkX, chunkZ); ++ if (ifLoaded != null) { ++ return ifLoaded; ++ } ++ ++ IChunkAccess ret = this.getChunkAtImmediately(chunkX, chunkZ); ++ if (ret != null && ret.getChunkStatus() == ChunkStatus.FULL) { ++ return ret; ++ } else { ++ return null; ++ } ++ } ++ ++ void getChunkAtAsynchronously(int chunkX, int chunkZ, int ticketLevel, ++ java.util.function.Consumer consumer) { ++ this.getChunkAtAsynchronously(chunkX, chunkZ, ticketLevel, (PlayerChunk playerChunk) -> { ++ if (ticketLevel <= 33) { ++ return (CompletableFuture)playerChunk.getFullChunkFuture(); ++ } else { ++ return playerChunk.getOrCreateFuture(PlayerChunk.getChunkStatus(ticketLevel), ChunkProviderServer.this.playerChunkMap); ++ } ++ }, consumer); ++ } ++ ++ void getChunkAtAsynchronously(int chunkX, int chunkZ, int ticketLevel, ++ java.util.function.Function>> function, ++ java.util.function.Consumer consumer) { ++ if (Thread.currentThread() != this.serverThread) { ++ throw new IllegalStateException(); ++ } ++ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(chunkX, chunkZ); ++ Long identifier = Long.valueOf(this.chunkFutureAwaitCounter++); ++ this.addTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier); ++ this.tickDistanceManager(); ++ ++ PlayerChunk chunk = this.playerChunkMap.getUpdatingChunk(chunkPos.pair()); ++ ++ if (chunk == null) { ++ throw new IllegalStateException("Expected playerchunk " + chunkPos + " in world '" + this.world.getWorld().getName() + "'"); ++ } ++ ++ CompletableFuture> future = function.apply(chunk); ++ ++ future.whenCompleteAsync((either, throwable) -> { ++ try { ++ if (throwable != null) { ++ if (throwable instanceof ThreadDeath) { ++ throw (ThreadDeath)throwable; ++ } ++ MinecraftServer.LOGGER.fatal("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ChunkProviderServer.this.world.getWorld().getName() + "'", throwable); ++ } else if (either.right().isPresent()) { ++ MinecraftServer.LOGGER.fatal("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ChunkProviderServer.this.world.getWorld().getName() + "': " + either.right().get().toString()); ++ } ++ ++ try { ++ if (consumer != null) { ++ consumer.accept(either == null ? null : either.left().orElse(null)); // indicate failure to the callback. ++ } ++ } catch (Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ MinecraftServer.LOGGER.fatal("Load callback for future await failed " + chunkPos.toString() + " in world '" + ChunkProviderServer.this.world.getWorld().getName() + "'", thr); ++ return; ++ } ++ } finally { ++ // due to odd behaviour with CB unload implementation we need to have these AFTER the load callback. ++ ChunkProviderServer.this.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos); ++ ChunkProviderServer.this.removeTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier); ++ } ++ }, this.serverThreadQueue); ++ } ++ ++ void chunkLoadAccept(int chunkX, int chunkZ, IChunkAccess chunk, java.util.function.Consumer consumer) { ++ try { ++ consumer.accept(chunk); ++ } catch (Throwable throwable) { ++ if (throwable instanceof ThreadDeath) { ++ throw (ThreadDeath)throwable; ++ } ++ MinecraftServer.LOGGER.error("Load callback for chunk " + chunkX + "," + chunkZ + " in world '" + this.world.getWorld().getName() + "' threw an exception", throwable); ++ } ++ } ++ ++ public final void getChunkAtAsynchronously(int chunkX, int chunkZ, ChunkStatus status, boolean gen, boolean allowSubTicketLevel, java.util.function.Consumer onLoad) { ++ // try to fire sync ++ int chunkStatusTicketLevel = 33 + ChunkStatus.getTicketLevelOffset(status); ++ IChunkAccess immediate = this.getChunkAtImmediately(chunkX, chunkZ); ++ if (immediate != null) { ++ if (allowSubTicketLevel || this.playerChunkMap.getUpdatingChunk(MCUtil.getCoordinateKey(chunkX, chunkZ)).getTicketLevel() <= chunkStatusTicketLevel) { ++ if (immediate.getChunkStatus().isAtLeastStatus(status)) { ++ this.chunkLoadAccept(chunkX, chunkZ, immediate, onLoad); ++ } else { ++ if (gen) { ++ this.getChunkAtAsynchronously(chunkX, chunkZ, chunkStatusTicketLevel, onLoad); ++ } else { ++ this.chunkLoadAccept(chunkX, chunkZ, null, onLoad); ++ } ++ } ++ } else { ++ if (gen || immediate.getChunkStatus().isAtLeastStatus(status)) { ++ this.getChunkAtAsynchronously(chunkX, chunkZ, chunkStatusTicketLevel, onLoad); ++ } else { ++ this.chunkLoadAccept(chunkX, chunkZ, null, onLoad); ++ } ++ } ++ return; ++ } ++ ++ // need to fire async ++ ++ if (gen && !allowSubTicketLevel) { ++ this.getChunkAtAsynchronously(chunkX, chunkZ, chunkStatusTicketLevel, onLoad); ++ return; ++ } ++ ++ this.getChunkAtAsynchronously(chunkX, chunkZ, 33 + ChunkStatus.getTicketLevelOffset(ChunkStatus.EMPTY), (IChunkAccess chunk) -> { ++ if (chunk == null) { ++ throw new IllegalStateException("Chunk cannot be null"); ++ } ++ ++ if (!chunk.getChunkStatus().isAtLeastStatus(status)) { ++ if (gen) { ++ this.getChunkAtAsynchronously(chunkX, chunkZ, chunkStatusTicketLevel, onLoad); ++ return; ++ } else { ++ ChunkProviderServer.this.chunkLoadAccept(chunkX, chunkZ, null, onLoad); ++ return; ++ } ++ } else { ++ if (allowSubTicketLevel) { ++ ChunkProviderServer.this.chunkLoadAccept(chunkX, chunkZ, chunk, onLoad); ++ return; ++ } else { ++ this.getChunkAtAsynchronously(chunkX, chunkZ, chunkStatusTicketLevel, onLoad); ++ return; ++ } ++ } ++ }); ++ } ++ // Tuinity end ++ + public ChunkProviderServer(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, ChunkGenerator chunkgenerator, int i, boolean flag, WorldLoadListener worldloadlistener, Supplier supplier) { + this.world = worldserver; + this.serverThreadQueue = new ChunkProviderServer.a(worldserver); +@@ -544,6 +702,8 @@ public class ChunkProviderServer extends IChunkProvider { + Arrays.fill(this.cacheChunk, (Object) null); + } + ++ private long syncLoadCounter; // Tuinity - prevent plugin unloads from removing our ticket ++ + 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 +722,12 @@ public class ChunkProviderServer extends IChunkProvider { + PlayerChunk.State currentChunkState = PlayerChunk.getChunkState(playerchunk.getTicketLevel()); + currentlyUnloading = (oldChunkState.isAtLeast(PlayerChunk.State.BORDER) && !currentChunkState.isAtLeast(PlayerChunk.State.BORDER)); + } ++ final Long identifier; // Tuinity - prevent plugin unloads from removing our ticket + if (flag && !currentlyUnloading) { + // CraftBukkit end + this.chunkMapDistance.a(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); ++ identifier = Long.valueOf(this.syncLoadCounter++); // Tuinity - prevent plugin unloads from removing our ticket ++ this.chunkMapDistance.addTicketAtLevel(TicketType.REQUIRED_LOAD, chunkcoordintpair, l, identifier); // Tuinity - prevent plugin unloads from removing our ticket + if (isUrgent) this.chunkMapDistance.markUrgent(chunkcoordintpair); // Paper + if (this.a(playerchunk, l)) { + GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler(); +@@ -575,12 +738,20 @@ public class ChunkProviderServer extends IChunkProvider { + playerchunk = this.getChunk(k); + gameprofilerfiller.exit(); + if (this.a(playerchunk, l)) { ++ this.chunkMapDistance.removeTicketAtLevel(TicketType.REQUIRED_LOAD, chunkcoordintpair, l, identifier); // Tuinity + throw (IllegalStateException) SystemUtils.c(new IllegalStateException("No chunk holder after ticket has been added")); + } + } +- } ++ } else { identifier = null; } // Tuinity - prevent plugin unloads from removing our ticket + // Paper start + CompletableFuture> future = this.a(playerchunk, l) ? PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE : playerchunk.a(chunkstatus, this.playerChunkMap); ++ // Tuinity start - prevent plugin unloads from removing our ticket ++ if (flag && !currentlyUnloading) { ++ future.thenAcceptAsync((either) -> { ++ ChunkProviderServer.this.chunkMapDistance.removeTicketAtLevel(TicketType.REQUIRED_LOAD, chunkcoordintpair, l, identifier); ++ }, ChunkProviderServer.this.serverThreadQueue); ++ } ++ // Tuinity end - prevent plugin unloads from removing our ticket + if (isUrgent) { + future.thenAccept(either -> this.chunkMapDistance.clearUrgent(chunkcoordintpair)); + } +@@ -734,7 +905,7 @@ public class ChunkProviderServer extends IChunkProvider { + this.world.getMethodProfiler().enter("purge"); + this.world.timings.doChunkMap.startTiming(); // Spigot + this.chunkMapDistance.purgeTickets(); +- this.world.getMinecraftServer().midTickLoadChunks(); // Paper ++ // Tuinity - replace logic + this.tickDistanceManager(); + this.world.timings.doChunkMap.stopTiming(); // Spigot + this.world.getMethodProfiler().exitEnter("chunks"); +@@ -744,12 +915,22 @@ public class ChunkProviderServer extends IChunkProvider { + this.world.timings.doChunkUnload.startTiming(); // Spigot + this.world.getMethodProfiler().exitEnter("unload"); + this.playerChunkMap.unloadChunks(booleansupplier); +- this.world.getMinecraftServer().midTickLoadChunks(); // Paper ++ // Tuinity - replace logic + this.world.timings.doChunkUnload.stopTiming(); // Spigot + this.world.getMethodProfiler().exit(); + this.clearCache(); + } + ++ // Tuinity start - optimise chunk tick iteration ++ // We need this here because since we remove the COW op for chunk map, we also remove ++ // the iterator safety of the visible map - meaning the only way for us to still ++ // iterate is to use a copy. Not acceptable at all, so here we hack in an iterable safe ++ // chunk map that will give the same behaviour as previous - without COW. ++ final com.destroystokyo.paper.util.maplist.ChunkList entityTickingChunks = new com.destroystokyo.paper.util.maplist.ChunkList(); ++ boolean isTickingChunks; ++ final it.unimi.dsi.fastutil.objects.Object2BooleanLinkedOpenHashMap pendingEntityTickingChunkChanges = new it.unimi.dsi.fastutil.objects.Object2BooleanLinkedOpenHashMap<>(16, 0.8f); ++ // Tuinity end - optimise chunk tick iteration ++ + private void tickChunks() { + long i = this.world.getTime(); + long j = i - this.lastTickTime; +@@ -820,19 +1001,21 @@ public class ChunkProviderServer extends IChunkProvider { + //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper + //Collections.shuffle(list); // Paper + // Paper - moved up +- final int[] chunksTicked = {0}; this.playerChunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping +- Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); +- +- if (optional.isPresent()) { ++ // Tuinity start - optimise chunk tick iteration ++ this.isTickingChunks = true; ++ for (Chunk chunk : this.entityTickingChunks) { ++ PlayerChunk playerchunk = chunk.playerChunk; ++ if (playerchunk != null) { // make sure load event has been called along with the load logic we put there ++ // Tuinity end - optimise chunk tick iteration + this.world.getMethodProfiler().enter("broadcast"); + this.world.timings.broadcastChunkUpdates.startTiming(); // Paper - timings +- playerchunk.a((Chunk) optional.get()); ++ playerchunk.a(chunk); // Tuinity + this.world.timings.broadcastChunkUpdates.stopTiming(); // Paper - timings + this.world.getMethodProfiler().exit(); +- Optional optional1 = ((Either) playerchunk.b().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); ++ // Tuinity + +- if (optional1.isPresent()) { +- Chunk chunk = (Chunk) optional1.get(); ++ if (true) { // Tuinity ++ // Tuinity + ChunkCoordIntPair chunkcoordintpair = playerchunk.i(); + + if (!this.playerChunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, false)) { // Paper - optimise isOutsideOfRange +@@ -844,11 +1027,27 @@ public class ChunkProviderServer extends IChunkProvider { + this.world.timings.chunkTicks.startTiming(); // Spigot // Paper + this.world.a(chunk, k); + this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper +- if (chunksTicked[0]++ % 10 == 0) this.world.getMinecraftServer().midTickLoadChunks(); // Paper ++ MinecraftServer.getServer().executeMidTickTasks(); // Tuinity - exec chunk tasks during world tick + } + } + } +- }); ++ } // Tuinity start - optimise chunk tick iteration ++ this.isTickingChunks = false; ++ if (!this.pendingEntityTickingChunkChanges.isEmpty()) { ++ // iterate backwards: fastutil maps have better remove times when iterating backwards ++ // (this is due to the fact that we likely wont shift entries on remove calls) ++ for (it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator> iterator = this.pendingEntityTickingChunkChanges.object2BooleanEntrySet().fastIterator(this.pendingEntityTickingChunkChanges.object2BooleanEntrySet().last()); iterator.hasPrevious();) { ++ it.unimi.dsi.fastutil.objects.Object2BooleanMap.Entry entry = iterator.previous(); ++ ++ if (entry.getBooleanValue()) { ++ this.entityTickingChunks.add(entry.getKey()); ++ } else { ++ this.entityTickingChunks.remove(entry.getKey()); ++ } ++ iterator.remove(); ++ } ++ } ++ // Tuinity end - optimise chunk tick iteration + this.world.getMethodProfiler().enter("customSpawners"); + if (flag1) { + try (co.aikar.timings.Timing ignored = this.world.timings.miscMobSpawning.startTiming()) { // Paper - timings +@@ -860,7 +1059,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()); ++ for (EntityPlayer player : this.world.getPlayers()) { ++ PlayerConnection connection = player.playerConnection; ++ if (connection != null) { ++ connection.networkManager.disableAutomaticFlush(); ++ disabledFlushes.add(connection.networkManager); ++ } ++ } ++ try { ++ // Tuinity end - controlled flush for entity tracker packets + this.playerChunkMap.g(); ++ // Tuinity start - controlled flush for entity tracker packets ++ } finally { ++ for (NetworkManager networkManager : disabledFlushes) { ++ networkManager.enableAutomaticFlush(); ++ } ++ } ++ // Tuinity end - controlled flush for entity tracker packets + } + + private void a(long i, Consumer consumer) { +@@ -1000,44 +1217,11 @@ public class ChunkProviderServer extends IChunkProvider { + ChunkProviderServer.this.world.getMethodProfiler().c("runTask"); + super.executeTask(runnable); + } +- +- // Paper start +- private long lastMidTickChunkTask = 0; +- public boolean pollChunkLoadTasks() { +- if (com.destroystokyo.paper.io.chunk.ChunkTaskManager.pollChunkWaitQueue() || ChunkProviderServer.this.world.asyncChunkTaskManager.pollNextChunkTask()) { +- try { +- ChunkProviderServer.this.tickDistanceManager(); +- } finally { +- // from below: process pending Chunk loadCallback() and unloadCallback() after each run task +- playerChunkMap.callbackExecutor.run(); +- } +- return true; +- } +- return false; +- } +- public void midTickLoadChunks() { +- MinecraftServer server = ChunkProviderServer.this.world.getMinecraftServer(); +- // always try to load chunks, restrain generation/other updates only. don't count these towards tick count +- //noinspection StatementWithEmptyBody +- while (pollChunkLoadTasks()) {} +- +- if (System.nanoTime() - lastMidTickChunkTask < 200000) { +- return; +- } +- +- for (;server.midTickChunksTasksRan < com.destroystokyo.paper.PaperConfig.midTickChunkTasks && server.canSleepForTick();) { +- if (this.executeNext()) { +- server.midTickChunksTasksRan++; +- lastMidTickChunkTask = System.nanoTime(); +- } else { +- break; +- } +- } +- } +- // Paper end ++ // Tuinity - replace logic + + @Override + protected boolean executeNext() { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Cannot execute chunk tasks off-main thread");// Tuinity + // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task + try { + boolean execChunkTask = com.destroystokyo.paper.io.chunk.ChunkTaskManager.pollChunkWaitQueue() || ChunkProviderServer.this.world.asyncChunkTaskManager.pollNextChunkTask(); // Paper +diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java +index ac58fcb79..742c59cb0 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) { +@@ -374,10 +382,10 @@ public class ChunkRegionLoader { + 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(); +diff --git a/src/main/java/net/minecraft/server/ChunkSection.java b/src/main/java/net/minecraft/server/ChunkSection.java +index 8d45588ec..4ab741985 100644 +--- a/src/main/java/net/minecraft/server/ChunkSection.java ++++ b/src/main/java/net/minecraft/server/ChunkSection.java +@@ -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 36c265122..dd8a3dc4f 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 1cb45f97b..e60ad41b2 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 8b2755a3b..578f7809c 100644 +--- a/src/main/java/net/minecraft/server/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/DedicatedServer.java +@@ -170,6 +170,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); +diff --git a/src/main/java/net/minecraft/server/EULA.java b/src/main/java/net/minecraft/server/EULA.java +index 550232cb3..229c3b0f0 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 fcb3d3ada..f8ca56be8 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; +@@ -212,6 +212,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 + /** + * Overriding this field will cause memory leaks. +@@ -625,7 +633,44 @@ 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 ++ ++ boolean collidedOnSomething; // Tuinity - optimise collisions ++ boolean requiredRelaxedCollisionCheck; // Tuinity - optimise collisions ++ + 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; ++ } ++ this.collidedOnSomething = false; // Tuinity - optimise collisions ++ try { ++ // Tuinity end - detailed watchdog information + if (this.noclip) { + this.a(this.getBoundingBox().c(vec3d)); + this.recalcPosition(); +@@ -653,7 +698,8 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke + // Paper end + + vec3d = this.a(vec3d, enummovetype); +- Vec3D vec3d1 = this.f(vec3d); ++ Vec3D vec3d1 = !this.requiredRelaxedCollisionCheck ? this.performCollision(vec3d) : this.performCollision(vec3d, 0.0625); // Tuinity - optimise collisions ++ this.collidedOnSomething = !vec3d.equals(vec3d1); // Tuinity - optimise collisions + + if (vec3d1.g() > 1.0E-7D) { + this.a(this.getBoundingBox().c(vec3d1)); +@@ -770,6 +816,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 ak() { +@@ -850,6 +903,138 @@ 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) { ++ if (Math.abs(value) < 1.0E-7) { ++ return 0.0; ++ } ++ AxisAlignedBB target = potentialCollisions.get(i); ++ value = target.collideX(currentBoundingBox, value); ++ } ++ ++ return value; ++ } ++ ++ private static double performCollisionsY(AxisAlignedBB currentBoundingBox, double value, List potentialCollisions) { ++ for (int i = 0, len = potentialCollisions.size(); i < len; ++i) { ++ if (Math.abs(value) < 1.0E-7) { ++ return 0.0; ++ } ++ AxisAlignedBB target = potentialCollisions.get(i); ++ value = target.collideY(currentBoundingBox, value); ++ } ++ ++ return value; ++ } ++ ++ private static double performCollisionsZ(AxisAlignedBB currentBoundingBox, double value, List potentialCollisions) { ++ for (int i = 0, len = potentialCollisions.size(); i < len; ++i) { ++ if (Math.abs(value) < 1.0E-7) { ++ return 0.0; ++ } ++ AxisAlignedBB target = potentialCollisions.get(i); ++ value = target.collideZ(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) { ++ return this.performCollision(moveVector, 0.0); ++ } ++ Vec3D performCollision(Vec3D moveVector, double contractAmount) { ++ if (moveVector.getX() == 0.0 && moveVector.getY() == 0.0 && moveVector.getZ() == 0.0) { ++ return moveVector; ++ } ++ ++ WorldServer world = ((WorldServer)this.world); ++ AxisAlignedBB currBoundingBox = contractAmount == 0.0 ? this.getBoundingBox() : this.getBoundingBox().grow(-contractAmount); ++ ++ List potentialCollisions = com.tuinity.tuinity.util.CachedLists.getTempCollisionList(); ++ try { ++ // We take a fat guess that we actually need to do the step height checks. ++ // So we collect all of the AABB's we would ever need into one list, and use that list ++ // for every collision check we want. ++ AxisAlignedBB collisionBox; ++ double stepHeight = (double)this.getStepHeight(); ++ if ((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, false); ++ ++ 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); ++ ++ 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 f(Vec3D vec3d) { + AxisAlignedBB axisalignedbb = this.getBoundingBox(); + VoxelShapeCollision voxelshapecollision = VoxelShapeCollision.a(this); +@@ -885,6 +1070,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke + return vec3d1; + } + ++ public static double getXZSquared(Vec3D vec3d) { return Entity.b(vec3d); } // Tuinity - OBFHELPER + public static double b(Vec3D vec3d) { + return vec3d.x * vec3d.x + vec3d.z * vec3d.z; + } +@@ -1091,6 +1277,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke + + + @Nullable public final AxisAlignedBB getCollisionBox(){return ay();} //Paper - OBFHELPER ++ @Nullable public final AxisAlignedBB getHardCollisionBox() { return this.ay(); } // Tuinity - OBFHELPER + @Nullable public AxisAlignedBB ay() { + return null; + } +@@ -1971,8 +2158,8 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke + } + + public final AxisAlignedBB getHardCollisionBox(Entity entity){ return j(entity);}//Paper - OBFHELPER +- @Nullable +- public AxisAlignedBB j(Entity entity) { ++ @Nullable public AxisAlignedBB getHardCollisionBoxWith(Entity entity) { return this.j(entity); } // Tuinity - OBFHELPER ++ @Nullable public AxisAlignedBB j(Entity entity) { // Tuinity - OBFHELPER + return null; + } + +@@ -3296,12 +3483,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) { +@@ -3358,7 +3549,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/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java +index 7a2140e4b..70c2be22b 100644 +--- a/src/main/java/net/minecraft/server/EntityLiving.java ++++ b/src/main/java/net/minecraft/server/EntityLiving.java +@@ -2835,7 +2835,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.a(this)); ++ // Tuinity start - reduce memory allocation from collideNearby ++ List list = com.tuinity.tuinity.util.CachedLists.getTempGetEntitiesList(); ++ this.world.getEntities(this, this.getBoundingBox(), IEntitySelector.a(this), list); ++ try { ++ // Tuinity end - reduce memory allocation from collideNearby + + if (!list.isEmpty()) { + // Paper - move up +@@ -2864,6 +2868,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/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/EntityTrackerEntry.java +index f75c09d44..bfb931268 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 { + + public final void tick() { this.a(); } // Paper - OBFHELPER + public void a() { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Tracker update"); // Tuinity + List list = this.tracker.getPassengers(); + + if (!list.equals(this.p)) { +diff --git a/src/main/java/net/minecraft/server/HeightMap.java b/src/main/java/net/minecraft/server/HeightMap.java +index 068b92c5c..476da43b9 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/IBlockData.java b/src/main/java/net/minecraft/server/IBlockData.java +index 10a5901db..911750476 100644 +--- a/src/main/java/net/minecraft/server/IBlockData.java ++++ b/src/main/java/net/minecraft/server/IBlockData.java +@@ -8,6 +8,19 @@ public class IBlockData extends BlockBase.BlockData { + + public static final Codec b = a((Codec) IRegistry.BLOCK, Block::getBlockData).stable(); + ++ ++ // Tuinity start - optimise getType calls ++ org.bukkit.Material cachedMaterial; ++ ++ public final org.bukkit.Material getBukkitMaterial() { ++ if (this.cachedMaterial == null) { ++ this.cachedMaterial = org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(this.getBlock()); ++ } ++ ++ return this.cachedMaterial; ++ } ++ // Tuinity end - optimise getType calls ++ + public IBlockData(Block block, ImmutableMap, Comparable> immutablemap, MapCodec mapcodec) { + super(block, immutablemap, mapcodec); + } +diff --git a/src/main/java/net/minecraft/server/IChunkLoader.java b/src/main/java/net/minecraft/server/IChunkLoader.java +index 582a5695b..5601088cd 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 1cc40b1f0..3ce2f7497 100644 +--- a/src/main/java/net/minecraft/server/ICollisionAccess.java ++++ b/src/main/java/net/minecraft/server/ICollisionAccess.java +@@ -46,6 +46,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 267a6baae..0edcb775e 100644 +--- a/src/main/java/net/minecraft/server/IEntityAccess.java ++++ b/src/main/java/net/minecraft/server/IEntityAccess.java +@@ -69,6 +69,7 @@ public interface IEntityAccess { + AxisAlignedBB axisalignedbb1 = axisalignedbb.g(1.0E-7D); + + // Paper start ++ if (predicate == null) predicate = (e) -> true; // Tuinity - allow nullable + Predicate effectivePredicate = predicate.and((entity1) -> { + return entity == null || !entity.isSameVehicle(entity1); + }); +diff --git a/src/main/java/net/minecraft/server/LightEngineStorage.java b/src/main/java/net/minecraft/server/LightEngineStorage.java +index b98e60772..e0bbfe142 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/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index e9cedbc8b..a29d54c77 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -48,6 +48,20 @@ public final class MCUtil { + new ThreadFactoryBuilder().setNameFormat("Paper Object Cleaner").build() + ); + ++ // Tuinity start ++ private static org.bukkit.entity.HumanEntity[] EMPTY_HUMAN_ARRAY = new org.bukkit.entity.HumanEntity[0]; ++ public static void closeInventory(IInventory inventory, org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ List viewers = inventory.getViewers(); ++ if (viewers.isEmpty()) { ++ return; ++ } ++ ++ for (org.bukkit.entity.HumanEntity viewer : viewers.toArray(EMPTY_HUMAN_ARRAY)) { ++ viewer.closeInventory(reason); ++ } ++ } ++ // Tuinity end ++ + public static final long INVALID_CHUNK_KEY = getCoordinateKey(Integer.MAX_VALUE, Integer.MAX_VALUE); + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 26f230a80..eb71fa6e3 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -986,7 +986,7 @@ 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); +@@ -1092,22 +1162,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(); +@@ -1260,6 +1316,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/NetworkManager.java b/src/main/java/net/minecraft/server/NetworkManager.java +index bd33f85cf..fa208a195 100644 +--- a/src/main/java/net/minecraft/server/NetworkManager.java ++++ b/src/main/java/net/minecraft/server/NetworkManager.java +@@ -71,6 +71,39 @@ 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 ++ + public NetworkManager(EnumProtocolDirection enumprotocoldirection) { + this.h = enumprotocoldirection; + } +@@ -217,7 +250,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 +@@ -243,6 +276,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(); + +@@ -265,7 +306,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); +@@ -297,7 +338,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + } + try { + // Paper end +- ChannelFuture channelfuture1 = this.channel.writeAndFlush(packet); ++ ChannelFuture channelfuture1 = (flush) ? this.channel.writeAndFlush(packet) : this.channel.write(packet); // Tuinity - add flush parameter + + + if (genericfuturelistener != null) { +@@ -340,6 +381,8 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + } + private boolean processQueue() { + 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(); +@@ -347,16 +390,22 @@ 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; +diff --git a/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java +index 8335d0033..e0ee52409 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 BiomeStorage 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; + private boolean i; + +@@ -32,14 +32,16 @@ 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() { + return extraPackets; + } + // Paper end +- public PacketPlayOutMapChunk(Chunk chunk, int i, boolean flag) { ++ public PacketPlayOutMapChunk(Chunk chunk, int i, boolean flag) { final int chunkSectionBitSet = i; // Tuinity - handle oversized chunk data packets more robustly + ChunkPacketInfo chunkPacketInfo = chunk.world.chunkPacketBlockController.getChunkPacketInfo(this, chunk, i); // Paper - Anti-Xray - Add chunk packet info + ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); + +@@ -48,29 +50,10 @@ public class PacketPlayOutMapChunk implements Packet { + this.h = i == 65535; + this.i = flag; + 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().b(); +- } +- +- 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.k()), chunk, i, chunkPacketInfo); +- // Paper end + this.g = Lists.newArrayList(); ++ // Tuinity start - moved code up (moved declaration of Iterator + Entry up) ++ Iterator iterator; ++ Entry entry; + iterator = chunk.getTileEntities().entrySet().iterator(); + int totalTileEntities = 0; // Paper + +@@ -82,7 +65,15 @@ public class PacketPlayOutMapChunk implements Packet { + + if (this.f() || (i & 1 << j) != 0) { + // Paper start - improve oversized chunk data packet handling +- if (++totalTileEntities > TE_LIMIT) { ++ // Tuinity start - improve oversized chunk data packet handling ++ ++totalTileEntities; ++ if (totalTileEntities > TE_SPLIT_LIMIT) { ++ this.mustSplit = true; ++ this.getTileEntityData().clear(); ++ this.extraPackets.clear(); ++ break; ++ } ++ if (totalTileEntities > TE_LIMIT) { // Tuinity end + PacketPlayOutTileEntityData updatePacket = tileentity.getUpdatePacket(); + if (updatePacket != null) { + this.extraPackets.add(updatePacket); +@@ -96,7 +87,69 @@ public class PacketPlayOutMapChunk implements Packet { + this.g.add(nbttagcompound); + } + } ++ iterator = chunk.f().iterator(); // Tuinity - moved declaration of Iterator and Entry up ++ // Tuinity - moved this all up ++ ++ 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().b(); ++ } ++ ++ 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.k()), chunk, i, chunkPacketInfo); ++ // Paper end ++ // Tuinity start - move this all up ++// this.g = Lists.newArrayList(); ++// iterator = chunk.getTileEntities().entrySet().iterator(); ++// int totalTileEntities = 0; // Paper ++// ++// while (iterator.hasNext()) { ++// entry = (Entry) iterator.next(); ++// BlockPosition blockposition = (BlockPosition) entry.getKey(); ++// TileEntity tileentity = (TileEntity) entry.getValue(); ++// int j = blockposition.getY() >> 4; ++// ++// if (this.f() || (i & 1 << j) != 0) { ++// // Paper start - improve oversized chunk data packet handling ++// if (++totalTileEntities > TE_LIMIT) { ++// PacketPlayOutTileEntityData updatePacket = tileentity.getUpdatePacket(); ++// if (updatePacket != null) { ++// this.extraPackets.add(updatePacket); ++// continue; ++// } ++// } ++// // Paper end ++// NBTTagCompound nbttagcompound = tileentity.b(); ++// if (tileentity instanceof TileEntitySkull) { TileEntitySkull.sanitizeTileEntityUUID(nbttagcompound); } // Paper ++// ++// this.g.add(nbttagcompound); ++// } ++// } ++ // Tuinity end - move this all up + 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, false)); ++ } ++ } ++ } // Tuinity end - improve oversized chunk data packet handling + } + + // Paper start - Async-Anti-Xray - Getter and Setter for the ready flag +@@ -189,7 +242,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 + } +@@ -206,7 +259,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/PathfinderNormal.java b/src/main/java/net/minecraft/server/PathfinderNormal.java +index d7f0df123..ec55785af 100644 +--- a/src/main/java/net/minecraft/server/PathfinderNormal.java ++++ b/src/main/java/net/minecraft/server/PathfinderNormal.java +@@ -538,7 +538,7 @@ public class PathfinderNormal extends PathfinderAbstract { + if (!iblockdata.a(iblockaccess, blockposition, PathMode.LAND)) { + return PathType.BLOCKED; + } else { +- Fluid fluid = iblockaccess.getFluid(blockposition); ++ Fluid fluid = iblockdata.getFluid(); // Tuinity - remove another getType call + + return fluid.a((Tag) TagsFluid.WATER) ? PathType.WATER : (fluid.a((Tag) TagsFluid.LAVA) ? PathType.LAVA : PathType.OPEN); + } +diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java +index a3bce8f13..a483ec0e2 100644 +--- a/src/main/java/net/minecraft/server/PlayerChunk.java ++++ b/src/main/java/net/minecraft/server/PlayerChunk.java +@@ -494,6 +494,7 @@ public class PlayerChunk { + // Paper end - per player view distance + } + ++ public final CompletableFuture> getOrCreateFuture(ChunkStatus chunkstatus, PlayerChunkMap playerchunkmap) { return this.a(chunkstatus, playerchunkmap); } // Tuinity - OBFHELPER + public CompletableFuture> a(ChunkStatus chunkstatus, PlayerChunkMap playerchunkmap) { + int i = chunkstatus.c(); + CompletableFuture> completablefuture = (CompletableFuture) this.statusFutures.get(i); +@@ -549,6 +550,7 @@ public class PlayerChunk { + } + + protected void a(PlayerChunkMap playerchunkmap) { ++ com.tuinity.tuinity.util.TickThread.ensureTickThread("Async ticket level update"); // Tuinity + ChunkStatus chunkstatus = getChunkStatus(this.oldTicketLevel); + ChunkStatus chunkstatus1 = getChunkStatus(this.ticketLevel); + boolean flag = this.oldTicketLevel <= PlayerChunkMap.GOLDEN_TICKET; +@@ -558,7 +560,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)) { +- this.getStatusFutureUncheckedMain(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main ++ this.getStatusFutureUnchecked(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main // Tuinity - is always on main ++ com.tuinity.tuinity.util.TickThread.ensureTickThread("Async full status chunk future completion"); // Tuinity + Chunk chunk = (Chunk)either.left().orElse(null); + if (chunk != null) { + playerchunkmap.callbackExecutor.execute(() -> { +@@ -623,7 +626,8 @@ public class PlayerChunk { + if (!flag2 && flag3) { + // Paper start - cache ticking ready status + int expectCreateCount = ++this.fullChunkCreateCount; +- this.fullChunkFuture = playerchunkmap.b(this); ensureMain(this.fullChunkFuture).thenAccept((either) -> { // Paper - ensure main ++ this.fullChunkFuture = playerchunkmap.b(this); this.fullChunkFuture.thenAccept((either) -> { // Paper - ensure main // Tuinity - always fired on main ++ com.tuinity.tuinity.util.TickThread.ensureTickThread("Async full chunk future completion"); // Tuinity + 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(); +@@ -654,7 +658,8 @@ public class PlayerChunk { + + if (!flag4 && flag5) { + // Paper start - cache ticking ready status +- this.tickingFuture = playerchunkmap.a(this); ensureMain(this.tickingFuture).thenAccept((either) -> { // Paper - ensure main ++ this.tickingFuture = playerchunkmap.a(this); this.tickingFuture.thenAccept((either) -> { // Paper - ensure main // Tuinity - always completed on main ++ com.tuinity.tuinity.util.TickThread.ensureTickThread("Async ticking chunk future completion"); // Tuinity + if (either.left().isPresent()) { + // note: Here is a very good place to add callbacks to logic waiting on this. + Chunk tickingChunk = either.left().get(); +@@ -685,12 +690,20 @@ public class PlayerChunk { + } + + // Paper start - cache ticking ready status +- this.entityTickingFuture = playerchunkmap.b(this.location); ensureMain(this.entityTickingFuture).thenAccept((either) -> { // Paper ensureMain ++ this.entityTickingFuture = playerchunkmap.b(this.location); this.entityTickingFuture.thenAccept((either) -> { // Paper ensureMain // Tuinity - always completed on main ++ com.tuinity.tuinity.util.TickThread.ensureTickThread("Async entity ticking chunk future completion"); // Tuinity + if (either.left().isPresent()) { + // note: Here is a very good place to add callbacks to logic waiting on this. + Chunk entityTickingChunk = either.left().get(); + PlayerChunk.this.isEntityTickingReady = true; +- ++ // Tuinity start - optimise chunk tick iteration ++ ChunkProviderServer chunkProvider = PlayerChunk.this.chunkMap.world.getChunkProvider(); ++ if (chunkProvider.isTickingChunks) { ++ chunkProvider.pendingEntityTickingChunkChanges.put(entityTickingChunk, true); ++ } else { ++ chunkProvider.entityTickingChunks.add(entityTickingChunk); ++ } ++ // Tuinity end - optimise chunk tick iteration + + + +@@ -702,6 +715,17 @@ public class PlayerChunk { + + if (flag6 && !flag7) { + this.entityTickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); this.isEntityTickingReady = false; // Paper - cache chunk ticking stage ++ // Tuinity start - optimise chunk tick iteration ++ ChunkProviderServer chunkProvider = PlayerChunk.this.chunkMap.world.getChunkProvider(); ++ Chunk chunk = this.getFullChunkIfCached(); ++ if (chunk != null) { ++ if (chunkProvider.isTickingChunks) { ++ chunkProvider.pendingEntityTickingChunkChanges.put(chunk, false); ++ } else { ++ chunkProvider.entityTickingChunks.remove(chunk); ++ } ++ } ++ // Tuinity end - optimise chunk tick iteration + this.entityTickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; + } + +@@ -728,7 +752,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)) { +- this.getStatusFutureUncheckedMain(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main ++ this.getStatusFutureUnchecked(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main // Tuinity - is always on main ++ com.tuinity.tuinity.util.TickThread.ensureTickThread("Async full status chunk future completion"); // Tuinity + 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 8c5639fa5..4dd6f48ca 100644 +--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java +@@ -119,31 +119,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 { +- +- // Paper start - replace impl with recursive safe multi entry queue +- // it's possible to schedule multiple tasks currently, so it's vital we change this impl +- // If we recurse into the executor again, we will append to another queue, ensuring task order consistency +- private java.util.ArrayDeque queued = new java.util.ArrayDeque<>(); ++ // Tuinity start - revert paper's change ++ private Runnable queued; + + @Override + public void execute(Runnable runnable) { + AsyncCatcher.catchOp("Callback Executor execute"); +- if (queued == null) { +- queued = new java.util.ArrayDeque<>(); ++ if (queued != null) { ++ MinecraftServer.LOGGER.fatal("Failed to schedule runnable", new IllegalStateException("Already queued")); // Paper - make sure this is printed ++ throw new IllegalStateException("Already queued"); + } +- queued.add(runnable); ++ queued = runnable; + } ++ // Tuinity end - revert paper's change + + @Override + public void run() { + AsyncCatcher.catchOp("Callback Executor run"); +- if (queued == null) { +- return; +- } +- java.util.ArrayDeque queue = queued; ++ // Tuinity start - revert paper's change ++ Runnable task = queued; + queued = null; +- Runnable task; +- while ((task = queue.pollFirst()) != null) { ++ if (task != null) { ++ // Tuinity end - revert paper's change + task.run(); + } + } +@@ -198,6 +195,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + // Paper end - no-tick view distance + + void addPlayerToDistanceMaps(EntityPlayer player) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Cannot update distance maps off of the main thread"); // Tuinity + 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 +@@ -228,6 +226,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + + void removePlayerFromDistanceMaps(EntityPlayer player) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Cannot update distance maps off of the main thread"); // Tuinity + // 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); +@@ -245,6 +244,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + + void updateMaps(EntityPlayer player) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Cannot update distance maps off of the main thread"); // Tuinity + 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 +@@ -746,6 +746,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + @Nullable + private PlayerChunk a(long i, int j, @Nullable PlayerChunk playerchunk, int k) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Chunk holder update"); // Tuinity + if (k > PlayerChunkMap.GOLDEN_TICKET && j > PlayerChunkMap.GOLDEN_TICKET) { + return playerchunk; + } else { +@@ -959,7 +960,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + + com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, chunkPos.x, chunkPos.z, +- poiData, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY); ++ poiData, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY); // Tuinity - use normal priority + + if (!chunk.isNeedsSaving()) { + return; +@@ -993,7 +994,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + asyncSaveData = ChunkRegionLoader.getAsyncSaveData(this.world, chunk); + } + +- this.world.asyncChunkTaskManager.scheduleChunkSave(chunkPos.x, chunkPos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY, ++ this.world.asyncChunkTaskManager.scheduleChunkSave(chunkPos.x, chunkPos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY, // Tuinity - use normal priority + asyncSaveData, chunk); + + chunk.setLastSaved(this.world.getTime()); +@@ -1048,6 +1049,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + + protected boolean b() { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Cannot update visibleChunks off of the main thread"); // Tuinity + if (!this.updatingChunksModified) { + return false; + } else { +@@ -1233,7 +1235,10 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + // Paper end + this.mailboxWorldGen.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); +- }); ++ }).thenComposeAsync((either) -> { // Tuinity start - force competion on the main thread ++ return CompletableFuture.completedFuture(either); ++ }, this.mainInvokingExecutor); ++ // Tuinity end - force competion on the main thread + } + + protected void c(ChunkCoordIntPair chunkcoordintpair) { +@@ -1485,6 +1490,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + + public void setViewDistance(int i) { // Paper - public ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Cannot update view distance off of the main thread"); // Tuinity + int j = MathHelper.clamp(i + 1, 3, 33); // Paper - diff on change, these make the lower view distance limit 2 and the upper 32 + + if (j != this.viewDistance) { +@@ -1498,6 +1504,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + // Paper start - no-tick view distance + public final void setNoTickViewDistance(int viewDistance) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Cannot update view distance off of the main thread"); // Tuinity + viewDistance = viewDistance == -1 ? -1 : MathHelper.clamp(viewDistance, 2, 32); + + this.noTickViewDistance = viewDistance; +@@ -2024,23 +2031,20 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + private final void processTrackQueue() { + this.world.timings.tracker1.startTiming(); + try { +- for (EntityTracker tracker : this.trackedEntities.values()) { +- // update tracker entry +- tracker.updatePlayers(tracker.tracker.getPlayersInTrackRange()); ++ for (Chunk chunk : this.world.getChunkProvider().entityTickingChunks) { ++ Entity[] entities = chunk.entities.getRawData(); ++ for (int i = 0, len = chunk.entities.size(); i < len; ++i) { ++ Entity entity = entities[i]; ++ EntityTracker tracker = this.trackedEntities.get(entity.getId()); ++ if (tracker != null) { ++ tracker.updatePlayers(tracker.tracker.getPlayersInTrackRange()); ++ tracker.trackerEntry.tick(); ++ } ++ } + } + } finally { + this.world.timings.tracker1.stopTiming(); + } +- +- +- this.world.timings.tracker2.startTiming(); +- try { +- for (EntityTracker tracker : this.trackedEntities.values()) { +- tracker.trackerEntry.tick(); +- } +- } finally { +- this.world.timings.tracker2.stopTiming(); +- } + } + // Paper end - optimised tracker + +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index cf83059fe..c40255263 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -322,19 +322,24 @@ public class PlayerConnection implements PacketListenerPlayIn { + + if (entity != this.player && entity.getRidingPassenger() == this.player && entity == this.r) { + WorldServer worldserver = this.player.getWorldServer(); +- double d0 = entity.locX(); +- double d1 = entity.locY(); +- double d2 = entity.locZ(); +- double d3 = packetplayinvehiclemove.getX(); +- double d4 = packetplayinvehiclemove.getY(); +- double d5 = packetplayinvehiclemove.getZ(); ++ double d0 = entity.locX();double fromX = d0; // Tuinity - OBFHELPER ++ double d1 = entity.locY();double fromY = d1; // Tuinity - OBFHELPER ++ double d2 = entity.locZ();double fromZ = d2; // Tuinity - OBFHELPER ++ double d3 = packetplayinvehiclemove.getX();double toX = d3; // Tuinity - OBFHELPER ++ double d4 = packetplayinvehiclemove.getY();double toY = d4; // Tuinity - OBFHELPER ++ double d5 = packetplayinvehiclemove.getZ();double toZ = d5; // Tuinity - OBFHELPER + float f = packetplayinvehiclemove.getYaw(); + float f1 = packetplayinvehiclemove.getPitch(); + double d6 = d3 - this.s; + double d7 = d4 - this.t; + double d8 = d5 - this.u; + double d9 = entity.getMot().g(); +- double d10 = d6 * d6 + d7 * d7 + d8 * d8; ++ // Tuinity start - fix large move vectors killing the server ++ double currDeltaX = toX - fromX; ++ double currDeltaY = toY - fromY; ++ double currDeltaZ = toZ - fromZ; ++ double d10 = Math.max(d6 * d6 + d7 * d7 + d8 * d8, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1); ++ // Tuinity end - fix large move vectors killing the server + + + // CraftBukkit start - handle custom speeds and skipped ticks +@@ -363,7 +368,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; + } +@@ -1000,7 +1007,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + double d2 = this.player.locZ(); + double d3 = this.player.locY(); + double d4 = packetplayinflying.a(this.player.locX());double toX = d4; // Paper - OBFHELPER +- double d5 = packetplayinflying.b(this.player.locY()); ++ double d5 = packetplayinflying.b(this.player.locY());double toY = d5; // Tuinity - OBFHELPER + double d6 = packetplayinflying.c(this.player.locZ());double toZ = d6; // Paper - OBFHELPER + float f = packetplayinflying.a(this.player.yaw); + float f1 = packetplayinflying.b(this.player.pitch); +@@ -1008,7 +1015,12 @@ public class PlayerConnection implements PacketListenerPlayIn { + double d8 = d5 - this.m; + double d9 = d6 - this.n; + double d10 = this.player.getMot().g(); +- double d11 = d7 * d7 + d8 * d8 + d9 * d9; ++ // Tuinity start - fix large move vectors killing the server ++ double currDeltaX = toX - prevX; ++ double currDeltaY = toY - prevY; ++ double currDeltaZ = toZ - prevZ; ++ double d11 = Math.max(d7 * d7 + d8 * d8 + d9 * d9, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1); ++ // Tuinity end - fix large move vectors killing the server + + if (this.player.isSleeping()) { + if (d11 > 1.0D) { +@@ -1041,7 +1053,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; + } +diff --git a/src/main/java/net/minecraft/server/PlayerConnectionUtils.java b/src/main/java/net/minecraft/server/PlayerConnectionUtils.java +index eb3269e0e..d9c9d01ae 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 ++ private static final java.util.concurrent.ConcurrentLinkedDeque packetProcessing = new java.util.concurrent.ConcurrentLinkedDeque<>(); ++ private 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 +@@ -25,6 +45,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 6d192b274..f5de49e3e 100644 +--- a/src/main/java/net/minecraft/server/PlayerInteractManager.java ++++ b/src/main/java/net/minecraft/server/PlayerInteractManager.java +@@ -21,14 +21,29 @@ public class PlayerInteractManager { + private EnumGamemode gamemode; + private EnumGamemode e; + private boolean f; +- private int lastDigTick; ++ private int lastDigTick; private long lastDigTime; // Tuinity - lag compensate block breaking + private BlockPosition h; + private int currentTick; +- private boolean j; ++ private boolean j; private final boolean hasDestroyedTooFast() { return this.j; } // Tuinity - OBFHELPER + private BlockPosition k; +- private int l; ++ private int l; private final int getHasDestroyedTooFastStartTick() { return this.l; } // Tuinity - OBFHELPER ++ private long hasDestroyedTooFastStartTime; // Tuinity - lag compensate block breaking + private int m; + ++ // Tuinity start - lag compensate block breaking ++ private int getTimeDiggingLagCompensate() { ++ int lagCompensated = (int)((System.nanoTime() - this.lastDigTime) / (50L * 1000L * 1000L)); ++ int tickDiff = this.currentTick - this.lastDigTick; ++ return (com.tuinity.tuinity.config.TuinityConfig.lagCompensateBlockBreaking && lagCompensated > (tickDiff + 1)) ? lagCompensated : tickDiff; // add one to ensure we don't lag compensate unless we need to ++ } ++ ++ private int getTimeDiggingTooFastLagCompensate() { ++ int lagCompensated = (int)((System.nanoTime() - this.hasDestroyedTooFastStartTime) / (50L * 1000L * 1000L)); ++ int tickDiff = this.currentTick - this.getHasDestroyedTooFastStartTick(); ++ return (com.tuinity.tuinity.config.TuinityConfig.lagCompensateBlockBreaking && lagCompensated > (tickDiff + 1)) ? lagCompensated : tickDiff; // add one to ensure we don't lag compensate unless we need to ++ } ++ // Tuinity end ++ + public PlayerInteractManager(WorldServer worldserver) { + this.gamemode = EnumGamemode.NOT_SET; + this.e = EnumGamemode.NOT_SET; +@@ -84,7 +99,7 @@ public class PlayerInteractManager { + if (iblockdata == null || iblockdata.isAir()) { // Paper + this.j = false; + } else { +- float f = this.a(iblockdata, this.k, this.l); ++ float f = this.updateBlockBreakAnimation(iblockdata, this.k, this.getTimeDiggingTooFastLagCompensate()); // Tuinity - lag compensate destroying blocks + + if (f >= 1.0F) { + this.j = false; +@@ -104,7 +119,7 @@ public class PlayerInteractManager { + this.m = -1; + this.f = false; + } else { +- this.a(iblockdata, this.h, this.lastDigTick); ++ this.updateBlockBreakAnimation(iblockdata, this.h, this.getTimeDiggingLagCompensate()); // Tuinity - lag compensate destroying blocks + } + } + +@@ -112,6 +127,12 @@ public class PlayerInteractManager { + + private float a(IBlockData iblockdata, BlockPosition blockposition, int i) { + int j = this.currentTick - i; ++ // Tuinity start - change i (startTime) to totalTime ++ return this.updateBlockBreakAnimation(iblockdata, blockposition, j); ++ } ++ private float updateBlockBreakAnimation(IBlockData iblockdata, BlockPosition blockposition, int totalTime) { ++ int j = totalTime; ++ // Tuinity end + float f = iblockdata.getDamage(this.player, this.player.world, blockposition) * (float) (j + 1); + int k = (int) (f * 10.0F); + +@@ -179,7 +200,7 @@ public class PlayerInteractManager { + return; + } + +- this.lastDigTick = this.currentTick; ++ this.lastDigTick = this.currentTick; this.lastDigTime = System.nanoTime(); // Tuinity - lag compensate block breaking + float f = 1.0F; + + iblockdata = this.world.getType(blockposition); +@@ -232,12 +253,12 @@ public class PlayerInteractManager { + int j = (int) (f * 10.0F); + + this.world.a(this.player.getId(), blockposition, j); +- this.player.playerConnection.sendPacket(new PacketPlayOutBlockBreak(blockposition, this.world.getType(blockposition), packetplayinblockdig_enumplayerdigtype, true, "actual start of destroying")); ++ if (!com.tuinity.tuinity.config.TuinityConfig.lagCompensateBlockBreaking) this.player.playerConnection.sendPacket(new PacketPlayOutBlockBreak(blockposition, this.world.getType(blockposition), packetplayinblockdig_enumplayerdigtype, true, "actual start of destroying")); // Tuinity - on lagging servers this can cause the client to think it's only just started to destroy a block when it already has/will + this.m = j; + } + } else if (packetplayinblockdig_enumplayerdigtype == PacketPlayInBlockDig.EnumPlayerDigType.STOP_DESTROY_BLOCK) { + if (blockposition.equals(this.h)) { +- int k = this.currentTick - this.lastDigTick; ++ int k = this.getTimeDiggingLagCompensate(); // Tuinity - lag compensate block breaking + + iblockdata = this.world.getType(blockposition); + if (!iblockdata.isAir()) { +@@ -254,12 +275,18 @@ public class PlayerInteractManager { + this.f = false; + this.j = true; + this.k = blockposition; +- this.l = this.lastDigTick; ++ this.l = this.lastDigTick; this.hasDestroyedTooFastStartTime = this.lastDigTime; // Tuinity - lag compensate block breaking + } + } + } + ++ // Tuinity start - this can cause clients on a lagging server to think they're not currently destroying a block ++ if (com.tuinity.tuinity.config.TuinityConfig.lagCompensateBlockBreaking) { ++ this.player.playerConnection.sendPacket(new PacketPlayOutBlockChange(this.world, blockposition)); ++ } else { + this.player.playerConnection.sendPacket(new PacketPlayOutBlockBreak(blockposition, this.world.getType(blockposition), packetplayinblockdig_enumplayerdigtype, true, "stopped destroying")); ++ } ++ // Tuinity end - this can cause clients on a lagging server to think they're not currently destroying a block + } else if (packetplayinblockdig_enumplayerdigtype == PacketPlayInBlockDig.EnumPlayerDigType.ABORT_DESTROY_BLOCK) { + this.f = false; + if (!Objects.equals(this.h, blockposition) && !BlockPosition.ZERO.equals(this.h)) { +@@ -271,7 +298,7 @@ public class PlayerInteractManager { + } + + this.world.a(this.player.getId(), blockposition, -1); +- this.player.playerConnection.sendPacket(new PacketPlayOutBlockBreak(blockposition, this.world.getType(blockposition), packetplayinblockdig_enumplayerdigtype, true, "aborted destroying")); ++ if (!com.tuinity.tuinity.config.TuinityConfig.lagCompensateBlockBreaking) this.player.playerConnection.sendPacket(new PacketPlayOutBlockBreak(blockposition, this.world.getType(blockposition), packetplayinblockdig_enumplayerdigtype, true, "aborted destroying")); // Tuinity - this can cause clients on a lagging server to think they stopped destroying a block they're currently destroying + } + + } +@@ -281,7 +308,13 @@ public class PlayerInteractManager { + + public void a(BlockPosition blockposition, PacketPlayInBlockDig.EnumPlayerDigType packetplayinblockdig_enumplayerdigtype, String s) { + if (this.breakBlock(blockposition)) { ++ // Tuinity start - this can cause clients on a lagging server to think they're not currently destroying a block ++ if (com.tuinity.tuinity.config.TuinityConfig.lagCompensateBlockBreaking) { ++ this.player.playerConnection.sendPacket(new PacketPlayOutBlockChange(this.world, blockposition)); ++ } else { + this.player.playerConnection.sendPacket(new PacketPlayOutBlockBreak(blockposition, this.world.getType(blockposition), packetplayinblockdig_enumplayerdigtype, true, s)); ++ } ++ // Tuinity end - this can cause clients on a lagging server to think they're not currently destroying a block + } else { + this.player.playerConnection.sendPacket(new PacketPlayOutBlockChange(this.world, blockposition)); // CraftBukkit - SPIGOT-5196 + } +diff --git a/src/main/java/net/minecraft/server/ProtoChunk.java b/src/main/java/net/minecraft/server/ProtoChunk.java +index 3b03c28ee..6ac9f437e 100644 +--- a/src/main/java/net/minecraft/server/ProtoChunk.java ++++ b/src/main/java/net/minecraft/server/ProtoChunk.java +@@ -179,14 +179,11 @@ public class ProtoChunk implements IChunkAccess { + 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(); ++ // Tuinity - reduce iterator creation + +- HeightMap.Type heightmap_type; +- +- 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 +199,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/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java +index 93797395c..6928b1730 100644 +--- a/src/main/java/net/minecraft/server/RegionFile.java ++++ b/src/main/java/net/minecraft/server/RegionFile.java +@@ -28,14 +28,349 @@ public class RegionFile implements AutoCloseable { + private static final Logger LOGGER = LogManager.getLogger(); + private static final ByteBuffer b = ByteBuffer.allocateDirect(1); + private final FileChannel dataFile; +- private final java.nio.file.Path d; +- private final RegionFileCompression e; ++ private final java.nio.file.Path d; private final java.nio.file.Path getContainingDataFolder() { return this.d; } // Tuinity - OBFHELPER ++ private final RegionFileCompression e; private final RegionFileCompression getRegionFileCompression() { return this.e; } // Tuinity - OBFHELPER + private final ByteBuffer f; +- private final IntBuffer g; +- private final IntBuffer h; ++ private final IntBuffer g; private final IntBuffer getOffsets() { return this.g; } // Tuinity - OBFHELPER ++ private final IntBuffer h; private final IntBuffer getTimestamps() { return this.h; } // Tuinity - OBFHELPER + private final RegionFileBitSet freeSectors; + public final File file; + ++ // 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(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(), 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(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 +@@ -63,10 +398,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(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.canRecalcHeader = canRecalcHeader; ++ // Tuinity end - add can recalc flag + this.file = java_nio_file_path.toFile(); // Paper + this.f = ByteBuffer.allocateDirect(8192); + initOversizedState(); +@@ -95,12 +441,15 @@ public class RegionFile implements AutoCloseable { + RegionFile.LOGGER.warn("Region file {} has truncated header: {}", java_nio_file_path, i); + } + +- for (int j = 0; j < 1024; ++j) { ++ boolean needsHeaderRecalc = false; // Tuinity - recalculate header on header corruption ++ boolean hasBackedUp = false; // Tuinity - recalculate header on header corruption ++ ++ for (int j = 0; j < 1024; ++j) { // Tuinity - diff on change, we expect j to be the header location + int k = this.g.get(j); + + if (k != 0) { +- int l = b(k); +- int i1 = a(k); ++ int l = b(k); // Tuinity - diff on change, we expect l to be offset in file ++ int i1 = a(k); // Tuinity - diff on change, we expect i1 to be sector length of region + // Spigot start + if (i1 == 255) { + // We're maxed out, so we need to read the proper length from the section +@@ -110,20 +459,87 @@ public class RegionFile implements AutoCloseable { + } + // Spigot end + +- this.freeSectors.a(l, i1); ++ // Tuinity start - recalculate header on header corruption ++ if (l < 0 || i1 < 0 || (l + i1) < 0) { ++ 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 (" + (j & 31) + "," + (j >>> 5) + ") from header"); ++ if (!hasBackedUp) { ++ hasBackedUp = true; ++ this.backupRegionFile(); ++ } ++ this.getTimestamps().put(j, 0); // be consistent, delete the timestamp too ++ this.getOffsets().put(j, 0); // delete the entry from header ++ continue; ++ } ++ } ++ boolean failedToAllocate = !this.freeSectors.tryAllocate(l, i1); ++ if (failedToAllocate && !canRecalcHeader) { ++ // location = chunkX | (chunkZ << 5); ++ MinecraftServer.LOGGER.fatal("Detected invalid header for regionfile " + this.file.getAbsolutePath() + ++ "! Cannot recalculate, removing local chunk (" + (j & 31) + "," + (j >>> 5) + ") from header"); ++ if (!hasBackedUp) { ++ hasBackedUp = true; ++ this.backupRegionFile(); ++ } ++ this.getTimestamps().put(j, 0); // be consistent, delete the timestamp too ++ this.getOffsets().put(j, 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 ++ MinecraftServer.LOGGER.error("Recalculating regionfile " + this.file.getAbsolutePath() + ", header gave conflicting 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.d.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 { +@@ -147,6 +563,12 @@ public class RegionFile implements AutoCloseable { + this.dataFile.read(bytebuffer, (long) (j * 4096)); + ((java.nio.Buffer) bytebuffer).flip(); + if (bytebuffer.remaining() < 5) { ++ // Tuinity start - recalculate header on regionfile corruption ++ if (this.canRecalcHeader) { ++ this.recalculateHeader(); ++ return this.getReadStream(chunkcoordintpair); ++ } ++ // Tuinity end + RegionFile.LOGGER.error("Chunk {} header is truncated: expected {} but read {}", chunkcoordintpair, l, bytebuffer.remaining()); + return null; + } else { +@@ -155,6 +577,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 + return null; + } else { + int j1 = i1 - 1; +@@ -167,9 +595,21 @@ public class RegionFile implements AutoCloseable { + return this.a(chunkcoordintpair, b(b0)); + } 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 + return null; + } else { + return this.a(chunkcoordintpair, b0, a(bytebuffer, j1)); +@@ -332,10 +772,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.e.a() | 128)); ++ bytebuffer.put((byte) (compressionType.a() | 128)); // Tuinity - replace with compressionType + ((java.nio.Buffer) bytebuffer).flip(); + return bytebuffer; + } +@@ -372,6 +817,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.f).position(0); + this.dataFile.write(this.f, 0L); +diff --git a/src/main/java/net/minecraft/server/RegionFileBitSet.java b/src/main/java/net/minecraft/server/RegionFileBitSet.java +index 1ebdf73cc..cfa3ecb03 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 867dc074b..60b4171a3 100644 +--- a/src/main/java/net/minecraft/server/RegionFileCache.java ++++ b/src/main/java/net/minecraft/server/RegionFileCache.java +@@ -14,12 +14,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 +@@ -53,9 +84,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 +@@ -144,6 +175,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 +@@ -159,6 +197,16 @@ public class RegionFileCache implements AutoCloseable { // Paper - no final + try { + if (datainputstream != null) { + nbttagcompound = NBTCompressedStreamTools.a(datainputstream); ++ // Tuinity start - recover from corrupt regionfile header ++ if (this.isChunkData) { ++ ChunkCoordIntPair chunkPos = ChunkRegionLoader.getChunkCoordinate(nbttagcompound); ++ if (!chunkPos.equals(chunkcoordintpair)) { ++ regionfile.recalculateHeader(); ++ regionfile.fileLock.lock(); // otherwise we will unlock twice and only lock once. ++ return this.readFromRegionFile(regionfile, chunkcoordintpair); ++ } ++ } ++ // Tuinity end + return nbttagcompound; + } + +diff --git a/src/main/java/net/minecraft/server/RegionFileCompression.java b/src/main/java/net/minecraft/server/RegionFileCompression.java +index 3382d678e..29137f495 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); + } + +@@ -53,6 +53,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/Ticket.java b/src/main/java/net/minecraft/server/Ticket.java +index e41cb8613..c19ffb925 100644 +--- a/src/main/java/net/minecraft/server/Ticket.java ++++ b/src/main/java/net/minecraft/server/Ticket.java +@@ -5,17 +5,17 @@ import java.util.Objects; + public final class Ticket implements Comparable> { + + private final TicketType a; +- private final int b; ++ private int b; public final void setTicketLevel(final int value) { this.b = value; } // Tuinity - remove final, add set OBFHELPER + public final T identifier; public final T getObjectReason() { return this.identifier; } // Paper - OBFHELPER +- private long d; public final long getCreationTick() { return this.d; } // Paper - OBFHELPER ++ private long d; public final long getCreationTick() { return this.d; } public final void setCreationTick(final long value) { this.d = value; } // Paper - OBFHELPER // Tuinity - OBFHELPER + public int priority = 0; // Paper +- public long delayUnloadBy; // Paper ++ boolean isCached; // Tuinity - delay chunk unloads, this defends against really stupid plugins + + protected Ticket(TicketType tickettype, int i, T t0) { + this.a = tickettype; + this.b = i; + this.identifier = t0; +- this.delayUnloadBy = tickettype.loadPeriod; // Paper ++ // Tuinity - delay chunk unloads + } + + public int compareTo(Ticket ticket) { +@@ -64,8 +64,9 @@ public final class Ticket implements Comparable> { + this.d = i; + } + ++ protected final boolean isExpired(long time) { return this.b(time); } // Tuinity - OBFHELPER + protected boolean b(long i) { +- long j = delayUnloadBy; // Paper ++ long j = this.a.b(); // Tuinity - delay chunk unloads + + 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 5c789b25f..4657b05a4 100644 +--- a/src/main/java/net/minecraft/server/TicketType.java ++++ b/src/main/java/net/minecraft/server/TicketType.java +@@ -26,7 +26,8 @@ public class TicketType { + public static final TicketType ASYNC_LOAD = a("async_load", Long::compareTo); // Paper + public static final TicketType PRIORITY = a("priority", Comparator.comparingLong(ChunkCoordIntPair::pair), 300); // Paper + public static final TicketType URGENT = a("urgent", Comparator.comparingLong(ChunkCoordIntPair::pair), 300); // Paper +- public static final TicketType DELAY_UNLOAD = a("delay_unload", Long::compareTo, 300); // Paper ++ public static final TicketType DELAYED_UNLOAD = a("delayed_unload", Long::compareTo); // Tuinity - delay chunk unloads ++ public static final TicketType REQUIRED_LOAD = a("required_load", Long::compareTo); // Tuinity - make sure getChunkAt does not fail + + public static TicketType a(String s, Comparator comparator) { + return new TicketType<>(s, comparator, 0L); +diff --git a/src/main/java/net/minecraft/server/TileEntity.java b/src/main/java/net/minecraft/server/TileEntity.java +index 67fda8bd5..e1f1d6e33 100644 +--- a/src/main/java/net/minecraft/server/TileEntity.java ++++ b/src/main/java/net/minecraft/server/TileEntity.java +@@ -12,7 +12,7 @@ import org.bukkit.inventory.InventoryHolder; + import co.aikar.timings.MinecraftTimings; // Paper + import co.aikar.timings.Timing; // Paper + +-public abstract class TileEntity implements KeyedObject { // Paper ++public abstract class TileEntity implements KeyedObject, Cloneable { // Paper // Tuinity + + public Timing tickTimer = MinecraftTimings.getTileEntityTimings(this); // Paper + // CraftBukkit start - data containers +@@ -27,7 +27,7 @@ public abstract class TileEntity implements KeyedObject { // Paper + protected BlockPosition position; + protected boolean f; + @Nullable +- private IBlockData c; ++ private IBlockData c; protected final IBlockData getBlockDataCache() { return this.c; } public final void setBlockDataCache(final IBlockData value) { this.c = value; } // Tuinity - OBFHELPER + private boolean g; + + public TileEntity(TileEntityTypes tileentitytypes) { +@@ -35,6 +35,51 @@ public abstract class TileEntity implements KeyedObject { // Paper + this.tileType = tileentitytypes; + } + ++ // Tuinity start - pushable TE's ++ public boolean isPushable() { ++ if (!com.tuinity.tuinity.config.TuinityConfig.pistonsCanPushTileEntities) { ++ return false; ++ } ++ IBlockData block = this.getBlock(); ++ if (this.isRemoved() || !this.tileType.isValidBlock(block.getBlock())) { ++ return false; ++ } ++ EnumPistonReaction reaction = block.getPushReaction(); ++ return reaction == EnumPistonReaction.NORMAL || reaction == EnumPistonReaction.PUSH_ONLY; ++ } ++ ++ @Override ++ protected final TileEntity clone() { ++ try { ++ return (TileEntity)super.clone(); ++ } catch (final Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ throw new InternalError(thr); ++ } ++ } ++ ++ // this method presumes the old TE has been completely dropped from worldstate and has no ties to it anymore (this ++ // includes players interacting with them) ++ public TileEntity createCopyForPush(WorldServer world, BlockPosition oldPos, BlockPosition newPos, IBlockData blockData) { ++ final TileEntity copy = this.clone(); ++ ++ copy.world = world; ++ copy.position = newPos; ++ ++ // removed is manually set to false after placing the entity into the world. ++ copy.setBlockDataCache(blockData); ++ ++ return copy; ++ } ++ ++ // updates TE state to its new position ++ public void onPostPush() { ++ this.update(); ++ } ++ // Tuinity end - pushable TE's ++ + // Paper start + private String tileEntityKeyString = null; + private MinecraftKey tileEntityKey = null; +diff --git a/src/main/java/net/minecraft/server/TileEntityBeacon.java b/src/main/java/net/minecraft/server/TileEntityBeacon.java +index 2858ea1f3..453f1301b 100644 +--- a/src/main/java/net/minecraft/server/TileEntityBeacon.java ++++ b/src/main/java/net/minecraft/server/TileEntityBeacon.java +@@ -35,7 +35,7 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic + @Nullable + public IChatBaseComponent customName; + public ChestLock chestLock; +- private final IContainerProperties containerProperties; ++ private IContainerProperties containerProperties; // Tuinity - need non-final for `createCopyForPush` + // CraftBukkit start - add fields and methods + public PotionEffect getPrimaryEffect() { + return (this.primaryEffect != null) ? CraftPotionUtil.toBukkit(new MobEffect(this.primaryEffect, getLevel(), getAmplification(), true, true)) : null; +@@ -46,10 +46,10 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic + } + // CraftBukkit end + +- public TileEntityBeacon() { +- super(TileEntityTypes.BEACON); +- this.chestLock = ChestLock.a; +- this.containerProperties = new IContainerProperties() { ++ // Tuinity start - pushable TE's ++ protected final IContainerProperties getNewContainerProperties() { ++ // moved from constructor - this should be re-copied if it changes ++ return new IContainerProperties() { + @Override + public int getProperty(int i) { + switch (i) { +@@ -90,6 +90,22 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic + }; + } + ++ @Override ++ public TileEntity createCopyForPush(WorldServer world, BlockPosition oldPos, BlockPosition newPos, IBlockData blockData) { ++ TileEntityBeacon copy = (TileEntityBeacon)super.createCopyForPush(world, oldPos, newPos, blockData); ++ ++ copy.containerProperties = copy.getNewContainerProperties(); // old properties retains reference to old te ++ ++ return copy; ++ } ++ // Tuinity end - pushable TE's ++ ++ public TileEntityBeacon() { ++ super(TileEntityTypes.BEACON); ++ this.chestLock = ChestLock.a; ++ this.containerProperties = this.getNewContainerProperties(); // Tuinity - move into function ++ } ++ + @Override + public void tick() { + int i = this.position.getX(); +diff --git a/src/main/java/net/minecraft/server/TileEntityBeehive.java b/src/main/java/net/minecraft/server/TileEntityBeehive.java +index 66ac41db7..016b06364 100644 +--- a/src/main/java/net/minecraft/server/TileEntityBeehive.java ++++ b/src/main/java/net/minecraft/server/TileEntityBeehive.java +@@ -12,6 +12,13 @@ public class TileEntityBeehive extends TileEntity implements ITickable { + public BlockPosition flowerPos = null; + public int maxBees = 3; // CraftBukkit - allow setting max amount of bees a hive can hold + ++ // Tuinity start - pushable TE's ++ @Override ++ public boolean isPushable() { ++ return false; // TODO until there is a good solution to making the already existing bees in the world re-acquire this position, this cannot be done. ++ } ++ // Tuinity end - pushable TE's ++ + public TileEntityBeehive() { + super(TileEntityTypes.BEEHIVE); + } +diff --git a/src/main/java/net/minecraft/server/TileEntityBrewingStand.java b/src/main/java/net/minecraft/server/TileEntityBrewingStand.java +index 276eba954..e38a494d7 100644 +--- a/src/main/java/net/minecraft/server/TileEntityBrewingStand.java ++++ b/src/main/java/net/minecraft/server/TileEntityBrewingStand.java +@@ -24,7 +24,7 @@ public class TileEntityBrewingStand extends TileEntityContainer implements IWorl + private boolean[] j; + private Item k; + public int fuelLevel; +- protected final IContainerProperties a; ++ protected IContainerProperties a; protected final void setContainerProperties(IContainerProperties value) { this.a = value; } // Tuinity - OBFHELPER // Tuinity - need non-final for `createCopyForPush` + // CraftBukkit start - add fields and methods + private int lastTick = MinecraftServer.currentTick; + public List transaction = new java.util.ArrayList(); +@@ -56,10 +56,10 @@ public class TileEntityBrewingStand extends TileEntityContainer implements IWorl + } + // CraftBukkit end + +- public TileEntityBrewingStand() { +- super(TileEntityTypes.BREWING_STAND); +- this.items = NonNullList.a(5, ItemStack.b); +- this.a = new IContainerProperties() { ++ // Tuinity start - pushable TE's ++ protected final IContainerProperties getNewContainerProperties() { ++ // moved from constructor - this should be re-copied if it changes ++ return new IContainerProperties() { + @Override + public int getProperty(int i) { + switch (i) { +@@ -91,6 +91,22 @@ public class TileEntityBrewingStand extends TileEntityContainer implements IWorl + }; + } + ++ @Override ++ public TileEntity createCopyForPush(WorldServer world, BlockPosition oldPos, BlockPosition newPos, IBlockData blockData) { ++ TileEntityBrewingStand copy = (TileEntityBrewingStand)super.createCopyForPush(world, oldPos, newPos, blockData); ++ ++ copy.setContainerProperties(copy.getNewContainerProperties()); // old properties retains reference to old te ++ ++ return copy; ++ } ++ // Tuinity end - pushable TE's ++ ++ public TileEntityBrewingStand() { ++ super(TileEntityTypes.BREWING_STAND); ++ this.items = NonNullList.a(5, ItemStack.b); ++ this.a = this.getNewContainerProperties(); ++ } ++ + @Override + protected IChatBaseComponent getContainerName() { + return new ChatMessage("container.brewing"); +diff --git a/src/main/java/net/minecraft/server/TileEntityChest.java b/src/main/java/net/minecraft/server/TileEntityChest.java +index f6f274389..f9a878bd0 100644 +--- a/src/main/java/net/minecraft/server/TileEntityChest.java ++++ b/src/main/java/net/minecraft/server/TileEntityChest.java +@@ -45,6 +45,22 @@ public class TileEntityChest extends TileEntityLootable { // Paper - Remove ITic + } + // CraftBukkit end + ++ // Tuinity start ++ @Override ++ public boolean isPushable() { ++ if (!super.isPushable()) { ++ return false; ++ } ++ // what should happen when a double chest is moved is generally just a mess to deal with in the current ++ // codebase. ++ IBlockData type = this.getBlock(); ++ if (type.getBlock() == Blocks.CHEST || type.getBlock() == Blocks.TRAPPED_CHEST) { ++ return type.get(BlockChest.getChestTypeEnum()) == BlockPropertyChestType.SINGLE; ++ } ++ return false; ++ } ++ // Tuinity end ++ + protected TileEntityChest(TileEntityTypes tileentitytypes) { + super(tileentitytypes); + this.items = NonNullList.a(27, ItemStack.b); +diff --git a/src/main/java/net/minecraft/server/TileEntityConduit.java b/src/main/java/net/minecraft/server/TileEntityConduit.java +index ade830122..7e9470caa 100644 +--- a/src/main/java/net/minecraft/server/TileEntityConduit.java ++++ b/src/main/java/net/minecraft/server/TileEntityConduit.java +@@ -16,15 +16,32 @@ public class TileEntityConduit extends TileEntity implements ITickable { + private static final Block[] b = new Block[]{Blocks.PRISMARINE, Blocks.PRISMARINE_BRICKS, Blocks.SEA_LANTERN, Blocks.DARK_PRISMARINE}; + public int a; + private float c; +- private boolean g; ++ private boolean g; private final void setActive(boolean value) { this.g = value; } // Tuinity - OBFHELPER + private boolean h; +- private final List i; ++ private final List i; private final List getPositionsActivating() { return this.i; } // Tuinity - OBFHELPER + @Nullable + private EntityLiving target; + @Nullable + private UUID k; + private long l; + ++ // Tuinity start - make TE's pushable ++ @Override ++ public TileEntity createCopyForPush(WorldServer world, BlockPosition oldPos, BlockPosition newPos, IBlockData blockData) { ++ final TileEntityConduit copy = (TileEntityConduit)super.createCopyForPush(world, oldPos, newPos, blockData); ++ ++ // the following states need to be re-calculated ++ copy.getPositionsActivating().clear(); ++ copy.setActive(false); ++ copy.target = null; ++ // also set our state because the copy and this share the same activating block list ++ this.setActive(false); ++ this.target = null; ++ ++ return copy; ++ } ++ // Tuinity end - make TE's pushable ++ + public TileEntityConduit() { + this(TileEntityTypes.CONDUIT); + } +diff --git a/src/main/java/net/minecraft/server/TileEntityFurnace.java b/src/main/java/net/minecraft/server/TileEntityFurnace.java +index f4f50fb83..59aa2f8a7 100644 +--- a/src/main/java/net/minecraft/server/TileEntityFurnace.java ++++ b/src/main/java/net/minecraft/server/TileEntityFurnace.java +@@ -32,14 +32,14 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I + public double cookSpeedMultiplier = 1.0; // Paper - cook speed multiplier API + public int cookTime; + public int cookTimeTotal; +- protected final IContainerProperties b; ++ protected IContainerProperties b; protected final void setContainerProperties(IContainerProperties value) { this.b = value; } // Tuinity - OBFHELPER // Tuinity - need non-final for `createCopyForPush` + private final Object2IntOpenHashMap n; + protected final Recipes c; + +- protected TileEntityFurnace(TileEntityTypes tileentitytypes, Recipes recipes) { +- super(tileentitytypes); +- this.items = NonNullList.a(3, ItemStack.b); +- this.b = new IContainerProperties() { ++ // Tuinity start - pushable TE's ++ protected final IContainerProperties getNewContainerProperties() { ++ // moved from constructor - this should be re-copied if it changes ++ return new IContainerProperties() { + @Override + public int getProperty(int i) { + switch (i) { +@@ -79,7 +79,23 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I + return 4; + } + }; ++ } ++ ++ @Override ++ public TileEntity createCopyForPush(WorldServer world, BlockPosition oldPos, BlockPosition newPos, IBlockData blockData) { ++ TileEntityFurnace copy = (TileEntityFurnace)super.createCopyForPush(world, oldPos, newPos, blockData); ++ ++ copy.setContainerProperties(copy.getNewContainerProperties()); // old properties retains reference to old te ++ ++ return copy; ++ } ++ // Tuinity end - pushable TE's ++ ++ protected TileEntityFurnace(TileEntityTypes tileentitytypes, Recipes recipes) { ++ super(tileentitytypes); ++ this.items = NonNullList.a(3, ItemStack.b); + this.n = new Object2IntOpenHashMap(); ++ this.b = this.getNewContainerProperties(); + this.c = recipes; + } + +diff --git a/src/main/java/net/minecraft/server/TileEntityJukeBox.java b/src/main/java/net/minecraft/server/TileEntityJukeBox.java +index 33c7dc56d..75eb1b8b2 100644 +--- a/src/main/java/net/minecraft/server/TileEntityJukeBox.java ++++ b/src/main/java/net/minecraft/server/TileEntityJukeBox.java +@@ -4,6 +4,13 @@ public class TileEntityJukeBox extends TileEntity implements Clearable { + + private ItemStack a; + ++ // Tuinity start - pushable TE's ++ @Override ++ public boolean isPushable() { ++ return false; // disabled due to buggy sound ++ } ++ // Tuinity end - pushable TE's ++ + public TileEntityJukeBox() { + super(TileEntityTypes.JUKEBOX); + this.a = ItemStack.b; +diff --git a/src/main/java/net/minecraft/server/TileEntityLectern.java b/src/main/java/net/minecraft/server/TileEntityLectern.java +index b2ceb6c17..b955d5d66 100644 +--- a/src/main/java/net/minecraft/server/TileEntityLectern.java ++++ b/src/main/java/net/minecraft/server/TileEntityLectern.java +@@ -17,7 +17,7 @@ import org.bukkit.inventory.InventoryHolder; + public class TileEntityLectern extends TileEntity implements Clearable, ITileInventory, ICommandListener { // CraftBukkit - ICommandListener + + // CraftBukkit start - add fields and methods +- public final IInventory inventory = new LecternInventory(); ++ public IInventory inventory = new LecternInventory(); // Tuinity - need non-final for `createCopyForPush` + public class LecternInventory implements IInventory { + + public List transaction = new ArrayList<>(); +@@ -137,29 +137,48 @@ public class TileEntityLectern extends TileEntity implements Clearable, ITileInv + @Override + public void clear() {} + }; +- private final IContainerProperties containerProperties = new IContainerProperties() { +- @Override +- public int getProperty(int i) { +- return i == 0 ? TileEntityLectern.this.page : 0; +- } ++ // Tuinity start - pushable TE's ++ private IContainerProperties containerProperties = this.getNewContainerProperties(); // Tuinity - need non-final for `createCopyForPush` ++ ++ protected final IContainerProperties getNewContainerProperties() { ++ return new IContainerProperties() { ++ @Override ++ public int getProperty(int i) { ++ return i == 0 ? TileEntityLectern.this.page : 0; ++ } ++ ++ @Override ++ public void setProperty(int i, int j) { ++ if (i == 0) { ++ TileEntityLectern.this.setPage(j); ++ } + +- @Override +- public void setProperty(int i, int j) { +- if (i == 0) { +- TileEntityLectern.this.setPage(j); + } + +- } ++ @Override ++ public int a() { ++ return 1; ++ } ++ }; ++ } ++ // Tuinity end - pushable TE's + +- @Override +- public int a() { +- return 1; +- } +- }; + private ItemStack book; + private int page; + private int maxPage; + ++ // Tuinity start - pushable TE's ++ @Override ++ public TileEntity createCopyForPush(WorldServer world, BlockPosition oldPos, BlockPosition newPos, IBlockData blockData) { ++ TileEntityLectern copy = (TileEntityLectern)super.createCopyForPush(world, oldPos, newPos, blockData); ++ ++ copy.inventory = copy.new LecternInventory(); ++ copy.containerProperties = copy.getNewContainerProperties(); // old properties retains reference to old te ++ ++ return copy; ++ } ++ // Tuinity end - pushable TE's ++ + public TileEntityLectern() { + super(TileEntityTypes.LECTERN); + this.book = ItemStack.b; +diff --git a/src/main/java/net/minecraft/server/TileEntityPiston.java b/src/main/java/net/minecraft/server/TileEntityPiston.java +index e7b7e468f..38d0e841c 100644 +--- a/src/main/java/net/minecraft/server/TileEntityPiston.java ++++ b/src/main/java/net/minecraft/server/TileEntityPiston.java +@@ -5,10 +5,10 @@ import java.util.List; + + public class TileEntityPiston extends TileEntity implements ITickable { + +- private IBlockData a; ++ private IBlockData a; protected final IBlockData getBlockData() { return this.a; } // Tuinity - OBFHELPER + private EnumDirection b; + private boolean c; +- private boolean g; ++ private boolean g; protected final boolean isSource() { return this.g; } // Tuinity - OBFHELPER + private static final ThreadLocal h = ThreadLocal.withInitial(() -> { + return null; + }); +@@ -16,12 +16,27 @@ public class TileEntityPiston extends TileEntity implements ITickable { + private float j; + private long k; + ++ // Tuinity start - pushable TE's ++ private TileEntity tileEntity; ++ ++ @Override ++ public boolean isPushable() { ++ return false; // fuck no. ++ } ++ // Tuinity end - pushable TE's ++ + public TileEntityPiston() { + super(TileEntityTypes.PISTON); + } + + public TileEntityPiston(IBlockData iblockdata, EnumDirection enumdirection, boolean flag, boolean flag1) { ++ // Tuinity start - add tileEntity parameter ++ this(iblockdata, enumdirection, flag, flag1, null); ++ } ++ public TileEntityPiston(IBlockData iblockdata, EnumDirection enumdirection, boolean flag, boolean flag1, TileEntity tileEntity) { + this(); ++ this.tileEntity = tileEntity; ++ // Tuinity end - add tileEntity parameter + this.a = iblockdata; + this.b = enumdirection; + this.c = flag; +@@ -30,7 +45,7 @@ public class TileEntityPiston extends TileEntity implements ITickable { + + @Override + public NBTTagCompound b() { +- return this.save(new NBTTagCompound()); ++ return this.save(new NBTTagCompound(), false); // Tuinity - clients don't need the copied tile entity. + } + + public boolean d() { +@@ -238,7 +253,25 @@ public class TileEntityPiston extends TileEntity implements ITickable { + iblockdata = Block.b(this.a, (GeneratorAccess) this.world, this.position); + } + +- this.world.setTypeAndData(this.position, iblockdata, 3); ++ // Tuinity start - pushable TE's ++ if ((iblockdata.isAir() && !this.isSource()) && !this.getBlockData().isAir()) { ++ // if the block can't exist at the location anymore, we need to fire drops for it, as ++ // setTypeAndData wont. ++ ++ // careful - the previous pos is moving_piston, which wont fire drops. So we're safe from dupes. ++ // but the setAir should be before the drop. ++ this.world.setAir(this.position, false); ++ Block.dropItems(this.getBlockData(), this.world, this.position, null, null, ItemStack.NULL_ITEM); ++ } else { ++ // need to set to air before else the setTypeAndData call will create a new TE and override ++ // the old one ++ this.world.setTypeAndDataRaw(this.position, Blocks.AIR.getBlockData(), null); ++ this.world.setTypeAndData(this.position, iblockdata, 3, iblockdata.getBlock() == this.getBlockData().getBlock() ? this.tileEntity : null); ++ } ++ if (this.tileEntity != null && this.world.getType(this.position).getBlock() == this.getBlockData().getBlock()) { ++ this.tileEntity.onPostPush(); ++ } ++ // Tuinity end - pushable TE's + this.world.a(this.position, iblockdata.getBlock(), this.position); + } + } +@@ -263,7 +296,12 @@ public class TileEntityPiston extends TileEntity implements ITickable { + iblockdata = (IBlockData) iblockdata.set(BlockProperties.C, false); + } + +- this.world.setTypeAndData(this.position, iblockdata, 67); ++ // Tuinity start - pushable TE's ++ this.world.setTypeAndData(this.position, iblockdata, 67, this.tileEntity); ++ if (this.tileEntity != null && this.world.getType(this.position).getBlock() == this.getBlockData().getBlock()) { ++ this.tileEntity.onPostPush(); ++ } ++ // Tuinity end - pushable TE's + this.world.a(this.position, iblockdata.getBlock(), this.position); + } + } +@@ -290,16 +328,34 @@ public class TileEntityPiston extends TileEntity implements ITickable { + this.j = this.i; + this.c = nbttagcompound.getBoolean("extending"); + this.g = nbttagcompound.getBoolean("source"); ++ // Tuinity start - pushable TE's ++ if (nbttagcompound.hasKey("Tuinity.tileEntity")) { ++ NBTTagCompound compound = nbttagcompound.getCompound("Tuinity.tileEntity"); ++ if (!compound.isEmpty()) { ++ this.tileEntity = TileEntity.create(this.getBlockData(), compound); ++ } ++ } ++ // Tuinity end - pushable TE's + } + + @Override + public NBTTagCompound save(NBTTagCompound nbttagcompound) { ++ // Tuinity start - add saveTile param ++ return this.save(nbttagcompound, true); ++ } ++ public NBTTagCompound save(NBTTagCompound nbttagcompound, boolean saveTile) { ++ // Tuinity end - add saveTile param + super.save(nbttagcompound); + nbttagcompound.set("blockState", GameProfileSerializer.a(this.a)); + nbttagcompound.setInt("facing", this.b.c()); + nbttagcompound.setFloat("progress", this.j); + nbttagcompound.setBoolean("extending", this.c); + nbttagcompound.setBoolean("source", this.g); ++ // Tuinity start - pushable TE's ++ if (saveTile && this.tileEntity != null) { ++ nbttagcompound.set("Tuinity.tileEntity", this.tileEntity.save(new NBTTagCompound())); ++ } ++ // Tuinity end - pushable TE's + return nbttagcompound; + } + +diff --git a/src/main/java/net/minecraft/server/Vec3D.java b/src/main/java/net/minecraft/server/Vec3D.java +index 3048ba008..84858ba39 100644 +--- a/src/main/java/net/minecraft/server/Vec3D.java ++++ b/src/main/java/net/minecraft/server/Vec3D.java +@@ -4,7 +4,7 @@ import java.util.EnumSet; + + public class Vec3D implements IPosition { + +- public static final Vec3D a = new Vec3D(0.0D, 0.0D, 0.0D); ++ public static final Vec3D a = new Vec3D(0.0D, 0.0D, 0.0D); public static Vec3D getZeroVector() { return Vec3D.a; } // Tuinity - OBFHELPER + public final double x; + public final double y; + public final double z; +@@ -61,6 +61,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 +110,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 303f6b095..c1e149f20 100644 +--- a/src/main/java/net/minecraft/server/VillagePlace.java ++++ b/src/main/java/net/minecraft/server/VillagePlace.java +@@ -155,7 +155,7 @@ 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 + } + } + // Paper end +diff --git a/src/main/java/net/minecraft/server/VoxelShape.java b/src/main/java/net/minecraft/server/VoxelShape.java +index c2b8c9820..3a98e242e 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; + } + +@@ -51,6 +51,12 @@ public abstract class VoxelShape { + 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 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 VoxelShape c() { + VoxelShape[] avoxelshape = new VoxelShape[]{VoxelShapes.a()}; + +@@ -70,6 +76,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 caf297fe9..8d68c783f 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(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,49 @@ 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); ++ } ++ ++ 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) { ++ double minX = axisalingedbb.minX - this.offsetX; ++ double maxX = axisalingedbb.maxX - this.offsetX; ++ double minY = axisalingedbb.minY - this.offsetY; ++ double maxY = axisalingedbb.maxY - this.offsetY; ++ double minZ = axisalingedbb.minZ - this.offsetZ; ++ double maxZ = axisalingedbb.maxZ - this.offsetZ; ++ ++ // this can be optimised by checking an "overall shape" ++ ++ for (AxisAlignedBB boundingBox : this.boundingBoxesRepresentation) { ++ if (boundingBox.intersects(minX, minY, minZ, maxX, maxY, maxZ)) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ // Tuinity end - optimise multi-aabb shapes + } +diff --git a/src/main/java/net/minecraft/server/VoxelShapes.java b/src/main/java/net/minecraft/server/VoxelShapes.java +index 1fa7061f7..f6f3bdc61 100644 +--- a/src/main/java/net/minecraft/server/VoxelShapes.java ++++ b/src/main/java/net/minecraft/server/VoxelShapes.java +@@ -17,18 +17,81 @@ 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})); 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 void 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.intersects(aabb)) { ++ list.add(shapeCasted.aabb); ++ } ++ } else if (shape instanceof VoxelShapeArray) { ++ VoxelShapeArray shapeCasted = (VoxelShapeArray)shape; ++ double minX = aabb.minX - shapeCasted.offsetX; ++ double maxX = aabb.maxX - shapeCasted.offsetX; ++ double minY = aabb.minY - shapeCasted.offsetY; ++ double maxY = aabb.maxY - shapeCasted.offsetY; ++ double minZ = aabb.minZ - shapeCasted.offsetZ; ++ double maxZ = aabb.maxZ - shapeCasted.offsetZ; ++ ++ // this can be optimised by checking an "overall shape" ++ ++ for (AxisAlignedBB boundingBox : shapeCasted.boundingBoxesRepresentation) { ++ if (boundingBox.intersects(minX, minY, minZ, maxX, maxY, maxZ)) { ++ 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.intersects(aabb)) { ++ list.add(box); ++ } ++ } ++ } ++ } ++ ++ 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; ++ list.add(shapeCasted.aabb); ++ } else if (shape instanceof VoxelShapeArray) { ++ VoxelShapeArray shapeCasted = (VoxelShapeArray)shape; ++ ++ for (AxisAlignedBB boundingBox : shapeCasted.boundingBoxesRepresentation) { ++ 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); ++ 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 +130,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 +195,14 @@ 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 && voxelshape instanceof com.tuinity.tuinity.voxel.AABBVoxelShape && voxelshape1 instanceof com.tuinity.tuinity.voxel.AABBVoxelShape) { ++ return ((com.tuinity.tuinity.voxel.AABBVoxelShape) voxelshape).aabb.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(new IllegalArgumentException()); + } else if (voxelshape == voxelshape1) { +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index b598c4869..8df4ef488 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,6 +123,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.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this.paperConfig, 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 +@@ -397,13 +400,38 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + } + } + ++ // Tuinity start ++ // Does not affect TE. This simply just a raw set type - runs no logic. ++ final void setTypeAndDataRaw(final BlockPosition pos, final IBlockData blockData, final TileEntity tileEntity) { ++ this.getChunkAt(pos.getX() >> 4, pos.getZ() >> 4).setTypeAndDataRaw(pos, blockData); ++ if (tileEntity == null) { ++ this.removeTileEntity(pos); ++ } else { ++ this.setTileEntity(pos, tileEntity); ++ } ++ ((WorldServer)this).getChunkProvider().flagDirty(pos); ++ } ++ // Tuinity end ++ + @Override + public boolean setTypeAndData(BlockPosition blockposition, IBlockData iblockdata, int i) { +- return this.a(blockposition, iblockdata, i, 512); ++ // Tuinity start - add tileEntity parameter ++ return this.setTypeAndData(blockposition, iblockdata, i, null); ++ } ++ // Up to the caller to handle previous tile state. ++ public boolean setTypeAndData(BlockPosition blockposition, IBlockData iblockdata, int i, TileEntity tileEntity) { ++ return this.setTypeAndData(blockposition, iblockdata, i, 512, tileEntity); ++ // Tuinity end - add tileEntity parameter + } + + @Override + public boolean a(BlockPosition blockposition, IBlockData iblockdata, int i, int j) { ++ // Tuinity start - add tileEntity parameter ++ return this.setTypeAndData(blockposition, iblockdata, i, j, null); ++ } ++ public boolean setTypeAndData(BlockPosition blockposition, IBlockData iblockdata, int i, int j, TileEntity tileEntity) { ++ // Tuinity end - add tileEntity parameter ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Async set type call"); // Tuinity + // CraftBukkit start - tree generation + if (this.captureTreeGeneration) { + // Paper start +@@ -436,7 +464,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + } + // CraftBukkit end + +- IBlockData iblockdata1 = chunk.setType(blockposition, iblockdata, (i & 64) != 0, (i & 1024) == 0); // CraftBukkit custom NO_PLACE flag ++ IBlockData iblockdata1 = chunk.setType(blockposition, iblockdata, (i & 64) != 0, (i & 1024) == 0, tileEntity); // CraftBukkit custom NO_PLACE flag // Tuinity - add tileEntity parameter + this.chunkPacketBlockController.onBlockChange(this, blockposition, iblockdata, iblockdata1, i); // Paper - Anti-Xray + + if (iblockdata1 == null) { +@@ -504,6 +532,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) { ++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Async notify and update"); // Tuinity + IBlockData iblockdata = newBlock; + IBlockData iblockdata1 = oldBlock; + IBlockData iblockdata2 = actualBlock; +@@ -941,6 +970,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 +@@ -1036,7 +1066,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + while (iterator.hasNext()) { + TileEntity tileentity1 = (TileEntity) iterator.next(); + +- if (tileentity1.getPosition().equals(blockposition)) { ++ if (tileentity != tileentity1 && tileentity1.getPosition().equals(blockposition)) { // Tuinity - don't remove us if we double set... + tileentity1.an_(); + iterator.remove(); + } +@@ -1125,6 +1155,11 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + public List getHardCollidingEntities(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate) { + // copied from below + List list = Lists.newArrayList(); ++ // Tuinity start - add list parameter ++ return this.getHardCollidingEntities(entity, axisalignedbb, predicate, list); ++ } ++ public List getHardCollidingEntities(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate, List list) { ++ // Tuinity end - add list parameter + 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); +@@ -1148,8 +1183,13 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + + @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); +diff --git a/src/main/java/net/minecraft/server/WorldBorder.java b/src/main/java/net/minecraft/server/WorldBorder.java +index b651eb87b..5cba3b0e6 100644 +--- a/src/main/java/net/minecraft/server/WorldBorder.java ++++ b/src/main/java/net/minecraft/server/WorldBorder.java +@@ -47,11 +47,43 @@ 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 colliding with one of the wordborder faces. ++ public final boolean isCollidingOnBorderEdge(AxisAlignedBB boundingBox) { ++ return this.isCollidingOnBorderEdge(boundingBox.minX, boundingBox.maxX, boundingBox.minZ, boundingBox.maxZ); ++ } ++ ++ public final boolean isCollidingOnBorderEdge(double boxMinX, double boxMaxX, double boxMinZ, double boxMaxZ) { ++ double minX = this.getMinX() - 1.0E-7; ++ double maxX = this.getMaxX() + 1.0E-7; ++ ++ double minZ = this.getMinZ() - 1.0E-7; ++ double maxZ = this.getMaxZ() + 1.0E-7; ++ ++ return ++ // First, check if the worldborder is enclosing the specified box. ++ // We check this first as it's most likely to fail. ++ !(minX < boxMinX && maxX > boxMaxX && minZ < boxMinZ && maxZ > boxMaxZ) ++ && ++ ++ // Now we verify if we're even intersecting. ++ (minX < boxMaxX && maxX > boxMinX && minZ < boxMaxZ && maxZ > boxMinZ) ++ && ++ ++ // Now verify that the worldborder isn't being enclosed. ++ // This is never expected to happen, but is left here to ensure our logic ++ // is right 100% of the time. ++ !(boxMinX < minX && boxMaxX > maxX && boxMinZ < minZ && boxMaxZ > maxZ) ++ ; ++ } ++ // 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(); + } +@@ -67,18 +99,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 3a740f566..6d37bbfeb 100644 +--- a/src/main/java/net/minecraft/server/WorldServer.java ++++ b/src/main/java/net/minecraft/server/WorldServer.java +@@ -55,7 +55,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + + public static final BlockPosition a = new BlockPosition(100, 50, 0); + private static final Logger LOGGER = LogManager.getLogger(); +- public final Int2ObjectMap entitiesById = new Int2ObjectLinkedOpenHashMap(); ++ public final Int2ObjectMap entitiesById = new Int2ObjectLinkedOpenHashMap(); final com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet entitiesForIteration = new com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet<>(2048, 0.5f, 2048, 0.2); // Tuinity - make removing entities while ticking safe + private final Map entitiesByUUID = Maps.newHashMap(); + private final Queue entitiesToAdd = Queues.newArrayDeque(); + public final List players = Lists.newArrayList(); // Paper - private -> public +@@ -79,7 +79,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + private final PortalTravelAgent portalTravelAgent; + private final TickListServer nextTickListBlock; + private final TickListServer nextTickListFluid; +- private final Set navigators; ++ private final Set navigators; final com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet navigatorsForIteration = new com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet<>(2048, 0.5f, 2048, 0.2); // Tuinity - make removing entities while ticking safe + protected final PersistentRaid persistentRaid; + private final ObjectLinkedOpenHashSet L; + private boolean ticking; +@@ -200,6 +200,100 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + // Paper end - rewrite ticklistserver + ++ // Tuinity start ++ public final boolean areChunksLoadedForMove(AxisAlignedBB axisalignedbb) { ++ // copied code from collision methods, so that we can guarantee that they wont load chunks (we don't override ++ // ICollisionAccess methods for VoxelShapes) ++ // be more strict too, add a block (dumb plugins in move events?) ++ int minBlockX = MathHelper.floor(axisalignedbb.minX - 1.0E-7D) - 3; ++ int maxBlockX = MathHelper.floor(axisalignedbb.maxX + 1.0E-7D) + 3; ++ ++ int minBlockZ = MathHelper.floor(axisalignedbb.minZ - 1.0E-7D) - 3; ++ int maxBlockZ = MathHelper.floor(axisalignedbb.maxZ + 1.0E-7D) + 3; ++ ++ int minChunkX = minBlockX >> 4; ++ int maxChunkX = maxBlockX >> 4; ++ ++ int minChunkZ = minBlockZ >> 4; ++ int maxChunkZ = maxBlockZ >> 4; ++ ++ ChunkProviderServer chunkProvider = this.getChunkProvider(); ++ ++ for (int cx = minChunkX; cx <= maxChunkX; ++cx) { ++ for (int cz = minChunkZ; cz <= maxChunkZ; ++cz) { ++ if (chunkProvider.getChunkAtIfLoadedImmediately(cx, cz) == null) { ++ return false; ++ } ++ } ++ } ++ ++ return true; ++ } ++ ++ public final void loadChunksForMoveAsync(AxisAlignedBB axisalignedbb, double toX, double toZ, ++ java.util.function.Consumer> onLoad) { ++ if (Thread.currentThread() != this.serverThread) { ++ this.getChunkProvider().serverThreadQueue.execute(() -> { ++ this.loadChunksForMoveAsync(axisalignedbb, toX, toZ, onLoad); ++ }); ++ return; ++ } ++ List ret = new java.util.ArrayList<>(); ++ it.unimi.dsi.fastutil.ints.IntArrayList ticketLevels = new it.unimi.dsi.fastutil.ints.IntArrayList(); ++ ++ int minBlockX = MathHelper.floor(axisalignedbb.minX - 1.0E-7D) - 3; ++ int maxBlockX = MathHelper.floor(axisalignedbb.maxX + 1.0E-7D) + 3; ++ ++ int minBlockZ = MathHelper.floor(axisalignedbb.minZ - 1.0E-7D) - 3; ++ int maxBlockZ = MathHelper.floor(axisalignedbb.maxZ + 1.0E-7D) + 3; ++ ++ int minChunkX = minBlockX >> 4; ++ int maxChunkX = maxBlockX >> 4; ++ ++ int minChunkZ = minBlockZ >> 4; ++ int maxChunkZ = maxBlockZ >> 4; ++ ++ ChunkProviderServer chunkProvider = this.getChunkProvider(); ++ ++ int requiredChunks = (maxChunkX - minChunkX + 1) * (maxChunkZ - minChunkZ + 1); ++ int[] loadedChunks = new int[1]; ++ ++ Long holderIdentifier = Long.valueOf(chunkProvider.chunkFutureAwaitCounter++); ++ ++ java.util.function.Consumer consumer = (IChunkAccess chunk) -> { ++ if (chunk != null) { ++ int ticketLevel = Math.max(33, chunkProvider.playerChunkMap.getUpdatingChunk(chunk.getPos().pair()).getTicketLevel()); ++ ret.add(chunk); ++ ticketLevels.add(ticketLevel); ++ chunkProvider.addTicketAtLevel(TicketType.FUTURE_AWAIT, chunk.getPos(), ticketLevel, holderIdentifier); ++ } ++ if (++loadedChunks[0] == requiredChunks) { ++ try { ++ onLoad.accept(java.util.Collections.unmodifiableList(ret)); ++ } finally { ++ for (int i = 0, len = ret.size(); i < len; ++i) { ++ ChunkCoordIntPair chunkPos = ret.get(i).getPos(); ++ int ticketLevel = ticketLevels.getInt(i); ++ ++ chunkProvider.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos); ++ chunkProvider.removeTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, holderIdentifier); ++ } ++ } ++ } ++ }; ++ ++ for (int cx = minChunkX; cx <= maxChunkX; ++cx) { ++ for (int cz = minChunkZ; cz <= maxChunkZ; ++cz) { ++ chunkProvider.getChunkAtAsynchronously(cx, cz, ChunkStatus.FULL, true, false, consumer); ++ } ++ } ++ } ++ // Tuinity end ++ ++ // Tuinity start - execute chunk tasks mid tick ++ long lastMidTickExecuteFailure; ++ // Tuinity end - execute chunk tasks mid tick ++ + // Add env and gen to constructor, WorldData -> WorldDataServer + public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, ResourceKey resourcekey1, 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, resourcekey1, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor +@@ -260,6 +354,349 @@ public class WorldServer extends World implements GeneratorAccessSeed { + this.asyncChunkTaskManager = new com.destroystokyo.paper.io.chunk.ChunkTaskManager(this); // Paper + } + ++ // Tuinity start - optimise collision ++ public boolean collidesWithAnyBlockOrWorldBorder(@Nullable Entity entity, AxisAlignedBB axisalignedbb, boolean loadChunks) { ++ if (entity != null) { ++ if (this.getWorldBorder().isCollidingOnBorderEdge(axisalignedbb)) { ++ return true; ++ } ++ } ++ ++ int minBlockX = MathHelper.floor(axisalignedbb.minX - 1.0E-7D) - 1; ++ int maxBlockX = MathHelper.floor(axisalignedbb.maxX + 1.0E-7D) + 1; ++ ++ int minBlockY = MathHelper.floor(axisalignedbb.minY - 1.0E-7D) - 1; ++ int maxBlockY = MathHelper.floor(axisalignedbb.maxY + 1.0E-7D) + 1; ++ ++ int minBlockZ = MathHelper.floor(axisalignedbb.minZ - 1.0E-7D) - 1; ++ int maxBlockZ = MathHelper.floor(axisalignedbb.maxZ + 1.0E-7D) + 1; ++ ++ ++ BlockPosition.MutableBlockPosition mutablePos = new BlockPosition.MutableBlockPosition(); ++ VoxelShapeCollision collisionShape = entity == null ? VoxelShapeCollision.a() : VoxelShapeCollision.a(entity); // TODO make this lazy ++ ++ // special cases: ++ if (minBlockY > 255 || maxBlockY < 0) { ++ // no point in checking ++ return false; ++ } ++ ++ 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; ++ ++ ChunkProviderServer chunkProvider = (ChunkProviderServer)this.chunkProvider; ++ // TODO special case single 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 ++ ++ 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 ++ ++ int chunkXGlobalPos = currChunkX << 4; ++ int chunkZGlobalPos = currChunkZ << 4; ++ Chunk chunk = loadChunks ? chunkProvider.getChunkAt(currChunkX, currChunkZ, true) : chunkProvider.getChunkAtIfLoadedImmediately(currChunkX, currChunkZ); ++ ++ if (chunk == null) { ++ return true; ++ } ++ ++ 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; ++ int blockKeyY = (currY & 15) << 8; ++ ++ int edgeCountY = (currY == minBlockY || currY == maxBlockY) ? 1 : 0; ++ ++ for (int currX = minX; currX <= maxX; ++currX) { ++ int blockKeyXY = blockKeyY | currX; ++ int blockX = currX | chunkXGlobalPos; // world position ++ ++ int edgeCountXY; ++ if (blockX == minBlockX || blockX == maxBlockX) { ++ edgeCountXY = edgeCountY + 1; ++ } else { ++ edgeCountXY = edgeCountY; ++ } ++ ++ for (int currZ = minZ; currZ <= maxZ; ++currZ) { ++ int blockZ = currZ | chunkZGlobalPos; // world position ++ ++ int edgeCountFull; ++ if (blockZ == minBlockZ || blockZ == maxBlockZ) { ++ edgeCountFull = edgeCountXY + 1; ++ } else { ++ edgeCountFull = edgeCountXY; ++ } ++ ++ if (edgeCountFull == 3) { ++ continue; ++ } ++ ++ int blockKeyFull = blockKeyXY | (currZ << 4); ++ IBlockData blockData = blocks.rawGet(blockKeyFull); ++ ++ if (!blockData.isAir() && (edgeCountFull != 1 || blockData.collisionBoxExceedsCube()) && (edgeCountFull != 2 || blockData.getBlock() == Blocks.MOVING_PISTON)) { ++ mutablePos.setValues(blockX, currY, blockZ); ++ VoxelShape voxelshape2 = blockData.getCollisionShape(this, mutablePos, collisionShape); ++ if (voxelshape2 != VoxelShapes.getEmptyShape()) { ++ VoxelShape voxelshape3 = voxelshape2.offset((double)blockX, (double)currY, (double)blockZ); ++ ++ if (voxelshape3.intersects(axisalignedbb)) { ++ return true; ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ return false; ++ } ++ ++ public final boolean hardCollidesWithAnyEntities(@Nullable Entity entity, AxisAlignedBB axisalignedbb, @Nullable Predicate predicate) { ++ if (axisalignedbb.isEmpty()) { ++ return false; ++ } ++ AxisAlignedBB axisalignedbb1 = axisalignedbb.grow(1.0E-7D, 1.0E-7D, 1.0E-7D); ++ List entities = (entity != null && entity.hardCollides()) ? this.getEntities(entity, axisalignedbb, predicate == null ? IEntitySelector.notSpectator() : predicate.and(IEntitySelector.notSpectator())) : this.getHardCollidingEntities(entity, axisalignedbb1, predicate); ++ ++ for (int i = 0, len = entities.size(); i < len; ++i) { ++ Entity otherEntity = entities.get(i); ++ ++ if (predicate != null && !predicate.test(otherEntity)) { ++ continue; ++ } ++ ++ if (entity != null) { ++ if (entity.isSameVehicle(otherEntity)) { ++ continue; ++ } ++ AxisAlignedBB hardCollisionBox = entity.getHardCollisionBoxWith(otherEntity); ++ if (hardCollisionBox != null && axisalignedbb1.intersects(hardCollisionBox)) { ++ return true; ++ } ++ } ++ ++ AxisAlignedBB hardCollisionBox = otherEntity.getHardCollisionBox(); ++ ++ if (hardCollisionBox != null && axisalignedbb1.intersects(hardCollisionBox)) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ public final boolean hasAnyCollisions(@Nullable Entity entity, AxisAlignedBB axisalignedbb) { ++ return this.hasAnyCollisions(entity, axisalignedbb, true); ++ } ++ ++ public final boolean hasAnyCollisions(@Nullable Entity entity, AxisAlignedBB axisalignedbb, boolean loadChunks) { ++ return this.collidesWithAnyBlockOrWorldBorder(entity, axisalignedbb, loadChunks) || this.hardCollidesWithAnyEntities(entity, axisalignedbb, null); ++ } ++ ++ // Tuinity start - optimise collision ++ public void getCollisionsForBlocksOrWorldBorder(@Nullable Entity entity, AxisAlignedBB axisalignedbb, List list, boolean loadChunks) { ++ if (entity != null) { ++ if (this.getWorldBorder().isCollidingOnBorderEdge(axisalignedbb)) { ++ VoxelShapes.addBoxesTo(this.getWorldBorder().getCollisionShape(), list); ++ } ++ } ++ ++ int minBlockX = MathHelper.floor(axisalignedbb.minX - 1.0E-7D) - 1; ++ int maxBlockX = MathHelper.floor(axisalignedbb.maxX + 1.0E-7D) + 1; ++ ++ int minBlockY = MathHelper.floor(axisalignedbb.minY - 1.0E-7D) - 1; ++ int maxBlockY = MathHelper.floor(axisalignedbb.maxY + 1.0E-7D) + 1; ++ ++ int minBlockZ = MathHelper.floor(axisalignedbb.minZ - 1.0E-7D) - 1; ++ int maxBlockZ = MathHelper.floor(axisalignedbb.maxZ + 1.0E-7D) + 1; ++ ++ ++ BlockPosition.MutableBlockPosition mutablePos = new BlockPosition.MutableBlockPosition(); ++ VoxelShapeCollision collisionShape = entity == null ? VoxelShapeCollision.a() : VoxelShapeCollision.a(entity); // TODO make this lazy ++ ++ // special cases: ++ if (minBlockY > 255 || maxBlockY < 0) { ++ // no point in checking ++ return; ++ } ++ ++ 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; ++ ++ ChunkProviderServer chunkProvider = (ChunkProviderServer)this.chunkProvider; ++ // TODO special case single 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 ++ ++ 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 ++ ++ int chunkXGlobalPos = currChunkX << 4; ++ int chunkZGlobalPos = currChunkZ << 4; ++ Chunk chunk = loadChunks ? chunkProvider.getChunkAt(currChunkX, currChunkZ, true) : chunkProvider.getChunkAtIfLoadedImmediately(currChunkX, currChunkZ); ++ ++ if (chunk == null) { ++ list.add(AxisAlignedBB.getBoxForChunk(currChunkX, currChunkZ)); ++ 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; ++ int blockKeyY = (currY & 15) << 8; ++ ++ int edgeCountY = (currY == minBlockY || currY == maxBlockY) ? 1 : 0; ++ ++ for (int currX = minX; currX <= maxX; ++currX) { ++ int blockKeyXY = blockKeyY | currX; ++ int blockX = currX | chunkXGlobalPos; // world position ++ ++ int edgeCountXY; ++ if (blockX == minBlockX || blockX == maxBlockX) { ++ edgeCountXY = edgeCountY + 1; ++ } else { ++ edgeCountXY = edgeCountY; ++ } ++ ++ for (int currZ = minZ; currZ <= maxZ; ++currZ) { ++ int blockZ = currZ | chunkZGlobalPos; // world position ++ ++ int edgeCountFull; ++ if (blockZ == minBlockZ || blockZ == maxBlockZ) { ++ edgeCountFull = edgeCountXY + 1; ++ } else { ++ edgeCountFull = edgeCountXY; ++ } ++ ++ if (edgeCountFull == 3) { ++ continue; ++ } ++ ++ int blockKeyFull = blockKeyXY | (currZ << 4); ++ IBlockData blockData = blocks.rawGet(blockKeyFull); ++ ++ if (!blockData.isAir() && (edgeCountFull != 1 || blockData.collisionBoxExceedsCube()) && (edgeCountFull != 2 || blockData.getBlock() == Blocks.MOVING_PISTON)) { ++ mutablePos.setValues(blockX, currY, blockZ); ++ VoxelShape voxelshape2 = blockData.getCollisionShape(this, mutablePos, collisionShape); ++ if (voxelshape2 != VoxelShapes.getEmptyShape()) { ++ VoxelShape voxelshape3 = voxelshape2.offset((double)blockX, (double)currY, (double)blockZ); ++ ++ VoxelShapes.addBoxesToIfIntersects(voxelshape3, axisalignedbb, list); ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ public final void getEntityHardCollisions(@Nullable Entity entity, AxisAlignedBB axisalignedbb, @Nullable Predicate predicate, List list) { ++ if (axisalignedbb.isEmpty()) { ++ return; ++ } ++ AxisAlignedBB axisalignedbb1 = axisalignedbb.grow(1.0E-7D, 1.0E-7D, 1.0E-7D); ++ List entities = com.tuinity.tuinity.util.CachedLists.getTempGetEntitiesList(); ++ try { ++ if (entity != null && entity.hardCollides()) { ++ this.getEntities(entity, axisalignedbb, predicate == null ? IEntitySelector.notSpectator() : predicate.and(IEntitySelector.notSpectator()), entities); ++ } else { ++ this.getHardCollidingEntities(entity, axisalignedbb1, predicate, entities); ++ } ++ ++ for (int i = 0, len = entities.size(); i < len; ++i) { ++ Entity otherEntity = entities.get(i); ++ ++ if (predicate != null && !predicate.test(otherEntity)) { ++ continue; ++ } ++ ++ if (entity != null) { ++ if (entity.isSameVehicle(otherEntity)) { ++ continue; ++ } ++ AxisAlignedBB hardCollisionBox = entity.getHardCollisionBoxWith(otherEntity); ++ if (hardCollisionBox != null && axisalignedbb1.intersects(hardCollisionBox)) { ++ list.add(hardCollisionBox); ++ } ++ } ++ ++ AxisAlignedBB hardCollisionBox = otherEntity.getHardCollisionBox(); ++ ++ if (hardCollisionBox != null && axisalignedbb1.intersects(hardCollisionBox)) { ++ list.add(hardCollisionBox); ++ } ++ } ++ } finally { ++ com.tuinity.tuinity.util.CachedLists.returnTempGetEntitiesList(entities); ++ } ++ } ++ ++ public final void getCollisions(@Nullable Entity entity, AxisAlignedBB axisalignedbb, List list, boolean loadChunks) { ++ this.getCollisionsForBlocksOrWorldBorder(entity, axisalignedbb, list, loadChunks); ++ this.getEntityHardCollisions(entity, axisalignedbb, null, list); ++ } ++ ++ @Override ++ public boolean getCubes(Entity entity) { ++ return !this.hasAnyCollisions(entity, entity.getBoundingBox()); ++ } ++ ++ @Override ++ public boolean getCubes(@Nullable Entity entity, AxisAlignedBB axisalignedbb) { ++ return !this.hasAnyCollisions(entity, axisalignedbb); ++ } ++ ++ @Override ++ public boolean getCubes(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate) { ++ return !this.collidesWithAnyBlockOrWorldBorder(entity, axisalignedbb, true) && !this.hardCollidesWithAnyEntities(entity, axisalignedbb, predicate); ++ } ++ // Tuinity end - optimise collision ++ + // CraftBukkit start + @Override + protected TileEntity getTileEntity(BlockPosition pos, boolean validate) { +@@ -462,7 +899,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + timings.scheduledBlocks.stopTiming(); // Paper + +- this.getMinecraftServer().midTickLoadChunks(); // Paper ++ // Tuinity - replace logic + gameprofilerfiller.exitEnter("raid"); + this.timings.raids.startTiming(); // Paper - timings + this.persistentRaid.a(); +@@ -471,7 +908,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + timings.doSounds.startTiming(); // Spigot + this.ah(); + timings.doSounds.stopTiming(); // Spigot +- this.getMinecraftServer().midTickLoadChunks(); // Paper ++ // Tuinity - replace logic + 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 +@@ -487,14 +924,13 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + + this.tickingEntities = true; +- ObjectIterator objectiterator = this.entitiesById.int2ObjectEntrySet().iterator(); ++ com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet.Iterator objectiterator = this.entitiesForIteration.iterator(); // Tuinity + + org.spigotmc.ActivationRange.activateEntities(this); // Spigot + timings.entityTick.startTiming(); // Spigot + TimingHistory.entityTicks += this.entitiesById.size(); // Paper + while (objectiterator.hasNext()) { +- Entry entry = (Entry) objectiterator.next(); +- Entity entity = (Entity) entry.getValue(); ++ Entity entity = (Entity) objectiterator.next(); // Tuinity + Entity entity1 = entity.getVehicle(); + + /* CraftBukkit start - We prevent spawning in general, so this butchering is not needed +@@ -530,7 +966,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + gameprofilerfiller.enter("remove"); + if (entity.dead) { + this.removeEntityFromChunk(entity); +- objectiterator.remove(); ++ this.entitiesById.remove(entity.getId()); // Tuinity + this.unregisterEntity(entity); + } + +@@ -538,6 +974,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + timings.entityTick.stopTiming(); // Spigot + ++ objectiterator.finishedIterating(); // Tuinity + this.tickingEntities = false; + // Paper start + for (java.lang.Runnable run : this.afterEntityTickingTasks) { +@@ -549,7 +986,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + this.afterEntityTickingTasks.clear(); + // Paper end +- this.getMinecraftServer().midTickLoadChunks(); // Paper ++ // Tuinity - replace logic + + Entity entity2; + +@@ -559,7 +996,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + + timings.tickEntities.stopTiming(); // Spigot +- this.getMinecraftServer().midTickLoadChunks(); // Paper ++ // Tuinity - replace logic + this.tickBlockEntities(); + } + +@@ -803,7 +1240,26 @@ public class WorldServer extends World implements GeneratorAccessSeed { + + } + ++ // Tuinity start - log detailed entity tick information ++ static final java.util.concurrent.ConcurrentLinkedDeque currentlyTickingEntities = new java.util.concurrent.ConcurrentLinkedDeque<>(); ++ ++ public static List getCurrentlyTickingEntities() { ++ List ret = Lists.newArrayListWithCapacity(4); ++ ++ for (Entity entity : currentlyTickingEntities) { ++ ret.add(entity); ++ } ++ ++ return ret; ++ } ++ // Tuinity end - log detailed entity tick information ++ + public void entityJoinedWorld(Entity entity) { ++ // Tuinity start - log detailed entity tick information ++ com.tuinity.tuinity.util.TickThread.ensureTickThread("Cannot tick an entity off-main"); ++ try { ++ currentlyTickingEntities.push(entity); ++ // Tuinity end - log detailed entity tick information + if (!(entity instanceof EntityHuman) && !this.getChunkProvider().a(entity)) { + this.chunkCheck(entity); + } else { +@@ -849,6 +1305,11 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } // Paper - timings + + } ++ // Tuinity start - log detailed entity tick information ++ } finally { ++ currentlyTickingEntities.pop(); ++ } ++ // Tuinity end - log detailed entity tick information + } + + public void a(Entity entity, Entity entity1) { +@@ -1225,7 +1686,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + Entity entity = (Entity) iterator.next(); + + if (!(entity instanceof EntityPlayer)) { +- if (this.tickingEntities) { ++ if (false && this.tickingEntities) { // Tuinity + throw (IllegalStateException) SystemUtils.c(new IllegalStateException("Removing entity while ticking!")); + } + +@@ -1253,6 +1714,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + + public void unregisterEntity(Entity entity) { + org.spigotmc.AsyncCatcher.catchOp("entity unregister"); // Spigot ++ this.entitiesForIteration.remove(entity); // Tuinity + // 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 +@@ -1319,12 +1781,16 @@ public class WorldServer extends World implements GeneratorAccessSeed { + this.getScoreboard().a(entity); + // CraftBukkit start - SPIGOT-5278 + if (entity instanceof EntityDrowned) { +- this.navigators.remove(((EntityDrowned) entity).navigationWater); +- this.navigators.remove(((EntityDrowned) entity).navigationLand); ++ // Tuinity start ++ this.navigators.remove(((EntityDrowned) entity).navigationWater); this.navigatorsForIteration.remove(((EntityDrowned) entity).navigationWater); ++ this.navigators.remove(((EntityDrowned) entity).navigationLand); this.navigatorsForIteration.remove(((EntityDrowned) entity).navigationLand); ++ // Tuinity end + } else + // CraftBukkit end + if (entity instanceof EntityInsentient) { +- this.navigators.remove(((EntityInsentient) entity).getNavigation()); ++ // Tuinity start ++ this.navigators.remove(((EntityInsentient) entity).getNavigation()); this.navigatorsForIteration.remove(((EntityInsentient) entity).getNavigation()); ++ // Tuinity end + } + new com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid + entity.valid = false; // CraftBukkit +@@ -1340,7 +1806,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + return; + } + // Paper end +- if (this.tickingEntities) { ++ if (false && this.tickingEntities) { // Tuinity + if (!entity.isQueuedForRegister) { // Paper + this.entitiesToAdd.add(entity); + entity.isQueuedForRegister = true; // Paper +@@ -1348,6 +1814,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } else { + entity.isQueuedForRegister = false; // Paper + this.entitiesById.put(entity.getId(), entity); ++ this.entitiesForIteration.add(entity); // Tuinity + if (entity instanceof EntityEnderDragon) { + EntityComplexPart[] aentitycomplexpart = ((EntityEnderDragon) entity).eK(); + int i = aentitycomplexpart.length; +@@ -1356,6 +1823,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + EntityComplexPart entitycomplexpart = aentitycomplexpart[j]; + + this.entitiesById.put(entitycomplexpart.getId(), entitycomplexpart); ++ this.entitiesForIteration.add(entitycomplexpart); // Tuinity + } + } + +@@ -1380,12 +1848,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) { +- this.navigators.add(((EntityDrowned) entity).navigationWater); +- this.navigators.add(((EntityDrowned) entity).navigationLand); ++ // Tuinity start ++ this.navigators.add(((EntityDrowned) entity).navigationWater); this.navigatorsForIteration.add(((EntityDrowned) entity).navigationWater); ++ this.navigators.add(((EntityDrowned) entity).navigationLand); this.navigatorsForIteration.add(((EntityDrowned) entity).navigationLand); ++ // Tuinity end + } else + // CraftBukkit end + if (entity instanceof EntityInsentient) { +- this.navigators.add(((EntityInsentient) entity).getNavigation()); ++ // Tuinity start ++ this.navigators.add(((EntityInsentient) entity).getNavigation()); this.navigatorsForIteration.add(((EntityInsentient) entity).getNavigation()); ++ // Tuinity end + } + entity.valid = true; // CraftBukkit + this.getChunkProvider().addEntity(entity); // Paper - from above to be below valid=true +@@ -1401,7 +1873,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + + public void removeEntity(Entity entity) { +- if (this.tickingEntities) { ++ if (false && this.tickingEntities) { // Tuinity + throw (IllegalStateException) SystemUtils.c(new IllegalStateException("Removing entity while ticking!")); + } else { + this.removeEntityFromChunk(entity); +@@ -1503,7 +1975,9 @@ public class WorldServer extends World implements GeneratorAccessSeed { + + if (VoxelShapes.c(voxelshape, voxelshape1, OperatorBoolean.NOT_SAME)) { + boolean wasTicking = this.tickingEntities; this.tickingEntities = true; // Paper +- Iterator iterator = this.navigators.iterator(); ++ // Tuinity start ++ com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet.Iterator iterator = this.navigatorsForIteration.iterator(); ++ try { // Tuinity end + + while (iterator.hasNext()) { + NavigationAbstract navigationabstract = (NavigationAbstract) iterator.next(); +@@ -1512,6 +1986,9 @@ public class WorldServer extends World implements GeneratorAccessSeed { + navigationabstract.b(blockposition); + } + } ++ } finally { // Tuinity start ++ iterator.finishedIterating(); ++ } // Tuinity end + + 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 5ccdc0b87..888dae2d5 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 { + int l = Integer.parseInt(matcher.group(2)) << 5; + + try { +- RegionFile regionfile = new RegionFile(file2, file1, true); ++ RegionFile regionfile = new RegionFile(file2, file1, true, true); // Tuinity - allow for chunk regionfiles to regen header + Throwable throwable = null; + + try { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java +index 4ec53a54e..31c81b4b5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java +@@ -77,7 +77,7 @@ public class CraftChunkSnapshot implements ChunkSnapshot { + public Material getBlockType(int x, int y, int z) { + CraftChunk.validateChunkCoordinates(x, y, z); + +- return CraftMagicNumbers.getMaterial(blockids[y >> 4].a(x, y & 0xF, z).getBlock()); ++ return blockids[y >> 4].a(x, y & 0xF, z).getBukkitMaterial(); // Tuinity - optimise getType calls + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 3bbc2d78b..cebcb845b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -229,7 +229,7 @@ import javax.annotation.Nullable; // Paper + import javax.annotation.Nonnull; // Paper + + public final class CraftServer implements Server { +- private final String serverName = "Paper"; // Paper ++ private final String serverName = "Tuinity"; // Paper // Tuinity + private final String serverVersion; + private final String bukkitVersion = Versioning.getBukkitVersion(); + private final Logger logger = Logger.getLogger("Minecraft"); +@@ -846,6 +846,7 @@ public final class CraftServer implements Server { + + org.spigotmc.SpigotConfig.init((File) console.options.valueOf("spigot-settings")); // Spigot + com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); // Paper ++ com.tuinity.tuinity.config.TuinityConfig.init((File) console.options.valueOf("tuinity-settings")); // Tuinity - Server Config + for (WorldServer world : console.getWorlds()) { + world.worldDataServer.setDifficulty(config.difficulty); + world.setSpawnFlags(config.spawnMonsters, config.spawnAnimals); +@@ -880,6 +881,7 @@ public final class CraftServer implements Server { + } + world.spigotConfig.init(); // Spigot + world.paperConfig.init(); // Paper ++ world.tuinityConfig.init(); // Tuinity - Server Config + } + + Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper +@@ -1817,7 +1819,10 @@ public final class CraftServer implements Server { + + @Override + public boolean isPrimaryThread() { +- return Thread.currentThread().equals(console.serverThread) || Thread.currentThread().equals(net.minecraft.server.MinecraftServer.getServer().shutdownThread); // Paper - Fix issues with detecting main thread properly, the only time Watchdog will be used is during a crash shutdown which is a "try our best" scenario ++ // Tuinity start ++ final Thread currThread = Thread.currentThread(); ++ return currThread == console.serverThread || currThread instanceof com.tuinity.tuinity.util.TickThread || currThread.equals(net.minecraft.server.MinecraftServer.getServer().shutdownThread); // Paper - Fix issues with detecting main thread properly, the only time Watchdog will be used is during a crash shutdown which is a "try our best" scenario ++ // Tuinity End + } + + @Override +@@ -2204,6 +2209,14 @@ public final class CraftServer implements Server { + return com.destroystokyo.paper.PaperConfig.config; + } + ++ // Tuinity start - add config to timings report ++ @Override ++ public YamlConfiguration getTuinityConfig() ++ { ++ return com.tuinity.tuinity.config.TuinityConfig.config; ++ } ++ // Tuinity end - add config to timings report ++ + @Override + 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 724c0816d..21bd9f14e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -336,6 +336,13 @@ public class CraftWorld implements World { + this.generator = gen; + + environment = env; ++ ++ //Tuinity start - per world spawn limits ++ monsterSpawn = world.tuinityConfig.spawnLimitMonsters; ++ animalSpawn = world.tuinityConfig.spawnLimitAnimals; ++ waterAnimalSpawn = world.tuinityConfig.spawnLimitWaterAnimals; ++ ambientSpawn = world.tuinityConfig.spawnLimitAmbient; ++ //Tuinity end + } + + @Override +@@ -402,14 +409,7 @@ public class CraftWorld implements World { + + @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); +- if (chunk == null) { +- addTicket(x, z); +- chunk = this.world.getChunkProvider().getChunkAt(x, z, true); +- } +- return chunk.bukkitChunk; +- // Paper end ++ return this.world.getChunkProvider().getChunkAt(x, z, true).bukkitChunk; // Tuinity - revert paper diff + } + + // Paper start +@@ -492,6 +492,7 @@ public class CraftWorld implements World { + org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot + if (isChunkLoaded(x, z)) { + world.getChunkProvider().removeTicket(TicketType.PLUGIN, new ChunkCoordIntPair(x, z), 0, Unit.INSTANCE); // Paper ++ ((ChunkMapDistance)world.getChunkProvider().playerChunkMap.getChunkMapDistanceManager()).removeTickets(ChunkCoordIntPair.pair(x, z), TicketType.DELAYED_UNLOAD); // Tuinity - delay chunk unloads - let plugins override + } + + return true; +@@ -2541,7 +2542,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); +- 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()); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index a8cd55d3c..a216b1336 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 { + .defaultsTo(new File("paper.yml")) + .describedAs("Yml file"); + // Paper end ++ // Tuinity Start - Server Config ++ acceptsAll(asList("tuinity", "tuinity-settings"), "File for tuinity settings") ++ .withRequiredArg() ++ .ofType(File.class) ++ .defaultsTo(new File("tuinity.yml")) ++ .describedAs("Yml file"); ++ /* Conctete End - Server Config */ + + // Paper start + acceptsAll(asList("server-name"), "Name of the server") +@@ -252,7 +259,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! ***"); +- System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads ***"); // Paper ++ System.err.println("*** Please download a new build ***"); // Paper // Tuinity + //System.err.println("*** Server will start in 20 seconds ***"); + //Thread.sleep(TimeUnit.SECONDS.toMillis(20)); + // Paper End +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index 9b0e868f0..ee53060b1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -207,7 +207,7 @@ public class CraftBlock implements Block { + + @Override + public Material getType() { +- return CraftMagicNumbers.getMaterial(world.getType(position).getBlock()); ++ return world.getType(position).getBukkitMaterial(); // Tuinity - optimise getType calls + } + + @Override +@@ -505,15 +505,30 @@ public class CraftBlock implements Block { + return null; + } + +- return Biome.valueOf(IRegistry.BIOME.getKey(base).getKey().toUpperCase(java.util.Locale.ENGLISH)); ++ return base.getBukkitBiome(); // Tuinity - optimise biome conversion + } + ++ private static final java.util.EnumMap BUKKIT_BIOME_TO_NMS_CACHE = new java.util.EnumMap<>(Biome.class); // Tuinity - optimise biome conversion ++ + public static BiomeBase biomeToBiomeBase(Biome bio) { + if (bio == null) { + return null; + } + +- return IRegistry.BIOME.get(new MinecraftKey(bio.name().toLowerCase(java.util.Locale.ENGLISH))); ++ // Tuinity start - optimise biome conversion ++ BiomeBase cached = BUKKIT_BIOME_TO_NMS_CACHE.get(bio); ++ ++ if (cached != null) { ++ return cached; ++ } ++ ++ BiomeBase ret = IRegistry.BIOME.get(new MinecraftKey(bio.name().toLowerCase(java.util.Locale.ENGLISH))); ++ synchronized (BUKKIT_BIOME_TO_NMS_CACHE) { ++ BUKKIT_BIOME_TO_NMS_CACHE.put(bio, ret); ++ } ++ ++ return ret; ++ // Tuinity end - optimise biome conversion + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java +index 11aa2dc18..c51c43573 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java +@@ -136,7 +136,7 @@ public class CraftBlockState implements BlockState { + + @Override + public Material getType() { +- return CraftMagicNumbers.getMaterial(data.getBlock()); ++ return data.getBukkitMaterial(); // Tuinity - optimise getType calls + } + + public void setFlag(int flag) { +diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java +index bbded5671..980890153 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java +@@ -44,7 +44,7 @@ public class CraftBlockData implements BlockData { + + @Override + public Material getMaterial() { +- return CraftMagicNumbers.getMaterial(state.getBlock()); ++ return state.getBukkitMaterial(); // Tuinity - optimise getType calls + } + + public IBlockData getState() { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 821417610..db330f573 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -527,6 +527,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) { ++ Preconditions.checkArgument(location != null, "location"); ++ 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(); ++ 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.MinecraftServer.getServer().scheduleOnMain(() -> { ++ try { ++ ret.complete(CraftEntity.this.teleport(locationClone, cause) ? Boolean.TRUE : Boolean.FALSE); ++ } catch (Throwable throwable) { ++ if (throwable instanceof ThreadDeath) { ++ throw (ThreadDeath)throwable; ++ } ++ ret.completeExceptionally(throwable); ++ } ++ }); ++ }); ++ ++ return ret; ++ } ++ // Tuinity end - implement teleportAsync better ++ + @Override + public boolean teleport(org.bukkit.entity.Entity destination) { + return teleport(destination.getLocation()); +diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +index bb18740eb..b048ec8ea 100644 +--- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java ++++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +@@ -73,7 +73,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { + + @Override + public Material getType(int x, int y, int z) { +- return CraftMagicNumbers.getMaterial(getTypeId(x, y, z).getBlock()); ++ return getTypeId(x, y, z).getBukkitMaterial(); // Tuinity - optimise getType calls + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java +index ca2be3060..2c5701376 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java +@@ -100,9 +100,18 @@ public final class CraftScoreboardManager implements ScoreboardManager { + + // CraftBukkit method + public void getScoreboardScores(IScoreboardCriteria criteria, String name, Consumer consumer) { ++ // Tuinity start - add timings for scoreboard search ++ // plugins leaking scoreboards will make this very expensive, let server owners debug it easily ++ co.aikar.timings.MinecraftTimings.scoreboardScoreSearch.startTimingIfSync(); ++ try { ++ // Tuinity end - add timings for scoreboard search + for (CraftScoreboard scoreboard : scoreboards) { + Scoreboard board = scoreboard.board; + board.getObjectivesForCriteria(criteria, name, (score) -> consumer.accept(score)); + } ++ } finally { // Tuinity start - add timings for scoreboard search ++ co.aikar.timings.MinecraftTimings.scoreboardScoreSearch.stopTimingIfSync(); ++ } ++ // Tuinity end - add timings for scoreboard search + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java +index f72c13bed..50f855b93 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java +@@ -119,6 +119,32 @@ public class UnsafeList extends AbstractList implements List, RandomAcc + return indexOf(o) >= 0; + } + ++ // Tuinity start ++ protected transient int maxSize; ++ public void setSize(int size) { ++ if (this.maxSize < this.size) { ++ this.maxSize = this.size; ++ } ++ this.size = size; ++ } ++ ++ public void completeReset() { ++ if (this.data != null) { ++ Arrays.fill(this.data, 0, Math.max(this.size, this.maxSize), null); ++ } ++ this.size = 0; ++ this.maxSize = 0; ++ if (this.iterPool != null) { ++ for (Iterator temp : this.iterPool) { ++ if (temp == null) { ++ continue; ++ } ++ ((Itr)temp).valid = false; ++ } ++ } ++ } ++ // Tuinity end ++ + @Override + public void clear() { + // Create new array to reset memory usage to initial capacity +diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +index 674096cab..001b1e519 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +@@ -11,7 +11,7 @@ public final class Versioning { + public static String getBukkitVersion() { + String result = "Unknown-Version"; + +- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/com.destroystokyo.paper/paper-api/pom.properties"); ++ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/com.tuinity/tuinity-api/pom.properties"); // Tuinity + Properties properties = new Properties(); + + if (stream != null) { +diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java +index 9f7d2ef93..c3ac1a46c 100644 +--- a/src/main/java/org/spigotmc/AsyncCatcher.java ++++ b/src/main/java/org/spigotmc/AsyncCatcher.java +@@ -10,7 +10,7 @@ public class AsyncCatcher + + public static void catchOp(String reason) + { +- if ( enabled && Thread.currentThread() != MinecraftServer.getServer().serverThread ) ++ if ( ( enabled || com.tuinity.tuinity.util.TickThread.STRICT_THREAD_CHECKS ) && !org.bukkit.Bukkit.isPrimaryThread() ) // Tuinity + { + throw new IllegalStateException( "Asynchronous " + reason + "!" ); + } +diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java +index 513c1041c..4d3109084 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -61,6 +61,84 @@ public class WatchdogThread extends Thread + } + } + ++ // Tuinity start - log detailed tick information ++ private void dumpTickingInfo() { ++ Logger log = Bukkit.getServer().getLogger(); ++ ++ // ticking entities ++ for (net.minecraft.server.Entity entity : net.minecraft.server.WorldServer.getCurrentlyTickingEntities()) { ++ double posX, posY, posZ; ++ net.minecraft.server.Vec3D mot; ++ double moveStartX, moveStartY, moveStartZ; ++ net.minecraft.server.Vec3D moveVec; ++ synchronized (entity.posLock) { ++ posX = entity.locX(); ++ posY = entity.locY(); ++ posZ = entity.locZ(); ++ mot = entity.getMot(); ++ moveStartX = entity.getMoveStartX(); ++ moveStartY = entity.getMoveStartY(); ++ moveStartZ = entity.getMoveStartZ(); ++ moveVec = entity.getMoveVector(); ++ } ++ ++ String entityType = entity.getMinecraftKey().toString(); ++ java.util.UUID entityUUID = entity.getUniqueID(); ++ net.minecraft.server.World world = entity.getWorld(); ++ ++ log.log(Level.SEVERE, "Ticking entity: " + entityType); ++ log.log(Level.SEVERE, "Position: world: '" + (world == null ? "unknown world?" : world.getWorld().getName()) + "' at location (" + posX + ", " + posY + ", " + posZ + ")"); ++ log.log(Level.SEVERE, "Velocity: " + (mot == null ? "unknown velocity" : mot.toString()) + " (in blocks per tick)"); ++ if (moveVec != null) { ++ log.log(Level.SEVERE, "Move call information: "); ++ log.log(Level.SEVERE, "Start position: (" + moveStartX + ", " + moveStartY + ", " + moveStartZ + ")"); ++ log.log(Level.SEVERE, "Move vector: " + moveVec.toString()); ++ } ++ log.log(Level.SEVERE, "UUID: " + entityUUID); ++ } ++ ++ // 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(); ++ if (player == null) { ++ log.log(Level.SEVERE, "Handling packet for player connection (null player): " + packetListener); ++ log.log(Level.SEVERE, "Total packets processed on the main thread for all players: " + totalPackets); ++ } else { ++ // exclude velocity, this is set client side... Paper will also warn on high velocity set too ++ double posX, posY, posZ; ++ double moveStartX, moveStartY, moveStartZ; ++ net.minecraft.server.Vec3D moveVec; ++ synchronized (player.posLock) { ++ posX = player.locX(); ++ posY = player.locY(); ++ posZ = player.locZ(); ++ moveStartX = player.getMoveStartX(); ++ moveStartY = player.getMoveStartY(); ++ moveStartZ = player.getMoveStartZ(); ++ moveVec = player.getMoveVector(); ++ } ++ ++ java.util.UUID entityUUID = player.getUniqueID(); ++ net.minecraft.server.World world = player.getWorld(); ++ ++ log.log(Level.SEVERE, "Handling packet for player '" + player.getName() + "', UUID: " + entityUUID); ++ log.log(Level.SEVERE, "Position: world: '" + (world == null ? "unknown world?" : world.getWorld().getName()) + "' at location (" + posX + ", " + posY + ", " + posZ + ")"); ++ if (moveVec != null) { ++ log.log(Level.SEVERE, "Move call information: "); ++ log.log(Level.SEVERE, "Start position: (" + moveStartX + ", " + moveStartY + ", " + moveStartZ + ")"); ++ log.log(Level.SEVERE, "Move vector: " + moveVec.toString()); ++ } ++ log.log(Level.SEVERE, "Total packets processed on the main thread for all players: " + totalPackets); ++ } ++ } else { ++ log.log(Level.SEVERE, "Handling packet for connection: " + packetListener); ++ } ++ } ++ } ++ // Tuinity end - log detailed tick information ++ + @Override + public void run() + { +@@ -117,6 +195,7 @@ public class WatchdogThread extends Thread + log.log( Level.SEVERE, "------------------------------" ); + log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper + ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper ++ this.dumpTickingInfo(); // Tuinity - log detailed tick information + dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( server.serverThread.getId(), Integer.MAX_VALUE ), log ); + log.log( Level.SEVERE, "------------------------------" ); + // +-- +2.26.2 + diff --git a/patches/server/0001-Rebrand.patch b/patches/server/0002-Rebrand.patch similarity index 87% rename from patches/server/0001-Rebrand.patch rename to patches/server/0002-Rebrand.patch index 47df01761..da985577d 100644 --- a/patches/server/0001-Rebrand.patch +++ b/patches/server/0002-Rebrand.patch @@ -1,33 +1,33 @@ -From 4c46391a0e33451b0574cacdc1596a713f90f05d Mon Sep 17 00:00:00 2001 +From 1785535c59fd991e1c0eeb05bd4834135cb1cfbe Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 4 May 2019 01:02:11 -0500 Subject: [PATCH] Rebrand --- - pom.xml | 33 +++-- + pom.xml | 35 ++++-- .../paper/console/PaperConsole.java | 2 +- .../net/minecraft/server/MinecraftServer.java | 2 +- .../net/pl3x/purpur/PurpurVersionFetcher.java | 115 ++++++++++++++++++ .../org/bukkit/craftbukkit/CraftServer.java | 2 +- .../craftbukkit/util/CraftMagicNumbers.java | 2 +- .../bukkit/craftbukkit/util/Versioning.java | 2 +- - 7 files changed, 143 insertions(+), 15 deletions(-) + 7 files changed, 144 insertions(+), 16 deletions(-) create mode 100644 src/main/java/net/pl3x/purpur/PurpurVersionFetcher.java diff --git a/pom.xml b/pom.xml -index ef8ee637a..8044fa074 100644 +index 6fd596817..285fa63b3 100644 --- a/pom.xml +++ b/pom.xml @@ -1,12 +1,11 @@ - 4.0.0 -- paper +- tuinity + purpur jar 1.16.1-R0.1-SNAPSHOT -- Paper -- https://papermc.io +- Tuinity-Server +- https://github.com/Spottedleaf/Tuinity - + Purpur + http://pl3x.net @@ -38,8 +38,8 @@ index ef8ee637a..8044fa074 100644 -- com.destroystokyo.paper -- paper-parent +- com.tuinity +- tuinity-parent + net.pl3x.purpur + purpur-parent dev-SNAPSHOT @@ -48,8 +48,8 @@ index ef8ee637a..8044fa074 100644 -- com.destroystokyo.paper -- paper-api +- com.tuinity +- tuinity-api + net.pl3x.purpur + purpur-api ${project.version} @@ -76,20 +76,21 @@ index ef8ee637a..8044fa074 100644 net.minecrell terminalconsoleappender -@@ -164,7 +177,7 @@ +@@ -164,15 +177,15 @@ -- paper-${minecraft.version} +- tuinity-${minecraft.version} +- install + purpur-${minecraft.version} - clean install ++ clean install -@@ -172,7 +185,7 @@ + com.lukegb.mojo gitdescribe-maven-plugin 1.3 -- git-Paper- +- git-Tuinity- + git-Purpur- .. @@ -108,15 +109,15 @@ index 74ed02fa9..c1280478e 100644 .completer(new ConsoleCommandCompleter(this.server)) ); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 26f230a80..d06536aba 100644 +index eb71fa6e3..e23e47ee7 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1446,7 +1446,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant // Spigot - Spigot > // CraftBukkit - cb > vanilla! -+ return "Purpur"; // Purpur // Paper // Spigot // CraftBukkit +- return "Tuinity"; // Tuinity //Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! ++ return "Purpur"; // Purpur // Tuinity // Paper // Spigot // CraftBukkit } public CrashReport b(CrashReport crashreport) { @@ -242,15 +243,15 @@ index 000000000..d8b408f06 + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 3bbc2d78b..1d5cb1548 100644 +index cebcb845b..56a2db25f 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -229,7 +229,7 @@ import javax.annotation.Nullable; // Paper import javax.annotation.Nonnull; // Paper public final class CraftServer implements Server { -- private final String serverName = "Paper"; // Paper -+ private final String serverName = "Purpur"; // Paper // Purpur +- private final String serverName = "Tuinity"; // Paper // Tuinity ++ private final String serverName = "Purpur"; // Paper // Tuinity // Purpur private final String serverVersion; private final String bukkitVersion = Versioning.getBukkitVersion(); private final Logger logger = Logger.getLogger("Minecraft"); @@ -268,15 +269,15 @@ index f1e60981a..1fe87d763 100644 @Override diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -index 674096cab..e9aee2d8a 100644 +index 001b1e519..13b984393 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java @@ -11,7 +11,7 @@ public final class Versioning { public static String getBukkitVersion() { String result = "Unknown-Version"; -- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/com.destroystokyo.paper/paper-api/pom.properties"); -+ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/net.pl3x.purpur/purpur-api/pom.properties"); // Purpur +- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/com.tuinity/tuinity-api/pom.properties"); // Tuinity ++ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/net.pl3x.purpur/purpur-api/pom.properties"); // Tuinity // Purpur Properties properties = new Properties(); if (stream != null) { diff --git a/patches/server/0002-Purpur-config-files.patch b/patches/server/0003-Purpur-config-files.patch similarity index 88% rename from patches/server/0002-Purpur-config-files.patch rename to patches/server/0003-Purpur-config-files.patch index 7d6aabe1d..f658b3161 100644 --- a/patches/server/0002-Purpur-config-files.patch +++ b/patches/server/0003-Purpur-config-files.patch @@ -1,24 +1,24 @@ -From 99870e5b09eef243de5335b21a4efbeb4b427322 Mon Sep 17 00:00:00 2001 +From a4e1b9d46aea64612ae6df1aa6e8e4f8e63962f6 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Thu, 9 May 2019 18:09:43 -0500 Subject: [PATCH] Purpur config files --- - .../java/com/destroystokyo/paper/Metrics.java | 6 +- + .../java/com/destroystokyo/paper/Metrics.java | 7 +- .../net/minecraft/server/DedicatedServer.java | 9 ++ src/main/java/net/minecraft/server/World.java | 2 + .../java/net/pl3x/purpur/PurpurConfig.java | 130 ++++++++++++++++++ - .../net/pl3x/purpur/PurpurWorldConfig.java | 67 +++++++++ - .../pl3x/purpur/command/PurpurCommand.java | 67 +++++++++ + .../net/pl3x/purpur/PurpurWorldConfig.java | 59 ++++++++ + .../pl3x/purpur/command/PurpurCommand.java | 65 +++++++++ .../org/bukkit/craftbukkit/CraftServer.java | 15 ++ .../java/org/bukkit/craftbukkit/Main.java | 8 ++ - 8 files changed, 301 insertions(+), 3 deletions(-) + 8 files changed, 292 insertions(+), 3 deletions(-) create mode 100644 src/main/java/net/pl3x/purpur/PurpurConfig.java create mode 100644 src/main/java/net/pl3x/purpur/PurpurWorldConfig.java create mode 100644 src/main/java/net/pl3x/purpur/command/PurpurCommand.java diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java -index 24641501a..b767dd1d0 100644 +index 24641501a..78369e670 100644 --- a/src/main/java/com/destroystokyo/paper/Metrics.java +++ b/src/main/java/com/destroystokyo/paper/Metrics.java @@ -581,7 +581,7 @@ public class Metrics { @@ -30,7 +30,7 @@ index 24641501a..b767dd1d0 100644 metrics.addCustomChart(new Metrics.SimplePie("minecraft_version", () -> { String minecraftVersion = Bukkit.getVersion(); -@@ -590,8 +590,8 @@ public class Metrics { +@@ -590,8 +590,9 @@ public class Metrics { })); metrics.addCustomChart(new Metrics.SingleLineChart("players", () -> Bukkit.getOnlinePlayers().size())); @@ -38,11 +38,12 @@ index 24641501a..b767dd1d0 100644 - metrics.addCustomChart(new Metrics.SimplePie("paper_version", () -> (Metrics.class.getPackage().getImplementationVersion() != null) ? Metrics.class.getPackage().getImplementationVersion() : "unknown")); + metrics.addCustomChart(new Metrics.SimplePie("online_mode", () -> Bukkit.getOnlineMode() ? "online" : (Bukkit.spigot().getSpigotConfig().getBoolean("settings.bungeecord") ? "bungee" : "offline"))); // Purpur + metrics.addCustomChart(new Metrics.SimplePie("purpur_version", () -> (Metrics.class.getPackage().getImplementationVersion() != null) ? Metrics.class.getPackage().getImplementationVersion() : "unknown")); // Purpur ++ metrics.addCustomChart(new Metrics.DrilldownPie("java_version", () -> { Map> map = new HashMap<>(); diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java -index 8b2755a3b..df75a9e8a 100644 +index 578f7809c..21dc3b9a6 100644 --- a/src/main/java/net/minecraft/server/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/DedicatedServer.java @@ -168,6 +168,15 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer @@ -60,27 +61,27 @@ index 8b2755a3b..df75a9e8a 100644 + // Purpur end 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 diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index b598c4869..c59282ef3 100644 +index 8df4ef488..aaef3bf59 100644 --- a/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java -@@ -91,6 +91,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public boolean populating; - public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot - -+ public final net.pl3x.purpur.PurpurWorldConfig purpurConfig; // Purpur - public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper +@@ -95,6 +95,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { public final ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray -@@ -120,6 +121,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - protected World(WorldDataMutable worlddatamutable, ResourceKey resourcekey, ResourceKey resourcekey1, 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) { - this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((WorldDataServer) worlddatamutable).getName()); // Spigot + public final com.tuinity.tuinity.config.TuinityConfig.WorldConfig tuinityConfig; // Tuinity - Server Config ++ public final net.pl3x.purpur.PurpurWorldConfig purpurConfig; // Purpur + + public final co.aikar.timings.WorldTimingsHandler timings; // Paper + public static BlockPosition lastPhysicsProblem; // Spigot +@@ -124,6 +125,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig((((WorldDataServer)worlddatamutable).getName()), this.spigotConfig); // Paper -+ this.purpurConfig = new net.pl3x.purpur.PurpurWorldConfig((((WorldDataServer)worlddatamutable).getName()), this.paperConfig, this.spigotConfig); // Purpur this.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this.paperConfig, 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.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/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java new file mode 100644 index 000000000..333c880bf @@ -219,30 +220,22 @@ index 000000000..333c880bf +} diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java new file mode 100644 -index 000000000..eda37fa43 +index 000000000..8c4b5f514 --- /dev/null +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -0,0 +1,67 @@ +@@ -0,0 +1,59 @@ +package net.pl3x.purpur; + -+import com.destroystokyo.paper.PaperWorldConfig; +import org.bukkit.configuration.ConfigurationSection; -+import org.spigotmc.SpigotWorldConfig; -+ +import java.util.List; -+ +import static net.pl3x.purpur.PurpurConfig.log; + +public class PurpurWorldConfig { + + private final String worldName; -+ private final PaperWorldConfig paperConfig; -+ private final SpigotWorldConfig spigotConfig; + -+ public PurpurWorldConfig(String worldName, PaperWorldConfig paperConfig, SpigotWorldConfig spigotConfig) { ++ public PurpurWorldConfig(String worldName) { + this.worldName = worldName; -+ this.paperConfig = paperConfig; -+ this.spigotConfig = spigotConfig; + init(); + } + @@ -292,10 +285,10 @@ index 000000000..eda37fa43 +} 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 000000000..7d983d9a5 +index 000000000..4904be939 --- /dev/null +++ b/src/main/java/net/pl3x/purpur/command/PurpurCommand.java -@@ -0,0 +1,67 @@ +@@ -0,0 +1,65 @@ +package net.pl3x.purpur.command; + +import net.minecraft.server.MinecraftServer; @@ -351,9 +344,7 @@ index 000000000..7d983d9a5 + console.server.reloadCount++; + + Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Purpur config reload complete."); -+ } -+ -+ else if (args[0].equalsIgnoreCase("version")) { ++ } else if (args[0].equalsIgnoreCase("version")) { + Command verCmd = org.bukkit.Bukkit.getServer().getCommandMap().getCommand("version"); + if (verCmd != null) { + return verCmd.execute(sender, commandLabel, new String[0]); @@ -364,26 +355,26 @@ index 000000000..7d983d9a5 + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 1026fd81b..6c602ef79 100644 +index 56a2db25f..957baebc4 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -846,6 +846,7 @@ public final class CraftServer implements Server { - +@@ -847,6 +847,7 @@ public final class CraftServer implements Server { org.spigotmc.SpigotConfig.init((File) console.options.valueOf("spigot-settings")); // Spigot com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); // Paper + com.tuinity.tuinity.config.TuinityConfig.init((File) console.options.valueOf("tuinity-settings")); // Tuinity - Server Config + net.pl3x.purpur.PurpurConfig.init((File) console.options.valueOf("purpur-settings")); // Purpur for (WorldServer world : console.getWorlds()) { world.worldDataServer.setDifficulty(config.difficulty); world.setSpawnFlags(config.spawnMonsters, config.spawnAnimals); -@@ -880,6 +881,7 @@ public final class CraftServer implements Server { - } +@@ -882,6 +883,7 @@ public final class CraftServer implements Server { world.spigotConfig.init(); // Spigot world.paperConfig.init(); // Paper + world.tuinityConfig.init(); // Tuinity - Server Config + world.purpurConfig.init(); // Purpur } Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper -@@ -898,6 +900,7 @@ public final class CraftServer implements Server { +@@ -900,6 +902,7 @@ public final class CraftServer implements Server { reloadData(); org.spigotmc.SpigotConfig.registerCommands(); // Spigot com.destroystokyo.paper.PaperConfig.registerCommands(); // Paper @@ -391,9 +382,9 @@ index 1026fd81b..6c602ef79 100644 overrideAllCommandBlockCommands = commandsConfiguration.getStringList("command-block-overrides").contains("*"); ignoreVanillaPermissions = commandsConfiguration.getBoolean("ignore-vanilla-permissions"); -@@ -2204,6 +2207,18 @@ public final class CraftServer implements Server { - return com.destroystokyo.paper.PaperConfig.config; +@@ -2217,6 +2220,18 @@ public final class CraftServer implements Server { } + // Tuinity end - add config to timings report + // Purpur start + @Override @@ -411,12 +402,12 @@ index 1026fd81b..6c602ef79 100644 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 83151f3d7..8879c6421 100644 +index a216b1336..c1e7e6a45 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -139,6 +139,14 @@ public class Main { +@@ -146,6 +146,14 @@ public class Main { .describedAs("Yml file"); - // Paper end + /* Conctete End - Server Config */ + // Purpur Start + acceptsAll(asList("purpur", "purpur-settings"), "File for purpur settings") diff --git a/patches/server/0003-Timings-stuff.patch b/patches/server/0004-Timings-stuff.patch similarity index 76% rename from patches/server/0003-Timings-stuff.patch rename to patches/server/0004-Timings-stuff.patch index 63da3fc9b..d76de79db 100644 --- a/patches/server/0003-Timings-stuff.patch +++ b/patches/server/0004-Timings-stuff.patch @@ -1,34 +1,36 @@ -From 89bd8621126f5990f782a9709221523940f229df Mon Sep 17 00:00:00 2001 +From bc659814e1291b1efc14e0b8c7940db3423008d6 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 5 Jun 2020 21:30:19 -0500 Subject: [PATCH] Timings stuff --- - .../java/co/aikar/timings/TimingsExport.java | 25 ++++++++++++++++--- - 1 file changed, 21 insertions(+), 4 deletions(-) + .../java/co/aikar/timings/TimingsExport.java | 27 +++++++++++++++---- + 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java -index e33e889c2..29174d903 100644 +index 5dfa06588..dae2e5d70 100644 --- a/src/main/java/co/aikar/timings/TimingsExport.java +++ b/src/main/java/co/aikar/timings/TimingsExport.java -@@ -227,9 +227,13 @@ public class TimingsExport extends Thread { +@@ -227,10 +227,14 @@ public class TimingsExport extends Thread { // Information on the users Config parent.put("config", createObject( - pair("spigot", mapAsJSON(Bukkit.spigot().getSpigotConfig(), null)), - pair("bukkit", mapAsJSON(Bukkit.spigot().getBukkitConfig(), null)), -- pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)) +- pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)), // Tuinity - add config to timings report +- pair("tuinity", mapAsJSON(Bukkit.spigot().getTuinityConfig(), null)) // Tuinity - add config to timings report + // Purpur start + pair("server.properties", mapAsJSON(Bukkit.spigot().getServerProperties())), + pair("bukkit", mapAsJSON(Bukkit.spigot().getBukkitConfig(), null)), + pair("spigot", mapAsJSON(Bukkit.spigot().getSpigotConfig(), null)), + pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)), ++ pair("tuinity", mapAsJSON(Bukkit.spigot().getTuinityConfig(), null)), // Tuinity - add config to timings report + pair("purpur", mapAsJSON(Bukkit.spigot().getPurpurConfig(), null)) + // Purpur end )); new TimingsExport(listeners, parent, history).start(); -@@ -270,6 +274,19 @@ public class TimingsExport extends Thread { +@@ -271,6 +275,19 @@ public class TimingsExport extends Thread { return timingsCost; } @@ -48,7 +50,7 @@ index e33e889c2..29174d903 100644 private static JSONObject mapAsJSON(ConfigurationSection config, String parentKey) { JSONObject object = new JSONObject(); -@@ -306,7 +323,7 @@ public class TimingsExport extends Thread { +@@ -307,7 +324,7 @@ public class TimingsExport extends Thread { String response = null; String timingsURL = null; try { diff --git a/patches/server/0004-Barrels-and-enderchests-6-rows.patch b/patches/server/0005-Barrels-and-enderchests-6-rows.patch similarity index 99% rename from patches/server/0004-Barrels-and-enderchests-6-rows.patch rename to patches/server/0005-Barrels-and-enderchests-6-rows.patch index 528ad77a4..c45dd048c 100644 --- a/patches/server/0004-Barrels-and-enderchests-6-rows.patch +++ b/patches/server/0005-Barrels-and-enderchests-6-rows.patch @@ -1,4 +1,4 @@ -From 6946e2a10fd1cb63084783c07c277936405d9b65 Mon Sep 17 00:00:00 2001 +From 1bbb9cf5c61f902c0c65e8cdc41ae27b6c3fc9c6 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Thu, 23 May 2019 21:50:37 -0500 Subject: [PATCH] Barrels and enderchests 6 rows diff --git a/patches/server/0005-Advancement-API.patch b/patches/server/0006-Advancement-API.patch similarity index 99% rename from patches/server/0005-Advancement-API.patch rename to patches/server/0006-Advancement-API.patch index 31e04800c..18d8fc708 100644 --- a/patches/server/0005-Advancement-API.patch +++ b/patches/server/0006-Advancement-API.patch @@ -1,4 +1,4 @@ -From f38bc41c719f4ec2f111350a6fb57cdf1cb1444a Mon Sep 17 00:00:00 2001 +From f9e2498834beb19689a969fb82358791dead4355 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 31 May 2019 21:24:33 -0500 Subject: [PATCH] Advancement API diff --git a/patches/server/0006-Llama-API.patch b/patches/server/0007-Llama-API.patch similarity index 99% rename from patches/server/0006-Llama-API.patch rename to patches/server/0007-Llama-API.patch index 0a2edbaf4..541390d08 100644 --- a/patches/server/0006-Llama-API.patch +++ b/patches/server/0007-Llama-API.patch @@ -1,4 +1,4 @@ -From ce23a90cbb5d648a846bdfc45696a55bab8a3ed9 Mon Sep 17 00:00:00 2001 +From 70dd31ae817bfcfb9e4b293673d48d009fcf73e1 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 18 Oct 2019 22:50:12 -0500 Subject: [PATCH] Llama API diff --git a/patches/server/0007-Evoker-API.patch b/patches/server/0008-Evoker-API.patch similarity index 98% rename from patches/server/0007-Evoker-API.patch rename to patches/server/0008-Evoker-API.patch index 807bf81cf..d6ddc00f9 100644 --- a/patches/server/0007-Evoker-API.patch +++ b/patches/server/0008-Evoker-API.patch @@ -1,4 +1,4 @@ -From b509638d3539212f7aa2d9dd86aebaac925ac2ab Mon Sep 17 00:00:00 2001 +From dfb25a8ebbc77cc96c5f8b3a7efb69c887e13669 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 19 Oct 2019 00:29:02 -0500 Subject: [PATCH] Evoker API diff --git a/patches/server/0008-AFK-API.patch b/patches/server/0009-AFK-API.patch similarity index 93% rename from patches/server/0008-AFK-API.patch rename to patches/server/0009-AFK-API.patch index 0f7ef8725..ece2a39ab 100644 --- a/patches/server/0008-AFK-API.patch +++ b/patches/server/0009-AFK-API.patch @@ -1,4 +1,4 @@ -From 331e2763353e816b3e1e8aa237d2343967486f2c Mon Sep 17 00:00:00 2001 +From 9cd56eb534d4b80984130f44742196cab273b9c4 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Thu, 8 Aug 2019 15:29:15 -0500 Subject: [PATCH] AFK API @@ -18,10 +18,10 @@ Subject: [PATCH] AFK API 11 files changed, 120 insertions(+), 25 deletions(-) diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index fcb3d3adae..405a5d87d8 100644 +index f8ca56be8..3ba812843 100644 --- a/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java -@@ -1384,6 +1384,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +@@ -1571,6 +1571,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke return MathHelper.c(f * f + f1 * f1 + f2 * f2); } @@ -30,7 +30,7 @@ index fcb3d3adae..405a5d87d8 100644 double d3 = this.locX() - d0; double d4 = this.locY() - d1; diff --git a/src/main/java/net/minecraft/server/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java -index 2cada09ced..a69a698594 100644 +index 2cada09ce..a69a69859 100644 --- a/src/main/java/net/minecraft/server/EntityHuman.java +++ b/src/main/java/net/minecraft/server/EntityHuman.java @@ -84,6 +84,15 @@ public abstract class EntityHuman extends EntityLiving { @@ -50,7 +50,7 @@ index 2cada09ced..a69a698594 100644 super(EntityTypes.PLAYER, world); this.bS = ItemStack.b; diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index eeed8edfdf..508a91418e 100644 +index eeed8edfd..508a91418 100644 --- a/src/main/java/net/minecraft/server/EntityPlayer.java +++ b/src/main/java/net/minecraft/server/EntityPlayer.java @@ -1752,8 +1752,54 @@ public class EntityPlayer extends EntityHuman implements ICrafting { @@ -109,10 +109,10 @@ index eeed8edfdf..508a91418e 100644 return this.serverStatisticManager; } diff --git a/src/main/java/net/minecraft/server/IEntityAccess.java b/src/main/java/net/minecraft/server/IEntityAccess.java -index 267a6baae8..d3ea51c27c 100644 +index 0edcb775e..dfa8f3439 100644 --- a/src/main/java/net/minecraft/server/IEntityAccess.java +++ b/src/main/java/net/minecraft/server/IEntityAccess.java -@@ -143,28 +143,18 @@ public interface IEntityAccess { +@@ -144,28 +144,18 @@ public interface IEntityAccess { } // Paper end @@ -154,7 +154,7 @@ index 267a6baae8..d3ea51c27c 100644 @Nullable diff --git a/src/main/java/net/minecraft/server/IEntitySelector.java b/src/main/java/net/minecraft/server/IEntitySelector.java -index a52dd0c021..9b4795f3bd 100644 +index a52dd0c02..9b4795f3b 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; @@ -174,7 +174,7 @@ index a52dd0c021..9b4795f3bd 100644 // 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 cf83059fec..0d8daf4569 100644 +index c40255263..6be2c0192 100644 --- a/src/main/java/net/minecraft/server/PlayerConnection.java +++ b/src/main/java/net/minecraft/server/PlayerConnection.java @@ -232,6 +232,12 @@ public class PlayerConnection implements PacketListenerPlayIn { @@ -190,7 +190,7 @@ index cf83059fec..0d8daf4569 100644 this.player.resetIdleTimer(); // CraftBukkit - SPIGOT-854 this.disconnect(new ChatMessage("multiplayer.disconnect.idling")); } -@@ -448,6 +454,8 @@ public class PlayerConnection implements PacketListenerPlayIn { +@@ -455,6 +461,8 @@ public class PlayerConnection implements PacketListenerPlayIn { this.lastYaw = to.getYaw(); this.lastPitch = to.getPitch(); @@ -199,7 +199,7 @@ index cf83059fec..0d8daf4569 100644 // Skip the first time we do this if (true) { // Spigot - don't skip any move events Location oldTo = to.clone(); -@@ -1117,7 +1125,7 @@ public class PlayerConnection implements PacketListenerPlayIn { +@@ -1129,7 +1137,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; @@ -208,7 +208,7 @@ index cf83059fec..0d8daf4569 100644 } this.player.setLocation(d4, d5, d6, f, f1); -@@ -1156,6 +1164,8 @@ public class PlayerConnection implements PacketListenerPlayIn { +@@ -1168,6 +1176,8 @@ public class PlayerConnection implements PacketListenerPlayIn { this.lastYaw = to.getYaw(); this.lastPitch = to.getPitch(); @@ -218,10 +218,10 @@ index cf83059fec..0d8daf4569 100644 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 3a740f5669..1dfd8a9598 100644 +index 6d37bbfeb..578cc6888 100644 --- a/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java -@@ -425,7 +425,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -862,7 +862,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { // CraftBukkit end if (this.everyoneSleeping && this.players.stream().noneMatch((entityplayer) -> { @@ -230,7 +230,7 @@ index 3a740f5669..1dfd8a9598 100644 })) { // CraftBukkit start long l = this.worldData.getDayTime() + 24000L; -@@ -745,7 +745,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -1182,7 +1182,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { while (iterator.hasNext()) { EntityPlayer entityplayer = (EntityPlayer) iterator.next(); @@ -240,7 +240,7 @@ index 3a740f5669..1dfd8a9598 100644 } 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 fc38163b19..cc08ad33e4 100644 +index fc38163b1..cc08ad33e 100644 --- a/src/main/java/net/pl3x/purpur/PurpurConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java @@ -1,6 +1,7 @@ @@ -266,10 +266,10 @@ index fc38163b19..cc08ad33e4 100644 private static void timingsSettings() { timingsUrl = getString("settings.timings.url", timingsUrl); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index eda37fa43f..5fa3330373 100644 +index 8c4b5f514..9ec1c5ce8 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -64,4 +64,15 @@ public class PurpurWorldConfig { +@@ -56,4 +56,15 @@ public class PurpurWorldConfig { PurpurConfig.config.addDefault("world-settings.default." + path, def); return PurpurConfig.config.getString("world-settings." + worldName + "." + path, PurpurConfig.config.getString("world-settings.default." + path)); } @@ -286,10 +286,10 @@ index eda37fa43f..5fa3330373 100644 + } } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 97a24b4dff..3bd2ffc206 100644 +index c7b4e5f2a..0ca6763ce 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2128,4 +2128,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2143,4 +2143,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return spigot; } // Spigot end @@ -312,7 +312,7 @@ index 97a24b4dff..3bd2ffc206 100644 + // Purpur end } diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index f78e44e05f..da4c49daf4 100644 +index f78e44e05..da4c49daf 100644 --- a/src/main/java/org/spigotmc/ActivationRange.java +++ b/src/main/java/org/spigotmc/ActivationRange.java @@ -207,6 +207,7 @@ public class ActivationRange diff --git a/patches/server/0009-Bring-back-server-name.patch b/patches/server/0010-Bring-back-server-name.patch similarity index 91% rename from patches/server/0009-Bring-back-server-name.patch rename to patches/server/0010-Bring-back-server-name.patch index 7c56caf7a..5bc36f4e4 100644 --- a/patches/server/0009-Bring-back-server-name.patch +++ b/patches/server/0010-Bring-back-server-name.patch @@ -1,4 +1,4 @@ -From fb7aa2524aa13598c3a498a60c44795a2647522f Mon Sep 17 00:00:00 2001 +From d8fc6c9dbc51e6fc4cf815ea6db5c23e37ec1387 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 26 May 2019 15:19:14 -0500 Subject: [PATCH] Bring back server name @@ -21,10 +21,10 @@ index 6786fd094..8a9be3fdb 100644 public final boolean spawnNpcs = this.getBoolean("spawn-npcs", true); public final boolean pvp = this.getBoolean("pvp", true); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 6c602ef79..39aa8c336 100644 +index 957baebc4..e7d60c114 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2356,4 +2356,11 @@ public final class CraftServer implements Server { +@@ -2369,4 +2369,11 @@ public final class CraftServer implements Server { return mobGoals; } // Paper end diff --git a/patches/server/0010-Configurable-server-mod-name.patch b/patches/server/0011-Configurable-server-mod-name.patch similarity index 84% rename from patches/server/0010-Configurable-server-mod-name.patch rename to patches/server/0011-Configurable-server-mod-name.patch index 25ae27d8a..cff7f1f07 100644 --- a/patches/server/0010-Configurable-server-mod-name.patch +++ b/patches/server/0011-Configurable-server-mod-name.patch @@ -1,4 +1,4 @@ -From 8cabdcc1fff88ba9e699619de4a6898a2c3ab69d Mon Sep 17 00:00:00 2001 +From a06e9db2cd0bedea59034541a472cb2d32d439f5 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 21 Mar 2020 11:47:39 -0500 Subject: [PATCH] Configurable server mod name @@ -9,15 +9,15 @@ Subject: [PATCH] Configurable server mod name 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0d0998b06..377cd8812 100644 +index e23e47ee7..ba0260fa5 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1446,7 +1446,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant Date: Sun, 5 May 2019 12:58:45 -0500 Subject: [PATCH] LivingEntity safeFallDistance @@ -36,7 +36,7 @@ index 364697e01..ee7a2fedd 100644 protected int getChestSlots() { diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index 7a2140e4b..732a3f21d 100644 +index 70c2be22b..ceeb0c4c1 100644 --- a/src/main/java/net/minecraft/server/EntityLiving.java +++ b/src/main/java/net/minecraft/server/EntityLiving.java @@ -132,6 +132,7 @@ public abstract class EntityLiving extends Entity { diff --git a/patches/server/0012-MoonPhase-API.patch b/patches/server/0013-MoonPhase-API.patch similarity index 82% rename from patches/server/0012-MoonPhase-API.patch rename to patches/server/0013-MoonPhase-API.patch index e2d6e3f94..302a2ab78 100644 --- a/patches/server/0012-MoonPhase-API.patch +++ b/patches/server/0013-MoonPhase-API.patch @@ -1,4 +1,4 @@ -From 2806cb90116acb2347f20188c1cebf6ad2ac7d84 Mon Sep 17 00:00:00 2001 +From a30746c5569efc03352fc4fbb82c0a76545ab483 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 1 Feb 2020 22:22:16 -0600 Subject: [PATCH] MoonPhase API @@ -8,10 +8,10 @@ Subject: [PATCH] MoonPhase API 1 file changed, 7 insertions(+) diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 724c0816d..8506ca886 100644 +index 21bd9f14e..0c721a5fd 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2613,4 +2613,11 @@ public class CraftWorld implements World { +@@ -2614,4 +2614,11 @@ public class CraftWorld implements World { return spigot; } // Spigot end diff --git a/patches/server/0013-Lagging-threshold.patch b/patches/server/0014-Lagging-threshold.patch similarity index 91% rename from patches/server/0013-Lagging-threshold.patch rename to patches/server/0014-Lagging-threshold.patch index a93a5130c..3bd34441a 100644 --- a/patches/server/0013-Lagging-threshold.patch +++ b/patches/server/0014-Lagging-threshold.patch @@ -1,4 +1,4 @@ -From 66165fa04ec062dbe138f99824d32840512a43c1 Mon Sep 17 00:00:00 2001 +From 2e657e19a4d8355da8e9c4fd5199b116b6bf83a7 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Tue, 23 Jul 2019 10:07:16 -0500 Subject: [PATCH] Lagging threshold @@ -10,7 +10,7 @@ Subject: [PATCH] Lagging threshold 3 files changed, 12 insertions(+) diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 377cd8812..822798741 100644 +index ba0260fa5..8ed47fe05 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -166,6 +166,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant Date: Fri, 5 Jul 2019 16:36:55 -0500 Subject: [PATCH] ItemFactory#getMonsterEgg diff --git a/patches/server/0015-PlayerSetSpawnerTypeWithEggEvent.patch b/patches/server/0016-PlayerSetSpawnerTypeWithEggEvent.patch similarity index 98% rename from patches/server/0015-PlayerSetSpawnerTypeWithEggEvent.patch rename to patches/server/0016-PlayerSetSpawnerTypeWithEggEvent.patch index 994c87b07..816b6b0c1 100644 --- a/patches/server/0015-PlayerSetSpawnerTypeWithEggEvent.patch +++ b/patches/server/0016-PlayerSetSpawnerTypeWithEggEvent.patch @@ -1,4 +1,4 @@ -From 00f1a7cbcc9ae0a4f2ad78b44287a34d81ed54e7 Mon Sep 17 00:00:00 2001 +From 8ed07ea5498704c7c2228ba4d45cdafcb7ef8c14 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 5 Jul 2019 18:21:00 -0500 Subject: [PATCH] PlayerSetSpawnerTypeWithEggEvent diff --git a/patches/server/0016-EMC-MonsterEggSpawnEvent.patch b/patches/server/0017-EMC-MonsterEggSpawnEvent.patch similarity index 98% rename from patches/server/0016-EMC-MonsterEggSpawnEvent.patch rename to patches/server/0017-EMC-MonsterEggSpawnEvent.patch index d2b30af15..46925b751 100644 --- a/patches/server/0016-EMC-MonsterEggSpawnEvent.patch +++ b/patches/server/0017-EMC-MonsterEggSpawnEvent.patch @@ -1,4 +1,4 @@ -From ebc3f075549750efdaf6d045a951b5082b1aa9c0 Mon Sep 17 00:00:00 2001 +From 1a08ed0d95f59a8c98d8d06a6b01264c4a343cdd Mon Sep 17 00:00:00 2001 From: Aikar Date: Sat, 20 Jul 2013 22:40:56 -0400 Subject: [PATCH] EMC - MonsterEggSpawnEvent diff --git a/patches/server/0017-Villager-resetOffers.patch b/patches/server/0018-Villager-resetOffers.patch similarity index 97% rename from patches/server/0017-Villager-resetOffers.patch rename to patches/server/0018-Villager-resetOffers.patch index f6bcd0c21..31926b8ef 100644 --- a/patches/server/0017-Villager-resetOffers.patch +++ b/patches/server/0018-Villager-resetOffers.patch @@ -1,4 +1,4 @@ -From f78891becd000d9c7787bc38deb9d35aa797405b Mon Sep 17 00:00:00 2001 +From 21fe0113b78ebd98f56eba3feb429e3b0cc8e240 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Mon, 7 Oct 2019 00:15:37 -0500 Subject: [PATCH] Villager#resetOffers diff --git a/patches/server/0018-World-getPlacementBlockData.patch b/patches/server/0019-World-getPlacementBlockData.patch similarity index 86% rename from patches/server/0018-World-getPlacementBlockData.patch rename to patches/server/0019-World-getPlacementBlockData.patch index ba74fc837..cd7ecef4f 100644 --- a/patches/server/0018-World-getPlacementBlockData.patch +++ b/patches/server/0019-World-getPlacementBlockData.patch @@ -1,4 +1,4 @@ -From bf81b900510fba99b4f8b9677f5ada6c49780e0d Mon Sep 17 00:00:00 2001 +From b149fadd0450fc4ebca351978f38c5457a12a82a Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 8 Feb 2020 23:30:17 -0600 Subject: [PATCH] World#getPlacementBlockData @@ -8,10 +8,10 @@ Subject: [PATCH] World#getPlacementBlockData 1 file changed, 5 insertions(+) diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 8506ca886..0a6ee278b 100644 +index 0c721a5fd..a9dfd40f1 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2619,5 +2619,10 @@ public class CraftWorld implements World { +@@ -2620,5 +2620,10 @@ public class CraftWorld implements World { public net.pl3x.purpur.MoonPhase getMoonPhase() { return net.pl3x.purpur.MoonPhase.getPhase(getFullTime() / 24000L); } diff --git a/patches/server/0019-LivingEntity-playPickupItemAnimation.patch b/patches/server/0020-LivingEntity-playPickupItemAnimation.patch similarity index 94% rename from patches/server/0019-LivingEntity-playPickupItemAnimation.patch rename to patches/server/0020-LivingEntity-playPickupItemAnimation.patch index c55b9fdc4..c78a5dea8 100644 --- a/patches/server/0019-LivingEntity-playPickupItemAnimation.patch +++ b/patches/server/0020-LivingEntity-playPickupItemAnimation.patch @@ -1,4 +1,4 @@ -From ad5c59131a490f3a1acf7e51ec0a25698f1d5d40 Mon Sep 17 00:00:00 2001 +From 53cdbac2ff0413c6af832bd4e331c3c8968a6afa Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 19 Oct 2019 02:25:16 -0500 Subject: [PATCH] LivingEntity#playPickupItemAnimation diff --git a/patches/server/0020-SkeletonHorseTrapEvent-getPlayer.patch b/patches/server/0021-SkeletonHorseTrapEvent-getPlayer.patch similarity index 96% rename from patches/server/0020-SkeletonHorseTrapEvent-getPlayer.patch rename to patches/server/0021-SkeletonHorseTrapEvent-getPlayer.patch index cd70b6d78..2305a9602 100644 --- a/patches/server/0020-SkeletonHorseTrapEvent-getPlayer.patch +++ b/patches/server/0021-SkeletonHorseTrapEvent-getPlayer.patch @@ -1,4 +1,4 @@ -From 31aa2e07a779236b98b8415007409eed934d8452 Mon Sep 17 00:00:00 2001 +From f607a151862c8aff8bb765024f5b408197d90f1a Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 19 Oct 2019 02:35:35 -0500 Subject: [PATCH] SkeletonHorseTrapEvent#getPlayer diff --git a/patches/server/0021-PaperPR-PlayerItemCooldownEvent.patch b/patches/server/0022-PaperPR-PlayerItemCooldownEvent.patch similarity index 95% rename from patches/server/0021-PaperPR-PlayerItemCooldownEvent.patch rename to patches/server/0022-PaperPR-PlayerItemCooldownEvent.patch index 9a039c3da..ae3ab265b 100644 --- a/patches/server/0021-PaperPR-PlayerItemCooldownEvent.patch +++ b/patches/server/0022-PaperPR-PlayerItemCooldownEvent.patch @@ -1,4 +1,4 @@ -From 8a99e19fa0556853736568a269dd892342449daf Mon Sep 17 00:00:00 2001 +From 453a7d6a6b56ff2546deef9f69f7d72dd013ce66 Mon Sep 17 00:00:00 2001 From: KennyTV Date: Mon, 20 Apr 2020 13:57:06 +0200 Subject: [PATCH] PaperPR - PlayerItemCooldownEvent diff --git a/patches/server/0022-EntityMoveEvent.patch b/patches/server/0023-EntityMoveEvent.patch similarity index 94% rename from patches/server/0022-EntityMoveEvent.patch rename to patches/server/0023-EntityMoveEvent.patch index d56992b8c..3fb19df98 100644 --- a/patches/server/0022-EntityMoveEvent.patch +++ b/patches/server/0023-EntityMoveEvent.patch @@ -1,4 +1,4 @@ -From c61f071c2eb1be7789fc51fc08b363eacf5e0473 Mon Sep 17 00:00:00 2001 +From 0106f4613bfbb72f454d45b0da08a6f32be00744 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Tue, 11 Feb 2020 21:56:48 -0600 Subject: [PATCH] EntityMoveEvent @@ -8,7 +8,7 @@ Subject: [PATCH] EntityMoveEvent 1 file changed, 14 insertions(+) diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index 732a3f21d..f917cd5df 100644 +index ceeb0c4c1..a5262b88e 100644 --- a/src/main/java/net/minecraft/server/EntityLiving.java +++ b/src/main/java/net/minecraft/server/EntityLiving.java @@ -2790,6 +2790,20 @@ public abstract class EntityLiving extends Entity { diff --git a/patches/server/0023-PaperPR-Add-BellRingEvent.patch b/patches/server/0024-PaperPR-Add-BellRingEvent.patch similarity index 97% rename from patches/server/0023-PaperPR-Add-BellRingEvent.patch rename to patches/server/0024-PaperPR-Add-BellRingEvent.patch index 21a4a4272..e22dc330e 100644 --- a/patches/server/0023-PaperPR-Add-BellRingEvent.patch +++ b/patches/server/0024-PaperPR-Add-BellRingEvent.patch @@ -1,4 +1,4 @@ -From 0d8728d2c77181579b7efcc4ca6d588d45f1615a Mon Sep 17 00:00:00 2001 +From 8616ee18ee7da78b892222532f3b42d62e94d89d Mon Sep 17 00:00:00 2001 From: Eearslya Sleiarion Date: Mon, 24 Jun 2019 21:27:32 -0700 Subject: [PATCH] PaperPR - Add BellRingEvent diff --git a/patches/server/0024-Player-invulnerabilities.patch b/patches/server/0025-Player-invulnerabilities.patch similarity index 93% rename from patches/server/0024-Player-invulnerabilities.patch rename to patches/server/0025-Player-invulnerabilities.patch index c4f3f5862..f49e0b50c 100644 --- a/patches/server/0024-Player-invulnerabilities.patch +++ b/patches/server/0025-Player-invulnerabilities.patch @@ -1,4 +1,4 @@ -From 0828a5d793cb60992427e2f0af477835712183fb Mon Sep 17 00:00:00 2001 +From d30691f6fe7bd486962d98a4ce81e115ce8237c1 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 2 May 2020 20:55:44 -0500 Subject: [PATCH] Player invulnerabilities @@ -12,7 +12,7 @@ Subject: [PATCH] Player invulnerabilities 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index 508a91418e..07f8f0fa7d 100644 +index 508a91418..07f8f0fa7 100644 --- a/src/main/java/net/minecraft/server/EntityPlayer.java +++ b/src/main/java/net/minecraft/server/EntityPlayer.java @@ -141,6 +141,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { @@ -74,10 +74,10 @@ index 508a91418e..07f8f0fa7d 100644 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 0d8daf4569..47a7d1c034 100644 +index 6be2c0192..e08143623 100644 --- a/src/main/java/net/minecraft/server/PlayerConnection.java +++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -1563,6 +1563,7 @@ public class PlayerConnection implements PacketListenerPlayIn { +@@ -1575,6 +1575,7 @@ public class PlayerConnection implements PacketListenerPlayIn { PlayerConnectionUtils.ensureMainThread(packetplayinresourcepackstatus, this, this.player.getWorldServer()); // Paper start PlayerResourcePackStatusEvent.Status packStatus = PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.status.ordinal()]; @@ -86,7 +86,7 @@ index 0d8daf4569..47a7d1c034 100644 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 3c5ba8f2fd..5807e77dab 100644 +index 3c5ba8f2f..5807e77da 100644 --- a/src/main/java/net/minecraft/server/PlayerList.java +++ b/src/main/java/net/minecraft/server/PlayerList.java @@ -869,6 +869,8 @@ public abstract class PlayerList { @@ -99,10 +99,10 @@ index 3c5ba8f2fd..5807e77dab 100644 return entityplayer1; } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 5fa3330373..bd9b82dadf 100644 +index 9ec1c5ce8..1c9393f28 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -75,4 +75,11 @@ public class PurpurWorldConfig { +@@ -67,4 +67,11 @@ public class PurpurWorldConfig { idleTimeoutCountAsSleeping = getBoolean("gameplay-mechanics.player.idle-timeout.count-as-sleeping", idleTimeoutCountAsSleeping); idleTimeoutUpdateTabList = getBoolean("gameplay-mechanics.player.idle-timeout.update-tab-list", idleTimeoutUpdateTabList); } @@ -115,10 +115,10 @@ index 5fa3330373..bd9b82dadf 100644 + } } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 3bd2ffc206..9b1c4d9320 100644 +index 0ca6763ce..8dc0aeb3b 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2144,5 +2144,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2159,5 +2159,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { public void resetIdleTimer() { getHandle().resetIdleTimer(); } diff --git a/patches/server/0025-Anvil-API.patch b/patches/server/0026-Anvil-API.patch similarity index 99% rename from patches/server/0025-Anvil-API.patch rename to patches/server/0026-Anvil-API.patch index 960844e98..cfe4e0c87 100644 --- a/patches/server/0025-Anvil-API.patch +++ b/patches/server/0026-Anvil-API.patch @@ -1,4 +1,4 @@ -From 44cafc5974e016c61841d8fd29e480e8605416b0 Mon Sep 17 00:00:00 2001 +From 55ca7128b336a2f50ca8c71e7c34ef4765ecee60 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 19 Apr 2020 00:17:56 -0500 Subject: [PATCH] Anvil API diff --git a/patches/server/0026-Configurable-villager-brain-ticks.patch b/patches/server/0027-Configurable-villager-brain-ticks.patch similarity index 95% rename from patches/server/0026-Configurable-villager-brain-ticks.patch rename to patches/server/0027-Configurable-villager-brain-ticks.patch index 3200d6b14..c3f890bdb 100644 --- a/patches/server/0026-Configurable-villager-brain-ticks.patch +++ b/patches/server/0027-Configurable-villager-brain-ticks.patch @@ -1,4 +1,4 @@ -From c748533f4bbafc0c16603882168e2cbf46960287 Mon Sep 17 00:00:00 2001 +From 68f62757b17a41d8e4158acc3d3ece8e3bb3d590 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Tue, 23 Jul 2019 08:28:21 -0500 Subject: [PATCH] Configurable villager brain ticks @@ -40,10 +40,10 @@ index bf019043a..7925c8991 100644 if (this.bM) { this.bM = false; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index bd9b82dad..8f8e61442 100644 +index 1c9393f28..644501d5e 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -82,4 +82,11 @@ public class PurpurWorldConfig { +@@ -74,4 +74,11 @@ public class PurpurWorldConfig { playerSpawnInvulnerableTicks = getInt("gameplay-mechanics.player.spawn-invulnerable-ticks", playerSpawnInvulnerableTicks); playerInvulnerableWhileAcceptingResourcePack = getBoolean("gameplay-mechanics.player.invulnerable-while-accepting-resource-pack", playerInvulnerableWhileAcceptingResourcePack); } diff --git a/patches/server/0027-Alternative-Keepalive-Handling.patch b/patches/server/0028-Alternative-Keepalive-Handling.patch similarity index 96% rename from patches/server/0027-Alternative-Keepalive-Handling.patch rename to patches/server/0028-Alternative-Keepalive-Handling.patch index 526856747..08c8f942b 100644 --- a/patches/server/0027-Alternative-Keepalive-Handling.patch +++ b/patches/server/0028-Alternative-Keepalive-Handling.patch @@ -1,4 +1,4 @@ -From 753e40b5abc1fde5f33910bd9b5a77898f44ea0d Mon Sep 17 00:00:00 2001 +From 76fe7d6818cac45ef64e56665e4a57122c920e85 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 11 Oct 2019 00:17:39 -0500 Subject: [PATCH] Alternative Keepalive Handling @@ -22,7 +22,7 @@ index 8e93f1540..470f92c4f 100644 return this.a; } diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 85016aa76..d2d96eacc 100644 +index e08143623..36519882f 100644 --- a/src/main/java/net/minecraft/server/PlayerConnection.java +++ b/src/main/java/net/minecraft/server/PlayerConnection.java @@ -75,6 +75,7 @@ public class PlayerConnection implements PacketListenerPlayIn { @@ -55,7 +55,7 @@ index 85016aa76..d2d96eacc 100644 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 -@@ -2704,6 +2720,16 @@ public class PlayerConnection implements PacketListenerPlayIn { +@@ -2716,6 +2732,16 @@ public class PlayerConnection implements PacketListenerPlayIn { @Override public void a(PacketPlayInKeepAlive packetplayinkeepalive) { diff --git a/patches/server/0028-Silk-touch-spawners.patch b/patches/server/0029-Silk-touch-spawners.patch similarity index 98% rename from patches/server/0028-Silk-touch-spawners.patch rename to patches/server/0029-Silk-touch-spawners.patch index 3a0ca02ec..a853c4044 100644 --- a/patches/server/0028-Silk-touch-spawners.patch +++ b/patches/server/0029-Silk-touch-spawners.patch @@ -1,4 +1,4 @@ -From 836c6dcd9b9cb396daeec8ddd59834f431bf1275 Mon Sep 17 00:00:00 2001 +From 6c9014787c2208705d67fad563db8b13bd7e186a Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Thu, 9 May 2019 14:27:37 -0500 Subject: [PATCH] Silk touch spawners diff --git a/patches/server/0029-MC-125757-Fix-Always-increment-arrow-despawn-counter.patch b/patches/server/0030-MC-125757-Fix-Always-increment-arrow-despawn-counter.patch similarity index 96% rename from patches/server/0029-MC-125757-Fix-Always-increment-arrow-despawn-counter.patch rename to patches/server/0030-MC-125757-Fix-Always-increment-arrow-despawn-counter.patch index 2c7049fe5..c53407061 100644 --- a/patches/server/0029-MC-125757-Fix-Always-increment-arrow-despawn-counter.patch +++ b/patches/server/0030-MC-125757-Fix-Always-increment-arrow-despawn-counter.patch @@ -1,4 +1,4 @@ -From 6bfbeb52d059e6241fbd31cb1c909fc4f4cd4e98 Mon Sep 17 00:00:00 2001 +From 90b7e35a44d65b660f29b35707c5fe508baf086e Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 21 Feb 2020 17:04:51 -0600 Subject: [PATCH] MC-125757 Fix - Always increment arrow despawn counter diff --git a/patches/server/0030-MC-168772-Fix-Add-turtle-egg-block-options.patch b/patches/server/0031-MC-168772-Fix-Add-turtle-egg-block-options.patch similarity index 95% rename from patches/server/0030-MC-168772-Fix-Add-turtle-egg-block-options.patch rename to patches/server/0031-MC-168772-Fix-Add-turtle-egg-block-options.patch index 18fdbca5a..7ff96917b 100644 --- a/patches/server/0030-MC-168772-Fix-Add-turtle-egg-block-options.patch +++ b/patches/server/0031-MC-168772-Fix-Add-turtle-egg-block-options.patch @@ -1,4 +1,4 @@ -From 3cdc8d59eb0d60369650ba50ff81fb65b9f5ecc3 Mon Sep 17 00:00:00 2001 +From 741df2b5d77b2223c04718fa78c8f19fead51cf3 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Thu, 6 Jun 2019 22:15:46 -0500 Subject: [PATCH] MC-168772 Fix - Add turtle egg block options @@ -38,10 +38,10 @@ index 553c8affa..92cca6c44 100644 } } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 8f8e61442..3367cfd47 100644 +index 644501d5e..741de8c51 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -83,6 +83,15 @@ public class PurpurWorldConfig { +@@ -75,6 +75,15 @@ public class PurpurWorldConfig { playerInvulnerableWhileAcceptingResourcePack = getBoolean("gameplay-mechanics.player.invulnerable-while-accepting-resource-pack", playerInvulnerableWhileAcceptingResourcePack); } diff --git a/patches/server/0031-MC-4-Fix-Item-position-desync.patch b/patches/server/0032-MC-4-Fix-Item-position-desync.patch similarity index 95% rename from patches/server/0031-MC-4-Fix-Item-position-desync.patch rename to patches/server/0032-MC-4-Fix-Item-position-desync.patch index de5cec3e0..0f8019fa9 100644 --- a/patches/server/0031-MC-4-Fix-Item-position-desync.patch +++ b/patches/server/0032-MC-4-Fix-Item-position-desync.patch @@ -1,4 +1,4 @@ -From eabe6232aad2e846f11e6082b5d9510ad3aa658c Mon Sep 17 00:00:00 2001 +From 9a719380dd77d81f543106abbe3a8f12ad72f054 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 6 Jul 2019 21:12:58 -0500 Subject: [PATCH] MC-4 Fix - Item position desync @@ -10,10 +10,10 @@ Subject: [PATCH] MC-4 Fix - Item position desync 3 files changed, 13 insertions(+) diff --git a/src/main/java/net/minecraft/server/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/EntityTrackerEntry.java -index f75c09d44..10cae053b 100644 +index bfb931268..e9bc546f8 100644 --- a/src/main/java/net/minecraft/server/EntityTrackerEntry.java +++ b/src/main/java/net/minecraft/server/EntityTrackerEntry.java -@@ -133,6 +133,12 @@ public class EntityTrackerEntry { +@@ -134,6 +134,12 @@ public class EntityTrackerEntry { double vec3d_dz = this.tracker.locZ() - 2.44140625E-4D*(this.zLoc); boolean flag1 = (vec3d_dx * vec3d_dx + vec3d_dy * vec3d_dy + vec3d_dz * vec3d_dz) >= 7.62939453125E-6D; // Paper end - reduce allocation of Vec3D here diff --git a/patches/server/0032-Fix-vanilla-command-permission-handler.patch b/patches/server/0033-Fix-vanilla-command-permission-handler.patch similarity index 96% rename from patches/server/0032-Fix-vanilla-command-permission-handler.patch rename to patches/server/0033-Fix-vanilla-command-permission-handler.patch index de28e69c0..eac8cf5f2 100644 --- a/patches/server/0032-Fix-vanilla-command-permission-handler.patch +++ b/patches/server/0033-Fix-vanilla-command-permission-handler.patch @@ -1,4 +1,4 @@ -From 0efc3418e55cf91ac4cfedd251486777e746768d Mon Sep 17 00:00:00 2001 +From b51bda6626891e402696410e1077c0246ab3de3e Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 28 Mar 2020 01:51:32 -0500 Subject: [PATCH] Fix vanilla command permission handler diff --git a/patches/server/0033-Logger-settings-suppressing-pointless-logs.patch b/patches/server/0034-Logger-settings-suppressing-pointless-logs.patch similarity index 97% rename from patches/server/0033-Logger-settings-suppressing-pointless-logs.patch rename to patches/server/0034-Logger-settings-suppressing-pointless-logs.patch index 2b32493e8..7cbd5889b 100644 --- a/patches/server/0033-Logger-settings-suppressing-pointless-logs.patch +++ b/patches/server/0034-Logger-settings-suppressing-pointless-logs.patch @@ -1,4 +1,4 @@ -From f6bc74d6d724638fe97b923a0caa06deced56b92 Mon Sep 17 00:00:00 2001 +From 8801394ee2cd8754cf1d766b26a228910d1eea42 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 19 Oct 2019 00:52:12 -0500 Subject: [PATCH] Logger settings (suppressing pointless logs) diff --git a/patches/server/0034-Disable-outdated-build-check.patch b/patches/server/0035-Disable-outdated-build-check.patch similarity index 89% rename from patches/server/0034-Disable-outdated-build-check.patch rename to patches/server/0035-Disable-outdated-build-check.patch index 2b67b4afc..dea527903 100644 --- a/patches/server/0034-Disable-outdated-build-check.patch +++ b/patches/server/0035-Disable-outdated-build-check.patch @@ -1,4 +1,4 @@ -From 1926ac0f3c9733e80ebe5b761edc0b805bc59ed0 Mon Sep 17 00:00:00 2001 +From c845120751b71ba6c9121c9c1c54cdf9ff4851c1 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 15 Dec 2019 12:53:59 -0600 Subject: [PATCH] Disable outdated build check @@ -8,10 +8,10 @@ Subject: [PATCH] Disable outdated build check 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 8879c6421..2434a5af8 100644 +index c1e7e6a45..38a982d3f 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -252,7 +252,7 @@ public class Main { +@@ -259,7 +259,7 @@ public class Main { System.setProperty(TerminalConsoleAppender.JLINE_OVERRIDE_PROPERTY, "false"); // Paper } diff --git a/patches/server/0035-Giants-AI-settings.patch b/patches/server/0036-Giants-AI-settings.patch similarity index 92% rename from patches/server/0035-Giants-AI-settings.patch rename to patches/server/0036-Giants-AI-settings.patch index 5db8cff5f..a67b1871f 100644 --- a/patches/server/0035-Giants-AI-settings.patch +++ b/patches/server/0036-Giants-AI-settings.patch @@ -1,42 +1,39 @@ -From 44ff3cae556ebd8727d61cfc675f6d482b69fed6 Mon Sep 17 00:00:00 2001 +From 2698d48eacd93e24ab955acc6dbce9c3ff90693d Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 12 May 2019 00:43:12 -0500 Subject: [PATCH] Giants AI settings --- - .../minecraft/server/AttributeMapBase.java | 4 +- + .../minecraft/server/AttributeMapBase.java | 1 + .../java/net/minecraft/server/Entity.java | 2 +- .../minecraft/server/EntityGiantZombie.java | 63 ++++++++++++++++++- .../minecraft/server/EntityInsentient.java | 6 +- .../net/minecraft/server/EntityLiving.java | 2 +- .../net/pl3x/purpur/PurpurWorldConfig.java | 17 +++++ - 6 files changed, 87 insertions(+), 7 deletions(-) + 6 files changed, 86 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/minecraft/server/AttributeMapBase.java b/src/main/java/net/minecraft/server/AttributeMapBase.java -index c57e23e16..772079a27 100644 +index c57e23e16..92aa104dc 100644 --- a/src/main/java/net/minecraft/server/AttributeMapBase.java +++ b/src/main/java/net/minecraft/server/AttributeMapBase.java -@@ -41,8 +41,8 @@ public class AttributeMapBase { +@@ -41,6 +41,7 @@ public class AttributeMapBase { }).collect(Collectors.toList()); } -- @Nullable -- public AttributeModifiable a(AttributeBase attributebase) { + @Nullable public AttributeModifiable getAttribute(AttributeBase attributebase) { return a(attributebase); } // Purpur - OBFHELPER -+ @Nullable public AttributeModifiable a(AttributeBase attributebase) { + @Nullable + public AttributeModifiable a(AttributeBase attributebase) { return (AttributeModifiable) this.b.computeIfAbsent(attributebase, (attributebase1) -> { - return this.d.a(this::a, attributebase1); - }); diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 3709f3386..ee36c537d 100644 +index 3ba812843..7ecf832c2 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 void setStepHeight(float stepHeight) { this.G = stepHeight; } // Purpur - OBFHELPER +- public float G; public final float getStepHeight() { return this.G; } // Tuinity - OBFHELPER ++ public float G; public final float getStepHeight() { return this.G; } public void setStepHeight(float stepHeight) { this.G = stepHeight; } // Tuinity - OBFHELPER // Purpur - OBFHELPER public boolean noclip; public float I; protected final Random random; @@ -155,7 +152,7 @@ index 605bbf017..93714e5d9 100644 return false; } diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index f917cd5df..03477c6e9 100644 +index a5262b88e..69901be8b 100644 --- a/src/main/java/net/minecraft/server/EntityLiving.java +++ b/src/main/java/net/minecraft/server/EntityLiving.java @@ -2150,7 +2150,7 @@ public abstract class EntityLiving extends Entity { @@ -168,10 +165,10 @@ index f917cd5df..03477c6e9 100644 } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 3367cfd47..2db2dd26d 100644 +index 741de8c51..96f4edaa8 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -92,6 +92,23 @@ public class PurpurWorldConfig { +@@ -84,6 +84,23 @@ public class PurpurWorldConfig { turtleEggsBreakFromMinecarts = getBoolean("blocks.turtle_egg.break-from-minecarts", turtleEggsBreakFromMinecarts); } diff --git a/patches/server/0036-Illusioners-AI-settings.patch b/patches/server/0037-Illusioners-AI-settings.patch similarity index 94% rename from patches/server/0036-Illusioners-AI-settings.patch rename to patches/server/0037-Illusioners-AI-settings.patch index 16a351524..ed2dd36cf 100644 --- a/patches/server/0036-Illusioners-AI-settings.patch +++ b/patches/server/0037-Illusioners-AI-settings.patch @@ -1,4 +1,4 @@ -From 441173477d957d8b8af8f86d72cb50e22c99bfb8 Mon Sep 17 00:00:00 2001 +From c6e42066fb741bb97a427a00ed3d0d63fb29d96f Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 5 Jul 2019 11:09:25 -0500 Subject: [PATCH] Illusioners AI settings @@ -31,10 +31,10 @@ index 76fd0513f..1a5b9a0f0 100644 public GroupDataEntity prepare(GeneratorAccess generatoraccess, DifficultyDamageScaler difficultydamagescaler, EnumMobSpawn enummobspawn, @Nullable GroupDataEntity groupdataentity, @Nullable NBTTagCompound nbttagcompound) { this.setSlot(EnumItemSlot.MAINHAND, new ItemStack(Items.BOW)); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 2db2dd26d..d79a7e242 100644 +index 96f4edaa8..6855759ee 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -109,6 +109,15 @@ public class PurpurWorldConfig { +@@ -101,6 +101,15 @@ public class PurpurWorldConfig { giantHaveHostileAI = getBoolean("mobs.giant.have-hostile-ai", giantHaveHostileAI); } diff --git a/patches/server/0037-Zombie-horse-naturally-spawn.patch b/patches/server/0038-Zombie-horse-naturally-spawn.patch similarity index 91% rename from patches/server/0037-Zombie-horse-naturally-spawn.patch rename to patches/server/0038-Zombie-horse-naturally-spawn.patch index fd8138dc1..9fb089d76 100644 --- a/patches/server/0037-Zombie-horse-naturally-spawn.patch +++ b/patches/server/0038-Zombie-horse-naturally-spawn.patch @@ -1,4 +1,4 @@ -From 08672f6e86a74640abb8a9b29f440da692558a85 Mon Sep 17 00:00:00 2001 +From 09696d5831ed23b189a48aa65ca0088888f14156 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 7 Jul 2019 19:52:16 -0500 Subject: [PATCH] Zombie horse naturally spawn @@ -9,10 +9,10 @@ Subject: [PATCH] Zombie horse naturally spawn 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index 093fa8074..7955a079b 100644 +index 578cc6888..ee95ed6fa 100644 --- a/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java -@@ -622,12 +622,18 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -1059,12 +1059,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) { @@ -38,10 +38,10 @@ index 093fa8074..7955a079b 100644 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 d79a7e242..3dad7bded 100644 +index 6855759ee..07f3296c6 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -124,4 +124,9 @@ public class PurpurWorldConfig { +@@ -116,4 +116,9 @@ public class PurpurWorldConfig { villagerBrainTicks = getInt("mobs.villager.brain-ticks", villagerBrainTicks); villagerUseBrainTicksOnlyWhenLagging = getBoolean("mobs.villager.use-brain-ticks-only-when-lagging", villagerUseBrainTicksOnlyWhenLagging); } diff --git a/patches/server/0038-Charged-creeper-naturally-spawn.patch b/patches/server/0039-Charged-creeper-naturally-spawn.patch similarity index 93% rename from patches/server/0038-Charged-creeper-naturally-spawn.patch rename to patches/server/0039-Charged-creeper-naturally-spawn.patch index 7e0c3a2fb..ca87e655e 100644 --- a/patches/server/0038-Charged-creeper-naturally-spawn.patch +++ b/patches/server/0039-Charged-creeper-naturally-spawn.patch @@ -1,4 +1,4 @@ -From 4e0bfa3879efb2558a9e2139c4fd0f5554b59a45 Mon Sep 17 00:00:00 2001 +From 95f4eaf182e502970e05b1cda5de1911ee283ce1 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 29 Nov 2019 22:37:44 -0600 Subject: [PATCH] Charged creeper naturally spawn @@ -29,10 +29,10 @@ index 5e7f3af37..ec5287fa5 100644 + // Purpur end } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 3dad7bded..d9c4ffbe8 100644 +index 07f3296c6..d8e72bd7c 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -92,6 +92,11 @@ public class PurpurWorldConfig { +@@ -84,6 +84,11 @@ public class PurpurWorldConfig { turtleEggsBreakFromMinecarts = getBoolean("blocks.turtle_egg.break-from-minecarts", turtleEggsBreakFromMinecarts); } diff --git a/patches/server/0039-Rabbit-naturally-spawn-toast-and-killer.patch b/patches/server/0040-Rabbit-naturally-spawn-toast-and-killer.patch similarity index 94% rename from patches/server/0039-Rabbit-naturally-spawn-toast-and-killer.patch rename to patches/server/0040-Rabbit-naturally-spawn-toast-and-killer.patch index 1a96fb108..b21474599 100644 --- a/patches/server/0039-Rabbit-naturally-spawn-toast-and-killer.patch +++ b/patches/server/0040-Rabbit-naturally-spawn-toast-and-killer.patch @@ -1,4 +1,4 @@ -From 65ded2f0ce2ede0d1b623971d998474e1b52c791 Mon Sep 17 00:00:00 2001 +From a1a7daf8ae4503b74199ce17c1b7d9574de44ed7 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 31 Aug 2019 17:47:11 -0500 Subject: [PATCH] Rabbit naturally spawn toast and killer @@ -41,10 +41,10 @@ index 00c9233f8..1be0f943b 100644 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 d9c4ffbe8..9e144a369 100644 +index d8e72bd7c..4ac9c9db5 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 { +@@ -115,6 +115,13 @@ public class PurpurWorldConfig { illusionerFollowRange = getDouble("mobs.illusioner.follow-range", illusionerFollowRange); } diff --git a/patches/server/0040-Fix-outdated-server-showing-in-ping-before-server-fu.patch b/patches/server/0041-Fix-outdated-server-showing-in-ping-before-server-fu.patch similarity index 91% rename from patches/server/0040-Fix-outdated-server-showing-in-ping-before-server-fu.patch rename to patches/server/0041-Fix-outdated-server-showing-in-ping-before-server-fu.patch index 3bb0922f4..30342298e 100644 --- a/patches/server/0040-Fix-outdated-server-showing-in-ping-before-server-fu.patch +++ b/patches/server/0041-Fix-outdated-server-showing-in-ping-before-server-fu.patch @@ -1,4 +1,4 @@ -From 25d12fdb337d2ee04701ad2142690107368c728f Mon Sep 17 00:00:00 2001 +From 367816c82ec5388b8cbdd72dcf6912900e66cfb2 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Tue, 4 Jun 2019 15:50:08 -0500 Subject: [PATCH] Fix 'outdated server' showing in ping before server fully @@ -9,7 +9,7 @@ Subject: [PATCH] Fix 'outdated server' showing in ping before server fully 1 file changed, 1 insertion(+) diff --git a/src/main/java/net/minecraft/server/PacketStatusListener.java b/src/main/java/net/minecraft/server/PacketStatusListener.java -index ee18dc3fa2..4532406c4e 100644 +index 9beb6fad2..b98d09442 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/patches/server/0041-Make-Iron-Golems-Swim.patch b/patches/server/0042-Make-Iron-Golems-Swim.patch similarity index 92% rename from patches/server/0041-Make-Iron-Golems-Swim.patch rename to patches/server/0042-Make-Iron-Golems-Swim.patch index 3540a6f6f..9891a23e4 100644 --- a/patches/server/0041-Make-Iron-Golems-Swim.patch +++ b/patches/server/0042-Make-Iron-Golems-Swim.patch @@ -1,4 +1,4 @@ -From a74080199c03418349b2f1857905c2349fce12c4 Mon Sep 17 00:00:00 2001 +From 914df1970bc65b4f06588cb21d179f47ad654c5c Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 15 Jun 2019 03:12:15 -0500 Subject: [PATCH] Make Iron Golems Swim @@ -21,10 +21,10 @@ index e38a675be..ab0731c2a 100644 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 9e144a369..c89d2221b 100644 +index 4ac9c9db5..0eba948fd 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -123,6 +123,11 @@ public class PurpurWorldConfig { +@@ -115,6 +115,11 @@ public class PurpurWorldConfig { illusionerFollowRange = getDouble("mobs.illusioner.follow-range", illusionerFollowRange); } diff --git a/patches/server/0042-Dont-send-useless-entity-packets.patch b/patches/server/0043-Dont-send-useless-entity-packets.patch similarity index 95% rename from patches/server/0042-Dont-send-useless-entity-packets.patch rename to patches/server/0043-Dont-send-useless-entity-packets.patch index 14b9676aa..5d6218b60 100644 --- a/patches/server/0042-Dont-send-useless-entity-packets.patch +++ b/patches/server/0043-Dont-send-useless-entity-packets.patch @@ -1,4 +1,4 @@ -From 2e265fe093ff3fefc0579df66571791c61b4e0e4 Mon Sep 17 00:00:00 2001 +From 0021421d337cbafb7fbc00cf55e838ce532b9cce Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 6 Jul 2019 17:00:04 -0500 Subject: [PATCH] Dont send useless entity packets @@ -10,10 +10,10 @@ Subject: [PATCH] Dont send useless entity packets 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/minecraft/server/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/EntityTrackerEntry.java -index 10cae053b..509df9bab 100644 +index e9bc546f8..c28e67f9b 100644 --- a/src/main/java/net/minecraft/server/EntityTrackerEntry.java +++ b/src/main/java/net/minecraft/server/EntityTrackerEntry.java -@@ -177,6 +177,7 @@ public class EntityTrackerEntry { +@@ -178,6 +178,7 @@ public class EntityTrackerEntry { this.o = 0; packet1 = new PacketPlayOutEntityTeleport(this.tracker); } @@ -21,7 +21,7 @@ index 10cae053b..509df9bab 100644 } if ((this.e || this.tracker.impulse || this.tracker instanceof EntityLiving && ((EntityLiving) this.tracker).isGliding()) && this.tickCounter > 0) { -@@ -263,6 +264,22 @@ public class EntityTrackerEntry { +@@ -264,6 +265,22 @@ public class EntityTrackerEntry { } diff --git a/patches/server/0043-Tulips-change-fox-type.patch b/patches/server/0044-Tulips-change-fox-type.patch similarity index 97% rename from patches/server/0043-Tulips-change-fox-type.patch rename to patches/server/0044-Tulips-change-fox-type.patch index 91a2bbb29..b55687d40 100644 --- a/patches/server/0043-Tulips-change-fox-type.patch +++ b/patches/server/0044-Tulips-change-fox-type.patch @@ -1,4 +1,4 @@ -From d544c399255148396c6f85f93a1dc42826115de5 Mon Sep 17 00:00:00 2001 +From 8b987119abc32fe686254fb78afd8e8902f5a961 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 13 Jul 2019 15:56:22 -0500 Subject: [PATCH] Tulips change fox type @@ -90,10 +90,10 @@ index 619c40b27..b5305eaa9 100644 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 c89d2221b..8d620b4ef 100644 +index 0eba948fd..007da617a 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -97,6 +97,11 @@ public class PurpurWorldConfig { +@@ -89,6 +89,11 @@ public class PurpurWorldConfig { creeperChargedChance = getDouble("mobs.creeper.naturally-charged-chance", creeperChargedChance); } diff --git a/patches/server/0044-Breedable-Polar-Bears.patch b/patches/server/0045-Breedable-Polar-Bears.patch similarity index 91% rename from patches/server/0044-Breedable-Polar-Bears.patch rename to patches/server/0045-Breedable-Polar-Bears.patch index 4e1cf3cb5..ed9ef3e4e 100644 --- a/patches/server/0044-Breedable-Polar-Bears.patch +++ b/patches/server/0045-Breedable-Polar-Bears.patch @@ -1,12 +1,12 @@ -From de732dfe84607cb98f4cda698738c786db24a793 Mon Sep 17 00:00:00 2001 +From d322c81aad3685053fdb6229dcadb438808e8fdf Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Thu, 26 Mar 2020 19:46:44 -0500 Subject: [PATCH] Breedable Polar Bears --- .../net/minecraft/server/EntityPolarBear.java | 34 ++++++++++++++++++- - .../net/pl3x/purpur/PurpurWorldConfig.java | 12 +++++++ - 2 files changed, 45 insertions(+), 1 deletion(-) + .../net/pl3x/purpur/PurpurWorldConfig.java | 13 +++++++ + 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/minecraft/server/EntityPolarBear.java b/src/main/java/net/minecraft/server/EntityPolarBear.java index 69e5c1aed..6506e0055 100644 @@ -73,21 +73,21 @@ index 69e5c1aed..6506e0055 100644 this.datawatcher.set(EntityPolarBear.bv, flag); } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 8d620b4ef..12e263d21 100644 +index 007da617a..fe7201939 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -1,6 +1,10 @@ +@@ -1,5 +1,10 @@ package net.pl3x.purpur; - import com.destroystokyo.paper.PaperWorldConfig; ++import com.destroystokyo.paper.PaperWorldConfig; +import net.minecraft.server.IRegistry; +import net.minecraft.server.Item; +import net.minecraft.server.Items; +import net.minecraft.server.MinecraftKey; import org.bukkit.configuration.ConfigurationSection; - import org.spigotmc.SpigotWorldConfig; - -@@ -133,6 +137,14 @@ public class PurpurWorldConfig { + import java.util.List; + import static net.pl3x.purpur.PurpurConfig.log; +@@ -125,6 +130,14 @@ public class PurpurWorldConfig { ironGolemCanSwim = getBoolean("mobs.iron_golem.can-swim", ironGolemCanSwim); } diff --git a/patches/server/0045-Chickens-can-retaliate.patch b/patches/server/0046-Chickens-can-retaliate.patch similarity index 94% rename from patches/server/0045-Chickens-can-retaliate.patch rename to patches/server/0046-Chickens-can-retaliate.patch index 9137ec044..400b4b0f1 100644 --- a/patches/server/0045-Chickens-can-retaliate.patch +++ b/patches/server/0046-Chickens-can-retaliate.patch @@ -1,4 +1,4 @@ -From 141f81a229d60cfd704a429e83fddb8e9d594008 Mon Sep 17 00:00:00 2001 +From 786ef853ee3b3e82b0d4dd5f045ed02ef70e19ca Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 12 Apr 2020 13:19:34 -0500 Subject: [PATCH] Chickens can retaliate @@ -9,7 +9,7 @@ Subject: [PATCH] Chickens can retaliate 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/minecraft/server/EntityChicken.java b/src/main/java/net/minecraft/server/EntityChicken.java -index c6ee92343a..fa97552bb4 100644 +index c6ee92343..fa97552bb 100644 --- a/src/main/java/net/minecraft/server/EntityChicken.java +++ b/src/main/java/net/minecraft/server/EntityChicken.java @@ -20,14 +20,33 @@ public class EntityChicken extends EntityAnimal { @@ -57,10 +57,10 @@ index c6ee92343a..fa97552bb4 100644 @Override diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 12e263d216..77cdd94d54 100644 +index fe7201939..56657c357 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -96,6 +96,11 @@ public class PurpurWorldConfig { +@@ -89,6 +89,11 @@ public class PurpurWorldConfig { turtleEggsBreakFromMinecarts = getBoolean("blocks.turtle_egg.break-from-minecarts", turtleEggsBreakFromMinecarts); } diff --git a/patches/server/0046-Add-option-to-set-armorstand-step-height.patch b/patches/server/0047-Add-option-to-set-armorstand-step-height.patch similarity index 91% rename from patches/server/0046-Add-option-to-set-armorstand-step-height.patch rename to patches/server/0047-Add-option-to-set-armorstand-step-height.patch index 8d8837242..ef5bcb4d7 100644 --- a/patches/server/0046-Add-option-to-set-armorstand-step-height.patch +++ b/patches/server/0047-Add-option-to-set-armorstand-step-height.patch @@ -1,4 +1,4 @@ -From 400fc0a593ffa7945c7d199507bcddd2273666e0 Mon Sep 17 00:00:00 2001 +From 8b35258b4e6dc36c81503d1a85d53cfae9625c6d Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 6 Oct 2019 12:46:35 -0500 Subject: [PATCH] Add option to set armorstand step height @@ -21,10 +21,10 @@ index 250bccee4..7543f2cee 100644 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 77cdd94d5..d403450e2 100644 +index 56657c357..90400b26f 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -69,6 +69,11 @@ public class PurpurWorldConfig { +@@ -62,6 +62,11 @@ public class PurpurWorldConfig { return PurpurConfig.config.getString("world-settings." + worldName + "." + path, PurpurConfig.config.getString("world-settings.default." + path)); } diff --git a/patches/server/0047-Cat-spawning-options.patch b/patches/server/0048-Cat-spawning-options.patch similarity index 95% rename from patches/server/0047-Cat-spawning-options.patch rename to patches/server/0048-Cat-spawning-options.patch index 494b98d3d..e687fe633 100644 --- a/patches/server/0047-Cat-spawning-options.patch +++ b/patches/server/0048-Cat-spawning-options.patch @@ -1,4 +1,4 @@ -From 55b3a3d0f209f9fed5b1973bb36c08b6534aaafc Mon Sep 17 00:00:00 2001 +From da88862d2962b0393e49eff4976f1dfc94325589 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Thu, 26 Dec 2019 18:52:55 -0600 Subject: [PATCH] Cat spawning options @@ -13,7 +13,7 @@ Subject: [PATCH] Cat spawning options 6 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/main/java/net/minecraft/server/IEntityAccess.java b/src/main/java/net/minecraft/server/IEntityAccess.java -index d3ea51c27..c9a808e22 100644 +index dfa8f3439..a3a073f9d 100644 --- a/src/main/java/net/minecraft/server/IEntityAccess.java +++ b/src/main/java/net/minecraft/server/IEntityAccess.java @@ -45,6 +45,7 @@ public interface IEntityAccess { @@ -74,7 +74,7 @@ index 67c20747a..68d37121f 100644 } diff --git a/src/main/java/net/minecraft/server/VillagePlace.java b/src/main/java/net/minecraft/server/VillagePlace.java -index 303f6b095..11d16842d 100644 +index c1e149f20..acc30cb0d 100644 --- a/src/main/java/net/minecraft/server/VillagePlace.java +++ b/src/main/java/net/minecraft/server/VillagePlace.java @@ -45,6 +45,7 @@ public class VillagePlace extends RegionFileSection { @@ -107,10 +107,10 @@ index 5bd3bcc2b..5f2bb140a 100644 return this.E; } diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index 7955a079b..149a0ada4 100644 +index ee95ed6fa..918a82d46 100644 --- a/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java -@@ -1881,6 +1881,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -2358,6 +2358,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { } } @@ -119,10 +119,10 @@ index 7955a079b..149a0ada4 100644 return this.getChunkProvider().j(); } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index d403450e2..ec490745b 100644 +index 90400b26f..013f3ba4d 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -101,6 +101,15 @@ public class PurpurWorldConfig { +@@ -94,6 +94,15 @@ public class PurpurWorldConfig { turtleEggsBreakFromMinecarts = getBoolean("blocks.turtle_egg.break-from-minecarts", turtleEggsBreakFromMinecarts); } diff --git a/patches/server/0048-MC-147659-Fix-non-black-cats-spawning-in-swamp-huts.patch b/patches/server/0049-MC-147659-Fix-non-black-cats-spawning-in-swamp-huts.patch similarity index 95% rename from patches/server/0048-MC-147659-Fix-non-black-cats-spawning-in-swamp-huts.patch rename to patches/server/0049-MC-147659-Fix-non-black-cats-spawning-in-swamp-huts.patch index fcefc2a3c..ec75ea1af 100644 --- a/patches/server/0048-MC-147659-Fix-non-black-cats-spawning-in-swamp-huts.patch +++ b/patches/server/0049-MC-147659-Fix-non-black-cats-spawning-in-swamp-huts.patch @@ -1,4 +1,4 @@ -From 6cef8b3a0a207fe01ddf73117cc3770203e8c01c Mon Sep 17 00:00:00 2001 +From 1f12359ab18d29323245a5cb22101c7faad3252f Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Thu, 2 Jan 2020 01:23:22 -0600 Subject: [PATCH] MC-147659 - Fix non black cats spawning in swamp huts diff --git a/patches/server/0049-Cows-eat-mushrooms.patch b/patches/server/0050-Cows-eat-mushrooms.patch similarity index 95% rename from patches/server/0049-Cows-eat-mushrooms.patch rename to patches/server/0050-Cows-eat-mushrooms.patch index b2f9e3156..925902636 100644 --- a/patches/server/0049-Cows-eat-mushrooms.patch +++ b/patches/server/0050-Cows-eat-mushrooms.patch @@ -1,4 +1,4 @@ -From 8fc20523d0a02bb4dfdf896059856706dc924463 Mon Sep 17 00:00:00 2001 +From e90551499231668e3dc14b45361a0ded003c1ac1 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 4 May 2019 01:10:30 -0500 Subject: [PATCH] Cows eat mushrooms @@ -11,10 +11,10 @@ Subject: [PATCH] Cows eat mushrooms 4 files changed, 77 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 846ebe876d..78b4d82620 100644 +index 7ecf832c2..a6105d8c8 100644 --- a/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java -@@ -2561,6 +2561,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +@@ -2748,6 +2748,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke this.invulnerable = flag; } @@ -23,7 +23,7 @@ index 846ebe876d..78b4d82620 100644 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 30ee6df6b4..d6baddb9d3 100644 +index 30ee6df6b..d6baddb9d 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 { @@ -116,7 +116,7 @@ index 30ee6df6b4..d6baddb9d3 100644 public EntityCow createChild(EntityAgeable entityageable) { return (EntityCow) EntityTypes.COW.a(this.world); diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index 03477c6e91..63cff85af9 100644 +index 69901be8b..dd894c7ea 100644 --- a/src/main/java/net/minecraft/server/EntityLiving.java +++ b/src/main/java/net/minecraft/server/EntityLiving.java @@ -80,7 +80,7 @@ public abstract class EntityLiving extends Entity { @@ -129,10 +129,10 @@ index 03477c6e91..63cff85af9 100644 public float aJ; public float aK; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index ec490745b0..faddf7c4bc 100644 +index 013f3ba4d..8f9aa5283 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -115,6 +115,11 @@ public class PurpurWorldConfig { +@@ -108,6 +108,11 @@ public class PurpurWorldConfig { chickenRetaliate = getBoolean("mobs.chicken.retaliate", chickenRetaliate); } diff --git a/patches/server/0050-Fix-cow-rotation-when-shearing-mooshroom.patch b/patches/server/0051-Fix-cow-rotation-when-shearing-mooshroom.patch similarity index 95% rename from patches/server/0050-Fix-cow-rotation-when-shearing-mooshroom.patch rename to patches/server/0051-Fix-cow-rotation-when-shearing-mooshroom.patch index 62b90947d..a3aa7c312 100644 --- a/patches/server/0050-Fix-cow-rotation-when-shearing-mooshroom.patch +++ b/patches/server/0051-Fix-cow-rotation-when-shearing-mooshroom.patch @@ -1,4 +1,4 @@ -From bb7737a02a0e52a0c6fceadc31e30de3957cc147 Mon Sep 17 00:00:00 2001 +From e97562ca51fbf4a9530a6d9c509e3cc58454bc78 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 3 May 2019 23:53:16 -0500 Subject: [PATCH] Fix cow rotation when shearing mooshroom diff --git a/patches/server/0051-Pigs-give-saddle-back.patch b/patches/server/0052-Pigs-give-saddle-back.patch similarity index 93% rename from patches/server/0051-Pigs-give-saddle-back.patch rename to patches/server/0052-Pigs-give-saddle-back.patch index 35862b1b9..a3fba45a3 100644 --- a/patches/server/0051-Pigs-give-saddle-back.patch +++ b/patches/server/0052-Pigs-give-saddle-back.patch @@ -1,4 +1,4 @@ -From e4a7d439a42b6139c1fe3308fdeaf1b5f8857b1a Mon Sep 17 00:00:00 2001 +From e75f4e76cc42d4b69d3c800d8b1259233841c06b Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 12 May 2019 01:14:46 -0500 Subject: [PATCH] Pigs give saddle back @@ -32,10 +32,10 @@ index cd0a94794..cf2df391a 100644 } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index faddf7c4b..84c025c4a 100644 +index 8f9aa5283..cc41c67f8 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -161,6 +161,11 @@ public class PurpurWorldConfig { +@@ -154,6 +154,11 @@ public class PurpurWorldConfig { ironGolemCanSwim = getBoolean("mobs.iron_golem.can-swim", ironGolemCanSwim); } diff --git a/patches/server/0052-Snowman-drop-and-put-back-pumpkin.patch b/patches/server/0053-Snowman-drop-and-put-back-pumpkin.patch similarity index 95% rename from patches/server/0052-Snowman-drop-and-put-back-pumpkin.patch rename to patches/server/0053-Snowman-drop-and-put-back-pumpkin.patch index 6680aa9f5..f5423ece5 100644 --- a/patches/server/0052-Snowman-drop-and-put-back-pumpkin.patch +++ b/patches/server/0053-Snowman-drop-and-put-back-pumpkin.patch @@ -1,4 +1,4 @@ -From 71ef94f480dde9459ce85b48fab104f511800038 Mon Sep 17 00:00:00 2001 +From 1f28d401cdd3db016f37f70cef4f62c6faf3e491 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 3 May 2019 23:58:44 -0500 Subject: [PATCH] Snowman drop and put back pumpkin @@ -47,10 +47,10 @@ index 15b886d9b..dfe615814 100644 return EnumInteractionResult.PASS; } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 84c025c4a..ce443f9d7 100644 +index cc41c67f8..76eff6baa 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -181,6 +181,13 @@ public class PurpurWorldConfig { +@@ -174,6 +174,13 @@ public class PurpurWorldConfig { rabbitNaturalKiller = getDouble("mobs.rabbit.spawn-killer-rabbit-chance", rabbitNaturalKiller); } diff --git a/patches/server/0053-Ender-dragon-always-drop-egg.patch b/patches/server/0054-Ender-dragon-always-drop-egg.patch similarity index 92% rename from patches/server/0053-Ender-dragon-always-drop-egg.patch rename to patches/server/0054-Ender-dragon-always-drop-egg.patch index 6837c1df0..9ef89cacc 100644 --- a/patches/server/0053-Ender-dragon-always-drop-egg.patch +++ b/patches/server/0054-Ender-dragon-always-drop-egg.patch @@ -1,4 +1,4 @@ -From cd0557107ef93a0cebc2242260df1d5a841de62d Mon Sep 17 00:00:00 2001 +From 0d58ae055ab7be9765224cee5fb13ecf470199aa Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 7 Feb 2020 04:42:57 -0600 Subject: [PATCH] Ender dragon always drop egg @@ -22,10 +22,10 @@ index 69faefbdb..ecd6af04d 100644 } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index ce443f9d7..c76b15bef 100644 +index 76eff6baa..fc310302d 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -125,6 +125,11 @@ public class PurpurWorldConfig { +@@ -118,6 +118,11 @@ public class PurpurWorldConfig { creeperChargedChance = getDouble("mobs.creeper.naturally-charged-chance", creeperChargedChance); } diff --git a/patches/server/0054-Ender-dragon-always-drop-full-exp.patch b/patches/server/0055-Ender-dragon-always-drop-full-exp.patch similarity index 92% rename from patches/server/0054-Ender-dragon-always-drop-full-exp.patch rename to patches/server/0055-Ender-dragon-always-drop-full-exp.patch index 4c52fdad8..a819c8715 100644 --- a/patches/server/0054-Ender-dragon-always-drop-full-exp.patch +++ b/patches/server/0055-Ender-dragon-always-drop-full-exp.patch @@ -1,4 +1,4 @@ -From f9a625ee7814a6561dbd3793117358008f98d1dd Mon Sep 17 00:00:00 2001 +From 2ec5767d24c8ee49d75f5cc64a29880d301820e9 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 24 Aug 2019 14:42:54 -0500 Subject: [PATCH] Ender dragon always drop full exp @@ -22,10 +22,10 @@ index 63a759cc1..08fa5a975 100644 } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index c76b15bef..328a0b4fe 100644 +index fc310302d..201e916d2 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -126,8 +126,10 @@ public class PurpurWorldConfig { +@@ -119,8 +119,10 @@ public class PurpurWorldConfig { } public boolean enderDragonAlwaysDropsEggBlock = false; diff --git a/patches/server/0055-Signs-editable-on-right-click.patch b/patches/server/0056-Signs-editable-on-right-click.patch similarity index 95% rename from patches/server/0055-Signs-editable-on-right-click.patch rename to patches/server/0056-Signs-editable-on-right-click.patch index e8370bb3a..bf44c0ff9 100644 --- a/patches/server/0055-Signs-editable-on-right-click.patch +++ b/patches/server/0056-Signs-editable-on-right-click.patch @@ -1,4 +1,4 @@ -From ee9e1bedb34e6afdc80e72d7a35ca24a9a5a1aab Mon Sep 17 00:00:00 2001 +From c582a3d813ffc01bd8eb7ebe3be1778483e0e9a6 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 24 May 2019 02:39:25 -0500 Subject: [PATCH] Signs editable on right click @@ -44,10 +44,10 @@ index c4b0d8720..e1ab29975 100644 // 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 328a0b4fe..ed6102b40 100644 +index 201e916d2..09a9e9b19 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -92,6 +92,11 @@ public class PurpurWorldConfig { +@@ -85,6 +85,11 @@ public class PurpurWorldConfig { playerInvulnerableWhileAcceptingResourcePack = getBoolean("gameplay-mechanics.player.invulnerable-while-accepting-resource-pack", playerInvulnerableWhileAcceptingResourcePack); } diff --git a/patches/server/0056-Signs-allow-color-codes.patch b/patches/server/0057-Signs-allow-color-codes.patch similarity index 94% rename from patches/server/0056-Signs-allow-color-codes.patch rename to patches/server/0057-Signs-allow-color-codes.patch index b39d08797..70390923a 100644 --- a/patches/server/0056-Signs-allow-color-codes.patch +++ b/patches/server/0057-Signs-allow-color-codes.patch @@ -1,4 +1,4 @@ -From 448a2ac9aa4422c108643494f19c1cdbe900ed3b Mon Sep 17 00:00:00 2001 +From 5632a01348b52cfaf94abc740bdcfa58556a546f Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Thu, 6 Jun 2019 17:40:30 -0500 Subject: [PATCH] Signs allow color codes @@ -12,7 +12,7 @@ Subject: [PATCH] Signs allow color codes 5 files changed, 36 insertions(+) diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index 07f8f0fa7d..3556e86fd7 100644 +index 07f8f0fa7..3556e86fd 100644 --- a/src/main/java/net/minecraft/server/EntityPlayer.java +++ b/src/main/java/net/minecraft/server/EntityPlayer.java @@ -1269,6 +1269,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { @@ -24,7 +24,7 @@ index 07f8f0fa7d..3556e86fd7 100644 public int nextContainerCounter() { // CraftBukkit - void -> int diff --git a/src/main/java/net/minecraft/server/IChatBaseComponent.java b/src/main/java/net/minecraft/server/IChatBaseComponent.java -index fd3e6cda6a..750896fc82 100644 +index fd3e6cda6..750896fc8 100644 --- a/src/main/java/net/minecraft/server/IChatBaseComponent.java +++ b/src/main/java/net/minecraft/server/IChatBaseComponent.java @@ -344,6 +344,7 @@ public interface IChatBaseComponent extends Message, IChatFormatted, Iterable Date: Fri, 21 Jun 2019 14:37:10 -0500 Subject: [PATCH] Allow soil to moisten from water directly under it @@ -40,10 +40,10 @@ index a315e2628..8dd48669c 100644 @Override diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 5df442c5b..c28c241ad 100644 +index 91dcfe1c6..6f8604c5c 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -92,6 +92,11 @@ public class PurpurWorldConfig { +@@ -85,6 +85,11 @@ public class PurpurWorldConfig { playerInvulnerableWhileAcceptingResourcePack = getBoolean("gameplay-mechanics.player.invulnerable-while-accepting-resource-pack", playerInvulnerableWhileAcceptingResourcePack); } diff --git a/patches/server/0058-Controllable-Minecarts.patch b/patches/server/0059-Controllable-Minecarts.patch similarity index 94% rename from patches/server/0058-Controllable-Minecarts.patch rename to patches/server/0059-Controllable-Minecarts.patch index bff8b34fe..f03fb6e77 100644 --- a/patches/server/0058-Controllable-Minecarts.patch +++ b/patches/server/0059-Controllable-Minecarts.patch @@ -1,4 +1,4 @@ -From 250f0664cec36bf8a6d9f0dde52344f3ff47ca2a Mon Sep 17 00:00:00 2001 +From e0798fdcdf2c55cf2e17ea5efcc61f5c1adade7b Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 29 Jun 2019 02:32:40 -0500 Subject: [PATCH] Controllable Minecarts @@ -9,8 +9,8 @@ Subject: [PATCH] Controllable Minecarts .../net/minecraft/server/EntityLiving.java | 6 +-- .../server/EntityMinecartAbstract.java | 38 +++++++++++++++++++ .../net/minecraft/server/ItemMinecart.java | 8 ++-- - .../net/pl3x/purpur/PurpurWorldConfig.java | 30 +++++++++++++++ - 6 files changed, 83 insertions(+), 6 deletions(-) + .../net/pl3x/purpur/PurpurWorldConfig.java | 32 ++++++++++++++++ + 6 files changed, 85 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java index 551ca4471..32757e231 100644 @@ -30,10 +30,10 @@ index 551ca4471..32757e231 100644 super(i, j, k); } diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 028f94a88..e72975ff6 100644 +index a6105d8c8..5b3f287c8 100644 --- a/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java -@@ -1286,6 +1286,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +@@ -1473,6 +1473,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke this.inLava = true; } @@ -42,7 +42,7 @@ index 028f94a88..e72975ff6 100644 return this.inLava; } diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index 63cff85af..cbfb62cd4 100644 +index dd894c7ea..bf8be6012 100644 --- a/src/main/java/net/minecraft/server/EntityLiving.java +++ b/src/main/java/net/minecraft/server/EntityLiving.java @@ -98,9 +98,9 @@ public abstract class EntityLiving extends Entity { @@ -139,10 +139,10 @@ index dc7decb06..0da16c200 100644 } } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index c28c241ad..d3d09d9a4 100644 +index 6f8604c5c..64867b68d 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -1,6 +1,8 @@ +@@ -1,12 +1,18 @@ package net.pl3x.purpur; import com.destroystokyo.paper.PaperWorldConfig; @@ -151,17 +151,17 @@ index c28c241ad..d3d09d9a4 100644 import net.minecraft.server.IRegistry; import net.minecraft.server.Item; import net.minecraft.server.Items; -@@ -8,7 +10,9 @@ import net.minecraft.server.MinecraftKey; + import net.minecraft.server.MinecraftKey; import org.bukkit.configuration.ConfigurationSection; - import org.spigotmc.SpigotWorldConfig; - ++ +import java.util.HashMap; import java.util.List; +import java.util.Map; - ++ import static net.pl3x.purpur.PurpurConfig.log; -@@ -74,6 +78,32 @@ public class PurpurWorldConfig { + public class PurpurWorldConfig { +@@ -67,6 +73,32 @@ public class PurpurWorldConfig { armorstandStepHeight = (float) getDouble("gameplay-mechanics.armorstand.step-height", armorstandStepHeight); } diff --git a/patches/server/0059-Disable-loot-drops-on-death-by-cramming.patch b/patches/server/0060-Disable-loot-drops-on-death-by-cramming.patch similarity index 91% rename from patches/server/0059-Disable-loot-drops-on-death-by-cramming.patch rename to patches/server/0060-Disable-loot-drops-on-death-by-cramming.patch index 11b5f2981..12b9ab499 100644 --- a/patches/server/0059-Disable-loot-drops-on-death-by-cramming.patch +++ b/patches/server/0060-Disable-loot-drops-on-death-by-cramming.patch @@ -1,4 +1,4 @@ -From 973be464795e3636e5b966303568ca44dc9d8858 Mon Sep 17 00:00:00 2001 +From 99ca97484fbadcd23964ca8ac80a3a759639f411 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Wed, 3 Jul 2019 23:58:31 -0500 Subject: [PATCH] Disable loot drops on death by cramming @@ -9,7 +9,7 @@ Subject: [PATCH] Disable loot drops on death by cramming 2 files changed, 7 insertions(+) diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index cbfb62cd4..f570f8955 100644 +index bf8be6012..e42185ad4 100644 --- a/src/main/java/net/minecraft/server/EntityLiving.java +++ b/src/main/java/net/minecraft/server/EntityLiving.java @@ -1484,8 +1484,10 @@ public abstract class EntityLiving extends Entity { @@ -24,10 +24,10 @@ index cbfb62cd4..f570f8955 100644 deathEvent = CraftEventFactory.callEntityDeathEvent(this, this.drops); // Paper } else { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index d3d09d9a4..0e0f59c96 100644 +index 64867b68d..579d5c9ff 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -115,6 +115,11 @@ public class PurpurWorldConfig { +@@ -110,6 +110,11 @@ public class PurpurWorldConfig { idleTimeoutUpdateTabList = getBoolean("gameplay-mechanics.player.idle-timeout.update-tab-list", idleTimeoutUpdateTabList); } diff --git a/patches/server/0060-Players-should-not-cram-to-death.patch b/patches/server/0061-Players-should-not-cram-to-death.patch similarity index 91% rename from patches/server/0060-Players-should-not-cram-to-death.patch rename to patches/server/0061-Players-should-not-cram-to-death.patch index a0ba598df..766c8d860 100644 --- a/patches/server/0060-Players-should-not-cram-to-death.patch +++ b/patches/server/0061-Players-should-not-cram-to-death.patch @@ -1,4 +1,4 @@ -From e5a6ecb6355378875b4a83f3976dbade4ffcb490 Mon Sep 17 00:00:00 2001 +From 6c0156560acd0c292d202b385d0ca4abcf6e39fc Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 21 Jul 2019 18:01:46 -0500 Subject: [PATCH] Players should not cram to death @@ -8,7 +8,7 @@ Subject: [PATCH] Players should not cram to death 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index 3556e86fd7..42f3ef1ee6 100644 +index 3556e86fd..42f3ef1ee 100644 --- a/src/main/java/net/minecraft/server/EntityPlayer.java +++ b/src/main/java/net/minecraft/server/EntityPlayer.java @@ -1243,7 +1243,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { diff --git a/patches/server/0061-Option-to-toggle-milk-curing-bad-omen.patch b/patches/server/0062-Option-to-toggle-milk-curing-bad-omen.patch similarity index 92% rename from patches/server/0061-Option-to-toggle-milk-curing-bad-omen.patch rename to patches/server/0062-Option-to-toggle-milk-curing-bad-omen.patch index 2828d73c5..ec243a863 100644 --- a/patches/server/0061-Option-to-toggle-milk-curing-bad-omen.patch +++ b/patches/server/0062-Option-to-toggle-milk-curing-bad-omen.patch @@ -1,4 +1,4 @@ -From b3e7d2a10bc7014139373f7f4d54b8469ecbc14b Mon Sep 17 00:00:00 2001 +From 0e01fed709f7230ffaff6accc97538e2d7ce528e Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Wed, 10 Jul 2019 20:43:05 -0500 Subject: [PATCH] Option to toggle milk curing bad omen @@ -23,10 +23,10 @@ index fcf254bba..79554e18f 100644 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 0e0f59c96..b6bcbd1e6 100644 +index 579d5c9ff..bdc6dc3e8 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -116,8 +116,10 @@ public class PurpurWorldConfig { +@@ -111,8 +111,10 @@ public class PurpurWorldConfig { } public boolean disableDropsOnCrammingDeath = false; diff --git a/patches/server/0062-End-gateway-should-check-if-entity-can-use-portal.patch b/patches/server/0063-End-gateway-should-check-if-entity-can-use-portal.patch similarity index 90% rename from patches/server/0062-End-gateway-should-check-if-entity-can-use-portal.patch rename to patches/server/0063-End-gateway-should-check-if-entity-can-use-portal.patch index 806847f8f..8d2028e24 100644 --- a/patches/server/0062-End-gateway-should-check-if-entity-can-use-portal.patch +++ b/patches/server/0063-End-gateway-should-check-if-entity-can-use-portal.patch @@ -1,4 +1,4 @@ -From 2ed2dad2f015763bcf4bf54e56ebadece69521bb Mon Sep 17 00:00:00 2001 +From 0f2c06bbaafea85a003d29915ddbaaa041ab1e87 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 21 Mar 2020 18:33:05 -0500 Subject: [PATCH] End gateway should check if entity can use portal @@ -8,7 +8,7 @@ Subject: [PATCH] End gateway should check if entity can use portal 1 file changed, 1 insertion(+) diff --git a/src/main/java/net/minecraft/server/TileEntityEndGateway.java b/src/main/java/net/minecraft/server/TileEntityEndGateway.java -index aebb6b6b2..c6b26f665 100644 +index ce239d2b2..d00ca8a53 100644 --- a/src/main/java/net/minecraft/server/TileEntityEndGateway.java +++ b/src/main/java/net/minecraft/server/TileEntityEndGateway.java @@ -122,6 +122,7 @@ public class TileEntityEndGateway extends TileEntityEnderPortal implements ITick diff --git a/patches/server/0063-Debug-stick-should-not-update-neighbors.patch b/patches/server/0064-Debug-stick-should-not-update-neighbors.patch similarity index 94% rename from patches/server/0063-Debug-stick-should-not-update-neighbors.patch rename to patches/server/0064-Debug-stick-should-not-update-neighbors.patch index 127972fd6..1747c39fa 100644 --- a/patches/server/0063-Debug-stick-should-not-update-neighbors.patch +++ b/patches/server/0064-Debug-stick-should-not-update-neighbors.patch @@ -1,4 +1,4 @@ -From e7b70b3784621d00d4579121864fa57f4e9c8b8a Mon Sep 17 00:00:00 2001 +From cd0ac1a5de8b0c879b224d790f3cb8420bcdfca5 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 4 Apr 2020 17:16:30 -0500 Subject: [PATCH] Debug stick should not update neighbors diff --git a/patches/server/0064-Fix-reloading-paper.yml.patch b/patches/server/0065-Fix-reloading-paper.yml.patch similarity index 94% rename from patches/server/0064-Fix-reloading-paper.yml.patch rename to patches/server/0065-Fix-reloading-paper.yml.patch index 52c822d6a..ecdf8869b 100644 --- a/patches/server/0064-Fix-reloading-paper.yml.patch +++ b/patches/server/0065-Fix-reloading-paper.yml.patch @@ -1,4 +1,4 @@ -From 123b61894938ade2049cf6b6c799bb0a670bdaa4 Mon Sep 17 00:00:00 2001 +From feeb2ba03825354e6158d559a00dec7e5a446d67 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 19 Jun 2020 21:36:16 -0500 Subject: [PATCH] Fix reloading paper.yml diff --git a/patches/server/0065-Fix-the-dead-lagging-the-server.patch b/patches/server/0066-Fix-the-dead-lagging-the-server.patch similarity index 89% rename from patches/server/0065-Fix-the-dead-lagging-the-server.patch rename to patches/server/0066-Fix-the-dead-lagging-the-server.patch index 01fbb7e01..24c39f76d 100644 --- a/patches/server/0065-Fix-the-dead-lagging-the-server.patch +++ b/patches/server/0066-Fix-the-dead-lagging-the-server.patch @@ -1,4 +1,4 @@ -From db4865d3be7d0d2ea790637854a9db73e7c98d42 Mon Sep 17 00:00:00 2001 +From 2402604643ff2228ee0eef62a9d22558ccb17316 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 6 Mar 2020 13:37:26 -0600 Subject: [PATCH] Fix the dead lagging the server @@ -9,10 +9,10 @@ Subject: [PATCH] Fix the dead lagging the server 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 3950842a8..5bedd61ee 100644 +index 5b3f287c8..a8706f754 100644 --- a/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java -@@ -1345,7 +1345,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +@@ -1532,7 +1532,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke this.pitch = MathHelper.a(f1, -90.0F, 90.0F) % 360.0F; this.lastYaw = this.yaw; this.lastPitch = this.pitch; @@ -22,7 +22,7 @@ index 3950842a8..5bedd61ee 100644 public void c(Vec3D vec3d) { diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index f570f8955..f86499c87 100644 +index e42185ad4..5c4608b7e 100644 --- a/src/main/java/net/minecraft/server/EntityLiving.java +++ b/src/main/java/net/minecraft/server/EntityLiving.java @@ -2468,7 +2468,7 @@ public abstract class EntityLiving extends Entity { diff --git a/patches/server/0066-Skip-events-if-there-s-no-listeners.patch b/patches/server/0067-Skip-events-if-there-s-no-listeners.patch similarity index 96% rename from patches/server/0066-Skip-events-if-there-s-no-listeners.patch rename to patches/server/0067-Skip-events-if-there-s-no-listeners.patch index a37bc8efa..a59e41d58 100644 --- a/patches/server/0066-Skip-events-if-there-s-no-listeners.patch +++ b/patches/server/0067-Skip-events-if-there-s-no-listeners.patch @@ -1,4 +1,4 @@ -From 8ded3a0a3455852f77e406fc37e2d54b150ccf1e Mon Sep 17 00:00:00 2001 +From efbf1cafc98f7392be6f9486a83b9c836e51c57e Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 4 Apr 2020 03:07:59 -0500 Subject: [PATCH] Skip events if there's no listeners diff --git a/patches/server/0067-Add-permission-for-F3-N-debug.patch b/patches/server/0068-Add-permission-for-F3-N-debug.patch similarity index 93% rename from patches/server/0067-Add-permission-for-F3-N-debug.patch rename to patches/server/0068-Add-permission-for-F3-N-debug.patch index 7bbc5e658..b6ed9f2e1 100644 --- a/patches/server/0067-Add-permission-for-F3-N-debug.patch +++ b/patches/server/0068-Add-permission-for-F3-N-debug.patch @@ -1,4 +1,4 @@ -From 62ee2b84a56861dd16a6e684bffb679081cd8a06 Mon Sep 17 00:00:00 2001 +From 81fa02e19fb81b0b604a26812e302aef25d2c139 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 28 Dec 2019 04:21:54 -0600 Subject: [PATCH] Add permission for F3+N debug diff --git a/patches/server/0068-Add-wither-skeleton-takes-wither-damage-option.patch b/patches/server/0069-Add-wither-skeleton-takes-wither-damage-option.patch similarity index 92% rename from patches/server/0068-Add-wither-skeleton-takes-wither-damage-option.patch rename to patches/server/0069-Add-wither-skeleton-takes-wither-damage-option.patch index 471c3ba83..146fbc9e9 100644 --- a/patches/server/0068-Add-wither-skeleton-takes-wither-damage-option.patch +++ b/patches/server/0069-Add-wither-skeleton-takes-wither-damage-option.patch @@ -1,4 +1,4 @@ -From fb4c424b01c1ae79cab705b551aa965039459b6c Mon Sep 17 00:00:00 2001 +From 91b343ffcc7d5824106805315e6691a858bbb38d Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Tue, 14 Jan 2020 19:43:40 -0600 Subject: [PATCH] Add wither skeleton takes wither damage option @@ -21,10 +21,10 @@ index 1819432e1..f415775ea 100644 } } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index b6bcbd1e6..5549a984d 100644 +index bdc6dc3e8..f60434669 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -252,6 +252,11 @@ public class PurpurWorldConfig { +@@ -247,6 +247,11 @@ public class PurpurWorldConfig { villagerUseBrainTicksOnlyWhenLagging = getBoolean("mobs.villager.use-brain-ticks-only-when-lagging", villagerUseBrainTicksOnlyWhenLagging); } diff --git a/patches/server/0069-Configurable-TPS-Catchup.patch b/patches/server/0070-Configurable-TPS-Catchup.patch similarity index 95% rename from patches/server/0069-Configurable-TPS-Catchup.patch rename to patches/server/0070-Configurable-TPS-Catchup.patch index 048f27c0d..8f7257f40 100644 --- a/patches/server/0069-Configurable-TPS-Catchup.patch +++ b/patches/server/0070-Configurable-TPS-Catchup.patch @@ -1,4 +1,4 @@ -From ebcd9fce18fd418afbe8a58d9aa7a70f7c3d49b4 Mon Sep 17 00:00:00 2001 +From 1175c64542b0d22dc132ca2f287b84621fea42d8 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Thu, 26 Mar 2020 19:06:22 -0500 Subject: [PATCH] Configurable TPS Catchup @@ -9,7 +9,7 @@ Subject: [PATCH] Configurable TPS Catchup 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index ae747377b..d052811a8 100644 +index 8ed47fe05..5acd2a97c 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -1002,7 +1002,13 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant Date: Thu, 19 Mar 2020 19:39:34 -0500 Subject: [PATCH] Add option to allow loyalty on tridents to work in the void @@ -22,10 +22,10 @@ index c68002ffe..9be919986 100644 if (b0 > 0 && !this.z()) { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 5549a984d..e571b3628 100644 +index f60434669..11c4742c2 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -117,9 +117,11 @@ public class PurpurWorldConfig { +@@ -112,9 +112,11 @@ public class PurpurWorldConfig { public boolean disableDropsOnCrammingDeath = false; public boolean milkCuresBadOmen = true; diff --git a/patches/server/0071-Add-enderman-and-creeper-griefing-controls.patch b/patches/server/0072-Add-enderman-and-creeper-griefing-controls.patch similarity index 94% rename from patches/server/0071-Add-enderman-and-creeper-griefing-controls.patch rename to patches/server/0072-Add-enderman-and-creeper-griefing-controls.patch index 3505d26e6..01fb77007 100644 --- a/patches/server/0071-Add-enderman-and-creeper-griefing-controls.patch +++ b/patches/server/0072-Add-enderman-and-creeper-griefing-controls.patch @@ -1,4 +1,4 @@ -From 11b683a401f03df22f26d56faf452f07e3b29f6b Mon Sep 17 00:00:00 2001 +From ef199323d2ecd67ab3248c5089800c06c3d407f0 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 26 Apr 2020 16:28:38 -0500 Subject: [PATCH] Add enderman and creeper griefing controls @@ -43,10 +43,10 @@ index b61de3351..245fc38de 100644 } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index e571b3628..bd9ac998f 100644 +index 11c4742c2..f015c456f 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -172,8 +172,10 @@ public class PurpurWorldConfig { +@@ -167,8 +167,10 @@ public class PurpurWorldConfig { cowFeedMushrooms = getInt("mobs.cow.feed-mushrooms-for-mooshroom", cowFeedMushrooms); } @@ -57,7 +57,7 @@ index e571b3628..bd9ac998f 100644 creeperChargedChance = getDouble("mobs.creeper.naturally-charged-chance", creeperChargedChance); } -@@ -184,6 +186,11 @@ public class PurpurWorldConfig { +@@ -179,6 +181,11 @@ public class PurpurWorldConfig { enderDragonAlwaysDropsFullExp = getBoolean("mobs.ender_dragon.always-drop-full-exp", enderDragonAlwaysDropsFullExp); } diff --git a/patches/server/0072-Entities-pick-up-loot-bypass-mob-griefing-gamerule.patch b/patches/server/0073-Entities-pick-up-loot-bypass-mob-griefing-gamerule.patch similarity index 94% rename from patches/server/0072-Entities-pick-up-loot-bypass-mob-griefing-gamerule.patch rename to patches/server/0073-Entities-pick-up-loot-bypass-mob-griefing-gamerule.patch index 8bf404a1d..597a2f734 100644 --- a/patches/server/0072-Entities-pick-up-loot-bypass-mob-griefing-gamerule.patch +++ b/patches/server/0073-Entities-pick-up-loot-bypass-mob-griefing-gamerule.patch @@ -1,4 +1,4 @@ -From f916325e8ddfdd78b0fb4f1e0613660cfc161bbf Mon Sep 17 00:00:00 2001 +From af5088ad60fdfeb33bb27d80816504f300a7ae0d Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 24 Apr 2020 09:33:11 -0500 Subject: [PATCH] Entities pick up loot bypass mob-griefing gamerule @@ -22,10 +22,10 @@ index 93714e5d9..b23674625 100644 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 bd9ac998f..7217c07e5 100644 +index f015c456f..3f1c33b5f 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -116,10 +116,12 @@ public class PurpurWorldConfig { +@@ -111,10 +111,12 @@ public class PurpurWorldConfig { } public boolean disableDropsOnCrammingDeath = false; diff --git a/patches/server/0073-Villagers-farming-can-bypass-mob-griefing-gamerule.patch b/patches/server/0074-Villagers-farming-can-bypass-mob-griefing-gamerule.patch similarity index 93% rename from patches/server/0073-Villagers-farming-can-bypass-mob-griefing-gamerule.patch rename to patches/server/0074-Villagers-farming-can-bypass-mob-griefing-gamerule.patch index 41859e816..7c03c3b3e 100644 --- a/patches/server/0073-Villagers-farming-can-bypass-mob-griefing-gamerule.patch +++ b/patches/server/0074-Villagers-farming-can-bypass-mob-griefing-gamerule.patch @@ -1,4 +1,4 @@ -From 9aec3455d54c7df3b2f008deefa7ad8e4bfab3ed Mon Sep 17 00:00:00 2001 +From cb4b26260622329c9395dc553eae15e1946ca124 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 24 Apr 2020 09:37:29 -0500 Subject: [PATCH] Villagers farming can bypass mob-griefing gamerule @@ -22,10 +22,10 @@ index 54a555509..0ff202c0d 100644 } 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 7217c07e5..15dc4e222 100644 +index 3f1c33b5f..cf9f33544 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -258,9 +258,11 @@ public class PurpurWorldConfig { +@@ -253,9 +253,11 @@ public class PurpurWorldConfig { public int villagerBrainTicks = 1; public boolean villagerUseBrainTicksOnlyWhenLagging = true; diff --git a/patches/server/0074-Villagers-follow-emerald-blocks.patch b/patches/server/0075-Villagers-follow-emerald-blocks.patch similarity index 96% rename from patches/server/0074-Villagers-follow-emerald-blocks.patch rename to patches/server/0075-Villagers-follow-emerald-blocks.patch index 5199a8c30..abc934fed 100644 --- a/patches/server/0074-Villagers-follow-emerald-blocks.patch +++ b/patches/server/0075-Villagers-follow-emerald-blocks.patch @@ -1,4 +1,4 @@ -From ffabf3305ff6809847d0cdf2d6d6f61bf6410d94 Mon Sep 17 00:00:00 2001 +From 17b932a2f016412c95602271454572ea71b699d4 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 29 Nov 2019 22:10:12 -0600 Subject: [PATCH] Villagers follow emerald blocks @@ -54,10 +54,10 @@ index a0841cfaf..ab5e97e39 100644 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 15dc4e222..1f22ee61b 100644 +index cf9f33544..4c2398313 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -259,10 +259,17 @@ public class PurpurWorldConfig { +@@ -254,10 +254,17 @@ public class PurpurWorldConfig { public int villagerBrainTicks = 1; public boolean villagerUseBrainTicksOnlyWhenLagging = true; public boolean villagerFarmingBypassMobGriefing = false; diff --git a/patches/server/0075-Allow-leashing-villagers.patch b/patches/server/0076-Allow-leashing-villagers.patch similarity index 96% rename from patches/server/0075-Allow-leashing-villagers.patch rename to patches/server/0076-Allow-leashing-villagers.patch index 8a704d2da..5ada4b2ad 100644 --- a/patches/server/0075-Allow-leashing-villagers.patch +++ b/patches/server/0076-Allow-leashing-villagers.patch @@ -1,4 +1,4 @@ -From df78ae333134e0b0076279dd1e27283b446974ba Mon Sep 17 00:00:00 2001 +From 97c949e1962c25613f92616619f098d8bff6069d Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Thu, 3 Oct 2019 18:08:03 -0500 Subject: [PATCH] Allow leashing villagers @@ -57,10 +57,10 @@ index ab5e97e39..9985afb12 100644 @Override public EntityAgeable createChild(EntityAgeable entityageable) { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 1f22ee61b..f82288126 100644 +index 4c2398313..98f88be8b 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -258,17 +258,21 @@ public class PurpurWorldConfig { +@@ -253,17 +253,21 @@ public class PurpurWorldConfig { public int villagerBrainTicks = 1; public boolean villagerUseBrainTicksOnlyWhenLagging = true; diff --git a/patches/server/0076-Implement-configurable-search-radius-for-villagers-t.patch b/patches/server/0077-Implement-configurable-search-radius-for-villagers-t.patch similarity index 94% rename from patches/server/0076-Implement-configurable-search-radius-for-villagers-t.patch rename to patches/server/0077-Implement-configurable-search-radius-for-villagers-t.patch index ee1ffcc6e..5328cca7b 100644 --- a/patches/server/0076-Implement-configurable-search-radius-for-villagers-t.patch +++ b/patches/server/0077-Implement-configurable-search-radius-for-villagers-t.patch @@ -1,4 +1,4 @@ -From 792d04191d5573257e7fba9a2f099e95c1de2455 Mon Sep 17 00:00:00 2001 +From a1754a7a370e7b99ceb2a670042bd30bfc09e945 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Mon, 22 Jul 2019 17:32:17 -0500 Subject: [PATCH] Implement configurable search radius for villagers to spawn @@ -22,10 +22,10 @@ index 97eb26482..86de40d15 100644 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 f82288126..224f1e9a0 100644 +index 98f88be8b..57f215572 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -261,12 +261,16 @@ public class PurpurWorldConfig { +@@ -256,12 +256,16 @@ public class PurpurWorldConfig { public boolean villagerCanBeLeashed = false; public boolean villagerFarmingBypassMobGriefing = false; public boolean villagerFollowEmeraldBlock = false; diff --git a/patches/server/0077-Implement-infinite-lava.patch b/patches/server/0078-Implement-infinite-lava.patch similarity index 95% rename from patches/server/0077-Implement-infinite-lava.patch rename to patches/server/0078-Implement-infinite-lava.patch index 6a943eca7..a497aad2d 100644 --- a/patches/server/0077-Implement-infinite-lava.patch +++ b/patches/server/0078-Implement-infinite-lava.patch @@ -1,4 +1,4 @@ -From 1bd7b866f1033ae011212fba5ca8d0b08f5cd460 Mon Sep 17 00:00:00 2001 +From ee1cbcdd7ed3523252131249f35cf1d9b92b081e Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 23 Nov 2019 17:55:42 -0600 Subject: [PATCH] Implement infinite lava @@ -55,10 +55,10 @@ index 29930e801..9e543449c 100644 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 224f1e9a0..01e5253e2 100644 +index 57f215572..cbfeb352a 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -138,6 +138,11 @@ public class PurpurWorldConfig { +@@ -133,6 +133,11 @@ public class PurpurWorldConfig { farmlandGetsMoistFromBelow = getBoolean("blocks.farmland.gets-moist-from-below", farmlandGetsMoistFromBelow); } diff --git a/patches/server/0078-Make-lava-flow-speed-configurable.patch b/patches/server/0079-Make-lava-flow-speed-configurable.patch similarity index 92% rename from patches/server/0078-Make-lava-flow-speed-configurable.patch rename to patches/server/0079-Make-lava-flow-speed-configurable.patch index 42194cf5c..865d6a0a1 100644 --- a/patches/server/0078-Make-lava-flow-speed-configurable.patch +++ b/patches/server/0079-Make-lava-flow-speed-configurable.patch @@ -1,4 +1,4 @@ -From d644b319f649206fa33e833e2c1cd5879cc12c7a Mon Sep 17 00:00:00 2001 +From ed3a4a07b4a0dfc0fef629ef7165d4d5d93787a7 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Thu, 2 Jan 2020 11:31:36 -0600 Subject: [PATCH] Make lava flow speed configurable @@ -22,10 +22,10 @@ index 9e543449c..fb501a6c5 100644 @Override diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 01e5253e2..a053ac84c 100644 +index cbfeb352a..2ac578bda 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -139,8 +139,12 @@ public class PurpurWorldConfig { +@@ -134,8 +134,12 @@ public class PurpurWorldConfig { } public boolean lavaInfinite = false; diff --git a/patches/server/0079-Add-player-death-exp-control-options.patch b/patches/server/0080-Add-player-death-exp-control-options.patch similarity index 94% rename from patches/server/0079-Add-player-death-exp-control-options.patch rename to patches/server/0080-Add-player-death-exp-control-options.patch index 121edb2ed..108fb0d8c 100644 --- a/patches/server/0079-Add-player-death-exp-control-options.patch +++ b/patches/server/0080-Add-player-death-exp-control-options.patch @@ -1,4 +1,4 @@ -From 8ef47fffdb2f3ef8a37da0cb8b565a8e9615a76c Mon Sep 17 00:00:00 2001 +From c9f22b56871cccda18e36d7802be88fe7782a56e Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Thu, 26 Dec 2019 22:08:37 -0600 Subject: [PATCH] Add player death exp control options @@ -44,10 +44,10 @@ index a69a69859..ea4144371 100644 return 0; } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index a053ac84c..54208a018 100644 +index 2ac578bda..86b3cdcdc 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -126,6 +126,13 @@ public class PurpurWorldConfig { +@@ -121,6 +121,13 @@ public class PurpurWorldConfig { tridentLoyaltyVoidReturnHeight = getDouble("gameplay-mechanics.trident-loyalty-void-return-height", tridentLoyaltyVoidReturnHeight); } diff --git a/patches/server/0080-Add-option-to-disable-saving-projectiles-to-disk.patch b/patches/server/0081-Add-option-to-disable-saving-projectiles-to-disk.patch similarity index 93% rename from patches/server/0080-Add-option-to-disable-saving-projectiles-to-disk.patch rename to patches/server/0081-Add-option-to-disable-saving-projectiles-to-disk.patch index ba2261d47..63b54d3c9 100644 --- a/patches/server/0080-Add-option-to-disable-saving-projectiles-to-disk.patch +++ b/patches/server/0081-Add-option-to-disable-saving-projectiles-to-disk.patch @@ -1,4 +1,4 @@ -From 7adbe0af58e15202ba8f2318eedccd53692984e6 Mon Sep 17 00:00:00 2001 +From d0d2ae9b7bb99f89e9d17307354d00d8e4dc9426 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Tue, 18 Feb 2020 20:07:08 -0600 Subject: [PATCH] Add option to disable saving projectiles to disk @@ -12,10 +12,10 @@ Subject: [PATCH] Add option to disable saving projectiles to disk 5 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -index ac58fcb79..0041027ec 100644 +index 742c59cb0..2b2471072 100644 --- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java +++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -@@ -467,6 +467,7 @@ public class ChunkRegionLoader { +@@ -475,6 +475,7 @@ public class ChunkRegionLoader { while (iterator1.hasNext()) { Entity entity = (Entity) iterator1.next(); @@ -24,10 +24,10 @@ index ac58fcb79..0041027ec 100644 // Paper start if (asyncsavedata == null && !entity.dead && (int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) { diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 5bedd61ee..2037fb1e1 100644 +index a8706f754..17c591b82 100644 --- a/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java -@@ -303,6 +303,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +@@ -311,6 +311,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke this.headHeight = this.getHeadHeight(EntityPose.STANDING, this.size); } @@ -81,10 +81,10 @@ index a961f5d5d..c5d788f22 100644 if (entity != null) { this.shooter = entity.getUniqueID(); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 54208a018..551d0ae31 100644 +index 86b3cdcdc..571fb0d11 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -118,11 +118,13 @@ public class PurpurWorldConfig { +@@ -113,11 +113,13 @@ public class PurpurWorldConfig { public boolean disableDropsOnCrammingDeath = false; public boolean entitiesPickUpLootBypassMobGriefing = false; public boolean milkCuresBadOmen = true; diff --git a/patches/server/0081-Configurable-void-damage-height.patch b/patches/server/0082-Configurable-void-damage-height.patch similarity index 90% rename from patches/server/0081-Configurable-void-damage-height.patch rename to patches/server/0082-Configurable-void-damage-height.patch index 3bef662d1..f9d8ec7d3 100644 --- a/patches/server/0081-Configurable-void-damage-height.patch +++ b/patches/server/0082-Configurable-void-damage-height.patch @@ -1,4 +1,4 @@ -From bac3a683e9956c339388e5ae5b926fbc550ef49a Mon Sep 17 00:00:00 2001 +From 111b356fa5f54cb0fe72f479074d657cd7813aa3 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Thu, 27 Feb 2020 21:42:19 -0600 Subject: [PATCH] Configurable void damage height @@ -9,10 +9,10 @@ Subject: [PATCH] Configurable void damage height 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 2037fb1e1..656413254 100644 +index 17c591b82..8f5151de8 100644 --- a/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java -@@ -526,7 +526,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +@@ -534,7 +534,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke // Paper start protected void performVoidDamage() { @@ -22,10 +22,10 @@ index 2037fb1e1..656413254 100644 && this.locY() >= world.paperConfig.netherVoidTopDamageHeight)) { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 551d0ae31..b51b00014 100644 +index 571fb0d11..199e0b8fe 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -120,12 +120,14 @@ public class PurpurWorldConfig { +@@ -115,12 +115,14 @@ public class PurpurWorldConfig { public boolean milkCuresBadOmen = true; public boolean saveProjectilesToDisk = true; public double tridentLoyaltyVoidReturnHeight = 0.0D; diff --git a/patches/server/0082-Add-option-for-zombies-targetting-turtle-eggs.patch b/patches/server/0083-Add-option-for-zombies-targetting-turtle-eggs.patch similarity index 92% rename from patches/server/0082-Add-option-for-zombies-targetting-turtle-eggs.patch rename to patches/server/0083-Add-option-for-zombies-targetting-turtle-eggs.patch index 0074fd6a8..03c0400c0 100644 --- a/patches/server/0082-Add-option-for-zombies-targetting-turtle-eggs.patch +++ b/patches/server/0083-Add-option-for-zombies-targetting-turtle-eggs.patch @@ -1,4 +1,4 @@ -From 5f7046fc2452c524155f338f6fefa7fe48506ada Mon Sep 17 00:00:00 2001 +From 9212d4fbac057fa0bbb70f786a4c10fd2e1c22f6 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 17 Aug 2019 15:27:09 -0500 Subject: [PATCH] Add option for zombies targetting turtle eggs @@ -22,10 +22,10 @@ index b66059836..00b89746f 100644 this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this)); this.m(); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index b51b00014..b6fc0c04e 100644 +index 199e0b8fe..006859cc1 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -305,6 +305,11 @@ public class PurpurWorldConfig { +@@ -300,6 +300,11 @@ public class PurpurWorldConfig { witherSkeletonTakesWitherDamage = getBoolean("mobs.wither_skeleton.takes-wither-damage", witherSkeletonTakesWitherDamage); } diff --git a/patches/server/0083-Dispenser-curse-of-binding-protection.patch b/patches/server/0084-Dispenser-curse-of-binding-protection.patch similarity index 95% rename from patches/server/0083-Dispenser-curse-of-binding-protection.patch rename to patches/server/0084-Dispenser-curse-of-binding-protection.patch index 5c6a30f06..969a42334 100644 --- a/patches/server/0083-Dispenser-curse-of-binding-protection.patch +++ b/patches/server/0084-Dispenser-curse-of-binding-protection.patch @@ -1,4 +1,4 @@ -From b227fee4191c35e86ea54f3781c1dcf77fb41027 Mon Sep 17 00:00:00 2001 +From d981fc197a4b22382002f37c6f251fee71984fae Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 25 Aug 2019 00:09:52 -0500 Subject: [PATCH] Dispenser curse of binding protection @@ -49,10 +49,10 @@ index 885458d54..c7d67d729 100644 return this.b; } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index b6fc0c04e..3deb3b8e3 100644 +index 006859cc1..4d0687146 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -144,6 +144,11 @@ public class PurpurWorldConfig { +@@ -139,6 +139,11 @@ public class PurpurWorldConfig { playerInvulnerableWhileAcceptingResourcePack = getBoolean("gameplay-mechanics.player.invulnerable-while-accepting-resource-pack", playerInvulnerableWhileAcceptingResourcePack); } diff --git a/patches/server/0084-Add-option-for-boats-to-eject-players-on-land.patch b/patches/server/0085-Add-option-for-boats-to-eject-players-on-land.patch similarity index 91% rename from patches/server/0084-Add-option-for-boats-to-eject-players-on-land.patch rename to patches/server/0085-Add-option-for-boats-to-eject-players-on-land.patch index 75ba949bf..1de17b79e 100644 --- a/patches/server/0084-Add-option-for-boats-to-eject-players-on-land.patch +++ b/patches/server/0085-Add-option-for-boats-to-eject-players-on-land.patch @@ -1,4 +1,4 @@ -From cc30d1a1a73f35e5eb72d8a6ce0e3709ac602f66 Mon Sep 17 00:00:00 2001 +From 26dbc8b8d852967b41e5f9e18faeb1adfebbcaea Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 7 Sep 2019 22:47:59 -0500 Subject: [PATCH] Add option for boats to eject players on land @@ -21,10 +21,10 @@ index 409e0ac0a..a20d6feb8 100644 } 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 3deb3b8e3..99235e56e 100644 +index 4d0687146..b90777b55 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -115,6 +115,7 @@ public class PurpurWorldConfig { +@@ -110,6 +110,7 @@ public class PurpurWorldConfig { idleTimeoutUpdateTabList = getBoolean("gameplay-mechanics.player.idle-timeout.update-tab-list", idleTimeoutUpdateTabList); } @@ -32,7 +32,7 @@ index 3deb3b8e3..99235e56e 100644 public boolean disableDropsOnCrammingDeath = false; public boolean entitiesPickUpLootBypassMobGriefing = false; public boolean milkCuresBadOmen = true; -@@ -122,6 +123,7 @@ public class PurpurWorldConfig { +@@ -117,6 +118,7 @@ public class PurpurWorldConfig { public double tridentLoyaltyVoidReturnHeight = 0.0D; public double voidDamageHeight = -64.0D; private void miscGameplayMechanicsSettings() { diff --git a/patches/server/0085-Add-obfhelpers-for-plugin-use.patch b/patches/server/0086-Add-obfhelpers-for-plugin-use.patch similarity index 95% rename from patches/server/0085-Add-obfhelpers-for-plugin-use.patch rename to patches/server/0086-Add-obfhelpers-for-plugin-use.patch index 8272d016e..90ad16af8 100644 --- a/patches/server/0085-Add-obfhelpers-for-plugin-use.patch +++ b/patches/server/0086-Add-obfhelpers-for-plugin-use.patch @@ -1,4 +1,4 @@ -From 269d558f5c6e572d3e4e96ecd3910a92b98d975d Mon Sep 17 00:00:00 2001 +From f7725461d43a8dabef8e3455f1c11a9a323be4bb Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Wed, 1 Jan 2020 20:12:39 -0600 Subject: [PATCH] Add obfhelpers for plugin use diff --git a/patches/server/0086-Mending-mends-most-damages-equipment-first.patch b/patches/server/0087-Mending-mends-most-damages-equipment-first.patch similarity index 96% rename from patches/server/0086-Mending-mends-most-damages-equipment-first.patch rename to patches/server/0087-Mending-mends-most-damages-equipment-first.patch index 4caea6756..14a73c01d 100644 --- a/patches/server/0086-Mending-mends-most-damages-equipment-first.patch +++ b/patches/server/0087-Mending-mends-most-damages-equipment-first.patch @@ -1,4 +1,4 @@ -From 72cdf58c8e3cb29c4963d77d10ddfac3ebb9d9c2 Mon Sep 17 00:00:00 2001 +From a0a344e5fa7ecf22e47fd9b885af1c07d8de28d2 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 14 Jul 2019 19:52:47 -0500 Subject: [PATCH] Mending mends most damages equipment first @@ -87,10 +87,10 @@ index c2e57a976..51e70db21 100644 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 99235e56e..abfa1d79b 100644 +index b90777b55..5079bd0f6 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -115,6 +115,7 @@ public class PurpurWorldConfig { +@@ -110,6 +110,7 @@ public class PurpurWorldConfig { idleTimeoutUpdateTabList = getBoolean("gameplay-mechanics.player.idle-timeout.update-tab-list", idleTimeoutUpdateTabList); } @@ -98,7 +98,7 @@ index 99235e56e..abfa1d79b 100644 public boolean boatEjectPlayersOnLand = false; public boolean disableDropsOnCrammingDeath = false; public boolean entitiesPickUpLootBypassMobGriefing = false; -@@ -123,6 +124,7 @@ public class PurpurWorldConfig { +@@ -118,6 +119,7 @@ public class PurpurWorldConfig { public double tridentLoyaltyVoidReturnHeight = 0.0D; public double voidDamageHeight = -64.0D; private void miscGameplayMechanicsSettings() { diff --git a/patches/server/0087-Implement-bamboo-growth-settings.patch b/patches/server/0088-Implement-bamboo-growth-settings.patch similarity index 97% rename from patches/server/0087-Implement-bamboo-growth-settings.patch rename to patches/server/0088-Implement-bamboo-growth-settings.patch index 627f9720d..6f1bb54a8 100644 --- a/patches/server/0087-Implement-bamboo-growth-settings.patch +++ b/patches/server/0088-Implement-bamboo-growth-settings.patch @@ -1,4 +1,4 @@ -From 6f93a87b376c43f64fafd766f320df8ff60d4260 Mon Sep 17 00:00:00 2001 +From 8177f00bda2be8ef2d8d5cbc6ce3f36fb79b2f2e Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 23 Aug 2019 20:57:29 -0500 Subject: [PATCH] Implement bamboo growth settings @@ -67,10 +67,10 @@ index 14790c167..bac1b8b30 100644 } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index abfa1d79b..f21b01565 100644 +index 5079bd0f6..6752119a7 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -148,6 +148,13 @@ public class PurpurWorldConfig { +@@ -143,6 +143,13 @@ public class PurpurWorldConfig { playerInvulnerableWhileAcceptingResourcePack = getBoolean("gameplay-mechanics.player.invulnerable-while-accepting-resource-pack", playerInvulnerableWhileAcceptingResourcePack); } diff --git a/patches/server/0088-Climbing-should-not-bypass-cramming-gamerule.patch b/patches/server/0089-Climbing-should-not-bypass-cramming-gamerule.patch similarity index 90% rename from patches/server/0088-Climbing-should-not-bypass-cramming-gamerule.patch rename to patches/server/0089-Climbing-should-not-bypass-cramming-gamerule.patch index ee35b72ae..74c296520 100644 --- a/patches/server/0088-Climbing-should-not-bypass-cramming-gamerule.patch +++ b/patches/server/0089-Climbing-should-not-bypass-cramming-gamerule.patch @@ -1,4 +1,4 @@ -From 46ca01a03fcc265bdc9bfa748cbc17a1082a0c97 Mon Sep 17 00:00:00 2001 +From cfdff7f48317faf48b2672c813799cf269bac163 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 21 Jul 2019 18:06:20 -0500 Subject: [PATCH] Climbing should not bypass cramming gamerule @@ -18,10 +18,10 @@ Subject: [PATCH] Climbing should not bypass cramming gamerule 11 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 656413254..2efb8a975 100644 +index 8f5151de8..7a4cc7c30 100644 --- a/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java -@@ -1525,6 +1525,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +@@ -1712,6 +1712,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke } public boolean isCollidable() { @@ -87,19 +87,19 @@ index ee7a2fedd..c9ab80ccd 100644 } diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index f86499c87..bc9e2e0c7 100644 +index 5c4608b7e..18a49e69a 100644 --- a/src/main/java/net/minecraft/server/EntityLiving.java +++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -2852,7 +2852,7 @@ public abstract class EntityLiving extends Entity { - return; - } +@@ -2854,7 +2854,7 @@ public abstract class EntityLiving extends Entity { // Paper - end don't run getEntities if we're not going to use its result -- List list = this.world.getEntities(this, this.getBoundingBox(), IEntitySelector.a(this)); -+ List list = this.world.getEntities(this, this.getBoundingBox(), IEntitySelector.pushable(this, world.purpurConfig.fixClimbingBypassingCrammingRule)); // Purpur + // Tuinity start - reduce memory allocation from collideNearby + List list = com.tuinity.tuinity.util.CachedLists.getTempGetEntitiesList(); +- this.world.getEntities(this, this.getBoundingBox(), IEntitySelector.a(this), list); ++ this.world.getEntities(this, this.getBoundingBox(), IEntitySelector.pushable(this, world.purpurConfig.fixClimbingBypassingCrammingRule), list); + try { + // Tuinity end - reduce memory allocation from collideNearby - if (!list.isEmpty()) { - // Paper - move up -@@ -2991,8 +2991,8 @@ public abstract class EntityLiving extends Entity { +@@ -2998,8 +2998,8 @@ public abstract class EntityLiving extends Entity { } @Override @@ -177,10 +177,10 @@ index 9b4795f3b..192d9798c 100644 } else if (entity.world.isClientSide && (!(entity1 instanceof EntityHuman) || !((EntityHuman) entity1).ey())) { return false; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index f21b01565..39163634c 100644 +index 6752119a7..0b3a7e01c 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -119,6 +119,7 @@ public class PurpurWorldConfig { +@@ -114,6 +114,7 @@ public class PurpurWorldConfig { public boolean boatEjectPlayersOnLand = false; public boolean disableDropsOnCrammingDeath = false; public boolean entitiesPickUpLootBypassMobGriefing = false; @@ -188,7 +188,7 @@ index f21b01565..39163634c 100644 public boolean milkCuresBadOmen = true; public boolean saveProjectilesToDisk = true; public double tridentLoyaltyVoidReturnHeight = 0.0D; -@@ -128,6 +129,7 @@ public class PurpurWorldConfig { +@@ -123,6 +124,7 @@ public class PurpurWorldConfig { boatEjectPlayersOnLand = getBoolean("gameplay-mechanics.boat.eject-players-on-land", boatEjectPlayersOnLand); disableDropsOnCrammingDeath = getBoolean("gameplay-mechanics.disable-drops-on-cramming-death", disableDropsOnCrammingDeath); entitiesPickUpLootBypassMobGriefing = getBoolean("gameplay-mechanics.entities-pick-up-loot-bypass-mob-griefing", entitiesPickUpLootBypassMobGriefing); diff --git a/patches/server/0089-Add-5-second-tps-average-in-tps.patch b/patches/server/0090-Add-5-second-tps-average-in-tps.patch similarity index 96% rename from patches/server/0089-Add-5-second-tps-average-in-tps.patch rename to patches/server/0090-Add-5-second-tps-average-in-tps.patch index 7178b3f26..b42f2b820 100644 --- a/patches/server/0089-Add-5-second-tps-average-in-tps.patch +++ b/patches/server/0090-Add-5-second-tps-average-in-tps.patch @@ -1,4 +1,4 @@ -From f8672129e3f1be70b1b81222c01520ecb5a6eaaa Mon Sep 17 00:00:00 2001 +From 17c9f3c75b390a40743295f7365d1fd2b7d9920b Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 28 Jul 2019 01:27:37 -0500 Subject: [PATCH] Add 5 second tps average in /tps @@ -10,7 +10,7 @@ Subject: [PATCH] Add 5 second tps average in /tps 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index d052811a8..46231e01d 100644 +index 5acd2a97c..6c0854623 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -165,7 +165,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant Date: Thu, 25 Jul 2019 18:07:37 -0500 Subject: [PATCH] Implement elytra settings @@ -8,12 +8,11 @@ Subject: [PATCH] Implement elytra settings .../java/net/minecraft/server/ItemFireworks.java | 8 ++++++++ src/main/java/net/minecraft/server/ItemStack.java | 8 +++++++- src/main/java/net/minecraft/server/ItemTrident.java | 10 ++++++++++ - src/main/java/net/minecraft/server/Vec3D.java | 2 ++ .../java/net/pl3x/purpur/PurpurWorldConfig.java | 13 +++++++++++++ - 6 files changed, 50 insertions(+), 2 deletions(-) + 5 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index bc9e2e0c7..ec0e31b27 100644 +index 18a49e69a..d02d7f21c 100644 --- a/src/main/java/net/minecraft/server/EntityLiving.java +++ b/src/main/java/net/minecraft/server/EntityLiving.java @@ -2825,7 +2825,16 @@ public abstract class EntityLiving extends Entity { @@ -100,28 +99,11 @@ index 32982bb47..a0e4d46ab 100644 entityhuman.h((double) f2, (double) f3, (double) f4); entityhuman.r(20); if (entityhuman.isOnGround()) { -diff --git a/src/main/java/net/minecraft/server/Vec3D.java b/src/main/java/net/minecraft/server/Vec3D.java -index 3048ba008..2a00569d4 100644 ---- a/src/main/java/net/minecraft/server/Vec3D.java -+++ b/src/main/java/net/minecraft/server/Vec3D.java -@@ -109,10 +109,12 @@ public class Vec3D implements IPosition { - return new Vec3D(this.x * d0, this.y * d1, this.z * d2); - } - -+ public double magnitude() { return f(); } // Purpur - OBFHELPER - public double f() { - return (double) MathHelper.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); - } - -+ public double magnitudeSquared() { return g(); } // Purpur - OBFHELPER - public double g() { - return this.x * this.x + this.y * this.y + this.z * this.z; - } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 39163634c..3f49a6a0b 100644 +index 0b3a7e01c..c1faba57f 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -136,6 +136,19 @@ public class PurpurWorldConfig { +@@ -131,6 +131,19 @@ public class PurpurWorldConfig { voidDamageHeight = getDouble("gameplay-mechanics.void-damage-height", voidDamageHeight); } diff --git a/patches/server/0091-Add-item-entity-options.patch b/patches/server/0092-Add-item-entity-options.patch similarity index 90% rename from patches/server/0091-Add-item-entity-options.patch rename to patches/server/0092-Add-item-entity-options.patch index 2e15c75ab..f1da107a5 100644 --- a/patches/server/0091-Add-item-entity-options.patch +++ b/patches/server/0092-Add-item-entity-options.patch @@ -1,4 +1,4 @@ -From 6699495e47994aba3b94784c943b9a3a99a67742 Mon Sep 17 00:00:00 2001 +From c8e390ea174ce6c8d02d78badc44b1073de1a9ad Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 22 Feb 2020 15:54:08 -0600 Subject: [PATCH] Add item entity options @@ -10,10 +10,10 @@ Subject: [PATCH] Add item entity options 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 2efb8a975..3e95af4ee 100644 +index 7a4cc7c30..476ca65a4 100644 --- a/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java -@@ -1284,6 +1284,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +@@ -1471,6 +1471,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke } @@ -44,18 +44,18 @@ index a7860cb4d..77e970c30 100644 // CraftBukkit start if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, damagesource, f)) { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 3f49a6a0b..b018bfe03 100644 +index c1faba57f..b0eac3dc9 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -10,6 +10,7 @@ import net.minecraft.server.MinecraftKey; +@@ -9,6 +9,7 @@ import net.minecraft.server.Items; + import net.minecraft.server.MinecraftKey; import org.bukkit.configuration.ConfigurationSection; - import org.spigotmc.SpigotWorldConfig; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -@@ -104,6 +105,19 @@ public class PurpurWorldConfig { +@@ -99,6 +100,19 @@ public class PurpurWorldConfig { } } diff --git a/patches/server/0092-Add-ping-command.patch b/patches/server/0093-Add-ping-command.patch similarity index 99% rename from patches/server/0092-Add-ping-command.patch rename to patches/server/0093-Add-ping-command.patch index 4a79aadc2..0a691e1e8 100644 --- a/patches/server/0092-Add-ping-command.patch +++ b/patches/server/0093-Add-ping-command.patch @@ -1,4 +1,4 @@ -From 0f1675c1fdc97b547706065d14be2f74aa04677d Mon Sep 17 00:00:00 2001 +From 0dc5a2febf37efa3a38cd08bbd4b37ca9da7d7ca Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 13 Mar 2020 22:29:10 -0500 Subject: [PATCH] Add /ping command diff --git a/patches/server/0093-Configurable-jockey-options.patch b/patches/server/0094-Configurable-jockey-options.patch similarity index 98% rename from patches/server/0093-Configurable-jockey-options.patch rename to patches/server/0094-Configurable-jockey-options.patch index e5df89d9e..75c535c83 100644 --- a/patches/server/0093-Configurable-jockey-options.patch +++ b/patches/server/0094-Configurable-jockey-options.patch @@ -1,4 +1,4 @@ -From a849d8c181f2b69e71ed8cf8357082fea30b9b32 Mon Sep 17 00:00:00 2001 +From 1a79c93d7b5429efd06aadad006fde39ad4e0aa1 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Thu, 26 Mar 2020 21:39:32 -0500 Subject: [PATCH] Configurable jockey options @@ -202,10 +202,10 @@ index 9b920332b..68fca8a8d 100644 public void saveData(NBTTagCompound nbttagcompound) { super.saveData(nbttagcompound); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index b018bfe03..8ce344c2a 100644 +index b0eac3dc9..982abc4f2 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -246,6 +246,15 @@ public class PurpurWorldConfig { +@@ -241,6 +241,15 @@ public class PurpurWorldConfig { creeperChargedChance = getDouble("mobs.creeper.naturally-charged-chance", creeperChargedChance); } @@ -221,7 +221,7 @@ index b018bfe03..8ce344c2a 100644 public boolean enderDragonAlwaysDropsEggBlock = false; public boolean enderDragonAlwaysDropsFullExp = false; private void enderDragonSettings() { -@@ -280,6 +289,15 @@ public class PurpurWorldConfig { +@@ -275,6 +284,15 @@ public class PurpurWorldConfig { giantHaveHostileAI = getBoolean("mobs.giant.have-hostile-ai", giantHaveHostileAI); } @@ -237,7 +237,7 @@ index b018bfe03..8ce344c2a 100644 public double illusionerMaxHealth = 32.0D; public double illusionerMovementSpeed = 0.5D; public double illusionerFollowRange = 18.0D; -@@ -351,12 +369,36 @@ public class PurpurWorldConfig { +@@ -346,12 +364,36 @@ public class PurpurWorldConfig { } public boolean zombieTargetTurtleEggs = true; diff --git a/patches/server/0094-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch b/patches/server/0095-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch similarity index 97% rename from patches/server/0094-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch rename to patches/server/0095-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch index 3b83c2e61..3712484bf 100644 --- a/patches/server/0094-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch +++ b/patches/server/0095-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch @@ -1,4 +1,4 @@ -From 7f5d7e8cb23ae79cd833edb1c8e00dbd99b928aa Mon Sep 17 00:00:00 2001 +From 12f7259837f77bc389ee0bb398ec707acaac4fc1 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Thu, 9 May 2019 18:26:06 -0500 Subject: [PATCH] Phantoms attracted to crystals and crystals shoot phantoms @@ -24,10 +24,10 @@ index 6fe5678cf..bd0267ee4 100644 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 3e95af4ee..a5d4ca51a 100644 +index 476ca65a4..6f12615d3 100644 --- a/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java -@@ -1401,6 +1401,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +@@ -1588,6 +1588,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke return d3 * d3 + d4 * d4 + d5 * d5; } @@ -35,7 +35,7 @@ index 3e95af4ee..a5d4ca51a 100644 public double h(Entity entity) { return this.d(entity.getPositionVector()); } -@@ -1928,8 +1929,8 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +@@ -2115,8 +2116,8 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke return this.a(new ItemStack(imaterial), (float) i); } @@ -336,10 +336,10 @@ index 3cb78924d..ec09ec241 100644 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 8ce344c2a..080a53544 100644 +index 982abc4f2..9d33db49e 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -312,6 +312,15 @@ public class PurpurWorldConfig { +@@ -307,6 +307,15 @@ public class PurpurWorldConfig { ironGolemCanSwim = getBoolean("mobs.iron_golem.can-swim", ironGolemCanSwim); } diff --git a/patches/server/0095-Convert-legacy-item-text.patch b/patches/server/0096-Convert-legacy-item-text.patch similarity index 98% rename from patches/server/0095-Convert-legacy-item-text.patch rename to patches/server/0096-Convert-legacy-item-text.patch index d74d0ed2c..efc262621 100644 --- a/patches/server/0095-Convert-legacy-item-text.patch +++ b/patches/server/0096-Convert-legacy-item-text.patch @@ -1,4 +1,4 @@ -From 4be77127264751572a421248622c5bd436b4bedf Mon Sep 17 00:00:00 2001 +From fa486db80a9ffdc62e4397c12bbbfa34cc09a2c6 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Mon, 29 Jun 2020 08:56:53 -0500 Subject: [PATCH] Convert legacy item text diff --git a/patches/server/0096-Customizable-EnderDragon-Health.patch b/patches/server/0097-Customizable-EnderDragon-Health.patch similarity index 93% rename from patches/server/0096-Customizable-EnderDragon-Health.patch rename to patches/server/0097-Customizable-EnderDragon-Health.patch index 70b0f8b23..3dae4e20e 100644 --- a/patches/server/0096-Customizable-EnderDragon-Health.patch +++ b/patches/server/0097-Customizable-EnderDragon-Health.patch @@ -1,4 +1,4 @@ -From 99298e332aac29a905f102a40356a783cee008f7 Mon Sep 17 00:00:00 2001 +From ae1e8e2ff7b4ca7f2d78e21057b839d978b023cb Mon Sep 17 00:00:00 2001 From: Jason Bierque Date: Wed, 1 Jul 2020 22:36:06 +0200 Subject: [PATCH] Customizable EnderDragon Health @@ -30,10 +30,10 @@ index 08fa5a975..e08e6014f 100644 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 080a53544..4de6edd87 100644 +index 9d33db49e..57bfa4a46 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -257,9 +257,11 @@ public class PurpurWorldConfig { +@@ -252,9 +252,11 @@ public class PurpurWorldConfig { public boolean enderDragonAlwaysDropsEggBlock = false; public boolean enderDragonAlwaysDropsFullExp = false;