1 | #ifndef ENGINE_CLIENT_GHOST_H |
2 | #define ENGINE_CLIENT_GHOST_H |
3 | |
4 | #include <engine/ghost.h> |
5 | |
6 | #include <base/system.h> |
7 | |
8 | enum |
9 | { |
10 | MAX_ITEM_SIZE = 128, |
11 | NUM_ITEMS_PER_CHUNK = 50, |
12 | }; |
13 | |
14 | // version 4-6 |
15 | struct |
16 | { |
17 | unsigned char [8]; |
18 | unsigned char ; |
19 | char [MAX_NAME_LENGTH]; |
20 | char [64]; |
21 | unsigned char [sizeof(int32_t)]; // Crc before version 6 |
22 | unsigned char [sizeof(int32_t)]; |
23 | unsigned char [sizeof(int32_t)]; |
24 | SHA256_DIGEST ; |
25 | |
26 | int () const |
27 | { |
28 | return bytes_be_to_uint(bytes: m_aNumTicks); |
29 | } |
30 | |
31 | int () const |
32 | { |
33 | return bytes_be_to_uint(bytes: m_aTime); |
34 | } |
35 | |
36 | CGhostInfo () const |
37 | { |
38 | CGhostInfo Result; |
39 | mem_zero(block: &Result, size: sizeof(Result)); |
40 | str_copy(dst&: Result.m_aOwner, src: m_aOwner); |
41 | str_copy(dst&: Result.m_aMap, src: m_aMap); |
42 | Result.m_NumTicks = GetTicks(); |
43 | Result.m_Time = GetTime(); |
44 | return Result; |
45 | } |
46 | }; |
47 | |
48 | class CGhostItem |
49 | { |
50 | public: |
51 | unsigned char m_aData[MAX_ITEM_SIZE]; |
52 | int m_Type; |
53 | |
54 | CGhostItem() : |
55 | m_Type(-1) {} |
56 | CGhostItem(int Type) : |
57 | m_Type(Type) {} |
58 | void Reset() { m_Type = -1; } |
59 | }; |
60 | |
61 | class CGhostRecorder : public IGhostRecorder |
62 | { |
63 | IOHANDLE m_File; |
64 | class IConsole *m_pConsole; |
65 | class IStorage *m_pStorage; |
66 | |
67 | CGhostItem m_LastItem; |
68 | |
69 | char m_aBuffer[MAX_ITEM_SIZE * NUM_ITEMS_PER_CHUNK]; |
70 | char *m_pBufferPos; |
71 | int m_BufferNumItems; |
72 | |
73 | void ResetBuffer(); |
74 | void FlushChunk(); |
75 | |
76 | public: |
77 | CGhostRecorder(); |
78 | |
79 | void Init(); |
80 | |
81 | int Start(const char *pFilename, const char *pMap, SHA256_DIGEST MapSha256, const char *pName) override; |
82 | int Stop(int Ticks, int Time) override; |
83 | |
84 | void WriteData(int Type, const void *pData, int Size) override; |
85 | bool IsRecording() const override { return m_File != nullptr; } |
86 | }; |
87 | |
88 | class CGhostLoader : public IGhostLoader |
89 | { |
90 | IOHANDLE m_File; |
91 | class IConsole *m_pConsole; |
92 | class IStorage *m_pStorage; |
93 | |
94 | CGhostHeader ; |
95 | CGhostInfo m_Info; |
96 | |
97 | CGhostItem m_LastItem; |
98 | |
99 | char m_aBuffer[MAX_ITEM_SIZE * NUM_ITEMS_PER_CHUNK]; |
100 | char *m_pBufferPos; |
101 | int m_BufferNumItems; |
102 | int m_BufferCurItem; |
103 | int m_BufferPrevItem; |
104 | |
105 | void ResetBuffer(); |
106 | int ReadChunk(int *pType); |
107 | |
108 | public: |
109 | CGhostLoader(); |
110 | |
111 | void Init(); |
112 | |
113 | int Load(const char *pFilename, const char *pMap, SHA256_DIGEST MapSha256, unsigned MapCrc) override; |
114 | void Close() override; |
115 | const CGhostInfo *GetInfo() const override { return &m_Info; } |
116 | |
117 | bool ReadNextType(int *pType) override; |
118 | bool ReadData(int Type, void *pData, int Size) override; |
119 | |
120 | bool GetGhostInfo(const char *pFilename, CGhostInfo *pGhostInfo, const char *pMap, SHA256_DIGEST MapSha256, unsigned MapCrc) override; |
121 | }; |
122 | #endif |
123 | |