2021-11-13 13:36:10 +01:00
2022-09-19 01:18:03 +02:00
local wea_c = worldeditadditions_core
local Vector3 = wea_c.Vector3
2021-11-13 13:36:10 +01:00
2024-01-02 17:59:51 +01:00
---
-- @module worldeditadditions
2021-11-13 13:36:10 +01:00
-- ███ ███ ██████ ██ ██ ███████
-- ████ ████ ██ ██ ██ ██ ██
-- ██ ████ ██ ██ ██ ██ ██ █████
-- ██ ██ ██ ██ ██ ██ ██ ██
-- ██ ██ ██████ ████ ███████
2023-07-07 02:25:42 +02:00
--- Moves a region to another location, overwriting any nodes at the target location.
-- @param source_pos1 Vector3 pos1 of the source region to move.
-- @param source_pos2 Vector3 pos2 of the source region to move.
-- @param target_pos1 Vector3 pos1 of the target region to move to.
-- @param target_pos2 Vector3 pos2 of the target region to move to.
-- @param airapply=false bool Whether to only replace target nodes that are air-like, leaving those that are not air-like. If false, then all target nodes are replaced regardless of whether they are air-like nodes or not.
-- **Caution:** If true, then **nodes in the source region will be removed and replaced with air, even if they are unable to be placed in the target location!**
-- @returns bool,numbers 1. Whether the move operation was successful or not
-- 2. The total number of nodes actually placed in the target region.
2023-07-02 02:52:25 +02:00
function worldeditadditions . move ( source_pos1 , source_pos2 , target_pos1 , target_pos2 , airapply )
2021-12-31 14:38:13 +01:00
---
-- 0: Preamble
---
2023-07-02 02:52:25 +02:00
if airapply == nil then airapply = false end
2021-11-13 13:36:10 +01:00
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 ( )
2023-07-10 22:08:17 +02:00
local data_source_param2 = manip_source : get_param2_data ( )
2021-11-13 13:36:10 +01:00
-- 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 ( )
2023-07-10 22:08:17 +02:00
local data_target_param2 = manip_target : get_param2_data ( )
2021-11-13 13:36:10 +01:00
2021-12-31 14:38:13 +01:00
---
-- 1: Perform Copy
---
2021-11-13 13:36:10 +01:00
-- 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)
2023-07-07 02:25:42 +02:00
local total_placed = 0
2021-11-13 13:36:10 +01:00
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 )
2023-07-02 02:52:25 +02:00
local should_replace = true
if airapply then
should_replace = wea_c.is_airlike ( data_target [ target_i ] )
end
if should_replace then
data_target [ target_i ] = data_source [ source_i ]
2023-07-10 22:08:17 +02:00
data_target_param2 [ target_i ] = data_source_param2 [ source_i ]
2023-07-07 02:25:42 +02:00
total_placed = total_placed + 1
2023-07-02 02:52:25 +02:00
end
2021-11-13 13:36:10 +01:00
end
end
end
-- Save the modified nodes back to disk & return
-- Note that we save the source region *first* to avoid issues with overlap
2021-12-31 04:01:51 +01:00
-- BUG: Voxel Manipulators cover a larger area than the source area if the target position is too close the to the source, then the source will be overwritten by the target by accident.
2021-12-31 04:05:02 +01:00
-- Potential solution:
-- 1. Grab source & target
2021-12-31 14:38:13 +01:00
-- 2. Perform copy → target
-- 3. Save target
2021-12-31 04:05:02 +01:00
-- 4. Re-grab source
-- 5. Zero out source, but avoiding touching any nodes that fall within target
2021-12-31 14:38:13 +01:00
-- 6. Save source
---
-- 2: Save target
---
2023-07-10 22:08:17 +02:00
manip_target : set_param2_data ( data_target_param2 )
2021-11-13 13:36:10 +01:00
worldedit.manip_helpers . finish ( manip_target , data_target )
2021-12-31 14:38:13 +01:00
---
-- 3: Re-grab source
---
manip_source , area_source = worldedit.manip_helpers . init ( source_pos1 , source_pos2 )
data_source = manip_source : get_data ( )
2023-07-10 22:08:17 +02:00
data_source_param2 = manip_source : get_param2_data ( )
2021-12-31 14:38:13 +01:00
---
-- 4: Zero out source, but avoiding touching any nodes that fall within target
---
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 )
if not source : is_contained ( target_pos1 , target_pos2 ) then
data_source [ source_i ] = node_id_air
2023-07-10 22:08:17 +02:00
data_source_param2 [ source_i ] = 0
2021-12-31 14:38:13 +01:00
end
end
end
end
---
-- 5: Save source
---
2023-07-10 22:08:17 +02:00
manip_source : set_param2_data ( data_source_param2 )
2021-12-31 14:38:13 +01:00
worldedit.manip_helpers . finish ( manip_source , data_source )
---
-- 6: Finish up and return
---
2023-07-07 02:25:42 +02:00
return true , total_placed
2021-11-13 13:36:10 +01:00
end