diff --git a/worldeditadditions/init.lua b/worldeditadditions/init.lua index babed60..f52424c 100644 --- a/worldeditadditions/init.lua +++ b/worldeditadditions/init.lua @@ -54,12 +54,12 @@ dofile(wea.modpath.."/lib/scale_down.lua") dofile(wea.modpath.."/lib/scale.lua") dofile(wea.modpath.."/lib/spiral_square.lua") dofile(wea.modpath.."/lib/spiral_circle.lua") -dofile(wea.modpath.."/lib/copy.lua") 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/move.lua") dofile(wea.modpath.."/lib/count.lua") diff --git a/worldeditadditions/lib/move.lua b/worldeditadditions/lib/move.lua new file mode 100644 index 0000000..d0963aa --- /dev/null +++ b/worldeditadditions/lib/move.lua @@ -0,0 +1,52 @@ +--- Copies a region to another location, potentially overwriting the exiting region. +-- @module worldeditadditions.copy + +local wea = worldeditadditions +local Vector3 = wea.Vector3 + +-- ███ ███ ██████ ██ ██ ███████ +-- ████ ████ ██ ██ ██ ██ ██ +-- ██ ████ ██ ██ ██ ██ ██ █████ +-- ██ ██ ██ ██ ██ ██ ██ ██ +-- ██ ██ ██████ ████ ███████ + +function worldeditadditions.move(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 + + local node_id_air = minetest.get_content_id("air") + + -- 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, since then we're iterating linearly through the data array backwards. This only holds true for little-endian machines however) + + 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_source[source_i] = node_id_air + data_target[target_i] = data_source[source_i] + end + end + end + + -- Save the modified nodes back to disk & return + -- Note that we save the source region *first* to avoid issues with overlap + worldedit.manip_helpers.finish(manip_source, data_source) + worldedit.manip_helpers.finish(manip_target, data_target) + + return true, worldedit.volume(target_pos1, target_pos2) +end diff --git a/worldeditadditions_commands/commands/move.lua b/worldeditadditions_commands/commands/move.lua new file mode 100644 index 0000000..7391526 --- /dev/null +++ b/worldeditadditions_commands/commands/move.lua @@ -0,0 +1,66 @@ +local wea = worldeditadditions +local Vector3 = wea.Vector3 + +local function parse_stage2(name, parts) + local success, vpos1, vpos2 = wea.parse.axes( + parts, + wea.player_dir(name) + ) + + if not success then return success, vpos1 end + + -- In this case, we aren't interested in keeping the multidirectional shape changing information insomuch as an offset to which we should shift the region's contents to. + local offset = vpos1 + vpos2 + + if offset == Vector3.new() then + return false, "Refusing to move region a distance of 0 nodes" + end + + return true, offset:floor() +end + +-- ███ ███ ██████ ██ ██ ███████ +-- ████ ████ ██ ██ ██ ██ ██ +-- ██ ████ ██ ██ ██ ██ ██ █████ +-- ██ ██ ██ ██ ██ ██ ██ ██ +-- ██ ██ ██████ ████ ███████ +worldedit.register_command("move+", { -- TODO: Make this an override + params = " [ [...]]", + description = "Moves the defined region to another location - potentially across 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) + + return true, parts + end, + nodes_needed = function(name) + return worldedit.volume(worldedit.pos1[name], worldedit.pos2[name]) + end, + func = function(name, parts) + local start_time = wea.get_ms_time() + + local success_a, copy_offset = parse_stage2(name, parts) + if not success_a then return success_a, copy_offset end + + local source_pos1 = Vector3.clone(worldedit.pos1[name]) + local source_pos2 = Vector3.clone(worldedit.pos2[name]) + + local target_pos1 = source_pos1 + copy_offset + local target_pos2 = source_pos2 + copy_offset + + local success_b, nodes_modified = wea.move( + source_pos1, source_pos2, + target_pos1, target_pos2 + ) + if not success_b then return success_b, nodes_modified end + + local time_taken = wea.get_ms_time() - start_time + + + minetest.log("action", name.." used //move+ 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 moved using offset "..copy_offset.." in "..wea.format.human_time(time_taken) + end +}) diff --git a/worldeditadditions_commands/init.lua b/worldeditadditions_commands/init.lua index 59c507d..a6d485f 100644 --- a/worldeditadditions_commands/init.lua +++ b/worldeditadditions_commands/init.lua @@ -37,6 +37,7 @@ dofile(we_c.modpath.."/commands/torus.lua") dofile(we_c.modpath.."/commands/walls.lua") dofile(we_c.modpath.."/commands/spiral2.lua") dofile(we_c.modpath.."/commands/copy.lua") +dofile(we_c.modpath.."/commands/move.lua") dofile(we_c.modpath.."/commands/count.lua")