]> git.lizzy.rs Git - minetest.git/blob - src/script/lua_api/l_util.cpp
Mapgen V6: Re-enable liquid flowing
[minetest.git] / src / script / lua_api / l_util.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.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 #include "lua_api/l_util.h"
21 #include "lua_api/l_internal.h"
22 #include "common/c_converter.h"
23 #include "common/c_content.h"
24 #include "cpp_api/s_async.h"
25 #include "serialization.h"
26 #include "json/json.h"
27 #include "debug.h"
28 #include "porting.h"
29 #include "log.h"
30 #include "tool.h"
31 #include "filesys.h"
32 #include "settings.h"
33 #include "main.h"  //required for g_settings, g_settings_path
34
35 // debug(...)
36 // Writes a line to dstream
37 int ModApiUtil::l_debug(lua_State *L)
38 {
39         NO_MAP_LOCK_REQUIRED;
40         // Handle multiple parameters to behave like standard lua print()
41         int n = lua_gettop(L);
42         lua_getglobal(L, "tostring");
43         for (int i = 1; i <= n; i++) {
44                 /*
45                         Call tostring(i-th argument).
46                         This is what print() does, and it behaves a bit
47                         differently from directly calling lua_tostring.
48                 */
49                 lua_pushvalue(L, -1);  /* function to be called */
50                 lua_pushvalue(L, i);   /* value to print */
51                 lua_call(L, 1, 1);
52                 size_t len;
53                 const char *s = lua_tolstring(L, -1, &len);
54                 if (i > 1)
55                         dstream << "\t";
56                 if (s)
57                         dstream << std::string(s, len);
58                 lua_pop(L, 1);
59         }
60         dstream << std::endl;
61         return 0;
62 }
63
64 // log([level,] text)
65 // Writes a line to the logger.
66 // The one-argument version logs to infostream.
67 // The two-argument version accept a log level: error, action, info, or verbose.
68 int ModApiUtil::l_log(lua_State *L)
69 {
70         NO_MAP_LOCK_REQUIRED;
71         std::string text;
72         LogMessageLevel level = LMT_INFO;
73         if (lua_isnone(L, 2)) {
74                 text = lua_tostring(L, 1);
75         }
76         else {
77                 std::string levelname = luaL_checkstring(L, 1);
78                 text = luaL_checkstring(L, 2);
79                 if(levelname == "error")
80                         level = LMT_ERROR;
81                 else if(levelname == "action")
82                         level = LMT_ACTION;
83                 else if(levelname == "verbose")
84                         level = LMT_VERBOSE;
85                 else if (levelname == "deprecated") {
86                         log_deprecated(L,text);
87                         return 0;
88                 }
89
90         }
91         log_printline(level, text);
92         return 0;
93 }
94
95 // setting_set(name, value)
96 int ModApiUtil::l_setting_set(lua_State *L)
97 {
98         NO_MAP_LOCK_REQUIRED;
99         const char *name = luaL_checkstring(L, 1);
100         const char *value = luaL_checkstring(L, 2);
101         g_settings->set(name, value);
102         return 0;
103 }
104
105 // setting_get(name)
106 int ModApiUtil::l_setting_get(lua_State *L)
107 {
108         NO_MAP_LOCK_REQUIRED;
109         const char *name = luaL_checkstring(L, 1);
110         try{
111                 std::string value = g_settings->get(name);
112                 lua_pushstring(L, value.c_str());
113         } catch(SettingNotFoundException &e){
114                 lua_pushnil(L);
115         }
116         return 1;
117 }
118
119 // setting_setbool(name)
120 int ModApiUtil::l_setting_setbool(lua_State *L)
121 {
122         NO_MAP_LOCK_REQUIRED;
123         const char *name = luaL_checkstring(L, 1);
124         bool value = lua_toboolean(L, 2);
125         g_settings->setBool(name, value);
126         return 0;
127 }
128
129 // setting_getbool(name)
130 int ModApiUtil::l_setting_getbool(lua_State *L)
131 {
132         NO_MAP_LOCK_REQUIRED;
133         const char *name = luaL_checkstring(L, 1);
134         try{
135                 bool value = g_settings->getBool(name);
136                 lua_pushboolean(L, value);
137         } catch(SettingNotFoundException &e){
138                 lua_pushnil(L);
139         }
140         return 1;
141 }
142
143 // setting_save()
144 int ModApiUtil::l_setting_save(lua_State *L)
145 {
146         NO_MAP_LOCK_REQUIRED;
147         if(g_settings_path != "")
148                 g_settings->updateConfigFile(g_settings_path.c_str());
149         return 0;
150 }
151
152 // parse_json(str[, nullvalue])
153 int ModApiUtil::l_parse_json(lua_State *L)
154 {
155         NO_MAP_LOCK_REQUIRED;
156
157         const char *jsonstr = luaL_checkstring(L, 1);
158
159         // Use passed nullvalue or default to nil
160         int nullindex = 2;
161         if (lua_isnone(L, nullindex)) {
162                 lua_pushnil(L);
163                 nullindex = lua_gettop(L);
164         }
165
166         Json::Value root;
167
168         {
169                 Json::Reader reader;
170                 std::istringstream stream(jsonstr);
171
172                 if (!reader.parse(stream, root)) {
173                         errorstream << "Failed to parse json data "
174                                 << reader.getFormattedErrorMessages();
175                         errorstream << "data: \"" << jsonstr << "\""
176                                 << std::endl;
177                         lua_pushnil(L);
178                         return 1;
179                 }
180         }
181
182         if (!push_json_value(L, root, nullindex)) {
183                 errorstream << "Failed to parse json data, "
184                         << "depth exceeds lua stack limit" << std::endl;
185                 errorstream << "data: \"" << jsonstr << "\"" << std::endl;
186                 lua_pushnil(L);
187         }
188         return 1;
189 }
190
191 // write_json(data[, styled]) -> string or nil and error message
192 int ModApiUtil::l_write_json(lua_State *L)
193 {
194         NO_MAP_LOCK_REQUIRED;
195
196         bool styled = false;
197         if (!lua_isnone(L, 2)) {
198                 styled = lua_toboolean(L, 2);
199                 lua_pop(L, 1);
200         }
201
202         Json::Value root;
203         try {
204                 read_json_value(L, root, 1);
205         } catch (SerializationError &e) {
206                 lua_pushnil(L);
207                 lua_pushstring(L, e.what());
208                 return 2;
209         }
210
211         std::string out;
212         if (styled) {
213                 Json::StyledWriter writer;
214                 out = writer.write(root);
215         } else {
216                 Json::FastWriter writer;
217                 out = writer.write(root);
218         }
219         lua_pushlstring(L, out.c_str(), out.size());
220         return 1;
221 }
222
223 // get_dig_params(groups, tool_capabilities[, time_from_last_punch])
224 int ModApiUtil::l_get_dig_params(lua_State *L)
225 {
226         NO_MAP_LOCK_REQUIRED;
227         std::map<std::string, int> groups;
228         read_groups(L, 1, groups);
229         ToolCapabilities tp = read_tool_capabilities(L, 2);
230         if(lua_isnoneornil(L, 3))
231                 push_dig_params(L, getDigParams(groups, &tp));
232         else
233                 push_dig_params(L, getDigParams(groups, &tp,
234                                         luaL_checknumber(L, 3)));
235         return 1;
236 }
237
238 // get_hit_params(groups, tool_capabilities[, time_from_last_punch])
239 int ModApiUtil::l_get_hit_params(lua_State *L)
240 {
241         NO_MAP_LOCK_REQUIRED;
242         std::map<std::string, int> groups;
243         read_groups(L, 1, groups);
244         ToolCapabilities tp = read_tool_capabilities(L, 2);
245         if(lua_isnoneornil(L, 3))
246                 push_hit_params(L, getHitParams(groups, &tp));
247         else
248                 push_hit_params(L, getHitParams(groups, &tp,
249                                         luaL_checknumber(L, 3)));
250         return 1;
251 }
252
253 // get_password_hash(name, raw_password)
254 int ModApiUtil::l_get_password_hash(lua_State *L)
255 {
256         NO_MAP_LOCK_REQUIRED;
257         std::string name = luaL_checkstring(L, 1);
258         std::string raw_password = luaL_checkstring(L, 2);
259         std::string hash = translatePassword(name,
260                         narrow_to_wide(raw_password));
261         lua_pushstring(L, hash.c_str());
262         return 1;
263 }
264
265 // is_yes(arg)
266 int ModApiUtil::l_is_yes(lua_State *L)
267 {
268         NO_MAP_LOCK_REQUIRED;
269
270         lua_getglobal(L, "tostring"); // function to be called
271         lua_pushvalue(L, 1); // 1st argument
272         lua_call(L, 1, 1); // execute function
273         std::string str(lua_tostring(L, -1)); // get result
274         lua_pop(L, 1);
275
276         bool yes = is_yes(str);
277         lua_pushboolean(L, yes);
278         return 1;
279 }
280
281 int ModApiUtil::l_get_builtin_path(lua_State *L)
282 {
283         std::string path = porting::path_share + DIR_DELIM + "builtin";
284         lua_pushstring(L, path.c_str());
285         return 1;
286 }
287
288 // compress(data, method, level)
289 int ModApiUtil::l_compress(lua_State *L)
290 {
291         size_t size;
292         const char *data = luaL_checklstring(L, 1, &size);
293
294         int level = -1;
295         if (!lua_isnone(L, 3) && !lua_isnil(L, 3))
296                 level = luaL_checknumber(L, 3);
297
298         std::ostringstream os;
299         compressZlib(std::string(data, size), os, level);
300
301         std::string out = os.str();
302
303         lua_pushlstring(L, out.data(), out.size());
304         return 1;
305 }
306
307 // decompress(data, method)
308 int ModApiUtil::l_decompress(lua_State *L)
309 {
310         size_t size;
311         const char * data = luaL_checklstring(L, 1, &size);
312
313         std::istringstream is(std::string(data, size));
314         std::ostringstream os;
315         decompressZlib(is, os);
316
317         std::string out = os.str();
318
319         lua_pushlstring(L, out.data(), out.size());
320         return 1;
321 }
322
323 void ModApiUtil::Initialize(lua_State *L, int top)
324 {
325         API_FCT(debug);
326         API_FCT(log);
327
328         API_FCT(setting_set);
329         API_FCT(setting_get);
330         API_FCT(setting_setbool);
331         API_FCT(setting_getbool);
332         API_FCT(setting_save);
333
334         API_FCT(parse_json);
335         API_FCT(write_json);
336
337         API_FCT(get_dig_params);
338         API_FCT(get_hit_params);
339
340         API_FCT(get_password_hash);
341
342         API_FCT(is_yes);
343
344         API_FCT(get_builtin_path);
345
346         API_FCT(compress);
347         API_FCT(decompress);
348 }
349
350 void ModApiUtil::InitializeAsync(AsyncEngine& engine)
351 {
352         ASYNC_API_FCT(debug);
353         ASYNC_API_FCT(log);
354
355         //ASYNC_API_FCT(setting_set);
356         ASYNC_API_FCT(setting_get);
357         //ASYNC_API_FCT(setting_setbool);
358         ASYNC_API_FCT(setting_getbool);
359         //ASYNC_API_FCT(setting_save);
360
361         ASYNC_API_FCT(parse_json);
362         ASYNC_API_FCT(write_json);
363
364         ASYNC_API_FCT(is_yes);
365
366         ASYNC_API_FCT(get_builtin_path);
367
368         ASYNC_API_FCT(compress);
369         ASYNC_API_FCT(decompress);
370 }
371