Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 6514 was 6417, checked in by rgrieder, 15 years ago

Merged presentation2 branch back to trunk.
Major new features:

  • Actual GUI with settings, etc.
  • Improved space ship steering (human interaction)
  • Rocket fire and more particle effects
  • Advanced sound framework
  • Property svn:eol-style set to native
File size: 8.4 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
[3214]30#ifndef _SynchronisableVariable_H__
31#define _SynchronisableVariable_H__
[2245]32
[2307]33#include "network/NetworkPrereqs.h"
34
35#include <cassert>
[3214]36#include <cstring>
[6417]37#include "Serialise.h"
[3332]38#include "util/TypeTraits.h"
[3084]39#include "core/GameMode.h"
[2309]40#include "network/synchronisable/NetworkCallbackManager.h"
[2245]41
42namespace orxonox{
[6417]43
[3280]44  namespace VariableDirection{
45    enum Value{
46      ToClient=0x1,
47      ToServer=0x2
[2245]48    };
[3280]49  }
50  namespace Bidirectionality{
51    enum Value{
52      ServerMaster=0x1,
53      ClientMaster=0x2
[2245]54    };
55  }
[6417]56
[2245]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:
[3280]74      SynchronisableVariable(T& variable, uint8_t syncDirection=VariableDirection::ToClient, NetworkCallbackBase *cb=0);
[2245]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);
[3332]81      virtual inline void* getReference(){ return static_cast<void*>(const_cast<typename Loki::TypeTraits<T>::UnqualifiedType*>(&this->variable_)); }
[2245]82    protected:
[6417]83      T&                       variable_;
84      uint8_t                  mode_;
85      NetworkCallbackBase      *callback_;
[2245]86  };
[6417]87
[2245]88  template <class T>
[2307]89  class SynchronisableVariableBidirectional: public SynchronisableVariable<T>
[2245]90  {
91    public:
[3280]92      SynchronisableVariableBidirectional(T& variable, uint8_t master=Bidirectionality::ServerMaster, NetworkCallbackBase *cb=0);
[2245]93      virtual ~SynchronisableVariableBidirectional();
[6417]94
[2245]95      virtual inline uint8_t getMode(){ return 0x3; } //this basically is a hack ^^
[3084]96      virtual inline uint32_t getData(uint8_t*& mem, uint8_t mode);
[2245]97      virtual void putData(uint8_t*& mem, uint8_t mode, bool forceCallback = false);
[3084]98      virtual inline uint32_t getSize(uint8_t mode);
[2245]99    private:
100      T varBuffer_;
101      uint8_t varReference_;
102  };
103
104  // ================= Unidirectional Part ===============
105
106  template <class T> SynchronisableVariable<T>::SynchronisableVariable(T& variable, uint8_t syncDirection, NetworkCallbackBase *cb):
107      variable_( variable ), mode_( syncDirection ), callback_( cb )
108  {
[3084]109    if ( state_ == 0x0 )
110    {
111      state_ = GameMode::isMaster() ? 0x1 : 0x2;  // set the appropriate mode here
112    }
[2245]113  }
[6417]114
[2245]115  template <class T> SynchronisableVariable<T>::~SynchronisableVariable()
116  {
[6417]117    if (this->callback_)
[3304]118    {
[2309]119      NetworkCallbackManager::deleteCallback(this->callback_); //safe call for deletion
[3304]120      // this is neccessary because for example for a Vector3 all 3 components of the vector use the same callback
121    }
[2245]122  }
123
[3084]124  template <class T> inline uint32_t SynchronisableVariable<T>::getData(uint8_t*& mem, uint8_t mode)
[2245]125  {
[3102]126    if ( mode == this->mode_ )
[3084]127    {
128      saveAndIncrease( this->variable_, mem );
129      return returnSize( this->variable_ );
130    }
131    else
132      return 0;
[2245]133  }
134
135  template <class T> void SynchronisableVariable<T>::putData(uint8_t*& mem, uint8_t mode, bool forceCallback)
136  {
137    assert ( mode == 0x1 || mode == 0x2 );
138    bool callback = false;
139    if ( mode == this->mode_ ) //don't do anything
140      return;
141  // check whether we need to consider a callback
[6417]142    if ( this->callback_ )
[2245]143    {
[6417]144      callback = forceCallback || !checkEquality( this->variable_, mem );
[2245]145    }
146  // now do a callback if neccessary
147    if ( callback )
[6417]148    {
[2309]149      NetworkCallbackManager::triggerCallback( this->callback_ );
[6417]150    }
151  // write the data
152    loadAndIncrease( this->variable_, mem );
[2245]153  }
154
[3084]155  template <class T> inline uint32_t SynchronisableVariable<T>::getSize(uint8_t mode)
[2245]156  {
157    if ( mode == this->mode_ )
[3084]158      return returnSize( this->variable_ );
[2245]159    else
160      return 0;
161  }
162
163
[2307]164
165
[2245]166// ================= Bidirectional Part ================
167
168    template <class T> SynchronisableVariableBidirectional<T>::SynchronisableVariableBidirectional(T& variable, uint8_t master, NetworkCallbackBase *cb):
169    SynchronisableVariable<T>( variable, master, cb ), varBuffer_( variable ), varReference_( 0 )
170    {
171    }
172
173    template <class T> SynchronisableVariableBidirectional<T>::~SynchronisableVariableBidirectional()
174    {
175    }
176
[3084]177    template <class T> uint32_t SynchronisableVariableBidirectional<T>::getData(uint8_t*& mem, uint8_t mode)
[2245]178    {
179      if ( this->mode_ == mode )
180      {   // we are master for this variable and have to check whether to change the varReference
181        if( this->varBuffer_ != this->variable_ )
182        {
183          this->varReference_++;
[3332]184          memcpy(static_cast<void*>(const_cast<typename Loki::TypeTraits<T>::UnqualifiedType*>(&this->varBuffer_)), &this->variable_, sizeof(this->variable_));
[2245]185        }
186      }
187  // write the reference number to the stream
188      *static_cast<uint8_t*>(mem) = varReference_;
189      mem += sizeof(this->varReference_);
190  // now write the content
[3084]191      saveAndIncrease( this->variable_, mem );
192      return SynchronisableVariableBidirectional::getSize(mode);
[2245]193    }
194
195    template <class T> void SynchronisableVariableBidirectional<T>::putData(uint8_t*& mem, uint8_t mode, bool forceCallback)
196    {
197      bool callback = false;
198      if ( this->mode_ == mode )
199      {   //        MASTER
200        // check that the client (source of the data) has a recent version of this variable
201        if ( *static_cast<uint8_t*>(mem) != this->varReference_ )
202        { // wrong reference number, so discard the data
[3084]203//           COUT(0) << "discharding data" << endl;
[2245]204          mem += getSize( mode ); // SynchronisableVariableBidirectional::getSize returns size of variable + reference
205          return;
206        }
207        else{
208          // apply data
[3084]209          if ( checkEquality( this->variable_, mem+sizeof(varReference_) )==true )
[2245]210          {
[3084]211            mem += getSize( mode );
[2245]212            return;
213          }
214          else
215          {
[3084]216            mem += sizeof(varReference_);
[3332]217            memcpy(static_cast<void*>(const_cast<typename Loki::TypeTraits<T>::UnqualifiedType*>(&this->varBuffer_)), &this->variable_, sizeof(T));
[6417]218            if ( this->callback_ )
[2245]219              callback = true;
220          }
221        }
222      }
223      else
224      {   // we are slave for this variable
225        if (*static_cast<uint8_t*>(mem) == this->varReference_ && !forceCallback)
226        {
227          mem += getSize( mode ); //just skip the variable because nothing changed
228          return;
229        }
230        else
231        {
232          this->varReference_ = *static_cast<uint8_t*>(mem);
233          mem += sizeof(varReference_);
[3084]234          if ( checkEquality( this->variable_, mem ) == false )
[2245]235          {
236            // value changed so remark for callback
[6417]237            if ( this->callback_ )
[2245]238              callback = true;
239          }
240        }
241      }
242  // now do a callback if neccessary
243      if ( callback )
[6417]244      {
[2309]245        NetworkCallbackManager::triggerCallback( this->callback_ );
[6417]246      }
247  // now write the data
248      loadAndIncrease(this->variable_, mem);
[2245]249    }
250
[3084]251    template <class T> inline uint32_t SynchronisableVariableBidirectional<T>::getSize(uint8_t mode)
[2245]252    {
[3084]253      return returnSize( this->variable_ ) + sizeof(varReference_);
[2245]254    }
255
[6417]256
[2245]257}
258
259
[3214]260#endif /* _SynchronisableVariable_H__ */
Note: See TracBrowser for help on using the repository browser.