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 "cpp_api/s_base.h"
21 #include "cpp_api/s_internal.h"
22 #include "lua_api/l_object.h"
23 #include "serverobject.h"
27 #include "util/string.h"
43 ModNameStorer(lua_State *L_, const std::string modname):
46 // Store current modname in registry
47 lua_pushstring(L, modname.c_str());
48 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
52 // Clear current modname in registry
54 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
58 static int loadScript_ErrorHandler(lua_State *L) {
59 lua_getfield(L, LUA_GLOBALSINDEX, "debug");
60 if (!lua_istable(L, -1)) {
64 lua_getfield(L, -1, "traceback");
65 if (!lua_isfunction(L, -1)) {
70 lua_pushinteger(L, 2);
80 ScriptApiBase::ScriptApiBase()
82 m_luastackmutex.Init();
84 #ifdef SCRIPTAPI_LOCK_DEBUG
88 m_luastack = luaL_newstate();
91 // Make the ScriptApiBase* accessible to ModApiBase
92 lua_pushlightuserdata(m_luastack, this);
93 lua_setfield(m_luastack, LUA_REGISTRYINDEX, "scriptapi");
100 ScriptApiBase::~ScriptApiBase()
102 lua_close(m_luastack);
105 bool ScriptApiBase::loadMod(const std::string &scriptpath,
106 const std::string &modname)
108 ModNameStorer modnamestorer(getStack(), modname);
110 if(!string_allowed(modname, MODNAME_ALLOWED_CHARS)){
111 errorstream<<"Error loading mod \""<<modname
112 <<"\": modname does not follow naming conventions: "
113 <<"Only chararacters [a-z0-9_] are allowed."<<std::endl;
117 bool success = false;
120 success = loadScript(scriptpath);
123 errorstream<<"Error loading mod \""<<modname
124 <<"\": "<<e.what()<<std::endl;
130 bool ScriptApiBase::loadScript(const std::string &scriptpath)
132 verbosestream<<"Loading and running script from "<<scriptpath<<std::endl;
134 lua_State *L = getStack();
136 lua_pushcfunction(L, loadScript_ErrorHandler);
137 int errorhandler = lua_gettop(L);
139 int ret = luaL_loadfile(L, scriptpath.c_str()) || lua_pcall(L, 0, 0, errorhandler);
141 errorstream<<"========== ERROR FROM LUA ==========="<<std::endl;
142 errorstream<<"Failed to load and run script from "<<std::endl;
143 errorstream<<scriptpath<<":"<<std::endl;
144 errorstream<<std::endl;
145 errorstream<<lua_tostring(L, -1)<<std::endl;
146 errorstream<<std::endl;
147 errorstream<<"=======END OF ERROR FROM LUA ========"<<std::endl;
148 lua_pop(L, 1); // Pop error message from stack
149 lua_pop(L, 1); // Pop the error handler from stack
152 lua_pop(L, 1); // Pop the error handler from stack
156 void ScriptApiBase::realityCheck()
158 int top = lua_gettop(m_luastack);
160 dstream<<"Stack is over 30:"<<std::endl;
162 scriptError("Stack is over 30 (reality check)");
166 void ScriptApiBase::scriptError(const char *fmt, ...)
171 vsnprintf(buf, 10000, fmt, argp);
173 //errorstream<<"SCRIPT ERROR: "<<buf;
174 throw LuaError(m_luastack, buf);
177 void ScriptApiBase::stackDump(std::ostream &o)
180 int top = lua_gettop(m_luastack);
181 for (i = 1; i <= top; i++) { /* repeat for each level */
182 int t = lua_type(m_luastack, i);
185 case LUA_TSTRING: /* strings */
186 o<<"\""<<lua_tostring(m_luastack, i)<<"\"";
189 case LUA_TBOOLEAN: /* booleans */
190 o<<(lua_toboolean(m_luastack, i) ? "true" : "false");
193 case LUA_TNUMBER: /* numbers */ {
195 snprintf(buf, 10, "%g", lua_tonumber(m_luastack, i));
199 default: /* other values */
200 o<<lua_typename(m_luastack, t);
209 void ScriptApiBase::addObjectReference(ServerActiveObject *cobj)
211 SCRIPTAPI_PRECHECKHEADER
212 //infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
214 // Create object on stack
215 ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
216 int object = lua_gettop(L);
218 // Get minetest.object_refs table
219 lua_getglobal(L, "minetest");
220 lua_getfield(L, -1, "object_refs");
221 luaL_checktype(L, -1, LUA_TTABLE);
222 int objectstable = lua_gettop(L);
224 // object_refs[id] = object
225 lua_pushnumber(L, cobj->getId()); // Push id
226 lua_pushvalue(L, object); // Copy object to top of stack
227 lua_settable(L, objectstable);
230 void ScriptApiBase::removeObjectReference(ServerActiveObject *cobj)
232 SCRIPTAPI_PRECHECKHEADER
233 //infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
235 // Get minetest.object_refs table
236 lua_getglobal(L, "minetest");
237 lua_getfield(L, -1, "object_refs");
238 luaL_checktype(L, -1, LUA_TTABLE);
239 int objectstable = lua_gettop(L);
241 // Get object_refs[id]
242 lua_pushnumber(L, cobj->getId()); // Push id
243 lua_gettable(L, objectstable);
244 // Set object reference to NULL
245 ObjectRef::set_null(L);
246 lua_pop(L, 1); // pop object
248 // Set object_refs[id] = nil
249 lua_pushnumber(L, cobj->getId()); // Push id
251 lua_settable(L, objectstable);
254 // Creates a new anonymous reference if cobj=NULL or id=0
255 void ScriptApiBase::objectrefGetOrCreate(
256 ServerActiveObject *cobj)
258 lua_State *L = getStack();
260 if(cobj == NULL || cobj->getId() == 0){
261 ObjectRef::create(L, cobj);
263 objectrefGet(cobj->getId());
267 void ScriptApiBase::objectrefGet(u16 id)
269 lua_State *L = getStack();
271 // Get minetest.object_refs[i]
272 lua_getglobal(L, "minetest");
273 lua_getfield(L, -1, "object_refs");
274 luaL_checktype(L, -1, LUA_TTABLE);
275 lua_pushnumber(L, id);
277 lua_remove(L, -2); // object_refs
278 lua_remove(L, -2); // minetest