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