Changeset 2662 for code/trunk/src/network/packet/Gamestate.cc
- Timestamp:
- Feb 14, 2009, 10:17:35 PM (15 years ago)
- Location:
- code/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
code/trunk
- Property svn:mergeinfo changed
-
code/trunk/src/network/packet/Gamestate.cc
r2171 r2662 28 28 29 29 #include "Gamestate.h" 30 #include "network/ClientInformation.h" 31 #include "network/GamestateHandler.h" 30 #include "../GamestateHandler.h" 31 #include "../synchronisable/Synchronisable.h" 32 #include "../TrafficControl.h" 33 #include "core/Core.h" 32 34 #include "core/CoreIncludes.h" 33 35 #include "core/Iterator.h" 34 36 35 37 #include <zlib.h> 36 #include < assert.h>38 #include <cassert> 37 39 38 40 … … 42 44 namespace packet { 43 45 44 #define GAMESTATE_START(data) (data + sizeof(GamestateHeader)) 45 #define GAMESTATE_HEADER(data) ((GamestateHeader *)data) 46 #define HEADER GAMESTATE_HEADER(data_) 47 46 #define GAMESTATE_START(data) (data + GamestateHeader::getSize()) 48 47 49 48 #define PACKET_FLAG_GAMESTATE ENET_PACKET_FLAG_RELIABLE 50 49 50 // Gamestate::Gamestate() 51 // { 52 // flags_ = flags_ | PACKET_FLAG_GAMESTATE; 53 // } 54 51 55 Gamestate::Gamestate() 52 56 { 53 57 flags_ = flags_ | PACKET_FLAG_GAMESTATE; 58 header_ = 0; 54 59 } 55 60 … … 58 63 { 59 64 flags_ = flags_ | PACKET_FLAG_GAMESTATE; 65 header_ = new GamestateHeader(data_); 60 66 } 61 67 … … 64 70 flags_ = flags_ | PACKET_FLAG_GAMESTATE; 65 71 data_=data; 72 header_ = new GamestateHeader(data_); 73 } 74 75 Gamestate::Gamestate(const Gamestate& g) : 76 Packet( *(Packet*)&g ) 77 { 78 flags_ = flags_ | PACKET_FLAG_GAMESTATE; 79 header_ = new GamestateHeader(data_); 66 80 } 67 81 … … 73 87 bool Gamestate::collectData(int id, uint8_t mode) 74 88 { 75 unsigned int tempsize=0, currentsize=0; 89 assert(this->header_==0); // make sure the header didn't exist before 90 uint32_t tempsize=0, currentsize=0; 76 91 assert(data_==0); 77 u nsigned int size = calcGamestateSize(id, mode);92 uint32_t size = calcGamestateSize(id, mode); 78 93 79 94 COUT(4) << "G.ST.Man: producing gamestate with id: " << id << std::endl; 80 95 if(size==0) 81 96 return false; 82 data_ = new u nsigned char[size + sizeof(GamestateHeader)];97 data_ = new uint8_t[size + GamestateHeader::getSize()]; 83 98 if(!data_){ 84 99 COUT(2) << "GameStateManager: could not allocate memory" << std::endl; 85 100 return false; 86 101 } 102 103 // create the header object 104 header_ = new GamestateHeader(data_); 87 105 88 106 //start collect data synchronisable by synchronisable 89 107 uint8_t *mem=data_; 90 mem +=sizeof(GamestateHeader);108 mem += GamestateHeader::getSize(); 91 109 ObjectList<Synchronisable>::iterator it; 92 110 for(it = ObjectList<Synchronisable>::begin(); it; ++it){ 111 112 #ifndef NDEBUG 93 113 tempsize=it->getSize(id, mode); 94 95 114 if(currentsize+tempsize > size){ 96 115 assert(0); // if we don't use multithreading this part shouldn't be neccessary … … 98 117 COUT(3) << "G.St.Man: need additional memory" << std::endl; 99 118 ObjectList<Synchronisable>::iterator temp = it; 100 int addsize=tempsize;119 uint32_t addsize=tempsize; 101 120 while(++temp) 102 121 addsize+=temp->getSize(id, mode); 103 data_ = (uint8_t *)realloc(data_, sizeof(GamestateHeader) + currentsize + addsize);122 data_ = (uint8_t *)realloc(data_, GamestateHeader::getSize() + currentsize + addsize); 104 123 if(!data_) 105 124 return false; 106 125 size = currentsize+addsize; 107 126 }// stop allocate additional memory 108 127 #endif 109 128 110 129 //if(it->doSelection(id)) 111 dataMap_[mem-data_]=(*it); // save the mem location of the synchronisable data 130 if ( it->doSync( id, mode ) ) 131 dataMap_.push_back( obj(it->getObjectID(), it->getCreatorID(), tempsize, mem-data_) ); 132 // dataMap_[mem-data_]=(*it); // save the mem location of the synchronisable data 112 133 if(!it->getData(mem, id, mode)) 113 134 return false; // mem pointer gets automatically increased because of call by reference … … 118 139 119 140 //start write gamestate header 120 HEADER->packetType = ENUM::Gamestate; 121 HEADER->datasize = currentsize; 122 HEADER->id = id; 123 HEADER->diffed = false; 124 HEADER->complete = true; 125 HEADER->compressed = false; 141 header_->setDataSize( currentsize ); 142 header_->setID( id ); 143 header_->setDiffed( false ); 144 header_->setComplete( true ); 145 header_->setCompressed( false ); 126 146 //stop write gamestate header 127 147 … … 133 153 bool Gamestate::spreadData(uint8_t mode) 134 154 { 135 assert(data_); 136 assert(!HEADER->compressed); 137 assert(!HEADER->diffed); 138 uint8_t *mem=data_+sizeof(GamestateHeader); 155 COUT(4) << "processing gamestate with id " << header_->getID() << endl; 156 assert(data_); 157 assert(!header_->isCompressed()); 158 assert(!header_->isDiffed()); 159 uint8_t *mem=data_+GamestateHeader::getSize(); 139 160 // get the start of the Synchronisable list 140 161 //ObjectList<Synchronisable>::iterator it=ObjectList<Synchronisable>::begin(); … … 142 163 143 164 // update the data of the objects we received 144 while(mem < data_+ sizeof(GamestateHeader)+HEADER->datasize){145 synchronisableHeader *objectheader = (synchronisableHeader*)mem;146 147 s = Synchronisable::getSynchronisable( objectheader ->objectID);165 while(mem < data_+GamestateHeader::getSize()+header_->getDataSize()){ 166 SynchronisableHeader objectheader(mem); 167 168 s = Synchronisable::getSynchronisable( objectheader.getObjectID() ); 148 169 if(!s) 149 170 { 150 Synchronisable::fabricate(mem, mode); 171 if (!Core::isMaster()) 172 { 173 Synchronisable::fabricate(mem, mode); 174 } 175 else 176 { 177 mem += objectheader.getDataSize(); 178 } 179 // COUT(0) << "could not fabricate synchronisable: " << objectheader->objectID << " classid: " << objectheader->classID << " creator: " << objectheader->creatorID << endl; 180 // else 181 // COUT(0) << "fabricated: " << objectheader->objectID << " classid: " << objectheader->classID << " creator: " << objectheader->creatorID << endl; 151 182 } 152 183 else … … 157 188 } 158 189 190 // In debug mode, check first, whether there are no duplicate objectIDs 191 #ifndef NDEBUG 192 ObjectList<Synchronisable>::iterator it; 193 for (it = ObjectList<Synchronisable>::begin(); it != ObjectList<Synchronisable>::end(); ++it) { 194 if (it->getObjectID() == OBJECTID_UNKNOWN) { 195 if (it->objectMode_ != 0x0) { 196 COUT(0) << "Found object with OBJECTID_UNKNOWN on the client with objectMode != 0x0!" << std::endl; 197 COUT(0) << "Possible reason for this error: Client created a synchronized object without the Server's approval." << std::endl; 198 COUT(0) << "Objects class: " << it->getIdentifier()->getName() << std::endl; 199 assert(false); 200 } 201 } 202 else { 203 ObjectList<Synchronisable>::iterator it2; 204 for (it2 = ObjectList<Synchronisable>::begin(); it2 != ObjectList<Synchronisable>::end(); ++it2) { 205 if (it->getObjectID() == it2->getObjectID() && *it != *it2) { 206 COUT(0) << "Found duplicate objectIDs on the client!" << std::endl 207 << "Are you sure you don't create a Sychnronisable objcect with 'new' \ 208 that doesn't have objectMode = 0x0?" << std::endl; 209 assert(false); 210 } 211 } 212 } 213 } 214 #endif 215 159 216 return true; 160 217 } 161 218 162 163 164 int Gamestate::getID(){ 165 return HEADER->id; 166 } 167 168 unsigned int Gamestate::getSize() const 169 { 170 assert(data_); 171 if(HEADER->compressed) 172 return HEADER->compsize+sizeof(GamestateHeader); 219 uint32_t Gamestate::getSize() const 220 { 221 assert(data_); 222 if(header_->isCompressed()) 223 return header_->getCompSize()+GamestateHeader::getSize(); 173 224 else 174 225 { 175 return HEADER->datasize+sizeof(GamestateHeader);226 return header_->getDataSize()+GamestateHeader::getSize(); 176 227 } 177 228 } 178 229 179 230 bool Gamestate::operator==(packet::Gamestate gs){ 180 uint8_t *d1 = data_+ sizeof(GamestateHeader);181 uint8_t *d2 = gs.data_+ sizeof(GamestateHeader);231 uint8_t *d1 = data_+GamestateHeader::getSize(); 232 uint8_t *d2 = gs.data_+GamestateHeader::getSize(); 182 233 assert(!isCompressed()); 183 234 assert(!gs.isCompressed()); 184 while(d1<data_+ HEADER->datasize)235 while(d1<data_+header_->getDataSize()) 185 236 { 186 237 if(*d1!=*d2) … … 201 252 bool Gamestate::compressData() 202 253 { 203 assert( HEADER);204 assert(! HEADER->compressed);205 uLongf buffer = (uLongf)((( HEADER->datasize+ 12)*1.01)+1);254 assert(data_); 255 assert(!header_->isCompressed()); 256 uLongf buffer = (uLongf)(((header_->getDataSize() + 12)*1.01)+1); 206 257 if(buffer==0) 207 258 return false; 208 259 209 uint8_t *ndata = new uint8_t[buffer+ sizeof(GamestateHeader)];210 uint8_t *dest = GAMESTATE_START(ndata);260 uint8_t *ndata = new uint8_t[buffer+GamestateHeader::getSize()]; 261 uint8_t *dest = ndata + GamestateHeader::getSize(); 211 262 //unsigned char *dest = new unsigned char[buffer]; 212 uint8_t *source = GAMESTATE_START(data_);263 uint8_t *source = data_ + GamestateHeader::getSize(); 213 264 int retval; 214 retval = compress( dest, &buffer, source, (uLong)( HEADER->datasize) );265 retval = compress( dest, &buffer, source, (uLong)(header_->getDataSize()) ); 215 266 switch ( retval ) { 216 267 case Z_OK: COUT(5) << "G.St.Man: compress: successfully compressed" << std::endl; break; … … 219 270 case Z_DATA_ERROR: COUT(2) << "G.St.Man: compress: data corrupted in gamestate.compress" << std::endl; return false; 220 271 } 221 #ifndef NDEBUG222 //decompress and compare the start and the decompressed data223 uint8_t *rdata = new uint8_t[HEADER->datasize+sizeof(GamestateHeader)];224 uint8_t *d2 = GAMESTATE_START(rdata);225 uLongf length2 = HEADER->datasize;226 uncompress(d2, &length2, dest, buffer);227 for(unsigned int i=0; i<HEADER->datasize; i++){228 assert(*(source+i)==*(d2+i));229 }230 delete[] rdata;231 #endif232 272 233 273 //copy and modify header 234 #ifndef NDEBUG 235 HEADER->crc32 = calcCRC(data_+sizeof(GamestateHeader), HEADER->datasize); 236 #endif 237 *GAMESTATE_HEADER(ndata) = *HEADER; 274 GamestateHeader *temp = header_; 275 header_ = new GamestateHeader(ndata, temp); 276 delete temp; 238 277 //delete old data 239 278 delete[] data_; 240 279 //save new data 241 280 data_ = ndata; 242 HEADER->compsize = buffer; 243 HEADER->compressed = true; 244 assert(HEADER->compressed); 245 COUT(4) << "gamestate compress datasize: " << HEADER->datasize << " compsize: " << HEADER->compsize << std::endl; 281 header_->setCompSize( buffer ); 282 header_->setCompressed( true ); 283 COUT(5) << "gamestate compress datasize: " << header_->getDataSize() << " compsize: " << header_->getCompSize() << std::endl; 246 284 return true; 247 285 } 248 286 bool Gamestate::decompressData() 249 287 { 250 assert( HEADER);251 assert( HEADER->compressed);252 COUT(4) << "GameStateClient: uncompressing gamestate. id: " << HEADER->id << ", baseid: " << HEADER->base_id << ", datasize: " << HEADER->datasize << ", compsize: " << HEADER->compsize<< std::endl;253 u nsigned int datasize = HEADER->datasize;254 u nsigned int compsize = HEADER->compsize;255 u nsigned int bufsize;288 assert(data_); 289 assert(header_->isCompressed()); 290 COUT(4) << "GameStateClient: uncompressing gamestate. id: " << header_->getID() << ", baseid: " << header_->getBaseID() << ", datasize: " << header_->getDataSize() << ", compsize: " << header_->getCompSize() << std::endl; 291 uint32_t datasize = header_->getDataSize(); 292 uint32_t compsize = header_->getCompSize(); 293 uint32_t bufsize; 256 294 // assert(compsize<=datasize); 257 295 bufsize = datasize; 258 296 assert(bufsize!=0); 259 uint8_t *ndata = new uint8_t[bufsize + sizeof(GamestateHeader)];260 uint8_t *dest = ndata + sizeof(GamestateHeader);261 uint8_t *source = data_ + sizeof(GamestateHeader);297 uint8_t *ndata = new uint8_t[bufsize + GamestateHeader::getSize()]; 298 uint8_t *dest = ndata + GamestateHeader::getSize(); 299 uint8_t *source = data_ + GamestateHeader::getSize(); 262 300 int retval; 263 301 uLongf length=bufsize; … … 269 307 case Z_DATA_ERROR: COUT(2) << "data corrupted (zlib)" << std::endl; return false; 270 308 } 271 #ifndef NDEBUG272 assert(HEADER->crc32==calcCRC(ndata+sizeof(GamestateHeader), HEADER->datasize));273 #endif274 309 275 310 //copy over the header 276 *GAMESTATE_HEADER(ndata) = *HEADER; 311 GamestateHeader *temp = header_; 312 header_ = new GamestateHeader( data_, header_ ); 313 delete temp; 277 314 278 315 if (this->bDataENetAllocated_){ … … 289 326 //set new pointers 290 327 data_ = ndata; 291 HEADER->compressed = false;292 assert( HEADER->datasize==datasize);293 assert( HEADER->compsize==compsize);328 header_->setCompressed( false ); 329 assert(header_->getDataSize()==datasize); 330 assert(header_->getCompSize()==compsize); 294 331 return true; 295 332 } … … 297 334 Gamestate *Gamestate::diff(Gamestate *base) 298 335 { 299 assert(HEADER); 300 assert(!HEADER->compressed); 301 assert(!HEADER->diffed); 336 assert(data_); 337 assert(!header_->isCompressed()); 338 assert(!header_->isDiffed()); 339 GamestateHeader diffHeader(base->data_); 302 340 //unsigned char *basep = base->getGs()/*, *gs = getGs()*/; 303 341 uint8_t *basep = GAMESTATE_START(base->data_), *gs = GAMESTATE_START(this->data_); 304 u nsigned int of=0; // pointers offset305 u nsigned int dest_length=0;306 dest_length= HEADER->datasize;342 uint32_t of=0; // pointers offset 343 uint32_t dest_length=0; 344 dest_length=header_->getDataSize(); 307 345 if(dest_length==0) 308 346 return NULL; 309 uint8_t *ndata = new uint8_t[dest_length*sizeof(uint8_t)+ sizeof(GamestateHeader)];310 uint8_t *dest = ndata + sizeof(GamestateHeader);311 while(of < GAMESTATE_HEADER(base->data_)->datasize && of < HEADER->datasize){347 uint8_t *ndata = new uint8_t[dest_length*sizeof(uint8_t)+GamestateHeader::getSize()]; 348 uint8_t *dest = ndata + GamestateHeader::getSize(); 349 while(of < diffHeader.getDataSize() && of < header_->getDataSize()){ 312 350 *(dest+of)=*(basep+of)^*(gs+of); // do the xor 313 351 ++of; 314 352 } 315 if( GAMESTATE_HEADER(base->data_)->datasize!=HEADER->datasize){353 if(diffHeader.getDataSize()!=header_->getDataSize()){ 316 354 uint8_t n=0; 317 if( GAMESTATE_HEADER(base->data_)->datasize < HEADER->datasize){355 if(diffHeader.getDataSize() < header_->getDataSize()){ 318 356 while(of<dest_length){ 319 357 *(dest+of)=n^*(gs+of); … … 323 361 } 324 362 325 *GAMESTATE_HEADER(ndata) = *HEADER;326 GAMESTATE_HEADER(ndata)->diffed = true;327 GAMESTATE_HEADER(ndata)->base_id = base->getID();328 363 Gamestate *g = new Gamestate(ndata, getClientID()); 364 *(g->header_) = *header_; 365 g->header_->setDiffed( true ); 366 g->header_->setBaseID( base->getID() ); 329 367 g->flags_=flags_; 330 368 g->packetDirection_ = packetDirection_; … … 332 370 } 333 371 334 Gamestate* Gamestate::doSelection(unsigned int clientID ){335 assert(data_); 336 std:: map<unsigned int, Synchronisable *>::iterator it;372 Gamestate* Gamestate::doSelection(unsigned int clientID, unsigned int targetSize){ 373 assert(data_); 374 std::list<obj>::iterator it; 337 375 338 376 // allocate memory for new data 339 uint8_t *gdata = new uint8_t[ HEADER->datasize+sizeof(GamestateHeader)];377 uint8_t *gdata = new uint8_t[header_->getDataSize()+GamestateHeader::getSize()]; 340 378 // create a gamestate out of it 341 379 Gamestate *gs = new Gamestate(gdata); 342 uint8_t *newdata = gdata + sizeof(GamestateHeader);380 uint8_t *newdata = gdata + GamestateHeader::getSize(); 343 381 uint8_t *origdata = GAMESTATE_START(data_); 344 382 345 383 //copy the GamestateHeader 346 *(GamestateHeader*)gdata = *HEADER; 347 348 synchronisableHeader *oldobjectheader, *newobjectheader; 349 unsigned int objectOffset; 384 assert(gs->header_); 385 *(gs->header_) = *header_; 386 387 uint32_t objectOffset; 388 unsigned int objectsize, destsize=0; 389 // TODO: Why is this variable not used? 390 //Synchronisable *object; 391 392 //call TrafficControl 393 TrafficControl::getInstance()->processObjectList( clientID, header_->getID(), &dataMap_ ); 350 394 351 395 //copy in the zeros 352 for(it=dataMap_.begin(); it!=dataMap_.end(); it++){ 353 oldobjectheader = (synchronisableHeader*)origdata; 354 newobjectheader = (synchronisableHeader*)newdata; 355 unsigned int objectsize = oldobjectheader->size; 356 assert(it->second->objectID==oldobjectheader->objectID); 357 *newobjectheader = *oldobjectheader; 358 objectOffset=sizeof(synchronisableHeader); //skip the size and the availableData variables in the objectheader 359 if(it->second->doSelection(HEADER->id)){ 360 assert(newobjectheader->dataAvailable==true); 361 memcpy(newdata+objectOffset, origdata+objectOffset, objectsize-objectOffset); 396 for(it=dataMap_.begin(); it!=dataMap_.end();){ 397 // if((*it).objSize==0) 398 // continue; 399 // if(it->second->getSize(HEADER->id)==0) // merged from objecthierarchy2, doesn't work anymore; TODO: change this 400 // continue; // merged from objecthierarchy2, doesn't work anymore; TODO: change this 401 SynchronisableHeader oldobjectheader(origdata); 402 SynchronisableHeader newobjectheader(newdata); 403 if ( (*it).objSize == 0 ) 404 { 405 ++it; 406 continue; 407 } 408 // object = Synchronisable::getSynchronisable( (*it).objID ); 409 // assert(object->objectID == oldobjectheader->objectID); 410 objectsize = oldobjectheader.getDataSize(); 411 objectOffset=SynchronisableHeader::getSize(); //skip the size and the availableData variables in the objectheader 412 if ( (*it).objID == oldobjectheader.getObjectID() ){ 413 memcpy(newdata, origdata, objectsize); 414 assert(newobjectheader.isDataAvailable()==true); 415 ++it; 362 416 }else{ 363 newobjectheader->dataAvailable=false; 417 newobjectheader = oldobjectheader; 418 newobjectheader.setDataAvailable(false); 364 419 memset(newdata+objectOffset, 0, objectsize-objectOffset); 365 assert(objectOffset==objectsize);366 420 } 367 421 newdata += objectsize; 368 422 origdata += objectsize; 369 } 423 destsize += objectsize; 424 } 425 #ifndef NDEBUG 426 uint32_t origsize = destsize; 427 while ( origsize < header_->getDataSize() ) 428 { 429 SynchronisableHeader oldobjectheader(origdata); 430 objectsize = oldobjectheader.getDataSize(); 431 origdata += objectsize; 432 origsize += objectsize; 433 } 434 assert(origsize==header_->getDataSize()); 435 assert(destsize!=0); 436 #endif 437 gs->header_->setDataSize( destsize ); 370 438 return gs; 371 439 } 372 440 373 441 374 Gamestate* Gamestate::intelligentDiff(Gamestate *base, unsigned int clientID){375 // asserts376 assert(data_);377 assert(base->data_);378 assert(!GAMESTATE_HEADER(base->data_)->diffed);379 assert(!GAMESTATE_HEADER(base->data_)->compressed);380 assert(!HEADER->compressed);381 assert(!HEADER->diffed);382 383 //preparations384 std::map<unsigned int, Synchronisable *>::iterator it;385 uint8_t *origdata, *basedata, *destdata, *ndata;386 unsigned int objectOffset, streamOffset=0; //data offset387 unsigned int minsize = (HEADER->datasize < GAMESTATE_HEADER(base->data_)->datasize) ? HEADER->datasize : GAMESTATE_HEADER(base->data_)->datasize;388 synchronisableHeader *origheader;389 synchronisableHeader *destheader;390 391 origdata = GAMESTATE_START(this->data_);392 basedata = GAMESTATE_START(base->data_);393 ndata = new uint8_t[HEADER->datasize + sizeof(GamestateHeader)];394 destdata = ndata + sizeof(GamestateHeader);395 396 // do the diff397 for(it=dataMap_.begin(); it!=dataMap_.end(); it++){398 assert(streamOffset<HEADER->datasize);399 bool sendData = it->second->doSelection(HEADER->id);400 origheader = (synchronisableHeader *)(origdata+streamOffset);401 destheader = (synchronisableHeader *)(destdata+streamOffset);402 403 //copy and partially diff the object header404 assert(sizeof(synchronisableHeader)==3*sizeof(unsigned int)+sizeof(bool));405 *(uint32_t*)destdata = *(uint32_t*)origdata; //size (do not diff)406 *(bool*)(destdata+sizeof(uint32_t)) = sendData;407 if(sendData){408 *(uint32_t*)(destdata+sizeof(uint32_t)+sizeof(bool)) = *(uint32_t*)(basedata+sizeof(uint32_t)+sizeof(bool)) ^ *(uint32_t*)(origdata+sizeof(uint32_t)+sizeof(bool)); //objectid (diff it)409 *(uint32_t*)(destdata+2*sizeof(uint32_t)+sizeof(bool)) = *(uint32_t*)(basedata+2*sizeof(uint32_t)+sizeof(bool)) ^ *(uint32_t*)(origdata+2*sizeof(uint32_t)+sizeof(bool)); //classid (diff it)410 }else{411 *(uint32_t*)(destdata+sizeof(uint32_t)+sizeof(bool)) = 0;412 *(uint32_t*)(destdata+2*sizeof(uint32_t)+sizeof(bool)) = 0;413 }414 objectOffset=sizeof(synchronisableHeader);415 streamOffset+=sizeof(synchronisableHeader);416 417 //now handle the object data or fill with zeros418 while(objectOffset<origheader->size ){419 420 if(sendData && streamOffset<minsize)421 *(destdata+objectOffset)=*(basedata+objectOffset)^*(origdata+objectOffset); // do the xor422 else if(sendData)423 *(destdata+objectOffset)=((uint8_t)0)^*(origdata+objectOffset); // xor with 0 (basestream is too short)424 else425 *(destdata+objectOffset)=0; // set to 0 because this object should not be transfered426 427 objectOffset++;428 streamOffset++;429 }430 destdata+=objectOffset;431 origdata+=objectOffset;432 basedata+=objectOffset;433 }434 435 //copy over the gamestate header and set the diffed flag436 *(GamestateHeader *)ndata = *HEADER; //copy over the header437 Gamestate *gs = new Gamestate(ndata);438 GAMESTATE_HEADER(ndata)->diffed=true;439 return gs;440 }441 442 Gamestate* Gamestate::intelligentUnDiff(Gamestate *base){443 // asserts444 assert(data_);445 assert(base->data_);446 assert(!GAMESTATE_HEADER(base->data_)->diffed);447 assert(!GAMESTATE_HEADER(base->data_)->compressed);448 assert(!HEADER->compressed);449 assert(HEADER->diffed);450 451 //preparations452 std::map<unsigned int, Synchronisable *>::iterator it;453 uint8_t *origdata, *basedata, *destdata, *ndata;454 unsigned int objectOffset, streamOffset=0; //data offset455 unsigned int minsize = (HEADER->datasize < GAMESTATE_HEADER(base->data_)->datasize) ? HEADER->datasize : GAMESTATE_HEADER(base->data_)->datasize;456 synchronisableHeader *origheader;457 synchronisableHeader *destheader;458 459 origdata = GAMESTATE_START(this->data_);460 basedata = GAMESTATE_START(base->data_);461 ndata = new uint8_t[HEADER->datasize + sizeof(GamestateHeader)];462 destdata = ndata + sizeof(GamestateHeader);463 464 // do the undiff465 for(it=dataMap_.begin(); it!=dataMap_.end(); it++){466 assert(streamOffset<HEADER->datasize);467 origheader = (synchronisableHeader *)(origdata+streamOffset);468 destheader = (synchronisableHeader *)(destdata+streamOffset);469 bool sendData;470 471 //copy and partially diff the object header472 assert(sizeof(synchronisableHeader)==3*sizeof(unsigned int)+sizeof(bool));473 *(unsigned int*)destdata = *(unsigned int*)origdata; //size (do not diff)474 *(bool*)(destdata+sizeof(unsigned int)) = *(bool*)(origdata+sizeof(unsigned int));475 sendData = *(bool*)(origdata+sizeof(unsigned int));476 if(sendData){477 *(unsigned int*)(destdata+sizeof(unsigned int)+sizeof(bool)) = *(unsigned int*)(basedata+sizeof(unsigned int)+sizeof(bool)) ^ *(unsigned int*)(origdata+sizeof(unsigned int)+sizeof(bool)); //objectid (diff it)478 *(unsigned int*)(destdata+2*sizeof(unsigned int)+sizeof(bool)) = *(unsigned int*)(basedata+2*sizeof(unsigned int)+sizeof(bool)) ^ *(unsigned int*)(origdata+2*sizeof(unsigned int)+sizeof(bool)); //classid (diff it)479 }else{480 *(unsigned int*)(destdata+sizeof(unsigned int)+sizeof(bool)) = 0;481 *(unsigned int*)(destdata+2*sizeof(unsigned int)+sizeof(bool)) = 0;482 }483 objectOffset=sizeof(synchronisableHeader);484 streamOffset+=sizeof(synchronisableHeader);485 486 //now handle the object data or fill with zeros487 while(objectOffset<origheader->size ){488 489 if(sendData && streamOffset<minsize)490 *(destdata+objectOffset)=*(basedata+objectOffset)^*(origdata+objectOffset); // do the xor491 else if(sendData)492 *(destdata+objectOffset)=((unsigned char)0)^*(origdata+objectOffset); // xor with 0 (basestream is too short)493 else494 *(destdata+objectOffset)=0; // set to 0 because this object should not be transfered495 496 objectOffset++;497 streamOffset++;498 }499 destdata+=objectOffset;500 origdata+=objectOffset;501 basedata+=objectOffset;502 }503 504 //copy over the gamestate header and set the diffed flag505 *(GamestateHeader *)ndata = *HEADER; //copy over the header506 Gamestate *gs = new Gamestate(ndata);507 GAMESTATE_HEADER(ndata)->diffed=false;508 return gs;509 }510 511 442 Gamestate *Gamestate::undiff(Gamestate *base) 512 443 { 513 assert(this && base);assert( HEADER);514 assert( HEADER->diffed);515 assert(! HEADER->compressed && !GAMESTATE_HEADER(base->data_)->compressed);444 assert(this && base);assert(data_); 445 assert(header_->isDiffed()); 446 assert(!header_->isCompressed() && !base->header_->isCompressed()); 516 447 //unsigned char *basep = base->getGs()/*, *gs = getGs()*/; 517 448 uint8_t *basep = GAMESTATE_START(base->data_); 518 449 uint8_t *gs = GAMESTATE_START(this->data_); 519 u nsigned int of=0; // pointers offset520 u nsigned int dest_length=0;521 dest_length= HEADER->datasize;450 uint32_t of=0; // pointers offset 451 uint32_t dest_length=0; 452 dest_length=header_->getDataSize(); 522 453 if(dest_length==0) 523 454 return NULL; 524 uint8_t *ndata = new uint8_t[dest_length*sizeof(uint8_t)+ sizeof(GamestateHeader)];525 uint8_t *dest = ndata + sizeof(GamestateHeader);526 while(of < GAMESTATE_HEADER(base->data_)->datasize && of < HEADER->datasize){455 uint8_t *ndata = new uint8_t[dest_length*sizeof(uint8_t)+GamestateHeader::getSize()]; 456 uint8_t *dest = ndata + GamestateHeader::getSize(); 457 while(of < base->header_->getDataSize() && of < header_->getDataSize()){ 527 458 *(dest+of)=*(basep+of)^*(gs+of); // do the xor 528 459 ++of; 529 460 } 530 if( GAMESTATE_HEADER(base->data_)->datasize!=HEADER->datasize){461 if(base->header_->getDataSize()!=header_->getDataSize()){ 531 462 uint8_t n=0; 532 if( GAMESTATE_HEADER(base->data_)->datasize < HEADER->datasize){463 if(base->header_->getDataSize() < header_->getDataSize()){ 533 464 while(of < dest_length){ 534 465 *(dest+of)=n^*(gs+of); … … 537 468 } 538 469 } 539 *GAMESTATE_HEADER(ndata) = *HEADER;540 GAMESTATE_HEADER(ndata)->diffed = false;541 470 Gamestate *g = new Gamestate(ndata, getClientID()); 471 assert(g->header_); 472 *(g->header_) = *header_; 473 g->header_->setDiffed( false ); 542 474 g->flags_=flags_; 543 475 g->packetDirection_ = packetDirection_; … … 548 480 549 481 550 u nsigned int Gamestate::calcGamestateSize(unsigned int id, uint8_t mode)551 { 552 u nsigned int size=0;482 uint32_t Gamestate::calcGamestateSize(int32_t id, uint8_t mode) 483 { 484 uint32_t size=0; 553 485 // get the start of the Synchronisable list 554 486 ObjectList<Synchronisable>::iterator it; … … 556 488 for(it = ObjectList<Synchronisable>::begin(); it; ++it) 557 489 size+=it->getSize(id, mode); // size of the actual data of the synchronisable 558 // size+=sizeof(GamestateHeader);559 490 return size; 560 491 } 561 492 562 /** 563 * This function removes a Synchronisable out of the universe 564 * @param it iterator of the list pointing to the object 565 * @return iterator pointing to the next object in the list 566 */ 567 void Gamestate::removeObject(ObjectList<Synchronisable>::iterator &it) { 568 ObjectList<Synchronisable>::iterator temp=it; 569 ++it; 570 delete *temp; 571 } 572 573 bool Gamestate::isDiffed(){ 574 return HEADER->diffed; 575 } 576 577 bool Gamestate::isCompressed(){ 578 return HEADER->compressed; 579 } 580 581 int Gamestate::getBaseID(){ 582 return HEADER->base_id; 583 } 584 } 585 586 } 493 } //namespace packet 494 } //namespace orxonox
Note: See TracChangeset
for help on using the changeset viewer.