
VillageAI
Intelligent village defense system. Villages centered on bells automatically detect nearby villagers. Friendly players gain reputation by trading. Hostile players lose reputation by attacking villagers. When hostile players are nearby reputation drops belo
Список изменений
[2.1.1] - 2026-03-11 - Bug Fix Release
🐛 Bug Fixes
-
Village data lost on restart —
loadVillagesAsync()andvalidateVillageData()checked for a"villages"YAML section that was never written; data is saved at root level ("village-0","village-1", …). Both methods now iterate root keys directly, so all villages survive server restarts. -
Data loss on shutdown (async save race) —
onDisable()calledsaveVillages()which usedCompletableFuture.supplyAsync(). On server shutdown, the JVM kills thread pools before async tasks complete, silently discarding the save.onDisable()now calls a new synchronoussaveVillagesSync()method that blocks until the file is written. -
VillageValidatorNPE on class load —private static final Logger logger = VillageAIPlugin.getInstance().getLogger()was evaluated when the class was first loaded by the JVM — potentially beforeonEnable()sets the instance — causing aNullPointerException. Replaced with a lazylogger()method that reads the instance at call time. -
/vtrade acceptalways returned "Quest not found" — The command displayed only the first 8 characters of the quest UUID (e.g.a1b2c3d4), then tried to reconstruct a full UUID by appending"-0000-0000-0000-000000000000". This produced a UUID that never matched any quest./vtrade questsnow shows the full UUID, and/vtrade acceptparses it directly without reconstruction. -
VillageManager.restoreVillage()did not populatevillagerToVillagemap — Members were written directly into theVillageset, bypassingaddMember(). After a restart,getVillageOf(villager)always returnednullfor all loaded villagers.restoreVillage()now iterates restored members and inserts them into the map.
⚠️ Minor Fixes
-
ECONOMY_UPDATE_INTERVAL = 24000was 24 000 ms (24 seconds), not 24 hours as the comment stated. Changed to86_400_000L. -
VillageEconomy.getVillageUUID()returned world UUID — every village in the same world shared the same economy UUID, making trade offers indistinguishable across villages. Now derives a deterministic per-village UUID from the village's coordinate-based ID string. -
updateAllPrices()andgenerateTradeOffers()looped all~1000 Materialvalues on every economy update. Both methods now only iterate materials actively tracked inSupplyData, reducing unnecessary CPU work. -
DeliveryQuest.onReward()never gave emeralds — only sent a chat message. Emeralds are now added to the player's inventory (or dropped at their feet if the inventory is full). -
Dead field
VillagerNameManager.villageManagers— declared but never read or written. Removed.
