diff --git a/patches/server-unmapped/0111-Persistent-TileEntity-Lore-and-DisplayName.patch b/patches/server-unmapped/0111-Persistent-TileEntity-Lore-and-DisplayName.patch deleted file mode 100644 index 25b17f5f0..000000000 --- a/patches/server-unmapped/0111-Persistent-TileEntity-Lore-and-DisplayName.patch +++ /dev/null @@ -1,235 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> -Date: Wed, 30 Sep 2020 14:32:46 -0700 -Subject: [PATCH] Persistent TileEntity Lore and DisplayName - -Makes it so that when a TileEntity is placed in the world and then broken, -the dropped ItemStack retains any original custom display name/lore. - -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityPainting.java b/src/main/java/net/minecraft/world/entity/decoration/EntityPainting.java -index 9c01ec42342cf0420bf5215604c24fbc89c1361b..3de0f21648ca60bdfcbc078bca896d51bf84e207 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityPainting.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityPainting.java -@@ -15,6 +15,7 @@ import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.player.EntityHuman; -+import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.Items; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.IMaterial; -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -index 01839c7319e175477ded7001e00e5937734ff516..e5cda8c040c93639211dacbf5b0c7cd6a9df9e6d 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -@@ -34,6 +34,7 @@ import net.minecraft.world.entity.animal.EntityAnimal; - import net.minecraft.world.entity.animal.EntityWaterAnimal; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.item.Item; -+import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.Items; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.IMaterial; -diff --git a/src/main/java/net/minecraft/world/item/ItemBlock.java b/src/main/java/net/minecraft/world/item/ItemBlock.java -index 59d52c252b2e59923b8e513dd4d2e1ec9ce34dc7..4be1c8ee85f411a8b01be50b8cc3dc3835f80a2e 100644 ---- a/src/main/java/net/minecraft/world/item/ItemBlock.java -+++ b/src/main/java/net/minecraft/world/item/ItemBlock.java -@@ -119,7 +119,24 @@ public class ItemBlock extends Item { - } - - protected boolean a(BlockPosition blockposition, World world, @Nullable EntityHuman entityhuman, ItemStack itemstack, IBlockData iblockdata) { -- return a(world, entityhuman, blockposition, itemstack); -+ // Purpur start -+ boolean handled = a(world, entityhuman, blockposition, itemstack); -+ if (world.purpurConfig.persistentTileEntityDisplayNames && itemstack.hasTag()) { -+ NBTTagCompound display = itemstack.getSubTag("display"); -+ if (display != null) { -+ TileEntity tile = world.getTileEntity(blockposition); -+ if (tile != null) { -+ if (display.hasKeyOfType("Name", 8)) { -+ tile.setPersistentDisplayName(display.getString("Name")); -+ } -+ if (display.hasKeyOfType("Lore", 9)) { -+ tile.setPersistentLore(display.getList("Lore", 8)); -+ } -+ } -+ } -+ } -+ return handled; -+ // Purpur end - } - - @Nullable -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index 4e0b88e26ad8017d93841c4149a1687c1db4ff0b..f65201f8cbf6d402b4366d63bfa03aacf329860f 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -15,10 +15,15 @@ import net.minecraft.core.EnumDirection; - import net.minecraft.core.IRegistry; - import net.minecraft.core.NonNullList; - import net.minecraft.core.RegistryBlockID; -+import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.nbt.NBTTagList; -+import net.minecraft.nbt.NBTTagString; -+import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.server.level.WorldServer; - import net.minecraft.stats.StatisticList; - import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsBlock; -+import net.minecraft.world.INamableTileEntity; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityExperienceOrb; - import net.minecraft.world.entity.EntityLiving; -@@ -247,7 +252,7 @@ public class Block extends BlockBase implements IMaterial { - public static void a(IBlockData iblockdata, GeneratorAccess generatoraccess, BlockPosition blockposition, @Nullable TileEntity tileentity) { - if (generatoraccess instanceof WorldServer) { - a(iblockdata, (WorldServer) generatoraccess, blockposition, tileentity).forEach((itemstack) -> { -- a((World) ((WorldServer) generatoraccess), blockposition, itemstack); -+ dropItem((WorldServer) generatoraccess, blockposition, applyDisplayNameAndLoreFromTile(itemstack, tileentity)); // Purpur - }); - iblockdata.dropNaturally((WorldServer) generatoraccess, blockposition, ItemStack.b); - } -@@ -256,14 +261,56 @@ public class Block extends BlockBase implements IMaterial { - - public static void dropItems(IBlockData iblockdata, World world, BlockPosition blockposition, @Nullable TileEntity tileentity, Entity entity, ItemStack itemstack) { - if (world instanceof WorldServer) { -- getDrops(iblockdata, (WorldServer) world, blockposition, tileentity, entity, itemstack).forEach((itemstack1) -> { -- a(world, blockposition, itemstack1); -+ // Purpur start -+ getDrops(iblockdata, (WorldServer) world, blockposition, tileentity, entity, itemstack).forEach(stackToDrop -> { -+ dropItem(world, blockposition, applyDisplayNameAndLoreFromTile(stackToDrop, tileentity)); -+ // Purpur end - }); - iblockdata.dropNaturally((WorldServer) world, blockposition, itemstack); - } - - } - -+ // Purpur start -+ private static ItemStack applyDisplayNameAndLoreFromTile(ItemStack itemStack, TileEntity tile) { -+ if (itemStack.getItem() instanceof ItemBlock) { -+ if (tile != null && tile.getWorld() instanceof WorldServer && tile.getWorld().purpurConfig.persistentTileEntityDisplayNames) { -+ String name = tile.getPersistentDisplayName(); -+ NBTTagList lore = tile.getPersistentLore(); -+ if (tile instanceof INamableTileEntity) { -+ INamableTileEntity namedTile = (INamableTileEntity) tile; -+ if (namedTile.hasCustomName()) { -+ name = IChatBaseComponent.ChatSerializer.componentToJson(namedTile.getCustomName()); -+ } -+ } -+ -+ if (name != null || lore != null) { -+ NBTTagCompound display = itemStack.getSubTag("display"); -+ if (display == null) { -+ display = new NBTTagCompound(); -+ } -+ -+ if (name != null) { -+ display.set("Name", NBTTagString.create(name)); -+ } -+ if (lore != null) { -+ display.set("Lore", lore); -+ } -+ -+ NBTTagCompound tag = itemStack.getTag(); -+ if (tag == null) { -+ tag = new NBTTagCompound(); -+ } -+ tag.set("display", display); -+ -+ itemStack.setTag(tag); -+ } -+ } -+ } -+ return itemStack; -+ } -+ // Purpur end -+ - public static void a(World world, BlockPosition blockposition, ItemStack itemstack) { dropItem(world, blockposition, itemstack); } public static void dropItem(World world, BlockPosition blockposition, ItemStack itemstack) { // Paper - OBFHELPER - if (!world.isClientSide && !itemstack.isEmpty() && world.getGameRules().getBoolean(GameRules.DO_TILE_DROPS)) { - float f = 0.5F; -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 93d02ccb87c17404c55884f52ae40c7b7ddfb103..35c4d5414db66b977a354ac50d35a6aa0fcd4cf8 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -6,6 +6,8 @@ import net.minecraft.ResourceKeyInvalidException; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.IRegistry; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.nbt.NBTTagList; -+import net.minecraft.nbt.NBTTagString; - import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.world.level.World; -@@ -105,9 +107,25 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - this.persistentDataContainer.putAll((NBTTagCompound) persistentDataTag); - } - // CraftBukkit end -+ // Purpur start -+ if (nbttagcompound.hasKey("Purpur.persistentDisplayName")) { -+ this.persistentDisplayName = nbttagcompound.getString("Purpur.persistentDisplayName"); -+ } -+ if (nbttagcompound.hasKey("Purpur.persistentLore")) { -+ this.persistentLore = nbttagcompound.getList("Purpur.persistentLore", 8); -+ } -+ // Purpur end - } - - public NBTTagCompound save(NBTTagCompound nbttagcompound) { -+ // Purpur start -+ if (this.persistentDisplayName != null) { -+ nbttagcompound.set("Purpur.persistentDisplayName", NBTTagString.create(this.persistentDisplayName)); -+ } -+ if (this.persistentLore != null) { -+ nbttagcompound.set("Purpur.persistentLore", this.persistentLore); -+ } -+ // Purpur end - return this.b(nbttagcompound); - } - -@@ -274,4 +292,25 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - return null; - } - // CraftBukkit end -+ -+ // Purpur start -+ private String persistentDisplayName = null; -+ private NBTTagList persistentLore = null; -+ -+ public void setPersistentDisplayName(String json) { -+ this.persistentDisplayName = json; -+ } -+ -+ public void setPersistentLore(NBTTagList lore) { -+ this.persistentLore = lore; -+ } -+ -+ public String getPersistentDisplayName() { -+ return this.persistentDisplayName; -+ } -+ -+ public NBTTagList getPersistentLore() { -+ return this.persistentLore; -+ } -+ // Purpur end - } -diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 94681a3cb57950b0cd074927aa63bf84e3ef0cf7..a9f4732ece4764cabb1ae7b55fa9c273996f7d9d 100644 ---- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -244,6 +244,7 @@ public class PurpurWorldConfig { - public boolean entitiesPickUpLootBypassMobGriefing = false; - public boolean entitiesCanUsePortals = true; - public boolean milkCuresBadOmen = true; -+ public boolean persistentTileEntityDisplayNames = false; - public double tridentLoyaltyVoidReturnHeight = 0.0D; - public double voidDamageHeight = -64.0D; - public double voidDamageDealt = 4.0D; -@@ -255,6 +256,7 @@ public class PurpurWorldConfig { - entitiesPickUpLootBypassMobGriefing = getBoolean("gameplay-mechanics.entities-pick-up-loot-bypass-mob-griefing", entitiesPickUpLootBypassMobGriefing); - entitiesCanUsePortals = getBoolean("gameplay-mechanics.entities-can-use-portals", entitiesCanUsePortals); - milkCuresBadOmen = getBoolean("gameplay-mechanics.milk-cures-bad-omen", milkCuresBadOmen); -+ persistentTileEntityDisplayNames = getBoolean("gameplay-mechanics.persistent-tileentity-display-names-and-lore", persistentTileEntityDisplayNames); - tridentLoyaltyVoidReturnHeight = getDouble("gameplay-mechanics.trident-loyalty-void-return-height", tridentLoyaltyVoidReturnHeight); - voidDamageHeight = getDouble("gameplay-mechanics.void-damage-height", voidDamageHeight); - voidDamageDealt = getDouble("gameplay-mechanics.void-damage-dealt", voidDamageDealt); diff --git a/patches/server-unmapped/0113-Flying-squids-Oh-my.patch b/patches/server-unmapped/0113-Flying-squids-Oh-my.patch deleted file mode 100644 index b29144311..000000000 --- a/patches/server-unmapped/0113-Flying-squids-Oh-my.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 4 Oct 2020 12:00:42 -0500 -Subject: [PATCH] Flying squids! Oh my! - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -index 777c3bcf267d6cf31300588826d3af6b55cab350..7ec3e5d136cbb708b3bb29aa79bdd401d37d56dc 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -@@ -81,6 +81,11 @@ public class EntitySquid extends EntityWaterAnimal { - vector.setX(cos * x - sine * z); - vector.setZ(sine * x + cos * z); - } -+ -+ @Override -+ public boolean isInWater() { -+ return this.inWater || world.purpurConfig.squidsCanFly; -+ } - // Purpur end - - @Override -@@ -146,6 +151,7 @@ public class EntitySquid extends EntityWaterAnimal { - } - - if (this.aH()) { -+ if (world.purpurConfig.squidsCanFly) setNoGravity(!inWater); // Purpur - if (this.bp < 3.1415927F) { - float f = this.bp / 3.1415927F; - -@@ -353,7 +359,7 @@ public class EntitySquid extends EntityWaterAnimal { - - if (i > 100) { - this.b.a(0.0F, 0.0F, 0.0F); -- } else if (this.b.getRandom().nextInt(50) == 0 || !this.b.inWater || !this.b.eK()) { -+ } else if (this.b.getRandom().nextInt(50) == 0 || !this.b.isInWater() || !this.b.eK()) { // Purpur - float f = this.b.getRandom().nextFloat() * 6.2831855F; - float f1 = MathHelper.cos(f) * 0.2F; - float f2 = -0.1F + this.b.getRandom().nextFloat() * 0.2F; -diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index a9f4732ece4764cabb1ae7b55fa9c273996f7d9d..9a18d3612d38cdd3d85cc69fba6df355b6cc6829 100644 ---- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -937,10 +937,12 @@ public class PurpurWorldConfig { - public boolean squidRidable = false; - public boolean squidImmuneToEAR = true; - public double squidOffsetWaterCheck = 0.0D; -+ public boolean squidsCanFly = false; - private void squidSettings() { - squidRidable = getBoolean("mobs.squid.ridable", squidRidable); - squidImmuneToEAR = getBoolean("mobs.squid.immune-to-EAR", squidImmuneToEAR); - squidOffsetWaterCheck = getDouble("mobs.squid.water-offset-check", squidOffsetWaterCheck); -+ squidsCanFly = getBoolean("mobs.squid.can-fly", squidsCanFly); - } - - public boolean spiderRidable = false; diff --git a/patches/server-unmapped/0114-Infinity-bow-settings.patch b/patches/server-unmapped/0114-Infinity-bow-settings.patch deleted file mode 100644 index 51c938b3f..000000000 --- a/patches/server-unmapped/0114-Infinity-bow-settings.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 4 Oct 2020 19:08:53 -0500 -Subject: [PATCH] Infinity bow settings - - -diff --git a/src/main/java/net/minecraft/world/item/ItemBow.java b/src/main/java/net/minecraft/world/item/ItemBow.java -index 015f4d71f35a9d512814389b6e6cab74c0daf116..c7e20b25b4d09463fa54c66e62208e90515013e2 100644 ---- a/src/main/java/net/minecraft/world/item/ItemBow.java -+++ b/src/main/java/net/minecraft/world/item/ItemBow.java -@@ -35,7 +35,7 @@ public class ItemBow extends ItemProjectileWeapon implements ItemVanishable { - float f = a(j); - - if ((double) f >= 0.1D) { -- boolean flag1 = flag && itemstack1.getItem() == Items.ARROW; -+ boolean flag1 = flag && ((itemstack1.getItem() == Items.ARROW && world.purpurConfig.infinityWorksWithNormalArrows) || (itemstack1.getItem() == Items.TIPPED_ARROW && world.purpurConfig.infinityWorksWithTippedArrows) || (itemstack1.getItem() == Items.SPECTRAL_ARROW && world.purpurConfig.infinityWorksWithSpectralArrows)); // Purpur - - if (!world.isClientSide) { - ItemArrow itemarrow = (ItemArrow) ((ItemArrow) (itemstack1.getItem() instanceof ItemArrow ? itemstack1.getItem() : Items.ARROW)); -@@ -96,6 +96,7 @@ public class ItemBow extends ItemProjectileWeapon implements ItemVanishable { - entityhuman.inventory.f(itemstack1); - } - } -+ else if (!entityhuman.abilities.canInstantlyBuild) ((org.bukkit.entity.Player) entityhuman.getBukkitEntity()).updateInventory(); // Purpur - - entityhuman.b(StatisticList.ITEM_USED.b(this)); - } -diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 9a18d3612d38cdd3d85cc69fba6df355b6cc6829..e982733732e3dfd9d34cf5d9e87a9caa3af2d6e8 100644 ---- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -209,6 +209,15 @@ public class PurpurWorldConfig { - idleTimeoutUpdateTabList = getBoolean("gameplay-mechanics.player.idle-timeout.update-tab-list", idleTimeoutUpdateTabList); - } - -+ public boolean infinityWorksWithNormalArrows = true; -+ public boolean infinityWorksWithSpectralArrows = false; -+ public boolean infinityWorksWithTippedArrows = false; -+ private void infinityArrowsSettings() { -+ infinityWorksWithNormalArrows = getBoolean("gameplay-mechanics.infinity-bow.normal-arrows", infinityWorksWithNormalArrows); -+ infinityWorksWithSpectralArrows = getBoolean("gameplay-mechanics.infinity-bow.spectral-arrows", infinityWorksWithSpectralArrows); -+ infinityWorksWithTippedArrows = getBoolean("gameplay-mechanics.infinity-bow.tipped-arrows", infinityWorksWithTippedArrows); -+ } -+ - public int dragonFireballDespawnRate = -1; - public int eggDespawnRate = -1; - public int enderPearlDespawnRate = -1; diff --git a/patches/server-unmapped/0115-Stonecutter-damage.patch b/patches/server-unmapped/0115-Stonecutter-damage.patch deleted file mode 100644 index 0460bfaa6..000000000 --- a/patches/server-unmapped/0115-Stonecutter-damage.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Mon, 5 Oct 2020 12:15:14 -0500 -Subject: [PATCH] Stonecutter damage - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index aeaac4221e1c235d89e872da4c1aaaa68ab70a48..5fd01caa85eedc2e703b76fd230762cc89fceb21 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -802,7 +802,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - // CraftBukkit end - -- if (this.onGround && !this.bv()) { -+ if (this.onGround && (!this.bv() || (block == Blocks.STONECUTTER && world.purpurConfig.stonecutterDamage > 0.0F))) { // Purpur - block.stepOn(this.world, blockposition, this); - } - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockStonecutter.java b/src/main/java/net/minecraft/world/level/block/BlockStonecutter.java -index 54c9586cd7f8c9691a1c7ded9c9c96b0f316b0b6..68c6f090a10564a790f3bf175e2378d1f7103b8e 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockStonecutter.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockStonecutter.java -@@ -94,4 +94,16 @@ public class BlockStonecutter extends Block { - public boolean a(IBlockData iblockdata, IBlockAccess iblockaccess, BlockPosition blockposition, PathMode pathmode) { - return false; - } -+ -+ // Purpur start -+ @Override -+ public void stepOn(World world, BlockPosition pos, net.minecraft.world.entity.Entity entity) { -+ if (world.purpurConfig.stonecutterDamage > 0.0F && entity instanceof net.minecraft.world.entity.EntityLiving) { -+ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); -+ entity.damageEntity(net.minecraft.world.damagesource.DamageSource.CACTUS, world.purpurConfig.stonecutterDamage); -+ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = null; -+ } -+ super.stepOn(world, pos, entity); -+ } -+ // Purpur end - } -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java -index a0c7d3ab747ba1a3cf07e716f3591663a8a9e14b..1fb27ca3e769c34b98c9b2d973f4da16f17b022d 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java -@@ -490,7 +490,7 @@ public class PathfinderNormal extends PathfinderAbstract { - return PathType.DANGER_CACTUS; - } - -- if (iblockdata.a(Blocks.SWEET_BERRY_BUSH)) { -+ if (iblockdata.a(Blocks.SWEET_BERRY_BUSH) || iblockdata.a(Blocks.STONECUTTER)) { // Purpur - return PathType.DANGER_OTHER; - } - -diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index e982733732e3dfd9d34cf5d9e87a9caa3af2d6e8..11f699eb7d68013df708a874a214da6be3fe6773 100644 ---- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -441,6 +441,11 @@ public class PurpurWorldConfig { - spawnerDeactivateByRedstone = getBoolean("blocks.spawner.deactivate-by-redstone", spawnerDeactivateByRedstone); - } - -+ public float stonecutterDamage = 0.0F; -+ private void stonecutterSettings() { -+ stonecutterDamage = (float) getDouble("blocks.stonecutter.damage", stonecutterDamage); -+ } -+ - public boolean turtleEggsBreakFromExpOrbs = true; - public boolean turtleEggsBreakFromItems = true; - public boolean turtleEggsBreakFromMinecarts = true; diff --git a/patches/server-unmapped/0116-Configurable-daylight-cycle.patch b/patches/server-unmapped/0116-Configurable-daylight-cycle.patch index c62ecb53f..0d825f4fa 100644 --- a/patches/server-unmapped/0116-Configurable-daylight-cycle.patch +++ b/patches/server-unmapped/0116-Configurable-daylight-cycle.patch @@ -10,13 +10,13 @@ index 3086ee023685781d94e2fb99fc8dff5264f01165..74c1047305cac5673e274096709c757e +++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutUpdateTime.java @@ -7,7 +7,7 @@ import net.minecraft.network.protocol.Packet; public class PacketPlayOutUpdateTime implements Packet { - + private long a; private final void setWorldAge(final long age) { this.a = age; } private final long getWorldAge() { return this.a; } // Paper - OBFHELPER - private long b; + private long b; public void setPlayerTime(long time) { this.b = time; } // Purpur - + public PacketPlayOutUpdateTime() {} - + diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java index 5567d12b2b74b0fcf17e600d2c7b8ab88c2f3b13..9276500e4cc2a0d2d374b3f1393410e8295b3b4d 100644 --- a/src/main/java/net/minecraft/server/level/WorldServer.java @@ -34,16 +34,16 @@ index 5567d12b2b74b0fcf17e600d2c7b8ab88c2f3b13..9276500e4cc2a0d2d374b3f1393410e8 private final StructureManager structureManager; private final boolean Q; + private double fakeTime; // Purpur - - + + // CraftBukkit start @@ -401,6 +403,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { this.getServer().addWorld(this.getWorld()); // CraftBukkit - + this.asyncChunkTaskManager = new com.destroystokyo.paper.io.chunk.ChunkTaskManager(this); // Paper + this.fakeTime = this.worldDataServer.getDayTime(); // Purpur } - + // CraftBukkit start @@ -718,7 +721,21 @@ public class WorldServer extends World implements GeneratorAccessSeed { this.nextTickListBlock.nextTick(); // Paper @@ -67,9 +67,9 @@ index 5567d12b2b74b0fcf17e600d2c7b8ab88c2f3b13..9276500e4cc2a0d2d374b3f1393410e8 + // Purpur end this.setDayTime(this.worldData.getDayTime() + 1L); } - + @@ -727,6 +744,12 @@ public class WorldServer extends World implements GeneratorAccessSeed { - + public void setDayTime(long i) { this.worldDataServer.setDayTime(i); + // Purpur start @@ -79,7 +79,7 @@ index 5567d12b2b74b0fcf17e600d2c7b8ab88c2f3b13..9276500e4cc2a0d2d374b3f1393410e8 + this.worldDataServer.setDayTime((long) i); + // Purpur end } - + public void doMobSpawning(boolean flag, boolean flag1) { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java index 11f699eb7d68013df708a874a214da6be3fe6773..b11a71a1dda78098f1995f289a1fb45c9a02eeb6 100644 @@ -88,7 +88,7 @@ index 11f699eb7d68013df708a874a214da6be3fe6773..b11a71a1dda78098f1995f289a1fb45c @@ -150,6 +150,13 @@ public class PurpurWorldConfig { } } - + + public int daytimeTicks = 12000; + public int nighttimeTicks = 12000; + private void daytimeCycleSettings() { diff --git a/patches/server/0003-Ridables.patch b/patches/server/0003-Ridables.patch index 0b7864734..c8456b9c2 100644 --- a/patches/server/0003-Ridables.patch +++ b/patches/server/0003-Ridables.patch @@ -86,7 +86,7 @@ index 40d0dac02bb1922483d68f3cdd09a228f66d09f6..8e585ea6a070b2339cf396d70224a0d3 if ((entity instanceof AbstractFish && origItem != null && origItem.asItem() == Items.WATER_BUCKET) && (event.isCancelled() || ServerGamePacketListenerImpl.this.player.getInventory().getSelected() == null || ServerGamePacketListenerImpl.this.player.getInventory().getSelected().getItem() != origItem)) { ServerGamePacketListenerImpl.this.send(new ClientboundAddMobPacket((AbstractFish) entity)); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index cfab75b70b4cf4c95f3a7971c78f6dc42c0d23d0..5e9b67f0a5a8052b3f769b4a66b5c230401bd57f 100644 +index cfab75b70b4cf4c95f3a7971c78f6dc42c0d23d0..f6f162b145bffe2d97b48b009641b0437fee5b1d 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -230,7 +230,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n @@ -98,15 +98,6 @@ index cfab75b70b4cf4c95f3a7971c78f6dc42c0d23d0..5e9b67f0a5a8052b3f769b4a66b5c230 public boolean horizontalCollision; public boolean verticalCollision; public boolean hurtMarked; -@@ -291,7 +291,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n - private final Set tags; - private final double[] pistonDeltas; - private long pistonDeltasGameTime; -- private EntityDimensions dimensions; -+ protected EntityDimensions dimensions; // Purpur - private -> protected - private float eyeHeight; - public boolean isInPowderSnow; - public boolean wasInPowderSnow; @@ -2408,6 +2408,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n this.passengers = ImmutableList.copyOf(list); } @@ -183,12 +174,12 @@ index cfab75b70b4cf4c95f3a7971c78f6dc42c0d23d0..5e9b67f0a5a8052b3f769b4a66b5c230 + return false; + } + -+ public void onMount(Player rider) { ++ public void onMount(Player player) { + if (this instanceof Mob) { + ((Mob) this).setGoalTarget(null, null, false); + ((Mob) this).getNavigation().stopPathfinding(); + } -+ rider.setJumping(false); // fixes jump on mount ++ player.setJumping(false); // fixes jump on mount + } + + public void onDismount(Player player) { @@ -495,7 +486,7 @@ index ffc87d14cdc7edc22a7e2ac642d0e37037c52487..f2957d7f4c377a67ee486a9d0f7ae173 } diff --git a/src/main/java/net/minecraft/world/entity/ambient/Bat.java b/src/main/java/net/minecraft/world/entity/ambient/Bat.java -index 153194d937d210e2e4fd8864e4a3c000f85d7e2e..5708a1f88f3e62856a5ec15dc71d8a169353170d 100644 +index 153194d937d210e2e4fd8864e4a3c000f85d7e2e..87c5915564487d40ba9d160b2d1dc2cd2f2c5bb5 100644 --- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java +++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java @@ -20,6 +20,7 @@ import net.minecraft.world.entity.EntityType; @@ -531,8 +522,8 @@ index 153194d937d210e2e4fd8864e4a3c000f85d7e2e..5708a1f88f3e62856a5ec15dc71d8a16 + } + + @Override -+ public void onMount(Player rider) { -+ super.onMount(rider); ++ public void onMount(Player player) { ++ super.onMount(player); + if (isResting()) { + setResting(false); + level.levelEvent(null, 1025, new BlockPos(this).above(), 0); @@ -579,68 +570,6 @@ index 153194d937d210e2e4fd8864e4a3c000f85d7e2e..5708a1f88f3e62856a5ec15dc71d8a16 super.customServerAiStep(); BlockPos blockposition = this.blockPosition(); BlockPos blockposition1 = blockposition.above(); -diff --git a/src/main/java/net/minecraft/world/entity/animal/AbstractFish.java b/src/main/java/net/minecraft/world/entity/animal/AbstractFish.java -index 17b54ac18ef862f0f39da2b3b48c8bb86d970744..c0413ad13bf13e981f460e65b3ebf499a6eb32b6 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/AbstractFish.java -+++ b/src/main/java/net/minecraft/world/entity/animal/AbstractFish.java -@@ -108,12 +108,9 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable { - @Override - protected void registerGoals() { - super.registerGoals(); -+ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(0, new PanicGoal(this, 1.25D)); -- GoalSelector pathfindergoalselector = this.goalSelector; -- Predicate predicate = EntitySelector.NO_SPECTATORS; -- -- Objects.requireNonNull(predicate); -- pathfindergoalselector.addGoal(2, new AvoidEntityGoal<>(this, Player.class, 8.0F, 1.6D, 1.4D, predicate::test)); -+ this.goalSelector.addGoal(2, new AvoidEntityGoal<>(this, Player.class, 8.0F, 1.6D, 1.4D, EntitySelector.NO_SPECTATORS::test)); // Purpur - decompile fix - this.goalSelector.addGoal(4, new AbstractFish.FishSwimGoal(this)); - } - -@@ -125,7 +122,7 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable { - @Override - public void travel(Vec3 movementInput) { - if (this.isEffectiveAi() && this.isInWater()) { -- this.moveRelative(0.01F, movementInput); -+ this.moveRelative(getRider() != null ? getSpeed() : 0.01F, movementInput); // Purpur - this.move(MoverType.SELF, this.getDeltaMovement()); - this.setDeltaMovement(this.getDeltaMovement().scale(0.9D)); - if (this.getTarget() == null) { -@@ -183,7 +180,7 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable { - @Override - protected void playStepSound(BlockPos pos, BlockState state) {} - -- private static class FishMoveControl extends MoveControl { -+ private static class FishMoveControl extends net.pl3x.purpur.controller.WaterMoveControllerWASD { // Purpur - - private final AbstractFish fish; - -@@ -192,14 +189,22 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable { - this.fish = owner; - } - -+ // Purpur start -+ @Override -+ public void purpurTick(Player rider) { -+ super.purpurTick(rider); -+ fish.setDeltaMovement(fish.getDeltaMovement().add(0.0D, 0.005D, 0.0D)); -+ } -+ // Purpur end -+ - @Override -- public void tick() { -+ public void vanillaTick() { // Purpur - if (this.fish.isEyeInFluid((Tag) FluidTags.WATER)) { - this.fish.setDeltaMovement(this.fish.getDeltaMovement().add(0.0D, 0.005D, 0.0D)); - } - - if (this.operation == MoveControl.Operation.MOVE_TO && !this.fish.getNavigation().isDone()) { -- float f = (float) (this.speedModifier * this.fish.getAttributeValue(Attributes.MOVEMENT_SPEED)); -+ float f = (float) (this.getSpeedModifier() * this.fish.getAttributeValue(Attributes.MOVEMENT_SPEED)); // Purpur - - this.fish.setSpeed(Mth.lerp(0.125F, this.fish.getSpeed(), f)); - double d0 = this.wantedX - this.fish.getX(); diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java index 2639f64f1a50faddc0284fb26b73b563b3e9eba9..8632a4047776723088b9b9fa27c6e8093fb17801 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Bee.java @@ -758,111 +687,6 @@ index 2639f64f1a50faddc0284fb26b73b563b3e9eba9..8632a4047776723088b9b9fa27c6e809 } } -diff --git a/src/main/java/net/minecraft/world/entity/animal/Cat.java b/src/main/java/net/minecraft/world/entity/animal/Cat.java -index 15773d61deb357917e2478f0731f0b470669b8f0..14822b20971b63290a7022f8efe65693c41664d2 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Cat.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Cat.java -@@ -121,6 +121,26 @@ public class Cat extends TamableAnimal { - super(type, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.catRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.catRidableInWater; -+ } -+ -+ @Override -+ public void onMount(Player rider) { -+ super.onMount(rider); -+ setInSittingPose(false); -+ setLying(false); -+ setRelaxStateOne(false); -+ } -+ // Purpur end -+ - public ResourceLocation getResourceLocation() { - return (ResourceLocation) Cat.TEXTURE_BY_TYPE.getOrDefault(this.getCatType(), (ResourceLocation) Cat.TEXTURE_BY_TYPE.get(0)); - } -@@ -129,6 +149,7 @@ public class Cat extends TamableAnimal { - protected void registerGoals() { - this.temptGoal = new Cat.CatTemptGoal(this, 0.6D, Cat.TEMPT_INGREDIENT, true); - this.goalSelector.addGoal(1, new FloatGoal(this)); -+ this.goalSelector.addGoal(1, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(1, new SitWhenOrderedToGoal(this)); - this.goalSelector.addGoal(2, new Cat.CatRelaxOnOwnerGoal(this)); - this.goalSelector.addGoal(3, this.temptGoal); -@@ -140,6 +161,7 @@ public class Cat extends TamableAnimal { - this.goalSelector.addGoal(10, new BreedGoal(this, 0.8D)); - this.goalSelector.addGoal(11, new WaterAvoidingRandomStrollGoal(this, 0.8D, 1.0000001E-5F)); - this.goalSelector.addGoal(12, new LookAtPlayerGoal(this, Player.class, 10.0F)); -+ this.targetSelector.addGoal(1, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.targetSelector.addGoal(1, new NonTameRandomTargetGoal<>(this, Rabbit.class, false, (Predicate) null)); - this.targetSelector.addGoal(1, new NonTameRandomTargetGoal<>(this, Turtle.class, false, Turtle.BABY_ON_LAND_SELECTOR)); - } -@@ -394,6 +416,7 @@ public class Cat extends TamableAnimal { - - @Override - public InteractionResult mobInteract(Player player, InteractionHand hand) { -+ if (getRider() != null) return InteractionResult.PASS; // Purpur - ItemStack itemstack = player.getItemInHand(hand); - Item item = itemstack.getItem(); - -diff --git a/src/main/java/net/minecraft/world/entity/animal/Chicken.java b/src/main/java/net/minecraft/world/entity/animal/Chicken.java -index 8460bed561c09a647f6e0209f7c5448e5a42b281..771e55cceaf17167c00554b1be7043a4cb3efb7e 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Chicken.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Chicken.java -@@ -52,9 +52,22 @@ public class Chicken extends Animal { - this.setPathfindingMalus(BlockPathTypes.WATER, 0.0F); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.chickenRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.chickenRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void registerGoals() { - this.goalSelector.addGoal(0, new FloatGoal(this)); -+ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(1, new PanicGoal(this, 1.4D)); - this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); - this.goalSelector.addGoal(3, new TemptGoal(this, 1.0D, Chicken.FOOD_ITEMS, false)); -diff --git a/src/main/java/net/minecraft/world/entity/animal/Cod.java b/src/main/java/net/minecraft/world/entity/animal/Cod.java -index ec9c235f00cc1b992340dfe0a0b79803361caac5..5275e4ed3d552d1e164ef580caf6c247ec5fd8c2 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Cod.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Cod.java -@@ -13,6 +13,18 @@ public class Cod extends AbstractSchoolingFish { - super(type, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.codRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return true; -+ } -+ // Purpur end -+ - @Override - public ItemStack getBucketItemStack() { - return new ItemStack(Items.COD_BUCKET); diff --git a/src/main/java/net/minecraft/world/entity/animal/Cow.java b/src/main/java/net/minecraft/world/entity/animal/Cow.java index c9dcbc2dcb2736d0f448496c67121db29b7d4deb..1cb5342d63011605b567a4fe16d07de831f04216 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Cow.java @@ -907,745 +731,11 @@ index c9dcbc2dcb2736d0f448496c67121db29b7d4deb..1cb5342d63011605b567a4fe16d07de8 } // CraftBukkit end -diff --git a/src/main/java/net/minecraft/world/entity/animal/Dolphin.java b/src/main/java/net/minecraft/world/entity/animal/Dolphin.java -index f3093815066e6881a2bb638ae4643f69374450b3..2300abc4e80449e6b92992f6fb8cfe8e99dea351 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Dolphin.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Dolphin.java -@@ -84,14 +84,82 @@ public class Dolphin extends WaterAnimal { - public static final Predicate ALLOWED_ITEMS = (entityitem) -> { - return !entityitem.hasPickUpDelay() && entityitem.isAlive() && entityitem.isInWater(); - }; -+ private int spitCooldown; // Purpur - - public Dolphin(EntityType type, Level world) { - super(type, world); -- this.moveControl = new SmoothSwimmingMoveControl(this, 85, 10, 0.02F, 0.1F, true); -+ // Purpur start -+ class DolphinMoveControl extends SmoothSwimmingMoveControl { -+ private final net.pl3x.purpur.controller.WaterMoveControllerWASD waterMoveControllerWASD; -+ private final Dolphin dolphin; -+ -+ public DolphinMoveControl(Dolphin dolphin, int pitchChange, int yawChange, float speedInWater, float speedInAir, boolean buoyant) { -+ super(dolphin, pitchChange, yawChange, speedInWater, speedInAir, buoyant); -+ this.dolphin = dolphin; -+ this.waterMoveControllerWASD = new net.pl3x.purpur.controller.WaterMoveControllerWASD(dolphin); -+ } -+ -+ @Override -+ public void tick() { -+ if (dolphin.getRider() != null) { -+ purpurTick(dolphin.getRider()); -+ } else { -+ super.tick(); -+ } -+ } -+ -+ public void purpurTick(Player rider) { -+ if (dolphin.getAirSupply() < 150) { -+ // if drowning override player WASD controls to find air -+ tick(); -+ } else { -+ waterMoveControllerWASD.purpurTick(rider); -+ dolphin.setDeltaMovement(dolphin.getDeltaMovement().add(0.0D, 0.005D, 0.0D)); -+ } -+ } -+ }; -+ this.moveControl = new DolphinMoveControl(this, 85, 10, 0.02F, 0.1F, true); -+ // Purpur end - this.lookControl = new SmoothSwimmingLookControl(this, 10); - this.setCanPickUpLoot(true); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.dolphinRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return true; -+ } -+ -+ @Override -+ public boolean onSpacebar() { -+ if (spitCooldown == 0 && getRider() != null) { -+ spitCooldown = level.purpurConfig.dolphinSpitCooldown; -+ -+ org.bukkit.craftbukkit.entity.CraftPlayer player = (org.bukkit.craftbukkit.entity.CraftPlayer) getRider().getBukkitEntity(); -+ if (!player.hasPermission("allow.special.dolphin")) { -+ return false; -+ } -+ -+ org.bukkit.Location loc = player.getEyeLocation(); -+ loc.setPitch(loc.getPitch() - 10); -+ org.bukkit.util.Vector target = loc.getDirection().normalize().multiply(10).add(loc.toVector()); -+ -+ net.pl3x.purpur.entity.DolphinSpit spit = new net.pl3x.purpur.entity.DolphinSpit(level, this); -+ spit.shoot(target.getX() - getX(), target.getY() - getY(), target.getZ() - getZ(), level.purpurConfig.dolphinSpitSpeed, 5.0F); -+ -+ level.addFreshEntity(spit); -+ playSound(SoundEvents.DOLPHIN_ATTACK, 1.0F, 1.0F + (random.nextFloat() - random.nextFloat()) * 0.2F); -+ return true; -+ } -+ return false; -+ } -+ // Purpur end -+ - @Nullable - @Override - public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData entityData, @Nullable CompoundTag entityNbt) { -@@ -166,6 +234,7 @@ public class Dolphin extends WaterAnimal { - protected void registerGoals() { - this.goalSelector.addGoal(0, new BreathAirGoal(this)); - this.goalSelector.addGoal(0, new TryFindWaterGoal(this)); -+ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(1, new Dolphin.DolphinSwimToTreasureGoal(this)); - this.goalSelector.addGoal(2, new Dolphin.DolphinSwimWithPlayerGoal(this, 4.0D)); - this.goalSelector.addGoal(4, new RandomSwimmingGoal(this, 1.0D, 10)); -@@ -176,6 +245,7 @@ public class Dolphin extends WaterAnimal { - this.goalSelector.addGoal(8, new Dolphin.PlayWithItemsGoal()); - this.goalSelector.addGoal(8, new FollowBoatGoal(this)); - this.goalSelector.addGoal(9, new AvoidEntityGoal<>(this, Guardian.class, 8.0F, 1.0D, 1.0D)); -+ this.targetSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Guardian.class})).setAlertOthers(new Class[0])); // CraftBukkit - decompile error - } - -@@ -227,7 +297,7 @@ public class Dolphin extends WaterAnimal { - - @Override - protected boolean canRide(Entity entity) { -- return true; -+ return boardingCooldown <= 0; // Purpur - make dolphin honor ride cooldown like all other non-boss mobs; - } - - @Override -@@ -262,6 +332,11 @@ public class Dolphin extends WaterAnimal { - @Override - public void tick() { - super.tick(); -+ // Purpur start -+ if (spitCooldown > 0) { -+ spitCooldown--; -+ } -+ // Purpur end - if (this.isNoAi()) { - this.setAirSupply(this.getMaxAirSupply()); - } else { -diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java -index 31f4e4a93ea5fd3ffe7e60dff2e2a9642b51daa2..6cc8f6ef75e4b8b4282e4f664a83ce6491042df1 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Fox.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java -@@ -138,6 +138,39 @@ public class Fox extends Animal { - this.setCanPickUpLoot(true); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.foxRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.foxRidableInWater; -+ } -+ -+ @Override -+ public float getJumpPower() { -+ return getRider() != null ? 0.5F : super.getJumpPower(); -+ } -+ -+ @Override -+ public void onMount(Player rider) { -+ super.onMount(rider); -+ setCanPickUpLoot(false); -+ clearStates(); -+ setIsPouncing(false); -+ spitOutItem(getItemBySlot(EquipmentSlot.MAINHAND)); -+ setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); -+ } -+ -+ @Override -+ public void onDismount(Player rider) { -+ super.onDismount(rider); -+ setCanPickUpLoot(true); -+ } -+ // Purpur end -+ - @Override - protected void defineSynchedData() { - super.defineSynchedData(); -@@ -157,6 +190,7 @@ public class Fox extends Animal { - return entityliving instanceof AbstractSchoolingFish; - }); - this.goalSelector.addGoal(0, new Fox.FoxFloatGoal()); -+ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(1, new Fox.FaceplantGoal()); - this.goalSelector.addGoal(2, new Fox.FoxPanicGoal(2.2D)); - this.goalSelector.addGoal(3, new Fox.FoxBreedGoal(1.0D)); -@@ -182,6 +216,7 @@ public class Fox extends Animal { - this.goalSelector.addGoal(11, new Fox.FoxSearchForItemsGoal()); - this.goalSelector.addGoal(12, new Fox.FoxLookAtPlayerGoal(this, Player.class, 24.0F)); - this.goalSelector.addGoal(13, new Fox.PerchAndSearchGoal()); -+ this.targetSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.targetSelector.addGoal(3, new Fox.DefendTrustedTargetGoal(LivingEntity.class, false, false, (entityliving) -> { - return Fox.TRUSTED_TARGET_SELECTOR.test(entityliving) && !this.trusts(entityliving.getUUID()); - })); -@@ -737,16 +772,16 @@ public class Fox extends Animal { - return new Vec3(0.0D, (double) (0.55F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F)); - } - -- public class FoxLookControl extends LookControl { -+ public class FoxLookControl extends net.pl3x.purpur.controller.LookControllerWASD { // Purpur - - public FoxLookControl() { - super(Fox.this); - } - - @Override -- public void tick() { -+ public void vanillaTick() { // Purpur - if (!Fox.this.isSleeping()) { -- super.tick(); -+ super.vanillaTick(); // Purpur - } - - } -@@ -757,16 +792,16 @@ public class Fox extends Animal { - } - } - -- private class FoxMoveControl extends MoveControl { -+ private class FoxMoveControl extends net.pl3x.purpur.controller.MoveControllerWASD { // Purpur - - public FoxMoveControl() { - super(Fox.this); - } - - @Override -- public void tick() { -+ public void vanillaTick() { // Purpur - if (Fox.this.canMove()) { -- super.tick(); -+ super.vanillaTick(); // Purpur - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java -index ec00c2dd8f969eb99ec6a014e3bcd09c7484b237..63b739c86d2ea22aa9a610796ad2f208b0db289e 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java -+++ b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java -@@ -70,8 +70,22 @@ public class IronGolem extends AbstractGolem implements NeutralMob { - this.maxUpStep = 1.0F; - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.ironGolemRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.ironGolemRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void registerGoals() { -+ if (level.purpurConfig.ironGolemCanSwim) this.goalSelector.addGoal(0, new net.minecraft.world.entity.ai.goal.FloatGoal(this)); // Purpur -+ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(1, new MeleeAttackGoal(this, 1.0D, true)); - this.goalSelector.addGoal(2, new MoveTowardsTargetGoal(this, 0.9D, 32.0F)); - this.goalSelector.addGoal(2, new MoveBackToVillageGoal(this, 0.6D, false)); -@@ -79,6 +93,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob { - this.goalSelector.addGoal(5, new OfferFlowerGoal(this)); - this.goalSelector.addGoal(7, new LookAtPlayerGoal(this, Player.class, 6.0F)); - this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); -+ this.targetSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.targetSelector.addGoal(1, new DefendVillageTargetGoal(this)); - this.targetSelector.addGoal(2, new HurtByTargetGoal(this, new Class[0])); - this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt)); -@@ -266,13 +281,13 @@ public class IronGolem extends AbstractGolem implements NeutralMob { - ItemStack itemstack = player.getItemInHand(hand); - - if (!itemstack.is(Items.IRON_INGOT)) { -- return InteractionResult.PASS; -+ return tryRide(player, hand); // Purpur - } else { - float f = this.getHealth(); - - this.heal(25.0F); - if (this.getHealth() == f) { -- return InteractionResult.PASS; -+ return tryRide(player, hand); // Purpur - } else { - float f1 = 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F; - -diff --git a/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java -index d9fb3df35de94ae5abbb86ace0328bbe6f5403b3..0e066782ee09bb5626715bcc500bc04f2252bc2e 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java -+++ b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java -@@ -59,6 +59,18 @@ public class MushroomCow extends Cow implements Shearable { - super(type, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.mooshroomRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.mooshroomRidableInWater; -+ } -+ // Purpur end -+ - @Override - public float getWalkTargetValue(BlockPos pos, LevelReader world) { - return world.getBlockState(pos.below()).is(Blocks.MYCELIUM) ? 10.0F : world.getBrightness(pos) - 0.5F; -@@ -120,7 +132,7 @@ public class MushroomCow extends Cow implements Shearable { - } else if (itemstack.is(Items.SHEARS) && this.readyForShearing()) { - // CraftBukkit start - if (!CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) { -- return InteractionResult.PASS; -+ return tryRide(player, hand); // Purpur - } - // CraftBukkit end - this.shear(SoundSource.PLAYERS); -@@ -141,7 +153,7 @@ public class MushroomCow extends Cow implements Shearable { - Optional> optional = this.getEffectFromItemStack(itemstack); - - if (!optional.isPresent()) { -- return InteractionResult.PASS; -+ return tryRide(player, hand); // Purpur - } - - Pair pair = (Pair) optional.get(); -diff --git a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java -index 8104ac0f77e8e94f294b82f7badefccd72419223..db17b971bb2da8ae375347040029e17b1a6165f5 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java -@@ -68,6 +68,18 @@ public class Ocelot extends Animal { - this.reassessTrustingGoals(); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.ocelotRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.ocelotRidableInWater; -+ } -+ // Purpur end -+ - boolean isTrusting() { - return (Boolean) this.entityData.get(Ocelot.DATA_TRUSTING); - } -@@ -99,12 +111,14 @@ public class Ocelot extends Animal { - protected void registerGoals() { - this.temptGoal = new Ocelot.OcelotTemptGoal(this, 0.6D, Ocelot.TEMPT_INGREDIENT, true); - this.goalSelector.addGoal(1, new FloatGoal(this)); -+ this.goalSelector.addGoal(1, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(3, this.temptGoal); - this.goalSelector.addGoal(7, new LeapAtTargetGoal(this, 0.3F)); - this.goalSelector.addGoal(8, new OcelotAttackGoal(this)); - this.goalSelector.addGoal(9, new BreedGoal(this, 0.8D)); - this.goalSelector.addGoal(10, new WaterAvoidingRandomStrollGoal(this, 0.8D, 1.0000001E-5F)); - this.goalSelector.addGoal(11, new LookAtPlayerGoal(this, Player.class, 10.0F)); -+ this.targetSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Chicken.class, false)); - this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, false, false, Turtle.BABY_ON_LAND_SELECTOR)); - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/Panda.java b/src/main/java/net/minecraft/world/entity/animal/Panda.java -index 851ee58e52c6003d6ae7b58c9b6b9a9a9795fa85..4591b67537aa95ce0a7e6ad838b7db9da80346cc 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Panda.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Panda.java -@@ -108,6 +108,27 @@ public class Panda extends Animal { - - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.pandaRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.pandaRidableInWater; -+ } -+ -+ @Override -+ public void onMount(Player rider) { -+ super.onMount(rider); -+ setForwardMot(0.0F); -+ sit(false); -+ eat(false); -+ setOnBack(false); -+ } -+ // Purpur end -+ - @Override - public boolean canTakeItem(ItemStack stack) { - EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(stack); -@@ -263,6 +284,7 @@ public class Panda extends Animal { - @Override - protected void registerGoals() { - this.goalSelector.addGoal(0, new FloatGoal(this)); -+ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(2, new Panda.PandaPanicGoal(this, 2.0D)); - this.goalSelector.addGoal(2, new Panda.PandaBreedGoal(this, 1.0D)); - this.goalSelector.addGoal(3, new Panda.PandaAttackGoal(this, 1.2000000476837158D, true)); -@@ -278,6 +300,7 @@ public class Panda extends Animal { - this.goalSelector.addGoal(12, new Panda.PandaRollGoal(this)); - this.goalSelector.addGoal(13, new FollowParentGoal(this, 1.25D)); - this.goalSelector.addGoal(14, new WaterAvoidingRandomStrollGoal(this, 1.0D)); -+ this.targetSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.targetSelector.addGoal(1, (new Panda.PandaHurtByTargetGoal(this, new Class[0])).setAlertOthers(new Class[0])); - } - -@@ -615,7 +638,7 @@ public class Panda extends Animal { - ItemStack itemstack = player.getItemInHand(hand); - - if (this.isScared()) { -- return InteractionResult.PASS; -+ return tryRide(player, hand); // Purpur - } else if (this.isOnBack()) { - this.setOnBack(false); - return InteractionResult.sidedSuccess(this.level.isClientSide); -@@ -634,7 +657,7 @@ public class Panda extends Animal { - this.gameEvent(GameEvent.MOB_INTERACT, this.eyeBlockPosition()); - } else { - if (this.level.isClientSide || this.isSitting() || this.isInWater()) { -- return InteractionResult.PASS; -+ return tryRide(player, hand); // Purpur - } - - this.tryToSit(); -@@ -651,7 +674,7 @@ public class Panda extends Animal { - - return InteractionResult.SUCCESS; - } else { -- return InteractionResult.PASS; -+ return tryRide(player, hand); // Purpur - } - } - -@@ -691,7 +714,7 @@ public class Panda extends Animal { - return !this.isOnBack() && !this.isScared() && !this.isEating() && !this.isRolling() && !this.isSitting(); - } - -- private static class PandaMoveControl extends MoveControl { -+ private static class PandaMoveControl extends net.pl3x.purpur.controller.MoveControllerWASD { // Purpur - - private final Panda panda; - -@@ -701,9 +724,9 @@ public class Panda extends Animal { - } - - @Override -- public void tick() { -+ public void vanillaTick() { // Purpur - if (this.panda.canPerformAction()) { -- super.tick(); -+ super.vanillaTick(); // Purpur - } - } - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/Parrot.java b/src/main/java/net/minecraft/world/entity/animal/Parrot.java -index 345fe87d5d6c3883c28d2c1b34d1020e18864d97..0a3996b0943c9b0666f4aa3ac6ca9de5b1204fb3 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Parrot.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Parrot.java -@@ -121,12 +121,63 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal { - - public Parrot(EntityType type, Level world) { - super(type, world); -- this.moveControl = new FlyingMoveControl(this, 10, false); -+ // Purpur start -+ final net.pl3x.purpur.controller.FlyingWithSpacebarMoveControllerWASD flyingController = new net.pl3x.purpur.controller.FlyingWithSpacebarMoveControllerWASD(this, 0.3F); -+ class ParrotMoveControl extends FlyingMoveControl { -+ public ParrotMoveControl(Mob entity, int maxPitchChange, boolean noGravity) { -+ super(entity, maxPitchChange, noGravity); -+ } -+ -+ @Override -+ public void tick() { -+ if (mob.getRider() != null) { -+ flyingController.purpurTick(mob.getRider()); -+ } else { -+ super.tick(); -+ } -+ } -+ -+ @Override -+ public boolean hasWanted() { -+ return mob.getRider() != null ? getForwardMot() != 0 || getStrafeMot() != 0 : super.hasWanted(); -+ } -+ } -+ this.moveControl = new ParrotMoveControl(this, 10, false); -+ // Purpur end - this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F); - this.setPathfindingMalus(BlockPathTypes.DAMAGE_FIRE, -1.0F); - this.setPathfindingMalus(BlockPathTypes.COCOA, -1.0F); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.parrotRidable; -+ } -+ -+ @Override -+ public boolean isRidableInWater() { -+ return level.purpurConfig.parrotRidableInWater; -+ } -+ -+ @Override -+ public double getMaxY() { -+ return level.purpurConfig.parrotMaxY; -+ } -+ -+ @Override -+ public void travel(Vec3 vec3) { -+ super.travel(vec3); -+ if (getRider() != null && !onGround) { -+ float speed = (float) getAttributeValue(Attributes.FLYING_SPEED) * 2; -+ setSpeed(speed); -+ Vec3 mot = getDeltaMovement(); -+ move(net.minecraft.world.entity.MoverType.SELF, mot.multiply(speed, 0.25, speed)); -+ setDeltaMovement(mot.scale(0.9D)); -+ } -+ } -+ // Purpur end -+ - @Nullable - @Override - public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData entityData, @Nullable CompoundTag entityNbt) { -@@ -145,8 +196,10 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal { - - @Override - protected void registerGoals() { -- this.goalSelector.addGoal(0, new PanicGoal(this, 1.25D)); -+ //this.goalSelector.addGoal(0, new PanicGoal(this, 1.25D)); // Purpur - move down - this.goalSelector.addGoal(0, new FloatGoal(this)); -+ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur -+ this.goalSelector.addGoal(1, new PanicGoal(this, 1.25D)); // Purpur - this.goalSelector.addGoal(1, new LookAtPlayerGoal(this, Player.class, 8.0F)); - this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this)); - this.goalSelector.addGoal(2, new FollowOwnerGoal(this, 1.0D, 5.0F, 1.0F, true)); -diff --git a/src/main/java/net/minecraft/world/entity/animal/Pig.java b/src/main/java/net/minecraft/world/entity/animal/Pig.java -index 2c95b6eddfe46e5d2ad495bfc86ccc24ae75e704..80c8ceda47bf8b3ff370f89a61aa01869d606ee6 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Pig.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Pig.java -@@ -65,9 +65,22 @@ public class Pig extends Animal implements ItemSteerable, Saddleable { - this.steering = new ItemBasedSteering(this.entityData, Pig.DATA_BOOST_TIME, Pig.DATA_SADDLE_ID); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.pigRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.pigRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void registerGoals() { - this.goalSelector.addGoal(0, new FloatGoal(this)); -+ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(1, new PanicGoal(this, 1.25D)); - this.goalSelector.addGoal(3, new BreedGoal(this, 1.0D)); - this.goalSelector.addGoal(4, new TemptGoal(this, 1.2D, Ingredient.of(Items.CARROT_ON_A_STICK), false)); -diff --git a/src/main/java/net/minecraft/world/entity/animal/PolarBear.java b/src/main/java/net/minecraft/world/entity/animal/PolarBear.java -index 0694cd0b994ee595adca43c988485e6dc13c7244..dc6bc8f10d147cb1d0e5c69b6f6df63b0e8d4531 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/PolarBear.java -+++ b/src/main/java/net/minecraft/world/entity/animal/PolarBear.java -@@ -61,11 +61,35 @@ public class PolarBear extends Animal implements NeutralMob { - private static final UniformInt PERSISTENT_ANGER_TIME = TimeUtil.rangeOfSeconds(20, 39); - private int remainingPersistentAngerTime; - private UUID persistentAngerTarget; -+ private int standTimer = 0; // Purpur - - public PolarBear(EntityType type, Level world) { - super(type, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.polarBearRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.polarBearRidableInWater; -+ } -+ -+ @Override -+ public boolean onSpacebar() { -+ if (!isStanding()) { -+ if (getRider() != null && getRider().getForwardMot() == 0 && getRider().getStrafeMot() == 0) { -+ setStanding(true); -+ playSound(SoundEvents.POLAR_BEAR_WARNING, 1.0F, 1.0F); -+ } -+ } -+ return false; -+ } -+ // Purpur end -+ - @Override - public AgeableMob getBreedOffspring(ServerLevel world, AgeableMob entity) { - return EntityType.POLAR_BEAR.create(world); -@@ -80,12 +104,14 @@ public class PolarBear extends Animal implements NeutralMob { - protected void registerGoals() { - super.registerGoals(); - this.goalSelector.addGoal(0, new FloatGoal(this)); -+ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(1, new PolarBear.PolarBearMeleeAttackGoal()); - this.goalSelector.addGoal(1, new PolarBear.PolarBearPanicGoal()); - this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.25D)); - this.goalSelector.addGoal(5, new RandomStrollGoal(this, 1.0D)); - this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F)); - this.goalSelector.addGoal(7, new RandomLookAroundGoal(this)); -+ this.targetSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.targetSelector.addGoal(1, new PolarBear.PolarBearHurtByTargetGoal()); - this.targetSelector.addGoal(2, new PolarBear.PolarBearAttackPlayersGoal()); - this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt)); -@@ -201,6 +227,11 @@ public class PolarBear extends Animal implements NeutralMob { - this.updatePersistentAnger((ServerLevel)this.level, true); - } - -+ // Purpur start -+ if (isStanding() && --standTimer <= 0) { -+ setStanding(false); -+ } -+ // Purpur end - } - - @Override -@@ -230,6 +261,7 @@ public class PolarBear extends Animal implements NeutralMob { - - public void setStanding(boolean warning) { - this.entityData.set(DATA_STANDING_ID, warning); -+ standTimer = warning ? 20 : -1; // Purpur - } - - public float getStandingAnimationScale(float tickDelta) { -diff --git a/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java b/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java -index 1b76e267cd36010a57d31852086dec0585d4bce5..42446fd8ba1d78cd5992bc6c2e5259da361eb716 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java -@@ -45,6 +45,18 @@ public class Pufferfish extends AbstractFish { - this.refreshDimensions(); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.pufferfishRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return true; -+ } -+ // Purpur end -+ - @Override - protected void defineSynchedData() { - super.defineSynchedData(); diff --git a/src/main/java/net/minecraft/world/entity/animal/Rabbit.java b/src/main/java/net/minecraft/world/entity/animal/Rabbit.java -index 3a9391b512974e812cac0d89119f68ba6728bfc9..29551a3b87f06c5876de5fda80615acf6c1f4764 100644 +index 3a9391b512974e812cac0d89119f68ba6728bfc9..4a60afbb79ffb86d3c41b48d923ca8b3beca1c54 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Rabbit.java +++ b/src/main/java/net/minecraft/world/entity/animal/Rabbit.java -@@ -81,6 +81,7 @@ public class Rabbit extends Animal { - private boolean wasOnGround; - private int jumpDelayTicks; - int moreCarrotTicks; -+ private boolean actualJump; // Purpur - - public Rabbit(EntityType type, Level world) { - super(type, world); -@@ -89,6 +90,46 @@ public class Rabbit extends Animal { - this.initializePathFinderGoals(); // CraftBukkit - moved code - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.rabbitRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.rabbitRidableInWater; -+ } -+ -+ @Override -+ public boolean onSpacebar() { -+ if (onGround) { -+ actualJump = true; -+ jumpFromGround(); -+ actualJump = false; -+ } -+ return true; -+ } -+ -+ private void handleJumping() { -+ if (onGround) { -+ RabbitJumpControl jumpController = (RabbitJumpControl) jumpControl; -+ if (!wasOnGround) { -+ setJumping(false); -+ jumpController.setCanJump(false); -+ } -+ if (!jumpController.wantJump()) { -+ if (moveControl.hasWanted()) { -+ startJumping(); -+ } -+ } else if (!jumpController.canJump()) { -+ jumpController.setCanJump(true); -+ } -+ } -+ wasOnGround = onGround; -+ } -+ // Purpur end -+ - // CraftBukkit start - code from constructor - public void initializePathFinderGoals(){ - this.setSpeedModifier(0.0D); -@@ -98,6 +139,7 @@ public class Rabbit extends Animal { - @Override - public void registerGoals() { - this.goalSelector.addGoal(1, new FloatGoal(this)); -+ this.goalSelector.addGoal(1, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(1, new Rabbit.RabbitPanicGoal(this, 2.2D)); - this.goalSelector.addGoal(2, new BreedGoal(this, 0.8D)); - this.goalSelector.addGoal(3, new TemptGoal(this, 1.0D, Ingredient.of(Items.CARROT, Items.GOLDEN_CARROT, Blocks.DANDELION), false)); -@@ -111,6 +153,13 @@ public class Rabbit extends Animal { - - @Override - protected float getJumpPower() { -+ if (getRider() != null) { -+ if (getForwardMot() < 0) { -+ setSpeed(getForwardMot() * 2F); -+ } -+ return actualJump ? 0.5F : 0.3F; -+ } -+ // Purpur end - if (!this.horizontalCollision && (!this.moveControl.hasWanted() || this.moveControl.getWantedY() <= this.getY() + 0.5D)) { - Path pathentity = this.navigation.getPath(); - -@@ -129,7 +178,7 @@ public class Rabbit extends Animal { +@@ -129,7 +129,7 @@ public class Rabbit extends Animal { } @Override @@ -1654,361 +744,6 @@ index 3a9391b512974e812cac0d89119f68ba6728bfc9..29551a3b87f06c5876de5fda80615acf super.jumpFromGround(); double d0 = this.moveControl.getSpeedModifier(); -@@ -179,6 +228,13 @@ public class Rabbit extends Animal { - - @Override - public void customServerAiStep() { -+ // Purpur start -+ if (getRider() != null) { -+ handleJumping(); -+ return; -+ } -+ // Purpur end -+ - if (this.jumpDelayTicks > 0) { - --this.jumpDelayTicks; - } -@@ -451,7 +507,7 @@ public class Rabbit extends Animal { - } - } - -- private static class RabbitMoveControl extends MoveControl { -+ private static class RabbitMoveControl extends net.pl3x.purpur.controller.MoveControllerWASD { // Purpur - - private final Rabbit rabbit; - private double nextJumpSpeed; -@@ -462,14 +518,14 @@ public class Rabbit extends Animal { - } - - @Override -- public void tick() { -+ public void vanillaTick() { // Purpur - if (this.rabbit.onGround && !this.rabbit.jumping && !((Rabbit.RabbitJumpControl) this.rabbit.jumpControl).wantJump()) { - this.rabbit.setSpeedModifier(0.0D); - } else if (this.hasWanted()) { - this.rabbit.setSpeedModifier(this.nextJumpSpeed); - } - -- super.tick(); -+ super.vanillaTick(); // Purpur - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/Salmon.java b/src/main/java/net/minecraft/world/entity/animal/Salmon.java -index 574f91414ecacd18fadef5a56a4142d9cfdb6713..02a9ce0b98bab47d57b51cdfb2194f0e72a9f705 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Salmon.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Salmon.java -@@ -13,6 +13,18 @@ public class Salmon extends AbstractSchoolingFish { - super(type, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.salmonRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return true; -+ } -+ // Purpur end -+ - @Override - public int getMaxSchoolSize() { - return 5; -diff --git a/src/main/java/net/minecraft/world/entity/animal/Sheep.java b/src/main/java/net/minecraft/world/entity/animal/Sheep.java -index 9315c34e61aa0432175385736de51f1bfdafbf85..5890bf8aa714dc219059bca4950a1b5b1882dd3a 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Sheep.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Sheep.java -@@ -116,10 +116,23 @@ public class Sheep extends Animal implements Shearable { - super(type, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.sheepRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.sheepRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void registerGoals() { - this.eatBlockGoal = new EatBlockGoal(this); - this.goalSelector.addGoal(0, new FloatGoal(this)); -+ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(1, new PanicGoal(this, 1.25D)); - this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); - this.goalSelector.addGoal(3, new TemptGoal(this, 1.1D, Ingredient.of(Items.WHEAT), false)); -diff --git a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java -index 2631f08496c8e45874b22760b559a91b7b2bf415..a76f3c1c409dc96f7033be8a7eeb06617053735b 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java -+++ b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java -@@ -53,12 +53,26 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM - super(type, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.snowGolemRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.snowGolemRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void registerGoals() { -+ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(1, new RangedAttackGoal(this, 1.25D, 20, 10.0F)); - this.goalSelector.addGoal(2, new WaterAvoidingRandomStrollGoal(this, 1.0D, 1.0000001E-5F)); - this.goalSelector.addGoal(3, new LookAtPlayerGoal(this, Player.class, 6.0F)); - this.goalSelector.addGoal(4, new RandomLookAroundGoal(this)); -+ this.targetSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Mob.class, 10, true, false, (entityliving) -> { - return entityliving instanceof Enemy; - })); -@@ -110,6 +124,7 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM - return; - } - -+ if (getRider() != null && !level.purpurConfig.snowGolemLeaveTrailWhenRidden) return; // Purpur - don't leave snow trail when being ridden - BlockState iblockdata = Blocks.SNOW.defaultBlockState(); - - for (int l = 0; l < 4; ++l) { -@@ -152,7 +167,7 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM - if (itemstack.is(Items.SHEARS) && this.readyForShearing()) { - // CraftBukkit start - if (!CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) { -- return InteractionResult.PASS; -+ return tryRide(player, hand); // Purpur - } - // CraftBukkit end - this.shear(SoundSource.PLAYERS); -@@ -165,7 +180,7 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM - - return InteractionResult.sidedSuccess(this.level.isClientSide); - } else { -- return InteractionResult.PASS; -+ return tryRide(player, hand); // Purpur - } - } - -diff --git a/src/main/java/net/minecraft/world/entity/animal/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java -index 56838c9f214c0f75041e75c45ad1a0c72fcacc66..0a744855f24ac54b22bc474a1c903da7af656364 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Squid.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Squid.java -@@ -54,9 +54,32 @@ public class Squid extends WaterAnimal { - this.tentacleSpeed = 1.0F / (this.random.nextFloat() + 1.0F) * 0.2F; - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.squidRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return true; -+ } -+ -+ private void rotateVectorAroundY(org.bukkit.util.Vector vector, double degrees) { -+ double rad = Math.toRadians(degrees); -+ double cos = Math.cos(rad); -+ double sine = Math.sin(rad); -+ double x = vector.getX(); -+ double z = vector.getZ(); -+ vector.setX(cos * x - sine * z); -+ vector.setZ(sine * x + cos * z); -+ } -+ // Purpur end -+ - @Override - protected void registerGoals() { - this.goalSelector.addGoal(0, new Squid.SquidRandomMovementGoal(this)); -+ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(1, new Squid.SquidFleeGoal()); - } - -@@ -250,6 +273,38 @@ public class Squid extends WaterAnimal { - - @Override - public void tick() { -+ // Purpur start -+ Player rider = squid.getRider(); -+ if (rider != null) { -+ if (rider.jumping) { -+ squid.onSpacebar(); -+ } -+ float forward = rider.getForwardMot(); -+ float strafe = rider.getStrafeMot(); -+ float speed = (float) squid.getAttributeValue(Attributes.MOVEMENT_SPEED) * 10F; -+ if (forward < 0.0F) { -+ speed *= -0.5; -+ } -+ org.bukkit.util.Vector dir = rider.getBukkitEntity().getEyeLocation().getDirection().normalize().multiply(speed / 20.0F); -+ if (strafe != 0.0F) { -+ if (forward == 0.0F) { -+ dir.setY(0); -+ rotateVectorAroundY(dir, strafe > 0.0F ? -90 : 90); -+ } else if (forward < 0.0F) { -+ rotateVectorAroundY(dir, strafe > 0.0F ? 45 : -45); -+ } else { -+ rotateVectorAroundY(dir, strafe > 0.0F ? -45 : 45); -+ } -+ } -+ if (forward != 0.0F || strafe != 0.0F) { -+ squid.setMovementVector((float) dir.getX(), (float) dir.getY(), (float) dir.getZ()); -+ } else { -+ squid.setMovementVector(0.0F, 0.0F, 0.0F); -+ } -+ return; -+ } -+ // Purpur end -+ - int i = this.squid.getNoActionTime(); - - if (i > 100) { -diff --git a/src/main/java/net/minecraft/world/entity/animal/TropicalFish.java b/src/main/java/net/minecraft/world/entity/animal/TropicalFish.java -index 77f56978449ece43bdca28a50a0681cda9f89eba..4d5ceb4ce913248ad404393e4f0c75cad24029bb 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/TropicalFish.java -+++ b/src/main/java/net/minecraft/world/entity/animal/TropicalFish.java -@@ -43,6 +43,18 @@ public class TropicalFish extends AbstractSchoolingFish { - super(type, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.tropicalFishRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return true; -+ } -+ // Purpur end -+ - public static String getPredefinedName(int variant) { - return "entity.minecraft.tropical_fish.predefined." + variant; - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -index 925f16d5eb092518ef774f69a8d99689feb0f5d7..b6d7692a779fb95d50aecb63b495336ae28d1933 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -@@ -90,6 +90,18 @@ public class Turtle extends Animal { - this.maxUpStep = 1.0F; - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.turtleRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.turtleRidableInWater; -+ } -+ // Purpur end -+ - public void setHomePos(BlockPos pos) { - this.entityData.set(Turtle.HOME_POS, pos); - } -@@ -192,6 +204,7 @@ public class Turtle extends Animal { - - @Override - protected void registerGoals() { -+ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(0, new Turtle.TurtlePanicGoal(this, 1.2D)); - this.goalSelector.addGoal(1, new Turtle.TurtleBreedGoal(this, 1.0D)); - this.goalSelector.addGoal(1, new Turtle.TurtleLayEggGoal(this, 1.0D)); -@@ -349,13 +362,15 @@ public class Turtle extends Animal { - org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = null; // CraftBukkit - } - -- private static class TurtleMoveControl extends MoveControl { -+ private static class TurtleMoveControl extends net.pl3x.purpur.controller.MoveControllerWASD { // Purpur - - private final Turtle turtle; -+ private final net.pl3x.purpur.controller.WaterMoveControllerWASD waterController; // Purpur - - TurtleMoveControl(Turtle turtle) { - super(turtle); - this.turtle = turtle; -+ waterController = new net.pl3x.purpur.controller.WaterMoveControllerWASD(turtle, 0.25D); // Purpur - } - - private void updateSpeed() { -@@ -374,8 +389,18 @@ public class Turtle extends Animal { - - } - -+ // Purpur start -+ public void purpurTick(Player rider) { -+ if (turtle.isInWater()) { -+ waterController.purpurTick(rider); -+ } else { -+ super.purpurTick(rider); -+ } -+ } -+ // Purpur end -+ - @Override -- public void tick() { -+ public void vanillaTick() { // Purpur - this.updateSpeed(); - if (this.operation == MoveControl.Operation.MOVE_TO && !this.turtle.getNavigation().isDone()) { - double d0 = this.wantedX - this.turtle.getX(); -diff --git a/src/main/java/net/minecraft/world/entity/animal/Wolf.java b/src/main/java/net/minecraft/world/entity/animal/Wolf.java -index 80caabee4d2100208f117a1c3e35247b65e318ad..bca3300e06d6eb0c6acdfb11d715a1e8447c9198 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Wolf.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Wolf.java -@@ -93,9 +93,27 @@ public class Wolf extends TamableAnimal implements NeutralMob { - this.setTame(false); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.wolfRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.wolfRidableInWater; -+ } -+ -+ public void onMount(Player rider) { -+ super.onMount(rider); -+ setInSittingPose(false); -+ } -+ // Purpur end -+ - @Override - protected void registerGoals() { - this.goalSelector.addGoal(1, new FloatGoal(this)); -+ this.goalSelector.addGoal(1, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this)); - this.goalSelector.addGoal(3, new Wolf.WolfAvoidEntityGoal<>(this, Llama.class, 24.0F, 1.5D, 1.5D)); - this.goalSelector.addGoal(4, new LeapAtTargetGoal(this, 0.4F)); -@@ -106,6 +124,7 @@ public class Wolf extends TamableAnimal implements NeutralMob { - this.goalSelector.addGoal(9, new BegGoal(this, 8.0F)); - this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Player.class, 8.0F)); - this.goalSelector.addGoal(10, new RandomLookAroundGoal(this)); -+ this.targetSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.targetSelector.addGoal(1, new OwnerHurtByTargetGoal(this)); - this.targetSelector.addGoal(2, new OwnerHurtTargetGoal(this)); - this.targetSelector.addGoal(3, (new HurtByTargetGoal(this, new Class[0])).setAlertOthers(new Class[0])); // CraftBukkit - decompile error diff --git a/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java b/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java index 25ebcb30cf5165675f26802983b6f68404b93b06..e076d03025690492c2226f03d777eba714819300 100644 --- a/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java @@ -2072,791 +807,6 @@ index 25ebcb30cf5165675f26802983b6f68404b93b06..e076d03025690492c2226f03d777eba7 } } -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java -index ba58e066cca533dfed7610a730c4dd7423fe124d..919410ce27e7e42e297c2caba7d3d7c1b623aede 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java -@@ -114,12 +114,22 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, - - protected AbstractHorse(EntityType type, Level world) { - super(type, world); -+ this.moveControl = new net.minecraft.world.entity.ai.control.MoveControl(this); // Purpur - use vanilla controller -+ this.lookControl = new net.minecraft.world.entity.ai.control.LookControl(this); // Purpur - use vanilla controller - this.maxUpStep = 1.0F; - this.createInventory(); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return false; // vanilla handles -+ } -+ // Purpur end -+ - @Override - protected void registerGoals() { -+ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(1, new PanicGoal(this, 1.2D)); - this.goalSelector.addGoal(1, new RunAroundLikeCrazyGoal(this, 1.2D)); - this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D, AbstractHorse.class)); -@@ -127,6 +137,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, - this.goalSelector.addGoal(6, new WaterAvoidingRandomStrollGoal(this, 0.7D)); - this.goalSelector.addGoal(7, new LookAtPlayerGoal(this, Player.class, 6.0F)); - this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); -+ this.targetSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.addBehaviourGoals(); - } - -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Donkey.java b/src/main/java/net/minecraft/world/entity/animal/horse/Donkey.java -index ab588b990c15ff809a1937321d11a03aab826f61..e5b13558f45966bf70593931922ca73f4a66c66a 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/Donkey.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/Donkey.java -@@ -15,6 +15,13 @@ public class Donkey extends AbstractChestedHorse { - super(type, world); - } - -+ // Purpur start -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.donkeyRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected SoundEvent getAmbientSound() { - super.getAmbientSound(); -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Horse.java b/src/main/java/net/minecraft/world/entity/animal/horse/Horse.java -index 6326471fe48133bef94e98fd028e60a951bccf2b..c7b0d6a987644e0b589c143b0b6b68053be04f37 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/Horse.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/Horse.java -@@ -39,6 +39,13 @@ public class Horse extends AbstractHorse { - super(type, world); - } - -+ // Purpur start -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.horseRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected void randomizeAttributes() { - this.getAttribute(Attributes.MAX_HEALTH).setBaseValue((double)this.generateRandomMaxHealth()); -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java -index 5c31519193126b715105e1e83bb54f6a1681d19e..0671185c358398fe0c4c1dbf4ede2f3e8c4794fb 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java -@@ -68,7 +68,46 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { - - public Llama(EntityType type, Level world) { - super(type, world); -+ // Purpur start -+ this.moveControl = new net.pl3x.purpur.controller.MoveControllerWASD(this) { -+ @Override -+ public void tick() { -+ if (entity.getRider() != null && isSaddled()) { -+ purpurTick(entity.getRider()); -+ } else { -+ vanillaTick(); -+ } -+ } -+ }; -+ this.lookControl = new net.pl3x.purpur.controller.LookControllerWASD(this) { -+ @Override -+ public void tick() { -+ if (entity.getRider() != null && isSaddled()) { -+ purpurTick(entity.getRider()); -+ } else { -+ vanillaTick(); -+ } -+ } -+ }; -+ // Purpur end -+ } -+ -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.llamaRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.llamaRidableInWater; -+ } -+ -+ @Override -+ public boolean isSaddled() { -+ return super.isSaddled() || (isTamed() && getSwag() != null); - } -+ // Purpur end - - public boolean isTraderLlama() { - return false; -@@ -113,6 +152,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { - @Override - protected void registerGoals() { - this.goalSelector.addGoal(0, new FloatGoal(this)); -+ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(1, new RunAroundLikeCrazyGoal(this, 1.2D)); - this.goalSelector.addGoal(2, new LlamaFollowCaravanGoal(this, (double)2.1F)); - this.goalSelector.addGoal(3, new RangedAttackGoal(this, 1.25D, 40, 20.0F)); -@@ -122,6 +162,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { - this.goalSelector.addGoal(6, new WaterAvoidingRandomStrollGoal(this, 0.7D)); - this.goalSelector.addGoal(7, new LookAtPlayerGoal(this, Player.class, 6.0F)); - this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); -+ this.targetSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.targetSelector.addGoal(1, new Llama.LlamaHurtByTargetGoal(this)); - this.targetSelector.addGoal(2, new Llama.LlamaAttackWolfGoal(this)); - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Mule.java b/src/main/java/net/minecraft/world/entity/animal/horse/Mule.java -index 6b10aeab9d671327f6e85a31b0c85ef310a1d0b2..40cc7e20913938d6e30e6bca9f4ad70fb5e9435b 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/Mule.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/Mule.java -@@ -14,6 +14,13 @@ public class Mule extends AbstractChestedHorse { - super(type, world); - } - -+ // Purpur start -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.muleRidableInWater; -+ } -+ // Purpur end -+ - @Override - protected SoundEvent getAmbientSound() { - super.getAmbientSound(); -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java -index 1d0a2296bab0140d3209c0749710d5fb952c79b4..d4057c300d39eca4ff2e11791ce5ba7993d9b66e 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java -@@ -29,6 +29,13 @@ public class SkeletonHorse extends AbstractHorse { - super(type, world); - } - -+ // Purpur start -+ @Override -+ public boolean isTamed() { -+ return true; -+ } -+ // Purpur end -+ - public static AttributeSupplier.Builder createAttributes() { - return createBaseHorseAttributes().add(Attributes.MAX_HEALTH, 15.0D).add(Attributes.MOVEMENT_SPEED, (double)0.2F); - } -@@ -40,6 +47,7 @@ public class SkeletonHorse extends AbstractHorse { - - @Override - protected void addBehaviourGoals() { -+ if (level.purpurConfig.skeletonHorseCanSwim) goalSelector.addGoal(0, new net.minecraft.world.entity.ai.goal.FloatGoal(this)); // Purpur - } - - @Override -@@ -135,7 +143,7 @@ public class SkeletonHorse extends AbstractHorse { - - @Override - public boolean rideableUnderWater() { -- return true; -+ return level.purpurConfig.skeletonHorseRidableInWater; // Purpur - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/TraderLlama.java b/src/main/java/net/minecraft/world/entity/animal/horse/TraderLlama.java -index 885937d7001259d9a8ee8d5bc16629a196a13fe8..ff252d9ca75b90ab7606f63aa5f89b6230e33a36 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/TraderLlama.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/TraderLlama.java -@@ -27,6 +27,23 @@ public class TraderLlama extends Llama { - super(type, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.traderLlamaRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.traderLlamaRidableInWater; -+ } -+ -+ @Override -+ public boolean isSaddled() { -+ return super.isSaddled() || isTamed(); -+ } -+ // Purpur end -+ - @Override - public boolean isTraderLlama() { - return true; -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/ZombieHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/ZombieHorse.java -index c6c7096ec476d91ef91b164e32c5a9cd112f3dd7..d328e36015b6b7d6a9e093fbe232eb5ecda46d96 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/ZombieHorse.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/ZombieHorse.java -@@ -22,6 +22,18 @@ public class ZombieHorse extends AbstractHorse { - super(type, world); - } - -+ // Purpur start -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.zombieHorseRidableInWater; -+ } -+ -+ @Override -+ public boolean isTamed() { -+ return true; -+ } -+ // Purpur end -+ - public static AttributeSupplier.Builder createAttributes() { - return createBaseHorseAttributes().add(Attributes.MAX_HEALTH, 15.0D).add(Attributes.MOVEMENT_SPEED, (double)0.2F); - } -@@ -92,5 +104,6 @@ public class ZombieHorse extends AbstractHorse { - - @Override - protected void addBehaviourGoals() { -+ if (level.purpurConfig.zombieHorseCanSwim) goalSelector.addGoal(0, new net.minecraft.world.entity.ai.goal.FloatGoal(this)); // Purpur - } - } -diff --git a/src/main/java/net/minecraft/world/entity/boss/EnderDragonPart.java b/src/main/java/net/minecraft/world/entity/boss/EnderDragonPart.java -index 305a891e4b51d1031d9e9238ff00e2ea7de8d954..84625d09df800fcfd477fc493fb5f8246567b7e8 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/EnderDragonPart.java -+++ b/src/main/java/net/minecraft/world/entity/boss/EnderDragonPart.java -@@ -21,6 +21,13 @@ public class EnderDragonPart extends Entity { - this.name = name; - } - -+ // Purpur start -+ @Override -+ public net.minecraft.world.InteractionResult interact(net.minecraft.world.entity.player.Player player, net.minecraft.world.InteractionHand hand) { -+ return parentMob.isAlive() ? parentMob.tryRide(player, hand) : net.minecraft.world.InteractionResult.PASS; -+ } -+ // Purpur end -+ - @Override - protected void defineSynchedData() { - } -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -index c98202092752a9015aaf95bd1471135b88e84425..a1a64591e6a6fb8a4550b91f89e3cdbd35c6d249 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -@@ -102,6 +102,7 @@ public class EnderDragon extends Mob implements Enemy { - private final int[] nodeAdjacency = new int[24]; - private final BinaryHeap openSet = new BinaryHeap(); - private Explosion explosionSource = new Explosion(null, this, null, null, Double.NaN, Double.NaN, Double.NaN, Float.NaN, true, Explosion.BlockInteraction.DESTROY); // CraftBukkit - reusable source for CraftTNTPrimed.getSource() -+ private boolean hadRider; // Purpur - - public EnderDragon(EntityType entitytypes, Level world) { - super(EntityType.ENDER_DRAGON, world); -@@ -116,8 +117,45 @@ public class EnderDragon extends Mob implements Enemy { - } - - this.phaseManager = new EnderDragonPhaseManager(this); -+ -+ // Purpur start -+ this.moveControl = new net.pl3x.purpur.controller.FlyingMoveControllerWASD(this) { -+ @Override -+ public void tick() { -+ // dragon doesn't use the controller. do nothing -+ } -+ }; -+ this.lookControl = new net.pl3x.purpur.controller.LookControllerWASD(this) { -+ @Override -+ public void tick() { -+ // dragon doesn't use the controller. do nothing -+ } -+ -+ @Override -+ public void purpurTick(Player rider) { -+ setYawPitch(rider.yRot - 180F, rider.xRotO * 0.5F); -+ } -+ }; -+ // Purpur end -+ } -+ -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.enderDragonRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.enderDragonRidableInWater; - } - -+ @Override -+ public double getMaxY() { -+ return level.purpurConfig.enderDragonMaxY; -+ } -+ // Purpur end -+ - public static AttributeSupplier.Builder createAttributes() { - return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 200.0D); - } -@@ -166,6 +204,37 @@ public class EnderDragon extends Mob implements Enemy { - - @Override - public void aiStep() { -+ // Purpur start -+ boolean hasRider = getRider() != null; -+ if (hasRider) { -+ if (!hadRider) { -+ hadRider = true; -+ noPhysics = false; -+ this.dimensions = net.minecraft.world.entity.EntityDimensions.scalable(4.0F, 2.0F); -+ } -+ -+ // dragon doesn't use controllers, so must tick manually -+ moveControl.tick(); -+ lookControl.tick(); -+ -+ moveRelative((float) getAttributeValue(Attributes.MOVEMENT_SPEED) * 0.1F, new Vec3(-getStrafeMot(), getVerticalMot(), -getForwardMot())); -+ Vec3 mot = getDeltaMovement(); -+ setDeltaMovement(mot); -+ move(MoverType.PLAYER, mot); -+ -+ mot = mot.multiply(0.9F, 0.9F, 0.9F); -+ setDeltaMovement(mot); -+ -+ // control wing flap speed on client -+ phaseManager.setPhase(mot.x() * mot.x() + mot.z() * mot.z() < 0.005F ? EnderDragonPhase.HOVERING : EnderDragonPhase.HOLDING_PATTERN); -+ } else if (hadRider) { -+ hadRider = false; -+ noPhysics = true; -+ this.dimensions = net.minecraft.world.entity.EntityDimensions.scalable(16.0F, 8.0F); -+ phaseManager.setPhase(EnderDragonPhase.HOLDING_PATTERN); // HoldingPattern -+ } -+ // Purpur end -+ - this.processFlappingMovement(); - if (this.level.isClientSide) { - this.setHealth(this.getHealth()); -@@ -179,6 +248,8 @@ public class EnderDragon extends Mob implements Enemy { - float f; - - if (this.isDeadOrDying()) { -+ if (hasRider) ejectPassengers(); // Purpur -+ - float f1 = (this.random.nextFloat() - 0.5F) * 8.0F; - - f = (this.random.nextFloat() - 0.5F) * 4.0F; -@@ -191,9 +262,9 @@ public class EnderDragon extends Mob implements Enemy { - - f = 0.2F / ((float) vec3d.horizontalDistance() * 10.0F + 1.0F); - f *= (float) Math.pow(2.0D, vec3d.y); -- if (this.phaseManager.getCurrentPhase().isSitting()) { -+ if (!hasRider && this.phaseManager.getCurrentPhase().isSitting()) { // Purpur - this.flapTime += 0.1F; -- } else if (this.inWall) { -+ } else if (!hasRider && this.inWall) { // Purpur - this.flapTime += f * 0.5F; - } else { - this.flapTime += f; -@@ -238,7 +309,7 @@ public class EnderDragon extends Mob implements Enemy { - } - - this.phaseManager.getCurrentPhase().doClientTick(); -- } else { -+ } else if (!hasRider) { // Purpur - DragonPhaseInstance idragoncontroller = this.phaseManager.getCurrentPhase(); - - idragoncontroller.doServerTick(); -@@ -308,7 +379,7 @@ public class EnderDragon extends Mob implements Enemy { - this.tickPart(this.body, (double) (f11 * 0.5F), 0.0D, (double) (-f12 * 0.5F)); - this.tickPart(this.wing1, (double) (f12 * 4.5F), 2.0D, (double) (f11 * 4.5F)); - this.tickPart(this.wing2, (double) (f12 * -4.5F), 2.0D, (double) (f11 * -4.5F)); -- if (!this.level.isClientSide && this.hurtTime == 0) { -+ if (!hasRider && !this.level.isClientSide && this.hurtTime == 0) { // Purpur - this.knockBack(this.level.getEntities(this, this.wing1.getBoundingBox().inflate(4.0D, 2.0D, 4.0D).move(0.0D, -2.0D, 0.0D), EntitySelector.NO_CREATIVE_OR_SPECTATOR)); - this.knockBack(this.level.getEntities(this, this.wing2.getBoundingBox().inflate(4.0D, 2.0D, 4.0D).move(0.0D, -2.0D, 0.0D), EntitySelector.NO_CREATIVE_OR_SPECTATOR)); - this.hurt(this.level.getEntities(this, this.head.getBoundingBox().inflate(1.0D), EntitySelector.NO_CREATIVE_OR_SPECTATOR)); -@@ -352,7 +423,7 @@ public class EnderDragon extends Mob implements Enemy { - } - - if (!this.level.isClientSide) { -- this.inWall = this.checkWalls(this.head.getBoundingBox()) | this.checkWalls(this.neck.getBoundingBox()) | this.checkWalls(this.body.getBoundingBox()); -+ this.inWall = !hasRider && this.checkWalls(this.head.getBoundingBox()) | this.checkWalls(this.neck.getBoundingBox()) | this.checkWalls(this.body.getBoundingBox()); // Purpur - if (this.dragonFight != null) { - this.dragonFight.updateDragon(this); - } -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -index 1c8f6863b976cfcb559de9b3e3cf9292831166ee..0b1f6fad51a985ebe4ccebde12a1db9e12a57bc0 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -@@ -83,6 +83,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob - return entityliving.getMobType() != MobType.UNDEAD && entityliving.attackable(); - }; - private static final TargetingConditions TARGETING_CONDITIONS = TargetingConditions.forCombat().range(20.0D).selector(WitherBoss.LIVING_ENTITY_SELECTOR); -+ private int shootCooldown = 0; // Purpur - // Paper start - private boolean canPortal = false; - -@@ -95,15 +96,117 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob - this.setHealth(this.getMaxHealth()); - this.getNavigation().setCanFloat(true); - this.xpReward = 50; -+ this.moveControl = new net.pl3x.purpur.controller.FlyingWithSpacebarMoveControllerWASD(this, 0.1F); // Purpur - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.witherRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.witherRidableInWater; -+ } -+ -+ @Override -+ public double getMaxY() { -+ return level.purpurConfig.witherMaxY; -+ } -+ -+ @Override -+ public void travel(Vec3 vec3) { -+ super.travel(vec3); -+ if (getRider() != null && !onGround) { -+ float speed = (float) getAttributeValue(Attributes.FLYING_SPEED) * 5F; -+ setSpeed(speed); -+ Vec3 mot = getDeltaMovement(); -+ move(net.minecraft.world.entity.MoverType.SELF, mot.multiply(speed, 0.5, speed)); -+ setDeltaMovement(mot.scale(0.9D)); -+ } -+ } -+ -+ @Override -+ public void onMount(Player rider) { -+ super.onMount(rider); -+ this.entityData.set(DATA_TARGETS.get(0), 0); -+ this.entityData.set(DATA_TARGETS.get(1), 0); -+ this.entityData.set(DATA_TARGETS.get(2), 0); -+ getNavigation().stopPathfinding(); -+ shootCooldown = 20; -+ } -+ -+ @Override -+ public boolean onClick(net.minecraft.world.InteractionHand hand) { -+ return shoot(getRider(), hand == net.minecraft.world.InteractionHand.MAIN_HAND ? new int[]{1} : new int[]{2}); -+ } -+ -+ public boolean shoot(@Nullable Player rider, int[] heads) { -+ if (shootCooldown > 0) { -+ return false; -+ } -+ -+ shootCooldown = 20; -+ if (rider == null) { -+ return false; -+ } -+ -+ org.bukkit.craftbukkit.entity.CraftHumanEntity player = rider.getBukkitEntity(); -+ if (!player.hasPermission("allow.special.wither")) { -+ return false; -+ } -+ -+ net.minecraft.world.phys.HitResult rayTrace = getRayTrace(120, net.minecraft.world.level.ClipContext.Fluid.NONE); -+ if (rayTrace == null) { -+ return false; -+ } -+ -+ Vec3 loc; -+ if (rayTrace.getType() == net.minecraft.world.phys.HitResult.Type.BLOCK) { -+ BlockPos pos = ((net.minecraft.world.phys.BlockHitResult) rayTrace).getBlockPos(); -+ loc = new Vec3(pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D); -+ } else if (rayTrace.getType() == net.minecraft.world.phys.HitResult.Type.ENTITY) { -+ Entity target = ((net.minecraft.world.phys.EntityHitResult) rayTrace).getEntity(); -+ loc = new Vec3(target.getX(), target.getY() + (target.getEyeHeight() / 2), target.getZ()); -+ } else { -+ org.bukkit.block.Block block = player.getTargetBlock(null, 120); -+ loc = new Vec3(block.getX() + 0.5D, block.getY() + 0.5D, block.getZ() + 0.5D); -+ } -+ -+ for (int head : heads) { -+ shoot(head, loc.x(), loc.y(), loc.z(), rider); -+ } -+ -+ return true; // handled -+ } -+ -+ public void shoot(int head, double x, double y, double z, Player rider) { -+ level.levelEvent(null, 1024, blockPosition(), 0); -+ double headX = getHeadX(head); -+ double headY = getHeadY(head); -+ double headZ = getHeadZ(head); -+ WitherSkull skull = new WitherSkull(level, this, x - headX, y - headY, z - headZ) { -+ @Override -+ public boolean canHitEntity(Entity target) { -+ // do not hit rider -+ return target != rider && super.canHitEntity(target); -+ } -+ }; -+ skull.setPosRaw(headX, headY, headZ); -+ level.addFreshEntity(skull); -+ } -+ // Purpur end -+ - @Override - protected void registerGoals() { -+ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(0, new WitherBoss.WitherDoNothingGoal()); - this.goalSelector.addGoal(2, new RangedAttackGoal(this, 1.0D, 40, 20.0F)); - this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0D)); - this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F)); - this.goalSelector.addGoal(7, new RandomLookAroundGoal(this)); -+ this.targetSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[0])); - if(this.level.paperConfig.fixWitherTargetingBug) this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 0, false, false, null)); // Paper - Fix MC-29274 - this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Mob.class, 0, false, false, WitherBoss.LIVING_ENTITY_SELECTOR)); -@@ -246,6 +349,16 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob - - @Override - protected void customServerAiStep() { -+ // Purpur start -+ if (getRider() != null) { -+ Vec3 mot = getDeltaMovement(); -+ setDeltaMovement(mot.x(), mot.y() + (getVerticalMot() > 0 ? 0.07D : 0.0D), mot.z()); -+ } -+ if (shootCooldown > 0) { -+ shootCooldown--; -+ } -+ // Purpur end -+ - int i; - - if (this.getInvulnerableTicks() > 0) { -@@ -553,7 +666,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob - } - - public static AttributeSupplier.Builder createAttributes() { -- return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 300.0D).add(Attributes.MOVEMENT_SPEED, 0.6000000238418579D).add(Attributes.FOLLOW_RANGE, 40.0D).add(Attributes.ARMOR, 4.0D); -+ return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 300.0D).add(Attributes.MOVEMENT_SPEED, 0.6000000238418579D).add(Attributes.FOLLOW_RANGE, 40.0D).add(Attributes.ARMOR, 4.0D).add(Attributes.FLYING_SPEED, 0.6D); // Purpur - } - - public float getHeadYRot(int headIndex) { -@@ -573,11 +686,11 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob - } - - public int getAlternativeTarget(int headIndex) { -- return (Integer) this.entityData.get((EntityDataAccessor) WitherBoss.DATA_TARGETS.get(headIndex)); -+ return getRider() != null ? 0 : this.entityData.get(WitherBoss.DATA_TARGETS.get(headIndex)); // Purpur - } - - public void setAlternativeTarget(int headIndex, int id) { -- this.entityData.set((EntityDataAccessor) WitherBoss.DATA_TARGETS.get(headIndex), id); -+ if (getRider() == null) this.entityData.set(WitherBoss.DATA_TARGETS.get(headIndex), id); // Purpur - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/monster/Blaze.java b/src/main/java/net/minecraft/world/entity/monster/Blaze.java -index a1bbe0c34bd5693f041dca9028a5a52b2ca71bc5..a5294012d432d5d1fce570a1eb1b1716a24522de 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Blaze.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Blaze.java -@@ -32,6 +32,7 @@ public class Blaze extends Monster { - - public Blaze(EntityType type, Level world) { - super(type, world); -+ this.moveControl = new net.pl3x.purpur.controller.FlyingWithSpacebarMoveControllerWASD(this, 0.3F); // Purpur - this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); - this.setPathfindingMalus(BlockPathTypes.LAVA, 8.0F); - this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, 0.0F); -@@ -39,19 +40,50 @@ public class Blaze extends Monster { - this.xpReward = 10; - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.blazeRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.blazeRidableInWater; -+ } -+ -+ @Override -+ public double getMaxY() { -+ return level.purpurConfig.blazeMaxY; -+ } -+ -+ @Override -+ public void travel(Vec3 vec3) { -+ super.travel(vec3); -+ if (getRider() != null && !onGround) { -+ float speed = (float) getAttributeValue(Attributes.FLYING_SPEED); -+ setSpeed(speed); -+ Vec3 mot = getDeltaMovement(); -+ move(net.minecraft.world.entity.MoverType.SELF, mot.multiply(speed, 1.0, speed)); -+ setDeltaMovement(mot.scale(0.9D)); -+ } -+ } -+ // Purpur end -+ - @Override - protected void registerGoals() { -+ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(4, new Blaze.BlazeAttackGoal(this)); - this.goalSelector.addGoal(5, new MoveTowardsRestrictionGoal(this, 1.0D)); - this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D, 0.0F)); - this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); - this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); -+ this.targetSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.targetSelector.addGoal(1, (new HurtByTargetGoal(this)).setAlertOthers()); - this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); - } - - public static AttributeSupplier.Builder createAttributes() { -- return Monster.createMonsterAttributes().add(Attributes.ATTACK_DAMAGE, 6.0D).add(Attributes.MOVEMENT_SPEED, (double)0.23F).add(Attributes.FOLLOW_RANGE, 48.0D); -+ return Monster.createMonsterAttributes().add(Attributes.ATTACK_DAMAGE, 6.0D).add(Attributes.MOVEMENT_SPEED, (double)0.23F).add(Attributes.FOLLOW_RANGE, 48.0D).add(Attributes.FLYING_SPEED, 0.6D); // Purpur - } - - @Override -@@ -106,6 +138,14 @@ public class Blaze extends Monster { - - @Override - protected void customServerAiStep() { -+ // Purpur start -+ if (getRider() != null) { -+ Vec3 mot = getDeltaMovement(); -+ setDeltaMovement(mot.x(), getVerticalMot() > 0 ? 0.07D : -0.07D, mot.z()); -+ return; -+ } -+ // Purpur end -+ - --this.nextHeightOffsetChangeTick; - if (this.nextHeightOffsetChangeTick <= 0) { - this.nextHeightOffsetChangeTick = 100; -diff --git a/src/main/java/net/minecraft/world/entity/monster/CaveSpider.java b/src/main/java/net/minecraft/world/entity/monster/CaveSpider.java -index d980b906d9206560741576fa4153c57212f307a0..dd05c5f35d78d1385f793f4e34333ff242d136e1 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/CaveSpider.java -+++ b/src/main/java/net/minecraft/world/entity/monster/CaveSpider.java -@@ -28,6 +28,18 @@ public class CaveSpider extends Spider { - return Spider.createAttributes().add(Attributes.MAX_HEALTH, 12.0D); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.caveSpiderRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.caveSpiderRidableInWater; -+ } -+ // Purpur end -+ - @Override - public boolean doHurtTarget(Entity target) { - if (super.doHurtTarget(target)) { -diff --git a/src/main/java/net/minecraft/world/entity/monster/Creeper.java b/src/main/java/net/minecraft/world/entity/monster/Creeper.java -index e8c36e8541f041a0d72a86f49ced2a3ce1549be0..1bf65519883585569a1acc780554505dc5d6c30b 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java -@@ -60,21 +60,89 @@ public class Creeper extends Monster implements PowerableMob { - public int maxSwell = 30; - public int explosionRadius = 3; - private int droppedSkulls; -+ // Purpur start -+ private int spacebarCharge = 0; -+ private int prevSpacebarCharge = 0; -+ private int powerToggleDelay = 0; -+ // Purpur end - - public Creeper(EntityType type, Level world) { - super(type, world); - } - -+ // Purpur start -+ @Override -+ public boolean isRidable() { -+ return level.purpurConfig.creeperRidable; -+ } -+ -+ @Override -+ public boolean rideableUnderWater() { -+ return level.purpurConfig.creeperRidableInWater; -+ } -+ -+ @Override -+ protected void customServerAiStep() { -+ if (powerToggleDelay > 0) { -+ powerToggleDelay--; -+ } -+ if (getRider() != null) { -+ if (getRider().getForwardMot() != 0 || getRider().getStrafeMot() != 0) { -+ spacebarCharge = 0; -+ setIgnited(false); -+ } -+ if (spacebarCharge == prevSpacebarCharge) { -+ spacebarCharge = 0; -+ } -+ prevSpacebarCharge = spacebarCharge; -+ } -+ super.customServerAiStep(); -+ } -+ -+ @Override -+ public void onMount(Player rider) { -+ super.onMount(rider); -+ setIgnited(false); -+ } -+ -+ @Override -+ public boolean onSpacebar() { -+ if (powerToggleDelay > 0) { -+ return true; // just toggled power, do not jump or ignite -+ } -+ spacebarCharge++; -+ if (spacebarCharge > maxSwell - 2) { -+ spacebarCharge = 0; -+ if (getRider() != null && getRider().getBukkitEntity().hasPermission("allow.powered.creeper")) { -+ powerToggleDelay = 20; -+ setPowered(!isPowered()); -+ setIgnited(false); -+ return true; -+ } -+ } -+ if (!isIgnited()) { -+ if (getRider() != null && getRider().getForwardMot() == 0 && getRider().getStrafeMot() == 0 && -+ getRider().getBukkitEntity().hasPermission("allow.special.creeper")) { -+ setIgnited(true); -+ return true; -+ } -+ } -+ return getForwardMot() == 0 && getStrafeMot() == 0; // do not jump if standing still -+ } -+ // Purpur end -+ - @Override - protected void registerGoals() { - this.goalSelector.addGoal(1, new FloatGoal(this)); - this.goalSelector.addGoal(2, new SwellGoal(this)); -+ this.goalSelector.addGoal(3, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Ocelot.class, 6.0F, 1.0D, 1.2D)); - this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Cat.class, 6.0F, 1.0D, 1.2D)); - this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0D, false)); - this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.8D)); - this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F)); - this.goalSelector.addGoal(6, new RandomLookAroundGoal(this)); -+ this.targetSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, true)); - this.targetSelector.addGoal(2, new HurtByTargetGoal(this, new Class[0])); - } -@@ -318,6 +386,7 @@ public class Creeper extends Monster implements PowerableMob { - com.destroystokyo.paper.event.entity.CreeperIgniteEvent event = new com.destroystokyo.paper.event.entity.CreeperIgniteEvent((org.bukkit.entity.Creeper) getBukkitEntity(), ignited); - if (event.callEvent()) { - this.entityData.set(Creeper.DATA_IS_IGNITED, event.isIgnited()); -+ if (!event.isIgnited()) setSwellDir(-1); // Purpur - } - } - // Paper end diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java index fdc01dee8a81f0376f3c0a154c4291d03ead7f8f..058f4e8729736f9650bb6b08e7aed28f9f78a89b 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Slime.java @@ -2939,10 +889,10 @@ index 74fc4fc2216cf82e1546ef3d567f2750b1240df1..c90dda3d62dab896f68481000c0b6db1 + } } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 361f7857e461578e90cb71e15027dadaf794cb69..9d261356c549a41e4bd676d5be60f6470501f0ae 100644 +index 361f7857e461578e90cb71e15027dadaf794cb69..5ad112baaa2dc0d56c0e7d36443eafd3ff0dc2c8 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -56,4 +56,532 @@ public class PurpurWorldConfig { +@@ -56,4 +56,530 @@ public class PurpurWorldConfig { PurpurConfig.config.addDefault("world-settings.default." + path, def); return PurpurConfig.config.getString("world-settings." + worldName + "." + path, PurpurConfig.config.getString("world-settings.default." + path)); } @@ -3419,11 +1369,9 @@ index 361f7857e461578e90cb71e15027dadaf794cb69..9d261356c549a41e4bd676d5be60f647 + + public boolean witherRidable = false; + public boolean witherRidableInWater = false; -+ public double witherMaxY = 256D; + private void witherSettings() { + witherRidable = getBoolean("mobs.wither.ridable", witherRidable); + witherRidableInWater = getBoolean("mobs.wither.ridable-in-water", witherRidableInWater); -+ witherMaxY = getDouble("mobs.wither.ridable-max-y", witherMaxY); + } + + public boolean witherSkeletonRidable = false; diff --git a/patches/server/0007-Llama-API.patch b/patches/server/0007-Llama-API.patch index caf105c3d..54835c6f2 100644 --- a/patches/server/0007-Llama-API.patch +++ b/patches/server/0007-Llama-API.patch @@ -25,7 +25,7 @@ index e037d618955de9a213a9cd90752b29d189faace4..34dec0a94840a8865f1d80857ec54a10 double d = this.llama.distanceToSqr(this.llama.getCaravanHead()); if (d > 676.0D) { diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java -index 0671185c358398fe0c4c1dbf4ede2f3e8c4794fb..31d965119b0d6481a50fbc237600c529aac0702d 100644 +index 5c31519193126b715105e1e83bb54f6a1681d19e..41b94ea6f3cc71b3521df8be15bf009404ce66d2 100644 --- a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java +++ b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java @@ -65,6 +65,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { @@ -36,7 +36,7 @@ index 0671185c358398fe0c4c1dbf4ede2f3e8c4794fb..31d965119b0d6481a50fbc237600c529 public Llama(EntityType type, Level world) { super(type, world); -@@ -134,7 +135,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { +@@ -95,7 +96,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { if (!this.inventory.getItem(1).isEmpty()) { nbt.put("DecorItem", this.inventory.getItem(1).save(new CompoundTag())); } @@ -45,7 +45,7 @@ index 0671185c358398fe0c4c1dbf4ede2f3e8c4794fb..31d965119b0d6481a50fbc237600c529 } @Override -@@ -146,6 +147,12 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { +@@ -107,6 +108,12 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { this.inventory.setItem(1, ItemStack.of(nbt.getCompound("DecorItem"))); } @@ -58,7 +58,7 @@ index 0671185c358398fe0c4c1dbf4ede2f3e8c4794fb..31d965119b0d6481a50fbc237600c529 this.updateContainerEquipment(); } -@@ -467,6 +474,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { +@@ -426,6 +433,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { public void leaveCaravan() { if (this.caravanHead != null) { @@ -66,7 +66,7 @@ index 0671185c358398fe0c4c1dbf4ede2f3e8c4794fb..31d965119b0d6481a50fbc237600c529 this.caravanHead.caravanTail = null; } -@@ -474,6 +482,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { +@@ -433,6 +441,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { } public void joinCaravan(Llama llama) { @@ -74,7 +74,7 @@ index 0671185c358398fe0c4c1dbf4ede2f3e8c4794fb..31d965119b0d6481a50fbc237600c529 this.caravanHead = llama; this.caravanHead.caravanTail = this; } -@@ -491,6 +500,13 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { +@@ -450,6 +459,13 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { return this.caravanHead; } diff --git a/patches/server/0011-LivingEntity-safeFallDistance.patch b/patches/server/0011-LivingEntity-safeFallDistance.patch index a8a0dbf88..cdd7f60d7 100644 --- a/patches/server/0011-LivingEntity-safeFallDistance.patch +++ b/patches/server/0011-LivingEntity-safeFallDistance.patch @@ -37,10 +37,10 @@ index e733c1e8f0b180bf1508e4f004124d44407f6c07..0fc358d5491900affb61545d89a788bb protected void playBlockFallSound() { diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java -index 919410ce27e7e42e297c2caba7d3d7c1b623aede..4dcacd1d156309abd29f48b9ac2d402395232e85 100644 +index ba58e066cca533dfed7610a730c4dd7423fe124d..ff032dd031360cd4022dd19e772176d72e3e1340 100644 --- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java +++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java -@@ -296,7 +296,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, +@@ -285,7 +285,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, @Override protected int calculateFallDamage(float fallDistance, float damageMultiplier) { diff --git a/patches/server/0027-Zombie-horse-naturally-spawn.patch b/patches/server/0027-Zombie-horse-naturally-spawn.patch index d7acb46c4..3a12232c7 100644 --- a/patches/server/0027-Zombie-horse-naturally-spawn.patch +++ b/patches/server/0027-Zombie-horse-naturally-spawn.patch @@ -42,10 +42,10 @@ index 900b30c9ba0d7b9e0b19c23c1eb5b75dbf2d7141..e09f031f08efa7ed5145566de459b044 LightningBolt entitylightning = (LightningBolt) EntityType.LIGHTNING_BOLT.create((net.minecraft.world.level.Level) this); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 983ad996bef9f05772f176357ab3f78fd330f8f4..e66fd35e16e152d18b511d727558b50d5071633f 100644 +index 97c0072bdd22ed0af5d7e0ade6b0a6dc40b003d4..eb96eeb82a3acb0c1342004016765a715689e7d4 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -653,9 +653,11 @@ public class PurpurWorldConfig { +@@ -651,9 +651,11 @@ public class PurpurWorldConfig { public boolean zombieHorseRidableInWater = false; public boolean zombieHorseCanSwim = false; diff --git a/patches/server/0028-Charged-creeper-naturally-spawn.patch b/patches/server/0028-Charged-creeper-naturally-spawn.patch index ec6f07f3e..7ee19d3ce 100644 --- a/patches/server/0028-Charged-creeper-naturally-spawn.patch +++ b/patches/server/0028-Charged-creeper-naturally-spawn.patch @@ -5,27 +5,59 @@ Subject: [PATCH] Charged creeper naturally spawn diff --git a/src/main/java/net/minecraft/world/entity/monster/Creeper.java b/src/main/java/net/minecraft/world/entity/monster/Creeper.java -index 1bf65519883585569a1acc780554505dc5d6c30b..f8fba694d53356036e302f66cfe92b15726242dc 100644 +index e8c36e8541f041a0d72a86f49ced2a3ce1549be0..27d8279b71f55ae711b0455bb4c5f1527a0e1ccb 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java +++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java -@@ -129,6 +129,15 @@ public class Creeper extends Monster implements PowerableMob { - } - return getForwardMot() == 0 && getStrafeMot() == 0; // do not jump if standing still +@@ -11,6 +11,7 @@ import net.minecraft.server.level.ServerLevel; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.util.Mth; ++import net.minecraft.world.DifficultyInstance; + import net.minecraft.world.InteractionHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; +@@ -20,7 +21,9 @@ import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.LightningBolt; + import net.minecraft.world.entity.LivingEntity; ++import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.PowerableMob; ++import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.AvoidEntityGoal; +@@ -38,10 +41,7 @@ import net.minecraft.world.entity.animal.goat.Goat; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +-import net.minecraft.world.level.Explosion; +-import net.minecraft.world.level.GameRules; +-import net.minecraft.world.level.ItemLike; +-import net.minecraft.world.level.Level; ++import net.minecraft.world.level.*; + import net.minecraft.world.level.gameevent.GameEvent; + + // CraftBukkit start +@@ -65,6 +65,17 @@ public class Creeper extends Monster implements PowerableMob { + super(type, world); } -+ + ++ // Purpur start + @Override -+ public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor world, net.minecraft.world.DifficultyInstance difficulty, net.minecraft.world.entity.MobSpawnType spawnReason, @Nullable net.minecraft.world.entity.SpawnGroupData entityData, @Nullable CompoundTag entityNbt) { ++ public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData entityData, @Nullable CompoundTag entityNbt) { + double chance = world.getMinecraftWorld().purpurConfig.creeperChargedChance; + if (chance > 0D && random.nextDouble() <= chance) { + setPowered(true); + } + return super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityNbt); + } - // Purpur end - ++ // Purpur end ++ @Override + protected void registerGoals() { + this.goalSelector.addGoal(1, new FloatGoal(this)); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index e66fd35e16e152d18b511d727558b50d5071633f..d2772e9d8cc9027994e98633594f20dc58a652cf 100644 +index eb96eeb82a3acb0c1342004016765a715689e7d4..a0a04f84ffceb2265e4dbdac22f544722e04bba7 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -180,9 +180,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0029-Rabbit-naturally-spawn-toast-and-killer.patch b/patches/server/0029-Rabbit-naturally-spawn-toast-and-killer.patch index bd71f0819..08f09d178 100644 --- a/patches/server/0029-Rabbit-naturally-spawn-toast-and-killer.patch +++ b/patches/server/0029-Rabbit-naturally-spawn-toast-and-killer.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Rabbit naturally spawn toast and killer diff --git a/src/main/java/net/minecraft/world/entity/animal/Rabbit.java b/src/main/java/net/minecraft/world/entity/animal/Rabbit.java -index 29551a3b87f06c5876de5fda80615acf6c1f4764..8f99b4c28539c7c5a4951d7a3b82b01b77082794 100644 +index 4a60afbb79ffb86d3c41b48d923ca8b3beca1c54..384f8abd0fd12906956d1459115f48738cc6e16d 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Rabbit.java +++ b/src/main/java/net/minecraft/world/entity/animal/Rabbit.java -@@ -421,7 +421,11 @@ public class Rabbit extends Animal { +@@ -365,7 +365,11 @@ public class Rabbit extends Animal { if (!this.hasCustomName()) { this.setCustomName(new TranslatableComponent(Util.makeDescriptionId("entity", Rabbit.KILLER_BUNNY))); } @@ -20,7 +20,7 @@ index 29551a3b87f06c5876de5fda80615acf6c1f4764..8f99b4c28539c7c5a4951d7a3b82b01b this.entityData.set(Rabbit.DATA_TYPE_ID, rabbitType); } -@@ -442,6 +446,16 @@ public class Rabbit extends Animal { +@@ -386,6 +390,16 @@ public class Rabbit extends Animal { } private int getRandomRabbitType(LevelAccessor world) { @@ -38,7 +38,7 @@ index 29551a3b87f06c5876de5fda80615acf6c1f4764..8f99b4c28539c7c5a4951d7a3b82b01b int i = this.random.nextInt(100); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index d2772e9d8cc9027994e98633594f20dc58a652cf..c2a43e6f48da724ff737fec8d3bce0a3611b2465 100644 +index a0a04f84ffceb2265e4dbdac22f544722e04bba7..684034f36ce0653a39392fa78a019bea1560538d 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -456,9 +456,13 @@ public class PurpurWorldConfig { diff --git a/patches/server/0032-Tulips-change-fox-type.patch b/patches/server/0032-Tulips-change-fox-type.patch index 931011fac..d4555879b 100644 --- a/patches/server/0032-Tulips-change-fox-type.patch +++ b/patches/server/0032-Tulips-change-fox-type.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Tulips change fox type diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java -index 6cc8f6ef75e4b8b4282e4f664a83ce6491042df1..97101e7e0442417b57e15d6ec76d2a4c88862c81 100644 +index 31f4e4a93ea5fd3ffe7e60dff2e2a9642b51daa2..26470e4e07387fcf0c02c1f8845950eca4140a56 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Fox.java +++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java @@ -34,6 +34,7 @@ import net.minecraft.tags.Tag; @@ -24,7 +24,7 @@ index 6cc8f6ef75e4b8b4282e4f664a83ce6491042df1..97101e7e0442417b57e15d6ec76d2a4c import net.minecraft.world.level.pathfinder.BlockPathTypes; import net.minecraft.world.phys.Vec3; -@@ -363,6 +365,11 @@ public class Fox extends Animal { +@@ -328,6 +330,11 @@ public class Fox extends Animal { } private void setTargetGoals() { @@ -36,7 +36,7 @@ index 6cc8f6ef75e4b8b4282e4f664a83ce6491042df1..97101e7e0442417b57e15d6ec76d2a4c if (this.getFoxType() == Fox.Type.RED) { this.targetSelector.addGoal(4, this.landTargetGoal); this.targetSelector.addGoal(4, this.turtleEggTargetGoal); -@@ -395,6 +402,7 @@ public class Fox extends Animal { +@@ -360,6 +367,7 @@ public class Fox extends Animal { public void setFoxType(Fox.Type type) { this.entityData.set(Fox.DATA_TYPE_ID, type.getId()); @@ -44,7 +44,7 @@ index 6cc8f6ef75e4b8b4282e4f664a83ce6491042df1..97101e7e0442417b57e15d6ec76d2a4c } List getTrustedUUIDs() { -@@ -725,6 +733,29 @@ public class Fox extends Animal { +@@ -690,6 +698,29 @@ public class Fox extends Animal { return this.getTrustedUUIDs().contains(uuid); } @@ -75,7 +75,7 @@ index 6cc8f6ef75e4b8b4282e4f664a83ce6491042df1..97101e7e0442417b57e15d6ec76d2a4c // Paper start - Cancellable death event protected org.bukkit.event.entity.EntityDeathEvent dropAllDeathLoot(DamageSource source) { diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index c2a43e6f48da724ff737fec8d3bce0a3611b2465..b949480d139ce6eb923c3efe788ac7a547f90c96 100644 +index 684034f36ce0653a39392fa78a019bea1560538d..376167ee0f0a029253c8e6988b430aab0ce1c21a 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -247,9 +247,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0033-Breedable-Polar-Bears.patch b/patches/server/0033-Breedable-Polar-Bears.patch index 924421325..83e395437 100644 --- a/patches/server/0033-Breedable-Polar-Bears.patch +++ b/patches/server/0033-Breedable-Polar-Bears.patch @@ -5,14 +5,36 @@ Subject: [PATCH] Breedable Polar Bears diff --git a/src/main/java/net/minecraft/world/entity/animal/PolarBear.java b/src/main/java/net/minecraft/world/entity/animal/PolarBear.java -index dc6bc8f10d147cb1d0e5c69b6f6df63b0e8d4531..652e8a43af5830a9bc5a6bdd00ebec5a6e07dc3c 100644 +index 0694cd0b994ee595adca43c988485e6dc13c7244..583bb80059b9351d27d15859b1687dd817ba165e 100644 --- a/src/main/java/net/minecraft/world/entity/animal/PolarBear.java +++ b/src/main/java/net/minecraft/world/entity/animal/PolarBear.java -@@ -88,6 +88,28 @@ public class PolarBear extends Animal implements NeutralMob { - } - return false; +@@ -32,6 +32,7 @@ import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; ++import net.minecraft.world.entity.ai.goal.BreedGoal; + import net.minecraft.world.entity.ai.goal.FloatGoal; + import net.minecraft.world.entity.ai.goal.FollowParentGoal; + import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; +@@ -39,11 +40,13 @@ import net.minecraft.world.entity.ai.goal.MeleeAttackGoal; + import net.minecraft.world.entity.ai.goal.PanicGoal; + import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal; + import net.minecraft.world.entity.ai.goal.RandomStrollGoal; ++import net.minecraft.world.entity.ai.goal.TemptGoal; + import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal; + import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; + import net.minecraft.world.entity.ai.goal.target.ResetUniversalAngerTargetGoal; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.item.crafting.Ingredient; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.ServerLevelAccessor; +@@ -66,6 +69,30 @@ public class PolarBear extends Animal implements NeutralMob { + super(type, world); } -+ + ++ // Purpur start + @Override + public boolean canMate(Animal other) { + if (other == this) { @@ -34,33 +56,35 @@ index dc6bc8f10d147cb1d0e5c69b6f6df63b0e8d4531..652e8a43af5830a9bc5a6bdd00ebec5a + return this.isInLove() && bear.isInLove(); + } + } - // Purpur end - ++ // Purpur end ++ @Override -@@ -97,7 +119,7 @@ public class PolarBear extends Animal implements NeutralMob { + public AgeableMob getBreedOffspring(ServerLevel world, AgeableMob entity) { + return EntityType.POLAR_BEAR.create(world); +@@ -73,7 +100,7 @@ public class PolarBear extends Animal implements NeutralMob { @Override public boolean isFood(ItemStack stack) { - return false; -+ return level.purpurConfig.polarBearBreedableItem != null && stack.getItem() == level.purpurConfig.polarBearBreedableItem; // Purpur ++ return level.purpurConfig.polarBearBreedableItem != null && stack.getItem() == level.purpurConfig.polarBearBreedableItem; // Purpur; } @Override -@@ -107,6 +129,12 @@ public class PolarBear extends Animal implements NeutralMob { - this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur +@@ -82,6 +109,12 @@ public class PolarBear extends Animal implements NeutralMob { + this.goalSelector.addGoal(0, new FloatGoal(this)); this.goalSelector.addGoal(1, new PolarBear.PolarBearMeleeAttackGoal()); this.goalSelector.addGoal(1, new PolarBear.PolarBearPanicGoal()); + // Purpur start + if (level.purpurConfig.polarBearBreedableItem != null) { -+ this.goalSelector.addGoal(2, new net.minecraft.world.entity.ai.goal.BreedGoal(this, 1.0D)); -+ this.goalSelector.addGoal(3, new net.minecraft.world.entity.ai.goal.TemptGoal(this, 1.0D, net.minecraft.world.item.crafting.Ingredient.of(level.purpurConfig.polarBearBreedableItem), false)); ++ this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); ++ this.goalSelector.addGoal(3, new TemptGoal(this, 1.0D, Ingredient.of(level.purpurConfig.polarBearBreedableItem), false)); + } + // Purpur end this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.25D)); this.goalSelector.addGoal(5, new RandomStrollGoal(this, 1.0D)); this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F)); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index b949480d139ce6eb923c3efe788ac7a547f90c96..3981e492b61d552735433fae05e13d1fe87637db 100644 +index 376167ee0f0a029253c8e6988b430aab0ce1c21a..60d010fdbe86fe267b038f36aae0385121b60807 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -446,9 +446,14 @@ public class PurpurWorldConfig { diff --git a/patches/server/0034-Chickens-can-retaliate.patch b/patches/server/0034-Chickens-can-retaliate.patch index 4cd5735de..96007c788 100644 --- a/patches/server/0034-Chickens-can-retaliate.patch +++ b/patches/server/0034-Chickens-can-retaliate.patch @@ -5,26 +5,38 @@ Subject: [PATCH] Chickens can retaliate diff --git a/src/main/java/net/minecraft/world/entity/animal/Chicken.java b/src/main/java/net/minecraft/world/entity/animal/Chicken.java -index 771e55cceaf17167c00554b1be7043a4cb3efb7e..11bdc951087d8630a26f398f36a56a9e7c043d70 100644 +index 8460bed561c09a647f6e0209f7c5448e5a42b281..56aee819372d4baacf73c345603ce889b3a60b52 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Chicken.java +++ b/src/main/java/net/minecraft/world/entity/animal/Chicken.java -@@ -62,19 +62,34 @@ public class Chicken extends Animal { - public boolean rideableUnderWater() { - return level.purpurConfig.chickenRidableInWater; +@@ -20,10 +20,12 @@ import net.minecraft.world.entity.ai.goal.BreedGoal; + import net.minecraft.world.entity.ai.goal.FloatGoal; + import net.minecraft.world.entity.ai.goal.FollowParentGoal; + import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; ++import net.minecraft.world.entity.ai.goal.MeleeAttackGoal; + import net.minecraft.world.entity.ai.goal.PanicGoal; + import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal; + import net.minecraft.world.entity.ai.goal.TemptGoal; + import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal; ++import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +@@ -52,16 +54,33 @@ public class Chicken extends Animal { + this.setPathfindingMalus(BlockPathTypes.WATER, 0.0F); } -+ + ++ // Purpur start + @Override + protected void initAttributes() { + if (level.purpurConfig.chickenRetaliate) { + this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(2.0D); + } + } - // Purpur end - ++ // Purpur end ++ @Override protected void registerGoals() { this.goalSelector.addGoal(0, new FloatGoal(this)); - this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(1, new PanicGoal(this, 1.4D)); + // this.goalSelector.addGoal(1, new PanicGoal(this, 1.4D)); // Purpur - moved down this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); @@ -35,8 +47,8 @@ index 771e55cceaf17167c00554b1be7043a4cb3efb7e..11bdc951087d8630a26f398f36a56a9e this.goalSelector.addGoal(7, new RandomLookAroundGoal(this)); + // Purpur start + if (level.purpurConfig.chickenRetaliate) { -+ this.goalSelector.addGoal(1, new net.minecraft.world.entity.ai.goal.MeleeAttackGoal(this, 1.0D, false)); -+ this.targetSelector.addGoal(1, new net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal(this)); ++ this.goalSelector.addGoal(1, new MeleeAttackGoal(this, 1.0D, false)); ++ this.targetSelector.addGoal(1, new HurtByTargetGoal(this)); + } else { + this.goalSelector.addGoal(1, new PanicGoal(this, 1.4D)); + } @@ -44,7 +56,7 @@ index 771e55cceaf17167c00554b1be7043a4cb3efb7e..11bdc951087d8630a26f398f36a56a9e } @Override -@@ -83,7 +98,7 @@ public class Chicken extends Animal { +@@ -70,7 +89,7 @@ public class Chicken extends Animal { } public static AttributeSupplier.Builder createAttributes() { @@ -54,7 +66,7 @@ index 771e55cceaf17167c00554b1be7043a4cb3efb7e..11bdc951087d8630a26f398f36a56a9e @Override diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 3981e492b61d552735433fae05e13d1fe87637db..5154e14c88cf79c8da3290ff945fac0361e9e7c5 100644 +index 60d010fdbe86fe267b038f36aae0385121b60807..2147f01e466add9822f03bfe2d8d3db75ab7e1cd 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -161,9 +161,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0039-Fix-cow-rotation-when-shearing-mooshroom.patch b/patches/server/0039-Fix-cow-rotation-when-shearing-mooshroom.patch index b011cf0a6..22340d374 100644 --- a/patches/server/0039-Fix-cow-rotation-when-shearing-mooshroom.patch +++ b/patches/server/0039-Fix-cow-rotation-when-shearing-mooshroom.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix cow rotation when shearing mooshroom diff --git a/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java -index 0e066782ee09bb5626715bcc500bc04f2252bc2e..00f9553c5c653517b3e0c1c7d6b2ec4b7bd34b59 100644 +index d9fb3df35de94ae5abbb86ace0328bbe6f5403b3..96f7ab847d05f461d4771a3fefbd32cab6366afa 100644 --- a/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java +++ b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java -@@ -187,7 +187,13 @@ public class MushroomCow extends Cow implements Shearable { +@@ -175,7 +175,13 @@ public class MushroomCow extends Cow implements Shearable { entitycow.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); entitycow.setHealth(this.getHealth()); diff --git a/patches/server/0040-Pigs-give-saddle-back.patch b/patches/server/0040-Pigs-give-saddle-back.patch index 9e2537962..1d5bf6d36 100644 --- a/patches/server/0040-Pigs-give-saddle-back.patch +++ b/patches/server/0040-Pigs-give-saddle-back.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Pigs give saddle back diff --git a/src/main/java/net/minecraft/world/entity/animal/Pig.java b/src/main/java/net/minecraft/world/entity/animal/Pig.java -index 80c8ceda47bf8b3ff370f89a61aa01869d606ee6..ff3f8ba62eb086fbb007853535aafd085578ea21 100644 +index 2c95b6eddfe46e5d2ad495bfc86ccc24ae75e704..8a99b04e8179a640a289c4853777aa88c725216a 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Pig.java +++ b/src/main/java/net/minecraft/world/entity/animal/Pig.java -@@ -168,6 +168,18 @@ public class Pig extends Animal implements ItemSteerable, Saddleable { +@@ -155,6 +155,18 @@ public class Pig extends Animal implements ItemSteerable, Saddleable { if (!flag && this.isSaddled() && !this.isVehicle() && !player.isSecondaryUseActive()) { if (!this.level.isClientSide) { @@ -28,7 +28,7 @@ index 80c8ceda47bf8b3ff370f89a61aa01869d606ee6..ff3f8ba62eb086fbb007853535aafd08 } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 0c7463c1d5c894c2d2bc9b6e422432e086a01446..84521916de0ce95333e95f458aac2a98e2ca1db0 100644 +index 557fa562b92a536aed85cca861899dd6c43a16b9..0c16976fd79d91794f90212efca94677ea9e406c 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -433,9 +433,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0041-Snowman-drop-and-put-back-pumpkin.patch b/patches/server/0041-Snowman-drop-and-put-back-pumpkin.patch index 908efa4ae..8e9a4e3e1 100644 --- a/patches/server/0041-Snowman-drop-and-put-back-pumpkin.patch +++ b/patches/server/0041-Snowman-drop-and-put-back-pumpkin.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Snowman drop and put back pumpkin diff --git a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java -index a76f3c1c409dc96f7033be8a7eeb06617053735b..06b6afe0724b2738b350cc671bb3cb2570b1dbad 100644 +index 2631f08496c8e45874b22760b559a91b7b2bf415..226cadfc5f109b8f5060b5147034ac273f14133d 100644 --- a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java +++ b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java -@@ -179,6 +179,14 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM +@@ -164,6 +164,14 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM } return InteractionResult.sidedSuccess(this.level.isClientSide); @@ -19,11 +19,11 @@ index a76f3c1c409dc96f7033be8a7eeb06617053735b..06b6afe0724b2738b350cc671bb3cb25 + itemstack.shrink(1); + } + return InteractionResult.SUCCESS; -+ // Purpur end ++ // Purpur end } else { - return tryRide(player, hand); // Purpur + return InteractionResult.PASS; } -@@ -189,6 +197,7 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM +@@ -174,6 +182,7 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM this.level.playSound((Player) null, (Entity) this, SoundEvents.SNOW_GOLEM_SHEAR, shearedSoundCategory, 1.0F, 1.0F); if (!this.level.isClientSide()) { this.setPumpkin(false); @@ -32,7 +32,7 @@ index a76f3c1c409dc96f7033be8a7eeb06617053735b..06b6afe0724b2738b350cc671bb3cb25 } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 84521916de0ce95333e95f458aac2a98e2ca1db0..6759bc46553d6fedb90597d73935d6255dbe5240 100644 +index 0c16976fd79d91794f90212efca94677ea9e406c..72a67a421229d208472ad05edca8020a007d9b9d 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -546,10 +546,14 @@ public class PurpurWorldConfig { diff --git a/patches/server/0042-Ender-dragon-always-drop-full-exp.patch b/patches/server/0042-Ender-dragon-always-drop-full-exp.patch index a217c6f30..142bc520f 100644 --- a/patches/server/0042-Ender-dragon-always-drop-full-exp.patch +++ b/patches/server/0042-Ender-dragon-always-drop-full-exp.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Ender dragon always drop full exp diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -index a1a64591e6a6fb8a4550b91f89e3cdbd35c6d249..3fd2d29e756d35a25e0cdd2ef10a5f1f48c230c0 100644 +index c98202092752a9015aaf95bd1471135b88e84425..682b532967a501e21df93c28c4ee4b59eed073a7 100644 --- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -@@ -704,7 +704,7 @@ public class EnderDragon extends Mob implements Enemy { +@@ -633,7 +633,7 @@ public class EnderDragon extends Mob implements Enemy { boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT); short short0 = 500; @@ -18,7 +18,7 @@ index a1a64591e6a6fb8a4550b91f89e3cdbd35c6d249..3fd2d29e756d35a25e0cdd2ef10a5f1f } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 6759bc46553d6fedb90597d73935d6255dbe5240..6d88e8011add9c54470ab122aee325764e22bb2f 100644 +index 72a67a421229d208472ad05edca8020a007d9b9d..7b9c11cf47d022861d9a2b390006c4c841e7e9cd 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -233,10 +233,12 @@ public class PurpurWorldConfig { diff --git a/patches/server/0054-Add-wither-skeleton-takes-wither-damage-option.patch b/patches/server/0054-Add-wither-skeleton-takes-wither-damage-option.patch index dce102a52..0c2aaa2ff 100644 --- a/patches/server/0054-Add-wither-skeleton-takes-wither-damage-option.patch +++ b/patches/server/0054-Add-wither-skeleton-takes-wither-damage-option.patch @@ -17,10 +17,10 @@ index 033d6389e4b7d986fc63abd67e325b68a6132824..f290c7b50c48b798697c49c738700457 } } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index b811b3db05e1bcc0fe5d641c6fa81cb4b1db9186..aa6e3b192fe80339df00c909d101449023d8f71f 100644 +index c45cfc3802940c15e9c2f2102a12741708bcc6ad..42f83dc3780b655f30b841efe3796f928fc805d5 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -747,9 +747,11 @@ public class PurpurWorldConfig { +@@ -745,9 +745,11 @@ public class PurpurWorldConfig { public boolean witherSkeletonRidable = false; public boolean witherSkeletonRidableInWater = false; diff --git a/patches/server/0057-Add-enderman-and-creeper-griefing-controls.patch b/patches/server/0057-Add-enderman-and-creeper-griefing-controls.patch index 428e8263a..dafd5d9c8 100644 --- a/patches/server/0057-Add-enderman-and-creeper-griefing-controls.patch +++ b/patches/server/0057-Add-enderman-and-creeper-griefing-controls.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add enderman and creeper griefing controls diff --git a/src/main/java/net/minecraft/world/entity/monster/Creeper.java b/src/main/java/net/minecraft/world/entity/monster/Creeper.java -index f8fba694d53356036e302f66cfe92b15726242dc..72edd66a7e0b46b9575982210d8c9af03310c8d2 100644 +index 27d8279b71f55ae711b0455bb4c5f1527a0e1ccb..689efb1a80a93d573cb109905105434281eba7d3 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java +++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java -@@ -336,7 +336,7 @@ public class Creeper extends Monster implements PowerableMob { +@@ -270,7 +270,7 @@ public class Creeper extends Monster implements PowerableMob { public void explodeCreeper() { if (!this.level.isClientSide) { @@ -38,7 +38,7 @@ index a39f4a1585ba888d27588a86130f6dae24f5a71b..b9cc542db0b5b9f7710c2f747cb9a4ed } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 7be145b284b0e618e9f52645a1e81c30e91ed186..f9756ee33ccfb011bda5c8b923d237d43e3a4093 100644 +index 0f5560701ba2e2d64c72a2d0469176fd815bec6d..cf889198f249c58b82019ba2a6c02526f26e2dfa 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -284,10 +284,12 @@ public class PurpurWorldConfig { diff --git a/patches/server/0075-Configurable-jockey-options.patch b/patches/server/0075-Configurable-jockey-options.patch index 3d8aeeb96..674a528e6 100644 --- a/patches/server/0075-Configurable-jockey-options.patch +++ b/patches/server/0075-Configurable-jockey-options.patch @@ -184,7 +184,7 @@ index 233b390541acddcf815db4a8f299496eaea4f758..a50191aac887dffd3a7930455cb222fa public void setPersistentAngerTarget(@Nullable UUID uuid) { this.persistentAngerTarget = uuid; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 0453764a9b47e3997aa32cda489e7f71d94b7e04..87f9ad516e8dd0c92b08c9054e086d8315c87c41 100644 +index aa984c2eebf2529e0be42b01ec7678d1f5157e0d..e39e1ff19f49b093ae27a98cba280ad2643df7a2 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -399,9 +399,15 @@ public class PurpurWorldConfig { @@ -219,7 +219,7 @@ index 0453764a9b47e3997aa32cda489e7f71d94b7e04..87f9ad516e8dd0c92b08c9054e086d83 } public boolean illusionerRidable = false; -@@ -879,9 +891,15 @@ public class PurpurWorldConfig { +@@ -877,9 +889,15 @@ public class PurpurWorldConfig { public boolean zombieRidable = false; public boolean zombieRidableInWater = false; @@ -235,7 +235,7 @@ index 0453764a9b47e3997aa32cda489e7f71d94b7e04..87f9ad516e8dd0c92b08c9054e086d83 } public boolean zombieHorseRidableInWater = false; -@@ -895,15 +913,27 @@ public class PurpurWorldConfig { +@@ -893,15 +911,27 @@ public class PurpurWorldConfig { public boolean zombieVillagerRidable = false; public boolean zombieVillagerRidableInWater = false; diff --git a/patches/server/0096-Add-option-to-disable-dolphin-treasure-searching.patch b/patches/server/0096-Add-option-to-disable-dolphin-treasure-searching.patch index 880ea29ef..70be3d37b 100644 --- a/patches/server/0096-Add-option-to-disable-dolphin-treasure-searching.patch +++ b/patches/server/0096-Add-option-to-disable-dolphin-treasure-searching.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add option to disable dolphin treasure searching diff --git a/src/main/java/net/minecraft/world/entity/animal/Dolphin.java b/src/main/java/net/minecraft/world/entity/animal/Dolphin.java -index 2300abc4e80449e6b92992f6fb8cfe8e99dea351..12a602a4a3b3e883ed04621fe627feb146f8afb9 100644 +index f3093815066e6881a2bb638ae4643f69374450b3..868a44fa2c54c43ed3dc3e3c346810588081ec1d 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Dolphin.java +++ b/src/main/java/net/minecraft/world/entity/animal/Dolphin.java -@@ -492,6 +492,7 @@ public class Dolphin extends WaterAnimal { +@@ -417,6 +417,7 @@ public class Dolphin extends WaterAnimal { @Override public boolean canUse() { @@ -17,7 +17,7 @@ index 2300abc4e80449e6b92992f6fb8cfe8e99dea351..12a602a4a3b3e883ed04621fe627feb1 } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index fff9679bfc715e8df5f88c2850c9623e1eef270f..1ca413f7a6cc2d445a2b026e7266919880692575 100644 +index 8797f781b97cece949dfb1014470f164503e61c4..5bead011214ca37dc59efafce845285ab07c409e 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -465,11 +465,13 @@ public class PurpurWorldConfig { diff --git a/patches/server/0098-Stop-squids-floating-on-top-of-water.patch b/patches/server/0098-Stop-squids-floating-on-top-of-water.patch index 627318e63..6926c16d0 100644 --- a/patches/server/0098-Stop-squids-floating-on-top-of-water.patch +++ b/patches/server/0098-Stop-squids-floating-on-top-of-water.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Stop squids floating on top of water diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 73d1efb6eb6a96368db57f316867cfc027159056..f9d8d5ef1ca960324351fa1151f79906950845b3 100644 +index 3eebc432befec2223e487a6bd48f30d2160feb0a..1950cd258f69f9c9430cda9ddd479277cc0fb6c9 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -3632,11 +3632,17 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n @@ -28,22 +28,32 @@ index 73d1efb6eb6a96368db57f316867cfc027159056..f9d8d5ef1ca960324351fa1151f79906 int j = Mth.ceil(axisalignedbb.maxX); int k = Mth.floor(axisalignedbb.minY); diff --git a/src/main/java/net/minecraft/world/entity/animal/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java -index 0a744855f24ac54b22bc474a1c903da7af656364..d6e35d1fec3eee80a7eafaa1997fee16f6ef5d04 100644 +index 56838c9f214c0f75041e75c45ad1a0c72fcacc66..8c9454612e71f1d1a82c6a13c7788dd9b892fedc 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Squid.java +++ b/src/main/java/net/minecraft/world/entity/animal/Squid.java -@@ -74,6 +74,12 @@ public class Squid extends WaterAnimal { - vector.setX(cos * x - sine * z); - vector.setZ(sine * x + cos * z); +@@ -29,6 +29,7 @@ import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.material.FluidState; ++import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + + public class Squid extends WaterAnimal { +@@ -54,6 +55,14 @@ public class Squid extends WaterAnimal { + this.tentacleSpeed = 1.0F / (this.random.nextFloat() + 1.0F) * 0.2F; } -+ + ++ // Purpur start + @Override -+ public net.minecraft.world.phys.AABB getAxisForFluidCheck() { ++ public AABB getAxisForFluidCheck() { + // Stops squids from floating just over the water + return this.getBoundingBox().deflate(0.001D).offsetY(level.purpurConfig.squidOffsetWaterCheck); + } - // Purpur end - ++ // Purpur end ++ @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new Squid.SquidRandomMovementGoal(this)); diff --git a/src/main/java/net/minecraft/world/phys/AABB.java b/src/main/java/net/minecraft/world/phys/AABB.java index 4eeb186231551a9df453ec9d6a8a9dc9f8835464..1e184724e112b28ff4abb6ecf5d564c260e795ba 100644 --- a/src/main/java/net/minecraft/world/phys/AABB.java @@ -60,7 +70,7 @@ index 4eeb186231551a9df453ec9d6a8a9dc9f8835464..1e184724e112b28ff4abb6ecf5d564c2 + // Purpur } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 1ca413f7a6cc2d445a2b026e7266919880692575..6e33bee4f01138bc0b553a318e87e3b6c6e0966d 100644 +index 5bead011214ca37dc59efafce845285ab07c409e..a339f842ec00253adc668fbb2b65c0513f23163a 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -871,9 +871,11 @@ public class PurpurWorldConfig { diff --git a/patches/server/0103-Customizable-wither-health-and-healing.patch b/patches/server/0103-Customizable-wither-health-and-healing.patch index f33a41cb4..cd9dde07c 100644 --- a/patches/server/0103-Customizable-wither-health-and-healing.patch +++ b/patches/server/0103-Customizable-wither-health-and-healing.patch @@ -6,22 +6,24 @@ Subject: [PATCH] Customizable wither health and healing Adds the ability to customize the health of the wither, as well as the amount that it heals, and how often. diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -index 0b1f6fad51a985ebe4ccebde12a1db9e12a57bc0..a91480bfecd17ef45e3380c726a42cd7534f07ae 100644 +index 1c8f6863b976cfcb559de9b3e3cf9292831166ee..7858e97db83085721310f7c9e35abe0b944b3b1f 100644 --- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -@@ -196,6 +196,11 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob - skull.setPosRaw(headX, headY, headZ); - level.addFreshEntity(skull); +@@ -97,6 +97,13 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob + this.xpReward = 50; } -+ + ++ // Purpur start + @Override + public void initAttributes() { + this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(level.purpurConfig.witherMaxHealth); + } - // Purpur end - ++ // Purpur end ++ @Override -@@ -401,7 +406,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob + protected void registerGoals() { + this.goalSelector.addGoal(0, new WitherBoss.WitherDoNothingGoal()); +@@ -288,7 +295,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob this.setInvulnerableTicks(i); if (this.tickCount % 10 == 0) { @@ -30,7 +32,7 @@ index 0b1f6fad51a985ebe4ccebde12a1db9e12a57bc0..a91480bfecd17ef45e3380c726a42cd7 } } else { -@@ -494,8 +499,10 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob +@@ -381,8 +388,10 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob } } @@ -44,20 +46,19 @@ index 0b1f6fad51a985ebe4ccebde12a1db9e12a57bc0..a91480bfecd17ef45e3380c726a42cd7 this.bossEvent.setProgress(this.getHealth() / this.getMaxHealth()); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index ae46aafd1a19e183e9a77fec8c0556a35c70c521..be3b2cc6fb2f8f01e38fb4a47324c825fee2aee7 100644 +index a6a6b766b5dc5b3743aecd0a2c8021d04df1d8d2..2681463ae89ea4e0746425114feb24aed0f34cb3 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -993,10 +993,21 @@ public class PurpurWorldConfig { +@@ -992,9 +992,20 @@ public class PurpurWorldConfig { + public boolean witherRidable = false; public boolean witherRidableInWater = false; - public double witherMaxY = 256D; + public float witherHealthRegenAmount = 1.0f; + public int witherHealthRegenDelay = 20; + public double witherMaxHealth = 300.0D; private void witherSettings() { witherRidable = getBoolean("mobs.wither.ridable", witherRidable); witherRidableInWater = getBoolean("mobs.wither.ridable-in-water", witherRidableInWater); - witherMaxY = getDouble("mobs.wither.ridable-max-y", witherMaxY); + witherHealthRegenAmount = (float) getDouble("mobs.wither.health-regen-amount", witherHealthRegenAmount); + witherHealthRegenDelay = getInt("mobs.wither.health-regen-delay", witherHealthRegenDelay); + if (PurpurConfig.version < 8) { diff --git a/patches/server/0107-Add-option-to-disable-zombie-aggressiveness-towards-.patch b/patches/server/0107-Add-option-to-disable-zombie-aggressiveness-towards-.patch index ea80d354d..743dd6b2e 100644 --- a/patches/server/0107-Add-option-to-disable-zombie-aggressiveness-towards-.patch +++ b/patches/server/0107-Add-option-to-disable-zombie-aggressiveness-towards-.patch @@ -71,10 +71,10 @@ index 747f872e0c9eef620f7713e674304e8f47738b1c..0f0df28c0d382cca5dc0556e03d7d465 this.targetSelector.addGoal(5, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, true, false, Turtle.BABY_ON_LAND_SELECTOR)); } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 1d55be36c8d075b48db1862e63bc28bbabad3a18..2c963f72caff78488ceb2a43abbad18013e1433f 100644 +index 53bda6f49386eb606ca259519f1494e3c5f144a5..cd1373f113f434aa0d3d3ea07096095dc99dbc18 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -1095,12 +1095,14 @@ public class PurpurWorldConfig { +@@ -1093,12 +1093,14 @@ public class PurpurWorldConfig { public boolean zombieJockeyOnlyBaby = true; public double zombieJockeyChance = 0.05D; public boolean zombieJockeyTryExistingChickens = true; diff --git a/patches/server/0108-Persistent-TileEntity-Lore-and-DisplayName.patch b/patches/server/0108-Persistent-TileEntity-Lore-and-DisplayName.patch new file mode 100644 index 000000000..9bd0bc6b5 --- /dev/null +++ b/patches/server/0108-Persistent-TileEntity-Lore-and-DisplayName.patch @@ -0,0 +1,210 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> +Date: Wed, 30 Sep 2020 14:32:46 -0700 +Subject: [PATCH] Persistent TileEntity Lore and DisplayName + +Makes it so that when a TileEntity is placed in the world and then broken, +the dropped ItemStack retains any original custom display name/lore. + +diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java +index 44b28773fe8e79931e738d493bd9405e0ee3dca9..f5cae6d2e811bc8594284ad425622773cd04f3e5 100644 +--- a/src/main/java/net/minecraft/world/item/BlockItem.java ++++ b/src/main/java/net/minecraft/world/item/BlockItem.java +@@ -133,7 +133,24 @@ public class BlockItem extends Item { + } + + protected boolean updateCustomBlockEntityTag(BlockPos pos, Level world, @Nullable Player player, ItemStack stack, BlockState state) { +- return BlockItem.updateCustomBlockEntityTag(world, player, pos, stack); ++ // Purpur start ++ boolean handled = updateCustomBlockEntityTag(world, player, pos, stack); ++ if (world.purpurConfig.persistentTileEntityDisplayNames && stack.hasTag()) { ++ CompoundTag display = stack.getSubTag("display"); ++ if (display != null) { ++ BlockEntity tile = world.getBlockEntity(pos); ++ if (tile != null) { ++ if (display.contains("Name", 8)) { ++ tile.setPersistentDisplayName(display.getString("Name")); ++ } ++ if (display.contains("Lore", 9)) { ++ tile.setPersistentLore(display.getList("Lore", 8)); ++ } ++ } ++ } ++ } ++ return handled; ++ // Purpur end + } + + @Nullable +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index 85fa2b26863e2da8f4de93aa10ffd77f7076b682..e821c6a33c7dfbc62859d4d72b19ee2b507b8efc 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -20,6 +20,9 @@ import net.minecraft.core.IdMapper; + import net.minecraft.core.NonNullList; + import net.minecraft.core.Registry; + import net.minecraft.core.Vec3i; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; ++import net.minecraft.nbt.StringTag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.MutableComponent; + import net.minecraft.network.chat.TranslatableComponent; +@@ -28,6 +31,7 @@ import net.minecraft.stats.Stats; + import net.minecraft.tags.BlockTags; + import net.minecraft.tags.Tag; + import net.minecraft.util.Mth; ++import net.minecraft.world.Nameable; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +@@ -325,7 +329,7 @@ public class Block extends BlockBehaviour implements ItemLike { + public static void dropResources(BlockState state, LevelAccessor world, BlockPos pos, @Nullable BlockEntity blockEntity) { + if (world instanceof ServerLevel) { + Block.getDrops(state, (ServerLevel) world, pos, blockEntity).forEach((itemstack) -> { +- Block.popResource((Level) ((ServerLevel) world), pos, itemstack); ++ Block.popResource((Level) ((ServerLevel) world), pos, applyDisplayNameAndLoreFromTile(itemstack, blockEntity)); // Purpur + }); + state.spawnAfterBreak((ServerLevel) world, pos, ItemStack.EMPTY); + } +@@ -335,13 +339,53 @@ public class Block extends BlockBehaviour implements ItemLike { + public static void dropResources(BlockState state, Level world, BlockPos pos, @Nullable BlockEntity blockEntity, Entity entity, ItemStack stack) { + if (world instanceof ServerLevel) { + Block.getDrops(state, (ServerLevel) world, pos, blockEntity, entity, stack).forEach((itemstack1) -> { +- Block.popResource(world, pos, itemstack1); ++ Block.popResource(world, pos, applyDisplayNameAndLoreFromTile(itemstack1, blockEntity)); // Purpur + }); + state.spawnAfterBreak((ServerLevel) world, pos, stack); + } + + } + ++ // Purpur start ++ private static ItemStack applyDisplayNameAndLoreFromTile(ItemStack stack, BlockEntity blockEntity) { ++ if (stack.getItem() instanceof BlockItem) { ++ if (blockEntity != null && blockEntity.getLevel() instanceof ServerLevel && blockEntity.getLevel().purpurConfig.persistentTileEntityDisplayNames) { ++ String name = blockEntity.getPersistentDisplayName(); ++ ListTag lore = blockEntity.getPersistentLore(); ++ if (blockEntity instanceof Nameable) { ++ Nameable namedBlockEntity = (Nameable) blockEntity; ++ if (namedBlockEntity.hasCustomName()) { ++ name = Component.Serializer.toJson(namedBlockEntity.getCustomName()); ++ } ++ } ++ ++ if (name != null || lore != null) { ++ CompoundTag display = stack.getSubTag("display"); ++ if (display == null) { ++ display = new CompoundTag(); ++ } ++ ++ if (name != null) { ++ display.put("Name", StringTag.valueOf(name)); ++ } ++ if (lore != null) { ++ display.put("Lore", lore); ++ } ++ ++ CompoundTag tag = stack.getTag(); ++ if (tag == null) { ++ tag = new CompoundTag(); ++ } ++ tag.put("display", display); ++ ++ stack.setTag(tag); ++ } ++ } ++ } ++ return stack; ++ } ++ // Purpur end ++ + public static void popResource(Level world, BlockPos pos, ItemStack stack) { + float f = EntityType.ITEM.getHeight() / 2.0F; + double d0 = (double) ((float) pos.getX() + 0.5F) + Mth.nextDouble(world.random, -0.25D, 0.25D); +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index c3a07ccccd5cc38552363c82398f432c8d624288..132c9e6a643995d9fde535a78d9edc9ee97e3a76 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -5,6 +5,8 @@ import net.minecraft.CrashReportCategory; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Registry; + import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; ++import net.minecraft.nbt.StringTag; + import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.world.level.Level; +@@ -87,10 +89,26 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + if (persistentDataTag instanceof CompoundTag) { + this.persistentDataContainer.putAll((CompoundTag) persistentDataTag); + } ++ // Purpur start ++ if (nbt.contains("Purpur.persistentDisplayName")) { ++ this.persistentDisplayName = nbt.getString("Purpur.persistentDisplayName"); ++ } ++ if (nbt.contains("Purpur.persistentLore")) { ++ this.persistentLore = nbt.getList("Purpur.persistentLore", 8); ++ } ++ // Purpur end + } + // CraftBukkit end + + public CompoundTag save(CompoundTag nbt) { ++ // Purpur start ++ if (this.persistentDisplayName != null) { ++ nbt.put("Purpur.persistentDisplayName", StringTag.valueOf(this.persistentDisplayName)); ++ } ++ if (this.persistentLore != null) { ++ nbt.put("Purpur.persistentLore", this.persistentLore); ++ } ++ // Purpur end + return this.saveMetadata(nbt); + } + +@@ -243,4 +261,25 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + return null; + } + // CraftBukkit end ++ ++ // Purpur start ++ private String persistentDisplayName = null; ++ private ListTag persistentLore = null; ++ ++ public void setPersistentDisplayName(String json) { ++ this.persistentDisplayName = json; ++ } ++ ++ public void setPersistentLore(ListTag lore) { ++ this.persistentLore = lore; ++ } ++ ++ public String getPersistentDisplayName() { ++ return this.persistentDisplayName; ++ } ++ ++ public ListTag getPersistentLore() { ++ return this.persistentLore; ++ } ++ // Purpur end + } +diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +index cd1373f113f434aa0d3d3ea07096095dc99dbc18..ff328f68fcbe50d4d5c34b4861577d1ccdb32dcb 100644 +--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java ++++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +@@ -123,6 +123,7 @@ public class PurpurWorldConfig { + public boolean entitiesPickUpLootBypassMobGriefing = false; + public boolean entitiesCanUsePortals = true; + public boolean milkCuresBadOmen = true; ++ public boolean persistentTileEntityDisplayNames = false; + public double tridentLoyaltyVoidReturnHeight = 0.0D; + public double voidDamageHeight = -64.0D; + public double voidDamageDealt = 4.0D; +@@ -134,6 +135,7 @@ public class PurpurWorldConfig { + entitiesPickUpLootBypassMobGriefing = getBoolean("gameplay-mechanics.entities-pick-up-loot-bypass-mob-griefing", entitiesPickUpLootBypassMobGriefing); + entitiesCanUsePortals = getBoolean("gameplay-mechanics.entities-can-use-portals", entitiesCanUsePortals); + milkCuresBadOmen = getBoolean("gameplay-mechanics.milk-cures-bad-omen", milkCuresBadOmen); ++ persistentTileEntityDisplayNames = getBoolean("gameplay-mechanics.persistent-tileentity-display-names-and-lore", persistentTileEntityDisplayNames); + tridentLoyaltyVoidReturnHeight = getDouble("gameplay-mechanics.trident-loyalty-void-return-height", tridentLoyaltyVoidReturnHeight); + voidDamageHeight = getDouble("gameplay-mechanics.void-damage-height", voidDamageHeight); + voidDamageDealt = getDouble("gameplay-mechanics.void-damage-dealt", voidDamageDealt); diff --git a/patches/server-unmapped/0112-Add-predicate-to-recipe-s-ExactChoice-ingredient.patch b/patches/server/0109-Add-predicate-to-recipe-s-ExactChoice-ingredient.patch similarity index 52% rename from patches/server-unmapped/0112-Add-predicate-to-recipe-s-ExactChoice-ingredient.patch rename to patches/server/0109-Add-predicate-to-recipe-s-ExactChoice-ingredient.patch index 2e1d8f600..11de903a4 100644 --- a/patches/server-unmapped/0112-Add-predicate-to-recipe-s-ExactChoice-ingredient.patch +++ b/patches/server/0109-Add-predicate-to-recipe-s-ExactChoice-ingredient.patch @@ -4,20 +4,20 @@ Date: Sat, 3 Oct 2020 17:40:52 -0500 Subject: [PATCH] Add predicate to recipe's ExactChoice ingredient -diff --git a/src/main/java/net/minecraft/world/item/crafting/RecipeItemStack.java b/src/main/java/net/minecraft/world/item/crafting/RecipeItemStack.java -index 63274908bc7552321a4db3d4e0eec0f55ee34786..c7f6dc5a933873a6118a5674e4ce04cfa1664f60 100644 ---- a/src/main/java/net/minecraft/world/item/crafting/RecipeItemStack.java -+++ b/src/main/java/net/minecraft/world/item/crafting/RecipeItemStack.java -@@ -36,6 +36,7 @@ public final class RecipeItemStack implements Predicate { - public ItemStack[] choices; - private IntList d; +diff --git a/src/main/java/net/minecraft/world/item/crafting/Ingredient.java b/src/main/java/net/minecraft/world/item/crafting/Ingredient.java +index e10a7268274488c50c0e4b5a10f8fa5de7d500e5..0db4f767c3a1d8fd885fcd695abc1fb44ca1166f 100644 +--- a/src/main/java/net/minecraft/world/item/crafting/Ingredient.java ++++ b/src/main/java/net/minecraft/world/item/crafting/Ingredient.java +@@ -36,6 +36,7 @@ public final class Ingredient implements Predicate { + public ItemStack[] itemStacks; + private IntList stackingIds; public boolean exact; // CraftBukkit + public Predicate predicate; // Purpur - public RecipeItemStack(Stream stream) { - this.b = (RecipeItemStack.Provider[]) stream.toArray((i) -> { -@@ -62,6 +63,12 @@ public final class RecipeItemStack implements Predicate { - if (this.choices.length == 0) { + public Ingredient(Stream entries) { + this.values = (Ingredient.Value[]) entries.toArray((i) -> { +@@ -67,6 +68,12 @@ public final class Ingredient implements Predicate { + if (this.itemStacks.length == 0) { return itemstack.isEmpty(); } else { + // Purpur start @@ -26,16 +26,16 @@ index 63274908bc7552321a4db3d4e0eec0f55ee34786..c7f6dc5a933873a6118a5674e4ce04cf + } + // Purpur end + - ItemStack[] aitemstack = this.choices; + ItemStack[] aitemstack = this.itemStacks; int i = aitemstack.length; diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java -index b7e8c3798628229be56289818caa3024014640d6..43c50c2c54444c67e4a875be4880afe97c32412c 100644 +index 10ace7bb17c36bfefc584a6322841ab6ea4c866f..a225ec89946cb4c9634a797c8568171cffe4410d 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java @@ -22,6 +22,7 @@ public interface CraftRecipe extends Recipe { } else if (bukkit instanceof RecipeChoice.ExactChoice) { - stack = new RecipeItemStack(((RecipeChoice.ExactChoice) bukkit).getChoices().stream().map((mat) -> new net.minecraft.world.item.crafting.RecipeItemStack.StackProvider(CraftItemStack.asNMSCopy(mat)))); + stack = new Ingredient(((RecipeChoice.ExactChoice) bukkit).getChoices().stream().map((mat) -> new net.minecraft.world.item.crafting.Ingredient.ItemValue(CraftItemStack.asNMSCopy(mat)))); stack.exact = true; + stack.predicate = ((RecipeChoice.ExactChoice) bukkit).getPredicate(); // Purpur } else { diff --git a/patches/server/0110-Flying-squids-Oh-my.patch b/patches/server/0110-Flying-squids-Oh-my.patch new file mode 100644 index 000000000..c34059bcb --- /dev/null +++ b/patches/server/0110-Flying-squids-Oh-my.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 4 Oct 2020 12:00:42 -0500 +Subject: [PATCH] Flying squids! Oh my! + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java +index 8c9454612e71f1d1a82c6a13c7788dd9b892fedc..0b93b2fc5c2f44ce7b3bcf879b46891311ca1c55 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Squid.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Squid.java +@@ -61,6 +61,11 @@ public class Squid extends WaterAnimal { + // Stops squids from floating just over the water + return this.getBoundingBox().deflate(0.001D).offsetY(level.purpurConfig.squidOffsetWaterCheck); + } ++ ++ @Override ++ public boolean isInWater() { ++ return this.wasTouchingWater || level.purpurConfig.squidsCanFly; ++ } + // Purpur end + + @Override +@@ -134,6 +139,7 @@ public class Squid extends WaterAnimal { + } + + if (this.isInWaterOrBubble()) { ++ if (level.purpurConfig.squidsCanFly) setNoGravity(!wasTouchingWater); // Purpur + if (this.tentacleMovement < 3.1415927F) { + float f = this.tentacleMovement / 3.1415927F; + +@@ -263,7 +269,7 @@ public class Squid extends WaterAnimal { + + if (i > 100) { + this.squid.setMovementVector(0.0F, 0.0F, 0.0F); +- } else if (this.squid.getRandom().nextInt(50) == 0 || !this.squid.wasTouchingWater || !this.squid.hasMovementVector()) { ++ } else if (this.squid.getRandom().nextInt(50) == 0 || !this.squid.isInWater() || !this.squid.hasMovementVector()) { // Purpur + float f = this.squid.getRandom().nextFloat() * 6.2831855F; + float f1 = Mth.cos(f) * 0.2F; + float f2 = -0.1F + this.squid.getRandom().nextFloat() * 0.2F; +diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +index ff328f68fcbe50d4d5c34b4861577d1ccdb32dcb..d04fe759b32926209150a9b412b5de200f3518ad 100644 +--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java ++++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +@@ -933,10 +933,12 @@ public class PurpurWorldConfig { + public boolean squidRidable = false; + public boolean squidImmuneToEAR = true; + public double squidOffsetWaterCheck = 0.0D; ++ public boolean squidsCanFly = false; + private void squidSettings() { + squidRidable = getBoolean("mobs.squid.ridable", squidRidable); + squidImmuneToEAR = getBoolean("mobs.squid.immune-to-EAR", squidImmuneToEAR); + squidOffsetWaterCheck = getDouble("mobs.squid.water-offset-check", squidOffsetWaterCheck); ++ squidsCanFly = getBoolean("mobs.squid.can-fly", squidsCanFly); + } + + public boolean spiderRidable = false; diff --git a/patches/server/0111-Infinity-bow-settings.patch b/patches/server/0111-Infinity-bow-settings.patch new file mode 100644 index 000000000..66b01e46f --- /dev/null +++ b/patches/server/0111-Infinity-bow-settings.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 4 Oct 2020 19:08:53 -0500 +Subject: [PATCH] Infinity bow settings + + +diff --git a/src/main/java/net/minecraft/world/item/BowItem.java b/src/main/java/net/minecraft/world/item/BowItem.java +index afe33f20578177cb517e1c116e6319481642e66c..ed077b79518f47be2bb9db316ab5b0f94eb17ff8 100644 +--- a/src/main/java/net/minecraft/world/item/BowItem.java ++++ b/src/main/java/net/minecraft/world/item/BowItem.java +@@ -38,7 +38,7 @@ public class BowItem extends ProjectileWeaponItem implements Vanishable { + float f = BowItem.getPowerForTime(j); + + if ((double) f >= 0.1D) { +- boolean flag1 = flag && itemstack1.is(Items.ARROW); ++ boolean flag1 = flag && ((itemstack1.is(Items.ARROW) && world.purpurConfig.infinityWorksWithNormalArrows) || (itemstack1.is(Items.TIPPED_ARROW) && world.purpurConfig.infinityWorksWithTippedArrows) || (itemstack1.is(Items.SPECTRAL_ARROW) && world.purpurConfig.infinityWorksWithSpectralArrows)); // Purpur + + if (!world.isClientSide) { + ArrowItem itemarrow = (ArrowItem) (itemstack1.getItem() instanceof ArrowItem ? itemstack1.getItem() : Items.ARROW); +@@ -99,6 +99,7 @@ public class BowItem extends ProjectileWeaponItem implements Vanishable { + entityhuman.getInventory().removeItem(itemstack1); + } + } ++ else if (!entityhuman.getAbilities().instabuild) ((org.bukkit.entity.Player) entityhuman.getBukkitEntity()).updateInventory(); // Purpur + + entityhuman.awardStat(Stats.ITEM_USED.get(this)); + } diff --git a/patches/server/0112-Stonecutter-damage.patch b/patches/server/0112-Stonecutter-damage.patch new file mode 100644 index 000000000..62be1dff2 --- /dev/null +++ b/patches/server/0112-Stonecutter-damage.patch @@ -0,0 +1,78 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Mon, 5 Oct 2020 12:15:14 -0500 +Subject: [PATCH] Stonecutter damage + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 517542c4cf412d81c4a85d5a48191fa06a635364..2e412ab5ef06e2c07a8b07e0b3948e51c29dc81e 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -897,7 +897,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + } + // CraftBukkit end + +- if (this.onGround && !this.isSteppingCarefully()) { ++ if (this.onGround && (!this.isSteppingCarefully()) || (block == Blocks.STONECUTTER && level.purpurConfig.stonecutterDamage > 0.0F)) { + block.stepOn(this.level, blockposition, iblockdata, this); + } + +diff --git a/src/main/java/net/minecraft/world/level/block/StonecutterBlock.java b/src/main/java/net/minecraft/world/level/block/StonecutterBlock.java +index e5c11ca529b524b444695f50e2648f0206ff34e1..75084a9943a3b481d20ce170565484071b96c8dc 100644 +--- a/src/main/java/net/minecraft/world/level/block/StonecutterBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/StonecutterBlock.java +@@ -93,4 +93,16 @@ public class StonecutterBlock extends Block { + public boolean isPathfindable(BlockState state, BlockGetter world, BlockPos pos, PathComputationType type) { + return false; + } ++ ++ // Purpur start ++ @Override ++ public void stepOn(Level level, BlockPos pos, BlockState state, net.minecraft.world.entity.Entity entity) { ++ if (level.purpurConfig.stonecutterDamage > 0.0F && entity instanceof net.minecraft.world.entity.LivingEntity) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ entity.hurt(net.minecraft.world.damagesource.DamageSource.CACTUS, level.purpurConfig.stonecutterDamage); ++ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = null; ++ } ++ super.stepOn(level, pos, state, entity); ++ } ++ // Purpur end + } +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java +index 2ad5ff9a1d7de54e75436e99da8a73db9dc91bde..e67c14c272b0058e210c83f91600431e11f65f33 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java +@@ -463,7 +463,7 @@ public class WalkNodeEvaluator extends NodeEvaluator { + return BlockPathTypes.DANGER_CACTUS; + } + +- if (blockState.is(Blocks.SWEET_BERRY_BUSH)) { ++ if (blockState.is(Blocks.SWEET_BERRY_BUSH) || blockState.is(Blocks.STONECUTTER)) { // Purpur + return BlockPathTypes.DANGER_OTHER; + } + +@@ -495,7 +495,7 @@ public class WalkNodeEvaluator extends NodeEvaluator { + return BlockPathTypes.POWDER_SNOW; + } else if (blockState.is(Blocks.CACTUS)) { + return BlockPathTypes.DAMAGE_CACTUS; +- } else if (blockState.is(Blocks.SWEET_BERRY_BUSH)) { ++ } else if (blockState.is(Blocks.SWEET_BERRY_BUSH) || blockState.is(Blocks.STONECUTTER)) { // Purpur + return BlockPathTypes.DAMAGE_OTHER; + } else if (blockState.is(Blocks.HONEY_BLOCK)) { + return BlockPathTypes.STICKY_HONEY; +diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +index d04fe759b32926209150a9b412b5de200f3518ad..db10ff41061e6d7cad6944e6506b20a35d99d3c3 100644 +--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java ++++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +@@ -979,6 +979,11 @@ public class PurpurWorldConfig { + spawnerDeactivateByRedstone = getBoolean("blocks.spawner.deactivate-by-redstone", spawnerDeactivateByRedstone); + } + ++ public float stonecutterDamage = 0.0F; ++ private void stonecutterSettings() { ++ stonecutterDamage = (float) getDouble("blocks.stonecutter.damage", stonecutterDamage); ++ } ++ + public boolean turtleRidable = false; + public boolean turtleRidableInWater = false; + public boolean turtleEggsBreakFromExpOrbs = true;