diff --git a/patches/server/0160-Option-for-Villager-Clerics-to-farm-Nether-Wart.patch b/patches/server/0160-Option-for-Villager-Clerics-to-farm-Nether-Wart.patch new file mode 100644 index 000000000..37eb0e3b9 --- /dev/null +++ b/patches/server/0160-Option-for-Villager-Clerics-to-farm-Nether-Wart.patch @@ -0,0 +1,219 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Sat, 5 Dec 2020 01:20:16 -0800 +Subject: [PATCH] Option for Villager Clerics to farm Nether Wart + +Adds an option so that Villagers with the Cleric profession are able to +farm Nether Wart. Reimplemented based on a feature of the carpet-extra +mod. + +diff --git a/src/main/java/net/minecraft/server/BehaviorFarm.java b/src/main/java/net/minecraft/server/BehaviorFarm.java +index 0ff202c0d..b9c6011c8 100644 +--- a/src/main/java/net/minecraft/server/BehaviorFarm.java ++++ b/src/main/java/net/minecraft/server/BehaviorFarm.java +@@ -12,6 +12,7 @@ public class BehaviorFarm extends Behavior { + private long c; + private int d; + private final List e = Lists.newArrayList(); ++ private boolean clericWartFarmer = false; // Purpur + + public BehaviorFarm() { + super(ImmutableMap.of(MemoryModuleType.LOOK_TARGET, MemoryStatus.VALUE_ABSENT, MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT, MemoryModuleType.SECONDARY_JOB_SITE, MemoryStatus.VALUE_PRESENT)); +@@ -20,9 +21,14 @@ public class BehaviorFarm extends Behavior { + protected boolean a(WorldServer worldserver, EntityVillager entityvillager) { + if (!worldserver.getGameRules().getBoolean(GameRules.MOB_GRIEFING) && !worldserver.purpurConfig.villagerFarmingBypassMobGriefing) { // Purpur + return false; +- } else if (entityvillager.getVillagerData().getProfession() != VillagerProfession.FARMER) { ++ } else if (entityvillager.getVillagerData().getProfession() != VillagerProfession.FARMER && !(worldserver.purpurConfig.villagerClericsFarmWarts && entityvillager.getVillagerData().getProfession() == VillagerProfession.CLERIC)) { // Purpur + return false; + } else { ++ // Purpur start ++ if (!this.clericWartFarmer && entityvillager.getVillagerData().getProfession() == VillagerProfession.CLERIC) { ++ this.clericWartFarmer = true; ++ } ++ // Purpur end + BlockPosition.MutableBlockPosition blockposition_mutableblockposition = entityvillager.getChunkCoordinates().i(); + + this.e.clear(); +@@ -53,6 +59,11 @@ public class BehaviorFarm extends Behavior { + Block block = iblockdata.getBlock(); + Block block1 = worldserver.getType(blockposition.down()).getBlock(); + ++ // Purpur start ++ if (this.clericWartFarmer) { ++ return block == Blocks.NETHER_WART && iblockdata.get(BlockNetherWart.AGE) == 3 || iblockdata.isAir() && block1 == Blocks.SOUL_SAND; ++ } ++ // Purpur end + return block instanceof BlockCrops && ((BlockCrops) block).isRipe(iblockdata) || iblockdata.isAir() && block1 instanceof BlockSoil; + } + +@@ -78,7 +89,7 @@ public class BehaviorFarm extends Behavior { + Block block = iblockdata.getBlock(); + Block block1 = worldserver.getType(this.farmBlock.down()).getBlock(); + +- if (block instanceof BlockCrops && ((BlockCrops) block).isRipe(iblockdata)) { ++ if (block instanceof BlockCrops && ((BlockCrops) block).isRipe(iblockdata) || this.clericWartFarmer && block == Blocks.NETHER_WART && iblockdata.get(BlockNetherWart.AGE) == 3) { // Purpur + // CraftBukkit start + if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entityvillager, this.farmBlock, Blocks.AIR.getBlockData()).isCancelled()) { + worldserver.a(this.farmBlock, true, entityvillager); +@@ -86,7 +97,7 @@ public class BehaviorFarm extends Behavior { + // CraftBukkit end + } + +- if (iblockdata.isAir() && block1 instanceof BlockSoil && entityvillager.canPlant()) { ++ if (iblockdata.isAir() && (block1 instanceof BlockSoil || this.clericWartFarmer && block1 == Blocks.SOUL_SAND) && entityvillager.canPlant()) { // Purpur + InventorySubcontainer inventorysubcontainer = entityvillager.getInventory(); + + for (int j = 0; j < inventorysubcontainer.getSize(); ++j) { +@@ -109,6 +120,12 @@ public class BehaviorFarm extends Behavior { + planted = Blocks.BEETROOTS; + flag = true; + } ++ // Purpur start ++ else if (itemstack.getItem() == Items.NETHER_WART) { ++ planted = Blocks.NETHER_WART; ++ flag = true; ++ } ++ // Purpur end + + if (planted != null && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entityvillager, this.farmBlock, planted.getBlockData()).isCancelled()) { + worldserver.setTypeAndData(this.farmBlock, planted.getBlockData(), 3); +@@ -119,7 +136,7 @@ public class BehaviorFarm extends Behavior { + } + + if (flag) { +- worldserver.playSound((EntityHuman) null, (double) this.farmBlock.getX(), (double) this.farmBlock.getY(), (double) this.farmBlock.getZ(), SoundEffects.ITEM_CROP_PLANT, SoundCategory.BLOCKS, 1.0F, 1.0F); ++ worldserver.playSound((EntityHuman) null, (double) this.farmBlock.getX(), (double) this.farmBlock.getY(), (double) this.farmBlock.getZ(), this.clericWartFarmer ? SoundEffects.ITEM_NETHER_WART_PLANT : SoundEffects.ITEM_CROP_PLANT, SoundCategory.BLOCKS, 1.0F, 1.0F); // Purpur + itemstack.subtract(1); + if (itemstack.isEmpty()) { + inventorysubcontainer.setItem(j, ItemStack.b); +diff --git a/src/main/java/net/minecraft/server/Behaviors.java b/src/main/java/net/minecraft/server/Behaviors.java +index 2d9186966..e376306bc 100644 +--- a/src/main/java/net/minecraft/server/Behaviors.java ++++ b/src/main/java/net/minecraft/server/Behaviors.java +@@ -12,10 +12,13 @@ public class Behaviors { + return ImmutableList.of(Pair.of(0, new BehaviorSwim(0.8F)), Pair.of(0, new BehaviorInteractDoor()), Pair.of(0, new BehaviorLook(45, 90)), Pair.of(0, new BehaviorPanic()), Pair.of(0, new BehaviorWake()), Pair.of(0, new BehaviorBellAlert()), Pair.of(0, new BehaviorRaid()), Pair.of(0, new BehaviorPositionValidate(villagerprofession.b(), MemoryModuleType.JOB_SITE)), Pair.of(0, new BehaviorPositionValidate(villagerprofession.b(), MemoryModuleType.POTENTIAL_JOB_SITE)), Pair.of(1, new BehavorMove()), Pair.of(2, new BehaviorBetterJob(villagerprofession)), Pair.of(3, new BehaviorInteractPlayer(f)), new Pair[]{Pair.of(5, new BehaviorFindAdmirableItem<>(f, false, 4)), Pair.of(6, new BehaviorFindPosition(villagerprofession.b(), MemoryModuleType.JOB_SITE, MemoryModuleType.POTENTIAL_JOB_SITE, true, Optional.empty())), Pair.of(7, new BehaviorPotentialJobSite(f)), Pair.of(8, new BehaviorLeaveJob(f)), Pair.of(10, new BehaviorFindPosition(VillagePlaceType.r, MemoryModuleType.HOME, false, Optional.of((byte) 14))), Pair.of(10, new BehaviorFindPosition(VillagePlaceType.s, MemoryModuleType.MEETING_POINT, true, Optional.of((byte) 14))), Pair.of(10, new BehaviorCareer()), Pair.of(10, new BehaviorProfession())}); + } + +- public static ImmutableList>> b(VillagerProfession villagerprofession, float f) { +- Object object; ++ // Purpur start - OBFHELPER, add clericsFarmWarts param ++ public static ImmutableList>> b(VillagerProfession villagerprofession, float f) { return createWorkTask(villagerprofession, f, false); } ++ public static ImmutableList>> createWorkTask(VillagerProfession villagerprofession, float f, boolean clericsFarmWarts) { ++ BehaviorWork object; // Purpur - decompile fix + +- if (villagerprofession == VillagerProfession.FARMER) { ++ if (villagerprofession == VillagerProfession.FARMER || (clericsFarmWarts && villagerprofession == VillagerProfession.CLERIC)) { ++ // Purpur end + object = new BehaviorWorkComposter(); + } else { + object = new BehaviorWork(); +diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java +index d882c1136..61b95d54c 100644 +--- a/src/main/java/net/minecraft/server/EntityVillager.java ++++ b/src/main/java/net/minecraft/server/EntityVillager.java +@@ -131,7 +131,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + behaviorcontroller.a(Activity.PLAY, Behaviors.a(0.5F)); + } else { + behaviorcontroller.setSchedule(Schedule.VILLAGER_DEFAULT); +- behaviorcontroller.a(Activity.WORK, Behaviors.b(villagerprofession, 0.5F), (Set) ImmutableSet.of(Pair.of(MemoryModuleType.JOB_SITE, MemoryStatus.VALUE_PRESENT))); ++ behaviorcontroller.a(Activity.WORK, Behaviors.createWorkTask(villagerprofession, 0.5F, this.world.purpurConfig.villagerClericsFarmWarts), (Set) ImmutableSet.of(Pair.of(MemoryModuleType.JOB_SITE, MemoryStatus.VALUE_PRESENT))); // Purpur + } + + behaviorcontroller.a(Activity.CORE, Behaviors.a(villagerprofession, 0.5F)); +@@ -833,6 +833,11 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + @Override + public boolean i(ItemStack itemstack) { + Item item = itemstack.getItem(); ++ // Purpur start ++ if (this.world.purpurConfig.villagerClericsFarmWarts && item.getItem() == Items.NETHER_WART && this.getVillagerData().getProfession() == VillagerProfession.CLERIC) { ++ return true; ++ } ++ // Purpur end + + return (EntityVillager.bs.contains(item) || this.getVillagerData().getProfession().c().contains(item)) && this.getInventory().b(itemstack); + } +@@ -854,6 +859,11 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + } + + public boolean canPlant() { ++ // Purpur start ++ if (this.world.purpurConfig.villagerClericsFarmWarts && this.getVillagerData().getProfession() == VillagerProfession.CLERIC) { ++ return this.getInventory().containsAny(ImmutableSet.of(Items.NETHER_WART)); ++ } ++ // Purpur end + return this.getInventory().a((Set) ImmutableSet.of(Items.WHEAT_SEEDS, Items.POTATO, Items.CARROT, Items.BEETROOT_SEEDS)); + } + +diff --git a/src/main/java/net/minecraft/server/IInventory.java b/src/main/java/net/minecraft/server/IInventory.java +index 46b88056b..507352807 100644 +--- a/src/main/java/net/minecraft/server/IInventory.java ++++ b/src/main/java/net/minecraft/server/IInventory.java +@@ -45,6 +45,7 @@ public interface IInventory extends Clearable { + return i; + } + ++ default boolean containsAny(Set itemSet) { return a(itemSet); } // Purpur - OBFHELPER + default boolean a(Set set) { + for (int i = 0; i < this.getSize(); ++i) { + ItemStack itemstack = this.getItem(i); +diff --git a/src/main/java/net/minecraft/server/SensorSecondaryPlaces.java b/src/main/java/net/minecraft/server/SensorSecondaryPlaces.java +index 24173f0d3..13ff2a1a2 100644 +--- a/src/main/java/net/minecraft/server/SensorSecondaryPlaces.java ++++ b/src/main/java/net/minecraft/server/SensorSecondaryPlaces.java +@@ -12,6 +12,13 @@ public class SensorSecondaryPlaces extends Sensor { + } + + protected void a(WorldServer worldserver, EntityVillager entityvillager) { ++ // Purpur start - make sure clerics don't wander to soul sand when the option is off ++ if (!worldserver.purpurConfig.villagerClericsFarmWarts && entityvillager.getVillagerData().getProfession() == VillagerProfession.CLERIC) { ++ BehaviorController brain = entityvillager.getBehaviorController(); ++ brain.removeMemory(MemoryModuleType.SECONDARY_JOB_SITE); ++ return; ++ } ++ // Purpur end + ResourceKey resourcekey = worldserver.getDimensionKey(); + BlockPosition blockposition = entityvillager.getChunkCoordinates(); + List list = Lists.newArrayList(); +@@ -32,7 +39,7 @@ public class SensorSecondaryPlaces extends Sensor { + BehaviorController behaviorcontroller = entityvillager.getBehaviorController(); + + if (!list.isEmpty()) { +- behaviorcontroller.setMemory(MemoryModuleType.SECONDARY_JOB_SITE, (Object) list); ++ behaviorcontroller.setMemory(MemoryModuleType.SECONDARY_JOB_SITE, list); // Purpur - decompile fix + } else { + behaviorcontroller.removeMemory(MemoryModuleType.SECONDARY_JOB_SITE); + } +diff --git a/src/main/java/net/minecraft/server/VillagerProfession.java b/src/main/java/net/minecraft/server/VillagerProfession.java +index 3c60da7ac..6493f220a 100644 +--- a/src/main/java/net/minecraft/server/VillagerProfession.java ++++ b/src/main/java/net/minecraft/server/VillagerProfession.java +@@ -9,7 +9,7 @@ public class VillagerProfession { + public static final VillagerProfession ARMORER = a("armorer", VillagePlaceType.d, SoundEffects.ENTITY_VILLAGER_WORK_ARMORER); + public static final VillagerProfession BUTCHER = a("butcher", VillagePlaceType.e, SoundEffects.ENTITY_VILLAGER_WORK_BUTCHER); + public static final VillagerProfession CARTOGRAPHER = a("cartographer", VillagePlaceType.f, SoundEffects.ENTITY_VILLAGER_WORK_CARTOGRAPHER); +- public static final VillagerProfession CLERIC = a("cleric", VillagePlaceType.g, SoundEffects.ENTITY_VILLAGER_WORK_CLERIC); ++ public static final VillagerProfession CLERIC = a("cleric", VillagePlaceType.g, ImmutableSet.of(Items.NETHER_WART), ImmutableSet.of(Blocks.SOUL_SAND), SoundEffects.ENTITY_VILLAGER_WORK_CLERIC); // Purpur + public static final VillagerProfession FARMER = a("farmer", VillagePlaceType.h, ImmutableSet.of(Items.WHEAT, Items.WHEAT_SEEDS, Items.BEETROOT_SEEDS, Items.BONE_MEAL), ImmutableSet.of(Blocks.FARMLAND), SoundEffects.ENTITY_VILLAGER_WORK_FARMER); + public static final VillagerProfession FISHERMAN = a("fisherman", VillagePlaceType.i, SoundEffects.ENTITY_VILLAGER_WORK_FISHERMAN); + public static final VillagerProfession FLETCHER = a("fletcher", VillagePlaceType.j, SoundEffects.ENTITY_VILLAGER_WORK_FLETCHER); +diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +index 020a42a5e..3a4fcbb53 100644 +--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java ++++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +@@ -1057,6 +1057,7 @@ public class PurpurWorldConfig { + public int villagerSpawnIronGolemLimit = 0; + public boolean villagerCanBreed = true; + public boolean villagerLobotomize1x1 = false; ++ public boolean villagerClericsFarmWarts = false; + private void villagerSettings() { + villagerRidable = getBoolean("mobs.villager.ridable", villagerRidable); + villagerRidableInWater = getBoolean("mobs.villager.ridable-in-water", villagerRidableInWater); +@@ -1069,6 +1070,7 @@ public class PurpurWorldConfig { + villagerSpawnIronGolemLimit = getInt("mobs.villager.spawn-iron-golem.limit", villagerSpawnIronGolemLimit); + villagerCanBreed = getBoolean("mobs.villager.can-breed", villagerCanBreed); + villagerLobotomize1x1 = getBoolean("mobs.villager.lobotomize-1x1", villagerLobotomize1x1); ++ villagerClericsFarmWarts = getBoolean("mobs.villager.clerics-farm-warts", villagerClericsFarmWarts); + } + + public boolean villagerTraderRidable = false;