1/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2/* If you are missing that file, acquire a complete release at teeworlds.com. */
3#ifndef ENGINE_SHARED_SNAPSHOT_H
4#define ENGINE_SHARED_SNAPSHOT_H
5
6#include <base/cxx.h>
7
8#include <cstddef>
9#include <cstdint>
10#include <memory>
11
12// CSnapshot
13
14class CSnapshotItem
15{
16 int *Data() { return (int *)(this + 1); }
17
18public:
19 int m_TypeAndId;
20
21 const int *Data() const { return (int *)(this + 1); }
22 int InternalType() const { return m_TypeAndId >> 16; }
23 int Id() const { return m_TypeAndId & 0xffff; }
24 int Key() const { return m_TypeAndId; }
25 void Invalidate() { m_TypeAndId = -1; }
26};
27
28class CSnapshot
29{
30 int m_DataSize = 0;
31 int m_NumItems = 0;
32
33 int *Offsets() const { return (int *)(this + 1); }
34 char *DataStart() const { return (char *)(Offsets() + m_NumItems); }
35
36 size_t OffsetSize() const { return sizeof(int) * m_NumItems; }
37 size_t TotalSize() const { return sizeof(CSnapshot) + OffsetSize() + m_DataSize; }
38
39 static const CSnapshot ms_EmptySnapshot;
40
41public:
42 enum
43 {
44 OFFSET_UUID_TYPE = 0x4000,
45 MAX_TYPE = 0x7fff,
46 MAX_ID = 0xffff,
47 MAX_ITEMS = 1024,
48 MAX_PARTS = 64,
49 MAX_SIZE = MAX_PARTS * 1024
50 };
51
52 int NumItems() const { return m_NumItems; }
53 int DataSize() const { return m_DataSize; }
54 const CSnapshotItem *GetItem(int Index) const;
55 int GetItemSize(int Index) const;
56 int GetItemIndex(int Key) const;
57 void InvalidateItem(int Index);
58 int GetItemType(int Index) const;
59 int GetExternalItemType(int InternalType) const;
60 const void *FindItem(int Type, int Id) const;
61
62 rust::Slice<const int32_t> AsSlice() const;
63
64 unsigned Crc() const;
65 // Prints the raw snapshot data showing item and int boundaries.
66 // See also `CNetObjHandler::DebugDumpSnapshot(const CSnapshot *pSnap)`
67 // For more detailed annotations of the data.
68 void DebugDump() const;
69 bool IsValid(size_t ActualSize) const;
70
71 static const CSnapshot *EmptySnapshot() { return &ms_EmptySnapshot; }
72};
73
74class alignas(int32_t) CSnapshotBuffer
75{
76public:
77 unsigned char m_aData[CSnapshot::MAX_SIZE];
78
79 CSnapshot *AsSnapshot() { return (CSnapshot *)m_aData; }
80 const CSnapshot *AsSnapshot() const { return (const CSnapshot *)m_aData; }
81 rust::Slice<int32_t> AsMutSlice() { return rust::Slice((int32_t *)m_aData, sizeof(m_aData) / sizeof(int32_t)); }
82};
83
84std::unique_ptr<CSnapshotBuffer> CSnapshotBuffer_New();
85
86// CSnapshotStorage
87
88class CSnapshotStorage
89{
90public:
91 class CHolder
92 {
93 public:
94 CHolder *m_pPrev;
95 CHolder *m_pNext;
96
97 int64_t m_Tagtime;
98 int m_Tick;
99
100 int m_SnapSize;
101 int m_AltSnapSize;
102
103 CSnapshot *m_pSnap;
104 CSnapshot *m_pAltSnap;
105 };
106
107 CHolder *m_pFirst;
108 CHolder *m_pLast;
109
110 CSnapshotStorage() { Init(); }
111 ~CSnapshotStorage() { PurgeAll(); }
112 void Init();
113 void PurgeAll();
114 void PurgeUntil(int Tick);
115 void Add(int Tick, int64_t Tagtime, size_t DataSize, const void *pData, size_t AltDataSize, const void *pAltData);
116 int Get(int Tick, int64_t *pTagtime, const CSnapshot **ppData, const CSnapshot **ppAltData) const;
117};
118
119#include <engine/shared/snapshot/builder.h> // NOLINT(misc-header-include-cycle)
120#include <engine/shared/snapshot/delta.h> // NOLINT(misc-header-include-cycle)
121
122#endif // ENGINE_SHARED_SNAPSHOT_H
123