From 269a73be48ddec8fc9946cbef847e6ccef138a9e Mon Sep 17 00:00:00 2001 From: VorTechnix <45538536+VorTechnix@users.noreply.github.com> Date: Mon, 7 Oct 2024 16:11:35 -0700 Subject: [PATCH] Fixed CLRF Issues (I hope) --- .gitattributes | 2 + .tests/parse/axes/axes_keyword.test.lua | 156 +++++------ .../commands/selectors/init.lua | 92 +++--- .../commands/selectors/scentre.lua | 66 ++--- .../commands/selectors/sfactor.lua | 44 +-- .../commands/selectors/sgrow.lua | 84 +++--- .../commands/selectors/smake.lua | 262 +++++++++--------- .../commands/selectors/srel.lua | 74 ++--- .../commands/selectors/sshrink.lua | 84 +++--- .../commands/uasparse.lua | 58 ++-- .../utils/strings/split.lua | 178 ++++++------ 11 files changed, 551 insertions(+), 549 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.tests/parse/axes/axes_keyword.test.lua b/.tests/parse/axes/axes_keyword.test.lua index b6e137c..4998351 100644 --- a/.tests/parse/axes/axes_keyword.test.lua +++ b/.tests/parse/axes/axes_keyword.test.lua @@ -1,78 +1,78 @@ -local Vector3 = require("worldeditadditions_core.utils.vector3") - -local facing_dirs = dofile("./.tests/parse/axes/include_facing_dirs.lua") - -local parse = require("worldeditadditions_core.utils.parse.axes_parser") -local parse_keyword = parse.keyword - - -describe("parse_keyword", function() - - -- Basic tests - it("should work on single axes", function() - local ktype, axis, sign = parse_keyword("x") - assert.are.equals("axis", ktype) - assert.are.same({"x"}, axis) - assert.are.equals(1, sign) - end) - - it("should work with axis clumping", function() - local ktype, axis, sign = parse_keyword("zx") - assert.are.equals("axis", ktype) - assert.are.same({"x", "z"}, axis) - assert.are.equals(1, sign) - end) - - it("should work with h and v", function() - local ktype, axis, sign = parse_keyword("hv") - assert.are.equals("axis", ktype) - assert.are.same( - {"x", "y", "z", rev={"x", "y", "z"}}, - axis) - assert.are.equals(1, sign) - end) - - it("should work with h and v in clumping", function() - local ktype, axis, sign = parse_keyword("hyxz") - assert.are.equals("axis", ktype) - assert.are.same( - {"x", "y", "z", rev={"x", "z"}}, - axis) - assert.are.equals(1, sign) - end) - - it("should work with negatives", function() - local ktype, axis, sign = parse_keyword("-xv") - assert.are.equals("axis", ktype) - assert.are.same({"x", "y", rev={"y"}}, axis) - assert.are.equals(-1, sign) - end) - - it("should work with dirs", function() - local ktype, axis, sign = parse_keyword("left") - assert.are.equals("dir", ktype) - assert.are.equals("left", axis) - assert.are.equals(1, sign) - end) - - it("should work with negative dirs", function() - local ktype, axis, sign = parse_keyword("-right") - assert.are.equals("dir", ktype) - assert.are.equals("right", axis) - assert.are.equals(-1, sign) - end) - - it("should work with mirroring", function() - local ktype, axis, sign = parse_keyword("m") - assert.are.equals("rev", ktype) - assert.are.equals("mirroring", axis) - assert.are.equals(nil, sign) - end) - - -- Error tests - it("should return error for bad axis", function() - local ktype, axis, sign = parse_keyword("-axv") - assert.are.equals("err", ktype) - end) - -end) +local Vector3 = require("worldeditadditions_core.utils.vector3") + +local facing_dirs = dofile("./.tests/parse/axes/include_facing_dirs.lua") + +local parse = require("worldeditadditions_core.utils.parse.axes_parser") +local parse_keyword = parse.keyword + + +describe("parse_keyword", function() + + -- Basic tests + it("should work on single axes", function() + local ktype, axis, sign = parse_keyword("x") + assert.are.equals("axis", ktype) + assert.are.same({"x"}, axis) + assert.are.equals(1, sign) + end) + + it("should work with axis clumping", function() + local ktype, axis, sign = parse_keyword("zx") + assert.are.equals("axis", ktype) + assert.are.same({"x", "z"}, axis) + assert.are.equals(1, sign) + end) + + it("should work with h and v", function() + local ktype, axis, sign = parse_keyword("hv") + assert.are.equals("axis", ktype) + assert.are.same( + {"x", "y", "z", rev={"x", "y", "z"}}, + axis) + assert.are.equals(1, sign) + end) + + it("should work with h and v in clumping", function() + local ktype, axis, sign = parse_keyword("hyxz") + assert.are.equals("axis", ktype) + assert.are.same( + {"x", "y", "z", rev={"x", "z"}}, + axis) + assert.are.equals(1, sign) + end) + + it("should work with negatives", function() + local ktype, axis, sign = parse_keyword("-xv") + assert.are.equals("axis", ktype) + assert.are.same({"x", "y", rev={"y"}}, axis) + assert.are.equals(-1, sign) + end) + + it("should work with dirs", function() + local ktype, axis, sign = parse_keyword("left") + assert.are.equals("dir", ktype) + assert.are.equals("left", axis) + assert.are.equals(1, sign) + end) + + it("should work with negative dirs", function() + local ktype, axis, sign = parse_keyword("-right") + assert.are.equals("dir", ktype) + assert.are.equals("right", axis) + assert.are.equals(-1, sign) + end) + + it("should work with mirroring", function() + local ktype, axis, sign = parse_keyword("m") + assert.are.equals("rev", ktype) + assert.are.equals("mirroring", axis) + assert.are.equals(nil, sign) + end) + + -- Error tests + it("should return error for bad axis", function() + local ktype, axis, sign = parse_keyword("-axv") + assert.are.equals("err", ktype) + end) + +end) diff --git a/worldeditadditions_commands/commands/selectors/init.lua b/worldeditadditions_commands/commands/selectors/init.lua index 9695fbc..bb7fe79 100644 --- a/worldeditadditions_commands/commands/selectors/init.lua +++ b/worldeditadditions_commands/commands/selectors/init.lua @@ -1,46 +1,46 @@ --- ███████ ███████ ██ ███████ ██████ ████████ ██████ ██████ ███████ --- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ --- ███████ █████ ██ █████ ██ ██ ██ ██ ██████ ███████ --- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ --- ███████ ███████ ███████ ███████ ██████ ██ ██████ ██ ██ ███████ - --- Chat commands that operate on selections. - -local wea_cmdpath = worldeditadditions_commands.modpath .. "/commands/selectors/" -local weac = worldeditadditions_core - -dofile(wea_cmdpath.."scentre.lua") -dofile(wea_cmdpath.."scloud.lua") -dofile(wea_cmdpath.."sgrow.lua") -dofile(wea_cmdpath.."smake.lua") -dofile(wea_cmdpath.."spop.lua") -dofile(wea_cmdpath.."spush.lua") -dofile(wea_cmdpath.."srel.lua") -dofile(wea_cmdpath.."sshift.lua") -dofile(wea_cmdpath.."sshrink.lua") -dofile(wea_cmdpath.."sstack.lua") - ---- DEPRECATED --- -dofile(wea_cmdpath.."scol.lua") -dofile(wea_cmdpath.."scube.lua") -dofile(wea_cmdpath.."srect.lua") -dofile(wea_cmdpath.."sfactor.lua") ---- END DEPRECATED --- - -dofile(wea_cmdpath.."unmark.lua") -dofile(wea_cmdpath.."mark.lua") -dofile(wea_cmdpath.."pos1-2.lua") -dofile(wea_cmdpath.."reset.lua") - --- Aliases -weac.register_alias("sfac", "sfactor") - -weac.register_alias("expand", "sgrow", true) -- true = override target -weac.register_alias("outset", "sgrow", true) -- true = override target -weac.register_alias("contract", "sshrink", true) -- true = override target -weac.register_alias("inset", "sshrink", true) -- true = override target - -weac.register_alias("shift", "sshift", true) -- true = override target - -weac.register_alias("1", "pos1", true) -- true = override target -weac.register_alias("2", "pos2", true) -- true = override target +-- ███████ ███████ ██ ███████ ██████ ████████ ██████ ██████ ███████ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ███████ █████ ██ █████ ██ ██ ██ ██ ██████ ███████ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ███████ ███████ ███████ ███████ ██████ ██ ██████ ██ ██ ███████ + +-- Chat commands that operate on selections. + +local wea_cmdpath = worldeditadditions_commands.modpath .. "/commands/selectors/" +local weac = worldeditadditions_core + +dofile(wea_cmdpath.."scentre.lua") +dofile(wea_cmdpath.."scloud.lua") +dofile(wea_cmdpath.."sgrow.lua") +dofile(wea_cmdpath.."smake.lua") +dofile(wea_cmdpath.."spop.lua") +dofile(wea_cmdpath.."spush.lua") +dofile(wea_cmdpath.."srel.lua") +dofile(wea_cmdpath.."sshift.lua") +dofile(wea_cmdpath.."sshrink.lua") +dofile(wea_cmdpath.."sstack.lua") + +--- DEPRECATED --- +dofile(wea_cmdpath.."scol.lua") +dofile(wea_cmdpath.."scube.lua") +dofile(wea_cmdpath.."srect.lua") +dofile(wea_cmdpath.."sfactor.lua") +--- END DEPRECATED --- + +dofile(wea_cmdpath.."unmark.lua") +dofile(wea_cmdpath.."mark.lua") +dofile(wea_cmdpath.."pos1-2.lua") +dofile(wea_cmdpath.."reset.lua") + +-- Aliases +weac.register_alias("sfac", "sfactor") + +weac.register_alias("expand", "sgrow", true) -- true = override target +weac.register_alias("outset", "sgrow", true) -- true = override target +weac.register_alias("contract", "sshrink", true) -- true = override target +weac.register_alias("inset", "sshrink", true) -- true = override target + +weac.register_alias("shift", "sshift", true) -- true = override target + +weac.register_alias("1", "pos1", true) -- true = override target +weac.register_alias("2", "pos2", true) -- true = override target diff --git a/worldeditadditions_commands/commands/selectors/scentre.lua b/worldeditadditions_commands/commands/selectors/scentre.lua index ec8c31e..9ab1b78 100644 --- a/worldeditadditions_commands/commands/selectors/scentre.lua +++ b/worldeditadditions_commands/commands/selectors/scentre.lua @@ -1,33 +1,33 @@ -local wea_c = worldeditadditions_core -local Vector3 = wea_c.Vector3 - --- ███████ ██████ ███████ ███ ██ ████████ ███████ ██████ --- ██ ██ ██ ████ ██ ██ ██ ██ ██ --- ███████ ██ █████ ██ ██ ██ ██ █████ ██████ --- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ --- ███████ ██████ ███████ ██ ████ ██ ███████ ██ ██ -worldeditadditions_core.register_command("scentre", { - params = "", - description = "Set WorldEdit region positions 1 and 2 to the centre of the current selection.", - privs = {worldedit=true}, - require_pos = 2, - parse = function(params_text) - return true - end, - func = function(name) - local mean = Vector3.mean( - Vector3.clone(wea_c.pos.get(name, 1)), - Vector3.clone(wea_c.pos.get(name, 2)) - ) - local pos1, pos2 = Vector3.clone(mean), Vector3.clone(mean) - - pos1 = pos1:floor() - pos2 = pos2:ceil() - - wea_c.pos.set_all(name, {pos1, pos2}) - - return true, "Position 1 to "..pos1..", Position 2 to "..pos2 - end, -}) - --- lua print(vecs.mean.x..", "..vecs.mean.y..", "..vecs.mean.z) +local wea_c = worldeditadditions_core +local Vector3 = wea_c.Vector3 + +-- ███████ ██████ ███████ ███ ██ ████████ ███████ ██████ +-- ██ ██ ██ ████ ██ ██ ██ ██ ██ +-- ███████ ██ █████ ██ ██ ██ ██ █████ ██████ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ███████ ██████ ███████ ██ ████ ██ ███████ ██ ██ +worldeditadditions_core.register_command("scentre", { + params = "", + description = "Set WorldEdit region positions 1 and 2 to the centre of the current selection.", + privs = {worldedit=true}, + require_pos = 2, + parse = function(params_text) + return true + end, + func = function(name) + local mean = Vector3.mean( + Vector3.clone(wea_c.pos.get(name, 1)), + Vector3.clone(wea_c.pos.get(name, 2)) + ) + local pos1, pos2 = Vector3.clone(mean), Vector3.clone(mean) + + pos1 = pos1:floor() + pos2 = pos2:ceil() + + wea_c.pos.set_all(name, {pos1, pos2}) + + return true, "Position 1 to "..pos1..", Position 2 to "..pos2 + end, +}) + +-- lua print(vecs.mean.x..", "..vecs.mean.y..", "..vecs.mean.z) diff --git a/worldeditadditions_commands/commands/selectors/sfactor.lua b/worldeditadditions_commands/commands/selectors/sfactor.lua index ef78473..f29eb32 100644 --- a/worldeditadditions_commands/commands/selectors/sfactor.lua +++ b/worldeditadditions_commands/commands/selectors/sfactor.lua @@ -1,22 +1,22 @@ -local wea = worldeditadditions -local wea_c = worldeditadditions_core -local Vector3 = wea_c.Vector3 - - --- ███████ ███████ █████ ██████ ████████ ██████ ██████ --- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ --- ███████ █████ ███████ ██ ██ ██ ██ ██████ --- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ --- ███████ ██ ██ ██ ██████ ██ ██████ ██ ██ -worldeditadditions_core.register_command("sfactor", { - params = "None", - description = "DEPRECATED: please use //grow or //shrink instead.", - - privs = { worldedit = true }, - parse = function(params_text) - return params_text - end, - func = function(name, paramtext) - return false, "DEPRECATED: please use //grow or //shrink instead..." - end -}) +local wea = worldeditadditions +local wea_c = worldeditadditions_core +local Vector3 = wea_c.Vector3 + + +-- ███████ ███████ █████ ██████ ████████ ██████ ██████ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ███████ █████ ███████ ██ ██ ██ ██ ██████ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ███████ ██ ██ ██ ██████ ██ ██████ ██ ██ +worldeditadditions_core.register_command("sfactor", { + params = "None", + description = "DEPRECATED: please use //grow or //shrink instead.", + + privs = { worldedit = true }, + parse = function(params_text) + return params_text + end, + func = function(name, paramtext) + return false, "DEPRECATED: please use //grow or //shrink instead..." + end +}) diff --git a/worldeditadditions_commands/commands/selectors/sgrow.lua b/worldeditadditions_commands/commands/selectors/sgrow.lua index 9ede412..e30b0ae 100644 --- a/worldeditadditions_commands/commands/selectors/sgrow.lua +++ b/worldeditadditions_commands/commands/selectors/sgrow.lua @@ -1,42 +1,42 @@ --- local wea = worldeditadditions -local wea_c = worldeditadditions_core -local Vector3 = wea_c.Vector3 - - --- ███████ ██████ ██████ ██████ ██ ██ --- ██ ██ ██ ██ ██ ██ ██ ██ --- ███████ ██ ███ ██████ ██ ██ ██ █ ██ --- ██ ██ ██ ██ ██ ██ ██ ██ ███ ██ --- ███████ ██████ ██ ██ ██████ ███ ███ - - -worldeditadditions_core.register_command("sgrow", { - params = "", - description = "Grow selection region", - privs = { worldedit = true }, - require_pos = 0, - parse = function(params_text) - local ret = wea_c.split(params_text) - if #ret < 1 then return false, "SGROW: No params found!" - else return true, ret end - end, - func = function(name, params_text) - local facing = wea_c.player_dir(name) - local min, max = wea_c.parse.directions(params_text, facing) - if not min then return false, max end - - local pos1 = wea_c.pos.get(name, 1) - local pos2 = wea_c.pos.get(name, 2) - - if not pos2 then wea_c.pos.set(name, 2, pos1) - else pos1, pos2 = Vector3.sort(pos1, pos2) end - - pos1, pos2 = pos1:add(min), pos2:add(max) - - wea_c.pos.set_all(name, {pos1, pos2}) - return true, "Position 1 to "..pos1..", Position 2 to "..pos2 - end, -}) - --- Tests --- //srel front 5 left 3 y 2 +-- local wea = worldeditadditions +local wea_c = worldeditadditions_core +local Vector3 = wea_c.Vector3 + + +-- ███████ ██████ ██████ ██████ ██ ██ +-- ██ ██ ██ ██ ██ ██ ██ ██ +-- ███████ ██ ███ ██████ ██ ██ ██ █ ██ +-- ██ ██ ██ ██ ██ ██ ██ ██ ███ ██ +-- ███████ ██████ ██ ██ ██████ ███ ███ + + +worldeditadditions_core.register_command("sgrow", { + params = "", + description = "Grow selection region", + privs = { worldedit = true }, + require_pos = 0, + parse = function(params_text) + local ret = wea_c.split(params_text) + if #ret < 1 then return false, "SGROW: No params found!" + else return true, ret end + end, + func = function(name, params_text) + local facing = wea_c.player_dir(name) + local min, max = wea_c.parse.directions(params_text, facing) + if not min then return false, max end + + local pos1 = wea_c.pos.get(name, 1) + local pos2 = wea_c.pos.get(name, 2) + + if not pos2 then wea_c.pos.set(name, 2, pos1) + else pos1, pos2 = Vector3.sort(pos1, pos2) end + + pos1, pos2 = pos1:add(min), pos2:add(max) + + wea_c.pos.set_all(name, {pos1, pos2}) + return true, "Position 1 to "..pos1..", Position 2 to "..pos2 + end, +}) + +-- Tests +-- //srel front 5 left 3 y 2 diff --git a/worldeditadditions_commands/commands/selectors/smake.lua b/worldeditadditions_commands/commands/selectors/smake.lua index 78309bb..d98fea9 100644 --- a/worldeditadditions_commands/commands/selectors/smake.lua +++ b/worldeditadditions_commands/commands/selectors/smake.lua @@ -1,131 +1,131 @@ -local wea_c = worldeditadditions_core -local Vector3 = wea_c.Vector3 - - --- ███████ ███ ███ █████ ██ ██ ███████ --- ██ ████ ████ ██ ██ ██ ██ ██ --- ███████ ██ ████ ██ ███████ █████ █████ --- ██ ██ ██ ██ ██ ██ ██ ██ ██ --- ███████ ██ ██ ██ ██ ██ ██ ███████ -worldeditadditions_core.register_command("smake", { - params = " [ []]", - description = "Make one or more axes of the current selection odd, even, or equal to another.", - privs = { worldedit = true }, - require_pos = 2, - parse = function(params_text) - -- Split params_text, check for missing arguments and fill in empty spots - local parts = wea_c.split(params_text, "%s+", false) - if #parts < 2 then - return false, "Error: Not enough arguments. Expected \" [ []]\"." - else - for i=3,4 do if not parts[i] then parts[i] = false end end - end - - -- Initialize local variables and sets - local oper, mode, targ, base = wea_c.table.unpack(parts) - local operSet, modeSet = wea_c.table.makeset {"equal", "odd", "even"}, wea_c.table.makeset {"grow", "shrink", "avg"} - - -- Main Logic - -- Check base if base is present and if so valid. - if base then - if base:match("[xyz]") then -- ensure correct base syntax - base = base:match("[xyz]") - else - return false, "Error: Invalid base \""..base.."\". Expected \"x\", \"y\" or \"z\"." - end - end - - -- Resolve target then mode (in that order incase mode is target). - if not targ then -- If no target set to default (xz) - targ = "xz" - elseif targ:match("[xyz]+") then -- ensure correct target syntax - targ = table.concat(wea_c.tochars(targ:match("[xyz]+"),true,true)) - else - return false, "Error: Invalid \""..targ.."\". Expected \"x\" and or \"y\" and or \"z\"." - end - - if mode == "average" then -- If mode is average set to avg - mode = "avg" - elseif mode:match("[xyz]+") then -- If target is actually base set vars to correct values. - base, targ, mode = targ:sub(1,1), table.concat(wea_c.tochars(mode:match("[xyz]+"),true,true)), false - elseif not modeSet[mode] and not base then -- If mode is invalid and base isn't present throw error - return false, "Error: Invalid \""..mode.."\". Expected \"grow\", \"shrink\", or \"average\"/\"avg\"." - end - - if base then - if oper ~= "equal" then base = false -- If operation isn't equalize we don't need - elseif targ:match(base) then -- Else check that base is not in target and return error if it is - return false, "Error: ("..base..") cannot be included in ("..targ..")." - end - end - - -- Check if operator is valid - if not operSet[oper] then - return false, "Error: Invalid operator \""..oper.."\". Expected \"odd\", \"even\" or \"equal\"." - end - - return true, oper, mode, targ, base - end, - func = function(name, oper, mode, targ, base) - local pos1, pos2 = Vector3.clone(wea_c.pos.get(name, 1)), Vector3.clone(wea_c.pos.get(name, 2)) - local eval -- Declare eval placeholder function to edit later - - local delta = pos2 - pos1 -- local delta equation: Vd(a) = V2(a) - V1(a) - local _tl = #targ -- Get targ length as a variable incase mode is "average"/"avg" - local targ = wea_c.tocharset(targ) -- Break up targ string into set table - local _m = 0 -- _m is the container to hold the max, min or average (depending on the mode) of the axes in targ - - -- set _m to the max, min or mean of the target axes depending on mode or base if it exists - if base then _m = delta[base] - elseif mode == "avg" then - for k,v in pairs(targ) do _m = _m + math.abs(delta[k]) end - _m = _m / _tl - elseif mode == "grow" then - for k,v in pairs(targ) do if math.abs(delta[k]) > _m then _m = math.abs(delta[k]) end end - else - -- Take output of next(targ), put it in a table, wrap the table in brackets to force evlauation so that - -- we can call the first element of that table to serve as the key for a call to delta. - _m = delta[({next(targ)})[1]] - for k,v in pairs(targ) do if math.abs(delta[k]) < _m then _m = math.abs(delta[k]) end end - end - - if oper == "even" then - eval = function(int) - local tmp, abs, neg = int / 2, math.abs(int), int < 0 - if math.floor(tmp) ~= tmp then - if mode == "avg" then - if int > _m then int = abs - 1 - else int = abs + 1 end - elseif mode == "shrink" and abs > 0 then int = abs - 1 - else int = abs + 1 end - end - if neg then int = int * -1 end -- Ensure correct facing direction - return int - end - elseif oper == "odd" then - eval = function(int) - local tmp, abs, neg = int / 2, math.abs(int), int < 0 - if math.floor(tmp) == tmp then - if mode == "avg" then - if int > _m then int = abs - 1 - else int = abs + 1 end - elseif mode == "shrink" and abs > 0 then int = abs - 1 - else int = abs + 1 end - end - if neg then int = int * -1 end - return int - end - else -- Case: oper == "equal" - eval = function(int) - -- Bug: shrink sets pos2 to pos1 - if int < 0 then return _m * -1 - else return _m end - end - end - - for k,_ in pairs(targ) do delta[k] = eval(delta[k]) end - - wea_c.pos.set(name, 2, pos1 + delta) - return true, "Position 2 to "..pos2 - end -}) +local wea_c = worldeditadditions_core +local Vector3 = wea_c.Vector3 + + +-- ███████ ███ ███ █████ ██ ██ ███████ +-- ██ ████ ████ ██ ██ ██ ██ ██ +-- ███████ ██ ████ ██ ███████ █████ █████ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ███████ ██ ██ ██ ██ ██ ██ ███████ +worldeditadditions_core.register_command("smake", { + params = " [ []]", + description = "Make one or more axes of the current selection odd, even, or equal to another.", + privs = { worldedit = true }, + require_pos = 2, + parse = function(params_text) + -- Split params_text, check for missing arguments and fill in empty spots + local parts = wea_c.split(params_text, "%s+", false) + if #parts < 2 then + return false, "Error: Not enough arguments. Expected \" [ []]\"." + else + for i=3,4 do if not parts[i] then parts[i] = false end end + end + + -- Initialize local variables and sets + local oper, mode, targ, base = wea_c.table.unpack(parts) + local operSet, modeSet = wea_c.table.makeset {"equal", "odd", "even"}, wea_c.table.makeset {"grow", "shrink", "avg"} + + -- Main Logic + -- Check base if base is present and if so valid. + if base then + if base:match("[xyz]") then -- ensure correct base syntax + base = base:match("[xyz]") + else + return false, "Error: Invalid base \""..base.."\". Expected \"x\", \"y\" or \"z\"." + end + end + + -- Resolve target then mode (in that order incase mode is target). + if not targ then -- If no target set to default (xz) + targ = "xz" + elseif targ:match("[xyz]+") then -- ensure correct target syntax + targ = table.concat(wea_c.tochars(targ:match("[xyz]+"),true,true)) + else + return false, "Error: Invalid \""..targ.."\". Expected \"x\" and or \"y\" and or \"z\"." + end + + if mode == "average" then -- If mode is average set to avg + mode = "avg" + elseif mode:match("[xyz]+") then -- If target is actually base set vars to correct values. + base, targ, mode = targ:sub(1,1), table.concat(wea_c.tochars(mode:match("[xyz]+"),true,true)), false + elseif not modeSet[mode] and not base then -- If mode is invalid and base isn't present throw error + return false, "Error: Invalid \""..mode.."\". Expected \"grow\", \"shrink\", or \"average\"/\"avg\"." + end + + if base then + if oper ~= "equal" then base = false -- If operation isn't equalize we don't need + elseif targ:match(base) then -- Else check that base is not in target and return error if it is + return false, "Error: ("..base..") cannot be included in ("..targ..")." + end + end + + -- Check if operator is valid + if not operSet[oper] then + return false, "Error: Invalid operator \""..oper.."\". Expected \"odd\", \"even\" or \"equal\"." + end + + return true, oper, mode, targ, base + end, + func = function(name, oper, mode, targ, base) + local pos1, pos2 = Vector3.clone(wea_c.pos.get(name, 1)), Vector3.clone(wea_c.pos.get(name, 2)) + local eval -- Declare eval placeholder function to edit later + + local delta = pos2 - pos1 -- local delta equation: Vd(a) = V2(a) - V1(a) + local _tl = #targ -- Get targ length as a variable incase mode is "average"/"avg" + local targ = wea_c.tocharset(targ) -- Break up targ string into set table + local _m = 0 -- _m is the container to hold the max, min or average (depending on the mode) of the axes in targ + + -- set _m to the max, min or mean of the target axes depending on mode or base if it exists + if base then _m = delta[base] + elseif mode == "avg" then + for k,v in pairs(targ) do _m = _m + math.abs(delta[k]) end + _m = _m / _tl + elseif mode == "grow" then + for k,v in pairs(targ) do if math.abs(delta[k]) > _m then _m = math.abs(delta[k]) end end + else + -- Take output of next(targ), put it in a table, wrap the table in brackets to force evlauation so that + -- we can call the first element of that table to serve as the key for a call to delta. + _m = delta[({next(targ)})[1]] + for k,v in pairs(targ) do if math.abs(delta[k]) < _m then _m = math.abs(delta[k]) end end + end + + if oper == "even" then + eval = function(int) + local tmp, abs, neg = int / 2, math.abs(int), int < 0 + if math.floor(tmp) ~= tmp then + if mode == "avg" then + if int > _m then int = abs - 1 + else int = abs + 1 end + elseif mode == "shrink" and abs > 0 then int = abs - 1 + else int = abs + 1 end + end + if neg then int = int * -1 end -- Ensure correct facing direction + return int + end + elseif oper == "odd" then + eval = function(int) + local tmp, abs, neg = int / 2, math.abs(int), int < 0 + if math.floor(tmp) == tmp then + if mode == "avg" then + if int > _m then int = abs - 1 + else int = abs + 1 end + elseif mode == "shrink" and abs > 0 then int = abs - 1 + else int = abs + 1 end + end + if neg then int = int * -1 end + return int + end + else -- Case: oper == "equal" + eval = function(int) + -- Bug: shrink sets pos2 to pos1 + if int < 0 then return _m * -1 + else return _m end + end + end + + for k,_ in pairs(targ) do delta[k] = eval(delta[k]) end + + wea_c.pos.set(name, 2, pos1 + delta) + return true, "Position 2 to "..pos2 + end +}) diff --git a/worldeditadditions_commands/commands/selectors/srel.lua b/worldeditadditions_commands/commands/selectors/srel.lua index b0af141..73d5cef 100644 --- a/worldeditadditions_commands/commands/selectors/srel.lua +++ b/worldeditadditions_commands/commands/selectors/srel.lua @@ -1,37 +1,37 @@ --- local wea = worldeditadditions -local wea_c = worldeditadditions_core -local Vector3 = wea_c.Vector3 - - --- ███████ ██████ ███████ ██ --- ██ ██ ██ ██ ██ --- ███████ ██████ █████ ██ --- ██ ██ ██ ██ ██ --- ███████ ██ ██ ███████ ███████ - - -worldeditadditions_core.register_command("srel", { - params = "", - description = "Set WorldEdit region position 2 relative to position 1 and player facing.", - privs = { worldedit = true }, - require_pos = 0, - parse = function(params_text) - local ret = wea_c.split(params_text) - if #ret < 1 then return false, "SREL: No params found!" - else return true, ret end - end, - func = function(name, params_text) - local facing = wea_c.player_dir(name) - local vec, err = wea_c.parse.directions(params_text, facing, true) - if not vec then return false, err end - - local pos1 = wea_c.pos.get(name, 1) - local pos2 = pos1:add(vec) - - wea_c.pos.set_all(name, {pos1, pos2}) - return true, "Position 1 to "..pos1..", Position 2 to "..pos2 - end, -}) - --- Tests --- //srel front 5 left 3 y 2 +-- local wea = worldeditadditions +local wea_c = worldeditadditions_core +local Vector3 = wea_c.Vector3 + + +-- ███████ ██████ ███████ ██ +-- ██ ██ ██ ██ ██ +-- ███████ ██████ █████ ██ +-- ██ ██ ██ ██ ██ +-- ███████ ██ ██ ███████ ███████ + + +worldeditadditions_core.register_command("srel", { + params = "", + description = "Set WorldEdit region position 2 relative to position 1 and player facing.", + privs = { worldedit = true }, + require_pos = 0, + parse = function(params_text) + local ret = wea_c.split(params_text) + if #ret < 1 then return false, "SREL: No params found!" + else return true, ret end + end, + func = function(name, params_text) + local facing = wea_c.player_dir(name) + local vec, err = wea_c.parse.directions(params_text, facing, true) + if not vec then return false, err end + + local pos1 = wea_c.pos.get(name, 1) + local pos2 = pos1:add(vec) + + wea_c.pos.set_all(name, {pos1, pos2}) + return true, "Position 1 to "..pos1..", Position 2 to "..pos2 + end, +}) + +-- Tests +-- //srel front 5 left 3 y 2 diff --git a/worldeditadditions_commands/commands/selectors/sshrink.lua b/worldeditadditions_commands/commands/selectors/sshrink.lua index e46ec67..17eb91d 100644 --- a/worldeditadditions_commands/commands/selectors/sshrink.lua +++ b/worldeditadditions_commands/commands/selectors/sshrink.lua @@ -1,42 +1,42 @@ --- local wea = worldeditadditions -local wea_c = worldeditadditions_core -local Vector3 = wea_c.Vector3 - - --- ███████ ███████ ██ ██ ██████ ██ ███ ██ ██ ██ --- ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██ --- ███████ ███████ ███████ ██████ ██ ██ ██ ██ █████ --- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ --- ███████ ███████ ██ ██ ██ ██ ██ ██ ████ ██ ██ - - -worldeditadditions_core.register_command("sshrink", { - params = "", - description = "Shrink selection region", - privs = { worldedit = true }, - require_pos = 0, - parse = function(params_text) - local ret = wea_c.split(params_text) - if #ret < 1 then return false, "Error: No params found!" - else return true, ret end - end, - func = function(name, params_text) - local facing = wea_c.player_dir(name) - local min, max = wea_c.parse.directions(params_text, facing) - if not min then return false, max end - - local pos1 = wea_c.pos.get(name, 1) - local pos2 = wea_c.pos.get(name, 2) - - if not pos2 then wea_c.pos.set(name, 2, pos1) - else pos1, pos2 = Vector3.sort(pos1, pos2) end - - pos1, pos2 = pos1:add(max), pos2:add(min) - - wea_c.pos.set_all(name, {pos1, pos2}) - return true, "Position 1 to "..pos1..", Position 2 to "..pos2 - end, -}) - --- Tests --- //srel front 5 left 3 y 2 +-- local wea = worldeditadditions +local wea_c = worldeditadditions_core +local Vector3 = wea_c.Vector3 + + +-- ███████ ███████ ██ ██ ██████ ██ ███ ██ ██ ██ +-- ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██ +-- ███████ ███████ ███████ ██████ ██ ██ ██ ██ █████ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ███████ ███████ ██ ██ ██ ██ ██ ██ ████ ██ ██ + + +worldeditadditions_core.register_command("sshrink", { + params = "", + description = "Shrink selection region", + privs = { worldedit = true }, + require_pos = 0, + parse = function(params_text) + local ret = wea_c.split(params_text) + if #ret < 1 then return false, "Error: No params found!" + else return true, ret end + end, + func = function(name, params_text) + local facing = wea_c.player_dir(name) + local min, max = wea_c.parse.directions(params_text, facing) + if not min then return false, max end + + local pos1 = wea_c.pos.get(name, 1) + local pos2 = wea_c.pos.get(name, 2) + + if not pos2 then wea_c.pos.set(name, 2, pos1) + else pos1, pos2 = Vector3.sort(pos1, pos2) end + + pos1, pos2 = pos1:add(max), pos2:add(min) + + wea_c.pos.set_all(name, {pos1, pos2}) + return true, "Position 1 to "..pos1..", Position 2 to "..pos2 + end, +}) + +-- Tests +-- //srel front 5 left 3 y 2 diff --git a/worldeditadditions_commands/commands/uasparse.lua b/worldeditadditions_commands/commands/uasparse.lua index bf072f4..d81b608 100644 --- a/worldeditadditions_commands/commands/uasparse.lua +++ b/worldeditadditions_commands/commands/uasparse.lua @@ -1,29 +1,29 @@ -local wea_c = worldeditadditions_core --- local Vector3 = wea_c.Vector3 - --- ██ ██ █████ ███████ ██████ █████ ██████ ███████ ███████ --- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ --- ██ ██ ███████ ███████ ██████ ███████ ██████ ███████ █████ --- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ --- ██████ ██ ██ ███████ ██ ██ ██ ██ ██ ███████ ███████ - -worldeditadditions_core.register_command("uasparse", { - params = "", - description = "Debug command. Returns min and max vectors for given inputs", - privs = { worldedit = true }, - -- require_pos = 2, - parse = function(params_text) - local ret = wea_c.split(params_text) - if #ret < 1 then return false, "Error: No params found!" - else return true, ret end - end, - func = function(name, params_text) - local facing = wea_c.player_dir(name) - local min, max = wea_c.parse.directions(params_text, facing) - if not min then - return false, max - else - return true, "Min: "..min.." Max: "..max - end - end -}) +local wea_c = worldeditadditions_core +-- local Vector3 = wea_c.Vector3 + +-- ██ ██ █████ ███████ ██████ █████ ██████ ███████ ███████ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ██ ██ ███████ ███████ ██████ ███████ ██████ ███████ █████ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ██████ ██ ██ ███████ ██ ██ ██ ██ ██ ███████ ███████ + +worldeditadditions_core.register_command("uasparse", { + params = "", + description = "Debug command. Returns min and max vectors for given inputs", + privs = { worldedit = true }, + -- require_pos = 2, + parse = function(params_text) + local ret = wea_c.split(params_text) + if #ret < 1 then return false, "Error: No params found!" + else return true, ret end + end, + func = function(name, params_text) + local facing = wea_c.player_dir(name) + local min, max = wea_c.parse.directions(params_text, facing) + if not min then + return false, max + else + return true, "Min: "..min.." Max: "..max + end + end +}) diff --git a/worldeditadditions_core/utils/strings/split.lua b/worldeditadditions_core/utils/strings/split.lua index 2436a74..1e1ff60 100644 --- a/worldeditadditions_core/utils/strings/split.lua +++ b/worldeditadditions_core/utils/strings/split.lua @@ -1,90 +1,90 @@ --- Licence: GPLv2 (MPL-2.0 is compatible, so we can use this here) --- Source: https://stackoverflow.com/a/43582076/1460422 - --- gsplit: iterate over substrings in a string separated by a pattern --- --- Parameters: --- text (string) - the string to iterate over --- pattern (string) - the separator pattern --- plain (boolean) - if true (or truthy), pattern is interpreted as a plain --- string, not a Lua pattern --- --- Returns: iterator --- --- Usage: --- for substr in gsplit(text, pattern, plain) do --- doSomething(substr) --- end -local function gsplit(text, pattern, plain) - local splitStart, length = 1, #text - return function () - if splitStart then - local sepStart, sepEnd = string.find(text, pattern, splitStart, plain) - local ret - if not sepStart then - ret = string.sub(text, splitStart) - splitStart = nil - elseif sepEnd < sepStart then - -- Empty separator! - ret = string.sub(text, splitStart, sepStart) - if sepStart < length then - splitStart = sepStart + 1 - else - splitStart = nil - end - else - ret = sepStart > splitStart and string.sub(text, splitStart, sepStart - 1) or '' - splitStart = sepEnd + 1 - end - return ret - end - end -end - - ---- Split a string into substrings separated by a pattern. -- Deprecated --- @param text string The string to iterate over --- @param pattern string The separator pattern --- @param plain boolean If true (or truthy), pattern is interpreted as a --- plain string, not a Lua pattern --- @returns table A sequence table containing the substrings -local function dsplit(text, pattern, plain) - local ret = {} - for match in gsplit(text, pattern, plain) do - table.insert(ret, match) - end - return ret -end - ---- Split a string into substrings separated by a pattern. --- @param str string The string to iterate over --- @param dlm="%s+" string The delimiter (separator) pattern. If a falsey value is passed, then the default value is used. --- @param plain boolean If true (or truthy), pattern is interpreted as a --- plain string, not a Lua pattern --- @returns table A sequence table containing the substrings -local function split(str,dlm,plain) - if not dlm then dlm = "%s+" end - local pos, ret = 0, {} - local ins, i = str:find(dlm,pos,plain) - -- "if plain" shaves off some time in the while statement - if plain then - while ins do - table.insert(ret,str:sub(pos,ins - 1)) - pos = ins + #dlm - ins = str:find(dlm,pos,true) - end - else - while ins do - table.insert(ret,str:sub(pos,ins - 1)) - pos = i + 1 - ins, i = str:find(dlm,pos) - end - end - -- print(pos..","..#str) - if str:sub(pos,#str) ~= "" then - table.insert(ret,str:sub(pos,#str)) - end - return ret -end - +-- Licence: GPLv2 (MPL-2.0 is compatible, so we can use this here) +-- Source: https://stackoverflow.com/a/43582076/1460422 + +-- gsplit: iterate over substrings in a string separated by a pattern +-- +-- Parameters: +-- text (string) - the string to iterate over +-- pattern (string) - the separator pattern +-- plain (boolean) - if true (or truthy), pattern is interpreted as a plain +-- string, not a Lua pattern +-- +-- Returns: iterator +-- +-- Usage: +-- for substr in gsplit(text, pattern, plain) do +-- doSomething(substr) +-- end +local function gsplit(text, pattern, plain) + local splitStart, length = 1, #text + return function () + if splitStart then + local sepStart, sepEnd = string.find(text, pattern, splitStart, plain) + local ret + if not sepStart then + ret = string.sub(text, splitStart) + splitStart = nil + elseif sepEnd < sepStart then + -- Empty separator! + ret = string.sub(text, splitStart, sepStart) + if sepStart < length then + splitStart = sepStart + 1 + else + splitStart = nil + end + else + ret = sepStart > splitStart and string.sub(text, splitStart, sepStart - 1) or '' + splitStart = sepEnd + 1 + end + return ret + end + end +end + + +--- Split a string into substrings separated by a pattern. -- Deprecated +-- @param text string The string to iterate over +-- @param pattern string The separator pattern +-- @param plain boolean If true (or truthy), pattern is interpreted as a +-- plain string, not a Lua pattern +-- @returns table A sequence table containing the substrings +local function dsplit(text, pattern, plain) + local ret = {} + for match in gsplit(text, pattern, plain) do + table.insert(ret, match) + end + return ret +end + +--- Split a string into substrings separated by a pattern. +-- @param str string The string to iterate over +-- @param dlm="%s+" string The delimiter (separator) pattern. If a falsey value is passed, then the default value is used. +-- @param plain boolean If true (or truthy), pattern is interpreted as a +-- plain string, not a Lua pattern +-- @returns table A sequence table containing the substrings +local function split(str,dlm,plain) + if not dlm then dlm = "%s+" end + local pos, ret = 0, {} + local ins, i = str:find(dlm,pos,plain) + -- "if plain" shaves off some time in the while statement + if plain then + while ins do + table.insert(ret,str:sub(pos,ins - 1)) + pos = ins + #dlm + ins = str:find(dlm,pos,true) + end + else + while ins do + table.insert(ret,str:sub(pos,ins - 1)) + pos = i + 1 + ins, i = str:find(dlm,pos) + end + end + -- print(pos..","..#str) + if str:sub(pos,#str) ~= "" then + table.insert(ret,str:sub(pos,#str)) + end + return ret +end + return split \ No newline at end of file