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