From 29cd73cb84f641267b52ddcff54fa65a64dfe6c1 Mon Sep 17 00:00:00 2001
From: ancientmarinerdev <ancientmariner_dev@proton.me>
Date: Fri, 30 Dec 2022 04:15:59 +0000
Subject: [PATCH] Pathfinding through door should also check door closest to
 position so villager can leave current house

---
 mods/ENTITIES/mcl_mobs/pathfinding.lua | 154 +++++++++++++------------
 1 file changed, 81 insertions(+), 73 deletions(-)

diff --git a/mods/ENTITIES/mcl_mobs/pathfinding.lua b/mods/ENTITIES/mcl_mobs/pathfinding.lua
index 5f70760da..f89f4a323 100644
--- a/mods/ENTITIES/mcl_mobs/pathfinding.lua
+++ b/mods/ENTITIES/mcl_mobs/pathfinding.lua
@@ -35,11 +35,11 @@ function append_paths (wp1, wp2)
 end
 
 local function output_enriched (wp_out)
-	--mcl_log("Output enriched path")
+	mcl_log("Output enriched path")
 	local i = 0
 	for _,outy in pairs (wp_out) do
 		i = i + 1
-		--mcl_log("Pos ".. i ..":" .. minetest.pos_to_string(outy["pos"]))
+		mcl_log("Pos ".. i ..":" .. minetest.pos_to_string(outy["pos"]))
 
 		local action =  outy["action"]
 		if action then
@@ -109,76 +109,6 @@ local plane_adjacents = {
 	vector.new(0,0,-1),
 }
 
--- This function is used to see if we can path. We could use to check a route, rather than making people move.
-local function calculate_path_through_door (p, t, target)
-	-- target is the same as t, just 1 square difference. Maybe we don't need target
-	mcl_log("Plot route from mob: " .. minetest.pos_to_string(p) .. ", to target: " .. minetest.pos_to_string(t))
-
-	local enriched_path = nil
-
-	local cur_door_pos = nil
-	local pos_closest_to_door = nil
-	local other_side_of_door = nil
-
-	--Check direct route
-	local wp = minetest.find_path(p,t,150,1,4)
-
-	--Path to door first
-	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.
-
-		-- target could be pos
-		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))
-			for _,v in pairs(plane_adjacents) do
-				pos_closest_to_door = vector.add(cur_door_pos,v)
-				local n = minetest.get_node(pos_closest_to_door)
-				if n.name == "air" then
-
-					wp = minetest.find_path(p,pos_closest_to_door,150,1,4)
-					if wp then
-
-						mcl_log("Found a path to next to door".. minetest.pos_to_string(pos_closest_to_door))
-						other_side_of_door = vector.add(cur_door_pos,-v)
-						mcl_log("Opposite is: ".. minetest.pos_to_string(other_side_of_door))
-
-						local wp_otherside_door_to_target = minetest.find_path(other_side_of_door,t,150,1,4)
-						if wp_otherside_door_to_target and #wp_otherside_door_to_target > 0 then
-							table.insert(wp, cur_door_pos)
-							append_paths (wp, wp_otherside_door_to_target)
-							enriched_path = generate_enriched_path(wp, pos_closest_to_door, other_side_of_door, cur_door_pos)
-							mcl_log("We have a path from outside door to target")
-						else
-							mcl_log("We cannot path from outside door to target")
-						end
-						break
-					else
-						mcl_log("This block next to door doesn't work.")
-					end
-				else
-					--mcl_log("Block is not air, it is: ".. n.name)
-				end
-
-			end
-		else
-			mcl_log("No door found")
-		end
-	else
-		mcl_log("We have a direct route")
-	end
-
-	-- If not, get door near pos
-	--path from pos to door, path from otherside to target
-
-	if wp and not enriched_path then
-		enriched_path = generate_enriched_path(wp)
-	end
-	return enriched_path
-end
-
 --local gopath_last = os.time()
 
 function mob_class:ready_to_path()
@@ -191,6 +121,63 @@ function mob_class:ready_to_path()
 	end
 end
 
+-- This function is used to see if we can path. We could use to check a route, rather than making people move.
+local function calculate_path_through_door (p, t, cur_door_pos)
+	-- target is the same as t, just 1 square difference. Maybe we don't need target
+	mcl_log("Plot route from mob: " .. minetest.pos_to_string(p) .. ", to target: " .. minetest.pos_to_string(t))
+
+	local enriched_path = nil
+
+	--local cur_door_pos = nil
+	local pos_closest_to_door = nil
+	local other_side_of_door = nil
+
+	local wp
+
+	if cur_door_pos then
+		mcl_log("Found a door near: " .. minetest.pos_to_string(cur_door_pos))
+		for _,v in pairs(plane_adjacents) do
+			pos_closest_to_door = vector.add(cur_door_pos,v)
+			local n = minetest.get_node(pos_closest_to_door)
+
+			if n.name == "air" then
+				mcl_log("We have air space next to door at: " .. minetest.pos_to_string(pos_closest_to_door))
+
+				wp = minetest.find_path(p,pos_closest_to_door,150,1,4)
+
+				if wp then
+					mcl_log("Found a path to next to door".. minetest.pos_to_string(pos_closest_to_door))
+					other_side_of_door = vector.add(cur_door_pos,-v)
+					mcl_log("Opposite is: ".. minetest.pos_to_string(other_side_of_door))
+
+					local wp_otherside_door_to_target = minetest.find_path(other_side_of_door,t,150,1,4)
+					if wp_otherside_door_to_target and #wp_otherside_door_to_target > 0 then
+						table.insert(wp, cur_door_pos)
+						append_paths (wp, wp_otherside_door_to_target)
+						enriched_path = generate_enriched_path(wp, pos_closest_to_door, other_side_of_door, cur_door_pos)
+						mcl_log("We have a path from outside door to target")
+					else
+						mcl_log("We cannot path from outside door to target")
+					end
+					break
+				else
+					mcl_log("This block next to door doesn't work.")
+				end
+			end
+		end
+	else
+		mcl_log("No door found")
+	end
+
+	if wp and not enriched_path then
+		mcl_log("Wp but not enriched")
+		enriched_path = generate_enriched_path(wp)
+	end
+	return enriched_path
+end
+
+
+
 function mob_class:gopath(target,callback_arrived)
 	if self.state == PATHFINDING then mcl_log("Already pathfinding, don't set another until done.") return end
 
@@ -210,7 +197,28 @@ function mob_class:gopath(target,callback_arrived)
 	local p = self.object:get_pos()
 	local t = vector.offset(target,0,1,0)
 
-	local wp = calculate_path_through_door(p, t, target)
+	--Check direct route
+	local wp = minetest.find_path(p,t,150,1,4)
+
+	if not wp then
+		mcl_log("No direct path. Path through door")
+		-- target could be pos
+		local cur_door_pos = minetest.find_node_near(target, 16, {"group:door"})
+		wp = calculate_path_through_door(p, t, cur_door_pos)
+
+		if not wp then
+			mcl_log("No path though door closest to target. Try door closest to origin.")
+			cur_door_pos = minetest.find_node_near(p, 16, {"group:door"})
+			wp = calculate_path_through_door(p, t, cur_door_pos)
+		end
+	else
+		wp = generate_enriched_path(wp)
+		mcl_log("We have a direct route")
+	end
+
+	--path from pos to door, path from otherside to target
+
+
 	if not wp then
 		mcl_log("Could not calculate path")
 		self._pf_last_failed = os.time()