Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

blub

File size: 7.4 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    COUT(4) << "GameStateClient: uncompressing gamestate. id: " << a->id << ", baseid: " << a->base_id << ", normsize: " << a->normsize << ", compsize: " << a->compsize << std::endl;
182    int normsize = a->normsize;
183    int compsize = a->compsize;
184    int bufsize;
185    if(normsize < compsize)
186      bufsize = compsize;
187    else
188      bufsize = normsize;
189    unsigned char* dest = (unsigned char*)malloc( bufsize );
190    int retval;
191    uLongf length=normsize;
192    //std::cout << "gamestateclient" << std::endl;
193    //std::cout << "normsize " << a.normsize << " compsize " << a.compsize << " " << bufsize << std::endl;
194    retval = uncompress( dest, &length, a->data, (uLong)compsize );
195    //std::cout << "length " << length << std::endl;
196    switch ( retval ) {
197      case Z_OK: COUT(4) << "successfully decompressed" << std::endl; break;
198      case Z_MEM_ERROR: COUT(1) << "not enough memory available" << std::endl; return NULL;
199      case Z_BUF_ERROR: COUT(2) << "not enough memory available in the buffer" << std::endl; return NULL;
200      case Z_DATA_ERROR: COUT(2) << "data corrupted (zlib)" << std::endl; return NULL;
201    }
202
203    GameState *gamestate = new GameState;
204    gamestate->id = a->id;
205    gamestate->size = normsize;
206    gamestate->data = dest;
207    gamestate->diffed = a->diffed;
208   
209    delete a->data; //delete compressed data
210    delete a; //we do not need the old (struct) gamestate anymore
211
212    return gamestate;
213  }
214
215  GameState *GameStateClient::decode(GameState *a, GameStateCompressed *x) {
216    GameState *t = decode(x);
217    gameStateList.push(t);
218    //return undiff(a, t);
219    return t;
220  }
221
222  GameState *GameStateClient::decode(GameStateCompressed *x) {
223    //GameState *t = decompress(x);
224    GameState *t = new GameState;
225    t->base_id = x->base_id;
226    t->id = x->id;
227    t->diffed = x->diffed;
228    t->data = x->data;
229    t->size = x->normsize;
230    gameStateList.push(t);
231    return t;
232  }
233
234}
Note: See TracBrowser for help on using the repository browser.