From ac45dec5442cbf485b3e446349fe7e6856847394 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Thu, 3 Nov 2022 00:23:03 +0000 Subject: [PATCH] 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 b256d3de12..36c44856bd 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