teste
[gestor/gestor2.git] / estruturador.lua
blob23d5df101a0001714fdcda7104a005046bb5fd76
1 --[[
2 Mod Gestor para Minetest
3 Gestor v1.0 Copyright (C) 2016 BrunoMine (https://github.com/BrunoMine)
5 Recebeste uma cópia da GNU Lesser General
6 Public License junto com esse software,
7 se não, veja em <http://www.gnu.org/licenses/>.
9 Estruturador
12 -- Diretorio do Mod
13 local modpath = minetest.get_modpath("gestor")
15 -- Variavel global de estruturador
16 gestor.estruturador = {}
19 -- Arredondar posicao
20 local arredondar = function(pos)
21 local r = {}
22 if pos.x > (math.floor(pos.x)+0.5) then
23 r.x = math.ceil(pos.x)
24 else
25 r.x = math.floor(pos.x)
26 end
27 if pos.y > (math.floor(pos.y)+0.5) then
28 r.y = math.ceil(pos.y)
29 else
30 r.y = math.floor(pos.y)
31 end
32 if pos.z > (math.floor(pos.z)+0.5) then
33 r.z = math.ceil(pos.z)
34 else
35 r.z = math.floor(pos.z)
36 end
37 return r
38 end
40 -- Restaurar as refenrencias em relacao a uma pos
41 local restaurar_pos = function(pos, ref)
42 local r = {}
43 r.x, r.y, r.z = (pos.x+ref.x), (pos.y+ref.y), (pos.z+ref.z)
44 return r
45 end
47 -- calcular o deslocamento de ref em relacao a pos
48 local ref_pos = function(pos, ref)
49 local r = {}
50 r.x, r.y, r.z = (ref.x-pos.x), (ref.y-pos.y), (ref.z-pos.z)
51 return r
52 end
54 -- metodo melhorado para pegar nodes (pega nodes ainda nao carregados)
55 local function pegar_node(pos)
56 local resp = {}
57 local node = minetest.get_node(pos)
58 if node.name == "ignore" then
59 minetest.get_voxel_manip():read_from_map(pos, pos)
60 node = minetest.get_node(pos)
61 end
62 resp = {node=node}
63 --[[
64 Para salvar os metadados é criada um valor meta (node.meta)
65 para que alguns dados possam ser mantidos de forma serializada
66 no node e posteriormente serem restaurados quando a estrutura
67 for restaurada
69 local meta = minetest.get_meta(pos)
70 if node.name == "placa_terreno:livre" then -- placas de terreno
71 local ref1 = ""
72 local ref2 = ""
73 if meta:get_string("ref1") ~= "" then
74 -- Mantem os antigos ref's caso existam no metadado
75 ref1 = minetest.deserialize(meta:get_string("ref1"))
76 ref2 = minetest.deserialize(meta:get_string("ref2"))
77 else
78 -- Calcula os ref's
79 ref1 = minetest.serialize(ref_pos(pos, minetest.deserialize(meta:get_string("pos1"))))
80 ref2 = minetest.serialize(ref_pos(pos, minetest.deserialize(meta:get_string("pos2"))))
81 end
82 local custo = meta:get_string("custo")
83 local altura = meta:get_string("altura")
84 resp = {node=node,meta={ref1=ref1,ref2=ref2,custo=custo,altura=altura}}
85 elseif node.name == "default:sign_wall" then -- placas normais de parede
86 local text = meta:get_string("text")
87 local infotext = meta:get_string("infotext")
88 resp = {node=node,meta={text=text,infotext=infotext}}
89 end
90 return resp
91 end
94 -- Serializar estrutura
95 gestor.estruturador.salvar = function(pos, nome, largura, altura, modp, silencio)
96 if not pos or not nome then return false end
97 -- arredondar posicao
98 pos = arredondar(pos)
100 if modp == nil then
101 modp = modpath
103 largura = largura or gestor.diretrizes.estruturas[nome][1]
104 altura = altura or gestor.diretrizes.estruturas[nome][1]
105 if not largura or not altura then return false end
106 -- Criar estrutura
107 if silencio == nil or silencio == false then minetest.chat_send_all("Serializando estrutura. Aguarde...") end
108 local estrutura = {}
109 local ix, iy, iz = 1, 1, 1
110 local x, y, z = pos.x, pos.y, pos.z
111 local limx, limy, limz = (pos.x+largura-1), (pos.y+altura-1), (pos.z+largura-1)
112 local i = 0
113 while (x <= limx) do
114 while (y <= limy) do
115 while (z <= limz) do
116 estrutura[ix.." "..iy.." "..iz] = pegar_node({x = x, y = y, z = z})
117 i = i + 1
118 z = z + 1
119 iz = iz + 1
121 z = pos.z
122 iz = 1
123 y = y + 1
124 iy = iy + 1
126 y = pos.y
127 iy = 1
128 x = x + 1
129 ix = ix + 1
132 -- Criar arquivo
133 local output = io.open(modp .. "/estruturas/"..nome, "w")
134 output:write(minetest.serialize(estrutura))
135 io.close(output)
137 -- Estrutura serializada com sucesso
138 if silencio == nil or silencio == false then minetest.chat_send_all("Serializacao concluida.") end
139 return true
142 -- Deserializar uma estrutura
143 gestor.estruturador.carregar = function(pos, nome, largura, altura, modp, silencio)
144 if pos == nil or nome == nil then return false end
145 if silencio == nil or silencio == false then minetest.chat_send_all("Criando estrutura. Aguarde...") end
146 -- Coleta de dados
147 local dados = {}
148 if modp == nil then
149 dados = gestor.diretrizes.estruturas[nome] or {}
150 largura = dados[1] or largura
151 altura = dados[2] or altura
152 modp = modpath
154 if largura == nil or altura == nil or nome == nil then return false end
155 local input = io.open(modp .. "/estruturas/"..nome, "r")
156 if input then
157 dados.estrutura = minetest.deserialize(input:read("*l"))
158 else
159 return false
161 io.close(input)
162 -- Criar estrutura
163 local ix, iy, iz = 1, 1, 1
164 local x, y, z = pos.x, pos.y, pos.z
165 local limx, limy, limz = (pos.x+largura-1), (pos.y+altura-1), (pos.z+largura-1)
166 local i = 0
167 while (x <= limx) do
168 while (y <= limy) do
169 while (z <= limz) do
170 local PosNode = dados.estrutura[ix.." "..iy.." "..iz] or {node={name="air"}}
171 minetest.set_node({x = x, y = y, z = z}, PosNode.node)
172 if PosNode.meta then
173 if PosNode.node.name == "placa_terreno:livre" then
174 local meta = minetest.get_meta({x = x, y = y, z = z})
175 --[[
176 Tenta restaurar pos1 e pos2 mas devido a um erro
177 desconhecido as vezes desloca 1 node de distancia
178 para alguma direção
180 meta:set_string("pos1",
181 minetest.serialize(restaurar_pos(minetest.deserialize(PosNode.meta.ref1),
182 {x = x, y = y, z = z}))
184 meta:set_string("pos2",
185 minetest.serialize(restaurar_pos(minetest.deserialize(PosNode.meta.ref2),
186 {x = x, y = y, z = z}))
188 --[[
189 Mantes ref1 e ref2 no meto do bloco para evitar distorções maiores
190 usando sempre esses ref's a distorção pode ser no maximo 1 node
192 meta:set_string("ref1", minetest.serialize(PosNode.meta.ref1))
193 meta:set_string("ref2", minetest.serialize(PosNode.meta.ref2))
194 meta:set_string("custo", PosNode.meta.custo)
195 meta:set_string("altura", PosNode.meta.altura)
196 meta:set_string("status", "livre")
197 meta:set_string("infotext", "Terreno a Venda")
198 elseif PosNode.node.name == "default:sign_wall" then
199 local meta = minetest.get_meta({x = x, y = y, z = z})
200 meta:set_string("text", PosNode.meta.text)
201 meta:set_string("infotext", PosNode.meta.infotext)
204 i = i + 1
205 z = z + 1
206 iz = iz + 1
208 z = pos.z
209 iz = 1
210 y = y + 1
211 iy = iy + 1
213 y = pos.y
214 iy = 1
215 x = x + 1
216 ix = ix + 1
219 -- Estrutura construida com sucesso
220 if silencio == nil or silencio == false then minetest.chat_send_all("Estrutura construida. Aguarde o mapa ser renderizado.") end
221 return true
225 -----
226 --------
227 -- Nodes restaurador de escadarias
228 local criar_nivel_escadaria = function(pos, largura, name)
229 local limx, limz = pos.x+(largura/2), pos.z+(largura/2)
230 local x, z = pos.x-(largura/2), pos.z-(largura/2)
231 while (x<=limx) do
232 z = pos.z-(largura/2)
233 while (z<=limz) do
234 local npos = {x=x,y=pos.y,z=z}
235 local node = minetest.get_node(npos)
236 if node.name == "ignore" then
237 minetest.get_voxel_manip():read_from_map(npos, npos)
238 node = minetest.get_node(npos)
240 if node.name == "air" then
241 minetest.set_node(npos, {name=name})
243 z=z+1
245 x=x+1
248 local criar_escadaria = function(pos, node)
249 local npos = {x=pos.x,y=pos.y-10,z=pos.z}
250 local altura = pos.y - 8
251 while altura <= pos.y do
252 criar_nivel_escadaria({x=pos.x,y=altura,z=pos.z}, (math.abs(pos.y-altura)*4)+7, node)
253 altura = altura + 1
256 minetest.register_node("gestor:escadaria", {
257 description = "Restaurador de escadaria",
258 tiles = {
259 "default_pine_wood.png",
260 "default_pine_wood.png",
261 "default_pine_wood.png",
262 "default_pine_wood.png",
263 "default_pine_wood.png",
264 "default_pine_wood.png"
266 groups = {choppy=2,oddly_breakable_by_hand=2,wood=1},
267 sounds = default.node_sound_wood_defaults(),
268 on_rightclick = function(pos)
269 local node = minetest.get_node({x=pos.x,y=pos.y+1,z=pos.z})
270 criar_escadaria({x=pos.x,y=pos.y-1,z=pos.z}, node.name)
271 minetest.set_node(pos, {name="air"})
272 minetest.set_node({x=pos.x,y=pos.y+1,z=pos.z}, {name="air"})
273 end,
275 -- Fim
276 --------
277 -----