Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/network2/src/network/GameStateClient.cc @ 1100

Last change on this file since 1100 was 1100, checked in by scheusso, 17 years ago

tardis sucks

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