From 444a2c665002198a55a9adc7350783543b61bc0d Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 19 Jun 2021 19:42:43 -0500 Subject: [PATCH] progress --- ...-check-to-EntityDamagedByEntityEvent.patch | 2 +- patches/api/0029-Left-handed-API.patch | 2 +- ...030-Alphabetize-in-game-plugins-list.patch | 2 +- ...oc-warnings-missing-param-and-return.patch | 2 +- .../api/0033-PlayerBookTooLargeEvent.patch | 2 +- ...therite-armor-grants-fire-resistance.patch | 2 +- ...on-change-for-adventure-deprecations.patch | 2 +- ...ntment-target-for-bows-and-crossbows.patch | 2 +- .../0040-Iron-golem-poppy-calms-anger.patch | 2 +- patches/server-unmapped/0001-Ridables.patch | 7069 ----------------- ...-Configurable-entity-base-attributes.patch | 2655 ------- ...34-Changeable-Mob-Left-Handed-Chance.patch | 34 - .../0141-Lobotomize-stuck-villagers.patch | 2 +- .../0148-Phantom-flames-on-swoop.patch | 2 +- .../0150-Implement-TPSBar.patch | 2 +- .../0152-PlayerBookTooLargeEvent.patch | 2 +- ...therite-armor-grants-fire-resistance.patch | 2 +- ...0154-Fix-rotating-UP-DOWN-CW-and-CCW.patch | 2 +- .../0155-Add-MC-4-fix-back.patch | 2 +- .../0162-Fix-stuck-in-portals.patch | 2 +- ...0168-Add-ghast-allow-griefing-option.patch | 2 +- ...0172-Add-config-for-snow-on-blue-ice.patch | 2 +- .../0177-Tick-fluids-config.patch | 2 +- ...urable-ravager-griefable-blocks-list.patch | 2 +- ...0181-Sneak-to-bulk-process-composter.patch | 2 +- ...Break-individual-slabs-when-sneaking.patch | 2 +- ...ption-to-make-doors-require-redstone.patch | 2 +- .../0194-Piglin-portal-spawn-modifier.patch | 2 +- .../0199-Gamemode-extra-permissions.patch | 2 +- .../0203-Fix-SPIGOT-6278.patch | 2 +- ...-hidden-players-from-entity-selector.patch | 2 +- .../0207-Iron-golem-poppy-calms-anger.patch | 2 +- .../0208-Breedable-parrots.patch | 2 +- ...on-to-disable-dragon-egg-teleporting.patch | 2 +- ...14-ShulkerBox-allow-oversized-stacks.patch | 2 +- ...advancement-triggers-on-entity-death.patch | 2 +- .../0220-Add-toggle-for-sand-duping-fix.patch | 2 +- ...ggle-for-end-portal-safe-teleporting.patch | 2 +- patches/server/0003-Ridables.patch | 4 +- ...-Configurable-entity-base-attributes.patch | 6 +- .../0067-Add-canSaveToDisk-to-Entity.patch | 48 + patches/server/0074-Add-ping-command.patch | 8 +- patches/server/0075-Add-demo-command.patch | 8 +- ...stomizable-wither-health-and-healing.patch | 4 +- ...justable-breeding-cooldown-to-config.patch | 4 +- ...e-entity-breeding-times-configurable.patch | 4 +- ...mes-from-item-forms-of-entities-to-e.patch | 4 +- ...-when-using-a-Name-Tag-on-an-Armor-S.patch | 4 +- ...sting-and-weeping-vines-growth-rates.patch | 4 +- ...-twisting-vines-configurable-max-gro.patch | 4 +- ...llowing-Endermen-to-despawn-even-whi.patch | 6 +- ...-check-to-EntityDamagedByEntityEvent.patch | 4 +- ...127-Add-configurable-snowball-damage.patch | 4 +- ...break-door-minimum-difficulty-option.patch | 4 +- patches/server/0129-Left-handed-API.patch | 4 +- ...30-Changeable-Mob-Left-Handed-Chance.patch | 34 + .../0131-Add-boat-fall-damage-config.patch} | 32 +- .../0132-Snow-Golem-rate-of-fire-config.patch | 50 + 58 files changed, 222 insertions(+), 9846 deletions(-) delete mode 100644 patches/server-unmapped/0001-Ridables.patch delete mode 100644 patches/server-unmapped/0002-Configurable-entity-base-attributes.patch delete mode 100644 patches/server-unmapped/0134-Changeable-Mob-Left-Handed-Chance.patch create mode 100644 patches/server/0130-Changeable-Mob-Left-Handed-Chance.patch rename patches/{server-unmapped/0135-Add-boat-fall-damage-config.patch => server/0131-Add-boat-fall-damage-config.patch} (55%) create mode 100644 patches/server/0132-Snow-Golem-rate-of-fire-config.patch diff --git a/patches/api/0028-Add-critical-hit-check-to-EntityDamagedByEntityEvent.patch b/patches/api/0028-Add-critical-hit-check-to-EntityDamagedByEntityEvent.patch index ebfe2021e..0a0b7c812 100644 --- a/patches/api/0028-Add-critical-hit-check-to-EntityDamagedByEntityEvent.patch +++ b/patches/api/0028-Add-critical-hit-check-to-EntityDamagedByEntityEvent.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Tue, 24 Nov 2020 04:30:34 -0600 Subject: [PATCH] Add critical hit check to EntityDamagedByEntityEvent diff --git a/patches/api/0029-Left-handed-API.patch b/patches/api/0029-Left-handed-API.patch index 5e8b1e020..1abf1a651 100644 --- a/patches/api/0029-Left-handed-API.patch +++ b/patches/api/0029-Left-handed-API.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Mon, 30 Nov 2020 06:02:54 -0600 Subject: [PATCH] Left handed API diff --git a/patches/api/0030-Alphabetize-in-game-plugins-list.patch b/patches/api/0030-Alphabetize-in-game-plugins-list.patch index 0e1b879bb..d10192b17 100644 --- a/patches/api/0030-Alphabetize-in-game-plugins-list.patch +++ b/patches/api/0030-Alphabetize-in-game-plugins-list.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Tue, 8 Dec 2020 09:48:18 -0600 Subject: [PATCH] Alphabetize in-game /plugins list diff --git a/patches/api/0032-Fix-javadoc-warnings-missing-param-and-return.patch b/patches/api/0032-Fix-javadoc-warnings-missing-param-and-return.patch index f68220a3d..daa784f3a 100644 --- a/patches/api/0032-Fix-javadoc-warnings-missing-param-and-return.patch +++ b/patches/api/0032-Fix-javadoc-warnings-missing-param-and-return.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Fri, 18 Dec 2020 21:21:48 -0600 Subject: [PATCH] Fix javadoc warnings (missing @param and @return) diff --git a/patches/api/0033-PlayerBookTooLargeEvent.patch b/patches/api/0033-PlayerBookTooLargeEvent.patch index dc89fde7d..3fe0eab33 100644 --- a/patches/api/0033-PlayerBookTooLargeEvent.patch +++ b/patches/api/0033-PlayerBookTooLargeEvent.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Wed, 23 Dec 2020 00:43:27 -0600 Subject: [PATCH] PlayerBookTooLargeEvent diff --git a/patches/api/0034-Full-netherite-armor-grants-fire-resistance.patch b/patches/api/0034-Full-netherite-armor-grants-fire-resistance.patch index 266d29fac..08279d395 100644 --- a/patches/api/0034-Full-netherite-armor-grants-fire-resistance.patch +++ b/patches/api/0034-Full-netherite-armor-grants-fire-resistance.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Thu, 24 Dec 2020 11:00:04 -0600 Subject: [PATCH] Full netherite armor grants fire resistance diff --git a/patches/api/0038-Conflict-on-change-for-adventure-deprecations.patch b/patches/api/0038-Conflict-on-change-for-adventure-deprecations.patch index 06092aab7..68275c11a 100644 --- a/patches/api/0038-Conflict-on-change-for-adventure-deprecations.patch +++ b/patches/api/0038-Conflict-on-change-for-adventure-deprecations.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Wed, 17 Mar 2021 15:56:47 -0500 Subject: [PATCH] Conflict on change for adventure deprecations diff --git a/patches/api/0039-Add-enchantment-target-for-bows-and-crossbows.patch b/patches/api/0039-Add-enchantment-target-for-bows-and-crossbows.patch index d30cd0043..c166b9889 100644 --- a/patches/api/0039-Add-enchantment-target-for-bows-and-crossbows.patch +++ b/patches/api/0039-Add-enchantment-target-for-bows-and-crossbows.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Tue, 23 Mar 2021 15:01:03 -0500 Subject: [PATCH] Add enchantment target for bows and crossbows diff --git a/patches/api/0040-Iron-golem-poppy-calms-anger.patch b/patches/api/0040-Iron-golem-poppy-calms-anger.patch index 2d172aa5a..1b8614c58 100644 --- a/patches/api/0040-Iron-golem-poppy-calms-anger.patch +++ b/patches/api/0040-Iron-golem-poppy-calms-anger.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Thu, 13 May 2021 21:38:01 -0500 Subject: [PATCH] Iron golem poppy calms anger diff --git a/patches/server-unmapped/0001-Ridables.patch b/patches/server-unmapped/0001-Ridables.patch deleted file mode 100644 index 515fb5084..000000000 --- a/patches/server-unmapped/0001-Ridables.patch +++ /dev/null @@ -1,7069 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 5 Jul 2020 22:19:49 -0500 -Subject: [PATCH] Ridables - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 6afff6ba0c59e3285c99fddf3de738d95153ed24..5c5da6e2be6d3a0ca2fee4e0a5510ccb15fa8020 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1482,6 +1482,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0; // Paper - worldserver.hasEntityMoveEvent = EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper -+ worldserver.hasRidableMoveEvent = net.pl3x.purpur.event.entity.RidableMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Purpur - TileEntityHopper.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - - this.methodProfiler.a(() -> { -diff --git a/src/main/java/net/minecraft/server/PathfinderGoalHasRider.java b/src/main/java/net/minecraft/server/PathfinderGoalHasRider.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4c5dd9431b9afb2f110228d058d2b0f0808f0ab9 ---- /dev/null -+++ b/src/main/java/net/minecraft/server/PathfinderGoalHasRider.java -@@ -0,0 +1,21 @@ -+package net.minecraft.server; -+ -+import net.minecraft.world.entity.EntityInsentient; -+import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+ -+import java.util.EnumSet; -+ -+public class PathfinderGoalHasRider extends PathfinderGoal { -+ public final EntityInsentient entity; -+ -+ public PathfinderGoalHasRider(EntityInsentient entity) { -+ this.entity = entity; -+ setTypes(EnumSet.of(Type.JUMP, Type.MOVE, Type.LOOK, Type.TARGET, Type.UNKNOWN_BEHAVIOR)); -+ } -+ -+ // shouldExecute -+ @Override -+ public boolean a() { -+ return entity.hasPurpurRider(); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/PathfinderGoalHorseHasRider.java b/src/main/java/net/minecraft/server/PathfinderGoalHorseHasRider.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8b66d1215a6eef1302b5ecb46a4b3d502846fef8 ---- /dev/null -+++ b/src/main/java/net/minecraft/server/PathfinderGoalHorseHasRider.java -@@ -0,0 +1,18 @@ -+package net.minecraft.server; -+ -+import net.minecraft.world.entity.animal.horse.EntityHorseAbstract; -+ -+public class PathfinderGoalHorseHasRider extends PathfinderGoalHasRider { -+ private final EntityHorseAbstract horse; -+ -+ public PathfinderGoalHorseHasRider(EntityHorseAbstract entity) { -+ super(entity); -+ this.horse = entity; -+ } -+ -+ // shouldExecute -+ @Override -+ public boolean a() { -+ return super.a() && horse.hasSaddle(); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 996ff0b36379f18af7c68b4c50ea291fe8091970..16b192f251374a477e9696581672515959338d7b 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -80,7 +80,6 @@ import net.minecraft.server.network.PlayerConnection; - import net.minecraft.server.players.PlayerList; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffect; --import net.minecraft.stats.RecipeBook; - import net.minecraft.stats.RecipeBookServer; - import net.minecraft.stats.ServerStatisticManager; - import net.minecraft.stats.Statistic; -@@ -132,7 +131,6 @@ import net.minecraft.world.level.block.entity.TileEntityCommand; - import net.minecraft.world.level.block.entity.TileEntitySign; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.portal.ShapeDetectorShape; --import net.minecraft.world.level.storage.WorldData; - import net.minecraft.world.phys.AxisAlignedBB; - import net.minecraft.world.phys.Vec3D; - import net.minecraft.world.scores.ScoreboardScore; -@@ -652,6 +650,15 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - - this.advancementDataPlayer.b(this); -+ -+ // Purpur start -+ if (this.world.purpurConfig.useNightVisionWhenRiding && this.getVehicle() != null && this.getVehicle().getPurpurRider() == this && world.getTime() % 100 == 0) { // 5 seconds -+ MobEffect nightVision = this.getEffect(MobEffects.NIGHT_VISION); -+ if (nightVision == null || nightVision.getDuration() <= 300) { // 15 seconds -+ this.addEffect(new MobEffect(MobEffects.NIGHT_VISION, 400, 0)); // 20 seconds -+ } -+ } -+ // Purpur end - } - - public void playerTick() { -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 74245e7f73f69ea843754102b81b26b87c2dc3c8..a83324f1f4479b5807f7f335b7e63ba1f6bcb057 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -215,6 +215,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - public final UUID uuid; - public boolean hasPhysicsEvent = true; // Paper - public boolean hasEntityMoveEvent = false; // Paper -+ public boolean hasRidableMoveEvent = false; // Purpur - private static Throwable getAddToWorldStackTrace(Entity entity) { - return new Throwable(entity + " Added to world at " + new java.util.Date()); - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index f92e412d7f49c620699274ecf9ed085c5af53ab8..dc830f1e23b6eb81d47e111e3f4d8d19010b4c9f 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -2399,6 +2399,8 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - this.server.getPluginManager().callEvent(event); - -+ player.processClick(enumhand); // Purpur -+ - // Fish bucket - SPIGOT-4048 - if ((entity instanceof EntityFish && origItem != null && origItem.getItem() == Items.WATER_BUCKET) && (event.isCancelled() || this.player.inventory.getItemInHand() == null || this.player.inventory.getItemInHand().getItem() != origItem)) { - this.sendPacket(new PacketPlayOutSpawnEntityLiving((EntityFish) entity)); -diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java -index e6bf78f46acc37d9515d58cec3587e236ac0733c..5842d23a536449d0c394c7b23ee0cef3d54d8dff 100644 ---- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java -+++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java -@@ -67,6 +67,7 @@ public class DamageSource { - return new EntityDamageSource("mob", entityliving); - } - -+ public static DamageSource indirectMobAttack(Entity entity, EntityLiving entityliving) { return a(entity, entityliving); } // Purpur - OBFHELPER - public static DamageSource a(Entity entity, EntityLiving entityliving) { - return new EntityDamageSourceIndirect("mob", entity, entityliving); - } -@@ -128,6 +129,7 @@ public class DamageSource { - return this.B; - } - -+ public DamageSource setProjectile() { return c(); } // Purpur - OBFHELPER - public DamageSource c() { - this.B = true; - return this; -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0ea8e9a4828689fa1f013590285a65a9841325b7..3bbc9d154215437e3db98ad0d10ce43712a70485 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -22,6 +22,7 @@ import net.minecraft.BlockUtil; - import net.minecraft.CrashReport; - import net.minecraft.CrashReportSystemDetails; - import net.minecraft.ReportedException; -+import net.minecraft.SystemUtils; - import net.minecraft.advancements.CriterionTriggers; - import net.minecraft.commands.CommandListenerWrapper; - import net.minecraft.commands.ICommandListener; -@@ -104,7 +105,6 @@ import net.minecraft.world.phys.AxisAlignedBB; - import net.minecraft.world.phys.MovingObjectPosition; - import net.minecraft.world.phys.Vec2F; - import net.minecraft.world.phys.Vec3D; --import net.minecraft.world.phys.shapes.OperatorBoolean; - import net.minecraft.world.phys.shapes.VoxelShape; - import net.minecraft.world.phys.shapes.VoxelShapeCollision; - import net.minecraft.world.phys.shapes.VoxelShapes; -@@ -197,7 +197,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - private int id; - public boolean i; public final boolean blocksEntitySpawning() { return this.i; } // Paper - OBFHELPER - public final List passengers; -- protected int j; -+ protected int j; public int getRideCooldown() { return j; } // Purpur - OBFHELPER - @Nullable - private Entity vehicle; - public boolean attachedToPlayer; -@@ -213,7 +213,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public float lastYaw; - public float lastPitch; - private AxisAlignedBB boundingBox; -- protected boolean onGround; -+ public boolean onGround; // Purpur - protected -> public - public boolean positionChanged; - public boolean v; - public boolean velocityChanged; -@@ -269,7 +269,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - private boolean az; - private final double[] aA; - private long aB; -- private EntitySize size; -+ protected EntitySize size; // Purpur - private -> protected - private float headHeight; - // CraftBukkit start - public boolean persist = true; -@@ -1374,6 +1374,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return !this.justCreated && this.M.getDouble(TagsFluid.LAVA) > 0.0D; - } - -+ public void moveRelative(float speed, Vec3D motion) { this.a(speed, motion); } // Purpur - OBFHELPER - public void a(float f, Vec3D vec3d) { - Vec3D vec3d1 = a(vec3d, f, this.yaw); - -@@ -2132,6 +2133,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.a(entity, false); - } - -+ public boolean startRiding(Entity entity, boolean flag) { return a(entity, flag); } // Purpur - OBFHELPER - public boolean a(Entity entity, boolean flag) { - for (Entity entity1 = entity; entity1.vehicle != null; entity1 = entity1.vehicle) { - if (entity1.vehicle == this) { -@@ -2227,6 +2229,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.passengers.add(entity); - } - -+ // Purpur start -+ if (isRidable() && passengers.get(0) == entity && entity instanceof EntityHuman) { -+ EntityHuman entityhuman = (EntityHuman) entity; -+ onMount(entityhuman); -+ this.purpurRider = entityhuman; -+ } -+ // Purpur end - } - return true; // CraftBukkit - } -@@ -2267,6 +2276,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return false; - } - // Spigot end -+ // Purpur start -+ if (purpurRider != null && passengers.get(0) == purpurRider) { -+ onDismount(purpurRider); -+ this.purpurRider = null; -+ } -+ // Purpur end - this.passengers.remove(entity); - entity.j = 60; - } -@@ -2433,6 +2448,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.setFlag(4, flag); - } - -+ public boolean isGlowing() { return bE(); } // Purpur - OBFHELPER - public boolean bE() { - return this.glowing || this.world.isClientSide && this.getFlag(6); - } -@@ -2655,6 +2671,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - public void setHeadRotation(float f) {} - -+ public void setBodyYaw(float yaw) { n(yaw); } // Purpur - OBFHELPER - public void n(float f) {} - - public boolean bL() { -@@ -3096,6 +3113,18 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return false; - } - -+ // Purpur Start -+ public void sendMessage(String str) { -+ sendMessage(org.bukkit.craftbukkit.util.CraftChatMessage.fromStringOrNull(str)); -+ } -+ -+ public void sendMessage(IChatBaseComponent ichatbasecomponent) { -+ if (ichatbasecomponent != null) { -+ sendMessage(ichatbasecomponent, SystemUtils.getNullUUID()); -+ } -+ } -+ // Purpur end -+ - @Override - public void sendMessage(IChatBaseComponent ichatbasecomponent, UUID uuid) {} - -@@ -3542,4 +3571,47 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return ((ChunkProviderServer) world.getChunkProvider()).isInEntityTickingChunk(this); - } - // Paper end -+ -+ // Purpur start -+ private EntityHuman purpurRider; -+ -+ public EntityHuman getPurpurRider() { -+ return purpurRider; -+ } -+ -+ public boolean hasPurpurRider() { -+ return purpurRider != null; -+ } -+ -+ public boolean isRidable() { -+ return false; -+ } -+ -+ public boolean isRidableInWater() { -+ return false; -+ } -+ -+ public void onMount(EntityHuman entityhuman) { -+ if (this instanceof EntityInsentient) { -+ ((EntityInsentient) this).setGoalTarget(null, null, false); -+ ((EntityInsentient) this).getNavigation().stopPathfinding(); -+ } -+ entityhuman.setJumping(false); // fixes jump on mount -+ } -+ -+ public void onDismount(EntityHuman entityhuman) { -+ } -+ -+ public boolean onSpacebar() { -+ return false; -+ } -+ -+ public boolean onClick(EnumHand hand) { -+ return false; -+ } -+ -+ public boolean processClick(EnumHand hand) { -+ return false; -+ } -+ // Purpur end - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 6ea0fc81efe976c2b33cc12de175b357323b9cfd..b26b6cf0a1a5b3d0c636cdd734437ed19642ea98 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -46,8 +46,6 @@ import net.minecraft.world.entity.ai.sensing.EntitySenses; - import net.minecraft.world.entity.decoration.EntityHanging; - import net.minecraft.world.entity.decoration.EntityLeash; - import net.minecraft.world.entity.item.EntityItem; --import net.minecraft.world.entity.monster.EntityBlaze; --import net.minecraft.world.entity.monster.EntityEnderman; - import net.minecraft.world.entity.monster.IMonster; - import net.minecraft.world.entity.npc.EntityVillagerAbstract; - import net.minecraft.world.entity.player.EntityHuman; -@@ -100,7 +98,7 @@ public abstract class EntityInsentient extends EntityLiving { - protected int f; - protected ControllerLook lookController; - protected ControllerMove moveController; -- protected ControllerJump bi; -+ protected ControllerJump bi; public ControllerJump getJumpController() { return bi; } // Purpur - OBFHELPER - private final EntityAIBodyControl c; - protected NavigationAbstract navigation; - public PathfinderGoalSelector goalSelector; -@@ -138,8 +136,8 @@ public abstract class EntityInsentient extends EntityLiving { - this.bA = -1.0F; - this.goalSelector = new PathfinderGoalSelector(world.getMethodProfilerSupplier()); - this.targetSelector = new PathfinderGoalSelector(world.getMethodProfilerSupplier()); -- this.lookController = new ControllerLook(this); -- this.moveController = new ControllerMove(this); -+ this.lookController = new net.pl3x.purpur.controller.ControllerLookWASD(this); // Purpur -+ this.moveController = new net.pl3x.purpur.controller.ControllerMoveWASD(this); // Purpur - this.bi = new ControllerJump(this); - this.c = this.r(); - this.navigation = this.b(world); -@@ -328,10 +326,10 @@ public abstract class EntityInsentient extends EntityLiving { - // Purpur start - private void incrementTicksSinceLastInteraction() { - ++ticksSinceLastInteraction; -- //if (hasRider()) { -- // ticksSinceLastInteraction = 0; -- // return; -- //} -+ if (hasPurpurRider()) { -+ ticksSinceLastInteraction = 0; -+ return; -+ } - if (world.purpurConfig.entityLifeSpan <= 0) { - return; // feature disabled - } -@@ -626,14 +624,17 @@ public abstract class EntityInsentient extends EntityLiving { - return super.dp(); - } - -+ public void setForwardSpeed(float speed) { this.t(speed); } // Purpur - OBFHELPER - public void t(float f) { - this.aT = f; - } - -+ public void setVerticalSpeed(float speed) { this.u(speed); } // Purpur - OBFHELPER - public void u(float f) { - this.aS = f; - } - -+ public void setStrafeSpeed(float speed) { this.v(speed); } // Purpur - OBFHELPER - public void v(float f) { - this.aR = f; - } -@@ -1320,7 +1321,7 @@ public abstract class EntityInsentient extends EntityLiving { - protected void a(EntityHuman entityhuman, EntityInsentient entityinsentient) {} - - protected EnumInteractionResult b(EntityHuman entityhuman, EnumHand enumhand) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); // Purpur - } - - public boolean ev() { -@@ -1701,4 +1702,54 @@ public abstract class EntityInsentient extends EntityLiving { - this.unleash(true, event.isDropLeash()); - // Paper end - } -+ -+ // Purpur start -+ public double getMaxY() { -+ return world.getHeight(); -+ } -+ -+ public EnumInteractionResult tryRide(EntityHuman entityhuman, EnumHand enumhand) { -+ if (!isRidable()) { -+ return EnumInteractionResult.PASS; -+ } -+ if (enumhand != EnumHand.MAIN_HAND) { -+ return EnumInteractionResult.PASS; -+ } -+ if (entityhuman.isSneaking()) { -+ return EnumInteractionResult.PASS; -+ } -+ if (!entityhuman.getItemInHand(enumhand).isEmpty()) { -+ return EnumInteractionResult.PASS; -+ } -+ if (!passengers.isEmpty() || entityhuman.isPassenger()) { -+ return EnumInteractionResult.PASS; -+ } -+ if (this instanceof EntityTameableAnimal) { -+ EntityTameableAnimal tameable = (EntityTameableAnimal) this; -+ if (tameable.isTamed() && !tameable.isOwner(entityhuman)) { -+ return EnumInteractionResult.PASS; -+ } -+ if (!tameable.isTamed() && !world.purpurConfig.untamedTamablesAreRidable) { -+ return EnumInteractionResult.PASS; -+ } -+ } -+ if (this instanceof EntityAgeable) { -+ EntityAgeable ageable = (EntityAgeable) this; -+ if (ageable.isBaby() && !world.purpurConfig.babiesAreRidable) { -+ return EnumInteractionResult.PASS; -+ } -+ } -+ if (!entityhuman.getBukkitEntity().hasPermission("allow.ride." + getEntityType().getName())) { -+ entityhuman.sendMessage(net.pl3x.purpur.PurpurConfig.cannotRideMob); -+ return EnumInteractionResult.PASS; -+ } -+ entityhuman.yaw = this.yaw; -+ entityhuman.pitch = this.pitch; -+ if (entityhuman.startRiding(this)) { -+ return EnumInteractionResult.SUCCESS; -+ } else { -+ return EnumInteractionResult.PASS; -+ } -+ } -+ // Purpur end - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 50b64ab1cbc1940d2f8b5d938e41f5a31830da5b..a1a8441e26ce1414b2406f9be559eeb3a34453d9 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -558,7 +558,7 @@ public abstract class EntityLiving extends Entity { - - @Override - public boolean bt() { -- return false; -+ return isRidableInWater(); // Purpur - } - - protected void cU() { -@@ -2297,7 +2297,7 @@ public abstract class EntityLiving extends Entity { - return 0.42F * this.getBlockJumpFactor(); - } - -- protected void jump() { -+ public void jump() { // Purpur - protected -> public - float f = this.dJ(); - - if (this.hasEffect(MobEffects.JUMP)) { -@@ -2546,10 +2546,12 @@ public abstract class EntityLiving extends Entity { - return this.onGround ? this.dN() * (0.21600002F / (f * f * f)) : this.aE; - } - -+ public float getSpeed() { return dN(); } // Purpur - OBFHELPER - public float dN() { - return this.bu; - } - -+ public void setSpeed(float speed) { q(speed); } // Purpur - OBFHELPER - public void q(float f) { - this.bu = f; - } -@@ -2935,8 +2937,10 @@ public abstract class EntityLiving extends Entity { - this.collideNearby(); - this.world.getMethodProfiler().exit(); - // Paper start -- if (((WorldServer) world).hasEntityMoveEvent) { -- if (lastX != locX() || lastY != locY() || lastZ != locZ() || lastYaw != yaw || lastPitch != pitch) { -+ // Purpur start -+ if (lastX != locX() || lastY != locY() || lastZ != locZ() || lastYaw != yaw || lastPitch != pitch) { -+ if (((WorldServer) world).hasEntityMoveEvent) { -+ // Purpur end - Location from = new Location(world.getWorld(), lastX, lastY, lastZ, lastYaw, lastPitch); - Location to = new Location (world.getWorld(), locX(), locY(), locZ(), yaw, pitch); - EntityMoveEvent event = new EntityMoveEvent(getBukkitLivingEntity(), from, to.clone()); -@@ -2946,6 +2950,21 @@ public abstract class EntityLiving extends Entity { - setLocation(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch()); - } - } -+ // Purpur start -+ if (hasPurpurRider()) { -+ getPurpurRider().resetIdleTimer(); -+ if (((WorldServer) world).hasRidableMoveEvent && this instanceof EntityInsentient) { -+ Location from = new Location(world.getWorld(), lastX, lastY, lastZ, lastYaw, lastPitch); -+ Location to = new Location(world.getWorld(), locX(), locY(), locZ(), yaw, pitch); -+ net.pl3x.purpur.event.entity.RidableMoveEvent event = new net.pl3x.purpur.event.entity.RidableMoveEvent((org.bukkit.entity.Mob) getBukkitLivingEntity(), (Player) getPurpurRider().getBukkitEntity(), from, to.clone()); -+ if (!event.callEvent()) { -+ setLocation(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch()); -+ } else if (!to.equals(event.getTo())) { -+ setLocation(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch()); -+ } -+ } -+ } -+ // Purpur end - } - // Paper end - if (!this.world.isClientSide && this.dO() && this.aG()) { -diff --git a/src/main/java/net/minecraft/world/entity/EntityTameableAnimal.java b/src/main/java/net/minecraft/world/entity/EntityTameableAnimal.java -index 74636c4c0851da1cd5732daa0a2d1a4edda2050f..cdb56555889d17913d7b0c03d5ba23408a500f26 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTameableAnimal.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTameableAnimal.java -@@ -144,6 +144,7 @@ public abstract class EntityTameableAnimal extends EntityAnimal { - return this.i(entityliving) ? false : super.c(entityliving); - } - -+ public boolean isOwner(EntityLiving entityLiving) { return i(entityLiving); } // Purpur - OBFHELPER - public boolean i(EntityLiving entityliving) { - return entityliving == this.getOwner(); - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeDefaults.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeDefaults.java -index 1b9cf77aa5d73b4834e5260a91d338620e0bb6b3..b6cc0e1286294e64568d11c452684071d4c5b636 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeDefaults.java -+++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeDefaults.java -@@ -50,6 +50,7 @@ import net.minecraft.world.entity.monster.EntityGuardianElder; - import net.minecraft.world.entity.monster.EntityIllagerIllusioner; - import net.minecraft.world.entity.monster.EntityMagmaCube; - import net.minecraft.world.entity.monster.EntityMonster; -+import net.minecraft.world.entity.monster.EntityPhantom; - import net.minecraft.world.entity.monster.EntityPigZombie; - import net.minecraft.world.entity.monster.EntityPillager; - import net.minecraft.world.entity.monster.EntityRavager; -@@ -74,7 +75,80 @@ import org.apache.logging.log4j.Logger; - public class AttributeDefaults { - - private static final Logger LOGGER = LogManager.getLogger(); -- private static final Map, AttributeProvider> b = ImmutableMap.builder().put(EntityTypes.ARMOR_STAND, EntityLiving.cL().a()).put(EntityTypes.BAT, EntityBat.m().a()).put(EntityTypes.BEE, EntityBee.eZ().a()).put(EntityTypes.BLAZE, EntityBlaze.m().a()).put(EntityTypes.CAT, EntityCat.fa().a()).put(EntityTypes.CAVE_SPIDER, EntityCaveSpider.m().a()).put(EntityTypes.CHICKEN, EntityChicken.eK().a()).put(EntityTypes.COD, EntityFish.m().a()).put(EntityTypes.COW, EntityCow.eK().a()).put(EntityTypes.CREEPER, EntityCreeper.m().a()).put(EntityTypes.DOLPHIN, EntityDolphin.eM().a()).put(EntityTypes.DONKEY, EntityHorseChestedAbstract.eL().a()).put(EntityTypes.DROWNED, EntityZombie.eS().a()).put(EntityTypes.ELDER_GUARDIAN, EntityGuardianElder.m().a()).put(EntityTypes.ENDERMAN, EntityEnderman.m().a()).put(EntityTypes.ENDERMITE, EntityEndermite.m().a()).put(EntityTypes.ENDER_DRAGON, EntityEnderDragon.m().a()).put(EntityTypes.EVOKER, EntityEvoker.eK().a()).put(EntityTypes.FOX, EntityFox.eK().a()).put(EntityTypes.GHAST, EntityGhast.eJ().a()).put(EntityTypes.GIANT, EntityGiantZombie.m().a()).put(EntityTypes.GUARDIAN, EntityGuardian.eM().a()).put(EntityTypes.HOGLIN, EntityHoglin.eK().a()).put(EntityTypes.HORSE, EntityHorseAbstract.fi().a()).put(EntityTypes.HUSK, EntityZombie.eS().a()).put(EntityTypes.ILLUSIONER, EntityIllagerIllusioner.eK().a()).put(EntityTypes.IRON_GOLEM, EntityIronGolem.m().a()).put(EntityTypes.LLAMA, EntityLlama.fw().a()).put(EntityTypes.MAGMA_CUBE, EntityMagmaCube.m().a()).put(EntityTypes.MOOSHROOM, EntityCow.eK().a()).put(EntityTypes.MULE, EntityHorseChestedAbstract.eL().a()).put(EntityTypes.OCELOT, EntityOcelot.eK().a()).put(EntityTypes.PANDA, EntityPanda.eY().a()).put(EntityTypes.PARROT, EntityParrot.eU().a()).put(EntityTypes.PHANTOM, EntityMonster.eR().a()).put(EntityTypes.PIG, EntityPig.eK().a()).put(EntityTypes.PIGLIN, EntityPiglin.eT().a()).put(EntityTypes.PIGLIN_BRUTE, EntityPiglinBrute.eS().a()).put(EntityTypes.PILLAGER, EntityPillager.eK().a()).put(EntityTypes.PLAYER, EntityHuman.ep().a()).put(EntityTypes.POLAR_BEAR, EntityPolarBear.eK().a()).put(EntityTypes.PUFFERFISH, EntityFish.m().a()).put(EntityTypes.RABBIT, EntityRabbit.eL().a()).put(EntityTypes.RAVAGER, EntityRavager.m().a()).put(EntityTypes.SALMON, EntityFish.m().a()).put(EntityTypes.SHEEP, EntitySheep.eK().a()).put(EntityTypes.SHULKER, EntityShulker.m().a()).put(EntityTypes.SILVERFISH, EntitySilverfish.m().a()).put(EntityTypes.SKELETON, EntitySkeletonAbstract.m().a()).put(EntityTypes.SKELETON_HORSE, EntityHorseSkeleton.eL().a()).put(EntityTypes.SLIME, EntityMonster.eR().a()).put(EntityTypes.SNOW_GOLEM, EntitySnowman.m().a()).put(EntityTypes.SPIDER, EntitySpider.eK().a()).put(EntityTypes.SQUID, EntitySquid.m().a()).put(EntityTypes.STRAY, EntitySkeletonAbstract.m().a()).put(EntityTypes.STRIDER, EntityStrider.eM().a()).put(EntityTypes.TRADER_LLAMA, EntityLlama.fw().a()).put(EntityTypes.TROPICAL_FISH, EntityFish.m().a()).put(EntityTypes.TURTLE, EntityTurtle.eM().a()).put(EntityTypes.VEX, EntityVex.m().a()).put(EntityTypes.VILLAGER, EntityVillager.eY().a()).put(EntityTypes.VINDICATOR, EntityVindicator.eK().a()).put(EntityTypes.WANDERING_TRADER, EntityInsentient.p().a()).put(EntityTypes.WITCH, EntityWitch.eK().a()).put(EntityTypes.WITHER, EntityWither.eK().a()).put(EntityTypes.WITHER_SKELETON, EntitySkeletonAbstract.m().a()).put(EntityTypes.WOLF, EntityWolf.eU().a()).put(EntityTypes.ZOGLIN, EntityZoglin.m().a()).put(EntityTypes.ZOMBIE, EntityZombie.eS().a()).put(EntityTypes.ZOMBIE_HORSE, EntityHorseZombie.eL().a()).put(EntityTypes.ZOMBIE_VILLAGER, EntityZombie.eS().a()).put(EntityTypes.ZOMBIFIED_PIGLIN, EntityPigZombie.eW().a()).build(); -+ private static final Map, AttributeProvider> b = ImmutableMap., AttributeProvider>builder() // Purpur decompile error -+ .put(EntityTypes.ARMOR_STAND, EntityLiving.cL().a()) -+ .put(EntityTypes.BAT, EntityBat.m().a()) -+ .put(EntityTypes.BEE, EntityBee.eZ().a()) -+ .put(EntityTypes.BLAZE, EntityBlaze.m().a()) -+ .put(EntityTypes.CAT, EntityCat.fa().a()) -+ .put(EntityTypes.CAVE_SPIDER, EntityCaveSpider.m().a()) -+ .put(EntityTypes.CHICKEN, EntityChicken.eK().a()) -+ .put(EntityTypes.COD, EntityFish.m().a()) -+ .put(EntityTypes.COW, EntityCow.eK().a()) -+ .put(EntityTypes.CREEPER, EntityCreeper.m().a()) -+ .put(EntityTypes.DOLPHIN, EntityDolphin.eM().a()) -+ .put(EntityTypes.DONKEY, EntityHorseChestedAbstract.eL().a()) -+ .put(EntityTypes.DROWNED, EntityZombie.eS().a()) -+ .put(EntityTypes.ELDER_GUARDIAN, EntityGuardianElder.m().a()) -+ .put(EntityTypes.ENDERMAN, EntityEnderman.m().a()) -+ .put(EntityTypes.ENDERMITE, EntityEndermite.m().a()) -+ .put(EntityTypes.ENDER_DRAGON, EntityEnderDragon.m().a()) -+ .put(EntityTypes.EVOKER, EntityEvoker.eK().a()) -+ .put(EntityTypes.FOX, EntityFox.eK().a()) -+ .put(EntityTypes.GHAST, EntityGhast.eJ().a()) -+ .put(EntityTypes.GIANT, EntityGiantZombie.m().a()) -+ .put(EntityTypes.GUARDIAN, EntityGuardian.eM().a()) -+ .put(EntityTypes.HOGLIN, EntityHoglin.eK().a()) -+ .put(EntityTypes.HORSE, EntityHorseAbstract.fi().a()) -+ .put(EntityTypes.HUSK, EntityZombie.eS().a()) -+ .put(EntityTypes.ILLUSIONER, EntityIllagerIllusioner.eK().a()) -+ .put(EntityTypes.IRON_GOLEM, EntityIronGolem.m().a()) -+ .put(EntityTypes.LLAMA, EntityLlama.fw().a()) -+ .put(EntityTypes.MAGMA_CUBE, EntityMagmaCube.m().a()) -+ .put(EntityTypes.MOOSHROOM, EntityCow.eK().a()) -+ .put(EntityTypes.MULE, EntityHorseChestedAbstract.eL().a()) -+ .put(EntityTypes.OCELOT, EntityOcelot.eK().a()) -+ .put(EntityTypes.PANDA, EntityPanda.eY().a()) -+ .put(EntityTypes.PARROT, EntityParrot.eU().a()) -+ .put(EntityTypes.PHANTOM, EntityPhantom.defaultAttributes().build()) // Purpur -+ .put(EntityTypes.PIG, EntityPig.eK().a()) -+ .put(EntityTypes.PIGLIN, EntityPiglin.eT().a()) -+ .put(EntityTypes.PIGLIN_BRUTE, EntityPiglinBrute.eS().a()) -+ .put(EntityTypes.PILLAGER, EntityPillager.eK().a()) -+ .put(EntityTypes.PLAYER, EntityHuman.ep().a()) -+ .put(EntityTypes.POLAR_BEAR, EntityPolarBear.eK().a()) -+ .put(EntityTypes.PUFFERFISH, EntityFish.m().a()) -+ .put(EntityTypes.RABBIT, EntityRabbit.eL().a()) -+ .put(EntityTypes.RAVAGER, EntityRavager.m().a()) -+ .put(EntityTypes.SALMON, EntityFish.m().a()) -+ .put(EntityTypes.SHEEP, EntitySheep.eK().a()) -+ .put(EntityTypes.SHULKER, EntityShulker.m().a()) -+ .put(EntityTypes.SILVERFISH, EntitySilverfish.m().a()) -+ .put(EntityTypes.SKELETON, EntitySkeletonAbstract.m().a()) -+ .put(EntityTypes.SKELETON_HORSE, EntityHorseSkeleton.eL().a()) -+ .put(EntityTypes.SLIME, EntityMonster.eR().a()) -+ .put(EntityTypes.SNOW_GOLEM, EntitySnowman.m().a()) -+ .put(EntityTypes.SPIDER, EntitySpider.eK().a()) -+ .put(EntityTypes.SQUID, EntitySquid.m().a()) -+ .put(EntityTypes.STRAY, EntitySkeletonAbstract.m().a()) -+ .put(EntityTypes.STRIDER, EntityStrider.eM().a()) -+ .put(EntityTypes.TRADER_LLAMA, EntityLlama.fw().a()) -+ .put(EntityTypes.TROPICAL_FISH, EntityFish.m().a()) -+ .put(EntityTypes.TURTLE, EntityTurtle.eM().a()) -+ .put(EntityTypes.VEX, EntityVex.m().a()) -+ .put(EntityTypes.VILLAGER, EntityVillager.eY().a()) -+ .put(EntityTypes.VINDICATOR, EntityVindicator.eK().a()) -+ .put(EntityTypes.WANDERING_TRADER, EntityInsentient.p().a()) -+ .put(EntityTypes.WITCH, EntityWitch.eK().a()) -+ .put(EntityTypes.WITHER, EntityWither.eK().a()) -+ .put(EntityTypes.WITHER_SKELETON, EntitySkeletonAbstract.m().a()) -+ .put(EntityTypes.WOLF, EntityWolf.eU().a()) -+ .put(EntityTypes.ZOGLIN, EntityZoglin.m().a()) -+ .put(EntityTypes.ZOMBIE, EntityZombie.eS().a()) -+ .put(EntityTypes.ZOMBIE_HORSE, EntityHorseZombie.eL().a()) -+ .put(EntityTypes.ZOMBIE_VILLAGER, EntityZombie.eS().a()) -+ .put(EntityTypes.ZOMBIFIED_PIGLIN, EntityPigZombie.eW().a()) -+ .build(); - - public static AttributeProvider a(EntityTypes entitytypes) { - return (AttributeProvider) AttributeDefaults.b.get(entitytypes); -diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeProvider.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeProvider.java -index c75659d0f2a6a198f338c38b600e639a4cb3d9ee..5edad3ee07cc0357442ede3a1e14e8d5c121e530 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeProvider.java -+++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeProvider.java -@@ -102,6 +102,7 @@ public class AttributeProvider { - return this; - } - -+ public AttributeProvider build() { return a(); } // Purpur - OBFHELPER - public AttributeProvider a() { - this.b = true; - return new AttributeProvider(this.a); -diff --git a/src/main/java/net/minecraft/world/entity/ai/control/ControllerLookDolphin.java b/src/main/java/net/minecraft/world/entity/ai/control/ControllerLookDolphin.java -index bf059f201c662d6492b093184e7feec711b846e8..1b472a659c140b368173237d54633f0dfbeb7419 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/control/ControllerLookDolphin.java -+++ b/src/main/java/net/minecraft/world/entity/ai/control/ControllerLookDolphin.java -@@ -3,7 +3,7 @@ package net.minecraft.world.entity.ai.control; - import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.EntityInsentient; - --public class ControllerLookDolphin extends ControllerLook { -+public class ControllerLookDolphin extends net.pl3x.purpur.controller.ControllerLookWASD { // Purpur - - private final int h; - -@@ -13,7 +13,7 @@ public class ControllerLookDolphin extends ControllerLook { - } - - @Override -- public void a() { -+ public void tick() { // Purpur - if (this.d) { - this.d = false; - this.a.aC = this.a(this.a.aC, this.h() + 20.0F, this.b); -diff --git a/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java b/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java -index 2aa5789437ba7eb20579da238c407a65a25b1d44..434229b146978ba7dc08a83ea55fdb3ab743fbf8 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java -+++ b/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java -@@ -20,9 +20,9 @@ public class ControllerMove { - protected double b; - protected double c; - protected double d; -- protected double e; -- protected float f; -- protected float g; -+ protected double e; public double getSpeed() { return e; } public void setSpeed(double speed) { this.e = speed; } // Purpur - OBFHELPER -+ protected float f; public float getForward() { return f; } public void setForward(float forward) { this.f = forward; } // Purpur - OBFHELPER -+ protected float g; public float getStrafe() { return g; } public void setStrafe(float strafe) { this.g = strafe; } // Purpur - OBFHELPER - protected ControllerMove.Operation h; - - public ControllerMove(EntityInsentient entityinsentient) { -diff --git a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java -index 61ebb278cf4ef57ae7a86c6c6ef1fa14559f21e2..bee72578fae2fba56f8e8dcc1142ab54c7ba7cb8 100644 ---- a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java -+++ b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java -@@ -21,6 +21,7 @@ import net.minecraft.world.entity.EntityPose; - import net.minecraft.world.entity.EntitySize; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.EnumMobSpawn; -+import net.minecraft.world.entity.EnumMoveType; - import net.minecraft.world.entity.ai.attributes.AttributeProvider; - import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition; -@@ -40,9 +41,48 @@ public class EntityBat extends EntityAmbient { - - public EntityBat(EntityTypes entitytypes, World world) { - super(entitytypes, world); -+ this.moveController = new net.pl3x.purpur.controller.ControllerMoveWASDFlyingWithSpacebar(this, 0.075F); // Purpur - this.setAsleep(true); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.batRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.batRidableInWater; -+ } -+ -+ @Override -+ public double getMaxY() { -+ return world.purpurConfig.batMaxY; -+ } -+ -+ @Override -+ public void onMount(EntityHuman entityhuman) { -+ super.onMount(entityhuman); -+ if (isAsleep()) { -+ setAsleep(false); -+ world.playEffect(null, 1025, new BlockPosition(this).up(), 0); -+ } -+ } -+ -+ @Override -+ public void g(Vec3D vec3d) { -+ super.g(vec3d); -+ if (hasPurpurRider() && !onGround) { -+ float speed = (float) getAttributeInstance(GenericAttributes.FLYING_SPEED).getValue() * 2; -+ setSpeed(speed); -+ Vec3D mot = getMot(); -+ move(EnumMoveType.SELF, mot.multiply(speed, 0.25, speed)); -+ setMot(mot.a(0.9D)); -+ } -+ } -+ // Purpur end -+ - @Override - protected void initDatawatcher() { - super.initDatawatcher(); -@@ -87,7 +127,7 @@ public class EntityBat extends EntityAmbient { - protected void collideNearby() {} - - public static AttributeProvider.Builder m() { -- return EntityInsentient.p().a(GenericAttributes.MAX_HEALTH, 6.0D); -+ return EntityInsentient.p().a(GenericAttributes.MAX_HEALTH, 6.0D).a(GenericAttributes.FLYING_SPEED, 0.6D); // Purpur - } - - public boolean isAsleep() { -@@ -119,6 +159,13 @@ public class EntityBat extends EntityAmbient { - - @Override - protected void mobTick() { -+ // Purpur start -+ if (hasPurpurRider()) { -+ Vec3D mot = getMot(); -+ setMot(mot.x, mot.y + (getVertical() > 0 ? 0.07D : 0.0D), mot.z); -+ return; -+ } -+ // Purpur end - super.mobTick(); - BlockPosition blockposition = this.getChunkCoordinates(); - BlockPosition blockposition1 = blockposition.up(); -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -index 1d1f71a995a99b2101891a7a5bda7bec5d67f118..bcd510e0bf647a240edfaac1348119c5e1d7dc42 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -@@ -22,6 +22,7 @@ import net.minecraft.network.protocol.game.PacketDebug; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -44,10 +45,10 @@ import net.minecraft.world.entity.EntityPose; - import net.minecraft.world.entity.EntitySize; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.EnumMonsterType; -+import net.minecraft.world.entity.EnumMoveType; - import net.minecraft.world.entity.IEntityAngerable; - import net.minecraft.world.entity.ai.attributes.AttributeProvider; - import net.minecraft.world.entity.ai.attributes.GenericAttributes; --import net.minecraft.world.entity.ai.control.ControllerLook; - import net.minecraft.world.entity.ai.control.ControllerMoveFlying; - import net.minecraft.world.entity.ai.goal.PathfinderGoal; - import net.minecraft.world.entity.ai.goal.PathfinderGoalBreed; -@@ -111,6 +112,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - - public EntityBee(EntityTypes entitytypes, World world) { - super(entitytypes, world); -+ final net.pl3x.purpur.controller.ControllerMoveWASDFlying flyingController = new net.pl3x.purpur.controller.ControllerMoveWASDFlying(this, 0.25F, false); // Purpur - // Paper start - apply gravity to bees when they get stuck in the void, fixes MC-167279 - this.moveController = new ControllerMoveFlying(this, 20, true) { - @Override -@@ -120,6 +122,22 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - } - super.tick(); - } -+ -+ // Purpur start -+ @Override -+ public void a() { // tick -+ if (getEntity().hasPurpurRider()) { -+ flyingController.tick(getEntity().getPurpurRider()); -+ } else { -+ tick(); -+ } -+ } -+ -+ @Override -+ public boolean b() { // isUpdating -+ return getEntity().hasPurpurRider() || super.b(); -+ } -+ // Purpur end - }; - // Paper end - this.lookController = new EntityBee.j(this); -@@ -130,6 +148,35 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - this.a(PathType.FENCE, -1.0F); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.beeRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.beeRidableInWater; -+ } -+ -+ @Override -+ public double getMaxY() { -+ return world.purpurConfig.beeMaxY; -+ } -+ -+ @Override -+ public void g(Vec3D vec3d) { -+ super.g(vec3d); -+ if (hasPurpurRider() && !onGround) { -+ float speed = (float) getAttributeInstance(GenericAttributes.FLYING_SPEED).getValue() * 2; -+ setSpeed(speed); -+ Vec3D mot = getMot(); -+ move(EnumMoveType.SELF, mot.multiply(speed, speed, speed)); -+ setMot(mot.a(0.9D)); -+ } -+ } -+ // Purpur end -+ - @Override - protected void initDatawatcher() { - super.initDatawatcher(); -@@ -144,6 +191,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - - @Override - protected void initPathfinder() { -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(0, new EntityBee.b(this, 1.399999976158142D, true)); - this.goalSelector.a(1, new EntityBee.d()); - this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D)); -@@ -159,6 +207,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - this.goalSelector.a(7, new EntityBee.g()); - this.goalSelector.a(8, new EntityBee.l()); - this.goalSelector.a(9, new PathfinderGoalFloat(this)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, (new EntityBee.h(this)).a(new Class[0])); - this.targetSelector.a(2, new EntityBee.c(this)); - this.targetSelector.a(3, new PathfinderGoalUniversalAngerReset<>(this, true)); -@@ -629,6 +678,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - - private d() { - super(); // CraftBukkit - decompile error -+ this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - enter hive - } - - @Override -@@ -691,6 +741,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - - private g() { - super(); // CraftBukkit - decompile error -+ this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - grow crop - } - - @Override -@@ -755,6 +806,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - - private i() { - super(); // CraftBukkit - decompile error -+ this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - go to hive - } - - @Override -@@ -978,16 +1030,16 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - } - } - -- class j extends ControllerLook { -+ class j extends net.pl3x.purpur.controller.ControllerLookWASD { // Purpur - - j(EntityInsentient entityinsentient) { - super(entityinsentient); - } - - @Override -- public void a() { -+ public void tick() { // Purpur - if (!EntityBee.this.isAngry()) { -- super.a(); -+ super.tick(); // Purpur - } - } - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCat.java b/src/main/java/net/minecraft/world/entity/animal/EntityCat.java -index 054a1a74c48a3d936e45cc6b62a9fd6a90663cbc..0ec711f8f1d103d24899854f8cbcd261a66f26fc 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityCat.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityCat.java -@@ -14,6 +14,7 @@ import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; - import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -104,6 +105,25 @@ public class EntityCat extends EntityTameableAnimal { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.catRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.catRidableInWater; -+ } -+ -+ public void onMount(EntityHuman entityhuman) { -+ super.onMount(entityhuman); -+ setSitting(false); -+ setSleepingWithOwner(false); -+ setHeadDown(false); -+ } -+ // Purpur end -+ - public MinecraftKey eU() { - return (MinecraftKey) EntityCat.bq.getOrDefault(this.getCatType(), EntityCat.bq.get(0)); - } -@@ -111,7 +131,8 @@ public class EntityCat extends EntityTameableAnimal { - @Override - protected void initPathfinder() { - this.bx = new EntityCat.PathfinderGoalTemptChance(this, 0.6D, EntityCat.br, true); -- this.goalSelector.a(1, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalFloat(this)); // Purpur -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new PathfinderGoalSit(this)); - this.goalSelector.a(2, new EntityCat.b(this)); - this.goalSelector.a(3, this.bx); -@@ -123,6 +144,7 @@ public class EntityCat extends EntityTameableAnimal { - this.goalSelector.a(10, new PathfinderGoalBreed(this, 0.8D)); - this.goalSelector.a(11, new PathfinderGoalRandomStrollLand(this, 0.8D, 1.0000001E-5F)); - this.goalSelector.a(12, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 10.0F)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new PathfinderGoalRandomTargetNonTamed<>(this, EntityRabbit.class, false, (Predicate) null)); - this.targetSelector.a(1, new PathfinderGoalRandomTargetNonTamed<>(this, EntityTurtle.class, false, EntityTurtle.bo)); - } -@@ -139,6 +161,7 @@ public class EntityCat extends EntityTameableAnimal { - this.datawatcher.set(EntityCat.bs, i); - } - -+ public void setSleepingWithOwner(boolean flag) { x(flag); } // Purpur - OBFHELPER - public void x(boolean flag) { - this.datawatcher.set(EntityCat.bt, flag); - } -@@ -147,6 +170,7 @@ public class EntityCat extends EntityTameableAnimal { - return (Boolean) this.datawatcher.get(EntityCat.bt); - } - -+ public void setHeadDown(boolean flag) { y(flag); } // Purpur - OBFHELPER - public void y(boolean flag) { - this.datawatcher.set(EntityCat.bu, flag); - } -@@ -365,6 +389,7 @@ public class EntityCat extends EntityTameableAnimal { - - @Override - public EnumInteractionResult b(EntityHuman entityhuman, EnumHand enumhand) { -+ if (hasPurpurRider()) return EnumInteractionResult.PASS; // Purpur - ItemStack itemstack = entityhuman.b(enumhand); - Item item = itemstack.getItem(); - -@@ -462,6 +487,7 @@ public class EntityCat extends EntityTameableAnimal { - - public b(EntityCat entitycat) { - this.a = entitycat; -+ this.a(java.util.EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - lay on owner - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java b/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java -index 600d6ebdf554dbaa8ca46a22a12d8b4e3255d987..5c744f1eac19e144c39a2c146d312f0547d6e589 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java -@@ -2,6 +2,7 @@ package net.minecraft.world.entity.animal; - - import net.minecraft.core.BlockPosition; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -54,6 +55,16 @@ public class EntityChicken extends EntityAnimal { - } - - // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.chickenRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.chickenRidableInWater; -+ } -+ - @Override - protected void initAttributes() { - if (world.purpurConfig.chickenRetaliate) { -@@ -65,6 +76,7 @@ public class EntityChicken extends EntityAnimal { - @Override - protected void initPathfinder() { - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - //this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.4D)); // Purpur - moved down - this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D)); - this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.0D, false, EntityChicken.bv)); -@@ -75,6 +87,7 @@ public class EntityChicken extends EntityAnimal { - // Purpur start - if (world.purpurConfig.chickenRetaliate) { - this.goalSelector.a(1, new PathfinderGoalMeleeAttack(this, 1.0D, false)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this)); - } else { - this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.4D)); -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCod.java b/src/main/java/net/minecraft/world/entity/animal/EntityCod.java -index aac7992a30a0b69cb34097aeb0fe021f54a3cdac..897e0d5ca44a0c475634f08e7d4fcf129ee197ab 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityCod.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityCod.java -@@ -14,6 +14,18 @@ public class EntityCod extends EntityFishSchool { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.codRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return true; -+ } -+ // Purpur end -+ - @Override - protected ItemStack eK() { - return new ItemStack(Items.COD_BUCKET); -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCow.java b/src/main/java/net/minecraft/world/entity/animal/EntityCow.java -index 962dde5fcc617bc39b7d06a1e295370b9d60696c..b2d3fc3151a952ac783101443772736a206a6a3b 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityCow.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityCow.java -@@ -2,6 +2,7 @@ package net.minecraft.world.entity.animal; - - import net.minecraft.core.BlockPosition; - import net.minecraft.core.particles.Particles; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -43,9 +44,22 @@ public class EntityCow extends EntityAnimal { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.cowRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.cowRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new PathfinderGoalPanic(this, 2.0D)); - this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D)); - if (world.purpurConfig.cowFeedMushrooms > 0) this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.25D, RecipeItemStack.a(Items.WHEAT, Blocks.RED_MUSHROOM.getItem(), Blocks.BROWN_MUSHROOM.getItem()), false)); else // Purpur -@@ -87,6 +101,7 @@ public class EntityCow extends EntityAnimal { - - @Override - public EnumInteractionResult b(EntityHuman entityhuman, EnumHand enumhand) { -+ if (hasPurpurRider()) return EnumInteractionResult.PASS; // Purpur - ItemStack itemstack = entityhuman.b(enumhand); - - if (itemstack.getItem() == Items.BUCKET && !this.isBaby()) { -@@ -94,7 +109,7 @@ public class EntityCow extends EntityAnimal { - org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) entityhuman.world, entityhuman, this.getChunkCoordinates(), this.getChunkCoordinates(), null, itemstack, Items.MILK_BUCKET, enumhand); // Paper - add enumHand - - if (event.isCancelled()) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); // Purpur - } - // CraftBukkit end - -@@ -105,7 +120,7 @@ public class EntityCow extends EntityAnimal { - return EnumInteractionResult.a(this.world.isClientSide); - // Purpur start - feed mushroom to change to mooshroom - } else if (world.purpurConfig.cowFeedMushrooms > 0 && getEntityType() != EntityTypes.MOOSHROOM && isMushroom(itemstack)) { -- return feedMushroom(entityhuman, itemstack); -+ return feedMushroom(entityhuman, enumhand, itemstack); - // Purpur end - } else { - return super.b(entityhuman, enumhand); -@@ -128,7 +143,7 @@ public class EntityCow extends EntityAnimal { - } - } - -- private EnumInteractionResult feedMushroom(EntityHuman entityhuman, ItemStack itemstack) { -+ private EnumInteractionResult feedMushroom(EntityHuman entityhuman, EnumHand enumhand, ItemStack itemstack) { - world.broadcastEntityEffect(this, (byte) 18); // hearts - playSound(SoundEffects.ENTITY_COW_MILK, 1.0F, 1.0F); - if (incrementFeedCount(itemstack) < world.purpurConfig.cowFeedMushrooms) { -@@ -139,7 +154,7 @@ public class EntityCow extends EntityAnimal { - } - EntityMushroomCow mooshroom = EntityTypes.MOOSHROOM.create(world); - if (mooshroom == null) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); - } - if (itemstack.getItem() == Blocks.BROWN_MUSHROOM.getItem()) { - mooshroom.setVariant(EntityMushroomCow.Type.BROWN); -@@ -158,10 +173,10 @@ public class EntityCow extends EntityAnimal { - mooshroom.setCustomName(this.getCustomName()); - } - if (CraftEventFactory.callEntityTransformEvent(this, mooshroom, org.bukkit.event.entity.EntityTransformEvent.TransformReason.INFECTION).isCancelled()) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); - } - if (!new com.destroystokyo.paper.event.entity.EntityTransformedEvent(this.getBukkitEntity(), mooshroom.getBukkitEntity(), com.destroystokyo.paper.event.entity.EntityTransformedEvent.TransformedReason.INFECTED).callEvent()) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); - } - this.world.addEntity(mooshroom); - this.die(); -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java b/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java -index e0a9b931c26dbd4e7739d09ae45e1cee72ab210c..e4442716b329f3101bfd39fc7ce13d5419b427bf 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java -@@ -16,6 +16,7 @@ import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; - import net.minecraft.resources.ResourceKey; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -81,6 +82,7 @@ public class EntityDolphin extends EntityWaterAnimal { - public static final Predicate b = (entityitem) -> { - return !entityitem.p() && entityitem.isAlive() && entityitem.isInWater(); - }; -+ private int spitCooldown; // Purpur - - public EntityDolphin(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -89,6 +91,45 @@ public class EntityDolphin extends EntityWaterAnimal { - this.setCanPickupLoot(true); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.dolphinRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return true; -+ } -+ -+ @Override -+ public boolean onSpacebar() { -+ if (spitCooldown == 0 && hasPurpurRider()) { -+ spitCooldown = world.purpurConfig.dolphinSpitCooldown; -+ if (!hasPurpurRider()) { -+ return false; -+ } -+ -+ org.bukkit.craftbukkit.entity.CraftPlayer player = (org.bukkit.craftbukkit.entity.CraftPlayer) getPurpurRider().getBukkitEntity(); -+ if (!player.hasPermission("allow.special.dolphin")) { -+ return false; -+ } -+ -+ org.bukkit.Location loc = player.getEyeLocation(); -+ loc.setPitch(loc.getPitch() - 10); -+ org.bukkit.util.Vector target = loc.getDirection().normalize().multiply(10).add(loc.toVector()); -+ -+ net.pl3x.purpur.entity.DolphinSpit spit = new net.pl3x.purpur.entity.DolphinSpit(world, this); -+ spit.shoot(target.getX() - locX(), target.getY() - locY(), target.getZ() - locZ(), world.purpurConfig.dolphinSpitSpeed, 5.0F); -+ -+ world.addEntity(spit); -+ playSound(SoundEffects.ENTITY_DOLPHIN_ATTACK, 1.0F, 1.0F + (random.nextFloat() - random.nextFloat()) * 0.2F); -+ return true; -+ } -+ return false; -+ } -+ // Purpur end -+ - @Nullable - @Override - public GroupDataEntity prepare(WorldAccess worldaccess, DifficultyDamageScaler difficultydamagescaler, EnumMobSpawn enummobspawn, @Nullable GroupDataEntity groupdataentity, @Nullable NBTTagCompound nbttagcompound) { -@@ -163,6 +204,7 @@ public class EntityDolphin extends EntityWaterAnimal { - protected void initPathfinder() { - this.goalSelector.a(0, new PathfinderGoalBreath(this)); - this.goalSelector.a(0, new PathfinderGoalWater(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new EntityDolphin.b(this)); - this.goalSelector.a(2, new EntityDolphin.c(this, 4.0D)); - this.goalSelector.a(4, new PathfinderGoalRandomSwim(this, 1.0D, 10)); -@@ -173,6 +215,7 @@ public class EntityDolphin extends EntityWaterAnimal { - this.goalSelector.a(8, new EntityDolphin.d()); - this.goalSelector.a(8, new PathfinderGoalFollowBoat(this)); - this.goalSelector.a(9, new PathfinderGoalAvoidTarget<>(this, EntityGuardian.class, 8.0F, 1.0D, 1.0D)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityGuardian.class})).a(new Class[0])); // CraftBukkit - decompile error - } - -@@ -224,7 +267,7 @@ public class EntityDolphin extends EntityWaterAnimal { - - @Override - protected boolean n(Entity entity) { -- return true; -+ return getRideCooldown() <= 0; // Purpur - make dolphin honor ride cooldown like all other non-boss mobs - } - - @Override -@@ -259,6 +302,9 @@ public class EntityDolphin extends EntityWaterAnimal { - @Override - public void tick() { - super.tick(); -+ if (spitCooldown > 0) { -+ spitCooldown--; -+ } - if (this.isNoAI()) { - this.setAirTicks(this.bH()); - } else { -@@ -532,7 +578,7 @@ public class EntityDolphin extends EntityWaterAnimal { - - private int b; - -- private d() {} -+ private d() { this.a(java.util.EnumSet.of(PathfinderGoal.Type.MOVE)); } // Purpur - play with item - - @Override - public boolean a() { -@@ -600,7 +646,7 @@ public class EntityDolphin extends EntityWaterAnimal { - } - } - -- static class a extends ControllerMove { -+ static class a extends net.pl3x.purpur.controller.ControllerMoveWASDWater { // Purpur - - private final EntityDolphin i; - -@@ -610,7 +656,20 @@ public class EntityDolphin extends EntityWaterAnimal { - } - - @Override -- public void a() { -+ // Purpur start -+ public void tick(EntityHuman rider) { -+ if (this.i.getAirTicks() < 150) { -+ // if drowning override player WASD controls to find air -+ tick(); -+ } else { -+ super.tick(rider); -+ this.i.setMot(this.i.getMot().add(0.0D, 0.005D, 0.0D)); -+ } -+ } -+ -+ @Override -+ public void tick() { -+ // Purpur end - if (this.i.isInWater()) { - this.i.setMot(this.i.getMot().add(0.0D, 0.005D, 0.0D)); - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFish.java b/src/main/java/net/minecraft/world/entity/animal/EntityFish.java -index cbd7c37cd1d6f5dddcbc515ecc2d9df46e109bfa..d9a5d5fb718f8c3d66844279622eae44fe826fff 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityFish.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityFish.java -@@ -1,13 +1,14 @@ - package net.minecraft.world.entity.animal; - - import java.util.Random; --import java.util.function.Predicate; -+ - import net.minecraft.advancements.CriterionTriggers; - import net.minecraft.core.BlockPosition; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -29,7 +30,6 @@ import net.minecraft.world.entity.ai.control.ControllerMove; - import net.minecraft.world.entity.ai.goal.PathfinderGoalAvoidTarget; - import net.minecraft.world.entity.ai.goal.PathfinderGoalPanic; - import net.minecraft.world.entity.ai.goal.PathfinderGoalRandomSwim; --import net.minecraft.world.entity.ai.goal.PathfinderGoalSelector; - import net.minecraft.world.entity.ai.navigation.NavigationAbstract; - import net.minecraft.world.entity.ai.navigation.NavigationGuardian; - import net.minecraft.world.entity.player.EntityHuman; -@@ -116,13 +116,12 @@ public abstract class EntityFish extends EntityWaterAnimal { - @Override - protected void initPathfinder() { - super.initPathfinder(); -- this.goalSelector.a(0, new PathfinderGoalPanic(this, 1.25D)); -- PathfinderGoalSelector pathfindergoalselector = this.goalSelector; -- Predicate predicate = IEntitySelector.g; -- -- predicate.getClass(); -- pathfindergoalselector.a(2, new PathfinderGoalAvoidTarget<>(this, EntityHuman.class, 8.0F, 1.6D, 1.4D, predicate::test)); -- this.goalSelector.a(4, new EntityFish.b(this)); -+ // Purpur start -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur -+ this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.25D)); -+ this.goalSelector.a(3, new PathfinderGoalAvoidTarget<>(this, EntityHuman.class, 8.0F, 1.6D, 1.4D, IEntitySelector.g::test)); // Purpur - decompile error -+ this.goalSelector.a(5, new EntityFish.b(this)); -+ // Purpur end - } - - @Override -@@ -133,7 +132,7 @@ public abstract class EntityFish extends EntityWaterAnimal { - @Override - public void g(Vec3D vec3d) { - if (this.doAITick() && this.isInWater()) { -- this.a(0.01F, vec3d); -+ this.a(hasPurpurRider() ? getSpeed() : 0.01F, vec3d); // Purpur - this.move(EnumMoveType.SELF, this.getMot()); - this.setMot(this.getMot().a(0.9D)); - if (this.getGoalTarget() == null) { -@@ -220,9 +219,9 @@ public abstract class EntityFish extends EntityWaterAnimal { - @Override - protected void b(BlockPosition blockposition, IBlockData iblockdata) {} - -- static class a extends ControllerMove { -+ static class a extends net.pl3x.purpur.controller.ControllerMoveWASDWater { // Purpur - -- private final EntityFish i; -+ private final EntityFish i; public EntityFish getFish() { return i; } // Purpur - OBFHELPER - - a(EntityFish entityfish) { - super(entityfish); -@@ -230,7 +229,15 @@ public abstract class EntityFish extends EntityWaterAnimal { - } - - @Override -- public void a() { -+ // Purpur start -+ public void tick(EntityHuman rider) { -+ super.tick(rider); -+ getFish().setMot(getFish().getMot().add(0.0D, 0.005D, 0.0D)); -+ } -+ -+ @Override -+ public void tick() { -+ // Purpur end - if (this.i.a((Tag) TagsFluid.WATER)) { - this.i.setMot(this.i.getMot().add(0.0D, 0.005D, 0.0D)); - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFishSchool.java b/src/main/java/net/minecraft/world/entity/animal/EntityFishSchool.java -index 21780f5dbcd4384649f08161f0812202ee94c96d..a03b0ed0a3f74ccb7572e1c4fa8e345a9e9bc49f 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityFishSchool.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityFishSchool.java -@@ -25,7 +25,7 @@ public abstract class EntityFishSchool extends EntityFish { - @Override - protected void initPathfinder() { - super.initPathfinder(); -- this.goalSelector.a(5, new PathfinderGoalFishSchool(this)); -+ this.goalSelector.a(6, new PathfinderGoalFishSchool(this)); // Purpur - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -index 19a9affdaba52d8e7dc1c4c20d5c0d52829f4989..7b1a6d846f25d8bc659a541fce59df79347ba9bc 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -@@ -21,6 +21,7 @@ import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; - import net.minecraft.resources.ResourceKey; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundEffect; -@@ -48,8 +49,6 @@ import net.minecraft.world.entity.GroupDataEntity; - import net.minecraft.world.entity.IEntitySelector; - import net.minecraft.world.entity.ai.attributes.AttributeProvider; - import net.minecraft.world.entity.ai.attributes.GenericAttributes; --import net.minecraft.world.entity.ai.control.ControllerLook; --import net.minecraft.world.entity.ai.control.ControllerMove; - import net.minecraft.world.entity.ai.goal.PathfinderGoal; - import net.minecraft.world.entity.ai.goal.PathfinderGoalAvoidTarget; - import net.minecraft.world.entity.ai.goal.PathfinderGoalBreed; -@@ -127,6 +126,39 @@ public class EntityFox extends EntityAnimal { - this.setCanPickupLoot(true); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.foxRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.foxRidableInWater; -+ } -+ -+ @Override -+ public float getJumpHeight() { -+ return !hasPurpurRider() ? super.getJumpHeight() : 0.5F; -+ } -+ -+ @Override -+ public void onMount(EntityHuman entityhuman) { -+ super.onMount(entityhuman); -+ setCanPickupLoot(false); -+ stopActions(); -+ setChasing(false); -+ spit(getEquipment(EnumItemSlot.MAINHAND)); -+ setSlot(EnumItemSlot.MAINHAND, ItemStack.NULL_ITEM); -+ } -+ -+ @Override -+ public void onDismount(EntityHuman entityhuman) { -+ super.onDismount(entityhuman); -+ setCanPickupLoot(true); -+ } -+ // Purpur end -+ - @Override - protected void initDatawatcher() { - super.initDatawatcher(); -@@ -146,6 +178,7 @@ public class EntityFox extends EntityAnimal { - return entityliving instanceof EntityFishSchool; - }); - this.goalSelector.a(0, new EntityFox.g()); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new EntityFox.b()); - this.goalSelector.a(2, new EntityFox.n(2.2D)); - this.goalSelector.a(3, new EntityFox.e(1.0D)); -@@ -171,6 +204,7 @@ public class EntityFox extends EntityAnimal { - this.goalSelector.a(11, new EntityFox.p()); - this.goalSelector.a(12, new EntityFox.j(this, EntityHuman.class, 24.0F)); - this.goalSelector.a(13, new EntityFox.r()); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(3, new EntityFox.a(EntityLiving.class, false, false, (entityliving) -> { - return EntityFox.bt.test(entityliving) && !this.c(entityliving.getUniqueID()); - })); -@@ -458,6 +492,7 @@ public class EntityFox extends EntityAnimal { - return itemstack1.isEmpty() || this.bD > 0 && item.isFood() && !itemstack1.getItem().isFood(); - } - -+ public void spit(ItemStack itemstack) { m(itemstack); } // Purpur - OBFHELPER - private void m(ItemStack itemstack) { - if (!itemstack.isEmpty() && !this.world.isClientSide) { - EntityItem entityitem = new EntityItem(this.world, this.locX() + this.getLookDirection().x, this.locY() + 1.0D, this.locZ() + this.getLookDirection().z, itemstack); -@@ -553,6 +588,7 @@ public class EntityFox extends EntityAnimal { - return this.t(16); - } - -+ public void setChasing(boolean flag) { u(flag); } // Purpur - OBFHELPER - public void u(boolean flag) { - this.d(16, flag); - } -@@ -595,6 +631,7 @@ public class EntityFox extends EntityAnimal { - this.setSleeping(false); - } - -+ public void stopActions() { fd(); } // Purpur - OBFHELPER - private void fd() { - this.w(false); - this.setCrouching(false); -@@ -760,16 +797,16 @@ public class EntityFox extends EntityAnimal { - } - } - -- public class k extends ControllerLook { -+ public class k extends net.pl3x.purpur.controller.ControllerLookWASD { // Purpur - - public k() { - super(EntityFox.this); - } - - @Override -- public void a() { -+ public void tick() { // Purpur - if (!EntityFox.this.isSleeping()) { -- super.a(); -+ super.tick(); // Purpur - } - - } -@@ -1439,16 +1476,16 @@ public class EntityFox extends EntityAnimal { - } - } - -- class m extends ControllerMove { -+ class m extends net.pl3x.purpur.controller.ControllerMoveWASD { // Purpur - - public m() { - super(EntityFox.this); - } - - @Override -- public void a() { -+ public void tick() { // Purpur - if (EntityFox.this.fe()) { -- super.a(); -+ super.tick(); // Purpur - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java b/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java -index 62cff5faafa076d05ebc59ad5c4fb020bea0509e..23e614f0c3cf1178acff8e72e0441c42c658e76b 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java -@@ -14,6 +14,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -69,9 +70,22 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable { - this.G = 1.0F; - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.ironGolemRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.ironGolemRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { - if (world.purpurConfig.ironGolemCanSwim) this.goalSelector.a(0, new PathfinderGoalFloat(this)); // Purpur -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new PathfinderGoalMeleeAttack(this, 1.0D, true)); - this.goalSelector.a(2, new PathfinderGoalMoveTowardsTarget(this, 0.9D, 32.0F)); - this.goalSelector.a(2, new PathfinderGoalStrollVillage(this, 0.6D, false)); -@@ -79,6 +93,7 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable { - this.goalSelector.a(5, new PathfinderGoalOfferFlower(this)); - this.goalSelector.a(7, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F)); - this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new PathfinderGoalDefendVillage(this)); - this.targetSelector.a(2, new PathfinderGoalHurtByTarget(this, new Class[0])); - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, this::a_)); -@@ -248,13 +263,13 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable { - Item item = itemstack.getItem(); - - if (item != Items.IRON_INGOT) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); // Purpur - } else { - float f = this.getHealth(); - - this.heal(25.0F); - if (this.getHealth() == f) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); // Purpur - } else { - float f1 = 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F; - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java b/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java -index d28d4d2c1eff2c130f49c2bce3c19da212dba5dc..815e907e8db721f2a6f0f831b69c44a9573b5c9b 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java -@@ -57,6 +57,18 @@ public class EntityMushroomCow extends EntityCow implements IShearable { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.mooshroomRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.mooshroomRidableInWater; -+ } -+ // Purpur end -+ - @Override - public float a(BlockPosition blockposition, IWorldReader iworldreader) { - return iworldreader.getType(blockposition.down()).a(Blocks.MYCELIUM) ? 10.0F : iworldreader.y(blockposition) - 0.5F; -@@ -118,7 +130,7 @@ public class EntityMushroomCow extends EntityCow implements IShearable { - } else if (itemstack.getItem() == Items.SHEARS && this.canShear()) { - // CraftBukkit start - if (!CraftEventFactory.handlePlayerShearEntityEvent(entityhuman, this, itemstack, enumhand)) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); // Purpur - } - // CraftBukkit end - this.shear(SoundCategory.PLAYERS); -@@ -138,7 +150,7 @@ public class EntityMushroomCow extends EntityCow implements IShearable { - Optional> optional = this.l(itemstack); - - if (!optional.isPresent()) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); // Purpur - } - - Pair pair = (Pair) optional.get(); -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java b/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java -index f3e9c73f28584bcccd6f82d8974eabe4b4a892fa..d7938ff0dca305f1d47fdfdbc57648892debe367 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java -@@ -10,6 +10,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -63,6 +64,18 @@ public class EntityOcelot extends EntityAnimal { - this.eL(); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.ocelotRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.ocelotRidableInWater; -+ } -+ // Purpur end -+ - private boolean isTrusting() { - return (Boolean) this.datawatcher.get(EntityOcelot.bp); - } -@@ -94,12 +107,14 @@ public class EntityOcelot extends EntityAnimal { - protected void initPathfinder() { - this.br = new EntityOcelot.b(this, 0.6D, EntityOcelot.bo, true); - this.goalSelector.a(1, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(1, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(3, this.br); - this.goalSelector.a(7, new PathfinderGoalLeapAtTarget(this, 0.3F)); - this.goalSelector.a(8, new PathfinderGoalOcelotAttack(this)); - this.goalSelector.a(9, new PathfinderGoalBreed(this, 0.8D)); - this.goalSelector.a(10, new PathfinderGoalRandomStrollLand(this, 0.8D, 1.0000001E-5F)); - this.goalSelector.a(11, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 10.0F)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityChicken.class, false)); - this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityTurtle.class, 10, false, false, EntityTurtle.bo)); - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java b/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java -index 711b322007a0973ff0aebf3c25efbae8fc7741d0..0d912399e1975d9c0d5525f5b89049f40e7efcc0 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java -@@ -16,6 +16,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -101,6 +102,27 @@ public class EntityPanda extends EntityAnimal { - - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.pandaRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.pandaRidableInWater; -+ } -+ -+ @Override -+ public void onMount(EntityHuman entityhuman) { -+ super.onMount(entityhuman); -+ this.setForwardSpeed(0.0F); -+ this.setScared(false); -+ this.setEating(false); -+ this.setLayingOnBack(false); -+ } -+ // Purpur end -+ - @Override - public boolean e(ItemStack itemstack) { - EnumItemSlot enumitemslot = EntityInsentient.j(itemstack); -@@ -124,6 +146,7 @@ public class EntityPanda extends EntityAnimal { - return this.w(8); - } - -+ public void setScared(boolean scared) { this.t(scared); } // Purpur - OBFHELPER - public void t(boolean flag) { - this.d(8, flag); - } -@@ -132,6 +155,7 @@ public class EntityPanda extends EntityAnimal { - return this.w(16); - } - -+ public void setLayingOnBack(boolean layingOnBack) { this.u(layingOnBack); } // Purpur - OBFHELPER - public void u(boolean flag) { - this.d(16, flag); - } -@@ -148,6 +172,7 @@ public class EntityPanda extends EntityAnimal { - return (Integer) this.datawatcher.get(EntityPanda.br); - } - -+ public void setEating(boolean eating) { this.v(eating); } // Purpur - OBFHELPER - private void v(int i) { - this.datawatcher.set(EntityPanda.br, i); - } -@@ -256,6 +281,7 @@ public class EntityPanda extends EntityAnimal { - @Override - protected void initPathfinder() { - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(2, new EntityPanda.i(this, 2.0D)); - this.goalSelector.a(2, new EntityPanda.d(this, 1.0D)); - this.goalSelector.a(3, new EntityPanda.b(this, 1.2000000476837158D, true)); -@@ -271,6 +297,7 @@ public class EntityPanda extends EntityAnimal { - this.goalSelector.a(12, new EntityPanda.j(this)); - this.goalSelector.a(13, new PathfinderGoalFollowParent(this, 1.25D)); - this.goalSelector.a(14, new PathfinderGoalRandomStrollLand(this, 1.0D)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, (new EntityPanda.e(this, new Class[0])).a(new Class[0])); - } - -@@ -591,7 +618,7 @@ public class EntityPanda extends EntityAnimal { - ItemStack itemstack = entityhuman.b(enumhand); - - if (this.ff()) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); // Purpur - } else if (this.eN()) { - this.u(false); - return EnumInteractionResult.a(this.world.isClientSide); -@@ -608,7 +635,7 @@ public class EntityPanda extends EntityAnimal { - this.g(entityhuman); - } else { - if (this.world.isClientSide || this.eM() || this.isInWater()) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); // Purpur - } - - this.ft(); -@@ -625,7 +652,7 @@ public class EntityPanda extends EntityAnimal { - - return EnumInteractionResult.SUCCESS; - } else { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); // Purpur - } - } - -@@ -738,6 +765,7 @@ public class EntityPanda extends EntityAnimal { - - public f(EntityPanda entitypanda) { - this.a = entitypanda; -+ this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - lay on back - } - - @Override -@@ -901,6 +929,7 @@ public class EntityPanda extends EntityAnimal { - - public l(EntityPanda entitypanda) { - this.a = entitypanda; -+ this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - sneeze - } - - @Override -@@ -1030,7 +1059,7 @@ public class EntityPanda extends EntityAnimal { - } - } - -- static class h extends ControllerMove { -+ static class h extends net.pl3x.purpur.controller.ControllerMoveWASD { // Purpur - - private final EntityPanda i; - -@@ -1040,9 +1069,9 @@ public class EntityPanda extends EntityAnimal { - } - - @Override -- public void a() { -+ public void tick() { // Purpur - if (this.i.fh()) { -- super.a(); -+ super.tick(); // Purpur - } - } - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java -index 699dd0ac1f8d0d340ab1a560106336fc7cc95d5b..9f705b75a14ba456808485ce4ddef9550aac3fe9 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java -@@ -16,6 +16,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffect; -@@ -38,6 +39,7 @@ import net.minecraft.world.entity.EntityPose; - import net.minecraft.world.entity.EntitySize; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.EnumMobSpawn; -+import net.minecraft.world.entity.EnumMoveType; - import net.minecraft.world.entity.GroupDataEntity; - import net.minecraft.world.entity.ai.attributes.AttributeProvider; - import net.minecraft.world.entity.ai.attributes.GenericAttributes; -@@ -119,12 +121,58 @@ public class EntityParrot extends EntityPerchable implements EntityBird { - - public EntityParrot(EntityTypes entitytypes, World world) { - super(entitytypes, world); -- this.moveController = new ControllerMoveFlying(this, 10, false); -+ // Purpur start -+ final net.pl3x.purpur.controller.ControllerMoveWASDFlyingWithSpacebar flyingController = new net.pl3x.purpur.controller.ControllerMoveWASDFlyingWithSpacebar(this, 0.3F); -+ this.moveController = new ControllerMoveFlying(this, 10, false) { -+ @Override -+ public void a() { // tick -+ if (getEntity().hasPurpurRider()) { -+ flyingController.tick(getEntity().getPurpurRider()); -+ } else { -+ tick(); -+ } -+ } -+ -+ @Override -+ public boolean b() { // isUpdating -+ return getEntity().hasPurpurRider() ? getForward() != 0 || getStrafe() != 0 : super.b(); -+ } -+ }; -+ // Purpur end - this.a(PathType.DANGER_FIRE, -1.0F); - this.a(PathType.DAMAGE_FIRE, -1.0F); - this.a(PathType.COCOA, -1.0F); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.parrotRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.parrotRidableInWater; -+ } -+ -+ @Override -+ public double getMaxY() { -+ return world.purpurConfig.parrotMaxY; -+ } -+ -+ @Override -+ public void g(Vec3D vec3d) { -+ super.g(vec3d); -+ if (hasPurpurRider() && !onGround) { -+ float speed = (float) getAttributeInstance(GenericAttributes.FLYING_SPEED).getValue() * 2; -+ setSpeed(speed); -+ Vec3D mot = getMot(); -+ move(EnumMoveType.SELF, mot.multiply(speed, 0.25, speed)); -+ setMot(mot.a(0.9D)); -+ } -+ } -+ // Purpur end -+ - @Nullable - @Override - public GroupDataEntity prepare(WorldAccess worldaccess, DifficultyDamageScaler difficultydamagescaler, EnumMobSpawn enummobspawn, @Nullable GroupDataEntity groupdataentity, @Nullable NBTTagCompound nbttagcompound) { -@@ -143,8 +191,10 @@ public class EntityParrot extends EntityPerchable implements EntityBird { - - @Override - protected void initPathfinder() { -- this.goalSelector.a(0, new PathfinderGoalPanic(this, 1.25D)); -+ // this.goalSelector.a(0, new PathfinderGoalPanic(this, 1.25D)); // Purpur - move down - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur -+ this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.25D)); // Purpur - this.goalSelector.a(1, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(2, new PathfinderGoalSit(this)); - this.goalSelector.a(2, new PathfinderGoalFollowOwner(this, 1.0D, 5.0F, 1.0F, true)); -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -index 1a540e41e6161d011ca4ed30c68ae9df4567b8db..cef69f99d7bc9b6605b9654c50f43a1ebc1a8509 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -@@ -9,6 +9,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffect; -@@ -66,9 +67,22 @@ public class EntityPig extends EntityAnimal implements ISteerable, ISaddleable { - this.saddleStorage = new SaddleStorage(this.datawatcher, EntityPig.bp, EntityPig.bo); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.pigRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.pigRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.25D)); - this.goalSelector.a(3, new PathfinderGoalBreed(this, 1.0D)); - this.goalSelector.a(4, new PathfinderGoalTempt(this, 1.2D, RecipeItemStack.a(Items.CARROT_ON_A_STICK), false)); -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java b/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java -index f25f5ced218555af0d62844a78842cfc7599d608..b46315700b8857318b03b83097fcf829047f8ca4 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java -@@ -14,6 +14,7 @@ import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; - import net.minecraft.resources.ResourceKey; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -66,12 +67,34 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { - private static final IntRange bs = TimeRange.a(20, 39); - private int bt; - private UUID bu; -+ private int standTimer = 0; // Purpur - - public EntityPolarBear(EntityTypes entitytypes, World world) { - super(entitytypes, world); - } - - // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.polarBearRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.polarBearRidableInWater; -+ } -+ -+ @Override -+ public boolean onSpacebar() { -+ if (!isStanding()) { -+ if (hasPurpurRider() && getPurpurRider().getForward() == 0 && getPurpurRider().getStrafe() == 0) { -+ setStanding(true); -+ playSound(SoundEffects.ENTITY_POLAR_BEAR_WARNING, 1.0F, 1.0F); -+ } -+ } -+ return false; -+ } -+ - @Override - public boolean mate(EntityAnimal entityanimal) { - if (entityanimal == this) { -@@ -109,6 +132,7 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { - protected void initPathfinder() { - super.initPathfinder(); - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new EntityPolarBear.c()); - this.goalSelector.a(1, new EntityPolarBear.d()); - // Purpur start -@@ -121,6 +145,7 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { - this.goalSelector.a(5, new PathfinderGoalRandomStroll(this, 1.0D)); - this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F)); - this.goalSelector.a(7, new PathfinderGoalRandomLookaround(this)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new EntityPolarBear.b()); - this.targetSelector.a(2, new EntityPolarBear.a()); - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, this::a_)); -@@ -233,6 +258,11 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { - this.a((WorldServer) this.world, true); - } - -+ // Purpur start -+ if (isStanding() && --standTimer <= 0) { -+ setStanding(false); -+ } -+ // Purpur end - } - - @Override -@@ -266,6 +296,7 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { - public void setStanding(boolean standing) { t(standing); } // Purpur - OBFHELPER - public void t(boolean flag) { - this.datawatcher.set(EntityPolarBear.bo, flag); -+ standTimer = flag ? 20 : -1; // Purpur - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java b/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java -index 4e4327b3cb84367534c6f5855cf8b89763b1419d..b94aa69e2c5f41161e8c21d68078a522d063e03d 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java -@@ -39,6 +39,18 @@ public class EntityPufferFish extends EntityFish { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.pufferfishRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return true; -+ } -+ // Purpur end -+ - @Override - protected void initDatawatcher() { - super.initDatawatcher(); -@@ -82,7 +94,7 @@ public class EntityPufferFish extends EntityFish { - @Override - protected void initPathfinder() { - super.initPathfinder(); -- this.goalSelector.a(1, new EntityPufferFish.a(this)); -+ this.goalSelector.a(2, new EntityPufferFish.a(this)); // Purpur - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java b/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java -index 180fc927074dc683ad4d482a00dd4e04ff7923d0..4660f37bc89418e0c3767305d390a53f5c0d3c55 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java -@@ -10,6 +10,7 @@ import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; - import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffect; -@@ -27,7 +28,6 @@ import net.minecraft.world.entity.GroupDataEntity; - import net.minecraft.world.entity.ai.attributes.AttributeProvider; - import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.entity.ai.control.ControllerJump; --import net.minecraft.world.entity.ai.control.ControllerMove; - import net.minecraft.world.entity.ai.goal.PathfinderGoalAvoidTarget; - import net.minecraft.world.entity.ai.goal.PathfinderGoalBreed; - import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat; -@@ -75,6 +75,18 @@ public class EntityRabbit extends EntityAnimal { - this.initializePathFinderGoals(); // CraftBukkit - moved code - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.rabbitRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.rabbitRidableInWater; -+ } -+ // Purpur end -+ - // CraftBukkit start - code from constructor - public void initializePathFinderGoals(){ - this.i(0.0D); -@@ -83,7 +95,8 @@ public class EntityRabbit extends EntityAnimal { - - @Override - public void initPathfinder() { -- this.goalSelector.a(1, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalFloat(this)); // Purpur -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new EntityRabbit.PathfinderGoalRabbitPanic(this, 2.2D)); - this.goalSelector.a(2, new PathfinderGoalBreed(this, 0.8D)); - this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.0D, RecipeItemStack.a(Items.CARROT, Items.GOLDEN_CARROT, Blocks.DANDELION), false)); -@@ -96,7 +109,15 @@ public class EntityRabbit extends EntityAnimal { - } - - @Override -- protected float dJ() { -+ // Purpur start -+ public float getJumpHeight() { -+ if (hasPurpurRider()) { -+ if (getForward() < 0) { -+ setSpeed(getForward() * 2F); -+ } -+ return actualJump ? 0.5F : 0.3F; -+ } -+ // Purpur end - if (!this.positionChanged && (!this.moveController.b() || this.moveController.e() <= this.locY() + 0.5D)) { - PathEntity pathentity = this.navigation.k(); - -@@ -115,7 +136,7 @@ public class EntityRabbit extends EntityAnimal { - } - - @Override -- protected void jump() { -+ public void jump() { // Purpur - protected -> public - super.jump(); - double d0 = this.moveController.c(); - -@@ -147,6 +168,7 @@ public class EntityRabbit extends EntityAnimal { - - } - -+ public void startJumping() { eK(); } // Purpur - OBFHELPER - public void eK() { - this.setJumping(true); - this.br = 10; -@@ -161,6 +183,13 @@ public class EntityRabbit extends EntityAnimal { - - @Override - public void mobTick() { -+ // Purpur start -+ if (hasPurpurRider()) { -+ handleJumping(); -+ return; -+ } -+ // Purpur end -+ - if (this.bt > 0) { - --this.bt; - } -@@ -211,6 +240,39 @@ public class EntityRabbit extends EntityAnimal { - this.bs = this.onGround; - } - -+ // Purpur start -+ private boolean wasOnGround; -+ private boolean actualJump; -+ -+ private void handleJumping() { -+ if (onGround) { -+ ControllerJumpRabbit jumpController = (ControllerJumpRabbit) getJumpController(); -+ if (!wasOnGround) { -+ setJumping(false); -+ jumpController.setCanJump(false); -+ } -+ if (!jumpController.isJumping()) { -+ if (moveController.b()) { // isUpdating -+ startJumping(); -+ } -+ } else if (!jumpController.canJump()) { -+ jumpController.setCanJump(true); -+ } -+ } -+ wasOnGround = onGround; -+ } -+ -+ @Override -+ public boolean onSpacebar() { -+ if (onGround) { -+ actualJump = true; -+ jump(); -+ actualJump = false; -+ } -+ return true; -+ } -+ // Purpur end -+ - @Override - public boolean aO() { - return false; -@@ -540,7 +602,7 @@ public class EntityRabbit extends EntityAnimal { - } - } - -- static class ControllerMoveRabbit extends ControllerMove { -+ static class ControllerMoveRabbit extends net.pl3x.purpur.controller.ControllerMoveWASD { // Purpur - - private final EntityRabbit i; - private double j; -@@ -551,14 +613,14 @@ public class EntityRabbit extends EntityAnimal { - } - - @Override -- public void a() { -+ public void tick() { // Purpur - if (this.i.onGround && !this.i.jumping && !((EntityRabbit.ControllerJumpRabbit) this.i.bi).c()) { - this.i.i(0.0D); - } else if (this.b()) { - this.i.i(this.j); - } - -- super.a(); -+ super.tick(); // Purpur - } - - @Override -@@ -585,14 +647,17 @@ public class EntityRabbit extends EntityAnimal { - this.c = entityrabbit; - } - -+ public boolean isJumping() { return c(); } // Purpur - OBFHELPER - public boolean c() { - return this.a; - } - -+ public boolean canJump() { return d(); } // Purpur - OBFHELPER - public boolean d() { - return this.d; - } - -+ public void setCanJump(boolean canJump) { a(canJump); } // Purpur - OBFHELPER - public void a(boolean flag) { - this.d = flag; - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySalmon.java b/src/main/java/net/minecraft/world/entity/animal/EntitySalmon.java -index ca125342f189d5db95ebd04043a2d11e5fbfd3fd..bf565671c167162b3d935447961f0d44ed4a2779 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntitySalmon.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntitySalmon.java -@@ -14,6 +14,18 @@ public class EntitySalmon extends EntityFishSchool { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.salmonRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return true; -+ } -+ // Purpur end -+ - @Override - public int eN() { - return 5; -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java b/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java -index 88bed962bc17242ee6a9c93b7e0fec8bc578b35f..8f3296031f220dd7bb3ae9fe2443e479954ebad3 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java -@@ -14,6 +14,7 @@ import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; - import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffect; -@@ -110,10 +111,23 @@ public class EntitySheep extends EntityAnimal implements IShearable { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.sheepRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.sheepRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { - this.bs = new PathfinderGoalEatTile(this); - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.25D)); - this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D)); - this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.1D, RecipeItemStack.a(Items.WHEAT), false)); -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java b/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java -index 44119f52a4f169ffcea53fb69393bfedfd1a62a7..a692b973717ecc56d808039418599a11aedc2c5a 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java -@@ -6,6 +6,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -50,12 +51,26 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.snowGolemRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.snowGolemRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new PathfinderGoalArrowAttack(this, 1.25D, 20, 10.0F)); - this.goalSelector.a(2, new PathfinderGoalRandomStrollLand(this, 1.0D, 1.0000001E-5F)); - this.goalSelector.a(3, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F)); - this.goalSelector.a(4, new PathfinderGoalRandomLookaround(this)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityInsentient.class, 10, true, false, (entityliving) -> { - return entityliving instanceof IMonster; - })); -@@ -107,6 +122,7 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt - return; - } - -+ if (hasPurpurRider() && !world.purpurConfig.snowGolemLeaveTrailWhenRidden) return; // Purpur - don't leave snow trail when being ridden - IBlockData iblockdata = Blocks.SNOW.getBlockData(); - - for (int l = 0; l < 4; ++l) { -@@ -149,7 +165,7 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt - if (itemstack.getItem() == Items.SHEARS && this.canShear()) { - // CraftBukkit start - if (!CraftEventFactory.handlePlayerShearEntityEvent(entityhuman, this, itemstack, enumhand)) { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); // Purpur - } - // CraftBukkit end - this.shear(SoundCategory.PLAYERS); -@@ -169,7 +185,7 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt - return EnumInteractionResult.SUCCESS; - // Purpur end - } else { -- return EnumInteractionResult.PASS; -+ return tryRide(entityhuman, enumhand); // Purpur - } - } - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -index e6757b22497c6e274c3999d58671653e931ebe2b..777c3bcf267d6cf31300588826d3af6b55cab350 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -@@ -4,6 +4,7 @@ package net.minecraft.world.entity.animal; - import java.util.Random; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.particles.Particles; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -23,6 +24,7 @@ import net.minecraft.world.entity.EnumMoveType; - import net.minecraft.world.entity.ai.attributes.AttributeProvider; - import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.level.GeneratorAccess; - import net.minecraft.world.level.World; - import net.minecraft.world.level.block.state.IBlockData; -@@ -54,17 +56,38 @@ public class EntitySquid extends EntityWaterAnimal { - } - - // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.squidRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return true; -+ } -+ - @Override - public AxisAlignedBB getAxisForFluidCheck() { - // Stops squids from floating just over the water - return this.getBoundingBox().shrink(0.001D).offsetY(world.purpurConfig.squidOffsetWaterCheck); - } -+ -+ private void rotateVectorAroundY(org.bukkit.util.Vector vector, double degrees) { -+ double rad = Math.toRadians(degrees); -+ double cos = Math.cos(rad); -+ double sine = Math.sin(rad); -+ double x = vector.getX(); -+ double z = vector.getZ(); -+ vector.setX(cos * x - sine * z); -+ vector.setZ(sine * x + cos * z); -+ } - // Purpur end - - @Override - protected void initPathfinder() { - this.goalSelector.a(0, new EntitySquid.PathfinderGoalSquid(this)); -- this.goalSelector.a(1, new EntitySquid.a()); -+ this.goalSelector.a(1, new PathfinderGoalHasRider(this)); // Purpur -+ this.goalSelector.a(2, new EntitySquid.a()); // Purpur - } - - public static AttributeProvider.Builder m() { -@@ -209,6 +232,7 @@ public class EntitySquid extends EntityWaterAnimal { - return blockposition.getY() > generatoraccess.getMinecraftWorld().spigotConfig.squidSpawnRangeMin && blockposition.getY() < maxHeight; // Spigot // Paper - } - -+ public void setMovementVector(float x, float y, float z) { a(x, y, z); } // Purpur - OBFHELPER - public void a(float f, float f1, float f2) { - this.bw = f; - this.bx = f1; -@@ -280,7 +304,7 @@ public class EntitySquid extends EntityWaterAnimal { - - class PathfinderGoalSquid extends PathfinderGoal { - -- private final EntitySquid b; -+ private final EntitySquid b; public EntitySquid getSquid() { return b; } // Purpur - OBFHELPER - - public PathfinderGoalSquid(EntitySquid entitysquid) { - this.b = entitysquid; -@@ -293,6 +317,38 @@ public class EntitySquid extends EntityWaterAnimal { - - @Override - public void e() { -+ // Purpur start -+ EntitySquid squid = getSquid(); -+ EntityHuman rider = squid.getPurpurRider(); -+ if (rider != null) { -+ if (rider.jumping) { -+ squid.onSpacebar(); -+ } -+ float forward = rider.getForward(); -+ float strafe = rider.getStrafe(); -+ float speed = (float) squid.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getValue() * 10F; -+ if (forward < 0.0F) { -+ speed *= -0.5; -+ } -+ org.bukkit.util.Vector dir = rider.getBukkitEntity().getEyeLocation().getDirection().normalize().multiply(speed / 20.0F); -+ if (strafe != 0.0F) { -+ if (forward == 0.0F) { -+ dir.setY(0); -+ rotateVectorAroundY(dir, strafe > 0.0F ? -90 : 90); -+ } else if (forward < 0.0F) { -+ rotateVectorAroundY(dir, strafe > 0.0F ? 45 : -45); -+ } else { -+ rotateVectorAroundY(dir, strafe > 0.0F ? -45 : 45); -+ } -+ } -+ if (forward != 0.0F || strafe != 0.0F) { -+ squid.setMovementVector((float) dir.getX(), (float) dir.getY(), (float) dir.getZ()); -+ } else { -+ squid.setMovementVector(0.0F, 0.0F, 0.0F); -+ } -+ return; -+ } -+ // Purpur end - int i = this.b.dd(); - - if (i > 100) { -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTropicalFish.java b/src/main/java/net/minecraft/world/entity/animal/EntityTropicalFish.java -index 29f6835da58c73a99fe620d6de7d86fede6ac893..478e55475ccc1410a442f4e30a1cbc08f479dbda 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityTropicalFish.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityTropicalFish.java -@@ -37,6 +37,18 @@ public class EntityTropicalFish extends EntityFishSchool { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.tropicalFishRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return true; -+ } -+ // Purpur end -+ - @Override - protected void initDatawatcher() { - super.initDatawatcher(); -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -index ecec8a3c4d4b5d491f79ad60d7ce5a118f30b3db..28d6e673f55fc8fae40dff4a96ac2c2b5eeab9d6 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -@@ -15,6 +15,7 @@ import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; - import net.minecraft.server.MCUtil; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundCategory; -@@ -90,6 +91,18 @@ public class EntityTurtle extends EntityAnimal { - this.G = 1.0F; - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.turtleRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.turtleRidableInWater; -+ } -+ // Purpur end -+ - public void setHomePos(BlockPosition blockposition) { - this.datawatcher.set(EntityTurtle.bp, blockposition.immutableCopy()); // Paper - called with mutablepos... - } -@@ -198,12 +211,13 @@ public class EntityTurtle extends EntityAnimal { - - @Override - protected void initPathfinder() { -- this.goalSelector.a(0, new EntityTurtle.f(this, 1.2D)); -- this.goalSelector.a(1, new EntityTurtle.a(this, 1.0D)); -- this.goalSelector.a(1, new EntityTurtle.d(this, 1.0D)); -- this.goalSelector.a(2, new EntityTurtle.i(this, 1.1D, Blocks.SEAGRASS.getItem())); -- this.goalSelector.a(3, new EntityTurtle.c(this, 1.0D)); -- this.goalSelector.a(4, new EntityTurtle.b(this, 1.0D)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur -+ this.goalSelector.a(1, new EntityTurtle.f(this, 1.2D)); // Purpur -+ this.goalSelector.a(2, new EntityTurtle.a(this, 1.0D)); // Purpur -+ this.goalSelector.a(2, new EntityTurtle.d(this, 1.0D)); // Purpur -+ this.goalSelector.a(3, new EntityTurtle.i(this, 1.1D, Blocks.SEAGRASS.getItem())); // Purpur -+ this.goalSelector.a(4, new EntityTurtle.c(this, 1.0D)); // Purpur -+ this.goalSelector.a(5, new EntityTurtle.b(this, 1.0D)); // Purpur - this.goalSelector.a(7, new EntityTurtle.j(this, 1.0D)); - this.goalSelector.a(8, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(9, new EntityTurtle.h(this, 1.0D, 100)); -@@ -386,13 +400,15 @@ public class EntityTurtle extends EntityAnimal { - } - } - -- static class e extends ControllerMove { -+ static class e extends net.pl3x.purpur.controller.ControllerMoveWASD { // Purpur - -- private final EntityTurtle i; -+ private final EntityTurtle i; public EntityTurtle getTurtle() { return i; } // Purpur - OBFHELPER -+ private final net.pl3x.purpur.controller.ControllerMoveWASDWater waterController; // Purpur - - e(EntityTurtle entityturtle) { -- super(entityturtle); -+ super(entityturtle, 0.1D); // Purpur - this.i = entityturtle; -+ waterController = new net.pl3x.purpur.controller.ControllerMoveWASDWater(entityturtle, 0.25D); // Purpur - } - - private void g() { -@@ -412,7 +428,18 @@ public class EntityTurtle extends EntityAnimal { - } - - @Override -- public void a() { -+ // Purpur start -+ public void tick(EntityHuman rider) { -+ if (getTurtle().isInWater()) { -+ waterController.tick(rider); -+ } else { -+ super.tick(rider); -+ } -+ } -+ -+ @Override -+ public void tick() { -+ // Purpur end - this.g(); - if (this.h == ControllerMove.Operation.MOVE_TO && !this.i.getNavigation().m()) { - double d0 = this.b - this.i.locX(); -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java b/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java -index b44b1544f401c1a5127bed3239bfd60420d17329..3fbd8f9122d7a5ac23af4d872f877030644ef86a 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java -@@ -9,6 +9,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -91,9 +92,27 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable - this.setTamed(false); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.wolfRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.wolfRidableInWater; -+ } -+ -+ public void onMount(EntityHuman entityhuman) { -+ super.onMount(entityhuman); -+ setSitting(false); -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { - this.goalSelector.a(1, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(1, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(2, new PathfinderGoalSit(this)); - this.goalSelector.a(3, new EntityWolf.a<>(this, EntityLlama.class, 24.0F, 1.5D, 1.5D)); - this.goalSelector.a(4, new PathfinderGoalLeapAtTarget(this, 0.4F)); -@@ -104,6 +123,7 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable - this.goalSelector.a(9, new PathfinderGoalBeg(this, 8.0F)); - this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(10, new PathfinderGoalRandomLookaround(this)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new PathfinderGoalOwnerHurtByTarget(this)); - this.targetSelector.a(2, new PathfinderGoalOwnerHurtTarget(this)); - this.targetSelector.a(3, (new PathfinderGoalHurtByTarget(this, new Class[0])).a(new Class[0])); // CraftBukkit - decompile error -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java -index 48f67652a0a6797e217ce1f6040b5dc0f7a74938..650f13b1133e4c61f71b36f3f91a9d2913996435 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java -@@ -41,6 +41,13 @@ public class EntityHorse extends EntityHorseAbstract { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.horseRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void eK() { - this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue((double) this.fp()); -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -index cb6e2053d1315b65812e7bff8a17988b5b8ab0e4..d4556fa190c754406d0c65baae941fb23af3f81f 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -@@ -14,6 +14,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHorseHasRider; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.server.players.NameReferencingFileConverter; -@@ -43,6 +44,8 @@ import net.minecraft.world.entity.IJumpable; - import net.minecraft.world.entity.ISaddleable; - import net.minecraft.world.entity.ai.attributes.AttributeProvider; - import net.minecraft.world.entity.ai.attributes.GenericAttributes; -+import net.minecraft.world.entity.ai.control.ControllerLook; -+import net.minecraft.world.entity.ai.control.ControllerMove; - import net.minecraft.world.entity.ai.goal.PathfinderGoalBreed; - import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat; - import net.minecraft.world.entity.ai.goal.PathfinderGoalFollowParent; -@@ -101,12 +104,27 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven - - protected EntityHorseAbstract(EntityTypes entitytypes, World world) { - super(entitytypes, world); -+ this.moveController = new ControllerMove(this); // Purpur - use vanilla controller -+ this.lookController = new ControllerLook(this); // Purpur - use vanilla controller - this.G = 1.0F; - this.loadChest(); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return false; // vanilla handles -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return false; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { -+ this.goalSelector.a(0, new PathfinderGoalHorseHasRider(this)); // Purpur - this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.2D)); - this.goalSelector.a(1, new PathfinderGoalTame(this, 1.2D)); - this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D, EntityHorseAbstract.class)); -@@ -114,6 +132,7 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven - this.goalSelector.a(6, new PathfinderGoalRandomStrollLand(this, 0.7D)); - this.goalSelector.a(7, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F)); - this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this)); -+ this.targetSelector.a(0, new PathfinderGoalHorseHasRider(this)); // Purpur - this.eV(); - } - -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java -index d9c87411f5c636bee3f28b724abf665826788be4..50700bf85a296b87fe3155651f869e2bbdb0875d 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java -@@ -16,6 +16,13 @@ public class EntityHorseDonkey extends EntityHorseChestedAbstract { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.donkeyRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected SoundEffect getSoundAmbient() { - super.getSoundAmbient(); -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java -index 7a5c14c1e80bde623473a39acb01b78b79d593e4..b6385a23050296611dbc8864b92d2cdd8321a1d0 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java -@@ -15,6 +15,12 @@ public class EntityHorseMule extends EntityHorseChestedAbstract { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.muleRidableInWater; -+ } -+ // Purpur end - @Override - protected SoundEffect getSoundAmbient() { - super.getSoundAmbient(); -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java -index da5365372e89b847d626e52c5541544467f14702..d21399fbb6ddc4f26a7509ce547f8c4ad6458089 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java -@@ -17,6 +17,7 @@ import net.minecraft.world.entity.EnumMonsterType; - import net.minecraft.world.entity.ai.attributes.AttributeProvider; - import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.Items; -@@ -32,6 +33,18 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.skeletonHorseRidableInWater; -+ } -+ -+ @Override -+ public boolean isTamed() { -+ return true; -+ } -+ // Purpur end -+ - public static AttributeProvider.Builder eL() { - return fi().a(GenericAttributes.MAX_HEALTH, 15.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.20000000298023224D); - } -@@ -42,7 +55,7 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { - } - - @Override -- protected void eV() {} -+ protected void eV() { if (world.purpurConfig.skeletonHorseCanSwim) goalSelector.a(0, new PathfinderGoalFloat(this)); } // Purpur - - @Override - protected SoundEffect getSoundAmbient() { -@@ -137,7 +150,7 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { - - @Override - public boolean bt() { -- return true; -+ return super.bt(); // Purpur - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java -index 2e448a40dbf2fa5b4df4493f14738210615bab38..d57e7c02268e5d8a00b0b5897fa03dcee10cd2e0 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java -@@ -13,6 +13,7 @@ import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.EnumMonsterType; - import net.minecraft.world.entity.ai.attributes.AttributeProvider; - import net.minecraft.world.entity.ai.attributes.GenericAttributes; -+import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.Items; -@@ -24,6 +25,18 @@ public class EntityHorseZombie extends EntityHorseAbstract { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.zombieHorseRidableInWater; -+ } -+ -+ @Override -+ public boolean isTamed() { -+ return true; -+ } -+ // Purpur end -+ - public static AttributeProvider.Builder eL() { - return fi().a(GenericAttributes.MAX_HEALTH, 15.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.20000000298023224D); - } -@@ -95,5 +108,5 @@ public class EntityHorseZombie extends EntityHorseAbstract { - } - - @Override -- protected void eV() {} -+ protected void eV() { if (world.purpurConfig.zombieHorseCanSwim) goalSelector.a(0, new PathfinderGoalFloat(this)); } // Purpur - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java -index 1c6435bf2cd870b795f87368057d8dfc1e1c938a..d25177f9500a084e0f18a20b1eb1c4ac170048ec 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java -@@ -8,6 +8,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHorseHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -68,7 +69,46 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn - - public EntityLlama(EntityTypes entitytypes, World world) { - super(entitytypes, world); -+ // Purpur start -+ this.moveController = new net.pl3x.purpur.controller.ControllerMoveWASD(this) { -+ @Override -+ public void a() { // tick -+ if (entity.hasPurpurRider() && hasSaddle()) { -+ tick(entity.getPurpurRider()); -+ } else { -+ tick(); -+ } -+ } -+ }; -+ this.lookController = new net.pl3x.purpur.controller.ControllerLookWASD(this) { -+ @Override -+ public void a() { // tick -+ if (entity.hasPurpurRider() && hasSaddle()) { -+ tick(entity.getPurpurRider()); -+ } else { -+ tick(); -+ } -+ } -+ }; -+ // Purpur end -+ } -+ -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.llamaRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.llamaRidableInWater; -+ } -+ -+ @Override -+ public boolean hasSaddle() { -+ return super.hasSaddle() || (isTamed() && getColor() != null); - } -+ // Purpur end - - public void setStrength(int i) { - this.datawatcher.set(EntityLlama.bx, Math.max(1, Math.min(5, i))); -@@ -116,6 +156,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn - @Override - protected void initPathfinder() { - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHorseHasRider(this)); // Purpur - this.goalSelector.a(1, new PathfinderGoalTame(this, 1.2D)); - this.goalSelector.a(2, new PathfinderGoalLlamaFollow(this, 2.0999999046325684D)); - this.goalSelector.a(3, new PathfinderGoalArrowAttack(this, 1.25D, 40, 20.0F)); -@@ -125,6 +166,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn - this.goalSelector.a(6, new PathfinderGoalRandomStrollLand(this, 0.7D)); - this.goalSelector.a(7, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F)); - this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this)); -+ this.targetSelector.a(0, new PathfinderGoalHorseHasRider(this)); // Purpur - this.targetSelector.a(1, new EntityLlama.c(this)); - this.targetSelector.a(2, new EntityLlama.a(this)); - } -@@ -362,7 +404,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn - } - - @Nullable -- public EnumColor fy() { -+ public EnumColor fy() { return getColor(); } public EnumColor getColor() { // Purpur - OBFHELPER - int i = (Integer) this.datawatcher.get(EntityLlama.by); - - return i == -1 ? null : EnumColor.fromColorIndex(i); -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.java -index f761e37f7329342f01f04df5602573a51c0aca4e..0fb651bcde1109b0eb30b60226d3512648dceb41 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.java -@@ -27,6 +27,23 @@ public class EntityLlamaTrader extends EntityLlama { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.llamaTraderRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.llamaTraderRidableInWater; -+ } -+ -+ @Override -+ public boolean hasSaddle() { -+ return super.hasSaddle() || isTamed(); -+ } -+ // Purpur end -+ - @Override - protected EntityLlama fz() { - return (EntityLlama) EntityTypes.TRADER_LLAMA.a(this.world); -diff --git a/src/main/java/net/minecraft/world/entity/boss/EntityComplexPart.java b/src/main/java/net/minecraft/world/entity/boss/EntityComplexPart.java -index f1065c2a37835d760fb57194f7edfd029f426b48..3f2065e2939be54639f44501f7aa8ee5500dfc84 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/EntityComplexPart.java -+++ b/src/main/java/net/minecraft/world/entity/boss/EntityComplexPart.java -@@ -2,11 +2,14 @@ package net.minecraft.world.entity.boss; - - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.world.EnumHand; -+import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityPose; - import net.minecraft.world.entity.EntitySize; - import net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon; -+import net.minecraft.world.entity.player.EntityHuman; - - public class EntityComplexPart extends Entity { - -@@ -55,4 +58,11 @@ public class EntityComplexPart extends Entity { - public EntitySize a(EntityPose entitypose) { - return this.d; - } -+ -+ // Purpur start -+ @Override -+ public EnumInteractionResult a(EntityHuman entityhuman, EnumHand enumhand) { -+ return owner.isAlive() ? owner.tryRide(entityhuman, enumhand) : EnumInteractionResult.PASS; -+ } -+ // Purpur end - } -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -index 58b9ace88793d1f661b16db1b43433484a697936..ad7a9e43e4031054267bb2d18c97d79ce7b16c75 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -@@ -23,6 +23,7 @@ import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityExperienceOrb; - import net.minecraft.world.entity.EntityInsentient; - import net.minecraft.world.entity.EntityLiving; -+import net.minecraft.world.entity.EntitySize; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.EnumMoveType; - import net.minecraft.world.entity.IEntitySelector; -@@ -95,6 +96,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - private final int[] bK = new int[24]; - private final Path bL = new Path(); - private Explosion explosionSource = new Explosion(null, this, null, null, Double.NaN, Double.NaN, Double.NaN, Float.NaN, true, Explosion.Effect.DESTROY); // CraftBukkit - reusable source for CraftTNTPrimed.getSource() -+ private boolean hadRider; // Purpur - - public EntityEnderDragon(EntityTypes entitytypes, World world) { - super(EntityTypes.ENDER_DRAGON, world); -@@ -109,8 +111,44 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - } - - this.bG = new DragonControllerManager(this); -+ // Purpur start -+ this.moveController = new net.pl3x.purpur.controller.ControllerMoveWASDFlying(this) { -+ @Override -+ public void tick() { -+ // dragon doesn't use the controller. do nothing -+ } -+ }; -+ this.lookController = new net.pl3x.purpur.controller.ControllerLookWASD(this) { -+ @Override -+ public void tick() { -+ // dragon doesn't use the controller. do nothing -+ } -+ -+ @Override -+ public void tick(EntityHuman rider) { -+ setYawPitch(rider.yaw - 180F, rider.pitch * 0.5F); -+ } -+ }; -+ // Purpur end -+ } -+ -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.enderDragonRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.enderDragonRidableInWater; - } - -+ @Override -+ public double getMaxY() { -+ return world.purpurConfig.enderDragonMaxY; -+ } -+ // Purpur end -+ - public static AttributeProvider.Builder m() { - return EntityInsentient.p().a(GenericAttributes.MAX_HEALTH, 200.0D); - } -@@ -143,6 +181,37 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - - @Override - public void movementTick() { -+ // Purpur start -+ boolean hasRider = getPurpurRider() != null; -+ if (hasRider) { -+ if (!hadRider) { -+ hadRider = true; -+ noclip = false; -+ this.size = EntitySize.b(4.0F, 2.0F); -+ } -+ -+ // dragon doesn't use controllers, so must tick manually -+ moveController.a(); -+ lookController.a(); -+ -+ moveRelative((float) getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getValue() * 0.1F, new Vec3D(-getStrafe(), getVertical(), -getForward())); -+ Vec3D mot = getMot(); -+ setMot(mot); -+ move(EnumMoveType.PLAYER, mot); -+ -+ mot = mot.multiply(0.9F, 0.9F, 0.9F); -+ setMot(mot); -+ -+ // control wing flap speed on client -+ getDragonControllerManager().setControllerPhase(mot.getX() * mot.getX() + mot.getZ() * mot.getZ() < 0.005F ? DragonControllerPhase.HOVER : DragonControllerPhase.HOLDING_PATTERN); -+ } else if (hadRider) { -+ hadRider = false; -+ noclip = true; -+ this.size = EntitySize.b(16.0F, 8.0F); -+ getDragonControllerManager().setControllerPhase(DragonControllerPhase.HOLDING_PATTERN); // HoldingPattern -+ } -+ // Purpur end -+ - float f; - float f1; - -@@ -164,6 +233,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - - this.bp = this.bq; - if (this.dl()) { -+ if (hasRider) ejectPassengers(); // Purpur - f = (this.random.nextFloat() - 0.5F) * 8.0F; - f1 = (this.random.nextFloat() - 0.5F) * 4.0F; - float f2 = (this.random.nextFloat() - 0.5F) * 8.0F; -@@ -175,9 +245,9 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - - f1 = 0.2F / (MathHelper.sqrt(c(vec3d)) * 10.0F + 1.0F); - f1 *= (float) Math.pow(2.0D, vec3d.y); -- if (this.bG.a().a()) { -+ if (!hasRider && this.bG.a().a()) { // Purpur - this.bq += 0.1F; -- } else if (this.br) { -+ } else if (!hasRider && this.br) { // Purpur - this.bq += f1 * 0.5F; - } else { - this.bq += f1; -@@ -221,7 +291,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - } - - this.bG.a().b(); -- } else { -+ } else if (!hasRider) { // Purpur - IDragonController idragoncontroller = this.bG.a(); - - idragoncontroller.c(); -@@ -288,7 +358,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - this.a(this.bz, (double) (f11 * 0.5F), 0.0D, (double) (-f12 * 0.5F)); - this.a(this.bD, (double) (f12 * 4.5F), 2.0D, (double) (f11 * 4.5F)); - this.a(this.bE, (double) (f12 * -4.5F), 2.0D, (double) (f11 * -4.5F)); -- if (!this.world.isClientSide && this.hurtTicks == 0) { -+ if (!hasRider && !this.world.isClientSide && this.hurtTicks == 0) { // Purpur - this.a(this.world.getEntities(this, this.bD.getBoundingBox().grow(4.0D, 2.0D, 4.0D).d(0.0D, -2.0D, 0.0D), IEntitySelector.e)); - this.a(this.world.getEntities(this, this.bE.getBoundingBox().grow(4.0D, 2.0D, 4.0D).d(0.0D, -2.0D, 0.0D), IEntitySelector.e)); - this.b(this.world.getEntities(this, this.bo.getBoundingBox().g(1.0D), IEntitySelector.e)); -@@ -331,7 +401,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - } - - if (!this.world.isClientSide) { -- this.br = this.b(this.bo.getBoundingBox()) | this.b(this.by.getBoundingBox()) | this.b(this.bz.getBoundingBox()); -+ this.br = !hasRider && this.b(this.bo.getBoundingBox()) | this.b(this.by.getBoundingBox()) | this.b(this.bz.getBoundingBox()); // Purpur - if (this.bF != null) { - this.bF.b(this); - } -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -index 635b1493eeb6c13cc5ef489bd747ac557bc131d8..8afb710441466918a7c97bd1daffafc48899decc 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -@@ -12,6 +12,7 @@ import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.BossBattleServer; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.sounds.SoundEffect; -@@ -20,6 +21,7 @@ import net.minecraft.tags.TagsBlock; - import net.minecraft.util.MathHelper; - import net.minecraft.world.BossBattle; - import net.minecraft.world.EnumDifficulty; -+import net.minecraft.world.EnumHand; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.effect.MobEffect; - import net.minecraft.world.effect.MobEffects; -@@ -28,6 +30,7 @@ import net.minecraft.world.entity.EntityInsentient; - import net.minecraft.world.entity.EntityLiving; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.EnumMonsterType; -+import net.minecraft.world.entity.EnumMoveType; - import net.minecraft.world.entity.ai.attributes.AttributeProvider; - import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.entity.ai.goal.PathfinderGoal; -@@ -48,14 +51,16 @@ import net.minecraft.world.item.Items; - import net.minecraft.world.level.Explosion; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.IMaterial; -+import net.minecraft.world.level.RayTrace; - import net.minecraft.world.level.World; - import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.world.phys.MovingObjectPosition; -+import net.minecraft.world.phys.MovingObjectPositionBlock; -+import net.minecraft.world.phys.MovingObjectPositionEntity; - import net.minecraft.world.phys.Vec3D; - - // CraftBukkit start - import net.minecraft.network.protocol.game.PacketPlayOutWorldEvent; --import net.minecraft.server.MinecraftServer; --import net.minecraft.server.level.WorldServer; - import net.minecraft.world.level.block.Blocks; - import org.bukkit.craftbukkit.event.CraftEventFactory; - import org.bukkit.event.entity.EntityRegainHealthEvent; -@@ -82,6 +87,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - return entityliving.getMonsterType() != EnumMonsterType.UNDEAD && entityliving.ei(); - }; - private static final PathfinderTargetCondition bz = (new PathfinderTargetCondition()).a(20.0D).a(EntityWither.by); -+ private int shootCooldown = 0; // Purpur - // Paper start - private boolean canPortal = false; - -@@ -94,15 +100,122 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - this.setHealth(this.getMaxHealth()); - this.getNavigation().d(true); - this.f = 50; -+ this.moveController = new net.pl3x.purpur.controller.ControllerMoveWASDFlyingWithSpacebar(this, 0.1F); // Purpur - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.witherRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.witherRidableInWater; -+ } -+ -+ @Override -+ public double getMaxY() { -+ return world.purpurConfig.witherMaxY; -+ } -+ -+ @Override -+ public void g(Vec3D vec3d) { -+ super.g(vec3d); -+ if (hasPurpurRider() && !onGround) { -+ float speed = (float) getAttributeInstance(GenericAttributes.FLYING_SPEED).getValue() * 5F; -+ setSpeed(speed); -+ Vec3D mot = getMot(); -+ move(EnumMoveType.SELF, mot.multiply(speed, 0.5, speed)); -+ setMot(mot.a(0.9D)); -+ } -+ } -+ -+ @Override -+ public void onMount(EntityHuman entityhuman) { -+ super.onMount(entityhuman); -+ this.datawatcher.set(bo.get(0), 0); -+ this.datawatcher.set(bo.get(1), 0); -+ this.datawatcher.set(bo.get(2), 0); -+ getNavigation().stopPathfinding(); -+ shootCooldown = 20; -+ } -+ -+ @Override -+ public boolean onClick(EnumHand hand) { -+ return shoot(getPurpurRider(), hand == EnumHand.MAIN_HAND ? new int[]{1} : new int[]{2}); -+ } -+ -+ public boolean shoot(EntityHuman rider, int[] heads) { -+ if (shootCooldown > 0) { -+ return false; -+ } -+ -+ shootCooldown = 20; -+ if (rider == null) { -+ return false; -+ } -+ -+ org.bukkit.craftbukkit.entity.CraftHumanEntity player = rider.getBukkitEntity(); -+ if (!player.hasPermission("allow.special.wither")) { -+ return false; -+ } -+ -+ MovingObjectPosition rayTrace = getRayTrace(120, RayTrace.FluidCollisionOption.NONE); -+ if (rayTrace == null) { -+ return false; -+ } -+ -+ Vec3D loc; -+ if (rayTrace.getType() == MovingObjectPosition.EnumMovingObjectType.BLOCK) { -+ BlockPosition pos = ((MovingObjectPositionBlock) rayTrace).getBlockPosition(); -+ loc = new Vec3D(pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D); -+ } else if (rayTrace.getType() == MovingObjectPosition.EnumMovingObjectType.ENTITY) { -+ Entity target = ((MovingObjectPositionEntity) rayTrace).getEntity(); -+ loc = new Vec3D(target.locX(), target.locY() + (target.getHeadHeight() / 2), target.locZ()); -+ } else { -+ org.bukkit.block.Block block = player.getTargetBlock(null, 120); -+ loc = new Vec3D(block.getX() + 0.5D, block.getY() + 0.5D, block.getZ() + 0.5D); -+ } -+ -+ for (int head : heads) { -+ shoot(head, loc.getX(), loc.getY(), loc.getZ(), rider); -+ } -+ -+ return true; // handled -+ } -+ -+ public void shoot(int head, double x, double y, double z, EntityHuman rider) { -+ world.playEvent(null, 1024, getChunkCoordinates(), 0); -+ double headX = getHeadX(head); -+ double headY = getHeadY(head); -+ double headZ = getHeadZ(head); -+ EntityWitherSkull skull = new EntityWitherSkull(world, this, x - headX, y - headY, z - headZ) { -+ @Override -+ public boolean canSaveToDisk() { -+ return false; -+ } -+ -+ @Override -+ public boolean hitPredicate(Entity target) { -+ // do not hit rider -+ return target != rider && super.hitPredicate(target); -+ } -+ }; -+ skull.setPositionRaw(headX, headY, headZ); -+ world.addEntity(skull); -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { -- this.goalSelector.a(0, new EntityWither.a()); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur -+ this.goalSelector.a(1, new EntityWither.a()); // Purpur - this.goalSelector.a(2, new PathfinderGoalArrowAttack(this, 1.0D, 40, 20.0F)); - this.goalSelector.a(5, new PathfinderGoalRandomStrollLand(this, 1.0D)); - this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(7, new PathfinderGoalRandomLookaround(this)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, new Class[0])); - if(this.world.paperConfig.fixWitherTargetingBug) this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 0, false, false, null)); // Paper - Fix MC-29274 - this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityInsentient.class, 0, false, false, EntityWither.by)); -@@ -245,6 +358,16 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - - @Override - protected void mobTick() { -+ // Purpur start -+ if (hasPurpurRider()) { -+ Vec3D mot = getMot(); -+ setMot(mot.x, mot.y + (getVertical() > 0 ? 0.07D : 0.0D), mot.z); -+ } -+ if (shootCooldown > 0) { -+ shootCooldown--; -+ } -+ // Purpur end -+ - int i; - - if (this.getInvul() > 0) { -@@ -428,7 +551,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - this.bossBattle.removePlayer(entityplayer); - } - -- private double u(int i) { -+ private double u(int i) { return getHeadX(i); } private double getHeadX(int i) { // Purpur - OBFHELPER - if (i <= 0) { - return this.locX(); - } else { -@@ -439,11 +562,11 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - } - } - -- private double v(int i) { -+ private double v(int i) { return getHeadY(i); } private double getHeadY(int i) { // Purpur - OBFHELPER - return i <= 0 ? this.locY() + 3.0D : this.locY() + 2.2D; - } - -- private double w(int i) { -+ private double w(int i) { return getHeadZ(i); } private double getHeadZ(int i) { // Purpur - OBFHELPER - if (i <= 0) { - return this.locZ(); - } else { -@@ -567,7 +690,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - } - - public static AttributeProvider.Builder eK() { -- return EntityMonster.eR().a(GenericAttributes.MAX_HEALTH, 300.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.6000000238418579D).a(GenericAttributes.FOLLOW_RANGE, 40.0D).a(GenericAttributes.ARMOR, 4.0D); -+ return EntityMonster.eR().a(GenericAttributes.MAX_HEALTH, 300.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.6000000238418579D).a(GenericAttributes.FOLLOW_RANGE, 40.0D).a(GenericAttributes.ARMOR, 4.0D).a(GenericAttributes.FLYING_SPEED, 0.6D); // Purpur - } - - public int getInvul() { -@@ -579,11 +702,11 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - } - - public int getHeadTarget(int i) { -- return (Integer) this.datawatcher.get((DataWatcherObject) EntityWither.bo.get(i)); -+ return hasPurpurRider() ? 0 : this.datawatcher.get(EntityWither.bo.get(i)); // Purpur - } - - public void setHeadTarget(int i, int j) { -- this.datawatcher.set((DataWatcherObject) EntityWither.bo.get(i), j); -+ if (!hasPurpurRider()) this.datawatcher.set(EntityWither.bo.get(i), j); // Purpur - } - - public final boolean isPowered() { return this.S_(); } // Paper - OBFHELPER -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java b/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java -index 88a4dcf9feaa5f66da1394c139b795582c00a8ac..6553fd92c26d71ac0a60bd046c7f968f2dfe6667 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java -@@ -5,6 +5,7 @@ import net.minecraft.core.particles.Particles; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.util.MathHelper; -@@ -12,6 +13,7 @@ import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityLiving; - import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.entity.EnumMoveType; - import net.minecraft.world.entity.ai.attributes.AttributeProvider; - import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.entity.ai.goal.PathfinderGoal; -@@ -35,6 +37,7 @@ public class EntityBlaze extends EntityMonster { - - public EntityBlaze(EntityTypes entitytypes, World world) { - super(entitytypes, world); -+ this.moveController = new net.pl3x.purpur.controller.ControllerMoveWASDFlyingWithSpacebar(this, 0.3F); // Purpur - this.a(PathType.WATER, -1.0F); - this.a(PathType.LAVA, 8.0F); - this.a(PathType.DANGER_FIRE, 0.0F); -@@ -42,19 +45,50 @@ public class EntityBlaze extends EntityMonster { - this.f = 10; - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.blazeRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.blazeRidableInWater; -+ } -+ -+ @Override -+ public double getMaxY() { -+ return world.purpurConfig.blazeMaxY; -+ } -+ -+ @Override -+ public void g(Vec3D vec3d) { -+ super.g(vec3d); -+ if (hasPurpurRider() && !onGround) { -+ float speed = (float) getAttributeInstance(GenericAttributes.FLYING_SPEED).getValue(); -+ setSpeed(speed); -+ Vec3D mot = getMot(); -+ move(EnumMoveType.SELF, mot.multiply(speed, 1.0, speed)); -+ setMot(mot.a(0.9D)); -+ } -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(4, new EntityBlaze.PathfinderGoalBlazeFireball(this)); - this.goalSelector.a(5, new PathfinderGoalMoveTowardsRestriction(this, 1.0D)); - this.goalSelector.a(7, new PathfinderGoalRandomStrollLand(this, 1.0D, 0.0F)); - this.goalSelector.a(8, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this)); -- this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[0])).a()); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur -+ this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[0])).a(new Class[0])); // Purpur - decompile error - this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); - } - - public static AttributeProvider.Builder m() { -- return EntityMonster.eR().a(GenericAttributes.ATTACK_DAMAGE, 6.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.23000000417232513D).a(GenericAttributes.FOLLOW_RANGE, 48.0D); -+ return EntityMonster.eR().a(GenericAttributes.ATTACK_DAMAGE, 6.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.23000000417232513D).a(GenericAttributes.FOLLOW_RANGE, 48.0D).a(GenericAttributes.FLYING_SPEED, 0.6D); // Purpur - } - - @Override -@@ -109,6 +143,14 @@ public class EntityBlaze extends EntityMonster { - - @Override - protected void mobTick() { -+ // Purpur start -+ if (hasPurpurRider()) { -+ Vec3D mot = getMot(); -+ setMot(mot.x, getVertical() > 0 ? 0.07D : -0.07D, mot.z); -+ return; -+ } -+ // Purpur end -+ - --this.c; - if (this.c <= 0) { - this.c = 100; -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCaveSpider.java b/src/main/java/net/minecraft/world/entity/monster/EntityCaveSpider.java -index 65d0027186f19f10292ea64976ebb93c12b98394..27baf5cde99d8f25b1e7583c30339fcc71a3786f 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityCaveSpider.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityCaveSpider.java -@@ -24,6 +24,18 @@ public class EntityCaveSpider extends EntitySpider { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.caveSpiderRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.caveSpiderRidableInWater; -+ } -+ // Purpur end -+ - public static AttributeProvider.Builder m() { - return EntitySpider.eK().a(GenericAttributes.MAX_HEALTH, 12.0D); - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -index 09df2bd3b523072de0e9858e6e707e3721474422..1daacdd75c709cd5508434b41589bd57032de27c 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -@@ -6,6 +6,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -58,12 +59,27 @@ public class EntityCreeper extends EntityMonster { - public int maxFuseTicks = 30; - public int explosionRadius = 3; - private int bs; -+ // Purpur start -+ private int spacebarCharge = 0; -+ private int prevSpacebarCharge = 0; -+ private int powerToggleDelay = 0; -+ // Purpur end - - public EntityCreeper(EntityTypes entitytypes, World world) { - super(entitytypes, world); - } - - // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.creeperRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.creeperRidableInWater; -+ } -+ - @Override - public GroupDataEntity prepare(WorldAccess worldaccess, DifficultyDamageScaler difficultydamagescaler, EnumMobSpawn enummobspawn, @javax.annotation.Nullable GroupDataEntity groupdataentity, @javax.annotation.Nullable NBTTagCompound nbttagcompound) { - double chance = worldaccess.getMinecraftWorld().purpurConfig.creeperChargedChance; -@@ -72,18 +88,69 @@ public class EntityCreeper extends EntityMonster { - } - return super.prepare(worldaccess, difficultydamagescaler, enummobspawn, groupdataentity, nbttagcompound); - } -+ -+ @Override -+ protected void mobTick() { -+ if (powerToggleDelay > 0) { -+ powerToggleDelay--; -+ } -+ if (hasPurpurRider()) { -+ if (getPurpurRider().getForward() != 0 || getPurpurRider().getStrafe() != 0) { -+ spacebarCharge = 0; -+ setIgnited(false); -+ } -+ if (spacebarCharge == prevSpacebarCharge) { -+ spacebarCharge = 0; -+ } -+ prevSpacebarCharge = spacebarCharge; -+ } -+ super.mobTick(); -+ } -+ -+ @Override -+ public void onMount(EntityHuman entityhuman) { -+ super.onMount(entityhuman); -+ setIgnited(false); -+ } -+ -+ @Override -+ public boolean onSpacebar() { -+ if (powerToggleDelay > 0) { -+ return true; // just toggled power, do not jump or ignite -+ } -+ spacebarCharge++; -+ if (spacebarCharge > maxFuseTicks - 2) { -+ spacebarCharge = 0; -+ if (getPurpurRider().getBukkitEntity().hasPermission("allow.powered.creeper")) { -+ powerToggleDelay = 20; -+ setPowered(!isPowered()); -+ setIgnited(false); -+ return true; -+ } -+ } -+ if (!isIgnited()) { -+ if (hasPurpurRider() && getPurpurRider().getForward() == 0 && getPurpurRider().getStrafe() == 0 && -+ getPurpurRider().getBukkitEntity().hasPermission("allow.special.creeper")) { -+ setIgnited(true); -+ return true; -+ } -+ } -+ return getForward() == 0 && getStrafe() == 0; // do not jump if standing still -+ } - // Purpur end - - @Override - protected void initPathfinder() { - this.goalSelector.a(1, new PathfinderGoalFloat(this)); - this.goalSelector.a(2, new PathfinderGoalSwell(this)); -+ this.goalSelector.a(3, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(3, new PathfinderGoalAvoidTarget<>(this, EntityOcelot.class, 6.0F, 1.0D, 1.2D)); - this.goalSelector.a(3, new PathfinderGoalAvoidTarget<>(this, EntityCat.class, 6.0F, 1.0D, 1.2D)); - this.goalSelector.a(4, new PathfinderGoalMeleeAttack(this, 1.0D, false)); - this.goalSelector.a(5, new PathfinderGoalRandomStrollLand(this, 0.8D)); - this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(6, new PathfinderGoalRandomLookaround(this)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); - this.targetSelector.a(2, new PathfinderGoalHurtByTarget(this, new Class[0])); - } -@@ -214,6 +281,7 @@ public class EntityCreeper extends EntityMonster { - return (Integer) this.datawatcher.get(EntityCreeper.b); - } - -+ public void setSwellDirection(int i) { a(i); } // Purpur - OBFHELPER - public void a(int i) { - this.datawatcher.set(EntityCreeper.b, i); - } -@@ -314,6 +382,7 @@ public class EntityCreeper extends EntityMonster { - com.destroystokyo.paper.event.entity.CreeperIgniteEvent event = new com.destroystokyo.paper.event.entity.CreeperIgniteEvent((org.bukkit.entity.Creeper) getBukkitEntity(), ignited); - if (event.callEvent()) { - this.datawatcher.set(EntityCreeper.d, event.isIgnited()); -+ if (!event.isIgnited()) setSwellDirection(-1); // Purpur - } - } - // Paper end -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java b/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java -index ea776755767f29e49de2792afa30f79420d0fa4c..1d4039d61a2c77a38a31947010cee26f41c0becd 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java -@@ -73,6 +73,16 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { - } - - // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.drownedRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.drownedRidableInWater; -+ } -+ - @Override - public boolean jockeyOnlyBaby() { - return world.purpurConfig.drownedJockeyOnlyBaby; -@@ -270,7 +280,7 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { - this.d = flag; - } - -- static class d extends ControllerMove { -+ static class d extends net.pl3x.purpur.controller.ControllerMoveWASD { // Purpur - - private final EntityDrowned i; - -@@ -280,7 +290,7 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { - } - - @Override -- public void a() { -+ public void tick() { // Purpur - EntityLiving entityliving = this.i.getGoalTarget(); - - if (this.i.eW() && this.i.isInWater()) { -@@ -313,7 +323,7 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { - this.i.setMot(this.i.getMot().add(0.0D, -0.008D, 0.0D)); - } - -- super.a(); -+ super.tick(); // Purpur - } - - } -@@ -452,6 +462,7 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { - this.a = entitydrowned; - this.b = d0; - this.c = i; -+ this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - swim up - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -index 1e50f7c51f88afaed01777d2da9ed543718a610d..a15dbd76e1d1afae7eb3809ef2e0448d8e2ab8e6 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -@@ -16,6 +16,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -84,9 +85,22 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - this.a(PathType.WATER, -1.0F); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.endermanRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.endermanRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new EntityEnderman.a(this)); - this.goalSelector.a(2, new PathfinderGoalMeleeAttack(this, 1.0D, false)); - this.goalSelector.a(7, new PathfinderGoalRandomStrollLand(this, 1.0D, 0.0F)); -@@ -94,6 +108,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this)); - this.goalSelector.a(10, new EntityEnderman.PathfinderGoalEndermanPlaceBlock(this)); - this.goalSelector.a(11, new EntityEnderman.PathfinderGoalEndermanPickupBlock(this)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new EntityEnderman.PathfinderGoalPlayerWhoLookedAtTarget(this, this::a_)); - this.targetSelector.a(2, new PathfinderGoalHurtByTarget(this, new Class[0])); - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityEndermite.class, 10, true, false, EntityEnderman.bq)); -@@ -274,7 +289,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - - @Override - protected void mobTick() { -- if (this.world.isDay() && this.ticksLived >= this.bs + 600) { -+ if (!hasPurpurRider() && this.world.isDay() && this.ticksLived >= this.bs + 600) { // Purpur - no random teleporting - float f = this.aR(); - - if (f > 0.5F && this.world.e(this.getChunkCoordinates()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.tryEscape(EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper -@@ -376,6 +391,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - if (this.isInvulnerable(damagesource)) { - return false; - } else if (net.pl3x.purpur.PurpurConfig.endermanShortHeight && damagesource == DamageSource.STUCK) { return false; // Purpur - no suffocation damage if short height -+ } else if (hasPurpurRider()) { return super.damageEntity(damagesource, f); // Purpur - no teleporting on damage - } else if (damagesource instanceof EntityDamageSourceIndirect) { - if (this.tryEscape(EndermanEscapeEvent.Reason.INDIRECT)) { // Paper start - for (int i = 0; i < 64; ++i) { -@@ -420,6 +436,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - - public PathfinderGoalEndermanPickupBlock(EntityEnderman entityenderman) { - this.enderman = entityenderman; -+ this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - } - - @Override -@@ -462,6 +479,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - - public PathfinderGoalEndermanPlaceBlock(EntityEnderman entityenderman) { - this.a = entityenderman; -+ this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEndermite.java b/src/main/java/net/minecraft/world/entity/monster/EntityEndermite.java -index 906ac1f861241a184819b4b113abe56625ff5e60..1c87bea9de812e57f8ccd3c9aa85330af87ed240 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityEndermite.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEndermite.java -@@ -4,6 +4,7 @@ import java.util.Random; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.particles.Particles; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.damagesource.DamageSource; -@@ -36,14 +37,28 @@ public class EntityEndermite extends EntityMonster { - this.f = 3; - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.endermiteRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.endermiteRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { - this.goalSelector.a(1, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(1, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(2, new PathfinderGoalMeleeAttack(this, 1.0D, false)); - this.goalSelector.a(3, new PathfinderGoalRandomStrollLand(this, 1.0D)); - this.goalSelector.a(7, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this)); -- this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[0])).a()); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur -+ this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[0])).a(new Class[0])); // Purpur - decompile error - this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); - } - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java b/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java -index 2aa6b6ca93c25c59ad224348aad1bb34d9bbc6a3..55607910183155080e3d96296421438d17f19c8f 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java -@@ -5,6 +5,7 @@ import javax.annotation.Nullable; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -19,6 +20,7 @@ import net.minecraft.world.entity.EnumMonsterType; - import net.minecraft.world.entity.GroupDataEntity; - import net.minecraft.world.entity.ai.attributes.AttributeProvider; - import net.minecraft.world.entity.ai.attributes.GenericAttributes; -+import net.minecraft.world.entity.ai.goal.PathfinderGoal; - import net.minecraft.world.entity.ai.goal.PathfinderGoalAvoidTarget; - import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat; - import net.minecraft.world.entity.ai.goal.PathfinderGoalLookAtPlayer; -@@ -47,10 +49,23 @@ public class EntityEvoker extends EntityIllagerWizard { - this.f = 10; - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.evokerRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.evokerRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { - super.initPathfinder(); - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new EntityEvoker.b()); - this.goalSelector.a(2, new PathfinderGoalAvoidTarget<>(this, EntityHuman.class, 8.0F, 0.6D, 1.0D)); - this.goalSelector.a(4, new EntityEvoker.c()); -@@ -59,6 +74,7 @@ public class EntityEvoker extends EntityIllagerWizard { - this.goalSelector.a(8, new PathfinderGoalRandomStroll(this, 0.6D)); - this.goalSelector.a(9, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 3.0F, 1.0F)); - this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 8.0F)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // Paper - decompile fix - this.targetSelector.a(2, (new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)).a(300)); - this.targetSelector.a(3, (new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)).a(300)); -@@ -139,6 +155,7 @@ public class EntityEvoker extends EntityIllagerWizard { - - public d() { - super(); -+ this.a(java.util.EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - wolololo spell - } - - @Override -@@ -217,6 +234,7 @@ public class EntityEvoker extends EntityIllagerWizard { - private c() { - super(); - this.e = (new PathfinderTargetCondition()).a(16.0D).c().e().a().b(); -+ this.a(java.util.EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - summon spell - } - - @Override -@@ -273,6 +291,7 @@ public class EntityEvoker extends EntityIllagerWizard { - - private a() { - super(); -+ this.a(java.util.EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - attack with spell - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java b/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java -index a3e3f6e07674c54c2d2a02661ce4342b43aafe44..b6d49740a1c8dfa19e871869b92b307fc8397588 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java -@@ -7,6 +7,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -21,6 +22,7 @@ import net.minecraft.world.entity.EntityPose; - import net.minecraft.world.entity.EntitySize; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.EnumMobSpawn; -+import net.minecraft.world.entity.EnumMoveType; - import net.minecraft.world.entity.ai.attributes.AttributeProvider; - import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.entity.ai.control.ControllerMove; -@@ -44,11 +46,42 @@ public class EntityGhast extends EntityFlying implements IMonster { - this.moveController = new EntityGhast.ControllerGhast(this); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.ghastRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.ghastRidableInWater; -+ } -+ -+ @Override -+ public double getMaxY() { -+ return world.purpurConfig.ghastMaxY; -+ } -+ -+ @Override -+ public void g(Vec3D vec3d) { -+ super.g(vec3d); -+ if (hasPurpurRider() && !onGround) { -+ float speed = (float) getAttributeInstance(GenericAttributes.FLYING_SPEED).getValue(); -+ setSpeed(speed); -+ Vec3D mot = getMot(); -+ move(EnumMoveType.SELF, mot.multiply(speed, 1.0, speed)); -+ setMot(mot.a(0.9D)); -+ } -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(5, new EntityGhast.PathfinderGoalGhastIdleMove(this)); - this.goalSelector.a(7, new EntityGhast.PathfinderGoalGhastMoveTowardsTarget(this)); - this.goalSelector.a(7, new EntityGhast.PathfinderGoalGhastAttackTarget(this)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, (entityliving) -> { - return Math.abs(entityliving.locY() - this.locY()) <= 4.0D; - })); -@@ -86,7 +119,7 @@ public class EntityGhast extends EntityFlying implements IMonster { - } - - public static AttributeProvider.Builder eJ() { -- return EntityInsentient.p().a(GenericAttributes.MAX_HEALTH, 10.0D).a(GenericAttributes.FOLLOW_RANGE, 100.0D); -+ return EntityInsentient.p().a(GenericAttributes.MAX_HEALTH, 10.0D).a(GenericAttributes.FOLLOW_RANGE, 100.0D).a(GenericAttributes.FLYING_SPEED, 0.6D); // Purpur - } - - @Override -@@ -285,7 +318,7 @@ public class EntityGhast extends EntityFlying implements IMonster { - } - } - -- static class ControllerGhast extends ControllerMove { -+ static class ControllerGhast extends net.pl3x.purpur.controller.ControllerMoveWASDFlying { // Purpur - - private final EntityGhast i; - private int j; -@@ -296,7 +329,7 @@ public class EntityGhast extends EntityFlying implements IMonster { - } - - @Override -- public void a() { -+ public void tick() { // Purpur - if (this.h == ControllerMove.Operation.MOVE_TO) { - if (this.j-- <= 0) { - this.j += this.i.getRandom().nextInt(5) + 2; -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGiantZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityGiantZombie.java -index a188a89143cb1b0243dacdec33c446ca4120219f..7395fa90198a9138b2c33273d8f3540355300029 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityGiantZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityGiantZombie.java -@@ -2,6 +2,7 @@ package net.minecraft.world.entity.monster; - - import net.minecraft.core.BlockPosition; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.world.DifficultyDamageScaler; - import net.minecraft.world.EnumDifficulty; - import net.minecraft.world.entity.EntityPose; -@@ -41,16 +42,28 @@ public class EntityGiantZombie extends EntityMonster { - } - - // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.giantRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.giantRidableInWater; -+ } -+ - @Override - protected void initPathfinder() { - if (world.purpurConfig.giantHaveAI) { - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(7, new PathfinderGoalRandomStrollLand(this, 1.0D)); - this.goalSelector.a(8, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 16.0F)); - this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this)); - this.goalSelector.a(5, new PathfinderGoalMoveTowardsRestriction(this, 1.0D)); - if (world.purpurConfig.giantHaveHostileAI) { - this.goalSelector.a(2, new PathfinderGoalMeleeAttack(this, 1.0D, false)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this).a(EntityPigZombie.class)); - this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillager.class, false)); -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGuardian.java b/src/main/java/net/minecraft/world/entity/monster/EntityGuardian.java -index d53e2a9d27f9976d1fd8ea30b88a0da089aec7b6..66ae664add95f4441724b49a470a2fef569042d6 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityGuardian.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityGuardian.java -@@ -9,6 +9,7 @@ import net.minecraft.core.particles.Particles; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.tags.Tag; -@@ -63,15 +64,36 @@ public class EntityGuardian extends EntityMonster { - this.f = 10; - this.a(PathType.WATER, 0.0F); - this.moveController = new EntityGuardian.ControllerMoveGuardian(this); -+ // Purpur start -+ this.lookController = new net.pl3x.purpur.controller.ControllerLookWASD(this) { -+ @Override -+ public void setYawPitch(float yaw, float pitch) { -+ super.setYawPitch(yaw, pitch * 0.35F); -+ } -+ }; -+ // Purpur end - this.bo = this.random.nextFloat(); - this.bp = this.bo; - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.guardianRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return true; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { - PathfinderGoalMoveTowardsRestriction pathfindergoalmovetowardsrestriction = new PathfinderGoalMoveTowardsRestriction(this, 1.0D); - - this.goalRandomStroll = new PathfinderGoalRandomStroll(this, 1.0D, 80); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(4, new EntityGuardian.PathfinderGoalGuardianAttack(this)); - this.goalSelector.a(5, pathfindergoalmovetowardsrestriction); - this.goalSelector.a(7, this.goalRandomStroll); -@@ -80,6 +102,7 @@ public class EntityGuardian extends EntityMonster { - this.goalSelector.a(9, new PathfinderGoalRandomLookaround(this)); - this.goalRandomStroll.a(EnumSet.of(PathfinderGoal.Type.MOVE, PathfinderGoal.Type.LOOK)); - pathfindergoalmovetowardsrestriction.a(EnumSet.of(PathfinderGoal.Type.MOVE, PathfinderGoal.Type.LOOK)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityLiving.class, 10, true, false, new EntityGuardian.EntitySelectorGuardianTargetHumanSquid(this))); - } - -@@ -113,6 +136,7 @@ public class EntityGuardian extends EntityMonster { - return (Boolean) this.datawatcher.get(EntityGuardian.b); - } - -+ private void setMovingFlag(boolean movingFlag) { t(movingFlag); } // Purpur - OBFHELPER - private void t(boolean flag) { - this.datawatcher.set(EntityGuardian.b, flag); - } -@@ -327,7 +351,7 @@ public class EntityGuardian extends EntityMonster { - @Override - public void g(Vec3D vec3d) { - if (this.doAITick() && this.isInWater()) { -- this.a(0.1F, vec3d); -+ this.a(hasPurpurRider() ? getSpeed() : 0.1F, vec3d); // Purpur - this.move(EnumMoveType.SELF, this.getMot()); - this.setMot(this.getMot().a(0.9D)); - if (!this.eN() && this.getGoalTarget() == null) { -@@ -339,17 +363,26 @@ public class EntityGuardian extends EntityMonster { - - } - -- static class ControllerMoveGuardian extends ControllerMove { -+ static class ControllerMoveGuardian extends net.pl3x.purpur.controller.ControllerMoveWASDWater { // Purpur - -- private final EntityGuardian i; -+ private final EntityGuardian i; private EntityGuardian getGuardian() { return i; } // Purpur - OBFHELPER - - public ControllerMoveGuardian(EntityGuardian entityguardian) { - super(entityguardian); - this.i = entityguardian; - } - -+ // Purpur start -+ @Override -+ public void tick(EntityHuman rider) { -+ super.tick(rider); -+ getGuardian().setMot(getGuardian().getMot().add(0.0D, 0.005D, 0.0D)); -+ getGuardian().setMovingFlag(getGuardian().getForward() > 0.0F); // control tail speed -+ } -+ // Purpur end -+ - @Override -- public void a() { -+ public void tick() { // Purpur - if (this.h == ControllerMove.Operation.MOVE_TO && !this.i.getNavigation().m()) { - Vec3D vec3d = new Vec3D(this.b - this.i.locX(), this.c - this.i.locY(), this.d - this.i.locZ()); - double d0 = vec3d.f(); -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java b/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java -index 300efeb98bb68b24faa68a4af9d703bf2b8c405c..ef48184f79920f053d62d34cc7b56a98e8aa4274 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java -@@ -30,6 +30,18 @@ public class EntityGuardianElder extends EntityGuardian { - - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.elderGuardianRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return true; -+ } -+ // Purpur end -+ - public static AttributeProvider.Builder m() { - return EntityGuardian.eM().a(GenericAttributes.MOVEMENT_SPEED, 0.30000001192092896D).a(GenericAttributes.ATTACK_DAMAGE, 8.0D).a(GenericAttributes.MAX_HEALTH, 80.0D); - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java b/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java -index cb092bee9d6827d4b0276bfa9b033cf7ca86ead4..5186d9957c94be359da5b08fd821e9471c159f03 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java -@@ -3,6 +3,7 @@ package net.minecraft.world.entity.monster; - import javax.annotation.Nullable; - import net.minecraft.core.particles.Particles; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.util.MathHelper; -@@ -57,6 +58,16 @@ public class EntityIllagerIllusioner extends EntityIllagerWizard implements IRan - } - - // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.illusionerRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.illusionerRidableInWater; -+ } -+ - @Override - protected void initAttributes() { - this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue(this.world.purpurConfig.illusionerMovementSpeed); -@@ -69,6 +80,7 @@ public class EntityIllagerIllusioner extends EntityIllagerWizard implements IRan - protected void initPathfinder() { - super.initPathfinder(); - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new EntityIllagerWizard.b()); - this.goalSelector.a(4, new EntityIllagerIllusioner.b()); - this.goalSelector.a(5, new EntityIllagerIllusioner.a()); -@@ -76,6 +88,7 @@ public class EntityIllagerIllusioner extends EntityIllagerWizard implements IRan - this.goalSelector.a(8, new PathfinderGoalRandomStroll(this, 0.6D)); - this.goalSelector.a(9, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 3.0F, 1.0F)); - this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 8.0F)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // CraftBukkit - decompile error - this.targetSelector.a(2, (new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)).a(300)); - this.targetSelector.a(3, (new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)).a(300)); -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityMagmaCube.java b/src/main/java/net/minecraft/world/entity/monster/EntityMagmaCube.java -index fe80e93b00f3bb2f297c6528c3951313fa3c08c7..15ed51a2746c09538a425fce25fa25f2619b7033 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityMagmaCube.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityMagmaCube.java -@@ -29,6 +29,23 @@ public class EntityMagmaCube extends EntitySlime { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.magmaCubeRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.magmaCubeRidableInWater; -+ } -+ -+ @Override -+ public float getJumpHeight() { -+ return 0.42F * this.getBlockJumpFactor(); // from EntityLiving -+ } -+ // Purpur end -+ - public static AttributeProvider.Builder m() { - return EntityMonster.eR().a(GenericAttributes.MOVEMENT_SPEED, 0.20000000298023224D); - } -@@ -79,11 +96,12 @@ public class EntityMagmaCube extends EntitySlime { - } - - @Override -- protected void jump() { -+ public void jump() { // Purpur - protected -> public - Vec3D vec3d = this.getMot(); - - this.setMot(vec3d.x, (double) (this.dJ() + (float) this.getSize() * 0.1F), vec3d.z); - this.impulse = true; -+ this.actualJump = false; // Purpur - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -index fd2e3a4abcfedaf04db4277291983627c097b545..1ea3054cebbf32588219f8915f9fb496495e3a10 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -@@ -13,6 +13,7 @@ import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; - import net.minecraft.server.level.WorldServer; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -29,11 +30,11 @@ import net.minecraft.world.entity.EntitySize; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.EnumMobSpawn; - import net.minecraft.world.entity.EnumMonsterType; -+import net.minecraft.world.entity.EnumMoveType; - import net.minecraft.world.entity.GroupDataEntity; - import net.minecraft.world.entity.IEntitySelector; -+import net.minecraft.world.entity.ai.attributes.AttributeProvider; - import net.minecraft.world.entity.ai.attributes.GenericAttributes; --import net.minecraft.world.entity.ai.control.ControllerLook; --import net.minecraft.world.entity.ai.control.ControllerMove; - import net.minecraft.world.entity.ai.control.EntityAIBodyControl; - import net.minecraft.world.entity.ai.goal.PathfinderGoal; - import net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition; -@@ -68,6 +69,59 @@ public class EntityPhantom extends EntityFlying implements IMonster { - this.lookController = new EntityPhantom.f(this); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.phantomRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.phantomRidableInWater; -+ } -+ -+ @Override -+ public double getMaxY() { -+ return world.purpurConfig.phantomMaxY; -+ } -+ -+ @Override -+ public void g(Vec3D vec3d) { -+ super.g(vec3d); -+ if (hasPurpurRider() && !onGround) { -+ float speed = (float) getAttributeInstance(GenericAttributes.FLYING_SPEED).getValue(); -+ setSpeed(speed); -+ Vec3D mot = getMot(); -+ move(EnumMoveType.SELF, mot.multiply(speed, speed, speed)); -+ setMot(mot.a(0.9D)); -+ } -+ } -+ -+ public static AttributeProvider.Builder defaultAttributes() { -+ return EntityMonster.eR().a(GenericAttributes.FLYING_SPEED, 3.0D); -+ } -+ -+ @Override -+ public boolean onSpacebar() { -+ if (hasPurpurRider() && getPurpurRider().getBukkitEntity().hasPermission("allow.special.phantom")) { -+ shoot(); -+ } -+ return false; -+ } -+ -+ public boolean shoot() { -+ org.bukkit.Location loc = ((org.bukkit.entity.LivingEntity) getBukkitEntity()).getEyeLocation(); -+ loc.setPitch(-loc.getPitch()); -+ 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; -+ } -+ // Purpur end -+ - @Override - protected EntityAIBodyControl r() { - return new EntityPhantom.d(this); -@@ -76,6 +130,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { - @Override - protected void initPathfinder() { - // Purpur start -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); - if (world.purpurConfig.phantomOrbitCrystalRadius > 0) { - this.goalSelector.a(1, new FindCrystalGoal(this)); - this.goalSelector.a(2, new OrbitCrystalGoal(this)); -@@ -83,6 +138,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { - this.goalSelector.a(3, new EntityPhantom.c()); // PickAttackGoal - this.goalSelector.a(4, new EntityPhantom.i()); // SweepAttackGoal - this.goalSelector.a(5, new EntityPhantom.e()); // OrbitPointGoal -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); - this.targetSelector.a(1, new EntityPhantom.b()); // AttackPlayer Goal - // Purpur end - } -@@ -169,7 +225,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { - - @Override - public void movementTick() { -- if (this.isAlive() && (((shouldBurnInDay || world.purpurConfig.phantomBurnInDaylight) && this.isInDaylight()) || (world.purpurConfig.phantomBurnInLight > 0 && world.getLightLevel(new BlockPosition(this)) >= world.purpurConfig.phantomBurnInLight))) { // Paper - Configurable Burning // Purpur -+ if (this.isAlive() && !hasPurpurRider() && (((shouldBurnInDay || world.purpurConfig.phantomBurnInDaylight) && this.isInDaylight()) || (world.purpurConfig.phantomBurnInLight > 0 && world.getLightLevel(new BlockPosition(this)) >= world.purpurConfig.phantomBurnInLight))) { // Paper - Configurable Burning // Purpur - this.setOnFire(8); - } - -@@ -418,7 +474,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { - - @Override - public boolean a() { -- if (isCirclingCrystal()) return false; // Purpur - pathfinder does not have a flag -+ if (getPurpurRider() != null || isCirclingCrystal()) return false; // Purpur - pathfinder does not have a flag - if (this.c > 0) { - --this.c; - return false; -@@ -447,7 +503,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { - - @Override - public boolean b() { -- if (isCirclingCrystal()) return false; // Purpur - pathfinder does not have a flag -+ if (getPurpurRider() != null || isCirclingCrystal()) return false; // Purpur - pathfinder does not have a flag - EntityLiving entityliving = EntityPhantom.this.getGoalTarget(); - - return entityliving != null ? EntityPhantom.this.a(entityliving, PathfinderTargetCondition.a) : false; -@@ -462,7 +518,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { - - @Override - public boolean a() { -- if (isCirclingCrystal()) return false; // Purpur - pathfinder does not have a flag -+ if (getPurpurRider() != null || isCirclingCrystal()) return false; // Purpur - pathfinder does not have a flag - EntityLiving entityliving = EntityPhantom.this.getGoalTarget(); - - return entityliving != null ? EntityPhantom.this.a(EntityPhantom.this.getGoalTarget(), PathfinderTargetCondition.a) : false; -@@ -660,14 +716,23 @@ public class EntityPhantom extends EntityFlying implements IMonster { - } - } - -- class f extends ControllerLook { -+ class f extends net.pl3x.purpur.controller.ControllerLookWASD { // Purpur - - public f(EntityInsentient entityinsentient) { - super(entityinsentient); - } - - @Override -- public void a() {} -+ // Purpur start -+ public void tick(EntityHuman rider) { -+ setYawPitch(rider.yaw, -rider.pitch * 0.75F); -+ } -+ -+ @Override -+ public void tick() { -+ // do nothing -+ } -+ // Purpur end - } - - class d extends EntityAIBodyControl { -@@ -683,7 +748,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { - } - } - -- class g extends ControllerMove { -+ class g extends net.pl3x.purpur.controller.ControllerMoveWASDFlying { // Purpur - - private float j = 0.1F; - -@@ -692,7 +757,19 @@ public class EntityPhantom extends EntityFlying implements IMonster { - } - - @Override -- public void a() { -+ // Purpur start -+ public void tick(EntityHuman rider) { -+ if (!EntityPhantom.this.onGround) { -+ // phantom is always in motion when flying -+ // TODO - FIX THIS -+ // rider.setForward(1.0F); -+ } -+ super.tick(rider); -+ } -+ -+ @Override -+ public void tick() { -+ // Purpur end - if (EntityPhantom.this.positionChanged) { - EntityPhantom.this.yaw += 180.0F; - this.j = 0.1F; -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java -index ee17e62d996d81ea149a5c0eae2e29404e363dcf..9f50054211db48e7fe764434e8d71aab0995e57a 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java -@@ -57,6 +57,16 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { - } - - // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.zombifiedPiglinRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.zombifiedPiglinRidableInWater; -+ } -+ - @Override - public boolean jockeyOnlyBaby() { - return world.purpurConfig.zombifiedPiglinJockeyOnlyBaby; -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPillager.java b/src/main/java/net/minecraft/world/entity/monster/EntityPillager.java -index ea105fb86553f5212d616c976eaf2a16bf5b6561..2a4ac6e608650d56cc2b564e715b7b685e7f3f62 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityPillager.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityPillager.java -@@ -9,6 +9,7 @@ import net.minecraft.nbt.NBTTagList; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.DifficultyDamageScaler; -@@ -61,15 +62,29 @@ public class EntityPillager extends EntityIllagerAbstract implements ICrossbow { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.pillagerRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.pillagerRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { - super.initPathfinder(); - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(2, new EntityRaider.a(this, 10.0F)); - this.goalSelector.a(3, new PathfinderGoalCrossbowAttack<>(this, 1.0D, 8.0F)); - this.goalSelector.a(8, new PathfinderGoalRandomStroll(this, 0.6D)); - this.goalSelector.a(9, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 15.0F, 1.0F)); - this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 15.0F)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // CraftBukkit - decompile error - this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)); -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java b/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java -index 16d5cae64887b82e67eeb61ccb714e6125ff0c09..cc37e545ece89803fad91801775470df4620bd62 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java -@@ -7,6 +7,7 @@ import javax.annotation.Nullable; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.particles.Particles; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.tags.Tag; -@@ -38,7 +39,6 @@ import net.minecraft.world.level.IBlockAccess; - import net.minecraft.world.level.IWorldReader; - import net.minecraft.world.level.World; - import net.minecraft.world.level.block.Block; --import net.minecraft.world.level.block.BlockLeaves; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.pathfinder.PathType; - import net.minecraft.world.level.pathfinder.Pathfinder; -@@ -61,14 +61,37 @@ public class EntityRavager extends EntityRaider { - this.f = 20; - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.ravagerRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.ravagerRidableInWater; -+ } -+ -+ @Override -+ public void onMount(EntityHuman entityhuman) { -+ super.onMount(entityhuman); -+ getNavigation().stopPathfinding(); -+ -+ double speed = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getBaseValue(); -+ getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue(speed); -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { - super.initPathfinder(); - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(4, new EntityRavager.a()); - this.goalSelector.a(5, new PathfinderGoalRandomStrollLand(this, 0.4D)); - this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F)); - this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 8.0F)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(2, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // CraftBukkit - decompile error - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); - this.targetSelector.a(4, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, true)); -@@ -140,7 +163,7 @@ public class EntityRavager extends EntityRaider { - @Override - public void movementTick() { - super.movementTick(); -- if (this.isAlive()) { -+ if (this.isAlive() && !hasPurpurRider()) { - if (this.isFrozen()) { - this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue(0.0D); - } else { -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityShulker.java b/src/main/java/net/minecraft/world/entity/monster/EntityShulker.java -index 49523302dd72a3dafab23c047412a2e77b6247ed..4b5c1691664f16594f316e55576086f2ae54e59e 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityShulker.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityShulker.java -@@ -12,6 +12,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -71,12 +72,26 @@ public class EntityShulker extends EntityGolem implements IMonster { - this.f = 5; - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.shulkerRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.shulkerRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(4, new EntityShulker.a()); - this.goalSelector.a(7, new EntityShulker.e()); - this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[0])).a(new Class[0])); // CraftBukkit - decompile error - this.targetSelector.a(2, new EntityShulker.d(this)); - this.targetSelector.a(3, new EntityShulker.c(this)); -@@ -560,7 +575,7 @@ public class EntityShulker extends EntityGolem implements IMonster { - - private int b; - -- private e() {} -+ private e() { this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); } // Purpur - peek - - @Override - public boolean a() { -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java b/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java -index e1fcb1be102822e87eaf7757fbd64a516b2f58ac..c0601af022d85c7b03463f0df975d713c0366b2c 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java -@@ -4,6 +4,7 @@ import java.util.EnumSet; - import java.util.Random; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.damagesource.DamageSource; -@@ -38,13 +39,27 @@ public class EntitySilverfish extends EntityMonster { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.silverfishRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.silverfishRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { - this.b = new EntitySilverfish.PathfinderGoalSilverfishWakeOthers(this); - this.goalSelector.a(1, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(1, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(3, this.b); - this.goalSelector.a(4, new PathfinderGoalMeleeAttack(this, 1.0D, false)); - this.goalSelector.a(5, new EntitySilverfish.PathfinderGoalSilverfishHideInBlock(this)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[0])).a(new Class[0])); // CraftBukkit - decompile error - this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); - } -@@ -204,6 +219,7 @@ public class EntitySilverfish extends EntityMonster { - - public PathfinderGoalSilverfishWakeOthers(EntitySilverfish entitysilverfish) { - this.silverfish = entitysilverfish; -+ this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - } - - public void g() { -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeleton.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeleton.java -index 342bc9b586ef835e865d6f84bf66f1069ab10f00..0b8517d4e83d14ddf8b6d1f1cf4c538f9e4cc68f 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeleton.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeleton.java -@@ -15,6 +15,18 @@ public class EntitySkeleton extends EntitySkeletonAbstract { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.skeletonRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.skeletonRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected SoundEffect getSoundAmbient() { - return SoundEffects.ENTITY_SKELETON_AMBIENT; -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -index f8358e40c42f219232bf928f4e0073339a5e19d5..81059fc3fc22f251b5b08f0cd6814a992cff6b1e 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -@@ -5,6 +5,7 @@ import java.time.temporal.ChronoField; - import javax.annotation.Nullable; - import net.minecraft.core.BlockPosition; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.util.MathHelper; -@@ -70,12 +71,14 @@ public abstract class EntitySkeletonAbstract extends EntityMonster implements IR - - @Override - protected void initPathfinder() { -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(2, new PathfinderGoalRestrictSun(this)); - this.goalSelector.a(3, new PathfinderGoalFleeSun(this, 1.0D)); - this.goalSelector.a(3, new PathfinderGoalAvoidTarget<>(this, EntityWolf.class, 6.0F, 1.0D, 1.2D)); - this.goalSelector.a(5, new PathfinderGoalRandomStrollLand(this, 1.0D)); - this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(6, new PathfinderGoalRandomLookaround(this)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, new Class[0])); - this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityIronGolem.class, true)); -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonStray.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonStray.java -index 8481b8fffed3f1f60e2e72e115e79e9ae1aaa635..8484000a1b0d9c252d6fab205b1e316e3f6f33bd 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonStray.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonStray.java -@@ -21,6 +21,18 @@ public class EntitySkeletonStray extends EntitySkeletonAbstract { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.strayRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.strayRidableInWater; -+ } -+ // Purpur end -+ - public static boolean a(EntityTypes entitytypes, WorldAccess worldaccess, EnumMobSpawn enummobspawn, BlockPosition blockposition, Random random) { - return b(entitytypes, worldaccess, enummobspawn, blockposition, random) && (enummobspawn == EnumMobSpawn.SPAWNER || worldaccess.e(blockposition)); - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java -index a90ac635ef7aef5289d21f948db7b170b23160d3..cb52c4e63ac487d55dc16accca6976f44f904112 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java -@@ -34,6 +34,18 @@ public class EntitySkeletonWither extends EntitySkeletonAbstract { - this.a(PathType.LAVA, 8.0F); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.witherSkeletonRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.witherSkeletonRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityPiglinAbstract.class, true)); -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -index 0af0b232ff1b6f1d58cf3fb543d32bd108be0af7..feb40c2ca8e8f3fae5665b2d71296a6b811b11f6 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -@@ -14,6 +14,7 @@ import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; - import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.util.MathHelper; -@@ -74,12 +75,45 @@ public class EntitySlime extends EntityInsentient implements IMonster { - this.moveController = new EntitySlime.ControllerMoveSlime(this); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.slimeRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.slimeRidableInWater; -+ } -+ -+ protected boolean actualJump; -+ -+ @Override -+ public float getJumpHeight() { -+ float height = super.getJumpHeight(); -+ return hasPurpurRider() && actualJump ? height * 1.5F : height; -+ } -+ -+ @Override -+ public boolean onSpacebar() { -+ if (onGround && hasPurpurRider()) { -+ actualJump = true; -+ if (getPurpurRider().getForward() == 0 || getPurpurRider().getStrafe() == 0) { -+ jump(); // jump() here if not moving -+ } -+ } -+ return true; // do not jump() in wasd controller, let vanilla controller handle -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new EntitySlime.PathfinderGoalSlimeRandomJump(this)); - this.goalSelector.a(2, new EntitySlime.PathfinderGoalSlimeNearestPlayer(this)); - this.goalSelector.a(3, new EntitySlime.PathfinderGoalSlimeRandomDirection(this)); - this.goalSelector.a(5, new EntitySlime.PathfinderGoalSlimeIdle(this)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, (entityliving) -> { - return Math.abs(entityliving.locY() - this.locY()) <= 4.0D; - })); -@@ -365,11 +399,12 @@ public class EntitySlime extends EntityInsentient implements IMonster { - } - - @Override -- protected void jump() { -+ public void jump() { // Purpur - protected -> public - Vec3D vec3d = this.getMot(); - - this.setMot(vec3d.x, (double) this.dJ(), vec3d.z); - this.impulse = true; -+ this.actualJump = false; // Purpur - } - - @Nullable -@@ -538,10 +573,10 @@ public class EntitySlime extends EntityInsentient implements IMonster { - // Paper end - } - -- static class ControllerMoveSlime extends ControllerMove { -+ static class ControllerMoveSlime extends net.pl3x.purpur.controller.ControllerMoveWASD { // Purpur - - private float i; -- private int j; -+ private int j; private int getJumpDelay() { return j; } private void setJumpDelay(int delay) { j = delay; } // Purpur - OBFHELPER - private final EntitySlime k; - private boolean l; - -@@ -563,15 +598,27 @@ public class EntitySlime extends EntityInsentient implements IMonster { - - @Override - public void a() { -+ // Purpur start -+ if (entity.hasPurpurRider()) { -+ tick(entity.getPurpurRider()); -+ if (entity.getForward() != 0 || entity.getStrafe() != 0) { -+ if (getJumpDelay() > 10) { -+ setJumpDelay(6); -+ } -+ } else { -+ setJumpDelay(20); -+ } -+ } else { -+ // Purpur end - this.a.yaw = this.a(this.a.yaw, this.i, 90.0F); - this.a.aC = this.a.yaw; - this.a.aA = this.a.yaw; -- if (this.h != ControllerMove.Operation.MOVE_TO) { -+ } if (!entity.hasPurpurRider() && this.h != ControllerMove.Operation.MOVE_TO) { // Purpur - this.a.t(0.0F); - } else { - this.h = ControllerMove.Operation.WAIT; - if (this.a.isOnGround()) { -- this.a.q((float) (this.e * this.a.b(GenericAttributes.MOVEMENT_SPEED))); -+ this.a.q((float) (this.e * this.a.b(GenericAttributes.MOVEMENT_SPEED) * (entity.hasPurpurRider() && (entity.getPurpurRider().getForward() != 0 || entity.getPurpurRider().getStrafe() != 0) ? 2.0D : 1.0D))); // Purpur - if (this.j-- <= 0) { - this.j = this.k.eJ(); - if (this.l) { -@@ -588,7 +635,7 @@ public class EntitySlime extends EntityInsentient implements IMonster { - this.a.q(0.0F); - } - } else { -- this.a.q((float) (this.e * this.a.b(GenericAttributes.MOVEMENT_SPEED))); -+ this.a.q((float) (this.e * this.a.b(GenericAttributes.MOVEMENT_SPEED) * (entity.hasPurpurRider() && (entity.getPurpurRider().getForward() != 0 || entity.getPurpurRider().getStrafe() != 0) ? 2.0D : 1.0D))); // Purpur - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySpider.java b/src/main/java/net/minecraft/world/entity/monster/EntitySpider.java -index c7b443623f3dd90741e52216199d8ed90bcea6b3..fbf7c31f57f6dbfac997480eb7db55efc15ef4cc 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySpider.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySpider.java -@@ -7,6 +7,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.DifficultyDamageScaler; -@@ -50,14 +51,28 @@ public class EntitySpider extends EntityMonster { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.spiderRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.spiderRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { - this.goalSelector.a(1, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(1, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(3, new PathfinderGoalLeapAtTarget(this, 0.4F)); - this.goalSelector.a(4, new EntitySpider.PathfinderGoalSpiderMeleeAttack(this)); - this.goalSelector.a(5, new PathfinderGoalRandomStrollLand(this, 0.8D)); - this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(6, new PathfinderGoalRandomLookaround(this)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, new Class[0])); - this.targetSelector.a(2, new EntitySpider.PathfinderGoalSpiderNearestAttackableTarget<>(this, EntityHuman.class)); - this.targetSelector.a(3, new EntitySpider.PathfinderGoalSpiderNearestAttackableTarget<>(this, EntityIronGolem.class)); -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java b/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java -index 5ce50c6fe788fbd6db95f6406bacbf218b7e691c..14dda6743ed9e6f4880bc560f7ba8892d8e84afe 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java -@@ -13,6 +13,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffect; -@@ -94,6 +95,18 @@ public class EntityStrider extends EntityAnimal implements ISteerable, ISaddleab - this.a(PathType.DAMAGE_FIRE, 0.0F); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.striderRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.striderRidableInWater; -+ } -+ // Purpur end -+ - public static boolean c(EntityTypes entitytypes, GeneratorAccess generatoraccess, EnumMobSpawn enummobspawn, BlockPosition blockposition, Random random) { - BlockPosition.MutableBlockPosition blockposition_mutableblockposition = blockposition.i(); - -@@ -155,6 +168,7 @@ public class EntityStrider extends EntityAnimal implements ISteerable, ISaddleab - @Override - protected void initPathfinder() { - this.bv = new PathfinderGoalPanic(this, 1.65D); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, this.bv); - this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D)); - this.bu = new PathfinderGoalTempt(this, 1.4D, false, EntityStrider.bp); -@@ -434,7 +448,7 @@ public class EntityStrider extends EntityAnimal implements ISteerable, ISaddleab - if (!enuminteractionresult.a()) { - ItemStack itemstack = entityhuman.b(enumhand); - -- return itemstack.getItem() == Items.SADDLE ? itemstack.a(entityhuman, (EntityLiving) this, enumhand) : EnumInteractionResult.PASS; -+ return itemstack.getItem() == Items.SADDLE ? itemstack.a(entityhuman, (EntityLiving) this, enumhand) : tryRide(entityhuman, enumhand); // Purpur - } else { - if (flag && !this.isSilent()) { - this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_STRIDER_EAT, this.getSoundCategory(), 1.0F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F); -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -index 9645d052069957311478a1ceca42ad52f7a9aa0b..5e2114d2321c1542dc892bc7aed07080008cfd20 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -@@ -7,6 +7,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.util.MathHelper; -@@ -54,6 +55,45 @@ public class EntityVex extends EntityMonster { - this.f = 3; - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.vexRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.vexRidableInWater; -+ } -+ -+ @Override -+ public double getMaxY() { -+ return world.purpurConfig.vexMaxY; -+ } -+ -+ @Override -+ public void g(Vec3D vec3d) { -+ super.g(vec3d); -+ if (hasPurpurRider()) { -+ float speed; -+ if (onGround) { -+ speed = (float) getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getValue() * 0.1F; -+ } else { -+ speed = (float) getAttributeInstance(GenericAttributes.FLYING_SPEED).getValue(); -+ } -+ setSpeed(speed); -+ Vec3D mot = getMot(); -+ move(EnumMoveType.SELF, mot.multiply(speed, 1.0, speed)); -+ setMot(mot.a(0.9D)); -+ } -+ } -+ -+ @Override -+ public boolean b(float f, float f1) { -+ return false; // no fall damage please -+ } -+ // Purpur end -+ - @Override - public void move(EnumMoveType enummovetype, Vec3D vec3d) { - super.move(enummovetype, vec3d); -@@ -62,7 +102,7 @@ public class EntityVex extends EntityMonster { - - @Override - public void tick() { -- this.noclip = true; -+ this.noclip = !hasPurpurRider(); // Purpur - super.tick(); - this.noclip = false; - this.setNoGravity(true); -@@ -77,17 +117,19 @@ public class EntityVex extends EntityMonster { - protected void initPathfinder() { - super.initPathfinder(); - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(4, new EntityVex.a()); - this.goalSelector.a(8, new EntityVex.d()); - this.goalSelector.a(9, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 3.0F, 1.0F)); - this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 8.0F)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // CraftBukkit - decompile error - this.targetSelector.a(2, new EntityVex.b(this)); - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); - } - - public static AttributeProvider.Builder m() { -- return EntityMonster.eR().a(GenericAttributes.MAX_HEALTH, 14.0D).a(GenericAttributes.ATTACK_DAMAGE, 4.0D); -+ return EntityMonster.eR().a(GenericAttributes.MAX_HEALTH, 14.0D).a(GenericAttributes.ATTACK_DAMAGE, 4.0D).a(GenericAttributes.FLYING_SPEED, 0.6D); // Purpur - } - - @Override -@@ -319,14 +361,14 @@ public class EntityVex extends EntityMonster { - } - } - -- class c extends ControllerMove { -+ class c extends net.pl3x.purpur.controller.ControllerMoveWASDFlying { // Purpur - - public c(EntityVex entityvex) { - super(entityvex); - } - - @Override -- public void a() { -+ public void tick() { // Purpur - if (this.h == ControllerMove.Operation.MOVE_TO) { - Vec3D vec3d = new Vec3D(this.b - EntityVex.this.locX(), this.c - EntityVex.this.locY(), this.d - EntityVex.this.locZ()); - double d0 = vec3d.f(); -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -index fe84d6d2b74b6ae00c4c66682107296a40b69adc..28d345e87f45fa839bc3bd758f79f34aba546db7 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -@@ -8,6 +8,7 @@ import javax.annotation.Nullable; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -59,14 +60,28 @@ public class EntityVindicator extends EntityIllagerAbstract { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.vindicatorRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.vindicatorRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { - super.initPathfinder(); - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new EntityVindicator.a(this)); - this.goalSelector.a(2, new EntityIllagerAbstract.b(this)); - this.goalSelector.a(3, new EntityRaider.a(this, 10.0F)); - this.goalSelector.a(4, new EntityVindicator.c(this)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // Paper - decompile fix - this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, true)); -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -index 63fb08e7b4290353e5148d1acb58f091dc5b08be..c4663c5b02363bd1499ce1f3b50027f8aa7c68e7 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -@@ -2,6 +2,7 @@ package net.minecraft.world.entity.monster; - - // Paper start - import com.destroystokyo.paper.event.entity.WitchReadyPotionEvent; -+import net.minecraft.server.PathfinderGoalHasRider; - import org.bukkit.craftbukkit.inventory.CraftItemStack; - import org.bukkit.entity.Witch; - // Paper end -@@ -63,6 +64,18 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - super(entitytypes, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.witchRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.witchRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void initPathfinder() { - super.initPathfinder(); -@@ -71,10 +84,12 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - }); - this.bs = new PathfinderGoalNearestAttackableTargetWitch<>(this, EntityHuman.class, 10, true, false, (Predicate) null); - this.goalSelector.a(1, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(1, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(2, new PathfinderGoalArrowAttack(this, 1.0D, 60, 10.0F)); - this.goalSelector.a(2, new PathfinderGoalRandomStrollLand(this, 1.0D)); - this.goalSelector.a(3, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(3, new PathfinderGoalRandomLookaround(this)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})); - this.targetSelector.a(2, this.br); - this.targetSelector.a(3, this.bs); -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZoglin.java b/src/main/java/net/minecraft/world/entity/monster/EntityZoglin.java -index aed585e2c1c88a4d09318c6be7ebe7168eac3631..249fb9cf43527af5c7818ce6b07487ad446811b7 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZoglin.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZoglin.java -@@ -62,6 +62,18 @@ public class EntityZoglin extends EntityMonster implements IMonster, IOglin { - this.f = 5; - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.zoglinRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.zoglinRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected BehaviorController.b cK() { - return BehaviorController.a((Collection) EntityZoglin.c, (Collection) EntityZoglin.b); -@@ -93,10 +105,10 @@ public class EntityZoglin extends EntityMonster implements IMonster, IOglin { - } - - private Optional eO() { -- return ((List) this.getBehaviorController().getMemory(MemoryModuleType.VISIBLE_MOBS).orElse(ImmutableList.of())).stream().filter(EntityZoglin::i).findFirst(); -+ return (this.getBehaviorController().getMemory(MemoryModuleType.VISIBLE_MOBS).orElse(ImmutableList.of())).stream().filter(EntityZoglin::predicate).findFirst(); // Purpur - decompile error - } - -- private static boolean i(EntityLiving entityliving) { -+ private static boolean predicate(EntityLiving entityliving) { // Purpur - decompile error - EntityTypes entitytypes = entityliving.getEntityType(); - - return entitytypes != EntityTypes.ZOGLIN && entitytypes != EntityTypes.CREEPER && IEntitySelector.f.test(entityliving); -@@ -181,14 +193,14 @@ public class EntityZoglin extends EntityMonster implements IMonster, IOglin { - - @Override - public BehaviorController getBehaviorController() { -- return super.getBehaviorController(); -+ return (BehaviorController) super.getBehaviorController(); // Purpur - decompile error - } - - protected void eL() { -- Activity activity = (Activity) this.bg.f().orElse((Object) null); -+ Activity activity = (Activity) this.bg.f().orElse(null); // Purpur - decompile error - - this.bg.a((List) ImmutableList.of(Activity.FLIGHT, Activity.IDLE)); -- Activity activity1 = (Activity) this.bg.f().orElse((Object) null); -+ Activity activity1 = (Activity) this.bg.f().orElse(null); // Purpur - decompile error - - if (activity1 == Activity.FLIGHT && activity != Activity.FLIGHT) { - this.eN(); -@@ -200,7 +212,8 @@ public class EntityZoglin extends EntityMonster implements IMonster, IOglin { - @Override - protected void mobTick() { - this.world.getMethodProfiler().enter("zoglinBrain"); -- this.getBehaviorController().a((WorldServer) this.world, (EntityLiving) this); -+ if (getPurpurRider() == null) // Purpur - only use brain if no rider -+ this.getBehaviorController().a((WorldServer) this.world, this); // Purpur - decompile error - this.world.getMethodProfiler().exit(); - this.eL(); - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index 5ac950614fc90d02a568bb38f71faee124584c16..901fe8d224130c67bad00636b065bc798859a18e 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -16,6 +16,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffect; -@@ -108,6 +109,16 @@ public class EntityZombie extends EntityMonster { - } - - // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.zombieRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.zombieRidableInWater; -+ } -+ - public boolean jockeyOnlyBaby() { - return world.purpurConfig.zombieJockeyOnlyBaby; - } -@@ -123,9 +134,11 @@ public class EntityZombie extends EntityMonster { - - @Override - protected void initPathfinder() { -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - if (world.paperConfig.zombiesTargetTurtleEggs) this.goalSelector.a(4, new EntityZombie.a(this, 1.0D, 3)); // Paper - this.goalSelector.a(8, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this)); -+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.m(); - } - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java -index 5d3e5873f19aaf8389eb5525693b9378ea9f94ee..ad801fc394fbb83cf280ee96f962e7f311615d72 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java -@@ -23,6 +23,16 @@ public class EntityZombieHusk extends EntityZombie { - } - - // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.huskRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.huskRidableInWater; -+ } -+ - @Override - public boolean jockeyOnlyBaby() { - return world.purpurConfig.huskJockeyOnlyBaby; -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java -index 99d0932e5352589cfbcc48a5e789651d0d77edde..b8395c7317494adf36010080931a1c8635ab6cfa 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java -@@ -71,6 +71,16 @@ public class EntityZombieVillager extends EntityZombie implements VillagerDataHo - } - - // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.zombieVillagerRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.zombieVillagerRidableInWater; -+ } -+ - @Override - public boolean jockeyOnlyBaby() { - return world.purpurConfig.zombieVillagerJockeyOnlyBaby; -diff --git a/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java b/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java -index 375409f4b72edc7990da90460b30486fb2980fb6..9bac45983b55abf9b72f2c45f632cdedd48f81f9 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java -+++ b/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java -@@ -54,13 +54,25 @@ public class EntityHoglin extends EntityAnimal implements IMonster, IOglin { - public int conversionTicks = 0; - public boolean cannotBeHunted = false; - protected static final ImmutableList>> bo = ImmutableList.of(SensorType.c, SensorType.d, SensorType.n, SensorType.m); -- protected static final ImmutableList> bp = ImmutableList.of(MemoryModuleType.BREED_TARGET, MemoryModuleType.MOBS, MemoryModuleType.VISIBLE_MOBS, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, MemoryModuleType.LOOK_TARGET, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.PATH, MemoryModuleType.ATTACK_TARGET, MemoryModuleType.ATTACK_COOLING_DOWN, MemoryModuleType.NEAREST_VISIBLE_ADULT_PIGLIN, new MemoryModuleType[]{MemoryModuleType.AVOID_TARGET, MemoryModuleType.VISIBLE_ADULT_PIGLIN_COUNT, MemoryModuleType.VISIBLE_ADULT_HOGLIN_COUNT, MemoryModuleType.NEAREST_VISIBLE_ADULT_HOGLINS, MemoryModuleType.NEAREST_VISIBLE_ADULY, MemoryModuleType.NEAREST_REPELLENT, MemoryModuleType.PACIFIED}); -+ protected static final ImmutableList bp = ImmutableList.of(MemoryModuleType.BREED_TARGET, MemoryModuleType.MOBS, MemoryModuleType.VISIBLE_MOBS, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, MemoryModuleType.LOOK_TARGET, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.PATH, MemoryModuleType.ATTACK_TARGET, MemoryModuleType.ATTACK_COOLING_DOWN, MemoryModuleType.NEAREST_VISIBLE_ADULT_PIGLIN, new MemoryModuleType[]{MemoryModuleType.AVOID_TARGET, MemoryModuleType.VISIBLE_ADULT_PIGLIN_COUNT, MemoryModuleType.VISIBLE_ADULT_HOGLIN_COUNT, MemoryModuleType.NEAREST_VISIBLE_ADULT_HOGLINS, MemoryModuleType.NEAREST_VISIBLE_ADULY, MemoryModuleType.NEAREST_REPELLENT, MemoryModuleType.PACIFIED}); // Purpur - decompile error - - public EntityHoglin(EntityTypes entitytypes, World world) { - super(entitytypes, world); - this.f = 5; - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.hoglinRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.hoglinRidableInWater; -+ } -+ // Purpur end -+ - @Override - public boolean a(EntityHuman entityhuman) { - return !this.isLeashed(); -@@ -118,13 +130,14 @@ public class EntityHoglin extends EntityAnimal implements IMonster, IOglin { - - @Override - public BehaviorController getBehaviorController() { -- return super.getBehaviorController(); -+ return (BehaviorController) super.getBehaviorController(); // Purpur decompile error - } - - @Override - protected void mobTick() { - this.world.getMethodProfiler().enter("hoglinBrain"); -- this.getBehaviorController().a((WorldServer) this.world, (EntityLiving) this); -+ if (getPurpurRider() == null) // Purpur - only use brain if no rider -+ this.getBehaviorController().a((WorldServer) this.world, this); // Purpour - decompile error - this.world.getMethodProfiler().exit(); - HoglinAI.a(this); - if (this.isConverting()) { -@@ -300,7 +313,7 @@ public class EntityHoglin extends EntityAnimal implements IMonster, IOglin { - - @Override - protected SoundEffect getSoundAmbient() { -- return this.world.isClientSide ? null : (SoundEffect) HoglinAI.b(this).orElse((Object) null); -+ return this.world.isClientSide ? null : (SoundEffect) HoglinAI.b(this).orElse(null); // Purpur - decompile error - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java -index 9a7bebd77302dbfd07ac802acbe2b9cb80eec26f..edac17b1072102abe322d69072c4277e6c21cfbe 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java -+++ b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java -@@ -86,6 +86,18 @@ public class EntityPiglin extends EntityPiglinAbstract implements ICrossbow { - this.f = 5; - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.piglinRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.piglinRidableInWater; -+ } -+ // Purpur end -+ - @Override - public void saveData(NBTTagCompound nbttagcompound) { - super.saveData(nbttagcompound); -@@ -275,6 +287,7 @@ public class EntityPiglin extends EntityPiglinAbstract implements ICrossbow { - @Override - protected void mobTick() { - this.world.getMethodProfiler().enter("piglinBrain"); -+ if (getPurpurRider() == null) // Purpur - only use brain if no rider - this.getBehaviorController().a((WorldServer) this.world, (EntityPiglin) this); // CraftBukkit - decompile error - this.world.getMethodProfiler().exit(); - PiglinAI.b(this); -diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglinBrute.java b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglinBrute.java -index 3d85501791fce621335f34bf508becb74b80210d..1370d2d8568a4ed62f2ec3d54abc7d2bebc48f75 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglinBrute.java -+++ b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglinBrute.java -@@ -39,6 +39,18 @@ public class EntityPiglinBrute extends EntityPiglinAbstract { - this.f = 20; - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.piglinBruteRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.piglinBruteRidableInWater; -+ } -+ // Purpur end -+ - public static AttributeProvider.Builder eS() { - return EntityMonster.eR().a(GenericAttributes.MAX_HEALTH, 50.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.3499999940395355D).a(GenericAttributes.ATTACK_DAMAGE, 7.0D); - } -@@ -68,7 +80,7 @@ public class EntityPiglinBrute extends EntityPiglinAbstract { - - @Override - public BehaviorController getBehaviorController() { -- return super.getBehaviorController(); -+ return (BehaviorController) super.getBehaviorController(); // Purpur - decompile error - } - - @Override -@@ -84,7 +96,8 @@ public class EntityPiglinBrute extends EntityPiglinAbstract { - @Override - protected void mobTick() { - this.world.getMethodProfiler().enter("piglinBruteBrain"); -- this.getBehaviorController().a((WorldServer) this.world, (EntityLiving) this); -+ if (getPurpurRider() == null) // Purpur - only use brain if no rider -+ this.getBehaviorController().a((WorldServer) this.world, this); // Purpur - decompile error - this.world.getMethodProfiler().exit(); - PiglinBruteAI.b(this); - PiglinBruteAI.c(this); -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index 2ff9dffc0f0b20582f5b3bffd01743ee26c63c20..85242947bd115f63f8807e1d4e6784fff537e802 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -32,6 +32,7 @@ import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; - import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -145,8 +146,19 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - } - - // Purpur start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.villagerRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.villagerRidableInWater; -+ } -+ - @Override - protected void initPathfinder() { -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - if (world.purpurConfig.villagerFollowEmeraldBlock) this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.0D, false, TEMPT_ITEMS)); - } - -@@ -311,7 +323,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - if (itemstack.getItem() != Items.VILLAGER_SPAWN_EGG && this.isAlive() && !this.eN() && !this.isSleeping()) { - if (this.isBaby()) { - this.fk(); -- return EnumInteractionResult.a(this.world.isClientSide); -+ return super.b(entityhuman, enumhand); // Purpur - } else { - boolean flag = this.getOffers().isEmpty(); - -@@ -324,8 +336,9 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - } - - if (flag) { -- return EnumInteractionResult.a(this.world.isClientSide); -+ return tryRide(entityhuman, enumhand); // Purpur - } else { -+ if (world.purpurConfig.villagerRidable && itemstack.isEmpty()) return tryRide(entityhuman, enumhand); // Purpur - if (!this.world.isClientSide && !this.trades.isEmpty()) { - this.h(entityhuman); - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -index 8df4d985e3124ddc1643da8385b15348937bc320..6c390fb20c7f29133a60780a75676d8d3d6eab29 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -@@ -6,6 +6,7 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.IPosition; - import net.minecraft.nbt.GameProfileSerializer; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.PathfinderGoalHasRider; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -73,6 +74,7 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { - @Override - protected void initPathfinder() { - this.goalSelector.a(0, new PathfinderGoalFloat(this)); -+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(0, new PathfinderGoalUseItem<>(this, PotionUtil.a(new ItemStack(Items.POTION), Potions.INVISIBILITY), SoundEffects.ENTITY_WANDERING_TRADER_DISAPPEARED, (entityvillagertrader) -> { - return canDrinkPotion && this.world.isNight() && !entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API - })); -@@ -98,6 +100,16 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { - } - - // Purpur - start -+ @Override -+ public boolean isRidable() { -+ return world.purpurConfig.villagerTraderRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return world.purpurConfig.villagerTraderRidableInWater; -+ } -+ - @Override - public boolean a(EntityHuman entityhuman) { - return world.purpurConfig.villagerTraderCanBeLeashed && !this.isLeashed(); -@@ -125,8 +137,9 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { - } - - if (this.getOffers().isEmpty()) { -- return EnumInteractionResult.a(this.world.isClientSide); -+ return tryRide(entityhuman, enumhand); // Purpur - } else { -+ if (world.purpurConfig.villagerTraderRidable && itemstack.isEmpty()) return tryRide(entityhuman, enumhand); // Purpur - if (!this.world.isClientSide) { - this.setTradingPlayer(entityhuman); - this.openTrade(entityhuman, this.getScoreboardDisplayName(), 1); -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 98a27249164be967512e7e745c20e80c80d3c5c8..92c086d276662d2de5c8f136a998384d54390b72 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -111,7 +111,6 @@ import net.minecraft.world.phys.AxisAlignedBB; - import net.minecraft.world.phys.Vec3D; - import net.minecraft.world.scores.Scoreboard; - import net.minecraft.world.scores.ScoreboardTeam; --import net.minecraft.world.scores.ScoreboardTeamBase; - - // CraftBukkit start - import org.bukkit.craftbukkit.entity.CraftHumanEntity; -@@ -182,6 +181,8 @@ public abstract class EntityHuman extends EntityLiving { - // CraftBukkit end - - // Purpur start -+ public abstract void resetIdleTimer(); -+ - private javax.script.ScriptEngine scriptEngine = new javax.script.ScriptEngineManager().getEngineByName("rhino"); - - public void setAfk(boolean setAfk){ -@@ -2259,4 +2260,15 @@ public abstract class EntityHuman extends EntityLiving { - return this.g; - } - } -+ -+ // Purpur start -+ @Override -+ public boolean processClick(EnumHand hand) { -+ Entity vehicle = getRootVehicle(); -+ if (vehicle != null && vehicle.getPurpurRider() == this) { -+ return vehicle.onClick(hand); -+ } -+ return false; -+ } -+ // Purpur end - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -index 8fe98404ebb8b3b5d1fdac0896b27da10736026d..390023a7a825eed850a13572b719f47ed534c003 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -@@ -24,7 +24,7 @@ public abstract class IProjectile extends Entity { - - private UUID shooter; - private int c; -- private boolean d; -+ private boolean d; public boolean leftOwner() { return d; } public void setLeftOwner(boolean leftOwner) { this.d = leftOwner; } // Purpur - OBFHELPER - - // CraftBukkit start - private boolean hitCancelled = false; -@@ -90,6 +90,7 @@ public abstract class IProjectile extends Entity { - super.tick(); - } - -+ public boolean checkIfLeftOwner() { return this.h(); } // Purpur - OBFHELPER - private boolean h() { - Entity entity = this.getShooter(); - -@@ -167,7 +168,7 @@ public abstract class IProjectile extends Entity { - iblockdata.a(this.world, iblockdata, movingobjectpositionblock, this); - } - -- protected boolean a(Entity entity) { -+ protected boolean a(Entity entity) { return hitPredicate(entity); } public boolean hitPredicate(Entity entity) { // Purpur - OBFHELPER - if (!entity.isSpectator() && entity.isAlive() && entity.isInteractable()) { - Entity entity1 = this.getShooter(); - // Paper start - Cancel hit for vanished players -diff --git a/src/main/java/net/minecraft/world/entity/projectile/ProjectileHelper.java b/src/main/java/net/minecraft/world/entity/projectile/ProjectileHelper.java -index 75889ac851d1c2b26c0b57bea6b75c1b65c2309f..80834537eba8bd33a0688e19d0aa9b963de4398a 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/ProjectileHelper.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/ProjectileHelper.java -@@ -21,6 +21,7 @@ import net.minecraft.world.phys.Vec3D; - - public final class ProjectileHelper { - -+ public static MovingObjectPosition getHitResult(Entity entity, Predicate predicate) { return a(entity, predicate); } // Purpur - OBFHELPER - public static MovingObjectPosition a(Entity entity, Predicate predicate) { - Vec3D vec3d = entity.getMot(); - World world = entity.world; -diff --git a/src/main/java/net/minecraft/world/level/GeneratorAccess.java b/src/main/java/net/minecraft/world/level/GeneratorAccess.java -index 96efd974f1eb9c1e7c70e576e51ed69e15aacb99..fc86ef53c48503139667f7703019a07c40814fd4 100644 ---- a/src/main/java/net/minecraft/world/level/GeneratorAccess.java -+++ b/src/main/java/net/minecraft/world/level/GeneratorAccess.java -@@ -48,6 +48,7 @@ public interface GeneratorAccess extends ICombinedAccess, IWorldTime { - - void addParticle(ParticleParam particleparam, double d0, double d1, double d2, double d3, double d4, double d5); - -+ default void playEvent(@Nullable EntityHuman entityhuman, int i, BlockPosition blockposition, int j) { a(entityhuman, i, blockposition, j); } // Purpur - OBFHELPER - void a(@Nullable EntityHuman entityhuman, int i, BlockPosition blockposition, int j); - - default int getHeight() { -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 2c4bfc663c31e72706eedd4db4533db5a50456db..d55a139f91905e8a2af125b4eeee05c957feae0a 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -1547,5 +1547,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public boolean isTheEnd() { - return getWorld().getEnvironment() == org.bukkit.World.Environment.THE_END; - } -+ -+ // Purpur start -+ public void playEffect(@Nullable EntityHuman entityhuman, int i, BlockPosition blockposition, int j) { -+ this.a(entityhuman, i, blockposition, j); -+ } - // Purpur end - } -diff --git a/src/main/java/net/minecraft/world/phys/Vec3D.java b/src/main/java/net/minecraft/world/phys/Vec3D.java -index b71e119eed6fa283d99dc033144c8be7b336d9c4..df6358d07ecad978383b679e7d03cdb2039de452 100644 ---- a/src/main/java/net/minecraft/world/phys/Vec3D.java -+++ b/src/main/java/net/minecraft/world/phys/Vec3D.java -@@ -44,6 +44,7 @@ public class Vec3D implements IPosition { - return new Vec3D(vec3d.x - this.x, vec3d.y - this.y, vec3d.z - this.z); - } - -+ public Vec3D normalize() { return d(); } // Purpur - OBFHELPER - public Vec3D d() { - double d0 = (double) MathHelper.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); - -@@ -102,6 +103,7 @@ public class Vec3D implements IPosition { - return d3 * d3 + d4 * d4 + d5 * d5; - } - -+ public Vec3D scale(double scale) { return a(scale); } // Purpur - OBFHELPER - public Vec3D a(double d0) { - return this.d(d0, d0, d0); - } -@@ -110,6 +112,7 @@ public class Vec3D implements IPosition { - return this.d(vec3d.x, vec3d.y, vec3d.z); - } - -+ public Vec3D multiply (double x, double y, double z) { return d(x, y, z); } // Purpur - OBFHELPER - public Vec3D d(double d0, double d1, double d2) { - return new Vec3D(this.x * d0, this.y * d1, this.z * d2); - } -diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index fc458beb3afcb9083b994246454c6ee3d94c80ac..65f436e0a27c8687180d7008dbff1cf8f667383c 100644 ---- a/src/main/java/net/pl3x/purpur/PurpurConfig.java -+++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java -@@ -137,11 +137,13 @@ public class PurpurConfig { - public static String afkBroadcastBack = "§e§o%s is no longer AFK"; - public static String afkTabListPrefix = "[AFK] "; - public static String pingCommandOutput = "§a%s's ping is %sms"; -+ public static String cannotRideMob = "§cYou cannot mount that mob"; - private static void messages() { - afkBroadcastAway = getString("settings.messages.afk-broadcast-away", afkBroadcastAway); - afkBroadcastBack = getString("settings.messages.afk-broadcast-back", afkBroadcastBack); - afkTabListPrefix = getString("settings.messages.afk-tab-list-prefix", afkTabListPrefix); - pingCommandOutput = getString("settings.messages.ping-command-output", pingCommandOutput); -+ cannotRideMob = getString("settings.messages.cannot-ride-mob", cannotRideMob); - } - - 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 f16f99517999ccbb0b5a678ffcb3befc93a3ae45..9fcc63a2f4a4c363ace85087665bf3a978d3d648 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 { - } - } - -- public double vindicatorJohnnySpawnChance = 0D; -- private void vindicatorSettings() { -- vindicatorJohnnySpawnChance = getDouble("mobs.vindicator.johnny.spawn-chance", vindicatorJohnnySpawnChance); -- } -- - private ConfigurationSection getConfigurationSection(String path) { - ConfigurationSection section = PurpurConfig.config.getConfigurationSection("world-settings." + worldName + "." + path); - return section != null ? section : PurpurConfig.config.getConfigurationSection("world-settings.default." + path); -@@ -385,61 +380,186 @@ public class PurpurWorldConfig { - turtleEggsBreakFromMinecarts = getBoolean("blocks.turtle_egg.break-from-minecarts", turtleEggsBreakFromMinecarts); - } - -+ public boolean babiesAreRidable = true; -+ public boolean untamedTamablesAreRidable = true; -+ public boolean useNightVisionWhenRiding = false; -+ private void ridableSettings() { -+ babiesAreRidable = getBoolean("ridable-settings.babies-are-ridable", babiesAreRidable); -+ untamedTamablesAreRidable = getBoolean("ridable-settings.untamed-tamables-are-ridable", untamedTamablesAreRidable); -+ useNightVisionWhenRiding = getBoolean("ridable-settings.use-night-vision", useNightVisionWhenRiding); -+ } -+ -+ public boolean batRidable = false; -+ public boolean batRidableInWater = false; -+ public double batMaxY = 256D; -+ private void batSettings() { -+ batRidable = getBoolean("mobs.bat.ridable", batRidable); -+ batRidableInWater = getBoolean("mobs.bat.ridable-in-water", batRidableInWater); -+ batMaxY = getDouble("mobs.bat.ridable-max-y", batMaxY); -+ } -+ -+ public boolean beeRidable = false; -+ public boolean beeRidableInWater = false; -+ public double beeMaxY = 256D; -+ private void beeSettings() { -+ beeRidable = getBoolean("mobs.bee.ridable", beeRidable); -+ beeRidableInWater = getBoolean("mobs.bee.ridable-in-water", beeRidableInWater); -+ beeMaxY = getDouble("mobs.bee.ridable-max-y", beeMaxY); -+ } -+ -+ public boolean blazeRidable = false; -+ public boolean blazeRidableInWater = false; -+ public double blazeMaxY = 256D; -+ private void blazeSettings() { -+ blazeRidable = getBoolean("mobs.blaze.ridable", blazeRidable); -+ blazeRidableInWater = getBoolean("mobs.blaze.ridable-in-water", blazeRidableInWater); -+ blazeMaxY = getDouble("mobs.blaze.ridable-max-y", blazeMaxY); -+ } -+ -+ public boolean catRidable = false; -+ public boolean catRidableInWater = false; - public int catSpawnDelay = 1200; - public int catSpawnSwampHutScanRange = 16; - public int catSpawnVillageScanRange = 48; - private void catSettings() { -+ catRidable = getBoolean("mobs.cat.ridable", catRidable); -+ catRidableInWater = getBoolean("mobs.cat.ridable-in-water", catRidableInWater); - catSpawnDelay = getInt("mobs.cat.spawn-delay", catSpawnDelay); - catSpawnSwampHutScanRange = getInt("mobs.cat.scan-range-for-other-cats.swamp-hut", catSpawnSwampHutScanRange); - catSpawnVillageScanRange = getInt("mobs.cat.scan-range-for-other-cats.village", catSpawnVillageScanRange); - } - -+ public boolean caveSpiderRidable = false; -+ public boolean caveSpiderRidableInWater = false; -+ private void caveSpiderSettings() { -+ caveSpiderRidable = getBoolean("mobs.cave_spider.ridable", caveSpiderRidable); -+ caveSpiderRidableInWater = getBoolean("mobs.cave_spider.ridable-in-water", caveSpiderRidableInWater); -+ } -+ -+ public boolean chickenRidable = false; -+ public boolean chickenRidableInWater = false; - public boolean chickenRetaliate = false; - private void chickenSettings() { -+ chickenRidable = getBoolean("mobs.chicken.ridable", chickenRidable); -+ chickenRidableInWater = getBoolean("mobs.chicken.ridable-in-water", chickenRidableInWater); - chickenRetaliate = getBoolean("mobs.chicken.retaliate", chickenRetaliate); - } - -+ public boolean codRidable = false; -+ private void codSettings() { -+ codRidable = getBoolean("mobs.cod.ridable", codRidable); -+ } -+ -+ public boolean cowRidable = false; -+ public boolean cowRidableInWater = false; - public int cowFeedMushrooms = 0; - private void cowSettings() { -+ cowRidable = getBoolean("mobs.cow.ridable", cowRidable); -+ cowRidableInWater = getBoolean("mobs.cow.ridable-in-water", cowRidableInWater); - cowFeedMushrooms = getInt("mobs.cow.feed-mushrooms-for-mooshroom", cowFeedMushrooms); - } - -+ public boolean creeperRidable = false; -+ public boolean creeperRidableInWater = false; - public boolean creeperAllowGriefing = true; - public double creeperChargedChance = 0.0D; - private void creeperSettings() { -+ creeperRidable = getBoolean("mobs.creeper.ridable", creeperRidable); -+ creeperRidableInWater = getBoolean("mobs.creeper.ridable-in-water", creeperRidableInWater); - creeperAllowGriefing = getBoolean("mobs.creeper.allow-griefing", creeperAllowGriefing); - creeperChargedChance = getDouble("mobs.creeper.naturally-charged-chance", creeperChargedChance); - } - -+ public boolean dolphinRidable = false; -+ public int dolphinSpitCooldown = 20; -+ public float dolphinSpitSpeed = 1.0F; -+ public float dolphinSpitDamage = 2.0F; - public boolean dolphinDisableTreasureSearching = false; - private void dolphinSettings() { -+ dolphinRidable = getBoolean("mobs.dolphin.ridable", dolphinRidable); -+ dolphinSpitCooldown = getInt("mobs.dolphin.spit.cooldown", dolphinSpitCooldown); -+ dolphinSpitSpeed = (float) getDouble("mobs.dolphin.spit.speed", dolphinSpitSpeed); -+ dolphinSpitDamage = (float) getDouble("mobs.dolphin.spit.damage", dolphinSpitDamage); - dolphinDisableTreasureSearching = getBoolean("mobs.dolphin.disable-treasure-searching", dolphinDisableTreasureSearching); - } - -+ public boolean donkeyRidableInWater = false; -+ private void donkeySettings() { -+ donkeyRidableInWater = getBoolean("mobs.donkey.ridable-in-water", donkeyRidableInWater); -+ } -+ -+ public boolean drownedRidable = false; -+ public boolean drownedRidableInWater = false; - public boolean drownedJockeyOnlyBaby = true; - public double drownedJockeyChance = 0.05D; - public boolean drownedJockeyTryExistingChickens = true; - private void drownedSettings() { -+ drownedRidable = getBoolean("mobs.drowned.ridable", drownedRidable); -+ drownedRidableInWater = getBoolean("mobs.drowned.ridable-in-water", drownedRidableInWater); - drownedJockeyOnlyBaby = getBoolean("mobs.drowned.jockey.only-babies", drownedJockeyOnlyBaby); - drownedJockeyChance = getDouble("mobs.drowned.jockey.chance", drownedJockeyChance); - drownedJockeyTryExistingChickens = getBoolean("mobs.drowned.jockey.try-existing-chickens", drownedJockeyTryExistingChickens); - } - -+ public boolean elderGuardianRidable = false; -+ private void elderGuardianSettings() { -+ elderGuardianRidable = getBoolean("mobs.elder_guardian.ridable", elderGuardianRidable); -+ } -+ -+ public boolean enderDragonRidable = false; -+ public boolean enderDragonRidableInWater = false; -+ public double enderDragonMaxY = 256D; - public boolean enderDragonAlwaysDropsFullExp = false; - private void enderDragonSettings() { -+ enderDragonRidable = getBoolean("mobs.ender_dragon.ridable", enderDragonRidable); -+ enderDragonRidableInWater = getBoolean("mobs.ender_dragon.ridable-in-water", enderDragonRidableInWater); -+ enderDragonMaxY = getDouble("mobs.ender_dragon.ridable-max-y", enderDragonMaxY); - enderDragonAlwaysDropsFullExp = getBoolean("mobs.ender_dragon.always-drop-full-exp", enderDragonAlwaysDropsFullExp); - } - -+ public boolean endermanRidable = false; -+ public boolean endermanRidableInWater = false; - public boolean endermanAllowGriefing = true; - private void endermanSettings() { -+ endermanRidable = getBoolean("mobs.enderman.ridable", endermanRidable); -+ endermanRidableInWater = getBoolean("mobs.enderman.ridable-in-water", endermanRidableInWater); - endermanAllowGriefing = getBoolean("mobs.enderman.allow-griefing", endermanAllowGriefing); - } - -+ public boolean endermiteRidable = false; -+ public boolean endermiteRidableInWater = false; -+ private void endermiteSettings() { -+ endermiteRidable = getBoolean("mobs.endermite.ridable", endermiteRidable); -+ endermiteRidableInWater = getBoolean("mobs.endermite.ridable-in-water", endermiteRidableInWater); -+ } -+ -+ public boolean evokerRidable = false; -+ public boolean evokerRidableInWater = false; -+ private void evokerSettings() { -+ evokerRidable = getBoolean("mobs.evoker.ridable", evokerRidable); -+ evokerRidableInWater = getBoolean("mobs.evoker.ridable-in-water", evokerRidableInWater); -+ } -+ -+ public boolean foxRidable = false; -+ public boolean foxRidableInWater = false; - public boolean foxTypeChangesWithTulips = false; - private void foxSettings() { -+ foxRidable = getBoolean("mobs.fox.ridable", foxRidable); -+ foxRidableInWater = getBoolean("mobs.fox.ridable-in-water", foxRidableInWater); - foxTypeChangesWithTulips = getBoolean("mobs.fox.tulips-change-type", foxTypeChangesWithTulips); - } - -+ public boolean ghastRidable = false; -+ public boolean ghastRidableInWater = false; -+ public double ghastMaxY = 256D; -+ private void ghastSettings() { -+ ghastRidable = getBoolean("mobs.ghast.ridable", ghastRidable); -+ ghastRidableInWater = getBoolean("mobs.ghast.ridable-in-water", ghastRidableInWater); -+ ghastMaxY = getDouble("mobs.ghast.ridable-max-y", ghastMaxY); -+ } -+ -+ public boolean giantRidable = false; -+ public boolean giantRidableInWater = false; - public float giantStepHeight = 2.0F; - public float giantJumpHeight = 1.0F; - public double giantMovementSpeed = 0.5D; -@@ -448,6 +568,8 @@ public class PurpurWorldConfig { - public boolean giantHaveHostileAI = false; - public double giantMaxHealth = 100.0D; - private void giantSettings() { -+ giantRidable = getBoolean("mobs.giant.ridable", giantRidable); -+ giantRidableInWater = getBoolean("mobs.giant.ridable-in-water", giantRidableInWater); - giantStepHeight = (float) getDouble("mobs.giant.step-height", giantStepHeight); - giantJumpHeight = (float) getDouble("mobs.giant.jump-height", giantJumpHeight); - giantMovementSpeed = getDouble("mobs.giant.movement-speed", giantMovementSpeed); -@@ -462,19 +584,44 @@ public class PurpurWorldConfig { - giantMaxHealth = getDouble("mobs.giant.attributes.max-health", giantMaxHealth); - } - -+ public boolean guardianRidable = false; -+ private void guardianSettings() { -+ guardianRidable = getBoolean("mobs.guardian.ridable", guardianRidable); -+ } -+ -+ public boolean hoglinRidable = false; -+ public boolean hoglinRidableInWater = false; -+ private void hoglinSettings() { -+ hoglinRidable = getBoolean("mobs.hoglin.ridable", hoglinRidable); -+ hoglinRidableInWater = getBoolean("mobs.hoglin.ridable-in-water", hoglinRidableInWater); -+ } -+ -+ public boolean horseRidableInWater = false; -+ private void horseSettings() { -+ horseRidableInWater = getBoolean("mobs.horse.ridable-in-water", horseRidableInWater); -+ } -+ -+ public boolean huskRidable = false; -+ public boolean huskRidableInWater = false; - public boolean huskJockeyOnlyBaby = true; - public double huskJockeyChance = 0.05D; - public boolean huskJockeyTryExistingChickens = true; - private void huskSettings() { -+ huskRidable = getBoolean("mobs.husk.ridable", huskRidable); -+ huskRidableInWater = getBoolean("mobs.husk.ridable-in-water", huskRidableInWater); - huskJockeyOnlyBaby = getBoolean("mobs.husk.jockey.only-babies", huskJockeyOnlyBaby); - huskJockeyChance = getDouble("mobs.husk.jockey.chance", huskJockeyChance); - huskJockeyTryExistingChickens = getBoolean("mobs.husk.jockey.try-existing-chickens", huskJockeyTryExistingChickens); - } - -+ public boolean illusionerRidable = false; -+ public boolean illusionerRidableInWater = false; - public double illusionerMovementSpeed = 0.5D; - public double illusionerFollowRange = 18.0D; - public double illusionerMaxHealth = 32.0D; - private void illusionerSettings() { -+ illusionerRidable = getBoolean("mobs.illusioner.ridable", illusionerRidable); -+ illusionerRidableInWater = getBoolean("mobs.illusioner.ridable-in-water", illusionerRidableInWater); - illusionerMovementSpeed = getDouble("mobs.illusioner.movement-speed", illusionerMovementSpeed); - illusionerFollowRange = getDouble("mobs.illusioner.follow-range", illusionerFollowRange); - if (PurpurConfig.version < 8) { -@@ -485,11 +632,76 @@ public class PurpurWorldConfig { - illusionerMaxHealth = getDouble("mobs.illusioner.attributes.max-health", illusionerMaxHealth); - } - -+ public boolean ironGolemRidable = false; -+ public boolean ironGolemRidableInWater = false; - public boolean ironGolemCanSwim = false; - private void ironGolemSettings() { -+ ironGolemRidable = getBoolean("mobs.iron_golem.ridable", ironGolemRidable); -+ ironGolemRidableInWater = getBoolean("mobs.iron_golem.ridable-in-water", ironGolemRidableInWater); - ironGolemCanSwim = getBoolean("mobs.iron_golem.can-swim", ironGolemCanSwim); - } - -+ public boolean llamaRidable = false; -+ public boolean llamaRidableInWater = false; -+ private void llamaSettings() { -+ llamaRidable = getBoolean("mobs.llama.ridable", llamaRidable); -+ llamaRidableInWater = getBoolean("mobs.llama.ridable-in-water", llamaRidableInWater); -+ } -+ -+ public boolean llamaTraderRidable = false; -+ public boolean llamaTraderRidableInWater = false; -+ private void llamaTraderSettings() { -+ llamaTraderRidable = getBoolean("mobs.trader_llama.ridable", llamaTraderRidable); -+ llamaTraderRidableInWater = getBoolean("mobs.trader_llama.ridable-in-water", llamaTraderRidableInWater); -+ } -+ -+ public boolean magmaCubeRidable = false; -+ public boolean magmaCubeRidableInWater = false; -+ private void magmaCubeSettings() { -+ magmaCubeRidable = getBoolean("mobs.magma_cube.ridable", magmaCubeRidable); -+ magmaCubeRidableInWater = getBoolean("mobs.magma_cube.ridable-in-water", magmaCubeRidableInWater); -+ } -+ -+ public boolean mooshroomRidable = false; -+ public boolean mooshroomRidableInWater = false; -+ private void mooshroomSettings() { -+ mooshroomRidable = getBoolean("mobs.mooshroom.ridable", mooshroomRidable); -+ mooshroomRidableInWater = getBoolean("mobs.mooshroom.ridable-in-water", mooshroomRidableInWater); -+ } -+ -+ public boolean muleRidableInWater = false; -+ private void muleSettings() { -+ muleRidableInWater = getBoolean("mobs.mule.ridable-in-water", muleRidableInWater); -+ } -+ -+ public boolean ocelotRidable = false; -+ public boolean ocelotRidableInWater = false; -+ private void ocelotSettings() { -+ ocelotRidable = getBoolean("mobs.ocelot.ridable", ocelotRidable); -+ ocelotRidableInWater = getBoolean("mobs.ocelot.ridable-in-water", ocelotRidableInWater); -+ } -+ -+ public boolean pandaRidable = false; -+ public boolean pandaRidableInWater = false; -+ private void pandaSettings() { -+ pandaRidable = getBoolean("mobs.panda.ridable", pandaRidable); -+ pandaRidableInWater = getBoolean("mobs.panda.ridable-in-water", pandaRidableInWater); -+ } -+ -+ public boolean parrotRidable = false; -+ public boolean parrotRidableInWater = false; -+ public double parrotMaxY = 256D; -+ private void parrotSettings() { -+ parrotRidable = getBoolean("mobs.parrot.ridable", parrotRidable); -+ parrotRidableInWater = getBoolean("mobs.parrot.ridable-in-water", parrotRidableInWater); -+ parrotMaxY = getDouble("mobs.parrot.ridable-max-y", parrotMaxY); -+ } -+ -+ public boolean phantomRidable = false; -+ public boolean phantomRidableInWater = false; -+ public double phantomMaxY = 256D; -+ public float phantomFlameDamage = 1.0F; -+ public int phantomFlameFireTime = 8; - public double phantomAttackedByCrystalRadius = 0.0D; - public float phantomAttackedByCrystalDamage = 1.0F; - public double phantomOrbitCrystalRadius = 0.0D; -@@ -508,7 +720,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); -+ phantomMaxY = getDouble("mobs.phantom.ridable-max-y", phantomMaxY); -+ phantomFlameDamage = (float) getDouble("mobs.phantom.flames.damage", phantomFlameDamage); -+ phantomFlameFireTime = getInt("mobs.phantom.flames.fire-time", phantomFlameFireTime); - 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); -@@ -527,42 +745,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; -+ public boolean pigRidableInWater = false; - public boolean pigGiveSaddleBack = false; - private void pigSettings() { -+ pigRidable = getBoolean("mobs.pig.ridable", pigRidable); -+ pigRidableInWater = getBoolean("mobs.pig.ridable-in-water", pigRidableInWater); - pigGiveSaddleBack = getBoolean("mobs.pig.give-saddle-back", pigGiveSaddleBack); - } - -+ public boolean piglinRidable = false; -+ public boolean piglinRidableInWater = false; -+ private void piglinSettings() { -+ piglinRidable = getBoolean("mobs.piglin.ridable", piglinRidable); -+ piglinRidableInWater = getBoolean("mobs.piglin.ridable-in-water", piglinRidableInWater); -+ } -+ -+ public boolean piglinBruteRidable = false; -+ public boolean piglinBruteRidableInWater = false; -+ private void piglinBruteSettings() { -+ piglinBruteRidable = getBoolean("mobs.piglin_brute.ridable", piglinBruteRidable); -+ piglinBruteRidableInWater = getBoolean("mobs.piglin_brute.ridable-in-water", piglinBruteRidableInWater); -+ } -+ -+ public boolean pillagerRidable = false; -+ public boolean pillagerRidableInWater = false; -+ private void pillagerSettings() { -+ pillagerRidable = getBoolean("mobs.pillager.ridable", pillagerRidable); -+ pillagerRidableInWater = getBoolean("mobs.pillager.ridable-in-water", pillagerRidableInWater); -+ } -+ -+ public boolean polarBearRidable = false; -+ public boolean polarBearRidableInWater = false; - public String polarBearBreedableItemString = ""; - public Item polarBearBreedableItem = null; - private void polarBearSettings() { -+ polarBearRidable = getBoolean("mobs.polar_bear.ridable", polarBearRidable); -+ polarBearRidableInWater = getBoolean("mobs.polar_bear.ridable-in-water", polarBearRidableInWater); - polarBearBreedableItemString = getString("mobs.polar_bear.breedable-item", polarBearBreedableItemString); - Item item = IRegistry.ITEM.get(new MinecraftKey(polarBearBreedableItemString)); - if (item != Items.AIR) polarBearBreedableItem = item; - } - -+ public boolean pufferfishRidable = false; -+ private void pufferfishSettings() { -+ pufferfishRidable = getBoolean("mobs.pufferfish.ridable", pufferfishRidable); -+ } -+ -+ public boolean rabbitRidable = false; -+ public boolean rabbitRidableInWater = false; - public double rabbitNaturalToast = 0.0D; - public double rabbitNaturalKiller = 0.0D; - private void rabbitSettings() { -+ rabbitRidable = getBoolean("mobs.rabbit.ridable", rabbitRidable); -+ rabbitRidableInWater = getBoolean("mobs.rabbit.ridable-in-water", rabbitRidableInWater); - rabbitNaturalToast = getDouble("mobs.rabbit.spawn-toast-chance", rabbitNaturalToast); - rabbitNaturalKiller = getDouble("mobs.rabbit.spawn-killer-rabbit-chance", rabbitNaturalKiller); - } - -+ public boolean ravagerRidable = false; -+ public boolean ravagerRidableInWater = false; -+ private void ravagerSettings() { -+ ravagerRidable = getBoolean("mobs.ravager.ridable", ravagerRidable); -+ ravagerRidableInWater = getBoolean("mobs.ravager.ridable-in-water", ravagerRidableInWater); -+ } -+ -+ public boolean salmonRidable = false; -+ private void salmonSettings() { -+ salmonRidable = getBoolean("mobs.salmon.ridable", salmonRidable); -+ } -+ -+ public boolean sheepRidable = false; -+ public boolean sheepRidableInWater = false; -+ private void sheepSettings() { -+ sheepRidable = getBoolean("mobs.sheep.ridable", sheepRidable); -+ sheepRidableInWater = getBoolean("mobs.sheep.ridable-in-water", sheepRidableInWater); -+ } -+ -+ public boolean shulkerRidable = false; -+ public boolean shulkerRidableInWater = false; -+ private void shulkerSettings() { -+ shulkerRidable = getBoolean("mobs.shulker.ridable", shulkerRidable); -+ shulkerRidableInWater = getBoolean("mobs.shulker.ridable-in-water", shulkerRidableInWater); -+ } -+ -+ public boolean silverfishRidable = false; -+ public boolean silverfishRidableInWater = false; -+ private void silverfishSettings() { -+ silverfishRidable = getBoolean("mobs.silverfish.ridable", silverfishRidable); -+ silverfishRidableInWater = getBoolean("mobs.silverfish.ridable-in-water", silverfishRidableInWater); -+ } -+ -+ public boolean skeletonRidable = false; -+ public boolean skeletonRidableInWater = false; -+ private void skeletonSettings() { -+ skeletonRidable = getBoolean("mobs.skeleton.ridable", skeletonRidable); -+ skeletonRidableInWater = getBoolean("mobs.skeleton.ridable-in-water", skeletonRidableInWater); -+ } -+ -+ public boolean skeletonHorseCanSwim = false; -+ public boolean skeletonHorseRidableInWater = true; -+ private void skeletonHorseSettings() { -+ skeletonHorseCanSwim = getBoolean("mobs.skeleton_horse.can-swim", skeletonHorseCanSwim); -+ skeletonHorseRidableInWater = getBoolean("mobs.skeleton_horse.ridable-in-water", skeletonHorseRidableInWater); -+ } -+ -+ public boolean slimeRidable = false; -+ public boolean slimeRidableInWater = false; -+ private void slimeSettings() { -+ slimeRidable = getBoolean("mobs.slime.ridable", slimeRidable); -+ slimeRidableInWater = getBoolean("mobs.slime.ridable-in-water", slimeRidableInWater); -+ } -+ -+ public boolean snowGolemRidable = false; -+ public boolean snowGolemRidableInWater = false; -+ public boolean snowGolemLeaveTrailWhenRidden = false; - public boolean snowGolemDropsPumpkin = true; - public boolean snowGolemPutPumpkinBack = false; - private void snowGolemSettings() { -+ 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); - snowGolemDropsPumpkin = getBoolean("mobs.snow_golem.drop-pumpkin-when-sheared", snowGolemDropsPumpkin); - snowGolemPutPumpkinBack = getBoolean("mobs.snow_golem.pumpkin-can-be-added-back", snowGolemPutPumpkinBack); - } - -+ public boolean squidRidable = false; - public boolean squidImmuneToEAR = true; - public double squidOffsetWaterCheck = 0.0D; - private void squidSettings() { -+ squidRidable = getBoolean("mobs.squid.ridable", squidRidable); - squidImmuneToEAR = getBoolean("mobs.squid.immune-to-EAR", squidImmuneToEAR); - squidOffsetWaterCheck = getDouble("mobs.squid.water-offset-check", squidOffsetWaterCheck); - } - -+ public boolean spiderRidable = false; -+ public boolean spiderRidableInWater = false; -+ private void spiderSettings() { -+ spiderRidable = getBoolean("mobs.spider.ridable", spiderRidable); -+ spiderRidableInWater = getBoolean("mobs.spider.ridable-in-water", spiderRidableInWater); -+ } -+ -+ public boolean strayRidable = false; -+ public boolean strayRidableInWater = false; -+ private void straySettings() { -+ strayRidable = getBoolean("mobs.stray.ridable", strayRidable); -+ strayRidableInWater = getBoolean("mobs.stray.ridable-in-water", strayRidableInWater); -+ } -+ -+ public boolean striderRidable = false; -+ public boolean striderRidableInWater = false; -+ private void striderSettings() { -+ striderRidable = getBoolean("mobs.strider.ridable", striderRidable); -+ striderRidableInWater = getBoolean("mobs.strider.ridable-in-water", striderRidableInWater); -+ } -+ -+ public boolean tropicalFishRidable = false; -+ private void tropicalFishSettings() { -+ tropicalFishRidable = getBoolean("mobs.tropical_fish.ridable", tropicalFishRidable); -+ } -+ -+ public boolean turtleRidable = false; -+ public boolean turtleRidableInWater = false; -+ private void turtleSettings() { -+ turtleRidable = getBoolean("mobs.turtle.ridable", turtleRidable); -+ turtleRidableInWater = getBoolean("mobs.turtle.ridable-in-water", turtleRidableInWater); -+ } -+ -+ public boolean vexRidable = false; -+ public boolean vexRidableInWater = false; -+ public double vexMaxY = 256D; -+ private void vexSettings() { -+ vexRidable = getBoolean("mobs.vex.ridable", vexRidable); -+ vexRidableInWater = getBoolean("mobs.vex.ridable-in-water", vexRidableInWater); -+ vexMaxY = getDouble("mobs.vex.ridable-max-y", vexMaxY); -+ } -+ -+ public boolean villagerRidable = false; -+ public boolean villagerRidableInWater = false; - public int villagerBrainTicks = 1; - public boolean villagerUseBrainTicksOnlyWhenLagging = true; - public boolean villagerCanBeLeashed = false; -@@ -572,6 +935,8 @@ public class PurpurWorldConfig { - public int villagerSpawnIronGolemLimit = 0; - public boolean villagerCanBreed = true; - private void villagerSettings() { -+ villagerRidable = getBoolean("mobs.villager.ridable", villagerRidable); -+ villagerRidableInWater = getBoolean("mobs.villager.ridable-in-water", villagerRidableInWater); - 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); -@@ -582,45 +947,108 @@ public class PurpurWorldConfig { - villagerCanBreed = getBoolean("mobs.villager.can-breed", villagerCanBreed); - } - -+ public boolean villagerTraderRidable = false; -+ public boolean villagerTraderRidableInWater = false; - public boolean villagerTraderCanBeLeashed = false; - public boolean villagerTraderFollowEmeraldBlock = false; - private void villagerTraderSettings() { -+ villagerTraderRidable = getBoolean("mobs.wandering_trader.ridable", villagerTraderRidable); -+ villagerTraderRidableInWater = getBoolean("mobs.wandering_trader.ridable-in-water", villagerTraderRidableInWater); - villagerTraderCanBeLeashed = getBoolean("mobs.wandering_trader.can-be-leashed", villagerTraderCanBeLeashed); - villagerTraderFollowEmeraldBlock = getBoolean("mobs.wandering_trader.follow-emerald-blocks", villagerTraderFollowEmeraldBlock); - } - -+ public boolean vindicatorRidable = false; -+ public boolean vindicatorRidableInWater = false; -+ public double vindicatorJohnnySpawnChance = 0D; -+ private void vindicatorSettings() { -+ vindicatorRidable = getBoolean("mobs.vindicator.ridable", vindicatorRidable); -+ vindicatorRidableInWater = getBoolean("mobs.vindicator.ridable-in-water", vindicatorRidableInWater); -+ vindicatorJohnnySpawnChance = getDouble("mobs.vindicator.johnny.spawn-chance", vindicatorJohnnySpawnChance); -+ } -+ -+ public boolean witchRidable = false; -+ public boolean witchRidableInWater = false; -+ private void witchSettings() { -+ witchRidable = getBoolean("mobs.witch.ridable", witchRidable); -+ witchRidableInWater = getBoolean("mobs.witch.ridable-in-water", witchRidableInWater); -+ } -+ -+ public boolean witherRidable = false; -+ public boolean witherRidableInWater = false; -+ public double witherMaxY = 256D; -+ private void witherSettings() { -+ witherRidable = getBoolean("mobs.wither.ridable", witherRidable); -+ witherRidableInWater = getBoolean("mobs.wither.ridable-in-water", witherRidableInWater); -+ witherMaxY = getDouble("mobs.wither.ridable-max-y", witherMaxY); -+ } -+ -+ public boolean witherSkeletonRidable = false; -+ public boolean witherSkeletonRidableInWater = false; - public boolean witherSkeletonTakesWitherDamage = false; - private void witherSkeletonSettings() { -+ witherSkeletonRidable = getBoolean("mobs.wither_skeleton.ridable", witherSkeletonRidable); -+ witherSkeletonRidableInWater = getBoolean("mobs.wither_skeleton.ridable-in-water", witherSkeletonRidableInWater); - witherSkeletonTakesWitherDamage = getBoolean("mobs.wither_skeleton.takes-wither-damage", witherSkeletonTakesWitherDamage); - } - -+ public boolean wolfRidable = false; -+ public boolean wolfRidableInWater = false; -+ private void wolfSettings() { -+ wolfRidable = getBoolean("mobs.wolf.ridable", wolfRidable); -+ wolfRidableInWater = getBoolean("mobs.wolf.ridable-in-water", wolfRidableInWater); -+ } -+ -+ public boolean zoglinRidable = false; -+ public boolean zoglinRidableInWater = false; -+ private void zoglinSettings() { -+ zoglinRidable = getBoolean("mobs.zoglin.ridable", zoglinRidable); -+ zoglinRidableInWater = getBoolean("mobs.zoglin.ridable-in-water", zoglinRidableInWater); -+ } -+ -+ public boolean zombieRidable = false; -+ public boolean zombieRidableInWater = false; - public boolean zombieJockeyOnlyBaby = true; - public double zombieJockeyChance = 0.05D; - public boolean zombieJockeyTryExistingChickens = true; - private void zombieSettings() { -+ zombieRidable = getBoolean("mobs.zombie.ridable", zombieRidable); -+ zombieRidableInWater = getBoolean("mobs.zombie.ridable-in-water", zombieRidableInWater); - zombieJockeyOnlyBaby = getBoolean("mobs.zombie.jockey.only-babies", zombieJockeyOnlyBaby); - zombieJockeyChance = getDouble("mobs.zombie.jockey.chance", zombieJockeyChance); - zombieJockeyTryExistingChickens = getBoolean("mobs.zombie.jockey.try-existing-chickens", zombieJockeyTryExistingChickens); - } - -+ public boolean zombieHorseCanSwim = false; -+ public boolean zombieHorseRidableInWater = false; - public double zombieHorseSpawnChance = 0.0D; - private void zombieHorseSettings() { -+ zombieHorseCanSwim = getBoolean("mobs.zombie_horse.can-swim", zombieHorseCanSwim); -+ zombieHorseRidableInWater = getBoolean("mobs.zombie_horse.ridable-in-water", zombieHorseRidableInWater); - zombieHorseSpawnChance = getDouble("mobs.zombie_horse.spawn-chance", zombieHorseSpawnChance); - } - -+ public boolean zombifiedPiglinRidable = false; -+ public boolean zombifiedPiglinRidableInWater = false; - public boolean zombifiedPiglinJockeyOnlyBaby = true; - public double zombifiedPiglinJockeyChance = 0.05D; - public boolean zombifiedPiglinJockeyTryExistingChickens = true; - private void zombifiedPiglinSettings() { -+ zombifiedPiglinRidable = getBoolean("mobs.zombified_piglin.ridable", zombifiedPiglinRidable); -+ zombifiedPiglinRidableInWater = getBoolean("mobs.zombified_piglin.ridable-in-water", zombifiedPiglinRidableInWater); - zombifiedPiglinJockeyOnlyBaby = getBoolean("mobs.zombified_piglin.jockey.only-babies", zombifiedPiglinJockeyOnlyBaby); - zombifiedPiglinJockeyChance = getDouble("mobs.zombified_piglin.jockey.chance", zombifiedPiglinJockeyChance); - zombifiedPiglinJockeyTryExistingChickens = getBoolean("mobs.zombified_piglin.jockey.try-existing-chickens", zombifiedPiglinJockeyTryExistingChickens); - } - -+ public boolean zombieVillagerRidable = false; -+ public boolean zombieVillagerRidableInWater = false; - public boolean zombieVillagerJockeyOnlyBaby = true; - public double zombieVillagerJockeyChance = 0.05D; - public boolean zombieVillagerJockeyTryExistingChickens = true; - private void zombieVillagerSettings() { -+ zombieVillagerRidable = getBoolean("mobs.zombie_villager.ridable", zombieVillagerRidable); -+ zombieVillagerRidableInWater = getBoolean("mobs.zombie_villager.ridable-in-water", zombieVillagerRidableInWater); - zombieVillagerJockeyOnlyBaby = getBoolean("mobs.zombie_villager.jockey.only-babies", zombieVillagerJockeyOnlyBaby); - zombieVillagerJockeyChance = getDouble("mobs.zombie_villager.jockey.chance", zombieVillagerJockeyChance); - zombieVillagerJockeyTryExistingChickens = getBoolean("mobs.zombie_villager.jockey.try-existing-chickens", zombieVillagerJockeyTryExistingChickens); -diff --git a/src/main/java/net/pl3x/purpur/controller/ControllerLookWASD.java b/src/main/java/net/pl3x/purpur/controller/ControllerLookWASD.java -new file mode 100644 -index 0000000000000000000000000000000000000000..088c830471b796908781bc1aa0693355849754cd ---- /dev/null -+++ b/src/main/java/net/pl3x/purpur/controller/ControllerLookWASD.java -@@ -0,0 +1,76 @@ -+package net.pl3x.purpur.controller; -+ -+import net.minecraft.network.protocol.game.PacketPlayOutEntity; -+import net.minecraft.world.entity.ai.control.ControllerLook; -+import net.minecraft.world.entity.EntityInsentient; -+import net.minecraft.util.MathHelper; -+import net.minecraft.world.entity.player.EntityHuman; -+ -+public class ControllerLookWASD extends ControllerLook { -+ protected final EntityInsentient entity; -+ private float yawOffset = 0; -+ private float pitchOffset = 0; -+ -+ public ControllerLookWASD(EntityInsentient entity) { -+ super(entity); -+ this.entity = entity; -+ } -+ -+ // tick -+ @Override -+ public void a() { -+ if (entity.hasPurpurRider()) { -+ tick(entity.getPurpurRider()); -+ } else { -+ tick(); -+ } -+ } -+ -+ protected void tick() { -+ super.a(); // tick -+ } -+ -+ protected void tick(EntityHuman rider) { -+ setYawPitch(rider.yaw, rider.pitch); -+ } -+ -+ public void setYawPitch(float yaw, float pitch) { -+ entity.yaw = normalizeYaw(yaw + yawOffset); -+ entity.lastYaw = entity.yaw; -+ entity.setBodyYaw(entity.yaw); -+ entity.setRenderYawOffset(entity.yaw); -+ entity.setHeadRotation(entity.yaw); -+ entity.pitch = normalizePitch(pitch + pitchOffset); -+ -+ entity.tracker.broadcast(new PacketPlayOutEntity -+ .PacketPlayOutRelEntityMoveLook(entity.getId(), -+ (short) 0, (short) 0, (short) 0, -+ (byte) MathHelper.d(entity.yaw * 256.0F / 360.0F), -+ (byte) MathHelper.d(entity.pitch * 256.0F / 360.0F), -+ entity.onGround)); -+ } -+ -+ public void setOffsets(float yaw, float pitch) { -+ yawOffset = yaw; -+ pitchOffset = pitch; -+ } -+ -+ public float normalizeYaw(float yaw) { -+ yaw %= 360.0f; -+ if (yaw >= 180.0f) { -+ yaw -= 360.0f; -+ } else if (yaw < -180.0f) { -+ yaw += 360.0f; -+ } -+ return yaw; -+ } -+ -+ public float normalizePitch(float pitch) { -+ if (pitch > 90.0f) { -+ pitch = 90.0f; -+ } else if (pitch < -90.0f) { -+ pitch = -90.0f; -+ } -+ return pitch; -+ } -+} -diff --git a/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASD.java b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASD.java -new file mode 100644 -index 0000000000000000000000000000000000000000..6b1f37398ef6cf5935e7acb4295f9223a026226a ---- /dev/null -+++ b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASD.java -@@ -0,0 +1,92 @@ -+package net.pl3x.purpur.controller; -+ -+import net.minecraft.world.entity.ai.control.ControllerMove; -+import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.EntityInsentient; -+import net.minecraft.world.entity.ai.attributes.GenericAttributes; -+import net.minecraft.world.entity.player.EntityHuman; -+import net.pl3x.purpur.event.entity.RidableSpacebarEvent; -+ -+public class ControllerMoveWASD extends ControllerMove { -+ protected final EntityInsentient entity; -+ private final double speedModifier; -+ -+ public ControllerMoveWASD(EntityInsentient entity) { -+ this(entity, 1.0D); -+ } -+ -+ public ControllerMoveWASD(EntityInsentient entity, double speedModifier) { -+ super(entity); -+ this.entity = entity; -+ this.speedModifier = speedModifier; -+ } -+ -+ // isUpdating -+ @Override -+ public boolean b() { -+ return entity.hasPurpurRider() ? getForward() != 0 || getStrafe() != 0 : super.b(); -+ } -+ -+ // tick -+ @Override -+ public void a() { -+ if (entity.hasPurpurRider()) { -+ tick(entity.getPurpurRider()); -+ } else { -+ tick(); -+ } -+ } -+ -+ public void tick() { -+ super.a(); // tick -+ } -+ -+ public void tick(EntityHuman rider) { -+ float forward = rider.getForward() * 0.5F; -+ float strafe = rider.getStrafe() * 0.25F; -+ -+ if (forward <= 0.0F) { -+ forward *= 0.5F; -+ } -+ -+ float yawOffset = 0; -+ if (strafe != 0) { -+ if (forward == 0) { -+ yawOffset += strafe > 0 ? -90 : 90; -+ forward = Math.abs(strafe * 2); -+ } else { -+ yawOffset += strafe > 0 ? -30 : 30; -+ strafe /= 2; -+ if (forward < 0) { -+ yawOffset += strafe > 0 ? -110 : 110; -+ forward *= -1; -+ } -+ } -+ } else if (forward < 0) { -+ yawOffset -= 180; -+ forward *= -1; -+ } -+ -+ ((ControllerLookWASD) entity.getControllerLook()).setOffsets(yawOffset, 0); -+ -+ if (rider.jumping && spacebarEvent(entity) && !entity.onSpacebar() && entity.onGround) { -+ entity.jump(); -+ } -+ -+ setSpeed(entity.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getValue() * speedModifier); -+ -+ entity.setSpeed((float) getSpeed()); -+ entity.setForward(forward); -+ -+ setForward(entity.getForward()); -+ setStrafe(entity.getStrafe()); -+ } -+ -+ public static boolean spacebarEvent(Entity entity) { -+ if (RidableSpacebarEvent.getHandlerList().getRegisteredListeners().length > 0) { -+ return new RidableSpacebarEvent(entity.getBukkitEntity()).callEvent(); -+ } else { -+ return true; -+ } -+ } -+} -diff --git a/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDFlying.java b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDFlying.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7737e87048e88b40c0b6b4a1093e2256ae252802 ---- /dev/null -+++ b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDFlying.java -@@ -0,0 +1,61 @@ -+package net.pl3x.purpur.controller; -+ -+import net.minecraft.world.entity.EntityInsentient; -+import net.minecraft.world.entity.ai.attributes.GenericAttributes; -+import net.minecraft.world.entity.player.EntityHuman; -+ -+public class ControllerMoveWASDFlying extends ControllerMoveWASD { -+ protected final float groundSpeedModifier; -+ protected int tooHighCooldown = 0; -+ protected boolean setGravityFlag = true; -+ -+ public ControllerMoveWASDFlying(EntityInsentient entity) { -+ this(entity, 1.0F); -+ } -+ -+ public ControllerMoveWASDFlying(EntityInsentient entity, float groundSpeedModifier) { -+ this(entity, groundSpeedModifier, true); -+ } -+ -+ public ControllerMoveWASDFlying(EntityInsentient entity, float groundSpeedModifier, boolean setGravityFlag) { -+ super(entity); -+ this.groundSpeedModifier = groundSpeedModifier; -+ this.setGravityFlag = setGravityFlag; -+ } -+ -+ @Override -+ public void tick(EntityHuman rider) { -+ float forward = Math.max(0.0F, rider.getForward()); -+ float vertical = forward == 0.0F ? 0.0F : -(rider.pitch / 45.0F); -+ float strafe = rider.getStrafe(); -+ -+ if (rider.jumping && spacebarEvent(entity)) { -+ entity.onSpacebar(); -+ } -+ -+ if (entity.locY() >= entity.getMaxY() || --tooHighCooldown > 0) { -+ tooHighCooldown = 60; -+ entity.setMot(entity.getMot().add(0.0D, -0.05D, 0.0D)); -+ vertical = 0.0F; -+ } -+ -+ setSpeed(entity.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getValue()); -+ float speed = (float) getSpeed(); -+ -+ if (entity.onGround) { -+ speed *= groundSpeedModifier; // TODO = fix this! -+ } -+ -+ if (setGravityFlag) { -+ entity.setNoGravity(forward > 0); -+ } -+ -+ entity.setSpeed(speed); -+ entity.setVertical(vertical); -+ entity.setStrafe(strafe); -+ entity.setForward(forward); -+ -+ setForward(entity.getForward()); -+ setStrafe(entity.getStrafe()); -+ } -+} -diff --git a/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDFlyingWithSpacebar.java b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDFlyingWithSpacebar.java -new file mode 100644 -index 0000000000000000000000000000000000000000..cdd32aa66b6bd9c01854e3d9baf25757c7e2a707 ---- /dev/null -+++ b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDFlyingWithSpacebar.java -@@ -0,0 +1,61 @@ -+package net.pl3x.purpur.controller; -+ -+import net.minecraft.world.entity.EntityInsentient; -+import net.minecraft.world.entity.ai.attributes.GenericAttributes; -+import net.minecraft.world.entity.player.EntityHuman; -+import net.minecraft.world.phys.Vec3D; -+ -+public class ControllerMoveWASDFlyingWithSpacebar extends ControllerMoveWASDFlying { -+ public ControllerMoveWASDFlyingWithSpacebar(EntityInsentient entity) { -+ super(entity); -+ } -+ -+ public ControllerMoveWASDFlyingWithSpacebar(EntityInsentient entity, float groundSpeedModifier) { -+ super(entity, groundSpeedModifier); -+ } -+ -+ @Override -+ public void tick(EntityHuman rider) { -+ float forward = rider.getForward(); -+ float strafe = rider.getStrafe() * 0.5F; -+ float vertical = 0; -+ -+ if (forward < 0.0F) { -+ forward *= 0.5F; -+ strafe *= 0.5F; -+ } -+ -+ float speed = (float) entity.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getValue(); -+ -+ if (entity.onGround) { -+ speed *= groundSpeedModifier; -+ } -+ -+ if (rider.jumping && spacebarEvent(entity) && !entity.onSpacebar()) { -+ entity.setNoGravity(true); -+ vertical = 1.0F; -+ } else { -+ entity.setNoGravity(false); -+ } -+ -+ if (entity.locY() >= entity.getMaxY() || --tooHighCooldown > 0) { -+ tooHighCooldown = 60; -+ entity.setMot(entity.getMot().add(0.0D, -0.2D, 0.0D)); -+ vertical = 0.0F; -+ } -+ -+ setSpeed(speed); -+ entity.setSpeed((float) getSpeed()); -+ entity.setVertical(vertical); -+ entity.setStrafe(strafe); -+ entity.setForward(forward); -+ -+ setForward(entity.getForward()); -+ setStrafe(entity.getStrafe()); -+ -+ Vec3D mot = entity.getMot(); -+ if (mot.y > 0.2D) { -+ entity.setMot(mot.x, 0.2D, mot.z); -+ } -+ } -+} -diff --git a/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDWater.java b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDWater.java -new file mode 100644 -index 0000000000000000000000000000000000000000..aa7eb0b3bd7be8d1992e99bf156dbad167e571aa ---- /dev/null -+++ b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDWater.java -@@ -0,0 +1,50 @@ -+package net.pl3x.purpur.controller; -+ -+import net.minecraft.world.entity.EntityInsentient; -+import net.minecraft.world.entity.ai.attributes.GenericAttributes; -+import net.minecraft.world.entity.player.EntityHuman; -+ -+public class ControllerMoveWASDWater extends ControllerMoveWASD { -+ private final double speedModifier; -+ -+ public ControllerMoveWASDWater(EntityInsentient entity) { -+ this(entity, 1.0D); -+ } -+ -+ public ControllerMoveWASDWater(EntityInsentient entity, double speedModifier) { -+ super(entity); -+ this.speedModifier = speedModifier; -+ } -+ -+ @Override -+ public void tick(EntityHuman rider) { -+ float forward = rider.getForward(); -+ float strafe = rider.getStrafe() * 0.5F; // strafe slower by default -+ float vertical = -(rider.pitch / 90); -+ -+ if (forward == 0.0F) { -+ // strafe slower if not moving forward -+ strafe *= 0.5F; -+ // do not move vertically if not moving forward -+ vertical = 0.0F; -+ } else if (forward < 0.0F) { -+ // water animals can't swim backwards -+ forward = 0.0F; -+ vertical = 0.0F; -+ } -+ -+ if (rider.jumping && spacebarEvent(entity)) { -+ entity.onSpacebar(); -+ } -+ -+ setSpeed(entity.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getValue() * speedModifier); -+ entity.setSpeed((float) getSpeed() * 0.1F); -+ -+ entity.setForward(forward * (float) speedModifier); -+ entity.setStrafe(strafe * (float) speedModifier); -+ entity.setVertical(vertical * (float) speedModifier); -+ -+ setForward(entity.getForward()); -+ setStrafe(entity.getStrafe()); -+ } -+} -diff --git a/src/main/java/net/pl3x/purpur/entity/DolphinSpit.java b/src/main/java/net/pl3x/purpur/entity/DolphinSpit.java -new file mode 100644 -index 0000000000000000000000000000000000000000..621e4d0af89e78404e79a92ba717392e4cf4f82b ---- /dev/null -+++ b/src/main/java/net/pl3x/purpur/entity/DolphinSpit.java -@@ -0,0 +1,119 @@ -+package net.pl3x.purpur.entity; -+ -+import net.minecraft.world.entity.animal.EntityDolphin; -+import net.minecraft.world.entity.projectile.EntityLlamaSpit; -+import net.minecraft.world.damagesource.DamageSource; -+import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.EntityLiving; -+import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.util.MathHelper; -+import net.minecraft.world.phys.MovingObjectPosition; -+import net.minecraft.world.phys.MovingObjectPositionBlock; -+import net.minecraft.world.phys.MovingObjectPositionEntity; -+import net.minecraft.core.particles.Particles; -+import net.minecraft.world.entity.projectile.ProjectileHelper; -+import net.minecraft.world.phys.Vec3D; -+import net.minecraft.world.level.World; -+import net.minecraft.server.level.WorldServer; -+import org.bukkit.craftbukkit.event.CraftEventFactory; -+ -+public class DolphinSpit extends EntityLlamaSpit { -+ public EntityLiving dolphin; -+ public int ticksLived; -+ -+ public DolphinSpit(EntityTypes entitytypes, World world) { -+ super(entitytypes, world); -+ } -+ -+ public DolphinSpit(World world, EntityDolphin dolphin) { -+ this(EntityTypes.LLAMA_SPIT, world); -+ setShooter(dolphin.hasPurpurRider() ? dolphin.getPurpurRider() : dolphin); -+ this.dolphin = dolphin; -+ this.setPosition( -+ dolphin.locX() - (double) (dolphin.getWidth() + 1.0F) * 0.5D * (double) MathHelper.sin(dolphin.getRenderYawOffset() * 0.017453292F), -+ dolphin.getHeadY() - 0.10000000149011612D, -+ dolphin.locZ() + (double) (dolphin.getWidth() + 1.0F) * 0.5D * (double) MathHelper.cos(dolphin.getRenderYawOffset() * 0.017453292F)); -+ } -+ -+ @Override -+ public boolean canSaveToDisk() { -+ return false; -+ } -+ -+ public void tick() { -+ if (dead || !valid) { -+ return; -+ } -+ -+ if (!leftOwner()) { -+ setLeftOwner(checkIfLeftOwner()); -+ } -+ -+ setFlag(6, isGlowing()); -+ entityBaseTick(); -+ -+ Vec3D mot = getMot(); -+ -+ MovingObjectPosition hitResult = ProjectileHelper.getHitResult(this, this::hitPredicate); -+ if (hitResult != null) { -+ onHit(hitResult); -+ } -+ -+ double x = this.locX() + mot.x; -+ double y = this.locY() + mot.y; -+ double z = this.locZ() + mot.z; -+ setMot(mot.scale(0.99D)); -+ -+ Vec3D motDouble = mot.scale(2.0); -+ for (int i = 0; i < 5; i++) { -+ ((WorldServer) world).sendParticles(null, Particles.BUBBLE, -+ locX() + random.nextFloat() / 2 - 0.25F, -+ locY() + random.nextFloat() / 2 - 0.25F, -+ locZ() + random.nextFloat() / 2 - 0.25F, -+ 0, motDouble.getX(), motDouble.getY(), motDouble.getZ(), 0.1, true); -+ } -+ -+ if (++ticksLived > 20) { -+ die(); -+ } else { -+ setMot(mot.scale(0.99D)); -+ if (!isNoGravity()) { -+ setMot(getMot().add(0.0D, -0.06D, 0.0D)); -+ } -+ setPosition(x, y, z); -+ } -+ } -+ -+ @Override -+ public void shoot(double x, double y, double z, float speed, float inaccuracy) { -+ setMot(new Vec3D(x, y, z).normalize().add( -+ random.nextGaussian() * (double) 0.0075F * (double) inaccuracy, -+ random.nextGaussian() * (double) 0.0075F * (double) inaccuracy, -+ random.nextGaussian() * (double) 0.0075F * (double) inaccuracy) -+ .scale(speed)); -+ } -+ -+ public void onHit(MovingObjectPosition rayTrace) { -+ CraftEventFactory.callProjectileHitEvent(this, rayTrace); -+ MovingObjectPosition.EnumMovingObjectType type = rayTrace.getType(); -+ if (type == MovingObjectPosition.EnumMovingObjectType.ENTITY) { -+ onHit((MovingObjectPositionEntity) rayTrace); -+ } else if (type == MovingObjectPosition.EnumMovingObjectType.BLOCK) { -+ onHit((MovingObjectPositionBlock) rayTrace); -+ } -+ } -+ -+ protected void onHit(MovingObjectPositionEntity rayTrace) { -+ Entity shooter = getShooter(); -+ if (shooter instanceof EntityLiving) { -+ rayTrace.getEntity().damageEntity(DamageSource.indirectMobAttack(this, (EntityLiving) shooter).setProjectile(), world.purpurConfig.dolphinSpitDamage); -+ } -+ } -+ -+ protected void onHit(MovingObjectPositionBlock rayTrace) { -+ IBlockData iblockdata = world.getType(rayTrace.getBlockPosition()); -+ iblockdata.a(world, iblockdata, rayTrace, this); -+ die(); -+ } -+} -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..c7cd0327084943dcb6339998805e6b7db1d87bba ---- /dev/null -+++ b/src/main/java/net/pl3x/purpur/entity/PhantomFlames.java -@@ -0,0 +1,140 @@ -+package net.pl3x.purpur.entity; -+ -+import net.minecraft.world.damagesource.DamageSource; -+import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.EntityLiving; -+import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.entity.decoration.EntityArmorStand; -+import net.minecraft.world.entity.monster.EntityPhantom; -+import net.minecraft.world.entity.projectile.EntityLlamaSpit; -+import net.minecraft.world.level.block.state.BlockBase; -+import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.util.MathHelper; -+import net.minecraft.world.phys.MovingObjectPosition; -+import net.minecraft.world.phys.MovingObjectPositionBlock; -+import net.minecraft.world.phys.MovingObjectPositionEntity; -+import net.minecraft.core.particles.Particles; -+import net.minecraft.world.entity.projectile.ProjectileHelper; -+import net.minecraft.world.phys.Vec3D; -+import net.minecraft.world.level.World; -+import net.minecraft.server.level.WorldServer; -+import org.bukkit.craftbukkit.event.CraftEventFactory; -+ -+public class PhantomFlames extends EntityLlamaSpit { -+ public EntityPhantom phantom; -+ public int ticksLived; -+ public boolean canGrief = false; -+ -+ public PhantomFlames(EntityTypes entitytypes, World world) { -+ super(entitytypes, world); -+ } -+ -+ public PhantomFlames(World world, EntityPhantom phantom) { -+ this(EntityTypes.LLAMA_SPIT, world); -+ setShooter(phantom.hasPurpurRider() ? phantom.getPurpurRider() : phantom); -+ this.phantom = phantom; -+ this.setPosition( -+ phantom.locX() - (double) (phantom.getWidth() + 1.0F) * 0.5D * (double) MathHelper.sin(phantom.getRenderYawOffset() * 0.017453292F), -+ phantom.getHeadY() - 0.10000000149011612D, -+ phantom.locZ() + (double) (phantom.getWidth() + 1.0F) * 0.5D * (double) MathHelper.cos(phantom.getRenderYawOffset() * 0.017453292F)); -+ } -+ -+ @Override -+ public boolean canSaveToDisk() { -+ return false; -+ } -+ -+ @Override -+ public void tick() { -+ if (dead || !valid) { -+ return; -+ } -+ -+ if (!leftOwner()) { -+ setLeftOwner(checkIfLeftOwner()); -+ } -+ -+ setFlag(6, isGlowing()); -+ entityBaseTick(); -+ -+ Vec3D mot = getMot(); -+ -+ MovingObjectPosition hitResult = ProjectileHelper.getHitResult(this, this::hitPredicate); -+ if (hitResult != null) { -+ onHit(hitResult); -+ } -+ -+ if (dead) { -+ return; -+ } -+ -+ double x = this.locX() + mot.x; -+ double y = this.locY() + mot.y; -+ double z = this.locZ() + mot.z; -+ setMot(mot.scale(0.99D)); -+ -+ Vec3D motDouble = mot.scale(2.0); -+ for (int i = 0; i < 5; i++) { -+ ((WorldServer) world).sendParticles(null, Particles.FLAME, -+ locX() + random.nextFloat() / 2 - 0.25F, -+ locY() + random.nextFloat() / 2 - 0.25F, -+ locZ() + random.nextFloat() / 2 - 0.25F, -+ 0, motDouble.getX(), motDouble.getY(), motDouble.getZ(), 0.1, true); -+ } -+ -+ if (world.a(getBoundingBox()).noneMatch(BlockBase.BlockData::isAir)) { -+ die(); -+ } else if (isInWaterOrBubbleColumn()) { -+ die(); -+ } else if (++ticksLived > 20) { -+ die(); -+ } else { -+ setMot(mot.scale(0.99D)); -+ if (!isNoGravity()) { -+ setMot(getMot().add(0.0D, -0.06D, 0.0D)); -+ } -+ setPosition(x, y, z); -+ } -+ } -+ -+ @Override -+ public void shoot(double x, double y, double z, float speed, float inaccuracy) { -+ setMot(new Vec3D(x, y, z).normalize().add( -+ random.nextGaussian() * (double) 0.0075F * (double) inaccuracy, -+ random.nextGaussian() * (double) 0.0075F * (double) inaccuracy, -+ random.nextGaussian() * (double) 0.0075F * (double) inaccuracy) -+ .scale(speed)); -+ } -+ -+ public void onHit(MovingObjectPosition rayTrace) { -+ CraftEventFactory.callProjectileHitEvent(this, rayTrace); -+ MovingObjectPosition.EnumMovingObjectType type = rayTrace.getType(); -+ if (type == MovingObjectPosition.EnumMovingObjectType.ENTITY) { -+ onHit((MovingObjectPositionEntity) rayTrace); -+ } else if (type == MovingObjectPosition.EnumMovingObjectType.BLOCK) { -+ onHit((MovingObjectPositionBlock) rayTrace); -+ } -+ } -+ -+ protected void onHit(MovingObjectPositionEntity rayTrace) { -+ Entity shooter = getShooter(); -+ if (shooter instanceof EntityLiving) { -+ 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) { -+ if (canGrief) { -+ IBlockData iblockdata = world.getType(rayTrace.getBlockPosition()); -+ iblockdata.a(world, iblockdata, rayTrace, this); -+ } -+ die(); -+ } -+} -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 295ffab08672d77d88aca368cb5b56f80bc4f1b5..701063a90492131a51007a9f70dbb72e31d016b7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -12,9 +12,6 @@ import net.minecraft.nbt.NBTBase; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.server.level.EntityPlayer; --import net.minecraft.server.level.PlayerChunk; --import net.minecraft.server.level.PlayerChunkMap; --import net.minecraft.server.level.TicketType; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityAreaEffectCloud; -@@ -147,7 +144,6 @@ import net.minecraft.world.entity.vehicle.EntityMinecartHopper; - import net.minecraft.world.entity.vehicle.EntityMinecartMobSpawner; - import net.minecraft.world.entity.vehicle.EntityMinecartRideable; - import net.minecraft.world.entity.vehicle.EntityMinecartTNT; --import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.phys.AxisAlignedBB; - import org.bukkit.Chunk; // Paper - import org.bukkit.EntityEffect; -@@ -1166,4 +1162,26 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - return getHandle().isTicking(); - } - // Paper end -+ -+ // Purpur start -+ @Override -+ public org.bukkit.entity.Player getRider() { -+ return hasRider() ? (org.bukkit.entity.Player) getHandle().getPurpurRider().getBukkitEntity() : null; -+ } -+ -+ @Override -+ public boolean hasRider() { -+ return getHandle().hasPurpurRider(); -+ } -+ -+ @Override -+ public boolean isRidable() { -+ return getHandle().isRidable(); -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return getHandle().isRidableInWater(); -+ } -+ // Purpur end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index a678277416cd71e01cd6980bcfaf9a9803e7ea17..c4218281721cf4a5b8f2cad5e12089e3aee89737 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -548,6 +548,18 @@ public class CraftEventFactory { - } - craftServer.getPluginManager().callEvent(event); - -+ // Purpur start -+ switch (action) { -+ case LEFT_CLICK_BLOCK: -+ case LEFT_CLICK_AIR: -+ who.processClick(EnumHand.MAIN_HAND); -+ break; -+ case RIGHT_CLICK_BLOCK: -+ case RIGHT_CLICK_AIR: -+ who.processClick(EnumHand.OFF_HAND); -+ } -+ // Purpur end -+ - return event; - } - -@@ -951,6 +963,7 @@ public class CraftEventFactory { - damageCause = DamageCause.ENTITY_EXPLOSION; - } - event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), entity.getBukkitEntity(), damageCause, modifiers, modifierFunctions); -+ damager.processClick(EnumHand.MAIN_HAND); // Purpur - } - event.setCancelled(cancelled); - -@@ -1035,6 +1048,7 @@ public class CraftEventFactory { - if (!event.isCancelled()) { - event.getEntity().setLastDamageCause(event); - } -+ damager.getHandle().processClick(EnumHand.MAIN_HAND); // Purpur - return event; - } - -@@ -1084,6 +1098,7 @@ public class CraftEventFactory { - EntityDamageEvent event; - if (damager != null) { - event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), damagee.getBukkitEntity(), cause, modifiers, modifierFunctions); -+ damager.processClick(EnumHand.MAIN_HAND); // Purpur - } else { - event = new EntityDamageEvent(damagee.getBukkitEntity(), cause, modifiers, modifierFunctions); - } diff --git a/patches/server-unmapped/0002-Configurable-entity-base-attributes.patch b/patches/server-unmapped/0002-Configurable-entity-base-attributes.patch deleted file mode 100644 index a093e81cf..000000000 --- a/patches/server-unmapped/0002-Configurable-entity-base-attributes.patch +++ /dev/null @@ -1,2655 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Thu, 10 Dec 2020 16:44:54 -0600 -Subject: [PATCH] Configurable entity base attributes - - -diff --git a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java -index bee72578fae2fba56f8e8dcc1142ab54c7ba7cb8..5c9e4724d46b6864cdb85f7d3c8fb0fe37032444 100644 ---- a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java -+++ b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java -@@ -81,6 +81,18 @@ public class EntityBat extends EntityAmbient { - setMot(mot.a(0.9D)); - } - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.batMaxHealth); -+ this.getAttributeInstance(GenericAttributes.FOLLOW_RANGE).setValue(this.world.purpurConfig.batFollowRange); -+ this.getAttributeInstance(GenericAttributes.KNOCKBACK_RESISTANCE).setValue(this.world.purpurConfig.batKnockbackResistance); -+ this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue(this.world.purpurConfig.batMovementSpeed); -+ this.getAttributeInstance(GenericAttributes.FLYING_SPEED).setValue(this.world.purpurConfig.batFlyingSpeed); -+ this.getAttributeInstance(GenericAttributes.ARMOR).setValue(this.world.purpurConfig.batArmor); -+ this.getAttributeInstance(GenericAttributes.ARMOR_TOUGHNESS).setValue(this.world.purpurConfig.batArmorToughness); -+ this.getAttributeInstance(GenericAttributes.ATTACK_KNOCKBACK).setValue(this.world.purpurConfig.batAttackKnockback); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -index 6086dda5b06f0c0e02734edf7141b13715420d3c..e425e093c233a21e5ef457e3a94defe8b74261d2 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -@@ -180,6 +180,11 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - public int getPurpurBreedTime() { - return this.world.purpurConfig.beeBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.beeMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCat.java b/src/main/java/net/minecraft/world/entity/animal/EntityCat.java -index 25b0d4ebb45ffa5579921e6966c63eff1e043b85..b3b26044daaf084b9bdc911f10804bbb852f088c 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityCat.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityCat.java -@@ -127,6 +127,11 @@ public class EntityCat extends EntityTameableAnimal { - public int getPurpurBreedTime() { - return this.world.purpurConfig.catBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.catMaxHealth); -+ } - // Purpur end - - public MinecraftKey eU() { -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java b/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java -index ab54e809f735cea7d84366d2bc205351f8992bef..51fd3d955c866cc09bb09abe1b6d23caad2d7e85 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java -@@ -70,6 +70,7 @@ public class EntityChicken extends EntityAnimal { - if (world.purpurConfig.chickenRetaliate) { - this.getAttributeInstance(GenericAttributes.ATTACK_DAMAGE).setValue(2.0D); - } -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.chickenMaxHealth); - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCod.java b/src/main/java/net/minecraft/world/entity/animal/EntityCod.java -index 897e0d5ca44a0c475634f08e7d4fcf129ee197ab..07c6dc6a1b9af7b9662f4dd4b4a2ddfcbe600c34 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityCod.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityCod.java -@@ -4,6 +4,7 @@ import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.Items; - import net.minecraft.world.level.World; -@@ -24,6 +25,11 @@ public class EntityCod extends EntityFishSchool { - public boolean isRidableInWater() { - return true; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.codMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCow.java b/src/main/java/net/minecraft/world/entity/animal/EntityCow.java -index 7ed55ebe1bb768351a5cb4cdc7d4d3b0816d53b1..06af4c63fa05b243b7692cbc41b4f62ca0548def 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityCow.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityCow.java -@@ -59,6 +59,11 @@ public class EntityCow extends EntityAnimal { - public int getPurpurBreedTime() { - return this.world.purpurConfig.cowBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.cowMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java b/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java -index e4442716b329f3101bfd39fc7ce13d5419b427bf..3ca911cebc01692f63b8731a5df6d9ea3fbad66b 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java -@@ -128,6 +128,11 @@ public class EntityDolphin extends EntityWaterAnimal { - } - return false; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.dolphinMaxHealth); -+ } - // Purpur end - - @Nullable -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -index 70369d03985250fa5eaf398fa98d35a2c2a06ff1..5a2e624f1b6636f058cc69989324914f174a271a 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -@@ -162,6 +162,11 @@ public class EntityFox extends EntityAnimal { - public int getPurpurBreedTime() { - return this.world.purpurConfig.foxBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.foxMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java b/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java -index 23e614f0c3cf1178acff8e72e0441c42c658e76b..9ee82c908008190e31034e614c241fc7a66248e1 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java -@@ -80,6 +80,11 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable { - public boolean isRidableInWater() { - return world.purpurConfig.ironGolemRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.ironGolemMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java b/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java -index ab4a8ee6e1912f230cbf3353eb42c3bc8a9db58e..4b7e21a611d87410805722c30c9ee77212b33348 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java -@@ -24,6 +24,7 @@ import net.minecraft.world.entity.EntityLightning; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.EnumMobSpawn; - import net.minecraft.world.entity.IShearable; -+import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.item.Item; -@@ -72,6 +73,11 @@ public class EntityMushroomCow extends EntityCow implements IShearable { - public int getPurpurBreedTime() { - return this.world.purpurConfig.mooshroomBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.mooshroomMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java b/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java -index cff2ff5a8beef739f0515832e072e7e390ac388f..12534673afe0b05868a5f400c9e59c22dfcf12d6 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java -@@ -79,6 +79,11 @@ public class EntityOcelot extends EntityAnimal { - public int getPurpurBreedTime() { - return this.world.purpurConfig.ocelotBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.ocelotMaxHealth); -+ } - // Purpur end - - private boolean isTrusting() { -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java b/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java -index e6952c0a8d90eb4b133c517d97299f2c3db7e329..94141b8c1ad62e6d187726734d25dd0ee5535618 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java -@@ -34,6 +34,7 @@ import net.minecraft.world.entity.EnumItemSlot; - import net.minecraft.world.entity.EnumMobSpawn; - import net.minecraft.world.entity.GroupDataEntity; - import net.minecraft.world.entity.IEntitySelector; -+import net.minecraft.world.entity.ai.attributes.AttributeModifiable; - import net.minecraft.world.entity.ai.attributes.AttributeProvider; - import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.entity.ai.control.ControllerMove; -@@ -126,6 +127,12 @@ public class EntityPanda extends EntityAnimal { - public int getPurpurBreedTime() { - return this.world.purpurConfig.pandaBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.pandaMaxHealth); -+ updateAttributes(); -+ } - // Purpur end - - @Override -@@ -598,9 +605,12 @@ public class EntityPanda extends EntityAnimal { - return this.random.nextBoolean() ? this.getMainGene() : this.getHiddenGene(); - } - -- public void fg() { -+ public void fg() { updateAttributes(); } public void updateAttributes() { // Purpur - OBFHELPER - if (this.isWeak()) { -- this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(10.0D); -+ // Purpur start -+ AttributeModifiable maxHealth = this.getAttributeInstance(GenericAttributes.MAX_HEALTH); -+ maxHealth.setValue(maxHealth.getValue() / 2); -+ // Purpur end - } - - if (this.isLazy()) { -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java -index 7346921a24bdd57aa3814386bc372b082b23b4bc..7500de8bcdd32f08bf6d32e70cfe09baf097cc2b 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java -@@ -176,6 +176,11 @@ public class EntityParrot extends EntityPerchable implements EntityBird { - public int getPurpurBreedTime() { - return 6000; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.parrotMaxHealth); -+ } - // Purpur end - - @Nullable -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -index 5aa8806063186bec36b38adc51e2ea82bf6ff21a..8d24855f230a5ca6280f885d5b1c26ecf5b91395 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -@@ -82,6 +82,11 @@ public class EntityPig extends EntityAnimal implements ISteerable, ISaddleable { - public int getPurpurBreedTime() { - return this.world.purpurConfig.pigBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.pigMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java b/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java -index c9c7c9de638079393bbea86f8069023dcbcbca83..83494d3c989a120297c21a1bd560bc37734dc86a 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java -@@ -121,6 +121,11 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable { - public int getPurpurBreedTime() { - return this.world.purpurConfig.polarBearBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.polarBearMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java b/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java -index b94aa69e2c5f41161e8c21d68078a522d063e03d..c81aa13dff40d41577c7c13f6aef8972bf31d69e 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java -@@ -20,6 +20,7 @@ import net.minecraft.world.entity.EntityPose; - import net.minecraft.world.entity.EntitySize; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.EnumMonsterType; -+import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.entity.ai.goal.PathfinderGoal; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.item.ItemStack; -@@ -49,6 +50,11 @@ public class EntityPufferFish extends EntityFish { - public boolean isRidableInWater() { - return true; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.pufferfishMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java b/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java -index 465701232567e4058f9dfc776560ccde33fee66c..ef031ac08b06e78d8826579c49cf5e43683318f9 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java -@@ -90,6 +90,11 @@ public class EntityRabbit extends EntityAnimal { - public int getPurpurBreedTime() { - return this.world.purpurConfig.rabbitBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.rabbitMaxHealth); -+ } - // Purpur end - - // CraftBukkit start - code from constructor -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySalmon.java b/src/main/java/net/minecraft/world/entity/animal/EntitySalmon.java -index bf565671c167162b3d935447961f0d44ed4a2779..36e60360193cb0cfd8fef03f964e0fa90002f8bc 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntitySalmon.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntitySalmon.java -@@ -4,6 +4,7 @@ import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.Items; - import net.minecraft.world.level.World; -@@ -24,6 +25,11 @@ public class EntitySalmon extends EntityFishSchool { - public boolean isRidableInWater() { - return true; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.salmonMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java b/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java -index ff6fc821085e4430a3b1008140b0b7fcacc59d2e..365f70117a287fab2fbf63ee8d89a10ac70b2f1b 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java -@@ -126,6 +126,11 @@ public class EntitySheep extends EntityAnimal implements IShearable { - public int getPurpurBreedTime() { - return this.world.purpurConfig.sheepBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.sheepMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java b/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java -index 76fe39cf57384602c7422cb340f15ca7cac65ef9..3934966b06eb9880ed316cee84d099edd80c09b9 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java -@@ -61,6 +61,11 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt - public boolean isRidableInWater() { - return world.purpurConfig.snowGolemRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.snowGolemMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -index 7ec3e5d136cbb708b3bb29aa79bdd401d37d56dc..fa629ebc4946a0c3e891e5e2dd881277b3e25347 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -@@ -86,6 +86,11 @@ public class EntitySquid extends EntityWaterAnimal { - public boolean isInWater() { - return this.inWater || world.purpurConfig.squidsCanFly; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.squidMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTropicalFish.java b/src/main/java/net/minecraft/world/entity/animal/EntityTropicalFish.java -index 478e55475ccc1410a442f4e30a1cbc08f479dbda..7d0982b8756b9e6c12cf4acae765ff651b846250 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityTropicalFish.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityTropicalFish.java -@@ -14,6 +14,7 @@ import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.EnumMobSpawn; - import net.minecraft.world.entity.GroupDataEntity; -+import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.item.EnumColor; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.Items; -@@ -47,6 +48,11 @@ public class EntityTropicalFish extends EntityFishSchool { - public boolean isRidableInWater() { - return true; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.tropicalFishMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -index a16f586934f24e599d00bf793f06d3f9134ed29d..2da43c75c5767973c43e42af37c0d0d9d3a27859 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -@@ -106,6 +106,11 @@ public class EntityTurtle extends EntityAnimal { - public int getPurpurBreedTime() { - return this.world.purpurConfig.turtleBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.turtleMaxHealth); -+ } - // Purpur end - - public void setHomePos(BlockPosition blockposition) { -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java b/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java -index e33aadead6e6c5e0a7b39ef95e7aeb0f0092a94e..090903fbc8f6cd1522c7afb358f708f5ae3395f4 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java -@@ -188,6 +188,11 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable - setCollarColor(world.purpurConfig.wolfDefaultCollarColor); - super.tame(entityhuman); - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.wolfMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java -index c830bf6e5e38f5ebacc07673c3d67e4157c8c2b5..c6e39fe54cc402869b2e9eaea1830ba1ccc9ffc1 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java -@@ -51,6 +51,21 @@ public class EntityHorse extends EntityHorseAbstract { - public int getPurpurBreedTime() { - return this.world.purpurConfig.horseBreedingTicks; - } -+ -+ @Override -+ public float generateMaxHealth() { -+ return (float) generateMaxHealth(this.world.purpurConfig.horseMaxHealthMin, this.world.purpurConfig.horseMaxHealthMax); -+ } -+ -+ @Override -+ public double generateJumpStrength() { -+ return generateJumpStrength(this.world.purpurConfig.horseJumpStrengthMin, this.world.purpurConfig.horseJumpStrengthMax); -+ } -+ -+ @Override -+ public double generateMovementSpeed() { -+ return generateMovementSpeed(this.world.purpurConfig.horseMovementSpeedMin, this.world.purpurConfig.horseMovementSpeedMax); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -index d4556fa190c754406d0c65baae941fb23af3f81f..1d938f324bc08c05b44c72b5a2927016ed599cf2 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -@@ -120,6 +120,32 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven - public boolean isRidableInWater() { - return false; - } -+ -+ protected double generateMaxHealth(double min, double max) { -+ if (min == max) return min; -+ int diff = MathHelper.floor(max - min); -+ double base = max - diff; -+ int first = MathHelper.floor((double) diff / 2); -+ int rest = diff - first; -+ return base + random.nextInt(first + 1) + random.nextInt(rest + 1); -+ } -+ -+ protected double generateJumpStrength(double min, double max) { -+ if (min == max) return min; -+ return min + (max - min) * this.random.nextDouble(); -+ } -+ -+ protected double generateMovementSpeed(double min, double max) { -+ if (min == max) return min; -+ return min + (max - min) * this.random.nextDouble(); -+ } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.generateMaxHealth()); -+ this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue(this.generateMovementSpeed()); -+ this.getAttributeInstance(GenericAttributes.JUMP_STRENGTH).setValue(this.generateJumpStrength()); -+ } - // Purpur end - - @Override -@@ -928,15 +954,15 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven - - } - -- protected float fp() { -+ protected float fp() { return generateMaxHealth(); } public float generateMaxHealth() { // Purpur - OBFHELPER - return 15.0F + (float) this.random.nextInt(8) + (float) this.random.nextInt(9); - } - -- protected double fq() { -+ protected double fq() { return generateJumpStrength(); } public double generateJumpStrength() { // Purpur - OBFHELPER - return 0.4000000059604645D + this.random.nextDouble() * 0.2D + this.random.nextDouble() * 0.2D + this.random.nextDouble() * 0.2D; - } - -- protected double fr() { -+ protected double fr() { return generateMovementSpeed(); } public double generateMovementSpeed() { // Purpur - OBFHELPER - return (0.44999998807907104D + this.random.nextDouble() * 0.3D + this.random.nextDouble() * 0.3D + this.random.nextDouble() * 0.3D) * 0.25D; - } - -@@ -1059,7 +1085,7 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven - groupdataentity = new EntityAgeable.a(0.2F); - } - -- this.eK(); -+ //this.eK(); // Purpur - return super.prepare(worldaccess, difficultydamagescaler, enummobspawn, (GroupDataEntity) groupdataentity, nbttagcompound); - } - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java -index 3b44394dcba8e9905aca46e6e585ee6d7a87de44..589986b36c12dd2774a87e1d22aafd6d3052f123 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java -@@ -26,6 +26,21 @@ public class EntityHorseDonkey extends EntityHorseChestedAbstract { - public int getPurpurBreedTime() { - return this.world.purpurConfig.donkeyBreedingTicks; - } -+ -+ @Override -+ public float generateMaxHealth() { -+ return (float) generateMaxHealth(this.world.purpurConfig.donkeyMaxHealthMin, this.world.purpurConfig.donkeyMaxHealthMax); -+ } -+ -+ @Override -+ public double generateJumpStrength() { -+ return generateJumpStrength(this.world.purpurConfig.donkeyJumpStrengthMin, this.world.purpurConfig.donkeyJumpStrengthMax); -+ } -+ -+ @Override -+ public double generateMovementSpeed() { -+ return generateMovementSpeed(this.world.purpurConfig.donkeyMovementSpeedMin, this.world.purpurConfig.donkeyMovementSpeedMax); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java -index 0536112357e0321dbb902331467b847894a4c11b..9cc1a371dfbb0305fa47e69665a12a6901224edc 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java -@@ -25,7 +25,23 @@ public class EntityHorseMule extends EntityHorseChestedAbstract { - public int getPurpurBreedTime() { - return this.world.purpurConfig.muleBreedingTicks; - } -+ -+ @Override -+ public float generateMaxHealth() { -+ return (float) generateMaxHealth(this.world.purpurConfig.muleMaxHealthMin, this.world.purpurConfig.muleMaxHealthMax); -+ } -+ -+ @Override -+ public double generateJumpStrength() { -+ return generateJumpStrength(this.world.purpurConfig.muleJumpStrengthMin, this.world.purpurConfig.muleJumpStrengthMax); -+ } -+ -+ @Override -+ public double generateMovementSpeed() { -+ return generateMovementSpeed(this.world.purpurConfig.muleMovementSpeedMin, this.world.purpurConfig.muleMovementSpeedMax); -+ } - // Purpur end -+ - @Override - protected SoundEffect getSoundAmbient() { - super.getSoundAmbient(); -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java -index 28c6e3745c61d0670bf7f3a324169472250e25f4..0fe21fde809aa72305b1145b994a7aafe3f03112 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java -@@ -48,6 +48,21 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { - public int getPurpurBreedTime() { - return 6000; - } -+ -+ @Override -+ public float generateMaxHealth() { -+ return (float) generateMaxHealth(this.world.purpurConfig.skeletonHorseMaxHealthMin, this.world.purpurConfig.skeletonHorseMaxHealthMax); -+ } -+ -+ @Override -+ public double generateJumpStrength() { -+ return generateJumpStrength(this.world.purpurConfig.skeletonHorseJumpStrengthMin, this.world.purpurConfig.skeletonHorseJumpStrengthMax); -+ } -+ -+ @Override -+ public double generateMovementSpeed() { -+ return generateMovementSpeed(this.world.purpurConfig.skeletonHorseMovementSpeedMin, this.world.purpurConfig.skeletonHorseMovementSpeedMax); -+ } - // Purpur end - - public static AttributeProvider.Builder eL() { -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java -index c776f18722d1aa73f53da66ef6b37564eeaddd2a..1820c2d225d1fa919de2b1c0593370a8a17b4b6a 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java -@@ -40,6 +40,21 @@ public class EntityHorseZombie extends EntityHorseAbstract { - public int getPurpurBreedTime() { - return 6000; - } -+ -+ @Override -+ public float generateMaxHealth() { -+ return (float) generateMaxHealth(this.world.purpurConfig.zombieHorseMaxHealthMin, this.world.purpurConfig.zombieHorseMaxHealthMax); -+ } -+ -+ @Override -+ public double generateJumpStrength() { -+ return generateJumpStrength(this.world.purpurConfig.zombieHorseJumpStrengthMin, this.world.purpurConfig.zombieHorseJumpStrengthMax); -+ } -+ -+ @Override -+ public double generateMovementSpeed() { -+ return generateMovementSpeed(this.world.purpurConfig.zombieHorseMovementSpeedMin, this.world.purpurConfig.zombieHorseMovementSpeedMax); -+ } - // Purpur end - - public static AttributeProvider.Builder eL() { -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java -index 2710c246a147f117d2d90014c37988888010dc36..4bea68fa35177d84a35dc5ced3e501a87e2a5391 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java -@@ -113,6 +113,21 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn - public int getPurpurBreedTime() { - return this.world.purpurConfig.llamaBreedingTicks; - } -+ -+ @Override -+ public float generateMaxHealth() { -+ return (float) generateMaxHealth(this.world.purpurConfig.llamaMaxHealthMin, this.world.purpurConfig.llamaMaxHealthMax); -+ } -+ -+ @Override -+ public double generateJumpStrength() { -+ return generateJumpStrength(this.world.purpurConfig.llamaJumpStrengthMin, this.world.purpurConfig.llamaJumpStrengthMax); -+ } -+ -+ @Override -+ public double generateMovementSpeed() { -+ return generateMovementSpeed(this.world.purpurConfig.llamaMovementSpeedMin, this.world.purpurConfig.llamaMovementSpeedMax); -+ } - // Purpur end - - public void setStrength(int i) { -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.java -index 0fb651bcde1109b0eb30b60226d3512648dceb41..73f59982d70093d308c6dc6a9a5693347c2699b7 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.java -@@ -42,6 +42,21 @@ public class EntityLlamaTrader extends EntityLlama { - public boolean hasSaddle() { - return super.hasSaddle() || isTamed(); - } -+ -+ @Override -+ public float generateMaxHealth() { -+ return (float) generateMaxHealth(this.world.purpurConfig.llamaTraderMaxHealthMin, this.world.purpurConfig.llamaTraderMaxHealthMax); -+ } -+ -+ @Override -+ public double generateJumpStrength() { -+ return generateJumpStrength(this.world.purpurConfig.llamaTraderJumpStrengthMin, this.world.purpurConfig.llamaTraderJumpStrengthMax); -+ } -+ -+ @Override -+ public double generateMovementSpeed() { -+ return generateMovementSpeed(this.world.purpurConfig.llamaTraderMovementSpeedMin, this.world.purpurConfig.llamaTraderMovementSpeedMax); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -index ad7a9e43e4031054267bb2d18c97d79ce7b16c75..1ac5ce2687aae103e7811fd3bacdf1cbc048c59f 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -@@ -147,6 +147,11 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - public double getMaxY() { - return world.purpurConfig.enderDragonMaxY; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.enderDragonMaxHealth); -+ } - // Purpur end - - public static AttributeProvider.Builder m() { -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java b/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java -index 6553fd92c26d71ac0a60bd046c7f968f2dfe6667..55b6f483aca8cbb5c30b3759e23c86a699e19569 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java -@@ -72,6 +72,11 @@ public class EntityBlaze extends EntityMonster { - setMot(mot.a(0.9D)); - } - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.blazeMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCaveSpider.java b/src/main/java/net/minecraft/world/entity/monster/EntityCaveSpider.java -index 27baf5cde99d8f25b1e7583c30339fcc71a3786f..72b298642f17c13f0f5959034e345a47f1e7ae26 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityCaveSpider.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityCaveSpider.java -@@ -34,6 +34,11 @@ public class EntityCaveSpider extends EntitySpider { - public boolean isRidableInWater() { - return world.purpurConfig.caveSpiderRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.caveSpiderMaxHealth); -+ } - // Purpur end - - public static AttributeProvider.Builder m() { -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -index 1daacdd75c709cd5508434b41589bd57032de27c..d049aac0208386198d1da4e9470e64898d27b1c9 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -@@ -137,6 +137,11 @@ public class EntityCreeper extends EntityMonster { - } - return getForward() == 0 && getStrafe() == 0; // do not jump if standing still - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.creeperMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java b/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java -index 93946f4e3cad07e20189a44ce512682b4cbc163b..926a38adb52b7d99ce2a9fcc52eb4878a2abdbcf 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java -@@ -97,6 +97,15 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { - public boolean jockeyTryExistingChickens() { - return world.purpurConfig.drownedJockeyTryExistingChickens; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.drownedMaxHealth); -+ } -+ -+ protected void generateReinforcementsChance() { -+ this.getAttributeInstance(GenericAttributes.SPAWN_REINFORCEMENTS).setValue(this.random.nextDouble() * this.world.purpurConfig.drownedSpawnReinforcements); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -index cae2b2139e398dd26e9562636f06e096b3e028ae..7c25a7610a5f18e21afead1290e4d879588845af 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -@@ -95,6 +95,11 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - public boolean isRidableInWater() { - return world.purpurConfig.endermanRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.endermanMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEndermite.java b/src/main/java/net/minecraft/world/entity/monster/EntityEndermite.java -index 1c87bea9de812e57f8ccd3c9aa85330af87ed240..0e1d60a744fb41d2c31950572720b8899281df47 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityEndermite.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEndermite.java -@@ -47,6 +47,11 @@ public class EntityEndermite extends EntityMonster { - public boolean isRidableInWater() { - return world.purpurConfig.endermiteRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.endermiteMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java b/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java -index 55607910183155080e3d96296421438d17f19c8f..8d7b8d2ac9a7340e2cfd0d1b8963e4e4d97e8bc8 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java -@@ -59,6 +59,11 @@ public class EntityEvoker extends EntityIllagerWizard { - public boolean isRidableInWater() { - return world.purpurConfig.evokerRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.evokerMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java b/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java -index b6d49740a1c8dfa19e871869b92b307fc8397588..e83d9aae4a04fc67587d40cec1f24ba5ebb58e10 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java -@@ -73,6 +73,11 @@ public class EntityGhast extends EntityFlying implements IMonster { - setMot(mot.a(0.9D)); - } - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.ghastMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGuardian.java b/src/main/java/net/minecraft/world/entity/monster/EntityGuardian.java -index 66ae664add95f4441724b49a470a2fef569042d6..291b2e0defe4d63d4f746a3879c1fee59d2997d7 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityGuardian.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityGuardian.java -@@ -86,6 +86,11 @@ public class EntityGuardian extends EntityMonster { - public boolean isRidableInWater() { - return true; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.guardianMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java b/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java -index ef48184f79920f053d62d34cc7b56a98e8aa4274..4ce2880c063e3552febd05dc7f38cb17cbb1b4d7 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java -@@ -40,6 +40,11 @@ public class EntityGuardianElder extends EntityGuardian { - public boolean isRidableInWater() { - return true; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.elderGuardianMaxHealth); -+ } - // Purpur end - - public static AttributeProvider.Builder m() { -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityMagmaCube.java b/src/main/java/net/minecraft/world/entity/monster/EntityMagmaCube.java -index 15ed51a2746c09538a425fce25fa25f2619b7033..626a207cdb727866cb75f4e53a6880867c1ca195 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityMagmaCube.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityMagmaCube.java -@@ -44,6 +44,15 @@ public class EntityMagmaCube extends EntitySlime { - public float getJumpHeight() { - return 0.42F * this.getBlockJumpFactor(); // from EntityLiving - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.generateMaxHealth()); -+ } -+ -+ public String getMaxHealthEquation() { -+ return world.purpurConfig.magmaCubeMaxHealth; -+ } - // Purpur end - - public static AttributeProvider.Builder m() { -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -index 1ea3054cebbf32588219f8915f9fb496495e3a10..437d602cf4a0da52fc61a50321d795290eea11bf 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -@@ -120,6 +120,11 @@ public class EntityPhantom extends EntityFlying implements IMonster { - world.addEntity(flames); - return true; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.phantomMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java -index 82279ab2f3c1edec14c24c3a7ad24d097d52dea2..dfe65943b3a2f744f06b4669590cc203e8419e60 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java -@@ -81,6 +81,15 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { - public boolean jockeyTryExistingChickens() { - return world.purpurConfig.zombifiedPiglinJockeyTryExistingChickens; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.zombifiedPiglinMaxHealth); -+ } -+ -+ protected void generateReinforcementsChance() { -+ this.getAttributeInstance(GenericAttributes.SPAWN_REINFORCEMENTS).setValue(this.random.nextDouble() * this.world.purpurConfig.zombifiedPiglinSpawnReinforcements); -+ } - // Purpur end - - @Override -@@ -270,7 +279,7 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { - - @Override - protected void eV() { -- this.getAttributeInstance(GenericAttributes.SPAWN_REINFORCEMENTS).setValue(0.0D); -+ generateReinforcementsChance(); // Purpur - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPillager.java b/src/main/java/net/minecraft/world/entity/monster/EntityPillager.java -index 2a4ac6e608650d56cc2b564e715b7b685e7f3f62..43a1a31db5ddfd30b66c63c6b2cceb1dcf62e412 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityPillager.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityPillager.java -@@ -72,6 +72,11 @@ public class EntityPillager extends EntityIllagerAbstract implements ICrossbow { - public boolean isRidableInWater() { - return world.purpurConfig.pillagerRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.pillagerMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java b/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java -index cc37e545ece89803fad91801775470df4620bd62..7e3b59e2302a27f7b8a3f43b75527199722a896f 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java -@@ -80,6 +80,11 @@ public class EntityRavager extends EntityRaider { - double speed = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getBaseValue(); - getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue(speed); - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.ravagerMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityShulker.java b/src/main/java/net/minecraft/world/entity/monster/EntityShulker.java -index 4b5c1691664f16594f316e55576086f2ae54e59e..24367e08c7a94ffdb80d098cf822c278e4e3fe70 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityShulker.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityShulker.java -@@ -82,6 +82,11 @@ public class EntityShulker extends EntityGolem implements IMonster { - public boolean isRidableInWater() { - return world.purpurConfig.shulkerRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.shulkerMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java b/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java -index c0601af022d85c7b03463f0df975d713c0366b2c..a0a1e5977a3cbc8e9befd827dd1e15352a2c0c39 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java -@@ -49,6 +49,11 @@ public class EntitySilverfish extends EntityMonster { - public boolean isRidableInWater() { - return world.purpurConfig.silverfishRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.silverfishMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeleton.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeleton.java -index 0b8517d4e83d14ddf8b6d1f1cf4c538f9e4cc68f..8ee51897af1199b9bed05ddf90fe914a7b214b91 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeleton.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeleton.java -@@ -5,6 +5,7 @@ import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.item.Items; - import net.minecraft.world.level.IMaterial; - import net.minecraft.world.level.World; -@@ -25,6 +26,11 @@ public class EntitySkeleton extends EntitySkeletonAbstract { - public boolean isRidableInWater() { - return world.purpurConfig.skeletonRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.skeletonMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonStray.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonStray.java -index 8484000a1b0d9c252d6fab205b1e316e3f6f33bd..a75a7785406143325b0364737dd1667aad464018 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonStray.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonStray.java -@@ -9,6 +9,7 @@ import net.minecraft.world.effect.MobEffect; - import net.minecraft.world.effect.MobEffects; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.EnumMobSpawn; -+import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.entity.projectile.EntityArrow; - import net.minecraft.world.entity.projectile.EntityTippedArrow; - import net.minecraft.world.item.ItemStack; -@@ -31,6 +32,11 @@ public class EntitySkeletonStray extends EntitySkeletonAbstract { - public boolean isRidableInWater() { - return world.purpurConfig.strayRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.strayMaxHealth); -+ } - // Purpur end - - public static boolean a(EntityTypes entitytypes, WorldAccess worldaccess, EnumMobSpawn enummobspawn, BlockPosition blockposition, Random random) { -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java -index cb52c4e63ac487d55dc16accca6976f44f904112..62f1808a456f46a6c7fbb5e030d9ed6546676a3d 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java -@@ -44,6 +44,11 @@ public class EntitySkeletonWither extends EntitySkeletonAbstract { - public boolean isRidableInWater() { - return world.purpurConfig.witherSkeletonRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.witherSkeletonMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -index feb40c2ca8e8f3fae5665b2d71296a6b811b11f6..2b826dadb4b9132541c9844d144ce7050829250b 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -@@ -51,6 +51,7 @@ import com.destroystokyo.paper.event.entity.SlimeChangeDirectionEvent; - import com.destroystokyo.paper.event.entity.SlimeSwimEvent; - import com.destroystokyo.paper.event.entity.SlimeTargetLivingEntityEvent; - import com.destroystokyo.paper.event.entity.SlimeWanderEvent; -+import javax.script.ScriptException; - import org.bukkit.entity.LivingEntity; - import org.bukkit.entity.Slime; - // Paper end -@@ -65,6 +66,7 @@ import org.bukkit.event.entity.SlimeSplitEvent; - public class EntitySlime extends EntityInsentient implements IMonster { - - private static final DataWatcherObject bo = DataWatcher.a(EntitySlime.class, DataWatcherRegistry.b); -+ private static javax.script.ScriptEngine scriptEngine = new javax.script.ScriptEngineManager().getEngineByName("rhino"); // Purpur - public float b; - public float c; - public float d; -@@ -104,6 +106,30 @@ public class EntitySlime extends EntityInsentient implements IMonster { - } - return true; // do not jump() in wasd controller, let vanilla controller handle - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.generateMaxHealth()); -+ } -+ -+ public String getMaxHealthEquation() { -+ return world.purpurConfig.slimeMaxHealth; -+ } -+ -+ public double generateMaxHealth() { -+ int size = getSize(); -+ Double maxHealth = world.purpurConfig.slimeMaxHealthCache.get(size); -+ if (maxHealth == null) { -+ try { -+ scriptEngine.eval("size = " + size); -+ maxHealth = (double) scriptEngine.eval(getMaxHealthEquation()); -+ } catch (Exception e) { -+ maxHealth = (double) size * size; -+ } -+ world.purpurConfig.slimeMaxHealthCache.put(size, maxHealth); -+ } -+ return maxHealth; -+ } - // Purpur end - - @Override -@@ -130,7 +156,7 @@ public class EntitySlime extends EntityInsentient implements IMonster { - this.datawatcher.set(EntitySlime.bo, i); - this.af(); - this.updateSize(); -- this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue((double) (i * i)); -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(generateMaxHealth()); // Purpur - this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue((double) (0.2F + 0.1F * (float) i)); - this.getAttributeInstance(GenericAttributes.ATTACK_DAMAGE).setValue((double) i); - if (flag) { -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySpider.java b/src/main/java/net/minecraft/world/entity/monster/EntitySpider.java -index fbf7c31f57f6dbfac997480eb7db55efc15ef4cc..9b596aa061aa1d4ddfd66361d5277089c3e18246 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySpider.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySpider.java -@@ -61,6 +61,11 @@ public class EntitySpider extends EntityMonster { - public boolean isRidableInWater() { - return world.purpurConfig.spiderRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.spiderMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java b/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java -index cba66a08feceeeaf7c123da595fc7b12c5749783..892aa844a98ae0d192737c6fc6df0a219256a47b 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java -@@ -110,6 +110,11 @@ public class EntityStrider extends EntityAnimal implements ISteerable, ISaddleab - public int getPurpurBreedTime() { - return this.world.purpurConfig.striderBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.striderMaxHealth); -+ } - // Purpur end - - public static boolean c(EntityTypes entitytypes, GeneratorAccess generatoraccess, EnumMobSpawn enummobspawn, BlockPosition blockposition, Random random) { -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -index 5e2114d2321c1542dc892bc7aed07080008cfd20..6835abd1badd1f03401870f4fed2b6911211d931 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -@@ -92,6 +92,11 @@ public class EntityVex extends EntityMonster { - public boolean b(float f, float f1) { - return false; // no fall damage please - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.vexMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -index 28d345e87f45fa839bc3bd758f79f34aba546db7..caaa27248637255ad9e8db20ca839a980e01bfb6 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -@@ -70,6 +70,11 @@ public class EntityVindicator extends EntityIllagerAbstract { - public boolean isRidableInWater() { - return world.purpurConfig.vindicatorRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.vindicatorMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -index c4663c5b02363bd1499ce1f3b50027f8aa7c68e7..a119923ee8d8ac00892f594a8af6d392f818b59c 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -@@ -74,6 +74,11 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - public boolean isRidableInWater() { - return world.purpurConfig.witchRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.witchMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZoglin.java b/src/main/java/net/minecraft/world/entity/monster/EntityZoglin.java -index 249fb9cf43527af5c7818ce6b07487ad446811b7..4d03a2dc2aed9b292ac17dc57d560f13e655cf4a 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZoglin.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZoglin.java -@@ -72,6 +72,11 @@ public class EntityZoglin extends EntityMonster implements IMonster, IOglin { - public boolean isRidableInWater() { - return world.purpurConfig.zoglinRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.zoglinMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index 88264b7b2c21a377f4b0dd857065e40165f0acde..7112db516e62ca75a445482005c524129b84f54c 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -130,6 +130,15 @@ public class EntityZombie extends EntityMonster { - public boolean jockeyTryExistingChickens() { - return world.purpurConfig.zombieJockeyTryExistingChickens; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.zombieMaxHealth); -+ } -+ -+ protected void generateReinforcementsChance() { -+ this.getAttributeInstance(GenericAttributes.SPAWN_REINFORCEMENTS).setValue(this.random.nextDouble() * this.world.purpurConfig.zombieSpawnReinforcements); -+ } - // Purpur end - - @Override -@@ -612,7 +621,7 @@ public class EntityZombie extends EntityMonster { - } - - protected void eV() { -- this.getAttributeInstance(GenericAttributes.SPAWN_REINFORCEMENTS).setValue(this.random.nextDouble() * 0.10000000149011612D); -+ generateReinforcementsChance(); // Purpur - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java -index ad801fc394fbb83cf280ee96f962e7f311615d72..c060d93d9f3332b514a1400dec14f2035c058e48 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java -@@ -11,6 +11,7 @@ import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityLiving; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.EnumMobSpawn; -+import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.level.World; -@@ -47,6 +48,15 @@ public class EntityZombieHusk extends EntityZombie { - public boolean jockeyTryExistingChickens() { - return world.purpurConfig.huskJockeyTryExistingChickens; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.huskMaxHealth); -+ } -+ -+ protected void generateReinforcementsChance() { -+ this.getAttributeInstance(GenericAttributes.SPAWN_REINFORCEMENTS).setValue(this.random.nextDouble() * this.world.purpurConfig.huskSpawnReinforcements); -+ } - // Purpur end - - public static boolean a(EntityTypes entitytypes, WorldAccess worldaccess, EnumMobSpawn enummobspawn, BlockPosition blockposition, Random random) { -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java -index b8395c7317494adf36010080931a1c8635ab6cfa..aeeee97a87680f072188d1fcc9ec55b5ca762295 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java -@@ -29,6 +29,7 @@ import net.minecraft.world.entity.EnumItemSlot; - import net.minecraft.world.entity.EnumMobSpawn; - import net.minecraft.world.entity.GroupDataEntity; - import net.minecraft.world.entity.ReputationHandler; -+import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.entity.ai.village.ReputationEvent; - import net.minecraft.world.entity.npc.EntityVillager; - import net.minecraft.world.entity.npc.VillagerData; -@@ -95,6 +96,15 @@ public class EntityZombieVillager extends EntityZombie implements VillagerDataHo - public boolean jockeyTryExistingChickens() { - return world.purpurConfig.zombieVillagerJockeyTryExistingChickens; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.zombieVillagerMaxHealth); -+ } -+ -+ protected void generateReinforcementsChance() { -+ this.getAttributeInstance(GenericAttributes.SPAWN_REINFORCEMENTS).setValue(this.random.nextDouble() * this.world.purpurConfig.zombieVillagerSpawnReinforcements); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java b/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java -index 9f2af4b37ffb22034b537cc27b42d520a41d4fe7..e9b466bb3172fcae1dee81e7e1b8c069b0a23944 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java -+++ b/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java -@@ -76,6 +76,11 @@ public class EntityHoglin extends EntityAnimal implements IMonster, IOglin { - public int getPurpurBreedTime() { - return this.world.purpurConfig.hoglinBreedingTicks; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.hoglinMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java -index edac17b1072102abe322d69072c4277e6c21cfbe..f34ee0cf7a31cd7a9ee8f7e7ae76e9008f6da35b 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java -+++ b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java -@@ -96,6 +96,11 @@ public class EntityPiglin extends EntityPiglinAbstract implements ICrossbow { - public boolean isRidableInWater() { - return world.purpurConfig.piglinRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.piglinMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglinBrute.java b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglinBrute.java -index 1370d2d8568a4ed62f2ec3d54abc7d2bebc48f75..201b78ffb5062254a6b3447f217df03dfb498710 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglinBrute.java -+++ b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglinBrute.java -@@ -49,6 +49,11 @@ public class EntityPiglinBrute extends EntityPiglinAbstract { - public boolean isRidableInWater() { - return world.purpurConfig.piglinBruteRidableInWater; - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.piglinBruteMaxHealth); -+ } - // Purpur end - - public static AttributeProvider.Builder eS() { -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index d888aa8df65d54a0dce23eaae609aa0d2c3be3d9..b36f62b38888d6eb64d46ac67c89a4189aafcfc4 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -167,6 +167,11 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - public boolean a(EntityHuman entityhuman) { - return world.purpurConfig.villagerCanBeLeashed && !this.isLeashed(); - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.villagerMaxHealth); -+ } - // Purpur end - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -index 6c390fb20c7f29133a60780a75676d8d3d6eab29..f6e0a92037d22de102c42cc1953ea90919bd3a34 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -@@ -18,6 +18,7 @@ import net.minecraft.world.entity.EntityAgeable; - import net.minecraft.world.entity.EntityExperienceOrb; - import net.minecraft.world.entity.EntityInsentient; - import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.entity.ai.goal.PathfinderGoal; - import net.minecraft.world.entity.ai.goal.PathfinderGoalAvoidTarget; - import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat; -@@ -114,6 +115,11 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { - public boolean a(EntityHuman entityhuman) { - return world.purpurConfig.villagerTraderCanBeLeashed && !this.isLeashed(); - } -+ -+ @Override -+ public void initAttributes() { -+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(this.world.purpurConfig.villagerTraderMaxHealth); -+ } - // Purpur - end - - @Nullable -diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 0666c523f82b9083ed8e81570faa923bbeb00ab8..f0f8165c51c17855d0c719d47bea194b80ff7847 100644 ---- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -542,30 +542,58 @@ public class PurpurWorldConfig { - public boolean batRidable = false; - public boolean batRidableInWater = false; - public double batMaxY = 256D; -+ public double batMaxHealth = 6.0D; -+ public double batFollowRange = 16.0D; -+ public double batKnockbackResistance = 0.0D; -+ public double batMovementSpeed = 0.6D; -+ public double batFlyingSpeed = 0.6D; -+ public double batArmor = 0.0D; -+ public double batArmorToughness = 0.0D; -+ public double batAttackKnockback = 0.0D; - private void batSettings() { - batRidable = getBoolean("mobs.bat.ridable", batRidable); - batRidableInWater = getBoolean("mobs.bat.ridable-in-water", batRidableInWater); - batMaxY = getDouble("mobs.bat.ridable-max-y", batMaxY); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.bat.attributes.max-health", batMaxHealth); -+ set("mobs.bat.attributes.max-health", null); -+ set("mobs.bat.attributes.max_health", oldValue); -+ } -+ batMaxHealth = getDouble("mobs.bat.attributes.max_health", batMaxHealth); - } - - public boolean beeRidable = false; - public boolean beeRidableInWater = false; - public double beeMaxY = 256D; - public int beeBreedingTicks = 6000; -+ public double beeMaxHealth = 10.0D; - private void beeSettings() { - beeRidable = getBoolean("mobs.bee.ridable", beeRidable); - beeRidableInWater = getBoolean("mobs.bee.ridable-in-water", beeRidableInWater); - beeMaxY = getDouble("mobs.bee.ridable-max-y", beeMaxY); - beeBreedingTicks = getInt("mobs.bee.breeding-delay-ticks", beeBreedingTicks); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.bee.attributes.max-health", beeMaxHealth); -+ set("mobs.bee.attributes.max-health", null); -+ set("mobs.bee.attributes.max_health", oldValue); -+ } -+ beeMaxHealth = getDouble("mobs.bee.attributes.max_health", beeMaxHealth); - } - - public boolean blazeRidable = false; - public boolean blazeRidableInWater = false; - public double blazeMaxY = 256D; -+ public double blazeMaxHealth = 20.0D; - private void blazeSettings() { - blazeRidable = getBoolean("mobs.blaze.ridable", blazeRidable); - blazeRidableInWater = getBoolean("mobs.blaze.ridable-in-water", blazeRidableInWater); - blazeMaxY = getDouble("mobs.blaze.ridable-max-y", blazeMaxY); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.blaze.attributes.max-health", blazeMaxHealth); -+ set("mobs.blaze.attributes.max-health", null); -+ set("mobs.blaze.attributes.max_health", oldValue); -+ } -+ blazeMaxHealth = getDouble("mobs.blaze.attributes.max_health", blazeMaxHealth); - } - - public boolean catRidable = false; -@@ -574,6 +602,7 @@ public class PurpurWorldConfig { - public int catSpawnSwampHutScanRange = 16; - public int catSpawnVillageScanRange = 48; - public int catBreedingTicks = 6000; -+ public double catMaxHealth = 10.0D; - private void catSettings() { - catRidable = getBoolean("mobs.cat.ridable", catRidable); - catRidableInWater = getBoolean("mobs.cat.ridable-in-water", catRidableInWater); -@@ -581,51 +610,92 @@ public class PurpurWorldConfig { - catSpawnSwampHutScanRange = getInt("mobs.cat.scan-range-for-other-cats.swamp-hut", catSpawnSwampHutScanRange); - catSpawnVillageScanRange = getInt("mobs.cat.scan-range-for-other-cats.village", catSpawnVillageScanRange); - catBreedingTicks = getInt("mobs.cat.breeding-delay-ticks", catBreedingTicks); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.cat.attributes.max-health", catMaxHealth); -+ set("mobs.cat.attributes.max-health", null); -+ set("mobs.cat.attributes.max_health", oldValue); -+ } -+ catMaxHealth = getDouble("mobs.cat.attributes.max_health", catMaxHealth); - } - - public boolean caveSpiderRidable = false; - public boolean caveSpiderRidableInWater = false; -+ public double caveSpiderMaxHealth = 12.0D; - private void caveSpiderSettings() { - caveSpiderRidable = getBoolean("mobs.cave_spider.ridable", caveSpiderRidable); - caveSpiderRidableInWater = getBoolean("mobs.cave_spider.ridable-in-water", caveSpiderRidableInWater); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.cave_spider.attributes.max-health", caveSpiderMaxHealth); -+ set("mobs.cave_spider.attributes.max-health", null); -+ set("mobs.cave_spider.attributes.max_health", oldValue); -+ } -+ caveSpiderMaxHealth = getDouble("mobs.cave_spider.attributes.max_health", caveSpiderMaxHealth); - } - - public boolean chickenRidable = false; - public boolean chickenRidableInWater = false; - public boolean chickenRetaliate = false; - public int chickenBreedingTicks = 6000; -+ public double chickenMaxHealth = 4.0D; - private void chickenSettings() { - chickenRidable = getBoolean("mobs.chicken.ridable", chickenRidable); - chickenRidableInWater = getBoolean("mobs.chicken.ridable-in-water", chickenRidableInWater); - chickenRetaliate = getBoolean("mobs.chicken.retaliate", chickenRetaliate); - chickenBreedingTicks = getInt("mobs.chicken.breeding-delay-ticks", chickenBreedingTicks); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.chicken.attributes.max-health", chickenMaxHealth); -+ set("mobs.chicken.attributes.max-health", null); -+ set("mobs.chicken.attributes.max_health", oldValue); -+ } -+ chickenMaxHealth = getDouble("mobs.chicken.attributes.max_health", chickenMaxHealth); - } - - public boolean codRidable = false; -+ public double codMaxHealth = 3.0D; - private void codSettings() { - codRidable = getBoolean("mobs.cod.ridable", codRidable); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.cod.attributes.max-health", codMaxHealth); -+ set("mobs.cod.attributes.max-health", null); -+ set("mobs.cod.attributes.max_health", oldValue); -+ } -+ codMaxHealth = getDouble("mobs.cod.attributes.max_health", codMaxHealth); - } - - public boolean cowRidable = false; - public boolean cowRidableInWater = false; - public int cowFeedMushrooms = 0; - public int cowBreedingTicks = 6000; -+ public double cowMaxHealth = 10.0D; - private void cowSettings() { - cowRidable = getBoolean("mobs.cow.ridable", cowRidable); - cowRidableInWater = getBoolean("mobs.cow.ridable-in-water", cowRidableInWater); - cowFeedMushrooms = getInt("mobs.cow.feed-mushrooms-for-mooshroom", cowFeedMushrooms); - cowBreedingTicks = getInt("mobs.cow.breeding-delay-ticks", cowBreedingTicks); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.cow.attributes.max-health", cowMaxHealth); -+ set("mobs.cow.attributes.max-health", null); -+ set("mobs.cow.attributes.max_health", oldValue); -+ } -+ cowMaxHealth = getDouble("mobs.cow.attributes.max_health", cowMaxHealth); - } - - public boolean creeperRidable = false; - public boolean creeperRidableInWater = false; - public boolean creeperAllowGriefing = true; - public double creeperChargedChance = 0.0D; -+ public double creeperMaxHealth = 20.0D; - private void creeperSettings() { - creeperRidable = getBoolean("mobs.creeper.ridable", creeperRidable); - creeperRidableInWater = getBoolean("mobs.creeper.ridable-in-water", creeperRidableInWater); - creeperAllowGriefing = getBoolean("mobs.creeper.allow-griefing", creeperAllowGriefing); - creeperChargedChance = getDouble("mobs.creeper.naturally-charged-chance", creeperChargedChance); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.creeper.attributes.max-health", creeperMaxHealth); -+ set("mobs.creeper.attributes.max-health", null); -+ set("mobs.creeper.attributes.max_health", oldValue); -+ } -+ creeperMaxHealth = getDouble("mobs.creeper.attributes.max_health", creeperMaxHealth); - } - - public boolean dolphinRidable = false; -@@ -633,19 +703,45 @@ public class PurpurWorldConfig { - public float dolphinSpitSpeed = 1.0F; - public float dolphinSpitDamage = 2.0F; - public boolean dolphinDisableTreasureSearching = false; -+ public double dolphinMaxHealth = 10.0D; - private void dolphinSettings() { - dolphinRidable = getBoolean("mobs.dolphin.ridable", dolphinRidable); - dolphinSpitCooldown = getInt("mobs.dolphin.spit.cooldown", dolphinSpitCooldown); - dolphinSpitSpeed = (float) getDouble("mobs.dolphin.spit.speed", dolphinSpitSpeed); - dolphinSpitDamage = (float) getDouble("mobs.dolphin.spit.damage", dolphinSpitDamage); - dolphinDisableTreasureSearching = getBoolean("mobs.dolphin.disable-treasure-searching", dolphinDisableTreasureSearching); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.dolphin.attributes.max-health", dolphinMaxHealth); -+ set("mobs.dolphin.attributes.max-health", null); -+ set("mobs.dolphin.attributes.max_health", oldValue); -+ } -+ dolphinMaxHealth = getDouble("mobs.dolphin.attributes.max_health", dolphinMaxHealth); - } - - public boolean donkeyRidableInWater = false; - public int donkeyBreedingTicks = 6000; -+ public double donkeyMaxHealthMin = 15.0D; -+ public double donkeyMaxHealthMax = 30.0D; -+ public double donkeyJumpStrengthMin = 0.5D; -+ public double donkeyJumpStrengthMax = 0.5D; -+ public double donkeyMovementSpeedMin = 0.175D; -+ public double donkeyMovementSpeedMax = 0.175D; - private void donkeySettings() { - donkeyRidableInWater = getBoolean("mobs.donkey.ridable-in-water", donkeyRidableInWater); - donkeyBreedingTicks = getInt("mobs.donkey.breeding-delay-ticks", donkeyBreedingTicks); -+ if (PurpurConfig.version < 10) { -+ double oldMin = getDouble("mobs.donkey.attributes.max-health.min", donkeyMaxHealthMin); -+ double oldMax = getDouble("mobs.donkey.attributes.max-health.max", donkeyMaxHealthMax); -+ set("mobs.donkey.attributes.max-health", null); -+ set("mobs.donkey.attributes.max_health.min", oldMin); -+ set("mobs.donkey.attributes.max_health.max", oldMax); -+ } -+ donkeyMaxHealthMin = getDouble("mobs.donkey.attributes.max_health.min", donkeyMaxHealthMin); -+ donkeyMaxHealthMax = getDouble("mobs.donkey.attributes.max_health.max", donkeyMaxHealthMax); -+ donkeyJumpStrengthMin = getDouble("mobs.donkey.attributes.jump_strength.min", donkeyJumpStrengthMin); -+ donkeyJumpStrengthMax = getDouble("mobs.donkey.attributes.jump_strength.max", donkeyJumpStrengthMax); -+ donkeyMovementSpeedMin = getDouble("mobs.donkey.attributes.movement_speed.min", donkeyMovementSpeedMin); -+ donkeyMovementSpeedMax = getDouble("mobs.donkey.attributes.movement_speed.max", donkeyMovementSpeedMax); - } - - public boolean drownedRidable = false; -@@ -653,73 +749,135 @@ public class PurpurWorldConfig { - public boolean drownedJockeyOnlyBaby = true; - public double drownedJockeyChance = 0.05D; - public boolean drownedJockeyTryExistingChickens = true; -+ public double drownedMaxHealth = 20.0D; -+ public double drownedSpawnReinforcements = 0.1D; - private void drownedSettings() { - drownedRidable = getBoolean("mobs.drowned.ridable", drownedRidable); - drownedRidableInWater = getBoolean("mobs.drowned.ridable-in-water", drownedRidableInWater); - drownedJockeyOnlyBaby = getBoolean("mobs.drowned.jockey.only-babies", drownedJockeyOnlyBaby); - drownedJockeyChance = getDouble("mobs.drowned.jockey.chance", drownedJockeyChance); - drownedJockeyTryExistingChickens = getBoolean("mobs.drowned.jockey.try-existing-chickens", drownedJockeyTryExistingChickens); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.drowned.attributes.max-health", drownedMaxHealth); -+ set("mobs.drowned.attributes.max-health", null); -+ set("mobs.drowned.attributes.max_health", oldValue); -+ } -+ drownedMaxHealth = getDouble("mobs.drowned.attributes.max_health", drownedMaxHealth); -+ drownedSpawnReinforcements = getDouble("mobs.drowned.attributes.spawn_reinforcements", drownedSpawnReinforcements); - } - - public boolean elderGuardianRidable = false; -+ public double elderGuardianMaxHealth = 80.0D; - private void elderGuardianSettings() { - elderGuardianRidable = getBoolean("mobs.elder_guardian.ridable", elderGuardianRidable); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.elder_guardian.attributes.max-health", elderGuardianMaxHealth); -+ set("mobs.elder_guardian.attributes.max-health", null); -+ set("mobs.elder_guardian.attributes.max_health", oldValue); -+ } -+ elderGuardianMaxHealth = getDouble("mobs.elder_guardian.attributes.max_health", elderGuardianMaxHealth); - } - - public boolean enderDragonRidable = false; - public boolean enderDragonRidableInWater = false; - public double enderDragonMaxY = 256D; - public boolean enderDragonAlwaysDropsFullExp = false; -+ public double enderDragonMaxHealth = 200.0D; - private void enderDragonSettings() { - enderDragonRidable = getBoolean("mobs.ender_dragon.ridable", enderDragonRidable); - enderDragonRidableInWater = getBoolean("mobs.ender_dragon.ridable-in-water", enderDragonRidableInWater); - enderDragonMaxY = getDouble("mobs.ender_dragon.ridable-max-y", enderDragonMaxY); - enderDragonAlwaysDropsFullExp = getBoolean("mobs.ender_dragon.always-drop-full-exp", enderDragonAlwaysDropsFullExp); -+ if (PurpurConfig.version < 8) { -+ double oldValue = getDouble("mobs.ender_dragon.max-health", enderDragonMaxHealth); -+ set("mobs.ender_dragon.max-health", null); -+ set("mobs.ender_dragon.attributes.max_health", oldValue); -+ } else if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.ender_dragon.attributes.max-health", enderDragonMaxHealth); -+ set("mobs.ender_dragon.attributes.max-health", null); -+ set("mobs.ender_dragon.attributes.max_health", oldValue); -+ } -+ enderDragonMaxHealth = getDouble("mobs.ender_dragon.attributes.max_health", enderDragonMaxHealth); - } - - public boolean endermanRidable = false; - public boolean endermanRidableInWater = false; - public boolean endermanAllowGriefing = true; - public boolean endermanDespawnEvenWithBlock = false; -+ public double endermanMaxHealth = 40.0D; - private void endermanSettings() { - endermanRidable = getBoolean("mobs.enderman.ridable", endermanRidable); - endermanRidableInWater = getBoolean("mobs.enderman.ridable-in-water", endermanRidableInWater); - endermanAllowGriefing = getBoolean("mobs.enderman.allow-griefing", endermanAllowGriefing); - endermanDespawnEvenWithBlock = getBoolean("mobs.enderman.can-despawn-with-held-block", endermanDespawnEvenWithBlock); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.enderman.attributes.max-health", endermanMaxHealth); -+ set("mobs.enderman.attributes.max-health", null); -+ set("mobs.enderman.attributes.max_health", oldValue); -+ } -+ endermanMaxHealth = getDouble("mobs.enderman.attributes.max_health", endermanMaxHealth); - } - - public boolean endermiteRidable = false; - public boolean endermiteRidableInWater = false; -+ public double endermiteMaxHealth = 8.0D; - private void endermiteSettings() { - endermiteRidable = getBoolean("mobs.endermite.ridable", endermiteRidable); - endermiteRidableInWater = getBoolean("mobs.endermite.ridable-in-water", endermiteRidableInWater); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.endermite.attributes.max-health", endermiteMaxHealth); -+ set("mobs.endermite.attributes.max-health", null); -+ set("mobs.endermite.attributes.max_health", oldValue); -+ } -+ endermiteMaxHealth = getDouble("mobs.endermite.attributes.max_health", endermiteMaxHealth); - } - - public boolean evokerRidable = false; - public boolean evokerRidableInWater = false; -+ public double evokerMaxHealth = 24.0D; - private void evokerSettings() { - evokerRidable = getBoolean("mobs.evoker.ridable", evokerRidable); - evokerRidableInWater = getBoolean("mobs.evoker.ridable-in-water", evokerRidableInWater); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.evoker.attributes.max-health", evokerMaxHealth); -+ set("mobs.evoker.attributes.max-health", null); -+ set("mobs.evoker.attributes.max_health", oldValue); -+ } -+ evokerMaxHealth = getDouble("mobs.evoker.attributes.max_health", evokerMaxHealth); - } - - public boolean foxRidable = false; - public boolean foxRidableInWater = false; - public boolean foxTypeChangesWithTulips = false; - public int foxBreedingTicks = 6000; -+ public double foxMaxHealth = 10.0D; - private void foxSettings() { - foxRidable = getBoolean("mobs.fox.ridable", foxRidable); - foxRidableInWater = getBoolean("mobs.fox.ridable-in-water", foxRidableInWater); - foxTypeChangesWithTulips = getBoolean("mobs.fox.tulips-change-type", foxTypeChangesWithTulips); - foxBreedingTicks = getInt("mobs.fox.breeding-delay-ticks", foxBreedingTicks); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.fox.attributes.max-health", foxMaxHealth); -+ set("mobs.fox.attributes.max-health", null); -+ set("mobs.fox.attributes.max_health", oldValue); -+ } -+ foxMaxHealth = getDouble("mobs.fox.attributes.max_health", foxMaxHealth); - } - - public boolean ghastRidable = false; - public boolean ghastRidableInWater = false; - public double ghastMaxY = 256D; -+ public double ghastMaxHealth = 10.0D; - private void ghastSettings() { - ghastRidable = getBoolean("mobs.ghast.ridable", ghastRidable); - ghastRidableInWater = getBoolean("mobs.ghast.ridable-in-water", ghastRidableInWater); - ghastMaxY = getDouble("mobs.ghast.ridable-max-y", ghastMaxY); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.ghast.attributes.max-health", ghastMaxHealth); -+ set("mobs.ghast.attributes.max-health", null); -+ set("mobs.ghast.attributes.max_health", oldValue); -+ } -+ ghastMaxHealth = getDouble("mobs.ghast.attributes.max_health", ghastMaxHealth); - } - - public boolean giantRidable = false; -@@ -742,31 +900,68 @@ public class PurpurWorldConfig { - giantHaveHostileAI = getBoolean("mobs.giant.have-hostile-ai", giantHaveHostileAI); - if (PurpurConfig.version < 8) { - double oldValue = getDouble("mobs.giant.max-health", giantMaxHealth); -- set("mobs.giant.attributes.max-health", oldValue); - set("mobs.giant.max-health", null); -+ set("mobs.giant.attributes.max_health", oldValue); -+ } else if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.giant.attributes.max-health", giantMaxHealth); -+ set("mobs.giant.attributes.max-health", null); -+ set("mobs.giant.attributes.max_health", oldValue); - } -- giantMaxHealth = getDouble("mobs.giant.attributes.max-health", giantMaxHealth); -+ giantMaxHealth = getDouble("mobs.giant.attributes.max_health", giantMaxHealth); - } - - public boolean guardianRidable = false; -+ public double guardianMaxHealth = 30.0D; - private void guardianSettings() { - guardianRidable = getBoolean("mobs.guardian.ridable", guardianRidable); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.guardian.attributes.max-health", guardianMaxHealth); -+ set("mobs.guardian.attributes.max-health", null); -+ set("mobs.guardian.attributes.max_health", oldValue); -+ } -+ guardianMaxHealth = getDouble("mobs.guardian.attributes.max_health", guardianMaxHealth); - } - - public boolean hoglinRidable = false; - public boolean hoglinRidableInWater = false; - public int hoglinBreedingTicks = 6000; -+ public double hoglinMaxHealth = 40.0D; - private void hoglinSettings() { - hoglinRidable = getBoolean("mobs.hoglin.ridable", hoglinRidable); - hoglinRidableInWater = getBoolean("mobs.hoglin.ridable-in-water", hoglinRidableInWater); - hoglinBreedingTicks = getInt("mobs.hoglin.breeding-delay-ticks", hoglinBreedingTicks); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.hoglin.attributes.max-health", hoglinMaxHealth); -+ set("mobs.hoglin.attributes.max-health", null); -+ set("mobs.hoglin.attributes.max_health", oldValue); -+ } -+ hoglinMaxHealth = getDouble("mobs.hoglin.attributes.max_health", hoglinMaxHealth); - } - - public boolean horseRidableInWater = false; - public int horseBreedingTicks = 6000; -+ public double horseMaxHealthMin = 15.0D; -+ public double horseMaxHealthMax = 30.0D; -+ public double horseJumpStrengthMin = 0.4D; -+ public double horseJumpStrengthMax = 1.0D; -+ public double horseMovementSpeedMin = 0.1125D; -+ public double horseMovementSpeedMax = 0.3375D; - private void horseSettings() { - horseRidableInWater = getBoolean("mobs.horse.ridable-in-water", horseRidableInWater); - horseBreedingTicks = getInt("mobs.horse.breeding-delay-ticks", horseBreedingTicks); -+ if (PurpurConfig.version < 10) { -+ double oldMin = getDouble("mobs.horse.attributes.max-health.min", horseMaxHealthMin); -+ double oldMax = getDouble("mobs.horse.attributes.max-health.max", horseMaxHealthMax); -+ set("mobs.horse.attributes.max-health", null); -+ set("mobs.horse.attributes.max_health.min", oldMin); -+ set("mobs.horse.attributes.max_health.max", oldMax); -+ } -+ horseMaxHealthMin = getDouble("mobs.horse.attributes.max_health.min", horseMaxHealthMin); -+ horseMaxHealthMax = getDouble("mobs.horse.attributes.max_health.max", horseMaxHealthMax); -+ horseJumpStrengthMin = getDouble("mobs.horse.attributes.jump_strength.min", horseJumpStrengthMin); -+ horseJumpStrengthMax = getDouble("mobs.horse.attributes.jump_strength.max", horseJumpStrengthMax); -+ horseMovementSpeedMin = getDouble("mobs.horse.attributes.movement_speed.min", horseMovementSpeedMin); -+ horseMovementSpeedMax = getDouble("mobs.horse.attributes.movement_speed.max", horseMovementSpeedMax); - } - - public boolean huskRidable = false; -@@ -774,12 +969,21 @@ public class PurpurWorldConfig { - public boolean huskJockeyOnlyBaby = true; - public double huskJockeyChance = 0.05D; - public boolean huskJockeyTryExistingChickens = true; -+ public double huskMaxHealth = 20.0D; -+ public double huskSpawnReinforcements = 0.1D; - private void huskSettings() { - huskRidable = getBoolean("mobs.husk.ridable", huskRidable); - huskRidableInWater = getBoolean("mobs.husk.ridable-in-water", huskRidableInWater); - huskJockeyOnlyBaby = getBoolean("mobs.husk.jockey.only-babies", huskJockeyOnlyBaby); - huskJockeyChance = getDouble("mobs.husk.jockey.chance", huskJockeyChance); - huskJockeyTryExistingChickens = getBoolean("mobs.husk.jockey.try-existing-chickens", huskJockeyTryExistingChickens); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.husk.attributes.max-health", huskMaxHealth); -+ set("mobs.husk.attributes.max-health", null); -+ set("mobs.husk.attributes.max_health", oldValue); -+ } -+ huskMaxHealth = getDouble("mobs.husk.attributes.max_health", huskMaxHealth); -+ huskSpawnReinforcements = getDouble("mobs.husk.attributes.spawn_reinforcements", huskSpawnReinforcements); - } - - public boolean illusionerRidable = false; -@@ -794,85 +998,188 @@ public class PurpurWorldConfig { - illusionerFollowRange = getDouble("mobs.illusioner.follow-range", illusionerFollowRange); - if (PurpurConfig.version < 8) { - double oldValue = getDouble("mobs.illusioner.max-health", illusionerMaxHealth); -- set("mobs.illusioner.attributes.max-health", oldValue); - set("mobs.illusioner.max-health", null); -+ set("mobs.illusioner.attributes.max_health", oldValue); -+ } else if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.illusioner.attributes.max-health", illusionerMaxHealth); -+ set("mobs.illusioner.attributes.max-health", null); -+ set("mobs.illusioner.attributes.max_health", oldValue); - } -- illusionerMaxHealth = getDouble("mobs.illusioner.attributes.max-health", illusionerMaxHealth); -+ illusionerMaxHealth = getDouble("mobs.illusioner.attributes.max_health", illusionerMaxHealth); - } - - public boolean ironGolemRidable = false; - public boolean ironGolemRidableInWater = false; - public boolean ironGolemCanSwim = false; -+ public double ironGolemMaxHealth = 100.0D; - private void ironGolemSettings() { - ironGolemRidable = getBoolean("mobs.iron_golem.ridable", ironGolemRidable); - ironGolemRidableInWater = getBoolean("mobs.iron_golem.ridable-in-water", ironGolemRidableInWater); - ironGolemCanSwim = getBoolean("mobs.iron_golem.can-swim", ironGolemCanSwim); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.iron_golem.attributes.max-health", ironGolemMaxHealth); -+ set("mobs.iron_golem.attributes.max-health", null); -+ set("mobs.iron_golem.attributes.max_health", oldValue); -+ } -+ ironGolemMaxHealth = getDouble("mobs.iron_golem.attributes.max_health", ironGolemMaxHealth); - } - - public boolean llamaRidable = false; - public boolean llamaRidableInWater = false; - public int llamaBreedingTicks = 6000; -+ public double llamaMaxHealthMin = 15.0D; -+ public double llamaMaxHealthMax = 30.0D; -+ public double llamaJumpStrengthMin = 0.5D; -+ public double llamaJumpStrengthMax = 0.5D; -+ public double llamaMovementSpeedMin = 0.175D; -+ public double llamaMovementSpeedMax = 0.175D; - private void llamaSettings() { - llamaRidable = getBoolean("mobs.llama.ridable", llamaRidable); - llamaRidableInWater = getBoolean("mobs.llama.ridable-in-water", llamaRidableInWater); - llamaBreedingTicks = getInt("mobs.llama.breeding-delay-ticks", llamaBreedingTicks); -+ if (PurpurConfig.version < 10) { -+ double oldMin = getDouble("mobs.llama.attributes.max-health.min", llamaMaxHealthMin); -+ double oldMax = getDouble("mobs.llama.attributes.max-health.max", llamaMaxHealthMax); -+ set("mobs.llama.attributes.max-health", null); -+ set("mobs.llama.attributes.max_health.min", oldMin); -+ set("mobs.llama.attributes.max_health.max", oldMax); -+ } -+ llamaMaxHealthMin = getDouble("mobs.llama.attributes.max_health.min", llamaMaxHealthMin); -+ llamaMaxHealthMax = getDouble("mobs.llama.attributes.max_health.max", llamaMaxHealthMax); -+ llamaJumpStrengthMin = getDouble("mobs.llama.attributes.jump_strength.min", llamaJumpStrengthMin); -+ llamaJumpStrengthMax = getDouble("mobs.llama.attributes.jump_strength.max", llamaJumpStrengthMax); -+ llamaMovementSpeedMin = getDouble("mobs.llama.attributes.movement_speed.min", llamaMovementSpeedMin); -+ llamaMovementSpeedMax = getDouble("mobs.llama.attributes.movement_speed.max", llamaMovementSpeedMax); - } - - public boolean llamaTraderRidable = false; - public boolean llamaTraderRidableInWater = false; -+ public double llamaTraderMaxHealthMin = 15.0D; -+ public double llamaTraderMaxHealthMax = 30.0D; -+ public double llamaTraderJumpStrengthMin = 0.5D; -+ public double llamaTraderJumpStrengthMax = 0.5D; -+ public double llamaTraderMovementSpeedMin = 0.175D; -+ public double llamaTraderMovementSpeedMax = 0.175D; - private void llamaTraderSettings() { - llamaTraderRidable = getBoolean("mobs.trader_llama.ridable", llamaTraderRidable); - llamaTraderRidableInWater = getBoolean("mobs.trader_llama.ridable-in-water", llamaTraderRidableInWater); -+ if (PurpurConfig.version < 10) { -+ double oldMin = getDouble("mobs.trader_llama.attributes.max-health.min", llamaTraderMaxHealthMin); -+ double oldMax = getDouble("mobs.trader_llama.attributes.max-health.max", llamaTraderMaxHealthMax); -+ set("mobs.trader_llama.attributes.max-health", null); -+ set("mobs.trader_llama.attributes.max_health.min", oldMin); -+ set("mobs.trader_llama.attributes.max_health.max", oldMax); -+ } -+ llamaTraderMaxHealthMin = getDouble("mobs.trader_llama.attributes.max_health.min", llamaTraderMaxHealthMin); -+ llamaTraderMaxHealthMax = getDouble("mobs.trader_llama.attributes.max_health.max", llamaTraderMaxHealthMax); -+ llamaTraderJumpStrengthMin = getDouble("mobs.trader_llama.attributes.jump_strength.min", llamaTraderJumpStrengthMin); -+ llamaTraderJumpStrengthMax = getDouble("mobs.trader_llama.attributes.jump_strength.max", llamaTraderJumpStrengthMax); -+ llamaTraderMovementSpeedMin = getDouble("mobs.trader_llama.attributes.movement_speed.min", llamaTraderMovementSpeedMin); -+ llamaTraderMovementSpeedMax = getDouble("mobs.trader_llama.attributes.movement_speed.max", llamaTraderMovementSpeedMax); - } - - public boolean magmaCubeRidable = false; - public boolean magmaCubeRidableInWater = false; -+ public String magmaCubeMaxHealth = "size * size"; - private void magmaCubeSettings() { - magmaCubeRidable = getBoolean("mobs.magma_cube.ridable", magmaCubeRidable); - magmaCubeRidableInWater = getBoolean("mobs.magma_cube.ridable-in-water", magmaCubeRidableInWater); -+ if (PurpurConfig.version < 10) { -+ String oldValue = getString("mobs.magma_cube.attributes.max-health", magmaCubeMaxHealth); -+ set("mobs.magma_cube.attributes.max-health", null); -+ set("mobs.magma_cube.attributes.max_health", oldValue); -+ } -+ magmaCubeMaxHealth = getString("mobs.magma_cube.attributes.max_health", magmaCubeMaxHealth); - } - - public boolean mooshroomRidable = false; - public boolean mooshroomRidableInWater = false; - public int mooshroomBreedingTicks = 6000; -+ public double mooshroomMaxHealth = 10.0D; - private void mooshroomSettings() { - mooshroomRidable = getBoolean("mobs.mooshroom.ridable", mooshroomRidable); - mooshroomRidableInWater = getBoolean("mobs.mooshroom.ridable-in-water", mooshroomRidableInWater); - mooshroomBreedingTicks = getInt("mobs.mooshroom.breeding-delay-ticks", mooshroomBreedingTicks); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.mooshroom.attributes.max-health", mooshroomMaxHealth); -+ set("mobs.mooshroom.attributes.max-health", null); -+ set("mobs.mooshroom.attributes.max_health", oldValue); -+ } -+ mooshroomMaxHealth = getDouble("mobs.mooshroom.attributes.max_health", mooshroomMaxHealth); - } - - public boolean muleRidableInWater = false; - public int muleBreedingTicks = 6000; -+ public double muleMaxHealthMin = 15.0D; -+ public double muleMaxHealthMax = 30.0D; -+ public double muleJumpStrengthMin = 0.5D; -+ public double muleJumpStrengthMax = 0.5D; -+ public double muleMovementSpeedMin = 0.175D; -+ public double muleMovementSpeedMax = 0.175D; - private void muleSettings() { - muleRidableInWater = getBoolean("mobs.mule.ridable-in-water", muleRidableInWater); - muleBreedingTicks = getInt("mobs.mule.breeding-delay-ticks", muleBreedingTicks); -+ if (PurpurConfig.version < 10) { -+ double oldMin = getDouble("mobs.mule.attributes.max-health.min", muleMaxHealthMin); -+ double oldMax = getDouble("mobs.mule.attributes.max-health.max", muleMaxHealthMax); -+ set("mobs.mule.attributes.max-health", null); -+ set("mobs.mule.attributes.max_health.min", oldMin); -+ set("mobs.mule.attributes.max_health.max", oldMax); -+ } -+ muleMaxHealthMin = getDouble("mobs.mule.attributes.max_health.min", muleMaxHealthMin); -+ muleMaxHealthMax = getDouble("mobs.mule.attributes.max_health.max", muleMaxHealthMax); -+ muleJumpStrengthMin = getDouble("mobs.mule.attributes.jump_strength.min", muleJumpStrengthMin); -+ muleJumpStrengthMax = getDouble("mobs.mule.attributes.jump_strength.max", muleJumpStrengthMax); -+ muleMovementSpeedMin = getDouble("mobs.mule.attributes.movement_speed.min", muleMovementSpeedMin); -+ muleMovementSpeedMax = getDouble("mobs.mule.attributes.movement_speed.max", muleMovementSpeedMax); - } - - public boolean ocelotRidable = false; - public boolean ocelotRidableInWater = false; - public int ocelotBreedingTicks = 6000; -+ public double ocelotMaxHealth = 10.0D; - private void ocelotSettings() { - ocelotRidable = getBoolean("mobs.ocelot.ridable", ocelotRidable); - ocelotRidableInWater = getBoolean("mobs.ocelot.ridable-in-water", ocelotRidableInWater); - ocelotBreedingTicks = getInt("mobs.ocelot.breeding-delay-ticks", ocelotBreedingTicks); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.ocelot.attributes.max-health", ocelotMaxHealth); -+ set("mobs.ocelot.attributes.max-health", null); -+ set("mobs.ocelot.attributes.max_health", oldValue); -+ } -+ ocelotMaxHealth = getDouble("mobs.ocelot.attributes.max_health", ocelotMaxHealth); - } - - public boolean pandaRidable = false; - public boolean pandaRidableInWater = false; - public int pandaBreedingTicks = 6000; -+ public double pandaMaxHealth = 20.0D; - private void pandaSettings() { - pandaRidable = getBoolean("mobs.panda.ridable", pandaRidable); - pandaRidableInWater = getBoolean("mobs.panda.ridable-in-water", pandaRidableInWater); - pandaBreedingTicks = getInt("mobs.panda.breeding-delay-ticks", pandaBreedingTicks); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.panda.attributes.max-health", pandaMaxHealth); -+ set("mobs.panda.attributes.max-health", null); -+ set("mobs.panda.attributes.max_health", oldValue); -+ } -+ pandaMaxHealth = getDouble("mobs.panda.attributes.max_health", pandaMaxHealth); - } - - public boolean parrotRidable = false; - public boolean parrotRidableInWater = false; - public double parrotMaxY = 256D; -+ public double parrotMaxHealth = 6.0D; - private void parrotSettings() { - parrotRidable = getBoolean("mobs.parrot.ridable", parrotRidable); - parrotRidableInWater = getBoolean("mobs.parrot.ridable-in-water", parrotRidableInWater); - parrotMaxY = getDouble("mobs.parrot.ridable-max-y", parrotMaxY); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.parrot.attributes.max-health", parrotMaxHealth); -+ set("mobs.parrot.attributes.max-health", null); -+ set("mobs.parrot.attributes.max_health", oldValue); -+ } -+ parrotMaxHealth = getDouble("mobs.parrot.attributes.max_health", parrotMaxHealth); - } - - public boolean phantomRidable = false; -@@ -899,6 +1206,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); -@@ -924,38 +1232,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); -+ set("mobs.phantom.attributes.max_health", oldValue); -+ } -+ phantomMaxHealth = getDouble("mobs.phantom.attributes.max_health", phantomMaxHealth); - } - - public boolean pigRidable = false; - public boolean pigRidableInWater = false; - public boolean pigGiveSaddleBack = false; - public int pigBreedingTicks = 6000; -+ public double pigMaxHealth = 10.0D; - private void pigSettings() { - pigRidable = getBoolean("mobs.pig.ridable", pigRidable); - pigRidableInWater = getBoolean("mobs.pig.ridable-in-water", pigRidableInWater); - pigGiveSaddleBack = getBoolean("mobs.pig.give-saddle-back", pigGiveSaddleBack); - pigBreedingTicks = getInt("mobs.pig.breeding-delay-ticks", pigBreedingTicks); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.pig.attributes.max-health", pigMaxHealth); -+ set("mobs.pig.attributes.max-health", null); -+ set("mobs.pig.attributes.max_health", oldValue); -+ } -+ pigMaxHealth = getDouble("mobs.pig.attributes.max_health", pigMaxHealth); - } - - public boolean piglinRidable = false; - public boolean piglinRidableInWater = false; -+ public double piglinMaxHealth = 16.0D; - private void piglinSettings() { - piglinRidable = getBoolean("mobs.piglin.ridable", piglinRidable); - piglinRidableInWater = getBoolean("mobs.piglin.ridable-in-water", piglinRidableInWater); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.piglin.attributes.max-health", piglinMaxHealth); -+ set("mobs.piglin.attributes.max-health", null); -+ set("mobs.piglin.attributes.max_health", oldValue); -+ } -+ piglinMaxHealth = getDouble("mobs.piglin.attributes.max_health", piglinMaxHealth); - } - - public boolean piglinBruteRidable = false; - public boolean piglinBruteRidableInWater = false; -+ public double piglinBruteMaxHealth = 50.0D; - private void piglinBruteSettings() { - piglinBruteRidable = getBoolean("mobs.piglin_brute.ridable", piglinBruteRidable); - piglinBruteRidableInWater = getBoolean("mobs.piglin_brute.ridable-in-water", piglinBruteRidableInWater); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.piglin_brute.attributes.max-health", piglinBruteMaxHealth); -+ set("mobs.piglin_brute.attributes.max-health", null); -+ set("mobs.piglin_brute.attributes.max_health", oldValue); -+ } -+ piglinBruteMaxHealth = getDouble("mobs.piglin_brute.attributes.max_health", piglinBruteMaxHealth); - } - - public boolean pillagerRidable = false; - public boolean pillagerRidableInWater = false; -+ public double pillagerMaxHealth = 24.0D; - private void pillagerSettings() { - pillagerRidable = getBoolean("mobs.pillager.ridable", pillagerRidable); - pillagerRidableInWater = getBoolean("mobs.pillager.ridable-in-water", pillagerRidableInWater); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.pillager.attributes.max-health", pillagerMaxHealth); -+ set("mobs.pillager.attributes.max-health", null); -+ set("mobs.pillager.attributes.max_health", oldValue); -+ } -+ pillagerMaxHealth = getDouble("mobs.pillager.attributes.max_health", pillagerMaxHealth); - } - - public boolean polarBearRidable = false; -@@ -963,6 +1305,7 @@ public class PurpurWorldConfig { - public String polarBearBreedableItemString = ""; - public Item polarBearBreedableItem = null; - public int polarBearBreedingTicks = 6000; -+ public double polarBearMaxHealth = 30.0D; - private void polarBearSettings() { - polarBearRidable = getBoolean("mobs.polar_bear.ridable", polarBearRidable); - polarBearRidableInWater = getBoolean("mobs.polar_bear.ridable-in-water", polarBearRidableInWater); -@@ -970,11 +1313,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); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.polar_bear.attributes.max-health", polarBearMaxHealth); -+ set("mobs.polar_bear.attributes.max-health", null); -+ set("mobs.polar_bear.attributes.max_health", oldValue); -+ } -+ polarBearMaxHealth = getDouble("mobs.polar_bear.attributes.max_health", polarBearMaxHealth); - } - - public boolean pufferfishRidable = false; -+ public double pufferfishMaxHealth = 3.0D; - private void pufferfishSettings() { - pufferfishRidable = getBoolean("mobs.pufferfish.ridable", pufferfishRidable); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.pufferfish.attributes.max-health", pufferfishMaxHealth); -+ set("mobs.pufferfish.attributes.max-health", null); -+ set("mobs.pufferfish.attributes.max_health", oldValue); -+ } -+ pufferfishMaxHealth = getDouble("mobs.pufferfish.attributes.max_health", pufferfishMaxHealth); - } - - public boolean rabbitRidable = false; -@@ -982,68 +1338,144 @@ public class PurpurWorldConfig { - public double rabbitNaturalToast = 0.0D; - public double rabbitNaturalKiller = 0.0D; - public int rabbitBreedingTicks = 6000; -+ public double rabbitMaxHealth = 3.0D; - private void rabbitSettings() { - rabbitRidable = getBoolean("mobs.rabbit.ridable", rabbitRidable); - rabbitRidableInWater = getBoolean("mobs.rabbit.ridable-in-water", rabbitRidableInWater); - 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); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.rabbit.attributes.max-health", rabbitMaxHealth); -+ set("mobs.rabbit.attributes.max-health", null); -+ set("mobs.rabbit.attributes.max_health", oldValue); -+ } -+ rabbitMaxHealth = getDouble("mobs.rabbit.attributes.max_health", rabbitMaxHealth); - } - - public boolean ravagerRidable = false; - public boolean ravagerRidableInWater = false; -+ public double ravagerMaxHealth = 100.0D; - private void ravagerSettings() { - ravagerRidable = getBoolean("mobs.ravager.ridable", ravagerRidable); - ravagerRidableInWater = getBoolean("mobs.ravager.ridable-in-water", ravagerRidableInWater); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.ravager.attributes.max-health", ravagerMaxHealth); -+ set("mobs.ravager.attributes.max-health", null); -+ set("mobs.ravager.attributes.max_health", oldValue); -+ } -+ ravagerMaxHealth = getDouble("mobs.ravager.attributes.max_health", ravagerMaxHealth); - } - - public boolean salmonRidable = false; -+ public double salmonMaxHealth = 3.0D; - private void salmonSettings() { - salmonRidable = getBoolean("mobs.salmon.ridable", salmonRidable); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.salmon.attributes.max-health", salmonMaxHealth); -+ set("mobs.salmon.attributes.max-health", null); -+ set("mobs.salmon.attributes.max_health", oldValue); -+ } -+ salmonMaxHealth = getDouble("mobs.salmon.attributes.max_health", salmonMaxHealth); - } - - public boolean sheepRidable = false; - public boolean sheepRidableInWater = false; - public int sheepBreedingTicks = 6000; -+ public double sheepMaxHealth = 8.0D; - private void sheepSettings() { - sheepRidable = getBoolean("mobs.sheep.ridable", sheepRidable); - sheepRidableInWater = getBoolean("mobs.sheep.ridable-in-water", sheepRidableInWater); - sheepBreedingTicks = getInt("mobs.sheep.breeding-delay-ticks", sheepBreedingTicks); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.sheep.attributes.max-health", sheepMaxHealth); -+ set("mobs.sheep.attributes.max-health", null); -+ set("mobs.sheep.attributes.max_health", oldValue); -+ } -+ sheepMaxHealth = getDouble("mobs.sheep.attributes.max_health", sheepMaxHealth); - } - - public boolean shulkerRidable = false; - public boolean shulkerRidableInWater = false; -+ public double shulkerMaxHealth = 30.0D; - private void shulkerSettings() { - shulkerRidable = getBoolean("mobs.shulker.ridable", shulkerRidable); - shulkerRidableInWater = getBoolean("mobs.shulker.ridable-in-water", shulkerRidableInWater); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.shulker.attributes.max-health", shulkerMaxHealth); -+ set("mobs.shulker.attributes.max-health", null); -+ set("mobs.shulker.attributes.max_health", oldValue); -+ } -+ shulkerMaxHealth = getDouble("mobs.shulker.attributes.max_health", shulkerMaxHealth); - } - - public boolean silverfishRidable = false; - public boolean silverfishRidableInWater = false; -+ public double silverfishMaxHealth = 8.0D; - private void silverfishSettings() { - silverfishRidable = getBoolean("mobs.silverfish.ridable", silverfishRidable); - silverfishRidableInWater = getBoolean("mobs.silverfish.ridable-in-water", silverfishRidableInWater); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.silverfish.attributes.max-health", silverfishMaxHealth); -+ set("mobs.silverfish.attributes.max-health", null); -+ set("mobs.silverfish.attributes.max_health", oldValue); -+ } -+ silverfishMaxHealth = getDouble("mobs.silverfish.attributes.max_health", silverfishMaxHealth); - } - - public boolean skeletonRidable = false; - public boolean skeletonRidableInWater = false; -+ public double skeletonMaxHealth = 20.0D; - private void skeletonSettings() { - skeletonRidable = getBoolean("mobs.skeleton.ridable", skeletonRidable); - skeletonRidableInWater = getBoolean("mobs.skeleton.ridable-in-water", skeletonRidableInWater); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.skeleton.attributes.max-health", skeletonMaxHealth); -+ set("mobs.skeleton.attributes.max-health", null); -+ set("mobs.skeleton.attributes.max_health", oldValue); -+ } -+ skeletonMaxHealth = getDouble("mobs.skeleton.attributes.max_health", skeletonMaxHealth); - } - - public boolean skeletonHorseCanSwim = false; - public boolean skeletonHorseRidableInWater = true; -+ public double skeletonHorseMaxHealthMin = 15.0D; -+ public double skeletonHorseMaxHealthMax = 15.0D; -+ public double skeletonHorseJumpStrengthMin = 0.4D; -+ public double skeletonHorseJumpStrengthMax = 1.0D; -+ public double skeletonHorseMovementSpeedMin = 0.2D; -+ public double skeletonHorseMovementSpeedMax = 0.2D; - private void skeletonHorseSettings() { - skeletonHorseCanSwim = getBoolean("mobs.skeleton_horse.can-swim", skeletonHorseCanSwim); - skeletonHorseRidableInWater = getBoolean("mobs.skeleton_horse.ridable-in-water", skeletonHorseRidableInWater); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.skeleton_horse.attributes.max-health", skeletonHorseMaxHealthMin); -+ set("mobs.skeleton_horse.attributes.max-health", null); -+ set("mobs.skeleton_horse.attributes.max_health.min", oldValue); -+ set("mobs.skeleton_horse.attributes.max_health.max", oldValue); -+ } -+ skeletonHorseMaxHealthMin = getDouble("mobs.skeleton_horse.attributes.max_health.min", skeletonHorseMaxHealthMin); -+ skeletonHorseMaxHealthMax = getDouble("mobs.skeleton_horse.attributes.max_health.max", skeletonHorseMaxHealthMax); -+ skeletonHorseJumpStrengthMin = getDouble("mobs.skeleton_horse.attributes.jump_strength.min", skeletonHorseJumpStrengthMin); -+ skeletonHorseJumpStrengthMax = getDouble("mobs.skeleton_horse.attributes.jump_strength.max", skeletonHorseJumpStrengthMax); -+ skeletonHorseMovementSpeedMin = getDouble("mobs.skeleton_horse.attributes.movement_speed.min", skeletonHorseMovementSpeedMin); -+ skeletonHorseMovementSpeedMax = getDouble("mobs.skeleton_horse.attributes.movement_speed.max", skeletonHorseMovementSpeedMax); - } - - public boolean slimeRidable = false; - public boolean slimeRidableInWater = false; -+ public String slimeMaxHealth = "size * size"; -+ public Map slimeMaxHealthCache = new HashMap<>(); - private void slimeSettings() { - slimeRidable = getBoolean("mobs.slime.ridable", slimeRidable); - slimeRidableInWater = getBoolean("mobs.slime.ridable-in-water", slimeRidableInWater); -+ if (PurpurConfig.version < 10) { -+ String oldValue = getString("mobs.slime.attributes.max-health", slimeMaxHealth); -+ set("mobs.slime.attributes.max-health", null); -+ set("mobs.slime.attributes.max_health", oldValue); -+ } -+ slimeMaxHealth = getString("mobs.slime.attributes.max_health", slimeMaxHealth); -+ slimeMaxHealthCache.clear(); - } - - public boolean snowGolemRidable = false; -@@ -1055,6 +1487,7 @@ public class PurpurWorldConfig { - public int snowGolemSnowBallMax = 20; - public float snowGolemSnowBallModifier = 10.0F; - public double snowGolemAttackDistance = 1.25D; -+ public double snowGolemMaxHealth = 4.0D; - private void snowGolemSettings() { - snowGolemRidable = getBoolean("mobs.snow_golem.ridable", snowGolemRidable); - snowGolemRidableInWater = getBoolean("mobs.snow_golem.ridable-in-water", snowGolemRidableInWater); -@@ -1065,63 +1498,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); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.snow_golem.attributes.max-health", snowGolemMaxHealth); -+ set("mobs.snow_golem.attributes.max-health", null); -+ set("mobs.snow_golem.attributes.max_health", oldValue); -+ } -+ snowGolemMaxHealth = getDouble("mobs.snow_golem.attributes.max_health", snowGolemMaxHealth); - } - - public boolean squidRidable = false; - public boolean squidImmuneToEAR = true; - public double squidOffsetWaterCheck = 0.0D; - public boolean squidsCanFly = false; -+ public double squidMaxHealth = 10.0D; - private void squidSettings() { - squidRidable = getBoolean("mobs.squid.ridable", squidRidable); - squidImmuneToEAR = getBoolean("mobs.squid.immune-to-EAR", squidImmuneToEAR); - squidOffsetWaterCheck = getDouble("mobs.squid.water-offset-check", squidOffsetWaterCheck); - squidsCanFly = getBoolean("mobs.squid.can-fly", squidsCanFly); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.squid.attributes.max-health", squidMaxHealth); -+ set("mobs.squid.attributes.max-health", null); -+ set("mobs.squid.attributes.max_health", oldValue); -+ } -+ squidMaxHealth = getDouble("mobs.squid.attributes.max_health", squidMaxHealth); - } - - public boolean spiderRidable = false; - public boolean spiderRidableInWater = false; -+ public double spiderMaxHealth = 16.0D; - private void spiderSettings() { - spiderRidable = getBoolean("mobs.spider.ridable", spiderRidable); - spiderRidableInWater = getBoolean("mobs.spider.ridable-in-water", spiderRidableInWater); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.spider.attributes.max-health", spiderMaxHealth); -+ set("mobs.spider.attributes.max-health", null); -+ set("mobs.spider.attributes.max_health", oldValue); -+ } -+ spiderMaxHealth = getDouble("mobs.spider.attributes.max_health", spiderMaxHealth); - } - - public boolean strayRidable = false; - public boolean strayRidableInWater = false; -+ public double strayMaxHealth = 20.0D; - private void straySettings() { - strayRidable = getBoolean("mobs.stray.ridable", strayRidable); - strayRidableInWater = getBoolean("mobs.stray.ridable-in-water", strayRidableInWater); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.stray.attributes.max-health", strayMaxHealth); -+ set("mobs.stray.attributes.max-health", null); -+ set("mobs.stray.attributes.max_health", oldValue); -+ } -+ strayMaxHealth = getDouble("mobs.stray.attributes.max_health", strayMaxHealth); - } - - public boolean striderRidable = false; - public boolean striderRidableInWater = false; - public int striderBreedingTicks = 6000; -+ public double striderMaxHealth = 20.0D; - private void striderSettings() { - striderRidable = getBoolean("mobs.strider.ridable", striderRidable); - striderRidableInWater = getBoolean("mobs.strider.ridable-in-water", striderRidableInWater); - striderBreedingTicks = getInt("mobs.strider.breeding-delay-ticks", striderBreedingTicks); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.strider.attributes.max-health", striderMaxHealth); -+ set("mobs.strider.attributes.max-health", null); -+ set("mobs.strider.attributes.max_health", oldValue); -+ } -+ striderMaxHealth = getDouble("mobs.strider.attributes.max_health", striderMaxHealth); - } - - public boolean tropicalFishRidable = false; -+ public double tropicalFishMaxHealth = 3.0D; - private void tropicalFishSettings() { - tropicalFishRidable = getBoolean("mobs.tropical_fish.ridable", tropicalFishRidable); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.tropical_fish.attributes.max-health", tropicalFishMaxHealth); -+ set("mobs.tropical_fish.attributes.max-health", null); -+ set("mobs.tropical_fish.attributes.max_health", oldValue); -+ } -+ tropicalFishMaxHealth = getDouble("mobs.tropical_fish.attributes.max_health", tropicalFishMaxHealth); - } - - public boolean turtleRidable = false; - public boolean turtleRidableInWater = false; - public int turtleBreedingTicks = 6000; -+ public double turtleMaxHealth = 30.0D; - private void turtleSettings() { - turtleRidable = getBoolean("mobs.turtle.ridable", turtleRidable); - turtleRidableInWater = getBoolean("mobs.turtle.ridable-in-water", turtleRidableInWater); - turtleBreedingTicks = getInt("mobs.turtle.breeding-delay-ticks", turtleBreedingTicks); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.turtle.attributes.max-health", turtleMaxHealth); -+ set("mobs.turtle.attributes.max-health", null); -+ set("mobs.turtle.attributes.max_health", oldValue); -+ } -+ turtleMaxHealth = getDouble("mobs.turtle.attributes.max_health", turtleMaxHealth); - } - - public boolean vexRidable = false; - public boolean vexRidableInWater = false; - public double vexMaxY = 256D; -+ public double vexMaxHealth = 14.0D; - private void vexSettings() { - vexRidable = getBoolean("mobs.vex.ridable", vexRidable); - vexRidableInWater = getBoolean("mobs.vex.ridable-in-water", vexRidableInWater); - vexMaxY = getDouble("mobs.vex.ridable-max-y", vexMaxY); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.vex.attributes.max-health", vexMaxHealth); -+ set("mobs.vex.attributes.max-health", null); -+ set("mobs.vex.attributes.max_health", oldValue); -+ } -+ vexMaxHealth = getDouble("mobs.vex.attributes.max_health", vexMaxHealth); - } - - public boolean villagerRidable = false; -@@ -1139,6 +1627,7 @@ public class PurpurWorldConfig { - public int villagerLobotomizeCheck = 60; - public boolean villagerClericsFarmWarts = false; - public boolean villagerClericFarmersThrowWarts = true; -+ public double villagerMaxHealth = 20.0D; - private void villagerSettings() { - villagerRidable = getBoolean("mobs.villager.ridable", villagerRidable); - villagerRidableInWater = getBoolean("mobs.villager.ridable-in-water", villagerRidableInWater); -@@ -1160,33 +1649,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); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.villager.attributes.max-health", villagerMaxHealth); -+ set("mobs.villager.attributes.max-health", null); -+ set("mobs.villager.attributes.max_health", oldValue); -+ } -+ villagerMaxHealth = getDouble("mobs.villager.attributes.max_health", villagerMaxHealth); - } - - public boolean villagerTraderRidable = false; - public boolean villagerTraderRidableInWater = false; - public boolean villagerTraderCanBeLeashed = false; - public boolean villagerTraderFollowEmeraldBlock = false; -+ public double villagerTraderMaxHealth = 20.0D; - private void villagerTraderSettings() { - villagerTraderRidable = getBoolean("mobs.wandering_trader.ridable", villagerTraderRidable); - villagerTraderRidableInWater = getBoolean("mobs.wandering_trader.ridable-in-water", villagerTraderRidableInWater); - villagerTraderCanBeLeashed = getBoolean("mobs.wandering_trader.can-be-leashed", villagerTraderCanBeLeashed); - villagerTraderFollowEmeraldBlock = getBoolean("mobs.wandering_trader.follow-emerald-blocks", villagerTraderFollowEmeraldBlock); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.wandering_trader.attributes.max-health", villagerTraderMaxHealth); -+ set("mobs.wandering_trader.attributes.max-health", null); -+ set("mobs.wandering_trader.attributes.max_health", oldValue); -+ } -+ villagerTraderMaxHealth = getDouble("mobs.wandering_trader.attributes.max_health", villagerTraderMaxHealth); - } - - public boolean vindicatorRidable = false; - public boolean vindicatorRidableInWater = false; - public double vindicatorJohnnySpawnChance = 0D; -+ public double vindicatorMaxHealth = 24.0D; - private void vindicatorSettings() { - vindicatorRidable = getBoolean("mobs.vindicator.ridable", vindicatorRidable); - vindicatorRidableInWater = getBoolean("mobs.vindicator.ridable-in-water", vindicatorRidableInWater); - vindicatorJohnnySpawnChance = getDouble("mobs.vindicator.johnny.spawn-chance", vindicatorJohnnySpawnChance); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.vindicator.attributes.max-health", vindicatorMaxHealth); -+ set("mobs.vindicator.attributes.max-health", null); -+ set("mobs.vindicator.attributes.max_health", oldValue); -+ } -+ vindicatorMaxHealth = getDouble("mobs.vindicator.attributes.max_health", vindicatorMaxHealth); - } - - public boolean witchRidable = false; - public boolean witchRidableInWater = false; -+ public double witchMaxHealth = 26.0D; - private void witchSettings() { - witchRidable = getBoolean("mobs.witch.ridable", witchRidable); - witchRidableInWater = getBoolean("mobs.witch.ridable-in-water", witchRidableInWater); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.witch.attributes.max-health", witchMaxHealth); -+ set("mobs.witch.attributes.max-health", null); -+ set("mobs.witch.attributes.max_health", oldValue); -+ } -+ witchMaxHealth = getDouble("mobs.witch.attributes.max_health", witchMaxHealth); - } - - public boolean witherRidable = false; -@@ -1203,19 +1719,30 @@ public class PurpurWorldConfig { - witherHealthRegenDelay = getInt("mobs.wither.health-regen-delay", witherHealthRegenDelay); - if (PurpurConfig.version < 8) { - double oldValue = getDouble("mobs.wither.max-health", witherMaxHealth); -+ set("mobs.wither.max_health", null); - set("mobs.wither.attributes.max-health", oldValue); -- set("mobs.wither.max-health", null); -+ } else if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.wither.attributes.max-health", witherMaxHealth); -+ set("mobs.wither.attributes.max-health", null); -+ set("mobs.wither.attributes.max_health", oldValue); - } -- witherMaxHealth = getDouble("mobs.wither.attributes.max-health", witherMaxHealth); -+ witherMaxHealth = getDouble("mobs.wither.attributes.max_health", witherMaxHealth); - } - - public boolean witherSkeletonRidable = false; - public boolean witherSkeletonRidableInWater = false; - public boolean witherSkeletonTakesWitherDamage = false; -+ public double witherSkeletonMaxHealth = 20.0D; - private void witherSkeletonSettings() { - witherSkeletonRidable = getBoolean("mobs.wither_skeleton.ridable", witherSkeletonRidable); - witherSkeletonRidableInWater = getBoolean("mobs.wither_skeleton.ridable-in-water", witherSkeletonRidableInWater); - witherSkeletonTakesWitherDamage = getBoolean("mobs.wither_skeleton.takes-wither-damage", witherSkeletonTakesWitherDamage); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.wither_skeleton.attributes.max-health", witherSkeletonMaxHealth); -+ set("mobs.wither_skeleton.attributes.max-health", null); -+ set("mobs.wither_skeleton.attributes.max_health", oldValue); -+ } -+ witherSkeletonMaxHealth = getDouble("mobs.wither_skeleton.attributes.max_health", witherSkeletonMaxHealth); - } - - public boolean wolfRidable = false; -@@ -1224,6 +1751,7 @@ public class PurpurWorldConfig { - public boolean wolfMilkCuresRabies = true; - public double wolfNaturalRabid = 0.0D; - public int wolfBreedingTicks = 6000; -+ public double wolfMaxHealth = 8.0D; - private void wolfSettings() { - wolfRidable = getBoolean("mobs.wolf.ridable", wolfRidable); - wolfRidableInWater = getBoolean("mobs.wolf.ridable-in-water", wolfRidableInWater); -@@ -1235,13 +1763,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); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.wolf.attributes.max-health", wolfMaxHealth); -+ set("mobs.wolf.attributes.max-health", null); -+ set("mobs.wolf.attributes.max_health", oldValue); -+ } -+ wolfMaxHealth = getDouble("mobs.wolf.attributes.max_health", wolfMaxHealth); - } - - public boolean zoglinRidable = false; - public boolean zoglinRidableInWater = false; -+ public double zoglinMaxHealth = 40.0D; - private void zoglinSettings() { - zoglinRidable = getBoolean("mobs.zoglin.ridable", zoglinRidable); - zoglinRidableInWater = getBoolean("mobs.zoglin.ridable-in-water", zoglinRidableInWater); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.zoglin.attributes.max-health", zoglinMaxHealth); -+ set("mobs.zoglin.attributes.max-health", null); -+ set("mobs.zoglin.attributes.max_health", oldValue); -+ } -+ zoglinMaxHealth = getDouble("mobs.zoglin.attributes.max_health", zoglinMaxHealth); - } - - public boolean zombieRidable = false; -@@ -1251,6 +1792,8 @@ public class PurpurWorldConfig { - public boolean zombieJockeyTryExistingChickens = true; - public boolean zombieAggressiveTowardsVillagerWhenLagging = true; - public EnumDifficulty zombieBreakDoorMinDifficulty = EnumDifficulty.HARD; -+ public double zombieMaxHealth = 20.0D; -+ public double zombieSpawnReinforcements = 0.1D; - private void zombieSettings() { - zombieRidable = getBoolean("mobs.zombie.ridable", zombieRidable); - zombieRidableInWater = getBoolean("mobs.zombie.ridable-in-water", zombieRidableInWater); -@@ -1263,15 +1806,40 @@ public class PurpurWorldConfig { - } catch (IllegalArgumentException ignore) { - zombieBreakDoorMinDifficulty = EnumDifficulty.HARD; - } -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.zombie.attributes.max-health", zombieMaxHealth); -+ set("mobs.zombie.attributes.max-health", null); -+ set("mobs.zombie.attributes.max_health", oldValue); -+ } -+ zombieMaxHealth = getDouble("mobs.zombie.attributes.max_health", zombieMaxHealth); -+ zombieSpawnReinforcements = getDouble("mobs.zombie.attributes.spawn_reinforcements", zombieSpawnReinforcements); - } - - public boolean zombieHorseCanSwim = false; - public boolean zombieHorseRidableInWater = false; - public double zombieHorseSpawnChance = 0.0D; -+ public double zombieHorseMaxHealthMin = 15.0D; -+ public double zombieHorseMaxHealthMax = 15.0D; -+ public double zombieHorseJumpStrengthMin = 0.4D; -+ public double zombieHorseJumpStrengthMax = 1.0D; -+ public double zombieHorseMovementSpeedMin = 0.2D; -+ public double zombieHorseMovementSpeedMax = 0.2D; - private void zombieHorseSettings() { - zombieHorseCanSwim = getBoolean("mobs.zombie_horse.can-swim", zombieHorseCanSwim); - zombieHorseRidableInWater = getBoolean("mobs.zombie_horse.ridable-in-water", zombieHorseRidableInWater); - zombieHorseSpawnChance = getDouble("mobs.zombie_horse.spawn-chance", zombieHorseSpawnChance); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.zombie_horse.attributes.max-health", zombieHorseMaxHealthMin); -+ set("mobs.zombie_horse.attributes.max-health", null); -+ set("mobs.zombie_horse.attributes.max_health.min", oldValue); -+ set("mobs.zombie_horse.attributes.max_health.max", oldValue); -+ } -+ zombieHorseMaxHealthMin = getDouble("mobs.zombie_horse.attributes.max_health.min", zombieHorseMaxHealthMin); -+ zombieHorseMaxHealthMax = getDouble("mobs.zombie_horse.attributes.max_health.max", zombieHorseMaxHealthMax); -+ zombieHorseJumpStrengthMin = getDouble("mobs.zombie_horse.attributes.jump_strength.min", zombieHorseJumpStrengthMin); -+ zombieHorseJumpStrengthMax = getDouble("mobs.zombie_horse.attributes.jump_strength.max", zombieHorseJumpStrengthMax); -+ zombieHorseMovementSpeedMin = getDouble("mobs.zombie_horse.attributes.movement_speed.min", zombieHorseMovementSpeedMin); -+ zombieHorseMovementSpeedMax = getDouble("mobs.zombie_horse.attributes.movement_speed.max", zombieHorseMovementSpeedMax); - } - - public boolean zombifiedPiglinRidable = false; -@@ -1280,6 +1848,8 @@ public class PurpurWorldConfig { - public double zombifiedPiglinJockeyChance = 0.05D; - public boolean zombifiedPiglinJockeyTryExistingChickens = true; - public boolean zombifiedPiglinCountAsPlayerKillWhenAngry = true; -+ public double zombifiedPiglinMaxHealth = 20.0D; -+ public double zombifiedPiglinSpawnReinforcements = 0.0D; - private void zombifiedPiglinSettings() { - zombifiedPiglinRidable = getBoolean("mobs.zombified_piglin.ridable", zombifiedPiglinRidable); - zombifiedPiglinRidableInWater = getBoolean("mobs.zombified_piglin.ridable-in-water", zombifiedPiglinRidableInWater); -@@ -1287,6 +1857,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); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.zombified_piglin.attributes.max-health", zombifiedPiglinMaxHealth); -+ set("mobs.zombified_piglin.attributes.max-health", null); -+ set("mobs.zombified_piglin.attributes.max_health", oldValue); -+ } -+ zombifiedPiglinMaxHealth = getDouble("mobs.zombified_piglin.attributes.max_health", zombifiedPiglinMaxHealth); -+ zombifiedPiglinSpawnReinforcements = getDouble("mobs.zombified_piglin.attributes.spawn_reinforcements", zombifiedPiglinSpawnReinforcements); - } - - public boolean zombieVillagerRidable = false; -@@ -1294,11 +1871,20 @@ public class PurpurWorldConfig { - public boolean zombieVillagerJockeyOnlyBaby = true; - public double zombieVillagerJockeyChance = 0.05D; - public boolean zombieVillagerJockeyTryExistingChickens = true; -+ public double zombieVillagerMaxHealth = 20.0D; -+ public double zombieVillagerSpawnReinforcements = 0.1D; - private void zombieVillagerSettings() { - zombieVillagerRidable = getBoolean("mobs.zombie_villager.ridable", zombieVillagerRidable); - zombieVillagerRidableInWater = getBoolean("mobs.zombie_villager.ridable-in-water", zombieVillagerRidableInWater); - zombieVillagerJockeyOnlyBaby = getBoolean("mobs.zombie_villager.jockey.only-babies", zombieVillagerJockeyOnlyBaby); - zombieVillagerJockeyChance = getDouble("mobs.zombie_villager.jockey.chance", zombieVillagerJockeyChance); - zombieVillagerJockeyTryExistingChickens = getBoolean("mobs.zombie_villager.jockey.try-existing-chickens", zombieVillagerJockeyTryExistingChickens); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.zombie_villager.attributes.max-health", zombieVillagerMaxHealth); -+ set("mobs.zombie_villager.attributes.max-health", null); -+ set("mobs.zombie_villager.attributes.max_health", oldValue); -+ } -+ zombieVillagerMaxHealth = getDouble("mobs.zombie_villager.attributes.max_health", zombieVillagerMaxHealth); -+ zombieVillagerSpawnReinforcements = getDouble("mobs.zombie_villager.attributes.spawn_reinforcements", zombieVillagerSpawnReinforcements); - } - } diff --git a/patches/server-unmapped/0134-Changeable-Mob-Left-Handed-Chance.patch b/patches/server-unmapped/0134-Changeable-Mob-Left-Handed-Chance.patch deleted file mode 100644 index 89d26117b..000000000 --- a/patches/server-unmapped/0134-Changeable-Mob-Left-Handed-Chance.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ben Kerllenevich -Date: Mon, 30 Nov 2020 11:40:11 -0500 -Subject: [PATCH] Changeable Mob Left Handed Chance - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index b26b6cf0a1a5b3d0c636cdd734437ed19642ea98..9f6c98a8649b31ef8f5f2e60b1cb2f9f62f70930 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -1202,7 +1202,7 @@ public abstract class EntityInsentient extends EntityLiving { - @Nullable - public GroupDataEntity prepare(WorldAccess worldaccess, DifficultyDamageScaler difficultydamagescaler, EnumMobSpawn enummobspawn, @Nullable GroupDataEntity groupdataentity, @Nullable NBTTagCompound nbttagcompound) { - this.getAttributeInstance(GenericAttributes.FOLLOW_RANGE).addModifier(new AttributeModifier("Random spawn bonus", this.random.nextGaussian() * 0.05D, AttributeModifier.Operation.MULTIPLY_BASE)); -- if (this.random.nextFloat() < 0.05F) { -+ if (this.random.nextFloat() < this.world.purpurConfig.entityLeftHandedChance) { // Purpur - this.setLeftHanded(true); - } 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 1ea011a2fbf6b6d2b7f9ff59e86303d17d130831..5e3b23d50b6e8494066c71bdf7c14edc4a4a3716 100644 ---- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -163,8 +163,10 @@ public class PurpurWorldConfig { - } - - public int entityLifeSpan = 0; -+ public float entityLeftHandedChance = 0.05f; - private void entitySettings() { - entityLifeSpan = getInt("gameplay-mechanics.entity-lifespan", entityLifeSpan); -+ entityLeftHandedChance = (float) getDouble("gameplay-mechanics.entity-left-handed-chance", entityLeftHandedChance); - } - - public List itemImmuneToCactus = new ArrayList<>(); diff --git a/patches/server-unmapped/0141-Lobotomize-stuck-villagers.patch b/patches/server-unmapped/0141-Lobotomize-stuck-villagers.patch index 238248e74..e859261ff 100644 --- a/patches/server-unmapped/0141-Lobotomize-stuck-villagers.patch +++ b/patches/server-unmapped/0141-Lobotomize-stuck-villagers.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Thu, 3 Dec 2020 17:56:18 -0600 Subject: [PATCH] Lobotomize stuck villagers diff --git a/patches/server-unmapped/0148-Phantom-flames-on-swoop.patch b/patches/server-unmapped/0148-Phantom-flames-on-swoop.patch index 574a9b309..59eb0bbb0 100644 --- a/patches/server-unmapped/0148-Phantom-flames-on-swoop.patch +++ b/patches/server-unmapped/0148-Phantom-flames-on-swoop.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Sat, 12 Dec 2020 09:10:59 -0600 Subject: [PATCH] Phantom flames on swoop diff --git a/patches/server-unmapped/0150-Implement-TPSBar.patch b/patches/server-unmapped/0150-Implement-TPSBar.patch index c65db8a13..f419817ec 100644 --- a/patches/server-unmapped/0150-Implement-TPSBar.patch +++ b/patches/server-unmapped/0150-Implement-TPSBar.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Sat, 12 Dec 2020 21:19:05 -0600 Subject: [PATCH] Implement TPSBar diff --git a/patches/server-unmapped/0152-PlayerBookTooLargeEvent.patch b/patches/server-unmapped/0152-PlayerBookTooLargeEvent.patch index 23328a408..e79c69c48 100644 --- a/patches/server-unmapped/0152-PlayerBookTooLargeEvent.patch +++ b/patches/server-unmapped/0152-PlayerBookTooLargeEvent.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Wed, 23 Dec 2020 00:43:59 -0600 Subject: [PATCH] PlayerBookTooLargeEvent diff --git a/patches/server-unmapped/0153-Full-netherite-armor-grants-fire-resistance.patch b/patches/server-unmapped/0153-Full-netherite-armor-grants-fire-resistance.patch index 470b13c6e..f3970392c 100644 --- a/patches/server-unmapped/0153-Full-netherite-armor-grants-fire-resistance.patch +++ b/patches/server-unmapped/0153-Full-netherite-armor-grants-fire-resistance.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Thu, 24 Dec 2020 11:00:15 -0600 Subject: [PATCH] Full netherite armor grants fire resistance diff --git a/patches/server-unmapped/0154-Fix-rotating-UP-DOWN-CW-and-CCW.patch b/patches/server-unmapped/0154-Fix-rotating-UP-DOWN-CW-and-CCW.patch index e4f7831b1..49c417f48 100644 --- a/patches/server-unmapped/0154-Fix-rotating-UP-DOWN-CW-and-CCW.patch +++ b/patches/server-unmapped/0154-Fix-rotating-UP-DOWN-CW-and-CCW.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Wed, 6 Jan 2021 02:19:29 -0600 Subject: [PATCH] Fix rotating UP/DOWN CW and CCW diff --git a/patches/server-unmapped/0155-Add-MC-4-fix-back.patch b/patches/server-unmapped/0155-Add-MC-4-fix-back.patch index 67b8cacf8..1aeb516d6 100644 --- a/patches/server-unmapped/0155-Add-MC-4-fix-back.patch +++ b/patches/server-unmapped/0155-Add-MC-4-fix-back.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Thu, 7 Jan 2021 07:51:25 -0600 Subject: [PATCH] Add MC-4 fix back diff --git a/patches/server-unmapped/0162-Fix-stuck-in-portals.patch b/patches/server-unmapped/0162-Fix-stuck-in-portals.patch index dac7f5367..8e07d4ee0 100644 --- a/patches/server-unmapped/0162-Fix-stuck-in-portals.patch +++ b/patches/server-unmapped/0162-Fix-stuck-in-portals.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Thu, 14 Jan 2021 16:48:10 -0600 Subject: [PATCH] Fix stuck in portals diff --git a/patches/server-unmapped/0168-Add-ghast-allow-griefing-option.patch b/patches/server-unmapped/0168-Add-ghast-allow-griefing-option.patch index fc94c688b..6ccfac862 100644 --- a/patches/server-unmapped/0168-Add-ghast-allow-griefing-option.patch +++ b/patches/server-unmapped/0168-Add-ghast-allow-griefing-option.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Sat, 13 Feb 2021 14:02:43 -0600 Subject: [PATCH] Add ghast allow-griefing option diff --git a/patches/server-unmapped/0172-Add-config-for-snow-on-blue-ice.patch b/patches/server-unmapped/0172-Add-config-for-snow-on-blue-ice.patch index 45beedc6b..bb5613af1 100644 --- a/patches/server-unmapped/0172-Add-config-for-snow-on-blue-ice.patch +++ b/patches/server-unmapped/0172-Add-config-for-snow-on-blue-ice.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Fri, 5 Mar 2021 17:59:05 -0600 Subject: [PATCH] Add config for snow on blue ice diff --git a/patches/server-unmapped/0177-Tick-fluids-config.patch b/patches/server-unmapped/0177-Tick-fluids-config.patch index 4f9630e59..d771b614b 100644 --- a/patches/server-unmapped/0177-Tick-fluids-config.patch +++ b/patches/server-unmapped/0177-Tick-fluids-config.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Mon, 15 Mar 2021 03:52:17 -0500 Subject: [PATCH] Tick fluids config diff --git a/patches/server-unmapped/0180-Configurable-ravager-griefable-blocks-list.patch b/patches/server-unmapped/0180-Configurable-ravager-griefable-blocks-list.patch index 0fa842b47..950a2acc8 100644 --- a/patches/server-unmapped/0180-Configurable-ravager-griefable-blocks-list.patch +++ b/patches/server-unmapped/0180-Configurable-ravager-griefable-blocks-list.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Wed, 17 Mar 2021 14:54:43 -0500 Subject: [PATCH] Configurable ravager griefable blocks list diff --git a/patches/server-unmapped/0181-Sneak-to-bulk-process-composter.patch b/patches/server-unmapped/0181-Sneak-to-bulk-process-composter.patch index 0e61afadf..1f37f03c6 100644 --- a/patches/server-unmapped/0181-Sneak-to-bulk-process-composter.patch +++ b/patches/server-unmapped/0181-Sneak-to-bulk-process-composter.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Sun, 21 Mar 2021 15:49:15 -0500 Subject: [PATCH] Sneak to bulk process composter diff --git a/patches/server-unmapped/0186-Break-individual-slabs-when-sneaking.patch b/patches/server-unmapped/0186-Break-individual-slabs-when-sneaking.patch index 8891a1e62..d7658210e 100644 --- a/patches/server-unmapped/0186-Break-individual-slabs-when-sneaking.patch +++ b/patches/server-unmapped/0186-Break-individual-slabs-when-sneaking.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Tue, 23 Mar 2021 19:38:53 -0500 Subject: [PATCH] Break individual slabs when sneaking diff --git a/patches/server-unmapped/0189-Option-to-make-doors-require-redstone.patch b/patches/server-unmapped/0189-Option-to-make-doors-require-redstone.patch index 086353f9f..c619a7911 100644 --- a/patches/server-unmapped/0189-Option-to-make-doors-require-redstone.patch +++ b/patches/server-unmapped/0189-Option-to-make-doors-require-redstone.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Wed, 24 Mar 2021 04:40:11 -0500 Subject: [PATCH] Option to make doors require redstone diff --git a/patches/server-unmapped/0194-Piglin-portal-spawn-modifier.patch b/patches/server-unmapped/0194-Piglin-portal-spawn-modifier.patch index 0d0a814da..85d90ba21 100644 --- a/patches/server-unmapped/0194-Piglin-portal-spawn-modifier.patch +++ b/patches/server-unmapped/0194-Piglin-portal-spawn-modifier.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Tue, 13 Apr 2021 11:19:35 -0500 Subject: [PATCH] Piglin portal spawn modifier diff --git a/patches/server-unmapped/0199-Gamemode-extra-permissions.patch b/patches/server-unmapped/0199-Gamemode-extra-permissions.patch index 1e559e76c..b0dfe0d0c 100644 --- a/patches/server-unmapped/0199-Gamemode-extra-permissions.patch +++ b/patches/server-unmapped/0199-Gamemode-extra-permissions.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Fri, 30 Apr 2021 13:39:39 -0500 Subject: [PATCH] Gamemode extra permissions diff --git a/patches/server-unmapped/0203-Fix-SPIGOT-6278.patch b/patches/server-unmapped/0203-Fix-SPIGOT-6278.patch index 92114fd5a..e7632c032 100644 --- a/patches/server-unmapped/0203-Fix-SPIGOT-6278.patch +++ b/patches/server-unmapped/0203-Fix-SPIGOT-6278.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Mon, 10 May 2021 02:08:53 -0500 Subject: [PATCH] Fix SPIGOT-6278 diff --git a/patches/server-unmapped/0205-Hide-hidden-players-from-entity-selector.patch b/patches/server-unmapped/0205-Hide-hidden-players-from-entity-selector.patch index 5044d5de2..2cfdf76da 100644 --- a/patches/server-unmapped/0205-Hide-hidden-players-from-entity-selector.patch +++ b/patches/server-unmapped/0205-Hide-hidden-players-from-entity-selector.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Thu, 13 May 2021 16:18:29 -0500 Subject: [PATCH] Hide hidden players from entity selector diff --git a/patches/server-unmapped/0207-Iron-golem-poppy-calms-anger.patch b/patches/server-unmapped/0207-Iron-golem-poppy-calms-anger.patch index 3763feae6..27859bb04 100644 --- a/patches/server-unmapped/0207-Iron-golem-poppy-calms-anger.patch +++ b/patches/server-unmapped/0207-Iron-golem-poppy-calms-anger.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Thu, 13 May 2021 21:22:51 -0500 Subject: [PATCH] Iron golem poppy calms anger diff --git a/patches/server-unmapped/0208-Breedable-parrots.patch b/patches/server-unmapped/0208-Breedable-parrots.patch index a14b9507a..17c70602a 100644 --- a/patches/server-unmapped/0208-Breedable-parrots.patch +++ b/patches/server-unmapped/0208-Breedable-parrots.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Thu, 13 May 2021 22:17:50 -0500 Subject: [PATCH] Breedable parrots diff --git a/patches/server-unmapped/0211-Option-to-disable-dragon-egg-teleporting.patch b/patches/server-unmapped/0211-Option-to-disable-dragon-egg-teleporting.patch index a028be71d..a9aa92098 100644 --- a/patches/server-unmapped/0211-Option-to-disable-dragon-egg-teleporting.patch +++ b/patches/server-unmapped/0211-Option-to-disable-dragon-egg-teleporting.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Mon, 17 May 2021 04:46:23 -0500 Subject: [PATCH] Option to disable dragon egg teleporting diff --git a/patches/server-unmapped/0214-ShulkerBox-allow-oversized-stacks.patch b/patches/server-unmapped/0214-ShulkerBox-allow-oversized-stacks.patch index 78ee5622e..c8a34b495 100644 --- a/patches/server-unmapped/0214-ShulkerBox-allow-oversized-stacks.patch +++ b/patches/server-unmapped/0214-ShulkerBox-allow-oversized-stacks.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Thu, 27 May 2021 04:04:23 -0500 Subject: [PATCH] ShulkerBox allow oversized stacks diff --git a/patches/server-unmapped/0217-Fix-advancement-triggers-on-entity-death.patch b/patches/server-unmapped/0217-Fix-advancement-triggers-on-entity-death.patch index 3d36451a0..a4b78b2a3 100644 --- a/patches/server-unmapped/0217-Fix-advancement-triggers-on-entity-death.patch +++ b/patches/server-unmapped/0217-Fix-advancement-triggers-on-entity-death.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Fri, 28 May 2021 12:24:45 -0500 Subject: [PATCH] Fix advancement triggers on entity death diff --git a/patches/server-unmapped/0220-Add-toggle-for-sand-duping-fix.patch b/patches/server-unmapped/0220-Add-toggle-for-sand-duping-fix.patch index a60d35713..1c651cbe3 100644 --- a/patches/server-unmapped/0220-Add-toggle-for-sand-duping-fix.patch +++ b/patches/server-unmapped/0220-Add-toggle-for-sand-duping-fix.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Fri, 4 Jun 2021 09:13:54 -0500 Subject: [PATCH] Add toggle for sand duping fix diff --git a/patches/server-unmapped/0221-Add-toggle-for-end-portal-safe-teleporting.patch b/patches/server-unmapped/0221-Add-toggle-for-end-portal-safe-teleporting.patch index 92820596a..943f838ee 100644 --- a/patches/server-unmapped/0221-Add-toggle-for-end-portal-safe-teleporting.patch +++ b/patches/server-unmapped/0221-Add-toggle-for-end-portal-safe-teleporting.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Wed, 9 Jun 2021 11:03:40 -0500 Subject: [PATCH] Add toggle for end portal safe teleporting diff --git a/patches/server/0003-Ridables.patch b/patches/server/0003-Ridables.patch index f8dae0979..c5ddb9a5b 100644 --- a/patches/server/0003-Ridables.patch +++ b/patches/server/0003-Ridables.patch @@ -1,6 +1,6 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Tue, 15 Jun 2021 18:57:52 -0500 +From: William Blake Galbreath +Date: Sun, 5 Jul 2020 22:19:49 -0500 Subject: [PATCH] Ridables diff --git a/patches/server/0004-Configurable-entity-base-attributes.patch b/patches/server/0004-Configurable-entity-base-attributes.patch index 5a2157216..c199ab6d2 100644 --- a/patches/server/0004-Configurable-entity-base-attributes.patch +++ b/patches/server/0004-Configurable-entity-base-attributes.patch @@ -1,6 +1,6 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 18 Jun 2021 18:30:03 -0500 +From: William Blake Galbreath +Date: Thu, 10 Dec 2020 16:44:54 -0600 Subject: [PATCH] Configurable entity base attributes @@ -1086,7 +1086,7 @@ index dca18730731407bb68ad32852c7994062b0b4ba6..070e1ef31d4dabb943fc57ea4f46bb8d @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java -index 8830121a89297cc49fb13a7ecac9e6d90f33969d..8b6ce4b962cab41b39a364136429e3ce4271286c 100644 +index 25ce1910a03947ce070b318f57379f0da5ac5db8..95fd7e0ef552c606eaa75a0e23c0fcbb6d714a72 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Slime.java +++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java @@ -61,6 +61,7 @@ import org.bukkit.event.entity.SlimeSplitEvent; diff --git a/patches/server/0067-Add-canSaveToDisk-to-Entity.patch b/patches/server/0067-Add-canSaveToDisk-to-Entity.patch index 53afa6835..441950e82 100644 --- a/patches/server/0067-Add-canSaveToDisk-to-Entity.patch +++ b/patches/server/0067-Add-canSaveToDisk-to-Entity.patch @@ -18,6 +18,22 @@ index a663de350f315596806253c961544d1ebb682751..f226ea02e83246d8763e9b0587f986a6 + } // Purpur end } +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +index 96631591db018545120ba1c9980a03eb596eb6e5..22dd455b3b9c148f38a63f72901009f864e63a4b 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +@@ -192,6 +192,11 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob + // do not hit rider + return target != rider && super.canHitEntity(target); + } ++ ++ @Override ++ public boolean canSaveToDisk() { ++ return false; ++ } + }; + skull.setPosRaw(headX, headY, headZ); + level.addFreshEntity(skull); diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java index 572a013445bd83d366cce27d0e015ba8271df7e0..bba780934f4bb05bdb5ff8e69dc615a6b555b2f0 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java @@ -30,3 +46,35 @@ index 572a013445bd83d366cce27d0e015ba8271df7e0..bba780934f4bb05bdb5ff8e69dc615a6 // Paper start final EntityType entityType = entity.getType(); final int saveLimit = this.level.paperConfig.entityPerChunkSaveLimits.getOrDefault(entityType, -1); +diff --git a/src/main/java/net/pl3x/purpur/entity/DolphinSpit.java b/src/main/java/net/pl3x/purpur/entity/DolphinSpit.java +index fda24d4ecff91cc28d2a7a45fbb55ea734261153..3cabafb00c293cbbcc60a0cc98479c2d62ddaa2d 100644 +--- a/src/main/java/net/pl3x/purpur/entity/DolphinSpit.java ++++ b/src/main/java/net/pl3x/purpur/entity/DolphinSpit.java +@@ -35,6 +35,11 @@ public class DolphinSpit extends LlamaSpit { + dolphin.getZ() + (double) (dolphin.getBbWidth() + 1.0F) * 0.5D * (double) Mth.cos(dolphin.yBodyRot * 0.017453292F)); + } + ++ @Override ++ public boolean canSaveToDisk() { ++ return false; ++ } ++ + public void tick() { + super_tick(); + +diff --git a/src/main/java/net/pl3x/purpur/entity/PhantomFlames.java b/src/main/java/net/pl3x/purpur/entity/PhantomFlames.java +index 57b59a12f609fda0787d49575724762362ce12af..9a9b7f80859c70fbd1fa66b390ab005cde813d02 100644 +--- a/src/main/java/net/pl3x/purpur/entity/PhantomFlames.java ++++ b/src/main/java/net/pl3x/purpur/entity/PhantomFlames.java +@@ -38,6 +38,11 @@ public class PhantomFlames extends LlamaSpit { + phantom.getZ() + (double) (phantom.getBbWidth() + 1.0F) * 0.5D * (double) Mth.cos(phantom.yBodyRot * 0.017453292F)); + } + ++ @Override ++ public boolean canSaveToDisk() { ++ return false; ++ } ++ + public void tick() { + super_tick(); + diff --git a/patches/server/0074-Add-ping-command.patch b/patches/server/0074-Add-ping-command.patch index 8214940b2..84d1e6e66 100644 --- a/patches/server/0074-Add-ping-command.patch +++ b/patches/server/0074-Add-ping-command.patch @@ -17,14 +17,14 @@ index d478627dcd2b6e3d3d95b3fa224a25d44e6bbafb..158fc5748f175708a0c3415a2217663f if (environment.includeIntegrated) { diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index 5f6fb1ac7c4b022109e102308cb6ca4c9997e1f1..5ad90e5c2f46b9ae1bf882a199d38e8cb49f6b5f 100644 +index 5f6fb1ac7c4b022109e102308cb6ca4c9997e1f1..1607dfe0bccf947ef8d9618e83dbe5e537913700 100644 --- a/src/main/java/net/pl3x/purpur/PurpurConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java @@ -133,12 +133,14 @@ public class PurpurConfig { public static String afkBroadcastBack = "%s is no longer AFK"; public static String afkTabListPrefix = "[AFK] "; public static String afkTabListSuffix = ""; -+ public static String pingCommandOutput = "§a%s's ping is %sms"; ++ public static String pingCommandOutput = "%s's ping is %sms"; private static void messages() { cannotRideMob = getString("settings.messages.cannot-ride-mob", cannotRideMob); afkBroadcastAway = getString("settings.messages.afk-broadcast-away", afkBroadcastAway); @@ -37,7 +37,7 @@ index 5f6fb1ac7c4b022109e102308cb6ca4c9997e1f1..5ad90e5c2f46b9ae1bf882a199d38e8c public static String serverModName = "Purpur"; diff --git a/src/main/java/net/pl3x/purpur/command/PingCommand.java b/src/main/java/net/pl3x/purpur/command/PingCommand.java new file mode 100644 -index 0000000000000000000000000000000000000000..c1d69aa60fa89730cb6e70ec50ba728ee7980053 +index 0000000000000000000000000000000000000000..6de4f71aa5d501f3f5da93cd631da654a6e264e0 --- /dev/null +++ b/src/main/java/net/pl3x/purpur/command/PingCommand.java @@ -0,0 +1,32 @@ @@ -68,7 +68,7 @@ index 0000000000000000000000000000000000000000..c1d69aa60fa89730cb6e70ec50ba728e + private static int execute(CommandSourceStack sender, Collection targets) { + for (ServerPlayer player : targets) { + String output = String.format(PurpurConfig.pingCommandOutput, player.getGameProfile().getName(), player.latency); -+ sender.sendSuccess(CraftChatMessage.fromStringOrNull(output), false); ++ sender.sendSuccess(output, false); + } + return targets.size(); + } diff --git a/patches/server/0075-Add-demo-command.patch b/patches/server/0075-Add-demo-command.patch index e6fe981c9..b01176f5e 100644 --- a/patches/server/0075-Add-demo-command.patch +++ b/patches/server/0075-Add-demo-command.patch @@ -1,6 +1,6 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 19 Jun 2021 18:16:31 -0500 +From: William Blake Galbreath +Date: Mon, 30 Nov 2020 03:12:04 -0600 Subject: [PATCH] Add demo command @@ -17,7 +17,7 @@ index 158fc5748f175708a0c3415a2217663f77271bc7..9cbaaf4cd138e6c1d2d51afcef24a81a } diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index 5ad90e5c2f46b9ae1bf882a199d38e8cb49f6b5f..c143f2c95fddece9c97f6f5eeb9a0ba52dae18b5 100644 +index 1607dfe0bccf947ef8d9618e83dbe5e537913700..8a515bbb2f680e27bf5169992bdb3cf19297660d 100644 --- a/src/main/java/net/pl3x/purpur/PurpurConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java @@ -133,6 +133,7 @@ public class PurpurConfig { @@ -25,7 +25,7 @@ index 5ad90e5c2f46b9ae1bf882a199d38e8cb49f6b5f..c143f2c95fddece9c97f6f5eeb9a0ba5 public static String afkTabListPrefix = "[AFK] "; public static String afkTabListSuffix = ""; + public static String demoCommandOutput = "%s has been shown the demo screen"; - public static String pingCommandOutput = "§a%s's ping is %sms"; + public static String pingCommandOutput = "%s's ping is %sms"; private static void messages() { cannotRideMob = getString("settings.messages.cannot-ride-mob", cannotRideMob); @@ -140,6 +141,7 @@ public class PurpurConfig { diff --git a/patches/server/0104-Customizable-wither-health-and-healing.patch b/patches/server/0104-Customizable-wither-health-and-healing.patch index de998eb43..5eae50585 100644 --- a/patches/server/0104-Customizable-wither-health-and-healing.patch +++ b/patches/server/0104-Customizable-wither-health-and-healing.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Customizable wither health and healing Adds the ability to customize the health of the wither, as well as the amount that it heals, and how often. diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -index 96631591db018545120ba1c9980a03eb596eb6e5..9c45c0e232da2597f071081443f9db3df57b5513 100644 +index 22dd455b3b9c148f38a63f72901009f864e63a4b..689df66281ef84f0cc31d89c6f2e654c9f3a5150 100644 --- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -@@ -499,8 +499,10 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob +@@ -504,8 +504,10 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob } } diff --git a/patches/server/0119-Add-adjustable-breeding-cooldown-to-config.patch b/patches/server/0119-Add-adjustable-breeding-cooldown-to-config.patch index 02e092def..0ac4383c3 100644 --- a/patches/server/0119-Add-adjustable-breeding-cooldown-to-config.patch +++ b/patches/server/0119-Add-adjustable-breeding-cooldown-to-config.patch @@ -1,6 +1,6 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 19 Jun 2021 12:54:11 -0500 +From: montlikadani +Date: Fri, 13 Nov 2020 17:52:40 +0100 Subject: [PATCH] Add adjustable breeding cooldown to config diff --git a/patches/server/0120-Make-entity-breeding-times-configurable.patch b/patches/server/0120-Make-entity-breeding-times-configurable.patch index d8b8d15e8..c469590ea 100644 --- a/patches/server/0120-Make-entity-breeding-times-configurable.patch +++ b/patches/server/0120-Make-entity-breeding-times-configurable.patch @@ -1,6 +1,6 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 19 Jun 2021 13:20:26 -0500 +From: jmp +Date: Sun, 15 Nov 2020 02:18:15 -0800 Subject: [PATCH] Make entity breeding times configurable diff --git a/patches/server/0121-Apply-display-names-from-item-forms-of-entities-to-e.patch b/patches/server/0121-Apply-display-names-from-item-forms-of-entities-to-e.patch index f3ca05c55..3bd4a4129 100644 --- a/patches/server/0121-Apply-display-names-from-item-forms-of-entities-to-e.patch +++ b/patches/server/0121-Apply-display-names-from-item-forms-of-entities-to-e.patch @@ -1,6 +1,6 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 19 Jun 2021 14:45:41 -0500 +From: jmp +Date: Tue, 17 Nov 2020 03:23:48 -0800 Subject: [PATCH] Apply display names from item forms of entities to entities and vice versa diff --git a/patches/server/0122-Set-name-visible-when-using-a-Name-Tag-on-an-Armor-S.patch b/patches/server/0122-Set-name-visible-when-using-a-Name-Tag-on-an-Armor-S.patch index a360f9931..3063f6214 100644 --- a/patches/server/0122-Set-name-visible-when-using-a-Name-Tag-on-an-Armor-S.patch +++ b/patches/server/0122-Set-name-visible-when-using-a-Name-Tag-on-an-Armor-S.patch @@ -1,6 +1,6 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 19 Jun 2021 14:53:40 -0500 +From: jmp +Date: Tue, 17 Nov 2020 13:12:09 -0800 Subject: [PATCH] Set name visible when using a Name Tag on an Armor Stand diff --git a/patches/server/0123-Add-twisting-and-weeping-vines-growth-rates.patch b/patches/server/0123-Add-twisting-and-weeping-vines-growth-rates.patch index ed7f419ad..e40e54a0c 100644 --- a/patches/server/0123-Add-twisting-and-weeping-vines-growth-rates.patch +++ b/patches/server/0123-Add-twisting-and-weeping-vines-growth-rates.patch @@ -1,6 +1,6 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 19 Jun 2021 15:16:56 -0500 +From: William Blake Galbreath +Date: Sun, 22 Nov 2020 06:02:32 -0600 Subject: [PATCH] Add twisting and weeping vines growth rates diff --git a/patches/server/0124-Kelp-weeping-and-twisting-vines-configurable-max-gro.patch b/patches/server/0124-Kelp-weeping-and-twisting-vines-configurable-max-gro.patch index 86c87c786..123444ffe 100644 --- a/patches/server/0124-Kelp-weeping-and-twisting-vines-configurable-max-gro.patch +++ b/patches/server/0124-Kelp-weeping-and-twisting-vines-configurable-max-gro.patch @@ -1,6 +1,6 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 19 Jun 2021 16:27:24 -0500 +From: William Blake Galbreath +Date: Sun, 22 Nov 2020 20:13:27 -0600 Subject: [PATCH] Kelp weeping and twisting vines configurable max growth age diff --git a/patches/server/0125-Add-config-for-allowing-Endermen-to-despawn-even-whi.patch b/patches/server/0125-Add-config-for-allowing-Endermen-to-despawn-even-whi.patch index d341377c9..4ce1f23e2 100644 --- a/patches/server/0125-Add-config-for-allowing-Endermen-to-despawn-even-whi.patch +++ b/patches/server/0125-Add-config-for-allowing-Endermen-to-despawn-even-whi.patch @@ -1,9 +1,11 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 19 Jun 2021 16:29:26 -0500 +From: jmp +Date: Sun, 22 Nov 2020 22:17:53 -0800 Subject: [PATCH] Add config for allowing Endermen to despawn even while holding a block +This should help to reduce the amount of dirt, gravel, grass, and etc. +that Endermen like to randomly place all over the world. diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java index 5ebedd6a156b06e98aded57c817f63429a1ae380..c99d295b999a28dd1eb504179250445d1b61d099 100644 diff --git a/patches/server/0126-Add-critical-hit-check-to-EntityDamagedByEntityEvent.patch b/patches/server/0126-Add-critical-hit-check-to-EntityDamagedByEntityEvent.patch index dac8af670..e3a7bda64 100644 --- a/patches/server/0126-Add-critical-hit-check-to-EntityDamagedByEntityEvent.patch +++ b/patches/server/0126-Add-critical-hit-check-to-EntityDamagedByEntityEvent.patch @@ -1,6 +1,6 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 19 Jun 2021 16:34:42 -0500 +From: William Blake Galbreath +Date: Tue, 24 Nov 2020 04:30:46 -0600 Subject: [PATCH] Add critical hit check to EntityDamagedByEntityEvent diff --git a/patches/server/0127-Add-configurable-snowball-damage.patch b/patches/server/0127-Add-configurable-snowball-damage.patch index 1c988c05d..8bf0e9e51 100644 --- a/patches/server/0127-Add-configurable-snowball-damage.patch +++ b/patches/server/0127-Add-configurable-snowball-damage.patch @@ -1,6 +1,6 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 19 Jun 2021 16:37:38 -0500 +From: William Blake Galbreath +Date: Tue, 24 Nov 2020 05:32:02 -0600 Subject: [PATCH] Add configurable snowball damage diff --git a/patches/server/0128-Zombie-break-door-minimum-difficulty-option.patch b/patches/server/0128-Zombie-break-door-minimum-difficulty-option.patch index 2e78bebf6..1650ed49d 100644 --- a/patches/server/0128-Zombie-break-door-minimum-difficulty-option.patch +++ b/patches/server/0128-Zombie-break-door-minimum-difficulty-option.patch @@ -1,6 +1,6 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 19 Jun 2021 16:47:15 -0500 +From: William Blake Galbreath +Date: Fri, 27 Nov 2020 10:33:33 -0600 Subject: [PATCH] Zombie break door minimum difficulty option diff --git a/patches/server/0129-Left-handed-API.patch b/patches/server/0129-Left-handed-API.patch index 967b7ed29..c85afcc0d 100644 --- a/patches/server/0129-Left-handed-API.patch +++ b/patches/server/0129-Left-handed-API.patch @@ -1,6 +1,6 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 19 Jun 2021 18:38:48 -0500 +From: William Blake Galbreath +Date: Mon, 30 Nov 2020 06:03:06 -0600 Subject: [PATCH] Left handed API diff --git a/patches/server/0130-Changeable-Mob-Left-Handed-Chance.patch b/patches/server/0130-Changeable-Mob-Left-Handed-Chance.patch new file mode 100644 index 000000000..cdc08f566 --- /dev/null +++ b/patches/server/0130-Changeable-Mob-Left-Handed-Chance.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ben Kerllenevich +Date: Mon, 30 Nov 2020 11:40:11 -0500 +Subject: [PATCH] Changeable Mob Left Handed Chance + + +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 568c11075c7a45f210bb2ddc81c313d0dec8539e..54ad0989cea052bf500ad5b48bcfa77b08763731 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -1198,7 +1198,7 @@ public abstract class Mob extends LivingEntity { + @Nullable + public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData entityData, @Nullable CompoundTag entityNbt) { + this.getAttribute(Attributes.FOLLOW_RANGE).addPermanentModifier(new AttributeModifier("Random spawn bonus", this.random.nextGaussian() * 0.05D, AttributeModifier.Operation.MULTIPLY_BASE)); +- if (this.random.nextFloat() < 0.05F) { ++ if (this.random.nextFloat() < this.level.purpurConfig.entityLeftHandedChance) { // Purpur + this.setLeftHanded(true); + } 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 ee68bc02ed398ef61a29bee9d5be728ec730133c..0539ff14b22839d8e64162aaf38f5ae84a6cf84e 100644 +--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java ++++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +@@ -115,8 +115,10 @@ public class PurpurWorldConfig { + } + + public int entityLifeSpan = 0; ++ public float entityLeftHandedChance = 0.05f; + private void entitySettings() { + entityLifeSpan = getInt("gameplay-mechanics.entity-lifespan", entityLifeSpan); ++ entityLeftHandedChance = (float) getDouble("gameplay-mechanics.entity-left-handed-chance", entityLeftHandedChance); + } + + public boolean infinityWorksWithNormalArrows = true; diff --git a/patches/server-unmapped/0135-Add-boat-fall-damage-config.patch b/patches/server/0131-Add-boat-fall-damage-config.patch similarity index 55% rename from patches/server-unmapped/0135-Add-boat-fall-damage-config.patch rename to patches/server/0131-Add-boat-fall-damage-config.patch index 935e53b32..d60f26f82 100644 --- a/patches/server-unmapped/0135-Add-boat-fall-damage-config.patch +++ b/patches/server/0131-Add-boat-fall-damage-config.patch @@ -1,36 +1,36 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath +From: William Blake Galbreath Date: Mon, 30 Nov 2020 19:36:35 -0600 Subject: [PATCH] Add boat fall damage config -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 6238469d8e973ca675bb02988d3324e5c5830b42..574486804ae64fa870de5499f6955ed13357d616 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -970,7 +970,16 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - if (this.isInvulnerable(damagesource)) { +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 5b395fb6f0e7bee4a24fb2d5b0bc9421b70e5b8d..c4ff2e17d032f20395bb8a42152d16de6287eff8 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -986,7 +986,16 @@ public class ServerPlayer extends Player { + if (this.isInvulnerableTo(source)) { return false; } else { -- if (damagesource == DamageSource.FALL && getRootVehicle() instanceof net.minecraft.world.entity.vehicle.EntityMinecartAbstract && world.purpurConfig.minecartControllable && !world.purpurConfig.minecartControllableFallDamage) return false; // Purpur +- if (source == DamageSource.FALL && getRootVehicle() instanceof net.minecraft.world.entity.vehicle.AbstractMinecart && level.purpurConfig.minecartControllable && !level.purpurConfig.minecartControllableFallDamage) return false; // Purpur + // Purpur start -+ if (damagesource == DamageSource.FALL) { -+ if (getRootVehicle() instanceof net.minecraft.world.entity.vehicle.EntityMinecartAbstract && world.purpurConfig.minecartControllable && !world.purpurConfig.minecartControllableFallDamage) { ++ if (source == DamageSource.FALL) { ++ if (getRootVehicle() instanceof net.minecraft.world.entity.vehicle.AbstractMinecart && level.purpurConfig.minecartControllable && !level.purpurConfig.minecartControllableFallDamage) { + return false; + } -+ if (getRootVehicle() instanceof net.minecraft.world.entity.vehicle.EntityBoat && !world.purpurConfig.boatsDoFallDamage) { ++ if (getRootVehicle() instanceof net.minecraft.world.entity.vehicle.Boat && !level.purpurConfig.boatsDoFallDamage) { + return false; + } + } + // Purpur end - boolean flag = this.server.j() && this.canPvP() && "fall".equals(damagesource.translationIndex); + boolean flag = this.server.isDedicatedServer() && this.isPvpAllowed() && "fall".equals(source.msgId); - if (!flag && isSpawnInvulnerable() && damagesource != DamageSource.OUT_OF_WORLD) { // Purpur + if (!flag && isSpawnInvulnerable() && source != 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 5e3b23d50b6e8494066c71bdf7c14edc4a4a3716..944c1bbcb868e2e24f26db04b588f6f0c13164e5 100644 +index 0539ff14b22839d8e64162aaf38f5ae84a6cf84e..48a15e27ca3485758a1b6c7c4041d26aa3b755e0 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -268,6 +268,7 @@ public class PurpurWorldConfig { +@@ -332,6 +332,7 @@ public class PurpurWorldConfig { public boolean useBetterMending = false; public boolean boatEjectPlayersOnLand = false; @@ -38,7 +38,7 @@ index 5e3b23d50b6e8494066c71bdf7c14edc4a4a3716..944c1bbcb868e2e24f26db04b588f6f0 public boolean disableDropsOnCrammingDeath = false; public boolean entitiesPickUpLootBypassMobGriefing = false; public boolean entitiesCanUsePortals = true; -@@ -282,6 +283,7 @@ public class PurpurWorldConfig { +@@ -346,6 +347,7 @@ public class PurpurWorldConfig { private void miscGameplayMechanicsSettings() { useBetterMending = getBoolean("gameplay-mechanics.use-better-mending", useBetterMending); boatEjectPlayersOnLand = getBoolean("gameplay-mechanics.boat.eject-players-on-land", boatEjectPlayersOnLand); diff --git a/patches/server/0132-Snow-Golem-rate-of-fire-config.patch b/patches/server/0132-Snow-Golem-rate-of-fire-config.patch new file mode 100644 index 000000000..bbc432282 --- /dev/null +++ b/patches/server/0132-Snow-Golem-rate-of-fire-config.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Simon Gardling +Date: Tue, 1 Dec 2020 16:50:36 -0500 +Subject: [PATCH] Snow Golem rate of fire config + +The formula used to determine the amount of ticks between shots is: + ((sqrt(distanceToTarget) / snowGolemAttackDistance) / snowGolemSnowBallModifer) * (maxShootIntervalTicks - minShootIntervalTicks) + minShootIntervalTicks + +If min-shoot-interval-ticks and max-shoot-interval-ticks are both set to +0, snow golems won't shoot any snowballs. + +diff --git a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java +index 0733f9c057fef17fd79a4769f19b78f4c83a7784..1697b573ffd0c5d17d2d538c40f5ce4b709f261a 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java ++++ b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java +@@ -73,7 +73,7 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur +- this.goalSelector.addGoal(1, new RangedAttackGoal(this, 1.25D, 20, 10.0F)); ++ this.goalSelector.addGoal(1, new RangedAttackGoal(this, level.purpurConfig.snowGolemAttackDistance, level.purpurConfig.snowGolemSnowBallMin, level.purpurConfig.snowGolemSnowBallMax, level.purpurConfig.snowGolemSnowBallModifier)); // Purpur + this.goalSelector.addGoal(2, new WaterAvoidingRandomStrollGoal(this, 1.0D, 1.0000001E-5F)); + this.goalSelector.addGoal(3, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(4, new RandomLookAroundGoal(this)); +diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +index 48a15e27ca3485758a1b6c7c4041d26aa3b755e0..eb4af292087a27b30a8f2898d1847a6cb6025442 100644 +--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java ++++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +@@ -1441,6 +1441,10 @@ public class PurpurWorldConfig { + public double snowGolemMaxHealth = 4.0D; + public boolean snowGolemDropsPumpkin = true; + public boolean snowGolemPutPumpkinBack = false; ++ public int snowGolemSnowBallMin = 20; ++ public int snowGolemSnowBallMax = 20; ++ public float snowGolemSnowBallModifier = 10.0F; ++ public double snowGolemAttackDistance = 1.25D; + private void snowGolemSettings() { + snowGolemRidable = getBoolean("mobs.snow_golem.ridable", snowGolemRidable); + snowGolemRidableInWater = getBoolean("mobs.snow_golem.ridable-in-water", snowGolemRidableInWater); +@@ -1453,6 +1457,10 @@ public class PurpurWorldConfig { + snowGolemMaxHealth = getDouble("mobs.snow_golem.attributes.max_health", snowGolemMaxHealth); + 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); ++ 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); + } + + public boolean squidRidable = false;