Orxonox  0.0.5 Codename: Arcturus
SynchronisableVariable.h
Go to the documentation of this file.
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 <loki/TypeTraits.h>
38 
39 #include "Serialise.h"
40 #include "core/GameMode.h"
42 
43 namespace orxonox{
44 
45  namespace VariableDirection{
46  enum Value{
47  ToClient=0x1,
49  };
50  }
51  namespace Bidirectionality{
52  enum Value{
55  };
56  }
57 
59  {
60  public:
61  virtual uint32_t getData(uint8_t*& mem, uint8_t mode)=0;
62  virtual void putData(uint8_t*& mem, uint8_t mode, bool forceCallback = false)=0;
63  virtual uint32_t getSize(uint8_t mode)=0;
64  virtual void* getReference()=0;
65  virtual uint8_t getMode()=0;
67  };
68 
69  template <class T>
71  {
72  public:
73  SynchronisableVariable(T& variable, uint8_t syncDirection=VariableDirection::ToClient, NetworkCallbackBase *cb=nullptr);
74  virtual ~SynchronisableVariable();
75 
76  virtual inline uint8_t getMode() override{ return mode_; }
77  virtual inline uint32_t getData(uint8_t*& mem, uint8_t mode) override;
78  virtual inline void putData(uint8_t*& mem, uint8_t mode, bool forceCallback = false) override;
79  virtual inline uint32_t getSize(uint8_t mode) override;
80  virtual inline void* getReference() override{ return static_cast<void*>(const_cast<typename Loki::TypeTraits<T>::UnqualifiedType*>(&this->variable_)); }
81  protected:
83  uint8_t mode_;
85  };
86 
87  template <class T>
89  {
90  public:
93 
94  virtual inline uint8_t getMode(){ return 0x3; } //this basically is a hack ^^
95  virtual inline uint32_t getData(uint8_t*& mem, uint8_t mode);
96  virtual void putData(uint8_t*& mem, uint8_t mode, bool forceCallback = false);
97  virtual inline uint32_t getSize(uint8_t mode);
98  private:
100  uint8_t varReference_;
101  };
102 
103  // ================= Unidirectional Part ===============
104 
105  template <class T> SynchronisableVariable<T>::SynchronisableVariable(T& variable, uint8_t syncDirection, NetworkCallbackBase *cb):
106  variable_( variable ), mode_( syncDirection ), callback_( cb )
107  {
108  }
109 
111  {
112  if (this->callback_)
113  {
114  NetworkCallbackManager::deleteCallback(this->callback_); //safe call for deletion
115  // this is neccessary because for example for a Vector3 all 3 components of the vector use the same callback
116  }
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_ )
138  {
139  callback = forceCallback || !checkEquality( this->variable_, mem );
140  }
141  // now do a callback if neccessary
142  if ( callback )
143  {
145  }
146  // write the data
147  loadAndIncrease( this->variable_, mem );
148  }
149 
150  template <class T> inline uint32_t SynchronisableVariable<T>::getSize(uint8_t mode)
151  {
152  if ( mode == this->mode_ )
153  return returnSize( this->variable_ );
154  else
155  return 0;
156  }
157 
158 
159 
160 
161 // ================= Bidirectional Part ================
162 
164  SynchronisableVariable<T>( variable, master, cb ), varBuffer_( variable ), varReference_( 0 )
165  {
166  }
167 
169  {
170  }
171 
172  template <class T> uint32_t SynchronisableVariableBidirectional<T>::getData(uint8_t*& mem, uint8_t mode)
173  {
174  if ( this->mode_ == mode )
175  { // we are master for this variable and have to check whether to change the varReference
176  if( this->varBuffer_ != this->variable_ )
177  {
178  this->varReference_++;
179  memcpy(static_cast<void*>(const_cast<typename Loki::TypeTraits<T>::UnqualifiedType*>(&this->varBuffer_)), &this->variable_, sizeof(this->variable_));
180  }
181  }
182  // write the reference number to the stream
183  *static_cast<uint8_t*>(mem) = varReference_;
184  mem += sizeof(this->varReference_);
185  // now write the content
186  saveAndIncrease( this->variable_, mem );
188  }
189 
190  template <class T> void SynchronisableVariableBidirectional<T>::putData(uint8_t*& mem, uint8_t mode, bool forceCallback)
191  {
192  bool callback = false;
193  if ( this->mode_ == mode )
194  { // MASTER
195  // check that the client (source of the data) has a recent version of this variable
196  if ( *static_cast<uint8_t*>(mem) != this->varReference_ )
197  { // wrong reference number, so discard the data
198 // orxout(debug_output, context::network) << "discharding data" << endl;
199  mem += getSize( mode ); // SynchronisableVariableBidirectional::getSize returns size of variable + reference
200  return;
201  }
202  else{
203  // apply data
204  if ( checkEquality( this->variable_, mem+sizeof(varReference_) )==true )
205  {
206  mem += getSize( mode );
207  return;
208  }
209  else
210  {
211  mem += sizeof(varReference_);
212  memcpy(static_cast<void*>(const_cast<typename Loki::TypeTraits<T>::UnqualifiedType*>(&this->varBuffer_)), &this->variable_, sizeof(T));
213  if ( this->callback_ )
214  callback = true;
215  }
216  }
217  }
218  else
219  { // we are slave for this variable
220  if (*static_cast<uint8_t*>(mem) == this->varReference_ && !forceCallback)
221  {
222  mem += getSize( mode ); //just skip the variable because nothing changed
223  return;
224  }
225  else
226  {
227  this->varReference_ = *static_cast<uint8_t*>(mem);
228  mem += sizeof(varReference_);
229  if ( checkEquality( this->variable_, mem ) == false )
230  {
231  // value changed so remark for callback
232  if ( this->callback_ )
233  callback = true;
234  }
235  }
236  }
237  // now do a callback if neccessary
238  if ( callback )
239  {
241  }
242  // now write the data
243  loadAndIncrease(this->variable_, mem);
244  }
245 
246  template <class T> inline uint32_t SynchronisableVariableBidirectional<T>::getSize(uint8_t mode)
247  {
248  return returnSize( this->variable_ ) + sizeof(varReference_);
249  }
250 
251 
252 }
253 
254 
255 #endif /* _SynchronisableVariable_H__ */
T & variable_
Definition: SynchronisableVariable.h:82
Definition: SynchronisableVariable.h:58
Shared library macros, enums, constants and forward declarations for the network library ...
static void triggerCallback(NetworkCallbackBase *cb)
Definition: NetworkCallbackManager.cc:51
NetworkCallbackBase * callback_
Definition: SynchronisableVariable.h:84
virtual uint8_t getMode() override
Definition: SynchronisableVariable.h:76
bool checkEquality(T *&variable, uint8_t *mem)
checks whether the objectID of the variable is the same as in the bytestream
Definition: Serialise.h:72
uint32_t returnSize(T *&variable)
returns the size of the objectID needed to synchronise the pointer
Definition: Serialise.h:49
virtual void * getReference() override
Definition: SynchronisableVariable.h:80
SynchronisableVariable(T &variable, uint8_t syncDirection=VariableDirection::ToClient, NetworkCallbackBase *cb=nullptr)
Definition: SynchronisableVariable.h:105
virtual uint32_t getData(uint8_t *&mem, uint8_t mode) override
Definition: SynchronisableVariable.h:119
Definition: SynchronisableVariable.h:47
Definition: NetworkPrereqs.h:177
uint8_t varReference_
Definition: SynchronisableVariable.h:100
uint8_t mode_
Definition: SynchronisableVariable.h:83
virtual uint8_t getMode()
Definition: SynchronisableVariable.h:94
Functions to serialise pointers to objects that inherit from Synchronisable.
virtual ~SynchronisableVariableBase()
Definition: SynchronisableVariable.h:66
Definition: SynchronisableVariable.h:48
T varBuffer_
Definition: SynchronisableVariable.h:99
SynchronisableVariableBidirectional(T &variable, uint8_t master=Bidirectionality::ServerMaster, NetworkCallbackBase *cb=nullptr)
Definition: SynchronisableVariable.h:163
Definition: SynchronisableVariable.h:53
UnVolatile< typename UnConst< T >::Result >::Result UnqualifiedType
Definition: TypeTraits.h:256
Die Wagnis Klasse hat die folgenden Aufgaben:
Definition: ApplicationPaths.cc:66
#define _NetworkExport
Definition: NetworkPrereqs.h:59
virtual void putData(uint8_t *&mem, uint8_t mode, bool forceCallback=false)
Definition: SynchronisableVariable.h:190
void saveAndIncrease(T *&variable, uint8_t *&mem)
saves the objectID of a pointer into the bytestream and increases the mem pointer ...
Definition: Serialise.h:62
Declaration of the GameMode class which stores and returns the current mode of the game...
Value
Definition: SynchronisableVariable.h:46
Definition: InputPrereqs.h:78
static void deleteCallback(NetworkCallbackBase *cb)
Definition: NetworkCallbackManager.cc:41
virtual uint32_t getSize(uint8_t mode) override
Definition: SynchronisableVariable.h:150
virtual ~SynchronisableVariable()
Definition: SynchronisableVariable.h:110
Definition: NetworkPrereqs.h:174
Definition: SynchronisableVariable.h:54
Value
Definition: SynchronisableVariable.h:52
virtual ~SynchronisableVariableBidirectional()
Definition: SynchronisableVariable.h:168
virtual uint32_t getData(uint8_t *&mem, uint8_t mode)
Definition: SynchronisableVariable.h:172
Definition: NetworkCallback.h:41
virtual void putData(uint8_t *&mem, uint8_t mode, bool forceCallback=false) override
Definition: SynchronisableVariable.h:130
void loadAndIncrease(T *&variable, uint8_t *&mem)
reads the objectID of a pointer out of the bytestream and increases the mem pointer ...
Definition: Serialise.h:55
virtual uint32_t getSize(uint8_t mode)
Definition: SynchronisableVariable.h:246