From 4b38df66d4996844531f57c56ddc37aa810b136f Mon Sep 17 00:00:00 2001 From: granny Date: Sat, 4 Jan 2025 02:12:23 -0800 Subject: [PATCH] port Configurable entity base attributes patch --- build-data/purpur.at | 1 + ...-Configurable-entity-base-attributes.patch | 3253 ----------------- purpur-server/build.gradle.kts.patch | 10 + ...-Configurable-entity-base-attributes.patch | 1786 +++++++++ .../minecraft/world/entity/Entity.java.patch | 11 + .../purpurmc/purpur/PurpurWorldConfig.java | 811 ++++ 6 files changed, 2619 insertions(+), 3253 deletions(-) delete mode 100644 patches/server/0008-Configurable-entity-base-attributes.patch create mode 100644 purpur-server/minecraft-patches/features/0002-Configurable-entity-base-attributes.patch create mode 100644 purpur-server/minecraft-patches/sources/net/minecraft/world/entity/Entity.java.patch diff --git a/build-data/purpur.at b/build-data/purpur.at index da5a42839..203f836e9 100644 --- a/build-data/purpur.at +++ b/build-data/purpur.at @@ -1,3 +1,4 @@ # This file is auto generated, any changes may be overridden! # See CONTRIBUTING.md on how to add access transformers. protected net.minecraft.world.entity.Entity dimensions +public net.minecraft.world.entity.monster.Shulker MAX_SCALE diff --git a/patches/server/0008-Configurable-entity-base-attributes.patch b/patches/server/0008-Configurable-entity-base-attributes.patch deleted file mode 100644 index b85e7164c..000000000 --- a/patches/server/0008-Configurable-entity-base-attributes.patch +++ /dev/null @@ -1,3253 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Thu, 10 Dec 2020 16:44:54 -0600 -Subject: [PATCH] Configurable entity base attributes - - -diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 5c14180d92e1baebe59b08311746418e7d9f6a24..755861185bd8434027acca7f03ed0bfdf9fa2cde 100644 ---- a/net/minecraft/world/entity/Entity.java -+++ b/net/minecraft/world/entity/Entity.java -@@ -177,7 +177,7 @@ import org.bukkit.plugin.PluginManager; - // CraftBukkit end - - public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, ScoreHolder, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity { // Paper - rewrite chunk system // Paper - optimise entity tracker -- -+ public static javax.script.ScriptEngine scriptEngine = new javax.script.ScriptEngineManager().getEngineByName("rhino"); // Purpur - Configurable entity base attributes - // CraftBukkit start - private static final int CURRENT_LEVEL = 2; - public boolean preserveMotion = true; // Paper - Fix Entity Teleportation and cancel velocity if teleported; keep initial motion on first setPositionRotation -diff --git a/net/minecraft/world/entity/GlowSquid.java b/net/minecraft/world/entity/GlowSquid.java -index 293ffe990de70f4f8872f063388a3a50c60b68e6..66a5c485ed2d29d0079ae714c2dd7b01aab11d86 100644 ---- a/net/minecraft/world/entity/GlowSquid.java -+++ b/net/minecraft/world/entity/GlowSquid.java -@@ -38,6 +38,12 @@ public class GlowSquid extends Squid { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.glowSquidMaxHealth); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected ParticleOptions getInkParticle() { - return ParticleTypes.GLOW_SQUID_INK; -diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 715b76bd0ccc0c29583a55f82a8ecd889ab49b56..6884475a5217acb8073dc38e5f7a7b341c8b1dd1 100644 ---- a/net/minecraft/world/entity/LivingEntity.java -+++ b/net/minecraft/world/entity/LivingEntity.java -@@ -324,6 +324,7 @@ public abstract class LivingEntity extends Entity implements Attackable { - this.activeLocationDependentEnchantments = new EnumMap(EquipmentSlot.class); - this.appliedScale = 1.0F; - this.attributes = new AttributeMap(DefaultAttributes.getSupplier(type), this); // Purpur - Ridables -+ this.initAttributes(); // Purpur - Configurable entity base attributes - this.craftAttributes = new CraftAttributeMap(this.attributes); // CraftBukkit - // CraftBukkit - setHealth(getMaxHealth()) inlined and simplified to skip the instanceof check for EntityPlayer, as getBukkitEntity() is not initialized in constructor - this.entityData.set(LivingEntity.DATA_HEALTH_ID, (float) this.getAttribute(Attributes.MAX_HEALTH).getValue()); -@@ -338,6 +339,8 @@ public abstract class LivingEntity extends Entity implements Attackable { - this.brain = this.makeBrain(new Dynamic(dynamicopsnbt, (Tag) dynamicopsnbt.createMap((Map) ImmutableMap.of(dynamicopsnbt.createString("memories"), (Tag) dynamicopsnbt.emptyMap())))); - } - -+ protected void initAttributes() {}// Purpur - Configurable entity base attributes -+ - public Brain getBrain() { - return this.brain; - } -diff --git a/net/minecraft/world/entity/ambient/Bat.java b/net/minecraft/world/entity/ambient/Bat.java -index add1c146cd7428547d9ef8810841b4cf39a6a05e..5f11c687df87015261d1d39c957e241fbeb5476a 100644 ---- a/net/minecraft/world/entity/ambient/Bat.java -+++ b/net/minecraft/world/entity/ambient/Bat.java -@@ -100,6 +100,20 @@ public class Bat extends AmbientCreature { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.batMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.batScale); -+ this.getAttribute(Attributes.FOLLOW_RANGE).setBaseValue(this.level().purpurConfig.batFollowRange); -+ this.getAttribute(Attributes.KNOCKBACK_RESISTANCE).setBaseValue(this.level().purpurConfig.batKnockbackResistance); -+ this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(this.level().purpurConfig.batMovementSpeed); -+ this.getAttribute(Attributes.FLYING_SPEED).setBaseValue(this.level().purpurConfig.batFlyingSpeed); -+ this.getAttribute(Attributes.ARMOR).setBaseValue(this.level().purpurConfig.batArmor); -+ this.getAttribute(Attributes.ARMOR_TOUGHNESS).setBaseValue(this.level().purpurConfig.batArmorToughness); -+ this.getAttribute(Attributes.ATTACK_KNOCKBACK).setBaseValue(this.level().purpurConfig.batAttackKnockback); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - public boolean isFlapping() { - return !this.isResting() && (float) this.tickCount % 10.0F == 0.0F; -diff --git a/net/minecraft/world/entity/animal/Bee.java b/net/minecraft/world/entity/animal/Bee.java -index 13f6e4c83e1775daadb13e3532d7dfe6eef15aac..8751cc882f2dcbf6dfc10cebab9d9a4f95ebfb10 100644 ---- a/net/minecraft/world/entity/animal/Bee.java -+++ b/net/minecraft/world/entity/animal/Bee.java -@@ -489,6 +489,13 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { - return tileentitybeehive != null && tileentitybeehive.isFireNearby(); - } - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.beeMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.beeScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - public int getRemainingPersistentAngerTime() { - return (Integer) this.entityData.get(Bee.DATA_REMAINING_ANGER_TIME); -diff --git a/net/minecraft/world/entity/animal/Cat.java b/net/minecraft/world/entity/animal/Cat.java -index 472bbf4c3f932e2b1c7d7fa3c74b41f5be11431f..b4f022093a52c1fe13ad67ad70d57fd0278a9d55 100644 ---- a/net/minecraft/world/entity/animal/Cat.java -+++ b/net/minecraft/world/entity/animal/Cat.java -@@ -125,6 +125,13 @@ public class Cat extends TamableAnimal implements VariantHolder { -diff --git a/net/minecraft/world/entity/animal/Chicken.java b/net/minecraft/world/entity/animal/Chicken.java -index 5eaa1d42ec72ff077d974db3284cae32a9809da7..2f1518536e63dfd94db5c8a2076004319408409c 100644 ---- a/net/minecraft/world/entity/animal/Chicken.java -+++ b/net/minecraft/world/entity/animal/Chicken.java -@@ -70,6 +70,13 @@ public class Chicken extends Animal { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.chickenMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.chickenScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected void registerGoals() { - this.goalSelector.addGoal(0, new FloatGoal(this)); -diff --git a/net/minecraft/world/entity/animal/Cod.java b/net/minecraft/world/entity/animal/Cod.java -index fcf7073dd2d79f1483bdc6e7fdc37c8c260ae418..dad2dc77afead53e0fa7f2f797ac3850279d5d40 100644 ---- a/net/minecraft/world/entity/animal/Cod.java -+++ b/net/minecraft/world/entity/animal/Cod.java -@@ -25,6 +25,12 @@ public class Cod extends AbstractSchoolingFish { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.codMaxHealth); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - public ItemStack getBucketItemStack() { - return new ItemStack(Items.COD_BUCKET); -diff --git a/net/minecraft/world/entity/animal/Cow.java b/net/minecraft/world/entity/animal/Cow.java -index dc7ccfe90a82892d65098a325fd71fbbc734da86..064188a7032170ed16cf3b538efc444e54325036 100644 ---- a/net/minecraft/world/entity/animal/Cow.java -+++ b/net/minecraft/world/entity/animal/Cow.java -@@ -61,6 +61,13 @@ public class Cow extends Animal { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.cowMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.cowScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected void registerGoals() { - this.goalSelector.addGoal(0, new FloatGoal(this)); -diff --git a/net/minecraft/world/entity/animal/Dolphin.java b/net/minecraft/world/entity/animal/Dolphin.java -index af677b6581514a07e6455977ffc591538d43bbc6..2ee7de39712d67b593ff287a9ed17c28fa768b3c 100644 ---- a/net/minecraft/world/entity/animal/Dolphin.java -+++ b/net/minecraft/world/entity/animal/Dolphin.java -@@ -161,6 +161,13 @@ public class Dolphin extends AgeableWaterCreature { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.dolphinMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.dolphinScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Nullable - @Override - public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, EntitySpawnReason spawnReason, @Nullable SpawnGroupData entityData) { -diff --git a/net/minecraft/world/entity/animal/Fox.java b/net/minecraft/world/entity/animal/Fox.java -index ce5ac300582f61d0f3eeb1e94340cfefbdff1ba9..584d08bca961f8b8487b844cd2412b773401296d 100644 ---- a/net/minecraft/world/entity/animal/Fox.java -+++ b/net/minecraft/world/entity/animal/Fox.java -@@ -182,6 +182,13 @@ public class Fox extends Animal implements VariantHolder { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.foxMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.foxScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected void defineSynchedData(SynchedEntityData.Builder builder) { - super.defineSynchedData(builder); -diff --git a/net/minecraft/world/entity/animal/IronGolem.java b/net/minecraft/world/entity/animal/IronGolem.java -index 938a0c6f7cfbb6cd459d5a2ec46f912d45fd2226..124b7d6881964039829313c52427e332e1ac526b 100644 ---- a/net/minecraft/world/entity/animal/IronGolem.java -+++ b/net/minecraft/world/entity/animal/IronGolem.java -@@ -79,6 +79,13 @@ public class IronGolem extends AbstractGolem implements NeutralMob { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.ironGolemMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.ironGolemScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected void registerGoals() { - if (level().purpurConfig.ironGolemCanSwim) this.goalSelector.addGoal(0, new net.minecraft.world.entity.ai.goal.FloatGoal(this)); // Purpur - Ridables -diff --git a/net/minecraft/world/entity/animal/MushroomCow.java b/net/minecraft/world/entity/animal/MushroomCow.java -index f37c8efa34efcb289bbeed06ea2d3860ff2662ac..215ec83077a1d40fdcee5bf4cd1af0d46fdd695e 100644 ---- a/net/minecraft/world/entity/animal/MushroomCow.java -+++ b/net/minecraft/world/entity/animal/MushroomCow.java -@@ -81,6 +81,12 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.rabbitMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.rabbitScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - public void registerGoals() { - this.goalSelector.addGoal(1, new FloatGoal(this)); -diff --git a/net/minecraft/world/entity/animal/Salmon.java b/net/minecraft/world/entity/animal/Salmon.java -index 9bc58ca4556baf6f6bc494ae249c11c5c627f86c..88f0f9074db9a9afff55aa6bd17c38fa2e1e1f81 100644 ---- a/net/minecraft/world/entity/animal/Salmon.java -+++ b/net/minecraft/world/entity/animal/Salmon.java -@@ -47,6 +47,12 @@ public class Salmon extends AbstractSchoolingFish implements VariantHolder brainProvider() { - return Brain.provider(Allay.MEMORY_TYPES, Allay.SENSOR_TYPES); -diff --git a/net/minecraft/world/entity/animal/armadillo/Armadillo.java b/net/minecraft/world/entity/animal/armadillo/Armadillo.java -index 4c9771725f9567790841094dae72c2bbf0d5ba62..1a6c88558a11066ec2a78d40e6a1b0f2fa546b88 100644 ---- a/net/minecraft/world/entity/animal/armadillo/Armadillo.java -+++ b/net/minecraft/world/entity/animal/armadillo/Armadillo.java -@@ -99,6 +99,13 @@ public class Armadillo extends Animal { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.armadilloMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.armadilloScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected void defineSynchedData(SynchedEntityData.Builder builder) { - super.defineSynchedData(builder); -diff --git a/net/minecraft/world/entity/animal/axolotl/Axolotl.java b/net/minecraft/world/entity/animal/axolotl/Axolotl.java -index b414edf515890066bd970f65c073964839851840..f95b9be60c3725fe279a07300f706abb25e152f1 100644 ---- a/net/minecraft/world/entity/animal/axolotl/Axolotl.java -+++ b/net/minecraft/world/entity/animal/axolotl/Axolotl.java -@@ -117,6 +117,13 @@ public class Axolotl extends Animal implements VariantHolder, B - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.axolotlMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.axolotlScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - public float getWalkTargetValue(BlockPos pos, LevelReader world) { - return 0.0F; -diff --git a/net/minecraft/world/entity/animal/camel/Camel.java b/net/minecraft/world/entity/animal/camel/Camel.java -index f794ac7af227d413ed030457cbe4cd68e6eca969..ab0b90c300d0610e423abe7ac9e5b93305a21c5a 100644 ---- a/net/minecraft/world/entity/animal/camel/Camel.java -+++ b/net/minecraft/world/entity/animal/camel/Camel.java -@@ -321,6 +321,22 @@ public class Camel extends AbstractHorse { - return this.dashCooldown; - } - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public float generateMaxHealth(net.minecraft.util.RandomSource random) { -+ return (float) generateMaxHealth(this.level().purpurConfig.camelMaxHealthMin, this.level().purpurConfig.camelMaxHealthMax); -+ } -+ -+ @Override -+ public double generateJumpStrength(net.minecraft.util.RandomSource random) { -+ return generateJumpStrength(this.level().purpurConfig.camelJumpStrengthMin, this.level().purpurConfig.camelJumpStrengthMax); -+ } -+ -+ @Override -+ public double generateSpeed(net.minecraft.util.RandomSource random) { -+ return generateSpeed(this.level().purpurConfig.camelMovementSpeedMin, this.level().purpurConfig.camelMovementSpeedMax); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected SoundEvent getAmbientSound() { - return SoundEvents.CAMEL_AMBIENT; -diff --git a/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/net/minecraft/world/entity/animal/horse/AbstractHorse.java -index d9e4eb76209abffd0079ccdbbd2fc3f29bd67052..f58a0f50d04004587d342c1bb5f681cd485cf302 100644 ---- a/net/minecraft/world/entity/animal/horse/AbstractHorse.java -+++ b/net/minecraft/world/entity/animal/horse/AbstractHorse.java -@@ -240,6 +240,45 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.generateMaxHealth(random)); -+ this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(this.generateSpeed(random)); -+ this.getAttribute(Attributes.JUMP_STRENGTH).setBaseValue(this.generateJumpStrength(random)); -+ } -+ -+ protected double generateMaxHealth(double min, double max) { -+ if (min == max) return min; -+ int diff = Mth.floor(max - min); -+ double base = max - diff; -+ int first = Mth.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 generateSpeed(double min, double max) { -+ if (min == max) return min; -+ return min + (max - min) * this.random.nextDouble(); -+ } -+ -+ protected float generateMaxHealth(RandomSource random) { -+ return 15.0F + (float) random.nextInt(8) + (float) random.nextInt(9); -+ } -+ -+ protected double generateJumpStrength(RandomSource random) { -+ return 0.4000000059604645D + random.nextDouble() * 0.2D + random.nextDouble() * 0.2D + random.nextDouble() * 0.2D; -+ } -+ -+ protected double generateSpeed(RandomSource random) { -+ return (0.44999998807907104D + random.nextDouble() * 0.3D + random.nextDouble() * 0.3D + random.nextDouble() * 0.3D) * 0.25D; -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected void registerGoals() { - this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HorseHasRider(this)); // Purpur - Ridables -@@ -1280,7 +1319,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, - entityData = new AgeableMob.AgeableMobGroupData(0.2F); - } - -- this.randomizeAttributes(world.getRandom()); -+ //this.randomizeAttributes(world.getRandom()); // Purpur - replaced by initAttributes() - return super.finalizeSpawn(world, difficulty, spawnReason, (SpawnGroupData) entityData); - } - -diff --git a/net/minecraft/world/entity/animal/horse/Donkey.java b/net/minecraft/world/entity/animal/horse/Donkey.java -index f4ef46c6cf40993b878ee965a0af397894231ba6..8fd709bcd4c7a5a875bdc65fd4dd1420ea618e3a 100644 ---- a/net/minecraft/world/entity/animal/horse/Donkey.java -+++ b/net/minecraft/world/entity/animal/horse/Donkey.java -@@ -23,6 +23,22 @@ public class Donkey extends AbstractChestedHorse { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public float generateMaxHealth(net.minecraft.util.RandomSource random) { -+ return (float) generateMaxHealth(this.level().purpurConfig.donkeyMaxHealthMin, this.level().purpurConfig.donkeyMaxHealthMax); -+ } -+ -+ @Override -+ public double generateJumpStrength(net.minecraft.util.RandomSource random) { -+ return generateJumpStrength(this.level().purpurConfig.donkeyJumpStrengthMin, this.level().purpurConfig.donkeyJumpStrengthMax); -+ } -+ -+ @Override -+ public double generateSpeed(net.minecraft.util.RandomSource random) { -+ return generateSpeed(this.level().purpurConfig.donkeyMovementSpeedMin, this.level().purpurConfig.donkeyMovementSpeedMax); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected SoundEvent getAmbientSound() { - return SoundEvents.DONKEY_AMBIENT; -diff --git a/net/minecraft/world/entity/animal/horse/Horse.java b/net/minecraft/world/entity/animal/horse/Horse.java -index 4505bcc6ab70ee2bc969ecfaecf7cff072f48ca1..13056a0a13eeb3dcc164344b973e6ff656c0793d 100644 ---- a/net/minecraft/world/entity/animal/horse/Horse.java -+++ b/net/minecraft/world/entity/animal/horse/Horse.java -@@ -50,6 +50,22 @@ public class Horse extends AbstractHorse implements VariantHolder { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public float generateMaxHealth(RandomSource random) { -+ return (float) generateMaxHealth(this.level().purpurConfig.horseMaxHealthMin, this.level().purpurConfig.horseMaxHealthMax); -+ } -+ -+ @Override -+ public double generateJumpStrength(RandomSource random) { -+ return generateJumpStrength(this.level().purpurConfig.horseJumpStrengthMin, this.level().purpurConfig.horseJumpStrengthMax); -+ } -+ -+ @Override -+ public double generateSpeed(RandomSource random) { -+ return generateSpeed(this.level().purpurConfig.horseMovementSpeedMin, this.level().purpurConfig.horseMovementSpeedMax); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected void randomizeAttributes(RandomSource random) { - this.getAttribute(Attributes.MAX_HEALTH).setBaseValue((double)generateMaxHealth(random::nextInt)); -diff --git a/net/minecraft/world/entity/animal/horse/Llama.java b/net/minecraft/world/entity/animal/horse/Llama.java -index 0e15cb99cab5ed664dc265f3754b9da7fef8958f..83fdbf55384a5c4429d65a88fcb788e449a8862a 100644 ---- a/net/minecraft/world/entity/animal/horse/Llama.java -+++ b/net/minecraft/world/entity/animal/horse/Llama.java -@@ -123,6 +123,22 @@ public class Llama extends AbstractChestedHorse implements VariantHolder type, ServerLevelAccessor world, EntitySpawnReason spawnReason, BlockPos pos, RandomSource random) { - return checkMonsterSpawnRules(type, world, spawnReason, pos, random) && (EntitySpawnReason.isSpawner(spawnReason) || world.canSeeSky(pos)); - } -diff --git a/net/minecraft/world/entity/monster/Illusioner.java b/net/minecraft/world/entity/monster/Illusioner.java -index 8ff616fe05071bd2a197a465c7e17f35a3e72d44..6e3362324c81afacaaa0f9766e2d23a0a4f53ac3 100644 ---- a/net/minecraft/world/entity/monster/Illusioner.java -+++ b/net/minecraft/world/entity/monster/Illusioner.java -@@ -76,6 +76,15 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ protected void initAttributes() { -+ this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(this.level().purpurConfig.illusionerMovementSpeed); -+ this.getAttribute(Attributes.FOLLOW_RANGE).setBaseValue(this.level().purpurConfig.illusionerFollowRange); -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.illusionerMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.illusionerScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected void registerGoals() { - super.registerGoals(); -diff --git a/net/minecraft/world/entity/monster/MagmaCube.java b/net/minecraft/world/entity/monster/MagmaCube.java -index 4f7d99fadfa1ba31439ec02bfb107288a722e828..5ba64f9c653345b742624f18c4cf692d1e7880e1 100644 ---- a/net/minecraft/world/entity/monster/MagmaCube.java -+++ b/net/minecraft/world/entity/monster/MagmaCube.java -@@ -46,6 +46,27 @@ public class MagmaCube extends Slime { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ protected String getMaxHealthEquation() { -+ return level().purpurConfig.magmaCubeMaxHealth; -+ } -+ -+ @Override -+ protected String getAttackDamageEquation() { -+ return level().purpurConfig.magmaCubeAttackDamage; -+ } -+ -+ @Override -+ protected java.util.Map getMaxHealthCache() { -+ return level().purpurConfig.magmaCubeMaxHealthCache; -+ } -+ -+ @Override -+ protected java.util.Map getAttackDamageCache() { -+ return level().purpurConfig.magmaCubeAttackDamageCache; -+ } -+ // Purpur end - Configurable entity base attributes - public static AttributeSupplier.Builder createAttributes() { - return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, 0.2F); - } -diff --git a/net/minecraft/world/entity/monster/Phantom.java b/net/minecraft/world/entity/monster/Phantom.java -index afd00fd83e6c246afecf7042435ae119057b9e93..ee00c4c7a1e0f08cdeccab63a20c4b465fdeb549 100644 ---- a/net/minecraft/world/entity/monster/Phantom.java -+++ b/net/minecraft/world/entity/monster/Phantom.java -@@ -150,7 +150,10 @@ public class Phantom extends FlyingMob implements Enemy { - - private void updatePhantomSizeInfo() { - this.refreshDimensions(); -- this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue((double) (6 + this.getPhantomSize())); -+ // Purpur start - Configurable entity base attributes -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(getFromCache(() -> this.level().purpurConfig.phantomMaxHealth, () -> this.level().purpurConfig.phantomMaxHealthCache, () -> 20.0D)); -+ this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(getFromCache(() -> this.level().purpurConfig.phantomAttackDamage, () -> this.level().purpurConfig.phantomAttackDamageCache, () -> (double) 6 + this.getPhantomSize())); -+ // Purpur end - Configurable entity base attributes - } - - public int getPhantomSize() { -@@ -175,6 +178,22 @@ public class Phantom extends FlyingMob implements Enemy { - return true; - } - -+ // Purpur start - Configurable entity base attributes -+ private double getFromCache(java.util.function.Supplier equation, java.util.function.Supplier> cache, java.util.function.Supplier defaultValue) { -+ int size = getPhantomSize(); -+ Double value = cache.get().get(size); -+ if (value == null) { -+ try { -+ value = ((Number) scriptEngine.eval("let size = " + size + "; " + equation.get())).doubleValue(); -+ } catch (javax.script.ScriptException e) { -+ e.printStackTrace(); -+ value = defaultValue.get(); -+ } -+ cache.get().put(size, value); -+ } -+ return value; -+ } -+ // Purpur end - Configurable entity base attributes - @Override - public void tick() { - super.tick(); -diff --git a/net/minecraft/world/entity/monster/Pillager.java b/net/minecraft/world/entity/monster/Pillager.java -index a629e31e6ea0f49f88746856382fcec96918c490..78c01f0be0cc6689f68e2fcf3111d79abb5a59fb 100644 ---- a/net/minecraft/world/entity/monster/Pillager.java -+++ b/net/minecraft/world/entity/monster/Pillager.java -@@ -84,6 +84,13 @@ public class Pillager extends AbstractIllager implements CrossbowAttackMob, Inve - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.pillagerMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.pillagerScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected void registerGoals() { - super.registerGoals(); -diff --git a/net/minecraft/world/entity/monster/Ravager.java b/net/minecraft/world/entity/monster/Ravager.java -index 6222ed8408096e0bb8e9572c07c0db6971fc8308..ecf37a99fa5e8919146ba73c7313998855ea0d88 100644 ---- a/net/minecraft/world/entity/monster/Ravager.java -+++ b/net/minecraft/world/entity/monster/Ravager.java -@@ -98,6 +98,13 @@ public class Ravager extends Raider { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.ravagerMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.ravagerScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected void registerGoals() { - super.registerGoals(); -diff --git a/net/minecraft/world/entity/monster/Shulker.java b/net/minecraft/world/entity/monster/Shulker.java -index 6541e1059ca16cfd01bf01aae2c56400cbe78132..c04d6a5190f3db06601c3a0ab0ddaede3a9f88ac 100644 ---- a/net/minecraft/world/entity/monster/Shulker.java -+++ b/net/minecraft/world/entity/monster/Shulker.java -@@ -84,7 +84,7 @@ public class Shulker extends AbstractGolem implements VariantHolder public - Configurable entity base attributes - private float currentPeekAmountO; - private float currentPeekAmount; - @Nullable -@@ -115,6 +115,12 @@ public class Shulker extends AbstractGolem implements VariantHolder variant) { -diff --git a/net/minecraft/world/entity/monster/Silverfish.java b/net/minecraft/world/entity/monster/Silverfish.java -index 6f1d59651552ef7443eb8274765614d5abc984df..191724aa48081017adf3db0b6ff99a77dd4ce68d 100644 ---- a/net/minecraft/world/entity/monster/Silverfish.java -+++ b/net/minecraft/world/entity/monster/Silverfish.java -@@ -61,6 +61,15 @@ public class Silverfish extends Monster { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.silverfishMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.silverfishScale); -+ this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(this.level().purpurConfig.silverfishMovementSpeed); -+ this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(this.level().purpurConfig.silverfishAttackDamage); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected void registerGoals() { - this.friendsGoal = new Silverfish.SilverfishWakeUpFriendsGoal(this); -diff --git a/net/minecraft/world/entity/monster/Skeleton.java b/net/minecraft/world/entity/monster/Skeleton.java -index 78c8483da3c0ac7f93e236dd723fc6051427a50e..8e93da5112cbb14af1ca755c40698740303717ee 100644 ---- a/net/minecraft/world/entity/monster/Skeleton.java -+++ b/net/minecraft/world/entity/monster/Skeleton.java -@@ -46,6 +46,12 @@ public class Skeleton extends AbstractSkeleton { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.skeletonMaxHealth); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected void defineSynchedData(SynchedEntityData.Builder builder) { - super.defineSynchedData(builder); -diff --git a/net/minecraft/world/entity/monster/Slime.java b/net/minecraft/world/entity/monster/Slime.java -index b7941230b082d4de9ab77c981bd396fa1184d78e..d2cdb2119cd6e0afd57e00b1b706d36342b8858d 100644 ---- a/net/minecraft/world/entity/monster/Slime.java -+++ b/net/minecraft/world/entity/monster/Slime.java -@@ -107,6 +107,38 @@ public class Slime extends Mob implements Enemy { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ protected String getMaxHealthEquation() { -+ return level().purpurConfig.slimeMaxHealth; -+ } -+ -+ protected String getAttackDamageEquation() { -+ return level().purpurConfig.slimeAttackDamage; -+ } -+ -+ protected java.util.Map getMaxHealthCache() { -+ return level().purpurConfig.slimeMaxHealthCache; -+ } -+ -+ protected java.util.Map getAttackDamageCache() { -+ return level().purpurConfig.slimeAttackDamageCache; -+ } -+ -+ protected double getFromCache(java.util.function.Supplier equation, java.util.function.Supplier> cache, java.util.function.Supplier defaultValue) { -+ int size = getSize(); -+ Double value = cache.get().get(size); -+ if (value == null) { -+ try { -+ value = ((Number) scriptEngine.eval("let size = " + size + "; " + equation.get())).doubleValue(); -+ } catch (javax.script.ScriptException e) { -+ e.printStackTrace(); -+ value = defaultValue.get(); -+ } -+ cache.get().put(size, value); -+ } -+ return value; -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected void registerGoals() { - this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables -@@ -139,9 +171,9 @@ public class Slime extends Mob implements Enemy { - this.entityData.set(Slime.ID_SIZE, j); - this.reapplyPosition(); - this.refreshDimensions(); -- this.getAttribute(Attributes.MAX_HEALTH).setBaseValue((double) (j * j)); -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(getFromCache(this::getMaxHealthEquation, this::getMaxHealthCache, () -> (double) size * size)); // Purpur - Configurable entity base attributes - this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue((double) (0.2F + 0.1F * (float) j)); -- this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue((double) j); -+ this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(getFromCache(this::getAttackDamageEquation, this::getAttackDamageCache, () -> (double) j)); // Purpur - Configurable entity base attributes - if (heal) { - this.setHealth(this.getMaxHealth()); - } -diff --git a/net/minecraft/world/entity/monster/Spider.java b/net/minecraft/world/entity/monster/Spider.java -index d3eabdde9e9bf010cae7fc81165f0123adfcf958..26ce5425d8217f8954ceef898b806d3b56c01027 100644 ---- a/net/minecraft/world/entity/monster/Spider.java -+++ b/net/minecraft/world/entity/monster/Spider.java -@@ -68,6 +68,13 @@ public class Spider extends Monster { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.spiderMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.spiderScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected void registerGoals() { - this.goalSelector.addGoal(1, new FloatGoal(this)); -diff --git a/net/minecraft/world/entity/monster/Stray.java b/net/minecraft/world/entity/monster/Stray.java -index 879748708e3fc8c0a3f126d265e99a7c054d2a10..4b4eced856ad68c38042b5368bf1b9433ec1e8b1 100644 ---- a/net/minecraft/world/entity/monster/Stray.java -+++ b/net/minecraft/world/entity/monster/Stray.java -@@ -39,6 +39,12 @@ public class Stray extends AbstractSkeleton { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.strayMaxHealth); -+ } -+ // Purpur end - Configurable entity base attributes - public static boolean checkStraySpawnRules( - EntityType type, ServerLevelAccessor world, EntitySpawnReason spawnReason, BlockPos pos, RandomSource random - ) { -diff --git a/net/minecraft/world/entity/monster/Strider.java b/net/minecraft/world/entity/monster/Strider.java -index 7b1525c6bc46d65660588d90c3121ad3d12cf077..c66126f3a43e6e011e5f9a977ad481c96529d1d5 100644 ---- a/net/minecraft/world/entity/monster/Strider.java -+++ b/net/minecraft/world/entity/monster/Strider.java -@@ -114,6 +114,13 @@ public class Strider extends Animal implements ItemSteerable, Saddleable { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.striderMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.striderScale); -+ } -+ // Purpur end - Configurable entity base attributes - public static boolean checkStriderSpawnRules(EntityType type, LevelAccessor world, EntitySpawnReason spawnReason, BlockPos pos, RandomSource random) { - BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); - -diff --git a/net/minecraft/world/entity/monster/Vex.java b/net/minecraft/world/entity/monster/Vex.java -index fba52457f85573f5918aeeb5f3b69b3f113cc9d5..906934076dd721a39f8ee960fc7c0d1058b66ae2 100644 ---- a/net/minecraft/world/entity/monster/Vex.java -+++ b/net/minecraft/world/entity/monster/Vex.java -@@ -103,6 +103,13 @@ public class Vex extends Monster implements TraceableEntity { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.vexMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.vexScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - public boolean isFlapping() { - return this.tickCount % Vex.TICKS_PER_FLAP == 0; -diff --git a/net/minecraft/world/entity/monster/Vindicator.java b/net/minecraft/world/entity/monster/Vindicator.java -index 5bf2aad976be5d6149b8252c84cd870551a2aa8e..065bd31afe948c1ffab4da6f2a236cd931e75259 100644 ---- a/net/minecraft/world/entity/monster/Vindicator.java -+++ b/net/minecraft/world/entity/monster/Vindicator.java -@@ -72,6 +72,13 @@ public class Vindicator extends AbstractIllager { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.vindicatorMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.vindicatorScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected void registerGoals() { - super.registerGoals(); -diff --git a/net/minecraft/world/entity/monster/Witch.java b/net/minecraft/world/entity/monster/Witch.java -index 5cba860f9ce81d90eec4c6bf45699d28cf8d93e6..9b2d76722385ccf9d0ace747339ca7705ca41f4f 100644 ---- a/net/minecraft/world/entity/monster/Witch.java -+++ b/net/minecraft/world/entity/monster/Witch.java -@@ -74,6 +74,13 @@ public class Witch extends Raider implements RangedAttackMob { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.witchMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.witchScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected void registerGoals() { - super.registerGoals(); -diff --git a/net/minecraft/world/entity/monster/WitherSkeleton.java b/net/minecraft/world/entity/monster/WitherSkeleton.java -index 626cab5a974d2c8736123cc23e535b5cf0e5349e..feb1b516c7ac7200e7cebeea739369426e87bf27 100644 ---- a/net/minecraft/world/entity/monster/WitherSkeleton.java -+++ b/net/minecraft/world/entity/monster/WitherSkeleton.java -@@ -53,6 +53,13 @@ public class WitherSkeleton extends AbstractSkeleton { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.witherSkeletonMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.witherSkeletonScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected void registerGoals() { - this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractPiglin.class, true)); -diff --git a/net/minecraft/world/entity/monster/Zoglin.java b/net/minecraft/world/entity/monster/Zoglin.java -index 2ac14783e7b5739a13c487d5028ecba38480980d..b5c4e127298795567ea4f35aa5a209ee6e1629b3 100644 ---- a/net/minecraft/world/entity/monster/Zoglin.java -+++ b/net/minecraft/world/entity/monster/Zoglin.java -@@ -102,6 +102,13 @@ public class Zoglin extends Monster implements HoglinBase { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.zoglinMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.zoglinScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected Brain.Provider brainProvider() { - return Brain.provider(MEMORY_TYPES, SENSOR_TYPES); -diff --git a/net/minecraft/world/entity/monster/Zombie.java b/net/minecraft/world/entity/monster/Zombie.java -index 9b4b923117a7025bdbb6d222c6388aeae9bef8a2..5763d259162750297e08acc51551489150dbc593 100644 ---- a/net/minecraft/world/entity/monster/Zombie.java -+++ b/net/minecraft/world/entity/monster/Zombie.java -@@ -127,6 +127,13 @@ public class Zombie extends Monster { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.zombieMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.zombieScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected void registerGoals() { - this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables -@@ -627,7 +634,7 @@ public class Zombie extends Monster { - } - - protected void randomizeReinforcementsChance() { -- this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).setBaseValue(this.random.nextDouble() * 0.10000000149011612D); -+ this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).setBaseValue(this.random.nextDouble() * this.level().purpurConfig.zombieSpawnReinforcements); // Purpur - Configurable entity base attributes - } - - @Override -diff --git a/net/minecraft/world/entity/monster/ZombieVillager.java b/net/minecraft/world/entity/monster/ZombieVillager.java -index 9fafe05ef0ffc1120873727082290a8ea177d62f..35d8cef3c84bfd1bbf8afe2885b4f303a4985cdd 100644 ---- a/net/minecraft/world/entity/monster/ZombieVillager.java -+++ b/net/minecraft/world/entity/monster/ZombieVillager.java -@@ -102,6 +102,17 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.zombieVillagerMaxHealth); -+ } -+ -+ @Override -+ protected void randomizeReinforcementsChance() { -+ this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.SPAWN_REINFORCEMENTS_CHANCE).setBaseValue(this.random.nextDouble() * this.level().purpurConfig.zombieVillagerSpawnReinforcements); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected void defineSynchedData(SynchedEntityData.Builder builder) { - super.defineSynchedData(builder); -diff --git a/net/minecraft/world/entity/monster/ZombifiedPiglin.java b/net/minecraft/world/entity/monster/ZombifiedPiglin.java -index 69c291c3347a3e3f454ecb8f418a310bbd688a43..ca74450f13198fd7bf0190b4dc1df4288df5729d 100644 ---- a/net/minecraft/world/entity/monster/ZombifiedPiglin.java -+++ b/net/minecraft/world/entity/monster/ZombifiedPiglin.java -@@ -80,6 +80,13 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.zombifiedPiglinMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.zombifiedPiglinScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - public void setPersistentAngerTarget(@Nullable UUID angryAt) { - this.persistentAngerTarget = angryAt; -@@ -262,7 +269,7 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { - - @Override - protected void randomizeReinforcementsChance() { -- this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).setBaseValue(0.0D); -+ this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).setBaseValue(this.random.nextDouble() * this.level().purpurConfig.zombifiedPiglinSpawnReinforcements); // Purpur - Configurable entity base attributes - } - - @Nullable -diff --git a/net/minecraft/world/entity/monster/creaking/Creaking.java b/net/minecraft/world/entity/monster/creaking/Creaking.java -index 6716bfa903be5ab34b80c963cc9d6a8a26272621..1f37384368c26b4bdd69533887a8e9b8456f7096 100644 ---- a/net/minecraft/world/entity/monster/creaking/Creaking.java -+++ b/net/minecraft/world/entity/monster/creaking/Creaking.java -@@ -129,6 +129,13 @@ public class Creaking extends Monster { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.creakingMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.creakingScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected BodyRotationControl createBodyControl() { - return new Creaking.CreakingBodyRotationControl(this); -diff --git a/net/minecraft/world/entity/monster/hoglin/Hoglin.java b/net/minecraft/world/entity/monster/hoglin/Hoglin.java -index 4ab971e86b48ce3010928fe9046e8f68224719ca..476dcc613f566d88273f195b847e6b4dec777e44 100644 ---- a/net/minecraft/world/entity/monster/hoglin/Hoglin.java -+++ b/net/minecraft/world/entity/monster/hoglin/Hoglin.java -@@ -88,6 +88,13 @@ public class Hoglin extends Animal implements Enemy, HoglinBase { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.hoglinMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.hoglinScale); -+ } -+ // Purpur end - Configurable entity base attributes - @VisibleForTesting - public void setTimeInOverworld(int timeInOverworld) { - this.timeInOverworld = timeInOverworld; -diff --git a/net/minecraft/world/entity/monster/piglin/Piglin.java b/net/minecraft/world/entity/monster/piglin/Piglin.java -index b19e3b442a650f773df462e32088648a2b7eafd4..1a40babc8f6b3f56377cb2af45e9d17d0028a77b 100644 ---- a/net/minecraft/world/entity/monster/piglin/Piglin.java -+++ b/net/minecraft/world/entity/monster/piglin/Piglin.java -@@ -116,6 +116,13 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.piglinMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.piglinScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - public void addAdditionalSaveData(CompoundTag nbt) { - super.addAdditionalSaveData(nbt); -diff --git a/net/minecraft/world/entity/monster/piglin/PiglinBrute.java b/net/minecraft/world/entity/monster/piglin/PiglinBrute.java -index 3dc234f8cea8769f715a4913ae4ecf7d47433577..a0fa32a1217bbdae2c91e5a51598d7bd555ca1eb 100644 ---- a/net/minecraft/world/entity/monster/piglin/PiglinBrute.java -+++ b/net/minecraft/world/entity/monster/piglin/PiglinBrute.java -@@ -82,6 +82,13 @@ public class PiglinBrute extends AbstractPiglin { - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.piglinBruteMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.piglinBruteScale); -+ } -+ // Purpur end - Configurable entity base attributes - public static AttributeSupplier.Builder createAttributes() { - return Monster.createMonsterAttributes() - .add(Attributes.MAX_HEALTH, 50.0) -diff --git a/net/minecraft/world/entity/npc/Villager.java b/net/minecraft/world/entity/npc/Villager.java -index 066836e450ca8d104990c3c5fba5fe3dad2e136e..39f2091391222bcd4ab0f2677f896c5ecdc6e86c 100644 ---- a/net/minecraft/world/entity/npc/Villager.java -+++ b/net/minecraft/world/entity/npc/Villager.java -@@ -178,6 +178,13 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.villagerMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.villagerScale); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - public Brain getBrain() { - return (Brain) super.getBrain(); // CraftBukkit - decompile error -diff --git a/net/minecraft/world/entity/npc/WanderingTrader.java b/net/minecraft/world/entity/npc/WanderingTrader.java -index c5bef9f0ad2a0f57d8c37ea0833e899dc588d30f..8e12ae313c76d742b61aa83a35d41d83b92bded5 100644 ---- a/net/minecraft/world/entity/npc/WanderingTrader.java -+++ b/net/minecraft/world/entity/npc/WanderingTrader.java -@@ -89,6 +89,12 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill - } - // Purpur end - Ridables - -+ // Purpur start - Configurable entity base attributes -+ @Override -+ public void initAttributes() { -+ this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.wanderingTraderMaxHealth); -+ } -+ // Purpur end - Configurable entity base attributes - @Override - protected void registerGoals() { - this.goalSelector.addGoal(0, new FloatGoal(this)); -diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -index 5004e86747306cc8d4bbed6f10d3a6e9047cb5f4..ee9bcb7d011f20575cbbbe2e0ded1e53087aba7a 100644 ---- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -@@ -105,134 +105,261 @@ public class PurpurWorldConfig { - public boolean allayRidable = false; - public boolean allayRidableInWater = true; - public boolean allayControllable = true; -+ public double allayMaxHealth = 20.0D; -+ public double allayScale = 1.0D; - private void allaySettings() { - allayRidable = getBoolean("mobs.allay.ridable", allayRidable); - allayRidableInWater = getBoolean("mobs.allay.ridable-in-water", allayRidableInWater); - allayControllable = getBoolean("mobs.allay.controllable", allayControllable); -+ allayMaxHealth = getDouble("mobs.allay.attributes.max_health", allayMaxHealth); -+ allayScale = Mth.clamp(getDouble("mobs.allay.attributes.scale", allayScale), 0.0625D, 16.0D); - } - - public boolean armadilloRidable = false; - public boolean armadilloRidableInWater = true; - public boolean armadilloControllable = true; -+ public double armadilloMaxHealth = 12.0D; -+ public double armadilloScale = 1.0D; - private void armadilloSettings() { - armadilloRidable = getBoolean("mobs.armadillo.ridable", armadilloRidable); - armadilloRidableInWater = getBoolean("mobs.armadillo.ridable-in-water", armadilloRidableInWater); - armadilloControllable = getBoolean("mobs.armadillo.controllable", armadilloControllable); -+ armadilloMaxHealth = getDouble("mobs.armadillo.attributes.max_health", armadilloMaxHealth); -+ armadilloScale = Mth.clamp(getDouble("mobs.armadillo.attributes.scale", armadilloScale), 0.0625D, 16.0D); - } - - public boolean axolotlRidable = false; - public boolean axolotlControllable = true; -+ public double axolotlMaxHealth = 14.0D; -+ public double axolotlScale = 1.0D; - private void axolotlSettings() { - axolotlRidable = getBoolean("mobs.axolotl.ridable", axolotlRidable); - axolotlControllable = getBoolean("mobs.axolotl.controllable", axolotlControllable); -+ axolotlMaxHealth = getDouble("mobs.axolotl.attributes.max_health", axolotlMaxHealth); -+ axolotlScale = Mth.clamp(getDouble("mobs.axolotl.attributes.scale", axolotlScale), 0.0625D, 16.0D); - } - - public boolean batRidable = false; - public boolean batRidableInWater = true; - public boolean batControllable = true; - public double batMaxY = 320D; -+ public double batMaxHealth = 6.0D; -+ public double batScale = 1.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); - batControllable = getBoolean("mobs.bat.controllable", batControllable); - 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); -+ batScale = Mth.clamp(getDouble("mobs.bat.attributes.scale", batScale), 0.0625D, 16.0D); -+ batFollowRange = getDouble("mobs.bat.attributes.follow_range", batFollowRange); -+ batKnockbackResistance = getDouble("mobs.bat.attributes.knockback_resistance", batKnockbackResistance); -+ batMovementSpeed = getDouble("mobs.bat.attributes.movement_speed", batMovementSpeed); -+ batFlyingSpeed = getDouble("mobs.bat.attributes.flying_speed", batFlyingSpeed); -+ batArmor = getDouble("mobs.bat.attributes.armor", batArmor); -+ batArmorToughness = getDouble("mobs.bat.attributes.armor_toughness", batArmorToughness); -+ batAttackKnockback = getDouble("mobs.bat.attributes.attack_knockback", batAttackKnockback); - } - - public boolean beeRidable = false; - public boolean beeRidableInWater = true; - public boolean beeControllable = true; - public double beeMaxY = 320D; -+ public double beeMaxHealth = 10.0D; -+ public double beeScale = 1.0D; - private void beeSettings() { - beeRidable = getBoolean("mobs.bee.ridable", beeRidable); - beeRidableInWater = getBoolean("mobs.bee.ridable-in-water", beeRidableInWater); - beeControllable = getBoolean("mobs.bee.controllable", beeControllable); - beeMaxY = getDouble("mobs.bee.ridable-max-y", beeMaxY); -+ 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); -+ beeScale = Mth.clamp(getDouble("mobs.bee.attributes.scale", beeScale), 0.0625D, 16.0D); - } - - public boolean blazeRidable = false; - public boolean blazeRidableInWater = true; - public boolean blazeControllable = true; - public double blazeMaxY = 320D; -+ public double blazeMaxHealth = 20.0D; -+ public double blazeScale = 1.0D; - private void blazeSettings() { - blazeRidable = getBoolean("mobs.blaze.ridable", blazeRidable); - blazeRidableInWater = getBoolean("mobs.blaze.ridable-in-water", blazeRidableInWater); - blazeControllable = getBoolean("mobs.blaze.controllable", blazeControllable); - 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); -+ blazeScale = Mth.clamp(getDouble("mobs.blaze.attributes.scale", blazeScale), 0.0625D, 16.0D); - } - - public boolean boggedRidable = false; - public boolean boggedRidableInWater = true; - public boolean boggedControllable = true; -+ public double boggedMaxHealth = 16.0D; -+ public double boggedScale = 1.0D; - private void boggedSettings() { - boggedRidable = getBoolean("mobs.bogged.ridable", boggedRidable); - boggedRidableInWater = getBoolean("mobs.bogged.ridable-in-water", boggedRidableInWater); - boggedControllable = getBoolean("mobs.bogged.controllable", boggedControllable); -+ boggedMaxHealth = getDouble("mobs.bogged.attributes.max_health", boggedMaxHealth); -+ boggedScale = Mth.clamp(getDouble("mobs.bogged.attributes.scale", boggedScale), 0.0625D, 16.0D); - } - - public boolean camelRidableInWater = false; -+ public double camelMaxHealthMin = 32.0D; -+ public double camelMaxHealthMax = 32.0D; -+ public double camelJumpStrengthMin = 0.42D; -+ public double camelJumpStrengthMax = 0.42D; -+ public double camelMovementSpeedMin = 0.09D; -+ public double camelMovementSpeedMax = 0.09D; - private void camelSettings() { - camelRidableInWater = getBoolean("mobs.camel.ridable-in-water", camelRidableInWater); -+ camelMaxHealthMin = getDouble("mobs.camel.attributes.max_health.min", camelMaxHealthMin); -+ camelMaxHealthMax = getDouble("mobs.camel.attributes.max_health.max", camelMaxHealthMax); -+ camelJumpStrengthMin = getDouble("mobs.camel.attributes.jump_strength.min", camelJumpStrengthMin); -+ camelJumpStrengthMax = getDouble("mobs.camel.attributes.jump_strength.max", camelJumpStrengthMax); -+ camelMovementSpeedMin = getDouble("mobs.camel.attributes.movement_speed.min", camelMovementSpeedMin); -+ camelMovementSpeedMax = getDouble("mobs.camel.attributes.movement_speed.max", camelMovementSpeedMax); - } - - public boolean catRidable = false; - public boolean catRidableInWater = true; - public boolean catControllable = true; -+ public double catMaxHealth = 10.0D; -+ public double catScale = 1.0D; - private void catSettings() { - catRidable = getBoolean("mobs.cat.ridable", catRidable); - catRidableInWater = getBoolean("mobs.cat.ridable-in-water", catRidableInWater); - catControllable = getBoolean("mobs.cat.controllable", catControllable); -+ 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); -+ catScale = Mth.clamp(getDouble("mobs.cat.attributes.scale", catScale), 0.0625D, 16.0D); - } - - public boolean caveSpiderRidable = false; - public boolean caveSpiderRidableInWater = true; - public boolean caveSpiderControllable = true; -+ public double caveSpiderMaxHealth = 12.0D; -+ public double caveSpiderScale = 1.0D; - private void caveSpiderSettings() { - caveSpiderRidable = getBoolean("mobs.cave_spider.ridable", caveSpiderRidable); - caveSpiderRidableInWater = getBoolean("mobs.cave_spider.ridable-in-water", caveSpiderRidableInWater); - caveSpiderControllable = getBoolean("mobs.cave_spider.controllable", caveSpiderControllable); -+ 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); -+ caveSpiderScale = Mth.clamp(getDouble("mobs.cave_spider.attributes.scale", caveSpiderScale), 0.0625D, 16.0D); - } - - public boolean chickenRidable = false; - public boolean chickenRidableInWater = false; - public boolean chickenControllable = true; -+ public double chickenMaxHealth = 4.0D; -+ public double chickenScale = 1.0D; - private void chickenSettings() { - chickenRidable = getBoolean("mobs.chicken.ridable", chickenRidable); - chickenRidableInWater = getBoolean("mobs.chicken.ridable-in-water", chickenRidableInWater); - chickenControllable = getBoolean("mobs.chicken.controllable", chickenControllable); -+ 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); -+ chickenScale = Mth.clamp(getDouble("mobs.chicken.attributes.scale", chickenScale), 0.0625D, 16.0D); - } - - public boolean codRidable = false; - public boolean codControllable = true; -+ public double codMaxHealth = 3.0D; -+ public double codScale = 1.0D; - private void codSettings() { - codRidable = getBoolean("mobs.cod.ridable", codRidable); - codControllable = getBoolean("mobs.cod.controllable", codControllable); -+ 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); -+ codScale = Mth.clamp(getDouble("mobs.cod.attributes.scale", codScale), 0.0625D, 16.0D); - } - - public boolean cowRidable = false; - public boolean cowRidableInWater = true; - public boolean cowControllable = true; -+ public double cowMaxHealth = 10.0D; -+ public double cowScale = 1.0D; - private void cowSettings() { - cowRidable = getBoolean("mobs.cow.ridable", cowRidable); - cowRidableInWater = getBoolean("mobs.cow.ridable-in-water", cowRidableInWater); - cowControllable = getBoolean("mobs.cow.controllable", cowControllable); -+ 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); -+ cowScale = Mth.clamp(getDouble("mobs.cow.attributes.scale", cowScale), 0.0625D, 16.0D); - } - - public boolean creakingRidable = false; - public boolean creakingRidableInWater = true; - public boolean creakingControllable = true; -+ public double creakingMaxHealth = 1.0D; -+ public double creakingScale = 1.0D; - private void creakingSettings() { - creakingRidable = getBoolean("mobs.creaking.ridable", creakingRidable); - creakingRidableInWater = getBoolean("mobs.creaking.ridable-in-water", creakingRidableInWater); - creakingControllable = getBoolean("mobs.creaking.controllable", creakingControllable); -+ creakingMaxHealth = getDouble("mobs.creaking.attributes.max_health", creakingMaxHealth); -+ creakingScale = Mth.clamp(getDouble("mobs.creaking.attributes.scale", creakingScale), 0.0625D, 16.0D); - } - - public boolean creeperRidable = false; - public boolean creeperRidableInWater = true; - public boolean creeperControllable = true; -+ public double creeperMaxHealth = 20.0D; -+ public double creeperScale = 1.0D; - private void creeperSettings() { - creeperRidable = getBoolean("mobs.creeper.ridable", creeperRidable); - creeperRidableInWater = getBoolean("mobs.creeper.ridable-in-water", creeperRidableInWater); - creeperControllable = getBoolean("mobs.creeper.controllable", creeperControllable); -+ 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); -+ creeperScale = Mth.clamp(getDouble("mobs.creeper.attributes.scale", creeperScale), 0.0625D, 16.0D); - } - - public boolean dolphinRidable = false; -@@ -240,80 +367,175 @@ public class PurpurWorldConfig { - public int dolphinSpitCooldown = 20; - public float dolphinSpitSpeed = 1.0F; - public float dolphinSpitDamage = 2.0F; -+ public double dolphinMaxHealth = 10.0D; -+ public double dolphinScale = 1.0D; - private void dolphinSettings() { - dolphinRidable = getBoolean("mobs.dolphin.ridable", dolphinRidable); - dolphinControllable = getBoolean("mobs.dolphin.controllable", dolphinControllable); - dolphinSpitCooldown = getInt("mobs.dolphin.spit.cooldown", dolphinSpitCooldown); - dolphinSpitSpeed = (float) getDouble("mobs.dolphin.spit.speed", dolphinSpitSpeed); - dolphinSpitDamage = (float) getDouble("mobs.dolphin.spit.damage", dolphinSpitDamage); -+ 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); -+ dolphinScale = Mth.clamp(getDouble("mobs.dolphin.attributes.scale", dolphinScale), 0.0625D, 16.0D); - } - - public boolean donkeyRidableInWater = false; -+ 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); -+ 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; - public boolean drownedRidableInWater = true; - public boolean drownedControllable = true; -+ public double drownedMaxHealth = 20.0D; -+ public double drownedScale = 1.0D; -+ public double drownedSpawnReinforcements = 0.1D; - private void drownedSettings() { - drownedRidable = getBoolean("mobs.drowned.ridable", drownedRidable); - drownedRidableInWater = getBoolean("mobs.drowned.ridable-in-water", drownedRidableInWater); - drownedControllable = getBoolean("mobs.drowned.controllable", drownedControllable); -+ 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); -+ drownedScale = Mth.clamp(getDouble("mobs.drowned.attributes.scale", drownedScale), 0.0625D, 16.0D); -+ drownedSpawnReinforcements = getDouble("mobs.drowned.attributes.spawn_reinforcements", drownedSpawnReinforcements); - } - - public boolean elderGuardianRidable = false; - public boolean elderGuardianControllable = true; -+ public double elderGuardianMaxHealth = 80.0D; -+ public double elderGuardianScale = 1.0D; - private void elderGuardianSettings() { - elderGuardianRidable = getBoolean("mobs.elder_guardian.ridable", elderGuardianRidable); - elderGuardianControllable = getBoolean("mobs.elder_guardian.controllable", elderGuardianControllable); -+ 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); -+ elderGuardianScale = Mth.clamp(getDouble("mobs.elder_guardian.attributes.scale", elderGuardianScale), 0.0625D, 16.0D); - } - - public boolean enderDragonRidable = false; - public boolean enderDragonRidableInWater = true; - public boolean enderDragonControllable = true; - public double enderDragonMaxY = 320D; -+ public double enderDragonMaxHealth = 200.0D; - private void enderDragonSettings() { - enderDragonRidable = getBoolean("mobs.ender_dragon.ridable", enderDragonRidable); - enderDragonRidableInWater = getBoolean("mobs.ender_dragon.ridable-in-water", enderDragonRidableInWater); - enderDragonControllable = getBoolean("mobs.ender_dragon.controllable", enderDragonControllable); - enderDragonMaxY = getDouble("mobs.ender_dragon.ridable-max-y", enderDragonMaxY); -+ 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 = true; - public boolean endermanControllable = true; -+ public double endermanMaxHealth = 40.0D; -+ public double endermanScale = 1.0D; - private void endermanSettings() { - endermanRidable = getBoolean("mobs.enderman.ridable", endermanRidable); - endermanRidableInWater = getBoolean("mobs.enderman.ridable-in-water", endermanRidableInWater); - endermanControllable = getBoolean("mobs.enderman.controllable", endermanControllable); -+ 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); -+ endermanScale = Mth.clamp(getDouble("mobs.enderman.attributes.scale", endermanScale), 0.0625D, 16.0D); - } - - public boolean endermiteRidable = false; - public boolean endermiteRidableInWater = true; - public boolean endermiteControllable = true; -+ public double endermiteMaxHealth = 8.0D; -+ public double endermiteScale = 1.0D; - private void endermiteSettings() { - endermiteRidable = getBoolean("mobs.endermite.ridable", endermiteRidable); - endermiteRidableInWater = getBoolean("mobs.endermite.ridable-in-water", endermiteRidableInWater); - endermiteControllable = getBoolean("mobs.endermite.controllable", endermiteControllable); -+ 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); -+ endermiteScale = Mth.clamp(getDouble("mobs.endermite.attributes.scale", endermiteScale), 0.0625D, 16.0D); - } - - public boolean evokerRidable = false; - public boolean evokerRidableInWater = true; - public boolean evokerControllable = true; -+ public double evokerMaxHealth = 24.0D; -+ public double evokerScale = 1.0D; - private void evokerSettings() { - evokerRidable = getBoolean("mobs.evoker.ridable", evokerRidable); - evokerRidableInWater = getBoolean("mobs.evoker.ridable-in-water", evokerRidableInWater); - evokerControllable = getBoolean("mobs.evoker.controllable", evokerControllable); -+ 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); -+ evokerScale = Mth.clamp(getDouble("mobs.evoker.attributes.scale", evokerScale), 0.0625D, 16.0D); - } - - public boolean foxRidable = false; - public boolean foxRidableInWater = true; - public boolean foxControllable = true; -+ public double foxMaxHealth = 10.0D; -+ public double foxScale = 1.0D; - private void foxSettings() { - foxRidable = getBoolean("mobs.fox.ridable", foxRidable); - foxRidableInWater = getBoolean("mobs.fox.ridable-in-water", foxRidableInWater); - foxControllable = getBoolean("mobs.fox.controllable", foxControllable); -+ 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); -+ foxScale = Mth.clamp(getDouble("mobs.fox.attributes.scale", foxScale), 0.0625D, 16.0D); - } - - public boolean frogRidable = false; -@@ -331,147 +553,342 @@ public class PurpurWorldConfig { - public boolean ghastRidableInWater = true; - public boolean ghastControllable = true; - public double ghastMaxY = 320D; -+ public double ghastMaxHealth = 10.0D; -+ public double ghastScale = 1.0D; - private void ghastSettings() { - ghastRidable = getBoolean("mobs.ghast.ridable", ghastRidable); - ghastRidableInWater = getBoolean("mobs.ghast.ridable-in-water", ghastRidableInWater); - ghastControllable = getBoolean("mobs.ghast.controllable", ghastControllable); - 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); -+ ghastScale = Mth.clamp(getDouble("mobs.ghast.attributes.scale", ghastScale), 0.0625D, 16.0D); - } - - public boolean giantRidable = false; - public boolean giantRidableInWater = true; - public boolean giantControllable = true; -+ public double giantMovementSpeed = 0.5D; -+ public double giantAttackDamage = 50.0D; -+ public double giantMaxHealth = 100.0D; -+ public double giantScale = 1.0D; - private void giantSettings() { - giantRidable = getBoolean("mobs.giant.ridable", giantRidable); - giantRidableInWater = getBoolean("mobs.giant.ridable-in-water", giantRidableInWater); - giantControllable = getBoolean("mobs.giant.controllable", giantControllable); -+ giantMovementSpeed = getDouble("mobs.giant.movement-speed", giantMovementSpeed); -+ giantAttackDamage = getDouble("mobs.giant.attack-damage", giantAttackDamage); -+ if (PurpurConfig.version < 8) { -+ double oldValue = getDouble("mobs.giant.max-health", giantMaxHealth); -+ 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); -+ giantScale = Mth.clamp(getDouble("mobs.giant.attributes.scale", giantScale), 0.0625D, 16.0D); - } - - public boolean glowSquidRidable = false; - public boolean glowSquidControllable = true; -+ public double glowSquidMaxHealth = 10.0D; -+ public double glowSquidScale = 1.0D; - private void glowSquidSettings() { - glowSquidRidable = getBoolean("mobs.glow_squid.ridable", glowSquidRidable); - glowSquidControllable = getBoolean("mobs.glow_squid.controllable", glowSquidControllable); -+ glowSquidMaxHealth = getDouble("mobs.glow_squid.attributes.max_health", glowSquidMaxHealth); -+ glowSquidScale = Mth.clamp(getDouble("mobs.glow_squid.attributes.scale", glowSquidScale), 0.0625D, 16.0D); - } - - public boolean goatRidable = false; - public boolean goatRidableInWater = true; - public boolean goatControllable = true; -+ public double goatMaxHealth = 10.0D; -+ public double goatScale = 1.0D; - private void goatSettings() { - goatRidable = getBoolean("mobs.goat.ridable", goatRidable); - goatRidableInWater = getBoolean("mobs.goat.ridable-in-water", goatRidableInWater); - goatControllable = getBoolean("mobs.goat.controllable", goatControllable); -+ goatMaxHealth = getDouble("mobs.goat.attributes.max_health", goatMaxHealth); -+ goatScale = Mth.clamp(getDouble("mobs.goat.attributes.scale", goatScale), 0.0625D, 16.0D); - } - - public boolean guardianRidable = false; - public boolean guardianControllable = true; -+ public double guardianMaxHealth = 30.0D; -+ public double guardianScale = 1.0D; - private void guardianSettings() { - guardianRidable = getBoolean("mobs.guardian.ridable", guardianRidable); - guardianControllable = getBoolean("mobs.guardian.controllable", guardianControllable); -+ 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); -+ guardianScale = Mth.clamp(getDouble("mobs.guardian.attributes.scale", guardianScale), 0.0625D, 16.0D); - } - - public boolean hoglinRidable = false; - public boolean hoglinRidableInWater = true; - public boolean hoglinControllable = true; -+ public double hoglinMaxHealth = 40.0D; -+ public double hoglinScale = 1.0D; - private void hoglinSettings() { - hoglinRidable = getBoolean("mobs.hoglin.ridable", hoglinRidable); - hoglinRidableInWater = getBoolean("mobs.hoglin.ridable-in-water", hoglinRidableInWater); - hoglinControllable = getBoolean("mobs.hoglin.controllable", hoglinControllable); -+ 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); -+ hoglinScale = Mth.clamp(getDouble("mobs.hoglin.attributes.scale", hoglinScale), 0.0625D, 16.0D); - } - - public boolean horseRidableInWater = false; -+ 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); -+ 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; - public boolean huskRidableInWater = true; - public boolean huskControllable = true; -+ public double huskMaxHealth = 20.0D; -+ public double huskScale = 1.0D; -+ public double huskSpawnReinforcements = 0.1D; - private void huskSettings() { - huskRidable = getBoolean("mobs.husk.ridable", huskRidable); - huskRidableInWater = getBoolean("mobs.husk.ridable-in-water", huskRidableInWater); - huskControllable = getBoolean("mobs.husk.controllable", huskControllable); -+ 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); -+ huskScale = Mth.clamp(getDouble("mobs.husk.attributes.scale", huskScale), 0.0625D, 16.0D); -+ huskSpawnReinforcements = getDouble("mobs.husk.attributes.spawn_reinforcements", huskSpawnReinforcements); - } - - public boolean illusionerRidable = false; - public boolean illusionerRidableInWater = true; - public boolean illusionerControllable = true; -+ public double illusionerMovementSpeed = 0.5D; -+ public double illusionerFollowRange = 18.0D; -+ public double illusionerMaxHealth = 32.0D; -+ public double illusionerScale = 1.0D; - private void illusionerSettings() { - illusionerRidable = getBoolean("mobs.illusioner.ridable", illusionerRidable); - illusionerRidableInWater = getBoolean("mobs.illusioner.ridable-in-water", illusionerRidableInWater); - illusionerControllable = getBoolean("mobs.illusioner.controllable", illusionerControllable); -+ illusionerMovementSpeed = getDouble("mobs.illusioner.movement-speed", illusionerMovementSpeed); -+ illusionerFollowRange = getDouble("mobs.illusioner.follow-range", illusionerFollowRange); -+ if (PurpurConfig.version < 8) { -+ double oldValue = getDouble("mobs.illusioner.max-health", illusionerMaxHealth); -+ 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); -+ illusionerScale = Mth.clamp(getDouble("mobs.illusioner.attributes.scale", illusionerScale), 0.0625D, 16.0D); - } - - public boolean ironGolemRidable = false; - public boolean ironGolemRidableInWater = true; - public boolean ironGolemControllable = true; - public boolean ironGolemCanSwim = false; -+ public double ironGolemMaxHealth = 100.0D; -+ public double ironGolemScale = 1.0D; - private void ironGolemSettings() { - ironGolemRidable = getBoolean("mobs.iron_golem.ridable", ironGolemRidable); - ironGolemRidableInWater = getBoolean("mobs.iron_golem.ridable-in-water", ironGolemRidableInWater); - ironGolemControllable = getBoolean("mobs.iron_golem.controllable", ironGolemControllable); - 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); -+ ironGolemScale = Mth.clamp(getDouble("mobs.iron_golem.attributes.scale", ironGolemScale), 0.0625D, 16.0D); - } - - public boolean llamaRidable = false; - public boolean llamaRidableInWater = false; - public boolean llamaControllable = true; -+ 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); - llamaControllable = getBoolean("mobs.llama.controllable", llamaControllable); -+ 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 magmaCubeRidable = false; - public boolean magmaCubeRidableInWater = true; - public boolean magmaCubeControllable = true; -+ public String magmaCubeMaxHealth = "size * size"; -+ public String magmaCubeAttackDamage = "size"; -+ public Map magmaCubeMaxHealthCache = new HashMap<>(); -+ public Map magmaCubeAttackDamageCache = new HashMap<>(); - private void magmaCubeSettings() { - magmaCubeRidable = getBoolean("mobs.magma_cube.ridable", magmaCubeRidable); - magmaCubeRidableInWater = getBoolean("mobs.magma_cube.ridable-in-water", magmaCubeRidableInWater); - magmaCubeControllable = getBoolean("mobs.magma_cube.controllable", magmaCubeControllable); -+ 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); -+ magmaCubeAttackDamage = getString("mobs.magma_cube.attributes.attack_damage", magmaCubeAttackDamage); -+ magmaCubeMaxHealthCache.clear(); -+ magmaCubeAttackDamageCache.clear(); - } - - public boolean mooshroomRidable = false; - public boolean mooshroomRidableInWater = true; - public boolean mooshroomControllable = true; -+ public double mooshroomMaxHealth = 10.0D; -+ public double mooshroomScale = 1.0D; - private void mooshroomSettings() { - mooshroomRidable = getBoolean("mobs.mooshroom.ridable", mooshroomRidable); - mooshroomRidableInWater = getBoolean("mobs.mooshroom.ridable-in-water", mooshroomRidableInWater); - mooshroomControllable = getBoolean("mobs.mooshroom.controllable", mooshroomControllable); -+ 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); -+ mooshroomScale = Mth.clamp(getDouble("mobs.mooshroom.attributes.scale", mooshroomScale), 0.0625D, 16.0D); - } - - public boolean muleRidableInWater = false; -+ 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); -+ 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 = true; - public boolean ocelotControllable = true; -+ public double ocelotMaxHealth = 10.0D; -+ public double ocelotScale = 1.0D; - private void ocelotSettings() { - ocelotRidable = getBoolean("mobs.ocelot.ridable", ocelotRidable); - ocelotRidableInWater = getBoolean("mobs.ocelot.ridable-in-water", ocelotRidableInWater); - ocelotControllable = getBoolean("mobs.ocelot.controllable", ocelotControllable); -+ 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); -+ ocelotScale = Mth.clamp(getDouble("mobs.ocelot.attributes.scale", ocelotScale), 0.0625D, 16.0D); - } - - public boolean pandaRidable = false; - public boolean pandaRidableInWater = true; - public boolean pandaControllable = true; -+ public double pandaMaxHealth = 20.0D; -+ public double pandaScale = 1.0D; - private void pandaSettings() { - pandaRidable = getBoolean("mobs.panda.ridable", pandaRidable); - pandaRidableInWater = getBoolean("mobs.panda.ridable-in-water", pandaRidableInWater); - pandaControllable = getBoolean("mobs.panda.controllable", pandaControllable); -+ 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); -+ pandaScale = Mth.clamp(getDouble("mobs.panda.attributes.scale", pandaScale), 0.0625D, 16.0D); - } - - public boolean parrotRidable = false; - public boolean parrotRidableInWater = true; - public boolean parrotControllable = true; - public double parrotMaxY = 320D; -+ public double parrotMaxHealth = 6.0D; -+ public double parrotScale = 1.0D; - private void parrotSettings() { - parrotRidable = getBoolean("mobs.parrot.ridable", parrotRidable); - parrotRidableInWater = getBoolean("mobs.parrot.ridable-in-water", parrotRidableInWater); - parrotControllable = getBoolean("mobs.parrot.controllable", parrotControllable); - 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); -+ parrotScale = Mth.clamp(getDouble("mobs.parrot.attributes.scale", parrotScale), 0.0625D, 16.0D); - } - - public boolean phantomRidable = false; -@@ -481,6 +898,10 @@ public class PurpurWorldConfig { - public float phantomFlameDamage = 1.0F; - public int phantomFlameFireTime = 8; - public boolean phantomAllowGriefing = false; -+ public String phantomMaxHealth = "20.0"; -+ public String phantomAttackDamage = "6 + size"; -+ public Map phantomMaxHealthCache = new HashMap<>(); -+ public Map phantomAttackDamageCache = new HashMap<>(); - private void phantomSettings() { - phantomRidable = getBoolean("mobs.phantom.ridable", phantomRidable); - phantomRidableInWater = getBoolean("mobs.phantom.ridable-in-water", phantomRidableInWater); -@@ -489,191 +910,405 @@ public class PurpurWorldConfig { - phantomFlameDamage = (float) getDouble("mobs.phantom.flames.damage", phantomFlameDamage); - phantomFlameFireTime = getInt("mobs.phantom.flames.fire-time", phantomFlameFireTime); - phantomAllowGriefing = getBoolean("mobs.phantom.allow-griefing", phantomAllowGriefing); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.phantom.attributes.max-health", Double.parseDouble(phantomMaxHealth)); -+ set("mobs.phantom.attributes.max-health", null); -+ set("mobs.phantom.attributes.max_health", String.valueOf(oldValue)); -+ } -+ if (PurpurConfig.version < 25) { -+ double oldValue = getDouble("mobs.phantom.attributes.max_health", Double.parseDouble(phantomMaxHealth)); -+ set("mobs.phantom.attributes.max_health", String.valueOf(oldValue)); -+ } -+ phantomMaxHealth = getString("mobs.phantom.attributes.max_health", phantomMaxHealth); -+ phantomAttackDamage = getString("mobs.phantom.attributes.attack_damage", phantomAttackDamage); -+ phantomMaxHealthCache.clear(); -+ phantomAttackDamageCache.clear(); - } - - public boolean pigRidable = false; - public boolean pigRidableInWater = false; - public boolean pigControllable = true; -+ public double pigMaxHealth = 10.0D; -+ public double pigScale = 1.0D; - private void pigSettings() { - pigRidable = getBoolean("mobs.pig.ridable", pigRidable); - pigRidableInWater = getBoolean("mobs.pig.ridable-in-water", pigRidableInWater); - pigControllable = getBoolean("mobs.pig.controllable", pigControllable); -+ 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); -+ pigScale = Mth.clamp(getDouble("mobs.pig.attributes.scale", pigScale), 0.0625D, 16.0D); - } - - public boolean piglinRidable = false; - public boolean piglinRidableInWater = true; - public boolean piglinControllable = true; -+ public double piglinMaxHealth = 16.0D; -+ public double piglinScale = 1.0D; - private void piglinSettings() { - piglinRidable = getBoolean("mobs.piglin.ridable", piglinRidable); - piglinRidableInWater = getBoolean("mobs.piglin.ridable-in-water", piglinRidableInWater); - piglinControllable = getBoolean("mobs.piglin.controllable", piglinControllable); -+ 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); -+ piglinScale = Mth.clamp(getDouble("mobs.piglin.attributes.scale", piglinScale), 0.0625D, 16.0D); - } - - public boolean piglinBruteRidable = false; - public boolean piglinBruteRidableInWater = true; - public boolean piglinBruteControllable = true; -+ public double piglinBruteMaxHealth = 50.0D; -+ public double piglinBruteScale = 1.0D; - private void piglinBruteSettings() { - piglinBruteRidable = getBoolean("mobs.piglin_brute.ridable", piglinBruteRidable); - piglinBruteRidableInWater = getBoolean("mobs.piglin_brute.ridable-in-water", piglinBruteRidableInWater); - piglinBruteControllable = getBoolean("mobs.piglin_brute.controllable", piglinBruteControllable); -+ 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); -+ piglinBruteScale = Mth.clamp(getDouble("mobs.piglin_brute.attributes.scale", piglinBruteScale), 0.0625D, 16.0D); - } - - public boolean pillagerRidable = false; - public boolean pillagerRidableInWater = true; - public boolean pillagerControllable = true; -+ public double pillagerMaxHealth = 24.0D; -+ public double pillagerScale = 1.0D; - private void pillagerSettings() { - pillagerRidable = getBoolean("mobs.pillager.ridable", pillagerRidable); - pillagerRidableInWater = getBoolean("mobs.pillager.ridable-in-water", pillagerRidableInWater); - pillagerControllable = getBoolean("mobs.pillager.controllable", pillagerControllable); -+ 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); -+ pillagerScale = Mth.clamp(getDouble("mobs.pillager.attributes.scale", pillagerScale), 0.0625D, 16.0D); - } - - public boolean polarBearRidable = false; - public boolean polarBearRidableInWater = true; - public boolean polarBearControllable = true; -+ public double polarBearMaxHealth = 30.0D; -+ public double polarBearScale = 1.0D; - private void polarBearSettings() { - polarBearRidable = getBoolean("mobs.polar_bear.ridable", polarBearRidable); - polarBearRidableInWater = getBoolean("mobs.polar_bear.ridable-in-water", polarBearRidableInWater); - polarBearControllable = getBoolean("mobs.polar_bear.controllable", polarBearControllable); -+ 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); -+ polarBearScale = Mth.clamp(getDouble("mobs.polar_bear.attributes.scale", polarBearScale), 0.0625D, 16.0D); - } - - public boolean pufferfishRidable = false; - public boolean pufferfishControllable = true; -+ public double pufferfishMaxHealth = 3.0D; -+ public double pufferfishScale = 1.0D; - private void pufferfishSettings() { - pufferfishRidable = getBoolean("mobs.pufferfish.ridable", pufferfishRidable); - pufferfishControllable = getBoolean("mobs.pufferfish.controllable", pufferfishControllable); -+ 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); -+ pufferfishScale = Mth.clamp(getDouble("mobs.pufferfish.attributes.scale", pufferfishScale), 0.0625D, 16.0D); - } - - public boolean rabbitRidable = false; - public boolean rabbitRidableInWater = true; - public boolean rabbitControllable = true; -+ public double rabbitMaxHealth = 3.0D; -+ public double rabbitScale = 1.0D; - private void rabbitSettings() { - rabbitRidable = getBoolean("mobs.rabbit.ridable", rabbitRidable); - rabbitRidableInWater = getBoolean("mobs.rabbit.ridable-in-water", rabbitRidableInWater); - rabbitControllable = getBoolean("mobs.rabbit.controllable", rabbitControllable); -+ 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); -+ rabbitScale = Mth.clamp(getDouble("mobs.rabbit.attributes.scale", rabbitScale), 0.0625D, 16.0D); - } - - public boolean ravagerRidable = false; - public boolean ravagerRidableInWater = false; - public boolean ravagerControllable = true; -+ public double ravagerMaxHealth = 100.0D; -+ public double ravagerScale = 1.0D; - private void ravagerSettings() { - ravagerRidable = getBoolean("mobs.ravager.ridable", ravagerRidable); - ravagerRidableInWater = getBoolean("mobs.ravager.ridable-in-water", ravagerRidableInWater); - ravagerControllable = getBoolean("mobs.ravager.controllable", ravagerControllable); -+ 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); -+ ravagerScale = Mth.clamp(getDouble("mobs.ravager.attributes.scale", ravagerScale), 0.0625D, 16.0D); - } - - public boolean salmonRidable = false; - public boolean salmonControllable = true; -+ public double salmonMaxHealth = 3.0D; -+ public double salmonScale = 1.0D; - private void salmonSettings() { - salmonRidable = getBoolean("mobs.salmon.ridable", salmonRidable); - salmonControllable = getBoolean("mobs.salmon.controllable", salmonControllable); -+ 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); -+ salmonScale = Mth.clamp(getDouble("mobs.salmon.attributes.scale", salmonScale), 0.0625D, 16.0D); - } - - public boolean sheepRidable = false; - public boolean sheepRidableInWater = true; - public boolean sheepControllable = true; -+ public double sheepMaxHealth = 8.0D; -+ public double sheepScale = 1.0D; - private void sheepSettings() { - sheepRidable = getBoolean("mobs.sheep.ridable", sheepRidable); - sheepRidableInWater = getBoolean("mobs.sheep.ridable-in-water", sheepRidableInWater); - sheepControllable = getBoolean("mobs.sheep.controllable", sheepControllable); -+ 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); -+ sheepScale = Mth.clamp(getDouble("mobs.sheep.attributes.scale", sheepScale), 0.0625D, 16.0D); - } - - public boolean shulkerRidable = false; - public boolean shulkerRidableInWater = true; - public boolean shulkerControllable = true; -+ public double shulkerMaxHealth = 30.0D; -+ public double shulkerScale = 1.0D; - private void shulkerSettings() { - shulkerRidable = getBoolean("mobs.shulker.ridable", shulkerRidable); - shulkerRidableInWater = getBoolean("mobs.shulker.ridable-in-water", shulkerRidableInWater); - shulkerControllable = getBoolean("mobs.shulker.controllable", shulkerControllable); -+ 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); -+ shulkerScale = Mth.clamp(getDouble("mobs.shulker.attributes.scale", shulkerScale), 0.0625D, Shulker.MAX_SCALE); - } - - public boolean silverfishRidable = false; - public boolean silverfishRidableInWater = true; - public boolean silverfishControllable = true; -+ public double silverfishMaxHealth = 8.0D; -+ public double silverfishScale = 1.0D; -+ public double silverfishMovementSpeed = 0.25D; -+ public double silverfishAttackDamage = 1.0D; - private void silverfishSettings() { - silverfishRidable = getBoolean("mobs.silverfish.ridable", silverfishRidable); - silverfishRidableInWater = getBoolean("mobs.silverfish.ridable-in-water", silverfishRidableInWater); - silverfishControllable = getBoolean("mobs.silverfish.controllable", silverfishControllable); -+ 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); -+ silverfishScale = Mth.clamp(getDouble("mobs.silverfish.attributes.scale", silverfishScale), 0.0625D, 16.0D); -+ silverfishMovementSpeed = getDouble("mobs.silverfish.attributes.movement_speed", silverfishMovementSpeed); -+ silverfishAttackDamage = getDouble("mobs.silverfish.attributes.attack_damage", silverfishAttackDamage); - } - - public boolean skeletonRidable = false; - public boolean skeletonRidableInWater = true; - public boolean skeletonControllable = true; -+ public double skeletonMaxHealth = 20.0D; -+ public double skeletonScale = 1.0D; - private void skeletonSettings() { - skeletonRidable = getBoolean("mobs.skeleton.ridable", skeletonRidable); - skeletonRidableInWater = getBoolean("mobs.skeleton.ridable-in-water", skeletonRidableInWater); - skeletonControllable = getBoolean("mobs.skeleton.controllable", skeletonControllable); -+ 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); -+ skeletonScale = Mth.clamp(getDouble("mobs.skeleton.attributes.scale", skeletonScale), 0.0625D, 16.0D); - } - - public boolean skeletonHorseRidable = false; - public boolean skeletonHorseRidableInWater = true; - public boolean skeletonHorseCanSwim = false; -+ 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() { - skeletonHorseRidable = getBoolean("mobs.skeleton_horse.ridable", skeletonHorseRidable); - skeletonHorseRidableInWater = getBoolean("mobs.skeleton_horse.ridable-in-water", skeletonHorseRidableInWater); - skeletonHorseCanSwim = getBoolean("mobs.skeleton_horse.can-swim", skeletonHorseCanSwim); -+ 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 = true; - public boolean slimeControllable = true; -+ public String slimeMaxHealth = "size * size"; -+ public String slimeAttackDamage = "size"; -+ public Map slimeMaxHealthCache = new HashMap<>(); -+ public Map slimeAttackDamageCache = new HashMap<>(); - private void slimeSettings() { - slimeRidable = getBoolean("mobs.slime.ridable", slimeRidable); - slimeRidableInWater = getBoolean("mobs.slime.ridable-in-water", slimeRidableInWater); - slimeControllable = getBoolean("mobs.slime.controllable", slimeControllable); -+ 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); -+ slimeAttackDamage = getString("mobs.slime.attributes.attack_damage", slimeAttackDamage); -+ slimeMaxHealthCache.clear(); -+ slimeAttackDamageCache.clear(); - } - - public boolean snowGolemRidable = false; - public boolean snowGolemRidableInWater = true; - public boolean snowGolemControllable = true; - public boolean snowGolemLeaveTrailWhenRidden = false; -+ public double snowGolemMaxHealth = 4.0D; -+ public double snowGolemScale = 1.0D; - private void snowGolemSettings() { - snowGolemRidable = getBoolean("mobs.snow_golem.ridable", snowGolemRidable); - snowGolemRidableInWater = getBoolean("mobs.snow_golem.ridable-in-water", snowGolemRidableInWater); - snowGolemControllable = getBoolean("mobs.snow_golem.controllable", snowGolemControllable); - snowGolemLeaveTrailWhenRidden = getBoolean("mobs.snow_golem.leave-trail-when-ridden", snowGolemLeaveTrailWhenRidden); -+ 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); -+ snowGolemScale = Mth.clamp(getDouble("mobs.snow_golem.attributes.scale", snowGolemScale), 0.0625D, 16.0D); - } - - public boolean snifferRidable = false; - public boolean snifferRidableInWater = true; - public boolean snifferControllable = true; -+ public double snifferMaxHealth = 14.0D; -+ public double snifferScale = 1.0D; - private void snifferSettings() { - snifferRidable = getBoolean("mobs.sniffer.ridable", snifferRidable); - snifferRidableInWater = getBoolean("mobs.sniffer.ridable-in-water", snifferRidableInWater); - snifferControllable = getBoolean("mobs.sniffer.controllable", snifferControllable); -+ snifferMaxHealth = getDouble("mobs.sniffer.attributes.max_health", snifferMaxHealth); -+ snifferScale = Mth.clamp(getDouble("mobs.sniffer.attributes.scale", snifferScale), 0.0625D, 16.0D); - } - - public boolean squidRidable = false; - public boolean squidControllable = true; -+ public double squidMaxHealth = 10.0D; -+ public double squidScale = 1.0D; - private void squidSettings() { - squidRidable = getBoolean("mobs.squid.ridable", squidRidable); - squidControllable = getBoolean("mobs.squid.controllable", squidControllable); -+ 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); -+ squidScale = Mth.clamp(getDouble("mobs.squid.attributes.scale", squidScale), 0.0625D, 16.0D); - } - - public boolean spiderRidable = false; - public boolean spiderRidableInWater = false; - public boolean spiderControllable = true; -+ public double spiderMaxHealth = 16.0D; -+ public double spiderScale = 1.0D; - private void spiderSettings() { - spiderRidable = getBoolean("mobs.spider.ridable", spiderRidable); - spiderRidableInWater = getBoolean("mobs.spider.ridable-in-water", spiderRidableInWater); - spiderControllable = getBoolean("mobs.spider.controllable", spiderControllable); -+ 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); -+ spiderScale = Mth.clamp(getDouble("mobs.spider.attributes.scale", spiderScale), 0.0625D, 16.0D); - } - - public boolean strayRidable = false; - public boolean strayRidableInWater = true; - public boolean strayControllable = true; -+ public double strayMaxHealth = 20.0D; -+ public double strayScale = 1.0D; - private void straySettings() { - strayRidable = getBoolean("mobs.stray.ridable", strayRidable); - strayRidableInWater = getBoolean("mobs.stray.ridable-in-water", strayRidableInWater); - strayControllable = getBoolean("mobs.stray.controllable", strayControllable); -+ 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); -+ strayScale = Mth.clamp(getDouble("mobs.stray.attributes.scale", strayScale), 0.0625D, 16.0D); - } - - public boolean striderRidable = false; - public boolean striderRidableInWater = false; - public boolean striderControllable = true; -+ public double striderMaxHealth = 20.0D; -+ public double striderScale = 1.0D; - private void striderSettings() { - striderRidable = getBoolean("mobs.strider.ridable", striderRidable); - striderRidableInWater = getBoolean("mobs.strider.ridable-in-water", striderRidableInWater); - striderControllable = getBoolean("mobs.strider.controllable", striderControllable); -+ 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); -+ striderScale = Mth.clamp(getDouble("mobs.strider.attributes.scale", striderScale), 0.0625D, 16.0D); - } - - public boolean tadpoleRidable = false; -@@ -688,64 +1323,137 @@ public class PurpurWorldConfig { - public boolean traderLlamaRidable = false; - public boolean traderLlamaRidableInWater = false; - public boolean traderLlamaControllable = true; -+ public double traderLlamaMaxHealthMin = 15.0D; -+ public double traderLlamaMaxHealthMax = 30.0D; -+ public double traderLlamaJumpStrengthMin = 0.5D; -+ public double traderLlamaJumpStrengthMax = 0.5D; -+ public double traderLlamaMovementSpeedMin = 0.175D; -+ public double traderLlamaMovementSpeedMax = 0.175D; - private void traderLlamaSettings() { - traderLlamaRidable = getBoolean("mobs.trader_llama.ridable", traderLlamaRidable); - traderLlamaRidableInWater = getBoolean("mobs.trader_llama.ridable-in-water", traderLlamaRidableInWater); - traderLlamaControllable = getBoolean("mobs.trader_llama.controllable", traderLlamaControllable); -+ if (PurpurConfig.version < 10) { -+ double oldMin = getDouble("mobs.trader_llama.attributes.max-health.min", traderLlamaMaxHealthMin); -+ double oldMax = getDouble("mobs.trader_llama.attributes.max-health.max", traderLlamaMaxHealthMax); -+ 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); -+ } -+ traderLlamaMaxHealthMin = getDouble("mobs.trader_llama.attributes.max_health.min", traderLlamaMaxHealthMin); -+ traderLlamaMaxHealthMax = getDouble("mobs.trader_llama.attributes.max_health.max", traderLlamaMaxHealthMax); -+ traderLlamaJumpStrengthMin = getDouble("mobs.trader_llama.attributes.jump_strength.min", traderLlamaJumpStrengthMin); -+ traderLlamaJumpStrengthMax = getDouble("mobs.trader_llama.attributes.jump_strength.max", traderLlamaJumpStrengthMax); -+ traderLlamaMovementSpeedMin = getDouble("mobs.trader_llama.attributes.movement_speed.min", traderLlamaMovementSpeedMin); -+ traderLlamaMovementSpeedMax = getDouble("mobs.trader_llama.attributes.movement_speed.max", traderLlamaMovementSpeedMax); - } - - public boolean tropicalFishRidable = false; - public boolean tropicalFishControllable = true; -+ public double tropicalFishMaxHealth = 3.0D; -+ public double tropicalFishScale = 1.0D; - private void tropicalFishSettings() { - tropicalFishRidable = getBoolean("mobs.tropical_fish.ridable", tropicalFishRidable); - tropicalFishControllable = getBoolean("mobs.tropical_fish.controllable", tropicalFishControllable); -+ 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); -+ tropicalFishScale = Mth.clamp(getDouble("mobs.tropical_fish.attributes.scale", tropicalFishScale), 0.0625D, 16.0D); - } - - public boolean turtleRidable = false; - public boolean turtleRidableInWater = true; - public boolean turtleControllable = true; -+ public double turtleMaxHealth = 30.0D; -+ public double turtleScale = 1.0D; - private void turtleSettings() { - turtleRidable = getBoolean("mobs.turtle.ridable", turtleRidable); - turtleRidableInWater = getBoolean("mobs.turtle.ridable-in-water", turtleRidableInWater); - turtleControllable = getBoolean("mobs.turtle.controllable", turtleControllable); -+ 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); -+ turtleScale = Mth.clamp(getDouble("mobs.turtle.attributes.scale", turtleScale), 0.0625D, 16.0D); - } - - public boolean vexRidable = false; - public boolean vexRidableInWater = true; - public boolean vexControllable = true; - public double vexMaxY = 320D; -+ public double vexMaxHealth = 14.0D; -+ public double vexScale = 1.0D; - private void vexSettings() { - vexRidable = getBoolean("mobs.vex.ridable", vexRidable); - vexRidableInWater = getBoolean("mobs.vex.ridable-in-water", vexRidableInWater); - vexControllable = getBoolean("mobs.vex.controllable", vexControllable); - 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); -+ vexScale = Mth.clamp(getDouble("mobs.vex.attributes.scale", vexScale), 0.0625D, 16.0D); - } - - public boolean villagerRidable = false; - public boolean villagerRidableInWater = true; - public boolean villagerControllable = true; -+ public double villagerMaxHealth = 20.0D; -+ public double villagerScale = 1.0D; - private void villagerSettings() { - villagerRidable = getBoolean("mobs.villager.ridable", villagerRidable); - villagerRidableInWater = getBoolean("mobs.villager.ridable-in-water", villagerRidableInWater); - villagerControllable = getBoolean("mobs.villager.controllable", villagerControllable); -+ 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); -+ villagerScale = Mth.clamp(getDouble("mobs.villager.attributes.scale", villagerScale), 0.0625D, 16.0D); - } - - public boolean vindicatorRidable = false; - public boolean vindicatorRidableInWater = true; - public boolean vindicatorControllable = true; -+ public double vindicatorMaxHealth = 24.0D; -+ public double vindicatorScale = 1.0D; - private void vindicatorSettings() { - vindicatorRidable = getBoolean("mobs.vindicator.ridable", vindicatorRidable); - vindicatorRidableInWater = getBoolean("mobs.vindicator.ridable-in-water", vindicatorRidableInWater); - vindicatorControllable = getBoolean("mobs.vindicator.controllable", vindicatorControllable); -+ 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); -+ vindicatorScale = Mth.clamp(getDouble("mobs.vindicator.attributes.scale", vindicatorScale), 0.0625D, 16.0D); - } - - public boolean wanderingTraderRidable = false; - public boolean wanderingTraderRidableInWater = true; - public boolean wanderingTraderControllable = true; -+ public double wanderingTraderMaxHealth = 20.0D; -+ public double wanderingTraderScale = 1.0D; - private void wanderingTraderSettings() { - wanderingTraderRidable = getBoolean("mobs.wandering_trader.ridable", wanderingTraderRidable); - wanderingTraderRidableInWater = getBoolean("mobs.wandering_trader.ridable-in-water", wanderingTraderRidableInWater); - wanderingTraderControllable = getBoolean("mobs.wandering_trader.controllable", wanderingTraderControllable); -+ if (PurpurConfig.version < 10) { -+ double oldValue = getDouble("mobs.wandering_trader.attributes.max-health", wanderingTraderMaxHealth); -+ set("mobs.wandering_trader.attributes.max-health", null); -+ set("mobs.wandering_trader.attributes.max_health", oldValue); -+ } -+ wanderingTraderMaxHealth = getDouble("mobs.wandering_trader.attributes.max_health", wanderingTraderMaxHealth); -+ wanderingTraderScale = Mth.clamp(getDouble("mobs.wandering_trader.attributes.scale", wanderingTraderScale), 0.0625D, 16.0D); - } - - public boolean wardenRidable = false; -@@ -760,83 +1468,183 @@ public class PurpurWorldConfig { - public boolean witchRidable = false; - public boolean witchRidableInWater = true; - public boolean witchControllable = true; -+ public double witchMaxHealth = 26.0D; -+ public double witchScale = 1.0D; - private void witchSettings() { - witchRidable = getBoolean("mobs.witch.ridable", witchRidable); - witchRidableInWater = getBoolean("mobs.witch.ridable-in-water", witchRidableInWater); - witchControllable = getBoolean("mobs.witch.controllable", witchControllable); -+ 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); -+ witchScale = Mth.clamp(getDouble("mobs.witch.attributes.scale", witchScale), 0.0625D, 16.0D); - } - - public boolean witherRidable = false; - public boolean witherRidableInWater = true; - public boolean witherControllable = true; - public double witherMaxY = 320D; -+ public double witherMaxHealth = 300.0D; -+ public double witherScale = 1.0D; - private void witherSettings() { - witherRidable = getBoolean("mobs.wither.ridable", witherRidable); - witherRidableInWater = getBoolean("mobs.wither.ridable-in-water", witherRidableInWater); - witherControllable = getBoolean("mobs.wither.controllable", witherControllable); - witherMaxY = getDouble("mobs.wither.ridable-max-y", witherMaxY); -+ 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); -+ } 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); -+ witherScale = Mth.clamp(getDouble("mobs.wither.attributes.scale", witherScale), 0.0625D, 16.0D); - } - - public boolean witherSkeletonRidable = false; - public boolean witherSkeletonRidableInWater = true; - public boolean witherSkeletonControllable = true; -+ public double witherSkeletonMaxHealth = 20.0D; -+ public double witherSkeletonScale = 1.0D; - private void witherSkeletonSettings() { - witherSkeletonRidable = getBoolean("mobs.wither_skeleton.ridable", witherSkeletonRidable); - witherSkeletonRidableInWater = getBoolean("mobs.wither_skeleton.ridable-in-water", witherSkeletonRidableInWater); - witherSkeletonControllable = getBoolean("mobs.wither_skeleton.controllable", witherSkeletonControllable); -+ 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); -+ witherSkeletonScale = Mth.clamp(getDouble("mobs.wither_skeleton.attributes.scale", witherSkeletonScale), 0.0625D, 16.0D); - } - - public boolean wolfRidable = false; - public boolean wolfRidableInWater = true; - public boolean wolfControllable = true; -+ public double wolfMaxHealth = 8.0D; -+ public double wolfScale = 1.0D; - private void wolfSettings() { - wolfRidable = getBoolean("mobs.wolf.ridable", wolfRidable); - wolfRidableInWater = getBoolean("mobs.wolf.ridable-in-water", wolfRidableInWater); - wolfControllable = getBoolean("mobs.wolf.controllable", wolfControllable); -+ 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); -+ wolfScale = Mth.clamp(getDouble("mobs.wolf.attributes.scale", wolfScale), 0.0625D, 16.0D); - } - - public boolean zoglinRidable = false; - public boolean zoglinRidableInWater = true; - public boolean zoglinControllable = true; -+ public double zoglinMaxHealth = 40.0D; -+ public double zoglinScale = 1.0D; - private void zoglinSettings() { - zoglinRidable = getBoolean("mobs.zoglin.ridable", zoglinRidable); - zoglinRidableInWater = getBoolean("mobs.zoglin.ridable-in-water", zoglinRidableInWater); - zoglinControllable = getBoolean("mobs.zoglin.controllable", zoglinControllable); -+ 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); -+ zoglinScale = Mth.clamp(getDouble("mobs.zoglin.attributes.scale", zoglinScale), 0.0625D, 16.0D); - } - - public boolean zombieRidable = false; - public boolean zombieRidableInWater = true; - public boolean zombieControllable = true; -+ public double zombieMaxHealth = 20.0D; -+ public double zombieScale = 1.0D; -+ public double zombieSpawnReinforcements = 0.1D; - private void zombieSettings() { - zombieRidable = getBoolean("mobs.zombie.ridable", zombieRidable); - zombieRidableInWater = getBoolean("mobs.zombie.ridable-in-water", zombieRidableInWater); - zombieControllable = getBoolean("mobs.zombie.controllable", zombieControllable); -+ 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); -+ zombieScale = Mth.clamp(getDouble("mobs.zombie.attributes.scale", zombieScale), 0.0625D, 16.0D); -+ zombieSpawnReinforcements = getDouble("mobs.zombie.attributes.spawn_reinforcements", zombieSpawnReinforcements); - } - - public boolean zombieHorseRidable = false; - public boolean zombieHorseRidableInWater = false; - public boolean zombieHorseCanSwim = false; -+ 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() { - zombieHorseRidable = getBoolean("mobs.zombie_horse.ridable", zombieHorseRidable); - zombieHorseRidableInWater = getBoolean("mobs.zombie_horse.ridable-in-water", zombieHorseRidableInWater); - zombieHorseCanSwim = getBoolean("mobs.zombie_horse.can-swim", zombieHorseCanSwim); -+ 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 zombieVillagerRidable = false; - public boolean zombieVillagerRidableInWater = true; - public boolean zombieVillagerControllable = true; -+ public double zombieVillagerMaxHealth = 20.0D; -+ public double zombieVillagerScale = 1.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); - zombieVillagerControllable = getBoolean("mobs.zombie_villager.controllable", zombieVillagerControllable); -+ 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); -+ zombieVillagerScale = Mth.clamp(getDouble("mobs.zombie_villager.attributes.scale", zombieVillagerScale), 0.0625D, 16.0D); -+ zombieVillagerSpawnReinforcements = getDouble("mobs.zombie_villager.attributes.spawn_reinforcements", zombieVillagerSpawnReinforcements); - } - - public boolean zombifiedPiglinRidable = false; - public boolean zombifiedPiglinRidableInWater = true; - public boolean zombifiedPiglinControllable = true; -+ public double zombifiedPiglinMaxHealth = 20.0D; -+ public double zombifiedPiglinScale = 1.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); - zombifiedPiglinControllable = getBoolean("mobs.zombified_piglin.controllable", zombifiedPiglinControllable); -+ 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); -+ zombifiedPiglinScale = Mth.clamp(getDouble("mobs.zombified_piglin.attributes.scale", zombifiedPiglinScale), 0.0625D, 16.0D); -+ zombifiedPiglinSpawnReinforcements = getDouble("mobs.zombified_piglin.attributes.spawn_reinforcements", zombifiedPiglinSpawnReinforcements); - } - } diff --git a/purpur-server/build.gradle.kts.patch b/purpur-server/build.gradle.kts.patch index b05afd61c..ef3dc048b 100644 --- a/purpur-server/build.gradle.kts.patch +++ b/purpur-server/build.gradle.kts.patch @@ -51,6 +51,16 @@ implementation("ca.spottedleaf:concurrentutil:0.0.2") // Paper - Add ConcurrentUtil dependency // Paper start implementation("org.jline:jline-terminal-ffm:3.27.1") // use ffm on java 22+ +@@ -155,6 +_,9 @@ + } + // Paper end - Use Velocity cipher + ++ implementation("org.mozilla:rhino-runtime:1.7.14") // Purpur ++ implementation("org.mozilla:rhino-engine:1.7.14") // Purpur ++ + runtimeOnly("org.apache.maven:maven-resolver-provider:3.9.6") + runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.9.18") + runtimeOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.9.18") @@ -193,14 +_,14 @@ val gitBranch = git.exec(providers, "rev-parse", "--abbrev-ref", "HEAD").get().trim() // Paper attributes( diff --git a/purpur-server/minecraft-patches/features/0002-Configurable-entity-base-attributes.patch b/purpur-server/minecraft-patches/features/0002-Configurable-entity-base-attributes.patch new file mode 100644 index 000000000..d9eb91cd8 --- /dev/null +++ b/purpur-server/minecraft-patches/features/0002-Configurable-entity-base-attributes.patch @@ -0,0 +1,1786 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Thu, 10 Dec 2020 16:44:54 -0600 +Subject: [PATCH] Configurable entity base attributes + + +diff --git a/net/minecraft/world/entity/GlowSquid.java b/net/minecraft/world/entity/GlowSquid.java +index 666455fff2b391b637cf1c07091e88100c5e1308..a53d662e2c78b002320956b9c7e39ccb44826113 100644 +--- a/net/minecraft/world/entity/GlowSquid.java ++++ b/net/minecraft/world/entity/GlowSquid.java +@@ -38,6 +38,13 @@ public class GlowSquid extends Squid { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.glowSquidMaxHealth); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected ParticleOptions getInkParticle() { + return ParticleTypes.GLOW_SQUID_INK; +diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java +index 67c99e33642964a1756d48e029e00f2676f07fbb..0f866a6d75afbd2238e49e56a2a2fbc6edb0168c 100644 +--- a/net/minecraft/world/entity/LivingEntity.java ++++ b/net/minecraft/world/entity/LivingEntity.java +@@ -311,6 +311,7 @@ public abstract class LivingEntity extends Entity implements Attackable { + protected LivingEntity(EntityType entityType, Level level) { + super(entityType, level); + this.attributes = new AttributeMap(DefaultAttributes.getSupplier(entityType), this); // Purpur - Ridables ++ this.initAttributes(); // Purpur - Configurable entity base attributes + this.craftAttributes = new CraftAttributeMap(this.attributes); // CraftBukkit + // CraftBukkit - this.setHealth(this.getMaxHealth()) inlined and simplified to skip the instanceof check for Player, as getBukkitEntity() is not initialized in constructor + this.entityData.set(LivingEntity.DATA_HEALTH_ID, this.getMaxHealth()); +@@ -324,6 +325,8 @@ public abstract class LivingEntity extends Entity implements Attackable { + this.brain = this.makeBrain(new Dynamic<>(nbtOps, nbtOps.createMap(ImmutableMap.of(nbtOps.createString("memories"), nbtOps.emptyMap())))); + } + ++ protected void initAttributes() {}// Purpur - Configurable entity base attributes ++ + public Brain getBrain() { + return this.brain; + } +diff --git a/net/minecraft/world/entity/ambient/Bat.java b/net/minecraft/world/entity/ambient/Bat.java +index f01ddd493d38e2e231c59841649a2e5bf3b87c49..e158fdc79c2c8f27203d6f229c1ac906394e5f96 100644 +--- a/net/minecraft/world/entity/ambient/Bat.java ++++ b/net/minecraft/world/entity/ambient/Bat.java +@@ -94,6 +94,21 @@ public class Bat extends AmbientCreature { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.batMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.batScale); ++ this.getAttribute(Attributes.FOLLOW_RANGE).setBaseValue(this.level().purpurConfig.batFollowRange); ++ this.getAttribute(Attributes.KNOCKBACK_RESISTANCE).setBaseValue(this.level().purpurConfig.batKnockbackResistance); ++ this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(this.level().purpurConfig.batMovementSpeed); ++ this.getAttribute(Attributes.FLYING_SPEED).setBaseValue(this.level().purpurConfig.batFlyingSpeed); ++ this.getAttribute(Attributes.ARMOR).setBaseValue(this.level().purpurConfig.batArmor); ++ this.getAttribute(Attributes.ARMOR_TOUGHNESS).setBaseValue(this.level().purpurConfig.batArmorToughness); ++ this.getAttribute(Attributes.ATTACK_KNOCKBACK).setBaseValue(this.level().purpurConfig.batAttackKnockback); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + public boolean isFlapping() { + return !this.isResting() && this.tickCount % 10.0F == 0.0F; +diff --git a/net/minecraft/world/entity/animal/Bee.java b/net/minecraft/world/entity/animal/Bee.java +index 474240c0fd68dbfe18b8fce7ae6e7634eea65956..bcf554054111f85b095341a5455856ee79f3ade6 100644 +--- a/net/minecraft/world/entity/animal/Bee.java ++++ b/net/minecraft/world/entity/animal/Bee.java +@@ -471,6 +471,14 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + return beehiveBlockEntity != null && beehiveBlockEntity.isFireNearby(); + } + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.beeMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.beeScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + public int getRemainingPersistentAngerTime() { + return this.entityData.get(DATA_REMAINING_ANGER_TIME); +diff --git a/net/minecraft/world/entity/animal/Cat.java b/net/minecraft/world/entity/animal/Cat.java +index b4cb2312a1948781cf087fa6d2eb8bb96667605e..54a003df555a3146fe30de1f95fe2469dced9fb0 100644 +--- a/net/minecraft/world/entity/animal/Cat.java ++++ b/net/minecraft/world/entity/animal/Cat.java +@@ -118,6 +118,14 @@ public class Cat extends TamableAnimal implements VariantHolder itemStack.is(ItemTags.CAT_FOOD), true); +diff --git a/net/minecraft/world/entity/animal/Chicken.java b/net/minecraft/world/entity/animal/Chicken.java +index aba1bf732bb78a24dba1f063d65894fde92789ef..509163f409a5b8988a484aedb2f3ddf042d5eb13 100644 +--- a/net/minecraft/world/entity/animal/Chicken.java ++++ b/net/minecraft/world/entity/animal/Chicken.java +@@ -68,6 +68,14 @@ public class Chicken extends Animal { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.chickenMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.chickenScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); +diff --git a/net/minecraft/world/entity/animal/Cod.java b/net/minecraft/world/entity/animal/Cod.java +index 6a19086e272363701260801f3c6db9b5c91b8ef5..434e1fabf2e360a8f5f4eefed96e3883aa786d10 100644 +--- a/net/minecraft/world/entity/animal/Cod.java ++++ b/net/minecraft/world/entity/animal/Cod.java +@@ -25,6 +25,13 @@ public class Cod extends AbstractSchoolingFish { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.codMaxHealth); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + public ItemStack getBucketItemStack() { + return new ItemStack(Items.COD_BUCKET); +diff --git a/net/minecraft/world/entity/animal/Cow.java b/net/minecraft/world/entity/animal/Cow.java +index b2bf4276952fa1c984bf0571b041be4141fbdf3a..ad59d1f1e505148b88c0d242a5d92f7c4d8f4ce8 100644 +--- a/net/minecraft/world/entity/animal/Cow.java ++++ b/net/minecraft/world/entity/animal/Cow.java +@@ -55,6 +55,14 @@ public class Cow extends Animal { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.cowMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.cowScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); +diff --git a/net/minecraft/world/entity/animal/Dolphin.java b/net/minecraft/world/entity/animal/Dolphin.java +index 0e4112793dddc0d75f4bed35bb880c03b2d1318f..bb5e9256f9eec523dadeaa80879a44e2374a667a 100644 +--- a/net/minecraft/world/entity/animal/Dolphin.java ++++ b/net/minecraft/world/entity/animal/Dolphin.java +@@ -147,6 +147,14 @@ public class Dolphin extends AgeableWaterCreature { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.dolphinMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.dolphinScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Nullable + @Override + public SpawnGroupData finalizeSpawn( +diff --git a/net/minecraft/world/entity/animal/Fox.java b/net/minecraft/world/entity/animal/Fox.java +index ff22b9bd7eb2b60fac58cae0a2be1d93a6eef7b7..f0bea098d69b98bb2baba2290239a5c803160c24 100644 +--- a/net/minecraft/world/entity/animal/Fox.java ++++ b/net/minecraft/world/entity/animal/Fox.java +@@ -167,6 +167,14 @@ public class Fox extends Animal implements VariantHolder { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.foxMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.foxScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected void defineSynchedData(SynchedEntityData.Builder builder) { + super.defineSynchedData(builder); +diff --git a/net/minecraft/world/entity/animal/IronGolem.java b/net/minecraft/world/entity/animal/IronGolem.java +index 654f5855e1b69f05205e6a132d79ac94b929eeb4..d195e8658fd5a4045c95ff1e921bfeeb4dfbecf5 100644 +--- a/net/minecraft/world/entity/animal/IronGolem.java ++++ b/net/minecraft/world/entity/animal/IronGolem.java +@@ -78,6 +78,14 @@ public class IronGolem extends AbstractGolem implements NeutralMob { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.ironGolemMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.ironGolemScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected void registerGoals() { + if (level().purpurConfig.ironGolemCanSwim) this.goalSelector.addGoal(0, new net.minecraft.world.entity.ai.goal.FloatGoal(this)); // Purpur - Ridables +diff --git a/net/minecraft/world/entity/animal/MushroomCow.java b/net/minecraft/world/entity/animal/MushroomCow.java +index 696b0eb93f8c8fe30f4c2cabadc50de730f93c22..0afc7aefbeb22ead66d59b3fd67630af0bce2df1 100644 +--- a/net/minecraft/world/entity/animal/MushroomCow.java ++++ b/net/minecraft/world/entity/animal/MushroomCow.java +@@ -72,6 +72,13 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.rabbitMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.rabbitScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + public void registerGoals() { + this.goalSelector.addGoal(1, new FloatGoal(this)); +diff --git a/net/minecraft/world/entity/animal/Salmon.java b/net/minecraft/world/entity/animal/Salmon.java +index ebbd6d39c3f5d6c66445c2c743785ed369408389..93eb3cc3605f694337c1604e2db63fed04693617 100644 +--- a/net/minecraft/world/entity/animal/Salmon.java ++++ b/net/minecraft/world/entity/animal/Salmon.java +@@ -47,6 +47,13 @@ public class Salmon extends AbstractSchoolingFish implements VariantHolder brainProvider() { + return Brain.provider(MEMORY_TYPES, SENSOR_TYPES); +diff --git a/net/minecraft/world/entity/animal/armadillo/Armadillo.java b/net/minecraft/world/entity/animal/armadillo/Armadillo.java +index 87a190d8646d8bbed8c182f9f0f7d8c398e63d26..c10ebb66dec26b6ccc223e98effa0b9a68363626 100644 +--- a/net/minecraft/world/entity/animal/armadillo/Armadillo.java ++++ b/net/minecraft/world/entity/animal/armadillo/Armadillo.java +@@ -97,6 +97,14 @@ public class Armadillo extends Animal { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.armadilloMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.armadilloScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected void defineSynchedData(SynchedEntityData.Builder builder) { + super.defineSynchedData(builder); +diff --git a/net/minecraft/world/entity/animal/axolotl/Axolotl.java b/net/minecraft/world/entity/animal/axolotl/Axolotl.java +index 2054e4624da0c9b04ea69b9bf39443c4574d48be..f2f09a529e9db88784ff4299fdf3966046c736ab 100644 +--- a/net/minecraft/world/entity/animal/axolotl/Axolotl.java ++++ b/net/minecraft/world/entity/animal/axolotl/Axolotl.java +@@ -132,6 +132,14 @@ public class Axolotl extends Animal implements VariantHolder, B + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.axolotlMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.axolotlScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + public float getWalkTargetValue(BlockPos pos, LevelReader level) { + return 0.0F; +diff --git a/net/minecraft/world/entity/animal/camel/Camel.java b/net/minecraft/world/entity/animal/camel/Camel.java +index 11311d2ec37d825e73e2218e60e2606dd3a25a1d..1d7e2358bac193af48dc4b7f5b0295e3bffa152b 100644 +--- a/net/minecraft/world/entity/animal/camel/Camel.java ++++ b/net/minecraft/world/entity/animal/camel/Camel.java +@@ -322,6 +322,23 @@ public class Camel extends AbstractHorse { + return this.dashCooldown; + } + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public float generateMaxHealth(net.minecraft.util.RandomSource random) { ++ return (float) generateMaxHealth(this.level().purpurConfig.camelMaxHealthMin, this.level().purpurConfig.camelMaxHealthMax); ++ } ++ ++ @Override ++ public double generateJumpStrength(net.minecraft.util.RandomSource random) { ++ return generateJumpStrength(this.level().purpurConfig.camelJumpStrengthMin, this.level().purpurConfig.camelJumpStrengthMax); ++ } ++ ++ @Override ++ public double generateSpeed(net.minecraft.util.RandomSource random) { ++ return generateSpeed(this.level().purpurConfig.camelMovementSpeedMin, this.level().purpurConfig.camelMovementSpeedMax); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.CAMEL_AMBIENT; +diff --git a/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/net/minecraft/world/entity/animal/horse/AbstractHorse.java +index 828406060e50ff62586929371aafb46ef7d81f92..56dc7011ed07f0bd5870fbadde2b5c0c630c5edd 100644 +--- a/net/minecraft/world/entity/animal/horse/AbstractHorse.java ++++ b/net/minecraft/world/entity/animal/horse/AbstractHorse.java +@@ -218,6 +218,46 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.generateMaxHealth(random)); ++ this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(this.generateSpeed(random)); ++ this.getAttribute(Attributes.JUMP_STRENGTH).setBaseValue(this.generateJumpStrength(random)); ++ } ++ ++ protected double generateMaxHealth(double min, double max) { ++ if (min == max) return min; ++ int diff = Mth.floor(max - min); ++ double base = max - diff; ++ int first = Mth.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 generateSpeed(double min, double max) { ++ if (min == max) return min; ++ return min + (max - min) * this.random.nextDouble(); ++ } ++ ++ protected float generateMaxHealth(RandomSource random) { ++ return 15.0F + (float) random.nextInt(8) + (float) random.nextInt(9); ++ } ++ ++ protected double generateJumpStrength(RandomSource random) { ++ return 0.4F + random.nextDouble() * 0.2 + random.nextDouble() * 0.2 + random.nextDouble() * 0.2; ++ } ++ ++ protected double generateSpeed(RandomSource random) { ++ return (0.45F + random.nextDouble() * 0.3 + random.nextDouble() * 0.3 + random.nextDouble() * 0.3) * 0.25; ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HorseHasRider(this)); // Purpur - Ridables +@@ -1218,7 +1258,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, + spawnGroupData = new AgeableMob.AgeableMobGroupData(0.2F); + } + +- this.randomizeAttributes(level.getRandom()); ++ //this.randomizeAttributes(level.getRandom()); // Purpur - replaced by initAttributes() + return super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData); + } + +diff --git a/net/minecraft/world/entity/animal/horse/Donkey.java b/net/minecraft/world/entity/animal/horse/Donkey.java +index ee3fa710e95f2e84f7f9bdce1159d1136815172d..223f1d109680e3643ab2c8343be22713e89755fd 100644 +--- a/net/minecraft/world/entity/animal/horse/Donkey.java ++++ b/net/minecraft/world/entity/animal/horse/Donkey.java +@@ -23,6 +23,23 @@ public class Donkey extends AbstractChestedHorse { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public float generateMaxHealth(net.minecraft.util.RandomSource random) { ++ return (float) generateMaxHealth(this.level().purpurConfig.donkeyMaxHealthMin, this.level().purpurConfig.donkeyMaxHealthMax); ++ } ++ ++ @Override ++ public double generateJumpStrength(net.minecraft.util.RandomSource random) { ++ return generateJumpStrength(this.level().purpurConfig.donkeyJumpStrengthMin, this.level().purpurConfig.donkeyJumpStrengthMax); ++ } ++ ++ @Override ++ public double generateSpeed(net.minecraft.util.RandomSource random) { ++ return generateSpeed(this.level().purpurConfig.donkeyMovementSpeedMin, this.level().purpurConfig.donkeyMovementSpeedMax); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.DONKEY_AMBIENT; +diff --git a/net/minecraft/world/entity/animal/horse/Horse.java b/net/minecraft/world/entity/animal/horse/Horse.java +index 361bf346153912bcbfcf962d7f716dfe12ae2a7b..8bd118e82da9e4d4153de0a3efaf6d69e3c4c540 100644 +--- a/net/minecraft/world/entity/animal/horse/Horse.java ++++ b/net/minecraft/world/entity/animal/horse/Horse.java +@@ -50,6 +50,23 @@ public class Horse extends AbstractHorse implements VariantHolder { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public float generateMaxHealth(RandomSource random) { ++ return (float) generateMaxHealth(this.level().purpurConfig.horseMaxHealthMin, this.level().purpurConfig.horseMaxHealthMax); ++ } ++ ++ @Override ++ public double generateJumpStrength(RandomSource random) { ++ return generateJumpStrength(this.level().purpurConfig.horseJumpStrengthMin, this.level().purpurConfig.horseJumpStrengthMax); ++ } ++ ++ @Override ++ public double generateSpeed(RandomSource random) { ++ return generateSpeed(this.level().purpurConfig.horseMovementSpeedMin, this.level().purpurConfig.horseMovementSpeedMax); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected void randomizeAttributes(RandomSource random) { + this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(generateMaxHealth(random::nextInt)); +diff --git a/net/minecraft/world/entity/animal/horse/Llama.java b/net/minecraft/world/entity/animal/horse/Llama.java +index 81a72b5ddbf7644d65dea972821d19e8fccd9b48..4946bc7140ca7859d908bcd46a9acb4dac3f3417 100644 +--- a/net/minecraft/world/entity/animal/horse/Llama.java ++++ b/net/minecraft/world/entity/animal/horse/Llama.java +@@ -123,6 +123,23 @@ public class Llama extends AbstractChestedHorse implements VariantHolder entityType, ServerLevelAccessor level, EntitySpawnReason spawnReason, BlockPos pos, RandomSource random + ) { +diff --git a/net/minecraft/world/entity/monster/Illusioner.java b/net/minecraft/world/entity/monster/Illusioner.java +index bd0f4d77260f5b123856fc7e72d5f8e74bb45321..1d1cf8748e3fba2e2963ad2fa153fbfe990f5087 100644 +--- a/net/minecraft/world/entity/monster/Illusioner.java ++++ b/net/minecraft/world/entity/monster/Illusioner.java +@@ -74,6 +74,16 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ protected void initAttributes() { ++ this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(this.level().purpurConfig.illusionerMovementSpeed); ++ this.getAttribute(Attributes.FOLLOW_RANGE).setBaseValue(this.level().purpurConfig.illusionerFollowRange); ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.illusionerMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.illusionerScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected void registerGoals() { + super.registerGoals(); +diff --git a/net/minecraft/world/entity/monster/MagmaCube.java b/net/minecraft/world/entity/monster/MagmaCube.java +index f10b204c18b88e9110cebf050b60c23367ea3aa0..2c6b0fd46d9ed6a8d1ca7e90ebf596dd3f310f0e 100644 +--- a/net/minecraft/world/entity/monster/MagmaCube.java ++++ b/net/minecraft/world/entity/monster/MagmaCube.java +@@ -46,6 +46,28 @@ public class MagmaCube extends Slime { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ protected String getMaxHealthEquation() { ++ return level().purpurConfig.magmaCubeMaxHealth; ++ } ++ ++ @Override ++ protected String getAttackDamageEquation() { ++ return level().purpurConfig.magmaCubeAttackDamage; ++ } ++ ++ @Override ++ protected java.util.Map getMaxHealthCache() { ++ return level().purpurConfig.magmaCubeMaxHealthCache; ++ } ++ ++ @Override ++ protected java.util.Map getAttackDamageCache() { ++ return level().purpurConfig.magmaCubeAttackDamageCache; ++ } ++ // Purpur end - Configurable entity base attributes ++ + public static AttributeSupplier.Builder createAttributes() { + return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, 0.2F); + } +diff --git a/net/minecraft/world/entity/monster/Phantom.java b/net/minecraft/world/entity/monster/Phantom.java +index f78976646ea03fbddabdc7ed56229e9d05f90027..21ec49ac173b9eac990b63a00f5efab4e7ccfac0 100644 +--- a/net/minecraft/world/entity/monster/Phantom.java ++++ b/net/minecraft/world/entity/monster/Phantom.java +@@ -150,7 +150,11 @@ public class Phantom extends FlyingMob implements Enemy { + + private void updatePhantomSizeInfo() { + this.refreshDimensions(); +- this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(6 + this.getPhantomSize()); ++ // Purpur start - Configurable entity base attributes ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(getFromCache(() -> this.level().purpurConfig.phantomMaxHealth, () -> this.level().purpurConfig.phantomMaxHealthCache, () -> 20.0D)); ++ this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(getFromCache(() -> this.level().purpurConfig.phantomAttackDamage, () -> this.level().purpurConfig.phantomAttackDamageCache, () -> (double) (6 + this.getPhantomSize()))); ++ // Purpur end - Configurable entity base attributes ++ + } + + public int getPhantomSize() { +@@ -175,6 +179,23 @@ public class Phantom extends FlyingMob implements Enemy { + return true; + } + ++ // Purpur start - Configurable entity base attributes ++ private double getFromCache(java.util.function.Supplier equation, java.util.function.Supplier> cache, java.util.function.Supplier defaultValue) { ++ int size = getPhantomSize(); ++ Double value = cache.get().get(size); ++ if (value == null) { ++ try { ++ value = ((Number) scriptEngine.eval("let size = " + size + "; " + equation.get())).doubleValue(); ++ } catch (javax.script.ScriptException e) { ++ e.printStackTrace(); ++ value = defaultValue.get(); ++ } ++ cache.get().put(size, value); ++ } ++ return value; ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + public void tick() { + super.tick(); +diff --git a/net/minecraft/world/entity/monster/Pillager.java b/net/minecraft/world/entity/monster/Pillager.java +index 4e799981f04cd17a34f043dda82869adcf16ea98..9586aa3f3eb61fb0c1224df9d0104da69d7fa6bb 100644 +--- a/net/minecraft/world/entity/monster/Pillager.java ++++ b/net/minecraft/world/entity/monster/Pillager.java +@@ -80,6 +80,14 @@ public class Pillager extends AbstractIllager implements CrossbowAttackMob, Inve + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.pillagerMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.pillagerScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected void registerGoals() { + super.registerGoals(); +diff --git a/net/minecraft/world/entity/monster/Ravager.java b/net/minecraft/world/entity/monster/Ravager.java +index a58a0d5d3872a57c8c5e464bd0f6d2fd7a054990..acfb473c0a085ed516ff25ebac366700c28c1ac0 100644 +--- a/net/minecraft/world/entity/monster/Ravager.java ++++ b/net/minecraft/world/entity/monster/Ravager.java +@@ -89,6 +89,14 @@ public class Ravager extends Raider { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.ravagerMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.ravagerScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected void registerGoals() { + super.registerGoals(); +diff --git a/net/minecraft/world/entity/monster/Shulker.java b/net/minecraft/world/entity/monster/Shulker.java +index 4dfc35f04ff841aa4fa198412c97cf59f843b4c2..83a8efba5937d61437c745f9b4be5aa02e7aac83 100644 +--- a/net/minecraft/world/entity/monster/Shulker.java ++++ b/net/minecraft/world/entity/monster/Shulker.java +@@ -105,6 +105,12 @@ public class Shulker extends AbstractGolem implements VariantHolder getMaxHealthCache() { ++ return level().purpurConfig.slimeMaxHealthCache; ++ } ++ ++ protected java.util.Map getAttackDamageCache() { ++ return level().purpurConfig.slimeAttackDamageCache; ++ } ++ ++ protected double getFromCache(java.util.function.Supplier equation, java.util.function.Supplier> cache, java.util.function.Supplier defaultValue) { ++ int size = getSize(); ++ Double value = cache.get().get(size); ++ if (value == null) { ++ try { ++ value = ((Number) scriptEngine.eval("let size = " + size + "; " + equation.get())).doubleValue(); ++ } catch (javax.script.ScriptException e) { ++ e.printStackTrace(); ++ value = defaultValue.get(); ++ } ++ cache.get().put(size, value); ++ } ++ return value; ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables +@@ -129,9 +162,9 @@ public class Slime extends Mob implements Enemy { + this.entityData.set(ID_SIZE, i); + this.reapplyPosition(); + this.refreshDimensions(); +- this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(i * i); ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(getFromCache(this::getMaxHealthEquation, this::getMaxHealthCache, () -> (double) (size * size))); // Purpur - Configurable entity base attributes + this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.2F + 0.1F * i); +- this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(i); ++ this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(getFromCache(this::getAttackDamageEquation, this::getAttackDamageCache, () -> (double) i)); // Purpur - Configurable entity base attributes + if (resetHealth) { + this.setHealth(this.getMaxHealth()); + } +diff --git a/net/minecraft/world/entity/monster/Spider.java b/net/minecraft/world/entity/monster/Spider.java +index ea83335dd0d128b32d2fe513eab82e642b533b4c..38d75a0a024fa1e7b12bfc5e3ab0ec8bb98cb17a 100644 +--- a/net/minecraft/world/entity/monster/Spider.java ++++ b/net/minecraft/world/entity/monster/Spider.java +@@ -67,6 +67,14 @@ public class Spider extends Monster { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.spiderMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.spiderScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(1, new FloatGoal(this)); +diff --git a/net/minecraft/world/entity/monster/Stray.java b/net/minecraft/world/entity/monster/Stray.java +index ed7ba19870a09ac78c1f069040a25e47c4b19d3a..0323456fca18450c22bf3999df97ff148a89e4c5 100644 +--- a/net/minecraft/world/entity/monster/Stray.java ++++ b/net/minecraft/world/entity/monster/Stray.java +@@ -39,6 +39,13 @@ public class Stray extends AbstractSkeleton { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.strayMaxHealth); ++ } ++ // Purpur end - Configurable entity base attributes ++ + public static boolean checkStraySpawnRules( + EntityType entityType, ServerLevelAccessor level, EntitySpawnReason spawnReason, BlockPos pos, RandomSource random + ) { +diff --git a/net/minecraft/world/entity/monster/Strider.java b/net/minecraft/world/entity/monster/Strider.java +index 15c1608b1a8f4d59b1d2cbc9c113ac3198119fb2..30cfd9b98f84f2aaa80aab529574d993b6d65c96 100644 +--- a/net/minecraft/world/entity/monster/Strider.java ++++ b/net/minecraft/world/entity/monster/Strider.java +@@ -111,6 +111,14 @@ public class Strider extends Animal implements ItemSteerable, Saddleable { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.striderMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.striderScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + public static boolean checkStriderSpawnRules( + EntityType entityType, LevelAccessor level, EntitySpawnReason spawnReason, BlockPos pos, RandomSource random + ) { +diff --git a/net/minecraft/world/entity/monster/Vex.java b/net/minecraft/world/entity/monster/Vex.java +index 26528bc9a9cffb68f82917a3e70900cfb65304d7..8356906b2c0707e21021bb05f9ca01a95682880a 100644 +--- a/net/minecraft/world/entity/monster/Vex.java ++++ b/net/minecraft/world/entity/monster/Vex.java +@@ -102,6 +102,14 @@ public class Vex extends Monster implements TraceableEntity { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.vexMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.vexScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + public boolean isFlapping() { + return this.tickCount % TICKS_PER_FLAP == 0; +diff --git a/net/minecraft/world/entity/monster/Vindicator.java b/net/minecraft/world/entity/monster/Vindicator.java +index 637d7a78dd92851afb8a68bfdbbf84019d21599c..81545d39715bffcadab8c48ae30be3a8023940e2 100644 +--- a/net/minecraft/world/entity/monster/Vindicator.java ++++ b/net/minecraft/world/entity/monster/Vindicator.java +@@ -72,6 +72,14 @@ public class Vindicator extends AbstractIllager { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.vindicatorMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.vindicatorScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected void registerGoals() { + super.registerGoals(); +diff --git a/net/minecraft/world/entity/monster/Witch.java b/net/minecraft/world/entity/monster/Witch.java +index 0b3c78e646d68ef57a7cf5d7eb77a07c497bd216..ff8380246f6c6c805b222a91ac6a1eb0d130558d 100644 +--- a/net/minecraft/world/entity/monster/Witch.java ++++ b/net/minecraft/world/entity/monster/Witch.java +@@ -73,6 +73,14 @@ public class Witch extends Raider implements RangedAttackMob { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.witchMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.witchScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected void registerGoals() { + super.registerGoals(); +diff --git a/net/minecraft/world/entity/monster/WitherSkeleton.java b/net/minecraft/world/entity/monster/WitherSkeleton.java +index b0f155564b11ff5fd2430694b937b7826df104ea..3342f2d92830049837636ff10b5e52f0d85fbd2c 100644 +--- a/net/minecraft/world/entity/monster/WitherSkeleton.java ++++ b/net/minecraft/world/entity/monster/WitherSkeleton.java +@@ -51,6 +51,14 @@ public class WitherSkeleton extends AbstractSkeleton { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.witherSkeletonMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.witherSkeletonScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected void registerGoals() { + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractPiglin.class, true)); +diff --git a/net/minecraft/world/entity/monster/Zoglin.java b/net/minecraft/world/entity/monster/Zoglin.java +index b279e33bb14dfea4813bba770daf950f5343419d..132b38d717ac3c5acc64a5ec519f345ac57021d8 100644 +--- a/net/minecraft/world/entity/monster/Zoglin.java ++++ b/net/minecraft/world/entity/monster/Zoglin.java +@@ -102,6 +102,14 @@ public class Zoglin extends Monster implements HoglinBase { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.zoglinMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.zoglinScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected Brain.Provider brainProvider() { + return Brain.provider(MEMORY_TYPES, SENSOR_TYPES); +diff --git a/net/minecraft/world/entity/monster/Zombie.java b/net/minecraft/world/entity/monster/Zombie.java +index c84de9ba38d365ae93ea4ba047f6812b1161a9ba..c1204ab167b84a33864d7a65f4bd3657ddf05e88 100644 +--- a/net/minecraft/world/entity/monster/Zombie.java ++++ b/net/minecraft/world/entity/monster/Zombie.java +@@ -117,6 +117,14 @@ public class Zombie extends Monster { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.zombieMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.zombieScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables +@@ -622,7 +630,7 @@ public class Zombie extends Monster { + } + + protected void randomizeReinforcementsChance() { +- this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).setBaseValue(this.random.nextDouble() * 0.1F); ++ this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).setBaseValue(this.random.nextDouble() * this.level().purpurConfig.zombieSpawnReinforcements); // Purpur - Configurable entity base attributes + } + + @Override +diff --git a/net/minecraft/world/entity/monster/ZombieVillager.java b/net/minecraft/world/entity/monster/ZombieVillager.java +index c79e03267b0030e844746945f947616c1b6e4726..610e5e5330462646034c5667c15245fdb2af77a0 100644 +--- a/net/minecraft/world/entity/monster/ZombieVillager.java ++++ b/net/minecraft/world/entity/monster/ZombieVillager.java +@@ -95,6 +95,18 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.zombieVillagerMaxHealth); ++ } ++ ++ @Override ++ protected void randomizeReinforcementsChance() { ++ this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.SPAWN_REINFORCEMENTS_CHANCE).setBaseValue(this.random.nextDouble() * this.level().purpurConfig.zombieVillagerSpawnReinforcements); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected void defineSynchedData(SynchedEntityData.Builder builder) { + super.defineSynchedData(builder); +diff --git a/net/minecraft/world/entity/monster/ZombifiedPiglin.java b/net/minecraft/world/entity/monster/ZombifiedPiglin.java +index f2d5866c10e82098d0276320cb3aa3f652b27477..486906b860b3ccbeb1702d9bd7a5d9f11f534b1a 100644 +--- a/net/minecraft/world/entity/monster/ZombifiedPiglin.java ++++ b/net/minecraft/world/entity/monster/ZombifiedPiglin.java +@@ -80,6 +80,14 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.zombifiedPiglinMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.zombifiedPiglinScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + public void setPersistentAngerTarget(@Nullable UUID target) { + this.persistentAngerTarget = target; +@@ -262,7 +270,7 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { + + @Override + protected void randomizeReinforcementsChance() { +- this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).setBaseValue(0.0); ++ this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).setBaseValue(this.random.nextDouble() * this.level().purpurConfig.zombifiedPiglinSpawnReinforcements); // Purpur - Configurable entity base attributes + } + + @Nullable +diff --git a/net/minecraft/world/entity/monster/creaking/Creaking.java b/net/minecraft/world/entity/monster/creaking/Creaking.java +index 57ac66c2de97c9b5940c1f0af663a1a26d2c8b73..887a81ea82b86edceaa46eb2032f53fccb84e158 100644 +--- a/net/minecraft/world/entity/monster/creaking/Creaking.java ++++ b/net/minecraft/world/entity/monster/creaking/Creaking.java +@@ -125,6 +125,14 @@ public class Creaking extends Monster { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.creakingMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.creakingScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected BodyRotationControl createBodyControl() { + return new Creaking.CreakingBodyRotationControl(this); +diff --git a/net/minecraft/world/entity/monster/hoglin/Hoglin.java b/net/minecraft/world/entity/monster/hoglin/Hoglin.java +index 028e09e1d8a14d989b2c19ca62e6544a93e1f1c4..54924cd7c84cbcd22ffc0bd37fc24f24e73c18bc 100644 +--- a/net/minecraft/world/entity/monster/hoglin/Hoglin.java ++++ b/net/minecraft/world/entity/monster/hoglin/Hoglin.java +@@ -109,6 +109,14 @@ public class Hoglin extends Animal implements Enemy, HoglinBase { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.hoglinMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.hoglinScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @VisibleForTesting + public void setTimeInOverworld(int timeInOverworld) { + this.timeInOverworld = timeInOverworld; +diff --git a/net/minecraft/world/entity/monster/piglin/Piglin.java b/net/minecraft/world/entity/monster/piglin/Piglin.java +index 02d748ecb10c3e20aafc0c449b99ca5b6cd80e04..897c57263ab7347987b289016a71d11f693bc8b2 100644 +--- a/net/minecraft/world/entity/monster/piglin/Piglin.java ++++ b/net/minecraft/world/entity/monster/piglin/Piglin.java +@@ -168,6 +168,14 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.piglinMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.piglinScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +diff --git a/net/minecraft/world/entity/monster/piglin/PiglinBrute.java b/net/minecraft/world/entity/monster/piglin/PiglinBrute.java +index 97241682311797faa93927e0477a7646ce53b2c8..eb82252cd87797927e153974b9280b5eaa251080 100644 +--- a/net/minecraft/world/entity/monster/piglin/PiglinBrute.java ++++ b/net/minecraft/world/entity/monster/piglin/PiglinBrute.java +@@ -82,6 +82,14 @@ public class PiglinBrute extends AbstractPiglin { + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.piglinBruteMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.piglinBruteScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + public static AttributeSupplier.Builder createAttributes() { + return Monster.createMonsterAttributes() + .add(Attributes.MAX_HEALTH, 50.0) +diff --git a/net/minecraft/world/entity/npc/Villager.java b/net/minecraft/world/entity/npc/Villager.java +index fbb12688470ac4dea129ee171c9fc001bdc8812b..85a6a38fb954915c7bf6290a40b0ab48818d08c8 100644 +--- a/net/minecraft/world/entity/npc/Villager.java ++++ b/net/minecraft/world/entity/npc/Villager.java +@@ -215,6 +215,14 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.villagerMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.villagerScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + public Brain getBrain() { + return (Brain)super.getBrain(); +diff --git a/net/minecraft/world/entity/npc/WanderingTrader.java b/net/minecraft/world/entity/npc/WanderingTrader.java +index 6c14537c8376bd392524aefde8dfe76b159c3655..470f8052af13b24d7cf6cfde19557219e32f4324 100644 +--- a/net/minecraft/world/entity/npc/WanderingTrader.java ++++ b/net/minecraft/world/entity/npc/WanderingTrader.java +@@ -86,6 +86,13 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill + } + // Purpur end - Ridables + ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.wanderingTraderMaxHealth); ++ } ++ // Purpur end - Configurable entity base attributes ++ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/world/entity/Entity.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/world/entity/Entity.java.patch new file mode 100644 index 000000000..f2101ff06 --- /dev/null +++ b/purpur-server/minecraft-patches/sources/net/minecraft/world/entity/Entity.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/Entity.java ++++ b/net/minecraft/world/entity/Entity.java +@@ -136,7 +_,7 @@ + import org.slf4j.Logger; + + public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, ScoreHolder, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity { // Paper - rewrite chunk system // Paper - optimise entity tracker +- ++ public static javax.script.ScriptEngine scriptEngine = new javax.script.ScriptEngineManager().getEngineByName("rhino"); // Purpur - Configurable entity base attributes + // CraftBukkit start + private static final int CURRENT_LEVEL = 2; + public boolean preserveMotion = true; // Paper - Fix Entity Teleportation and cancel velocity if teleported; keep initial motion on first setPositionRotation diff --git a/purpur-server/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/purpur-server/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java index 74e1d7474..6a745f39f 100644 --- a/purpur-server/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java +++ b/purpur-server/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java @@ -1,5 +1,8 @@ package org.purpurmc.purpur; +import java.util.HashMap; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.monster.Shulker; import org.bukkit.World; import org.bukkit.configuration.ConfigurationSection; import java.util.List; @@ -82,134 +85,261 @@ public class PurpurWorldConfig { public boolean allayRidable = false; public boolean allayRidableInWater = true; public boolean allayControllable = true; + public double allayMaxHealth = 20.0D; + public double allayScale = 1.0D; private void allaySettings() { allayRidable = getBoolean("mobs.allay.ridable", allayRidable); allayRidableInWater = getBoolean("mobs.allay.ridable-in-water", allayRidableInWater); allayControllable = getBoolean("mobs.allay.controllable", allayControllable); + allayMaxHealth = getDouble("mobs.allay.attributes.max_health", allayMaxHealth); + allayScale = Mth.clamp(getDouble("mobs.allay.attributes.scale", allayScale), 0.0625D, 16.0D); } public boolean armadilloRidable = false; public boolean armadilloRidableInWater = true; public boolean armadilloControllable = true; + public double armadilloMaxHealth = 12.0D; + public double armadilloScale = 1.0D; private void armadilloSettings() { armadilloRidable = getBoolean("mobs.armadillo.ridable", armadilloRidable); armadilloRidableInWater = getBoolean("mobs.armadillo.ridable-in-water", armadilloRidableInWater); armadilloControllable = getBoolean("mobs.armadillo.controllable", armadilloControllable); + armadilloMaxHealth = getDouble("mobs.armadillo.attributes.max_health", armadilloMaxHealth); + armadilloScale = Mth.clamp(getDouble("mobs.armadillo.attributes.scale", armadilloScale), 0.0625D, 16.0D); } public boolean axolotlRidable = false; public boolean axolotlControllable = true; + public double axolotlMaxHealth = 14.0D; + public double axolotlScale = 1.0D; private void axolotlSettings() { axolotlRidable = getBoolean("mobs.axolotl.ridable", axolotlRidable); axolotlControllable = getBoolean("mobs.axolotl.controllable", axolotlControllable); + axolotlMaxHealth = getDouble("mobs.axolotl.attributes.max_health", axolotlMaxHealth); + axolotlScale = Mth.clamp(getDouble("mobs.axolotl.attributes.scale", axolotlScale), 0.0625D, 16.0D); } public boolean batRidable = false; public boolean batRidableInWater = true; public boolean batControllable = true; public double batMaxY = 320D; + public double batMaxHealth = 6.0D; + public double batScale = 1.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); batControllable = getBoolean("mobs.bat.controllable", batControllable); 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); + batScale = Mth.clamp(getDouble("mobs.bat.attributes.scale", batScale), 0.0625D, 16.0D); + batFollowRange = getDouble("mobs.bat.attributes.follow_range", batFollowRange); + batKnockbackResistance = getDouble("mobs.bat.attributes.knockback_resistance", batKnockbackResistance); + batMovementSpeed = getDouble("mobs.bat.attributes.movement_speed", batMovementSpeed); + batFlyingSpeed = getDouble("mobs.bat.attributes.flying_speed", batFlyingSpeed); + batArmor = getDouble("mobs.bat.attributes.armor", batArmor); + batArmorToughness = getDouble("mobs.bat.attributes.armor_toughness", batArmorToughness); + batAttackKnockback = getDouble("mobs.bat.attributes.attack_knockback", batAttackKnockback); } public boolean beeRidable = false; public boolean beeRidableInWater = true; public boolean beeControllable = true; public double beeMaxY = 320D; + public double beeMaxHealth = 10.0D; + public double beeScale = 1.0D; private void beeSettings() { beeRidable = getBoolean("mobs.bee.ridable", beeRidable); beeRidableInWater = getBoolean("mobs.bee.ridable-in-water", beeRidableInWater); beeControllable = getBoolean("mobs.bee.controllable", beeControllable); beeMaxY = getDouble("mobs.bee.ridable-max-y", beeMaxY); + 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); + beeScale = Mth.clamp(getDouble("mobs.bee.attributes.scale", beeScale), 0.0625D, 16.0D); } public boolean blazeRidable = false; public boolean blazeRidableInWater = true; public boolean blazeControllable = true; public double blazeMaxY = 320D; + public double blazeMaxHealth = 20.0D; + public double blazeScale = 1.0D; private void blazeSettings() { blazeRidable = getBoolean("mobs.blaze.ridable", blazeRidable); blazeRidableInWater = getBoolean("mobs.blaze.ridable-in-water", blazeRidableInWater); blazeControllable = getBoolean("mobs.blaze.controllable", blazeControllable); 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); + blazeScale = Mth.clamp(getDouble("mobs.blaze.attributes.scale", blazeScale), 0.0625D, 16.0D); } public boolean boggedRidable = false; public boolean boggedRidableInWater = true; public boolean boggedControllable = true; + public double boggedMaxHealth = 16.0D; + public double boggedScale = 1.0D; private void boggedSettings() { boggedRidable = getBoolean("mobs.bogged.ridable", boggedRidable); boggedRidableInWater = getBoolean("mobs.bogged.ridable-in-water", boggedRidableInWater); boggedControllable = getBoolean("mobs.bogged.controllable", boggedControllable); + boggedMaxHealth = getDouble("mobs.bogged.attributes.max_health", boggedMaxHealth); + boggedScale = Mth.clamp(getDouble("mobs.bogged.attributes.scale", boggedScale), 0.0625D, 16.0D); } public boolean camelRidableInWater = false; + public double camelMaxHealthMin = 32.0D; + public double camelMaxHealthMax = 32.0D; + public double camelJumpStrengthMin = 0.42D; + public double camelJumpStrengthMax = 0.42D; + public double camelMovementSpeedMin = 0.09D; + public double camelMovementSpeedMax = 0.09D; private void camelSettings() { camelRidableInWater = getBoolean("mobs.camel.ridable-in-water", camelRidableInWater); + camelMaxHealthMin = getDouble("mobs.camel.attributes.max_health.min", camelMaxHealthMin); + camelMaxHealthMax = getDouble("mobs.camel.attributes.max_health.max", camelMaxHealthMax); + camelJumpStrengthMin = getDouble("mobs.camel.attributes.jump_strength.min", camelJumpStrengthMin); + camelJumpStrengthMax = getDouble("mobs.camel.attributes.jump_strength.max", camelJumpStrengthMax); + camelMovementSpeedMin = getDouble("mobs.camel.attributes.movement_speed.min", camelMovementSpeedMin); + camelMovementSpeedMax = getDouble("mobs.camel.attributes.movement_speed.max", camelMovementSpeedMax); } public boolean catRidable = false; public boolean catRidableInWater = true; public boolean catControllable = true; + public double catMaxHealth = 10.0D; + public double catScale = 1.0D; private void catSettings() { catRidable = getBoolean("mobs.cat.ridable", catRidable); catRidableInWater = getBoolean("mobs.cat.ridable-in-water", catRidableInWater); catControllable = getBoolean("mobs.cat.controllable", catControllable); + 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); + catScale = Mth.clamp(getDouble("mobs.cat.attributes.scale", catScale), 0.0625D, 16.0D); } public boolean caveSpiderRidable = false; public boolean caveSpiderRidableInWater = true; public boolean caveSpiderControllable = true; + public double caveSpiderMaxHealth = 12.0D; + public double caveSpiderScale = 1.0D; private void caveSpiderSettings() { caveSpiderRidable = getBoolean("mobs.cave_spider.ridable", caveSpiderRidable); caveSpiderRidableInWater = getBoolean("mobs.cave_spider.ridable-in-water", caveSpiderRidableInWater); caveSpiderControllable = getBoolean("mobs.cave_spider.controllable", caveSpiderControllable); + 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); + caveSpiderScale = Mth.clamp(getDouble("mobs.cave_spider.attributes.scale", caveSpiderScale), 0.0625D, 16.0D); } public boolean chickenRidable = false; public boolean chickenRidableInWater = false; public boolean chickenControllable = true; + public double chickenMaxHealth = 4.0D; + public double chickenScale = 1.0D; private void chickenSettings() { chickenRidable = getBoolean("mobs.chicken.ridable", chickenRidable); chickenRidableInWater = getBoolean("mobs.chicken.ridable-in-water", chickenRidableInWater); chickenControllable = getBoolean("mobs.chicken.controllable", chickenControllable); + 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); + chickenScale = Mth.clamp(getDouble("mobs.chicken.attributes.scale", chickenScale), 0.0625D, 16.0D); } public boolean codRidable = false; public boolean codControllable = true; + public double codMaxHealth = 3.0D; + public double codScale = 1.0D; private void codSettings() { codRidable = getBoolean("mobs.cod.ridable", codRidable); codControllable = getBoolean("mobs.cod.controllable", codControllable); + 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); + codScale = Mth.clamp(getDouble("mobs.cod.attributes.scale", codScale), 0.0625D, 16.0D); } public boolean cowRidable = false; public boolean cowRidableInWater = true; public boolean cowControllable = true; + public double cowMaxHealth = 10.0D; + public double cowScale = 1.0D; private void cowSettings() { cowRidable = getBoolean("mobs.cow.ridable", cowRidable); cowRidableInWater = getBoolean("mobs.cow.ridable-in-water", cowRidableInWater); cowControllable = getBoolean("mobs.cow.controllable", cowControllable); + 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); + cowScale = Mth.clamp(getDouble("mobs.cow.attributes.scale", cowScale), 0.0625D, 16.0D); } public boolean creakingRidable = false; public boolean creakingRidableInWater = true; public boolean creakingControllable = true; + public double creakingMaxHealth = 1.0D; + public double creakingScale = 1.0D; private void creakingSettings() { creakingRidable = getBoolean("mobs.creaking.ridable", creakingRidable); creakingRidableInWater = getBoolean("mobs.creaking.ridable-in-water", creakingRidableInWater); creakingControllable = getBoolean("mobs.creaking.controllable", creakingControllable); + creakingMaxHealth = getDouble("mobs.creaking.attributes.max_health", creakingMaxHealth); + creakingScale = Mth.clamp(getDouble("mobs.creaking.attributes.scale", creakingScale), 0.0625D, 16.0D); } public boolean creeperRidable = false; public boolean creeperRidableInWater = true; public boolean creeperControllable = true; + public double creeperMaxHealth = 20.0D; + public double creeperScale = 1.0D; private void creeperSettings() { creeperRidable = getBoolean("mobs.creeper.ridable", creeperRidable); creeperRidableInWater = getBoolean("mobs.creeper.ridable-in-water", creeperRidableInWater); creeperControllable = getBoolean("mobs.creeper.controllable", creeperControllable); + 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); + creeperScale = Mth.clamp(getDouble("mobs.creeper.attributes.scale", creeperScale), 0.0625D, 16.0D); } public boolean dolphinRidable = false; @@ -217,80 +347,175 @@ public class PurpurWorldConfig { public int dolphinSpitCooldown = 20; public float dolphinSpitSpeed = 1.0F; public float dolphinSpitDamage = 2.0F; + public double dolphinMaxHealth = 10.0D; + public double dolphinScale = 1.0D; private void dolphinSettings() { dolphinRidable = getBoolean("mobs.dolphin.ridable", dolphinRidable); dolphinControllable = getBoolean("mobs.dolphin.controllable", dolphinControllable); dolphinSpitCooldown = getInt("mobs.dolphin.spit.cooldown", dolphinSpitCooldown); dolphinSpitSpeed = (float) getDouble("mobs.dolphin.spit.speed", dolphinSpitSpeed); dolphinSpitDamage = (float) getDouble("mobs.dolphin.spit.damage", dolphinSpitDamage); + 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); + dolphinScale = Mth.clamp(getDouble("mobs.dolphin.attributes.scale", dolphinScale), 0.0625D, 16.0D); } public boolean donkeyRidableInWater = false; + 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); + 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; public boolean drownedRidableInWater = true; public boolean drownedControllable = true; + public double drownedMaxHealth = 20.0D; + public double drownedScale = 1.0D; + public double drownedSpawnReinforcements = 0.1D; private void drownedSettings() { drownedRidable = getBoolean("mobs.drowned.ridable", drownedRidable); drownedRidableInWater = getBoolean("mobs.drowned.ridable-in-water", drownedRidableInWater); drownedControllable = getBoolean("mobs.drowned.controllable", drownedControllable); + 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); + drownedScale = Mth.clamp(getDouble("mobs.drowned.attributes.scale", drownedScale), 0.0625D, 16.0D); + drownedSpawnReinforcements = getDouble("mobs.drowned.attributes.spawn_reinforcements", drownedSpawnReinforcements); } public boolean elderGuardianRidable = false; public boolean elderGuardianControllable = true; + public double elderGuardianMaxHealth = 80.0D; + public double elderGuardianScale = 1.0D; private void elderGuardianSettings() { elderGuardianRidable = getBoolean("mobs.elder_guardian.ridable", elderGuardianRidable); elderGuardianControllable = getBoolean("mobs.elder_guardian.controllable", elderGuardianControllable); + 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); + elderGuardianScale = Mth.clamp(getDouble("mobs.elder_guardian.attributes.scale", elderGuardianScale), 0.0625D, 16.0D); } public boolean enderDragonRidable = false; public boolean enderDragonRidableInWater = true; public boolean enderDragonControllable = true; public double enderDragonMaxY = 320D; + public double enderDragonMaxHealth = 200.0D; private void enderDragonSettings() { enderDragonRidable = getBoolean("mobs.ender_dragon.ridable", enderDragonRidable); enderDragonRidableInWater = getBoolean("mobs.ender_dragon.ridable-in-water", enderDragonRidableInWater); enderDragonControllable = getBoolean("mobs.ender_dragon.controllable", enderDragonControllable); enderDragonMaxY = getDouble("mobs.ender_dragon.ridable-max-y", enderDragonMaxY); + 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 = true; public boolean endermanControllable = true; + public double endermanMaxHealth = 40.0D; + public double endermanScale = 1.0D; private void endermanSettings() { endermanRidable = getBoolean("mobs.enderman.ridable", endermanRidable); endermanRidableInWater = getBoolean("mobs.enderman.ridable-in-water", endermanRidableInWater); endermanControllable = getBoolean("mobs.enderman.controllable", endermanControllable); + 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); + endermanScale = Mth.clamp(getDouble("mobs.enderman.attributes.scale", endermanScale), 0.0625D, 16.0D); } public boolean endermiteRidable = false; public boolean endermiteRidableInWater = true; public boolean endermiteControllable = true; + public double endermiteMaxHealth = 8.0D; + public double endermiteScale = 1.0D; private void endermiteSettings() { endermiteRidable = getBoolean("mobs.endermite.ridable", endermiteRidable); endermiteRidableInWater = getBoolean("mobs.endermite.ridable-in-water", endermiteRidableInWater); endermiteControllable = getBoolean("mobs.endermite.controllable", endermiteControllable); + 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); + endermiteScale = Mth.clamp(getDouble("mobs.endermite.attributes.scale", endermiteScale), 0.0625D, 16.0D); } public boolean evokerRidable = false; public boolean evokerRidableInWater = true; public boolean evokerControllable = true; + public double evokerMaxHealth = 24.0D; + public double evokerScale = 1.0D; private void evokerSettings() { evokerRidable = getBoolean("mobs.evoker.ridable", evokerRidable); evokerRidableInWater = getBoolean("mobs.evoker.ridable-in-water", evokerRidableInWater); evokerControllable = getBoolean("mobs.evoker.controllable", evokerControllable); + 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); + evokerScale = Mth.clamp(getDouble("mobs.evoker.attributes.scale", evokerScale), 0.0625D, 16.0D); } public boolean foxRidable = false; public boolean foxRidableInWater = true; public boolean foxControllable = true; + public double foxMaxHealth = 10.0D; + public double foxScale = 1.0D; private void foxSettings() { foxRidable = getBoolean("mobs.fox.ridable", foxRidable); foxRidableInWater = getBoolean("mobs.fox.ridable-in-water", foxRidableInWater); foxControllable = getBoolean("mobs.fox.controllable", foxControllable); + 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); + foxScale = Mth.clamp(getDouble("mobs.fox.attributes.scale", foxScale), 0.0625D, 16.0D); } public boolean frogRidable = false; @@ -308,147 +533,342 @@ public class PurpurWorldConfig { public boolean ghastRidableInWater = true; public boolean ghastControllable = true; public double ghastMaxY = 320D; + public double ghastMaxHealth = 10.0D; + public double ghastScale = 1.0D; private void ghastSettings() { ghastRidable = getBoolean("mobs.ghast.ridable", ghastRidable); ghastRidableInWater = getBoolean("mobs.ghast.ridable-in-water", ghastRidableInWater); ghastControllable = getBoolean("mobs.ghast.controllable", ghastControllable); 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); + ghastScale = Mth.clamp(getDouble("mobs.ghast.attributes.scale", ghastScale), 0.0625D, 16.0D); } public boolean giantRidable = false; public boolean giantRidableInWater = true; public boolean giantControllable = true; + public double giantMovementSpeed = 0.5D; + public double giantAttackDamage = 50.0D; + public double giantMaxHealth = 100.0D; + public double giantScale = 1.0D; private void giantSettings() { giantRidable = getBoolean("mobs.giant.ridable", giantRidable); giantRidableInWater = getBoolean("mobs.giant.ridable-in-water", giantRidableInWater); giantControllable = getBoolean("mobs.giant.controllable", giantControllable); + giantMovementSpeed = getDouble("mobs.giant.movement-speed", giantMovementSpeed); + giantAttackDamage = getDouble("mobs.giant.attack-damage", giantAttackDamage); + if (PurpurConfig.version < 8) { + double oldValue = getDouble("mobs.giant.max-health", giantMaxHealth); + 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); + giantScale = Mth.clamp(getDouble("mobs.giant.attributes.scale", giantScale), 0.0625D, 16.0D); } public boolean glowSquidRidable = false; public boolean glowSquidControllable = true; + public double glowSquidMaxHealth = 10.0D; + public double glowSquidScale = 1.0D; private void glowSquidSettings() { glowSquidRidable = getBoolean("mobs.glow_squid.ridable", glowSquidRidable); glowSquidControllable = getBoolean("mobs.glow_squid.controllable", glowSquidControllable); + glowSquidMaxHealth = getDouble("mobs.glow_squid.attributes.max_health", glowSquidMaxHealth); + glowSquidScale = Mth.clamp(getDouble("mobs.glow_squid.attributes.scale", glowSquidScale), 0.0625D, 16.0D); } public boolean goatRidable = false; public boolean goatRidableInWater = true; public boolean goatControllable = true; + public double goatMaxHealth = 10.0D; + public double goatScale = 1.0D; private void goatSettings() { goatRidable = getBoolean("mobs.goat.ridable", goatRidable); goatRidableInWater = getBoolean("mobs.goat.ridable-in-water", goatRidableInWater); goatControllable = getBoolean("mobs.goat.controllable", goatControllable); + goatMaxHealth = getDouble("mobs.goat.attributes.max_health", goatMaxHealth); + goatScale = Mth.clamp(getDouble("mobs.goat.attributes.scale", goatScale), 0.0625D, 16.0D); } public boolean guardianRidable = false; public boolean guardianControllable = true; + public double guardianMaxHealth = 30.0D; + public double guardianScale = 1.0D; private void guardianSettings() { guardianRidable = getBoolean("mobs.guardian.ridable", guardianRidable); guardianControllable = getBoolean("mobs.guardian.controllable", guardianControllable); + 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); + guardianScale = Mth.clamp(getDouble("mobs.guardian.attributes.scale", guardianScale), 0.0625D, 16.0D); } public boolean hoglinRidable = false; public boolean hoglinRidableInWater = true; public boolean hoglinControllable = true; + public double hoglinMaxHealth = 40.0D; + public double hoglinScale = 1.0D; private void hoglinSettings() { hoglinRidable = getBoolean("mobs.hoglin.ridable", hoglinRidable); hoglinRidableInWater = getBoolean("mobs.hoglin.ridable-in-water", hoglinRidableInWater); hoglinControllable = getBoolean("mobs.hoglin.controllable", hoglinControllable); + 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); + hoglinScale = Mth.clamp(getDouble("mobs.hoglin.attributes.scale", hoglinScale), 0.0625D, 16.0D); } public boolean horseRidableInWater = false; + 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); + 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; public boolean huskRidableInWater = true; public boolean huskControllable = true; + public double huskMaxHealth = 20.0D; + public double huskScale = 1.0D; + public double huskSpawnReinforcements = 0.1D; private void huskSettings() { huskRidable = getBoolean("mobs.husk.ridable", huskRidable); huskRidableInWater = getBoolean("mobs.husk.ridable-in-water", huskRidableInWater); huskControllable = getBoolean("mobs.husk.controllable", huskControllable); + 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); + huskScale = Mth.clamp(getDouble("mobs.husk.attributes.scale", huskScale), 0.0625D, 16.0D); + huskSpawnReinforcements = getDouble("mobs.husk.attributes.spawn_reinforcements", huskSpawnReinforcements); } public boolean illusionerRidable = false; public boolean illusionerRidableInWater = true; public boolean illusionerControllable = true; + public double illusionerMovementSpeed = 0.5D; + public double illusionerFollowRange = 18.0D; + public double illusionerMaxHealth = 32.0D; + public double illusionerScale = 1.0D; private void illusionerSettings() { illusionerRidable = getBoolean("mobs.illusioner.ridable", illusionerRidable); illusionerRidableInWater = getBoolean("mobs.illusioner.ridable-in-water", illusionerRidableInWater); illusionerControllable = getBoolean("mobs.illusioner.controllable", illusionerControllable); + illusionerMovementSpeed = getDouble("mobs.illusioner.movement-speed", illusionerMovementSpeed); + illusionerFollowRange = getDouble("mobs.illusioner.follow-range", illusionerFollowRange); + if (PurpurConfig.version < 8) { + double oldValue = getDouble("mobs.illusioner.max-health", illusionerMaxHealth); + 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); + illusionerScale = Mth.clamp(getDouble("mobs.illusioner.attributes.scale", illusionerScale), 0.0625D, 16.0D); } public boolean ironGolemRidable = false; public boolean ironGolemRidableInWater = true; public boolean ironGolemControllable = true; public boolean ironGolemCanSwim = false; + public double ironGolemMaxHealth = 100.0D; + public double ironGolemScale = 1.0D; private void ironGolemSettings() { ironGolemRidable = getBoolean("mobs.iron_golem.ridable", ironGolemRidable); ironGolemRidableInWater = getBoolean("mobs.iron_golem.ridable-in-water", ironGolemRidableInWater); ironGolemControllable = getBoolean("mobs.iron_golem.controllable", ironGolemControllable); 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); + ironGolemScale = Mth.clamp(getDouble("mobs.iron_golem.attributes.scale", ironGolemScale), 0.0625D, 16.0D); } public boolean llamaRidable = false; public boolean llamaRidableInWater = false; public boolean llamaControllable = true; + 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); llamaControllable = getBoolean("mobs.llama.controllable", llamaControllable); + 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 magmaCubeRidable = false; public boolean magmaCubeRidableInWater = true; public boolean magmaCubeControllable = true; + public String magmaCubeMaxHealth = "size * size"; + public String magmaCubeAttackDamage = "size"; + public Map magmaCubeMaxHealthCache = new HashMap<>(); + public Map magmaCubeAttackDamageCache = new HashMap<>(); private void magmaCubeSettings() { magmaCubeRidable = getBoolean("mobs.magma_cube.ridable", magmaCubeRidable); magmaCubeRidableInWater = getBoolean("mobs.magma_cube.ridable-in-water", magmaCubeRidableInWater); magmaCubeControllable = getBoolean("mobs.magma_cube.controllable", magmaCubeControllable); + 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); + magmaCubeAttackDamage = getString("mobs.magma_cube.attributes.attack_damage", magmaCubeAttackDamage); + magmaCubeMaxHealthCache.clear(); + magmaCubeAttackDamageCache.clear(); } public boolean mooshroomRidable = false; public boolean mooshroomRidableInWater = true; public boolean mooshroomControllable = true; + public double mooshroomMaxHealth = 10.0D; + public double mooshroomScale = 1.0D; private void mooshroomSettings() { mooshroomRidable = getBoolean("mobs.mooshroom.ridable", mooshroomRidable); mooshroomRidableInWater = getBoolean("mobs.mooshroom.ridable-in-water", mooshroomRidableInWater); mooshroomControllable = getBoolean("mobs.mooshroom.controllable", mooshroomControllable); + 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); + mooshroomScale = Mth.clamp(getDouble("mobs.mooshroom.attributes.scale", mooshroomScale), 0.0625D, 16.0D); } public boolean muleRidableInWater = false; + 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); + 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 = true; public boolean ocelotControllable = true; + public double ocelotMaxHealth = 10.0D; + public double ocelotScale = 1.0D; private void ocelotSettings() { ocelotRidable = getBoolean("mobs.ocelot.ridable", ocelotRidable); ocelotRidableInWater = getBoolean("mobs.ocelot.ridable-in-water", ocelotRidableInWater); ocelotControllable = getBoolean("mobs.ocelot.controllable", ocelotControllable); + 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); + ocelotScale = Mth.clamp(getDouble("mobs.ocelot.attributes.scale", ocelotScale), 0.0625D, 16.0D); } public boolean pandaRidable = false; public boolean pandaRidableInWater = true; public boolean pandaControllable = true; + public double pandaMaxHealth = 20.0D; + public double pandaScale = 1.0D; private void pandaSettings() { pandaRidable = getBoolean("mobs.panda.ridable", pandaRidable); pandaRidableInWater = getBoolean("mobs.panda.ridable-in-water", pandaRidableInWater); pandaControllable = getBoolean("mobs.panda.controllable", pandaControllable); + 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); + pandaScale = Mth.clamp(getDouble("mobs.panda.attributes.scale", pandaScale), 0.0625D, 16.0D); } public boolean parrotRidable = false; public boolean parrotRidableInWater = true; public boolean parrotControllable = true; public double parrotMaxY = 320D; + public double parrotMaxHealth = 6.0D; + public double parrotScale = 1.0D; private void parrotSettings() { parrotRidable = getBoolean("mobs.parrot.ridable", parrotRidable); parrotRidableInWater = getBoolean("mobs.parrot.ridable-in-water", parrotRidableInWater); parrotControllable = getBoolean("mobs.parrot.controllable", parrotControllable); 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); + parrotScale = Mth.clamp(getDouble("mobs.parrot.attributes.scale", parrotScale), 0.0625D, 16.0D); } public boolean phantomRidable = false; @@ -458,6 +878,10 @@ public class PurpurWorldConfig { public float phantomFlameDamage = 1.0F; public int phantomFlameFireTime = 8; public boolean phantomAllowGriefing = false; + public String phantomMaxHealth = "20.0"; + public String phantomAttackDamage = "6 + size"; + public Map phantomMaxHealthCache = new HashMap<>(); + public Map phantomAttackDamageCache = new HashMap<>(); private void phantomSettings() { phantomRidable = getBoolean("mobs.phantom.ridable", phantomRidable); phantomRidableInWater = getBoolean("mobs.phantom.ridable-in-water", phantomRidableInWater); @@ -466,191 +890,405 @@ public class PurpurWorldConfig { phantomFlameDamage = (float) getDouble("mobs.phantom.flames.damage", phantomFlameDamage); phantomFlameFireTime = getInt("mobs.phantom.flames.fire-time", phantomFlameFireTime); phantomAllowGriefing = getBoolean("mobs.phantom.allow-griefing", phantomAllowGriefing); + if (PurpurConfig.version < 10) { + double oldValue = getDouble("mobs.phantom.attributes.max-health", Double.parseDouble(phantomMaxHealth)); + set("mobs.phantom.attributes.max-health", null); + set("mobs.phantom.attributes.max_health", String.valueOf(oldValue)); + } + if (PurpurConfig.version < 25) { + double oldValue = getDouble("mobs.phantom.attributes.max_health", Double.parseDouble(phantomMaxHealth)); + set("mobs.phantom.attributes.max_health", String.valueOf(oldValue)); + } + phantomMaxHealth = getString("mobs.phantom.attributes.max_health", phantomMaxHealth); + phantomAttackDamage = getString("mobs.phantom.attributes.attack_damage", phantomAttackDamage); + phantomMaxHealthCache.clear(); + phantomAttackDamageCache.clear(); } public boolean pigRidable = false; public boolean pigRidableInWater = false; public boolean pigControllable = true; + public double pigMaxHealth = 10.0D; + public double pigScale = 1.0D; private void pigSettings() { pigRidable = getBoolean("mobs.pig.ridable", pigRidable); pigRidableInWater = getBoolean("mobs.pig.ridable-in-water", pigRidableInWater); pigControllable = getBoolean("mobs.pig.controllable", pigControllable); + 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); + pigScale = Mth.clamp(getDouble("mobs.pig.attributes.scale", pigScale), 0.0625D, 16.0D); } public boolean piglinRidable = false; public boolean piglinRidableInWater = true; public boolean piglinControllable = true; + public double piglinMaxHealth = 16.0D; + public double piglinScale = 1.0D; private void piglinSettings() { piglinRidable = getBoolean("mobs.piglin.ridable", piglinRidable); piglinRidableInWater = getBoolean("mobs.piglin.ridable-in-water", piglinRidableInWater); piglinControllable = getBoolean("mobs.piglin.controllable", piglinControllable); + 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); + piglinScale = Mth.clamp(getDouble("mobs.piglin.attributes.scale", piglinScale), 0.0625D, 16.0D); } public boolean piglinBruteRidable = false; public boolean piglinBruteRidableInWater = true; public boolean piglinBruteControllable = true; + public double piglinBruteMaxHealth = 50.0D; + public double piglinBruteScale = 1.0D; private void piglinBruteSettings() { piglinBruteRidable = getBoolean("mobs.piglin_brute.ridable", piglinBruteRidable); piglinBruteRidableInWater = getBoolean("mobs.piglin_brute.ridable-in-water", piglinBruteRidableInWater); piglinBruteControllable = getBoolean("mobs.piglin_brute.controllable", piglinBruteControllable); + 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); + piglinBruteScale = Mth.clamp(getDouble("mobs.piglin_brute.attributes.scale", piglinBruteScale), 0.0625D, 16.0D); } public boolean pillagerRidable = false; public boolean pillagerRidableInWater = true; public boolean pillagerControllable = true; + public double pillagerMaxHealth = 24.0D; + public double pillagerScale = 1.0D; private void pillagerSettings() { pillagerRidable = getBoolean("mobs.pillager.ridable", pillagerRidable); pillagerRidableInWater = getBoolean("mobs.pillager.ridable-in-water", pillagerRidableInWater); pillagerControllable = getBoolean("mobs.pillager.controllable", pillagerControllable); + 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); + pillagerScale = Mth.clamp(getDouble("mobs.pillager.attributes.scale", pillagerScale), 0.0625D, 16.0D); } public boolean polarBearRidable = false; public boolean polarBearRidableInWater = true; public boolean polarBearControllable = true; + public double polarBearMaxHealth = 30.0D; + public double polarBearScale = 1.0D; private void polarBearSettings() { polarBearRidable = getBoolean("mobs.polar_bear.ridable", polarBearRidable); polarBearRidableInWater = getBoolean("mobs.polar_bear.ridable-in-water", polarBearRidableInWater); polarBearControllable = getBoolean("mobs.polar_bear.controllable", polarBearControllable); + 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); + polarBearScale = Mth.clamp(getDouble("mobs.polar_bear.attributes.scale", polarBearScale), 0.0625D, 16.0D); } public boolean pufferfishRidable = false; public boolean pufferfishControllable = true; + public double pufferfishMaxHealth = 3.0D; + public double pufferfishScale = 1.0D; private void pufferfishSettings() { pufferfishRidable = getBoolean("mobs.pufferfish.ridable", pufferfishRidable); pufferfishControllable = getBoolean("mobs.pufferfish.controllable", pufferfishControllable); + 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); + pufferfishScale = Mth.clamp(getDouble("mobs.pufferfish.attributes.scale", pufferfishScale), 0.0625D, 16.0D); } public boolean rabbitRidable = false; public boolean rabbitRidableInWater = true; public boolean rabbitControllable = true; + public double rabbitMaxHealth = 3.0D; + public double rabbitScale = 1.0D; private void rabbitSettings() { rabbitRidable = getBoolean("mobs.rabbit.ridable", rabbitRidable); rabbitRidableInWater = getBoolean("mobs.rabbit.ridable-in-water", rabbitRidableInWater); rabbitControllable = getBoolean("mobs.rabbit.controllable", rabbitControllable); + 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); + rabbitScale = Mth.clamp(getDouble("mobs.rabbit.attributes.scale", rabbitScale), 0.0625D, 16.0D); } public boolean ravagerRidable = false; public boolean ravagerRidableInWater = false; public boolean ravagerControllable = true; + public double ravagerMaxHealth = 100.0D; + public double ravagerScale = 1.0D; private void ravagerSettings() { ravagerRidable = getBoolean("mobs.ravager.ridable", ravagerRidable); ravagerRidableInWater = getBoolean("mobs.ravager.ridable-in-water", ravagerRidableInWater); ravagerControllable = getBoolean("mobs.ravager.controllable", ravagerControllable); + 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); + ravagerScale = Mth.clamp(getDouble("mobs.ravager.attributes.scale", ravagerScale), 0.0625D, 16.0D); } public boolean salmonRidable = false; public boolean salmonControllable = true; + public double salmonMaxHealth = 3.0D; + public double salmonScale = 1.0D; private void salmonSettings() { salmonRidable = getBoolean("mobs.salmon.ridable", salmonRidable); salmonControllable = getBoolean("mobs.salmon.controllable", salmonControllable); + 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); + salmonScale = Mth.clamp(getDouble("mobs.salmon.attributes.scale", salmonScale), 0.0625D, 16.0D); } public boolean sheepRidable = false; public boolean sheepRidableInWater = true; public boolean sheepControllable = true; + public double sheepMaxHealth = 8.0D; + public double sheepScale = 1.0D; private void sheepSettings() { sheepRidable = getBoolean("mobs.sheep.ridable", sheepRidable); sheepRidableInWater = getBoolean("mobs.sheep.ridable-in-water", sheepRidableInWater); sheepControllable = getBoolean("mobs.sheep.controllable", sheepControllable); + 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); + sheepScale = Mth.clamp(getDouble("mobs.sheep.attributes.scale", sheepScale), 0.0625D, 16.0D); } public boolean shulkerRidable = false; public boolean shulkerRidableInWater = true; public boolean shulkerControllable = true; + public double shulkerMaxHealth = 30.0D; + public double shulkerScale = 1.0D; private void shulkerSettings() { shulkerRidable = getBoolean("mobs.shulker.ridable", shulkerRidable); shulkerRidableInWater = getBoolean("mobs.shulker.ridable-in-water", shulkerRidableInWater); shulkerControllable = getBoolean("mobs.shulker.controllable", shulkerControllable); + 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); + shulkerScale = Mth.clamp(getDouble("mobs.shulker.attributes.scale", shulkerScale), 0.0625D, Shulker.MAX_SCALE); } public boolean silverfishRidable = false; public boolean silverfishRidableInWater = true; public boolean silverfishControllable = true; + public double silverfishMaxHealth = 8.0D; + public double silverfishScale = 1.0D; + public double silverfishMovementSpeed = 0.25D; + public double silverfishAttackDamage = 1.0D; private void silverfishSettings() { silverfishRidable = getBoolean("mobs.silverfish.ridable", silverfishRidable); silverfishRidableInWater = getBoolean("mobs.silverfish.ridable-in-water", silverfishRidableInWater); silverfishControllable = getBoolean("mobs.silverfish.controllable", silverfishControllable); + 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); + silverfishScale = Mth.clamp(getDouble("mobs.silverfish.attributes.scale", silverfishScale), 0.0625D, 16.0D); + silverfishMovementSpeed = getDouble("mobs.silverfish.attributes.movement_speed", silverfishMovementSpeed); + silverfishAttackDamage = getDouble("mobs.silverfish.attributes.attack_damage", silverfishAttackDamage); } public boolean skeletonRidable = false; public boolean skeletonRidableInWater = true; public boolean skeletonControllable = true; + public double skeletonMaxHealth = 20.0D; + public double skeletonScale = 1.0D; private void skeletonSettings() { skeletonRidable = getBoolean("mobs.skeleton.ridable", skeletonRidable); skeletonRidableInWater = getBoolean("mobs.skeleton.ridable-in-water", skeletonRidableInWater); skeletonControllable = getBoolean("mobs.skeleton.controllable", skeletonControllable); + 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); + skeletonScale = Mth.clamp(getDouble("mobs.skeleton.attributes.scale", skeletonScale), 0.0625D, 16.0D); } public boolean skeletonHorseRidable = false; public boolean skeletonHorseRidableInWater = true; public boolean skeletonHorseCanSwim = false; + 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() { skeletonHorseRidable = getBoolean("mobs.skeleton_horse.ridable", skeletonHorseRidable); skeletonHorseRidableInWater = getBoolean("mobs.skeleton_horse.ridable-in-water", skeletonHorseRidableInWater); skeletonHorseCanSwim = getBoolean("mobs.skeleton_horse.can-swim", skeletonHorseCanSwim); + 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 = true; public boolean slimeControllable = true; + public String slimeMaxHealth = "size * size"; + public String slimeAttackDamage = "size"; + public Map slimeMaxHealthCache = new HashMap<>(); + public Map slimeAttackDamageCache = new HashMap<>(); private void slimeSettings() { slimeRidable = getBoolean("mobs.slime.ridable", slimeRidable); slimeRidableInWater = getBoolean("mobs.slime.ridable-in-water", slimeRidableInWater); slimeControllable = getBoolean("mobs.slime.controllable", slimeControllable); + 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); + slimeAttackDamage = getString("mobs.slime.attributes.attack_damage", slimeAttackDamage); + slimeMaxHealthCache.clear(); + slimeAttackDamageCache.clear(); } public boolean snowGolemRidable = false; public boolean snowGolemRidableInWater = true; public boolean snowGolemControllable = true; public boolean snowGolemLeaveTrailWhenRidden = false; + public double snowGolemMaxHealth = 4.0D; + public double snowGolemScale = 1.0D; private void snowGolemSettings() { snowGolemRidable = getBoolean("mobs.snow_golem.ridable", snowGolemRidable); snowGolemRidableInWater = getBoolean("mobs.snow_golem.ridable-in-water", snowGolemRidableInWater); snowGolemControllable = getBoolean("mobs.snow_golem.controllable", snowGolemControllable); snowGolemLeaveTrailWhenRidden = getBoolean("mobs.snow_golem.leave-trail-when-ridden", snowGolemLeaveTrailWhenRidden); + 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); + snowGolemScale = Mth.clamp(getDouble("mobs.snow_golem.attributes.scale", snowGolemScale), 0.0625D, 16.0D); } public boolean snifferRidable = false; public boolean snifferRidableInWater = true; public boolean snifferControllable = true; + public double snifferMaxHealth = 14.0D; + public double snifferScale = 1.0D; private void snifferSettings() { snifferRidable = getBoolean("mobs.sniffer.ridable", snifferRidable); snifferRidableInWater = getBoolean("mobs.sniffer.ridable-in-water", snifferRidableInWater); snifferControllable = getBoolean("mobs.sniffer.controllable", snifferControllable); + snifferMaxHealth = getDouble("mobs.sniffer.attributes.max_health", snifferMaxHealth); + snifferScale = Mth.clamp(getDouble("mobs.sniffer.attributes.scale", snifferScale), 0.0625D, 16.0D); } public boolean squidRidable = false; public boolean squidControllable = true; + public double squidMaxHealth = 10.0D; + public double squidScale = 1.0D; private void squidSettings() { squidRidable = getBoolean("mobs.squid.ridable", squidRidable); squidControllable = getBoolean("mobs.squid.controllable", squidControllable); + 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); + squidScale = Mth.clamp(getDouble("mobs.squid.attributes.scale", squidScale), 0.0625D, 16.0D); } public boolean spiderRidable = false; public boolean spiderRidableInWater = false; public boolean spiderControllable = true; + public double spiderMaxHealth = 16.0D; + public double spiderScale = 1.0D; private void spiderSettings() { spiderRidable = getBoolean("mobs.spider.ridable", spiderRidable); spiderRidableInWater = getBoolean("mobs.spider.ridable-in-water", spiderRidableInWater); spiderControllable = getBoolean("mobs.spider.controllable", spiderControllable); + 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); + spiderScale = Mth.clamp(getDouble("mobs.spider.attributes.scale", spiderScale), 0.0625D, 16.0D); } public boolean strayRidable = false; public boolean strayRidableInWater = true; public boolean strayControllable = true; + public double strayMaxHealth = 20.0D; + public double strayScale = 1.0D; private void straySettings() { strayRidable = getBoolean("mobs.stray.ridable", strayRidable); strayRidableInWater = getBoolean("mobs.stray.ridable-in-water", strayRidableInWater); strayControllable = getBoolean("mobs.stray.controllable", strayControllable); + 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); + strayScale = Mth.clamp(getDouble("mobs.stray.attributes.scale", strayScale), 0.0625D, 16.0D); } public boolean striderRidable = false; public boolean striderRidableInWater = false; public boolean striderControllable = true; + public double striderMaxHealth = 20.0D; + public double striderScale = 1.0D; private void striderSettings() { striderRidable = getBoolean("mobs.strider.ridable", striderRidable); striderRidableInWater = getBoolean("mobs.strider.ridable-in-water", striderRidableInWater); striderControllable = getBoolean("mobs.strider.controllable", striderControllable); + 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); + striderScale = Mth.clamp(getDouble("mobs.strider.attributes.scale", striderScale), 0.0625D, 16.0D); } public boolean tadpoleRidable = false; @@ -665,64 +1303,137 @@ public class PurpurWorldConfig { public boolean traderLlamaRidable = false; public boolean traderLlamaRidableInWater = false; public boolean traderLlamaControllable = true; + public double traderLlamaMaxHealthMin = 15.0D; + public double traderLlamaMaxHealthMax = 30.0D; + public double traderLlamaJumpStrengthMin = 0.5D; + public double traderLlamaJumpStrengthMax = 0.5D; + public double traderLlamaMovementSpeedMin = 0.175D; + public double traderLlamaMovementSpeedMax = 0.175D; private void traderLlamaSettings() { traderLlamaRidable = getBoolean("mobs.trader_llama.ridable", traderLlamaRidable); traderLlamaRidableInWater = getBoolean("mobs.trader_llama.ridable-in-water", traderLlamaRidableInWater); traderLlamaControllable = getBoolean("mobs.trader_llama.controllable", traderLlamaControllable); + if (PurpurConfig.version < 10) { + double oldMin = getDouble("mobs.trader_llama.attributes.max-health.min", traderLlamaMaxHealthMin); + double oldMax = getDouble("mobs.trader_llama.attributes.max-health.max", traderLlamaMaxHealthMax); + 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); + } + traderLlamaMaxHealthMin = getDouble("mobs.trader_llama.attributes.max_health.min", traderLlamaMaxHealthMin); + traderLlamaMaxHealthMax = getDouble("mobs.trader_llama.attributes.max_health.max", traderLlamaMaxHealthMax); + traderLlamaJumpStrengthMin = getDouble("mobs.trader_llama.attributes.jump_strength.min", traderLlamaJumpStrengthMin); + traderLlamaJumpStrengthMax = getDouble("mobs.trader_llama.attributes.jump_strength.max", traderLlamaJumpStrengthMax); + traderLlamaMovementSpeedMin = getDouble("mobs.trader_llama.attributes.movement_speed.min", traderLlamaMovementSpeedMin); + traderLlamaMovementSpeedMax = getDouble("mobs.trader_llama.attributes.movement_speed.max", traderLlamaMovementSpeedMax); } public boolean tropicalFishRidable = false; public boolean tropicalFishControllable = true; + public double tropicalFishMaxHealth = 3.0D; + public double tropicalFishScale = 1.0D; private void tropicalFishSettings() { tropicalFishRidable = getBoolean("mobs.tropical_fish.ridable", tropicalFishRidable); tropicalFishControllable = getBoolean("mobs.tropical_fish.controllable", tropicalFishControllable); + 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); + tropicalFishScale = Mth.clamp(getDouble("mobs.tropical_fish.attributes.scale", tropicalFishScale), 0.0625D, 16.0D); } public boolean turtleRidable = false; public boolean turtleRidableInWater = true; public boolean turtleControllable = true; + public double turtleMaxHealth = 30.0D; + public double turtleScale = 1.0D; private void turtleSettings() { turtleRidable = getBoolean("mobs.turtle.ridable", turtleRidable); turtleRidableInWater = getBoolean("mobs.turtle.ridable-in-water", turtleRidableInWater); turtleControllable = getBoolean("mobs.turtle.controllable", turtleControllable); + 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); + turtleScale = Mth.clamp(getDouble("mobs.turtle.attributes.scale", turtleScale), 0.0625D, 16.0D); } public boolean vexRidable = false; public boolean vexRidableInWater = true; public boolean vexControllable = true; public double vexMaxY = 320D; + public double vexMaxHealth = 14.0D; + public double vexScale = 1.0D; private void vexSettings() { vexRidable = getBoolean("mobs.vex.ridable", vexRidable); vexRidableInWater = getBoolean("mobs.vex.ridable-in-water", vexRidableInWater); vexControllable = getBoolean("mobs.vex.controllable", vexControllable); 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); + vexScale = Mth.clamp(getDouble("mobs.vex.attributes.scale", vexScale), 0.0625D, 16.0D); } public boolean villagerRidable = false; public boolean villagerRidableInWater = true; public boolean villagerControllable = true; + public double villagerMaxHealth = 20.0D; + public double villagerScale = 1.0D; private void villagerSettings() { villagerRidable = getBoolean("mobs.villager.ridable", villagerRidable); villagerRidableInWater = getBoolean("mobs.villager.ridable-in-water", villagerRidableInWater); villagerControllable = getBoolean("mobs.villager.controllable", villagerControllable); + 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); + villagerScale = Mth.clamp(getDouble("mobs.villager.attributes.scale", villagerScale), 0.0625D, 16.0D); } public boolean vindicatorRidable = false; public boolean vindicatorRidableInWater = true; public boolean vindicatorControllable = true; + public double vindicatorMaxHealth = 24.0D; + public double vindicatorScale = 1.0D; private void vindicatorSettings() { vindicatorRidable = getBoolean("mobs.vindicator.ridable", vindicatorRidable); vindicatorRidableInWater = getBoolean("mobs.vindicator.ridable-in-water", vindicatorRidableInWater); vindicatorControllable = getBoolean("mobs.vindicator.controllable", vindicatorControllable); + 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); + vindicatorScale = Mth.clamp(getDouble("mobs.vindicator.attributes.scale", vindicatorScale), 0.0625D, 16.0D); } public boolean wanderingTraderRidable = false; public boolean wanderingTraderRidableInWater = true; public boolean wanderingTraderControllable = true; + public double wanderingTraderMaxHealth = 20.0D; + public double wanderingTraderScale = 1.0D; private void wanderingTraderSettings() { wanderingTraderRidable = getBoolean("mobs.wandering_trader.ridable", wanderingTraderRidable); wanderingTraderRidableInWater = getBoolean("mobs.wandering_trader.ridable-in-water", wanderingTraderRidableInWater); wanderingTraderControllable = getBoolean("mobs.wandering_trader.controllable", wanderingTraderControllable); + if (PurpurConfig.version < 10) { + double oldValue = getDouble("mobs.wandering_trader.attributes.max-health", wanderingTraderMaxHealth); + set("mobs.wandering_trader.attributes.max-health", null); + set("mobs.wandering_trader.attributes.max_health", oldValue); + } + wanderingTraderMaxHealth = getDouble("mobs.wandering_trader.attributes.max_health", wanderingTraderMaxHealth); + wanderingTraderScale = Mth.clamp(getDouble("mobs.wandering_trader.attributes.scale", wanderingTraderScale), 0.0625D, 16.0D); } public boolean wardenRidable = false; @@ -737,83 +1448,183 @@ public class PurpurWorldConfig { public boolean witchRidable = false; public boolean witchRidableInWater = true; public boolean witchControllable = true; + public double witchMaxHealth = 26.0D; + public double witchScale = 1.0D; private void witchSettings() { witchRidable = getBoolean("mobs.witch.ridable", witchRidable); witchRidableInWater = getBoolean("mobs.witch.ridable-in-water", witchRidableInWater); witchControllable = getBoolean("mobs.witch.controllable", witchControllable); + 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); + witchScale = Mth.clamp(getDouble("mobs.witch.attributes.scale", witchScale), 0.0625D, 16.0D); } public boolean witherRidable = false; public boolean witherRidableInWater = true; public boolean witherControllable = true; public double witherMaxY = 320D; + public double witherMaxHealth = 300.0D; + public double witherScale = 1.0D; private void witherSettings() { witherRidable = getBoolean("mobs.wither.ridable", witherRidable); witherRidableInWater = getBoolean("mobs.wither.ridable-in-water", witherRidableInWater); witherControllable = getBoolean("mobs.wither.controllable", witherControllable); witherMaxY = getDouble("mobs.wither.ridable-max-y", witherMaxY); + 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); + } 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); + witherScale = Mth.clamp(getDouble("mobs.wither.attributes.scale", witherScale), 0.0625D, 16.0D); } public boolean witherSkeletonRidable = false; public boolean witherSkeletonRidableInWater = true; public boolean witherSkeletonControllable = true; + public double witherSkeletonMaxHealth = 20.0D; + public double witherSkeletonScale = 1.0D; private void witherSkeletonSettings() { witherSkeletonRidable = getBoolean("mobs.wither_skeleton.ridable", witherSkeletonRidable); witherSkeletonRidableInWater = getBoolean("mobs.wither_skeleton.ridable-in-water", witherSkeletonRidableInWater); witherSkeletonControllable = getBoolean("mobs.wither_skeleton.controllable", witherSkeletonControllable); + 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); + witherSkeletonScale = Mth.clamp(getDouble("mobs.wither_skeleton.attributes.scale", witherSkeletonScale), 0.0625D, 16.0D); } public boolean wolfRidable = false; public boolean wolfRidableInWater = true; public boolean wolfControllable = true; + public double wolfMaxHealth = 8.0D; + public double wolfScale = 1.0D; private void wolfSettings() { wolfRidable = getBoolean("mobs.wolf.ridable", wolfRidable); wolfRidableInWater = getBoolean("mobs.wolf.ridable-in-water", wolfRidableInWater); wolfControllable = getBoolean("mobs.wolf.controllable", wolfControllable); + 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); + wolfScale = Mth.clamp(getDouble("mobs.wolf.attributes.scale", wolfScale), 0.0625D, 16.0D); } public boolean zoglinRidable = false; public boolean zoglinRidableInWater = true; public boolean zoglinControllable = true; + public double zoglinMaxHealth = 40.0D; + public double zoglinScale = 1.0D; private void zoglinSettings() { zoglinRidable = getBoolean("mobs.zoglin.ridable", zoglinRidable); zoglinRidableInWater = getBoolean("mobs.zoglin.ridable-in-water", zoglinRidableInWater); zoglinControllable = getBoolean("mobs.zoglin.controllable", zoglinControllable); + 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); + zoglinScale = Mth.clamp(getDouble("mobs.zoglin.attributes.scale", zoglinScale), 0.0625D, 16.0D); } public boolean zombieRidable = false; public boolean zombieRidableInWater = true; public boolean zombieControllable = true; + public double zombieMaxHealth = 20.0D; + public double zombieScale = 1.0D; + public double zombieSpawnReinforcements = 0.1D; private void zombieSettings() { zombieRidable = getBoolean("mobs.zombie.ridable", zombieRidable); zombieRidableInWater = getBoolean("mobs.zombie.ridable-in-water", zombieRidableInWater); zombieControllable = getBoolean("mobs.zombie.controllable", zombieControllable); + 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); + zombieScale = Mth.clamp(getDouble("mobs.zombie.attributes.scale", zombieScale), 0.0625D, 16.0D); + zombieSpawnReinforcements = getDouble("mobs.zombie.attributes.spawn_reinforcements", zombieSpawnReinforcements); } public boolean zombieHorseRidable = false; public boolean zombieHorseRidableInWater = false; public boolean zombieHorseCanSwim = false; + 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() { zombieHorseRidable = getBoolean("mobs.zombie_horse.ridable", zombieHorseRidable); zombieHorseRidableInWater = getBoolean("mobs.zombie_horse.ridable-in-water", zombieHorseRidableInWater); zombieHorseCanSwim = getBoolean("mobs.zombie_horse.can-swim", zombieHorseCanSwim); + 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 zombieVillagerRidable = false; public boolean zombieVillagerRidableInWater = true; public boolean zombieVillagerControllable = true; + public double zombieVillagerMaxHealth = 20.0D; + public double zombieVillagerScale = 1.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); zombieVillagerControllable = getBoolean("mobs.zombie_villager.controllable", zombieVillagerControllable); + 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); + zombieVillagerScale = Mth.clamp(getDouble("mobs.zombie_villager.attributes.scale", zombieVillagerScale), 0.0625D, 16.0D); + zombieVillagerSpawnReinforcements = getDouble("mobs.zombie_villager.attributes.spawn_reinforcements", zombieVillagerSpawnReinforcements); } public boolean zombifiedPiglinRidable = false; public boolean zombifiedPiglinRidableInWater = true; public boolean zombifiedPiglinControllable = true; + public double zombifiedPiglinMaxHealth = 20.0D; + public double zombifiedPiglinScale = 1.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); zombifiedPiglinControllable = getBoolean("mobs.zombified_piglin.controllable", zombifiedPiglinControllable); + 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); + zombifiedPiglinScale = Mth.clamp(getDouble("mobs.zombified_piglin.attributes.scale", zombifiedPiglinScale), 0.0625D, 16.0D); + zombifiedPiglinSpawnReinforcements = getDouble("mobs.zombified_piglin.attributes.spawn_reinforcements", zombifiedPiglinSpawnReinforcements); } }