From af69d4f7a96ec1627ea19ffd7f87489b428098ee Mon Sep 17 00:00:00 2001 From: sfan5 Date: Mon, 22 Jan 2024 20:37:26 +0100 Subject: [PATCH] Allow dynamic_add_media at mod load time --- .gitignore | 3 --- builtin/game/features.lua | 1 + doc/lua_api.md | 5 ++++ games/devtest/mods/testnodes/textures.lua | 16 +++++++++--- src/script/lua_api/l_server.cpp | 14 +++++++--- src/server.cpp | 32 ++++++++++++++--------- 6 files changed, 50 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index 5405a74e9..d996a0d4c 100644 --- a/.gitignore +++ b/.gitignore @@ -92,11 +92,8 @@ cmake_install.cmake CMakeCache.txt CPackConfig.cmake CPackSourceConfig.cmake -src/test_config.h src/cmake_config.h src/cmake_config_githash.h -src/unittest/test_world/world.mt -games/devtest/mods/testnodes/textures/testnodes_generated_*.png /locale/ .directory *.cbp diff --git a/builtin/game/features.lua b/builtin/game/features.lua index 510d0461f..d3f171680 100644 --- a/builtin/game/features.lua +++ b/builtin/game/features.lua @@ -35,6 +35,7 @@ core.features = { wallmounted_rotate = true, item_specific_pointabilities = true, blocking_pointability_type = true, + dynamic_add_media_startup = true, } function core.has_feature(arg) diff --git a/doc/lua_api.md b/doc/lua_api.md index 5a4bc059c..5e0393767 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -5304,6 +5304,8 @@ Utilities item_specific_pointabilities = true, -- Nodes `pointable` property can be `"blocking"` (5.9.0) blocking_pointability_type = true, + -- dynamic_add_media can be called at startup when leaving callback as `nil` (5.9.0) + dynamic_add_media_startup = true, } ``` @@ -6621,6 +6623,9 @@ Server name twice is not possible/guaranteed to work. An exception to this is the use of `to_player` to send the same, already existent file to multiple chosen players. + * You can also call this at startup time. In that case `callback` MUST + be `nil` and you cannot use `ephemeral` or `to_player`, as these logically + do not make sense. * Clients will attempt to fetch files added this way via remote media, this can make transfer of bigger files painless (if set up). Nevertheless it is advised not to use dynamic media for big media files. diff --git a/games/devtest/mods/testnodes/textures.lua b/games/devtest/mods/testnodes/textures.lua index 9ecf0cc12..cf88d4a7d 100644 --- a/games/devtest/mods/testnodes/textures.lua +++ b/games/devtest/mods/testnodes/textures.lua @@ -149,15 +149,25 @@ fractal = nil frac_emb = nil checker = nil -local textures_path = minetest.get_modpath( minetest.get_current_modname() ) .. "/textures/" -minetest.safe_file_write( +do + -- we used to write the textures to our mod folder. in order to avoid + -- duplicate errors delete them if they still exist. + local path = core.get_modpath(core.get_current_modname()) .. "/textures/" + os.remove(path .. "testnodes_generated_mb.png") + os.remove(path .. "testnodes_generated_ck.png") +end + +local textures_path = core.get_worldpath() .. "/" +core.safe_file_write( textures_path .. "testnodes_generated_mb.png", encode_and_check(512, 512, "rgb", data_mb) ) -minetest.safe_file_write( +core.safe_file_write( textures_path .. "testnodes_generated_ck.png", encode_and_check(512, 512, "gray", data_ck) ) +core.dynamic_add_media(textures_path .. "testnodes_generated_mb.png") +core.dynamic_add_media(textures_path .. "testnodes_generated_ck.png") minetest.register_node("testnodes:generated_png_mb", { description = S("Generated Mandelbrot PNG Test Node"), diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp index 21ec17617..f0e79cd62 100644 --- a/src/script/lua_api/l_server.cpp +++ b/src/script/lua_api/l_server.cpp @@ -545,9 +545,8 @@ 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); + const bool at_startup = !getEnv(L); std::string filepath; std::string to_player; @@ -562,7 +561,16 @@ int ModApiServer::l_dynamic_add_media(lua_State *L) } if (filepath.empty()) luaL_typerror(L, 1, "non-empty string"); - luaL_checktype(L, 2, LUA_TFUNCTION); + if (at_startup) { + if (!lua_isnoneornil(L, 2)) + throw LuaError("must be called without callback at load-time"); + // In order to keep edge cases to a minimum actually use an empty function. + int err = luaL_loadstring(L, ""); + SANITY_CHECK(err == 0); + lua_replace(L, 2); + } else { + luaL_checktype(L, 2, LUA_TFUNCTION); + } CHECK_SECURE_PATH(L, filepath.c_str(), false); diff --git a/src/server.cpp b/src/server.cpp index c1ea49e04..ef8922635 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -3582,6 +3582,13 @@ bool Server::dynamicAddMedia(std::string filepath, } } + if (!m_env && (!to_player.empty() || ephemeral)) { + errorstream << "Server::dynamicAddMedia(): " + "adding ephemeral or player-specific media at startup is nonsense" + << std::endl; + return false; + } + // Load the file and add it to our media cache std::string filedata, raw_hash; bool ok = addMediaFile(filename, filepath, &filedata, &raw_hash); @@ -3618,19 +3625,20 @@ bool Server::dynamicAddMedia(std::string filepath, m_media[filename].no_announce = true; } - // Push file to existing clients - NetworkPacket pkt(TOCLIENT_MEDIA_PUSH, 0); - pkt << raw_hash << filename << (bool)ephemeral; - - NetworkPacket legacy_pkt = pkt; - - // Newer clients get asked to fetch the file (asynchronous) - pkt << token; - // Older clients have an awful hack that just throws the data at them - legacy_pkt.putLongString(filedata); - std::unordered_set delivered, waiting; - { + + // Push file to existing clients + if (m_env) { + NetworkPacket pkt(TOCLIENT_MEDIA_PUSH, 0); + pkt << raw_hash << filename << static_cast(ephemeral); + + NetworkPacket legacy_pkt = pkt; + + // Newer clients get asked to fetch the file (asynchronous) + pkt << token; + // Older clients have an awful hack that just throws the data at them + legacy_pkt.putLongString(filedata); + ClientInterface::AutoLock clientlock(m_clients); for (auto &pair : m_clients.getClientList()) { if (pair.second->getState() == CS_DefinitionsSent && !ephemeral) {