1 /* 2 Minetest 3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> 4 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. 9 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. 14 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. 18 */ 19 20 #pragma once 21 22 #include <iostream> 23 #include <string> 24 #include <thread> 25 #include <mutex> 26 #include <unordered_map> 27 #include "common/helper.h" 28 #include "util/basic_macros.h" 29 30 extern "C" { 31 #include <lua.h> 32 #include <lualib.h> 33 } 34 35 #include "irrlichttypes.h" 36 #include "common/c_types.h" 37 #include "common/c_internal.h" 38 #include "debug.h" 39 #include "config.h" 40 41 #define SCRIPTAPI_LOCK_DEBUG 42 #define SCRIPTAPI_DEBUG 43 44 // MUST be an invalid mod name so that mods can't 45 // use that name to bypass security! 46 #define BUILTIN_MOD_NAME "*builtin*" 47 48 #define PCALL_RES(RES) { \ 49 int result_ = (RES); \ 50 if (result_ != 0) { \ 51 scriptError(result_, __FUNCTION__); \ 52 } \ 53 } 54 55 #define runCallbacks(nargs, mode) \ 56 runCallbacksRaw((nargs), (mode), __FUNCTION__) 57 58 #define setOriginFromTable(index) \ 59 setOriginFromTableRaw(index, __FUNCTION__) 60 61 enum class ScriptingType: u8 { 62 Async, 63 Client, 64 MainMenu, 65 Server 66 }; 67 68 class Server; 69 #ifndef SERVER 70 class Client; 71 #endif 72 class IGameDef; 73 class Environment; 74 class GUIEngine; 75 class ServerActiveObject; 76 struct PlayerHPChangeReason; 77 78 class ScriptApiBase : protected LuaHelper { 79 public: 80 ScriptApiBase(ScriptingType type); 81 // fake constructor to allow script API classes (e.g ScriptApiEnv) to virtually inherit from this one. ScriptApiBase()82 ScriptApiBase() 83 { 84 FATAL_ERROR("ScriptApiBase created without ScriptingType!"); 85 } 86 virtual ~ScriptApiBase(); 87 DISABLE_CLASS_COPY(ScriptApiBase); 88 89 // These throw a ModError on failure 90 void loadMod(const std::string &script_path, const std::string &mod_name); 91 void loadScript(const std::string &script_path); 92 93 #ifndef SERVER 94 void loadModFromMemory(const std::string &mod_name); 95 #endif 96 97 void runCallbacksRaw(int nargs, 98 RunCallbacksMode mode, const char *fxn); 99 100 /* object */ 101 void addObjectReference(ServerActiveObject *cobj); 102 void removeObjectReference(ServerActiveObject *cobj); 103 getGameDef()104 IGameDef *getGameDef() { return m_gamedef; } 105 Server* getServer(); getType()106 ScriptingType getType() { return m_type; } 107 #ifndef SERVER 108 Client* getClient(); 109 #endif 110 getOrigin()111 std::string getOrigin() { return m_last_run_mod; } 112 void setOriginDirect(const char *origin); 113 void setOriginFromTableRaw(int index, const char *fxn); 114 115 void clientOpenLibs(lua_State *L); 116 117 protected: 118 friend class LuaABM; 119 friend class LuaLBM; 120 friend class InvRef; 121 friend class ObjectRef; 122 friend class NodeMetaRef; 123 friend class ModApiBase; 124 friend class ModApiEnvMod; 125 friend class LuaVoxelManip; 126 getStack()127 lua_State* getStack() 128 { return m_luastack; } 129 130 void realityCheck(); 131 void scriptError(int result, const char *fxn); 132 void stackDump(std::ostream &o); 133 setGameDef(IGameDef * gamedef)134 void setGameDef(IGameDef* gamedef) { m_gamedef = gamedef; } 135 getEnv()136 Environment* getEnv() { return m_environment; } setEnv(Environment * env)137 void setEnv(Environment* env) { m_environment = env; } 138 139 #ifndef SERVER getGuiEngine()140 GUIEngine* getGuiEngine() { return m_guiengine; } setGuiEngine(GUIEngine * guiengine)141 void setGuiEngine(GUIEngine* guiengine) { m_guiengine = guiengine; } 142 #endif 143 144 void objectrefGetOrCreate(lua_State *L, ServerActiveObject *cobj); 145 146 void pushPlayerHPChangeReason(lua_State *L, const PlayerHPChangeReason& reason); 147 148 std::recursive_mutex m_luastackmutex; 149 std::string m_last_run_mod; 150 bool m_secure = false; 151 #ifdef SCRIPTAPI_LOCK_DEBUG 152 int m_lock_recursion_count{}; 153 std::thread::id m_owning_thread; 154 #endif 155 156 private: 157 static int luaPanic(lua_State *L); 158 159 lua_State *m_luastack = nullptr; 160 161 IGameDef *m_gamedef = nullptr; 162 Environment *m_environment = nullptr; 163 #ifndef SERVER 164 GUIEngine *m_guiengine = nullptr; 165 #endif 166 ScriptingType m_type; 167 }; 168