Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/questsystem5/src/network/synchronisable/Synchronisable.cc @ 2961

Last change on this file since 2961 was 2908, checked in by dafrick, 16 years ago

Reverted to revision 2906 (because I'm too stupid to merge correctly, 2nd try will follow shortly. ;))

  • 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: 12.3 KB
RevLine 
[1505]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
[1837]33#include <cstring>
[2087]34#include <string>
[1505]35#include <iostream>
[2773]36#include <cassert>
[1505]37
38#include "core/CoreIncludes.h"
[1735]39#include "core/BaseObject.h"
[1534]40// #include "core/Identifier.h"
[1505]41
[2211]42#include "network/Host.h"
[2171]43namespace orxonox
[1505]44{
[1639]45
[2309]46  std::map<uint32_t, Synchronisable *> Synchronisable::objectMap_;
47  std::queue<uint32_t> Synchronisable::deletedObjects_;
[1639]48
[2171]49  uint8_t Synchronisable::state_=0x1; // detemines wheter we are server (default) or client
[1639]50
[1505]51  /**
52  * Constructor:
[1907]53  * Initializes all Variables and sets the right objectID
[1505]54  */
[2171]55  Synchronisable::Synchronisable(BaseObject* creator){
[1505]56    RegisterRootObject(Synchronisable);
[1907]57    static uint32_t idCounter=0;
58    objectMode_=0x1; // by default do not send data to server
[2171]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;
[2309]67    classID = static_cast<uint32_t>(-1);
[2087]68
[2415]69    // set standard priority
70    this->setPriority( priority::normal );
[2171]71
[2415]72    // get creator id
[2087]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    }
[1505]89  }
90
[1907]91  /**
[2087]92   * Destructor:
[1907]93   * Delete all callback objects and remove objectID from the objectMap_
94   */
[1505]95  Synchronisable::~Synchronisable(){
[1534]96    // delete callback function objects
[2171]97    if(!Identifier::isCreatingHierarchy()){
[2245]98      for(std::list<SynchronisableVariableBase*>::iterator it = syncList.begin(); it!=syncList.end(); it++)
99        delete (*it);
[2171]100      if (this->objectMode_ != 0x0 && (Host::running() && Host::isServer()))
[2087]101        deletedObjects_.push(objectID);
[1907]102    }
[2309]103    std::map<uint32_t, Synchronisable*>::iterator it;
[2171]104    it = objectMap_.find(objectID);
105    if (it != objectMap_.end())
106      objectMap_.erase(it);
[2485]107
[1505]108  }
[1639]109
[2087]110
[1907]111  /**
112   * This function sets the internal mode for synchronisation
113   * @param b true if this object is located on a client or on a server
114   */
[1505]115  void Synchronisable::setClient(bool b){
116    if(b) // client
117      state_=0x2;
118    else  // server
119      state_=0x1;
120  }
[1856]121
[1907]122  /**
123   * This function fabricated a new synchrnisable (and children of it), sets calls updateData and create
124   * After calling this function the mem pointer will be increased by the size of the needed data
125   * @param mem pointer to where the appropriate data is located
126   * @param mode defines the mode, how the data should be loaded
127   * @return pointer to the newly created synchronisable
128   */
[2171]129  Synchronisable *Synchronisable::fabricate(uint8_t*& mem, uint8_t mode)
[1735]130  {
[2662]131    SynchronisableHeader header(mem);
[1856]132
[2662]133    if(!header.isDataAvailable())
[2087]134    {
[2662]135      mem += header.getDataSize();
[2087]136      return 0;
137    }
[2171]138
[2662]139    COUT(4) << "fabricating object with id: " << header.getObjectID() << std::endl;
[1856]140
[2662]141    Identifier* id = ClassByID(header.getClassID());
[2485]142    if (!id)
143    {
[2759]144        for(int i = 0; i<100; i++)
145            COUT(0) << "classid: " << i << " identifier: " << ClassByID(i) << endl;
[2485]146        COUT(0) << "Assertion failed: id" << std::endl;
147        COUT(0) << "Possible reason for this error: Client received a synchronizable object whose class has no factory." << std::endl;
148        abort();
149    }
[1907]150    assert(id);
[2171]151    BaseObject* creator = 0;
[2662]152    if (header.getCreatorID() != OBJECTID_UNKNOWN)
[2087]153    {
[2662]154      Synchronisable* synchronisable_creator = Synchronisable::getSynchronisable(header.getCreatorID());
[2087]155      if (!synchronisable_creator)
156      {
[2662]157        mem += header.getDataSize(); //.TODO: this suckz.... remove size from header
158        assert(0); // TODO: uncomment this if we have a clean objecthierarchy (with destruction of children of objects) ^^
[2087]159        return 0;
160      }
161      else
[2171]162        creator = dynamic_cast<BaseObject*>(synchronisable_creator);
[2087]163    }
[2662]164    assert(getSynchronisable(header.getObjectID())==0);   //make sure no object with this id exists
[2171]165    BaseObject *bo = id->fabricate(creator);
[2087]166    assert(bo);
[1735]167    Synchronisable *no = dynamic_cast<Synchronisable *>(bo);
168    assert(no);
[2662]169    no->objectID=header.getObjectID();
170    no->creatorID=header.getCreatorID(); //TODO: remove this
171    no->classID=header.getClassID();
[2087]172    COUT(4) << "fabricate objectID: " << no->objectID << " classID: " << no->classID << std::endl;
[1735]173          // update data and create object/entity...
[2087]174    bool b = no->updateData(mem, mode, true);
[1907]175    assert(b);
[2087]176    if (b)
177    {
[2245]178//        b = no->create();
[2087]179        assert(b);
180    }
[1907]181    return no;
182  }
183
[2087]184
[1907]185  /**
186   * Finds and deletes the Synchronisable with the appropriate objectID
187   * @param objectID objectID of the Synchronisable
188   * @return true/false
189   */
[2309]190  bool Synchronisable::deleteObject(uint32_t objectID){
[1907]191    if(!getSynchronisable(objectID))
[1735]192      return false;
[1907]193    assert(getSynchronisable(objectID)->objectID==objectID);
194    Synchronisable *s = getSynchronisable(objectID);
195    if(s)
196      delete s;
197    else
[1735]198      return false;
199    return true;
200  }
[2087]201
[1907]202  /**
203   * This function looks up the objectID in the objectMap_ and returns a pointer to the right Synchronisable
204   * @param objectID objectID of the Synchronisable
205   * @return pointer to the Synchronisable with the objectID
206   */
[2309]207  Synchronisable* Synchronisable::getSynchronisable(uint32_t objectID){
208    std::map<uint32_t, Synchronisable*>::iterator it1;
[2171]209    it1 = objectMap_.find(objectID);
210    if (it1 != objectMap_.end())
211      return it1->second;
212
213    ObjectList<Synchronisable>::iterator it;
214    for(it = ObjectList<Synchronisable>::begin(); it; ++it){
215      if( it->getObjectID()==objectID ){
216        objectMap_[objectID] = *it;
217        return *it;
218      }
[1907]219    }
220    return NULL;
221  }
222
[2087]223
[1505]224  /**
[1907]225   * This function takes all SynchronisableVariables out of the Synchronisable and saves them together with the size, objectID and classID to the given memory
[1735]226   * takes a pointer to already allocated memory (must have at least getSize bytes length)
[1751]227   * structure of the bitstream:
[1907]228   * |totalsize,objectID,classID,var1,var2,string1_length,string1,var3,...|
229   * length of varx: size saved int syncvarlist
230   * @param mem pointer to allocated memory with enough size
231   * @param id gamestateid of the gamestate to be saved (important for priorities)
232   * @param mode defines the direction in which the data will be send/received
233   *             0x1: server->client
234   *             0x2: client->server (not recommended)
235   *             0x3: bidirectional
[2087]236   * @return true: if !doSync or if everything was successfully saved
[1735]237   */
[2309]238  bool Synchronisable::getData(uint8_t*& mem, int32_t id, uint8_t mode){
[2171]239    if(mode==0x0)
240      mode=state_;
[1907]241    //if this tick is we dont synchronise, then abort now
[2171]242    if(!doSync(id, mode))
[1907]243      return true;
[2309]244    uint32_t tempsize = 0;
[2316]245    if (this->classID==0)
[1735]246      COUT(3) << "classid 0 " << this->getIdentifier()->getName() << std::endl;
[2087]247
[2309]248    if (this->classID == static_cast<uint32_t>(-1))
[2087]249        this->classID = this->getIdentifier()->getNetworkID();
250
[1907]251    assert(this->classID==this->getIdentifier()->getNetworkID());
[2245]252    std::list<SynchronisableVariableBase*>::iterator i;
[2309]253    uint32_t size;
[1907]254    size=getSize(id, mode);
[1856]255
[1735]256    // start copy header
[2662]257    SynchronisableHeader header(mem);
258    header.setDataSize( size );
259    header.setObjectID( this->objectID );
260    header.setCreatorID( this->creatorID );
261    header.setClassID( this->classID );
262    header.setDataAvailable( true );
263    tempsize += SynchronisableHeader::getSize();
264    mem += SynchronisableHeader::getSize();
[1735]265    // end copy header
[1856]266
267
[1735]268    COUT(5) << "Synchronisable getting data from objectID: " << objectID << " classID: " << classID << " length: " << size << std::endl;
269    // copy to location
[2245]270    for(i=syncList.begin(); i!=syncList.end(); ++i){
271      (*i)->getData( mem, mode );
272      tempsize += (*i)->getSize( mode );
[1735]273    }
274    assert(tempsize==size);
275    return true;
276  }
[1505]277
[1856]278
[1505]279  /**
[1907]280   * This function takes a bytestream and loads the data into the registered variables
281   * @param mem pointer to the bytestream
282   * @param mode same as in getData
[1735]283   * @return true/false
284   */
[2171]285  bool Synchronisable::updateData(uint8_t*& mem, uint8_t mode, bool forceCallback){
[1735]286    if(mode==0x0)
287      mode=state_;
[2245]288    std::list<SynchronisableVariableBase *>::iterator i;
289    if(syncList.empty()){
[2419]290      assert(0);
[1735]291      COUT(4) << "Synchronisable::updateData syncList is empty" << std::endl;
292      return false;
293    }
[1856]294
[2245]295    uint8_t* data=mem;
[1735]296    // start extract header
[2662]297    SynchronisableHeader syncHeader(mem);
298    assert(syncHeader.getObjectID()==this->objectID);
299    assert(syncHeader.getCreatorID()==this->creatorID);
300    assert(syncHeader.getClassID()==this->classID);
301    if(syncHeader.isDataAvailable()==false){
302      mem += syncHeader.getDataSize();
[1751]303      return true;
[1907]304    }
[1856]305
[2662]306    mem += SynchronisableHeader::getSize();
[1907]307    // stop extract header
[2087]308
[2662]309    //COUT(5) << "Synchronisable: objectID " << syncHeader.getObjectID() << ", classID " << syncHeader.getClassID() << " size: " << syncHeader.getDataSize() << " synchronising data" << std::endl;
310    for(i=syncList.begin(); i!=syncList.end(); i++)
[2245]311    {
[2662]312      assert( mem <= data+syncHeader.getDataSize() ); // always make sure we don't exceed the datasize in our stream
[2245]313      (*i)->putData( mem, mode, forceCallback );
[1735]314    }
[2662]315    assert(mem == data+syncHeader.getDataSize());
[1735]316    return true;
317  }
[1505]318
319  /**
320  * This function returns the total amount of bytes needed by getData to save the whole content of the variables
[1907]321  * @param id id of the gamestate
322  * @param mode same as getData
[1505]323  * @return amount of bytes
324  */
[2309]325  uint32_t Synchronisable::getSize(int32_t id, uint8_t mode){
[2662]326    int tsize=SynchronisableHeader::getSize();
[1505]327    if(mode==0x0)
328      mode=state_;
[2171]329    if(!doSync(id, mode))
330      return 0;
[2245]331    std::list<SynchronisableVariableBase*>::iterator i;
332    for(i=syncList.begin(); i!=syncList.end(); i++){
333      tsize += (*i)->getSize( mode );
[1505]334    }
335    return tsize;
336  }
[1639]337
[1735]338  /**
[1907]339   * This function determines, wheter the object should be saved to the bytestream (according to its syncmode/direction)
340   * @param id gamestate id
341   * @return true/false
[1735]342   */
[2309]343  bool Synchronisable::doSync(int32_t id, uint8_t mode){
[2171]344    if(mode==0x0)
345      mode=state_;
[2245]346    return ( (objectMode_&mode)!=0 && (!syncList.empty() ) );
[1735]347  }
[1856]348
[1907]349  /**
350   * This function looks at the header located in the bytestream and checks wheter objectID and classID match with the Synchronisables ones
351   * @param mem pointer to the bytestream
352   */
353  bool Synchronisable::isMyData(uint8_t* mem)
[1735]354  {
[2662]355    SynchronisableHeader header(mem);
356    assert(header.getObjectID()==this->objectID);
357    return header.isDataAvailable();
[1735]358  }
[1856]359
[1907]360  /**
361   * This function sets the synchronisation mode of the object
[2171]362   * If set to 0x0 variables will not be synchronised at all
[1907]363   * If set to 0x1 variables will only be synchronised to the client
364   * If set to 0x2 variables will only be synchronised to the server
365   * If set to 0x3 variables will be synchronised bidirectionally (only if set so in registerVar)
366   * @param mode same as in registerVar
367   */
[2171]368  void Synchronisable::setObjectMode(uint8_t mode){
[2087]369    assert(mode==0x0 || mode==0x1 || mode==0x2 || mode==0x3);
[1751]370    objectMode_=mode;
[1505]371  }
372
[2485]373
[1505]374}
Note: See TracBrowser for help on using the repository browser.