diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index e8c8a36180..42dad6a068 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 @@ -2663,6 +2664,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 @@ -3408,6 +3410,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)) @@ -3457,21 +3460,29 @@ 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") + 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 + mcl_log("We are ready to pathfind, no previous fail or we are past threshold") 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 - --mcl_log("gowp target: " .. minetest.pos_to_string(target)) local p = self.object:get_pos() local t = vector.offset(target,0,1,0) 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) @@ -3484,21 +3495,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 diff --git a/mods/ENTITIES/mobs_mc/villager.lua b/mods/ENTITIES/mobs_mc/villager.lua index 440a5d127e..5e547c8844 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,31 @@ 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) + + 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) + + 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 +701,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,43 +867,32 @@ end local function look_for_job(self, requested_jobsites) mcl_log("Looking for jobs") - 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) - --Ideally should check for closest available. It'll make pathing easier. - for _,n in pairs(nn) do - local m = minetest.get_meta(n) - --mcl_log("Job owner: ".. m:get_string("villager")) + local closest_block = find_closest_unclaimed_block(p, requested_jobsites) - 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) ) + 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,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 + 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("We could not path to block or it's not ready to path yet.") + 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 @@ -1052,7 +1061,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 @@ -1063,7 +1072,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) @@ -1074,7 +1082,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 @@ -1769,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