]> git.lizzy.rs Git - dragonfireclient.git/blob - src/script/lua_api/l_areastore.cpp
ff6abbd9fc057bb5d122278f730cd846af887570
[dragonfireclient.git] / src / script / lua_api / l_areastore.cpp
1 /*
2 Minetest
3 Copyright (C) 2015 est31 <mtest31@outlook.com>
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_areastore.h"
22 #include "lua_api/l_internal.h"
23 #include "common/c_converter.h"
24 #include "cpp_api/s_security.h"
25 #include "irr_v3d.h"
26 #include "areastore.h"
27 #include "filesys.h"
28 #ifndef ANDROID
29         #include "cmake_config.h"
30 #endif
31 #include <fstream>
32
33 static inline void get_data_and_border_flags(lua_State *L, u8 start_i,
34                 bool *borders, bool *data)
35 {
36         if (!lua_isboolean(L, start_i))
37                 return;
38         *borders = lua_toboolean(L, start_i);
39         if (!lua_isboolean(L, start_i + 1))
40                 return;
41         *data = lua_toboolean(L, start_i + 1);
42 }
43
44 static void push_area(lua_State *L, const Area *a,
45                 bool include_borders, bool include_data)
46 {
47         if (!include_borders && !include_data) {
48                 lua_pushboolean(L, true);
49                 return;
50         }
51         lua_newtable(L);
52         if (include_borders) {
53                 push_v3s16(L, a->minedge);
54                 lua_setfield(L, -2, "min");
55                 push_v3s16(L, a->maxedge);
56                 lua_setfield(L, -2, "max");
57         }
58         if (include_data) {
59                 lua_pushlstring(L, a->data.c_str(), a->data.size());
60                 lua_setfield(L, -2, "data");
61         }
62 }
63
64 static inline void push_areas(lua_State *L, const std::vector<Area *> &areas,
65                 bool borders, bool data)
66 {
67         lua_newtable(L);
68         size_t cnt = areas.size();
69         for (size_t i = 0; i < cnt; i++) {
70                 lua_pushnumber(L, areas[i]->id);
71                 push_area(L, areas[i], borders, data);
72                 lua_settable(L, -3);
73         }
74 }
75
76 // garbage collector
77 int LuaAreaStore::gc_object(lua_State *L)
78 {
79         LuaAreaStore *o = *(LuaAreaStore **)(lua_touserdata(L, 1));
80         delete o;
81         return 0;
82 }
83
84 // get_area(id, include_borders, include_data)
85 int LuaAreaStore::l_get_area(lua_State *L)
86 {
87         NO_MAP_LOCK_REQUIRED;
88
89         LuaAreaStore *o = checkobject(L, 1);
90         AreaStore *ast = o->as;
91
92         u32 id = luaL_checknumber(L, 2);
93
94         bool include_borders = true;
95         bool include_data = false;
96         get_data_and_border_flags(L, 3, &include_borders, &include_data);
97
98         const Area *res;
99
100         res = ast->getArea(id);
101         push_area(L, res, include_borders, include_data);
102
103         return 1;
104 }
105
106 // get_areas_for_pos(pos, include_borders, include_data)
107 int LuaAreaStore::l_get_areas_for_pos(lua_State *L)
108 {
109         NO_MAP_LOCK_REQUIRED;
110
111         LuaAreaStore *o = checkobject(L, 1);
112         AreaStore *ast = o->as;
113
114         v3s16 pos = check_v3s16(L, 2);
115
116         bool include_borders = true;
117         bool include_data = false;
118         get_data_and_border_flags(L, 3, &include_borders, &include_data);
119
120         std::vector<Area *> res;
121
122         ast->getAreasForPos(&res, pos);
123         push_areas(L, res, include_borders, include_data);
124
125         return 1;
126 }
127
128 // get_areas_in_area(edge1, edge2, accept_overlap, include_borders, include_data)
129 int LuaAreaStore::l_get_areas_in_area(lua_State *L)
130 {
131         NO_MAP_LOCK_REQUIRED;
132
133         LuaAreaStore *o = checkobject(L, 1);
134         AreaStore *ast = o->as;
135
136         v3s16 minedge = check_v3s16(L, 2);
137         v3s16 maxedge = check_v3s16(L, 3);
138
139         bool include_borders = true;
140         bool include_data = false;
141         bool accept_overlap = false;
142         if (lua_isboolean(L, 4)) {
143                 accept_overlap = lua_toboolean(L, 4);
144                 get_data_and_border_flags(L, 5, &include_borders, &include_data);
145         }
146         std::vector<Area *> res;
147
148         ast->getAreasInArea(&res, minedge, maxedge, accept_overlap);
149         push_areas(L, res, include_borders, include_data);
150
151         return 1;
152 }
153
154 // insert_area(edge1, edge2, data)
155 int LuaAreaStore::l_insert_area(lua_State *L)
156 {
157         NO_MAP_LOCK_REQUIRED;
158
159         LuaAreaStore *o = checkobject(L, 1);
160         AreaStore *ast = o->as;
161
162         Area a(check_v3s16(L, 2), check_v3s16(L, 3));
163
164         size_t d_len;
165         const char *data = luaL_checklstring(L, 4, &d_len);
166
167         a.data = std::string(data, d_len);
168
169         if (!ast->insertArea(&a))
170                 return 0;
171
172         lua_pushnumber(L, a.id);
173         return 1;
174 }
175
176 // reserve(count)
177 int LuaAreaStore::l_reserve(lua_State *L)
178 {
179         NO_MAP_LOCK_REQUIRED;
180
181         LuaAreaStore *o = checkobject(L, 1);
182         AreaStore *ast = o->as;
183
184         size_t count = luaL_checknumber(L, 2);
185         ast->reserve(count);
186         return 0;
187 }
188
189 // remove_area(id)
190 int LuaAreaStore::l_remove_area(lua_State *L)
191 {
192         NO_MAP_LOCK_REQUIRED;
193
194         LuaAreaStore *o = checkobject(L, 1);
195         AreaStore *ast = o->as;
196
197         u32 id = luaL_checknumber(L, 2);
198         bool success = ast->removeArea(id);
199
200         lua_pushboolean(L, success);
201         return 1;
202 }
203
204 // set_cache_params(params)
205 int LuaAreaStore::l_set_cache_params(lua_State *L)
206 {
207         NO_MAP_LOCK_REQUIRED;
208
209         LuaAreaStore *o = checkobject(L, 1);
210         AreaStore *ast = o->as;
211
212         luaL_checktype(L, 2, LUA_TTABLE);
213
214         bool enabled = getboolfield_default(L, 2, "enabled", true);
215         u8 block_radius = getintfield_default(L, 2, "block_radius", 64);
216         size_t limit = getintfield_default(L, 2, "block_radius", 1000);
217
218         ast->setCacheParams(enabled, block_radius, limit);
219
220         return 0;
221 }
222
223 #if 0
224 // to_string()
225 int LuaAreaStore::l_to_string(lua_State *L)
226 {
227         NO_MAP_LOCK_REQUIRED;
228
229         LuaAreaStore *o = checkobject(L, 1);
230         AreaStore *ast = o->as;
231
232         std::ostringstream os(std::ios_base::binary);
233         ast->serialize(os);
234         std::string str = os.str();
235
236         lua_pushlstring(L, str.c_str(), str.length());
237         return 1;
238 }
239
240 // to_file(filename)
241 int LuaAreaStore::l_to_file(lua_State *L)
242 {
243         NO_MAP_LOCK_REQUIRED;
244
245         LuaAreaStore *o = checkobject(L, 1);
246         AreaStore *ast = o->as;
247
248         const char *filename = luaL_checkstring(L, 2);
249         CHECK_SECURE_PATH_OPTIONAL(L, filename);
250
251         std::ostringstream os(std::ios_base::binary);
252         ast->serialize(os);
253
254         lua_pushboolean(L, fs::safeWriteToFile(filename, os.str()));
255         return 1;
256 }
257
258 // from_string(str)
259 int LuaAreaStore::l_from_string(lua_State *L)
260 {
261         NO_MAP_LOCK_REQUIRED;
262
263         LuaAreaStore *o = checkobject(L, 1);
264         AreaStore *ast = o->as;
265
266         size_t len;
267         const char *str = luaL_checklstring(L, 2, &len);
268
269         std::istringstream is(std::string(str, len), std::ios::binary);
270         bool success = ast->deserialize(is);
271
272         lua_pushboolean(L, success);
273         return 1;
274 }
275
276 // from_file(filename)
277 int LuaAreaStore::l_from_file(lua_State *L)
278 {
279         NO_MAP_LOCK_REQUIRED;
280
281         LuaAreaStore *o = checkobject(L, 1);
282         AreaStore *ast = o->as;
283
284         const char *filename = luaL_checkstring(L, 2);
285         CHECK_SECURE_PATH_OPTIONAL(L, filename);
286
287         std::ifstream is(filename, std::ios::binary);
288         bool success = ast->deserialize(is);
289
290         lua_pushboolean(L, success);
291         return 1;
292 }
293 #endif
294
295 LuaAreaStore::LuaAreaStore()
296 {
297 #if USE_SPATIAL
298         this->as = new SpatialAreaStore();
299 #else
300         this->as = new VectorAreaStore();
301 #endif
302 }
303
304 LuaAreaStore::LuaAreaStore(const std::string &type)
305 {
306 #if USE_SPATIAL
307         if (type == "LibSpatial") {
308                 this->as = new SpatialAreaStore();
309         } else
310 #endif
311         {
312                 this->as = new VectorAreaStore();
313         }
314 }
315
316 LuaAreaStore::~LuaAreaStore()
317 {
318         delete as;
319 }
320
321 // LuaAreaStore()
322 // Creates an LuaAreaStore and leaves it on top of stack
323 int LuaAreaStore::create_object(lua_State *L)
324 {
325         NO_MAP_LOCK_REQUIRED;
326
327         LuaAreaStore *o = (lua_isstring(L, 1)) ?
328                 new LuaAreaStore(lua_tostring(L, 1)) :
329                 new LuaAreaStore();
330
331         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
332         luaL_getmetatable(L, className);
333         lua_setmetatable(L, -2);
334         return 1;
335 }
336
337 LuaAreaStore *LuaAreaStore::checkobject(lua_State *L, int narg)
338 {
339         NO_MAP_LOCK_REQUIRED;
340
341         luaL_checktype(L, narg, LUA_TUSERDATA);
342
343         void *ud = luaL_checkudata(L, narg, className);
344         if (!ud)
345                 luaL_typerror(L, narg, className);
346
347         return *(LuaAreaStore **)ud;  // unbox pointer
348 }
349
350 void LuaAreaStore::Register(lua_State *L)
351 {
352         lua_newtable(L);
353         int methodtable = lua_gettop(L);
354         luaL_newmetatable(L, className);
355         int metatable = lua_gettop(L);
356
357         lua_pushliteral(L, "__metatable");
358         lua_pushvalue(L, methodtable);
359         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
360
361         lua_pushliteral(L, "__index");
362         lua_pushvalue(L, methodtable);
363         lua_settable(L, metatable);
364
365         lua_pushliteral(L, "__gc");
366         lua_pushcfunction(L, gc_object);
367         lua_settable(L, metatable);
368
369         lua_pop(L, 1);  // drop metatable
370
371         luaL_openlib(L, 0, methods, 0);  // fill methodtable
372         lua_pop(L, 1);  // drop methodtable
373
374         // Can be created from Lua (AreaStore())
375         lua_register(L, className, create_object);
376 }
377
378 const char LuaAreaStore::className[] = "AreaStore";
379 const luaL_reg LuaAreaStore::methods[] = {
380         luamethod(LuaAreaStore, get_area),
381         luamethod(LuaAreaStore, get_areas_for_pos),
382         luamethod(LuaAreaStore, get_areas_in_area),
383         luamethod(LuaAreaStore, insert_area),
384         luamethod(LuaAreaStore, reserve),
385         luamethod(LuaAreaStore, remove_area),
386         luamethod(LuaAreaStore, set_cache_params),
387         /* luamethod(LuaAreaStore, to_string),
388         luamethod(LuaAreaStore, to_file),
389         luamethod(LuaAreaStore, from_string),
390         luamethod(LuaAreaStore, from_file),*/
391         {0,0}
392 };