Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3214 was 3214, checked in by scheusso, 15 years ago

merged netp5 back to trunk

  • Property svn:eol-style set to native
File size: 8.0 KB
Line 
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:
23 *      Oliver Scheuss
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29
30#ifndef _SynchronisableVariable_H__
31#define _SynchronisableVariable_H__
32
33#include "network/NetworkPrereqs.h"
34
35#include <cassert>
36#include <cstring>
37#include "util/Serialise.h"
38#include "core/GameMode.h"
39#include "network/synchronisable/NetworkCallbackManager.h"
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:
57      virtual uint32_t getData(uint8_t*& mem, uint8_t mode)=0;
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>
68  class SynchronisableVariable: public SynchronisableVariableBase
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_; }
75      virtual inline uint32_t getData(uint8_t*& mem, uint8_t mode);
76      virtual inline void putData(uint8_t*& mem, uint8_t mode, bool forceCallback = false);
77      virtual inline uint32_t getSize(uint8_t mode);
78      virtual inline void* getReference(){ return (void *)&this->variable_; }
79    protected:
80     
81      T& variable_;
82      uint8_t mode_;
83      NetworkCallbackBase *callback_;
84  };
85 
86  template <class T>
87  class SynchronisableVariableBidirectional: public SynchronisableVariable<T>
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 ^^
94      virtual inline uint32_t getData(uint8_t*& mem, uint8_t mode);
95      virtual void putData(uint8_t*& mem, uint8_t mode, bool forceCallback = false);
96      virtual inline uint32_t getSize(uint8_t mode);
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  {
107    if ( state_ == 0x0 )
108    {
109      state_ = GameMode::isMaster() ? 0x1 : 0x2;  // set the appropriate mode here
110    }
111  }
112 
113  template <class T> SynchronisableVariable<T>::~SynchronisableVariable()
114  {
115    if (this->callback_ != 0)
116      NetworkCallbackManager::deleteCallback(this->callback_); //safe call for deletion
117  }
118
119  template <class T> inline uint32_t SynchronisableVariable<T>::getData(uint8_t*& mem, uint8_t mode)
120  {
121    if ( mode == this->mode_ )
122    {
123      saveAndIncrease( this->variable_, mem );
124      return returnSize( this->variable_ );
125    }
126    else
127      return 0;
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    {
139      if( forceCallback || !checkEquality( this->variable_, mem ) )
140        callback = true;
141    }
142  // write the data
143    loadAndIncrease( this->variable_, mem );
144  // now do a callback if neccessary
145    if ( callback )
146      NetworkCallbackManager::triggerCallback( this->callback_ );
147  }
148
149  template <class T> inline uint32_t SynchronisableVariable<T>::getSize(uint8_t mode)
150  {
151    if ( mode == this->mode_ )
152      return returnSize( this->variable_ );
153    else
154      return 0;
155  }
156
157
158
159
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
171    template <class T> uint32_t SynchronisableVariableBidirectional<T>::getData(uint8_t*& mem, uint8_t mode)
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
185      saveAndIncrease( this->variable_, mem );
186      return SynchronisableVariableBidirectional::getSize(mode);
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
197//           COUT(0) << "discharding data" << endl;
198          mem += getSize( mode ); // SynchronisableVariableBidirectional::getSize returns size of variable + reference
199          return;
200        }
201        else{
202          // apply data
203          if ( checkEquality( this->variable_, mem+sizeof(varReference_) )==true )
204          {
205            mem += getSize( mode );
206            return;
207          }
208          else
209          {
210            mem += sizeof(varReference_);
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_);
228          if ( checkEquality( this->variable_, mem ) == false )
229          {
230            // value changed so remark for callback
231            if ( this->callback_ != 0 )
232              callback = true;
233          }
234        }
235      }
236  // now write the data
237      loadAndIncrease(this->variable_, mem);
238  // now do a callback if neccessary
239      if ( callback )
240        NetworkCallbackManager::triggerCallback( this->callback_ );
241    }
242
243    template <class T> inline uint32_t SynchronisableVariableBidirectional<T>::getSize(uint8_t mode)
244    {
245      return returnSize( this->variable_ ) + sizeof(varReference_);
246    }
247 
248
249}
250
251
252#endif /* _SynchronisableVariable_H__ */
Note: See TracBrowser for help on using the repository browser.