Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/netp3/src/network/synchronisable/SynchronisableVariable.h @ 2991

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

forgot some things

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