Features and fixtures
Added ability to stop pathfinding whilst in the middle of running Prevented more than one instance of pathfinding being run at once Added search area bounds to netNav (already existed in starNav) Other minor fixes
This commit is contained in:
parent
72aef91397
commit
718c324bf3
@ -16,18 +16,27 @@ end
|
|||||||
|
|
||||||
local position
|
local position
|
||||||
|
|
||||||
|
local SESSION_MAX_DISTANCE_DEFAULT = 32
|
||||||
|
|
||||||
local SESSION_COORD_CLEAR = 1
|
local SESSION_COORD_CLEAR = 1
|
||||||
local SESSION_COORD_BLOCKED = 2
|
local SESSION_COORD_BLOCKED = 2
|
||||||
|
|
||||||
local UPDATE_COORD_CLEAR = -1
|
local UPDATE_COORD_CLEAR = -1
|
||||||
local UPDATE_COORD_BLOCKED = 1
|
local UPDATE_COORD_BLOCKED = 1
|
||||||
|
|
||||||
|
local sessionMidPoint
|
||||||
|
local sessionMaxDistance
|
||||||
|
|
||||||
local sessionMap
|
local sessionMap
|
||||||
local serverMap
|
local serverMap
|
||||||
|
|
||||||
local function distanceFunc(a, b)
|
local function distanceFunc(a, b)
|
||||||
local sessionMapA, sessionMapB = sessionMap:get(a), sessionMap:get(b)
|
local sessionMapA, sessionMapB = sessionMap:get(a), sessionMap:get(b)
|
||||||
if sessionMapA == SESSION_COORD_BLOCKED or sessionMapB == SESSION_COORD_BLOCKED then
|
if aStar.distance(a, sessionMidPoint) > sessionMaxDistance then
|
||||||
|
return math.huge -- first coord is outside the search region
|
||||||
|
elseif aStar.distance(b, sessionMidPoint) > sessionMaxDistance then
|
||||||
|
return math.huge -- second coord is outside the search region
|
||||||
|
elseif sessionMapA == SESSION_COORD_BLOCKED or sessionMapB == SESSION_COORD_BLOCKED then
|
||||||
return math.huge -- we have found one of these coords to be blocked during this session
|
return math.huge -- we have found one of these coords to be blocked during this session
|
||||||
elseif sessionMapA == SESSION_COORD_CLEAR and sessionMapB == SESSION_COORD_CLEAR then
|
elseif sessionMapA == SESSION_COORD_CLEAR and sessionMapB == SESSION_COORD_CLEAR then
|
||||||
return aStar.distance(a, b) -- we have found both of these coords to be clear during this session
|
return aStar.distance(a, b) -- we have found both of these coords to be clear during this session
|
||||||
@ -193,9 +202,22 @@ local function scan(currPos)
|
|||||||
end
|
end
|
||||||
blockInfo.checked = true
|
blockInfo.checked = true
|
||||||
end
|
end
|
||||||
|
for _, blockInfo in ipairs(rawBlockInfo) do
|
||||||
|
local pos = currPos + vector.new(blockInfo.x, blockInfo.y, blockInfo.z)
|
||||||
|
local blockInfo = sortedBlockInfo:get(pos)
|
||||||
|
if not blockInfo.checked then
|
||||||
|
if blockInfo.type == "AIR" then
|
||||||
|
sessionMap:set(pos, SESSION_COORD_CLEAR)
|
||||||
|
else
|
||||||
|
sessionMap:set(pos, SESSION_COORD_BLOCKED)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
else
|
else
|
||||||
detectAll(currPos)
|
detectAll(currPos)
|
||||||
end
|
end
|
||||||
|
serverMap:check()
|
||||||
|
serverMap:pushUpdates()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function move(currPos, adjPos)
|
local function move(currPos, adjPos)
|
||||||
@ -213,7 +235,9 @@ local function move(currPos, adjPos)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function goto(x, y, z)
|
local exit = false
|
||||||
|
local function _goto(x, y, z, maxDistance)
|
||||||
|
exit = false
|
||||||
if not serverMap then
|
if not serverMap then
|
||||||
error("serverMap has not been specified")
|
error("serverMap has not been specified")
|
||||||
end
|
end
|
||||||
@ -231,13 +255,16 @@ function goto(x, y, z)
|
|||||||
|
|
||||||
serverMap:check() -- remove timed out data we have received from server
|
serverMap:check() -- remove timed out data we have received from server
|
||||||
sessionMap = aStar.newMap() -- reset the sessionMap
|
sessionMap = aStar.newMap() -- reset the sessionMap
|
||||||
|
|
||||||
|
sessionMidPoint = vector.new(math.floor((goal.x + position.x)/2), math.floor((goal.y + position.y)/2), math.floor((goal.z + position.z)/2))
|
||||||
|
sessionMaxDistance = (type(maxDistance) == "number" and maxDistance) or math.max(2*aStar.distance(sessionMidPoint, goal), SESSION_MAX_DISTANCE_DEFAULT)
|
||||||
|
|
||||||
local path = aStar.compute(distanceFunc, position, goal)
|
local path = aStar.compute(distanceFunc, position, goal)
|
||||||
if not path then
|
if not path then
|
||||||
return false, "no known path to goal"
|
return false, "no known path to goal"
|
||||||
end
|
end
|
||||||
|
|
||||||
while not aStar.vectorEquals(position, goal) do
|
while not (exit or aStar.vectorEquals(position, goal)) do
|
||||||
local movePos = table.remove(path)
|
local movePos = table.remove(path)
|
||||||
while not move(position, movePos) do
|
while not move(position, movePos) do
|
||||||
local blockPresent, blockData = inspect(position, movePos)
|
local blockPresent, blockData = inspect(position, movePos)
|
||||||
@ -257,8 +284,6 @@ function goto(x, y, z)
|
|||||||
end
|
end
|
||||||
if recalculate then
|
if recalculate then
|
||||||
scan(position)
|
scan(position)
|
||||||
serverMap:check()
|
|
||||||
serverMap:pushUpdates()
|
|
||||||
if sessionMap:get(goal) == SESSION_COORD_BLOCKED then return false, "goal is blocked" end
|
if sessionMap:get(goal) == SESSION_COORD_BLOCKED then return false, "goal is blocked" end
|
||||||
path = aStar.compute(distanceFunc, position, goal)
|
path = aStar.compute(distanceFunc, position, goal)
|
||||||
if not path then
|
if not path then
|
||||||
@ -278,7 +303,28 @@ function goto(x, y, z)
|
|||||||
serverMap:check()
|
serverMap:check()
|
||||||
serverMap:pushUpdates(true)
|
serverMap:pushUpdates(true)
|
||||||
|
|
||||||
return true
|
return aStar.vectorEquals(position, goal)
|
||||||
|
end
|
||||||
|
|
||||||
|
local isRunning = false
|
||||||
|
function goto(...)
|
||||||
|
if isRunning then
|
||||||
|
return false, "already running"
|
||||||
|
end
|
||||||
|
isRunning = true
|
||||||
|
local passback = {pcall(_goto, ...)}
|
||||||
|
isRunning = false
|
||||||
|
if not passback[1] then
|
||||||
|
printError(passback[2])
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return unpack(passback, 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
function stop()
|
||||||
|
if isRunning then
|
||||||
|
exit = true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function setMap(mapName, mapTimeout)
|
function setMap(mapName, mapTimeout)
|
||||||
|
|||||||
@ -27,18 +27,15 @@ local MAIN_COORD_DISTANCE = 1024
|
|||||||
|
|
||||||
local sessionMidPoint
|
local sessionMidPoint
|
||||||
local sessionMaxDistance
|
local sessionMaxDistance
|
||||||
|
|
||||||
local sessionMap
|
local sessionMap
|
||||||
local mainMap
|
local mainMap
|
||||||
|
|
||||||
local function sup_norm(a, b)
|
|
||||||
return math.max(math.abs(a.x - b.x), math.abs(a.y - b.y), math.abs(a.z - b.z))
|
|
||||||
end
|
|
||||||
|
|
||||||
local function distanceFunc(a, b)
|
local function distanceFunc(a, b)
|
||||||
local sessionMapA, sessionMapB = sessionMap:get(a), sessionMap:get(b)
|
local sessionMapA, sessionMapB = sessionMap:get(a), sessionMap:get(b)
|
||||||
if sup_norm(a, sessionMidPoint) > sessionMaxDistance then
|
if aStar.distance(a, sessionMidPoint) > sessionMaxDistance then
|
||||||
return SESSION_COORD_DISTANCE -- first coord is outside the search region
|
return SESSION_COORD_DISTANCE -- first coord is outside the search region
|
||||||
elseif sup_norm(b, sessionMidPoint) > sessionMaxDistance then
|
elseif aStar.distance(b, sessionMidPoint) > sessionMaxDistance then
|
||||||
return SESSION_COORD_DISTANCE -- second coord is outside the search region
|
return SESSION_COORD_DISTANCE -- second coord is outside the search region
|
||||||
elseif sessionMapA == SESSION_COORD_BLOCKED or sessionMapB == SESSION_COORD_BLOCKED then
|
elseif sessionMapA == SESSION_COORD_BLOCKED or sessionMapB == SESSION_COORD_BLOCKED then
|
||||||
return SESSION_COORD_DISTANCE -- one of the coords has been found to be blocked this during this session
|
return SESSION_COORD_DISTANCE -- one of the coords has been found to be blocked this during this session
|
||||||
@ -201,6 +198,17 @@ local function scan(currPos)
|
|||||||
end
|
end
|
||||||
blockInfo.checked = true
|
blockInfo.checked = true
|
||||||
end
|
end
|
||||||
|
for _, blockInfo in ipairs(rawBlockInfo) do
|
||||||
|
local pos = currPos + vector.new(blockInfo.x, blockInfo.y, blockInfo.z)
|
||||||
|
local blockInfo = sortedBlockInfo:get(pos)
|
||||||
|
if not blockInfo.checked then
|
||||||
|
if blockInfo.type == "AIR" then
|
||||||
|
sessionMap:set(pos, SESSION_COORD_CLEAR)
|
||||||
|
else
|
||||||
|
sessionMap:set(pos, SESSION_COORD_BLOCKED)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
else
|
else
|
||||||
detectAll(currPos)
|
detectAll(currPos)
|
||||||
end
|
end
|
||||||
@ -222,7 +230,7 @@ local function move(currPos, adjPos)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function goto(x, y, z, maxDistance)
|
local function _goto(x, y, z, maxDistance)
|
||||||
if not mainMap then
|
if not mainMap then
|
||||||
error("mainMap has not been specified")
|
error("mainMap has not been specified")
|
||||||
end
|
end
|
||||||
@ -240,12 +248,13 @@ function goto(x, y, z, maxDistance)
|
|||||||
|
|
||||||
sessionMap = aStar.newMap()
|
sessionMap = aStar.newMap()
|
||||||
sessionMidPoint = vector.new(math.floor((goal.x + position.x)/2), math.floor((goal.y + position.y)/2), math.floor((goal.z + position.z)/2))
|
sessionMidPoint = vector.new(math.floor((goal.x + position.x)/2), math.floor((goal.y + position.y)/2), math.floor((goal.z + position.z)/2))
|
||||||
sessionMaxDistance = (type(maxDistance) == "number" and maxDistance) or math.max(2*sup_norm(sessionMidPoint, goal), SESSION_MAX_DISTANCE_DEFAULT)
|
sessionMaxDistance = (type(maxDistance) == "number" and maxDistance) or math.max(2*aStar.distance(sessionMidPoint, goal), SESSION_MAX_DISTANCE_DEFAULT)
|
||||||
|
|
||||||
local path = aStar.compute(distanceFunc, position, goal)
|
local path = aStar.compute(distanceFunc, position, goal)
|
||||||
if not path then
|
if not path then
|
||||||
return false, "no known path to goal"
|
return false, "no known path to goal"
|
||||||
end
|
end
|
||||||
|
|
||||||
while not aStar.vectorEquals(position, goal) do
|
while not aStar.vectorEquals(position, goal) do
|
||||||
local movePos = table.remove(path)
|
local movePos = table.remove(path)
|
||||||
while not move(position, movePos) do
|
while not move(position, movePos) do
|
||||||
@ -281,9 +290,27 @@ function goto(x, y, z, maxDistance)
|
|||||||
mainMap:set(movePos, MAIN_COORD_CLEAR)
|
mainMap:set(movePos, MAIN_COORD_CLEAR)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
mainMap:saveAll()
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local isRunning = false
|
||||||
|
function goto(...)
|
||||||
|
if isRunning then
|
||||||
|
return false, "already running"
|
||||||
|
end
|
||||||
|
isRunning = true
|
||||||
|
local passback = {pcall(_goto, ...)}
|
||||||
|
isRunning = false
|
||||||
|
if not passback[1] then
|
||||||
|
printError(passback[2])
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return unpack(passback, 2)
|
||||||
|
end
|
||||||
|
|
||||||
function setMap(mapName)
|
function setMap(mapName)
|
||||||
if type(mapName) ~= "string" then
|
if type(mapName) ~= "string" then
|
||||||
error("mapName must be string")
|
error("mapName must be string")
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user