diff options
Diffstat (limited to 'src/script/cpp_api')
-rw-r--r-- | src/script/cpp_api/s_async.cpp | 29 | ||||
-rw-r--r-- | src/script/cpp_api/s_async.h | 6 | ||||
-rw-r--r-- | src/script/cpp_api/s_base.cpp | 20 | ||||
-rw-r--r-- | src/script/cpp_api/s_base.h | 5 | ||||
-rw-r--r-- | src/script/cpp_api/s_client.cpp | 87 | ||||
-rw-r--r-- | src/script/cpp_api/s_client.h | 5 | ||||
-rw-r--r-- | src/script/cpp_api/s_node.cpp | 20 | ||||
-rw-r--r-- | src/script/cpp_api/s_node.h | 1 | ||||
-rw-r--r-- | src/script/cpp_api/s_player.cpp | 13 | ||||
-rw-r--r-- | src/script/cpp_api/s_player.h | 1 | ||||
-rw-r--r-- | src/script/cpp_api/s_security.cpp | 44 |
11 files changed, 175 insertions, 56 deletions
diff --git a/src/script/cpp_api/s_async.cpp b/src/script/cpp_api/s_async.cpp index 5f1f9297e..0619b32c0 100644 --- a/src/script/cpp_api/s_async.cpp +++ b/src/script/cpp_api/s_async.cpp @@ -158,35 +158,6 @@ void AsyncEngine::step(lua_State *L) } /******************************************************************************/ -void AsyncEngine::pushFinishedJobs(lua_State* L) { - // Result Table - MutexAutoLock l(resultQueueMutex); - - unsigned int index = 1; - lua_createtable(L, resultQueue.size(), 0); - int top = lua_gettop(L); - - while (!resultQueue.empty()) { - LuaJobInfo jobDone = resultQueue.front(); - resultQueue.pop_front(); - - lua_createtable(L, 0, 2); // Pre-allocate space for two map fields - int top_lvl2 = lua_gettop(L); - - lua_pushstring(L, "jobid"); - lua_pushnumber(L, jobDone.id); - lua_settable(L, top_lvl2); - - lua_pushstring(L, "retval"); - lua_pushlstring(L, jobDone.serializedResult.data(), - jobDone.serializedResult.size()); - lua_settable(L, top_lvl2); - - lua_rawseti(L, top, index++); - } -} - -/******************************************************************************/ void AsyncEngine::prepareEnvironment(lua_State* L, int top) { for (StateInitializer &stateInitializer : stateInitializers) { diff --git a/src/script/cpp_api/s_async.h b/src/script/cpp_api/s_async.h index b1f4bf45f..99a4f891c 100644 --- a/src/script/cpp_api/s_async.h +++ b/src/script/cpp_api/s_async.h @@ -98,12 +98,6 @@ public: */ void step(lua_State *L); - /** - * Push a list of finished jobs onto the stack - * @param L The Lua stack - */ - void pushFinishedJobs(lua_State *L); - protected: /** * Get a Job from queue to be processed diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp index 1d62d8b65..5711ccbfd 100644 --- a/src/script/cpp_api/s_base.cpp +++ b/src/script/cpp_api/s_base.cpp @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "cpp_api/s_internal.h" #include "cpp_api/s_security.h" #include "lua_api/l_object.h" +#include "lua_api/l_clientobject.h" #include "common/c_converter.h" #include "server/player_sao.h" #include "filesys.h" @@ -354,13 +355,18 @@ void ScriptApiBase::setOriginFromTableRaw(int index, const char *fxn) * since we lose control over the ref and the contained pointer. */ -void ScriptApiBase::addObjectReference(ServerActiveObject *cobj) +void ScriptApiBase::addObjectReference(ActiveObject *cobj) { SCRIPTAPI_PRECHECKHEADER //infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl; // Create object on stack - ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack +#ifndef SERVER + if (m_type == ScriptingType::Client) + ClientObjectRef::create(L, dynamic_cast<ClientActiveObject *>(cobj)); + else +#endif + ObjectRef::create(L, dynamic_cast<ServerActiveObject *>(cobj)); // Puts ObjectRef (as userdata) on stack int object = lua_gettop(L); // Get core.object_refs table @@ -375,7 +381,7 @@ void ScriptApiBase::addObjectReference(ServerActiveObject *cobj) lua_settable(L, objectstable); } -void ScriptApiBase::removeObjectReference(ServerActiveObject *cobj) +void ScriptApiBase::removeObjectReference(ActiveObject *cobj) { SCRIPTAPI_PRECHECKHEADER //infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl; @@ -390,7 +396,12 @@ void ScriptApiBase::removeObjectReference(ServerActiveObject *cobj) lua_pushnumber(L, cobj->getId()); // Push id lua_gettable(L, objectstable); // Set object reference to NULL - ObjectRef::set_null(L); +#ifndef SERVER + if (m_type == ScriptingType::Client) + ClientObjectRef::set_null(L); + else +#endif + ObjectRef::set_null(L); lua_pop(L, 1); // pop object // Set object_refs[id] = nil @@ -413,7 +424,6 @@ void ScriptApiBase::objectrefGetOrCreate(lua_State *L, << ", this is probably a bug." << std::endl; } } - void ScriptApiBase::pushPlayerHPChangeReason(lua_State *L, const PlayerHPChangeReason &reason) { if (reason.hasLuaReference()) diff --git a/src/script/cpp_api/s_base.h b/src/script/cpp_api/s_base.h index 36331ad37..a7a2c7203 100644 --- a/src/script/cpp_api/s_base.h +++ b/src/script/cpp_api/s_base.h @@ -73,6 +73,7 @@ class Game; class IGameDef; class Environment; class GUIEngine; +class ActiveObject; class ServerActiveObject; struct PlayerHPChangeReason; @@ -99,8 +100,8 @@ public: RunCallbacksMode mode, const char *fxn); /* object */ - void addObjectReference(ServerActiveObject *cobj); - void removeObjectReference(ServerActiveObject *cobj); + void addObjectReference(ActiveObject *cobj); + void removeObjectReference(ActiveObject *cobj); IGameDef *getGameDef() { return m_gamedef; } Server* getServer(); diff --git a/src/script/cpp_api/s_client.cpp b/src/script/cpp_api/s_client.cpp index b90decfb5..b0e7a073e 100644 --- a/src/script/cpp_api/s_client.cpp +++ b/src/script/cpp_api/s_client.cpp @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client/client.h" #include "common/c_converter.h" #include "common/c_content.h" +#include "lua_api/l_clientobject.h" #include "s_item.h" void ScriptApiClient::on_mods_loaded() @@ -176,7 +177,7 @@ bool ScriptApiClient::on_punchnode(v3s16 p, MapNode node) const NodeDefManager *ndef = getClient()->ndef(); - // Get core.registered_on_punchgnode + // Get core.registered_on_punchnode lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_on_punchnode"); @@ -260,7 +261,7 @@ bool ScriptApiClient::on_spawn_particle(struct ParticleParameters param) SCRIPTAPI_PRECHECKHEADER // Get core.registered_on_play_sound - + lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_on_spawn_particle"); @@ -285,13 +286,58 @@ bool ScriptApiClient::on_spawn_particle(struct ParticleParameters param) pushnode(L, param.node, getGameDef()->ndef()); lua_setfield(L, -2, "node"); } - setintfield(L, -1, "node_tile", param.node_tile); - + setintfield(L, -1, "node_tile", param.node_tile); + // Call functions runCallbacks(1, RUN_CALLBACKS_MODE_OR); return readParam<bool>(L, -1); } +void ScriptApiClient::on_object_properties_change(s16 id) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get core.registered_on_object_properties_change + lua_getglobal(L, "core"); + lua_getfield(L, -1, "registered_on_object_properties_change"); + + // Push data + push_objectRef(L, id); + + // Call functions + runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); +} + +void ScriptApiClient::on_object_hp_change(s16 id) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get core.registered_on_object_hp_change + lua_getglobal(L, "core"); + lua_getfield(L, -1, "registered_on_object_hp_change"); + + // Push data + push_objectRef(L, id); + + // Call functions + runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); +} + +void ScriptApiClient::on_object_add(s16 id) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get core.registered_on_object_add + lua_getglobal(L, "core"); + lua_getfield(L, -1, "registered_on_object_add"); + + // Push data + push_objectRef(L, id); + + // Call functions + runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); +} + bool ScriptApiClient::on_inventory_open(Inventory *inventory) { SCRIPTAPI_PRECHECKHEADER @@ -308,24 +354,45 @@ bool ScriptApiClient::on_inventory_open(Inventory *inventory) void ScriptApiClient::open_enderchest() { SCRIPTAPI_PRECHECKHEADER - + PUSH_ERROR_HANDLER(L); int error_handler = lua_gettop(L) - 1; lua_insert(L, error_handler); - + lua_getglobal(L, "core"); lua_getfield(L, -1, "open_enderchest"); if (lua_isfunction(L, -1)) lua_pcall(L, 0, 0, error_handler); } +v3f ScriptApiClient::get_send_speed(v3f speed) +{ + SCRIPTAPI_PRECHECKHEADER + + PUSH_ERROR_HANDLER(L); + int error_handler = lua_gettop(L) - 1; + lua_insert(L, error_handler); + + lua_getglobal(L, "core"); + lua_getfield(L, -1, "get_send_speed"); + if (lua_isfunction(L, -1)) { + speed /= BS; + push_v3f(L, speed); + lua_pcall(L, 1, 1, error_handler); + speed = read_v3f(L, -1); + speed *= BS; + } + + return speed; +} + void ScriptApiClient::set_node_def(const ContentFeatures &f) { SCRIPTAPI_PRECHECKHEADER - + lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_nodes"); - + push_content_features(L, f); lua_setfield(L, -2, f.name.c_str()); } @@ -333,10 +400,10 @@ void ScriptApiClient::set_node_def(const ContentFeatures &f) void ScriptApiClient::set_item_def(const ItemDefinition &i) { SCRIPTAPI_PRECHECKHEADER - + lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_items"); - + push_item_definition(L, i); lua_setfield(L, -2, i.name.c_str()); } diff --git a/src/script/cpp_api/s_client.h b/src/script/cpp_api/s_client.h index 9f68a14fc..2f9ce7aa3 100644 --- a/src/script/cpp_api/s_client.h +++ b/src/script/cpp_api/s_client.h @@ -63,10 +63,15 @@ public: bool new_move); bool on_play_sound(SimpleSoundSpec spec); bool on_spawn_particle(struct ParticleParameters param); + void on_object_properties_change(s16 id); + void on_object_hp_change(s16 id); + void on_object_add(s16 id); bool on_inventory_open(Inventory *inventory); void open_enderchest(); + v3f get_send_speed(v3f speed); + void set_node_def(const ContentFeatures &f); void set_item_def(const ItemDefinition &i); diff --git a/src/script/cpp_api/s_node.cpp b/src/script/cpp_api/s_node.cpp index e0f9bcd78..029cb6308 100644 --- a/src/script/cpp_api/s_node.cpp +++ b/src/script/cpp_api/s_node.cpp @@ -65,6 +65,7 @@ struct EnumString ScriptApiNode::es_ContentParamType2[] = {CPT2_COLORED_FACEDIR, "colorfacedir"}, {CPT2_COLORED_WALLMOUNTED, "colorwallmounted"}, {CPT2_GLASSLIKE_LIQUID_LEVEL, "glasslikeliquidlevel"}, + {CPT2_COLORED_DEGROTATE, "colordegrotate"}, {0, NULL}, }; @@ -93,6 +94,14 @@ struct EnumString ScriptApiNode::es_NodeBoxType[] = {0, NULL}, }; +struct EnumString ScriptApiNode::es_TextureAlphaMode[] = + { + {ALPHAMODE_OPAQUE, "opaque"}, + {ALPHAMODE_CLIP, "clip"}, + {ALPHAMODE_BLEND, "blend"}, + {0, NULL}, + }; + bool ScriptApiNode::node_on_punch(v3s16 p, MapNode node, ServerActiveObject *puncher, const PointedThing &pointed) { @@ -133,9 +142,14 @@ bool ScriptApiNode::node_on_dig(v3s16 p, MapNode node, push_v3s16(L, p); pushnode(L, node, ndef); objectrefGetOrCreate(L, digger); - PCALL_RES(lua_pcall(L, 3, 0, error_handler)); - lua_pop(L, 1); // Pop error handler - return true; + PCALL_RES(lua_pcall(L, 3, 1, error_handler)); + + // nil is treated as true for backwards compat + bool result = lua_isnil(L, -1) || lua_toboolean(L, -1); + + lua_pop(L, 2); // Pop error handler and result + + return result; } void ScriptApiNode::node_on_construct(v3s16 p, MapNode node) diff --git a/src/script/cpp_api/s_node.h b/src/script/cpp_api/s_node.h index 81b44f0f0..3f771c838 100644 --- a/src/script/cpp_api/s_node.h +++ b/src/script/cpp_api/s_node.h @@ -54,4 +54,5 @@ public: static struct EnumString es_ContentParamType2[]; static struct EnumString es_LiquidType[]; static struct EnumString es_NodeBoxType[]; + static struct EnumString es_TextureAlphaMode[]; }; diff --git a/src/script/cpp_api/s_player.cpp b/src/script/cpp_api/s_player.cpp index 712120c61..d3e6138dc 100644 --- a/src/script/cpp_api/s_player.cpp +++ b/src/script/cpp_api/s_player.cpp @@ -77,6 +77,19 @@ bool ScriptApiPlayer::on_punchplayer(ServerActiveObject *player, return readParam<bool>(L, -1); } +void ScriptApiPlayer::on_rightclickplayer(ServerActiveObject *player, + ServerActiveObject *clicker) +{ + SCRIPTAPI_PRECHECKHEADER + // Get core.registered_on_rightclickplayers + lua_getglobal(L, "core"); + lua_getfield(L, -1, "registered_on_rightclickplayers"); + // Call callbacks + objectrefGetOrCreate(L, player); + objectrefGetOrCreate(L, clicker); + runCallbacks(2, RUN_CALLBACKS_MODE_FIRST); +} + s32 ScriptApiPlayer::on_player_hpchange(ServerActiveObject *player, s32 hp_change, const PlayerHPChangeReason &reason) { diff --git a/src/script/cpp_api/s_player.h b/src/script/cpp_api/s_player.h index a337f975b..c0f141862 100644 --- a/src/script/cpp_api/s_player.h +++ b/src/script/cpp_api/s_player.h @@ -47,6 +47,7 @@ public: bool on_punchplayer(ServerActiveObject *player, ServerActiveObject *hitter, float time_from_last_punch, const ToolCapabilities *toolcap, v3f dir, s16 damage); + void on_rightclickplayer(ServerActiveObject *player, ServerActiveObject *clicker); s32 on_player_hpchange(ServerActiveObject *player, s32 hp_change, const PlayerHPChangeReason &reason); void on_playerReceiveFields(ServerActiveObject *player, diff --git a/src/script/cpp_api/s_security.cpp b/src/script/cpp_api/s_security.cpp index 37c5b61dc..8fe5d2c5a 100644 --- a/src/script/cpp_api/s_security.cpp +++ b/src/script/cpp_api/s_security.cpp @@ -45,6 +45,21 @@ static inline void copy_safe(lua_State *L, const char *list[], unsigned len, int } } +static void shallow_copy_table(lua_State *L, int from=-2, int to=-1) +{ + if (from < 0) from = lua_gettop(L) + from + 1; + if (to < 0) to = lua_gettop(L) + to + 1; + lua_pushnil(L); + while (lua_next(L, from) != 0) { + assert(lua_type(L, -1) != LUA_TTABLE); + // duplicate key and value for lua_rawset + lua_pushvalue(L, -2); + lua_pushvalue(L, -2); + lua_rawset(L, to); + lua_pop(L, 1); + } +} + // Pushes the original version of a library function on the stack, from the old version static inline void push_original(lua_State *L, const char *lib, const char *func) { @@ -83,7 +98,10 @@ void ScriptApiSecurity::initializeSecurity() "unpack", "_VERSION", "xpcall", - // Completely safe libraries + }; + static const char *whitelist_tables[] = { + // These libraries are completely safe BUT we need to duplicate their table + // to ensure the sandbox can't affect the insecure env "coroutine", "string", "table", @@ -168,6 +186,17 @@ void ScriptApiSecurity::initializeSecurity() lua_pop(L, 1); + // Copy safe libraries + for (const char *libname : whitelist_tables) { + lua_getfield(L, old_globals, libname); + lua_newtable(L); + shallow_copy_table(L); + + lua_setglobal(L, libname); + lua_pop(L, 1); + } + + // Copy safe IO functions lua_getfield(L, old_globals, "io"); lua_newtable(L); @@ -223,6 +252,19 @@ void ScriptApiSecurity::initializeSecurity() #endif lua_pop(L, 1); // Pop globals_backup + + + /* + * In addition to copying the tables in whitelist_tables, we also need to + * replace the string metatable. Otherwise old_globals.string would + * be accessible via getmetatable("").__index from inside the sandbox. + */ + lua_pushliteral(L, ""); + lua_newtable(L); + lua_getglobal(L, "string"); + lua_setfield(L, -2, "__index"); + lua_setmetatable(L, -2); + lua_pop(L, 1); // Pop empty string } void ScriptApiSecurity::initializeSecurityClient() |