2021-11-07 18:04:18 +00:00
local Vector3
if worldeditadditions then
local wea = worldeditadditions
Vector3 = dofile ( wea.modpath .. " /utils/vector3.lua " )
else
Vector3 = require ( " worldeditadditions.utils.vector3 " )
end
2021-11-07 17:14:11 +00:00
--- Parses an absolute axis name to a Vector3 instance.
-- @example
-- local v3instance = parse_abs_axis_name("-x")
-- -- v3instance will now be equal to Vector3.new(-1, 0, 0)
-- @param axis_name string The axis name to parse.
-- @returns bool,Vector3|string A bool success value, followed by the resulting Vector3 instance (if succeeded) or an error message string (if failed).
local function parse_abs_axis_name ( axis_name )
if type ( axis_name ) ~= " string " then
return false , " Error: Expected axis_name to be of type string, but found value of type ' " .. type ( axis_name ) .. " ' instead. "
end
local result = Vector3.new ( )
if axis_name : match ( " -x " ) then result.x = - 1
elseif axis_name : match ( " x " ) then result.x = 1 end
if axis_name : match ( " -y " ) then result.y = - 1
elseif axis_name : match ( " y " ) then result.y = 1 end
if axis_name : match ( " -z " ) then result.z = - 1
elseif axis_name : match ( " z " ) then result.z = 1 end
2021-11-07 18:04:18 +00:00
if Vector3.new ( ) == result then
return false , " Error: Unknown axis_name ' " .. axis_name .. " '. "
end
2021-11-07 17:14:11 +00:00
return true , result
end
-- Parses a relative axis name (e.g. "front", "back", etc) to an absolute
-- Vector3 instance.
-- @param axis_name string The axis name to parse.
-- @param player_name PlayerDir The directional information that the parsing should be relative to.
-- @returns bool,Vector3|string A bool success value, followed by the resulting Vector3 instance (if succeeded) or an error message string (if failed).
local function parse_relative_axis_name ( axis_name , facing_dir )
if type ( axis_name ) ~= " string " then
return false , " Error: Expected axis_name to be of type string, value was of type ' " .. type ( axis_name ) .. " ' instead. "
end
local dir
local flip = Vector3.new ( - 1 , - 1 , - 1 )
if axis_name == " ? " then dir = facing_dir.front end
if axis_name == " front " or axis_name == " f " then dir = facing_dir.front end
if axis_name == " back " or axis_name == " b " then dir = facing_dir.back end
if axis_name == " left " or axis_name == " l " then dir = facing_dir.left end
if axis_name == " right " or axis_name == " r " then dir = facing_dir.right end
if axis_name == " up " or axis_name == " u " then dir = facing_dir.up end
if axis_name == " down " or axis_name == " d " then dir = facing_dir.down end
if not dir then return false , " Error: Unknown axis name ' " .. axis_name .. " '. Valid values: ?, front, f, back, b, left, l, right, r, up, u, down, d. " end
axis_name = ( dir.sign < 0 and " - " or " " ) .. dir.axis
local success , result = parse_abs_axis_name ( axis_name )
if not success then return success , result end
return true , result
end
2021-11-11 01:47:22 +00:00
--- Parses a relative or absolute axis name into a Vector3 instance.
-- @param axis_name string The axis name to parse.
-- @param facing_dir table The direction the player is facing. Obtain this by calling worldeditadditions.
2021-11-07 17:14:11 +00:00
local function parse_axis_name ( axis_name , facing_dir )
local success , result = parse_relative_axis_name ( axis_name , facing_dir )
if not success then
success , result = parse_abs_axis_name ( axis_name )
end
return success , result
end
2021-10-11 01:41:45 +00:00
2021-11-11 01:47:22 +00:00
local function vregion_apply ( vpos1 , vpos2 , offset )
-- It's a specific axis
if offset.x < 0 then vpos1.x = vpos1.x + offset.x
else vpos2.x = vpos2.x + offset.x end
if offset.y < 0 then vpos1.y = vpos1.y + offset.y
else vpos2.y = vpos2.y + offset.y end
if offset.z < 0 then vpos1.z = vpos1.z + offset.z
else vpos2.z = vpos2.z + offset.z end
return vpos1 , vpos2
end
local function in_list ( list , str )
for i , item in ipairs ( list ) do
if item == str then return true end
end
return false
end
2021-10-11 01:41:45 +00:00
--- Parses a token list of axes and counts into a Vector3.
-- For example, "x 4" would become { x = 4, y = 0, z = 0 }, and "? 4 -z 10"
-- might become { x = 4, y = 0, z = -10 }.
2021-11-07 18:04:18 +00:00
-- Note that the input here needs to be *post split*. wea.split_shell is
2021-10-11 01:41:45 +00:00
-- recommended for this purpose.
-- @param token_list string[] A list of tokens to parse
2021-11-07 17:14:11 +00:00
-- @param facing_dir PlayerDir The direction the player is facing. Returned from wea.player_dir(name).
-- @returns Vector3,Vector3 A Vector3 pair generated from parsing out the input token list representing the delta change that can be applied to a defined pos1, pos2 region.
local function parse_axes ( token_list , facing_dir )
2021-11-11 01:47:22 +00:00
local mirroring_keywords = {
" sym " , " symmetrical " ,
" mirror " , " mir " ,
2021-11-11 01:50:12 +00:00
" rev " , " reverse " ,
" true "
2021-11-11 01:47:22 +00:00
}
2021-11-08 00:47:35 +00:00
if type ( token_list ) ~= " table " then
return false , " Error: Expected list of tokens as a table, but found value of type ' " .. type ( token_list ) .. " ' instead. "
end
if type ( facing_dir ) ~= " table " then
2021-11-11 02:20:37 +00:00
return false , " Error: Expected facing_dir to be a table, but found value of type ' " .. type ( facing_dir ) .. " ' instead. "
2021-11-08 00:47:35 +00:00
end
2021-11-11 01:47:22 +00:00
local vpos1 , vpos2 = Vector3.new ( ) , Vector3.new ( )
2021-10-11 01:41:45 +00:00
if # token_list < 2 then
return false , " Error: Not enough arguments (at least 2 are required) "
end
local state = " AXIS "
local current_axis = nil
2021-11-07 17:14:11 +00:00
local current_axis_text = nil
2021-10-11 01:41:45 +00:00
local success
2021-11-11 01:47:22 +00:00
-- for i,token in ipairs(token_list) do
for i = 1 , # token_list do
local token = token_list [ i ]
local token_next
if i < # token_list then token_next = token_list [ i + 1 ] end
2021-11-08 00:47:35 +00:00
if type ( token ) ~= " string " then
return false , " Error: Found token of unexpected type ' " .. type ( token ) .. " ' at position " .. i .. " . "
end
-- print("DEBUG i", i, "token", token)
2021-10-11 01:41:45 +00:00
if state == " AXIS " then
2021-11-08 00:47:35 +00:00
if token == " h " or token == " horizontal " then
2021-11-07 17:14:11 +00:00
current_axis_text = " horizontal "
current_axis = Vector3.new ( 1 , 0 , 1 )
elseif token == " v " or token == " vertical " then
current_axis_text = " vertical "
current_axis = Vector3.new ( 0 , 1 , 0 )
2021-11-11 01:47:22 +00:00
elseif not in_list ( mirroring_keywords , token ) then
2021-11-07 17:14:11 +00:00
current_axis_text = token
success , current_axis = parse_axis_name ( token , facing_dir )
if not success then return success , current_axis end
end
2021-11-08 00:47:35 +00:00
2021-10-11 01:41:45 +00:00
state = " VALUE "
elseif state == " VALUE " then
2021-11-11 01:47:22 +00:00
2021-10-11 01:41:45 +00:00
local offset_this = tonumber ( token )
if not offset_this then
2021-11-07 17:14:11 +00:00
return false , " Error: Invalid count value ' " .. tostring ( token ) .. " ' for axis ' " .. current_axis_text .. " '. Values may only be positive or negative integers. "
2021-10-11 01:41:45 +00:00
end
2021-11-07 17:14:11 +00:00
offset_this = current_axis * offset_this
2021-10-11 01:41:45 +00:00
2021-11-08 00:47:35 +00:00
-- print("DEBUG STATE VALUE offset_this", offset_this)
2021-11-07 17:14:11 +00:00
-- Apply the new offset to the virtual defined region
if current_axis_text == " horizontal " or current_axis_text == " vertical " then
-- We're horizonal / vertical
2021-11-11 01:47:22 +00:00
vpos1 = vpos1 + ( offset_this * - 1 )
vpos2 = vpos2 + offset_this
2021-11-07 17:14:11 +00:00
else
2021-11-11 01:47:22 +00:00
vpos1 , vpos2 = vregion_apply ( vpos1 , vpos2 , offset_this )
-- Handle the extra mirroring keyword
if in_list ( mirroring_keywords , token_next ) then
vpos1 , vpos2 = vregion_apply ( vpos1 , vpos2 , offset_this * - 1 )
end
2021-11-07 17:14:11 +00:00
end
2021-10-11 01:41:45 +00:00
state = " AXIS "
else
return false , " Error: Failed to parse input due to unknown state ' " .. tostring ( state ) .. " ' (this is probably a bug - please report it!) "
end
end
2021-11-11 01:47:22 +00:00
return true , vpos1 , vpos2
2021-10-11 01:41:45 +00:00
end
2021-11-07 18:04:18 +00:00
return {
parse_axes = parse_axes ,
parse_axis_name = parse_axis_name ,
parse_abs_axis_name = parse_abs_axis_name ,
parse_relative_axis_name = parse_relative_axis_name
}