diff options
Diffstat (limited to 'src/script')
-rw-r--r-- | src/script/cpp_api/s_server.cpp | 66 | ||||
-rw-r--r-- | src/script/cpp_api/s_server.h | 6 | ||||
-rw-r--r-- | src/script/lua_api/l_server.cpp | 38 | ||||
-rw-r--r-- | src/script/lua_api/l_server.h | 2 |
4 files changed, 96 insertions, 16 deletions
diff --git a/src/script/cpp_api/s_server.cpp b/src/script/cpp_api/s_server.cpp index 96cb28b28..6ddb2630d 100644 --- a/src/script/cpp_api/s_server.cpp +++ b/src/script/cpp_api/s_server.cpp @@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "cpp_api/s_server.h" #include "cpp_api/s_internal.h" #include "common/c_converter.h" +#include "util/numeric.h" // myrand bool ScriptApiServer::getAuth(const std::string &playername, std::string *dst_password, @@ -196,3 +197,68 @@ std::string ScriptApiServer::formatChatMessage(const std::string &name, return ret; } + +u32 ScriptApiServer::allocateDynamicMediaCallback(int f_idx) +{ + lua_State *L = getStack(); + + if (f_idx < 0) + f_idx = lua_gettop(L) + f_idx + 1; + + lua_getglobal(L, "core"); + lua_getfield(L, -1, "dynamic_media_callbacks"); + luaL_checktype(L, -1, LUA_TTABLE); + + // Find a randomly generated token that doesn't exist yet + int tries = 100; + u32 token; + while (1) { + token = myrand(); + lua_rawgeti(L, -2, token); + bool is_free = lua_isnil(L, -1); + lua_pop(L, 1); + if (is_free) + break; + if (--tries < 0) + FATAL_ERROR("Ran out of callbacks IDs?!"); + } + + // core.dynamic_media_callbacks[token] = callback_func + lua_pushvalue(L, f_idx); + lua_rawseti(L, -2, token); + + lua_pop(L, 2); + + verbosestream << "allocateDynamicMediaCallback() = " << token << std::endl; + return token; +} + +void ScriptApiServer::freeDynamicMediaCallback(u32 token) +{ + lua_State *L = getStack(); + + verbosestream << "freeDynamicMediaCallback(" << token << ")" << std::endl; + + // core.dynamic_media_callbacks[token] = nil + lua_getglobal(L, "core"); + lua_getfield(L, -1, "dynamic_media_callbacks"); + luaL_checktype(L, -1, LUA_TTABLE); + lua_pushnil(L); + lua_rawseti(L, -2, token); + lua_pop(L, 2); +} + +void ScriptApiServer::on_dynamic_media_added(u32 token, const char *playername) +{ + SCRIPTAPI_PRECHECKHEADER + + int error_handler = PUSH_ERROR_HANDLER(L); + lua_getglobal(L, "core"); + lua_getfield(L, -1, "dynamic_media_callbacks"); + luaL_checktype(L, -1, LUA_TTABLE); + lua_rawgeti(L, -1, token); + luaL_checktype(L, -1, LUA_TFUNCTION); + + lua_pushstring(L, playername); + PCALL_RES(lua_pcall(L, 1, 0, error_handler)); +} diff --git a/src/script/cpp_api/s_server.h b/src/script/cpp_api/s_server.h index d8639cba7..c5c3d5596 100644 --- a/src/script/cpp_api/s_server.h +++ b/src/script/cpp_api/s_server.h @@ -49,6 +49,12 @@ public: const std::string &password); bool setPassword(const std::string &playername, const std::string &password); + + /* dynamic media handling */ + u32 allocateDynamicMediaCallback(int f_idx); + void freeDynamicMediaCallback(u32 token); + void on_dynamic_media_added(u32 token, const char *playername); + private: void getAuthHandler(); void readPrivileges(int index, std::set<std::string> &result); diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp index 9866e0bc8..473faaa14 100644 --- a/src/script/lua_api/l_server.cpp +++ b/src/script/lua_api/l_server.cpp @@ -453,29 +453,37 @@ int ModApiServer::l_sound_fade(lua_State *L) } // dynamic_add_media(filepath) -int ModApiServer::l_dynamic_add_media_raw(lua_State *L) +int ModApiServer::l_dynamic_add_media(lua_State *L) { NO_MAP_LOCK_REQUIRED; if (!getEnv(L)) throw LuaError("Dynamic media cannot be added before server has started up"); + Server *server = getServer(L); - std::string filepath = readParam<std::string>(L, 1); - CHECK_SECURE_PATH(L, filepath.c_str(), false); + std::string filepath; + std::string to_player; + bool ephemeral = false; - std::vector<RemotePlayer*> sent_to; - bool ok = getServer(L)->dynamicAddMedia(filepath, sent_to); - if (ok) { - // (see wrapper code in builtin) - lua_createtable(L, sent_to.size(), 0); - int i = 0; - for (RemotePlayer *player : sent_to) { - lua_pushstring(L, player->getName()); - lua_rawseti(L, -2, ++i); - } + if (lua_istable(L, 1)) { + getstringfield(L, 1, "filepath", filepath); + getstringfield(L, 1, "to_player", to_player); + getboolfield(L, 1, "ephemeral", ephemeral); } else { - lua_pushboolean(L, false); + filepath = readParam<std::string>(L, 1); } + if (filepath.empty()) + luaL_typerror(L, 1, "non-empty string"); + luaL_checktype(L, 2, LUA_TFUNCTION); + + CHECK_SECURE_PATH(L, filepath.c_str(), false); + + u32 token = server->getScriptIface()->allocateDynamicMediaCallback(2); + + bool ok = server->dynamicAddMedia(filepath, token, to_player, ephemeral); + if (!ok) + server->getScriptIface()->freeDynamicMediaCallback(token); + lua_pushboolean(L, ok); return 1; } @@ -519,7 +527,7 @@ void ModApiServer::Initialize(lua_State *L, int top) API_FCT(sound_play); API_FCT(sound_stop); API_FCT(sound_fade); - API_FCT(dynamic_add_media_raw); + API_FCT(dynamic_add_media); API_FCT(get_player_information); API_FCT(get_player_privs); diff --git a/src/script/lua_api/l_server.h b/src/script/lua_api/l_server.h index fb7a851f4..c688e494b 100644 --- a/src/script/lua_api/l_server.h +++ b/src/script/lua_api/l_server.h @@ -71,7 +71,7 @@ private: static int l_sound_fade(lua_State *L); // dynamic_add_media(filepath) - static int l_dynamic_add_media_raw(lua_State *L); + static int l_dynamic_add_media(lua_State *L); // get_player_privs(name, text) static int l_get_player_privs(lua_State *L); |