LuaVoxelManip: Add get_param2_data and set_param2_data
[oweals/minetest.git] / src / script / lua_api / l_vmanip.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20
21 #include "lua_api/l_vmanip.h"
22 #include "lua_api/l_internal.h"
23 #include "common/c_converter.h"
24 #include "emerge.h"
25 #include "environment.h"
26 #include "map.h"
27 #include "server.h"
28 #include "mapgen.h"
29
30 // garbage collector
31 int LuaVoxelManip::gc_object(lua_State *L)
32 {
33         LuaVoxelManip *o = *(LuaVoxelManip **)(lua_touserdata(L, 1));
34         if (!o->is_mapgen_vm)
35                 delete o;
36         
37         return 0;
38 }
39
40 int LuaVoxelManip::l_read_from_map(lua_State *L)
41 {
42         LuaVoxelManip *o = checkobject(L, 1);
43         ManualMapVoxelManipulator *vm = o->vm;
44         
45         v3s16 bp1 = getNodeBlockPos(read_v3s16(L, 2));
46         v3s16 bp2 = getNodeBlockPos(read_v3s16(L, 3));
47         sortBoxVerticies(bp1, bp2);
48         
49         vm->initialEmerge(bp1, bp2);
50         
51         push_v3s16(L, vm->m_area.MinEdge);
52         push_v3s16(L, vm->m_area.MaxEdge);
53         
54         return 2;
55 }
56
57 int LuaVoxelManip::l_get_data(lua_State *L)
58 {
59         NO_MAP_LOCK_REQUIRED;
60
61         LuaVoxelManip *o = checkobject(L, 1);
62         ManualMapVoxelManipulator *vm = o->vm;
63         
64         int volume = vm->m_area.getVolume();
65         
66         lua_newtable(L);
67         for (int i = 0; i != volume; i++) {
68                 lua_Integer cid = vm->m_data[i].getContent();
69                 lua_pushinteger(L, cid);
70                 lua_rawseti(L, -2, i + 1);
71         }
72         
73         return 1;
74 }
75
76 int LuaVoxelManip::l_set_data(lua_State *L)
77 {
78         NO_MAP_LOCK_REQUIRED;
79         
80         LuaVoxelManip *o = checkobject(L, 1);
81         ManualMapVoxelManipulator *vm = o->vm;
82         
83         if (!lua_istable(L, 2))
84                 return 0;
85         
86         int volume = vm->m_area.getVolume();
87         for (int i = 0; i != volume; i++) {
88                 lua_rawgeti(L, 2, i + 1);
89                 content_t c = lua_tointeger(L, -1);
90                 
91                 vm->m_data[i].setContent(c);
92
93                 lua_pop(L, 1);
94         }
95                 
96         return 0;
97 }
98
99 int LuaVoxelManip::l_write_to_map(lua_State *L)
100 {
101         LuaVoxelManip *o = checkobject(L, 1);
102         ManualMapVoxelManipulator *vm = o->vm;
103
104         vm->blitBackAll(&o->modified_blocks);
105
106         return 0;       
107 }
108
109 int LuaVoxelManip::l_update_liquids(lua_State *L)
110 {
111         LuaVoxelManip *o = checkobject(L, 1);
112
113         Environment *env = getEnv(L);
114         if (!env)
115                 return 0;
116
117         Map *map = &(env->getMap());
118         INodeDefManager *ndef = getServer(L)->getNodeDefManager();
119         ManualMapVoxelManipulator *vm = o->vm;
120
121         Mapgen mg;
122         mg.vm   = vm;
123         mg.ndef = ndef;
124
125         mg.updateLiquid(&map->m_transforming_liquid,
126                         vm->m_area.MinEdge, vm->m_area.MaxEdge);
127
128         return 0;
129 }
130
131 int LuaVoxelManip::l_calc_lighting(lua_State *L)
132 {
133         NO_MAP_LOCK_REQUIRED;
134         
135         LuaVoxelManip *o = checkobject(L, 1);
136         if (!o->is_mapgen_vm)
137                 return 0;
138
139         INodeDefManager *ndef = getServer(L)->getNodeDefManager();
140         EmergeManager *emerge = getServer(L)->getEmergeManager();
141         ManualMapVoxelManipulator *vm = o->vm;
142
143         v3s16 p1 = lua_istable(L, 2) ? read_v3s16(L, 2) :
144                 vm->m_area.MinEdge + v3s16(0, 1, 0) * MAP_BLOCKSIZE;
145         v3s16 p2 = lua_istable(L, 3) ? read_v3s16(L, 3) :
146                 vm->m_area.MaxEdge - v3s16(0, 1, 0) * MAP_BLOCKSIZE;
147         sortBoxVerticies(p1, p2);
148
149         Mapgen mg;
150         mg.vm          = vm;
151         mg.ndef        = ndef;
152         mg.water_level = emerge->params->water_level;
153         
154         mg.calcLighting(p1, p2);
155
156         return 0;
157 }
158
159 int LuaVoxelManip::l_set_lighting(lua_State *L)
160 {
161         NO_MAP_LOCK_REQUIRED;
162         
163         LuaVoxelManip *o = checkobject(L, 1);
164         if (!o->is_mapgen_vm)
165                 return 0;
166         
167         if (!lua_istable(L, 2))
168                 return 0;
169
170         u8 light;
171         light  = (getintfield_default(L, 2, "day",   0) & 0x0F);
172         light |= (getintfield_default(L, 2, "night", 0) & 0x0F) << 4;
173         
174         ManualMapVoxelManipulator *vm = o->vm;
175         
176         v3s16 p1 = lua_istable(L, 3) ? read_v3s16(L, 3) :
177                 vm->m_area.MinEdge + v3s16(0, 1, 0) * MAP_BLOCKSIZE;
178         v3s16 p2 = lua_istable(L, 4) ? read_v3s16(L, 4) :
179                 vm->m_area.MaxEdge - v3s16(0, 1, 0) * MAP_BLOCKSIZE;
180         sortBoxVerticies(p1, p2);
181
182         Mapgen mg;
183         mg.vm = vm;
184         
185         mg.setLighting(p1, p2, light);
186
187         return 0;
188 }
189
190 int LuaVoxelManip::l_get_light_data(lua_State *L)
191 {
192         NO_MAP_LOCK_REQUIRED;
193
194         LuaVoxelManip *o = checkobject(L, 1);
195         ManualMapVoxelManipulator *vm = o->vm;
196
197         int volume = vm->m_area.getVolume();
198
199         lua_newtable(L);
200         for (int i = 0; i != volume; i++) {
201                 lua_Integer light = vm->m_data[i].param1;
202                 lua_pushinteger(L, light);
203                 lua_rawseti(L, -2, i + 1);
204         }
205
206         return 1;
207 }
208
209 int LuaVoxelManip::l_set_light_data(lua_State *L)
210 {
211         NO_MAP_LOCK_REQUIRED;
212
213         LuaVoxelManip *o = checkobject(L, 1);
214         ManualMapVoxelManipulator *vm = o->vm;
215
216         if (!lua_istable(L, 2))
217                 return 0;
218
219         int volume = vm->m_area.getVolume();
220         for (int i = 0; i != volume; i++) {
221                 lua_rawgeti(L, 2, i + 1);
222                 u8 light = lua_tointeger(L, -1);
223
224                 vm->m_data[i].param1 = light;
225
226                 lua_pop(L, 1);
227         }
228
229         return 0;
230 }
231
232 int LuaVoxelManip::l_get_param2_data(lua_State *L)
233 {
234         NO_MAP_LOCK_REQUIRED;
235
236         LuaVoxelManip *o = checkobject(L, 1);
237         ManualMapVoxelManipulator *vm = o->vm;
238
239         int volume = vm->m_area.getVolume();
240
241         lua_newtable(L);
242         for (int i = 0; i != volume; i++) {
243                 lua_Integer param2 = vm->m_data[i].param2;
244                 lua_pushinteger(L, param2);
245                 lua_rawseti(L, -2, i + 1);
246         }
247
248         return 1;
249 }
250
251 int LuaVoxelManip::l_set_param2_data(lua_State *L)
252 {
253         NO_MAP_LOCK_REQUIRED;
254
255         LuaVoxelManip *o = checkobject(L, 1);
256         ManualMapVoxelManipulator *vm = o->vm;
257
258         if (!lua_istable(L, 2))
259                 return 0;
260
261         int volume = vm->m_area.getVolume();
262         for (int i = 0; i != volume; i++) {
263                 lua_rawgeti(L, 2, i + 1);
264                 u8 param2 = lua_tointeger(L, -1);
265
266                 vm->m_data[i].param2 = param2;
267
268                 lua_pop(L, 1);
269         }
270
271         return 0;
272 }
273
274 int LuaVoxelManip::l_update_map(lua_State *L)
275 {
276         LuaVoxelManip *o = checkobject(L, 1);
277         if (o->is_mapgen_vm)
278                 return 0;
279         
280         Environment *env = getEnv(L);
281         if (!env)
282                 return 0;
283
284         Map *map = &(env->getMap());
285
286         // TODO: Optimize this by using Mapgen::calcLighting() instead
287         std::map<v3s16, MapBlock *> lighting_mblocks;
288         std::map<v3s16, MapBlock *> *mblocks = &o->modified_blocks;
289         
290         lighting_mblocks.insert(mblocks->begin(), mblocks->end());
291         
292         map->updateLighting(lighting_mblocks, *mblocks);
293
294         MapEditEvent event;
295         event.type = MEET_OTHER;
296         for (std::map<v3s16, MapBlock *>::iterator
297                 it = mblocks->begin();
298                 it != mblocks->end(); ++it)
299                 event.modified_blocks.insert(it->first);
300                 
301         map->dispatchEvent(&event);
302
303         mblocks->clear();
304
305         return 0;       
306 }
307
308 LuaVoxelManip::LuaVoxelManip(ManualMapVoxelManipulator *mmvm, bool is_mg_vm)
309 {
310         this->vm           = mmvm;
311         this->is_mapgen_vm = is_mg_vm;
312 }
313
314 LuaVoxelManip::LuaVoxelManip(Map *map)
315 {
316         this->vm = new ManualMapVoxelManipulator(map);
317         this->is_mapgen_vm = false;
318 }
319
320 LuaVoxelManip::~LuaVoxelManip()
321 {
322         delete vm;
323 }
324
325 // LuaVoxelManip()
326 // Creates an LuaVoxelManip and leaves it on top of stack
327 int LuaVoxelManip::create_object(lua_State *L)
328 {
329         NO_MAP_LOCK_REQUIRED;
330         
331         Environment *env = getEnv(L);
332         if (!env)
333                 return 0;
334                 
335         Map *map = &(env->getMap());
336         LuaVoxelManip *o = new LuaVoxelManip(map);
337         
338         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
339         luaL_getmetatable(L, className);
340         lua_setmetatable(L, -2);
341         return 1;
342 }
343
344 LuaVoxelManip *LuaVoxelManip::checkobject(lua_State *L, int narg)
345 {
346         NO_MAP_LOCK_REQUIRED;
347         
348         luaL_checktype(L, narg, LUA_TUSERDATA);
349
350         void *ud = luaL_checkudata(L, narg, className);
351         if (!ud)
352                 luaL_typerror(L, narg, className);
353         
354         return *(LuaVoxelManip **)ud;  // unbox pointer
355 }
356
357 void LuaVoxelManip::Register(lua_State *L)
358 {
359         lua_newtable(L);
360         int methodtable = lua_gettop(L);
361         luaL_newmetatable(L, className);
362         int metatable = lua_gettop(L);
363
364         lua_pushliteral(L, "__metatable");
365         lua_pushvalue(L, methodtable);
366         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
367
368         lua_pushliteral(L, "__index");
369         lua_pushvalue(L, methodtable);
370         lua_settable(L, metatable);
371
372         lua_pushliteral(L, "__gc");
373         lua_pushcfunction(L, gc_object);
374         lua_settable(L, metatable);
375
376         lua_pop(L, 1);  // drop metatable
377
378         luaL_openlib(L, 0, methods, 0);  // fill methodtable
379         lua_pop(L, 1);  // drop methodtable
380
381         // Can be created from Lua (VoxelManip())
382         lua_register(L, className, create_object);
383 }
384
385 const char LuaVoxelManip::className[] = "VoxelManip";
386 const luaL_reg LuaVoxelManip::methods[] = {
387         luamethod(LuaVoxelManip, read_from_map),
388         luamethod(LuaVoxelManip, get_data),
389         luamethod(LuaVoxelManip, set_data),
390         luamethod(LuaVoxelManip, write_to_map),
391         luamethod(LuaVoxelManip, update_map),
392         luamethod(LuaVoxelManip, update_liquids),
393         luamethod(LuaVoxelManip, calc_lighting),
394         luamethod(LuaVoxelManip, set_lighting),
395         luamethod(LuaVoxelManip, get_light_data),
396         luamethod(LuaVoxelManip, set_light_data),
397         luamethod(LuaVoxelManip, get_param2_data),
398         luamethod(LuaVoxelManip, set_param2_data),
399         {0,0}
400 };