Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/miniprojects/src/network/synchronisable/Synchronisable.cc @ 2830

Last change on this file since 2830 was 2710, checked in by rgrieder, 16 years ago

Merged buildsystem3 containing buildsystem2 containing Adi's buildsystem branch back to the trunk.
Please update the media directory if you were not using buildsystem3 before.

  • Property svn:eol-style set to native
  • Property svn:mergeinfo set to (toggle deleted branches)
    /code/branches/buildsystem3/src/network/synchronisable/Synchronisable.cc2662-2708
    /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/network/src/network/synchronisable/Synchronisable.cc2356
    /code/branches/objecthierarchy/src/network/Synchronisable.cc1911-2085,​2100,​2110-2169
    /code/branches/physics_merge/src/network/synchronisable/Synchronisable.cc2436-2457
    /code/branches/pickups/src/network/Synchronisable.cc1926-2086
    /code/branches/presentation/src/network/synchronisable/Synchronisable.cc2654-2660
    /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: 13.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#include "Synchronisable.h"
32
33#include <cstring>
34#include <string>
35#include <iostream>
36#include <assert.h>
37
38#include "core/CoreIncludes.h"
39#include "core/BaseObject.h"
40// #include "core/Identifier.h"
41
42#include "network/Host.h"
43namespace orxonox
44{
45
46  std::map<uint32_t, Synchronisable *> Synchronisable::objectMap_;
47  std::queue<uint32_t> Synchronisable::deletedObjects_;
48
49  uint8_t Synchronisable::state_=0x1; // detemines wheter we are server (default) or client
50
51  /**
52  * Constructor:
53  * Initializes all Variables and sets the right objectID
54  */
55  Synchronisable::Synchronisable(BaseObject* creator){
56    RegisterRootObject(Synchronisable);
57    static uint32_t idCounter=0;
58    objectMode_=0x1; // by default do not send data to server
59    if ( !Host::running() || ( Host::running() && Host::isServer() ) )
60    {
61      this->objectID = idCounter++; //this is only needed when running a server
62    //add synchronisable to the objectMap
63      objectMap_[this->objectID] = this;
64    }
65    else
66      objectID=OBJECTID_UNKNOWN;
67    classID = static_cast<uint32_t>(-1);
68
69    // set standard priority
70    this->setPriority( priority::normal );
71
72    // get creator id
73    this->creatorID = OBJECTID_UNKNOWN;
74
75    searchcreatorID:
76    if (creator)
77    {
78        Synchronisable* synchronisable_creator = dynamic_cast<Synchronisable*>(creator);
79        if (synchronisable_creator && synchronisable_creator->objectMode_)
80        {
81            this->creatorID = synchronisable_creator->getObjectID();
82        }
83        else if (creator != creator->getCreator())
84        {
85            creator = creator->getCreator();
86            goto searchcreatorID;
87        }
88    }
89  }
90
91  /**
92   * Destructor:
93   * Delete all callback objects and remove objectID from the objectMap_
94   */
95  Synchronisable::~Synchronisable(){
96    // delete callback function objects
97    if(!Identifier::isCreatingHierarchy()){
98      for(std::list<SynchronisableVariableBase*>::iterator it = syncList.begin(); it!=syncList.end(); it++)
99        delete (*it);
100      if (this->objectMode_ != 0x0 && (Host::running() && Host::isServer()))
101        deletedObjects_.push(objectID);
102//       COUT(3) << "destruct synchronisable +++" << objectID << " | " << classID << std::endl;
103//       COUT(3) << " bump ---" << objectID << " | " << &objectMap_ << std::endl;
104//       assert(objectMap_[objectID]->objectID==objectID);
105//       objectMap_.erase(objectID);
106    }
107    std::map<uint32_t, Synchronisable*>::iterator it;
108    it = objectMap_.find(objectID);
109    if (it != objectMap_.end())
110      objectMap_.erase(it);
111
112    //HACK HACK HACK HACK HACK HACK
113    // this hack ensures that children of this object also get destroyed
114//     ObjectList<Synchronisable>::iterator it2, it3;
115//     // get total size of gamestate
116//     for(it2 = ObjectList<Synchronisable>::begin(); it2; ++it2)
117//     {
118//       if ( it2->getCreatorID() == this->objectID && it2->getCreatorID() != OBJECTID_UNKNOWN )
119//       {
120//         Synchronisable::deleteObject( it2->getObjectID() );
121//       }
122//     }
123    //HACK HACK HACK HACK HACK HACK
124  }
125
126
127  /**
128   * This function sets the internal mode for synchronisation
129   * @param b true if this object is located on a client or on a server
130   */
131  void Synchronisable::setClient(bool b){
132    if(b) // client
133      state_=0x2;
134    else  // server
135      state_=0x1;
136  }
137
138  /**
139   * This function fabricated a new synchrnisable (and children of it), sets calls updateData and create
140   * After calling this function the mem pointer will be increased by the size of the needed data
141   * @param mem pointer to where the appropriate data is located
142   * @param mode defines the mode, how the data should be loaded
143   * @return pointer to the newly created synchronisable
144   */
145  Synchronisable *Synchronisable::fabricate(uint8_t*& mem, uint8_t mode)
146  {
147    SynchronisableHeader header(mem);
148
149    if(!header.isDataAvailable())
150    {
151      mem += header.getDataSize();
152      return 0;
153    }
154
155    COUT(4) << "fabricating object with id: " << header.getObjectID() << std::endl;
156
157    Identifier* id = ClassByID(header.getClassID());
158    if (!id)
159    {
160        COUT(0) << "Assertion failed: id" << std::endl;
161        COUT(0) << "Possible reason for this error: Client received a synchronizable object whose class has no factory." << std::endl;
162        abort();
163    }
164    assert(id);
165    BaseObject* creator = 0;
166    if (header.getCreatorID() != OBJECTID_UNKNOWN)
167    {
168      Synchronisable* synchronisable_creator = Synchronisable::getSynchronisable(header.getCreatorID());
169      if (!synchronisable_creator)
170      {
171        mem += header.getDataSize(); //.TODO: this suckz.... remove size from header
172        assert(0); // TODO: uncomment this if we have a clean objecthierarchy (with destruction of children of objects) ^^
173        return 0;
174      }
175      else
176        creator = dynamic_cast<BaseObject*>(synchronisable_creator);
177    }
178    assert(getSynchronisable(header.getObjectID())==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.getObjectID();
184    no->creatorID=header.getCreatorID(); //TODO: remove this
185    no->classID=header.getClassID();
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 takes all SynchronisableVariables out of the Synchronisable and saves them together with the size, objectID and classID to the given memory
242   * takes a pointer to already allocated memory (must have at least getSize bytes length)
243   * structure of the bitstream:
244   * |totalsize,objectID,classID,var1,var2,string1_length,string1,var3,...|
245   * length of varx: size saved int syncvarlist
246   * @param mem pointer to allocated memory with enough size
247   * @param id gamestateid of the gamestate to be saved (important for priorities)
248   * @param mode defines the direction in which the data will be send/received
249   *             0x1: server->client
250   *             0x2: client->server (not recommended)
251   *             0x3: bidirectional
252   * @return true: if !doSync or if everything was successfully saved
253   */
254  bool Synchronisable::getData(uint8_t*& mem, int32_t id, uint8_t mode){
255    if(mode==0x0)
256      mode=state_;
257    //if this tick is we dont synchronise, then abort now
258    if(!doSync(id, mode))
259      return true;
260    //std::cout << "inside getData" << std::endl;
261    uint32_t tempsize = 0;
262    if (this->classID==0)
263      COUT(3) << "classid 0 " << this->getIdentifier()->getName() << std::endl;
264
265    if (this->classID == static_cast<uint32_t>(-1))
266        this->classID = this->getIdentifier()->getNetworkID();
267
268    assert(this->classID==this->getIdentifier()->getNetworkID());
269//     this->classID=this->getIdentifier()->getNetworkID(); // TODO: correct this
270    std::list<SynchronisableVariableBase*>::iterator i;
271    uint32_t size;
272    size=getSize(id, mode);
273
274    // start copy header
275    SynchronisableHeader header(mem);
276    header.setDataSize( size );
277    header.setObjectID( this->objectID );
278    header.setCreatorID( this->creatorID );
279    header.setClassID( this->classID );
280    header.setDataAvailable( true );
281    tempsize += SynchronisableHeader::getSize();
282    mem += SynchronisableHeader::getSize();
283    // end copy header
284
285
286    COUT(5) << "Synchronisable getting data from objectID: " << objectID << " classID: " << classID << " length: " << size << std::endl;
287    // copy to location
288    for(i=syncList.begin(); i!=syncList.end(); ++i){
289      (*i)->getData( mem, mode );
290      tempsize += (*i)->getSize( mode );
291    }
292    assert(tempsize==size);
293    return true;
294  }
295
296
297  /**
298   * This function takes a bytestream and loads the data into the registered variables
299   * @param mem pointer to the bytestream
300   * @param mode same as in getData
301   * @return true/false
302   */
303  bool Synchronisable::updateData(uint8_t*& mem, uint8_t mode, bool forceCallback){
304    if(mode==0x0)
305      mode=state_;
306    std::list<SynchronisableVariableBase *>::iterator i;
307    //assert(objectMode_!=0x0);
308    //assert( (mode ^ objectMode_) != 0);
309    if(syncList.empty()){
310      assert(0);
311      COUT(4) << "Synchronisable::updateData syncList is empty" << std::endl;
312      return false;
313    }
314
315    uint8_t* data=mem;
316    // start extract header
317    SynchronisableHeader syncHeader(mem);
318    assert(syncHeader.getObjectID()==this->objectID);
319    assert(syncHeader.getCreatorID()==this->creatorID);
320    assert(syncHeader.getClassID()==this->classID);
321    if(syncHeader.isDataAvailable()==false){
322      mem += syncHeader.getDataSize();
323      return true;
324    }
325
326    mem += SynchronisableHeader::getSize();
327    // stop extract header
328
329    //COUT(5) << "Synchronisable: objectID " << syncHeader.getObjectID() << ", classID " << syncHeader.getClassID() << " size: " << syncHeader.getDataSize() << " synchronising data" << std::endl;
330    for(i=syncList.begin(); i!=syncList.end(); i++)
331    {
332      assert( mem <= data+syncHeader.getDataSize() ); // always make sure we don't exceed the datasize in our stream
333      (*i)->putData( mem, mode, forceCallback );
334    }
335    assert(mem == data+syncHeader.getDataSize());
336    return true;
337  }
338
339  /**
340  * This function returns the total amount of bytes needed by getData to save the whole content of the variables
341  * @param id id of the gamestate
342  * @param mode same as getData
343  * @return amount of bytes
344  */
345  uint32_t Synchronisable::getSize(int32_t id, uint8_t mode){
346    int tsize=SynchronisableHeader::getSize();
347    if(mode==0x0)
348      mode=state_;
349    if(!doSync(id, mode))
350      return 0;
351    std::list<SynchronisableVariableBase*>::iterator i;
352    for(i=syncList.begin(); i!=syncList.end(); i++){
353      tsize += (*i)->getSize( mode );
354    }
355    return tsize;
356  }
357
358  /**
359   * This function determines, wheter the object should be saved to the bytestream (according to its syncmode/direction)
360   * @param id gamestate id
361   * @return true/false
362   */
363  bool Synchronisable::doSync(int32_t id, uint8_t mode){
364    if(mode==0x0)
365      mode=state_;
366    return ( (objectMode_&mode)!=0 && (!syncList.empty() ) );
367  }
368
369  /**
370   * This function looks at the header located in the bytestream and checks wheter objectID and classID match with the Synchronisables ones
371   * @param mem pointer to the bytestream
372   */
373  bool Synchronisable::isMyData(uint8_t* mem)
374  {
375    SynchronisableHeader header(mem);
376    assert(header.getObjectID()==this->objectID);
377    return header.isDataAvailable();
378  }
379
380  /**
381   * This function sets the synchronisation mode of the object
382   * If set to 0x0 variables will not be synchronised at all
383   * If set to 0x1 variables will only be synchronised to the client
384   * If set to 0x2 variables will only be synchronised to the server
385   * If set to 0x3 variables will be synchronised bidirectionally (only if set so in registerVar)
386   * @param mode same as in registerVar
387   */
388  void Synchronisable::setObjectMode(uint8_t mode){
389    assert(mode==0x0 || mode==0x1 || mode==0x2 || mode==0x3);
390    objectMode_=mode;
391  }
392
393
394}
Note: See TracBrowser for help on using the repository browser.