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 SESSION_MAX_DISTANCE_DEFAULT = 32
|
||||
|
||||
local SESSION_COORD_CLEAR = 1
|
||||
local SESSION_COORD_BLOCKED = 2
|
||||
|
||||
local UPDATE_COORD_CLEAR = -1
|
||||
local UPDATE_COORD_BLOCKED = 1
|
||||
|
||||
local sessionMidPoint
|
||||
local sessionMaxDistance
|
||||
|
||||
local sessionMap
|
||||
local serverMap
|
||||
|
||||
local function distanceFunc(a, 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
|
||||
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
|
||||
@ -193,9 +202,22 @@ local function scan(currPos)
|
||||
end
|
||||
blockInfo.checked = true
|
||||
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
|
||||
detectAll(currPos)
|
||||
end
|
||||
serverMap:check()
|
||||
serverMap:pushUpdates()
|
||||
end
|
||||
|
||||
local function move(currPos, adjPos)
|
||||
@ -213,7 +235,9 @@ local function move(currPos, adjPos)
|
||||
return false
|
||||
end
|
||||
|
||||
function goto(x, y, z)
|
||||
local exit = false
|
||||
local function _goto(x, y, z, maxDistance)
|
||||
exit = false
|
||||
if not serverMap then
|
||||
error("serverMap has not been specified")
|
||||
end
|
||||
@ -231,13 +255,16 @@ function goto(x, y, z)
|
||||
|
||||
serverMap:check() -- remove timed out data we have received from server
|
||||
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)
|
||||
if not path then
|
||||
return false, "no known path to goal"
|
||||
end
|
||||
|
||||
while not aStar.vectorEquals(position, goal) do
|
||||
while not (exit or aStar.vectorEquals(position, goal)) do
|
||||
local movePos = table.remove(path)
|
||||
while not move(position, movePos) do
|
||||
local blockPresent, blockData = inspect(position, movePos)
|
||||
@ -257,8 +284,6 @@ function goto(x, y, z)
|
||||
end
|
||||
if recalculate then
|
||||
scan(position)
|
||||
serverMap:check()
|
||||
serverMap:pushUpdates()
|
||||
if sessionMap:get(goal) == SESSION_COORD_BLOCKED then return false, "goal is blocked" end
|
||||
path = aStar.compute(distanceFunc, position, goal)
|
||||
if not path then
|
||||
@ -278,7 +303,28 @@ function goto(x, y, z)
|
||||
serverMap:check()
|
||||
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
|
||||
|
||||
function setMap(mapName, mapTimeout)
|
||||
|
||||
@ -27,18 +27,15 @@ local MAIN_COORD_DISTANCE = 1024
|
||||
|
||||
local sessionMidPoint
|
||||
local sessionMaxDistance
|
||||
|
||||
local sessionMap
|
||||
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 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
|
||||
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
|
||||
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
|
||||
@ -201,6 +198,17 @@ local function scan(currPos)
|
||||
end
|
||||
blockInfo.checked = true
|
||||
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
|
||||
detectAll(currPos)
|
||||
end
|
||||
@ -222,7 +230,7 @@ local function move(currPos, adjPos)
|
||||
return false
|
||||
end
|
||||
|
||||
function goto(x, y, z, maxDistance)
|
||||
local function _goto(x, y, z, maxDistance)
|
||||
if not mainMap then
|
||||
error("mainMap has not been specified")
|
||||
end
|
||||
@ -240,12 +248,13 @@ function goto(x, y, z, maxDistance)
|
||||
|
||||
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))
|
||||
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)
|
||||
if not path then
|
||||
return false, "no known path to goal"
|
||||
end
|
||||
|
||||
while not aStar.vectorEquals(position, goal) do
|
||||
local movePos = table.remove(path)
|
||||
while not move(position, movePos) do
|
||||
@ -281,9 +290,27 @@ function goto(x, y, z, maxDistance)
|
||||
mainMap:set(movePos, MAIN_COORD_CLEAR)
|
||||
end
|
||||
end
|
||||
|
||||
mainMap:saveAll()
|
||||
|
||||
return true
|
||||
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)
|
||||
if type(mapName) ~= "string" then
|
||||
error("mapName must be string")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user