mirror of
https://github.com/sbrl/Minetest-WorldEditAdditions.git
synced 2024-11-22 07:23:00 +00:00
Add //noiseapply
This commit is contained in:
parent
6cd367915d
commit
2920f7081d
5 changed files with 151 additions and 0 deletions
|
@ -7,6 +7,8 @@ Note to self: See the bottom of this file for the release template text.
|
|||
- Add `//sfactor` (_selection factor_) - Selection Tools by @VorTechnix are finished for now.
|
||||
- Add `//mface` (_measure facing_), `//midpos` (_measure middle position_), `//msize` (_measure size_), `//mtrig` (_measure trigonometry_) - Measuring Tools implemented by @VorTechnix.
|
||||
- Add `//airapply` for applying commands only to air nodes in the defined region
|
||||
- Add `//noise2d` for perturbing terrain with multiple different noise functions
|
||||
- Add `//noiseapply2d` for running commands on columns where a noise value is over a threshold
|
||||
- Use [luacheck](https://github.com/mpeterv/luacheck) to find and fix a large number of bugs and other issues
|
||||
- Multiple commands: Allow using quotes (`"thing"`, `'thing'`) to quote values when splitting
|
||||
- `//layers`: Add optional slope constraint (inspired by [WorldPainter](https://worldpainter.net/))
|
||||
|
|
|
@ -60,6 +60,7 @@ dofile(wea.modpath.."/lib/forest.lua")
|
|||
|
||||
dofile(wea.modpath.."/lib/ellipsoidapply.lua")
|
||||
dofile(wea.modpath.."/lib/airapply.lua")
|
||||
dofile(wea.modpath.."/lib/noiseapply2d.lua")
|
||||
|
||||
dofile(wea.modpath.."/lib/subdivide.lua")
|
||||
dofile(wea.modpath.."/lib/selection/stack.lua")
|
||||
|
|
60
worldeditadditions/lib/noiseapply2d.lua
Normal file
60
worldeditadditions/lib/noiseapply2d.lua
Normal file
|
@ -0,0 +1,60 @@
|
|||
-- ███ ██ ██████ ██ ███████ ███████ █████ ██████ ██████ ██ ██ ██ ██████ ██████
|
||||
-- ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||
-- ██ ██ ██ ██ ██ ██ ███████ █████ ███████ ██████ ██████ ██ ████ █████ ██ ██
|
||||
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||
-- ██ ████ ██████ ██ ███████ ███████ ██ ██ ██ ██ ███████ ██ ███████ ██████
|
||||
|
||||
--- Similar to cubeapply, except that it takes 2 positions and randomly keeps changes based on a noise pattern.
|
||||
-- Takes a backup copy of the defined region, runs the given function, and then
|
||||
-- restores the bits that aren't above the nosie threshold.
|
||||
-- @param {Position} pos1 The 1st position defining the region boundary
|
||||
-- @param {Position} pos2 The 2nd positioon defining the region boundary
|
||||
-- @param {Function} func The function to call that performs the action in question. It is expected that the given function will accept no arguments.
|
||||
function worldeditadditions.noiseapply2d(pos1, pos2, threshold, scale, func)
|
||||
local time_taken_all = worldeditadditions.get_ms_time()
|
||||
pos1, pos2 = worldeditadditions.Vector3.sort(pos1, pos2)
|
||||
if not threshold then threshold = 0.5 end
|
||||
-- pos2 will always have the highest co-ordinates now
|
||||
|
||||
-- Fetch the nodes in the specified area
|
||||
local manip_before, area_before = worldedit.manip_helpers.init(pos1, pos2)
|
||||
local data_before = manip_before:get_data()
|
||||
|
||||
local time_taken_fn = worldeditadditions.get_ms_time()
|
||||
func()
|
||||
time_taken_fn = worldeditadditions.get_ms_time() - time_taken_fn
|
||||
|
||||
local manip_after, area_after = worldedit.manip_helpers.init(pos1, pos2)
|
||||
local data_after = manip_after:get_data()
|
||||
|
||||
local size2d = pos2 - pos1 + worldeditadditions.Vector3.new(1, 1, 1)
|
||||
print("DEBUG pos1", pos1, "pos2", pos2, "size2d", size2d)
|
||||
local success, noise = worldeditadditions.noise.make_2d(size2d, pos1, {
|
||||
algorithm = "perlinmt",
|
||||
scale = scale
|
||||
})
|
||||
if not success then return success, noise end
|
||||
|
||||
for z = pos2.z, pos1.z, -1 do
|
||||
for y = pos2.y, pos1.y, -1 do
|
||||
for x = pos2.x, pos1.x, -1 do
|
||||
local i_before = area_before:index(x, y, z)
|
||||
local i_after = area_after:index(x, y, z)
|
||||
|
||||
local i_noise = (z-pos1.z)*size2d.x + (x-pos1.x)
|
||||
|
||||
-- Roll everything where the noise function returns less than 0.5
|
||||
if noise[i_noise] < threshold then
|
||||
data_after[i_after] = data_before[i_before]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Save the modified nodes back to disk & return
|
||||
-- No need to save - this function doesn't actually change anything
|
||||
worldedit.manip_helpers.finish(manip_after, data_after)
|
||||
|
||||
time_taken_all = worldeditadditions.get_ms_time() - time_taken_all
|
||||
return true, { all = time_taken_all, fn = time_taken_fn }
|
||||
end
|
87
worldeditadditions_commands/commands/meta/noiseapply2d.lua
Normal file
87
worldeditadditions_commands/commands/meta/noiseapply2d.lua
Normal file
|
@ -0,0 +1,87 @@
|
|||
-- ███ ██ ██████ ██ ███████ ███████ █████ ██████ ██████ ██ ██ ██ ██████ ██████
|
||||
-- ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||
-- ██ ██ ██ ██ ██ ██ ███████ █████ ███████ ██████ ██████ ██ ████ █████ ██ ██
|
||||
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||
-- ██ ████ ██████ ██ ███████ ███████ ██ ██ ██ ██ ███████ ██ ███████ ██████
|
||||
|
||||
|
||||
worldedit.register_command("noiseapply2d", {
|
||||
params = "<threshold> <scale> <command_name> <args>",
|
||||
description = "Executes the given command (automatically prepending '//'), but uses a 2d noise function with both a threshold value (a number between 0 and 1) and a scale value (number, 1 = normal scale, for small areas 10+ is recommended) to filter where in the defined region it's applied.",
|
||||
privs = { worldedit = true },
|
||||
require_pos = 2,
|
||||
parse = function(params_text)
|
||||
if params_text == "" then return false, "Error: No command specified." end
|
||||
|
||||
local threshold_text, scale_text, cmd_name, args_text = params_text:match("([^%s]+)%s+([^%s]+)%s+([^%s]+)%s*(.*)")
|
||||
if not args_text then
|
||||
args_text = ""
|
||||
end
|
||||
|
||||
-- Note that we search the worldedit commands here, not the minetest ones
|
||||
local cmd_we = worldedit.registered_commands[cmd_name]
|
||||
if cmd_we == nil then
|
||||
return false, "Error: "..cmd_name.." isn't a valid command."
|
||||
end
|
||||
if cmd_we.require_pos ~= 2 and cmd_name ~= "multi" then
|
||||
return false, "Error: The command "..cmd_name.." exists, but doesn't take 2 positions and so can't be used with //noiseapply2d."
|
||||
end
|
||||
|
||||
-- Run parsing of target command
|
||||
-- Lifted from cubeapply in WorldEdit
|
||||
local args_parsed = {cmd_we.parse(args_text)}
|
||||
if not table.remove(args_parsed, 1) then
|
||||
return false, args_parsed[1]
|
||||
end
|
||||
|
||||
local threshold = tonumber(threshold_text)
|
||||
if not threshold then
|
||||
return false, "Error: Invalid threshold value '"..threshold_text.."'. Threshold values should be a floating-point number between 0 and 1."
|
||||
end
|
||||
if threshold < 0 or threshold > 1 then
|
||||
return false, "Error: The threshold value '"..threshold.."' is out of bounds. Threshold values should be floating-point numbers between 0 and 1."
|
||||
end
|
||||
local scale = tonumber(scale_text)
|
||||
if not scale then
|
||||
return false, "Error: Invalid scale value '"..threshold_text.."'. Threshold values should be a floating-point number between 0 and 1."
|
||||
end
|
||||
|
||||
return true, 1 - threshold, scale, cmd_we, args_parsed
|
||||
end,
|
||||
nodes_needed = function(name)
|
||||
return worldedit.volume(
|
||||
worldedit.pos1[name],
|
||||
worldedit.pos2[name]
|
||||
)
|
||||
end,
|
||||
func = function(name, threshold, scale, cmd, args_parsed)
|
||||
if not minetest.check_player_privs(name, cmd.privs) then
|
||||
return false, "Your privileges are insufficient to execute the command '"..cmd.."'."
|
||||
end
|
||||
|
||||
local pos1, pos2 = worldeditadditions.Vector3.sort(
|
||||
worldedit.pos1[name],
|
||||
worldedit.pos2[name]
|
||||
)
|
||||
|
||||
|
||||
local success, stats_time = worldeditadditions.noiseapply2d(
|
||||
pos1, pos2,
|
||||
threshold,
|
||||
worldeditadditions.Vector3.new(
|
||||
scale, scale, scale
|
||||
),
|
||||
function()
|
||||
cmd.func(name, worldeditadditions.table.unpack(args_parsed))
|
||||
end
|
||||
)
|
||||
if not success then return success, stats_time end
|
||||
|
||||
local time_overhead = 100 - worldeditadditions.round((stats_time.fn / stats_time.all) * 100, 3)
|
||||
local text_time_all = worldeditadditions.format.human_time(stats_time.all)
|
||||
local text_time_fn = worldeditadditions.format.human_time(stats_time.fn)
|
||||
|
||||
minetest.log("action", name.." used //noiseapply2d at "..pos1.." - "..pos2.." in "..text_time_all)
|
||||
return true, "Complete in "..text_time_all.." ("..text_time_fn.." fn, "..time_overhead.."% noiseapply2d overhead)"
|
||||
end
|
||||
})
|
|
@ -42,6 +42,7 @@ dofile(we_c.modpath.."/commands/meta/many.lua")
|
|||
dofile(we_c.modpath.."/commands/meta/subdivide.lua")
|
||||
dofile(we_c.modpath.."/commands/meta/ellipsoidapply.lua")
|
||||
dofile(we_c.modpath.."/commands/meta/airapply.lua")
|
||||
dofile(we_c.modpath.."/commands/meta/noiseapply2d.lua")
|
||||
|
||||
-- Selection Tools
|
||||
dofile(we_c.modpath.."/commands/selectors/init.lua")
|
||||
|
|
Loading…
Reference in a new issue