2023-03-20 12:15:40 -05:00
|
|
|
function edit.schematic_from_map(pos, size)
|
|
|
|
local schematic = {data = {}}
|
|
|
|
schematic.size = size
|
|
|
|
schematic._pos = pos
|
|
|
|
schematic._meta = {}
|
2023-09-08 12:30:23 -05:00
|
|
|
schematic._timers = {}
|
|
|
|
schematic._rotation = 0
|
2023-03-20 12:15:40 -05:00
|
|
|
|
|
|
|
local start = vector.new(1, 1, 1)
|
|
|
|
local voxel_area = VoxelArea:new({MinEdge = start, MaxEdge = size})
|
|
|
|
|
|
|
|
for i in voxel_area:iterp(start, size) do
|
|
|
|
local offset = voxel_area:position(i)
|
|
|
|
local node_pos = vector.subtract(vector.add(pos, offset), start)
|
|
|
|
local node = minetest.get_node(node_pos)
|
|
|
|
node.param1 = nil
|
|
|
|
schematic.data[i] = node
|
|
|
|
|
|
|
|
local meta = minetest.get_meta(node_pos):to_table()
|
|
|
|
|
|
|
|
local has_meta = false
|
|
|
|
-- Convert metadata item stacks to item strings
|
|
|
|
for name, inventory in pairs(meta.inventory) do
|
|
|
|
for i, stack in ipairs(inventory) do
|
|
|
|
has_meta = true
|
|
|
|
if stack.to_string then
|
|
|
|
inventory[i] = stack:to_string()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if meta.fields and next(meta.fields) ~= nil then
|
|
|
|
has_meta = true
|
|
|
|
end
|
|
|
|
|
|
|
|
if not has_meta then
|
|
|
|
for k in pairs(meta) do
|
|
|
|
if k ~= "inventory" and k ~= "fields" then
|
|
|
|
has_meta = true
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if has_meta then
|
|
|
|
local key = minetest.hash_node_position(offset)
|
|
|
|
schematic._meta[key] = meta
|
|
|
|
end
|
2023-09-08 12:30:23 -05:00
|
|
|
|
|
|
|
local timer = minetest.get_node_timer(node_pos)
|
|
|
|
local timeout = timer:get_timeout()
|
|
|
|
if timeout ~= 0 then
|
|
|
|
local key = minetest.hash_node_position(offset)
|
|
|
|
local elapsed = timer:get_elapsed()
|
|
|
|
schematic._timers[key] = {timeout, elapsed}
|
|
|
|
end
|
2023-03-20 12:15:40 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
return schematic
|
|
|
|
end
|
|
|
|
|
|
|
|
function edit.set_schematic_rotation(schematic, angle)
|
|
|
|
schematic._rotation = schematic._rotation + angle
|
|
|
|
if schematic._rotation < 0 then
|
|
|
|
schematic._rotation = schematic._rotation + 360
|
|
|
|
elseif schematic._rotation > 270 then
|
|
|
|
schematic._rotation = schematic._rotation - 360
|
|
|
|
end
|
|
|
|
|
|
|
|
--[[local old_schematic = player_data[player].schematic
|
|
|
|
local new_schematic = {data = {}}
|
|
|
|
player_data[player].schematic = new_schematic
|
|
|
|
|
|
|
|
local old_size = old_schematic.size
|
|
|
|
local new_size
|
|
|
|
if direction == "L" or direction == "R" then
|
|
|
|
new_size = vector.new(old_size.z, old_size.y, old_size.x)
|
|
|
|
elseif direction == "U" or direction == "D" then
|
|
|
|
new_size = vector.new(old_size.y, old_size.x, old_size.z)
|
|
|
|
end
|
|
|
|
new_schematic.size = new_size
|
|
|
|
|
|
|
|
local sign = vector.apply(old_schematic._offset, math.sign)
|
|
|
|
new_schematic._offset = vector.apply(
|
|
|
|
vector.multiply(new_size, sign),
|
|
|
|
function(n) return n < 0 and n or 1 end
|
|
|
|
)
|
|
|
|
|
|
|
|
local start = vector.new(1, 1, 1)
|
|
|
|
local old_voxel_area = VoxelArea:new({MinEdge = start, MaxEdge = old_size})
|
|
|
|
local new_voxel_area = VoxelArea:new({MinEdge = start, MaxEdge = new_size})
|
|
|
|
for old_index in old_voxel_area:iterp(start, old_schematic.size) do
|
|
|
|
local old_pos = old_voxel_area:position(old_index)
|
|
|
|
local new_pos
|
|
|
|
local node = old_schematic.data[old_index]
|
|
|
|
|
|
|
|
if direction == "L" then
|
|
|
|
new_pos = vector.new(old_pos.z, old_pos.y, old_size.x - old_pos.x + 1)
|
|
|
|
elseif direction == "R" then
|
|
|
|
new_pos = vector.new(old_size.z - old_pos.z + 1, old_pos.y, old_pos.x)
|
|
|
|
elseif direction == "U" then
|
|
|
|
new_pos = vector.new(old_pos.y, old_size.x - old_pos.x + 1, old_pos.z)
|
|
|
|
elseif direction == "D" then
|
|
|
|
new_pos = vector.new(old_size.y - old_pos.y + 1, old_pos.x, old_pos.z)
|
|
|
|
end
|
|
|
|
|
|
|
|
local new_index = new_voxel_area:indexp(new_pos)
|
|
|
|
new_schematic.data[new_index] = node
|
|
|
|
end
|
|
|
|
delete_paste_preview(player)]]
|
|
|
|
end
|
|
|
|
|
|
|
|
function edit.schematic_to_map(pos, schematic)
|
|
|
|
minetest.place_schematic(pos, schematic, tostring(schematic._rotation), nil, true)
|
|
|
|
local size = schematic.size
|
|
|
|
for hash, metadata in pairs(schematic._meta) do
|
|
|
|
local offset = minetest.get_position_from_hash(hash)
|
|
|
|
offset = vector.subtract(offset, 1)
|
|
|
|
if schematic._rotation == 90 then
|
|
|
|
offset = vector.new(offset.z, offset.y, size.x - offset.x - 1)
|
|
|
|
elseif schematic._rotation == 180 then
|
|
|
|
offset = vector.new(size.x - offset.x - 1, offset.y, size.z - offset.z - 1)
|
|
|
|
elseif schematic._rotation == 270 then
|
|
|
|
offset = vector.new(size.z - offset.z - 1, offset.y, offset.x)
|
|
|
|
end
|
|
|
|
local node_pos = vector.add(pos, offset)
|
|
|
|
local meta = minetest.get_meta(node_pos)
|
2023-09-08 12:30:23 -05:00
|
|
|
if meta then
|
|
|
|
meta:from_table(metadata)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
for hash, timer_data in pairs(schematic._timers) do
|
|
|
|
local offset = minetest.get_position_from_hash(hash)
|
|
|
|
offset = vector.subtract(offset, 1)
|
|
|
|
if schematic._rotation == 90 then
|
|
|
|
offset = vector.new(offset.z, offset.y, size.x - offset.x - 1)
|
|
|
|
elseif schematic._rotation == 180 then
|
|
|
|
offset = vector.new(size.x - offset.x - 1, offset.y, size.z - offset.z - 1)
|
|
|
|
elseif schematic._rotation == 270 then
|
|
|
|
offset = vector.new(size.z - offset.z - 1, offset.y, offset.x)
|
|
|
|
end
|
|
|
|
local node_pos = vector.add(pos, offset)
|
|
|
|
local timer = minetest.get_node_timer(node_pos)
|
|
|
|
if timer then
|
|
|
|
timer:set(timer_data[1], timer_data[2])
|
|
|
|
end
|
2023-03-20 12:15:40 -05:00
|
|
|
end
|
|
|
|
end
|