Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/network/synchronisable/SynchronisableVariable.h @ 3118

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

fixed some problems when changing the gamestate (from menu to server i.e.)

  • Property svn:eol-style set to native
File size: 8.1 KB
RevLine 
[2245]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:
[3084]23 *      Oliver Scheuss
[2245]24 *   Co-authors:
25 *      ...
26 *
27 */
28
29
30#ifndef _NETWORK_SYNCHRONISABLEVARIABLE__
31#define _NETWORK_SYNCHRONISABLEVARIABLE__
32
[2307]33#include "network/NetworkPrereqs.h"
34
35#include <string>
36#include <cassert>
[3084]37#include "util/Serialise.h"
38#include "core/Core.h"
39#include "core/CoreIncludes.h"
40#include "core/GameMode.h"
[2307]41#include "network/synchronisable/NetworkCallback.h"
[2309]42#include "network/synchronisable/NetworkCallbackManager.h"
[2245]43
44namespace orxonox{
45 
46  namespace variableDirection{
47    enum syncdirection{
48      toclient=0x1,
49      toserver=0x2
50    };
51    enum bidirectional{
52      serverMaster=0x1,
53      clientMaster=0x2
54    };
55  }
56 
57  class _NetworkExport SynchronisableVariableBase
58  {
59    public:
[3084]60      virtual uint32_t getData(uint8_t*& mem, uint8_t mode)=0;
[2245]61      virtual void putData(uint8_t*& mem, uint8_t mode, bool forceCallback = false)=0;
62      virtual uint32_t getSize(uint8_t mode)=0;
63      virtual void* getReference()=0;
64      virtual uint8_t getMode()=0;
65      virtual ~SynchronisableVariableBase() {}
66    protected:
67      static uint8_t state_;
68  };
69
70  template <class T>
[2307]71  class SynchronisableVariable: public SynchronisableVariableBase
[2245]72  {
73    public:
74      SynchronisableVariable(T& variable, uint8_t syncDirection=variableDirection::toclient, NetworkCallbackBase *cb=0);
75      virtual ~SynchronisableVariable();
76
77      virtual inline uint8_t getMode(){ return mode_; }
[3084]78      virtual inline uint32_t getData(uint8_t*& mem, uint8_t mode);
[2307]79      virtual inline void putData(uint8_t*& mem, uint8_t mode, bool forceCallback = false);
[2575]80      virtual inline uint32_t getSize(uint8_t mode);
[2307]81      virtual inline void* getReference(){ return (void *)&this->variable_; }
[2245]82    protected:
83     
84      T& variable_;
85      uint8_t mode_;
86      NetworkCallbackBase *callback_;
87  };
88 
89  template <class T>
[2307]90  class SynchronisableVariableBidirectional: public SynchronisableVariable<T>
[2245]91  {
92    public:
93      SynchronisableVariableBidirectional(T& variable, uint8_t master=variableDirection::serverMaster, NetworkCallbackBase *cb=0);
94      virtual ~SynchronisableVariableBidirectional();
95     
96      virtual inline uint8_t getMode(){ return 0x3; } //this basically is a hack ^^
[3084]97      virtual inline uint32_t getData(uint8_t*& mem, uint8_t mode);
[2245]98      virtual void putData(uint8_t*& mem, uint8_t mode, bool forceCallback = false);
[3084]99      virtual inline uint32_t getSize(uint8_t mode);
[2245]100    private:
101      T varBuffer_;
102      uint8_t varReference_;
103  };
104
105  // ================= Unidirectional Part ===============
106
107  template <class T> SynchronisableVariable<T>::SynchronisableVariable(T& variable, uint8_t syncDirection, NetworkCallbackBase *cb):
108      variable_( variable ), mode_( syncDirection ), callback_( cb )
109  {
[3084]110    if ( state_ == 0x0 )
111    {
112      state_ = GameMode::isMaster() ? 0x1 : 0x2;  // set the appropriate mode here
113    }
[2245]114  }
115 
116  template <class T> SynchronisableVariable<T>::~SynchronisableVariable()
117  {
118    if (this->callback_ != 0)
[2309]119      NetworkCallbackManager::deleteCallback(this->callback_); //safe call for deletion
[2245]120  }
121
[3084]122  template <class T> inline uint32_t SynchronisableVariable<T>::getData(uint8_t*& mem, uint8_t mode)
[2245]123  {
[3102]124    if ( mode == this->mode_ )
[3084]125    {
126      saveAndIncrease( this->variable_, mem );
127      return returnSize( this->variable_ );
128    }
129    else
130      return 0;
[2245]131  }
132
133  template <class T> void SynchronisableVariable<T>::putData(uint8_t*& mem, uint8_t mode, bool forceCallback)
134  {
135    assert ( mode == 0x1 || mode == 0x2 );
136    bool callback = false;
137    if ( mode == this->mode_ ) //don't do anything
138      return;
139  // check whether we need to consider a callback
140    if ( this->callback_ != 0 )
141    {
[3084]142      if( forceCallback || !checkEquality( this->variable_, mem ) )
[2245]143        callback = true;
144    }
145  // write the data
[3084]146    loadAndIncrease( this->variable_, mem );
[2245]147  // now do a callback if neccessary
148    if ( callback )
[2309]149      NetworkCallbackManager::triggerCallback( this->callback_ );
[2245]150  }
151
[3084]152  template <class T> inline uint32_t SynchronisableVariable<T>::getSize(uint8_t mode)
[2245]153  {
154    if ( mode == this->mode_ )
[3084]155      return returnSize( this->variable_ );
[2245]156    else
157      return 0;
158  }
159
160
[2307]161
162
[2245]163// ================= Bidirectional Part ================
164
165    template <class T> SynchronisableVariableBidirectional<T>::SynchronisableVariableBidirectional(T& variable, uint8_t master, NetworkCallbackBase *cb):
166    SynchronisableVariable<T>( variable, master, cb ), varBuffer_( variable ), varReference_( 0 )
167    {
168    }
169
170    template <class T> SynchronisableVariableBidirectional<T>::~SynchronisableVariableBidirectional()
171    {
172    }
173
[3084]174    template <class T> uint32_t SynchronisableVariableBidirectional<T>::getData(uint8_t*& mem, uint8_t mode)
[2245]175    {
176      if ( this->mode_ == mode )
177      {   // we are master for this variable and have to check whether to change the varReference
178        if( this->varBuffer_ != this->variable_ )
179        {
180          this->varReference_++;
181          memcpy((void*)&this->varBuffer_, &this->variable_, sizeof(this->variable_));
182        }
183      }
184  // write the reference number to the stream
185      *static_cast<uint8_t*>(mem) = varReference_;
186      mem += sizeof(this->varReference_);
187  // now write the content
[3084]188      saveAndIncrease( this->variable_, mem );
189      return SynchronisableVariableBidirectional::getSize(mode);
[2245]190    }
191
192    template <class T> void SynchronisableVariableBidirectional<T>::putData(uint8_t*& mem, uint8_t mode, bool forceCallback)
193    {
194      bool callback = false;
195      if ( this->mode_ == mode )
196      {   //        MASTER
197        // check that the client (source of the data) has a recent version of this variable
198        if ( *static_cast<uint8_t*>(mem) != this->varReference_ )
199        { // wrong reference number, so discard the data
[3084]200//           COUT(0) << "discharding data" << endl;
[2245]201          mem += getSize( mode ); // SynchronisableVariableBidirectional::getSize returns size of variable + reference
202          return;
203        }
204        else{
205          // apply data
[3084]206          if ( checkEquality( this->variable_, mem+sizeof(varReference_) )==true )
[2245]207          {
[3084]208            mem += getSize( mode );
[2245]209            return;
210          }
211          else
212          {
[3084]213            mem += sizeof(varReference_);
[2245]214            memcpy((void*)&this->varBuffer_, &this->variable_, sizeof(T));
215            if ( this->callback_ != 0 )
216              callback = true;
217          }
218        }
219      }
220      else
221      {   // we are slave for this variable
222        if (*static_cast<uint8_t*>(mem) == this->varReference_ && !forceCallback)
223        {
224          mem += getSize( mode ); //just skip the variable because nothing changed
225          return;
226        }
227        else
228        {
229          this->varReference_ = *static_cast<uint8_t*>(mem);
230          mem += sizeof(varReference_);
[3084]231          if ( checkEquality( this->variable_, mem ) == false )
[2245]232          {
233            // value changed so remark for callback
234            if ( this->callback_ != 0 )
235              callback = true;
236          }
237        }
238      }
239  // now write the data
[3084]240      loadAndIncrease(this->variable_, mem);
[2245]241  // now do a callback if neccessary
242      if ( callback )
[2309]243        NetworkCallbackManager::triggerCallback( this->callback_ );
[2245]244    }
245
[3084]246    template <class T> inline uint32_t SynchronisableVariableBidirectional<T>::getSize(uint8_t mode)
[2245]247    {
[3084]248      return returnSize( this->variable_ ) + sizeof(varReference_);
[2245]249    }
250 
251
252}
253
254
255#endif
Note: See TracBrowser for help on using the repository browser.