diff options
author | Loïc Blot <nerzhul@users.noreply.github.com> | 2017-09-26 00:11:20 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-09-26 00:11:20 +0200 |
commit | 6f1c90720402415b62fb4d5e809ec7dbc1cd7f96 (patch) | |
tree | 6f94c2bbc2d343be50945a0074bc16da282a4bc1 /src/script | |
parent | 6df312a608912b3cb21d04532151e29e8b0c7301 (diff) | |
download | minetest-6f1c90720402415b62fb4d5e809ec7dbc1cd7f96.tar.gz minetest-6f1c90720402415b62fb4d5e809ec7dbc1cd7f96.tar.bz2 minetest-6f1c90720402415b62fb4d5e809ec7dbc1cd7f96.zip |
Implement mod communication channels (#6351)
Implement network communication for channels
* Implement ModChannel manager server side to route incoming messages from clients to other clients
* Add signal handler switch on client & ModChannelMgr on client to handle channels
* Add Lua API bindings + client packet sending + unittests
* Implement server message sending
* Add callback from received message handler to Lua API using registration method
Diffstat (limited to 'src/script')
-rw-r--r-- | src/script/cpp_api/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/script/cpp_api/s_modchannels.cpp | 50 | ||||
-rw-r--r-- | src/script/cpp_api/s_modchannels.h | 31 | ||||
-rw-r--r-- | src/script/lua_api/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/script/lua_api/l_modchannels.cpp | 161 | ||||
-rw-r--r-- | src/script/lua_api/l_modchannels.h | 66 | ||||
-rw-r--r-- | src/script/scripting_client.cpp | 3 | ||||
-rw-r--r-- | src/script/scripting_client.h | 4 | ||||
-rw-r--r-- | src/script/scripting_server.cpp | 3 | ||||
-rw-r--r-- | src/script/scripting_server.h | 2 |
10 files changed, 321 insertions, 1 deletions
diff --git a/src/script/cpp_api/CMakeLists.txt b/src/script/cpp_api/CMakeLists.txt index 4b13356a8..3cfd7709a 100644 --- a/src/script/cpp_api/CMakeLists.txt +++ b/src/script/cpp_api/CMakeLists.txt @@ -5,6 +5,7 @@ set(common_SCRIPT_CPP_API_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/s_env.cpp ${CMAKE_CURRENT_SOURCE_DIR}/s_inventory.cpp ${CMAKE_CURRENT_SOURCE_DIR}/s_item.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/s_modchannels.cpp ${CMAKE_CURRENT_SOURCE_DIR}/s_node.cpp ${CMAKE_CURRENT_SOURCE_DIR}/s_nodemeta.cpp ${CMAKE_CURRENT_SOURCE_DIR}/s_player.cpp diff --git a/src/script/cpp_api/s_modchannels.cpp b/src/script/cpp_api/s_modchannels.cpp new file mode 100644 index 000000000..caff3f05e --- /dev/null +++ b/src/script/cpp_api/s_modchannels.cpp @@ -0,0 +1,50 @@ +/* +Minetest +Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "s_modchannels.h" +#include "s_internal.h" + +void ScriptApiModChannels::on_modchannel_message(const std::string &channel, + const std::string &sender, const std::string &message) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get core.registered_on_generateds + lua_getglobal(L, "core"); + lua_getfield(L, -1, "registered_on_modchannel_message"); + // Call callbacks + lua_pushstring(L, channel.c_str()); + lua_pushstring(L, sender.c_str()); + lua_pushstring(L, message.c_str()); + runCallbacks(3, RUN_CALLBACKS_MODE_AND); +} + +void ScriptApiModChannels::on_modchannel_signal( + const std::string &channel, ModChannelSignal signal) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get core.registered_on_generateds + lua_getglobal(L, "core"); + lua_getfield(L, -1, "registered_on_modchannel_signal"); + // Call callbacks + lua_pushstring(L, channel.c_str()); + lua_pushinteger(L, (int)signal); + runCallbacks(2, RUN_CALLBACKS_MODE_AND); +} diff --git a/src/script/cpp_api/s_modchannels.h b/src/script/cpp_api/s_modchannels.h new file mode 100644 index 000000000..4de7a8291 --- /dev/null +++ b/src/script/cpp_api/s_modchannels.h @@ -0,0 +1,31 @@ +/* +Minetest +Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#pragma once + +#include "cpp_api/s_base.h" +#include "modchannels.h" + +class ScriptApiModChannels : virtual public ScriptApiBase +{ +public: + void on_modchannel_message(const std::string &channel, const std::string &sender, + const std::string &message); + void on_modchannel_signal(const std::string &channel, ModChannelSignal signal); +}; diff --git a/src/script/lua_api/CMakeLists.txt b/src/script/lua_api/CMakeLists.txt index 1a78580e6..55bbf934b 100644 --- a/src/script/lua_api/CMakeLists.txt +++ b/src/script/lua_api/CMakeLists.txt @@ -8,6 +8,7 @@ set(common_SCRIPT_LUA_API_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/l_itemstackmeta.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_mapgen.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_metadata.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/l_modchannels.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_nodemeta.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_nodetimer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_noise.cpp diff --git a/src/script/lua_api/l_modchannels.cpp b/src/script/lua_api/l_modchannels.cpp new file mode 100644 index 000000000..ac28e2ada --- /dev/null +++ b/src/script/lua_api/l_modchannels.cpp @@ -0,0 +1,161 @@ +/* +Minetest +Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include <cassert> +#include <log.h> +#include "lua_api/l_modchannels.h" +#include "l_internal.h" +#include "modchannels.h" + +int ModApiChannels::l_mod_channel_join(lua_State *L) +{ + if (!lua_isstring(L, 1)) + return 0; + + std::string channel = luaL_checkstring(L, 1); + if (channel.empty()) + return 0; + + getGameDef(L)->joinModChannel(channel); + ModChannel *channelObj = getGameDef(L)->getModChannel(channel); + assert(channelObj); + ModChannelRef::create(L, channelObj); + + int object = lua_gettop(L); + lua_pushvalue(L, object); + return 1; +} + +void ModApiChannels::Initialize(lua_State *L, int top) +{ + API_FCT(mod_channel_join); +} + +/* + * ModChannelRef + */ + +ModChannelRef::ModChannelRef(ModChannel *modchannel) : m_modchannel(modchannel) +{ +} + +int ModChannelRef::l_leave(lua_State *L) +{ + ModChannelRef *ref = checkobject(L, 1); + ModChannel *channel = getobject(ref); + if (!channel) + return 0; + + getGameDef(L)->leaveModChannel(channel->getName()); + // Channel left, invalidate the channel object ptr + // This permits to invalidate every object action from Lua because core removed + // channel consuming link + ref->m_modchannel = nullptr; + return 0; +} + +int ModChannelRef::l_send_all(lua_State *L) +{ + ModChannelRef *ref = checkobject(L, 1); + ModChannel *channel = getobject(ref); + if (!channel || !channel->canWrite()) + return 0; + + // @TODO serialize message + std::string message = luaL_checkstring(L, 2); + + getGameDef(L)->sendModChannelMessage(channel->getName(), message); + return 0; +} + +int ModChannelRef::l_is_writeable(lua_State *L) +{ + ModChannelRef *ref = checkobject(L, 1); + ModChannel *channel = getobject(ref); + if (!channel) + return 0; + + lua_pushboolean(L, channel->canWrite()); + return 1; +} +void ModChannelRef::Register(lua_State *L) +{ + lua_newtable(L); + int methodtable = lua_gettop(L); + luaL_newmetatable(L, className); + int metatable = lua_gettop(L); + + lua_pushliteral(L, "__metatable"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); // hide metatable from lua getmetatable() + + lua_pushliteral(L, "__index"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); + + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, gc_object); + lua_settable(L, metatable); + + lua_pop(L, 1); // Drop metatable + + luaL_openlib(L, 0, methods, 0); // fill methodtable + lua_pop(L, 1); // Drop methodtable +} + +void ModChannelRef::create(lua_State *L, ModChannel *channel) +{ + ModChannelRef *o = new ModChannelRef(channel); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); +} + +int ModChannelRef::gc_object(lua_State *L) +{ + ModChannelRef *o = *(ModChannelRef **)(lua_touserdata(L, 1)); + delete o; + return 0; +} + +ModChannelRef *ModChannelRef::checkobject(lua_State *L, int narg) +{ + luaL_checktype(L, narg, LUA_TUSERDATA); + + void *ud = luaL_checkudata(L, narg, className); + if (!ud) + luaL_typerror(L, narg, className); + + return *(ModChannelRef **)ud; // unbox pointer +} + +ModChannel *ModChannelRef::getobject(ModChannelRef *ref) +{ + return ref->m_modchannel; +} + +// clang-format off +const char ModChannelRef::className[] = "ModChannelRef"; +const luaL_Reg ModChannelRef::methods[] = { + luamethod(ModChannelRef, leave), + luamethod(ModChannelRef, is_writeable), + luamethod(ModChannelRef, send_all), + {0, 0}, +}; +// clang-format on diff --git a/src/script/lua_api/l_modchannels.h b/src/script/lua_api/l_modchannels.h new file mode 100644 index 000000000..dbbf11a05 --- /dev/null +++ b/src/script/lua_api/l_modchannels.h @@ -0,0 +1,66 @@ +/* +Minetest +Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#pragma once + +#include "lua_api/l_base.h" +#include "config.h" + +class ModChannel; + +class ModApiChannels : public ModApiBase +{ +private: + // mod_channel_join(name) + static int l_mod_channel_join(lua_State *L); + +public: + static void Initialize(lua_State *L, int top); +}; + +class ModChannelRef : public ModApiBase +{ +public: + ModChannelRef(ModChannel *modchannel); + ~ModChannelRef() = default; + + static void Register(lua_State *L); + static void create(lua_State *L, ModChannel *channel); + + // leave() + static int l_leave(lua_State *L); + + // send(message) + static int l_send_all(lua_State *L); + + // is_writeable() + static int l_is_writeable(lua_State *L); + +private: + // garbage collector + static int gc_object(lua_State *L); + + static ModChannelRef *checkobject(lua_State *L, int narg); + static ModChannel *getobject(ModChannelRef *ref); + + ModChannel *m_modchannel = nullptr; + + static const char className[]; + static const luaL_Reg methods[]; +}; diff --git a/src/script/scripting_client.cpp b/src/script/scripting_client.cpp index b121f3712..29836c47b 100644 --- a/src/script/scripting_client.cpp +++ b/src/script/scripting_client.cpp @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_client.h" #include "lua_api/l_env.h" #include "lua_api/l_minimap.h" +#include "lua_api/l_modchannels.h" #include "lua_api/l_storage.h" #include "lua_api/l_sound.h" #include "lua_api/l_util.h" @@ -72,11 +73,13 @@ void ClientScripting::InitializeModApi(lua_State *L, int top) NodeMetaRef::RegisterClient(L); LuaLocalPlayer::Register(L); LuaCamera::Register(L); + ModChannelRef::Register(L); ModApiUtil::InitializeClient(L, top); ModApiClient::Initialize(L, top); ModApiStorage::Initialize(L, top); ModApiEnvMod::InitializeClient(L, top); + ModApiChannels::Initialize(L, top); } void ClientScripting::on_client_ready(LocalPlayer *localplayer) diff --git a/src/script/scripting_client.h b/src/script/scripting_client.h index 721bb2b05..cfecfa165 100644 --- a/src/script/scripting_client.h +++ b/src/script/scripting_client.h @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "cpp_api/s_base.h" #include "cpp_api/s_client.h" +#include "cpp_api/s_modchannels.h" #include "cpp_api/s_security.h" class Client; @@ -30,7 +31,8 @@ class Camera; class ClientScripting: virtual public ScriptApiBase, public ScriptApiSecurity, - public ScriptApiClient + public ScriptApiClient, + public ScriptApiModChannels { public: ClientScripting(Client *client); diff --git a/src/script/scripting_server.cpp b/src/script/scripting_server.cpp index 01e8e2fb5..095216a74 100644 --- a/src/script/scripting_server.cpp +++ b/src/script/scripting_server.cpp @@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_item.h" #include "lua_api/l_itemstackmeta.h" #include "lua_api/l_mapgen.h" +#include "lua_api/l_modchannels.h" #include "lua_api/l_nodemeta.h" #include "lua_api/l_nodetimer.h" #include "lua_api/l_noise.h" @@ -100,6 +101,7 @@ void ServerScripting::InitializeModApi(lua_State *L, int top) ObjectRef::Register(L); LuaSettings::Register(L); StorageRef::Register(L); + ModChannelRef::Register(L); // Initialize mod api modules ModApiCraft::Initialize(L, top); @@ -113,6 +115,7 @@ void ServerScripting::InitializeModApi(lua_State *L, int top) ModApiUtil::Initialize(L, top); ModApiHttp::Initialize(L, top); ModApiStorage::Initialize(L, top); + ModApiChannels::Initialize(L, top); } void log_deprecated(const std::string &message) diff --git a/src/script/scripting_server.h b/src/script/scripting_server.h index b549a1bc9..88cea143c 100644 --- a/src/script/scripting_server.h +++ b/src/script/scripting_server.h @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "cpp_api/s_entity.h" #include "cpp_api/s_env.h" #include "cpp_api/s_inventory.h" +#include "cpp_api/s_modchannels.h" #include "cpp_api/s_node.h" #include "cpp_api/s_player.h" #include "cpp_api/s_server.h" @@ -36,6 +37,7 @@ class ServerScripting: public ScriptApiDetached, public ScriptApiEntity, public ScriptApiEnv, + public ScriptApiModChannels, public ScriptApiNode, public ScriptApiPlayer, public ScriptApiServer, |