]> git.lizzy.rs Git - dragonfireclient.git/blob - src/script/lua_api/l_vmanip.cpp
Update Mapgen VoxelManipulator on buffer invalidation
[dragonfireclient.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         delete o;
35
36         return 0;
37 }
38
39 int LuaVoxelManip::l_read_from_map(lua_State *L)
40 {
41         LuaVoxelManip *o = checkobject(L, 1);
42         ManualMapVoxelManipulator *vm = o->vm;
43
44         v3s16 bp1 = getNodeBlockPos(read_v3s16(L, 2));
45         v3s16 bp2 = getNodeBlockPos(read_v3s16(L, 3));
46         sortBoxVerticies(bp1, bp2);
47
48         vm->initialEmerge(bp1, bp2);
49
50         push_v3s16(L, vm->m_area.MinEdge);
51         push_v3s16(L, vm->m_area.MaxEdge);
52
53         return 2;
54 }
55
56 int LuaVoxelManip::l_get_data(lua_State *L)
57 {
58         NO_MAP_LOCK_REQUIRED;
59
60         LuaVoxelManip *o = checkobject(L, 1);
61         ManualMapVoxelManipulator *vm = o->vm;
62
63         int volume = vm->m_area.getVolume();
64
65         lua_newtable(L);
66         for (int i = 0; i != volume; i++) {
67                 lua_Integer cid = vm->m_data[i].getContent();
68                 lua_pushinteger(L, cid);
69                 lua_rawseti(L, -2, i + 1);
70         }
71
72         return 1;
73 }
74
75 int LuaVoxelManip::l_set_data(lua_State *L)
76 {
77         NO_MAP_LOCK_REQUIRED;
78
79         LuaVoxelManip *o = checkobject(L, 1);
80         ManualMapVoxelManipulator *vm = o->vm;
81
82         if (!lua_istable(L, 2))
83                 return 0;
84
85         int volume = vm->m_area.getVolume();
86         for (int i = 0; i != volume; i++) {
87                 lua_rawgeti(L, 2, i + 1);
88                 content_t c = lua_tointeger(L, -1);
89
90                 vm->m_data[i].setContent(c);
91
92                 lua_pop(L, 1);
93         }
94
95         return 0;
96 }
97
98 int LuaVoxelManip::l_write_to_map(lua_State *L)
99 {
100         LuaVoxelManip *o = checkobject(L, 1);
101         ManualMapVoxelManipulator *vm = o->vm;
102
103         vm->blitBackAll(&o->modified_blocks);
104
105         return 0;
106 }
107
108 int LuaVoxelManip::l_update_liquids(lua_State *L)
109 {
110         LuaVoxelManip *o = checkobject(L, 1);
111
112         Environment *env = getEnv(L);
113         if (!env)
114                 return 0;
115
116         Map *map = &(env->getMap());
117         INodeDefManager *ndef = getServer(L)->getNodeDefManager();
118         ManualMapVoxelManipulator *vm = o->vm;
119
120         Mapgen mg;
121         mg.vm   = vm;
122         mg.ndef = ndef;
123
124         mg.updateLiquid(&map->m_transforming_liquid,
125                         vm->m_area.MinEdge, vm->m_area.MaxEdge);
126
127         return 0;
128 }
129
130 int LuaVoxelManip::l_calc_lighting(lua_State *L)
131 {
132         NO_MAP_LOCK_REQUIRED;
133
134         LuaVoxelManip *o = checkobject(L, 1);
135         if (!o->is_mapgen_vm)
136                 return 0;
137
138         INodeDefManager *ndef = getServer(L)->getNodeDefManager();
139         EmergeManager *emerge = getServer(L)->getEmergeManager();
140         ManualMapVoxelManipulator *vm = o->vm;
141
142         v3s16 p1 = lua_istable(L, 2) ? read_v3s16(L, 2) :
143                 vm->m_area.MinEdge + v3s16(0, 1, 0) * MAP_BLOCKSIZE;
144         v3s16 p2 = lua_istable(L, 3) ? read_v3s16(L, 3) :
145                 vm->m_area.MaxEdge - v3s16(0, 1, 0) * MAP_BLOCKSIZE;
146         sortBoxVerticies(p1, p2);
147
148         Mapgen mg;
149         mg.vm          = vm;
150         mg.ndef        = ndef;
151         mg.water_level = emerge->params.water_level;
152
153         mg.calcLighting(p1, p2);
154
155         return 0;
156 }
157
158 int LuaVoxelManip::l_set_lighting(lua_State *L)
159 {
160         NO_MAP_LOCK_REQUIRED;
161
162         LuaVoxelManip *o = checkobject(L, 1);
163         if (!o->is_mapgen_vm)
164                 return 0;
165
166         if (!lua_istable(L, 2))
167                 return 0;
168
169         u8 light;
170         light  = (getintfield_default(L, 2, "day",   0) & 0x0F);
171         light |= (getintfield_default(L, 2, "night", 0) & 0x0F) << 4;
172
173         ManualMapVoxelManipulator *vm = o->vm;
174
175         v3s16 p1 = lua_istable(L, 3) ? read_v3s16(L, 3) :
176                 vm->m_area.MinEdge + v3s16(0, 1, 0) * MAP_BLOCKSIZE;
177         v3s16 p2 = lua_istable(L, 4) ? read_v3s16(L, 4) :
178                 vm->m_area.MaxEdge - v3s16(0, 1, 0) * MAP_BLOCKSIZE;
179         sortBoxVerticies(p1, p2);
180
181         Mapgen mg;
182         mg.vm = vm;
183
184         mg.setLighting(p1, p2, light);
185
186         return 0;
187 }
188
189 int LuaVoxelManip::l_get_light_data(lua_State *L)
190 {
191         NO_MAP_LOCK_REQUIRED;
192
193         LuaVoxelManip *o = checkobject(L, 1);
194         ManualMapVoxelManipulator *vm = o->vm;
195
196         int volume = vm->m_area.getVolume();
197
198         lua_newtable(L);
199         for (int i = 0; i != volume; i++) {
200                 lua_Integer light = vm->m_data[i].param1;
201                 lua_pushinteger(L, light);
202                 lua_rawseti(L, -2, i + 1);
203         }
204
205         return 1;
206 }
207
208 int LuaVoxelManip::l_set_light_data(lua_State *L)
209 {
210         NO_MAP_LOCK_REQUIRED;
211
212         LuaVoxelManip *o = checkobject(L, 1);
213         ManualMapVoxelManipulator *vm = o->vm;
214
215         if (!lua_istable(L, 2))
216                 return 0;
217
218         int volume = vm->m_area.getVolume();
219         for (int i = 0; i != volume; i++) {
220                 lua_rawgeti(L, 2, i + 1);
221                 u8 light = lua_tointeger(L, -1);
222
223                 vm->m_data[i].param1 = light;
224
225                 lua_pop(L, 1);
226         }
227
228         return 0;
229 }
230
231 int LuaVoxelManip::l_get_param2_data(lua_State *L)
232 {
233         NO_MAP_LOCK_REQUIRED;
234
235         LuaVoxelManip *o = checkobject(L, 1);
236         ManualMapVoxelManipulator *vm = o->vm;
237
238         int volume = vm->m_area.getVolume();
239
240         lua_newtable(L);
241         for (int i = 0; i != volume; i++) {
242                 lua_Integer param2 = vm->m_data[i].param2;
243                 lua_pushinteger(L, param2);
244                 lua_rawseti(L, -2, i + 1);
245         }
246
247         return 1;
248 }
249
250 int LuaVoxelManip::l_set_param2_data(lua_State *L)
251 {
252         NO_MAP_LOCK_REQUIRED;
253
254         LuaVoxelManip *o = checkobject(L, 1);
255         ManualMapVoxelManipulator *vm = o->vm;
256
257         if (!lua_istable(L, 2))
258                 return 0;
259
260         int volume = vm->m_area.getVolume();
261         for (int i = 0; i != volume; i++) {
262                 lua_rawgeti(L, 2, i + 1);
263                 u8 param2 = lua_tointeger(L, -1);
264
265                 vm->m_data[i].param2 = param2;
266
267                 lua_pop(L, 1);
268         }
269
270         return 0;
271 }
272
273 int LuaVoxelManip::l_update_map(lua_State *L)
274 {
275         LuaVoxelManip *o = checkobject(L, 1);
276         if (o->is_mapgen_vm)
277                 return 0;
278
279         Environment *env = getEnv(L);
280         if (!env)
281                 return 0;
282
283         Map *map = &(env->getMap());
284
285         // TODO: Optimize this by using Mapgen::calcLighting() instead
286         std::map<v3s16, MapBlock *> lighting_mblocks;
287         std::map<v3s16, MapBlock *> *mblocks = &o->modified_blocks;
288
289         lighting_mblocks.insert(mblocks->begin(), mblocks->end());
290
291         map->updateLighting(lighting_mblocks, *mblocks);
292
293         MapEditEvent event;
294         event.type = MEET_OTHER;
295         for (std::map<v3s16, MapBlock *>::iterator
296                 it = mblocks->begin();
297                 it != mblocks->end(); ++it)
298                 event.modified_blocks.insert(it->first);
299
300         map->dispatchEvent(&event);
301
302         mblocks->clear();
303
304         return 0;
305 }
306
307 int LuaVoxelManip::l_was_modified(lua_State *L)
308 {
309         NO_MAP_LOCK_REQUIRED;
310
311         LuaVoxelManip *o = checkobject(L, 1);
312         ManualMapVoxelManipulator *vm = o->vm;
313
314         lua_pushboolean(L, vm->m_is_dirty);
315
316         return 1;
317 }
318
319 LuaVoxelManip::LuaVoxelManip(ManualMapVoxelManipulator *mmvm, bool is_mg_vm)
320 {
321         this->vm           = mmvm;
322         this->is_mapgen_vm = is_mg_vm;
323 }
324
325 LuaVoxelManip::LuaVoxelManip(Map *map)
326 {
327         this->vm = new ManualMapVoxelManipulator(map);
328         this->is_mapgen_vm = false;
329 }
330
331 LuaVoxelManip::~LuaVoxelManip()
332 {
333         if (!is_mapgen_vm)
334                 delete vm;
335 }
336
337 // LuaVoxelManip()
338 // Creates an LuaVoxelManip and leaves it on top of stack
339 int LuaVoxelManip::create_object(lua_State *L)
340 {
341         NO_MAP_LOCK_REQUIRED;
342
343         Environment *env = getEnv(L);
344         if (!env)
345                 return 0;
346
347         Map *map = &(env->getMap());
348         LuaVoxelManip *o = new LuaVoxelManip(map);
349
350         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
351         luaL_getmetatable(L, className);
352         lua_setmetatable(L, -2);
353         return 1;
354 }
355
356 LuaVoxelManip *LuaVoxelManip::checkobject(lua_State *L, int narg)
357 {
358         NO_MAP_LOCK_REQUIRED;
359
360         luaL_checktype(L, narg, LUA_TUSERDATA);
361
362         void *ud = luaL_checkudata(L, narg, className);
363         if (!ud)
364                 luaL_typerror(L, narg, className);
365
366         return *(LuaVoxelManip **)ud;  // unbox pointer
367 }
368
369 void LuaVoxelManip::Register(lua_State *L)
370 {
371         lua_newtable(L);
372         int methodtable = lua_gettop(L);
373         luaL_newmetatable(L, className);
374         int metatable = lua_gettop(L);
375
376         lua_pushliteral(L, "__metatable");
377         lua_pushvalue(L, methodtable);
378         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
379
380         lua_pushliteral(L, "__index");
381         lua_pushvalue(L, methodtable);
382         lua_settable(L, metatable);
383
384         lua_pushliteral(L, "__gc");
385         lua_pushcfunction(L, gc_object);
386         lua_settable(L, metatable);
387
388         lua_pop(L, 1);  // drop metatable
389
390         luaL_openlib(L, 0, methods, 0);  // fill methodtable
391         lua_pop(L, 1);  // drop methodtable
392
393         // Can be created from Lua (VoxelManip())
394         lua_register(L, className, create_object);
395 }
396
397 const char LuaVoxelManip::className[] = "VoxelManip";
398 const luaL_reg LuaVoxelManip::methods[] = {
399         luamethod(LuaVoxelManip, read_from_map),
400         luamethod(LuaVoxelManip, get_data),
401         luamethod(LuaVoxelManip, set_data),
402         luamethod(LuaVoxelManip, write_to_map),
403         luamethod(LuaVoxelManip, update_map),
404         luamethod(LuaVoxelManip, update_liquids),
405         luamethod(LuaVoxelManip, calc_lighting),
406         luamethod(LuaVoxelManip, set_lighting),
407         luamethod(LuaVoxelManip, get_light_data),
408         luamethod(LuaVoxelManip, set_light_data),
409         luamethod(LuaVoxelManip, get_param2_data),
410         luamethod(LuaVoxelManip, set_param2_data),
411         luamethod(LuaVoxelManip, was_modified),
412         {0,0}
413 };