3 Copyright (C) 2015 est31 <mtest31@outlook.com>
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.
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.
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.
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"
26 #include "util/areastore.h"
30 static inline void get_data_and_border_flags(lua_State *L, u8 start_i,
31 bool *borders, bool *data)
33 if (!lua_isboolean(L, start_i))
35 *borders = lua_toboolean(L, start_i);
36 if (!lua_isboolean(L, start_i + 1))
38 *data = lua_toboolean(L, start_i + 1);
41 static void push_area(lua_State *L, const Area *a,
42 bool include_borders, bool include_data)
44 if (!include_borders && !include_data) {
45 lua_pushboolean(L, true);
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");
56 lua_pushlstring(L, a->data.c_str(), a->data.size());
57 lua_setfield(L, -2, "data");
61 static inline void push_areas(lua_State *L, const std::vector<Area *> &areas,
62 bool borders, bool data)
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);
73 // Deserializes value and handles errors
74 static int deserialization_helper(lua_State *L, AreaStore *as,
79 } catch (const SerializationError &e) {
80 lua_pushboolean(L, false);
81 lua_pushstring(L, e.what());
85 lua_pushboolean(L, true);
90 int LuaAreaStore::gc_object(lua_State *L)
92 LuaAreaStore *o = *(LuaAreaStore **)(lua_touserdata(L, 1));
97 // get_area(id, include_borders, include_data)
98 int LuaAreaStore::l_get_area(lua_State *L)
100 NO_MAP_LOCK_REQUIRED;
102 LuaAreaStore *o = checkobject(L, 1);
103 AreaStore *ast = o->as;
105 u32 id = luaL_checknumber(L, 2);
107 bool include_borders = true;
108 bool include_data = false;
109 get_data_and_border_flags(L, 3, &include_borders, &include_data);
113 res = ast->getArea(id);
117 push_area(L, res, include_borders, include_data);
122 // get_areas_for_pos(pos, include_borders, include_data)
123 int LuaAreaStore::l_get_areas_for_pos(lua_State *L)
125 NO_MAP_LOCK_REQUIRED;
127 LuaAreaStore *o = checkobject(L, 1);
128 AreaStore *ast = o->as;
130 v3s16 pos = check_v3s16(L, 2);
132 bool include_borders = true;
133 bool include_data = false;
134 get_data_and_border_flags(L, 3, &include_borders, &include_data);
136 std::vector<Area *> res;
138 ast->getAreasForPos(&res, pos);
139 push_areas(L, res, include_borders, include_data);
144 // get_areas_in_area(edge1, edge2, accept_overlap, include_borders, include_data)
145 int LuaAreaStore::l_get_areas_in_area(lua_State *L)
147 NO_MAP_LOCK_REQUIRED;
149 LuaAreaStore *o = checkobject(L, 1);
150 AreaStore *ast = o->as;
152 v3s16 minedge = check_v3s16(L, 2);
153 v3s16 maxedge = check_v3s16(L, 3);
155 bool include_borders = true;
156 bool include_data = false;
157 bool accept_overlap = false;
158 if (lua_isboolean(L, 4)) {
159 accept_overlap = lua_toboolean(L, 4);
160 get_data_and_border_flags(L, 5, &include_borders, &include_data);
162 std::vector<Area *> res;
164 ast->getAreasInArea(&res, minedge, maxedge, accept_overlap);
165 push_areas(L, res, include_borders, include_data);
170 // insert_area(edge1, edge2, data, id)
171 int LuaAreaStore::l_insert_area(lua_State *L)
173 NO_MAP_LOCK_REQUIRED;
175 LuaAreaStore *o = checkobject(L, 1);
176 AreaStore *ast = o->as;
178 Area a(check_v3s16(L, 2), check_v3s16(L, 3));
181 const char *data = luaL_checklstring(L, 4, &d_len);
183 a.data = std::string(data, d_len);
185 if (lua_isnumber(L, 5))
186 a.id = lua_tonumber(L, 5);
188 if (!ast->insertArea(&a))
191 lua_pushnumber(L, a.id);
196 int LuaAreaStore::l_reserve(lua_State *L)
198 NO_MAP_LOCK_REQUIRED;
200 LuaAreaStore *o = checkobject(L, 1);
201 AreaStore *ast = o->as;
203 size_t count = luaL_checknumber(L, 2);
209 int LuaAreaStore::l_remove_area(lua_State *L)
211 NO_MAP_LOCK_REQUIRED;
213 LuaAreaStore *o = checkobject(L, 1);
214 AreaStore *ast = o->as;
216 u32 id = luaL_checknumber(L, 2);
217 bool success = ast->removeArea(id);
219 lua_pushboolean(L, success);
223 // set_cache_params(params)
224 int LuaAreaStore::l_set_cache_params(lua_State *L)
226 NO_MAP_LOCK_REQUIRED;
228 LuaAreaStore *o = checkobject(L, 1);
229 AreaStore *ast = o->as;
231 luaL_checktype(L, 2, LUA_TTABLE);
233 bool enabled = getboolfield_default(L, 2, "enabled", true);
234 u8 block_radius = getintfield_default(L, 2, "block_radius", 64);
235 size_t limit = getintfield_default(L, 2, "block_radius", 1000);
237 ast->setCacheParams(enabled, block_radius, limit);
243 int LuaAreaStore::l_to_string(lua_State *L)
245 NO_MAP_LOCK_REQUIRED;
247 LuaAreaStore *o = checkobject(L, 1);
249 std::ostringstream os(std::ios_base::binary);
250 o->as->serialize(os);
251 std::string str = os.str();
253 lua_pushlstring(L, str.c_str(), str.length());
258 int LuaAreaStore::l_to_file(lua_State *L)
260 NO_MAP_LOCK_REQUIRED;
262 LuaAreaStore *o = checkobject(L, 1);
263 AreaStore *ast = o->as;
265 const char *filename = luaL_checkstring(L, 2);
266 CHECK_SECURE_PATH(L, filename, true);
268 std::ostringstream os(std::ios_base::binary);
271 lua_pushboolean(L, fs::safeWriteToFile(filename, os.str()));
276 int LuaAreaStore::l_from_string(lua_State *L)
278 NO_MAP_LOCK_REQUIRED;
280 LuaAreaStore *o = checkobject(L, 1);
283 const char *str = luaL_checklstring(L, 2, &len);
285 std::istringstream is(std::string(str, len), std::ios::binary);
286 return deserialization_helper(L, o->as, is);
289 // from_file(filename)
290 int LuaAreaStore::l_from_file(lua_State *L)
292 NO_MAP_LOCK_REQUIRED;
294 LuaAreaStore *o = checkobject(L, 1);
296 const char *filename = luaL_checkstring(L, 2);
297 CHECK_SECURE_PATH(L, filename, false);
299 std::ifstream is(filename, std::ios::binary);
300 return deserialization_helper(L, o->as, is);
303 LuaAreaStore::LuaAreaStore() : as(AreaStore::getOptimalImplementation())
307 LuaAreaStore::LuaAreaStore(const std::string &type)
310 if (type == "LibSpatial") {
311 as = new SpatialAreaStore();
315 as = new VectorAreaStore();
319 LuaAreaStore::~LuaAreaStore()
325 // Creates an LuaAreaStore and leaves it on top of stack
326 int LuaAreaStore::create_object(lua_State *L)
328 NO_MAP_LOCK_REQUIRED;
330 LuaAreaStore *o = (lua_isstring(L, 1)) ?
331 new LuaAreaStore(lua_tostring(L, 1)) :
334 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
335 luaL_getmetatable(L, className);
336 lua_setmetatable(L, -2);
340 LuaAreaStore *LuaAreaStore::checkobject(lua_State *L, int narg)
342 NO_MAP_LOCK_REQUIRED;
344 luaL_checktype(L, narg, LUA_TUSERDATA);
346 void *ud = luaL_checkudata(L, narg, className);
348 luaL_typerror(L, narg, className);
350 return *(LuaAreaStore **)ud; // unbox pointer
353 void LuaAreaStore::Register(lua_State *L)
356 int methodtable = lua_gettop(L);
357 luaL_newmetatable(L, className);
358 int metatable = lua_gettop(L);
360 lua_pushliteral(L, "__metatable");
361 lua_pushvalue(L, methodtable);
362 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
364 lua_pushliteral(L, "__index");
365 lua_pushvalue(L, methodtable);
366 lua_settable(L, metatable);
368 lua_pushliteral(L, "__gc");
369 lua_pushcfunction(L, gc_object);
370 lua_settable(L, metatable);
372 lua_pop(L, 1); // drop metatable
374 luaL_openlib(L, 0, methods, 0); // fill methodtable
375 lua_pop(L, 1); // drop methodtable
377 // Can be created from Lua (AreaStore())
378 lua_register(L, className, create_object);
381 const char LuaAreaStore::className[] = "AreaStore";
382 const luaL_Reg LuaAreaStore::methods[] = {
383 luamethod(LuaAreaStore, get_area),
384 luamethod(LuaAreaStore, get_areas_for_pos),
385 luamethod(LuaAreaStore, get_areas_in_area),
386 luamethod(LuaAreaStore, insert_area),
387 luamethod(LuaAreaStore, reserve),
388 luamethod(LuaAreaStore, remove_area),
389 luamethod(LuaAreaStore, set_cache_params),
390 luamethod(LuaAreaStore, to_string),
391 luamethod(LuaAreaStore, to_file),
392 luamethod(LuaAreaStore, from_string),
393 luamethod(LuaAreaStore, from_file),