+Date: Sat, 9 Jan 2021 21:21:27 +0100
+Subject: [PATCH] Add unsafe Entity serialization API
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+
+diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java
+index 97b9ade0e771eae663fb42f91e15545034d58fc9..0c9d3c8a28a791fe26bb1c014b568e955eca0e8f 100644
+--- a/src/main/java/org/bukkit/UnsafeValues.java
++++ b/src/main/java/org/bukkit/UnsafeValues.java
+@@ -135,4 +135,28 @@ public interface UnsafeValues {
+ public int nextEntityId();
+
+ // Paper end
++
++ // Purpur start
++
++ /**
++ * Serialize entity to byte array
++ *
++ * @param entity entity to serialize
++ * @return serialized entity
++ */
++ byte[] serializeEntity(org.bukkit.entity.Entity entity);
++
++ /**
++ * Deserialize an entity from byte array
++ *
++ * The entity is not automatically spawned in the world. You will have to spawn
++ * the entity yourself with {@link org.bukkit.entity.Entity#spawnAt(Location)} or
++ * {@link org.bukkit.entity.Entity#spawnAt(Location, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason)}
++ *
++ * @param data serialized entity
++ * @param world world entity belongs in
++ * @return deserialized entity
++ */
++ org.bukkit.entity.Entity deserializeEntity(byte[] data, org.bukkit.World world);
++ // Purpur end
+ }
+diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java
+index 08dbe8208fad174f03a0e08c26bb48a0729ec0ce..2b7e8c7f24b2d9dd49db901f6279b8b5930a3006 100644
+--- a/src/main/java/org/bukkit/entity/Entity.java
++++ b/src/main/java/org/bukkit/entity/Entity.java
+@@ -745,5 +745,24 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
+ * @return True if ridable in water
+ */
+ boolean isRidableInWater();
++
++ /**
++ * Spawn this entity in the world at the given {@link Location} with the default spawn reason.
++ *
++ * @param location The location at which to spawn the entity.
++ * @return Whether the entity was successfully spawned.
++ */
++ default boolean spawnAt(@NotNull Location location) {
++ return spawnAt(location, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
++ }
++
++ /**
++ * Spawn this entity in the world at the given {@link Location} with the reason given.
++ *
++ * @param location The location at which to spawn the entity.
++ * @param spawnReason The reason for which the entity was spawned.
++ * @return Whether the entity was successfully spawned.
++ */
++ boolean spawnAt(@NotNull Location location, @NotNull org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason);
+ // Purpur end
+ }
diff --git a/patches/Purpur/patches/server/0025-Giants-AI-settings.patch b/patches/Purpur/patches/server/0025-Giants-AI-settings.patch
index 84ef9fab5..961eae292 100644
--- a/patches/Purpur/patches/server/0025-Giants-AI-settings.patch
+++ b/patches/Purpur/patches/server/0025-Giants-AI-settings.patch
@@ -5,7 +5,7 @@ Subject: [PATCH] Giants AI settings
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
-index 013c44f80f74376e8bbb37afb5de07aa5d8fb1bc..39036105b51dddbce8e4986e3be226f31fb13051 100644
+index 2b76b5a70280def08f239ff387407a9d328d484c..ceb30228fefee86d5706b3ac0c5f2ea83d336dfb 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -136,7 +136,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
diff --git a/patches/Purpur/patches/server/0039-Cows-eat-mushrooms.patch b/patches/Purpur/patches/server/0039-Cows-eat-mushrooms.patch
index 457a3c9b1..a16338263 100644
--- a/patches/Purpur/patches/server/0039-Cows-eat-mushrooms.patch
+++ b/patches/Purpur/patches/server/0039-Cows-eat-mushrooms.patch
@@ -5,7 +5,7 @@ Subject: [PATCH] Cows eat mushrooms
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
-index 39036105b51dddbce8e4986e3be226f31fb13051..4ed4f31c8e34279f9aa9fd7bbddbb36239ea36ef 100644
+index ceb30228fefee86d5706b3ac0c5f2ea83d336dfb..d16b3482914e1bd390c745b590f2b538c1a45601 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -2778,6 +2778,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
diff --git a/patches/Purpur/patches/server/0052-Fix-the-dead-lagging-the-server.patch b/patches/Purpur/patches/server/0052-Fix-the-dead-lagging-the-server.patch
index c23ba84cf..7f907d9fd 100644
--- a/patches/Purpur/patches/server/0052-Fix-the-dead-lagging-the-server.patch
+++ b/patches/Purpur/patches/server/0052-Fix-the-dead-lagging-the-server.patch
@@ -5,7 +5,7 @@ Subject: [PATCH] Fix the dead lagging the server
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
-index 4ed4f31c8e34279f9aa9fd7bbddbb36239ea36ef..f18941c7c740959181b728ab9da06c7e9d97aa79 100644
+index d16b3482914e1bd390c745b590f2b538c1a45601..a218a7b35514a59f0bc7ed65ce3547d383faaa41 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -1523,6 +1523,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
diff --git a/patches/Purpur/patches/server/0067-Add-canSaveToDisk-to-Entity.patch b/patches/Purpur/patches/server/0067-Add-canSaveToDisk-to-Entity.patch
index 1dd9f44d5..214888102 100644
--- a/patches/Purpur/patches/server/0067-Add-canSaveToDisk-to-Entity.patch
+++ b/patches/Purpur/patches/server/0067-Add-canSaveToDisk-to-Entity.patch
@@ -17,7 +17,7 @@ index 076d6c1e1cc049dd312ecb30518e7b25fc2d7371..5f04591193d58ba7897194142da5efcb
final int saveLimit = worldserver.paperConfig.entityPerChunkSaveLimits.getOrDefault(entityType, -1);
if (saveLimit > -1) {
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
-index f18941c7c740959181b728ab9da06c7e9d97aa79..dfbb5a9538780cbd2a5766486138f35b189da235 100644
+index a218a7b35514a59f0bc7ed65ce3547d383faaa41..32e072b7ddf20203c7db83c5e0c0504e3b8ba8da 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -308,6 +308,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
diff --git a/patches/Purpur/patches/server/0068-Configurable-void-damage-height.patch b/patches/Purpur/patches/server/0068-Configurable-void-damage-height.patch
index 809b31c00..e1a27ed4a 100644
--- a/patches/Purpur/patches/server/0068-Configurable-void-damage-height.patch
+++ b/patches/Purpur/patches/server/0068-Configurable-void-damage-height.patch
@@ -5,7 +5,7 @@ Subject: [PATCH] Configurable void damage height
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
-index dfbb5a9538780cbd2a5766486138f35b189da235..9eb2e73c084b142bf04f798b572e6ca87f4f8416 100644
+index 32e072b7ddf20203c7db83c5e0c0504e3b8ba8da..7b232293803f19bcfd4a8201a06bfdaa7fb08093 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -611,7 +611,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
diff --git a/patches/Purpur/patches/server/0075-Item-entity-immunities.patch b/patches/Purpur/patches/server/0075-Item-entity-immunities.patch
index 99fa23233..f469bbed3 100644
--- a/patches/Purpur/patches/server/0075-Item-entity-immunities.patch
+++ b/patches/Purpur/patches/server/0075-Item-entity-immunities.patch
@@ -5,7 +5,7 @@ Subject: [PATCH] Item entity immunities
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
-index 9eb2e73c084b142bf04f798b572e6ca87f4f8416..f5159b76dee6127d7db2addfcb512b5b1f5b9c41 100644
+index 7b232293803f19bcfd4a8201a06bfdaa7fb08093..1c88b914dac85cf1d5cf1733cb9f8d5f0407a986 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -1472,6 +1472,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
diff --git a/patches/Purpur/patches/server/0078-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch b/patches/Purpur/patches/server/0078-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch
index 926ee69ac..b00c34489 100644
--- a/patches/Purpur/patches/server/0078-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch
+++ b/patches/Purpur/patches/server/0078-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch
@@ -17,7 +17,7 @@ index 6fe5678cffc2487fe00c953d772f764bb37a4b11..bd0267ee4b3782f6d1ec39cba7966ba4
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 f5159b76dee6127d7db2addfcb512b5b1f5b9c41..905e3a98fe900c82053b1514122bfe6cf1000dfa 100644
+index 1c88b914dac85cf1d5cf1733cb9f8d5f0407a986..d888dbb2f6c20eee98c0c8b0d1c62ba30615e8eb 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -2138,8 +2138,8 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
diff --git a/patches/Purpur/patches/server/0103-Stop-squids-floating-on-top-of-water.patch b/patches/Purpur/patches/server/0103-Stop-squids-floating-on-top-of-water.patch
index be260dede..d8aff1356 100644
--- a/patches/Purpur/patches/server/0103-Stop-squids-floating-on-top-of-water.patch
+++ b/patches/Purpur/patches/server/0103-Stop-squids-floating-on-top-of-water.patch
@@ -5,7 +5,7 @@ Subject: [PATCH] Stop squids floating on top of water
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
-index 905e3a98fe900c82053b1514122bfe6cf1000dfa..e59826b3e822a49378ae0d7b7cbca8c5d5ff476d 100644
+index d888dbb2f6c20eee98c0c8b0d1c62ba30615e8eb..b3b654da3c5a036871248b0a7c8e6ca77b44345d 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -3448,8 +3448,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
diff --git a/patches/Purpur/patches/server/0104-Ridables.patch b/patches/Purpur/patches/server/0104-Ridables.patch
index ec42d29bc..46e4f09ec 100644
--- a/patches/Purpur/patches/server/0104-Ridables.patch
+++ b/patches/Purpur/patches/server/0104-Ridables.patch
@@ -3,6 +3,7 @@ From: William Blake Galbreath
Date: Sun, 5 Jul 2020 22:19:49 -0500
Subject: [PATCH] Ridables
+test
diff --git a/src/main/java/net/minecraft/server/AttributeDefaults.java b/src/main/java/net/minecraft/server/AttributeDefaults.java
index 8f95a4e49714e352b9cdf82d7f4acdd3459978ad..ab05b5e403cf54756aa35891dc0d950187a9d4ec 100644
@@ -161,7 +162,7 @@ index bd0267ee4b3782f6d1ec39cba7966ba4f62f1adf..8b36ac2b0950a827763aa2357700f37e
this.B = true;
return this;
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
-index e59826b3e822a49378ae0d7b7cbca8c5d5ff476d..0115e2c73eff9d5e4c6778e32fc54b9c116b6b22 100644
+index b3b654da3c5a036871248b0a7c8e6ca77b44345d..40432014000b0e6113dc06ab36b64111fa50ad50 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -80,7 +80,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
@@ -2865,10 +2866,10 @@ index 0af6c9395b5d98e6bfa162f651d0e8cb89035afd..e402d4a77b57b8b12b7575a9793c30d7
this.goalSelector.a(2, new PathfinderGoalSit(this));
this.goalSelector.a(2, new PathfinderGoalFollowOwner(this, 1.0D, 5.0F, 1.0F, true));
diff --git a/src/main/java/net/minecraft/server/EntityPhantom.java b/src/main/java/net/minecraft/server/EntityPhantom.java
-index bdfe073dcd255a7359127f9ae3a962642be5526d..f8c3480045e86a18501db223c1b2254cf3298a42 100644
+index bdfe073dcd255a7359127f9ae3a962642be5526d..c70281fddcbe5a97a1eb176def99cdf31de37579 100644
--- a/src/main/java/net/minecraft/server/EntityPhantom.java
+++ b/src/main/java/net/minecraft/server/EntityPhantom.java
-@@ -25,6 +25,58 @@ public class EntityPhantom extends EntityFlying implements IMonster {
+@@ -25,6 +25,59 @@ public class EntityPhantom extends EntityFlying implements IMonster {
this.lookController = new EntityPhantom.f(this);
}
@@ -2918,6 +2919,7 @@ index bdfe073dcd255a7359127f9ae3a962642be5526d..f8c3480045e86a18501db223c1b2254c
+ org.bukkit.util.Vector target = loc.getDirection().normalize().multiply(100).add(loc.toVector());
+
+ net.pl3x.purpur.entity.PhantomFlames flames = new net.pl3x.purpur.entity.PhantomFlames(world, this);
++ flames.canGrief = world.purpurConfig.phantomAllowGriefing;
+ flames.shoot(target.getX() - locX(), target.getY() - locY(), target.getZ() - locZ(), 1.0F, 5.0F);
+ world.addEntity(flames);
+ return true;
@@ -2927,7 +2929,7 @@ index bdfe073dcd255a7359127f9ae3a962642be5526d..f8c3480045e86a18501db223c1b2254c
@Override
protected EntityAIBodyControl r() {
return new EntityPhantom.d(this);
-@@ -33,6 +85,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
+@@ -33,6 +86,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
@Override
protected void initPathfinder() {
// Purpur start
@@ -2935,7 +2937,7 @@ index bdfe073dcd255a7359127f9ae3a962642be5526d..f8c3480045e86a18501db223c1b2254c
if (world.purpurConfig.phantomOrbitCrystalRadius > 0) {
this.goalSelector.a(1, new FindCrystalGoal(this));
this.goalSelector.a(2, new OrbitCrystalGoal(this));
-@@ -40,6 +93,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
+@@ -40,6 +94,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
this.goalSelector.a(3, new EntityPhantom.c()); // PickAttackGoal
this.goalSelector.a(4, new EntityPhantom.i()); // SweepAttackGoal
this.goalSelector.a(5, new EntityPhantom.e()); // OrbitPointGoal
@@ -2943,7 +2945,7 @@ index bdfe073dcd255a7359127f9ae3a962642be5526d..f8c3480045e86a18501db223c1b2254c
this.targetSelector.a(1, new EntityPhantom.b()); // AttackPlayer Goal
// Purpur end
}
-@@ -126,7 +180,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
+@@ -126,7 +181,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
@Override
public void movementTick() {
@@ -2952,7 +2954,7 @@ index bdfe073dcd255a7359127f9ae3a962642be5526d..f8c3480045e86a18501db223c1b2254c
this.setOnFire(8);
}
-@@ -368,7 +422,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
+@@ -368,7 +423,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
@Override
public boolean a() {
@@ -2961,7 +2963,7 @@ index bdfe073dcd255a7359127f9ae3a962642be5526d..f8c3480045e86a18501db223c1b2254c
if (this.c > 0) {
--this.c;
return false;
-@@ -397,7 +451,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
+@@ -397,7 +452,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
@Override
public boolean b() {
@@ -2970,7 +2972,7 @@ index bdfe073dcd255a7359127f9ae3a962642be5526d..f8c3480045e86a18501db223c1b2254c
EntityLiving entityliving = EntityPhantom.this.getGoalTarget();
return entityliving != null ? EntityPhantom.this.a(entityliving, PathfinderTargetCondition.a) : false;
-@@ -412,7 +466,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
+@@ -412,7 +467,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
@Override
public boolean a() {
@@ -2979,7 +2981,7 @@ index bdfe073dcd255a7359127f9ae3a962642be5526d..f8c3480045e86a18501db223c1b2254c
EntityLiving entityliving = EntityPhantom.this.getGoalTarget();
return entityliving != null ? EntityPhantom.this.a(EntityPhantom.this.getGoalTarget(), PathfinderTargetCondition.a) : false;
-@@ -610,14 +664,23 @@ public class EntityPhantom extends EntityFlying implements IMonster {
+@@ -610,14 +665,23 @@ public class EntityPhantom extends EntityFlying implements IMonster {
}
}
@@ -3005,7 +3007,7 @@ index bdfe073dcd255a7359127f9ae3a962642be5526d..f8c3480045e86a18501db223c1b2254c
}
class d extends EntityAIBodyControl {
-@@ -633,7 +696,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
+@@ -633,7 +697,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
}
}
@@ -3014,7 +3016,7 @@ index bdfe073dcd255a7359127f9ae3a962642be5526d..f8c3480045e86a18501db223c1b2254c
private float j = 0.1F;
-@@ -642,7 +705,19 @@ public class EntityPhantom extends EntityFlying implements IMonster {
+@@ -642,7 +706,19 @@ public class EntityPhantom extends EntityFlying implements IMonster {
}
@Override
@@ -5071,7 +5073,7 @@ index c314a8c9a921a95cea43b748e2037521d948e1e7..59f3122aab9940cb3c3c1efb2664ab08
public static int dungeonSeed = -1;
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 637cac2758a44e72794953b9fbca2accb7d86b6a..3d3505f538510fbef4a7d584fa5f03c48be184f7 100644
+index 637cac2758a44e72794953b9fbca2accb7d86b6a..d8b5e091047210a8eff45e493f07d30ffa6d9f81 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -42,11 +42,6 @@ public class PurpurWorldConfig {
@@ -5404,9 +5406,11 @@ index 637cac2758a44e72794953b9fbca2accb7d86b6a..3d3505f538510fbef4a7d584fa5f03c4
public double phantomAttackedByCrystalRadius = 0.0D;
public float phantomAttackedByCrystalDamage = 1.0F;
public double phantomOrbitCrystalRadius = 0.0D;
-@@ -451,6 +663,11 @@ public class PurpurWorldConfig {
+@@ -450,7 +662,13 @@ public class PurpurWorldConfig {
+ public int phantomBurnInLight = 0;
public boolean phantomIgnorePlayersWithTorch = false;
public boolean phantomBurnInDaylight = true;
++ public boolean phantomAllowGriefing = false;
private void phantomSettings() {
+ phantomRidable = getBoolean("mobs.phantom.ridable", phantomRidable);
+ phantomRidableInWater = getBoolean("mobs.phantom.ridable-in-water", phantomRidableInWater);
@@ -5416,8 +5420,11 @@ index 637cac2758a44e72794953b9fbca2accb7d86b6a..3d3505f538510fbef4a7d584fa5f03c4
phantomAttackedByCrystalRadius = getDouble("mobs.phantom.attacked-by-crystal-range", phantomAttackedByCrystalRadius);
phantomAttackedByCrystalDamage = (float) getDouble("mobs.phantom.attacked-by-crystal-damage", phantomAttackedByCrystalDamage);
phantomOrbitCrystalRadius = getDouble("mobs.phantom.orbit-crystal-radius", phantomOrbitCrystalRadius);
-@@ -471,40 +688,184 @@ public class PurpurWorldConfig {
+@@ -469,42 +687,187 @@ public class PurpurWorldConfig {
+ phantomBurnInLight = getInt("mobs.phantom.burn-in-light", phantomBurnInLight);
+ phantomBurnInDaylight = getBoolean("mobs.phantom.burn-in-daylight", phantomBurnInDaylight);
phantomIgnorePlayersWithTorch = getBoolean("mobs.phantom.ignore-players-with-torch", phantomIgnorePlayersWithTorch);
++ phantomAllowGriefing = getBoolean("mobs.phantom.allow-griefing", phantomAllowGriefing);
}
+ public boolean pigRidable = false;
@@ -5601,7 +5608,7 @@ index 637cac2758a44e72794953b9fbca2accb7d86b6a..3d3505f538510fbef4a7d584fa5f03c4
public int villagerBrainTicks = 1;
public boolean villagerUseBrainTicksOnlyWhenLagging = true;
public boolean villagerCanBeLeashed = false;
-@@ -514,6 +875,8 @@ public class PurpurWorldConfig {
+@@ -514,6 +877,8 @@ public class PurpurWorldConfig {
public int villagerSpawnIronGolemLimit = 0;
public boolean villagerCanBreed = true;
private void villagerSettings() {
@@ -5610,7 +5617,7 @@ index 637cac2758a44e72794953b9fbca2accb7d86b6a..3d3505f538510fbef4a7d584fa5f03c4
villagerBrainTicks = getInt("mobs.villager.brain-ticks", villagerBrainTicks);
villagerUseBrainTicksOnlyWhenLagging = getBoolean("mobs.villager.use-brain-ticks-only-when-lagging", villagerUseBrainTicksOnlyWhenLagging);
villagerCanBeLeashed = getBoolean("mobs.villager.can-be-leashed", villagerCanBeLeashed);
-@@ -524,45 +887,108 @@ public class PurpurWorldConfig {
+@@ -524,45 +889,108 @@ public class PurpurWorldConfig {
villagerCanBreed = getBoolean("mobs.villager.can-breed", villagerCanBreed);
}
@@ -6217,15 +6224,16 @@ index 0000000000000000000000000000000000000000..a01524c6abaec13d7249d7aba6da9e4b
+}
diff --git a/src/main/java/net/pl3x/purpur/entity/PhantomFlames.java b/src/main/java/net/pl3x/purpur/entity/PhantomFlames.java
new file mode 100644
-index 0000000000000000000000000000000000000000..3059078c37deb35fcd20e27767f9b79503802cf4
+index 0000000000000000000000000000000000000000..9a9e46d7ee247f9e43ae5c697f10e4665fd6e4e6
--- /dev/null
+++ b/src/main/java/net/pl3x/purpur/entity/PhantomFlames.java
-@@ -0,0 +1,128 @@
+@@ -0,0 +1,140 @@
+package net.pl3x.purpur.entity;
+
+import net.minecraft.server.BlockBase;
+import net.minecraft.server.DamageSource;
+import net.minecraft.server.Entity;
++import net.minecraft.server.EntityArmorStand;
+import net.minecraft.server.EntityLiving;
+import net.minecraft.server.EntityLlamaSpit;
+import net.minecraft.server.EntityPhantom;
@@ -6245,6 +6253,7 @@ index 0000000000000000000000000000000000000000..3059078c37deb35fcd20e27767f9b795
+public class PhantomFlames extends EntityLlamaSpit {
+ public EntityPhantom phantom;
+ public int ticksLived;
++ public boolean canGrief = false;
+
+ public PhantomFlames(EntityTypes extends EntityLlamaSpit> entitytypes, World world) {
+ super(entitytypes, world);
@@ -6285,6 +6294,10 @@ index 0000000000000000000000000000000000000000..3059078c37deb35fcd20e27767f9b795
+ onHit(hitResult);
+ }
+
++ if (dead) {
++ return;
++ }
++
+ double x = this.locX() + mot.x;
+ double y = this.locY() + mot.y;
+ double z = this.locZ() + mot.z;
@@ -6336,16 +6349,22 @@ index 0000000000000000000000000000000000000000..3059078c37deb35fcd20e27767f9b795
+ protected void onHit(MovingObjectPositionEntity rayTrace) {
+ Entity shooter = getShooter();
+ if (shooter instanceof EntityLiving) {
-+ rayTrace.getEntity().damageEntity(DamageSource.indirectMobAttack(this, (EntityLiving) shooter).setProjectile(), world.purpurConfig.phantomFlameDamage);
-+ if (world.purpurConfig.phantomFlameFireTime > 0) {
-+ rayTrace.getEntity().setOnFire(world.purpurConfig.phantomFlameFireTime);
++ Entity target = rayTrace.getEntity();
++ if (canGrief || (target instanceof EntityLiving && !(target instanceof EntityArmorStand))) {
++ target.damageEntity(DamageSource.indirectMobAttack(this, (EntityLiving) shooter).setProjectile(), world.purpurConfig.phantomFlameDamage);
++ if (world.purpurConfig.phantomFlameFireTime > 0) {
++ target.setOnFire(world.purpurConfig.phantomFlameFireTime);
++ }
+ }
+ }
++ die();
+ }
+
+ protected void onHit(MovingObjectPositionBlock rayTrace) {
-+ IBlockData iblockdata = world.getType(rayTrace.getBlockPosition());
-+ iblockdata.a(world, iblockdata, rayTrace, this);
++ if (canGrief) {
++ IBlockData iblockdata = world.getType(rayTrace.getBlockPosition());
++ iblockdata.a(world, iblockdata, rayTrace, this);
++ }
+ die();
+ }
+}
diff --git a/patches/Purpur/patches/server/0107-Entities-can-use-portals-configuration.patch b/patches/Purpur/patches/server/0107-Entities-can-use-portals-configuration.patch
index fa616d1dc..2e7b2e0e2 100644
--- a/patches/Purpur/patches/server/0107-Entities-can-use-portals-configuration.patch
+++ b/patches/Purpur/patches/server/0107-Entities-can-use-portals-configuration.patch
@@ -5,7 +5,7 @@ Subject: [PATCH] Entities can use portals configuration
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
-index 0115e2c73eff9d5e4c6778e32fc54b9c116b6b22..e4f2e51b6306fcaf161b7dfb734d9d28947e964b 100644
+index 40432014000b0e6113dc06ab36b64111fa50ad50..444305d11eb1652b8618b5e2a41992974622e1a0 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -2414,7 +2414,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
@@ -27,7 +27,7 @@ index 0115e2c73eff9d5e4c6778e32fc54b9c116b6b22..e4f2e51b6306fcaf161b7dfb734d9d28
public float a(Explosion explosion, IBlockAccess iblockaccess, BlockPosition blockposition, IBlockData iblockdata, Fluid fluid, float f) {
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 3d3505f538510fbef4a7d584fa5f03c48be184f7..d0d220ece6596bbefcb428ffc94aff566ad6ef19 100644
+index d8b5e091047210a8eff45e493f07d30ffa6d9f81..cf4ac765fdbaf961e913ca028edc084373eba978 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -158,6 +158,7 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0109-Customizable-wither-health-and-healing.patch b/patches/Purpur/patches/server/0109-Customizable-wither-health-and-healing.patch
index e8c231571..ad8dd4d74 100644
--- a/patches/Purpur/patches/server/0109-Customizable-wither-health-and-healing.patch
+++ b/patches/Purpur/patches/server/0109-Customizable-wither-health-and-healing.patch
@@ -44,10 +44,10 @@ index 59382230aec623f7de889c30a0ed6a2a3fa35a05..121eefd5d89f88c762b19088c657a41f
//this.bossBattle.setProgress(this.getHealth() / this.getMaxHealth()); // Paper - Moved down
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index d0d220ece6596bbefcb428ffc94aff566ad6ef19..9ca3615cc66f4bca038f63add1dfb739d8b0a4c0 100644
+index cf4ac765fdbaf961e913ca028edc084373eba978..94a870113dc45201379c1efc7e83162c303573df 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-@@ -919,10 +919,21 @@ public class PurpurWorldConfig {
+@@ -921,10 +921,21 @@ public class PurpurWorldConfig {
public boolean witherRidable = false;
public boolean witherRidableInWater = false;
public double witherMaxY = 256D;
diff --git a/patches/Purpur/patches/server/0110-Allow-toggling-special-MobSpawners-per-world.patch b/patches/Purpur/patches/server/0110-Allow-toggling-special-MobSpawners-per-world.patch
index 90e760d45..44a210317 100644
--- a/patches/Purpur/patches/server/0110-Allow-toggling-special-MobSpawners-per-world.patch
+++ b/patches/Purpur/patches/server/0110-Allow-toggling-special-MobSpawners-per-world.patch
@@ -72,7 +72,7 @@ index 5a6aace070e64b6db315d766d16773c408de638e..ded19d1773237eaf51f72ce93a6794db
this.worldDataServer = (WorldDataServer) iworlddataserver;
worldDataServer.world = this;
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 9ca3615cc66f4bca038f63add1dfb739d8b0a4c0..7843d6ed07ae928eb450b6604cf58900a71fc958 100644
+index 94a870113dc45201379c1efc7e83162c303573df..c8666ce6bdf2e61dd3ccc7ff6cc0810559ce3f5b 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -7,6 +7,8 @@ import net.minecraft.server.IRegistry;
diff --git a/patches/Purpur/patches/server/0111-Raid-cooldown-setting.patch b/patches/Purpur/patches/server/0111-Raid-cooldown-setting.patch
index 41daf9508..e7504aee8 100644
--- a/patches/Purpur/patches/server/0111-Raid-cooldown-setting.patch
+++ b/patches/Purpur/patches/server/0111-Raid-cooldown-setting.patch
@@ -52,7 +52,7 @@ index 826dcf9f7eedc3664d66170b97b2a19552a0dc60..807910c60e6cad58b91474b0477e6fc1
if (!this.raids.containsKey(raid.getId())) {
this.raids.put(raid.getId(), raid);
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 7843d6ed07ae928eb450b6604cf58900a71fc958..9461f12a4c4e863f9e7e2d7fc0848f328f580339 100644
+index c8666ce6bdf2e61dd3ccc7ff6cc0810559ce3f5b..1c9db2dc3d5577906aa1ac208aad3c6865040381 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -173,6 +173,7 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0112-Despawn-rate-config-options-per-projectile-type.patch b/patches/Purpur/patches/server/0112-Despawn-rate-config-options-per-projectile-type.patch
index e6424b931..e8ba78c37 100644
--- a/patches/Purpur/patches/server/0112-Despawn-rate-config-options-per-projectile-type.patch
+++ b/patches/Purpur/patches/server/0112-Despawn-rate-config-options-per-projectile-type.patch
@@ -300,7 +300,7 @@ index b7e540dfeeabb13227596ecfc6eddabf3cfde537..56adefabdfbf444e87129715f107c6d3
public boolean checkIfLeftOwner() { return this.h(); } // Purpur - OBFHELPER
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 9461f12a4c4e863f9e7e2d7fc0848f328f580339..5da0cd476fd2d99bede6c4f897c93144cfeb7579 100644
+index 1c9db2dc3d5577906aa1ac208aad3c6865040381..c9884c382e3e16db0d4c1b7d0d804aafbd6a3fa8 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -165,6 +165,35 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0114-Add-option-to-disable-zombie-aggressiveness-towards-.patch b/patches/Purpur/patches/server/0114-Add-option-to-disable-zombie-aggressiveness-towards-.patch
index 2b5efca0b..ebfb530d8 100644
--- a/patches/Purpur/patches/server/0114-Add-option-to-disable-zombie-aggressiveness-towards-.patch
+++ b/patches/Purpur/patches/server/0114-Add-option-to-disable-zombie-aggressiveness-towards-.patch
@@ -69,10 +69,10 @@ index 7e1e056bdd966a14a184eb76717116998b6e5cb3..fd28ef623f8b6db5e36328d4ef2771e8
this.targetSelector.a(5, new PathfinderGoalNearestAttackableTarget<>(this, EntityTurtle.class, 10, true, false, EntityTurtle.bo));
}
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 5da0cd476fd2d99bede6c4f897c93144cfeb7579..6eb30ec9f9e25cb0d9a18cee49fb8ed6a3b00f95 100644
+index c9884c382e3e16db0d4c1b7d0d804aafbd6a3fa8..6d0d43e77bbf6f792257eb368e572b1bfade3266 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-@@ -1021,12 +1021,14 @@ public class PurpurWorldConfig {
+@@ -1023,12 +1023,14 @@ public class PurpurWorldConfig {
public boolean zombieJockeyOnlyBaby = true;
public double zombieJockeyChance = 0.05D;
public boolean zombieJockeyTryExistingChickens = true;
diff --git a/patches/Purpur/patches/server/0115-Persistent-TileEntity-Lore-and-DisplayName.patch b/patches/Purpur/patches/server/0115-Persistent-TileEntity-Lore-and-DisplayName.patch
index 334e385fb..369b6b067 100644
--- a/patches/Purpur/patches/server/0115-Persistent-TileEntity-Lore-and-DisplayName.patch
+++ b/patches/Purpur/patches/server/0115-Persistent-TileEntity-Lore-and-DisplayName.patch
@@ -165,7 +165,7 @@ index 58d958a88ac5af5b889d719d9f1ea90ce45cf184..8e8749095427b44e04582593114cae8c
+ // Purpur end
}
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 6eb30ec9f9e25cb0d9a18cee49fb8ed6a3b00f95..203913c91d1c12a233a9c0af8b812752457b99e4 100644
+index 6d0d43e77bbf6f792257eb368e572b1bfade3266..4515c95a195ab962513ddc6868f9cdfd47f61d68 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -200,6 +200,7 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0117-Flying-squids-Oh-my.patch b/patches/Purpur/patches/server/0117-Flying-squids-Oh-my.patch
index ef9d32fbd..cc82d9481 100644
--- a/patches/Purpur/patches/server/0117-Flying-squids-Oh-my.patch
+++ b/patches/Purpur/patches/server/0117-Flying-squids-Oh-my.patch
@@ -38,10 +38,10 @@ index 70b952f10a2af547f58069977ee135469d02f84d..cee226501690e1c00983a01ac82bc738
float f1 = MathHelper.cos(f) * 0.2F;
float f2 = -0.1F + this.b.getRandom().nextFloat() * 0.2F;
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 203913c91d1c12a233a9c0af8b812752457b99e4..1ea4a9b5c710a188f8321406737400a3caeb3c94 100644
+index 4515c95a195ab962513ddc6868f9cdfd47f61d68..39f25fe85d8d2c8cd48ba0f5988b1839d3d331aa 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-@@ -877,10 +877,12 @@ public class PurpurWorldConfig {
+@@ -879,10 +879,12 @@ public class PurpurWorldConfig {
public boolean squidRidable = false;
public boolean squidImmuneToEAR = true;
public double squidOffsetWaterCheck = 0.0D;
diff --git a/patches/Purpur/patches/server/0118-Infinity-bow-settings.patch b/patches/Purpur/patches/server/0118-Infinity-bow-settings.patch
index 6eaf7a0d4..e7a9d8a2f 100644
--- a/patches/Purpur/patches/server/0118-Infinity-bow-settings.patch
+++ b/patches/Purpur/patches/server/0118-Infinity-bow-settings.patch
@@ -26,7 +26,7 @@ index dd6a93dc78a4589f2c65d1738c432def1285f3e2..8241f3dafa5852bed7a3967e7260b36f
entityhuman.b(StatisticList.ITEM_USED.b(this));
}
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 1ea4a9b5c710a188f8321406737400a3caeb3c94..65b9b55e9cfaa4d741a09249c54b9d64cab3e910 100644
+index 39f25fe85d8d2c8cd48ba0f5988b1839d3d331aa..3d6e1eb623b66d9157ca33f64483e857e3b6b39e 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -165,6 +165,15 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0119-Stonecutter-damage.patch b/patches/Purpur/patches/server/0119-Stonecutter-damage.patch
index 9ea272199..a5bdec3ed 100644
--- a/patches/Purpur/patches/server/0119-Stonecutter-damage.patch
+++ b/patches/Purpur/patches/server/0119-Stonecutter-damage.patch
@@ -39,7 +39,7 @@ index 33804e68931e8b4145b896eedeab79bde78779f2..fabadcd7a21b0e4ad0e2eeadcd8926df
}
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 65b9b55e9cfaa4d741a09249c54b9d64cab3e910..a1c4a408abb729e2fa6e08aa57bcaaf2a2a2d065 100644
+index 3d6e1eb623b66d9157ca33f64483e857e3b6b39e..95d14d82d6f8bce762ef70645f0f8eae3093914c 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -383,6 +383,11 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0120-Configurable-daylight-cycle.patch b/patches/Purpur/patches/server/0120-Configurable-daylight-cycle.patch
index 0c0ec51f9..0b86873c6 100644
--- a/patches/Purpur/patches/server/0120-Configurable-daylight-cycle.patch
+++ b/patches/Purpur/patches/server/0120-Configurable-daylight-cycle.patch
@@ -74,7 +74,7 @@ index ded19d1773237eaf51f72ce93a6794db8f56d160..cb2c429bda81b8c151a50ef3627716fe
public void doMobSpawning(boolean flag, boolean flag1) {
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index a1c4a408abb729e2fa6e08aa57bcaaf2a2a2d065..ef09664ad1521b17b99fa99f5a560167e4ca19b2 100644
+index 95d14d82d6f8bce762ef70645f0f8eae3093914c..0b58a2e99a2f89d450d7980eb4837172e8a10dba 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -116,6 +116,13 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0122-Infinite-fuel-furnace.patch b/patches/Purpur/patches/server/0122-Infinite-fuel-furnace.patch
index 72f01689c..26047db6b 100644
--- a/patches/Purpur/patches/server/0122-Infinite-fuel-furnace.patch
+++ b/patches/Purpur/patches/server/0122-Infinite-fuel-furnace.patch
@@ -41,7 +41,7 @@ index e75e676d196d9f5a3409ec50645fab611b0afdad..76ea1d003b43d822e2b85eec3b874015
if (flag1) {
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index ef09664ad1521b17b99fa99f5a560167e4ca19b2..8bd8a84bd14fff380662d19c1cbe6997a65fb33a 100644
+index 0b58a2e99a2f89d450d7980eb4837172e8a10dba..0cae636df21d73f88acc4dbbf7563cf8a44c5a58 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -351,6 +351,11 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0125-Ability-to-re-add-farmland-mechanics-from-Alpha.patch b/patches/Purpur/patches/server/0125-Ability-to-re-add-farmland-mechanics-from-Alpha.patch
index 44b13ff51..b7361f011 100644
--- a/patches/Purpur/patches/server/0125-Ability-to-re-add-farmland-mechanics-from-Alpha.patch
+++ b/patches/Purpur/patches/server/0125-Ability-to-re-add-farmland-mechanics-from-Alpha.patch
@@ -24,7 +24,7 @@ index 8dd48669c29dd51ed4d535dad0b0319f4bb2250c..099e0d3df219408ebe2a741a02e53eb9
return;
}
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 8bd8a84bd14fff380662d19c1cbe6997a65fb33a..f8d7cefc1f231bfe6f09ff6bc01f00a7e3a90553 100644
+index 0cae636df21d73f88acc4dbbf7563cf8a44c5a58..9f8d9b65b151149720ce2d69299ddd0bbe0045d1 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -347,8 +347,10 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0126-Add-adjustable-breeding-cooldown-to-config.patch b/patches/Purpur/patches/server/0126-Add-adjustable-breeding-cooldown-to-config.patch
index c0e1f5d25..94d49da80 100644
--- a/patches/Purpur/patches/server/0126-Add-adjustable-breeding-cooldown-to-config.patch
+++ b/patches/Purpur/patches/server/0126-Add-adjustable-breeding-cooldown-to-config.patch
@@ -94,7 +94,7 @@ index ded92fe7c7871bae6e9741747a67636d570cdeef..7c367fe6152c30aab3e53c8f88cceba6
this.generator = gen;
this.world = new CraftWorld((WorldServer) this, gen, env);
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index f8d7cefc1f231bfe6f09ff6bc01f00a7e3a90553..a70bd4fdb0634110bc2b68780c28d4a2b788e1e6 100644
+index 9f8d9b65b151149720ce2d69299ddd0bbe0045d1..84b2b8618162f81369dac9e8341374447d9b1737 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -220,6 +220,7 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0127-Make-animal-breeding-times-configurable.patch b/patches/Purpur/patches/server/0127-Make-animal-breeding-times-configurable.patch
index 4b6d63ddf..ada8316fe 100644
--- a/patches/Purpur/patches/server/0127-Make-animal-breeding-times-configurable.patch
+++ b/patches/Purpur/patches/server/0127-Make-animal-breeding-times-configurable.patch
@@ -398,7 +398,7 @@ index 9ae7168595dd66860e09ef87f946b18b010e54b1..6c25f667eecdf345289a0dbf885c9d71
@Override
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index a70bd4fdb0634110bc2b68780c28d4a2b788e1e6..9947b5ad48ff24f79f900aa59ae39364db44576b 100644
+index 84b2b8618162f81369dac9e8341374447d9b1737..2b68f25b6a589de13c534e10f9f24a45f7274963 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -434,10 +434,12 @@ public class PurpurWorldConfig {
@@ -547,7 +547,7 @@ index a70bd4fdb0634110bc2b68780c28d4a2b788e1e6..9947b5ad48ff24f79f900aa59ae39364
}
public boolean parrotRidable = false;
-@@ -782,10 +808,12 @@ public class PurpurWorldConfig {
+@@ -784,10 +810,12 @@ public class PurpurWorldConfig {
public boolean pigRidable = false;
public boolean pigRidableInWater = false;
public boolean pigGiveSaddleBack = false;
@@ -560,7 +560,7 @@ index a70bd4fdb0634110bc2b68780c28d4a2b788e1e6..9947b5ad48ff24f79f900aa59ae39364
}
public boolean piglinRidable = false;
-@@ -813,12 +841,14 @@ public class PurpurWorldConfig {
+@@ -815,12 +843,14 @@ public class PurpurWorldConfig {
public boolean polarBearRidableInWater = false;
public String polarBearBreedableItemString = "";
public Item polarBearBreedableItem = null;
@@ -575,7 +575,7 @@ index a70bd4fdb0634110bc2b68780c28d4a2b788e1e6..9947b5ad48ff24f79f900aa59ae39364
}
public boolean pufferfishRidable = false;
-@@ -830,11 +860,13 @@ public class PurpurWorldConfig {
+@@ -832,11 +862,13 @@ public class PurpurWorldConfig {
public boolean rabbitRidableInWater = false;
public double rabbitNaturalToast = 0.0D;
public double rabbitNaturalKiller = 0.0D;
@@ -589,7 +589,7 @@ index a70bd4fdb0634110bc2b68780c28d4a2b788e1e6..9947b5ad48ff24f79f900aa59ae39364
}
public boolean ravagerRidable = false;
-@@ -851,9 +883,11 @@ public class PurpurWorldConfig {
+@@ -853,9 +885,11 @@ public class PurpurWorldConfig {
public boolean sheepRidable = false;
public boolean sheepRidableInWater = false;
@@ -601,7 +601,7 @@ index a70bd4fdb0634110bc2b68780c28d4a2b788e1e6..9947b5ad48ff24f79f900aa59ae39364
}
public boolean shulkerRidable = false;
-@@ -931,9 +965,11 @@ public class PurpurWorldConfig {
+@@ -933,9 +967,11 @@ public class PurpurWorldConfig {
public boolean striderRidable = false;
public boolean striderRidableInWater = false;
@@ -613,7 +613,7 @@ index a70bd4fdb0634110bc2b68780c28d4a2b788e1e6..9947b5ad48ff24f79f900aa59ae39364
}
public boolean tropicalFishRidable = false;
-@@ -943,9 +979,11 @@ public class PurpurWorldConfig {
+@@ -945,9 +981,11 @@ public class PurpurWorldConfig {
public boolean turtleRidable = false;
public boolean turtleRidableInWater = false;
@@ -625,7 +625,7 @@ index a70bd4fdb0634110bc2b68780c28d4a2b788e1e6..9947b5ad48ff24f79f900aa59ae39364
}
public boolean vexRidable = false;
-@@ -1038,9 +1076,11 @@ public class PurpurWorldConfig {
+@@ -1040,9 +1078,11 @@ public class PurpurWorldConfig {
public boolean wolfRidable = false;
public boolean wolfRidableInWater = false;
diff --git a/patches/Purpur/patches/server/0128-Apply-display-names-from-item-forms-of-entities-to-e.patch b/patches/Purpur/patches/server/0128-Apply-display-names-from-item-forms-of-entities-to-e.patch
index 495092aec..f2c3325e5 100644
--- a/patches/Purpur/patches/server/0128-Apply-display-names-from-item-forms-of-entities-to-e.patch
+++ b/patches/Purpur/patches/server/0128-Apply-display-names-from-item-forms-of-entities-to-e.patch
@@ -43,40 +43,6 @@ index 603910a6f9ecc34be9eb2d4fb28e5c2e20aca90a..72d2eea40c37b5fa627c8deeda180273
}
this.die();
-diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java
-index d9b00a24b378b74e126518da9142249d2ad62c55..91e5741876e97e85a93d9ffe62164176f99f6808 100644
---- a/src/main/java/net/minecraft/server/EntityInsentient.java
-+++ b/src/main/java/net/minecraft/server/EntityInsentient.java
-@@ -1374,7 +1374,13 @@ public abstract class EntityInsentient extends EntityLiving {
- this.by = null;
- if (!this.world.isClientSide && flag1) {
- this.forceDrops = true; // CraftBukkit
-- this.a((IMaterial) Items.LEAD);
-+ // Purpur start
-+ final ItemStack lead = new ItemStack(Items.LEAD);
-+ if (this.world.purpurConfig.persistentDroppableEntityDisplayNames && this.hasCustomName()) {
-+ lead.setName(this.getCustomName());
-+ }
-+ this.dropItem(lead);
-+ // Purpur end
- this.forceDrops = false; // CraftBukkit
- }
-
-@@ -1453,7 +1459,13 @@ public abstract class EntityInsentient extends EntityLiving {
- }
-
- if (this.ticksLived > 100) {
-- this.a((IMaterial) Items.LEAD);
-+ // Purpur start
-+ final ItemStack lead = new ItemStack(Items.LEAD);
-+ if (this.world.purpurConfig.persistentDroppableEntityDisplayNames && this.hasCustomName()) {
-+ lead.setName(this.getCustomName());
-+ }
-+ this.dropItem(lead);
-+ // Purpur end
- this.by = null;
- }
- }
diff --git a/src/main/java/net/minecraft/server/EntityItemFrame.java b/src/main/java/net/minecraft/server/EntityItemFrame.java
index 8a95e698d5caa3730954ce1135b0ec37a389dd70..372be937f1cf95775e37931f326f6a77836968f3 100644
--- a/src/main/java/net/minecraft/server/EntityItemFrame.java
@@ -188,7 +154,7 @@ index a4edfb02fd350433020b0f3699726b6127ab9933..3f9062d8eca3ce53c0fb9e9e40330aa4
NBTTagCompound nbttagcompound = this.a("display");
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 9947b5ad48ff24f79f900aa59ae39364db44576b..e7817f9dfdf809a5d6d15cf28aedcc9ed1c7ca72 100644
+index 2b68f25b6a589de13c534e10f9f24a45f7274963..a3f4e6ccf8d8099ddde37ca774ca14e270005c51 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -83,8 +83,10 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0129-Set-name-visible-when-using-a-Name-Tag-on-an-Armor-S.patch b/patches/Purpur/patches/server/0129-Set-name-visible-when-using-a-Name-Tag-on-an-Armor-S.patch
index 1a5056007..3dceabb3d 100644
--- a/patches/Purpur/patches/server/0129-Set-name-visible-when-using-a-Name-Tag-on-an-Armor-S.patch
+++ b/patches/Purpur/patches/server/0129-Set-name-visible-when-using-a-Name-Tag-on-an-Armor-S.patch
@@ -21,7 +21,7 @@ index 01163ce38602f9345f00ee0535b4e73be7c6d735..a7efce97318fcf95d98f33ad4ac2da69
((EntityInsentient) entityliving).setPersistent();
}
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index e7817f9dfdf809a5d6d15cf28aedcc9ed1c7ca72..d9f385d97887110558747ef16a13e42a0115e5bd 100644
+index a3f4e6ccf8d8099ddde37ca774ca14e270005c51..bb39abc44c7151a57b9af66cb77f2ed8e043a4f0 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -84,9 +84,11 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0130-Add-twisting-and-weeping-vines-growth-rates.patch b/patches/Purpur/patches/server/0130-Add-twisting-and-weeping-vines-growth-rates.patch
index 2654f08e7..0481d42f5 100644
--- a/patches/Purpur/patches/server/0130-Add-twisting-and-weeping-vines-growth-rates.patch
+++ b/patches/Purpur/patches/server/0130-Add-twisting-and-weeping-vines-growth-rates.patch
@@ -67,7 +67,7 @@ index 23dca1940375d243531fc4a891f04e937ae2f48f..94ffadb91fec65a721cf0c8fa98bad70
+ // Purpur end
}
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index d9f385d97887110558747ef16a13e42a0115e5bd..eb04a84ecd69c8c64857d509c4629f599055c6e6 100644
+index bb39abc44c7151a57b9af66cb77f2ed8e043a4f0..ceaf3e4716262eaa3b29c63ca041bafa8b30efbc 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -419,6 +419,16 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0131-Kelp-weeping-and-twisting-vines-configurable-max-gro.patch b/patches/Purpur/patches/server/0131-Kelp-weeping-and-twisting-vines-configurable-max-gro.patch
index c9548cef4..eeb2c63b1 100644
--- a/patches/Purpur/patches/server/0131-Kelp-weeping-and-twisting-vines-configurable-max-gro.patch
+++ b/patches/Purpur/patches/server/0131-Kelp-weeping-and-twisting-vines-configurable-max-gro.patch
@@ -89,7 +89,7 @@ index 94ffadb91fec65a721cf0c8fa98bad708a2ca269..067df63ab27ecb9fe0a0d012b16efbd5
// Purpur end
}
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index eb04a84ecd69c8c64857d509c4629f599055c6e6..95fd7fddba102965b1948214c9ceeee3e9ba41f8 100644
+index ceaf3e4716262eaa3b29c63ca041bafa8b30efbc..732773250e70cfcb7fda55758d73305e2b97cd97 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -366,6 +366,11 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0132-Add-config-for-allowing-Endermen-to-despawn-even-whi.patch b/patches/Purpur/patches/server/0132-Add-config-for-allowing-Endermen-to-despawn-even-whi.patch
index 0781971b2..bb011122b 100644
--- a/patches/Purpur/patches/server/0132-Add-config-for-allowing-Endermen-to-despawn-even-whi.patch
+++ b/patches/Purpur/patches/server/0132-Add-config-for-allowing-Endermen-to-despawn-even-whi.patch
@@ -21,7 +21,7 @@ index 995849212c25568d3aa28ada78babf8b8e669960..acb2b3ed04ea0bf19335415310ce22cd
static class PathfinderGoalEndermanPickupBlock extends PathfinderGoal {
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 95fd7fddba102965b1948214c9ceeee3e9ba41f8..95202b48e08971bb096f01899a8a250e794777fe 100644
+index 732773250e70cfcb7fda55758d73305e2b97cd97..89bea8f3889d2d2f1469ad1dc5af5cda70153a17 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -588,10 +588,12 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0134-Add-configurable-snowball-damage.patch b/patches/Purpur/patches/server/0134-Add-configurable-snowball-damage.patch
index 745521c4c..7b4a4cc72 100644
--- a/patches/Purpur/patches/server/0134-Add-configurable-snowball-damage.patch
+++ b/patches/Purpur/patches/server/0134-Add-configurable-snowball-damage.patch
@@ -18,7 +18,7 @@ index 34a5f481e6ed1357861dca15fb4013ec8484a292..d7bab4446a5a8eef98c10b1f6eb89de9
entity.damageEntity(DamageSource.projectile(this, this.getShooter()), (float) i);
}
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 95202b48e08971bb096f01899a8a250e794777fe..ad799b1abc425b78ae2435001ec591660b3965b2 100644
+index 89bea8f3889d2d2f1469ad1dc5af5cda70153a17..5290b84281d68ac6fb15c997983507aee85e58f7 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -214,6 +214,11 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0135-Zombie-break-door-minimum-difficulty-option.patch b/patches/Purpur/patches/server/0135-Zombie-break-door-minimum-difficulty-option.patch
index c7ed0485a..8f13d01f0 100644
--- a/patches/Purpur/patches/server/0135-Zombie-break-door-minimum-difficulty-option.patch
+++ b/patches/Purpur/patches/server/0135-Zombie-break-door-minimum-difficulty-option.patch
@@ -40,7 +40,7 @@ index 7488a12926c5ee4adc3bc1fa3973988350381544..23870a271b759a953a095df835e08ea2
+ // Purpur end
}
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index ad799b1abc425b78ae2435001ec591660b3965b2..53f0fbb036d45749190d078282d0e92e87b83269 100644
+index 5290b84281d68ac6fb15c997983507aee85e58f7..4e80fab96f7c9f0192bcda91acf761750cf8621c 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -2,6 +2,7 @@ package net.pl3x.purpur;
@@ -51,7 +51,7 @@ index ad799b1abc425b78ae2435001ec591660b3965b2..53f0fbb036d45749190d078282d0e92e
import net.minecraft.server.Explosion;
import net.minecraft.server.IRegistry;
import net.minecraft.server.Item;
-@@ -1128,6 +1129,7 @@ public class PurpurWorldConfig {
+@@ -1130,6 +1131,7 @@ public class PurpurWorldConfig {
public double zombieJockeyChance = 0.05D;
public boolean zombieJockeyTryExistingChickens = true;
public boolean zombieAggressiveTowardsVillagerWhenLagging = true;
@@ -59,7 +59,7 @@ index ad799b1abc425b78ae2435001ec591660b3965b2..53f0fbb036d45749190d078282d0e92e
private void zombieSettings() {
zombieRidable = getBoolean("mobs.zombie.ridable", zombieRidable);
zombieRidableInWater = getBoolean("mobs.zombie.ridable-in-water", zombieRidableInWater);
-@@ -1135,6 +1137,11 @@ public class PurpurWorldConfig {
+@@ -1137,6 +1139,11 @@ public class PurpurWorldConfig {
zombieJockeyChance = getDouble("mobs.zombie.jockey.chance", zombieJockeyChance);
zombieJockeyTryExistingChickens = getBoolean("mobs.zombie.jockey.try-existing-chickens", zombieJockeyTryExistingChickens);
zombieAggressiveTowardsVillagerWhenLagging = getBoolean("mobs.zombie.aggressive-towards-villager-when-lagging", zombieAggressiveTowardsVillagerWhenLagging);
diff --git a/patches/Purpur/patches/server/0139-Changeable-Mob-Left-Handed-Chance.patch b/patches/Purpur/patches/server/0139-Changeable-Mob-Left-Handed-Chance.patch
index a0e881502..fbcf338db 100644
--- a/patches/Purpur/patches/server/0139-Changeable-Mob-Left-Handed-Chance.patch
+++ b/patches/Purpur/patches/server/0139-Changeable-Mob-Left-Handed-Chance.patch
@@ -5,7 +5,7 @@ Subject: [PATCH] Changeable Mob Left Handed Chance
diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java
-index 91e5741876e97e85a93d9ffe62164176f99f6808..03f480e29b92e278e1d4901ee4388f02ef6e3a82 100644
+index d9b00a24b378b74e126518da9142249d2ad62c55..de977e80eb6cad74cbea3a00702ef804693374f0 100644
--- a/src/main/java/net/minecraft/server/EntityInsentient.java
+++ b/src/main/java/net/minecraft/server/EntityInsentient.java
@@ -1137,7 +1137,7 @@ public abstract class EntityInsentient extends EntityLiving {
@@ -18,7 +18,7 @@ index 91e5741876e97e85a93d9ffe62164176f99f6808..03f480e29b92e278e1d4901ee4388f02
} else {
this.setLeftHanded(false);
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 53f0fbb036d45749190d078282d0e92e87b83269..d58cba46018b4ce96eb3d88450eed098825c03b1 100644
+index 4e80fab96f7c9f0192bcda91acf761750cf8621c..da99f39a17513be21222c7c1289f638b36b1ca58 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -129,8 +129,10 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0140-Add-boat-fall-damage-config.patch b/patches/Purpur/patches/server/0140-Add-boat-fall-damage-config.patch
index 7cf863a11..12001e412 100644
--- a/patches/Purpur/patches/server/0140-Add-boat-fall-damage-config.patch
+++ b/patches/Purpur/patches/server/0140-Add-boat-fall-damage-config.patch
@@ -27,7 +27,7 @@ index 871119dc506ff3bcd96f57fb5f5923227e0c7f1f..63b919bef1a4420e02b4822097cadc1a
if (!flag && isSpawnInvulnerable() && damagesource != DamageSource.OUT_OF_WORLD) { // Purpur
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index d58cba46018b4ce96eb3d88450eed098825c03b1..e6dc9c07ecf26c68510ed1aed7888d2192e6d54b 100644
+index da99f39a17513be21222c7c1289f638b36b1ca58..e6e31aa9cc9df9e4810f5bed22500e6590cffb6c 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -224,6 +224,7 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0141-Config-migration-disable-saving-projectiles-to-disk-.patch b/patches/Purpur/patches/server/0141-Config-migration-disable-saving-projectiles-to-disk-.patch
index 7e03629d3..01814cd5f 100644
--- a/patches/Purpur/patches/server/0141-Config-migration-disable-saving-projectiles-to-disk-.patch
+++ b/patches/Purpur/patches/server/0141-Config-migration-disable-saving-projectiles-to-disk-.patch
@@ -36,7 +36,7 @@ index 9294bfab12ef88690e359ff90551c5c615cdd3dd..e928716d7a2dcb390507b746763e6f7e
public static String afkBroadcastBack = "§e§o%s is no longer AFK";
public static String afkTabListPrefix = "[AFK] ";
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index e6dc9c07ecf26c68510ed1aed7888d2192e6d54b..2b406c22f7d481fb9e62f8b1b7e317edf7543a84 100644
+index e6e31aa9cc9df9e4810f5bed22500e6590cffb6c..d4f90fc2f48df7d7be38086285754e8be9e006f5 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -1,5 +1,6 @@
diff --git a/patches/Purpur/patches/server/0142-Snow-Golem-rate-of-fire-config.patch b/patches/Purpur/patches/server/0142-Snow-Golem-rate-of-fire-config.patch
index adcc0609e..b744d7009 100644
--- a/patches/Purpur/patches/server/0142-Snow-Golem-rate-of-fire-config.patch
+++ b/patches/Purpur/patches/server/0142-Snow-Golem-rate-of-fire-config.patch
@@ -23,10 +23,10 @@ index 66a90507aaf16bb8512a77f3c9aa501697e49862..4c083bcfe7d083713b418486f0918f39
this.goalSelector.a(3, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F));
this.goalSelector.a(4, new PathfinderGoalRandomLookaround(this));
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 2b406c22f7d481fb9e62f8b1b7e317edf7543a84..9922410c8d11acca6ba774bca40804091b95d12e 100644
+index d4f90fc2f48df7d7be38086285754e8be9e006f5..cb8646621dcbf6683b5bc980c1c46f1ad629de05 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-@@ -979,12 +979,20 @@ public class PurpurWorldConfig {
+@@ -981,12 +981,20 @@ public class PurpurWorldConfig {
public boolean snowGolemLeaveTrailWhenRidden = false;
public boolean snowGolemDropsPumpkin = true;
public boolean snowGolemPutPumpkinBack = false;
diff --git a/patches/Purpur/patches/server/0145-Config-migration-climbing-should-not-bypass-cramming.patch b/patches/Purpur/patches/server/0145-Config-migration-climbing-should-not-bypass-cramming.patch
index 6c085790b..1467d6745 100644
--- a/patches/Purpur/patches/server/0145-Config-migration-climbing-should-not-bypass-cramming.patch
+++ b/patches/Purpur/patches/server/0145-Config-migration-climbing-should-not-bypass-cramming.patch
@@ -28,7 +28,7 @@ index bce8781a2a1d856429d00b8cd9c9ac03425e1bbb..83c1176888ead8fe045f1e1dfc78115a
public static String afkBroadcastBack = "§e§o%s is no longer AFK";
public static String afkTabListPrefix = "[AFK] ";
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 9922410c8d11acca6ba774bca40804091b95d12e..4b5c42d78f8e62fd2260778b3170d3eb2ebaea83 100644
+index cb8646621dcbf6683b5bc980c1c46f1ad629de05..7f51df85a93765bb2e6130b96c832fdecc0c3915 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -96,6 +96,17 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0146-Lobotomize-stuck-villagers.patch b/patches/Purpur/patches/server/0146-Lobotomize-stuck-villagers.patch
index f3598b4df..0d795f1fb 100644
--- a/patches/Purpur/patches/server/0146-Lobotomize-stuck-villagers.patch
+++ b/patches/Purpur/patches/server/0146-Lobotomize-stuck-villagers.patch
@@ -5,7 +5,7 @@ Subject: [PATCH] Lobotomize stuck villagers
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
-index e4f2e51b6306fcaf161b7dfb734d9d28947e964b..cb4856e3bbb25e1077f5b4832f359549d57acd7e 100644
+index 444305d11eb1652b8618b5e2a41992974622e1a0..b861922586dc08a660050e9f2f94433b54c16def 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -114,7 +114,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
@@ -88,10 +88,10 @@ index b92ca4a6de01f3f86367fb8dfe3591b08a3e9218..1208464fba96daf276c9cc0c1c9b18db
// Paper start - add target parameter
return this.a(blockposition, null, i);
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 4b5c42d78f8e62fd2260778b3170d3eb2ebaea83..46859afbf3c2cbc5718e240f7965288549e915a9 100644
+index 7f51df85a93765bb2e6130b96c832fdecc0c3915..c42b76c449c55ece8ca08e596253e20aab3ecb09 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-@@ -1073,6 +1073,8 @@ public class PurpurWorldConfig {
+@@ -1075,6 +1075,8 @@ public class PurpurWorldConfig {
public int villagerSpawnIronGolemRadius = 0;
public int villagerSpawnIronGolemLimit = 0;
public boolean villagerCanBreed = true;
@@ -100,7 +100,7 @@ index 4b5c42d78f8e62fd2260778b3170d3eb2ebaea83..46859afbf3c2cbc5718e240f79652885
private void villagerSettings() {
villagerRidable = getBoolean("mobs.villager.ridable", villagerRidable);
villagerRidableInWater = getBoolean("mobs.villager.ridable-in-water", villagerRidableInWater);
-@@ -1084,6 +1086,13 @@ public class PurpurWorldConfig {
+@@ -1086,6 +1088,13 @@ public class PurpurWorldConfig {
villagerSpawnIronGolemRadius = getInt("mobs.villager.spawn-iron-golem.radius", villagerSpawnIronGolemRadius);
villagerSpawnIronGolemLimit = getInt("mobs.villager.spawn-iron-golem.limit", villagerSpawnIronGolemLimit);
villagerCanBreed = getBoolean("mobs.villager.can-breed", villagerCanBreed);
diff --git a/patches/Purpur/patches/server/0147-Option-for-Villager-Clerics-to-farm-Nether-Wart.patch b/patches/Purpur/patches/server/0147-Option-for-Villager-Clerics-to-farm-Nether-Wart.patch
index 2d3fbffc5..ab87ff1b8 100644
--- a/patches/Purpur/patches/server/0147-Option-for-Villager-Clerics-to-farm-Nether-Wart.patch
+++ b/patches/Purpur/patches/server/0147-Option-for-Villager-Clerics-to-farm-Nether-Wart.patch
@@ -234,10 +234,10 @@ index 3c60da7ac6faebe9d964e893974e42613c59b4c1..6493f220a0cf627e82e5f3f3c85e9934
public static final VillagerProfession FISHERMAN = a("fisherman", VillagePlaceType.i, SoundEffects.ENTITY_VILLAGER_WORK_FISHERMAN);
public static final VillagerProfession FLETCHER = a("fletcher", VillagePlaceType.j, SoundEffects.ENTITY_VILLAGER_WORK_FLETCHER);
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 46859afbf3c2cbc5718e240f7965288549e915a9..b8dcb9c48ed8cac881b4bb1b4d995966d15f44eb 100644
+index c42b76c449c55ece8ca08e596253e20aab3ecb09..c690238bb16d7172ba53321f9512a7bb9c5683fd 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-@@ -1075,6 +1075,8 @@ public class PurpurWorldConfig {
+@@ -1077,6 +1077,8 @@ public class PurpurWorldConfig {
public boolean villagerCanBreed = true;
public boolean villagerLobotomizeEnabled = false;
public int villagerLobotomizeCheck = 60;
@@ -246,7 +246,7 @@ index 46859afbf3c2cbc5718e240f7965288549e915a9..b8dcb9c48ed8cac881b4bb1b4d995966
private void villagerSettings() {
villagerRidable = getBoolean("mobs.villager.ridable", villagerRidable);
villagerRidableInWater = getBoolean("mobs.villager.ridable-in-water", villagerRidableInWater);
-@@ -1093,6 +1095,8 @@ public class PurpurWorldConfig {
+@@ -1095,6 +1097,8 @@ public class PurpurWorldConfig {
}
villagerLobotomizeEnabled = getBoolean("mobs.villager.lobotomize.enabled", villagerLobotomizeEnabled);
villagerLobotomizeCheck = getInt("mobs.villager.lobotomize.check-interval", villagerLobotomizeCheck);
diff --git a/patches/Purpur/patches/server/0148-Toggle-for-Zombified-Piglin-death-always-counting-as.patch b/patches/Purpur/patches/server/0148-Toggle-for-Zombified-Piglin-death-always-counting-as.patch
index 6c94b686f..e80bb2ece 100644
--- a/patches/Purpur/patches/server/0148-Toggle-for-Zombified-Piglin-death-always-counting-as.patch
+++ b/patches/Purpur/patches/server/0148-Toggle-for-Zombified-Piglin-death-always-counting-as.patch
@@ -35,10 +35,10 @@ index 3327dbbf87d8f43cbc7cd728df2f4c6a33dae40d..57f3358b8dfd53f5b1d2e976d64b809f
}
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index b8dcb9c48ed8cac881b4bb1b4d995966d15f44eb..7ec9a135778c685344d22ddba02c0858872c50fa 100644
+index c690238bb16d7172ba53321f9512a7bb9c5683fd..27f053eb3929de9baa2f20c95fff3e6413ddc4ee 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-@@ -1206,12 +1206,14 @@ public class PurpurWorldConfig {
+@@ -1208,12 +1208,14 @@ public class PurpurWorldConfig {
public boolean zombifiedPiglinJockeyOnlyBaby = true;
public double zombifiedPiglinJockeyChance = 0.05D;
public boolean zombifiedPiglinJockeyTryExistingChickens = true;
diff --git a/patches/Purpur/patches/server/0150-Configurable-chance-for-wolves-to-spawn-rabid.patch b/patches/Purpur/patches/server/0150-Configurable-chance-for-wolves-to-spawn-rabid.patch
index 357402515..c7f3acee2 100644
--- a/patches/Purpur/patches/server/0150-Configurable-chance-for-wolves-to-spawn-rabid.patch
+++ b/patches/Purpur/patches/server/0150-Configurable-chance-for-wolves-to-spawn-rabid.patch
@@ -201,10 +201,10 @@ index 9a4819815c7a4bf2fd4a92c4169ace35f2261704..da29898574d30d5fecc5a44ad7b36556
public PathfinderGoalAvoidTarget(EntityCreature entitycreature, Class oclass, Predicate predicate, float f, double d0, double d1, Predicate predicate1) {
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 7ec9a135778c685344d22ddba02c0858872c50fa..7fb9ceba6cb35fb0a2ae782abc1ebc1f56c0d55a 100644
+index 27f053eb3929de9baa2f20c95fff3e6413ddc4ee..56e1af807e3f2763c0878c5003bc062bdf50355e 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-@@ -1157,10 +1157,14 @@ public class PurpurWorldConfig {
+@@ -1159,10 +1159,14 @@ public class PurpurWorldConfig {
public boolean wolfRidable = false;
public boolean wolfRidableInWater = false;
diff --git a/patches/Purpur/patches/server/0151-Configurable-default-wolf-collar-color.patch b/patches/Purpur/patches/server/0151-Configurable-default-wolf-collar-color.patch
index 54704114c..4d1a50bf4 100644
--- a/patches/Purpur/patches/server/0151-Configurable-default-wolf-collar-color.patch
+++ b/patches/Purpur/patches/server/0151-Configurable-default-wolf-collar-color.patch
@@ -24,7 +24,7 @@ index 5fe2e9f4bfbdc08690eacd6196e59529dc7953e8..fd62dc51258876275adbe02f750fd881
@Override
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 7fb9ceba6cb35fb0a2ae782abc1ebc1f56c0d55a..878c5f324484bbd401ea177fda6b1b5e53aaf778 100644
+index 56e1af807e3f2763c0878c5003bc062bdf50355e..f025bc73be48716310f1716d2cabbd5af5c39727 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -3,6 +3,7 @@ package net.pl3x.purpur;
@@ -35,7 +35,7 @@ index 7fb9ceba6cb35fb0a2ae782abc1ebc1f56c0d55a..878c5f324484bbd401ea177fda6b1b5e
import net.minecraft.server.EnumDifficulty;
import net.minecraft.server.Explosion;
import net.minecraft.server.IRegistry;
-@@ -1157,12 +1158,18 @@ public class PurpurWorldConfig {
+@@ -1159,12 +1160,18 @@ public class PurpurWorldConfig {
public boolean wolfRidable = false;
public boolean wolfRidableInWater = false;
diff --git a/patches/Purpur/patches/server/0152-Configurable-entity-base-attributes.patch b/patches/Purpur/patches/server/0152-Configurable-entity-base-attributes.patch
index 310cafaff..ecfa014c3 100644
--- a/patches/Purpur/patches/server/0152-Configurable-entity-base-attributes.patch
+++ b/patches/Purpur/patches/server/0152-Configurable-entity-base-attributes.patch
@@ -697,10 +697,10 @@ index 398e92bf7053c411bd98626efe4261e15256d3ee..d19f8dda87c97de594ad051a6791d99e
@Nullable
diff --git a/src/main/java/net/minecraft/server/EntityPhantom.java b/src/main/java/net/minecraft/server/EntityPhantom.java
-index f8c3480045e86a18501db223c1b2254cf3298a42..25345d8d585735af407787f2c26fe92674721239 100644
+index c70281fddcbe5a97a1eb176def99cdf31de37579..80cc4467d601b653583e387eb4be6f3b739058e6 100644
--- a/src/main/java/net/minecraft/server/EntityPhantom.java
+++ b/src/main/java/net/minecraft/server/EntityPhantom.java
-@@ -75,6 +75,11 @@ public class EntityPhantom extends EntityFlying implements IMonster {
+@@ -76,6 +76,11 @@ public class EntityPhantom extends EntityFlying implements IMonster {
world.addEntity(flames);
return true;
}
@@ -1314,7 +1314,7 @@ index 0c47477b416980d2e932321730525bf5a8feda4f..dc850677c29c16805f28af00b2a63363
@Override
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 878c5f324484bbd401ea177fda6b1b5e53aaf778..a9953a72055d23354b72f9800625a745c7d4eada 100644
+index f025bc73be48716310f1716d2cabbd5af5c39727..72d1ccb375496ffaa3d02d7c65f3cfb7ddb84db4 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -484,30 +484,58 @@ public class PurpurWorldConfig {
@@ -1943,18 +1943,18 @@ index 878c5f324484bbd401ea177fda6b1b5e53aaf778..a9953a72055d23354b72f9800625a745
}
public boolean phantomRidable = false;
-@@ -840,6 +1147,7 @@ public class PurpurWorldConfig {
- public int phantomBurnInLight = 0;
+@@ -841,6 +1148,7 @@ public class PurpurWorldConfig {
public boolean phantomIgnorePlayersWithTorch = false;
public boolean phantomBurnInDaylight = true;
+ public boolean phantomAllowGriefing = false;
+ public double phantomMaxHealth = 20.0D;
private void phantomSettings() {
phantomRidable = getBoolean("mobs.phantom.ridable", phantomRidable);
phantomRidableInWater = getBoolean("mobs.phantom.ridable-in-water", phantomRidableInWater);
-@@ -864,38 +1172,72 @@ public class PurpurWorldConfig {
- phantomBurnInLight = getInt("mobs.phantom.burn-in-light", phantomBurnInLight);
+@@ -866,38 +1174,72 @@ public class PurpurWorldConfig {
phantomBurnInDaylight = getBoolean("mobs.phantom.burn-in-daylight", phantomBurnInDaylight);
phantomIgnorePlayersWithTorch = getBoolean("mobs.phantom.ignore-players-with-torch", phantomIgnorePlayersWithTorch);
+ phantomAllowGriefing = getBoolean("mobs.phantom.allow-griefing", phantomAllowGriefing);
+ if (PurpurConfig.version < 10) {
+ double oldValue = getDouble("mobs.phantom.attributes.max-health", phantomMaxHealth);
+ set("mobs.phantom.attributes.max-health", null);
@@ -2024,7 +2024,7 @@ index 878c5f324484bbd401ea177fda6b1b5e53aaf778..a9953a72055d23354b72f9800625a745
}
public boolean polarBearRidable = false;
-@@ -903,6 +1245,7 @@ public class PurpurWorldConfig {
+@@ -905,6 +1247,7 @@ public class PurpurWorldConfig {
public String polarBearBreedableItemString = "";
public Item polarBearBreedableItem = null;
public int polarBearBreedingTicks = 6000;
@@ -2032,7 +2032,7 @@ index 878c5f324484bbd401ea177fda6b1b5e53aaf778..a9953a72055d23354b72f9800625a745
private void polarBearSettings() {
polarBearRidable = getBoolean("mobs.polar_bear.ridable", polarBearRidable);
polarBearRidableInWater = getBoolean("mobs.polar_bear.ridable-in-water", polarBearRidableInWater);
-@@ -910,11 +1253,24 @@ public class PurpurWorldConfig {
+@@ -912,11 +1255,24 @@ public class PurpurWorldConfig {
Item item = IRegistry.ITEM.get(new MinecraftKey(polarBearBreedableItemString));
if (item != Items.AIR) polarBearBreedableItem = item;
polarBearBreedingTicks = getInt("mobs.polar_bear.breeding-delay-ticks", polarBearBreedingTicks);
@@ -2057,7 +2057,7 @@ index 878c5f324484bbd401ea177fda6b1b5e53aaf778..a9953a72055d23354b72f9800625a745
}
public boolean rabbitRidable = false;
-@@ -922,68 +1278,142 @@ public class PurpurWorldConfig {
+@@ -924,68 +1280,142 @@ public class PurpurWorldConfig {
public double rabbitNaturalToast = 0.0D;
public double rabbitNaturalKiller = 0.0D;
public int rabbitBreedingTicks = 6000;
@@ -2200,7 +2200,7 @@ index 878c5f324484bbd401ea177fda6b1b5e53aaf778..a9953a72055d23354b72f9800625a745
}
public boolean snowGolemRidable = false;
-@@ -995,6 +1425,7 @@ public class PurpurWorldConfig {
+@@ -997,6 +1427,7 @@ public class PurpurWorldConfig {
public int snowGolemSnowBallMax = 20;
public float snowGolemSnowBallModifier = 10.0F;
public double snowGolemAttackDistance = 1.25D;
@@ -2208,7 +2208,7 @@ index 878c5f324484bbd401ea177fda6b1b5e53aaf778..a9953a72055d23354b72f9800625a745
private void snowGolemSettings() {
snowGolemRidable = getBoolean("mobs.snow_golem.ridable", snowGolemRidable);
snowGolemRidableInWater = getBoolean("mobs.snow_golem.ridable-in-water", snowGolemRidableInWater);
-@@ -1005,63 +1436,118 @@ public class PurpurWorldConfig {
+@@ -1007,63 +1438,118 @@ public class PurpurWorldConfig {
snowGolemSnowBallMax = getInt("mobs.snow_golem.max-shoot-interval-ticks", snowGolemSnowBallMax);
snowGolemSnowBallModifier = (float) getDouble("mobs.snow_golem.snow-ball-modifier", snowGolemSnowBallModifier);
snowGolemAttackDistance = getDouble("mobs.snow_golem.attack-distance", snowGolemAttackDistance);
@@ -2327,7 +2327,7 @@ index 878c5f324484bbd401ea177fda6b1b5e53aaf778..a9953a72055d23354b72f9800625a745
}
public boolean villagerRidable = false;
-@@ -1078,6 +1564,7 @@ public class PurpurWorldConfig {
+@@ -1080,6 +1566,7 @@ public class PurpurWorldConfig {
public int villagerLobotomizeCheck = 60;
public boolean villagerClericsFarmWarts = false;
public boolean villagerClericFarmersThrowWarts = true;
@@ -2335,7 +2335,7 @@ index 878c5f324484bbd401ea177fda6b1b5e53aaf778..a9953a72055d23354b72f9800625a745
private void villagerSettings() {
villagerRidable = getBoolean("mobs.villager.ridable", villagerRidable);
villagerRidableInWater = getBoolean("mobs.villager.ridable-in-water", villagerRidableInWater);
-@@ -1098,33 +1585,60 @@ public class PurpurWorldConfig {
+@@ -1100,33 +1587,60 @@ public class PurpurWorldConfig {
villagerLobotomizeCheck = getInt("mobs.villager.lobotomize.check-interval", villagerLobotomizeCheck);
villagerClericsFarmWarts = getBoolean("mobs.villager.clerics-farm-warts", villagerClericsFarmWarts);
villagerClericFarmersThrowWarts = getBoolean("mobs.villager.cleric-wart-farmers-throw-warts-at-villagers", villagerClericFarmersThrowWarts);
@@ -2396,7 +2396,7 @@ index 878c5f324484bbd401ea177fda6b1b5e53aaf778..a9953a72055d23354b72f9800625a745
}
public boolean witherRidable = false;
-@@ -1141,19 +1655,30 @@ public class PurpurWorldConfig {
+@@ -1143,19 +1657,30 @@ public class PurpurWorldConfig {
witherHealthRegenDelay = getInt("mobs.wither.health-regen-delay", witherHealthRegenDelay);
if (PurpurConfig.version < 8) {
double oldValue = getDouble("mobs.wither.max-health", witherMaxHealth);
@@ -2429,7 +2429,7 @@ index 878c5f324484bbd401ea177fda6b1b5e53aaf778..a9953a72055d23354b72f9800625a745
}
public boolean wolfRidable = false;
-@@ -1162,6 +1687,7 @@ public class PurpurWorldConfig {
+@@ -1164,6 +1689,7 @@ public class PurpurWorldConfig {
public boolean wolfMilkCuresRabies = true;
public double wolfNaturalRabid = 0.0D;
public int wolfBreedingTicks = 6000;
@@ -2437,7 +2437,7 @@ index 878c5f324484bbd401ea177fda6b1b5e53aaf778..a9953a72055d23354b72f9800625a745
private void wolfSettings() {
wolfRidable = getBoolean("mobs.wolf.ridable", wolfRidable);
wolfRidableInWater = getBoolean("mobs.wolf.ridable-in-water", wolfRidableInWater);
-@@ -1173,13 +1699,26 @@ public class PurpurWorldConfig {
+@@ -1175,13 +1701,26 @@ public class PurpurWorldConfig {
wolfMilkCuresRabies = getBoolean("mobs.wolf.milk-cures-rabid-wolves", wolfMilkCuresRabies);
wolfNaturalRabid = getDouble("mobs.wolf.spawn-rabid-chance", wolfNaturalRabid);
wolfBreedingTicks = getInt("mobs.wolf.breeding-delay-ticks", wolfBreedingTicks);
@@ -2464,7 +2464,7 @@ index 878c5f324484bbd401ea177fda6b1b5e53aaf778..a9953a72055d23354b72f9800625a745
}
public boolean zombieRidable = false;
-@@ -1189,6 +1728,8 @@ public class PurpurWorldConfig {
+@@ -1191,6 +1730,8 @@ public class PurpurWorldConfig {
public boolean zombieJockeyTryExistingChickens = true;
public boolean zombieAggressiveTowardsVillagerWhenLagging = true;
public EnumDifficulty zombieBreakDoorMinDifficulty = EnumDifficulty.HARD;
@@ -2473,7 +2473,7 @@ index 878c5f324484bbd401ea177fda6b1b5e53aaf778..a9953a72055d23354b72f9800625a745
private void zombieSettings() {
zombieRidable = getBoolean("mobs.zombie.ridable", zombieRidable);
zombieRidableInWater = getBoolean("mobs.zombie.ridable-in-water", zombieRidableInWater);
-@@ -1201,15 +1742,40 @@ public class PurpurWorldConfig {
+@@ -1203,15 +1744,40 @@ public class PurpurWorldConfig {
} catch (IllegalArgumentException ignore) {
zombieBreakDoorMinDifficulty = EnumDifficulty.HARD;
}
@@ -2514,7 +2514,7 @@ index 878c5f324484bbd401ea177fda6b1b5e53aaf778..a9953a72055d23354b72f9800625a745
}
public boolean zombifiedPiglinRidable = false;
-@@ -1218,6 +1784,8 @@ public class PurpurWorldConfig {
+@@ -1220,6 +1786,8 @@ public class PurpurWorldConfig {
public double zombifiedPiglinJockeyChance = 0.05D;
public boolean zombifiedPiglinJockeyTryExistingChickens = true;
public boolean zombifiedPiglinCountAsPlayerKillWhenAngry = true;
@@ -2523,7 +2523,7 @@ index 878c5f324484bbd401ea177fda6b1b5e53aaf778..a9953a72055d23354b72f9800625a745
private void zombifiedPiglinSettings() {
zombifiedPiglinRidable = getBoolean("mobs.zombified_piglin.ridable", zombifiedPiglinRidable);
zombifiedPiglinRidableInWater = getBoolean("mobs.zombified_piglin.ridable-in-water", zombifiedPiglinRidableInWater);
-@@ -1225,6 +1793,13 @@ public class PurpurWorldConfig {
+@@ -1227,6 +1795,13 @@ public class PurpurWorldConfig {
zombifiedPiglinJockeyChance = getDouble("mobs.zombified_piglin.jockey.chance", zombifiedPiglinJockeyChance);
zombifiedPiglinJockeyTryExistingChickens = getBoolean("mobs.zombified_piglin.jockey.try-existing-chickens", zombifiedPiglinJockeyTryExistingChickens);
zombifiedPiglinCountAsPlayerKillWhenAngry = getBoolean("mobs.zombified_piglin.count-as-player-kill-when-angry", zombifiedPiglinCountAsPlayerKillWhenAngry);
@@ -2537,7 +2537,7 @@ index 878c5f324484bbd401ea177fda6b1b5e53aaf778..a9953a72055d23354b72f9800625a745
}
public boolean zombieVillagerRidable = false;
-@@ -1232,11 +1807,20 @@ public class PurpurWorldConfig {
+@@ -1234,11 +1809,20 @@ public class PurpurWorldConfig {
public boolean zombieVillagerJockeyOnlyBaby = true;
public double zombieVillagerJockeyChance = 0.05D;
public boolean zombieVillagerJockeyTryExistingChickens = true;
diff --git a/patches/Purpur/patches/server/0153-Phantom-flames-on-swoop.patch b/patches/Purpur/patches/server/0153-Phantom-flames-on-swoop.patch
index 7342a7e65..9054095e2 100644
--- a/patches/Purpur/patches/server/0153-Phantom-flames-on-swoop.patch
+++ b/patches/Purpur/patches/server/0153-Phantom-flames-on-swoop.patch
@@ -5,10 +5,10 @@ Subject: [PATCH] Phantom flames on swoop
diff --git a/src/main/java/net/minecraft/server/EntityPhantom.java b/src/main/java/net/minecraft/server/EntityPhantom.java
-index 25345d8d585735af407787f2c26fe92674721239..087a91fedc49aaf6e74b81b90494849c4932c956 100644
+index 80cc4467d601b653583e387eb4be6f3b739058e6..52a3ae1eda874b41e5d71c16b8ab24d3c9f17470 100644
--- a/src/main/java/net/minecraft/server/EntityPhantom.java
+++ b/src/main/java/net/minecraft/server/EntityPhantom.java
-@@ -181,6 +181,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
+@@ -182,6 +182,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
this.world.addParticle(Particles.MYCELIUM, this.locX() - (double) f2, this.locY() + (double) f4, this.locZ() - (double) f3, 0.0D, 0.0D, 0.0D);
}
@@ -17,21 +17,21 @@ index 25345d8d585735af407787f2c26fe92674721239..087a91fedc49aaf6e74b81b90494849c
@Override
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index a9953a72055d23354b72f9800625a745c7d4eada..c96d20c5a4b2885cc0f1417de961a381ef44f7d2 100644
+index 72d1ccb375496ffaa3d02d7c65f3cfb7ddb84db4..1b0e8f2fbdfe6d48ed86ae49f296bbf6ebd0bd23 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-@@ -1147,6 +1147,7 @@ public class PurpurWorldConfig {
- public int phantomBurnInLight = 0;
+@@ -1148,6 +1148,7 @@ public class PurpurWorldConfig {
public boolean phantomIgnorePlayersWithTorch = false;
public boolean phantomBurnInDaylight = true;
+ public boolean phantomAllowGriefing = false;
+ public boolean phantomFlamesOnSwoop = false;
public double phantomMaxHealth = 20.0D;
private void phantomSettings() {
phantomRidable = getBoolean("mobs.phantom.ridable", phantomRidable);
-@@ -1172,6 +1173,7 @@ public class PurpurWorldConfig {
- phantomBurnInLight = getInt("mobs.phantom.burn-in-light", phantomBurnInLight);
+@@ -1174,6 +1175,7 @@ public class PurpurWorldConfig {
phantomBurnInDaylight = getBoolean("mobs.phantom.burn-in-daylight", phantomBurnInDaylight);
phantomIgnorePlayersWithTorch = getBoolean("mobs.phantom.ignore-players-with-torch", phantomIgnorePlayersWithTorch);
+ phantomAllowGriefing = getBoolean("mobs.phantom.allow-griefing", phantomAllowGriefing);
+ phantomFlamesOnSwoop = getBoolean("mobs.phantom.flames-on-swoop", phantomFlamesOnSwoop);
if (PurpurConfig.version < 10) {
double oldValue = getDouble("mobs.phantom.attributes.max-health", phantomMaxHealth);
diff --git a/patches/Purpur/patches/server/0154-Option-for-chests-to-open-even-with-a-solid-block-on.patch b/patches/Purpur/patches/server/0154-Option-for-chests-to-open-even-with-a-solid-block-on.patch
index 338b51332..1072f5261 100644
--- a/patches/Purpur/patches/server/0154-Option-for-chests-to-open-even-with-a-solid-block-on.patch
+++ b/patches/Purpur/patches/server/0154-Option-for-chests-to-open-even-with-a-solid-block-on.patch
@@ -17,7 +17,7 @@ index c4ff93a6b908c1bd157c7fe45b504909b189d09c..71a32a317e38b9c8f802fd5dd9ae546f
return iblockaccess.getType(blockposition1).isOccluding(iblockaccess, blockposition1);
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index c96d20c5a4b2885cc0f1417de961a381ef44f7d2..fbcf02831d1ca663c85988a53f8593c7e999178d 100644
+index 1b0e8f2fbdfe6d48ed86ae49f296bbf6ebd0bd23..9c6992fe621065151238281fe101566b6e634ad4 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -381,6 +381,11 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0156-Striders-give-saddle-back.patch b/patches/Purpur/patches/server/0156-Striders-give-saddle-back.patch
index 52a0499a7..baee10735 100644
--- a/patches/Purpur/patches/server/0156-Striders-give-saddle-back.patch
+++ b/patches/Purpur/patches/server/0156-Striders-give-saddle-back.patch
@@ -28,10 +28,10 @@ index 1bca386b7dea01af88a6c8d8e87ff11a0b21cc7a..964956a0027bf0941ff75d658be760b7
}
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index fbcf02831d1ca663c85988a53f8593c7e999178d..c3085b3c82f39b9b3343c36c0659e21ee4e8f70c 100644
+index 9c6992fe621065151238281fe101566b6e634ad4..31c902edfec4a69dfa36cd31ec1a82f3ac0fc621 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-@@ -1500,11 +1500,13 @@ public class PurpurWorldConfig {
+@@ -1502,11 +1502,13 @@ public class PurpurWorldConfig {
public boolean striderRidable = false;
public boolean striderRidableInWater = false;
public int striderBreedingTicks = 6000;
diff --git a/patches/Purpur/patches/server/0158-Full-netherite-armor-grants-fire-resistance.patch b/patches/Purpur/patches/server/0158-Full-netherite-armor-grants-fire-resistance.patch
index a8fcdd2b3..42b819967 100644
--- a/patches/Purpur/patches/server/0158-Full-netherite-armor-grants-fire-resistance.patch
+++ b/patches/Purpur/patches/server/0158-Full-netherite-armor-grants-fire-resistance.patch
@@ -26,7 +26,7 @@ index b6bfd8f5073ce481dfe2b1667ece42d32eaeb227..81f7d5bc581b42289a79121da1586899
protected ItemCooldown i() {
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index c3085b3c82f39b9b3343c36c0659e21ee4e8f70c..5c82f785e0dd5c0015d2e46ba1b93b784d91030a 100644
+index 31c902edfec4a69dfa36cd31ec1a82f3ac0fc621..f6d4ac90f9bad65743a02be21b0f7b52f6772659 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -310,6 +310,19 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0160-Add-mobGriefing-bypass-to-everything-affected.patch b/patches/Purpur/patches/server/0160-Add-mobGriefing-bypass-to-everything-affected.patch
index e278bb9ce..2263221d0 100644
--- a/patches/Purpur/patches/server/0160-Add-mobGriefing-bypass-to-everything-affected.patch
+++ b/patches/Purpur/patches/server/0160-Add-mobGriefing-bypass-to-everything-affected.patch
@@ -338,7 +338,7 @@ index c03ebbc933197be3e7097ea3f7b7cd08c90db7bb..37c1d1ac1bfcaf84d00135ad3c9d9e9b
} else if (this.c > 0) {
--this.c;
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 5c82f785e0dd5c0015d2e46ba1b93b784d91030a..c156f89e74e7db776fdfcfb2f7b30b4326fc0506 100644
+index f6d4ac90f9bad65743a02be21b0f7b52f6772659..106240d48b6bd472545bb46fdada3e023d3cfdca 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -252,6 +252,7 @@ public class PurpurWorldConfig {
@@ -440,7 +440,7 @@ index 5c82f785e0dd5c0015d2e46ba1b93b784d91030a..c156f89e74e7db776fdfcfb2f7b30b43
foxTypeChangesWithTulips = getBoolean("mobs.fox.tulips-change-type", foxTypeChangesWithTulips);
foxBreedingTicks = getInt("mobs.fox.breeding-delay-ticks", foxBreedingTicks);
if (PurpurConfig.version < 10) {
-@@ -1248,10 +1262,12 @@ public class PurpurWorldConfig {
+@@ -1250,10 +1264,12 @@ public class PurpurWorldConfig {
public boolean pillagerRidable = false;
public boolean pillagerRidableInWater = false;
@@ -453,7 +453,7 @@ index 5c82f785e0dd5c0015d2e46ba1b93b784d91030a..c156f89e74e7db776fdfcfb2f7b30b43
if (PurpurConfig.version < 10) {
double oldValue = getDouble("mobs.pillager.attributes.max-health", pillagerMaxHealth);
set("mobs.pillager.attributes.max-health", null);
-@@ -1295,6 +1311,7 @@ public class PurpurWorldConfig {
+@@ -1297,6 +1313,7 @@ public class PurpurWorldConfig {
public boolean rabbitRidable = false;
public boolean rabbitRidableInWater = false;
@@ -461,7 +461,7 @@ index 5c82f785e0dd5c0015d2e46ba1b93b784d91030a..c156f89e74e7db776fdfcfb2f7b30b43
public double rabbitNaturalToast = 0.0D;
public double rabbitNaturalKiller = 0.0D;
public int rabbitBreedingTicks = 6000;
-@@ -1302,6 +1319,7 @@ public class PurpurWorldConfig {
+@@ -1304,6 +1321,7 @@ public class PurpurWorldConfig {
private void rabbitSettings() {
rabbitRidable = getBoolean("mobs.rabbit.ridable", rabbitRidable);
rabbitRidableInWater = getBoolean("mobs.rabbit.ridable-in-water", rabbitRidableInWater);
@@ -469,7 +469,7 @@ index 5c82f785e0dd5c0015d2e46ba1b93b784d91030a..c156f89e74e7db776fdfcfb2f7b30b43
rabbitNaturalToast = getDouble("mobs.rabbit.spawn-toast-chance", rabbitNaturalToast);
rabbitNaturalKiller = getDouble("mobs.rabbit.spawn-killer-rabbit-chance", rabbitNaturalKiller);
rabbitBreedingTicks = getInt("mobs.rabbit.breeding-delay-ticks", rabbitBreedingTicks);
-@@ -1315,10 +1333,12 @@ public class PurpurWorldConfig {
+@@ -1317,10 +1335,12 @@ public class PurpurWorldConfig {
public boolean ravagerRidable = false;
public boolean ravagerRidableInWater = false;
@@ -482,7 +482,7 @@ index 5c82f785e0dd5c0015d2e46ba1b93b784d91030a..c156f89e74e7db776fdfcfb2f7b30b43
if (PurpurConfig.version < 10) {
double oldValue = getDouble("mobs.ravager.attributes.max-health", ravagerMaxHealth);
set("mobs.ravager.attributes.max-health", null);
-@@ -1342,11 +1362,13 @@ public class PurpurWorldConfig {
+@@ -1344,11 +1364,13 @@ public class PurpurWorldConfig {
public boolean sheepRidable = false;
public boolean sheepRidableInWater = false;
public int sheepBreedingTicks = 6000;
@@ -496,7 +496,7 @@ index 5c82f785e0dd5c0015d2e46ba1b93b784d91030a..c156f89e74e7db776fdfcfb2f7b30b43
if (PurpurConfig.version < 10) {
double oldValue = getDouble("mobs.sheep.attributes.max-health", sheepMaxHealth);
set("mobs.sheep.attributes.max-health", null);
-@@ -1371,10 +1393,12 @@ public class PurpurWorldConfig {
+@@ -1373,10 +1395,12 @@ public class PurpurWorldConfig {
public boolean silverfishRidable = false;
public boolean silverfishRidableInWater = false;
@@ -509,7 +509,7 @@ index 5c82f785e0dd5c0015d2e46ba1b93b784d91030a..c156f89e74e7db776fdfcfb2f7b30b43
if (PurpurConfig.version < 10) {
double oldValue = getDouble("mobs.silverfish.attributes.max-health", silverfishMaxHealth);
set("mobs.silverfish.attributes.max-health", null);
-@@ -1439,6 +1463,7 @@ public class PurpurWorldConfig {
+@@ -1441,6 +1465,7 @@ public class PurpurWorldConfig {
public boolean snowGolemRidable = false;
public boolean snowGolemRidableInWater = false;
public boolean snowGolemLeaveTrailWhenRidden = false;
@@ -517,7 +517,7 @@ index 5c82f785e0dd5c0015d2e46ba1b93b784d91030a..c156f89e74e7db776fdfcfb2f7b30b43
public boolean snowGolemDropsPumpkin = true;
public boolean snowGolemPutPumpkinBack = false;
public int snowGolemSnowBallMin = 20;
-@@ -1450,6 +1475,7 @@ public class PurpurWorldConfig {
+@@ -1452,6 +1477,7 @@ public class PurpurWorldConfig {
snowGolemRidable = getBoolean("mobs.snow_golem.ridable", snowGolemRidable);
snowGolemRidableInWater = getBoolean("mobs.snow_golem.ridable-in-water", snowGolemRidableInWater);
snowGolemLeaveTrailWhenRidden = getBoolean("mobs.snow_golem.leave-trail-when-ridden", snowGolemLeaveTrailWhenRidden);
@@ -525,7 +525,7 @@ index 5c82f785e0dd5c0015d2e46ba1b93b784d91030a..c156f89e74e7db776fdfcfb2f7b30b43
snowGolemDropsPumpkin = getBoolean("mobs.snow_golem.drop-pumpkin-when-sheared", snowGolemDropsPumpkin);
snowGolemPutPumpkinBack = getBoolean("mobs.snow_golem.pumpkin-can-be-added-back", snowGolemPutPumpkinBack);
snowGolemSnowBallMin = getInt("mobs.snow_golem.min-shoot-interval-ticks", snowGolemSnowBallMin);
-@@ -1666,6 +1692,7 @@ public class PurpurWorldConfig {
+@@ -1668,6 +1694,7 @@ public class PurpurWorldConfig {
public boolean witherRidable = false;
public boolean witherRidableInWater = false;
public double witherMaxY = 256D;
@@ -533,7 +533,7 @@ index 5c82f785e0dd5c0015d2e46ba1b93b784d91030a..c156f89e74e7db776fdfcfb2f7b30b43
public float witherHealthRegenAmount = 1.0f;
public int witherHealthRegenDelay = 20;
public double witherMaxHealth = 300.0D;
-@@ -1673,6 +1700,7 @@ public class PurpurWorldConfig {
+@@ -1675,6 +1702,7 @@ public class PurpurWorldConfig {
witherRidable = getBoolean("mobs.wither.ridable", witherRidable);
witherRidableInWater = getBoolean("mobs.wither.ridable-in-water", witherRidableInWater);
witherMaxY = getDouble("mobs.wither.ridable-max-y", witherMaxY);
@@ -541,7 +541,7 @@ index 5c82f785e0dd5c0015d2e46ba1b93b784d91030a..c156f89e74e7db776fdfcfb2f7b30b43
witherHealthRegenAmount = (float) getDouble("mobs.wither.health-regen-amount", witherHealthRegenAmount);
witherHealthRegenDelay = getInt("mobs.wither.health-regen-delay", witherHealthRegenDelay);
if (PurpurConfig.version < 8) {
-@@ -1745,6 +1773,7 @@ public class PurpurWorldConfig {
+@@ -1747,6 +1775,7 @@ public class PurpurWorldConfig {
public boolean zombieRidable = false;
public boolean zombieRidableInWater = false;
@@ -549,7 +549,7 @@ index 5c82f785e0dd5c0015d2e46ba1b93b784d91030a..c156f89e74e7db776fdfcfb2f7b30b43
public boolean zombieJockeyOnlyBaby = true;
public double zombieJockeyChance = 0.05D;
public boolean zombieJockeyTryExistingChickens = true;
-@@ -1755,6 +1784,7 @@ public class PurpurWorldConfig {
+@@ -1757,6 +1786,7 @@ public class PurpurWorldConfig {
private void zombieSettings() {
zombieRidable = getBoolean("mobs.zombie.ridable", zombieRidable);
zombieRidableInWater = getBoolean("mobs.zombie.ridable-in-water", zombieRidableInWater);
diff --git a/patches/Purpur/patches/server/0161-Config-to-allow-Note-Block-sounds-when-blocked.patch b/patches/Purpur/patches/server/0161-Config-to-allow-Note-Block-sounds-when-blocked.patch
index 247db7ab1..c5a066023 100644
--- a/patches/Purpur/patches/server/0161-Config-to-allow-Note-Block-sounds-when-blocked.patch
+++ b/patches/Purpur/patches/server/0161-Config-to-allow-Note-Block-sounds-when-blocked.patch
@@ -22,7 +22,7 @@ index df69d00d3a38417e53f433cd1eb1f6cf3ec9b55b..6bb6e229c8734d7b9f4e3cd3dd1b4b64
org.bukkit.event.block.NotePlayEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callNotePlayEvent(world, blockposition, data.get(BlockNote.INSTRUMENT), data.get(BlockNote.NOTE));
if (!event.isCancelled()) {
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index c156f89e74e7db776fdfcfb2f7b30b4326fc0506..5b69a3c3aa7fc830e3471ef7b99c8c4d38178127 100644
+index 106240d48b6bd472545bb46fdada3e023d3cfdca..2b25d505a5b5d8799177beacfaa9a5bcddb939ef 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -254,6 +254,7 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0162-Add-EntityTeleportHinderedEvent.patch b/patches/Purpur/patches/server/0162-Add-EntityTeleportHinderedEvent.patch
index a78baa6ae..d0bfea078 100644
--- a/patches/Purpur/patches/server/0162-Add-EntityTeleportHinderedEvent.patch
+++ b/patches/Purpur/patches/server/0162-Add-EntityTeleportHinderedEvent.patch
@@ -94,10 +94,10 @@ index ed8e91bf6c8b9d410d439bdddd5067d346a20a7e..127b5d8215f2bb4c5c523c5a77ebccfb
if (this.exitPortal == null && this.world.getTypeKey() == DimensionManager.THE_END) { // CraftBukkit - work in alternate worlds
this.a((WorldServer) this.world);
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 5b69a3c3aa7fc830e3471ef7b99c8c4d38178127..14e80ed8cb3c0cacef8c7a5d44cda9805249ed03 100644
+index 2b25d505a5b5d8799177beacfaa9a5bcddb939ef..31d011ad08b2756fb236099cb92cd37b6a2934ff 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-@@ -1877,4 +1877,9 @@ public class PurpurWorldConfig {
+@@ -1879,4 +1879,9 @@ public class PurpurWorldConfig {
zombieVillagerMaxHealth = getDouble("mobs.zombie_villager.attributes.max_health", zombieVillagerMaxHealth);
zombieVillagerSpawnReinforcements = getDouble("mobs.zombie_villager.attributes.spawn_reinforcements", zombieVillagerSpawnReinforcements);
}
diff --git a/patches/Purpur/patches/server/0164-Farmland-trampling-changes.patch b/patches/Purpur/patches/server/0164-Farmland-trampling-changes.patch
index 78004a319..a61229262 100644
--- a/patches/Purpur/patches/server/0164-Farmland-trampling-changes.patch
+++ b/patches/Purpur/patches/server/0164-Farmland-trampling-changes.patch
@@ -28,7 +28,7 @@ index 73dc0f499c456c21d298013fbab8c79ebcdecd6b..6b65a4b1845c6770f92ceebd04827595
if (CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, Blocks.DIRT.getBlockData()).isCancelled()) {
return;
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 14e80ed8cb3c0cacef8c7a5d44cda9805249ed03..8ce8f9eaf9b41003bbfa3acc4f7cbd8329d1b9b2 100644
+index 31d011ad08b2756fb236099cb92cd37b6a2934ff..92f16b14a0da17da7a731301892535982605347a 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -413,10 +413,14 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0165-Movement-options-for-armour-stands.patch b/patches/Purpur/patches/server/0165-Movement-options-for-armour-stands.patch
index ce3a62a47..d3fd10e7a 100644
--- a/patches/Purpur/patches/server/0165-Movement-options-for-armour-stands.patch
+++ b/patches/Purpur/patches/server/0165-Movement-options-for-armour-stands.patch
@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
-index cb4856e3bbb25e1077f5b4832f359549d57acd7e..41844f30a2a98eb14559b3ab0885ae738b54520c 100644
+index b861922586dc08a660050e9f2f94433b54c16def..1c407f3050ba34afd33ce66b6ef8ef682010091a 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -1360,7 +1360,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
@@ -66,7 +66,7 @@ index 759a8f95038778aead2f33a65a2d8f2d6b26a765..74fda434ed7beb6612f46ed75fdccad5
+ // Purpur end
}
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 8ce8f9eaf9b41003bbfa3acc4f7cbd8329d1b9b2..87f1af12abe92d10dcab532715d10c39f95119b7 100644
+index 92f16b14a0da17da7a731301892535982605347a..2c555ac0bee9e0a37fada8c04e75699f2cb311bc 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -111,10 +111,16 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0166-Fix-stuck-in-portals.patch b/patches/Purpur/patches/server/0166-Fix-stuck-in-portals.patch
index 034d47b56..623f6910d 100644
--- a/patches/Purpur/patches/server/0166-Fix-stuck-in-portals.patch
+++ b/patches/Purpur/patches/server/0166-Fix-stuck-in-portals.patch
@@ -5,7 +5,7 @@ Subject: [PATCH] Fix stuck in portals
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
-index 41844f30a2a98eb14559b3ab0885ae738b54520c..63eb29635957d4e6ce1274ee17a59af62d442d4e 100644
+index 1c407f3050ba34afd33ce66b6ef8ef682010091a..a2ba87dac005572d2617b6fe2c92f6984665588c 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -2411,12 +2411,15 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
@@ -37,7 +37,7 @@ index 63b919bef1a4420e02b4822097cadc1af9cd97a2..9013e8655d6e09f830adda8001567ab8
// CraftBukkit end
this.spawnIn(worldserver);
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 87f1af12abe92d10dcab532715d10c39f95119b7..ed9703608467aa99f5cef6a6154fdf05efdbe0f7 100644
+index 2c555ac0bee9e0a37fada8c04e75699f2cb311bc..3df5798e91b767aa0843a3cc520116c02b5e277e 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -350,6 +350,11 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0168-Config-to-use-infinity-bows-without-arrows.patch b/patches/Purpur/patches/server/0168-Config-to-use-infinity-bows-without-arrows.patch
index eeb8cc3c3..344d04bd5 100644
--- a/patches/Purpur/patches/server/0168-Config-to-use-infinity-bows-without-arrows.patch
+++ b/patches/Purpur/patches/server/0168-Config-to-use-infinity-bows-without-arrows.patch
@@ -20,7 +20,7 @@ index 8241f3dafa5852bed7a3967e7260b36f47198dba..edfb09fe673a9a7fe4e0410c0c0eeeda
} else {
entityhuman.c(enumhand);
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index ed9703608467aa99f5cef6a6154fdf05efdbe0f7..0747718f8705f5f56089e83e8344ad93b0055a15 100644
+index 3df5798e91b767aa0843a3cc520116c02b5e277e..200ac6aff09a38198b13d4cb91b5c08fddf83261 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -209,10 +209,12 @@ public class PurpurWorldConfig {
diff --git a/patches/Purpur/patches/server/0169-Toggle-for-water-sensitive-mob-damage.patch b/patches/Purpur/patches/server/0169-Toggle-for-water-sensitive-mob-damage.patch
index cbc1ca66e..e725d33ce 100644
--- a/patches/Purpur/patches/server/0169-Toggle-for-water-sensitive-mob-damage.patch
+++ b/patches/Purpur/patches/server/0169-Toggle-for-water-sensitive-mob-damage.patch
@@ -31,7 +31,7 @@ index beee80c3d8277f2d784fb6b8a4152a871ee020b0..b884addf2ce6f1ef7394658078deb2e7
@Override
diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java
-index 03f480e29b92e278e1d4901ee4388f02ef6e3a82..dac0d2f9f4c8c909f0c03baa30c0565633d3af42 100644
+index de977e80eb6cad74cbea3a00702ef804693374f0..65841a7bb58e210f07c0afd74c2fd5b3873bdd60 100644
--- a/src/main/java/net/minecraft/server/EntityInsentient.java
+++ b/src/main/java/net/minecraft/server/EntityInsentient.java
@@ -786,7 +786,8 @@ public abstract class EntityInsentient extends EntityLiving {
@@ -83,7 +83,7 @@ index 964956a0027bf0941ff75d658be760b754772fa0..7c5472a5138011a3376b7b6ec2467bdf
@Override
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
-index 0747718f8705f5f56089e83e8344ad93b0055a15..ad6f5bf3a2f0734ffeba044025a52fd15e9970fb 100644
+index 200ac6aff09a38198b13d4cb91b5c08fddf83261..2d379971fbe5c90c5e2e518bdae1d2e74f7ebc52 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -569,6 +569,7 @@ public class PurpurWorldConfig {
@@ -118,7 +118,7 @@ index 0747718f8705f5f56089e83e8344ad93b0055a15..ad6f5bf3a2f0734ffeba044025a52fd1
}
public boolean endermiteRidable = false;
-@@ -1490,6 +1494,7 @@ public class PurpurWorldConfig {
+@@ -1492,6 +1496,7 @@ public class PurpurWorldConfig {
public float snowGolemSnowBallModifier = 10.0F;
public double snowGolemAttackDistance = 1.25D;
public double snowGolemMaxHealth = 4.0D;
@@ -126,7 +126,7 @@ index 0747718f8705f5f56089e83e8344ad93b0055a15..ad6f5bf3a2f0734ffeba044025a52fd1
private void snowGolemSettings() {
snowGolemRidable = getBoolean("mobs.snow_golem.ridable", snowGolemRidable);
snowGolemRidableInWater = getBoolean("mobs.snow_golem.ridable-in-water", snowGolemRidableInWater);
-@@ -1507,6 +1512,7 @@ public class PurpurWorldConfig {
+@@ -1509,6 +1514,7 @@ public class PurpurWorldConfig {
set("mobs.snow_golem.attributes.max_health", oldValue);
}
snowGolemMaxHealth = getDouble("mobs.snow_golem.attributes.max_health", snowGolemMaxHealth);
@@ -134,7 +134,7 @@ index 0747718f8705f5f56089e83e8344ad93b0055a15..ad6f5bf3a2f0734ffeba044025a52fd1
}
public boolean squidRidable = false;
-@@ -1560,6 +1566,7 @@ public class PurpurWorldConfig {
+@@ -1562,6 +1568,7 @@ public class PurpurWorldConfig {
public int striderBreedingTicks = 6000;
public boolean striderGiveSaddleBack = false;
public double striderMaxHealth = 20.0D;
@@ -142,7 +142,7 @@ index 0747718f8705f5f56089e83e8344ad93b0055a15..ad6f5bf3a2f0734ffeba044025a52fd1
private void striderSettings() {
striderRidable = getBoolean("mobs.strider.ridable", striderRidable);
striderRidableInWater = getBoolean("mobs.strider.ridable-in-water", striderRidableInWater);
-@@ -1571,6 +1578,7 @@ public class PurpurWorldConfig {
+@@ -1573,6 +1580,7 @@ public class PurpurWorldConfig {
set("mobs.strider.attributes.max_health", oldValue);
}
striderMaxHealth = getDouble("mobs.strider.attributes.max_health", striderMaxHealth);
diff --git a/patches/Purpur/patches/server/0170-Config-to-always-tame-in-Creative.patch b/patches/Purpur/patches/server/0170-Config-to-always-tame-in-Creative.patch
new file mode 100644
index 000000000..da9633deb
--- /dev/null
+++ b/patches/Purpur/patches/server/0170-Config-to-always-tame-in-Creative.patch
@@ -0,0 +1,80 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Encode42
+Date: Tue, 9 Feb 2021 21:23:37 -0500
+Subject: [PATCH] Config to always tame in Creative
+
+Adds a configuration option that ensures a player in Creative always tames a tameable entity.
+This essentially allows Creative mode players to tame animals on their first try.
+
+diff --git a/src/main/java/net/minecraft/server/EntityCat.java b/src/main/java/net/minecraft/server/EntityCat.java
+index f973408b1f098c8a090401205f809e95fdcf2f62..2128d8a9a6fe6bdea81881cfc8ab7b03f448576f 100644
+--- a/src/main/java/net/minecraft/server/EntityCat.java
++++ b/src/main/java/net/minecraft/server/EntityCat.java
+@@ -375,7 +375,7 @@ public class EntityCat extends EntityTameableAnimal {
+ }
+ } else if (this.k(itemstack)) {
+ this.a(entityhuman, itemstack);
+- if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled()) { // CraftBukkit
++ if ((this.world.purpurConfig.alwaysTameInCreative && entityhuman.abilities.canInstantlyBuild) || (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled())) { // CraftBukkit // Purpur
+ this.tame(entityhuman);
+ this.setWillSit(true);
+ this.world.broadcastEntityEffect(this, (byte) 7);
+diff --git a/src/main/java/net/minecraft/server/EntityParrot.java b/src/main/java/net/minecraft/server/EntityParrot.java
+index d19f8dda87c97de594ad051a6791d99eec581e95..6d5a56b96c3759c594fe2ee4b7cdd7fa67f3d3fb 100644
+--- a/src/main/java/net/minecraft/server/EntityParrot.java
++++ b/src/main/java/net/minecraft/server/EntityParrot.java
+@@ -245,7 +245,7 @@ public class EntityParrot extends EntityPerchable implements EntityBird {
+ }
+
+ if (!this.world.isClientSide) {
+- if (this.random.nextInt(10) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled()) { // CraftBukkit
++ if ((this.world.purpurConfig.alwaysTameInCreative && entityhuman.abilities.canInstantlyBuild) || (this.random.nextInt(10) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled())) { // CraftBukkit // Purpur
+ this.tame(entityhuman);
+ this.world.broadcastEntityEffect(this, (byte) 7);
+ } else {
+diff --git a/src/main/java/net/minecraft/server/EntityWolf.java b/src/main/java/net/minecraft/server/EntityWolf.java
+index 03bcbf7c280476ef0e6fe87e3a96edb75544bddb..5bf2a3205671a7cb001835ab241c34bcbe47e02c 100644
+--- a/src/main/java/net/minecraft/server/EntityWolf.java
++++ b/src/main/java/net/minecraft/server/EntityWolf.java
+@@ -415,7 +415,7 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable
+ }
+
+ // CraftBukkit - added event call and isCancelled check.
+- if (this.random.nextInt(3) == 0 && !CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled()) {
++ if ((this.world.purpurConfig.alwaysTameInCreative && entityhuman.abilities.canInstantlyBuild) || (this.random.nextInt(3) == 0 && !CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled())) { // Purpur
+ this.tame(entityhuman);
+ this.navigation.o();
+ this.setGoalTarget((EntityLiving) null);
+diff --git a/src/main/java/net/minecraft/server/PathfinderGoalTame.java b/src/main/java/net/minecraft/server/PathfinderGoalTame.java
+index fc831dc26eaeab802d5fee456d5c662fe3f8bdfd..76dda6f777fbdf515990651594b5b3fa57cc1f66 100644
+--- a/src/main/java/net/minecraft/server/PathfinderGoalTame.java
++++ b/src/main/java/net/minecraft/server/PathfinderGoalTame.java
+@@ -58,7 +58,7 @@ public class PathfinderGoalTame extends PathfinderGoal {
+ int j = this.entity.getMaxDomestication();
+
+ // CraftBukkit - fire EntityTameEvent
+- if (j > 0 && this.entity.getRandom().nextInt(j) < i && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this.entity, ((org.bukkit.craftbukkit.entity.CraftHumanEntity) this.entity.getBukkitEntity().getPassenger()).getHandle()).isCancelled()) {
++ if ((this.entity.world.purpurConfig.alwaysTameInCreative && ((EntityHuman) entity).abilities.canInstantlyBuild) || (j > 0 && this.entity.getRandom().nextInt(j) < i && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this.entity, ((org.bukkit.craftbukkit.entity.CraftHumanEntity) this.entity.getBukkitEntity().getPassenger()).getHandle()).isCancelled())) { // Purpur
+ this.entity.i((EntityHuman) entity);
+ return;
+ }
+diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+index 2d379971fbe5c90c5e2e518bdae1d2e74f7ebc52..5d1f77c20429f74590d22e9c5dec3f45056664d5 100644
+--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
++++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+@@ -255,6 +255,7 @@ public class PurpurWorldConfig {
+ }
+
+ public boolean useBetterMending = false;
++ public boolean alwaysTameInCreative = false;
+ public boolean boatEjectPlayersOnLand = false;
+ public boolean boatsDoFallDamage = true;
+ public boolean disableDropsOnCrammingDeath = false;
+@@ -271,6 +272,7 @@ public class PurpurWorldConfig {
+ public int animalBreedingCooldownSeconds = 0;
+ private void miscGameplayMechanicsSettings() {
+ useBetterMending = getBoolean("gameplay-mechanics.use-better-mending", useBetterMending);
++ alwaysTameInCreative = getBoolean("gameplay-mechanics.always-tame-in-creative", alwaysTameInCreative);
+ boatEjectPlayersOnLand = getBoolean("gameplay-mechanics.boat.eject-players-on-land", boatEjectPlayersOnLand);
+ boatsDoFallDamage = getBoolean("gameplay-mechanics.boat.do-fall-damage", boatsDoFallDamage);
+ disableDropsOnCrammingDeath = getBoolean("gameplay-mechanics.disable-drops-on-cramming-death", disableDropsOnCrammingDeath);
diff --git a/patches/Purpur/patches/server/0171-End-crystal-explosion-options.patch b/patches/Purpur/patches/server/0171-End-crystal-explosion-options.patch
new file mode 100644
index 000000000..49143400f
--- /dev/null
+++ b/patches/Purpur/patches/server/0171-End-crystal-explosion-options.patch
@@ -0,0 +1,91 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Ben Kerllenevich
+Date: Sat, 13 Feb 2021 09:28:56 -0500
+Subject: [PATCH] End crystal explosion options
+
+
+diff --git a/src/main/java/net/minecraft/server/EntityEnderCrystal.java b/src/main/java/net/minecraft/server/EntityEnderCrystal.java
+index 1942fae27051af79b6eb1d790a219da100bf889e..0e2f9777fe1b62f8da20bf7559150e1dd041febc 100644
+--- a/src/main/java/net/minecraft/server/EntityEnderCrystal.java
++++ b/src/main/java/net/minecraft/server/EntityEnderCrystal.java
+@@ -100,6 +100,22 @@ public class EntityEnderCrystal extends Entity {
+ phantomDamageCooldown = 0;
+ idleCooldown = 60;
+ }
++
++ public boolean shouldExplode() {
++ return isShowingBottom() ? world.purpurConfig.baseCrystalExplode : world.purpurConfig.baselessCrystalExplode;
++ }
++
++ public float getExplosionPower() {
++ return (float) (isShowingBottom() ? world.purpurConfig.baseCrystalExplosionPower : world.purpurConfig.baselessCrystalExplosionPower);
++ }
++
++ public boolean hasExplosionFire() {
++ return isShowingBottom() ? world.purpurConfig.baseCrystalExplosionFire : world.purpurConfig.baselessCrystalExplosionFire;
++ }
++
++ public Explosion.Effect getExplosionEffect() {
++ return isShowingBottom() ? world.purpurConfig.baseCrystalExplosionEffect : world.purpurConfig.baselessCrystalExplosionEffect;
++ }
+ // Purpur end
+
+ @Override
+@@ -143,15 +159,17 @@ public class EntityEnderCrystal extends Entity {
+ // CraftBukkit end
+ this.die();
+ if (!damagesource.isExplosion()) {
++ if (shouldExplode()) { // Purpur
+ // CraftBukkit start
+- ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), 6.0F, false);
++ ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), getExplosionPower(), hasExplosionFire()); // Purpur
+ this.world.getServer().getPluginManager().callEvent(event);
+ if (event.isCancelled()) {
+ this.dead = false;
+ return false;
+ }
+- this.world.createExplosion(this, this.locX(), this.locY(), this.locZ(), event.getRadius(), event.getFire(), Explosion.Effect.DESTROY);
++ this.world.createExplosion(this, this.locX(), this.locY(), this.locZ(), event.getRadius(), event.getFire(), getExplosionEffect()); // Purpur
+ // CraftBukkit end
++ } else this.dead = false; // Purpur
+ }
+
+ this.a(damagesource);
+diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+index 5d1f77c20429f74590d22e9c5dec3f45056664d5..73ff19d8aed27e6717c201ef59b17f4b26056aa4 100644
+--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
++++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+@@ -1911,4 +1911,33 @@ public class PurpurWorldConfig {
+ private void imposeTeleportRestrictionsOnGateways() {
+ imposeTeleportRestrictionsOnGateways = getBoolean("gameplay-mechanics.impose-teleport-restrictions-on-gateways", imposeTeleportRestrictionsOnGateways);
+ }
++
++ public boolean baselessCrystalExplode = true;
++ public double baselessCrystalExplosionPower = 6.0D;
++ public boolean baselessCrystalExplosionFire = false;
++ public Explosion.Effect baselessCrystalExplosionEffect = Explosion.Effect.DESTROY;
++ public boolean baseCrystalExplode = true;
++ public double baseCrystalExplosionPower = 6.0D;
++ public boolean baseCrystalExplosionFire = false;
++ public Explosion.Effect baseCrystalExplosionEffect = Explosion.Effect.DESTROY;
++ private void crystalSettings() {
++ baselessCrystalExplode = getBoolean("blocks.end-crystal.baseless.explode", baselessCrystalExplode);
++ baselessCrystalExplosionPower = getDouble("blocks.end-crystal.baseless.explosion-power", baselessCrystalExplosionPower);
++ baselessCrystalExplosionFire = getBoolean("blocks.end-crystal.baseless.explosion-fire", baselessCrystalExplosionFire);
++ try {
++ baselessCrystalExplosionEffect = Explosion.Effect.valueOf(getString("blocks.end-crystal.baseless.explosion-effect", baselessCrystalExplosionEffect.name()));
++ } catch (IllegalArgumentException e) {
++ log(Level.SEVERE, "Unknown value for `blocks.end-crystal.baseless.explosion-effect`! Using default of `DESTROY`");
++ baselessCrystalExplosionEffect = Explosion.Effect.DESTROY;
++ }
++ baseCrystalExplode = getBoolean("blocks.end-crystal.base.explode", baseCrystalExplode);
++ baseCrystalExplosionPower = getDouble("blocks.end-crystal.base.explosion-power", baseCrystalExplosionPower);
++ baseCrystalExplosionFire = getBoolean("blocks.end-crystal.base.explosion-fire", baseCrystalExplosionFire);
++ try {
++ baseCrystalExplosionEffect = Explosion.Effect.valueOf(getString("blocks.end-crystal.base.explosion-effect", baseCrystalExplosionEffect.name()));
++ } catch (IllegalArgumentException e) {
++ log(Level.SEVERE, "Unknown value for `blocks.end-crystal.base.explosion-effect`! Using default of `DESTROY`");
++ baseCrystalExplosionEffect = Explosion.Effect.DESTROY;
++ }
++ }
+ }
diff --git a/patches/Purpur/patches/server/0172-Add-unsafe-Entity-serialization-API.patch b/patches/Purpur/patches/server/0172-Add-unsafe-Entity-serialization-API.patch
new file mode 100644
index 000000000..78886ad74
--- /dev/null
+++ b/patches/Purpur/patches/server/0172-Add-unsafe-Entity-serialization-API.patch
@@ -0,0 +1,129 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Mariell Hoversholm
+Date: Sat, 9 Jan 2021 21:22:58 +0100
+Subject: [PATCH] Add unsafe Entity serialization API
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+
+diff --git a/src/main/java/net/minecraft/server/EntityTypes.java b/src/main/java/net/minecraft/server/EntityTypes.java
+index 919cf670327bed6faa50f29c9bf7a9b54174f7f2..631eb682e81e30d2a937fd1eafccd8a9ab82d21e 100644
+--- a/src/main/java/net/minecraft/server/EntityTypes.java
++++ b/src/main/java/net/minecraft/server/EntityTypes.java
+@@ -380,6 +380,7 @@ public class EntityTypes {
+ return this.bf.create(this, world);
+ }
+
++ public static Optional loadEntityFixedData(NBTTagCompound nbtTagCompound, World world) { return a(nbtTagCompound, world); } // Purpur - OBFHELPER
+ public static Optional a(NBTTagCompound nbttagcompound, World world) {
+ return SystemUtils.a(a(nbttagcompound).map((entitytypes) -> {
+ return entitytypes.a(world);
+diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+index eb0ce05d25ba33626d2dd3e3380d805c560bfe58..7c30064237bd58673de710915b1a9437335a3e8a 100644
+--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+@@ -1185,5 +1185,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
+ public boolean isRidableInWater() {
+ return getHandle().isRidableInWater();
+ }
++
++ @Override
++ public boolean spawnAt(Location location, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
++ entity.world = ((CraftWorld) location.getWorld()).getHandle();
++ entity.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
++ return !entity.valid && entity.world.addEntity(entity, spawnReason);
++ }
+ // Purpur end
+ }
+diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+index 37c561fb775cf7dd955b185b4ea94fecc574be63..821b8665b4ed70c010a0824df99de2667fd4c8ba 100644
+--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+@@ -383,9 +383,14 @@ public final class CraftMagicNumbers implements UnsafeValues {
+ Preconditions.checkNotNull(item, "null cannot be serialized");
+ Preconditions.checkArgument(item.getType() != Material.AIR, "air cannot be serialized");
+
++ // Purpur start - rework NBT <-> bytes
++ return serializeNbtToBytes(CraftItemStack.asNMSCopy(item).save(new NBTTagCompound()), true);
++ }
++
++ public byte[] serializeNbtToBytes(NBTTagCompound compound, boolean addDataVersion) {
++ if (addDataVersion) compound.setInt("DataVersion", getDataVersion());
+ java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream();
+- NBTTagCompound compound = (item instanceof CraftItemStack ? ((CraftItemStack) item).getHandle() : CraftItemStack.asNMSCopy(item)).save(new NBTTagCompound());
+- compound.setInt("DataVersion", getDataVersion());
++ // Purpur end
+ try {
+ net.minecraft.server.NBTCompressedStreamTools.writeNBT(
+ compound,
+@@ -398,26 +403,58 @@ public final class CraftMagicNumbers implements UnsafeValues {
+ return outputStream.toByteArray();
+ }
+
++ public static DynamicOpsNBT getDynamicOpsNbtInstance() { return DynamicOpsNBT.a; } // Purpur - OBFHELPER - keeping out of the class because it's FULL of decompile errors
+ @Override
+ public ItemStack deserializeItem(byte[] data) {
+ Preconditions.checkNotNull(data, "null cannot be deserialized");
+ Preconditions.checkArgument(data.length > 0, "cannot deserialize nothing");
+
++ // Purpur start - rework NBT <-> bytes
++ NBTTagCompound compound = deserializeNbtFromBytes(data, true);
++ Dynamic converted = DataConverterRegistry.getDataFixer().update(DataConverterTypes.ITEM_STACK, new Dynamic<>(getDynamicOpsNbtInstance(), compound), compound.getInt("DataVersion"), getDataVersion()); // TODO: obfhelper
++ return net.minecraft.server.ItemStack.fromCompound((NBTTagCompound) converted.getValue()).asBukkitMirror();
++ }
++
++ public NBTTagCompound deserializeNbtFromBytes(byte[] data, boolean verifyDataVersion) {
++ // Purpur end
+ try {
+ NBTTagCompound compound = net.minecraft.server.NBTCompressedStreamTools.readNBT(
+ new java.io.ByteArrayInputStream(data)
+ );
++ if (verifyDataVersion) { // Purpur
+ int dataVersion = compound.getInt("DataVersion");
+
+ Preconditions.checkArgument(dataVersion <= getDataVersion(), "Newer version! Server downgrades are not supported!");
+- Dynamic converted = DataConverterRegistry.getDataFixer().update(DataConverterTypes.ITEM_STACK, new Dynamic(DynamicOpsNBT.a, compound), dataVersion, getDataVersion());
+- return CraftItemStack.asCraftMirror(net.minecraft.server.ItemStack.fromCompound((NBTTagCompound) converted.getValue()));
++ } // Purpur
++ return compound; // Purpur
+ } catch (IOException ex) {
+ com.destroystokyo.paper.util.SneakyThrow.sneaky(ex);
+ throw new RuntimeException();
+ }
+ }
+
++ // Purpur start
++ @Override
++ public byte[] serializeEntity(org.bukkit.entity.Entity entity) {
++ Preconditions.checkNotNull(entity, "null cannot be serialized");
++ Preconditions.checkArgument(entity instanceof org.bukkit.craftbukkit.entity.CraftEntity, "non-CraftEntity cannot be serialized");
++ NBTTagCompound compound = new NBTTagCompound();
++ compound.setString("id", ((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle().getMinecraftKeyString());
++ return serializeNbtToBytes(((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle().save(compound), true);
++ }
++
++ @Override
++ public org.bukkit.entity.Entity deserializeEntity(byte[] data, org.bukkit.World world) {
++ NBTTagCompound compound = deserializeNbtFromBytes(data, true);
++ Dynamic converted = DataConverterRegistry.getDataFixer().update(DataConverterTypes.ENTITY, new Dynamic<>(getDynamicOpsNbtInstance(), compound), compound.getInt("DataVersion"), getDataVersion());
++ compound = (NBTTagCompound) converted.getValue();
++ compound.remove("UUID"); // Make the server make a new UUID for this entity; makes entities always spawnable.
++ return net.minecraft.server.EntityTypes.loadEntityFixedData(compound, ((org.bukkit.craftbukkit.CraftWorld) world).getHandle())
++ .orElseThrow(() -> new IllegalArgumentException("unknown ID was found for the data; did you downgrade?"))
++ .getBukkitEntity();
++ }
++ // Pupur end
++
+ @Override
+ public String getTranslationKey(Material mat) {
+ return getItem(mat).getOrCreateDescriptionId();
diff --git a/patches/Purpur/patches/server/0173-Add-ghast-allow-griefing-option.patch b/patches/Purpur/patches/server/0173-Add-ghast-allow-griefing-option.patch
new file mode 100644
index 000000000..43bd290dc
--- /dev/null
+++ b/patches/Purpur/patches/server/0173-Add-ghast-allow-griefing-option.patch
@@ -0,0 +1,59 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: BillyGalbreath
+Date: Sat, 13 Feb 2021 14:02:43 -0600
+Subject: [PATCH] Add ghast allow-griefing option
+
+
+diff --git a/src/main/java/net/minecraft/server/EntityGhast.java b/src/main/java/net/minecraft/server/EntityGhast.java
+index 2c0148229283f95bed3c8f33cc02a31d6f682191..db96d2bb02dfeea4136eb587a7bd744c9eb30bf3 100644
+--- a/src/main/java/net/minecraft/server/EntityGhast.java
++++ b/src/main/java/net/minecraft/server/EntityGhast.java
+@@ -198,6 +198,7 @@ public class EntityGhast extends EntityFlying implements IMonster {
+ }
+
+ EntityLargeFireball entitylargefireball = new EntityLargeFireball(world, this.ghast, d2, d3, d4);
++ entitylargefireball.canCauseGrief = world.purpurConfig.ghastAllowGriefing; // Purpur
+
+ // CraftBukkit - set bukkitYield when setting explosionpower
+ entitylargefireball.bukkitYield = entitylargefireball.yield = this.ghast.getPower();
+diff --git a/src/main/java/net/minecraft/server/EntityLargeFireball.java b/src/main/java/net/minecraft/server/EntityLargeFireball.java
+index 3f3be1b2ded6ad118ae7860c1231c7affc0715b6..48174610518af8d053149e609c1b140e1ae6ba61 100644
+--- a/src/main/java/net/minecraft/server/EntityLargeFireball.java
++++ b/src/main/java/net/minecraft/server/EntityLargeFireball.java
+@@ -5,6 +5,7 @@ import org.bukkit.event.entity.ExplosionPrimeEvent; // CraftBukkit
+ public class EntityLargeFireball extends EntityFireballFireball {
+
+ public int yield = 1;
++ public boolean canCauseGrief = true; // Purpur
+
+ public EntityLargeFireball(EntityTypes extends EntityLargeFireball> entitytypes, World world) {
+ super(entitytypes, world);
+@@ -20,7 +21,7 @@ public class EntityLargeFireball extends EntityFireballFireball {
+ protected void a(MovingObjectPosition movingobjectposition) {
+ super.a(movingobjectposition);
+ if (!this.world.isClientSide) {
+- boolean flag = this.world.purpurConfig.fireballsBypassMobGriefing || this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING); // Purpur
++ boolean flag = isIncendiary = canCauseGrief && (this.world.purpurConfig.fireballsBypassMobGriefing || this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)); // Purpur
+
+ // CraftBukkit start - fire ExplosionPrimeEvent
+ ExplosionPrimeEvent event = new ExplosionPrimeEvent((org.bukkit.entity.Explosive) this.getBukkitEntity());
+diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+index 73ff19d8aed27e6717c201ef59b17f4b26056aa4..99853bbf5d5a173bb109bfb863476464cb0bee1f 100644
+--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
++++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+@@ -866,6 +866,7 @@ public class PurpurWorldConfig {
+ public boolean ghastRidable = false;
+ public boolean ghastRidableInWater = false;
+ public double ghastMaxY = 256D;
++ public boolean ghastAllowGriefing = true;
+ public double ghastMaxHealth = 10.0D;
+ private void ghastSettings() {
+ ghastRidable = getBoolean("mobs.ghast.ridable", ghastRidable);
+@@ -876,6 +877,7 @@ public class PurpurWorldConfig {
+ set("mobs.ghast.attributes.max-health", null);
+ set("mobs.ghast.attributes.max_health", oldValue);
+ }
++ ghastAllowGriefing = getBoolean("mobs.ghast.allow-griefing", ghastAllowGriefing);
+ ghastMaxHealth = getDouble("mobs.ghast.attributes.max_health", ghastMaxHealth);
+ }
+
diff --git a/patches/Tuinity/patches/server/0004-Util-patch.patch b/patches/Tuinity/patches/server/0004-Util-patch.patch
index 32e3e64e4..2b6ba671e 100644
--- a/patches/Tuinity/patches/server/0004-Util-patch.patch
+++ b/patches/Tuinity/patches/server/0004-Util-patch.patch
@@ -2222,7 +2222,7 @@ index 96a6f4675dc10a0047b7d2ee4164d0376de36c27..a4bbf3d9520db9911a5709d8d8c60322
PlayerChunk playerchunk = this.getChunk(k);
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
-index f307a6361144c7e315b2e0ea45df27527cdb26ca..5c8dd000af238ea703c9f84a4621472f17955060 100644
+index d8787985ab4c94e9808332c15b3d16d4b52ba195..0b25e0a4d050e77fa2fabd4e389d4ce693431aca 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -207,6 +207,14 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
diff --git a/patches/Tuinity/patches/server/0008-Add-soft-async-catcher.patch b/patches/Tuinity/patches/server/0008-Add-soft-async-catcher.patch
index 7155a65a6..632835692 100644
--- a/patches/Tuinity/patches/server/0008-Add-soft-async-catcher.patch
+++ b/patches/Tuinity/patches/server/0008-Add-soft-async-catcher.patch
@@ -147,26 +147,6 @@ index 033548a58d27f64d3954206d267783c0437d4019..08ed243259f052165c6f75aed1d1d65a
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) {
-diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
-index af9d54ef057d5f6977cf77c57cde25b6b0d1f39d..8816d3326af25431e2235c5e735e86c7335f60dc 100644
---- a/src/main/java/net/minecraft/server/Chunk.java
-+++ b/src/main/java/net/minecraft/server/Chunk.java
-@@ -548,6 +548,7 @@ public class Chunk implements IChunkAccess {
-
- @Override
- public void a(Entity entity) {
-+ org.spigotmc.AsyncCatcher.catchOp("Chunk add entity"); // Tuinity
- this.q = true;
- int i = MathHelper.floor(entity.locX() / 16.0D);
- int j = MathHelper.floor(entity.locZ() / 16.0D);
-@@ -617,6 +618,7 @@ public class Chunk implements IChunkAccess {
- }
-
- public void a(Entity entity, int i) {
-+ org.spigotmc.AsyncCatcher.catchOp("Chunk remove entity"); // Tuinity // Tuinity
- if (i < 0) {
- i = 0;
- }
diff --git a/src/main/java/net/minecraft/server/ChunkMapDistance.java b/src/main/java/net/minecraft/server/ChunkMapDistance.java
index 76f9bb728def91744910d0b680b73e753f1a2b26..84ff9cfe89defad2e907708f837d33f620a84ef3 100644
--- a/src/main/java/net/minecraft/server/ChunkMapDistance.java
diff --git a/patches/Tuinity/patches/server/0009-Delay-chunk-unloads.patch b/patches/Tuinity/patches/server/0009-Delay-chunk-unloads.patch
index b4e929912..13981bb21 100644
--- a/patches/Tuinity/patches/server/0009-Delay-chunk-unloads.patch
+++ b/patches/Tuinity/patches/server/0009-Delay-chunk-unloads.patch
@@ -247,7 +247,7 @@ index 5c789b25f1df2eae8ea8ceb4ba977ba336fe6d5e..ab0417b3897911ba29602d696f4842bf
return new TicketType<>(s, comparator, 0L);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
-index d86c25593db7cc0a73db1c37af94ae4e41bb4e93..02b5547e53f6a2c4bdfffa96c6f70d74416a7d40 100644
+index 22eba9372d334c65d009721e808c958dfc271308..a5e2c7924580489c19e7c80536feb0f96df55d71 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -504,6 +504,7 @@ public class CraftWorld implements World {
diff --git a/patches/Tuinity/patches/server/0013-Per-World-Spawn-Limits.patch b/patches/Tuinity/patches/server/0013-Per-World-Spawn-Limits.patch
index f06c0397b..88bed5679 100644
--- a/patches/Tuinity/patches/server/0013-Per-World-Spawn-Limits.patch
+++ b/patches/Tuinity/patches/server/0013-Per-World-Spawn-Limits.patch
@@ -34,7 +34,7 @@ index 994c735958dc0ee0dfd8c28820fcd4f50057aad0..a302cda14aa2dd6550cca03b07be21cd
}
\ No newline at end of file
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
-index 02b5547e53f6a2c4bdfffa96c6f70d74416a7d40..61c0ea8ec08c08793ddffd4a7fa84c29a75185fc 100644
+index a5e2c7924580489c19e7c80536feb0f96df55d71..506d14966fd8fd91fa26274537a2cb7b5bb9fdf1 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -341,6 +341,14 @@ public class CraftWorld implements World {
diff --git a/patches/Tuinity/patches/server/0014-Detail-more-information-in-watchdog-dumps.patch b/patches/Tuinity/patches/server/0014-Detail-more-information-in-watchdog-dumps.patch
index dc148309c..719f3bd85 100644
--- a/patches/Tuinity/patches/server/0014-Detail-more-information-in-watchdog-dumps.patch
+++ b/patches/Tuinity/patches/server/0014-Detail-more-information-in-watchdog-dumps.patch
@@ -7,7 +7,7 @@ Subject: [PATCH] Detail more information in watchdog dumps
- Dump player name, player uuid, position, and world for packet handling
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
-index 5c8dd000af238ea703c9f84a4621472f17955060..c9b6fc731f478976466972a4bdc5002e0d704b35 100644
+index 0b25e0a4d050e77fa2fabd4e389d4ce693431aca..7690b5a8b0c595d664f88d161f5da7932d9fa034 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -599,7 +599,39 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
diff --git a/patches/Tuinity/patches/server/0021-Optimise-entity-hard-collision-checking.patch b/patches/Tuinity/patches/server/0021-Optimise-entity-hard-collision-checking.patch
index 1b80035bd..5d697967f 100644
--- a/patches/Tuinity/patches/server/0021-Optimise-entity-hard-collision-checking.patch
+++ b/patches/Tuinity/patches/server/0021-Optimise-entity-hard-collision-checking.patch
@@ -11,7 +11,7 @@ Less crammed entities are likely to show significantly less benefit.
Effectively, this patch optimises crammed entity situations.
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
-index 8816d3326af25431e2235c5e735e86c7335f60dc..2e25102b6d7e71b0a536e77c2116981aed8623e2 100644
+index 3bcd63a754538ccfc5965207a8fc79faa31925c0..dface62144bb230c576e9eafad1016d19d211118 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -91,6 +91,56 @@ public class Chunk implements IChunkAccess {
@@ -90,7 +90,7 @@ index 8816d3326af25431e2235c5e735e86c7335f60dc..2e25102b6d7e71b0a536e77c2116981a
}
if (entity instanceof EntityItem) {
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
-index c9b6fc731f478976466972a4bdc5002e0d704b35..6548ffe332460e66409b345bae2f5222d32cec71 100644
+index 7690b5a8b0c595d664f88d161f5da7932d9fa034..eff1f15e0e776f987e692505abb28a3c7998e883 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -230,6 +230,41 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
diff --git a/patches/Tuinity/patches/server/0025-Highly-optimise-single-and-multi-AABB-VoxelShapes-an.patch b/patches/Tuinity/patches/server/0025-Highly-optimise-single-and-multi-AABB-VoxelShapes-an.patch
index 79ed55314..d4a862e96 100644
--- a/patches/Tuinity/patches/server/0025-Highly-optimise-single-and-multi-AABB-VoxelShapes-an.patch
+++ b/patches/Tuinity/patches/server/0025-Highly-optimise-single-and-multi-AABB-VoxelShapes-an.patch
@@ -614,7 +614,7 @@ index 95ef96286855624590b72d69514b0fc0e08fddba..73163b417af7e522a4509bf9c1ab56d6
T t0 = this.h.a(this.a.a(i));
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
-index 6548ffe332460e66409b345bae2f5222d32cec71..9287ab8e861a97fc4b132e46163b050a9ae52ced 100644
+index eff1f15e0e776f987e692505abb28a3c7998e883..fc2c4d127ec2eecfcec681fbe9599b72b09b078a 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -136,7 +136,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
diff --git a/patches/Tuinity/patches/server/0031-Revert-getChunkAt-Async-retaining-chunks-for-long-pe.patch b/patches/Tuinity/patches/server/0031-Revert-getChunkAt-Async-retaining-chunks-for-long-pe.patch
index f7870c115..29c16a9c6 100644
--- a/patches/Tuinity/patches/server/0031-Revert-getChunkAt-Async-retaining-chunks-for-long-pe.patch
+++ b/patches/Tuinity/patches/server/0031-Revert-getChunkAt-Async-retaining-chunks-for-long-pe.patch
@@ -6,7 +6,7 @@ Subject: [PATCH] Revert getChunkAt(Async) retaining chunks for long periods of
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
-index 61c0ea8ec08c08793ddffd4a7fa84c29a75185fc..545a8bcf16215bde467d39881b19486bee7db873 100644
+index 506d14966fd8fd91fa26274537a2cb7b5bb9fdf1..20b0b7d9ad095622fa7ad6dd02c4c3f248672cf0 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -422,14 +422,7 @@ public class CraftWorld implements World {
@@ -25,7 +25,7 @@ index 61c0ea8ec08c08793ddffd4a7fa84c29a75185fc..545a8bcf16215bde467d39881b19486b
}
// Paper start
-@@ -2571,7 +2564,7 @@ public class CraftWorld implements World {
+@@ -2576,7 +2569,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);
diff --git a/patches/Tuinity/patches/server/0046-Optimise-closest-entity-lookup-used-by-AI-goals.patch b/patches/Tuinity/patches/server/0046-Optimise-closest-entity-lookup-used-by-AI-goals.patch
index 0c57b18dd..3d5b01a44 100644
--- a/patches/Tuinity/patches/server/0046-Optimise-closest-entity-lookup-used-by-AI-goals.patch
+++ b/patches/Tuinity/patches/server/0046-Optimise-closest-entity-lookup-used-by-AI-goals.patch
@@ -240,7 +240,7 @@ index 387eeb5d770ba9fe564c61df8cc92ac8b1569f61..21e50c75e0bffaa5cc5faf6aa81ae742
}
}
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
-index 2e25102b6d7e71b0a536e77c2116981aed8623e2..8c6c653b3454f59cf823fd92f7b464a8f998b675 100644
+index dface62144bb230c576e9eafad1016d19d211118..cd4a36a2f0feb2df928ee5ed7f0bca6d996bad7f 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -141,6 +141,22 @@ public class Chunk implements IChunkAccess {
diff --git a/patches/Tuinity/patches/server/0047-Optimise-EntityInsentient-checkDespawn.patch b/patches/Tuinity/patches/server/0047-Optimise-EntityInsentient-checkDespawn.patch
index 43a9bb0ad..9568a5dd1 100644
--- a/patches/Tuinity/patches/server/0047-Optimise-EntityInsentient-checkDespawn.patch
+++ b/patches/Tuinity/patches/server/0047-Optimise-EntityInsentient-checkDespawn.patch
@@ -9,7 +9,7 @@ since the penalty of a map lookup could outweigh the benefits of
searching less players (as it basically did in the outside range patch).
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
-index 8c6c653b3454f59cf823fd92f7b464a8f998b675..781d74cf7e3669d71727cce781a8f8ce088c5547 100644
+index cd4a36a2f0feb2df928ee5ed7f0bca6d996bad7f..9ea915101379913cf36b123088af3dfa9833c4ff 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -157,6 +157,85 @@ public class Chunk implements IChunkAccess {
diff --git a/patches/Tuinity/patches/server/0048-Remove-streams-for-villager-AI.patch b/patches/Tuinity/patches/server/0048-Remove-streams-for-villager-AI.patch
index 2a7b5e179..bb1ccbd1e 100644
--- a/patches/Tuinity/patches/server/0048-Remove-streams-for-villager-AI.patch
+++ b/patches/Tuinity/patches/server/0048-Remove-streams-for-villager-AI.patch
@@ -462,7 +462,7 @@ index a33303c31881b6391723e16a06d7841d48679958..ce57e6a4acac97d6da82202094306e7e
return this.b.equals(entityliving.getEntityType()) && this.d.test(entityliving);
}
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
-index 9287ab8e861a97fc4b132e46163b050a9ae52ced..3ad523b8ff4d5954cafb0dd71950262d83b04e8f 100644
+index fc2c4d127ec2eecfcec681fbe9599b72b09b078a..630fb7784be996d4503a81fc20a6c7f65a10e7dd 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -1589,6 +1589,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
diff --git a/patches/Tuinity/patches/server/0054-Do-not-load-chunks-during-a-crash-report.patch b/patches/Tuinity/patches/server/0054-Do-not-load-chunks-during-a-crash-report.patch
index af9946f53..871edb8f8 100644
--- a/patches/Tuinity/patches/server/0054-Do-not-load-chunks-during-a-crash-report.patch
+++ b/patches/Tuinity/patches/server/0054-Do-not-load-chunks-during-a-crash-report.patch
@@ -22,7 +22,7 @@ index 7511e38130f38703164395a670f12d1af648ff04..e602efcb3fad390bb6bff1055e782bba
}
value.append("},");
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
-index 545a8bcf16215bde467d39881b19486bee7db873..f34e1570052eac83fb3e03b3e361d8d4f451abac 100644
+index 20b0b7d9ad095622fa7ad6dd02c4c3f248672cf0..15ce459aa15a8bb936740a8c055f4304e21312d2 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -719,6 +719,30 @@ public class CraftWorld implements World {
diff --git a/patches/Tuinity/patches/server/0056-Copy-passenger-list-in-enderTeleportTo.patch b/patches/Tuinity/patches/server/0056-Copy-passenger-list-in-enderTeleportTo.patch
index 38f84efd7..df5e8f846 100644
--- a/patches/Tuinity/patches/server/0056-Copy-passenger-list-in-enderTeleportTo.patch
+++ b/patches/Tuinity/patches/server/0056-Copy-passenger-list-in-enderTeleportTo.patch
@@ -6,7 +6,7 @@ Subject: [PATCH] Copy passenger list in enderTeleportTo
Fixes https://github.com/Spottedleaf/Tuinity/issues/208
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
-index 3ad523b8ff4d5954cafb0dd71950262d83b04e8f..013c44f80f74376e8bbb37afb5de07aa5d8fb1bc 100644
+index 630fb7784be996d4503a81fc20a6c7f65a10e7dd..2b76b5a70280def08f239ff387407a9d328d484c 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -3084,7 +3084,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
diff --git a/patches/Tuinity/patches/server/0061-Rewrite-the-light-engine.patch b/patches/Tuinity/patches/server/0061-Rewrite-the-light-engine.patch
index 4f5a79098..dd99ecc9c 100644
--- a/patches/Tuinity/patches/server/0061-Rewrite-the-light-engine.patch
+++ b/patches/Tuinity/patches/server/0061-Rewrite-the-light-engine.patch
@@ -4216,7 +4216,7 @@ index 2760b377d1f68ac5f66e7274317379e2dda8288a..829d4a7508e1656dbdc912096b7eafcf
protected final boolean c;
private final boolean[] j;
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
-index 781d74cf7e3669d71727cce781a8f8ce088c5547..ae07ea2a34f5cd82ce2eae523359cb7540065335 100644
+index 9ea915101379913cf36b123088af3dfa9833c4ff..68d6fb69a0c1b98b3c11b6d80783faaa58272526 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -140,6 +140,52 @@ public class Chunk implements IChunkAccess {
diff --git a/patches/api/0005-Add-NBT-API-as-a-first-class-lib.patch b/patches/api/0005-Add-NBT-API-as-a-first-class-lib.patch
index 780643c85..f71770d1f 100644
--- a/patches/api/0005-Add-NBT-API-as-a-first-class-lib.patch
+++ b/patches/api/0005-Add-NBT-API-as-a-first-class-lib.patch
@@ -98,12 +98,12 @@ index 3b10fcc13893403b29f0260b8605144679e89b82..1e9a96d8b08cc396acf73dc420830093
+ // Yatopia end
}
diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java
-index 08dbe8208fad174f03a0e08c26bb48a0729ec0ce..d83e9814878ff185e659dfaabc2175d1577db0e1 100644
+index 2b7e8c7f24b2d9dd49db901f6279b8b5930a3006..04f7fedc8ab4aaf35bbe5c028b87c9fd9f235867 100644
--- a/src/main/java/org/bukkit/entity/Entity.java
+++ b/src/main/java/org/bukkit/entity/Entity.java
-@@ -746,4 +746,26 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
+@@ -765,4 +765,26 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
*/
- boolean isRidableInWater();
+ boolean spawnAt(@NotNull Location location, @NotNull org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason);
// Purpur end
+
+ // Yatopia start
diff --git a/patches/server/0002-Brandings.patch b/patches/server/0002-Brandings.patch
index f6ad752df..ed71e8b35 100644
--- a/patches/server/0002-Brandings.patch
+++ b/patches/server/0002-Brandings.patch
@@ -79,7 +79,7 @@ index 448538cc8a3d16b028a0a6f0f05c9370a02f4259..e51dcb259d511c369806a83b96c2820f
//Thread.sleep(TimeUnit.SECONDS.toMillis(20));
// Paper End
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
-index 37c561fb775cf7dd955b185b4ea94fecc574be63..9ef99b4a9e2a648a9245cfae70d12645a15fb12c 100644
+index 821b8665b4ed70c010a0824df99de2667fd4c8ba..939469fa77fad724243abc4d75cba3ae2dd01fcf 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
@@ -370,7 +370,7 @@ public final class CraftMagicNumbers implements UnsafeValues {
diff --git a/patches/server/0024-Fix-lead-fall-dmg-config.patch b/patches/server/0024-Fix-lead-fall-dmg-config.patch
index 7a18af7be..fe39b14bd 100644
--- a/patches/server/0024-Fix-lead-fall-dmg-config.patch
+++ b/patches/server/0024-Fix-lead-fall-dmg-config.patch
@@ -5,7 +5,7 @@ Subject: [PATCH] Fix lead fall dmg config
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
-index d74086ee72cfae3d2bead9fb08c808299d755e2a..48224c50293ff34f163724fa9d1d54c9bcfb2321 100644
+index 0fe4c8f9c669f343fef3e2869f22b46d8ef7136b..275d730601c4a60c4bd74eb5e5db52a58b1e2be7 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -1290,6 +1290,8 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
diff --git a/patches/server/0060-Port-hydrogen.patch b/patches/server/0060-Port-hydrogen.patch
index ec535658a..dc19e3cfd 100644
--- a/patches/server/0060-Port-hydrogen.patch
+++ b/patches/server/0060-Port-hydrogen.patch
@@ -336,7 +336,7 @@ index 0000000000000000000000000000000000000000..a5314a0396f4a8f373d855e873820ddd
+ }
+}
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
-index 4732320d973d89bda2cd2a94db48bc6c98df3e9d..d9ff68765dd1d14615ca6119cb1906249e95d426 100644
+index fa1d559a07199bf52d8ae04b2c34261efdebdcdb..a3c86e6b56f744b340bc486b9d728114f884d28f 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -337,6 +337,14 @@ public class Chunk implements IChunkAccess {
diff --git a/test.txt b/test.txt
new file mode 100644
index 000000000..8344fee51
--- /dev/null
+++ b/test.txt
@@ -0,0 +1,325 @@
+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 e7624948e..a263cd7a0 100644
+--- a/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java
++++ b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java
+@@ -186,6 +186,7 @@ public final class PaperTickList extends TickListServer { // extend to avo
+ }
+
+ 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
+ protected void nextTick() {
++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("async tick list tick"); // Tuinity - soft async catcher
+ ++this.currentTick;
+ if (this.currentTick != this.world.getTime()) {
+ if (!this.warnedAboutDesync) {
+@@ -280,6 +282,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");
+@@ -424,6 +427,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;
+@@ -479,6 +483,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
+ }
+@@ -535,6 +540,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();
+@@ -554,6 +560,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
+@@ -585,6 +592,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);
+
+@@ -594,6 +602,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
+index 20150ad07..cae06962d 100644
+--- a/src/main/java/com/tuinity/tuinity/chunk/SingleThreadChunkRegionManager.java
++++ b/src/main/java/com/tuinity/tuinity/chunk/SingleThreadChunkRegionManager.java
+@@ -162,6 +162,7 @@ public final class SingleThreadChunkRegionManager & SingleThre
+ }
+
+ public void addChunk(final int chunkX, final int chunkZ) {
++ com.tuinity.tuinity.util.TickThread.ensureTickThread("async region manager add chunk"); // Tuinity
+ this.addChunkTimings.startTiming();
+ try {
+ this.getOrCreateAndMergeSection(chunkX >> REGION_CHUNK_SIZE_SHIFT, chunkZ >> REGION_CHUNK_SIZE_SHIFT, null).addChunk(chunkX, chunkZ);
+@@ -171,6 +172,7 @@ public final class SingleThreadChunkRegionManager & SingleThre
+ }
+
+ public void removeChunk(final int chunkX, final int chunkZ) {
++ com.tuinity.tuinity.util.TickThread.ensureTickThread("async region manager remove chunk"); // Tuinity
+ this.removeChunkTimings.startTiming();
+ try {
+ final RegionSection section = this.regionsBySection.get(
+@@ -187,6 +189,7 @@ public final class SingleThreadChunkRegionManager & SingleThre
+ }
+
+ public void recalculateRegions() {
++ com.tuinity.tuinity.util.TickThread.ensureTickThread("async region recalculation"); // Tuinity
+ for (int i = 0, len = this.needsRecalculation.size(); i < len; ++i) {
+ final Region region = this.needsRecalculation.removeFirst();
+
+diff --git a/src/main/java/com/tuinity/tuinity/util/TickThread.java b/src/main/java/com/tuinity/tuinity/util/TickThread.java
+index 033548a58..08ed24325 100644
+--- a/src/main/java/com/tuinity/tuinity/util/TickThread.java
++++ b/src/main/java/com/tuinity/tuinity/util/TickThread.java
+@@ -1,7 +1,33 @@
+ 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) {
+diff --git a/src/main/java/net/minecraft/server/ChunkMapDistance.java b/src/main/java/net/minecraft/server/ChunkMapDistance.java
+index 76f9bb728..84ff9cfe8 100644
+--- a/src/main/java/net/minecraft/server/ChunkMapDistance.java
++++ b/src/main/java/net/minecraft/server/ChunkMapDistance.java
+@@ -65,6 +65,7 @@ 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();
+
+@@ -98,6 +99,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();
+@@ -370,6 +372,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 +390,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 +401,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);
+ if (objectset == null) return; // CraftBukkit - SPIGOT-6208
+@@ -447,6 +452,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 a4bbf3d95..a61a9e71c 100644
+--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
++++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
+@@ -1190,6 +1190,7 @@ public class ChunkProviderServer extends IChunkProvider {
+
+ @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/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/EntityTrackerEntry.java
+index 3960a975e..526c1419a 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/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
+index fb46fdeb2..2be8c1b79 100644
+--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
++++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
+@@ -200,6 +200,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
+@@ -230,6 +231,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);
+@@ -247,6 +249,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
+@@ -774,6 +777,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 {
+@@ -1081,6 +1085,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 {
+@@ -1520,6 +1525,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) {
+@@ -1533,6 +1539,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;
+diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
+index 8efdd9bd0..43b5fa67a 100644
+--- a/src/main/java/net/minecraft/server/World.java
++++ b/src/main/java/net/minecraft/server/World.java
+@@ -363,6 +363,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
+
+ @Override
+ public boolean a(BlockPosition blockposition, IBlockData iblockdata, int i, int j) {
++ org.spigotmc.AsyncCatcher.catchOp("set type call"); // Tuinity
+ // CraftBukkit start - tree generation
+ if (this.captureTreeGeneration) {
+ // Paper start
+@@ -464,6 +465,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
+
+ // CraftBukkit start - Split off from above in order to directly send client and physic updates
+ public void notifyAndUpdatePhysics(BlockPosition blockposition, Chunk chunk, IBlockData oldBlock, IBlockData newBlock, IBlockData actualBlock, int i, int j) {
++ com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Async notify and update"); // Tuinity
+ IBlockData iblockdata = newBlock;
+ IBlockData iblockdata1 = oldBlock;
+ IBlockData iblockdata2 = actualBlock;
+diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
+index 2abce373f..bc3248603 100644
+--- a/src/main/java/net/minecraft/server/WorldServer.java
++++ b/src/main/java/net/minecraft/server/WorldServer.java
+@@ -1661,6 +1661,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
+
+ @Override
+ public void notify(BlockPosition blockposition, IBlockData iblockdata, IBlockData iblockdata1, int i) {
++ org.spigotmc.AsyncCatcher.catchOp("notify call"); // Tuinity
+ this.getChunkProvider().flagDirty(blockposition);
+ if(this.paperConfig.updatePathfindingOnBlockUpdate) { // Paper - option to disable pathfinding updates
+ VoxelShape voxelshape = iblockdata.getCollisionShape(this, blockposition);
+diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java
+index 10606ed03..51e9c54cd 100644
+--- a/src/main/java/org/spigotmc/AsyncCatcher.java
++++ b/src/main/java/org/spigotmc/AsyncCatcher.java
+@@ -10,8 +10,9 @@ public class AsyncCatcher
+
+ public static void catchOp(String reason)
+ {
+- if ( enabled && !org.bukkit.Bukkit.isPrimaryThread() ) // Tuinity
++ if ( ( enabled || com.tuinity.tuinity.util.TickThread.STRICT_THREAD_CHECKS ) && !org.bukkit.Bukkit.isPrimaryThread() ) // Tuinity
+ {
++ MinecraftServer.LOGGER.fatal("Thread " + Thread.currentThread().getName() + " failed thread check for reason: Asynchronous " + reason, new Throwable()); // Tuinity - not all exceptions are printed
+ throw new IllegalStateException( "Asynchronous " + reason + "!" );
+ }
+ }
diff --git a/upstream/Purpur b/upstream/Purpur
index be941d842..9537c770b 160000
--- a/upstream/Purpur
+++ b/upstream/Purpur
@@ -1 +1 @@
-Subproject commit be941d8428321bc535121848f95d0236a1953271
+Subproject commit 9537c770b0820b8b7a9915a7d571de528dc5ce8c
diff --git a/upstreamCommits/Purpur b/upstreamCommits/Purpur
index d939d8bfb..3fd50d31f 100644
--- a/upstreamCommits/Purpur
+++ b/upstreamCommits/Purpur
@@ -1 +1 @@
-be941d8428321bc535121848f95d0236a1953271
\ No newline at end of file
+9537c770b0820b8b7a9915a7d571de528dc5ce8c
\ No newline at end of file