Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/network/src/network/Synchronisable.cc @ 1699

Last change on this file since 1699 was 1699, checked in by scheusso, 16 years ago

some missing files

  • Property svn:eol-style set to native
File size: 16.3 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Dumeni Manatschal, (C) 2007
24 *      Oliver Scheuss, (C) 2007
25 *   Co-authors:
26 *      ...
27 *
28 */
29
30//
31// C++ Implementation: synchronisable
32//
33// Description:
34//
35//
36// Author:  Dumeni, Oliver Scheuss, (C) 2007
37//
38// Copyright: See COPYING file that comes with this distribution
39//
40
41#include "Synchronisable.h"
42
43#include <string>
44#include <iostream>
45#include <assert.h>
46
47#include "core/CoreIncludes.h"
48#include "core/BaseObject.h"
49// #include "core/Identifier.h"
50
51namespace network
52{
53 
54 
55  int Synchronisable::state_=0x1; // detemines wheter we are server (default) or client
56 
57  /**
58  * Constructor:
59  * calls registarAllVariables, that has to be implemented by the inheriting classID
60  */
61  Synchronisable::Synchronisable(){
62    RegisterRootObject(Synchronisable);
63    static int idCounter=0;
64    datasize=0;
65    objectID=idCounter++;
66    syncList = new std::list<synchronisableVariable *>;
67    //registerAllVariables();
68  }
69
70  Synchronisable::~Synchronisable(){
71    // delete callback function objects
72    if(!orxonox::Identifier::isCreatingHierarchy())
73      for(std::list<synchronisableVariable *>::iterator it = syncList->begin(); it!=syncList->end(); it++)
74        delete (*it)->callback;
75  }
76 
77  bool Synchronisable::create(){
78    this->classID = this->getIdentifier()->getNetworkID();
79    COUT(4) << "creating synchronisable: setting classid from " << this->getIdentifier()->getName() << " to: " << classID << std::endl;
80    return true;
81  }
82 
83  void Synchronisable::setClient(bool b){
84    if(b) // client
85      state_=0x2;
86    else  // server
87      state_=0x1;
88  }
89 
90  bool Synchronisable::fabricate(unsigned char*& mem, int mode)
91  {
92    int size, objectID, classID;
93    size = *(int *)mem;
94    objectID = *(int*)(mem+sizeof(int));
95    classID = *(int*)(mem+2*sizeof(int));
96   
97    orxonox::Identifier* id = ID((unsigned int)classID);
98    if(!id){
99      COUT(3) << "We could not identify a new object; classid: " << classID << " uint: " << (unsigned int)classID << " objectID: " << objectID << " size: " << size << std::endl;
100      return false; // most probably the gamestate is corrupted
101    }
102    Synchronisable *no = dynamic_cast<Synchronisable *>(id->fabricate());
103    if(!no){
104      COUT(2) << "coudl not frabricate classid: " << classID << " objectID: " << objectID << " identifier: " << id << std::endl;
105      return false;
106    }
107    no->objectID=objectID;
108    no->classID=classID;
109          // update data and create object/entity...
110    if( !no->updateData(mem, mode) ){
111      COUT(1) << "We couldn't update the object: " << objectID << std::endl;
112      return false;
113    }
114    if( !no->create() )
115    {
116      COUT(1) << "We couldn't manifest (create() ) the object: " << objectID << std::endl;
117      return false;
118    }
119    return true;
120  }
121
122  /**
123  * This function is used to register a variable to be synchronized
124  * also counts the total datasize needed to save the variables
125  * @param var pointer to the variable
126  * @param size size of the datatype the variable consists of
127  */
128  void Synchronisable::registerVar(void *var, int size, variableType t, int mode, NetworkCallbackBase *cb){
129    // create temporary synch.Var struct
130    synchronisableVariable *temp = new synchronisableVariable;
131    temp->size = size;
132    temp->var = var;
133    temp->mode = mode; 
134    temp->type = t;
135    temp->callback = cb;
136    COUT(5) << "Syncronisable::registering var with size: " << temp->size << " and type: " << temp->type << std::endl; 
137    // increase datasize
138    datasize+=sizeof(int)+size;
139    //std::cout << "push temp to syncList (at the bottom) " << datasize << std::endl;
140    COUT(5) << "Syncronisable::objectID: " << objectID << " this: " << this << " name: " << this->getIdentifier()->getName() << " networkID: " << this->getIdentifier()->getNetworkID() << std::endl;
141    syncList->push_back(temp);
142  }
143
144
145  /**
146  * This function takes all SynchronisableVariables out of the Synchronisable and saves it into a syncData struct
147  * Difference to the above function:
148  * takes a pointer to already allocated memory (must have at least getSize bytes length)
149  * structure of the bitstream:
150  * (var1_size,var1,var2_size,var2,...)
151  * varx_size: size = sizeof(int)
152  * varx: size = varx_size
153  * @return data containing all variables and their sizes
154  */
155  syncData Synchronisable::getData(unsigned char *mem, int mode){
156    //std::cout << "inside getData" << std::endl;
157    if(mode==0x0)
158      mode=state_;
159    if(classID==0)
160      COUT(3) << "classid 0 " << this->getIdentifier()->getName() << std::endl;
161    this->classID=this->getIdentifier()->getNetworkID();
162    std::list<synchronisableVariable *>::iterator i;
163    syncData retVal;
164    retVal.objectID=this->objectID;
165    retVal.classID=this->classID;
166    retVal.length=getSize();
167    COUT(5) << "Synchronisable getting data from objectID: " << retVal.objectID << " classID: " << retVal.classID << " length: " << retVal.length << std::endl;
168    retVal.data=mem;
169    // copy to location
170    int n=0; //offset
171    for(i=syncList->begin(); n<datasize && i!=syncList->end(); ++i){
172      //(std::memcpy(retVal.data+n, (const void*)(&(i->size)), sizeof(int));
173      if( ((*i)->mode & mode) == 0 ){
174        COUT(5) << "not getting data: " << std::endl;
175        continue;  // this variable should only be received
176      }
177      switch((*i)->type){
178      case DATA:
179        std::memcpy( (void *)(retVal.data+n), (void*)((*i)->var), (*i)->size);
180        n+=(*i)->size;
181        break;
182      case STRING:
183        memcpy( (void *)(retVal.data+n), (void *)&((*i)->size), sizeof(int) );
184        n+=sizeof(int);
185        const char *data = ( ( *(std::string *) (*i)->var).c_str());
186        std::memcpy( retVal.data+n, (void*)data, (*i)->size);
187        COUT(5) << "synchronisable: char: " << (const char *)(retVal.data+n) << " data: " << data << " string: " << *(std::string *)((*i)->var) << std::endl;
188        n+=(*i)->size;
189        break;
190      }
191    }
192    return retVal;
193  }
194 
195  /**
196   * This function takes all SynchronisableVariables out of the Synchronisable and saves it into a syncData struct
197  * Difference to the above function:
198   * takes a pointer to already allocated memory (must have at least getSize bytes length)
199  * structure of the bitstream:
200   * (var1_size,var1,var2_size,var2,...)
201   * varx_size: size = sizeof(int)
202   * varx: size = varx_size
203   * @return data containing all variables and their sizes
204   */
205  bool Synchronisable::getData2(unsigned char*& mem, int mode){
206    //std::cout << "inside getData" << std::endl;
207    unsigned int tempsize = 0;
208    if(mode==0x0)
209      mode=state_;
210    if(classID==0)
211      COUT(3) << "classid 0 " << this->getIdentifier()->getName() << std::endl;
212    this->classID=this->getIdentifier()->getNetworkID();
213    std::list<synchronisableVariable *>::iterator i;
214    unsigned int size;
215    size=getSize2(mode);
216   
217    // start copy header
218    memcpy(mem, &size, sizeof(unsigned int));
219    mem+=sizeof(unsigned int);
220    memcpy(mem, &(this->objectID), sizeof(unsigned int));
221    mem+=sizeof(unsigned int);
222    memcpy(mem, &(this->classID), sizeof(unsigned int));
223    mem+=sizeof(unsigned int);
224    tempsize+=12;
225    // end copy header
226   
227   
228    COUT(5) << "Synchronisable getting data from objectID: " << objectID << " classID: " << classID << " length: " << size << std::endl;
229    // copy to location
230    for(i=syncList->begin(); i!=syncList->end(); ++i){
231      //(std::memcpy(retVal.data+n, (const void*)(&(i->size)), sizeof(int));
232      if( ((*i)->mode & mode) == 0 ){
233        COUT(5) << "not getting data: " << std::endl;
234        continue;  // this variable should only be received
235      }
236      switch((*i)->type){
237        case DATA:
238          memcpy( (void *)(mem), (void*)((*i)->var), (*i)->size);
239          mem+=(*i)->size;
240          tempsize+=(*i)->size;
241          break;
242        case STRING:
243          memcpy( (void *)(mem), (void *)&((*i)->size), sizeof(int) );
244          mem+=sizeof(int);
245          const char *data = ( ( *(std::string *) (*i)->var).c_str());
246          memcpy( mem, (void*)data, (*i)->size);
247          COUT(5) << "synchronisable: char: " << (const char *)(mem) << " data: " << data << " string: " << *(std::string *)((*i)->var) << std::endl;
248          mem+=(*i)->size;
249          tempsize+=(*i)->size + 4;
250          break;
251      }
252    }
253    assert(tempsize==size);
254    return true;
255  }
256
257  /*bool Synchronisable::getData(Bytestream& bs, int mode)
258  {
259    //std::cout << "inside getData" << std::endl;
260    if(mode==0x0)
261      mode=state_;
262    if(classID==0)
263      COUT(3) << "classid 0 " << this->getIdentifier()->getName() << std::endl;
264    this->classID=this->getIdentifier()->getNetworkID();
265    std::list<synchronisableVariable *>::iterator i;
266    bs << this->getSize();
267    bs << this->objectID;
268    bs << this->classID;
269    // copy to location
270    for(i=syncList->begin(); i!=syncList->end(); ++i){
271      if( ((*i)->mode & mode) == 0 ){
272        COUT(5) << "not getting data: " << std::endl;
273        continue;  // this variable should only be received
274      }
275      switch((*i)->type){
276        case DATA:
277          bs << *(*i)->var;
278          //std::memcpy( (void *)(retVal.data+n), (void*)((*i)->var), (*i)->size);
279          //n+=(*i)->size;
280          break;
281        case STRING:
282          bs << *(String *)((*i)->var);
283          //memcpy( (void *)(retVal.data+n), (void *)&((*i)->size), sizeof(int) );
284          //n+=sizeof(int);
285          //const char *data = ( ( *(std::string *) (*i)->var).c_str());
286          //std::memcpy( retVal.data+n, (void*)data, (*i)->size);
287          //COUT(5) << "synchronisable: char: " << (const char *)(retVal.data+n) << " data: " << data << " string: " << *(std::string *)((*i)->var) << std::endl;
288          //n+=(*i)->size;
289          break;
290      }
291    }
292    return true;
293  }*/
294
295 
296  /**
297  * This function takes a syncData struct and takes it to update the variables
298  * @param vars data of the variables
299  * @return true/false
300  */
301  bool Synchronisable::updateData(syncData vars, int mode){
302    if(mode==0x0)
303      mode=state_;
304    unsigned char *data=vars.data;
305    std::list<synchronisableVariable *>::iterator i;
306    if(syncList->empty()){
307      COUT(4) << "Synchronisable::updateData syncList is empty" << std::endl;
308      return false;
309    }
310    COUT(5) << "Synchronisable: objectID " << vars.objectID << ", classID " << vars.classID << " size: " << vars.length << " synchronising data" << std::endl;
311    for(i=syncList->begin(); i!=syncList->end(); i++){
312      if( ((*i)->mode ^ mode) == 0 ){
313        COUT(5) << "synchronisable: not updating variable " << std::endl;
314        continue;  // this variable should only be set
315      }
316      COUT(5) << "Synchronisable: element size: " << (*i)->size << " type: " << (*i)->type << std::endl;
317      bool callback=false;
318      switch((*i)->type){
319      case DATA:
320        if((*i)->callback) // check whether this variable changed (but only if callback was set)
321          if(strncmp((char *)(*i)->var, (char *)data, (*i)->size)!=0)
322            callback=true;
323        memcpy((void*)(*i)->var, data, (*i)->size);
324        data+=(*i)->size;
325        break;
326      case STRING:
327        (*i)->size = *(int *)data;
328        COUT(5) << "string size: " << (*i)->size << std::endl;
329        data+=sizeof(int);
330        if((*i)->callback) // check whether this string changed
331          if( *(std::string *)((*i)->var) != std::string((char *)data) )
332            callback=true;
333        *((std::string *)((*i)->var)) = std::string((const char*)data);
334        COUT(5) << "synchronisable: char: " << (const char*)data << " string: " << std::string((const char*)data) << std::endl;
335        data += (*i)->size;
336        break;
337      }
338      // call the callback function, if defined
339      if(callback && (*i)->callback)
340        (*i)->callback->call();
341    }
342    return true;
343  }
344 
345  /**
346   * This function takes a syncData struct and takes it to update the variables
347   * @param vars data of the variables
348   * @return true/false
349   */
350  bool Synchronisable::updateData(unsigned char*& mem, int mode){
351    unsigned char *data = mem;
352    if(mode==0x0)
353      mode=state_;
354    std::list<synchronisableVariable *>::iterator i;
355    if(syncList->empty()){
356      COUT(4) << "Synchronisable::updateData syncList is empty" << std::endl;
357      return false;
358    }
359   
360    // start extract header
361    unsigned int objectID, classID, size;
362    size = *(int *)mem;
363    mem+=sizeof(size);
364    objectID = *(int *)mem;
365    mem+=sizeof(objectID);
366    classID = *(int *)mem;
367    mem+=sizeof(classID);
368    // stop extract header
369    assert(this->objectID==objectID);
370    assert(this->classID==classID);
371   
372    COUT(5) << "Synchronisable: objectID " << objectID << ", classID " << classID << " size: " << size << " synchronising data" << std::endl;
373    for(i=syncList->begin(); i!=syncList->end() && mem <= data+size; i++){
374      if( ((*i)->mode ^ mode) == 0 ){
375        COUT(5) << "synchronisable: not updating variable " << std::endl;
376        continue;  // this variable should only be set
377      }
378      COUT(5) << "Synchronisable: element size: " << (*i)->size << " type: " << (*i)->type << std::endl;
379      bool callback=false;
380      switch((*i)->type){
381        case DATA:
382          if((*i)->callback) // check whether this variable changed (but only if callback was set)
383            if(strncmp((char *)(*i)->var, (char *)mem, (*i)->size)!=0)
384              callback=true;
385          memcpy((void*)(*i)->var, mem, (*i)->size);
386          mem+=(*i)->size;
387          break;
388        case STRING:
389          (*i)->size = *(int *)mem;
390          COUT(5) << "string size: " << (*i)->size << std::endl;
391          mem+=sizeof(int);
392          if((*i)->callback) // check whether this string changed
393            if( *(std::string *)((*i)->var) != std::string((char *)mem) )
394              callback=true;
395          *((std::string *)((*i)->var)) = std::string((const char*)mem);
396          COUT(5) << "synchronisable: char: " << (const char*)mem << " string: " << std::string((const char*)mem) << std::endl;
397          mem += (*i)->size;
398          break;
399      }
400      // call the callback function, if defined
401      if(callback && (*i)->callback)
402        (*i)->callback->call();
403    }
404    return true;
405  }
406
407  /**
408  * This function returns the total amount of bytes needed by getData to save the whole content of the variables
409  * @return amount of bytes
410  */
411  int Synchronisable::getSize(int mode){
412    int tsize=0;
413    if(mode==0x0)
414      mode=state_;
415    std::list<synchronisableVariable *>::iterator i;
416    for(i=syncList->begin(); i!=syncList->end(); i++){
417      if( ((*i)->mode & mode) == 0 )
418        continue;  // this variable should only be received, so dont add its size to the send-size
419      switch((*i)->type){
420      case DATA:
421        tsize+=(*i)->size;
422        break;
423      case STRING:
424        tsize+=sizeof(int);
425        (*i)->size=((std::string *)(*i)->var)->length()+1;
426        COUT(5) << "String size: " << (*i)->size << std::endl;
427        tsize+=(*i)->size;
428        break;
429      }
430    }
431    return tsize;
432  }
433 
434  /**
435   * This function returns the total amount of bytes needed by getData to save the whole content of the variables
436   * @return amount of bytes
437   */
438  int Synchronisable::getSize2(int mode){
439    return 3*sizeof(unsigned int) + getSize( mode );
440  }
441 
442  bool Synchronisable::isMyData(unsigned char* mem)
443  {
444    unsigned int objectID, classID, size;
445    size = *(int *)mem;
446    mem+=sizeof(size);
447    objectID = *(int *)mem;
448    mem+=sizeof(objectID);
449    classID = *(int *)mem;
450    mem+=sizeof(classID);
451   
452    assert(classID == this->classID);
453    return (objectID == this->objectID);
454  }
455 
456  void Synchronisable::setBacksync(bool sync){
457    backsync_=sync;
458  }
459
460  bool Synchronisable::getBacksync(){
461    return backsync_;
462  }
463 
464}
Note: See TracBrowser for help on using the repository browser.