Emergency 20 Dokumentation  4.2.0
MapCache.h
Go to the documentation of this file.
1 // Copyright (C) 2012-2018 Promotion Software GmbH
2 
3 
4 //[-------------------------------------------------------]
5 //[ Header guard ]
6 //[-------------------------------------------------------]
7 #pragma once
8 
9 
10 //[-------------------------------------------------------]
11 //[ Includes ]
12 //[-------------------------------------------------------]
13 #include "em5/Export.h"
15 
17 
18 #include <qsf/base/WeakPtr.h>
19 #include <qsf/time/Time.h>
21 
22 #include <boost/noncopyable.hpp>
23 
24 #include <vector>
25 #include <unordered_map>
26 #include <memory> // for std::unique_ptr
27 
28 
29 //[-------------------------------------------------------]
30 //[ Forward declarations ]
31 //[-------------------------------------------------------]
32 namespace qsf
33 {
34  class Clock;
35  class Map;
36  class Entity;
37 }
38 namespace em5
39 {
40  namespace multiplayer
41  {
42  class DataCacheBase;
43  }
44 }
45 
46 
47 //[-------------------------------------------------------]
48 //[ Namespace ]
49 //[-------------------------------------------------------]
50 namespace em5
51 {
52  namespace multiplayer
53  {
54 
55 
56  //[-------------------------------------------------------]
57  //[ Classes ]
58  //[-------------------------------------------------------]
63  class EM5_API_EXPORT MapCache : public boost::noncopyable
64  {
65 
66 
67  //[-------------------------------------------------------]
68  //[ Public methods ]
69  //[-------------------------------------------------------]
70  public:
75  MapCache();
76 
81  virtual ~MapCache();
82 
83  bool isInitialized() { return mInitialized; }
84 
89  void setMap(qsf::Map& map);
90 
91  //void reset()
92 
97  void addEntity(qsf::Entity& entity);
98 
103  void addEntities(const std::unordered_set<uint64>& entityIdList);
104 
109  void removeEntity(const uint64 entityId);
110 
115  void removeEntities(const std::unordered_set<uint64>& entityIdList);
116 
127  // TODO(sw) Might be changed, when any bandwith management should not be done inside this class
128  void updateCache(qsf::game::BitStream& bitStream, const qsf::Clock& clock);
129 
140  void applyChanges(uint64 dataSize, const qsf::game::BitStream& bitStream);
141 
152  bool interpolate(const qsf::Clock& clock);
153 
154  void logStatistics();
155 
156 
157  //[-------------------------------------------------------]
158  //[ Private definitions ]
159  //[-------------------------------------------------------]
160  private:
161  // Don't use here unordered_map it cause troubles on client side (e.g. the fire hose equipment isn't visually linked to the hand of the firefighter. Instead it is visually linked to his feet)
162  typedef boost::container::flat_map<uint8, std::unique_ptr<DataCacheBase>> ComponentCacheMap;
163  typedef std::unordered_map<uint8, DataCacheBase*> ChangedComponentCacheMap;
164  typedef std::unordered_map<uint64, ComponentCacheMap> EntityCacheMap;
165  typedef std::unordered_map<uint64, ChangedComponentCacheMap> ChangedEntityCacheMap;
166  typedef std::unordered_map<uint64, qsf::WeakPtr<qsf::Entity>> EntityMap;
167 
168 
169  //[-------------------------------------------------------]
170  //[ Private methods ]
171  //[-------------------------------------------------------]
172  private:
173  void initializeCache();
174  void addEntityInternal(qsf::Entity& entity);
175  void addDynamicEntityInternal(qsf::Entity& entity);
176 
177  void updateCoreDataCache(qsf::game::BitStream& bitStream, const qsf::Clock& clock);
178  void updateDataCache(qsf::game::BitStream& bitStream, const qsf::Clock& clock);
179 
180  bool applyReadData(int32 currentClientTick);
181  bool applyCoreChanges(const qsf::game::BitStream& bitStream, int32 currentTick);
182  bool applyChanges(const qsf::game::BitStream& bitStream, int32 currentTick);
183 
184  void removeEntityFromCache(const uint64 entityId, EntityCacheMap& cacheMap);
185 
186  void writeComponentIdToStream(const uint8 componentId, qsf::game::BitStream& bitStream);
187  bool readComponentIdFromStream(uint8& componentId, const qsf::game::BitStream& bitStream);
188  void writeChangedEntitiesToTheStream(const ChangedEntityCacheMap& changedEntities, qsf::game::BitStream& bitStream, const qsf::Clock& clock);
189  void writeChangedComponentsToTheStream(const ChangedComponentCacheMap& changedComponents, qsf::game::BitStream& bitStream);
190 
191  // Statistics methods
192  void updateStatistics(size_t index, uint64 initialSize, const qsf::game::BitStream& bitStream);
193  void logStatistics(const size_t index, const std::string& prefix);
194  void initPerComponentStatistics(const std::vector<uint8>& list);
195  void updatePerComponentCurrentValue(const uint8 componentId, uint64 initialSize, const qsf::game::BitStream& bitStream);
196  void updatePerComponentStatistics();
197  void logPerComponentStatistics(boost::container::flat_map<uint8, uint64>& dataList, const std::string& prefix);
198 
199 
200  //[-------------------------------------------------------]
201  //[ Private data ]
202  //[-------------------------------------------------------]
203  private:
204  bool mInitialized;
205  qsf::Map* mCurrentMap;
206  int32 mLastReceivedTickCount;
207  EntityCacheMap mDataCache;
208  ComponentCacheMap mCoreEntityCache;
209  EntityMap mEntityMap;
210  std::unordered_set<uint64> mVisibleEntities;
211  qsf::Time mWaitTimeBetweenVisibleUpdates;
212 
213  // Statistics
214  std::vector<uint64> mPeekDataPerUpdate;
215  std::vector<uint64> mAverageDataPerUpdate;
216  std::vector<uint64> mLowestDataPerUpdate;
217  boost::container::flat_map<uint8, uint64> mPeakPerComponentData;
218  boost::container::flat_map<uint8, uint64> mAveragePerComponentData;
219  boost::container::flat_map<uint8, uint64> mLowestPerComponentData;
220  boost::container::flat_map<uint8, uint64> mCurrentPerComponentData;
221  boost::container::flat_map<uint8, uint64> mComponentCount;
222 
223  ComponentValueHistory mComponentValueHistory;
224  std::vector<uint8> mChangedComponentIds;
225 
226  struct RemoveEntityHistory
227  {
228  int32 tickCount;
229  uint64 entityId;
230  };
231  std::vector<RemoveEntityHistory> mRemoveEntityHistoryList;
232 
233  struct ReceivedDataHistory
234  {
235  int32 tickCount;
237  };
238 
239  // We cannot use here an container, which copies elements around, when the container get resized or expectes the elements be copy/movable. Because qsf::game::BitStream is not copy and movable :(
240  std::list<ReceivedDataHistory> mReceivedDataHistoryList;
241 
242  qsf::DebugDrawProxy mDebugDrawProxy;
243 
244 
245  };
246 
247 
248 //[-------------------------------------------------------]
249 //[ Namespace ]
250 //[-------------------------------------------------------]
251  } // multiplayer
252 } // em5
Definition: ActionPriority.h:13
EMERGENCY 5 multiplayer per component value history.
Definition: MapCacheStatistics.h:109
Entity class.
Definition: Entity.h:46
Map class.
Definition: Map.h:93
bool isInitialized()
Definition: MapCache.h:83
Clock class.
Definition: Clock.h:33
#define EM5_API_EXPORT
Definition: Export.h:28
uint64_t uint64
Definition: PlatformTypes.h:184
Game bit stream class (just a wrapper for linnet bit stream)
Definition: BitStream.h:40
Definition: PickupPersonByParamedicAction.h:21
Debug draw proxy class.
Definition: DebugDrawProxy.h:46
signed int int32
Definition: PlatformTypes.h:180
EMERGENCY 5 multiplayer map cache.
Definition: MapCache.h:63
unsigned char uint8
Definition: PlatformTypes.h:175
Data type for encapsulating time information. It might represents points in time and time spans...
Definition: Time.h:32