diff --git a/patches/server/0104-Ridables.patch b/patches/server/0104-Ridables.patch index 993096b73..767090ace 100644 --- a/patches/server/0104-Ridables.patch +++ b/patches/server/0104-Ridables.patch @@ -146,6 +146,130 @@ index 2d49816311..d14e4b1eef 100644 + } + // Purpur end } +diff --git a/src/main/java/net/minecraft/server/EntityCat.java b/src/main/java/net/minecraft/server/EntityCat.java +index 20497c3962..3ac0d7afbf 100644 +--- a/src/main/java/net/minecraft/server/EntityCat.java ++++ b/src/main/java/net/minecraft/server/EntityCat.java +@@ -15,7 +15,7 @@ public class EntityCat extends EntityTameableAnimal { + private static final DataWatcherObject bA = DataWatcher.a(EntityCat.class, DataWatcherRegistry.i); + private static final DataWatcherObject bB = DataWatcher.a(EntityCat.class, DataWatcherRegistry.i); + private static final DataWatcherObject bC = DataWatcher.a(EntityCat.class, DataWatcherRegistry.b); +- public static final Map bx = (Map) SystemUtils.a(Maps.newHashMap(), (hashmap) -> { // CraftBukkit - decompile error ++ public static final Map bx = SystemUtils.a(Maps.newHashMap(), (hashmap) -> { // CraftBukkit - decompile error // Purpur - decompile error + hashmap.put(0, new MinecraftKey("textures/entity/cat/tabby.png")); + hashmap.put(1, new MinecraftKey("textures/entity/cat/black.png")); + hashmap.put(2, new MinecraftKey("textures/entity/cat/red.png")); +@@ -41,6 +41,25 @@ public class EntityCat extends EntityTameableAnimal { + super(entitytypes, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.catRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.catRidableInWater; ++ } ++ ++ public void onMount(EntityHuman entityhuman) { ++ super.onMount(entityhuman); ++ setSitting(false); ++ setSleepingWithOwner(false); ++ setHeadDown(false); ++ } ++ // Purpur end ++ + public MinecraftKey eV() { + return (MinecraftKey) EntityCat.bx.getOrDefault(this.getCatType(), EntityCat.bx.get(0)); + } +@@ -48,7 +67,8 @@ public class EntityCat extends EntityTameableAnimal { + @Override + protected void initPathfinder() { + this.bE = new EntityCat.PathfinderGoalTemptChance(this, 0.6D, EntityCat.by, true); +- this.goalSelector.a(1, new PathfinderGoalFloat(this)); ++ this.goalSelector.a(0, new PathfinderGoalFloat(this)); // Purpur ++ this.goalSelector.a(0, new net.pl3x.purpur.pathfinder.PathfinderGoalHasRider(this)); // Purpur + this.goalSelector.a(1, new PathfinderGoalSit(this)); + this.goalSelector.a(2, new EntityCat.b(this)); + this.goalSelector.a(3, this.bE); +@@ -60,6 +80,7 @@ public class EntityCat extends EntityTameableAnimal { + this.goalSelector.a(10, new PathfinderGoalBreed(this, 0.8D)); + this.goalSelector.a(11, new PathfinderGoalRandomStrollLand(this, 0.8D, 1.0000001E-5F)); + this.goalSelector.a(12, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 10.0F)); ++ this.targetSelector.a(0, new net.pl3x.purpur.pathfinder.PathfinderGoalHasRider(this)); // Purpur + this.targetSelector.a(1, new PathfinderGoalRandomTargetNonTamed<>(this, EntityRabbit.class, false, (Predicate) null)); + this.targetSelector.a(1, new PathfinderGoalRandomTargetNonTamed<>(this, EntityTurtle.class, false, EntityTurtle.bv)); + } +@@ -76,6 +97,7 @@ public class EntityCat extends EntityTameableAnimal { + this.datawatcher.set(EntityCat.bz, i); + } + ++ public void setSleepingWithOwner(boolean flag) { x(flag); } // Purpur - OBFHELPER + public void x(boolean flag) { + this.datawatcher.set(EntityCat.bA, flag); + } +@@ -84,6 +106,7 @@ public class EntityCat extends EntityTameableAnimal { + return (Boolean) this.datawatcher.get(EntityCat.bA); + } + ++ public void setHeadDown(boolean flag) { y(flag); } // Purpur - OBFHELPER + public void y(boolean flag) { + this.datawatcher.set(EntityCat.bB, flag); + } +@@ -302,6 +325,7 @@ public class EntityCat extends EntityTameableAnimal { + + @Override + public EnumInteractionResult b(EntityHuman entityhuman, EnumHand enumhand) { ++ if (hasRider()) return EnumInteractionResult.PASS; // Purpur + ItemStack itemstack = entityhuman.b(enumhand); + Item item = itemstack.getItem(); + +@@ -399,6 +423,7 @@ public class EntityCat extends EntityTameableAnimal { + + public b(EntityCat entitycat) { + this.a = entitycat; ++ this.a(java.util.EnumSet.of(PathfinderGoal.Type.MOVE)); // Purpur - lay on owner + } + + @Override +diff --git a/src/main/java/net/minecraft/server/EntityChicken.java b/src/main/java/net/minecraft/server/EntityChicken.java +index fa97552bb4..3a1d0a2f23 100644 +--- a/src/main/java/net/minecraft/server/EntityChicken.java ++++ b/src/main/java/net/minecraft/server/EntityChicken.java +@@ -17,9 +17,22 @@ public class EntityChicken extends EntityAnimal { + this.a(PathType.WATER, 0.0F); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.chickenRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.chickenRidableInWater; ++ } ++ // Purpur end ++ + @Override + protected void initPathfinder() { + this.goalSelector.a(0, new PathfinderGoalFloat(this)); ++ this.goalSelector.a(0, new net.pl3x.purpur.pathfinder.PathfinderGoalHasRider(this)); // Purpur + //this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.4D)); // Purpur - moved down + this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D)); + this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.0D, false, EntityChicken.bC)); +@@ -30,6 +43,7 @@ public class EntityChicken extends EntityAnimal { + // Purpur start + if (world.purpurConfig.chickenRetaliate) { + this.goalSelector.a(1, new PathfinderGoalMeleeAttack(this, 1.0D, false)); ++ this.targetSelector.a(0, new net.pl3x.purpur.pathfinder.PathfinderGoalHasRider(this)); // Purpur + this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this)); + } else { + this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.4D)); diff --git a/src/main/java/net/minecraft/server/EntityComplexPart.java b/src/main/java/net/minecraft/server/EntityComplexPart.java index 920f4c7671..7fec83387a 100644 --- a/src/main/java/net/minecraft/server/EntityComplexPart.java @@ -163,7 +287,7 @@ index 920f4c7671..7fec83387a 100644 + // Purpur end } diff --git a/src/main/java/net/minecraft/server/EntityCow.java b/src/main/java/net/minecraft/server/EntityCow.java -index d6baddb9d3..404c548d26 100644 +index d6baddb9d3..a4b1255add 100644 --- a/src/main/java/net/minecraft/server/EntityCow.java +++ b/src/main/java/net/minecraft/server/EntityCow.java @@ -11,9 +11,22 @@ public class EntityCow extends EntityAnimal { @@ -189,7 +313,15 @@ index d6baddb9d3..404c548d26 100644 this.goalSelector.a(1, new PathfinderGoalPanic(this, 2.0D)); this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D)); if (world.purpurConfig.cowFeedMushrooms > 0) this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.25D, RecipeItemStack.a(Items.WHEAT, Blocks.RED_MUSHROOM.getItem(), Blocks.BROWN_MUSHROOM.getItem()), false)); else // Purpur -@@ -62,7 +75,7 @@ public class EntityCow extends EntityAnimal { +@@ -55,6 +68,7 @@ public class EntityCow extends EntityAnimal { + + @Override + public EnumInteractionResult b(EntityHuman entityhuman, EnumHand enumhand) { ++ if (hasRider()) return EnumInteractionResult.PASS; // Purpur + ItemStack itemstack = entityhuman.b(enumhand); + + if (itemstack.getItem() == Items.BUCKET && !this.isBaby()) { +@@ -62,7 +76,7 @@ public class EntityCow extends EntityAnimal { org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) entityhuman.world, entityhuman, this.getChunkCoordinates(), this.getChunkCoordinates(), null, itemstack, Items.MILK_BUCKET, enumhand); // Paper - add enumHand if (event.isCancelled()) { @@ -198,7 +330,7 @@ index d6baddb9d3..404c548d26 100644 } // CraftBukkit end -@@ -73,7 +86,7 @@ public class EntityCow extends EntityAnimal { +@@ -73,7 +87,7 @@ public class EntityCow extends EntityAnimal { return EnumInteractionResult.a(this.world.isClientSide); // Purpur start - feed mushroom to change to mooshroom } else if (world.purpurConfig.cowFeedMushrooms > 0 && getEntityType() != EntityTypes.MOOSHROOM && isMushroom(itemstack)) { @@ -207,7 +339,7 @@ index d6baddb9d3..404c548d26 100644 // Purpur end } else { return super.b(entityhuman, enumhand); -@@ -96,7 +109,7 @@ public class EntityCow extends EntityAnimal { +@@ -96,7 +110,7 @@ public class EntityCow extends EntityAnimal { } } @@ -216,7 +348,7 @@ index d6baddb9d3..404c548d26 100644 world.broadcastEntityEffect(this, (byte) 18); // hearts playSound(SoundEffects.ENTITY_COW_MILK, 1.0F, 1.0F); if (incrementFeedCount(itemstack) < world.purpurConfig.cowFeedMushrooms) { -@@ -107,7 +120,7 @@ public class EntityCow extends EntityAnimal { +@@ -107,7 +121,7 @@ public class EntityCow extends EntityAnimal { } EntityMushroomCow mooshroom = EntityTypes.MOOSHROOM.create(world); if (mooshroom == null) { @@ -225,7 +357,7 @@ index d6baddb9d3..404c548d26 100644 } if (itemstack.getItem() == Blocks.BROWN_MUSHROOM.getItem()) { mooshroom.setVariant(EntityMushroomCow.Type.BROWN); -@@ -126,10 +139,10 @@ public class EntityCow extends EntityAnimal { +@@ -126,10 +140,10 @@ public class EntityCow extends EntityAnimal { mooshroom.setCustomName(this.getCustomName()); } if (CraftEventFactory.callEntityTransformEvent(this, mooshroom, org.bukkit.event.entity.EntityTransformEvent.TransformReason.INFECTION).isCancelled()) { @@ -238,11 +370,153 @@ index d6baddb9d3..404c548d26 100644 } this.world.addEntity(mooshroom); this.die(); +diff --git a/src/main/java/net/minecraft/server/EntityFox.java b/src/main/java/net/minecraft/server/EntityFox.java +index 90b01adbec..26de8c3ad6 100644 +--- a/src/main/java/net/minecraft/server/EntityFox.java ++++ b/src/main/java/net/minecraft/server/EntityFox.java +@@ -55,6 +55,39 @@ public class EntityFox extends EntityAnimal { + this.setCanPickupLoot(true); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return world.purpurConfig.foxRidable; ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.foxRidableInWater; ++ } ++ ++ @Override ++ public float getJumpHeight() { ++ return !hasRider() ? super.getJumpHeight() : 0.5F; ++ } ++ ++ @Override ++ public void onMount(EntityHuman entityhuman) { ++ super.onMount(entityhuman); ++ setCanPickupLoot(false); ++ stopActions(); ++ setChasing(false); ++ spit(getEquipment(EnumItemSlot.MAINHAND)); ++ setSlot(EnumItemSlot.MAINHAND, ItemStack.NULL_ITEM); ++ } ++ ++ @Override ++ public void onDismount(EntityHuman entityhuman) { ++ super.onDismount(entityhuman); ++ setCanPickupLoot(true); ++ } ++ // Purpur end ++ + @Override + protected void initDatawatcher() { + super.initDatawatcher(); +@@ -74,6 +107,7 @@ public class EntityFox extends EntityAnimal { + return entityliving instanceof EntityFishSchool; + }); + this.goalSelector.a(0, new EntityFox.g()); ++ this.goalSelector.a(0, new net.pl3x.purpur.pathfinder.PathfinderGoalHasRider(this)); // Purpur + this.goalSelector.a(1, new EntityFox.b()); + this.goalSelector.a(2, new EntityFox.n(2.2D)); + this.goalSelector.a(3, new EntityFox.e(1.0D)); +@@ -99,6 +133,7 @@ public class EntityFox extends EntityAnimal { + this.goalSelector.a(11, new EntityFox.p()); + this.goalSelector.a(12, new EntityFox.j(this, EntityHuman.class, 24.0F)); + this.goalSelector.a(13, new EntityFox.r()); ++ this.targetSelector.a(0, new net.pl3x.purpur.pathfinder.PathfinderGoalHasRider(this)); // Purpur + this.targetSelector.a(3, new EntityFox.a(EntityLiving.class, false, false, (entityliving) -> { + return EntityFox.bA.test(entityliving) && !this.c(entityliving.getUniqueID()); + })); +@@ -386,6 +421,7 @@ public class EntityFox extends EntityAnimal { + return itemstack1.isEmpty() || this.bK > 0 && item.isFood() && !itemstack1.getItem().isFood(); + } + ++ public void spit(ItemStack itemstack) { m(itemstack); } // Purpur - OBFHELPER + private void m(ItemStack itemstack) { + if (!itemstack.isEmpty() && !this.world.isClientSide) { + EntityItem entityitem = new EntityItem(this.world, this.locX() + this.getLookDirection().x, this.locY() + 1.0D, this.locZ() + this.getLookDirection().z, itemstack); +@@ -480,6 +516,7 @@ public class EntityFox extends EntityAnimal { + return this.t(16); + } + ++ public void setChasing(boolean flag) { u(flag); } // Purpur - OBFHELPER + public void u(boolean flag) { + this.d(16, flag); + } +@@ -522,6 +559,7 @@ public class EntityFox extends EntityAnimal { + this.setSleeping(false); + } + ++ public void stopActions() { fe(); } // Purpur - OBFHELPER + private void fe() { + this.w(false); + this.setCrouching(false); +@@ -687,16 +725,16 @@ public class EntityFox extends EntityAnimal { + } + } + +- public class k extends ControllerLook { ++ public class k extends net.pl3x.purpur.controller.ControllerLookWASD { // Purpur + + public k() { + super(EntityFox.this); + } + + @Override +- public void a() { ++ public void tick() { // Purpur + if (!EntityFox.this.isSleeping()) { +- super.a(); ++ super.tick(); // Purpur + } + + } +@@ -1365,16 +1403,16 @@ public class EntityFox extends EntityAnimal { + } + } + +- class m extends ControllerMove { ++ class m extends net.pl3x.purpur.controller.ControllerMoveWASD { // Purpur + + public m() { + super(EntityFox.this); + } + + @Override +- public void a() { ++ public void tick() { // Purpur + if (EntityFox.this.ff()) { +- super.a(); ++ super.tick(); // Purpur + } + + } +diff --git a/src/main/java/net/minecraft/server/EntityHorse.java b/src/main/java/net/minecraft/server/EntityHorse.java +index adf414b479..a6c2119be9 100644 +--- a/src/main/java/net/minecraft/server/EntityHorse.java ++++ b/src/main/java/net/minecraft/server/EntityHorse.java +@@ -12,6 +12,13 @@ public class EntityHorse extends EntityHorseAbstract { + super(entitytypes, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.horseRidableInWater; ++ } ++ // Purpur end ++ + @Override + protected void eL() { + this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue((double) this.fq()); diff --git a/src/main/java/net/minecraft/server/EntityHorseAbstract.java b/src/main/java/net/minecraft/server/EntityHorseAbstract.java -index c9ab80ccd1..501de63fb2 100644 +index c9ab80ccd1..94fd1b14f3 100644 --- a/src/main/java/net/minecraft/server/EntityHorseAbstract.java +++ b/src/main/java/net/minecraft/server/EntityHorseAbstract.java -@@ -39,6 +39,8 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven +@@ -39,12 +39,27 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven protected EntityHorseAbstract(EntityTypes entitytypes, World world) { super(entitytypes, world); @@ -251,6 +525,132 @@ index c9ab80ccd1..501de63fb2 100644 this.G = 1.0F; this.loadChest(); } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return false; // vanilla handles ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return false; ++ } ++ // Purpur end ++ + @Override + protected void initPathfinder() { ++ this.goalSelector.a(0, new net.pl3x.purpur.pathfinder.PathfinderGoalHorseHasRider(this)); // Purpur + this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.2D)); + this.goalSelector.a(1, new PathfinderGoalTame(this, 1.2D)); + this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D, EntityHorseAbstract.class)); +diff --git a/src/main/java/net/minecraft/server/EntityHorseDonkey.java b/src/main/java/net/minecraft/server/EntityHorseDonkey.java +index d349e8a34b..01672ed635 100644 +--- a/src/main/java/net/minecraft/server/EntityHorseDonkey.java ++++ b/src/main/java/net/minecraft/server/EntityHorseDonkey.java +@@ -8,6 +8,13 @@ public class EntityHorseDonkey extends EntityHorseChestedAbstract { + super(entitytypes, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.donkeyRidableInWater; ++ } ++ // Purpur end ++ + @Override + protected SoundEffect getSoundAmbient() { + super.getSoundAmbient(); +diff --git a/src/main/java/net/minecraft/server/EntityHorseMule.java b/src/main/java/net/minecraft/server/EntityHorseMule.java +index 5105418c42..4d45976d7c 100644 +--- a/src/main/java/net/minecraft/server/EntityHorseMule.java ++++ b/src/main/java/net/minecraft/server/EntityHorseMule.java +@@ -8,6 +8,13 @@ public class EntityHorseMule extends EntityHorseChestedAbstract { + super(entitytypes, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.muleRidableInWater; ++ } ++ // Purpur end ++ + @Override + protected SoundEffect getSoundAmbient() { + super.getSoundAmbient(); +diff --git a/src/main/java/net/minecraft/server/EntityHorseSkeleton.java b/src/main/java/net/minecraft/server/EntityHorseSkeleton.java +index 43e605f682..ca8f73c752 100644 +--- a/src/main/java/net/minecraft/server/EntityHorseSkeleton.java ++++ b/src/main/java/net/minecraft/server/EntityHorseSkeleton.java +@@ -12,6 +12,18 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { + super(entitytypes, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.skeletonHorseRidableInWater; ++ } ++ ++ @Override ++ public boolean isTamed() { ++ return true; ++ } ++ // Purpur end ++ + public static AttributeProvider.Builder eM() { + return fj().a(GenericAttributes.MAX_HEALTH, 15.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.20000000298023224D); + } +@@ -22,7 +34,7 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { + } + + @Override +- protected void eW() {} ++ protected void eW() { if (world.purpurConfig.skeletonHorseCanSwim) goalSelector.a(0, new PathfinderGoalFloat(this)); } // Purpur + + @Override + protected SoundEffect getSoundAmbient() { +@@ -117,7 +129,7 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { + + @Override + public boolean bp() { +- return true; ++ return super.bp(); // Purpur + } + + @Override +diff --git a/src/main/java/net/minecraft/server/EntityHorseZombie.java b/src/main/java/net/minecraft/server/EntityHorseZombie.java +index 0cbdccf4c5..19a21ff98d 100644 +--- a/src/main/java/net/minecraft/server/EntityHorseZombie.java ++++ b/src/main/java/net/minecraft/server/EntityHorseZombie.java +@@ -8,6 +8,18 @@ public class EntityHorseZombie extends EntityHorseAbstract { + super(entitytypes, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidableInWater() { ++ return world.purpurConfig.zombieHorseRidableInWater; ++ } ++ ++ @Override ++ public boolean isTamed() { ++ return true; ++ } ++ // Purpur end ++ + public static AttributeProvider.Builder eM() { + return fj().a(GenericAttributes.MAX_HEALTH, 15.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.20000000298023224D); + } +@@ -79,5 +91,5 @@ public class EntityHorseZombie extends EntityHorseAbstract { + } + + @Override +- protected void eW() {} ++ protected void eW() { if (world.purpurConfig.zombieHorseCanSwim) goalSelector.a(0, new PathfinderGoalFloat(this)); } // Purpur + } diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java index 8def5fbfb4..a64de2248b 100644 --- a/src/main/java/net/minecraft/server/EntityInsentient.java @@ -437,22 +837,120 @@ index 494d36085e..9cde3693c5 100644 public static String serverModName = "Purpur"; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 2f5bc77e03..ebc9a4f344 100644 +index 2f5bc77e03..9d6894a24c 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -281,8 +281,12 @@ public class PurpurWorldConfig { +@@ -266,22 +266,34 @@ public class PurpurWorldConfig { + turtleEggsBreakFromMinecarts = getBoolean("blocks.turtle_egg.break-from-minecarts", turtleEggsBreakFromMinecarts); + } + ++ public boolean catRidable = false; ++ public boolean catRidableInWater = false; + public int catSpawnDelay = 1200; + public int catSpawnSwampHutScanRange = 16; + public int catSpawnVillageScanRange = 48; + private void catSettings() { ++ catRidable = getBoolean("mobs.cat.ridable", catRidable); ++ catRidableInWater = getBoolean("mobs.cat.ridable-in-water", catRidableInWater); + catSpawnDelay = getInt("mobs.cat.spawn-delay", catSpawnDelay); + catSpawnSwampHutScanRange = getInt("mobs.cat.scan-range-for-other-cats.swamp-hut", catSpawnSwampHutScanRange); + catSpawnVillageScanRange = getInt("mobs.cat.scan-range-for-other-cats.village", catSpawnVillageScanRange); + } + ++ public boolean chickenRidable = false; ++ public boolean chickenRidableInWater = false; + public boolean chickenRetaliate = false; + private void chickenSettings() { ++ chickenRidable = getBoolean("mobs.chicken.ridable", chickenRidable); ++ chickenRidableInWater = getBoolean("mobs.chicken.ridable-in-water", chickenRidableInWater); + chickenRetaliate = getBoolean("mobs.chicken.retaliate", chickenRetaliate); } - public int cowFeedMushrooms = 0; + public boolean cowRidable = false; + public boolean cowRidableInWater = false; + public int cowFeedMushrooms = 0; private void cowSettings() { - cowFeedMushrooms = getInt("mobs.cow.feed-mushrooms-for-mooshroom", cowFeedMushrooms); + cowRidable = getBoolean("mobs.cow.ridable", cowRidable); + cowRidableInWater = getBoolean("mobs.cow.ridable-in-water", cowRidableInWater); + cowFeedMushrooms = getInt("mobs.cow.feed-mushrooms-for-mooshroom", cowFeedMushrooms); + } + +@@ -292,6 +304,11 @@ public class PurpurWorldConfig { + creeperChargedChance = getDouble("mobs.creeper.naturally-charged-chance", creeperChargedChance); + } + ++ public boolean donkeyRidableInWater = false; ++ private void donkeySettings() { ++ donkeyRidableInWater = getBoolean("mobs.donkey.ridable-in-water", donkeyRidableInWater); ++ } ++ + public boolean drownedJockeyOnlyBaby = true; + public double drownedJockeyChance = 0.05D; + public boolean drownedJockeyTryExistingChickens = true; +@@ -315,8 +332,12 @@ public class PurpurWorldConfig { + endermanAllowGriefing = getBoolean("mobs.enderman.allow-griefing", endermanAllowGriefing); + } + ++ public boolean foxRidable = false; ++ public boolean foxRidableInWater = false; + public boolean foxTypeChangesWithTulips = false; + private void foxSettings() { ++ foxRidable = getBoolean("mobs.fox.ridable", foxRidable); ++ foxRidableInWater = getBoolean("mobs.fox.ridable-in-water", foxRidableInWater); + foxTypeChangesWithTulips = getBoolean("mobs.fox.tulips-change-type", foxTypeChangesWithTulips); + } + +@@ -337,6 +358,11 @@ public class PurpurWorldConfig { + giantHaveHostileAI = getBoolean("mobs.giant.have-hostile-ai", giantHaveHostileAI); + } + ++ public boolean horseRidableInWater = false; ++ private void horseSettings() { ++ horseRidableInWater = getBoolean("mobs.horse.ridable-in-water", horseRidableInWater); ++ } ++ + public boolean huskJockeyOnlyBaby = true; + public double huskJockeyChance = 0.05D; + public boolean huskJockeyTryExistingChickens = true; +@@ -360,6 +386,11 @@ public class PurpurWorldConfig { + ironGolemCanSwim = getBoolean("mobs.iron_golem.can-swim", ironGolemCanSwim); + } + ++ public boolean muleRidableInWater = false; ++ private void muleSettings() { ++ muleRidableInWater = getBoolean("mobs.mule.ridable-in-water", muleRidableInWater); ++ } ++ + public double phantomAttackedByCrystalRadius = 0.0D; + public float phantomAttackedByCrystalDamage = 1.0F; + public double phantomOrbitCrystalRadius = 0.0D; +@@ -413,6 +444,13 @@ public class PurpurWorldConfig { + rabbitNaturalKiller = getDouble("mobs.rabbit.spawn-killer-rabbit-chance", rabbitNaturalKiller); + } + ++ public boolean skeletonHorseCanSwim = false; ++ public boolean skeletonHorseRidableInWater = true; ++ private void skeletonHorseSettings() { ++ skeletonHorseCanSwim = getBoolean("mobs.skeleton_horse.can-swim", skeletonHorseCanSwim); ++ skeletonHorseRidableInWater = getBoolean("mobs.skeleton_horse.ridable-in-water", skeletonHorseRidableInWater); ++ } ++ + public boolean snowGolemDropsPumpkin = false; + public boolean snowGolemPutPumpkinBack = false; + private void snowGolemSettings() { +@@ -460,8 +498,12 @@ public class PurpurWorldConfig { + zombieJockeyTryExistingChickens = getBoolean("mobs.zombie.jockey.try-existing-chickens", zombieJockeyTryExistingChickens); + } + ++ public boolean zombieHorseCanSwim = false; ++ public boolean zombieHorseRidableInWater = false; + public double zombieHorseSpawnChance = 0.0D; + private void zombieHorseSettings() { ++ zombieHorseCanSwim = getBoolean("mobs.zombie_horse.can-swim", zombieHorseCanSwim); ++ zombieHorseRidableInWater = getBoolean("mobs.zombie_horse.ridable-in-water", zombieHorseRidableInWater); + zombieHorseSpawnChance = getDouble("mobs.zombie_horse.spawn-chance", zombieHorseSpawnChance); } - public boolean creeperAllowGriefing = true; diff --git a/src/main/java/net/pl3x/purpur/controller/ControllerLookWASD.java b/src/main/java/net/pl3x/purpur/controller/ControllerLookWASD.java new file mode 100644 index 0000000000..828e1b8730