Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/netp5/src/network/synchronisable/SynchronisableVariable.h @ 3211

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

Moved PacketFlag and added includes for memcpy() and abort() (Mingw didn't seem to care).

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