From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: jmp <jasonpenilla2@me.com>
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/world/IInventory.java b/src/main/java/net/minecraft/world/IInventory.java
index 774ba6a923f7e329f6af5efc17e1c46e87ed2d77..b8c73cd0ba916b7bf166a6d2f6b7ab68cd9c939b 100644
--- a/src/main/java/net/minecraft/world/IInventory.java
+++ b/src/main/java/net/minecraft/world/IInventory.java
@@ -38,6 +38,7 @@ public interface IInventory extends Clearable {
         return true;
     }
 
+    default int getAmount(Item item) { return this.a(item); } // Purpur - OBFHELPER
     default int a(Item item) {
         int i = 0;
 
@@ -52,6 +53,7 @@ public interface IInventory extends Clearable {
         return i;
     }
 
+    default boolean containsAny(Set<Item> itemSet) { return a(itemSet); } // Purpur - OBFHELPER
     default boolean a(Set<Item> set) {
         for (int i = 0; i < this.getSize(); ++i) {
             ItemStack itemstack = this.getItem(i);
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFarm.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFarm.java
index 42c70a6c2972ac38e889a6d42fe2d7d4f6017d57..752642c0a15d68fcc1871e1cb02658b12c8978b3 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFarm.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFarm.java
@@ -32,6 +32,7 @@ public class BehaviorFarm extends Behavior<EntityVillager> {
     private long c;
     private int d;
     private final List<BlockPosition> 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));
@@ -40,9 +41,14 @@ public class BehaviorFarm extends Behavior<EntityVillager> {
     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();
@@ -73,6 +79,11 @@ public class BehaviorFarm extends Behavior<EntityVillager> {
         Block block = iblockdata.getBlock();
         Block block1 = worldserver.getType(blockposition.down()).getBlock();
 
+        // Purpur start
+        if (this.clericWartFarmer) {
+            return block == Blocks.NETHER_WART && iblockdata.get(net.minecraft.world.level.block.BlockNetherWart.AGE) == 3 || iblockdata.isAir() && block1 == Blocks.SOUL_SAND;
+        }
+        // Purpur end
         return block instanceof BlockCrops && ((BlockCrops) block).isRipe(iblockdata) || iblockdata.isAir() && block1 instanceof BlockSoil;
     }
 
@@ -98,7 +109,7 @@ public class BehaviorFarm extends Behavior<EntityVillager> {
                 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 || this.clericWartFarmer && block == Blocks.NETHER_WART && iblockdata.get(net.minecraft.world.level.block.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);
@@ -106,7 +117,7 @@ public class BehaviorFarm extends Behavior<EntityVillager> {
                     // CraftBukkit end
                 }
 
-                if (iblockdata.isAir() && block1 instanceof BlockSoil && entityvillager.canPlant()) {
+                if (iblockdata.isAir() && (block1 instanceof BlockSoil && !this.clericWartFarmer || this.clericWartFarmer && block1 == Blocks.SOUL_SAND) && entityvillager.canPlant()) { // Purpur
                     InventorySubcontainer inventorysubcontainer = entityvillager.getInventory();
 
                     for (int j = 0; j < inventorysubcontainer.getSize(); ++j) {
@@ -116,6 +127,14 @@ public class BehaviorFarm extends Behavior<EntityVillager> {
                         if (!itemstack.isEmpty()) {
                             // CraftBukkit start
                             Block planted = null;
+                            // Purpur start
+                            if (this.clericWartFarmer) {
+                                if (itemstack.getItem() == Items.NETHER_WART) {
+                                    planted = Blocks.NETHER_WART;
+                                    flag = true;
+                                }
+                            } else
+                            // Purpur end
                             if (itemstack.getItem() == Items.WHEAT_SEEDS) {
                                 planted = Blocks.WHEAT;
                                 flag = true;
@@ -139,7 +158,7 @@ public class BehaviorFarm extends Behavior<EntityVillager> {
                         }
 
                         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/world/entity/ai/behavior/BehaviorTradeVillager.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorTradeVillager.java
index 71ea6c43d76bf1abe6b08dadb20ea4708b0ecfc7..c73b4475182541fa8261bec44f1eeeef21c22f42 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorTradeVillager.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorTradeVillager.java
@@ -53,6 +53,11 @@ public class BehaviorTradeVillager extends Behavior<EntityVillager> {
             if (entityvillager1.getVillagerData().getProfession() == VillagerProfession.FARMER && entityvillager.getInventory().a(Items.WHEAT) > Items.WHEAT.getMaxStackSize() / 2) {
                 a(entityvillager, ImmutableSet.of(Items.WHEAT), entityvillager1);
             }
+            // Purpur start
+            if (worldserver.purpurConfig.villagerClericsFarmWarts && worldserver.purpurConfig.villagerClericFarmersThrowWarts && entityvillager.getVillagerData().getProfession() == VillagerProfession.CLERIC && entityvillager.getInventory().getAmount(Items.NETHER_WART) > Items.NETHER_WART.getMaxStackSize() / 2) {
+                tryThrowingItems(entityvillager, ImmutableSet.of(Items.NETHER_WART), entityvillager1);
+            }
+            // Purpur end
 
             if (!this.b.isEmpty() && entityvillager.getInventory().a(this.b)) {
                 a(entityvillager, this.b, entityvillager1);
@@ -74,6 +79,7 @@ public class BehaviorTradeVillager extends Behavior<EntityVillager> {
         }).collect(Collectors.toSet());
     }
 
+    private static void tryThrowingItems(EntityVillager entityVillager, Set<Item> acceptableItems, EntityLiving targetEntity) { a(entityVillager, acceptableItems, targetEntity); } // Purpur - OBFHELPER
     private static void a(EntityVillager entityvillager, Set<Item> set, EntityLiving entityliving) {
         InventorySubcontainer inventorysubcontainer = entityvillager.getInventory();
         ItemStack itemstack = ItemStack.b;
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/Behaviors.java b/src/main/java/net/minecraft/world/entity/ai/behavior/Behaviors.java
index df12193e1a2e449193a3feab53fc684a2571ae3a..4a8217862a98488ce71ce577b5fa9d6a0f9c898a 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/Behaviors.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/Behaviors.java
@@ -21,10 +21,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<Pair<Integer, ? extends Behavior<? super EntityVillager>>> b(VillagerProfession villagerprofession, float f) {
-        Object object;
+    // Purpur start - OBFHELPER, add clericsFarmWarts param
+    public static ImmutableList<Pair<Integer, ? extends Behavior<? super EntityVillager>>> b(VillagerProfession villagerprofession, float f) { return createWorkTask(villagerprofession, f, false); }
+    public static ImmutableList<Pair<Integer, ? extends Behavior<? super EntityVillager>>> 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/world/entity/ai/sensing/SensorSecondaryPlaces.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorSecondaryPlaces.java
index 25c10973c74f98224dd1d2ae5e7178b9781374aa..d50b5632f0e53147ea23109f1ed627b44f798b58 100644
--- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorSecondaryPlaces.java
+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorSecondaryPlaces.java
@@ -20,6 +20,13 @@ public class SensorSecondaryPlaces extends Sensor<EntityVillager> {
     }
 
     protected void a(WorldServer worldserver, EntityVillager entityvillager) {
+        // Purpur start - make sure clerics don't wander to soul sand when the option is off
+        BehaviorController<?> behaviorcontroller = entityvillager.getBehaviorController();
+        if (!worldserver.purpurConfig.villagerClericsFarmWarts && entityvillager.getVillagerData().getProfession() == net.minecraft.world.entity.npc.VillagerProfession.CLERIC) {
+            behaviorcontroller.removeMemory(MemoryModuleType.SECONDARY_JOB_SITE);
+            return;
+        }
+        // Purpur end
         ResourceKey<World> resourcekey = worldserver.getDimensionKey();
         BlockPosition blockposition = entityvillager.getChunkCoordinates();
         List<GlobalPos> list = Lists.newArrayList();
@@ -37,10 +44,10 @@ public class SensorSecondaryPlaces extends Sensor<EntityVillager> {
             }
         }
 
-        BehaviorController<?> behaviorcontroller = entityvillager.getBehaviorController();
+        //BehaviorController<?> behaviorcontroller = entityvillager.getBehaviorController(); // Purpur - move up
 
         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/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java
index bc14e242f97f9f6d8e581d12319c95ae5f70f250..0924e0c13b3c57e46f6dc40232707088f96e98c7 100644
--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java
@@ -203,7 +203,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), ImmutableSet.of(Pair.of(MemoryModuleType.JOB_SITE, MemoryStatus.VALUE_PRESENT))); // Purpur
         }
 
         behaviorcontroller.a(Activity.CORE, Behaviors.a(villagerprofession, 0.5F));
@@ -944,6 +944,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/world/entity/npc/VillagerProfession.java b/src/main/java/net/minecraft/world/entity/npc/VillagerProfession.java
index 69de7588eebba7557cdaec129f19ec1fc2c675c5..dd9b678481620856fb7eaaa04c3b812c861e892a 100644
--- a/src/main/java/net/minecraft/world/entity/npc/VillagerProfession.java
+++ b/src/main/java/net/minecraft/world/entity/npc/VillagerProfession.java
@@ -18,7 +18,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 50cacb7ab275229c0d2fdeeca4719a565977b630..40ce04e9a3f55f42e44230c63b53efbfe08fcd74 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -1090,6 +1090,8 @@ public class PurpurWorldConfig {
     public int villagerBreedingTicks = 6000;
     public boolean villagerLobotomizeEnabled = false;
     public int villagerLobotomizeCheck = 60;
+    public boolean villagerClericsFarmWarts = false;
+    public boolean villagerClericFarmersThrowWarts = true;
     private void villagerSettings() {
         villagerRidable = getBoolean("mobs.villager.ridable", villagerRidable);
         villagerRidableInWater = getBoolean("mobs.villager.ridable-in-water", villagerRidableInWater);
@@ -1109,6 +1111,8 @@ public class PurpurWorldConfig {
         }
         villagerLobotomizeEnabled = getBoolean("mobs.villager.lobotomize.enabled", villagerLobotomizeEnabled);
         villagerLobotomizeCheck = getInt("mobs.villager.lobotomize.check-interval", villagerLobotomizeCheck);
+        villagerClericsFarmWarts = getBoolean("mobs.villager.clerics-farm-warts", villagerClericsFarmWarts);
+        villagerClericFarmersThrowWarts = getBoolean("mobs.villager.cleric-wart-farmers-throw-warts-at-villagers", villagerClericFarmersThrowWarts);
     }
 
     public boolean villagerTraderRidable = false;
