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.
28 #include "cpp_api/s_base.h"
29 #include "lua_api/l_object.h"
30 #include "serverobject.h"
32 ScriptApiBase::ScriptApiBase() :
45 void ScriptApiBase::realityCheck()
47 int top = lua_gettop(m_luastack);
49 dstream<<"Stack is over 30:"<<std::endl;
51 scriptError("Stack is over 30 (reality check)");
55 void ScriptApiBase::scriptError(const char *fmt, ...)
60 vsnprintf(buf, 10000, fmt, argp);
62 //errorstream<<"SCRIPT ERROR: "<<buf;
63 throw LuaError(m_luastack, buf);
66 void ScriptApiBase::stackDump(std::ostream &o)
69 int top = lua_gettop(m_luastack);
70 for (i = 1; i <= top; i++) { /* repeat for each level */
71 int t = lua_type(m_luastack, i);
74 case LUA_TSTRING: /* strings */
75 o<<"\""<<lua_tostring(m_luastack, i)<<"\"";
78 case LUA_TBOOLEAN: /* booleans */
79 o<<(lua_toboolean(m_luastack, i) ? "true" : "false");
82 case LUA_TNUMBER: /* numbers */ {
84 snprintf(buf, 10, "%g", lua_tonumber(m_luastack, i));
88 default: /* other values */
89 o<<lua_typename(m_luastack, t);
98 // Push the list of callbacks (a lua table).
99 // Then push nargs arguments.
100 // Then call this function, which
101 // - runs the callbacks
102 // - removes the table and arguments from the lua stack
103 // - pushes the return value, computed depending on mode
104 void ScriptApiBase::runCallbacks(int nargs,RunCallbacksMode mode)
106 lua_State *L = getStack();
108 // Insert the return value into the lua stack, below the table
109 assert(lua_gettop(L) >= nargs + 1);
111 lua_insert(L, -(nargs + 1) - 1);
112 // Stack now looks like this:
113 // ... <return value = nil> <table> <arg#1> <arg#2> ... <arg#n>
115 int rv = lua_gettop(L) - nargs - 1;
119 luaL_checktype(L, table, LUA_TTABLE);
123 bool first_loop = true;
124 while(lua_next(L, table) != 0){
125 // key at index -2 and value at index -1
126 luaL_checktype(L, -1, LUA_TFUNCTION);
128 for(int i = 0; i < nargs; i++)
129 lua_pushvalue(L, arg+i);
130 if(lua_pcall(L, nargs, 1, 0))
131 scriptError("error: %s", lua_tostring(L, -1));
133 // Move return value to designated space in stack
136 // Result of first callback is always moved
140 // Otherwise, what happens depends on the mode
141 if(mode == RUN_CALLBACKS_MODE_FIRST)
143 else if(mode == RUN_CALLBACKS_MODE_LAST)
145 else if(mode == RUN_CALLBACKS_MODE_AND ||
146 mode == RUN_CALLBACKS_MODE_AND_SC){
147 if((bool)lua_toboolean(L, rv) == true &&
148 (bool)lua_toboolean(L, -1) == false)
153 else if(mode == RUN_CALLBACKS_MODE_OR ||
154 mode == RUN_CALLBACKS_MODE_OR_SC){
155 if((bool)lua_toboolean(L, rv) == false &&
156 (bool)lua_toboolean(L, -1) == true)
165 // Handle short circuit modes
166 if(mode == RUN_CALLBACKS_MODE_AND_SC &&
167 (bool)lua_toboolean(L, rv) == false)
169 else if(mode == RUN_CALLBACKS_MODE_OR_SC &&
170 (bool)lua_toboolean(L, rv) == true)
173 // value removed, keep key for next iteration
176 // Remove stuff from stack, leaving only the return value
179 // Fix return value in case no callbacks were called
181 if(mode == RUN_CALLBACKS_MODE_AND ||
182 mode == RUN_CALLBACKS_MODE_AND_SC){
184 lua_pushboolean(L, true);
186 else if(mode == RUN_CALLBACKS_MODE_OR ||
187 mode == RUN_CALLBACKS_MODE_OR_SC){
189 lua_pushboolean(L, false);
194 void ScriptApiBase::addObjectReference(ServerActiveObject *cobj)
196 SCRIPTAPI_PRECHECKHEADER
197 //infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
199 // Create object on stack
200 ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
201 int object = lua_gettop(L);
203 // Get minetest.object_refs table
204 lua_getglobal(L, "minetest");
205 lua_getfield(L, -1, "object_refs");
206 luaL_checktype(L, -1, LUA_TTABLE);
207 int objectstable = lua_gettop(L);
209 // object_refs[id] = object
210 lua_pushnumber(L, cobj->getId()); // Push id
211 lua_pushvalue(L, object); // Copy object to top of stack
212 lua_settable(L, objectstable);
215 void ScriptApiBase::removeObjectReference(ServerActiveObject *cobj)
217 SCRIPTAPI_PRECHECKHEADER
218 //infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
220 // Get minetest.object_refs table
221 lua_getglobal(L, "minetest");
222 lua_getfield(L, -1, "object_refs");
223 luaL_checktype(L, -1, LUA_TTABLE);
224 int objectstable = lua_gettop(L);
226 // Get object_refs[id]
227 lua_pushnumber(L, cobj->getId()); // Push id
228 lua_gettable(L, objectstable);
229 // Set object reference to NULL
230 ObjectRef::set_null(L);
231 lua_pop(L, 1); // pop object
233 // Set object_refs[id] = nil
234 lua_pushnumber(L, cobj->getId()); // Push id
236 lua_settable(L, objectstable);
239 // Creates a new anonymous reference if cobj=NULL or id=0
240 void ScriptApiBase::objectrefGetOrCreate(
241 ServerActiveObject *cobj)
243 lua_State *L = getStack();
245 if(cobj == NULL || cobj->getId() == 0){
246 ObjectRef::create(L, cobj);
248 objectrefGet(cobj->getId());
252 void ScriptApiBase::objectrefGet(u16 id)
254 lua_State *L = getStack();
256 // Get minetest.object_refs[i]
257 lua_getglobal(L, "minetest");
258 lua_getfield(L, -1, "object_refs");
259 luaL_checktype(L, -1, LUA_TTABLE);
260 lua_pushnumber(L, id);
262 lua_remove(L, -2); // object_refs
263 lua_remove(L, -2); // minetest