From ab433775777c4f5055bcf4d2a1cffc506c4f9961 Mon Sep 17 00:00:00 2001 From: sapier Date: Sat, 25 May 2013 00:51:02 +0200 Subject: Move scriptapi to separate folder (by sapier) On the lua side, notably minetest.env:() should now be replaced by minetest.(). The old way is and will stay supported for a long time. Also: Update and clean up lua_api.txt (by celeron55) Move EnvRef to lua and remove add_rat and add_firefly (by kahrl) Add separate src/util/CMakeLists.txt, other minor fixes (by kahrl) --- src/script/cpp_api/s_base.cpp | 264 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 264 insertions(+) create mode 100644 src/script/cpp_api/s_base.cpp (limited to 'src/script/cpp_api/s_base.cpp') diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp new file mode 100644 index 000000000..e2e586357 --- /dev/null +++ b/src/script/cpp_api/s_base.cpp @@ -0,0 +1,264 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#include + +extern "C" { +#include "lua.h" +#include "lauxlib.h" +} + +#include "cpp_api/s_base.h" +#include "lua_api/l_object.h" +#include "serverobject.h" + +ScriptApiBase::ScriptApiBase() : + m_luastackmutex(), +#ifdef LOCK_DEBUG + m_locked(false), +#endif + m_luastack(0), + m_server(0), + m_environment(0) +{ + +} + + +void ScriptApiBase::realityCheck() +{ + int top = lua_gettop(m_luastack); + if(top >= 30){ + dstream<<"Stack is over 30:"<= nargs + 1); + lua_pushnil(L); + lua_insert(L, -(nargs + 1) - 1); + // Stack now looks like this: + // ... ... + + int rv = lua_gettop(L) - nargs - 1; + int table = rv + 1; + int arg = table + 1; + + luaL_checktype(L, table, LUA_TTABLE); + + // Foreach + lua_pushnil(L); + bool first_loop = true; + while(lua_next(L, table) != 0){ + // key at index -2 and value at index -1 + luaL_checktype(L, -1, LUA_TFUNCTION); + // Call function + for(int i = 0; i < nargs; i++) + lua_pushvalue(L, arg+i); + if(lua_pcall(L, nargs, 1, 0)) + scriptError("error: %s", lua_tostring(L, -1)); + + // Move return value to designated space in stack + // Or pop it + if(first_loop){ + // Result of first callback is always moved + lua_replace(L, rv); + first_loop = false; + } else { + // Otherwise, what happens depends on the mode + if(mode == RUN_CALLBACKS_MODE_FIRST) + lua_pop(L, 1); + else if(mode == RUN_CALLBACKS_MODE_LAST) + lua_replace(L, rv); + else if(mode == RUN_CALLBACKS_MODE_AND || + mode == RUN_CALLBACKS_MODE_AND_SC){ + if((bool)lua_toboolean(L, rv) == true && + (bool)lua_toboolean(L, -1) == false) + lua_replace(L, rv); + else + lua_pop(L, 1); + } + else if(mode == RUN_CALLBACKS_MODE_OR || + mode == RUN_CALLBACKS_MODE_OR_SC){ + if((bool)lua_toboolean(L, rv) == false && + (bool)lua_toboolean(L, -1) == true) + lua_replace(L, rv); + else + lua_pop(L, 1); + } + else + assert(0); + } + + // Handle short circuit modes + if(mode == RUN_CALLBACKS_MODE_AND_SC && + (bool)lua_toboolean(L, rv) == false) + break; + else if(mode == RUN_CALLBACKS_MODE_OR_SC && + (bool)lua_toboolean(L, rv) == true) + break; + + // value removed, keep key for next iteration + } + + // Remove stuff from stack, leaving only the return value + lua_settop(L, rv); + + // Fix return value in case no callbacks were called + if(first_loop){ + if(mode == RUN_CALLBACKS_MODE_AND || + mode == RUN_CALLBACKS_MODE_AND_SC){ + lua_pop(L, 1); + lua_pushboolean(L, true); + } + else if(mode == RUN_CALLBACKS_MODE_OR || + mode == RUN_CALLBACKS_MODE_OR_SC){ + lua_pop(L, 1); + lua_pushboolean(L, false); + } + } +} + +void ScriptApiBase::addObjectReference(ServerActiveObject *cobj) +{ + SCRIPTAPI_PRECHECKHEADER + //infostream<<"scriptapi_add_object_reference: id="<getId()<getId()); // Push id + lua_pushvalue(L, object); // Copy object to top of stack + lua_settable(L, objectstable); +} + +void ScriptApiBase::removeObjectReference(ServerActiveObject *cobj) +{ + SCRIPTAPI_PRECHECKHEADER + //infostream<<"scriptapi_rm_object_reference: id="<getId()<getId()); // Push id + lua_gettable(L, objectstable); + // Set object reference to NULL + ObjectRef::set_null(L); + lua_pop(L, 1); // pop object + + // Set object_refs[id] = nil + lua_pushnumber(L, cobj->getId()); // Push id + lua_pushnil(L); + lua_settable(L, objectstable); +} + +// Creates a new anonymous reference if cobj=NULL or id=0 +void ScriptApiBase::objectrefGetOrCreate( + ServerActiveObject *cobj) +{ + lua_State *L = getStack(); + + if(cobj == NULL || cobj->getId() == 0){ + ObjectRef::create(L, cobj); + } else { + objectrefGet(cobj->getId()); + } +} + +void ScriptApiBase::objectrefGet(u16 id) +{ + lua_State *L = getStack(); + + // Get minetest.object_refs[i] + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "object_refs"); + luaL_checktype(L, -1, LUA_TTABLE); + lua_pushnumber(L, id); + lua_gettable(L, -2); + lua_remove(L, -2); // object_refs + lua_remove(L, -2); // minetest +} -- cgit v1.2.3