doxygen: prevent GPL license block from being parsed as doxygen comment.
[blender.git] / source / gameengine / Network / NG_NetworkScene.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  * NetworkSceneManagement generic implementation
29  */
30 #include <stdio.h>
31 #include <MT_assert.h>
32 #include <algorithm>
33
34 #include "NG_NetworkScene.h"
35 #include "NG_NetworkDeviceInterface.h"
36 #include "NG_NetworkMessage.h"
37 #include "NG_NetworkObject.h"
38
39 NG_NetworkScene::NG_NetworkScene(NG_NetworkDeviceInterface* nic)
40 {
41         m_networkdevice = nic;
42 }
43
44 NG_NetworkScene::~NG_NetworkScene()
45 {
46         ClearAllMessageMaps();
47 }
48
49 /**
50  * progress one frame, handle all network traffic
51  */
52 void NG_NetworkScene::proceed(double curtime)
53 {
54         if (!m_networkdevice) return;
55         if (!m_networkdevice->IsOnline()) return;
56
57         ClearAllMessageMaps();
58
59         // read all NetworkMessages from the device
60         vector<NG_NetworkMessage*> messages =
61                 m_networkdevice->RetrieveNetworkMessages();
62
63         vector<NG_NetworkMessage*>::iterator mesit = messages.begin();
64         for (; !(mesit == messages.end()); mesit++) {
65                 NG_NetworkMessage* message = (*mesit);
66                 vector<NG_NetworkMessage*>* tmplist=NULL;
67
68                 vector<NG_NetworkMessage*>** tmplistptr =
69                         m_messagesByDestinationName[message->GetDestinationName()];
70                 // if there is already a vector of messages, append, else create
71                 // a new vector and insert into map
72                 if (!tmplistptr) {
73                         tmplist = new vector<NG_NetworkMessage*>;
74                         m_messagesByDestinationName.insert(message->GetDestinationName(),
75                                                                                            tmplist);
76                 } else {
77                         tmplist = *tmplistptr;
78                 }
79                 message->AddRef();
80                 tmplist->push_back(message);
81                 tmplist = NULL;
82
83                 tmplistptr = m_messagesBySenderName[message->GetSenderName()];
84                 // if there is already a vector of messages, append, else create
85                 // a new vector and insert into map
86                 if (!tmplistptr) {
87                         tmplist = new vector<NG_NetworkMessage*>;
88                         m_messagesBySenderName.insert(message->GetSenderName(), tmplist);
89                 }  else {
90                         tmplist = *tmplistptr;
91                 }
92                 message->AddRef();
93                 tmplist->push_back(message);
94                 tmplist = NULL;
95                 
96                 tmplistptr = m_messagesBySubject[message->GetSubject()];
97                 // if there is already a vector of messages, append, else create
98                 // a new vector and insert into map
99                 if (!tmplistptr) {
100                         tmplist = new vector<NG_NetworkMessage*>;
101                         m_messagesBySubject.insert(message->GetSubject(), tmplist);
102                 }  else {
103                         tmplist = *tmplistptr;
104                 }
105                 message->AddRef();
106                 tmplist->push_back(message);
107                 tmplist = NULL;
108         }
109 }
110
111 /**
112  * add a network object to the network scene
113  */
114 void NG_NetworkScene::AddObject(NG_NetworkObject* object)
115 {
116         if (! m_networkdevice->IsOnline()) return;
117
118         const STR_String& name = object->GetName();
119         m_networkObjects.insert(name, object);
120 }
121
122 /**
123  * remove a network object from the network scene
124  */
125 void NG_NetworkScene::RemoveObject(NG_NetworkObject* object)
126 {
127         if (! m_networkdevice->IsOnline()) return;
128
129         const STR_String& name = object->GetName();
130         m_networkObjects.remove(name);
131 }
132
133 /**
134  * remove all network scene objects at once
135  */
136 void NG_NetworkScene::RemoveAllObjects()
137 {
138         m_networkObjects.clear();
139 }
140
141 /**
142  * get a single network object given its name
143  */
144 NG_NetworkObject* NG_NetworkScene::FindNetworkObject(const STR_String& objname) {
145         NG_NetworkObject *nwobj = NULL;
146         if (! m_networkdevice->IsOnline()) return nwobj;
147
148         NG_NetworkObject **nwobjptr = m_networkObjects[objname];
149         if (nwobjptr) {
150                 nwobj = *nwobjptr;
151         }
152
153         return nwobj;
154 }
155
156 bool NG_NetworkScene::ConstraintsAreValid(
157         const STR_String& from,
158         const STR_String& subject,
159         NG_NetworkMessage* message)
160 {
161         vector<NG_NetworkMessage*>** fromlistptr =  m_messagesBySenderName[from];
162         vector<NG_NetworkMessage*>** subjectlistptr =  m_messagesBySubject[subject];
163
164         vector<NG_NetworkMessage*>* fromlist = (fromlistptr ? *fromlistptr : NULL);
165         vector<NG_NetworkMessage*>* subjectlist = (subjectlistptr ? *subjectlistptr : NULL);
166         
167         return (
168                 ( from.IsEmpty()    || (!fromlist ? false    : (!(std::find(fromlist->begin(), fromlist->end(), message)       == fromlist->end())))
169                 ) &&
170                 ( subject.IsEmpty() || (!subjectlist ? false : (!(std::find(subjectlist->begin(), subjectlist->end(), message) == subjectlist->end())))
171                 ));
172 }
173
174 vector<NG_NetworkMessage*> NG_NetworkScene::FindMessages(
175         const STR_String& to,
176         const STR_String& from,
177         const STR_String& subject,
178         bool spamallowed)
179 {
180         vector<NG_NetworkMessage*> foundmessages;
181         bool notfound = false;
182
183         // broad phase
184         notfound = ((to.IsEmpty() || spamallowed) ? notfound : m_messagesByDestinationName[to] == NULL);
185         if (!notfound)
186                 notfound = (from.IsEmpty() ? notfound : m_messagesBySenderName[from] == NULL);
187         if (!notfound)
188                 notfound = (subject.IsEmpty() ? notfound : m_messagesBySubject[subject] == NULL);
189         if (notfound) {
190                 // it's definitely NOT in the scene, so stop looking
191         } else { // narrow phase
192                 // possibly it's there, but maybe not (false hit)
193                 if (to.IsEmpty()) {
194                         // take all messages, and check other fields
195                         MT_assert(!"objectnames that are empty are not valid, so make it a hobby project :)\n");
196                 } else {
197                         //todo: find intersection of messages (that are in other 2 maps)
198                         vector<NG_NetworkMessage*>** tolistptr = m_messagesByDestinationName[to];
199                         if (tolistptr) {
200                                 vector<NG_NetworkMessage*>* tolist = *tolistptr;
201                                 vector<NG_NetworkMessage*>::iterator listit;
202                                 for (listit=tolist->begin();!(listit==tolist->end());listit++) {
203                                         NG_NetworkMessage* message = *listit;
204                                         if (ConstraintsAreValid(from, subject, message)) {
205                                                 message->AddRef();
206                                                 foundmessages.push_back(message);
207                                         }
208                                 } 
209                         }
210                         // TODO find intersection of messages (that are in other 2 maps)
211                         if (spamallowed) {
212                                 tolistptr = m_messagesByDestinationName[""];
213                                 if (tolistptr) {
214                                         vector<NG_NetworkMessage*>* tolist = *tolistptr;
215                                         vector<NG_NetworkMessage*>::iterator listit;
216                                         for (listit=tolist->begin();!(listit==tolist->end());listit++) {
217                                                 NG_NetworkMessage* message = *listit;
218                                                 if (ConstraintsAreValid(from, subject, message)) {
219                                                         message->AddRef();
220                                                         foundmessages.push_back(message);
221                                                 }
222                                         } 
223                                 }
224                         }
225                 }
226         } 
227         return foundmessages;
228 }
229
230 void NG_NetworkScene::SendMessage(
231         const STR_String& to,
232         const STR_String& from,
233         const STR_String& subject,
234         const STR_String& message)
235 {
236         NG_NetworkMessage* msg = new NG_NetworkMessage(to, from, subject, message);
237         m_networkdevice->SendNetworkMessage(msg);
238         msg->Release();
239 }
240
241 void NG_NetworkScene::ClearAllMessageMaps(void)
242 {
243         ClearMessageMap(m_messagesByDestinationName);
244         ClearMessageMap(m_messagesBySenderName);
245         ClearMessageMap(m_messagesBySubject);
246 }
247
248 void NG_NetworkScene::ClearMessageMap(TMessageMap& map)
249 {
250         // Release the messages in the map
251         for (int i = 0; i < map.size(); i++) {
252                 vector<NG_NetworkMessage*>* msglist;
253                 msglist = *(map.at(i));
254
255                 // Iterate through the current vector and release all it's messages
256                 vector<NG_NetworkMessage*>::iterator msgit;
257                 for (msgit = msglist->begin(); msgit != msglist->end(); msgit++) {
258                         (*msgit)->Release();
259                 }
260
261                 // Delete the actual vector
262                 delete (msglist);
263         }
264
265         // Empty the map
266         map.clear();
267 }
268