Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/network/GameStateClient.cc @ 1056

Last change on this file since 1056 was 1056, checked in by landauf, 16 years ago

don't panic, no codechanges!
added a link to www.orxonox.net

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