Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/network/Synchronisable.cc @ 1663

Last change on this file since 1663 was 1639, checked in by rgrieder, 16 years ago

merged nico's fixes for gcc 4.3 back to trunk.
I'm not going to delete branch yet.

  • Property svn:eol-style set to native
File size: 10.2 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 <string.h>
46
47#include "core/CoreIncludes.h"
48// #include "core/Identifier.h"
49
50namespace network
51{
52
53
54  int Synchronisable::state_=0x1; // detemines wheter we are server (default) or client
55
56  /**
57  * Constructor:
58  * calls registarAllVariables, that has to be implemented by the inheriting classID
59  */
60  Synchronisable::Synchronisable(){
61    RegisterRootObject(Synchronisable);
62    static int idCounter=0;
63    datasize=0;
64    objectID=idCounter++;
65    syncList = new std::list<synchronisableVariable *>;
66    //registerAllVariables();
67  }
68
69  Synchronisable::~Synchronisable(){
70    // delete callback function objects
71    if(!orxonox::Identifier::isCreatingHierarchy())
72      for(std::list<synchronisableVariable *>::iterator it = syncList->begin(); it!=syncList->end(); it++)
73        delete (*it)->callback;
74  }
75
76  bool Synchronisable::create(){
77    this->classID = this->getIdentifier()->getNetworkID();
78    COUT(4) << "creating synchronisable: setting classid from " << this->getIdentifier()->getName() << " to: " << classID << std::endl;
79    return true;
80  }
81
82  void Synchronisable::setClient(bool b){
83    if(b) // client
84      state_=0x2;
85    else  // server
86      state_=0x1;
87  }
88
89  /**
90  * This function is used to register a variable to be synchronized
91  * also counts the total datasize needed to save the variables
92  * @param var pointer to the variable
93  * @param size size of the datatype the variable consists of
94  */
95  void Synchronisable::registerVar(void *var, int size, variableType t, int mode, NetworkCallbackBase *cb){
96    // create temporary synch.Var struct
97    synchronisableVariable *temp = new synchronisableVariable;
98    temp->size = size;
99    temp->var = var;
100    temp->mode = mode;
101    temp->type = t;
102    temp->callback = cb;
103    COUT(5) << "Syncronisable::registering var with size: " << temp->size << " and type: " << temp->type << std::endl;
104    // increase datasize
105    datasize+=sizeof(int)+size;
106    //std::cout << "push temp to syncList (at the bottom) " << datasize << std::endl;
107    COUT(5) << "Syncronisable::objectID: " << objectID << " this: " << this << " name: " << this->getIdentifier()->getName() << " networkID: " << this->getIdentifier()->getNetworkID() << std::endl;
108    syncList->push_back(temp);
109  }
110
111  /**
112  * note: only use this function for debug use, because it's inefficient (in order to produce a gamestate, you have to copy the whole data again to another memory location after this process)
113  * This function takes all SynchronisableVariables out of the Synchronisable and saves it into a syncData struct
114  * structure of the bitstream:
115  * (var1_size,var1,var2_size,var2,...)
116  * varx_size: size = sizeof(int)
117  * varx: size = varx_size
118  * @return data containing all variables and their sizes
119  */
120  // syncData Synchronisable::getData(){
121  //   std::list<synchronisableVariable>::iterator i;
122  //   int totalsize=0;
123  //   //figure out size of data to be allocated
124  //   for(i=syncList->begin(); i!=syncList->end(); i++){
125  //     // increase size (size of variable and size of size of variable ;)
126  //     if(i->type == STRING)
127  //       totalsize+=sizeof(int)+((std::string *)i->var)->length()+1;
128  //     else
129  //       totalsize+=sizeof(int)+i->size;
130  //   }
131  //   syncData retVal;
132  //   retVal.objectID=this->objectID;
133  //   retVal.classID=this->classID;
134  //   retVal.length=totalsize;
135  //   // allocate memory
136  //   retVal.data = (unsigned char *)malloc(totalsize);
137  //   // copy to location
138  //   //CHANGED: REMOVED DECLARATION int n=0 FROM LOOP
139  //   int n=0;
140  //   for(i=syncList->begin(); n<totalsize && i!=syncList->end(); i++){
141  //     std::memcpy(retVal.data+n, (const void*)(i->size), sizeof(int));
142  //     n+=sizeof(int);
143  //     switch(i->type){
144  //     case STRING:
145  //       std::memcpy(retVal.data+n, (const void *)(((std::string *)i->var)->c_str()), ((std::string *)i->var)->length()+1);
146  //       n+=((std::string *)i->var)->length()+1;
147  //       break;
148  //     case DATA:
149  //       std::memcpy(retVal.data+n, ((const void*)i->var), i->size);
150  //       n+=i->size;
151  //       break;
152  //     }
153  //   }
154  //   return retVal;
155  // }
156  /**
157  * This function takes all SynchronisableVariables out of the Synchronisable and saves it into a syncData struct
158  * Difference to the above function:
159  * takes a pointer to already allocated memory (must have at least getSize bytes length)
160  * structure of the bitstream:
161  * (var1_size,var1,var2_size,var2,...)
162  * varx_size: size = sizeof(int)
163  * varx: size = varx_size
164  * @return data containing all variables and their sizes
165  */
166  syncData Synchronisable::getData(unsigned char *mem, int mode){
167    //std::cout << "inside getData" << std::endl;
168    if(mode==0x0)
169      mode=state_;
170    if(classID==0)
171      COUT(3) << "classid 0 " << this->getIdentifier()->getName() << std::endl;
172    this->classID=this->getIdentifier()->getNetworkID();
173    std::list<synchronisableVariable *>::iterator i;
174    syncData retVal;
175    retVal.objectID=this->objectID;
176    retVal.classID=this->classID;
177    retVal.length=getSize();
178    COUT(5) << "Synchronisable getting data from objectID: " << retVal.objectID << " classID: " << retVal.classID << " length: " << retVal.length << std::endl;
179    retVal.data=mem;
180    // copy to location
181    int n=0; //offset
182    for(i=syncList->begin(); n<datasize && i!=syncList->end(); ++i){
183      //(std::memcpy(retVal.data+n, (const void*)(&(i->size)), sizeof(int));
184      if( ((*i)->mode & mode) == 0 ){
185        COUT(5) << "not getting data: " << std::endl;
186        continue;  // this variable should only be received
187      }
188      switch((*i)->type){
189      case DATA:
190        memcpy( (void *)(retVal.data+n), (void*)((*i)->var), (*i)->size);
191        n+=(*i)->size;
192        break;
193      case STRING:
194        memcpy( (void *)(retVal.data+n), (void *)&((*i)->size), sizeof(int) );
195        n+=sizeof(int);
196        const char *data = ( ( *(std::string *) (*i)->var).c_str());
197        memcpy( retVal.data+n, (void*)data, (*i)->size);
198        COUT(5) << "synchronisable: char: " << (const char *)(retVal.data+n) << " data: " << data << " string: " << *(std::string *)((*i)->var) << std::endl;
199        n+=(*i)->size;
200        break;
201      }
202    }
203    return retVal;
204  }
205
206  /**
207  * This function takes a syncData struct and takes it to update the variables
208  * @param vars data of the variables
209  * @return true/false
210  */
211  bool Synchronisable::updateData(syncData vars, int mode){
212    if(mode==0x0)
213      mode=state_;
214    unsigned char *data=vars.data;
215    std::list<synchronisableVariable *>::iterator i;
216    if(syncList->empty()){
217      COUT(4) << "Synchronisable::updateData syncList is empty" << std::endl;
218      return false;
219    }
220    COUT(5) << "Synchronisable: objectID " << vars.objectID << ", classID " << vars.classID << " size: " << vars.length << " synchronising data" << std::endl;
221    for(i=syncList->begin(); i!=syncList->end(); i++){
222      if( ((*i)->mode ^ mode) == 0 ){
223        COUT(5) << "synchronisable: not updating variable " << std::endl;
224        continue;  // this variable should only be set
225      }
226      COUT(5) << "Synchronisable: element size: " << (*i)->size << " type: " << (*i)->type << std::endl;
227      bool callback=false;
228      switch((*i)->type){
229      case DATA:
230        if((*i)->callback) // check whether this variable changed (but only if callback was set)
231          if(strncmp((char *)(*i)->var, (char *)data, (*i)->size)!=0)
232            callback=true;
233        memcpy((void*)(*i)->var, data, (*i)->size);
234        data+=(*i)->size;
235        break;
236      case STRING:
237        (*i)->size = *(int *)data;
238        COUT(5) << "string size: " << (*i)->size << std::endl;
239        data+=sizeof(int);
240        if((*i)->callback) // check whether this string changed
241          if( *(std::string *)((*i)->var) != std::string((char *)data) )
242            callback=true;
243        *((std::string *)((*i)->var)) = std::string((const char*)data);
244        COUT(5) << "synchronisable: char: " << (const char*)data << " string: " << std::string((const char*)data) << std::endl;
245        data += (*i)->size;
246        break;
247      }
248      // call the callback function, if defined
249      if(callback)
250        (*i)->callback->call();
251    }
252    return true;
253  }
254
255  /**
256  * This function returns the total amount of bytes needed by getData to save the whole content of the variables
257  * @return amount of bytes
258  */
259  int Synchronisable::getSize(int mode){
260    int tsize=0;
261    if(mode==0x0)
262      mode=state_;
263    std::list<synchronisableVariable *>::iterator i;
264    for(i=syncList->begin(); i!=syncList->end(); i++){
265      if( ((*i)->mode & mode) == 0 )
266        continue;  // this variable should only be received, so dont add its size to the send-size
267      switch((*i)->type){
268      case DATA:
269        tsize+=(*i)->size;
270        break;
271      case STRING:
272        tsize+=sizeof(int);
273        (*i)->size=((std::string *)(*i)->var)->length()+1;
274        COUT(5) << "String size: " << (*i)->size << std::endl;
275        tsize+=(*i)->size;
276        break;
277      }
278    }
279    return tsize;
280  }
281
282  void Synchronisable::setBacksync(bool sync){
283    backsync_=sync;
284  }
285
286  bool Synchronisable::getBacksync(){
287    return backsync_;
288  }
289
290}
Note: See TracBrowser for help on using the repository browser.