Compare commits
5 Commits
74a8996afc
...
9f8cb4d5da
Author | SHA1 | Date |
---|---|---|
Starbeamrainbowlabs | 9f8cb4d5da | |
Starbeamrainbowlabs | 27aa3a9c8f | |
Starbeamrainbowlabs | 7d29453699 | |
Starbeamrainbowlabs | b92cc434db | |
Starbeamrainbowlabs | 873ff4bef8 |
|
@ -11,6 +11,9 @@ Note to self: See the bottom of this file for the release template text.
|
|||
- Added [`//nodeapply`](https://worldeditadditions.mooncarrot.space/Reference/#nodeapply), a generalisation of [`//airapply`](https://worldeditadditions.mooncarrot.space/Reference/#airapply) that works with a defined list of nodes. Check out [the reference](https://worldeditadditions.mooncarrot.space/Reference/#nodeapply) - it has some cool tricks to it! (thanks for suggesting, @kliv91 from the Discord server!)
|
||||
- Added [`//ngroups`](https://worldeditadditions.mooncarrot.space/Reference/#ngroups), which lists the groups that a given node is a member of. Useful when paired with [`//nodeapply`](https://worldeditadditions.mooncarrot.space/Reference/#nodeapply)!
|
||||
|
||||
### Bugfixes and changes
|
||||
- Don't warn on failed registration of `//flora` → [`//bonemeal`](https://worldeditadditions.mooncarrot.space/Reference/#bonemeal) if the `bonemeal` mod isn't installed (e.g. in MineClone2) - thanks @VorTechnix in #106
|
||||
|
||||
|
||||
## v1.14.5: The multipoint update, hotfix 5 (1st August 2023)
|
||||
- Fix a bug where creative players in survival couldn't punch out position markers
|
||||
|
|
|
@ -32,6 +32,7 @@ dofile(wea.modpath.."/lib/spiral_circle.lua")
|
|||
dofile(wea.modpath.."/lib/dome.lua")
|
||||
dofile(wea.modpath.."/lib/spline.lua")
|
||||
dofile(wea.modpath.."/lib/revolve.lua")
|
||||
dofile(wea.modpath.."/lib/rotate.lua")
|
||||
dofile(wea.modpath.."/lib/conv/conv.lua")
|
||||
dofile(wea.modpath.."/lib/erode/erode.lua")
|
||||
dofile(wea.modpath.."/lib/noise/init.lua")
|
||||
|
|
|
@ -16,15 +16,20 @@ local function __compile_rotlist(rotlist)
|
|||
--- 1: Construct a Vector3 to represent which axis we want to rotate on
|
||||
local rotval = Vector3.new(0, 0, 0)
|
||||
-- Assume that if it's a table, it's a Vector3 instance
|
||||
if type(rot) == "table" then rotval = rot:clone() end
|
||||
|
||||
if rot.axis:find("x", 1, true) then rotval.x = 1
|
||||
elseif rot.axis:find("y", 1, true) then rotval.y = 1
|
||||
elseif rot.axis:find("z", 1, true) then rotval.z = 1 end
|
||||
if rot.axis:sub(1, 1) == "-" then
|
||||
rotval = rotval * -1
|
||||
if type(rot) == "table" then
|
||||
print("DEBUG:__compile_rotlist rot is talble, ROT", weac.inspect(rot))
|
||||
rotval = rot.axis:clone()
|
||||
else
|
||||
-- Otherwise, treat it as a string
|
||||
if rot.axis:find("x", 1, true) then rotval.x = 1
|
||||
elseif rot.axis:find("y", 1, true) then rotval.y = 1
|
||||
elseif rot.axis:find("z", 1, true) then rotval.z = 1 end
|
||||
if rot.axis:sub(1, 1) == "-" then
|
||||
rotval = rotval * -1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- 2: Rotate & apply amount of rotation to apply in radians
|
||||
return rotval * rot.rad
|
||||
end)
|
||||
|
@ -53,6 +58,7 @@ function worldeditadditions.rotate(pos1, pos2, origin, rotlist)
|
|||
-- First, rotate the defined region to find the target region
|
||||
local pos1_rot, pos2_rot = pos1:clone(), pos2:clone()
|
||||
for i, rot in ipairs(rotlist_c) do
|
||||
print("DEBUG origin", weac.inspect(origin), "pos1_rot", weac.inspect(pos1_rot), "pos2_rot", weac.inspect(pos2_rot), "rot", weac.inspect(rot))
|
||||
pos1_rot = Vector3.rotate3d(origin, pos1_rot, rot)
|
||||
pos2_rot = Vector3.rotate3d(origin, pos2_rot, rot)
|
||||
end
|
||||
|
@ -67,6 +73,9 @@ function worldeditadditions.rotate(pos1, pos2, origin, rotlist)
|
|||
local manip_src, area_src = worldedit.manip_helpers.init(pos1, pos2)
|
||||
local data_src = manip_src:get_data()
|
||||
|
||||
-- TODO: grab only an area at this point for dest and a blank target table. Then copy over to the real dest later to ensure consistency. This is important because we are dealing in (potentially) non-cardinal rectangles here
|
||||
-- local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
|
||||
|
||||
local manip_dest, area_dest = worldedit.manip_helpers.init(pos1_dstvm, pos2_dstvm)
|
||||
local data_dest = manip_dest:get_data()
|
||||
-- TODO: Also carry param2 along for the ride
|
||||
|
@ -81,7 +90,7 @@ function worldeditadditions.rotate(pos1, pos2, origin, rotlist)
|
|||
local cpos_dest = cpos_src:clone()
|
||||
|
||||
-- TODO: This is very inefficient. If we could use quaternions here to stack up the rotations, it would be much more efficient.
|
||||
for i, rot in ipairs(rotlist) do
|
||||
for i, rot in ipairs(rotlist_c) do
|
||||
cpos_dest = Vector3.rotate3d(origin, cpos_dest, rot)
|
||||
end
|
||||
|
||||
|
|
|
@ -7,7 +7,10 @@ wea_c.register_alias("conv", "convolve")
|
|||
wea_c.register_alias("naturalise", "layers")
|
||||
wea_c.register_alias("naturalize", "layers")
|
||||
|
||||
wea_c.register_alias("flora", "bonemeal")
|
||||
if wea_c.command_exists("/bonemeal") then
|
||||
-- No need to log here, since we notify the server admin in the server logs in the dofile() for the main //bonemeal command
|
||||
wea_c.register_alias("flora", "bonemeal")
|
||||
end
|
||||
|
||||
-- Measure Tools
|
||||
wea_c.register_alias("mcount", "count")
|
||||
|
|
|
@ -8,7 +8,7 @@ local Vector3 = wea_c.Vector3
|
|||
-- ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||
-- ██ ██ ██████ ██ ██ ██ ██ ███████
|
||||
|
||||
worldeditadditions_core.register_command("rotate", {
|
||||
worldeditadditions_core.register_command("rotate+", {
|
||||
params = "<axis> <degrees> [<axis> <degrees> ...] [origin|o [<pos_number>]]",
|
||||
description = "Rotates the defined region arounnd the given axis by the given number of degrees. Angles are NOT limited to 90-degree increments. When multiple axes and angles are specified, these transformations are applied in order. If o [<pos_number>] is specified, then the specific position number (default: 3) is considered a custom rotation origin instead of the centre of the region. CAUTION: Rotating large areas of memory by 45° can be memory intensive!",
|
||||
privs = { worldedit = true },
|
||||
|
@ -17,6 +17,8 @@ worldeditadditions_core.register_command("rotate", {
|
|||
if not params_text then params_text = "" end
|
||||
local parts = wea_c.split_shell(params_text)
|
||||
|
||||
print("DEBUG:rotate/parse parts", wea_c.inspect(parts))
|
||||
|
||||
local mode_store
|
||||
local mode = "AXIS"
|
||||
local success, axis_next, angle
|
||||
|
@ -27,7 +29,14 @@ worldeditadditions_core.register_command("rotate", {
|
|||
for i,part in ipairs(parts) do
|
||||
if part == "origin" or part == "o" then
|
||||
mode_store = mode
|
||||
mode = "ORIGIN"
|
||||
|
||||
-- If the NEXT item is a number, then parse it.
|
||||
if i < #parts and tonumber(parts[i+1]) ~= nil then
|
||||
mode = "ORIGIN"
|
||||
else
|
||||
-- If not, then default to pos3 and continue in the original mode
|
||||
origin = 3
|
||||
end
|
||||
elseif mode == "ORIGIN" then
|
||||
origin = tonumber(part)
|
||||
if not origin or origin < 1 then
|
||||
|
@ -38,7 +47,7 @@ worldeditadditions_core.register_command("rotate", {
|
|||
mode = mode_store
|
||||
mode_store = nil
|
||||
elseif mode == "AXIS" then
|
||||
axis_next = wea_c.parse.axis_rotation.axis_name(part)
|
||||
success, axis_next = wea_c.parse.axes_rotation.axis_name(part)
|
||||
if not success then return success, axis_next end
|
||||
mode = "ANGLE"
|
||||
elseif mode == "ANGLE" then
|
||||
|
@ -75,21 +84,46 @@ worldeditadditions_core.register_command("rotate", {
|
|||
end
|
||||
end
|
||||
|
||||
print("DEBUG:rotate/parse ORIGIN", origin, "rotlist", wea_c.inspect(rotlist))
|
||||
|
||||
return true, origin, rotlist
|
||||
end,
|
||||
nodes_needed = function(name, times)
|
||||
-- TODO: .......this is a good question, actually.
|
||||
nodes_needed = function(name, origin, rotlist)
|
||||
-- BUG: .......this is a good question, actually. This naïve is flawed, since if we rotate by e.g. 45° we could end up replacing more nodes than if we rotate by 90° increments. This is further complicated by the allowance of a custom point of origin.
|
||||
return Vector3.volume(wea_c.pos.get1(name), wea_c.pos.get2(name)) * 2
|
||||
end,
|
||||
func = function(name, origin, rotlist)
|
||||
local start_time = wea_c.get_ms_time()
|
||||
|
||||
-- TODO: Do rotation operation here.
|
||||
-------------------------------------------------
|
||||
|
||||
|
||||
local pos1, pos2 = wea_c.pos.get1(name), wea_c.pos.get2(name)
|
||||
|
||||
local pos_origin = nil
|
||||
if type(origin) == "number" then
|
||||
pos_origin = wea_c.pos.get(name, origin)
|
||||
elseif type(origin) == "string" and origin == "__AUTO__" then
|
||||
pos_origin = Vector3.mean(pos1, pos2)
|
||||
end
|
||||
if pos_origin == nil then
|
||||
-- There's a very small chance that this could be a bug here if origin is (NOT type("number") and NOT type("string") and ~= "__AUTO__"), but this shouldn't happen because we constrain the output of the above parser. This means we can safely make this assumption here
|
||||
return false, "Error: Failed to get origin point from position "..tostring(origin).." because it doesn't exist."
|
||||
end
|
||||
|
||||
|
||||
local success, stats = worldeditadditions.rotate(
|
||||
pos1, pos2,
|
||||
pos_origin,
|
||||
rotlist
|
||||
)
|
||||
if not success then return success, stats end
|
||||
|
||||
-- TODO: Adjust the defined area to match the target here? Maybe make this optional somehow given the target may or may nor be axis-aligned
|
||||
-------------------------------------------------
|
||||
local time_taken = wea_c.get_ms_time() - start_time
|
||||
|
||||
|
||||
-- TODO: Update logging below. This will obviously crash due to unknown variables right now.
|
||||
minetest.log("action", name .. " used //rotate at "..pos1.." - "..pos2.." with origin "..origin..", replacing "..changed.." nodes in "..time_taken.."s")
|
||||
return true, changed.." nodes replaced in "..wea_c.format.human_time(time_taken)
|
||||
minetest.log("action", name .. " used //rotate at "..pos1.." - "..pos2.." with origin "..pos_origin..", rotating "..stats.count_rotated.." nodes in "..time_taken.."s")
|
||||
return true, stats.count_rotated.." nodes rotated through "..tostring(#rotlist).." rotations in "..wea_c.format.human_time(time_taken)
|
||||
end
|
||||
})
|
||||
|
|
|
@ -38,6 +38,7 @@ dofile(wea_cmd.modpath.."/commands/count.lua")
|
|||
dofile(wea_cmd.modpath.."/commands/sculpt.lua")
|
||||
dofile(wea_cmd.modpath.."/commands/spline.lua")
|
||||
dofile(wea_cmd.modpath.."/commands/revolve.lua")
|
||||
dofile(wea_cmd.modpath.."/commands/rotate.lua")
|
||||
|
||||
-- Meta Commands
|
||||
dofile(wea_cmd.modpath .. "/commands/meta/init.lua")
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
--- WorldEditAdditions chat command registration
|
||||
-- @namespace worldeditadditions_core
|
||||
local wea_c = worldeditadditions_core
|
||||
|
||||
|
||||
--- Returns whether a WorldEditAdditions (or WorldEdit) command exists with the given name.
|
||||
-- Note that this does NOT check for general Minetest chat commands - only commands registered through WorldEditAdditions or WorldEdit, if WorldEdit is currently loaded - the eventual plan is to make it an optional dependency.
|
||||
-- @param cmdname string The name of the command to check for. Remember to remove the first forward slash! In other words if you would normally type `//layers` in-game, then you'd call `worldeditadditions.command_exists("/layers")`.
|
||||
-- @param only_wea bool If true, then only check for WorldEditAdditions commands and not commands from related compatible mods such as WorldEdit.
|
||||
-- @returns bool Whether a WorldEdit/WorldEditAdditions command exists with the given name.
|
||||
local function command_exists(cmdname, only_wea)
|
||||
if only_wea == nil then only_wea = false end
|
||||
if wea_c.registered_commands[cmdname] ~= nil then
|
||||
return true
|
||||
end
|
||||
if only_wea == true then return false end
|
||||
if worldedit.registered_commands[cmdname] ~= nil then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
return command_exists
|
|
@ -5,7 +5,7 @@
|
|||
-- ██ ██ ███████ ██████ ██ ███████ ██ ███████ ██ ██
|
||||
|
||||
--- WorldEditAdditions chat command registration
|
||||
-- @module worldeditadditions_core
|
||||
-- @namespace worldeditadditions_core
|
||||
local wea_c = worldeditadditions_core
|
||||
local run_command = dofile(wea_c.modpath.."/core/run_command.lua")
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ local function run_command(cmdname, options, player_name, paramtext)
|
|||
local parse_result = { options.parse(paramtext) }
|
||||
local success = table.remove(parse_result, 1)
|
||||
if not success then
|
||||
worldedit.player_notify(player_name, parse_result[1] or "Invalid usage (no further error message was provided by the command. This is probably a bug.)")
|
||||
worldedit.player_notify(player_name, tostring(parse_result[1]) or "Invalid usage (no further error message was provided by the command. This is probably a bug.)")
|
||||
return false
|
||||
end
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@ wea_c.setting_handler = dofile(wea_c.modpath.."/utils/setting_handler.lua") -- A
|
|||
|
||||
wea_c.pos = dofile(modpath.."/core/pos.lua") -- AFTER EventEmitter
|
||||
wea_c.register_command = dofile(modpath.."/core/register_command.lua")
|
||||
wea_c.command_exists = dofile(modpath.."/core/command_exists.lua")
|
||||
wea_c.fetch_command_def = dofile(modpath.."/core/fetch_command_def.lua")
|
||||
wea_c.register_alias = dofile(modpath.."/core/register_alias.lua")
|
||||
wea_c.entities = dofile(modpath.."/core/entities/init.lua") -- AFTER pos
|
||||
|
|
|
@ -21,7 +21,7 @@ function rot_axis_left(axis)
|
|||
elseif axis.z == 1 or axis.z == -1 then
|
||||
axis.x, axis.z = -axis.z, 0
|
||||
end
|
||||
return axis -- CAUDION, this function mutates!
|
||||
return axis -- CAUTION, this function mutates!
|
||||
end
|
||||
|
||||
--- Parses an axis name into a string.
|
||||
|
@ -40,12 +40,12 @@ local function parse_rotation_axis_name(str, player)
|
|||
|
||||
-- At most ONE of these cases is true at a time.
|
||||
-- Even if it were possible to handle more than one (which it isn't without quaternions which aren't used in the backend), we would have an undefined ordering problem with the application of such rotations. Rotations ≠ translations in this case!
|
||||
if str:find("x", 1, true) then rotval.x = 1
|
||||
elseif str:find("y", 1, true) then rotval.y = 1
|
||||
elseif str:find("z", 1, true) then rotval.z = 1
|
||||
elseif str:find("left", 1, true) then rotval.z = -1
|
||||
if str:find("x", 1, true) then vector.x = 1
|
||||
elseif str:find("y", 1, true) then vector.y = 1
|
||||
elseif str:find("z", 1, true) then vector.z = 1
|
||||
elseif str:find("left", 1, true) then vector.z = -1
|
||||
elseif str:find("right", 1, true)
|
||||
or str:find("yaw") then rotval.z = 1
|
||||
or str:find("yaw") then vector.z = 1
|
||||
elseif type(player) ~= "nil" then
|
||||
local player_rotation_h = calc_rotation_text(player:get_look_horizontal())
|
||||
|
||||
|
|
Loading…
Reference in New Issue