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_DEMO_H
4#define ENGINE_DEMO_H
5
6#include "kernel.h"
7
8#include <base/hash.h>
9
10#include <engine/map.h>
11#include <engine/shared/uuid_manager.h>
12
13#include <cstdint>
14#include <optional>
15
16enum
17{
18 MAX_TIMELINE_MARKERS = 64
19};
20
21static const unsigned char gs_aHeaderMarker[7] = {'T', 'W', 'D', 'E', 'M', 'O', 0};
22
23static constexpr double DEMO_SPEEDS[] = {0.1, 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 2.0, 3.0, 4.0, 6.0, 8.0, 12.0, 16.0, 20.0, 24.0, 28.0, 32.0, 40.0, 48.0, 56.0, 64.0};
24static constexpr int DEMO_SPEED_INDEX_DEFAULT = 4;
25static_assert(DEMO_SPEEDS[DEMO_SPEED_INDEX_DEFAULT] == 1.0);
26
27typedef bool (*DEMOFUNC_FILTER)(const void *pData, int DataSize, void *pUser);
28
29// TODO: Properly extend demo format using uuids
30// "6be6da4a-cebd-380c-9b5b-1289c842d780"
31// "demoitem-sha256@ddnet.tw"
32extern const CUuid SHA256_EXTENSION;
33
34struct CDemoHeader
35{
36 unsigned char m_aMarker[7];
37 unsigned char m_Version;
38 char m_aNetversion[64];
39 char m_aMapName[64];
40 unsigned char m_aMapSize[sizeof(int32_t)];
41 unsigned char m_aMapCrc[sizeof(int32_t)];
42 char m_aType[8];
43 unsigned char m_aLength[sizeof(int32_t)];
44 char m_aTimestamp[20];
45
46 bool Valid() const;
47};
48
49struct CTimelineMarkers
50{
51 unsigned char m_aNumTimelineMarkers[sizeof(int32_t)];
52 unsigned char m_aTimelineMarkers[MAX_TIMELINE_MARKERS][sizeof(int32_t)];
53};
54
55struct CMapInfo
56{
57 char m_aName[MAX_MAP_LENGTH];
58 std::optional<SHA256_DIGEST> m_Sha256;
59 unsigned m_Crc;
60 unsigned m_Size;
61};
62
63class IDemoPlayer : public IInterface
64{
65 MACRO_INTERFACE("demoplayer")
66public:
67 class CInfo
68 {
69 public:
70 bool m_Paused;
71 bool m_LiveDemo;
72 bool m_LivePlayback;
73 float m_Speed;
74
75 int m_FirstTick;
76 int m_CurrentTick;
77 int m_LastTick;
78
79 int m_NumTimelineMarkers;
80 int m_aTimelineMarkers[MAX_TIMELINE_MARKERS];
81 };
82
83 enum ETickOffset
84 {
85 TICK_CURRENT, // update the current tick again
86 TICK_PREVIOUS, // go to the previous tick
87 TICK_NEXT, // go to the next tick
88 };
89
90 virtual void SetSpeed(float Speed) = 0;
91 virtual void SetSpeedIndex(int SpeedIndex) = 0;
92 virtual void AdjustSpeedIndex(int Offset) = 0;
93 virtual bool SeekPercent(float Percent) = 0;
94 virtual bool SeekTime(float Seconds) = 0;
95 virtual bool SeekTick(ETickOffset TickOffset) = 0;
96 virtual bool SetPos(int WantedTick) = 0;
97 virtual void Pause() = 0;
98 virtual void Unpause() = 0;
99 virtual const char *ErrorMessage() const = 0;
100 virtual bool IsPlaying() const = 0;
101 virtual const CInfo *BaseInfo() const = 0;
102 virtual void GetDemoName(char *pBuffer, size_t BufferSize) const = 0;
103 virtual bool GetDemoInfo(class IStorage *pStorage, class IConsole *pConsole, const char *pFilename, int StorageType, CDemoHeader *pDemoHeader, CTimelineMarkers *pTimelineMarkers, CMapInfo *pMapInfo, IOHANDLE *pFile = nullptr, char *pErrorMessage = nullptr, size_t ErrorMessageSize = 0) const = 0;
104};
105
106class IDemoRecorder : public IInterface
107{
108 MACRO_INTERFACE("demorecorder")
109public:
110 enum class EStopMode
111 {
112 KEEP_FILE,
113 REMOVE_FILE,
114 };
115
116 virtual bool IsRecording() const = 0;
117 virtual int Stop(IDemoRecorder::EStopMode Mode, const char *pTargetFilename = "") = 0;
118 virtual int Length() const = 0;
119 virtual const char *CurrentFilename() const = 0;
120};
121
122class IDemoEditor : public IInterface
123{
124 MACRO_INTERFACE("demoeditor")
125public:
126 virtual bool Slice(const char *pDemo, const char *pDst, int StartTick, int EndTick, DEMOFUNC_FILTER pfnFilter, void *pUser) = 0;
127};
128
129#endif
130