Fix bone-attached entities (#10015)
[oweals/minetest.git] / src / modchannels.cpp
1 /*
2 Minetest
3 Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "modchannels.h"
21 #include <algorithm>
22 #include <cassert>
23 #include "util/basic_macros.h"
24
25 bool ModChannel::registerConsumer(session_t peer_id)
26 {
27
28         // ignore if peer_id already joined
29         if (CONTAINS(m_client_consumers, peer_id))
30                 return false;
31
32         m_client_consumers.push_back(peer_id);
33         return true;
34 }
35
36 bool ModChannel::removeConsumer(session_t peer_id)
37 {
38         bool found = false;
39         auto peer_removal_fct = [peer_id, &found](u16 p) {
40                 if (p == peer_id)
41                         found = true;
42
43                 return p == peer_id;
44         };
45
46         m_client_consumers.erase(
47                         std::remove_if(m_client_consumers.begin(),
48                                         m_client_consumers.end(), peer_removal_fct),
49                         m_client_consumers.end());
50
51         return found;
52 }
53
54 bool ModChannel::canWrite() const
55 {
56         return m_state == MODCHANNEL_STATE_READ_WRITE;
57 }
58
59 void ModChannel::setState(ModChannelState state)
60 {
61         assert(state != MODCHANNEL_STATE_INIT);
62
63         m_state = state;
64 }
65
66 bool ModChannelMgr::channelRegistered(const std::string &channel) const
67 {
68         return m_registered_channels.find(channel) != m_registered_channels.end();
69 }
70
71 ModChannel *ModChannelMgr::getModChannel(const std::string &channel)
72 {
73         if (!channelRegistered(channel))
74                 return nullptr;
75
76         return m_registered_channels[channel].get();
77 }
78
79 bool ModChannelMgr::canWriteOnChannel(const std::string &channel) const
80 {
81         const auto channel_it = m_registered_channels.find(channel);
82         if (channel_it == m_registered_channels.end()) {
83                 return false;
84         }
85
86         return channel_it->second->canWrite();
87 }
88
89 void ModChannelMgr::registerChannel(const std::string &channel)
90 {
91         m_registered_channels[channel] =
92                         std::unique_ptr<ModChannel>(new ModChannel(channel));
93 }
94
95 bool ModChannelMgr::setChannelState(const std::string &channel, ModChannelState state)
96 {
97         if (!channelRegistered(channel))
98                 return false;
99
100         auto channel_it = m_registered_channels.find(channel);
101         channel_it->second->setState(state);
102
103         return true;
104 }
105
106 bool ModChannelMgr::removeChannel(const std::string &channel)
107 {
108         if (!channelRegistered(channel))
109                 return false;
110
111         m_registered_channels.erase(channel);
112         return true;
113 }
114
115 bool ModChannelMgr::joinChannel(const std::string &channel, session_t peer_id)
116 {
117         if (!channelRegistered(channel))
118                 registerChannel(channel);
119
120         return m_registered_channels[channel]->registerConsumer(peer_id);
121 }
122
123 bool ModChannelMgr::leaveChannel(const std::string &channel, session_t peer_id)
124 {
125         if (!channelRegistered(channel))
126                 return false;
127
128         // Remove consumer from channel
129         bool consumerRemoved = m_registered_channels[channel]->removeConsumer(peer_id);
130
131         // If channel is empty, remove it
132         if (m_registered_channels[channel]->getChannelPeers().empty()) {
133                 removeChannel(channel);
134         }
135         return consumerRemoved;
136 }
137
138 void ModChannelMgr::leaveAllChannels(session_t peer_id)
139 {
140         for (auto &channel_it : m_registered_channels)
141                 channel_it.second->removeConsumer(peer_id);
142 }
143
144 static std::vector<u16> empty_channel_list;
145 const std::vector<u16> &ModChannelMgr::getChannelPeers(const std::string &channel) const
146 {
147         const auto &channel_it = m_registered_channels.find(channel);
148         if (channel_it == m_registered_channels.end())
149                 return empty_channel_list;
150
151         return channel_it->second->getChannelPeers();
152 }