Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 1008 was 1008, checked in by dumenim, 16 years ago

changed some comments and catched some return values and maybe some stuff we have to unchange

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