Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

some changes

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