Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

found that fucking bug

File size: 7.5 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"
[1083]30#include "core/BaseObject.h"
[777]31#include "Synchronisable.h"
[416]32#include "GameStateClient.h"
33
[777]34namespace network
[416]35{
[1005]36  struct GameStateItem{
37    GameState *state;
38    int id;
39  };
40 
[777]41  GameStateClient::GameStateClient() {
[1083]42    COUT(5) << "this: " << this << std::endl;
[777]43  }
[416]44
[777]45  GameStateClient::~GameStateClient() {
46  }
[416]47
[777]48  bool GameStateClient::pushGameState(GameStateCompressed *compstate) {
[912]49    GameState *gs;
[1005]50    if(compstate->diffed){
51      while(compstate->base_id > gameStateList.front()->id){
52        // clean up old gamestates
53        free(gameStateList.front()->data);
54        // TODO: critical section
55        delete gameStateList.front();
56        gameStateList.pop();
57      }
58      if(compstate->base_id!=gameStateList.front()->id){
59        COUT(4) << "pushGameState: no reference found to diff" << std::endl;
60        return false;
61      }
62      gs = decode(gameStateList.front(), compstate);
63    }
[777]64    else
[912]65      gs = decode(compstate);
66    if(gs)
67      return loadSnapshot(gs);
68    COUT(4) << "could not use gamestate sent by server" << std::endl;
69    return false;
[777]70  }
[416]71
[777]72  /**
73  * This function removes a Synchronisable out of the universe
74  * @param it iterator of the list pointing to the object
75  * @return iterator pointing to the next object in the list
76  */
77  void GameStateClient::removeObject(orxonox::Iterator<Synchronisable> &it) {
78    orxonox::Iterator<Synchronisable> temp=it;
79    ++it;
80    delete  *temp;
81  }
[416]82
[777]83  /**
84  * This function loads a Snapshort of the gamestate into the universe
85  * @param state a GameState struct containing the size of the gamestate and a pointer linking to a flat list (returned by getSnapshot)
86  */
[905]87  bool GameStateClient::loadSnapshot(GameState *state) {
88    unsigned char *data=state->data;
89    COUT(4) << "loadSnapshot: loading gs: " << state->id << std::endl;
[777]90    // get the start of the Synchronisable list
91    orxonox::Iterator<Synchronisable> it=orxonox::ObjectList<Synchronisable>::start();
92    syncData sync;
93    // loop as long as we have some data ;)
[905]94    while(data < state->data+state->size){
[777]95      // prepare the syncData struct
96      sync.length = (int)*data;
97      data+=sizeof(int);
98      sync.objectID = (int)*data;
99      data+=sizeof(int);
100      sync.classID = (int)*data;
101      data+=sizeof(int);
102      sync.data = data;
103      data+=sync.length;
[416]104
[777]105      if(it->objectID!=sync.objectID){
106        // bad luck ;)
107        // delete the synchronisable (obviously seems to be deleted on the server)
[905]108        while(it && it->objectID!=sync.objectID)
[777]109          removeObject(it);
[905]110       
111       
112        if(!it){
[1008]113          COUT(4) << "loadSnapshot:\tclassid: " << sync.classID << ", name: " << ID((unsigned int) sync.classID)->getName() << std::endl;
[1083]114          Synchronisable *no = dynamic_cast<Synchronisable *>(ID((unsigned int) sync.classID)->fabricate());
[777]115          no->objectID=sync.objectID;
116          no->classID=sync.classID;
117          it=orxonox::ObjectList<Synchronisable>::end();
118          // update data and create object/entity...
119          if( !no->updateData(sync) && !no->create() )
[905]120            COUT(1) << "We couldn't create/update the object: " << sync.objectID << std::endl;
[777]121        }
122      } else {
123        // we have our object
124        if(! it->updateData(sync))
[905]125          COUT(1) << "We couldn't update objectID: " \
[777]126          << sync.objectID << "; classID: " << sync.classID << std::endl;
[416]127      }
[777]128      ++it;
[416]129    }
[777]130
131    return true;
[416]132  }
[514]133
[905]134  GameState *GameStateClient::undiff(GameState *a, GameState *b) {
135    unsigned char *ap = a->data, *bp = b->data;
[777]136    int of=0; // pointers offset
137    int dest_length=0;
[905]138    if(a->size>=b->size)
139      dest_length=a->size;
[777]140    else
[905]141      dest_length=b->size;
[777]142    unsigned char *dp = (unsigned char *)malloc(dest_length*sizeof(unsigned char));
[905]143    while(of<a->size && of<b->size){
[777]144      *(dp+of)=*(ap+of)^*(bp+of); // do the xor
145      ++of;
146    }
[905]147    if(a->size!=b->size){ // do we have to fill up ?
[777]148      unsigned char n=0;
[905]149      if(a->size<b->size){
[777]150        while(of<dest_length){
151          *(dp+of)=n^*(bp+of);
152          of++;
153        }
154      } else{
155        while(of<dest_length){
156          *(dp+of)=*(ap+of)^n;
157          of++;
158        }
[416]159      }
160    }
[777]161    // should be finished now
[782]162    // FIXME: is it true or false now? (struct has changed, producing warnings)
[905]163    GameState *r = new GameState;
164    r->id = b->id;
165    r->size = dest_length;
166    r->diffed = false;
167    r->data = dp;
[777]168    return r;
[416]169  }
170
[984]171  //##### ADDED FOR TESTING PURPOSE #####
172  GameState* GameStateClient::testDecompress( GameStateCompressed* gc ) {
173    return decompress( gc );
174  }
175 
176  GameState* GameStateClient::testUndiff( GameState* g_old, GameState* g_diffed ) {
177    return undiff( g_old, g_diffed );
178  }
179  //##### ADDED FOR TESTING PURPOSE #####
180
[905]181  GameState *GameStateClient::decompress(GameStateCompressed *a) {
[1013]182    COUT(4) << "GameStateClient: uncompressing gamestate. id: " << a->id << ", baseid: " << a->base_id << ", normsize: " << a->normsize << ", compsize: " << a->compsize << std::endl;
[905]183    int normsize = a->normsize;
184    int compsize = a->compsize;
[777]185    int bufsize;
186    if(normsize < compsize)
187      bufsize = compsize;
188    else
189      bufsize = normsize;
190    unsigned char* dest = (unsigned char*)malloc( bufsize );
191    int retval;
192    uLongf length=normsize;
193    //std::cout << "gamestateclient" << std::endl;
194    //std::cout << "normsize " << a.normsize << " compsize " << a.compsize << " " << bufsize << std::endl;
[905]195    retval = uncompress( dest, &length, a->data, (uLong)compsize );
[777]196    //std::cout << "length " << length << std::endl;
197    switch ( retval ) {
[905]198      case Z_OK: COUT(4) << "successfully decompressed" << std::endl; break;
199      case Z_MEM_ERROR: COUT(1) << "not enough memory available" << std::endl; return NULL;
200      case Z_BUF_ERROR: COUT(2) << "not enough memory available in the buffer" << std::endl; return NULL;
[1008]201      case Z_DATA_ERROR: COUT(2) << "data corrupted (zlib)" << std::endl; return NULL;
[777]202    }
[416]203
[905]204    GameState *gamestate = new GameState;
205    gamestate->id = a->id;
206    gamestate->size = normsize;
207    gamestate->data = dest;
208    gamestate->diffed = a->diffed;
209   
210    delete a->data; //delete compressed data
211    delete a; //we do not need the old (struct) gamestate anymore
[777]212
213    return gamestate;
[416]214  }
[514]215
[905]216  GameState *GameStateClient::decode(GameState *a, GameStateCompressed *x) {
[1016]217    GameState *t = decode(x);
[1005]218    gameStateList.push(t);
[1016]219    //return undiff(a, t);
220    return t;
[777]221  }
[416]222
[905]223  GameState *GameStateClient::decode(GameStateCompressed *x) {
[1016]224    //GameState *t = decompress(x);
225    GameState *t = new GameState;
226    t->base_id = x->base_id;
227    t->id = x->id;
228    t->diffed = x->diffed;
229    t->data = x->data;
230    t->size = x->normsize;
[1005]231    gameStateList.push(t);
[777]232    return t;
233  }
[416]234
235}
Note: See TracBrowser for help on using the repository browser.