Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3290 was 3280, checked in by rgrieder, 16 years ago

Merged most of the core4 revisions back to the trunk except for:

  • orxonox_cast
  • all the radical changes in the input library
  • Property svn:eol-style set to native
File size: 8.0 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>
[3084]37#include "util/Serialise.h"
38#include "core/GameMode.h"
[2309]39#include "network/synchronisable/NetworkCallbackManager.h"
[2245]40
41namespace orxonox{
42 
[3280]43  namespace VariableDirection{
44    enum Value{
45      ToClient=0x1,
46      ToServer=0x2
[2245]47    };
[3280]48  }
49  namespace Bidirectionality{
50    enum Value{
51      ServerMaster=0x1,
52      ClientMaster=0x2
[2245]53    };
54  }
55 
56  class _NetworkExport SynchronisableVariableBase
57  {
58    public:
[3084]59      virtual uint32_t getData(uint8_t*& mem, uint8_t mode)=0;
[2245]60      virtual void putData(uint8_t*& mem, uint8_t mode, bool forceCallback = false)=0;
61      virtual uint32_t getSize(uint8_t mode)=0;
62      virtual void* getReference()=0;
63      virtual uint8_t getMode()=0;
64      virtual ~SynchronisableVariableBase() {}
65    protected:
66      static uint8_t state_;
67  };
68
69  template <class T>
[2307]70  class SynchronisableVariable: public SynchronisableVariableBase
[2245]71  {
72    public:
[3280]73      SynchronisableVariable(T& variable, uint8_t syncDirection=VariableDirection::ToClient, NetworkCallbackBase *cb=0);
[2245]74      virtual ~SynchronisableVariable();
75
76      virtual inline uint8_t getMode(){ return mode_; }
[3084]77      virtual inline uint32_t getData(uint8_t*& mem, uint8_t mode);
[2307]78      virtual inline void putData(uint8_t*& mem, uint8_t mode, bool forceCallback = false);
[2575]79      virtual inline uint32_t getSize(uint8_t mode);
[2307]80      virtual inline void* getReference(){ return (void *)&this->variable_; }
[2245]81    protected:
82     
83      T& variable_;
84      uint8_t mode_;
85      NetworkCallbackBase *callback_;
86  };
87 
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();
94     
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  }
114 
115  template <class T> SynchronisableVariable<T>::~SynchronisableVariable()
116  {
117    if (this->callback_ != 0)
[2309]118      NetworkCallbackManager::deleteCallback(this->callback_); //safe call for deletion
[2245]119  }
120
[3084]121  template <class T> inline uint32_t SynchronisableVariable<T>::getData(uint8_t*& mem, uint8_t mode)
[2245]122  {
[3102]123    if ( mode == this->mode_ )
[3084]124    {
125      saveAndIncrease( this->variable_, mem );
126      return returnSize( this->variable_ );
127    }
128    else
129      return 0;
[2245]130  }
131
132  template <class T> void SynchronisableVariable<T>::putData(uint8_t*& mem, uint8_t mode, bool forceCallback)
133  {
134    assert ( mode == 0x1 || mode == 0x2 );
135    bool callback = false;
136    if ( mode == this->mode_ ) //don't do anything
137      return;
138  // check whether we need to consider a callback
139    if ( this->callback_ != 0 )
140    {
[3084]141      if( forceCallback || !checkEquality( this->variable_, mem ) )
[2245]142        callback = true;
143    }
144  // write the data
[3084]145    loadAndIncrease( this->variable_, mem );
[2245]146  // now do a callback if neccessary
147    if ( callback )
[2309]148      NetworkCallbackManager::triggerCallback( this->callback_ );
[2245]149  }
150
[3084]151  template <class T> inline uint32_t SynchronisableVariable<T>::getSize(uint8_t mode)
[2245]152  {
153    if ( mode == this->mode_ )
[3084]154      return returnSize( this->variable_ );
[2245]155    else
156      return 0;
157  }
158
159
[2307]160
161
[2245]162// ================= Bidirectional Part ================
163
164    template <class T> SynchronisableVariableBidirectional<T>::SynchronisableVariableBidirectional(T& variable, uint8_t master, NetworkCallbackBase *cb):
165    SynchronisableVariable<T>( variable, master, cb ), varBuffer_( variable ), varReference_( 0 )
166    {
167    }
168
169    template <class T> SynchronisableVariableBidirectional<T>::~SynchronisableVariableBidirectional()
170    {
171    }
172
[3084]173    template <class T> uint32_t SynchronisableVariableBidirectional<T>::getData(uint8_t*& mem, uint8_t mode)
[2245]174    {
175      if ( this->mode_ == mode )
176      {   // we are master for this variable and have to check whether to change the varReference
177        if( this->varBuffer_ != this->variable_ )
178        {
179          this->varReference_++;
180          memcpy((void*)&this->varBuffer_, &this->variable_, sizeof(this->variable_));
181        }
182      }
183  // write the reference number to the stream
184      *static_cast<uint8_t*>(mem) = varReference_;
185      mem += sizeof(this->varReference_);
186  // now write the content
[3084]187      saveAndIncrease( this->variable_, mem );
188      return SynchronisableVariableBidirectional::getSize(mode);
[2245]189    }
190
191    template <class T> void SynchronisableVariableBidirectional<T>::putData(uint8_t*& mem, uint8_t mode, bool forceCallback)
192    {
193      bool callback = false;
194      if ( this->mode_ == mode )
195      {   //        MASTER
196        // check that the client (source of the data) has a recent version of this variable
197        if ( *static_cast<uint8_t*>(mem) != this->varReference_ )
198        { // wrong reference number, so discard the data
[3084]199//           COUT(0) << "discharding data" << endl;
[2245]200          mem += getSize( mode ); // SynchronisableVariableBidirectional::getSize returns size of variable + reference
201          return;
202        }
203        else{
204          // apply data
[3084]205          if ( checkEquality( this->variable_, mem+sizeof(varReference_) )==true )
[2245]206          {
[3084]207            mem += getSize( mode );
[2245]208            return;
209          }
210          else
211          {
[3084]212            mem += sizeof(varReference_);
[2245]213            memcpy((void*)&this->varBuffer_, &this->variable_, sizeof(T));
214            if ( this->callback_ != 0 )
215              callback = true;
216          }
217        }
218      }
219      else
220      {   // we are slave for this variable
221        if (*static_cast<uint8_t*>(mem) == this->varReference_ && !forceCallback)
222        {
223          mem += getSize( mode ); //just skip the variable because nothing changed
224          return;
225        }
226        else
227        {
228          this->varReference_ = *static_cast<uint8_t*>(mem);
229          mem += sizeof(varReference_);
[3084]230          if ( checkEquality( this->variable_, mem ) == false )
[2245]231          {
232            // value changed so remark for callback
233            if ( this->callback_ != 0 )
234              callback = true;
235          }
236        }
237      }
238  // now write the data
[3084]239      loadAndIncrease(this->variable_, mem);
[2245]240  // now do a callback if neccessary
241      if ( callback )
[2309]242        NetworkCallbackManager::triggerCallback( this->callback_ );
[2245]243    }
244
[3084]245    template <class T> inline uint32_t SynchronisableVariableBidirectional<T>::getSize(uint8_t mode)
[2245]246    {
[3084]247      return returnSize( this->variable_ ) + sizeof(varReference_);
[2245]248    }
249 
250
251}
252
253
[3214]254#endif /* _SynchronisableVariable_H__ */
Note: See TracBrowser for help on using the repository browser.