Merged changes in the trunk up to revision 36408.
[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
31 /** \file gameengine/Network/NG_NetworkScene.cpp
32  *  \ingroup bgenet
33  */
34
35 #include <stdio.h>
36 #include <MT_assert.h>
37 #include <algorithm>
38
39 #include "NG_NetworkScene.h"
40 #include "NG_NetworkDeviceInterface.h"
41 #include "NG_NetworkMessage.h"
42 #include "NG_NetworkObject.h"
43
44 NG_NetworkScene::NG_NetworkScene(NG_NetworkDeviceInterface* nic)
45 {
46         m_networkdevice = nic;
47 }
48
49 NG_NetworkScene::~NG_NetworkScene()
50 {
51         ClearAllMessageMaps();
52 }
53
54 /**
55  * progress one frame, handle all network traffic
56  */
57 void NG_NetworkScene::proceed(double curtime)
58 {
59         if (!m_networkdevice) return;
60         if (!m_networkdevice->IsOnline()) return;
61
62         ClearAllMessageMaps();
63
64         // read all NetworkMessages from the device
65         vector<NG_NetworkMessage*> messages =
66                 m_networkdevice->RetrieveNetworkMessages();
67
68         vector<NG_NetworkMessage*>::iterator mesit = messages.begin();
69         for (; !(mesit == messages.end()); mesit++) {
70                 NG_NetworkMessage* message = (*mesit);
71                 vector<NG_NetworkMessage*>* tmplist=NULL;
72
73                 vector<NG_NetworkMessage*>** tmplistptr =
74                         m_messagesByDestinationName[message->GetDestinationName()];
75                 // if there is already a vector of messages, append, else create
76                 // a new vector and insert into map
77                 if (!tmplistptr) {
78                         tmplist = new vector<NG_NetworkMessage*>;
79                         m_messagesByDestinationName.insert(message->GetDestinationName(),
80                                                                                            tmplist);
81                 } else {
82                         tmplist = *tmplistptr;
83                 }
84                 message->AddRef();
85                 tmplist->push_back(message);
86                 tmplist = NULL;
87
88                 tmplistptr = m_messagesBySenderName[message->GetSenderName()];
89                 // if there is already a vector of messages, append, else create
90                 // a new vector and insert into map
91                 if (!tmplistptr) {
92                         tmplist = new vector<NG_NetworkMessage*>;
93                         m_messagesBySenderName.insert(message->GetSenderName(), tmplist);
94                 }  else {
95                         tmplist = *tmplistptr;
96                 }
97                 message->AddRef();
98                 tmplist->push_back(message);
99                 tmplist = NULL;
100                 
101                 tmplistptr = m_messagesBySubject[message->GetSubject()];
102                 // if there is already a vector of messages, append, else create
103                 // a new vector and insert into map
104                 if (!tmplistptr) {
105                         tmplist = new vector<NG_NetworkMessage*>;
106                         m_messagesBySubject.insert(message->GetSubject(), tmplist);
107                 }  else {
108                         tmplist = *tmplistptr;
109                 }
110                 message->AddRef();
111                 tmplist->push_back(message);
112                 tmplist = NULL;
113         }
114 }
115
116 /**
117  * add a network object to the network scene
118  */
119 void NG_NetworkScene::AddObject(NG_NetworkObject* object)
120 {
121         if (! m_networkdevice->IsOnline()) return;
122
123         const STR_String& name = object->GetName();
124         m_networkObjects.insert(name, object);
125 }
126
127 /**
128  * remove a network object from the network scene
129  */
130 void NG_NetworkScene::RemoveObject(NG_NetworkObject* object)
131 {
132         if (! m_networkdevice->IsOnline()) return;
133
134         const STR_String& name = object->GetName();
135         m_networkObjects.remove(name);
136 }
137
138 /**
139  * remove all network scene objects at once
140  */
141 void NG_NetworkScene::RemoveAllObjects()
142 {
143         m_networkObjects.clear();
144 }
145
146 /**
147  * get a single network object given its name
148  */
149 NG_NetworkObject* NG_NetworkScene::FindNetworkObject(const STR_String& objname) {
150         NG_NetworkObject *nwobj = NULL;
151         if (! m_networkdevice->IsOnline()) return nwobj;
152
153         NG_NetworkObject **nwobjptr = m_networkObjects[objname];
154         if (nwobjptr) {
155                 nwobj = *nwobjptr;
156         }
157
158         return nwobj;
159 }
160
161 bool NG_NetworkScene::ConstraintsAreValid(
162         const STR_String& from,
163         const STR_String& subject,
164         NG_NetworkMessage* message)
165 {
166         vector<NG_NetworkMessage*>** fromlistptr =  m_messagesBySenderName[from];
167         vector<NG_NetworkMessage*>** subjectlistptr =  m_messagesBySubject[subject];
168
169         vector<NG_NetworkMessage*>* fromlist = (fromlistptr ? *fromlistptr : NULL);
170         vector<NG_NetworkMessage*>* subjectlist = (subjectlistptr ? *subjectlistptr : NULL);
171         
172         return (
173                 ( from.IsEmpty()    || (!fromlist ? false    : (!(std::find(fromlist->begin(), fromlist->end(), message)       == fromlist->end())))
174                 ) &&
175                 ( subject.IsEmpty() || (!subjectlist ? false : (!(std::find(subjectlist->begin(), subjectlist->end(), message) == subjectlist->end())))
176                 ));
177 }
178
179 vector<NG_NetworkMessage*> NG_NetworkScene::FindMessages(
180         const STR_String& to,
181         const STR_String& from,
182         const STR_String& subject,
183         bool spamallowed)
184 {
185         vector<NG_NetworkMessage*> foundmessages;
186         bool notfound = false;
187
188         // broad phase
189         notfound = ((to.IsEmpty() || spamallowed) ? notfound : m_messagesByDestinationName[to] == NULL);
190         if (!notfound)
191                 notfound = (from.IsEmpty() ? notfound : m_messagesBySenderName[from] == NULL);
192         if (!notfound)
193                 notfound = (subject.IsEmpty() ? notfound : m_messagesBySubject[subject] == NULL);
194         if (notfound) {
195                 // it's definitely NOT in the scene, so stop looking
196         } else { // narrow phase
197                 // possibly it's there, but maybe not (false hit)
198                 if (to.IsEmpty()) {
199                         // take all messages, and check other fields
200                         MT_assert(!"objectnames that are empty are not valid, so make it a hobby project :)\n");
201                 } else {
202                         //todo: find intersection of messages (that are in other 2 maps)
203                         vector<NG_NetworkMessage*>** tolistptr = m_messagesByDestinationName[to];
204                         if (tolistptr) {
205                                 vector<NG_NetworkMessage*>* tolist = *tolistptr;
206                                 vector<NG_NetworkMessage*>::iterator listit;
207                                 for (listit=tolist->begin();!(listit==tolist->end());listit++) {
208                                         NG_NetworkMessage* message = *listit;
209                                         if (ConstraintsAreValid(from, subject, message)) {
210                                                 message->AddRef();
211                                                 foundmessages.push_back(message);
212                                         }
213                                 } 
214                         }
215                         // TODO find intersection of messages (that are in other 2 maps)
216                         if (spamallowed) {
217                                 tolistptr = m_messagesByDestinationName[""];
218                                 if (tolistptr) {
219                                         vector<NG_NetworkMessage*>* tolist = *tolistptr;
220                                         vector<NG_NetworkMessage*>::iterator listit;
221                                         for (listit=tolist->begin();!(listit==tolist->end());listit++) {
222                                                 NG_NetworkMessage* message = *listit;
223                                                 if (ConstraintsAreValid(from, subject, message)) {
224                                                         message->AddRef();
225                                                         foundmessages.push_back(message);
226                                                 }
227                                         } 
228                                 }
229                         }
230                 }
231         } 
232         return foundmessages;
233 }
234
235 void NG_NetworkScene::SendMessage(
236         const STR_String& to,
237         const STR_String& from,
238         const STR_String& subject,
239         const STR_String& message)
240 {
241         NG_NetworkMessage* msg = new NG_NetworkMessage(to, from, subject, message);
242         m_networkdevice->SendNetworkMessage(msg);
243         msg->Release();
244 }
245
246 void NG_NetworkScene::ClearAllMessageMaps(void)
247 {
248         ClearMessageMap(m_messagesByDestinationName);
249         ClearMessageMap(m_messagesBySenderName);
250         ClearMessageMap(m_messagesBySubject);
251 }
252
253 void NG_NetworkScene::ClearMessageMap(TMessageMap& map)
254 {
255         // Release the messages in the map
256         for (int i = 0; i < map.size(); i++) {
257                 vector<NG_NetworkMessage*>* msglist;
258                 msglist = *(map.at(i));
259
260                 // Iterate through the current vector and release all it's messages
261                 vector<NG_NetworkMessage*>::iterator msgit;
262                 for (msgit = msglist->begin(); msgit != msglist->end(); msgit++) {
263                         (*msgit)->Release();
264                 }
265
266                 // Delete the actual vector
267                 delete (msglist);
268         }
269
270         // Empty the map
271         map.clear();
272 }
273