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