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