]> git.lizzy.rs Git - dragonfireclient.git/blob - src/script/lua_api/l_vmanip.cpp
Omnicleanup: header cleanup, add ModApiUtil shared between game and mainmenu
[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         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         Mapgen mg;
144         mg.vm          = vm;
145         mg.ndef        = ndef;
146         mg.water_level = emerge->params->water_level;
147         
148         mg.calcLighting(vm->m_area.MinEdge + v3s16(0, 1, 0) * MAP_BLOCKSIZE,
149                                         vm->m_area.MaxEdge - v3s16(0, 1, 0) * MAP_BLOCKSIZE);
150
151         return 0;
152 }
153
154 int LuaVoxelManip::l_set_lighting(lua_State *L)
155 {
156         NO_MAP_LOCK_REQUIRED;
157         
158         LuaVoxelManip *o = checkobject(L, 1);
159         if (!o->is_mapgen_vm)
160                 return 0;
161         
162         if (!lua_istable(L, 2))
163                 return 0;
164
165         u8 light;
166         light  = (getintfield_default(L, 4, "day",   0) & 0x0F);
167         light |= (getintfield_default(L, 4, "night", 0) & 0x0F) << 8;
168         
169         ManualMapVoxelManipulator *vm = o->vm;
170         
171         Mapgen mg;
172         mg.vm = vm;
173         
174         mg.setLighting(vm->m_area.MinEdge + v3s16(0, 1, 0) * MAP_BLOCKSIZE,
175                                    vm->m_area.MaxEdge - v3s16(0, 1, 0) * MAP_BLOCKSIZE,
176                                    light);
177
178         return 0;
179 }
180
181 int LuaVoxelManip::l_update_map(lua_State *L)
182 {
183         LuaVoxelManip *o = checkobject(L, 1);
184         if (o->is_mapgen_vm)
185                 return 0;
186         
187         Environment *env = getEnv(L);
188         if (!env)
189                 return 0;
190
191         Map *map = &(env->getMap());
192
193         // TODO: Optimize this by using Mapgen::calcLighting() instead
194         std::map<v3s16, MapBlock *> lighting_mblocks;
195         std::map<v3s16, MapBlock *> *mblocks = &o->modified_blocks;
196         
197         lighting_mblocks.insert(mblocks->begin(), mblocks->end());
198         
199         map->updateLighting(lighting_mblocks, *mblocks);
200
201         MapEditEvent event;
202         event.type = MEET_OTHER;
203         for (std::map<v3s16, MapBlock *>::iterator
204                 it = mblocks->begin();
205                 it != mblocks->end(); ++it)
206                 event.modified_blocks.insert(it->first);
207                 
208         map->dispatchEvent(&event);
209
210         mblocks->clear();
211
212         return 0;       
213 }
214
215 LuaVoxelManip::LuaVoxelManip(ManualMapVoxelManipulator *mmvm, bool is_mg_vm)
216 {
217         this->vm           = mmvm;
218         this->is_mapgen_vm = is_mg_vm;
219 }
220
221 LuaVoxelManip::LuaVoxelManip(Map *map)
222 {
223         this->vm = new ManualMapVoxelManipulator(map);
224         this->is_mapgen_vm = false;
225 }
226
227 LuaVoxelManip::~LuaVoxelManip()
228 {
229         delete vm;
230 }
231
232 // LuaVoxelManip()
233 // Creates an LuaVoxelManip and leaves it on top of stack
234 int LuaVoxelManip::create_object(lua_State *L)
235 {
236         NO_MAP_LOCK_REQUIRED;
237         
238         Environment *env = getEnv(L);
239         if (!env)
240                 return 0;
241                 
242         Map *map = &(env->getMap());
243         LuaVoxelManip *o = new LuaVoxelManip(map);
244         
245         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
246         luaL_getmetatable(L, className);
247         lua_setmetatable(L, -2);
248         return 1;
249 }
250
251 LuaVoxelManip *LuaVoxelManip::checkobject(lua_State *L, int narg)
252 {
253         NO_MAP_LOCK_REQUIRED;
254         
255         luaL_checktype(L, narg, LUA_TUSERDATA);
256
257         void *ud = luaL_checkudata(L, narg, className);
258         if (!ud)
259                 luaL_typerror(L, narg, className);
260         
261         return *(LuaVoxelManip **)ud;  // unbox pointer
262 }
263
264 void LuaVoxelManip::Register(lua_State *L)
265 {
266         lua_newtable(L);
267         int methodtable = lua_gettop(L);
268         luaL_newmetatable(L, className);
269         int metatable = lua_gettop(L);
270
271         lua_pushliteral(L, "__metatable");
272         lua_pushvalue(L, methodtable);
273         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
274
275         lua_pushliteral(L, "__index");
276         lua_pushvalue(L, methodtable);
277         lua_settable(L, metatable);
278
279         lua_pushliteral(L, "__gc");
280         lua_pushcfunction(L, gc_object);
281         lua_settable(L, metatable);
282
283         lua_pop(L, 1);  // drop metatable
284
285         luaL_openlib(L, 0, methods, 0);  // fill methodtable
286         lua_pop(L, 1);  // drop methodtable
287
288         // Can be created from Lua (VoxelManip())
289         lua_register(L, className, create_object);
290 }
291
292 const char LuaVoxelManip::className[] = "VoxelManip";
293 const luaL_reg LuaVoxelManip::methods[] = {
294         luamethod(LuaVoxelManip, read_from_map),
295         luamethod(LuaVoxelManip, get_data),
296         luamethod(LuaVoxelManip, set_data),
297         luamethod(LuaVoxelManip, write_to_map),
298         luamethod(LuaVoxelManip, update_map),
299         luamethod(LuaVoxelManip, update_liquids),
300         luamethod(LuaVoxelManip, calc_lighting),
301         luamethod(LuaVoxelManip, set_lighting),
302         {0,0}
303 };