1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2010 Matt RAYKOWSKI (sfb) <matt.raykowski@gmail.com>
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/>.
27 using namespace NLMISC
;
29 NL_INSTANCE_COUNTER_IMPL(CDynChatSession
);
31 uint
CDynChatSession::_NumSessions
= 0;
37 //================================================================
38 CDynChatSession::CDynChatSession(CDynChatClient
*client
, CDynChatChan
*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;
69 //================================================================
70 void CDynChatSession::unlink()
72 nlassert(_Client
); // object already unlinked ?
74 nlassert(_PrevClientSession
);
76 *_PrevClientSession
= _NextClientSession
;
77 if (_NextClientSession
)
79 nlassert(_NextClientSession
->_PrevClientSession
= &_NextClientSession
);
80 _NextClientSession
->_PrevClientSession
= _PrevClientSession
;
82 _PrevClientSession
= NULL
;
83 _NextClientSession
= NULL
;
85 *_PrevChannelSession
= _NextChannelSession
;
86 if (_NextChannelSession
)
88 nlassert(_NextChannelSession
->_PrevChannelSession
= &_NextChannelSession
);
89 _NextChannelSession
->_PrevChannelSession
= _PrevChannelSession
;
91 _PrevChannelSession
= NULL
;
92 _NextChannelSession
= NULL
;
97 //================================================================
98 CDynChatSession::~CDynChatSession()
100 nlassert(!_Client
); // unlink() hasn't been called
102 nlassert(!_PrevClientSession
);
103 nlassert(!_NextClientSession
);
104 nlassert(_NumSessions
> 0); // check for memory leaks
111 //================================================================
112 CDynChatClient::CDynChatClient(const TDataSetRow
&client
) : _FirstSession(NULL
), _ID(client
)
116 //================================================================
117 CDynChatClient::~CDynChatClient()
119 // remove all sessions
120 CDynChatSession
*currSession
= _FirstSession
;
123 CDynChatSession
*tmpSession
= currSession
;
124 currSession
= currSession
->getNextClientSession();
125 tmpSession
->unlink();
130 //================================================================
131 CDynChatSession
*CDynChatClient::getSession(TChanID chan
) const
133 CDynChatSession
*currSession
= _FirstSession
;
136 if (currSession
->getChan()->getID() == chan
) break;
137 currSession
= currSession
->getNextClientSession();
145 CDynChatChan::CDynChatChan()
148 UniversalChannel(false),
150 _ID(CEntityId::Unknown
),
151 _DontBroadcastPlayerInputs(false),
152 _ForwardPlayerIntputToOwnerService(false),
157 //================================================================
158 //CDynChatChan::CDynChatChan(TChanID id) : _ID(id), _FirstSession(NULL), HistoricSize(0)
159 CDynChatChan::CDynChatChan(TChanID id
, bool noBroadcast
, bool forwardInput
, bool unified
)
162 UniversalChannel(false),
165 _DontBroadcastPlayerInputs(noBroadcast
),
166 _ForwardPlayerIntputToOwnerService(forwardInput
),
167 _UnifyChannel(unified
)
171 //================================================================
172 CDynChatChan::~CDynChatChan()
174 // remove all sessions
175 CDynChatSession
*currSession
= _FirstSession
;
178 CDynChatSession
*tmpSession
= currSession
;
179 currSession
= currSession
->getNextChannelSession();
180 tmpSession
->unlink();
185 //================================================================
186 uint
CDynChatChan::getSessionCount() const
189 // remove all sessions
190 CDynChatSession
*currSession
= _FirstSession
;
194 currSession
= currSession
->getNextChannelSession();
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
);
212 //================================================================
213 bool CDynChat::removeChan(TChanID chan
)
215 TChanMap::iterator it
= _Chans
.find(chan
);
216 if (it
!= _Chans
.end())
227 //================================================================
228 bool CDynChat::addClient(const TDataSetRow
&client
)
230 if (_Clients
.count(client
)) return false;
231 _Clients
[client
] = CDynChatClient(client
);
235 //================================================================
236 bool CDynChat::removeClient(const TDataSetRow
&client
)
238 TClientMap::iterator it
= _Clients
.find(client
);
239 if (it
!= _Clients
.end())
250 //================================================================
251 CDynChatSession
*CDynChat::addSession(TChanID chanID
, const TDataSetRow
&clientID
)
253 CDynChatChan
*chan
= getChan(chanID
);
256 CDynChatClient
*client
= getClient(clientID
);
259 // look for channel in session (faster because there are few channels used by a single player)
260 CDynChatSession
*session
= client
->getSession(chanID
);
263 nlwarning("Session already created for player %s in channel %p", clientID
.toString().c_str(), chan
);
266 CDynChatSession
*newSession
= new CDynChatSession(client
, chan
);
270 //================================================================
271 bool CDynChat::removeSession(TChanID chanID
, const TDataSetRow
&clientID
)
273 CDynChatClient
*client
= getClient(clientID
);
276 nlwarning("Client %s unknown", clientID
.toString().c_str());
279 // look for channel in session (faster because there are few channels used by a single player)
280 CDynChatSession
*session
= client
->getSession(chanID
);
283 nlwarning("Channel %s unknown", chanID
.toString().c_str());
291 //================================================================
292 CDynChatChan
*CDynChat::getChan(TChanID chan
)
294 TChanMap::iterator it
= _Chans
.find(chan
);
295 if (it
!= _Chans
.end()) return &(it
->second
);
299 //================================================================
300 CDynChatClient
*CDynChat::getClient(const TDataSetRow
&client
)
302 TClientMap::iterator it
= _Clients
.find(client
);
303 if (it
!= _Clients
.end()) return &(it
->second
);
307 //================================================================
312 //================================================================
313 CDynChat::~CDynChat()
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
);
333 for(TChanMap::iterator it
= _Chans
.begin(); it
!= _Chans
.end(); ++it
, ++k
)
335 channels
[k
] = &(it
->second
);