diff --git a/init.lua b/init.lua index 2a6022f..fb42f43 100644 --- a/init.lua +++ b/init.lua @@ -188,16 +188,53 @@ local function coords_to_string(pos) end +function trim(s) + -- code from lua-users.org + return s:match'^()%s*$' and '' or s:match'^%s*(.*%S)' +end + + +local function clamp(x, min, max) + return math.max(math.min(x, max), min) +end + + local function coords_from_string(str) - -- numbers are separated by "," - local tmp = {} - for n in string.gmatch(str, "([^,]+)") do - table.insert(tmp, n) + -- parse "1,2,3" or "1 2 3" or "(1,2,3)" or "{x=1,y=2,z=3}" or return nil on fail + local function parse(str) + str = trim(str) + local result = nil + local first = string.sub(str, 1, 1) + local last = string.sub(str, -1, -1) + if first == "{" and last == "}" then + local maybe_pos = minetest.deserialize("return " .. str) + result = {x = maybe_pos.x, y = maybe_pos.y, z = maybe_pos.z} + end + + if not result and first == "(" and last == ")" then + str = string.sub(str, 2, -2) + end + + if not result then + -- numbers are separated by "," or " " + local tmp = {} + for n in string.gmatch(str, "([^, ]+)") do + table.insert(tmp, n) + end + result = {x = tonumber(tmp[1]), y = tonumber(tmp[2]), z = tonumber(tmp[3])} + end + -- if any of xyz are not numbers, this will throw an error and pcall will fail + result.x = clamp(result.x, -32000, 32000) + result.y = clamp(result.y, -32000, 32000) + result.z = clamp(result.z, -32000, 32000) + return result + end + local success, result = pcall(parse, str) + if success then + return result + else + return nil end - tmp[1] = tonumber(tmp[1]) or 0 - tmp[2] = tonumber(tmp[2]) or 0 - tmp[3] = tonumber(tmp[3]) or 0 - return {x = tmp[1], y = tmp[2], z = tmp[3]} end