From 17e3e83f4336fd832da29f05a0c43b4a76801b29 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Wed, 2 Nov 2022 22:27:45 +0000 Subject: [PATCH 1/8] Villagers should not try and path if they have failed recently --- mods/ENTITIES/mcl_mobs/api.lua | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index e8c8a3618..7591b0af8 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -2663,6 +2663,7 @@ local function check_gowp(self,dtime) self.current_target = nil self.waypoints = nil self._target = nil + self._pf_last_failed = os.time() self.object:set_velocity({x = 0, y = 0, z = 0}) self.object:set_acceleration({x = 0, y = 0, z = 0}) return @@ -3463,9 +3464,15 @@ function mcl_mobs:gopath(self,target,callback_arrived) end gopath_last = os.time() + if self._pf_last_failed and (os.time() - self._pf_last_failed) < 60 then + mcl_log("We are not ready to path as last fail is less than threshold: " .. (os.time() - self._pf_last_failed)) + return + else + mcl_log("We are ready to pathfind, no previous fail or we are past threshold") + end + self.order = nil - --mcl_log("gowp target: " .. minetest.pos_to_string(target)) local p = self.object:get_pos() local t = vector.offset(target,0,1,0) @@ -3484,21 +3491,15 @@ function mcl_mobs:gopath(self,target,callback_arrived) else mcl_log("Nil pos") end - --current_location = table.remove(wp,1) - --if current_location and current_location["pos"] then - -- mcl_log("Removing first co-ord? " .. tostring(current_location["pos"])) - --else - -- mcl_log("Nil pos") - --end self.current_target = current_location self.waypoints = wp self.state = PATHFINDING return true else - self.state = "walk" - self.waypoints = nil - self.current_target = nil - -- minetest.log("no path found") + self.state = "walk" + self.waypoints = nil + self.current_target = nil + -- minetest.log("no path found") end end From 5866983bf5facb5d7bc9a39fff2c1badd28f92f6 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Wed, 2 Nov 2022 23:06:10 +0000 Subject: [PATCH 2/8] Villager will try to take the job block closest to them --- mods/ENTITIES/mobs_mc/villager.lua | 56 ++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/villager.lua b/mods/ENTITIES/mobs_mc/villager.lua index 440a5d127..b256d3de1 100644 --- a/mods/ENTITIES/mobs_mc/villager.lua +++ b/mods/ENTITIES/mobs_mc/villager.lua @@ -847,6 +847,7 @@ end local function look_for_job(self, requested_jobsites) mcl_log("Looking for jobs") + -- This logic is done twice. Remove this. local looking_for_type = jobsites if requested_jobsites then --mcl_log("Looking for jobs of my type: " .. tostring(requested_jobsites)) @@ -858,34 +859,51 @@ local function look_for_job(self, requested_jobsites) local p = self.object:get_pos() local nn = minetest.find_nodes_in_area(vector.offset(p,-48,-48,-48),vector.offset(p,48,48,48), looking_for_type) + local distance_to_closest_block = nil + local closest_block = nil + --Ideally should check for closest available. It'll make pathing easier. - for _,n in pairs(nn) do + for i,n in pairs(nn) do local m = minetest.get_meta(n) - --mcl_log("Job owner: ".. m:get_string("villager")) + mcl_log("Block: " .. minetest.pos_to_string(n).. "Job owner: ".. m:get_string("villager")) if m:get_string("villager") == "" then - mcl_log("It's a free job for me (".. minetest.pos_to_string(p) .. ")! I might be interested: "..minetest.pos_to_string(n) ) + -- Distance check + local distance_to_block = vector.distance(self.object:get_pos(), n) + mcl_log("Distance to block ".. i .. ": ".. distance_to_block) - local gp = mcl_mobs:gopath(self,n,function(self) - mcl_log("Arrived at block callback") - if self and self.state == "stand" then - self.order = WORK - else - mcl_log("no self. passing param to callback failed") - end - - end) - if gp then - if n then - mcl_log("We can path to this block.. " .. tostring(n)) - end - return n - else - mcl_log("We could not path to block or it's not ready to path yet.") + if not distance_to_closest_block or distance_to_closest_block > distance_to_block then + mcl_log("This block is closer than the last.") + closest_block = n + distance_to_closest_block = distance_to_block end end end + if closest_block then + mcl_log("It's a free job for me (" .. minetest.pos_to_string(p) .. ")! I might be interested: ".. minetest.pos_to_string(closest_block) ) + + local gp = mcl_mobs:gopath(self, closest_block,function(self) + mcl_log("Arrived at block callback") + if self and self.state == "stand" then + self.order = WORK + else + mcl_log("no self. passing param to callback failed") + end + end) + + if gp then + if closest_block then + mcl_log("We can path to this block.. " .. tostring(closest_block)) + end + return closest_block + else + mcl_log("We could not path to block or it's not ready to path yet.") + end + else + mcl_log("We don't have a job block to path to") + end + return nil end From ea9c9e74b09040e5650a6abd939e9ffe5dd1e469 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Thu, 3 Nov 2022 00:22:05 +0000 Subject: [PATCH 3/8] Failed check should come before last pathed check to avoid a failed check taking up a good opportunity to path --- mods/ENTITIES/mcl_mobs/api.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 7591b0af8..4687a6b0b 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -3458,12 +3458,6 @@ local gopath_last = os.time() function mcl_mobs:gopath(self,target,callback_arrived) if self.state == PATHFINDING then mcl_log("Already pathfinding, don't set another until done.") return end - if os.time() - gopath_last < 5 then - mcl_log("Not ready to path yet") - return - end - gopath_last = os.time() - if self._pf_last_failed and (os.time() - self._pf_last_failed) < 60 then mcl_log("We are not ready to path as last fail is less than threshold: " .. (os.time() - self._pf_last_failed)) return @@ -3471,6 +3465,12 @@ function mcl_mobs:gopath(self,target,callback_arrived) mcl_log("We are ready to pathfind, no previous fail or we are past threshold") end + if os.time() - gopath_last < 5 then + mcl_log("Not ready to path yet") + return + end + gopath_last = os.time() + self.order = nil local p = self.object:get_pos() From ac45dec5442cbf485b3e446349fe7e6856847394 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Thu, 3 Nov 2022 00:23:03 +0000 Subject: [PATCH 4/8] Villager should find the closest bed to claim --- mods/ENTITIES/mobs_mc/villager.lua | 102 +++++++++++++---------------- 1 file changed, 45 insertions(+), 57 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/villager.lua b/mods/ENTITIES/mobs_mc/villager.lua index b256d3de1..36c44856b 100644 --- a/mods/ENTITIES/mobs_mc/villager.lua +++ b/mods/ENTITIES/mobs_mc/villager.lua @@ -578,10 +578,9 @@ function get_activity(tod) end tod = ( tod * 24000 ) % 24000 - - local lunch_start = 12000 + local lunch_start = 11000 local lunch_end = 13500 - local work_start = 8500 + local work_start = 7000 local work_end = 16500 local activity = nil @@ -602,6 +601,30 @@ function get_activity(tod) end +local function find_closest_unclaimed_block (p, requested_block_types) + local nn = minetest.find_nodes_in_area(vector.offset(p,-48,-48,-48),vector.offset(p,48,48,48), requested_block_types) + + local distance_to_closest_block = nil + local closest_block = nil + + for i,n in pairs(nn) do + local m = minetest.get_meta(n) + mcl_log("Block: " .. minetest.pos_to_string(n).. ", owner: ".. m:get_string("villager")) + + if m:get_string("villager") == "" then + local distance_to_block = vector.distance(p, n) + mcl_log("Distance to block ".. i .. ": ".. distance_to_block) + + if not distance_to_closest_block or distance_to_closest_block > distance_to_block then + mcl_log("This block is closer than the last.") + closest_block = n + distance_to_closest_block = distance_to_block + end + end + end + return closest_block +end + local function check_bed (entity) local b = entity._bed if not b then @@ -677,33 +700,29 @@ local function take_bed (entity) if not entity then return end local p = entity.object:get_pos() - local nn = minetest.find_nodes_in_area(vector.offset(p,-48,-48,-48), vector.offset(p,48,48,48), spawnable_bed) - for _,n in pairs(nn) do - local m=minetest.get_meta(n) - --mcl_log("Bed owner: ".. m:get_string("villager")) - if m:get_string("villager") == "" and not (entity.state == PATHFINDING) then - mcl_log("Can we path to bed: "..minetest.pos_to_string(n) ) - local gp = mcl_mobs:gopath(entity,n,function(self) - if self then - self.order = "sleep" - mcl_log("Sleepy time" ) - else - mcl_log("Can't sleep, no self in the callback" ) - end - end) - if gp then - mcl_log("Nice bed. I'll defintely take it as I can path") - m:set_string("villager", entity._id) - entity._bed = n - break + local closest_block = find_closest_unclaimed_block (p, spawnable_bed) + + if closest_block then + local m = minetest.get_meta(closest_block) + mcl_log("Can we path to bed: "..minetest.pos_to_string(closest_block) ) + local gp = mcl_mobs:gopath(entity, closest_block,function(self) + if self then + self.order = SLEEP + mcl_log("Sleepy time" ) else - mcl_log("Awww. I can't find my bed.") + mcl_log("Can't sleep, no self in the callback" ) end + end) + if gp then + mcl_log("Nice bed. I'll defintely take it as I can path") + m:set_string("villager", entity._id) + entity._bed = closest_block else - mcl_log("Currently gowp, or it's taken: ".. m:get_string("villager")) + mcl_log("Awww. I can't find my bed.") end end + end local function has_golem(pos) @@ -847,38 +866,9 @@ end local function look_for_job(self, requested_jobsites) mcl_log("Looking for jobs") - -- This logic is done twice. Remove this. - local looking_for_type = jobsites - if requested_jobsites then - --mcl_log("Looking for jobs of my type: " .. tostring(requested_jobsites)) - looking_for_type = requested_jobsites - else - mcl_log("Looking for any job type") - end - local p = self.object:get_pos() - local nn = minetest.find_nodes_in_area(vector.offset(p,-48,-48,-48),vector.offset(p,48,48,48), looking_for_type) - local distance_to_closest_block = nil - local closest_block = nil - - --Ideally should check for closest available. It'll make pathing easier. - for i,n in pairs(nn) do - local m = minetest.get_meta(n) - mcl_log("Block: " .. minetest.pos_to_string(n).. "Job owner: ".. m:get_string("villager")) - - if m:get_string("villager") == "" then - -- Distance check - local distance_to_block = vector.distance(self.object:get_pos(), n) - mcl_log("Distance to block ".. i .. ": ".. distance_to_block) - - if not distance_to_closest_block or distance_to_closest_block > distance_to_block then - mcl_log("This block is closer than the last.") - closest_block = n - distance_to_closest_block = distance_to_block - end - end - end + local closest_block = find_closest_unclaimed_block(p, requested_jobsites) if closest_block then mcl_log("It's a free job for me (" .. minetest.pos_to_string(p) .. ")! I might be interested: ".. minetest.pos_to_string(closest_block) ) @@ -1070,7 +1060,7 @@ end local function do_activity (self) -- Maybe just check we're pathfinding first? - if not self._bed then + if not self._bed and self.state ~= PATHFINDING then --mcl_log("Villager has no bed. Currently at location: "..minetest.pos_to_string(self.object:get_pos())) take_bed (self) end @@ -1081,7 +1071,6 @@ local function do_activity (self) wandered_too_far = ( self.state ~= PATHFINDING ) and (vector.distance(self.object:get_pos(),self._bed) > 50 ) end - if wandered_too_far then --mcl_log("Wandered too far! Return home ") go_home(self, false) @@ -1092,7 +1081,6 @@ local function do_activity (self) elseif get_activity() == GATHERING then go_to_town_bell(self) else - -- gossip at town bell or stroll around mcl_log("No order, so remove it.") self.order = nil end From ad137304bce58faca628b280f98751be294ba0fa Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Thu, 3 Nov 2022 01:00:48 +0000 Subject: [PATCH 5/8] Fix bug where if it finds wrong door and can't plot route it hogs the pathing --- mods/ENTITIES/mcl_mobs/api.lua | 3 +++ mods/ENTITIES/mobs_mc/villager.lua | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 4687a6b0b..96381dde6 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -3409,6 +3409,7 @@ local function calculate_path_through_door (p, t, target) if not wp then mcl_log("No direct path. Path through door") + -- This could improve. There could be multiple doors. Check you can path from door to target first. local cur_door_pos = minetest.find_node_near(target,16,{"group:door"}) if cur_door_pos then mcl_log("Found a door near: " .. minetest.pos_to_string(cur_door_pos)) @@ -3479,6 +3480,8 @@ function mcl_mobs:gopath(self,target,callback_arrived) local wp = calculate_path_through_door(p, t, target) if not wp then mcl_log("Could not calculate path") + self._pf_last_failed = os.time() + -- Cover for a flaw in pathfind where it chooses the wrong door and gets stuck. Take a break, allow others. end --output_table(wp) diff --git a/mods/ENTITIES/mobs_mc/villager.lua b/mods/ENTITIES/mobs_mc/villager.lua index 36c44856b..4bf174c35 100644 --- a/mods/ENTITIES/mobs_mc/villager.lua +++ b/mods/ENTITIES/mobs_mc/villager.lua @@ -609,9 +609,10 @@ local function find_closest_unclaimed_block (p, requested_block_types) for i,n in pairs(nn) do local m = minetest.get_meta(n) - mcl_log("Block: " .. minetest.pos_to_string(n).. ", owner: ".. m:get_string("villager")) if m:get_string("villager") == "" then + mcl_log("Block: " .. minetest.pos_to_string(n).. ", owner: ".. m:get_string("villager")) + local distance_to_block = vector.distance(p, n) mcl_log("Distance to block ".. i .. ": ".. distance_to_block) From 2d0ea5e205237f99d197cf4481846f320e87675d Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Thu, 3 Nov 2022 21:15:27 +0000 Subject: [PATCH 6/8] Enable concurrent pathing so pathing orders aren't queued --- mods/ENTITIES/mcl_mobs/api.lua | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 96381dde6..f11d98a1a 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -2607,8 +2607,9 @@ local function check_gowp(self,dtime) -- 0.1 is optimal. --less frequently = villager will get sent back after passing a point. --more frequently = villager will fail points they shouldn't they just didn't get there yet - if gowp_etime < 0.1 then return end - gowp_etime = 0 + + --if gowp_etime < 0.05 then return end + --gowp_etime = 0 local p = self.object:get_pos() -- no destination @@ -3466,11 +3467,11 @@ function mcl_mobs:gopath(self,target,callback_arrived) mcl_log("We are ready to pathfind, no previous fail or we are past threshold") end - if os.time() - gopath_last < 5 then - mcl_log("Not ready to path yet") - return - end - gopath_last = os.time() + --if os.time() - gopath_last < 5 then + -- mcl_log("Not ready to path yet") + -- return + --end + --gopath_last = os.time() self.order = nil From 8b0c4c17adf79c88d20326db7be350f0a067583c Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Thu, 3 Nov 2022 21:27:59 +0000 Subject: [PATCH 7/8] Slightly more frequent failed pathing attempts for villagers --- mods/ENTITIES/mcl_mobs/api.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index f11d98a1a..42dad6a06 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -2607,7 +2607,7 @@ local function check_gowp(self,dtime) -- 0.1 is optimal. --less frequently = villager will get sent back after passing a point. --more frequently = villager will fail points they shouldn't they just didn't get there yet - + --if gowp_etime < 0.05 then return end --gowp_etime = 0 local p = self.object:get_pos() @@ -3460,7 +3460,7 @@ local gopath_last = os.time() function mcl_mobs:gopath(self,target,callback_arrived) if self.state == PATHFINDING then mcl_log("Already pathfinding, don't set another until done.") return end - if self._pf_last_failed and (os.time() - self._pf_last_failed) < 60 then + if self._pf_last_failed and (os.time() - self._pf_last_failed) < 30 then mcl_log("We are not ready to path as last fail is less than threshold: " .. (os.time() - self._pf_last_failed)) return else From 32e4a122a1d53393c10d128e91c9f0fa5a203f73 Mon Sep 17 00:00:00 2001 From: cora Date: Sat, 5 Nov 2022 01:14:54 +0100 Subject: [PATCH 8/8] Comment out stray debug lines --- mods/ENTITIES/mobs_mc/villager.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/villager.lua b/mods/ENTITIES/mobs_mc/villager.lua index 4bf174c35..5e547c884 100644 --- a/mods/ENTITIES/mobs_mc/villager.lua +++ b/mods/ENTITIES/mobs_mc/villager.lua @@ -1776,12 +1776,12 @@ mcl_mobs:register_mob("mobs_mc:villager", { self._trading_players[name] = true if self._trades == nil or self._trades == false then - minetest.log("Trades is nil so init") + --minetest.log("Trades is nil so init") init_trades(self) end update_max_tradenum(self) if self._trades == false then - minetest.log("Trades is false. no right click op") + --minetest.log("Trades is false. no right click op") -- Villager has no trades, rightclick is a no-op return end