From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Thu, 3 Dec 2020 17:56:18 -0600
Subject: [PATCH] Lobotomize stuck villagers


diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java
index 1d03e936b696f3b7e88b411816a8195a716fc3eb..80d86ce8944e38dcdbd15574aea4e3cb073d2cf7 100644
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
@@ -142,6 +142,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
         return villageplacetype == PoiType.MEETING;
     });
     private final int brainTickOffset; // Purpur
+    boolean lobotomized = false; // Purpur
 
     public long nextGolemPanic = -1; // Airplane
 
@@ -185,6 +186,22 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
     public boolean canBeLeashed(Player player) {
         return level.purpurConfig.villagerCanBeLeashed && !this.isLeashed();
     }
+
+    private boolean isLobotomized() {
+        if ((level.getGameTime() + brainTickOffset) % level.purpurConfig.villagerLobotomizeCheck == 0) {
+            this.lobotomized = !canTravelFrom(blockPosition().above());
+        }
+        return this.lobotomized;
+    }
+
+    private boolean canTravelFrom(BlockPos pos) {
+        return canTravelTo(pos.east()) || canTravelTo(pos.west()) || canTravelTo(pos.north()) || canTravelTo(pos.south());
+    }
+
+    private boolean canTravelTo(BlockPos pos) {
+        net.minecraft.world.level.pathfinder.Path to = navigation.createPath(pos, 0);
+        return to != null && to.nodes.size() > 0;
+    }
     // Purpur end
 
     @Override
@@ -283,6 +300,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
     protected void mobTick(boolean inactive) {
         this.level.getProfiler().push("villagerBrain");
         // Purpur start
+        if (level.purpurConfig.villagerLobotomizeEnabled) inactive = inactive || isLobotomized();
         boolean tick = (level.getGameTime() + brainTickOffset) % level.purpurConfig.villagerBrainTicks == 0;
         if (((ServerLevel) level).getServer().lagging ? tick : level.purpurConfig.villagerUseBrainTicksOnlyWhenLagging || tick)
         // Purpur end
@@ -292,6 +310,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
             this.getBrain().tick((ServerLevel) this.level, this);
          }
         // Airplane end
+        else if (shouldRestock()) restock(); // Purpur
         this.level.getProfiler().pop();
         if (this.assignProfessionWhenSpawned) {
             this.assignProfessionWhenSpawned = false;
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
index b7d6a9d783d306a88e162bf13fa7d9d8f8a21fd0..076e0ebdcb5334a4d89d53e31aa751ccf7df2ea2 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -1647,6 +1647,8 @@ public class PurpurWorldConfig {
     public int villagerSpawnIronGolemLimit = 0;
     public boolean villagerCanBreed = true;
     public int villagerBreedingTicks = 6000;
+    public boolean villagerLobotomizeEnabled = false;
+    public int villagerLobotomizeCheck = 60;
     private void villagerSettings() {
         villagerRidable = getBoolean("mobs.villager.ridable", villagerRidable);
         villagerRidableInWater = getBoolean("mobs.villager.ridable-in-water", villagerRidableInWater);
@@ -1664,6 +1666,13 @@ public class PurpurWorldConfig {
         villagerSpawnIronGolemLimit = getInt("mobs.villager.spawn-iron-golem.limit", villagerSpawnIronGolemLimit);
         villagerCanBreed = getBoolean("mobs.villager.can-breed", villagerCanBreed);
         villagerBreedingTicks = getInt("mobs.villager.breeding-delay-ticks", villagerBreedingTicks);
+        if (PurpurConfig.version < 9) {
+            boolean oldValue = getBoolean("mobs.villager.lobotomize-1x1", villagerLobotomizeEnabled);
+            set("mobs.villager.lobotomize.enabled", oldValue);
+            set("mobs.villager.lobotomize-1x1", null);
+        }
+        villagerLobotomizeEnabled = getBoolean("mobs.villager.lobotomize.enabled", villagerLobotomizeEnabled);
+        villagerLobotomizeCheck = getInt("mobs.villager.lobotomize.check-interval", villagerLobotomizeCheck);
     }
 
     public boolean vindicatorRidable = false;
