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