LibNRG  0.0.1
Networking for Real-time Games library
 All Classes Files Functions Variables Friends
nrg_field.h
Go to the documentation of this file.
1 /*
2  LibNRG - Networking for Real-time Games
3 
4  Copyright (C) 2012-2014 Alex Baines <alex@abaines.me.uk>
5 
6  This software is provided 'as-is', without any express or implied
7  warranty. In no event will the authors be held liable for any damages
8  arising from the use of this software.
9 
10  Permission is granted to anyone to use this software for any purpose,
11  including commercial applications, and to alter it and redistribute it
12  freely, subject to the following restrictions:
13 
14  1. The origin of this software must not be misrepresented; you must not
15  claim that you wrote the original software. If you use this software
16  in a product, an acknowledgment in the product documentation would be
17  appreciated but is not required.
18  2. Altered source versions must be plainly marked as such, and must not be
19  misrepresented as being the original software.
20  3. This notice may not be removed or altered from any source distribution.
21 */
25 #ifndef NRG_FIELD_H
26 #define NRG_FIELD_H
27 #include "nrg_core.h"
28 #include "nrg_packet.h"
29 #include "nrg_codec.h"
30 #include "nrg_util.h"
31 #include "nrg_interp.h"
32 #include <bitset>
33 
34 namespace nrg {
35 
36 class FieldContainer;
37 
39 class FieldBase {
40 public:
42  FieldBase(FieldContainer* container);
43 
45  FieldBase(const FieldBase& copy);
46 
48  FieldBase& operator=(const FieldBase& copy);
49 
51  virtual size_t readFromPacket(Packet& p) = 0;
52 
54  virtual size_t writeToPacket(Packet& p) const = 0;
55 
57  virtual void shiftData() = 0;
58 
60  virtual ~FieldBase(){}
61 
63  virtual bool wasUpdated() const;
64 
66  virtual void setUpdated(bool updated);
67 
69  FieldBase* getNextField() const;
70 
72  void setNextField(FieldBase* f);
74 protected:
75  FieldContainer* container;
76  FieldBase* next;
77  bool updated;
78 };
79 
84 
86  FieldContainer(const FieldContainer& copy);
87 
90 
92  FieldBase* getFirstField() const;
93 
95  size_t getNumFields() const;
96 
99  virtual void markUpdated(bool b) = 0;
101  virtual double getInterpTimer() const { return 1.0; }
103  void addField(FieldBase* f);
105 private:
106  FieldBase* field_head;
107  size_t num_fields;
108 };
109 
111 template<typename T, class Cdc = nrg::Codec<T> >
112 class Field : private FieldBase {
113 public:
114  /* Standard Constructor */
115  Field(FieldContainer* c) : FieldBase(c), data(), data_next(){}
116 
117  /* Constructor with specified initial value \p t */
118  Field(FieldContainer* c, const T& t) : FieldBase(c), data(t), data_next(t){}
119 
120  virtual size_t readFromPacket(Packet& p){
121  return Cdc().decode(p, data_next);
122  }
123 
124  virtual size_t writeToPacket(Packet& p) const {
125  return Cdc().encode(p, data);
126  }
127 
128  virtual void shiftData(){
129  data = data_next;
130  }
131 
133  void set(const T& other){
134  *this = other;
135  }
136 
138  Field& operator=(const T& other){
139  if(data != other){
140  data = data_next = other;
141  this->setUpdated(true);
142  }
143  return *this;
144  }
145 
147  T get() const {
148  return data_next;
149  }
150 
152  template<class F>
153  T getInterp(const F& func) const {
154  return func(data, data_next, this->container->getInterpTimer());
155  }
156 
158  T getInterp() const {
159  return lerp<T>()(data, data_next, this->container->getInterpTimer());
160  }
161 private:
162  T data, data_next;
163 };
164 
166 template<typename T, size_t N>
167 class Field<T[N]> : private FieldBase {
168 public:
169  Field(FieldContainer* c) : FieldBase(c), data(){
170  updated_indices.set();
171  }
172  Field(FieldContainer* c, const T (&t)[N]) : FieldBase(c), data(t){
173  updated_indices.set();
174  }
175 
176  virtual size_t readFromPacket(Packet& p){
177  index_t count;
178  p.read<index_t>(count);
179  size_t uic = count + 1;
180 
181  if(uic * (sizeof(index_t) + sizeof(T)) > N * sizeof(T)){
182  for(size_t i = 0; i < N; ++i){
183  p.read<T>(data_next[i]);
184  }
185  return sizeof(index_t) + N * sizeof(T);
186  } else {
187  for(size_t i = 0; i < uic; ++i){
188  index_t k;
189  p.read<index_t>(k);
190  if(k < N){
191  p.read<T>(data_next[k]);
192  } else { // out of bounds for some reason, don't crash.
193  p.seek(SEEK_CUR, sizeof(T));
194  }
195  }
196  return sizeof(index_t) + (uic * (sizeof(index_t) + sizeof(T)));
197  }
198  }
199 
200  virtual size_t writeToPacket(Packet& p) const {
201  size_t uic = updated_indices.count();
202  p.write<index_t>(uic-1);
203 
204  if(uic * (sizeof(index_t) + sizeof(T)) > N * sizeof(T)){
205  for(size_t i = 0; i < N; ++i){
206  p.write<T>(data[i]);
207  }
208  return sizeof(index_t) + (N * sizeof(T));
209  } else {
210  for(size_t i = 0; i < N; ++i){
211  if(updated_indices[i]){
212  p.write<index_t>(i);
213  p.write<T>(data[i]);
214  }
215  }
216  return sizeof(index_t) + (uic * (sizeof(index_t) + sizeof(T)));
217  }
218  }
219 
220  virtual void shiftData(){
221  memcpy(data, data_next, N * sizeof(T));
222  }
223 
224  virtual void setUpdated(bool updated){
225  FieldBase::setUpdated(updated);
226  if(!updated) updated_indices.reset();
227  }
228 
229  void set(size_t index, const T& other){
230  if(data[index] != other){
231  data[index] = other;
232  updated_indices.set(index);
233  FieldBase::setUpdated(true);
234  }
235  }
236 
237  Field& operator=(const T (&other)[N]){
238  data = other;
239  FieldBase::setUpdated(true);
240  return *this;
241  }
242 
243  T get(size_t index) const {
244  return data_next[index];
245  }
246 
247  template<class F>
248  T getInterp(size_t index, const F& func) const {
249  return func(data[index], data_next[index], this->container->getInterpTimer());
250  }
251 
252  T getInterp(size_t index) const {
253  return lerp<T>()(data[index], data_next[index], this->container->getInterpTimer());
254  }
255 private:
256  T data[N], data_next[N];
257  std::bitset<N> updated_indices;
258  typedef typename detail::size2type<detail::min_sizeof<N-1>::val>::type index_t;
259 };
260 
261 }
262 
263 #endif
Packet & seek(off_t offset, int whence)
Seeks the packet to some offset using SEEK_SET, SEEK_CUR or SEEK_END.
virtual void setUpdated(bool updated)
Force this Field's updated flag to be true or false.
Definition: nrg_field.h:224
FieldContainer()
Standard Constructor.
Field & operator=(const T &other)
Assignment operator, which also marks this field as having been updated.
Definition: nrg_field.h:138
Template class encapsulating a type that will be replicated from Server to Clients, and is stored inside a FieldContainer.
Definition: nrg_field.h:112
FieldBase * getNextField() const
Returns the next Field in the FielcContainer's linked list, or nullptr at the end of the list...
FieldBase & operator=(const FieldBase &copy)
Assignment operator.
Contains the Codec class, which encodes and decodes types to and from Packets.
Class for storing data to be sent / received across the network.
Definition: nrg_packet.h:58
void read(T &v)
Generic read function with endian conversion, be careful with types like size_t that differ across pl...
Definition: nrg_packet.h:115
virtual void shiftData()
Indicates a new Snapshot has begun and the Field should move data_next to data.
Definition: nrg_field.h:220
virtual size_t readFromPacket(Packet &p)
Reads data from Packet p into this Field.
Definition: nrg_field.h:120
virtual size_t writeToPacket(Packet &p) const
Writes this Field into the Packet p.
Definition: nrg_field.h:200
virtual size_t readFromPacket(Packet &p)=0
Reads data from Packet p into this Field.
virtual void setUpdated(bool updated)
Force this Field's updated flag to be true or false.
Various utility classes and functions.
virtual size_t readFromPacket(Packet &p)
Reads data from Packet p into this Field.
Definition: nrg_field.h:176
virtual size_t writeToPacket(Packet &p) const =0
Writes this Field into the Packet p.
FieldContainer & operator=(const FieldContainer &copy)
Assignment Operator.
FieldBase(FieldContainer *container)
Standard Constructor.
virtual size_t writeToPacket(Packet &p) const
Writes this Field into the Packet p.
Definition: nrg_field.h:124
T getInterp(const F &func) const
Returns data interpolated between the two latest Snapshots using func.
Definition: nrg_field.h:153
virtual void shiftData()=0
Indicates a new Snapshot has begun and the Field should move data_next to data.
Abstract base class that Field inherits from.
Definition: nrg_field.h:39
virtual void shiftData()
Indicates a new Snapshot has begun and the Field should move data_next to data.
Definition: nrg_field.h:128
Simple linear-interpolation functor.
Definition: nrg_interp.h:33
virtual bool wasUpdated() const
Returns true if the Field was updated since the last update.
void set(const T &other)
Alternative to Field::operator=.
Definition: nrg_field.h:133
size_t getNumFields() const
Returns the number of fields in this FieldContainer's linked-list.
Abstract class used by anything that contains Fields, like Entity or InputBase.
Definition: nrg_field.h:81
T getInterp() const
Returns data linearly interpolated between the two latest Snapshots using nrg::lerp.
Definition: nrg_field.h:158
Common defines and includes used by all the other nrg header files.
FieldBase * getFirstField() const
Return the first field in this FieldContainer's internal linked-list.
virtual ~FieldBase()
Standard Destructor.
Definition: nrg_field.h:60
void write(const T &v)
Generic write function with endian conversion, be careful with types like size_t that differ across p...
Definition: nrg_packet.h:94
Interpolation functionality.