Start working on //copy, but it's not finished yet.

We need to merge @VorTechnix's branch in first to gain access to 
advanced axis parsing functions before we can complete it.

For this reason, the command registration for //copy is currently 
commented out.
This commit is contained in:
Starbeamrainbowlabs 2021-10-11 02:41:45 +01:00
parent 8044a9059c
commit 653864be99
No known key found for this signature in database
GPG Key ID: 1BE5172E637709C2
5 changed files with 157 additions and 1 deletions

@ -53,6 +53,8 @@ dofile(wea.modpath.."/lib/conv/conv.lua")
dofile(wea.modpath.."/lib/erode/erode.lua")
dofile(wea.modpath.."/lib/noise/init.lua")
dofile(wea.modpath.."/lib/copy.lua")
dofile(wea.modpath.."/lib/count.lua")
dofile(wea.modpath.."/lib/bonemeal.lua")

@ -0,0 +1,47 @@
--- Copies a region to another location, potentially overwriting the exiting region.
-- @module worldeditadditions.copy
local wea = worldeditadditions
local Vector3 = wea.Vector3
-- ██████ ██████ ██████ ██ ██
-- ██ ██ ██ ██ ██ ██ ██
-- ██ ██ ██ ██████ ████
-- ██ ██ ██ ██ ██
-- ██████ ██████ ██ ██
function worldeditadditions.count(source_pos1, source_pos2, target_pos1, target_pos2)
source_pos1, source_pos2 = Vector3.sort(source_pos1, source_pos2)
target_pos1, target_pos2 = Vector3.sort(target_pos1, target_pos2)
local offset = source_pos1:subtract(target_pos1)
-- {source,target}_pos2 will always have the highest co-ordinates now
-- Fetch the nodes in the source area
local manip_source, area_source = worldedit.manip_helpers.init(source_pos1, source_pos2)
local data_source = manip_source:get_data()
-- Fetch a manip for the target area
local manip_target, area_target = worldedit.manip_helpers.init(target_pos1, target_pos2)
local data_target = manip_target:get_data()
-- z y x is the preferred loop order (because CPU cache I'd guess, since then we're iterating linearly through the data array)
for z = source_pos2.z, source_pos1.z, -1 do
for y = source_pos2.y, source_pos1.y, -1 do
for x = source_pos2.x, source_pos1.x, -1 do
local source = Vector3.new(x, y, z)
local source_i = area_source:index(x, y, z)
local target = source:subtract(offset)
local target_i = area_target:index(target.x, target.y, target.z)
data_target[target_i] = data_source[source_i]
end
end
end
-- Save the modified nodes back to disk & return
worldedit.manip_helpers.finish(manip_target, data_target)
return true, worldedit.volume(target_pos1, target_pos2)
end

@ -0,0 +1,55 @@
local wea = worldeditadditions
local Vector3 = dofile(wea.modpath.."/utils/vector3.lua")
-- BUG: This does not exist yet - need to merge @VorTechnix's branch first to get it
-- TODO: Uncomment then once it's implemented
-- local parse_axis = dofile(wea.modpath.."/utils/axis.lua")
--- 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 }.
-- Note that the input here needs to be *pre split*. wea.split_shell is
-- recommended for this purpose.
-- Uses wea.parse.axis for parsing axis names.
-- @param token_list string[] A list of tokens to parse
-- @returns Vector3 A Vector3 generated from parsing out the input token list.
local function parse_axes(token_list)
local vector_result = wea.Vector3.new()
if #token_list < 2 then
return false, "Error: Not enough arguments (at least 2 are required)"
end
local state = "AXIS"
local current_axis = nil
local success
for i,token in ipairs(token_list) do
if state == "AXIS" then
success, current_axis = parse_axis(token)
if not success then return success, current_axis end
state = "VALUE"
elseif state == "VALUE" then
local offset_this = tonumber(token)
if not offset_this then
return false, "Error: Invalid count value for axis '"..current_axis.."'. Values may only be positive or negative integers."
end
-- Handle negative axes
if current_axis:sub(1, 1) == "-" then
offset_this = -offset_this
current_axis = current_axis:sub(2, 2)
end
vector_result[current_axis] = vector_result[current_axis] + offset_this
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
return vector_result
end
return parse_axes

@ -4,7 +4,9 @@
-- ██ ██ ██ ██ ██ ██ ██
-- ██ ██ ██ ██ ██ ███████ ███████
worldeditadditions.parse = {}
worldeditadditions.parse = {
axes = dofile(worldeditadditions.modpath.."/utils/parse/axes.lua")
}
dofile(worldeditadditions.modpath.."/utils/parse/chance.lua")
dofile(worldeditadditions.modpath.."/utils/parse/map.lua")

@ -0,0 +1,50 @@
local wea = worldeditadditions
-- ██████ ██████ ██████ ██ ██
-- ██ ██ ██ ██ ██ ██ ██
-- ██ ██ ██ ██████ ████
-- ██ ██ ██ ██ ██
-- ██████ ██████ ██ ██
worldedit.register_command("copy", { -- TODO: Make this an override
params = "<axis:x|y|z|-x|-y|-z|?|front|back|left|right|up|down> <count> [<axis> <count> [...]]",
description = "Copies the defined region to another location - potentially on multiple axes at once.",
privs = { worldedit = true },
require_pos = 2,
parse = function(params_text)
if not params_text then params_text = "" end
local parts = wea.split_shell(params_text)
local copy_offset = wea.parse.axes(parts)
if copy_offset == wea.Vector3.new() then
return false, "Refusing to copy region a distance of 0 nodes"
end
return true, copy_offset:floor()
end,
nodes_needed = function(name)
-- We don't actually modify anything, but without returning a
-- number here safe_region doesn't work
return worldedit.volume(worldedit.pos1[name], worldedit.pos2[name])
end,
func = function(name, copy_offset)
local start_time = wea.get_ms_time()
local source_pos1 = wea.Vector3.clone(worldedit.pos1[name])
local source_pos2 = wea.Vector3.clone(worldedit.pos2[name])
local target_pos1 = source_pos1:add(copy_offset)
local target_pos2 = source_pos2:add(copy_offset)
local success, nodes_modified = wea.copy(
source_pos1, source_pos2,
target_pos1, target_pos2
)
local time_taken = wea.get_ms_time() - start_time
minetest.log("action", name.." used //copy from "..source_pos1.." - "..source_pos2.." to "..target_pos1.." - "..target_pos2..", modifying "..nodes_modified.." nodes in "..wea.format.human_time(time_taken))
return true, nodes_modified.." nodes copied using offset "..copy_offset.." in "..wea.format.human_time(time_taken)
end
})