Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/network/src/network/GameStateClient.cc @ 912

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

bugfix in packetdecoder, inserted some std::

File size: 6.2 KB
RevLine 
[514]1/*
[777]2*   ORXONOX - the hottest 3D action shooter ever to exist
3*
4*
5*   License notice:
6*
7*   This program is free software; you can redistribute it and/or
8*   modify it under the terms of the GNU General Public License
9*   as published by the Free Software Foundation; either version 2
10*   of the License, or (at your option) any later version.
11*
12*   This program is distributed in the hope that it will be useful,
13*   but WITHOUT ANY WARRANTY; without even the implied warranty of
14*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*   GNU General Public License for more details.
16*
17*   You should have received a copy of the GNU General Public License
18*   along with this program; if not, write to the Free Software
19*   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20*
21*   Author:
22*      ...
23*   Co-authors:
24*      ...
25*
26*/
27#include <zlib.h>
[514]28
[777]29#include "core/CoreIncludes.h"
30#include "Synchronisable.h"
[416]31#include "GameStateClient.h"
32
[777]33namespace network
[416]34{
[777]35  GameStateClient::GameStateClient() {
36  }
[416]37
[777]38  GameStateClient::~GameStateClient() {
39  }
[416]40
[777]41  bool GameStateClient::pushGameState(GameStateCompressed *compstate) {
[912]42    GameState *gs;
[777]43    if(compstate->diffed)
[912]44      gs = decode(reference, compstate);
[777]45    else
[912]46      gs = decode(compstate);
47    if(gs)
48      return loadSnapshot(gs);
49    COUT(4) << "could not use gamestate sent by server" << std::endl;
50    return false;
[777]51  }
[416]52
[777]53  /**
54  * This function removes a Synchronisable out of the universe
55  * @param it iterator of the list pointing to the object
56  * @return iterator pointing to the next object in the list
57  */
58  void GameStateClient::removeObject(orxonox::Iterator<Synchronisable> &it) {
59    orxonox::Iterator<Synchronisable> temp=it;
60    ++it;
61    delete  *temp;
62  }
[416]63
[777]64  /**
65  * This function loads a Snapshort of the gamestate into the universe
66  * @param state a GameState struct containing the size of the gamestate and a pointer linking to a flat list (returned by getSnapshot)
67  */
[905]68  bool GameStateClient::loadSnapshot(GameState *state) {
69    unsigned char *data=state->data;
70    COUT(4) << "loadSnapshot: loading gs: " << state->id << std::endl;
[777]71    // get the start of the Synchronisable list
72    orxonox::Iterator<Synchronisable> it=orxonox::ObjectList<Synchronisable>::start();
73    syncData sync;
74    // loop as long as we have some data ;)
[905]75    while(data < state->data+state->size){
[777]76      // prepare the syncData struct
77      sync.length = (int)*data;
78      data+=sizeof(int);
79      sync.objectID = (int)*data;
80      data+=sizeof(int);
81      sync.classID = (int)*data;
82      data+=sizeof(int);
83      sync.data = data;
84      data+=sync.length;
[416]85
[777]86      if(it->objectID!=sync.objectID){
87        // bad luck ;)
88        // delete the synchronisable (obviously seems to be deleted on the server)
[905]89        while(it && it->objectID!=sync.objectID)
[777]90          removeObject(it);
[905]91       
92       
93        if(!it){
94          COUT(5) << "classid: " << sync.classID << ", name: " << ID((unsigned int) sync.classID)->getName() << std::endl;
95          Synchronisable *no = (Synchronisable*)(ID((unsigned int) sync.classID)->fabricate());
[777]96          no->objectID=sync.objectID;
97          no->classID=sync.classID;
98          it=orxonox::ObjectList<Synchronisable>::end();
99          // update data and create object/entity...
100          if( !no->updateData(sync) && !no->create() )
[905]101            COUT(1) << "We couldn't create/update the object: " << sync.objectID << std::endl;
[777]102          ++it;
103        }
104      } else {
105        // we have our object
106        if(! it->updateData(sync))
[905]107          COUT(1) << "We couldn't update objectID: " \
[777]108          << sync.objectID << "; classID: " << sync.classID << std::endl;
[416]109      }
[777]110      ++it;
[416]111    }
[777]112
113    return true;
[416]114  }
[514]115
[905]116  GameState *GameStateClient::undiff(GameState *a, GameState *b) {
117    unsigned char *ap = a->data, *bp = b->data;
[777]118    int of=0; // pointers offset
119    int dest_length=0;
[905]120    if(a->size>=b->size)
121      dest_length=a->size;
[777]122    else
[905]123      dest_length=b->size;
[777]124    unsigned char *dp = (unsigned char *)malloc(dest_length*sizeof(unsigned char));
[905]125    while(of<a->size && of<b->size){
[777]126      *(dp+of)=*(ap+of)^*(bp+of); // do the xor
127      ++of;
128    }
[905]129    if(a->size!=b->size){ // do we have to fill up ?
[777]130      unsigned char n=0;
[905]131      if(a->size<b->size){
[777]132        while(of<dest_length){
133          *(dp+of)=n^*(bp+of);
134          of++;
135        }
136      } else{
137        while(of<dest_length){
138          *(dp+of)=*(ap+of)^n;
139          of++;
140        }
[416]141      }
142    }
[777]143    // should be finished now
[782]144    // FIXME: is it true or false now? (struct has changed, producing warnings)
[905]145    GameState *r = new GameState;
146    r->id = b->id;
147    r->size = dest_length;
148    r->diffed = false;
149    r->data = dp;
[777]150    return r;
[416]151  }
152
[905]153  GameState *GameStateClient::decompress(GameStateCompressed *a) {
154    int normsize = a->normsize;
155    int compsize = a->compsize;
[777]156    int bufsize;
157    if(normsize < compsize)
158      bufsize = compsize;
159    else
160      bufsize = normsize;
161    unsigned char* dest = (unsigned char*)malloc( bufsize );
162    int retval;
163    uLongf length=normsize;
164    //std::cout << "gamestateclient" << std::endl;
165    //std::cout << "normsize " << a.normsize << " compsize " << a.compsize << " " << bufsize << std::endl;
[905]166    retval = uncompress( dest, &length, a->data, (uLong)compsize );
[777]167    //std::cout << "length " << length << std::endl;
168    switch ( retval ) {
[905]169      case Z_OK: COUT(4) << "successfully decompressed" << std::endl; break;
170      case Z_MEM_ERROR: COUT(1) << "not enough memory available" << std::endl; return NULL;
171      case Z_BUF_ERROR: COUT(2) << "not enough memory available in the buffer" << std::endl; return NULL;
172      case Z_DATA_ERROR: COUT(2) << "data corrupted" << std::endl; return NULL;
[777]173    }
[416]174
[905]175    GameState *gamestate = new GameState;
176    gamestate->id = a->id;
177    gamestate->size = normsize;
178    gamestate->data = dest;
179    gamestate->diffed = a->diffed;
180   
181    delete a->data; //delete compressed data
182    delete a; //we do not need the old (struct) gamestate anymore
[777]183
184    return gamestate;
[416]185  }
[514]186
[905]187  GameState *GameStateClient::decode(GameState *a, GameStateCompressed *x) {
188    GameState *t = decompress(x);
189    return undiff(a, t);
[777]190  }
[416]191
[905]192  GameState *GameStateClient::decode(GameStateCompressed *x) {
193    GameState *t = decompress(x);
[777]194    return t;
195  }
[416]196
197}
Note: See TracBrowser for help on using the repository browser.