3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.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.
20 #include "scriptapi.h"
21 #include "scriptapi_common.h"
28 #include "scriptapi_types.h"
29 #include "scriptapi_object.h"
32 Server* get_server(lua_State *L)
34 // Get server from registry
35 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
36 Server *server = (Server*)lua_touserdata(L, -1);
41 ServerEnvironment* get_env(lua_State *L)
43 // Get environment from registry
44 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_env");
45 ServerEnvironment *env = (ServerEnvironment*)lua_touserdata(L, -1);
50 void warn_if_field_exists(lua_State *L, int table,
51 const char *fieldname, const std::string &message)
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<<"\": "
66 ToolCapabilities read_tool_capabilities(
67 lua_State *L, int table)
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);
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
88 if(getfloatfield(L, table_groupcap, "maxwear", maxwear)){
90 groupcap.uses = 1.0/maxwear;
93 infostream<<script_get_backtrace(L)<<std::endl;
94 infostream<<"WARNING: field \"maxwear\" is deprecated; "
95 <<"should replace with uses=1/maxwear"<<std::endl;
98 lua_getfield(L, table_groupcap, "times");
99 if(lua_istable(L, -1)){
100 int table_times = lua_gettop(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
112 // Insert groupcap into toolcap
113 toolcap.groupcaps[groupname] = groupcap;
115 // removes value, keeps key for next iteration
120 lua_getfield(L, table, "damage_groups");
121 if(lua_istable(L, -1)){
122 int table_damage_groups = lua_gettop(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
137 void set_tool_capabilities(lua_State *L, int table,
138 const ToolCapabilities &toolcap)
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
145 for(std::map<std::string, ToolGroupCap>::const_iterator
146 i = toolcap.groupcaps.begin(); i != toolcap.groupcaps.end(); i++){
147 // Create groupcap table
149 const std::string &name = i->first;
150 const ToolGroupCap &groupcap = i->second;
151 // Create subtable "times"
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);
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());
169 // Set groupcaps table
170 lua_setfield(L, -2, "groupcaps");
171 //Create damage_groups table
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());
180 lua_setfield(L, -2, "damage_groups");
183 void push_tool_capabilities(lua_State *L,
184 const ToolCapabilities &prop)
187 set_tool_capabilities(L, -1, prop);
190 void realitycheck(lua_State *L)
192 int top = lua_gettop(L);
194 dstream<<"Stack is over 30:"<<std::endl;
195 stackDump(L, dstream);
196 script_error(L, "Stack is over 30 (reality check)");
204 void push_pointed_thing(lua_State *L, const PointedThing& pointed)
207 if(pointed.type == POINTEDTHING_NODE)
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");
216 else if(pointed.type == POINTEDTHING_OBJECT)
218 lua_pushstring(L, "object");
219 lua_setfield(L, -2, "type");
220 objectref_get(L, pointed.object_id);
221 lua_setfield(L, -2, "ref");
225 lua_pushstring(L, "nothing");
226 lua_setfield(L, -2, "type");
230 void stackDump(lua_State *L, std::ostream &o)
233 int top = lua_gettop(L);
234 for (i = 1; i <= top; i++) { /* repeat for each level */
235 int t = lua_type(L, i);
238 case LUA_TSTRING: /* strings */
239 o<<"\""<<lua_tostring(L, i)<<"\"";
242 case LUA_TBOOLEAN: /* booleans */
243 o<<(lua_toboolean(L, i) ? "true" : "false");
246 case LUA_TNUMBER: /* numbers */ {
248 snprintf(buf, 10, "%g", lua_tonumber(L, i));
252 default: /* other values */
253 o<<lua_typename(L, t);
263 // Dump stack top with the dump2 function
264 static void dump2(lua_State *L, const char *name)
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));
276 bool string_to_enum(const EnumString *spec, int &result,
277 const std::string &str)
279 const EnumString *esp = spec;
281 if(str == std::string(esp->str)){
290 /*bool enum_to_string(const EnumString *spec, std::string &result,
293 const EnumString *esp = spec;
304 int getenumfield(lua_State *L, int table,
305 const char *fieldname, const EnumString *spec, int default_)
307 int result = default_;
308 string_to_enum(spec, result,
309 getstringfield_default(L, table, fieldname, ""));