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.
27 #include "scriptapi.h"
28 #include "common/c_converter.h"
29 #include "lua_api/l_base.h"
33 int script_ErrorHandler(lua_State *L) {
34 lua_getfield(L, LUA_GLOBALSINDEX, "debug");
35 if (!lua_istable(L, -1)) {
39 lua_getfield(L, -1, "traceback");
40 if (!lua_isfunction(L, -1)) {
45 lua_pushinteger(L, 2);
51 bool ScriptApi::getAuth(const std::string &playername,
52 std::string *dst_password, std::set<std::string> *dst_privs)
54 SCRIPTAPI_PRECHECKHEADER
57 lua_getfield(L, -1, "get_auth");
58 if(lua_type(L, -1) != LUA_TFUNCTION)
59 throw LuaError(L, "Authentication handler missing get_auth");
60 lua_pushstring(L, playername.c_str());
61 if(lua_pcall(L, 1, 1, 0))
62 scriptError("error: %s", lua_tostring(L, -1));
64 // nil = login not allowed
67 luaL_checktype(L, -1, LUA_TTABLE);
70 bool found = getstringfield(L, -1, "password", password);
72 throw LuaError(L, "Authentication handler didn't return password");
74 *dst_password = password;
76 lua_getfield(L, -1, "privileges");
77 if(!lua_istable(L, -1))
79 "Authentication handler didn't return privilege table");
81 readPrivileges(-1, *dst_privs);
87 void ScriptApi::getAuthHandler()
89 lua_State *L = getStack();
91 lua_getglobal(L, "minetest");
92 lua_getfield(L, -1, "registered_auth_handler");
95 lua_getfield(L, -1, "builtin_auth_handler");
97 if(lua_type(L, -1) != LUA_TTABLE)
98 throw LuaError(L, "Authentication handler table not valid");
101 void ScriptApi::readPrivileges(int index,std::set<std::string> &result)
103 lua_State *L = getStack();
109 while(lua_next(L, index) != 0){
110 // key at index -2 and value at index -1
111 std::string key = luaL_checkstring(L, -2);
112 bool value = lua_toboolean(L, -1);
115 // removes value, keeps key for next iteration
120 void ScriptApi::createAuth(const std::string &playername,
121 const std::string &password)
123 SCRIPTAPI_PRECHECKHEADER
126 lua_getfield(L, -1, "create_auth");
127 if(lua_type(L, -1) != LUA_TFUNCTION)
128 throw LuaError(L, "Authentication handler missing create_auth");
129 lua_pushstring(L, playername.c_str());
130 lua_pushstring(L, password.c_str());
131 if(lua_pcall(L, 2, 0, 0))
132 scriptError("error: %s", lua_tostring(L, -1));
135 bool ScriptApi::setPassword(const std::string &playername,
136 const std::string &password)
138 SCRIPTAPI_PRECHECKHEADER
141 lua_getfield(L, -1, "set_password");
142 if(lua_type(L, -1) != LUA_TFUNCTION)
143 throw LuaError(L, "Authentication handler missing set_password");
144 lua_pushstring(L, playername.c_str());
145 lua_pushstring(L, password.c_str());
146 if(lua_pcall(L, 2, 1, 0))
147 scriptError("error: %s", lua_tostring(L, -1));
148 return lua_toboolean(L, -1);
151 bool ScriptApi::on_chat_message(const std::string &name,
152 const std::string &message)
154 SCRIPTAPI_PRECHECKHEADER
156 // Get minetest.registered_on_chat_messages
157 lua_getglobal(L, "minetest");
158 lua_getfield(L, -1, "registered_on_chat_messages");
160 lua_pushstring(L, name.c_str());
161 lua_pushstring(L, message.c_str());
162 runCallbacks(2, RUN_CALLBACKS_MODE_OR_SC);
163 bool ate = lua_toboolean(L, -1);
167 void ScriptApi::on_shutdown()
169 SCRIPTAPI_PRECHECKHEADER
171 // Get registered shutdown hooks
172 lua_getglobal(L, "minetest");
173 lua_getfield(L, -1, "registered_on_shutdown");
175 runCallbacks(0, RUN_CALLBACKS_MODE_FIRST);
178 bool ScriptApi::loadMod(const std::string &scriptpath,const std::string &modname)
180 ModNameStorer modnamestorer(getStack(), modname);
182 if(!string_allowed(modname, MODNAME_ALLOWED_CHARS)){
183 errorstream<<"Error loading mod \""<<modname
184 <<"\": modname does not follow naming conventions: "
185 <<"Only chararacters [a-z0-9_] are allowed."<<std::endl;
189 bool success = false;
192 success = scriptLoad(scriptpath.c_str());
195 errorstream<<"Error loading mod \""<<modname
196 <<"\": "<<e.what()<<std::endl;
202 ScriptApi::ScriptApi() {
203 assert("Invalid call to default constructor of scriptapi!" == 0);
206 ScriptApi::ScriptApi(Server* server)
210 setStack(luaL_newstate());
215 luaL_openlibs(getStack());
217 SCRIPTAPI_PRECHECKHEADER
219 lua_pushlightuserdata(L, this);
220 lua_setfield(L, LUA_REGISTRYINDEX, "scriptapi");
223 lua_setglobal(L, "minetest");
226 for (std::vector<ModApiBase*>::iterator i = m_mod_api_modules->begin();
227 i != m_mod_api_modules->end(); i++) {
228 //initializers are called within minetest global table!
229 lua_getglobal(L, "minetest");
230 int top = lua_gettop(L);
231 bool ModInitializedSuccessfull = (*i)->Initialize(L,top);
232 assert(ModInitializedSuccessfull);
235 infostream << "SCRIPTAPI: initialized " << m_mod_api_modules->size()
236 << " modules" << std::endl;
238 // Get the main minetest table
239 lua_getglobal(L, "minetest");
241 // Add tables to minetest
243 lua_setfield(L, -2, "object_refs");
246 lua_setfield(L, -2, "luaentities");
249 ScriptApi::~ScriptApi() {
250 lua_close(getStack());
253 bool ScriptApi::scriptLoad(const char *path)
255 lua_State* L = getStack();
258 verbosestream<<"Loading and running script from "<<path<<std::endl;
260 lua_pushcfunction(L, script_ErrorHandler);
261 int errorhandler = lua_gettop(L);
263 int ret = luaL_loadfile(L, path) || lua_pcall(L, 0, 0, errorhandler);
265 errorstream<<"========== ERROR FROM LUA ==========="<<std::endl;
266 errorstream<<"Failed to load and run script from "<<std::endl;
267 errorstream<<path<<":"<<std::endl;
268 errorstream<<std::endl;
269 errorstream<<lua_tostring(L, -1)<<std::endl;
270 errorstream<<std::endl;
271 errorstream<<"=======END OF ERROR FROM LUA ========"<<std::endl;
272 lua_pop(L, 1); // Pop error message from stack
273 lua_pop(L, 1); // Pop the error handler from stack
276 lua_pop(L, 1); // Pop the error handler from stack
280 bool ScriptApi::registerModApiModule(ModApiBase* ptr) {
281 if (ScriptApi::m_mod_api_modules == 0)
282 ScriptApi::m_mod_api_modules = new std::vector<ModApiBase*>();
284 assert(ScriptApi::m_mod_api_modules != 0);
286 ScriptApi::m_mod_api_modules->push_back(ptr);
291 std::vector<ModApiBase*>* ScriptApi::m_mod_api_modules = 0;