Implement //set+

This is on the road to //orient and later stair/etc support in //rotate :D
This commit is contained in:
Starbeamrainbowlabs 2024-05-25 14:45:56 +01:00
parent 00478c2ea8
commit ffdd1b65b3
No known key found for this signature in database
GPG Key ID: 1BE5172E637709C2
8 changed files with 266 additions and 0 deletions

@ -13,11 +13,16 @@ Note to self: See the bottom of this file for the release template text.
- Added [`//rotate+`](https://worldeditadditions.mooncarrot.space/Reference/#rotate) to rotate regions through arbitrary series of potentially non-axis-aligned rotations. **Does not support slabs/stairs yet,** but this is on the todo list!
- Added [`//speed`](https://worldeditadditions.mooncarrot.space/Reference/#rotate) to adjust your own movement speed
- Also added an associated [movement speed adjustment tool](https://worldeditadditions.mooncarrot.space/Reference/#movement), which looks like this: ![A picture of the move speed adjustment tool. It looks like a monarch butterfly.](https://raw.githubusercontent.com/sbrl/Minetest-WorldEditAdditions/dev/worldeditadditions_farwand/textures/worldeditadditions_movement.png)
- Added [`//set+`](https://worldeditadditions.mooncarrot.space/Reference/#set) for setting nodes and param2/light levels quickly.
- NOTE TO SELF: Setting light values doesn't appear to be working very well for some reason
### 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
- Improve documentation of [`//noise2d`](https://worldeditadditions.mooncarrot.space/Reference/#noise2d). If it still doesn't make sense, please let me know. It's a complicated command that needs reworking a bit to be easier to use.
### Lua API changes
- Add `core.pos.get12(player_name, sort=false)`
## 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

@ -41,6 +41,7 @@ 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/set.lua")
dofile(wea.modpath.."/lib/conv/conv.lua")
dofile(wea.modpath.."/lib/erode/erode.lua")
dofile(wea.modpath.."/lib/noise/init.lua")

@ -0,0 +1,51 @@
local weac = worldeditadditions_core
local Vector3 = weac.Vector3
---
-- @module worldeditadditions
-- ██████ ██████ ██ ███████ ███ ██ ████████
-- ██ ██ ██ ██ ██ ██ ████ ██ ██
-- ██ ██ ██████ ██ █████ ██ ██ ██ ██
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
-- ██████ ██ ██ ██ ███████ ██ ████ ██
--- Re-orients the nodes in the given region around a given origin point using a set of rotations.
-- TODO Learn quaternions and make this more effiient.
-- @param pos1 Vector3 Position 1 of the region to orient nodes in.
-- @param pos2 Vector3 Position 2 of the region to orient nodes in.
-- @param rotlist table<{axis: string, rad: number}> The list of rotations. Rotations will be processed in order. Each rotation is a table with a SINGLE axis as a string (x, y, z, -x, -y, or -z; the axis parameter), and an amount in radians to rotate by (the rad parameter).
-- @returns bool,string|table<{changed: number}> A success boolean (true == success; false == failure), followed by either an error message as a string if success == false or a table of statistics if success == true.
--
-- Currently the only parameter in the statistics table is changed, which is a number representing the number of nodes that were rotated.
--
-- This is NOT NECESSARILY the number of nodes in the target region..... since rotations and roundings mean the target area the source region was rotated into could have slightly more or less nodes than the source region.
function worldeditadditions.orient(pos1, pos2, rotlist)
pos1, pos2 = Vector3.sort(pos1, pos2)
--- 1: Compile the rotation list
local rotlist_c = weac.rotation.rotlist_compile(rotlist)
--- 2: Fetch the nodes in the specified area
local manip, area = worldedit.manip_helpers.init(pos1, pos2)
local data = manip:get_data()
local stats = {
count = 0
}
local param2_cache = {}
for i in area:iterp(pos1, pos2) do
-- data[i]
stats.count = stats.count + 1
end
--- 8: Return
return true, stats
end

@ -0,0 +1,79 @@
local wea_c = worldeditadditions_core
local Vector3 = wea_c.Vector3
---
-- @module worldeditadditions
-- ███████ ███████ ████████
-- ██ ██ ██
-- ███████ █████ ██
-- ██ ██ ██
-- ███████ ███████ ██
--- Sets the given parameter to the given value.
-- This function would pair well with worldeditadditions.nodeapply.
-- @param pos1 Vector3 Position 1 of the define region to operate on.
-- @param pos2 Vector3 Position 2 of the define region to operate on.
-- @param param string="param|param2" The name of the parameter to set. Currently possible values:
-- - **`param`:** Param1, aka the node id.
-- - **`param2`:** The supplementary parameter that each node has. See also <https://api.minetest.net/nodes/#node-paramtypes>. The node type is set by the mod or game that provides each node in question.
-- - **`light`:** Sets the light value of all nodes in the defined region.
-- @param value string|number The value to set the given parameter to. If `param` is set to "param" and `value` is a `string`, then `value` is converted into a number by calling `minetest.get_content_id()`.
-- @returns bool,table|string true,statistics_table OR false,error_message.
function worldeditadditions.set(pos1, pos2, mode, value)
if mode ~= "param" and mode ~= "param2" and mode ~= "light" then
return false, "Error: Unknown parameter type "..tostring(mode)..". Supported values: param, param2."
end
pos1, pos2 = Vector3.sort(pos1, pos2)
-- pos2 will always have the highest co-ordinates now
print("SET mode", mode, "value", value)
local setvalue = value
if mode == "param" and type(setvalue) == "string" then
setvalue = minetest.get_content_id(setvalue)
print("SET TRANSFORM setvalue TO", setvalue)
end
print("SET setvalue", setvalue)
-- Initialise statistics
local stats = { changed = 0 }
-- Fetch the nodes in the specified area
local manip, area = worldedit.manip_helpers.init(pos1, pos2)
local data = nil
if mode == "param" then
data = manip:get_data()
elseif mode == "param2" then
data = manip:get_param2_data()
elseif mode == "light" then
-- Shortcut!
manip:set_lighting({ day = setvalue, night = setvalue }, pos1, pos2)
manip:write_to_map(false)
manip:update_map()
return true, stats
end
for i in area:iterp(pos1, pos2) do
data[i] = setvalue
stats.changed = stats.changed + 1
end
if mode == "param" then
manip:set_data(data)
else
manip:set_param2_data(data)
end
-- Save the modified nodes back to disk & return
-- Can't use worldedit.manip_helpers.finish 'cause of dynamic param/light setting
manip:write_to_map()
manip:update_map()
return true, stats
end

@ -0,0 +1,83 @@
local wea = worldeditadditions
local core = worldeditadditions_core
local Vector3 = core.Vector3
-- ███████ ███████ ████████ █
-- ██ ██ ██ █
-- ███████ █████ ██ ████████
-- ██ ██ ██ █
-- ███████ ███████ ██ █
core.register_command("set+", {
params =
"[param|param2|p2|light|l] <value>",
description =
"Sets the node, param2, or light level to a fixed value in the defined region. Defaults to setting the node. If param2/p2 is specified, the param2 value associated with nodes is set instead. If light/l is specified, the light level is set.",
privs = { worldedit = true },
require_pos = 2,
parse = function(params_text)
if not params_text or params_text == "" then
return false, "Error: No arguments specified"
end
local parts = core.split_shell(params_text)
print("parts", core.inspect(parts))
local mode = "param"
local value = nil
local possible_modes = { "param", "p", "param2", "p2", "light", "l" }
if core.table.contains(possible_modes, parts[1]) then
mode = parts[1]
table.remove(parts, 1)
end
value = table.concat(parts, " ")
print("mode", core.inspect(mode))
print("value", core.inspect(value))
-- Normalise mode
if mode == "p" then mode = "param"
elseif mode == "p2" then mode = "param2"
elseif mode == "l" then mode = "light" end
if mode == "param" then
local val_raw = value
value = worldedit.normalize_nodename(value)
if not value then return false, tostring(val_raw).." could not be normalised into a valid node name, and the mode was set to 'param'." end
else
local val_raw = value
value = tonumber(value)
if not value then return false, tostring(val_raw).." does not appear to be a valid number." end
value = math.floor(value)
end
print("AFTER mode", core.inspect(mode))
print("AFTER value", core.inspect(value))
return true, mode, value
end,
nodes_needed = function(name) -- target_node, target_node_chance, replace_nodes
return worldedit.volume(worldedit.pos1[name], worldedit.pos2[name])
end,
func = function(name, mode, value)
local start_time = core.get_ms_time()
local pos1, pos2 = core.pos.get12(name)
local success, stats = wea.set(
worldedit.pos1[name], worldedit.pos2[name],
mode,
value
)
if not success then return success, stats end
local time_taken = core.get_ms_time() - start_time
minetest.log("action",
name ..
" used //set+ at "..pos1.." - "..pos2..", affecting "..stats.changed.." nodes in "..time_taken.."s")
return true, stats.changed.." nodes updated in "..core.format.human_time(time_taken)
end
})

@ -39,6 +39,7 @@ 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")
dofile(wea_cmd.modpath.."/commands/set.lua")
-- Meta Commands
dofile(wea_cmd.modpath .. "/commands/meta/init.lua")

@ -133,6 +133,19 @@ local function get1(player_name) return get(player_name, 1) end
-- @returns Vector3? The position requested, or nil if it doesn't exist.
local function get2(player_name) return get(player_name, 2) end
--- Convenience function that returns pos1 and pos2 with the coordinates sorted for the given player.
-- @param player_name string The name of the player to fetch the position for.
-- @param sort=false bool If true, the pos1 and pos2 are run through Vector3.sort() automatically.
-- @returns Vector3?,Vector3 The positions requested, or nil if either of them don't exist.
local function get12(player_name, sort)
if sort == nil then sort = false end
local pos1 = get(player_name, 1)
local pos2 = get(player_name, 2)
if pos1 == nil or pos2 == nil then return nil, nil end
if sort then pos1, pos2 = Vector3.sort(pos1, pos2) end
return pos1, pos2
end
--- Gets a list of all the positions for the given player.
-- @param player_name string The name of the player to fetch the position for.
-- @returns Vector3[] A list of positions for the given player.
@ -296,6 +309,7 @@ anchor = wea_c.EventEmitter.new({
get = get,
get1 = get1,
get2 = get2,
get12 = get12,
get_all = get_all,
get_bounds = get_bounds,
count = count,

@ -0,0 +1,32 @@
---
-- @module worldeditadditions_core.param2
-- //set <nodename>
-- //set param2|p2 <param2>
local function param2_to_dir(param2_type, param2)
if param2_type == "" then
return {
}
else
return nil
end
end
local function dir_to_param2(dir)
end
local function orient(param2, rotlist)
end
return {
orient = orient
}