Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

some bugfix in GameStateManager.cc, CMakeLists now generates networktest executable, some test functions added

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