Files
Purpur/patches/server/0224-Lobotomize-stuck-villagers.patch
granny 20e182a936 Updated Upstream (Paper)
Upstream has released updates that appear to apply and compile correctly

Paper Changes:
PaperMC/Paper@730882f Chunk System and Starlight WIP
PaperMC/Paper@512fd08 Update Gradle Wrapper to v8.8
PaperMC/Paper@097284d Bump tiny-remapper to 0.10.3
PaperMC/Paper@ee9b820 Update more optimization patches
PaperMC/Paper@5d834b1 rebuild patches
PaperMC/Paper@4bc15f1 Updated Upstream (Bukkit/CraftBukkit)
PaperMC/Paper@0b6701d Revert DamageSource#getCausingEntity to vanilla
PaperMC/Paper@5bd7f4e Update AbstractArrow item method implementations for 1.20.6 (#10885)
PaperMC/Paper@fb511c6 Fix Player#sendBlockState (#10855)
PaperMC/Paper@b420038 Fix ItemMeta#removeEnchantments (#10886)
PaperMC/Paper@a835ad1 Merge remote-tracking branch 'origin/dev/1.21' into dev/1.21
PaperMC/Paper@04dad71 Improve enchantWithLevels logic
PaperMC/Paper@0008fa1 Add back more optimization patches
PaperMC/Paper@56b5b7d Fix max chunk status checks
PaperMC/Paper@c1aefee correctly change enchantment registry to a 'delayed' version
PaperMC/Paper@d41636f Add back RecipeIterator fixes patch (#10887)
PaperMC/Paper@7df4725 Configurable damage tick when blocking with shield (#10877)
PaperMC/Paper@3555a77 Properly forward DispenseEvent #getItem to saddle
PaperMC/Paper@e339ec2 Deprecate BlockData#getDestroySpeed for removal
PaperMC/Paper@b090c65 Remove unnecessary changes from chunk status fix
PaperMC/Paper@5e7cd07 add some generated typed/tag keys
PaperMC/Paper@5a5412c Owen fixing stuff!!!
PaperMC/Paper@7240d9d Restore functionality to sand dupe setting
2024-06-15 23:01:19 -07:00

139 lines
7.4 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 de09bae637ea8637d13b55cd406d5dd2de72b00d..92b2dfd2d4013ab6ae1114ab319c7bdaf674afe1 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,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 Villager(EntityType<? extends Villager> entityType, Level world) {
this(entityType, world, VillagerType.PLAINS);
@@ -194,6 +196,48 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
return this.level().purpurConfig.villagerAlwaysDropExp;
}
+ private boolean checkLobotomized() {
+ int interval = this.level().purpurConfig.villagerLobotomizeCheckInterval;
+ boolean shouldCheckForTradeLocked = this.level().purpurConfig.villagerLobotomizeWaitUntilTradeLocked;
+ 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 = !(shouldCheckForTradeLocked && this.getVillagerXp() == 0) && !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
@@ -290,10 +334,19 @@ 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");
+ // Purpur start
+ if (this.level().purpurConfig.villagerLobotomizeEnabled) {
+ // treat as inactive if lobotomized
+ inactive = inactive || checkLobotomized();
+ } else {
+ this.isLobotomized = false;
+ }
+ // Purpur end
if (!inactive) this.getBrain().tick((ServerLevel) this.level(), this); // Paper
+ else if (this.isLobotomized && shouldRestock()) restock(); // Purpur
/*// Purpur start // Purpur - TODO: Pufferfish
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
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
index 6c15d40979fd3e3d246a447c432b321fbf29ada3..6ace76a829c88e2e747dbbcce0a6582c615fc56d 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
@@ -252,4 +252,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 20c17408972b37cc5504661b8ff43a0f971fd45f..cc1a55ed607cac6d47ab92dbd93c06c791c8e9ce 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -2798,6 +2798,9 @@ public class PurpurWorldConfig {
public boolean villagerAllowTrading = true;
public boolean villagerAlwaysDropExp = false;
public int villagerMinimumDemand = 0;
+ public boolean villagerLobotomizeEnabled = false;
+ public int villagerLobotomizeCheckInterval = 100;
+ public boolean villagerLobotomizeWaitUntilTradeLocked = false;
private void villagerSettings() {
villagerRidable = getBoolean("mobs.villager.ridable", villagerRidable);
villagerRidableInWater = getBoolean("mobs.villager.ridable-in-water", villagerRidableInWater);
@@ -2818,6 +2821,18 @@ 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);
+ villagerLobotomizeWaitUntilTradeLocked = getBoolean("mobs.villager.lobotomize.wait-until-trade-locked", villagerLobotomizeWaitUntilTradeLocked);
}
public boolean vindicatorRidable = false;