-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathschematic.lua
149 lines (131 loc) · 4.65 KB
/
schematic.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
function edit.schematic_from_map(pos, size)
local schematic = {data = {}}
schematic.size = size
schematic._pos = pos
schematic._meta = {}
schematic._timers = {}
schematic._rotation = 0
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
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
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)
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
end
end