mirror of
https://github.com/PurpurMC/Purpur.git
synced 2026-02-17 16:37:43 +01:00
Upstream has released updates that appear to apply and compile correctly Paper Changes: PaperMC/Paper@de3f149 Fix possible NPE on painting creation (#9391) PaperMC/Paper@fe780d0 Add back accidentally dropped Wandering Trader patch (#9492) PaperMC/Paper@b533905 fix 2 vanilla issues (#8940)
142 lines
7.3 KiB
Diff
142 lines
7.3 KiB
Diff
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 0d817148dedd9919e6e1dd0c38c96a57ad919ced..3eb7ac97ea11d0c47ecbc047e2e64c17baaa70f4 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
|
|
@@ -140,6 +140,8 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
|
}, MemoryModuleType.MEETING_POINT, (entityvillager, holder) -> {
|
|
return holder.is(PoiTypes.MEETING);
|
|
});
|
|
+ private boolean isLobotomized = false; public boolean isLobotomized() { return this.isLobotomized; } // Purpur
|
|
+ private int notLobotomizedCount = 0; // Purpur
|
|
|
|
public long nextGolemPanic = -1; // Pufferfish
|
|
|
|
@@ -199,6 +201,47 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
|
return this.level().purpurConfig.villagerAlwaysDropExp;
|
|
}
|
|
|
|
+ private boolean checkLobotomized() {
|
|
+ int interval = this.level().purpurConfig.villagerLobotomizeCheckInterval;
|
|
+ if (this.notLobotomizedCount > 3) {
|
|
+ // check half as often if not lobotomized for the last 3+ consecutive checks
|
|
+ interval *= 2;
|
|
+ }
|
|
+ if (this.level().getGameTime() % interval == 0) {
|
|
+ // offset Y for short blocks like dirt_path/farmland
|
|
+ this.isLobotomized = !canTravelFrom(BlockPos.containing(this.position().x, this.getBoundingBox().minY + 0.0625D, this.position().z));
|
|
+
|
|
+ if (this.isLobotomized) {
|
|
+ this.notLobotomizedCount = 0;
|
|
+ } else {
|
|
+ this.notLobotomizedCount++;
|
|
+ }
|
|
+ }
|
|
+ return this.isLobotomized;
|
|
+ }
|
|
+
|
|
+ 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.block.state.BlockState state = this.level().getBlockStateIfLoaded(pos);
|
|
+ if (state == null) {
|
|
+ // chunk not loaded
|
|
+ return false;
|
|
+ }
|
|
+ net.minecraft.world.level.block.Block bottom = state.getBlock();
|
|
+ if (bottom instanceof net.minecraft.world.level.block.FenceBlock ||
|
|
+ bottom instanceof net.minecraft.world.level.block.FenceGateBlock ||
|
|
+ bottom instanceof net.minecraft.world.level.block.WallBlock) {
|
|
+ // bottom block is too tall to get over
|
|
+ return false;
|
|
+ }
|
|
+ net.minecraft.world.level.block.Block top = level().getBlockState(pos.above()).getBlock();
|
|
+ // only if both blocks have no collision
|
|
+ return !bottom.hasCollision && !top.hasCollision;
|
|
+ }
|
|
+
|
|
@Override
|
|
public Brain<Villager> getBrain() {
|
|
return (Brain<Villager>) super.getBrain(); // CraftBukkit - decompile error
|
|
@@ -296,14 +339,21 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
|
// Paper start
|
|
this.customServerAiStep(false);
|
|
}
|
|
- protected void customServerAiStep(final boolean inactive) {
|
|
+ protected void customServerAiStep(boolean inactive) { // Purpur - not final
|
|
// Paper end
|
|
this.level().getProfiler().push("villagerBrain");
|
|
- // Pufferfish start
|
|
- if (!inactive && (getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) { // Purpur - only use brain if no rider
|
|
- this.getBrain().tick((ServerLevel) this.level(), this); // Paper
|
|
+ // Purpur start
|
|
+ if (this.level().purpurConfig.villagerLobotomizeEnabled) {
|
|
+ // treat as inactive if lobotomized
|
|
+ inactive = inactive || checkLobotomized();
|
|
+ } else {
|
|
+ // clean up state for API
|
|
+ this.isLobotomized = false;
|
|
}
|
|
- // Pufferfish end
|
|
+ if (!inactive && (getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Purpur - only use brain if no rider
|
|
+ this.getBrain().tick((ServerLevel) this.level(), this); // Paper
|
|
+ else if (this.isLobotomized && shouldRestock()) restock();
|
|
+ // Purpur end
|
|
this.level().getProfiler().pop();
|
|
if (this.assignProfessionWhenSpawned) {
|
|
this.assignProfessionWhenSpawned = false;
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
|
|
index f21c715ea109164efa755cddb35ef656a9859759..0c9154d1d3c1534a25c08c75fab102b68958fab9 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
|
|
@@ -222,4 +222,11 @@ public class CraftVillager extends CraftAbstractVillager implements Villager {
|
|
getHandle().getGossips().gossips.clear();
|
|
}
|
|
// Paper end
|
|
+
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isLobotomized() {
|
|
+ return getHandle().isLobotomized();
|
|
+ }
|
|
+ // Purpur end
|
|
}
|
|
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
|
|
index 9d9bb2a758df0363e898bced7f5edad8afe3c55c..ef335cde8f7fb9f3b85a8eb67d35b71535d9321a 100644
|
|
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
|
|
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
|
|
@@ -2711,6 +2711,8 @@ public class PurpurWorldConfig {
|
|
public boolean villagerAllowTrading = true;
|
|
public boolean villagerAlwaysDropExp = false;
|
|
public int villagerMinimumDemand = 0;
|
|
+ public boolean villagerLobotomizeEnabled = false;
|
|
+ public int villagerLobotomizeCheckInterval = 100;
|
|
private void villagerSettings() {
|
|
villagerRidable = getBoolean("mobs.villager.ridable", villagerRidable);
|
|
villagerRidableInWater = getBoolean("mobs.villager.ridable-in-water", villagerRidableInWater);
|
|
@@ -2732,6 +2734,17 @@ public class PurpurWorldConfig {
|
|
villagerAllowTrading = getBoolean("mobs.villager.allow-trading", villagerAllowTrading);
|
|
villagerAlwaysDropExp = getBoolean("mobs.villager.always-drop-exp", villagerAlwaysDropExp);
|
|
villagerMinimumDemand = getInt("mobs.villager.minimum-demand", villagerMinimumDemand);
|
|
+ if (PurpurConfig.version < 9) {
|
|
+ boolean oldValue = getBoolean("mobs.villager.lobotomize-1x1", villagerLobotomizeEnabled);
|
|
+ set("mobs.villager.lobotomize.enabled", oldValue);
|
|
+ set("mobs.villager.lobotomize-1x1", null);
|
|
+ }
|
|
+ if (PurpurConfig.version < 27) {
|
|
+ int oldValue = getInt("mobs.villager.lobotomize.check-interval", villagerLobotomizeCheckInterval);
|
|
+ set("mobs.villager.lobotomize.check-interval", oldValue == 60 ? 100 : oldValue);
|
|
+ }
|
|
+ villagerLobotomizeEnabled = getBoolean("mobs.villager.lobotomize.enabled", villagerLobotomizeEnabled);
|
|
+ villagerLobotomizeCheckInterval = getInt("mobs.villager.lobotomize.check-interval", villagerLobotomizeCheckInterval);
|
|
}
|
|
|
|
public boolean vindicatorRidable = false;
|