Merge branch 'fixes' into main/rendor-staging
[ryzomcore.git] / ryzom / common / src / game_share / dyn_chat.cpp
blob080cfed0c781340e583ee45d65be81d2e2c74ad7
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2010 Matt RAYKOWSKI (sfb) <matt.raykowski@gmail.com>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "stdpch.h"
21 #include "dyn_chat.h"
23 #ifdef DEBUG_NEW
24 #define new DEBUG_NEW
25 #endif
27 using namespace NLMISC;
29 NL_INSTANCE_COUNTER_IMPL(CDynChatSession);
31 uint CDynChatSession::_NumSessions = 0;
34 /////////////////////
35 // CDynChatSession //
36 /////////////////////
37 //================================================================
38 CDynChatSession::CDynChatSession(CDynChatClient *client, CDynChatChan *channel)
39 : StringID(0),
40 WriteRight(false),
41 _Client(client),
42 _Channel(channel)
44 nlassert(client);
45 nlassert(channel);
46 // insert at head of client linked list of session
47 _NextClientSession = client->_FirstSession;
48 if (client->_FirstSession)
50 nlassert(client->_FirstSession->_PrevClientSession == &client->_FirstSession);
51 client->_FirstSession->_PrevClientSession = &_NextClientSession;
53 _PrevClientSession = &client->_FirstSession;
54 client->_FirstSession = this;
55 // insert at head of channel linked list of session
56 _NextChannelSession = channel->_FirstSession;
57 if (channel->_FirstSession)
59 nlassert(channel->_FirstSession->_PrevChannelSession == &channel->_FirstSession);
60 channel->_FirstSession->_PrevChannelSession = &_NextChannelSession;
62 _PrevChannelSession = &channel->_FirstSession;
63 channel->_FirstSession = this;
65 ++ _NumSessions;
69 //================================================================
70 void CDynChatSession::unlink()
72 nlassert(_Client); // object already unlinked ?
73 nlassert(_Channel);
74 nlassert(_PrevClientSession);
75 // client
76 *_PrevClientSession = _NextClientSession;
77 if (_NextClientSession)
79 nlassert(_NextClientSession->_PrevClientSession = &_NextClientSession);
80 _NextClientSession->_PrevClientSession = _PrevClientSession;
82 _PrevClientSession = NULL;
83 _NextClientSession = NULL;
84 // channel
85 *_PrevChannelSession = _NextChannelSession;
86 if (_NextChannelSession)
88 nlassert(_NextChannelSession->_PrevChannelSession = &_NextChannelSession);
89 _NextChannelSession->_PrevChannelSession = _PrevChannelSession;
91 _PrevChannelSession = NULL;
92 _NextChannelSession = NULL;
93 _Client = NULL;
94 _Channel = NULL;
97 //================================================================
98 CDynChatSession::~CDynChatSession()
100 nlassert(!_Client); // unlink() hasn't been called
101 nlassert(!_Channel);
102 nlassert(!_PrevClientSession);
103 nlassert(!_NextClientSession);
104 nlassert(_NumSessions > 0); // check for memory leaks
105 --_NumSessions;
108 ////////////////////
109 // CDynChatClient //
110 ////////////////////
111 //================================================================
112 CDynChatClient::CDynChatClient(const TDataSetRow &client) : _FirstSession(NULL), _ID(client)
116 //================================================================
117 CDynChatClient::~CDynChatClient()
119 // remove all sessions
120 CDynChatSession *currSession = _FirstSession;
121 while (currSession)
123 CDynChatSession *tmpSession = currSession;
124 currSession = currSession->getNextClientSession();
125 tmpSession->unlink();
126 delete tmpSession;
130 //================================================================
131 CDynChatSession *CDynChatClient::getSession(TChanID chan) const
133 CDynChatSession *currSession = _FirstSession;
134 while (currSession)
136 if (currSession->getChan()->getID() == chan) break;
137 currSession = currSession->getNextClientSession();
139 return currSession;
142 //////////////////
143 // CDynChatChan //
144 //////////////////
145 CDynChatChan::CDynChatChan()
146 : HistoricSize(0),
147 HideBubble(false),
148 UniversalChannel(false),
149 _FirstSession(NULL),
150 _ID(CEntityId::Unknown),
151 _DontBroadcastPlayerInputs(false),
152 _ForwardPlayerIntputToOwnerService(false),
153 _UnifyChannel(false)
157 //================================================================
158 //CDynChatChan::CDynChatChan(TChanID id) : _ID(id), _FirstSession(NULL), HistoricSize(0)
159 CDynChatChan::CDynChatChan(TChanID id, bool noBroadcast, bool forwardInput, bool unified)
160 : HistoricSize(0),
161 HideBubble(false),
162 UniversalChannel(false),
163 _FirstSession(NULL),
164 _ID(id),
165 _DontBroadcastPlayerInputs(noBroadcast),
166 _ForwardPlayerIntputToOwnerService(forwardInput),
167 _UnifyChannel(unified)
171 //================================================================
172 CDynChatChan::~CDynChatChan()
174 // remove all sessions
175 CDynChatSession *currSession = _FirstSession;
176 while (currSession)
178 CDynChatSession *tmpSession = currSession;
179 currSession = currSession->getNextChannelSession();
180 tmpSession->unlink();
181 delete tmpSession;
185 //================================================================
186 uint CDynChatChan::getSessionCount() const
188 uint count = 0;
189 // remove all sessions
190 CDynChatSession *currSession = _FirstSession;
191 while (currSession)
193 ++ count;
194 currSession = currSession->getNextChannelSession();
196 return count;
199 //////////////
200 // CDynChat //
201 //////////////
204 //================================================================
205 bool CDynChat::addChan(TChanID chan, bool noBroadcast, bool forwardInput, bool unify)
207 if (_Chans.count(chan)) return false;
208 _Chans[chan] = CDynChatChan(chan, noBroadcast, forwardInput, unify);
209 return true;
212 //================================================================
213 bool CDynChat::removeChan(TChanID chan)
215 TChanMap::iterator it = _Chans.find(chan);
216 if (it != _Chans.end())
218 _Chans.erase(it);
219 return true;
221 else
223 return false;
227 //================================================================
228 bool CDynChat::addClient(const TDataSetRow &client)
230 if (_Clients.count(client)) return false;
231 _Clients[client] = CDynChatClient(client);
232 return true;
235 //================================================================
236 bool CDynChat::removeClient(const TDataSetRow &client)
238 TClientMap::iterator it = _Clients.find(client);
239 if (it != _Clients.end())
241 _Clients.erase(it);
242 return true;
244 else
246 return false;
250 //================================================================
251 CDynChatSession *CDynChat::addSession(TChanID chanID, const TDataSetRow &clientID)
253 CDynChatChan *chan = getChan(chanID);
254 if (!chan)
255 return NULL;
256 CDynChatClient *client = getClient(clientID);
257 if (!client)
258 return NULL;
259 // look for channel in session (faster because there are few channels used by a single player)
260 CDynChatSession *session = client->getSession(chanID);
261 if (session)
263 nlwarning("Session already created for player %s in channel %p", clientID.toString().c_str(), chan);
264 return NULL;
266 CDynChatSession *newSession = new CDynChatSession(client, chan);
267 return newSession;
270 //================================================================
271 bool CDynChat::removeSession(TChanID chanID, const TDataSetRow &clientID)
273 CDynChatClient *client = getClient(clientID);
274 if (!client)
276 nlwarning("Client %s unknown", clientID.toString().c_str());
277 return false;
279 // look for channel in session (faster because there are few channels used by a single player)
280 CDynChatSession *session = client->getSession(chanID);
281 if (!session)
283 nlwarning("Channel %s unknown", chanID.toString().c_str());
284 return false;
286 session->unlink();
287 delete session;
288 return true;
291 //================================================================
292 CDynChatChan *CDynChat::getChan(TChanID chan)
294 TChanMap::iterator it = _Chans.find(chan);
295 if (it != _Chans.end()) return &(it->second);
296 return NULL;
299 //================================================================
300 CDynChatClient *CDynChat::getClient(const TDataSetRow &client)
302 TClientMap::iterator it = _Clients.find(client);
303 if (it != _Clients.end()) return &(it->second);
304 return NULL;
307 //================================================================
308 CDynChat::CDynChat()
312 //================================================================
313 CDynChat::~CDynChat()
315 _Chans.clear();
316 _Clients.clear();
319 //================================================================
320 CDynChatSession *CDynChat::getSession(TChanID chan, const TDataSetRow &client)
322 CDynChatClient *clientPtr = getClient(client);
323 if (!clientPtr) return NULL;
324 return clientPtr->getSession(chan);
327 //================================================================
328 void CDynChat::getChans(std::vector<CDynChatChan *> &channels)
330 uint numChans = (uint)_Chans.size();
331 channels.resize(numChans);
332 uint k = 0;
333 for(TChanMap::iterator it = _Chans.begin(); it != _Chans.end(); ++it, ++k)
335 channels[k] = &(it->second);