Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/network3/GameStateClient.cc @ 1162

Last change on this file since 1162 was 1152, checked in by dumenim, 17 years ago

may have found another seg fault in GameStateClient in loadShapshot line 118

File size: 8.0 KB
Line 
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 */
28
29#include "GameStateClient.h"
30
31#include <zlib.h>
32
33#include "core/CoreIncludes.h"
34#include "core/BaseObject.h"
35#include "Synchronisable.h"
36
37namespace network
38{
39  struct GameStateItem{
40    GameState *state;
41    int id;
42  };
43 
44  GameStateClient::GameStateClient() {
45    COUT(5) << "this: " << this << std::endl;
46  }
47
48  GameStateClient::~GameStateClient() {
49  }
50
51  bool GameStateClient::pushGameState(GameStateCompressed *compstate) {
52    GameState *gs;
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    }
67    else
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;
73  }
74
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  }
85
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  */
90  bool GameStateClient::loadSnapshot(GameState *state) {
91    unsigned char *data=state->data;
92    COUT(4) << "loadSnapshot: loading gs: " << state->id << std::endl;
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 ;)
97    while(data < state->data+state->size){
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;
107
108      if(!it || it->objectID!=sync.objectID){
109        // bad luck ;)
110        // delete the synchronisable (obviously seems to be deleted on the server)
111        while(it && it->objectID!=sync.objectID)
112          removeObject(it);
113
114
115        if(!it){
116          COUT(4) << "loadSnapshot:\tclassid: " << sync.classID << ", name: " << ID((unsigned int) sync.classID)->getName() << std::endl;
117          ///sigsegv may happen here again for some reason
118          ///sigsegv is receved after the COUT(4) above
119          Synchronisable *no = dynamic_cast<Synchronisable *>(ID((unsigned int) sync.classID)->fabricate());
120          no->objectID=sync.objectID;
121          no->classID=sync.classID;
122          it=orxonox::ObjectList<Synchronisable>::end();
123          // update data and create object/entity...
124          if( !no->updateData(sync) )
125            COUT(1) << "We couldn't update the object: " << sync.objectID << std::endl;
126          if( !no->create() )
127            COUT(1) << "We couldn't manifest (create() ) the object: " << sync.objectID << std::endl;
128        }
129      } else {
130        // we have our object
131        if(! it->updateData(sync))
132          COUT(1) << "We couldn't update objectID: " \
133          << sync.objectID << "; classID: " << sync.classID << std::endl;
134      }
135      ++it;
136    }
137
138    return true;
139  }
140
141  GameState *GameStateClient::undiff(GameState *a, GameState *b) {
142    unsigned char *ap = a->data, *bp = b->data;
143    int of=0; // pointers offset
144    int dest_length=0;
145    if(a->size>=b->size)
146      dest_length=a->size;
147    else
148      dest_length=b->size;
149    unsigned char *dp = (unsigned char *)malloc(dest_length*sizeof(unsigned char));
150    while(of<a->size && of<b->size){
151      *(dp+of)=*(ap+of)^*(bp+of); // do the xor
152      ++of;
153    }
154    if(a->size!=b->size){ // do we have to fill up ?
155      unsigned char n=0;
156      if(a->size<b->size){
157        while(of<dest_length){
158          *(dp+of)=n^*(bp+of);
159          of++;
160        }
161      } else{
162        while(of<dest_length){
163          *(dp+of)=*(ap+of)^n;
164          of++;
165        }
166      }
167    }
168    // should be finished now
169    // FIXME: is it true or false now? (struct has changed, producing warnings)
170    GameState *r = new GameState;
171    r->id = b->id;
172    r->size = dest_length;
173    r->diffed = false;
174    r->data = dp;
175    return r;
176  }
177
178  //##### ADDED FOR TESTING PURPOSE #####
179  GameState* GameStateClient::testDecompress( GameStateCompressed* gc ) {
180    return decompress( gc );
181  }
182 
183  GameState* GameStateClient::testUndiff( GameState* g_old, GameState* g_diffed ) {
184    return undiff( g_old, g_diffed );
185  }
186  //##### ADDED FOR TESTING PURPOSE #####
187
188  GameState *GameStateClient::decompress(GameStateCompressed *a) {
189    //COUT(4) << "GameStateClient: uncompressing gamestate. id: " << a->id << ", baseid: " << a->base_id << ", normsize: " << a->normsize << ", compsize: " << a->compsize << std::endl;
190    int normsize = a->normsize;
191    int compsize = a->compsize;
192    int bufsize;
193    if(normsize < compsize)
194      bufsize = compsize;
195    else
196      bufsize = normsize;
197    unsigned char* dest = (unsigned char*)malloc( bufsize );
198    int retval;
199    uLongf length=normsize;
200    //std::cout << "gamestateclient" << std::endl;
201    //std::cout << "normsize " << a.normsize << " compsize " << a.compsize << " " << bufsize << std::endl;
202    retval = uncompress( dest, &length, a->data, (uLong)compsize );
203    //std::cout << "length " << length << std::endl;
204    switch ( retval ) {
205      case Z_OK: COUT(4) << "successfully decompressed" << std::endl; break;
206      case Z_MEM_ERROR: COUT(1) << "not enough memory available" << std::endl; return NULL;
207      case Z_BUF_ERROR: COUT(2) << "not enough memory available in the buffer" << std::endl; return NULL;
208      case Z_DATA_ERROR: COUT(2) << "data corrupted (zlib)" << std::endl; return NULL;
209    }
210
211    GameState *gamestate = new GameState;
212    gamestate->id = a->id;
213    gamestate->size = normsize;
214    gamestate->data = dest;
215    gamestate->diffed = a->diffed;
216
217    delete a->data; //delete compressed data
218    delete a; //we do not need the old (struct) gamestate anymore
219
220    return gamestate;
221  }
222
223  GameState *GameStateClient::decode(GameState *a, GameStateCompressed *x) {
224    GameState *t = decode(x);
225    gameStateList.push(t);
226    //return undiff(a, t);
227    return t;
228  }
229
230  GameState *GameStateClient::decode(GameStateCompressed *x) {
231    //GameState *t = decompress(x);
232    GameState *t = new GameState;
233    t->base_id = x->base_id;
234    t->id = x->id;
235    t->diffed = x->diffed;
236    t->data = x->data;
237    t->size = x->normsize;
238    gameStateList.push(t);
239    return t;
240  }
241
242}
Note: See TracBrowser for help on using the repository browser.