1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

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
This commit is contained in:
Loïc Blot 2017-09-26 00:11:20 +02:00 committed by GitHub
parent 6df312a608
commit 6f1c907204
37 changed files with 1206 additions and 39 deletions

View file

@ -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

View file

@ -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);
}

View file

@ -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);
};

View file

@ -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

View file

@ -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

View file

@ -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[];
};

View file

@ -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)

View file

@ -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);

View file

@ -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)

View file

@ -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,