| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,152 @@ | ||
| /* | ||
| 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 "modchannels.h" | ||
| #include <algorithm> | ||
| #include <cassert> | ||
| #include "util/basic_macros.h" | ||
|
|
||
| bool ModChannel::registerConsumer(u16 peer_id) | ||
| { | ||
|
|
||
| // ignore if peer_id already joined | ||
| if (CONTAINS(m_client_consumers, peer_id)) | ||
| return false; | ||
|
|
||
| m_client_consumers.push_back(peer_id); | ||
| return true; | ||
| } | ||
|
|
||
| bool ModChannel::removeConsumer(u16 peer_id) | ||
| { | ||
| bool found = false; | ||
| auto peer_removal_fct = [peer_id, &found](u16 p) { | ||
| if (p == peer_id) | ||
| found = true; | ||
|
|
||
| return p == peer_id; | ||
| }; | ||
|
|
||
| m_client_consumers.erase( | ||
| std::remove_if(m_client_consumers.begin(), | ||
| m_client_consumers.end(), peer_removal_fct), | ||
| m_client_consumers.end()); | ||
|
|
||
| return found; | ||
| } | ||
|
|
||
| bool ModChannel::canWrite() const | ||
| { | ||
| return m_state == MODCHANNEL_STATE_READ_WRITE; | ||
| } | ||
|
|
||
| void ModChannel::setState(ModChannelState state) | ||
| { | ||
| assert(state != MODCHANNEL_STATE_INIT); | ||
|
|
||
| m_state = state; | ||
| } | ||
|
|
||
| bool ModChannelMgr::channelRegistered(const std::string &channel) const | ||
| { | ||
| return m_registered_channels.find(channel) != m_registered_channels.end(); | ||
| } | ||
|
|
||
| ModChannel *ModChannelMgr::getModChannel(const std::string &channel) | ||
| { | ||
| if (!channelRegistered(channel)) | ||
| return nullptr; | ||
|
|
||
| return m_registered_channels[channel].get(); | ||
| } | ||
|
|
||
| bool ModChannelMgr::canWriteOnChannel(const std::string &channel) const | ||
| { | ||
| const auto channel_it = m_registered_channels.find(channel); | ||
| if (channel_it == m_registered_channels.end()) { | ||
| return false; | ||
| } | ||
|
|
||
| return channel_it->second->canWrite(); | ||
| } | ||
|
|
||
| void ModChannelMgr::registerChannel(const std::string &channel) | ||
| { | ||
| m_registered_channels[channel] = | ||
| std::unique_ptr<ModChannel>(new ModChannel(channel)); | ||
| } | ||
|
|
||
| bool ModChannelMgr::setChannelState(const std::string &channel, ModChannelState state) | ||
| { | ||
| if (!channelRegistered(channel)) | ||
| return false; | ||
|
|
||
| auto channel_it = m_registered_channels.find(channel); | ||
| channel_it->second->setState(state); | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| bool ModChannelMgr::removeChannel(const std::string &channel) | ||
| { | ||
| if (!channelRegistered(channel)) | ||
| return false; | ||
|
|
||
| m_registered_channels.erase(channel); | ||
| return true; | ||
| } | ||
|
|
||
| bool ModChannelMgr::joinChannel(const std::string &channel, u16 peer_id) | ||
| { | ||
| if (!channelRegistered(channel)) | ||
| registerChannel(channel); | ||
|
|
||
| return m_registered_channels[channel]->registerConsumer(peer_id); | ||
| } | ||
|
|
||
| bool ModChannelMgr::leaveChannel(const std::string &channel, u16 peer_id) | ||
| { | ||
| if (!channelRegistered(channel)) | ||
| return false; | ||
|
|
||
| // Remove consumer from channel | ||
| bool consumerRemoved = m_registered_channels[channel]->removeConsumer(peer_id); | ||
|
|
||
| // If channel is empty, remove it | ||
| if (m_registered_channels[channel]->getChannelPeers().empty()) { | ||
| removeChannel(channel); | ||
| } | ||
| return consumerRemoved; | ||
| } | ||
|
|
||
| void ModChannelMgr::leaveAllChannels(u16 peer_id) | ||
| { | ||
| for (auto &channel_it : m_registered_channels) | ||
| channel_it.second->removeConsumer(peer_id); | ||
| } | ||
|
|
||
| static std::vector<u16> empty_channel_list; | ||
| const std::vector<u16> &ModChannelMgr::getChannelPeers(const std::string &channel) const | ||
| { | ||
| const auto &channel_it = m_registered_channels.find(channel); | ||
| if (channel_it == m_registered_channels.end()) | ||
| return empty_channel_list; | ||
|
|
||
| return channel_it->second->getChannelPeers(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| /* | ||
| 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 <unordered_map> | ||
| #include <string> | ||
| #include <vector> | ||
| #include <memory> | ||
| #include "irrlichttypes.h" | ||
|
|
||
| enum ModChannelState : u8 | ||
| { | ||
| MODCHANNEL_STATE_INIT, | ||
| MODCHANNEL_STATE_READ_WRITE, | ||
| MODCHANNEL_STATE_READ_ONLY, | ||
| MODCHANNEL_STATE_MAX, | ||
| }; | ||
|
|
||
| class ModChannel | ||
| { | ||
| public: | ||
| ModChannel(const std::string &name) : m_name(name) {} | ||
| ~ModChannel() = default; | ||
|
|
||
| const std::string &getName() const { return m_name; } | ||
| bool registerConsumer(u16 peer_id); | ||
| bool removeConsumer(u16 peer_id); | ||
| const std::vector<u16> &getChannelPeers() const { return m_client_consumers; } | ||
| bool canWrite() const; | ||
| void setState(ModChannelState state); | ||
|
|
||
| private: | ||
| std::string m_name; | ||
| ModChannelState m_state = MODCHANNEL_STATE_INIT; | ||
| std::vector<u16> m_client_consumers; | ||
| }; | ||
|
|
||
| enum ModChannelSignal : u8 | ||
| { | ||
| MODCHANNEL_SIGNAL_JOIN_OK, | ||
| MODCHANNEL_SIGNAL_JOIN_FAILURE, | ||
| MODCHANNEL_SIGNAL_LEAVE_OK, | ||
| MODCHANNEL_SIGNAL_LEAVE_FAILURE, | ||
| MODCHANNEL_SIGNAL_CHANNEL_NOT_REGISTERED, | ||
| MODCHANNEL_SIGNAL_SET_STATE, | ||
| }; | ||
|
|
||
| class ModChannelMgr | ||
| { | ||
| public: | ||
| ModChannelMgr() = default; | ||
| ~ModChannelMgr() = default; | ||
|
|
||
| void registerChannel(const std::string &channel); | ||
| bool setChannelState(const std::string &channel, ModChannelState state); | ||
| bool joinChannel(const std::string &channel, u16 peer_id); | ||
| bool leaveChannel(const std::string &channel, u16 peer_id); | ||
| bool channelRegistered(const std::string &channel) const; | ||
| ModChannel *getModChannel(const std::string &channel); | ||
| /** | ||
| * This function check if a local mod can write on the channel | ||
| * | ||
| * @param channel | ||
| * @return true if write is allowed | ||
| */ | ||
| bool canWriteOnChannel(const std::string &channel) const; | ||
| void leaveAllChannels(u16 peer_id); | ||
| const std::vector<u16> &getChannelPeers(const std::string &channel) const; | ||
|
|
||
| private: | ||
| bool removeChannel(const std::string &channel); | ||
|
|
||
| std::unordered_map<std::string, std::unique_ptr<ModChannel>> | ||
| m_registered_channels; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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); | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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[]; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| /* | ||
| Minetest | ||
| Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> | ||
| 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 "test.h" | ||
|
|
||
| #include "gamedef.h" | ||
| #include "modchannels.h" | ||
|
|
||
| class TestModChannels : public TestBase | ||
| { | ||
| public: | ||
| TestModChannels() { TestManager::registerTestModule(this); } | ||
| const char *getName() { return "TestModChannels"; } | ||
|
|
||
| void runTests(IGameDef *gamedef); | ||
|
|
||
| void testJoinChannel(IGameDef *gamedef); | ||
| void testLeaveChannel(IGameDef *gamedef); | ||
| void testSendMessageToChannel(IGameDef *gamedef); | ||
| }; | ||
|
|
||
| static TestModChannels g_test_instance; | ||
|
|
||
| void TestModChannels::runTests(IGameDef *gamedef) | ||
| { | ||
| TEST(testJoinChannel, gamedef); | ||
| TEST(testLeaveChannel, gamedef); | ||
| TEST(testSendMessageToChannel, gamedef); | ||
| } | ||
|
|
||
| void TestModChannels::testJoinChannel(IGameDef *gamedef) | ||
| { | ||
| // Test join | ||
| UASSERT(gamedef->joinModChannel("test_join_channel")); | ||
| // Test join (fail, already join) | ||
| UASSERT(!gamedef->joinModChannel("test_join_channel")); | ||
| } | ||
|
|
||
| void TestModChannels::testLeaveChannel(IGameDef *gamedef) | ||
| { | ||
| // Test leave (not joined) | ||
| UASSERT(!gamedef->leaveModChannel("test_leave_channel")); | ||
|
|
||
| UASSERT(gamedef->joinModChannel("test_leave_channel")); | ||
|
|
||
| // Test leave (joined) | ||
| UASSERT(gamedef->leaveModChannel("test_leave_channel")); | ||
| } | ||
|
|
||
| void TestModChannels::testSendMessageToChannel(IGameDef *gamedef) | ||
| { | ||
| // Test sendmsg (not joined) | ||
| UASSERT(!gamedef->sendModChannelMessage( | ||
| "test_sendmsg_channel", "testmsgchannel")); | ||
|
|
||
| UASSERT(gamedef->joinModChannel("test_sendmsg_channel")); | ||
|
|
||
| // Test sendmsg (joined) | ||
| UASSERT(gamedef->sendModChannelMessage("test_sendmsg_channel", "testmsgchannel")); | ||
| } |