Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics_merge/src/network/synchronisable/Synchronisable.cc @ 2518

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

some cleaning up in TrafficControl
small bugfix in Gamestate
priorities should work quite well now

  • Property svn:eol-style set to native
  • Property svn:mergeinfo set to (toggle deleted branches)
    /code/branches/network/src/network/synchronisable/Synchronisable.ccmergedeligible
    /code/branches/ceguilua/src/network/Synchronisable.cc1802-1808
    /code/branches/core3/src/network/Synchronisable.cc1572-1739
    /code/branches/gcc43/src/network/Synchronisable.cc1580
    /code/branches/gui/src/network/Synchronisable.cc1635-1723
    /code/branches/input/src/network/Synchronisable.cc1629-1636
    /code/branches/objecthierarchy/src/network/Synchronisable.cc1911-2085,​2100,​2110-2169
    /code/branches/pickups/src/network/Synchronisable.cc1926-2086
    /code/branches/questsystem/src/network/Synchronisable.cc1894-2088
    /code/branches/script_trigger/src/network/Synchronisable.cc1295-1953,​1955
    /code/branches/weapon/src/network/Synchronisable.cc1925-2094
File size: 14.8 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 <cstring>
44#include <string>
45#include <iostream>
46#include <assert.h>
47
48#include "core/CoreIncludes.h"
49#include "core/BaseObject.h"
50// #include "core/Identifier.h"
51
52#include "network/Host.h"
53namespace orxonox
54{
55
56  std::map<uint32_t, Synchronisable *> Synchronisable::objectMap_;
57  std::queue<uint32_t> Synchronisable::deletedObjects_;
58
59  uint8_t Synchronisable::state_=0x1; // detemines wheter we are server (default) or client
60
61  /**
62  * Constructor:
63  * Initializes all Variables and sets the right objectID
64  */
65  Synchronisable::Synchronisable(BaseObject* creator){
66    RegisterRootObject(Synchronisable);
67    static uint32_t idCounter=0;
68    objectMode_=0x1; // by default do not send data to server
69    if ( !Host::running() || ( Host::running() && Host::isServer() ) )
70    {
71      this->objectID = idCounter++; //this is only needed when running a server
72    //add synchronisable to the objectMap
73      objectMap_[this->objectID] = this;
74    }
75    else
76      objectID=OBJECTID_UNKNOWN;
77    classID = static_cast<uint32_t>(-1);
78
79    // set standard priority
80    this->setPriority( priority::normal );
81
82   
83    // get creator id
84#ifndef NDEBUG
85    ObjectList<Synchronisable>::iterator it;
86    for(it = ObjectList<Synchronisable>::begin(); it!=ObjectList<Synchronisable>::end(); ++it){
87      if( it->getObjectID()==this->objectID )
88        assert(*it==this || (it->objectID==OBJECTID_UNKNOWN && it->objectMode_==0x0));
89    }
90#endif
91
92    this->creatorID = OBJECTID_UNKNOWN;
93
94    searchcreatorID:
95    if (creator)
96    {
97        Synchronisable* synchronisable_creator = dynamic_cast<Synchronisable*>(creator);
98        if (synchronisable_creator && synchronisable_creator->objectMode_)
99        {
100            this->creatorID = synchronisable_creator->getObjectID();
101        }
102        else if (creator != creator->getCreator())
103        {
104            creator = creator->getCreator();
105            goto searchcreatorID;
106        }
107    }
108  }
109
110  /**
111   * Destructor:
112   * Delete all callback objects and remove objectID from the objectMap_
113   */
114  Synchronisable::~Synchronisable(){
115    // delete callback function objects
116    if(!Identifier::isCreatingHierarchy()){
117      for(std::list<SynchronisableVariableBase*>::iterator it = syncList.begin(); it!=syncList.end(); it++)
118        delete (*it);
119      if (this->objectMode_ != 0x0 && (Host::running() && Host::isServer()))
120        deletedObjects_.push(objectID);
121//       COUT(3) << "destruct synchronisable +++" << objectID << " | " << classID << std::endl;
122//       COUT(3) << " bump ---" << objectID << " | " << &objectMap_ << std::endl;
123//       assert(objectMap_[objectID]->objectID==objectID);
124//       objectMap_.erase(objectID);
125    }
126    std::map<uint32_t, Synchronisable*>::iterator it;
127    it = objectMap_.find(objectID);
128    if (it != objectMap_.end())
129      objectMap_.erase(it);
130  }
131
132
133  /**
134   * This function sets the internal mode for synchronisation
135   * @param b true if this object is located on a client or on a server
136   */
137  void Synchronisable::setClient(bool b){
138    if(b) // client
139      state_=0x2;
140    else  // server
141      state_=0x1;
142  }
143
144  /**
145   * This function fabricated a new synchrnisable (and children of it), sets calls updateData and create
146   * After calling this function the mem pointer will be increased by the size of the needed data
147   * @param mem pointer to where the appropriate data is located
148   * @param mode defines the mode, how the data should be loaded
149   * @return pointer to the newly created synchronisable
150   */
151  Synchronisable *Synchronisable::fabricate(uint8_t*& mem, uint8_t mode)
152  {
153    synchronisableHeader *header = (synchronisableHeader *)mem;
154
155    if(!header->dataAvailable)
156    {
157      mem += header->size;
158      return 0;
159    }
160
161    COUT(4) << "fabricating object with id: " << header->objectID << std::endl;
162
163    Identifier* id = ClassByID(header->classID);
164    assert(id);
165    BaseObject* creator = 0;
166    if (header->creatorID != OBJECTID_UNKNOWN)
167    {
168      Synchronisable* synchronisable_creator = Synchronisable::getSynchronisable(header->creatorID);
169      if (!synchronisable_creator)
170      {
171        mem += header->size; //.TODO: this suckz.... remove size from header
172        assert(0);
173        return 0;
174      }
175      else
176        creator = dynamic_cast<BaseObject*>(synchronisable_creator);
177    }
178    assert(getSynchronisable(header->objectID)==0);   //make sure no object with this id exists
179    BaseObject *bo = id->fabricate(creator);
180    assert(bo);
181    Synchronisable *no = dynamic_cast<Synchronisable *>(bo);
182    assert(no);
183    no->objectID=header->objectID;
184    no->creatorID=header->creatorID; //TODO: remove this
185    no->classID=header->classID;
186    COUT(4) << "fabricate objectID: " << no->objectID << " classID: " << no->classID << std::endl;
187          // update data and create object/entity...
188    bool b = no->updateData(mem, mode, true);
189    assert(b);
190    if (b)
191    {
192//        b = no->create();
193        assert(b);
194    }
195    return no;
196  }
197
198
199  /**
200   * Finds and deletes the Synchronisable with the appropriate objectID
201   * @param objectID objectID of the Synchronisable
202   * @return true/false
203   */
204  bool Synchronisable::deleteObject(uint32_t objectID){
205//     assert(getSynchronisable(objectID));
206    if(!getSynchronisable(objectID))
207      return false;
208    assert(getSynchronisable(objectID)->objectID==objectID);
209//     delete objectMap_[objectID];
210    Synchronisable *s = getSynchronisable(objectID);
211    if(s)
212      delete s;
213    else
214      return false;
215    return true;
216  }
217
218  /**
219   * This function looks up the objectID in the objectMap_ and returns a pointer to the right Synchronisable
220   * @param objectID objectID of the Synchronisable
221   * @return pointer to the Synchronisable with the objectID
222   */
223  Synchronisable* Synchronisable::getSynchronisable(uint32_t objectID){
224    std::map<uint32_t, Synchronisable*>::iterator it1;
225    it1 = objectMap_.find(objectID);
226    if (it1 != objectMap_.end())
227      return it1->second;
228
229    ObjectList<Synchronisable>::iterator it;
230    for(it = ObjectList<Synchronisable>::begin(); it; ++it){
231      if( it->getObjectID()==objectID ){
232        objectMap_[objectID] = *it;
233        return *it;
234      }
235    }
236    return NULL;
237  }
238
239
240  /**
241  * This function is used to register a variable to be synchronized
242  * also counts the total datasize needed to save the variables
243  * @param var pointer to the variable
244  * @param size size of the datatype the variable consists of
245  * @param t the type of the variable (DATA or STRING
246  * @param mode same as in getData
247  * @param cb callback object that should get called, if the value of the variable changes
248  */
249
250/*  void Synchronisable::registerVariable(void *var, int size, variableType t, uint8_t mode, NetworkCallbackBase *cb){
251    assert( mode==direction::toclient || mode==direction::toserver || mode==direction::serverMaster || mode==direction::clientMaster);
252    // create temporary synch.Var struct
253    synchronisableVariable *temp = new synchronisableVariable;
254    temp->size = size;
255    temp->var = var;
256    temp->mode = mode;
257    temp->type = t;
258    temp->callback = cb;
259    if( ( mode & direction::bidirectional ) )
260    {
261      if(t!=STRING)
262      {
263        temp->varBuffer = new uint8_t[size];
264        memcpy(temp->varBuffer, temp->var, size); //now fill the buffer for the first time
265      }
266      else
267      {
268        temp->varBuffer=new std::string( *static_cast<std::string*>(var) );
269      }
270      temp->varReference = 0;
271    }
272    COUT(5) << "Syncronisable::registering var with size: " << temp->size << " and type: " << temp->type << std::endl;
273    //std::cout << "push temp to syncList (at the bottom) " << datasize << std::endl;
274    COUT(5) << "Syncronisable::objectID: " << objectID << " this: " << this << " name: " << this->getIdentifier()->getName() << " networkID: " << this->getIdentifier()->getNetworkID() << std::endl;
275    syncList->push_back(temp);
276#ifndef NDEBUG
277    std::list<synchronisableVariable *>::iterator it = syncList->begin();
278    while(it!=syncList->end()){
279      assert(*it!=var);
280      it++;
281    }
282#endif
283  }*/
284 
285
286  /**
287   * This function takes all SynchronisableVariables out of the Synchronisable and saves them together with the size, objectID and classID to the given memory
288   * takes a pointer to already allocated memory (must have at least getSize bytes length)
289   * structure of the bitstream:
290   * |totalsize,objectID,classID,var1,var2,string1_length,string1,var3,...|
291   * length of varx: size saved int syncvarlist
292   * @param mem pointer to allocated memory with enough size
293   * @param id gamestateid of the gamestate to be saved (important for priorities)
294   * @param mode defines the direction in which the data will be send/received
295   *             0x1: server->client
296   *             0x2: client->server (not recommended)
297   *             0x3: bidirectional
298   * @return true: if !doSync or if everything was successfully saved
299   */
300  bool Synchronisable::getData(uint8_t*& mem, int32_t id, uint8_t mode){
301    if(mode==0x0)
302      mode=state_;
303    //if this tick is we dont synchronise, then abort now
304    if(!doSync(id, mode))
305      return true;
306    //std::cout << "inside getData" << std::endl;
307    uint32_t tempsize = 0;
308    if (this->classID==0)
309      COUT(3) << "classid 0 " << this->getIdentifier()->getName() << std::endl;
310
311    if (this->classID == static_cast<uint32_t>(-1))
312        this->classID = this->getIdentifier()->getNetworkID();
313
314    assert(this->classID==this->getIdentifier()->getNetworkID());
315//     this->classID=this->getIdentifier()->getNetworkID(); // TODO: correct this
316    std::list<SynchronisableVariableBase*>::iterator i;
317    uint32_t size;
318    size=getSize(id, mode);
319
320    // start copy header
321    synchronisableHeader *header = (synchronisableHeader *)mem;
322    header->size = size;
323    header->objectID = this->objectID;
324    header->creatorID = this->creatorID;
325    header->classID = this->classID;
326    header->dataAvailable = true;
327    tempsize += sizeof(synchronisableHeader);
328    mem += sizeof(synchronisableHeader);
329    // end copy header
330
331
332    COUT(5) << "Synchronisable getting data from objectID: " << objectID << " classID: " << classID << " length: " << size << std::endl;
333    // copy to location
334    for(i=syncList.begin(); i!=syncList.end(); ++i){
335      (*i)->getData( mem, mode );
336      tempsize += (*i)->getSize( mode );
337    }
338    assert(tempsize==size);
339    return true;
340  }
341
342
343  /**
344   * This function takes a bytestream and loads the data into the registered variables
345   * @param mem pointer to the bytestream
346   * @param mode same as in getData
347   * @return true/false
348   */
349  bool Synchronisable::updateData(uint8_t*& mem, uint8_t mode, bool forceCallback){
350    if(mode==0x0)
351      mode=state_;
352    std::list<SynchronisableVariableBase *>::iterator i;
353    //assert(objectMode_!=0x0);
354    //assert( (mode ^ objectMode_) != 0);
355    if(syncList.empty()){
356      assert(0);
357      COUT(4) << "Synchronisable::updateData syncList is empty" << std::endl;
358      return false;
359    }
360
361    uint8_t* data=mem;
362    // start extract header
363    synchronisableHeader *syncHeader = (synchronisableHeader *)mem;
364    assert(syncHeader->objectID==this->objectID);
365    assert(syncHeader->creatorID==this->creatorID);
366    assert(this->classID==syncHeader->classID); //TODO: fix this!!! maybe a problem with the identifier ?
367    if(syncHeader->dataAvailable==false){
368      mem += syncHeader->size;
369      return true;
370    }
371
372    mem += sizeof(synchronisableHeader);
373    // stop extract header
374
375    COUT(5) << "Synchronisable: objectID " << syncHeader->objectID << ", classID " << syncHeader->classID << " size: " << syncHeader->size << " synchronising data" << std::endl;
376    for(i=syncList.begin(); i!=syncList.end() && mem <= data+syncHeader->size; i++)
377    {
378      (*i)->putData( mem, mode, forceCallback );
379    }
380    assert(mem == data+syncHeader->size);
381    return true;
382  }
383
384  /**
385  * This function returns the total amount of bytes needed by getData to save the whole content of the variables
386  * @param id id of the gamestate
387  * @param mode same as getData
388  * @return amount of bytes
389  */
390  uint32_t Synchronisable::getSize(int32_t id, uint8_t mode){
391    int tsize=sizeof(synchronisableHeader);
392    if(mode==0x0)
393      mode=state_;
394    if(!doSync(id, mode))
395      return 0;
396    std::list<SynchronisableVariableBase*>::iterator i;
397    for(i=syncList.begin(); i!=syncList.end(); i++){
398      tsize += (*i)->getSize( mode );
399    }
400    return tsize;
401  }
402
403  /**
404   * This function determines, wheter the object should be saved to the bytestream (according to its syncmode/direction)
405   * @param id gamestate id
406   * @return true/false
407   */
408  bool Synchronisable::doSync(int32_t id, uint8_t mode){
409    if(mode==0x0)
410      mode=state_;
411    return ( (objectMode_&mode)!=0 && (!syncList.empty() ) );
412  }
413
414  bool Synchronisable::doSelection(int32_t id){
415    return true; //TODO: change this
416    //return ( id==0 || id%objectFrequency_==objectID%objectFrequency_ ) && ((objectMode_&state_)!=0);
417  }
418
419  /**
420   * This function looks at the header located in the bytestream and checks wheter objectID and classID match with the Synchronisables ones
421   * @param mem pointer to the bytestream
422   */
423  bool Synchronisable::isMyData(uint8_t* mem)
424  {
425    synchronisableHeader *header = (synchronisableHeader *)mem;
426    assert(header->objectID==this->objectID);
427    return header->dataAvailable;
428  }
429
430  /**
431   * This function sets the synchronisation mode of the object
432   * If set to 0x0 variables will not be synchronised at all
433   * If set to 0x1 variables will only be synchronised to the client
434   * If set to 0x2 variables will only be synchronised to the server
435   * If set to 0x3 variables will be synchronised bidirectionally (only if set so in registerVar)
436   * @param mode same as in registerVar
437   */
438  void Synchronisable::setObjectMode(uint8_t mode){
439    assert(mode==0x0 || mode==0x1 || mode==0x2 || mode==0x3);
440    objectMode_=mode;
441  }
442 
443
444}
Note: See TracBrowser for help on using the repository browser.