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