]> git.lizzy.rs Git - minetest.git/blob - src/scriptapi_common.cpp
Remove no virtual dtor warnings, make MapgenParams contain actual NoiseParams
[minetest.git] / src / scriptapi_common.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 "scriptapi.h"
21 #include "scriptapi_common.h"
22
23 extern "C" {
24 #include "lauxlib.h"
25 }
26
27 #include "script.h"
28 #include "scriptapi_types.h"
29 #include "scriptapi_object.h"
30
31
32 Server* get_server(lua_State *L)
33 {
34         // Get server from registry
35         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
36         Server *server = (Server*)lua_touserdata(L, -1);
37         lua_pop(L, 1);
38         return server;
39 }
40
41 ServerEnvironment* get_env(lua_State *L)
42 {
43         // Get environment from registry
44         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_env");
45         ServerEnvironment *env = (ServerEnvironment*)lua_touserdata(L, -1);
46         lua_pop(L, 1);
47         return env;
48 }
49
50 void warn_if_field_exists(lua_State *L, int table,
51                 const char *fieldname, const std::string &message)
52 {
53         lua_getfield(L, table, fieldname);
54         if(!lua_isnil(L, -1)){
55                 infostream<<script_get_backtrace(L)<<std::endl;
56                 infostream<<"WARNING: field \""<<fieldname<<"\": "
57                                 <<message<<std::endl;
58         }
59         lua_pop(L, 1);
60 }
61
62 /*
63         ToolCapabilities
64 */
65
66 ToolCapabilities read_tool_capabilities(
67                 lua_State *L, int table)
68 {
69         ToolCapabilities toolcap;
70         getfloatfield(L, table, "full_punch_interval", toolcap.full_punch_interval);
71         getintfield(L, table, "max_drop_level", toolcap.max_drop_level);
72         lua_getfield(L, table, "groupcaps");
73         if(lua_istable(L, -1)){
74                 int table_groupcaps = lua_gettop(L);
75                 lua_pushnil(L);
76                 while(lua_next(L, table_groupcaps) != 0){
77                         // key at index -2 and value at index -1
78                         std::string groupname = luaL_checkstring(L, -2);
79                         if(lua_istable(L, -1)){
80                                 int table_groupcap = lua_gettop(L);
81                                 // This will be created
82                                 ToolGroupCap groupcap;
83                                 // Read simple parameters
84                                 getintfield(L, table_groupcap, "maxlevel", groupcap.maxlevel);
85                                 getintfield(L, table_groupcap, "uses", groupcap.uses);
86                                 // DEPRECATED: maxwear
87                                 float maxwear = 0;
88                                 if(getfloatfield(L, table_groupcap, "maxwear", maxwear)){
89                                         if(maxwear != 0)
90                                                 groupcap.uses = 1.0/maxwear;
91                                         else
92                                                 groupcap.uses = 0;
93                                         infostream<<script_get_backtrace(L)<<std::endl;
94                                         infostream<<"WARNING: field \"maxwear\" is deprecated; "
95                                                         <<"should replace with uses=1/maxwear"<<std::endl;
96                                 }
97                                 // Read "times" table
98                                 lua_getfield(L, table_groupcap, "times");
99                                 if(lua_istable(L, -1)){
100                                         int table_times = lua_gettop(L);
101                                         lua_pushnil(L);
102                                         while(lua_next(L, table_times) != 0){
103                                                 // key at index -2 and value at index -1
104                                                 int rating = luaL_checkinteger(L, -2);
105                                                 float time = luaL_checknumber(L, -1);
106                                                 groupcap.times[rating] = time;
107                                                 // removes value, keeps key for next iteration
108                                                 lua_pop(L, 1);
109                                         }
110                                 }
111                                 lua_pop(L, 1);
112                                 // Insert groupcap into toolcap
113                                 toolcap.groupcaps[groupname] = groupcap;
114                         }
115                         // removes value, keeps key for next iteration
116                         lua_pop(L, 1);
117                 }
118         }
119         lua_pop(L, 1);
120         lua_getfield(L, table, "damage_groups");
121         if(lua_istable(L, -1)){
122                 int table_damage_groups = lua_gettop(L);
123                 lua_pushnil(L);
124                 while(lua_next(L, table_damage_groups) != 0){
125                         // key at index -2 and value at index -1
126                         std::string groupname = luaL_checkstring(L, -2);
127                         u16 value = luaL_checkinteger(L, -1);
128                         toolcap.damageGroups[groupname] = value;
129                         // removes value, keeps key for next iteration
130                         lua_pop(L, 1);
131                 }
132         }
133         lua_pop(L, 1);
134         return toolcap;
135 }
136
137 void set_tool_capabilities(lua_State *L, int table,
138                 const ToolCapabilities &toolcap)
139 {
140         setfloatfield(L, table, "full_punch_interval", toolcap.full_punch_interval);
141         setintfield(L, table, "max_drop_level", toolcap.max_drop_level);
142         // Create groupcaps table
143         lua_newtable(L);
144         // For each groupcap
145         for(std::map<std::string, ToolGroupCap>::const_iterator
146                         i = toolcap.groupcaps.begin(); i != toolcap.groupcaps.end(); i++){
147                 // Create groupcap table
148                 lua_newtable(L);
149                 const std::string &name = i->first;
150                 const ToolGroupCap &groupcap = i->second;
151                 // Create subtable "times"
152                 lua_newtable(L);
153                 for(std::map<int, float>::const_iterator
154                                 i = groupcap.times.begin(); i != groupcap.times.end(); i++){
155                         int rating = i->first;
156                         float time = i->second;
157                         lua_pushinteger(L, rating);
158                         lua_pushnumber(L, time);
159                         lua_settable(L, -3);
160                 }
161                 // Set subtable "times"
162                 lua_setfield(L, -2, "times");
163                 // Set simple parameters
164                 setintfield(L, -1, "maxlevel", groupcap.maxlevel);
165                 setintfield(L, -1, "uses", groupcap.uses);
166                 // Insert groupcap table into groupcaps table
167                 lua_setfield(L, -2, name.c_str());
168         }
169         // Set groupcaps table
170         lua_setfield(L, -2, "groupcaps");
171         //Create damage_groups table
172         lua_newtable(L);
173         // For each damage group
174         for(std::map<std::string, s16>::const_iterator
175                         i = toolcap.damageGroups.begin(); i != toolcap.damageGroups.end(); i++){
176                 // Create damage group table
177                 lua_pushinteger(L, i->second);
178                 lua_setfield(L, -2, i->first.c_str());
179         }
180         lua_setfield(L, -2, "damage_groups");
181 }
182
183 void push_tool_capabilities(lua_State *L,
184                 const ToolCapabilities &prop)
185 {
186         lua_newtable(L);
187         set_tool_capabilities(L, -1, prop);
188 }
189
190 void realitycheck(lua_State *L)
191 {
192         int top = lua_gettop(L);
193         if(top >= 30){
194                 dstream<<"Stack is over 30:"<<std::endl;
195                 stackDump(L, dstream);
196                 script_error(L, "Stack is over 30 (reality check)");
197         }
198 }
199
200 /*
201         PointedThing
202 */
203
204 void push_pointed_thing(lua_State *L, const PointedThing& pointed)
205 {
206         lua_newtable(L);
207         if(pointed.type == POINTEDTHING_NODE)
208         {
209                 lua_pushstring(L, "node");
210                 lua_setfield(L, -2, "type");
211                 push_v3s16(L, pointed.node_undersurface);
212                 lua_setfield(L, -2, "under");
213                 push_v3s16(L, pointed.node_abovesurface);
214                 lua_setfield(L, -2, "above");
215         }
216         else if(pointed.type == POINTEDTHING_OBJECT)
217         {
218                 lua_pushstring(L, "object");
219                 lua_setfield(L, -2, "type");
220                 objectref_get(L, pointed.object_id);
221                 lua_setfield(L, -2, "ref");
222         }
223         else
224         {
225                 lua_pushstring(L, "nothing");
226                 lua_setfield(L, -2, "type");
227         }
228 }
229
230 void stackDump(lua_State *L, std::ostream &o)
231 {
232   int i;
233   int top = lua_gettop(L);
234   for (i = 1; i <= top; i++) {  /* repeat for each level */
235         int t = lua_type(L, i);
236         switch (t) {
237
238           case LUA_TSTRING:  /* strings */
239                 o<<"\""<<lua_tostring(L, i)<<"\"";
240                 break;
241
242           case LUA_TBOOLEAN:  /* booleans */
243                 o<<(lua_toboolean(L, i) ? "true" : "false");
244                 break;
245
246           case LUA_TNUMBER:  /* numbers */ {
247                 char buf[10];
248                 snprintf(buf, 10, "%g", lua_tonumber(L, i));
249                 o<<buf;
250                 break; }
251
252           default:  /* other values */
253                 o<<lua_typename(L, t);
254                 break;
255
256         }
257         o<<" ";
258   }
259   o<<std::endl;
260 }
261
262 #if 0
263 // Dump stack top with the dump2 function
264 static void dump2(lua_State *L, const char *name)
265 {
266         // Dump object (debug)
267         lua_getglobal(L, "dump2");
268         luaL_checktype(L, -1, LUA_TFUNCTION);
269         lua_pushvalue(L, -2); // Get previous stack top as first parameter
270         lua_pushstring(L, name);
271         if(lua_pcall(L, 2, 0, 0))
272                 script_error(L, "error: %s", lua_tostring(L, -1));
273 }
274 #endif
275
276 bool string_to_enum(const EnumString *spec, int &result,
277                 const std::string &str)
278 {
279         const EnumString *esp = spec;
280         while(esp->str){
281                 if(str == std::string(esp->str)){
282                         result = esp->num;
283                         return true;
284                 }
285                 esp++;
286         }
287         return false;
288 }
289
290 /*bool enum_to_string(const EnumString *spec, std::string &result,
291                 int num)
292 {
293         const EnumString *esp = spec;
294         while(esp){
295                 if(num == esp->num){
296                         result = esp->str;
297                         return true;
298                 }
299                 esp++;
300         }
301         return false;
302 }*/
303
304 int getenumfield(lua_State *L, int table,
305                 const char *fieldname, const EnumString *spec, int default_)
306 {
307         int result = default_;
308         string_to_enum(spec, result,
309                         getstringfield_default(L, table, fieldname, ""));
310         return result;
311 }