1/*
2 * LegacyClonk
3 *
4 * Copyright (c) RedWolf Design
5 * Copyright (c) 2017-2019, The LegacyClonk Team and contributors
6 *
7 * Distributed under the terms of the ISC license; see accompanying file
8 * "COPYING" for details.
9 *
10 * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11 * See accompanying file "TRADEMARK" for details.
12 *
13 * To redistribute this file separately, substitute the full license texts
14 * for the above references.
15 */
16
17/* control management */
18
19#pragma once
20
21#include "C4Control.h"
22#include "C4GameControlNetwork.h"
23#include "C4Log.h"
24#include "C4Network2Client.h"
25#include "C4Record.h"
26
27enum C4ControlMode
28{
29 CM_None,
30 CM_Local, // control = input
31 CM_Network, // control = input + network input
32 CM_Replay, // control = replay
33};
34
35#ifndef NDEBUG
36const int32_t C4SyncCheckRate = 1,
37#else
38const int32_t C4SyncCheckRate = 100,
39#endif
40 C4SyncCheckMaxKeep = 50;
41
42class C4GameControl
43{
44 friend class C4ControlSyncCheck;
45 friend class C4GameControlNetwork;
46
47public:
48 C4GameControl();
49 ~C4GameControl();
50
51public:
52 C4Control Input;
53 C4GameControlNetwork Network;
54
55protected:
56 C4ControlMode eMode;
57 bool fPreInit, fInitComplete;
58 bool fHost; // (set for local, too)
59 bool fActivated;
60 bool fRecordNeeded;
61 int32_t iClientID;
62
63 C4Record *pRecord;
64 C4Playback *pPlayback;
65
66 C4Control SyncChecks;
67
68 C4GameControlClient *pClients;
69
70 C4Control *pExecutingControl; // Control that is in the process of being executed - needed by non-initial records
71
72private:
73 std::shared_ptr<spdlog::logger> logger;
74
75public:
76 // ticks
77 int32_t ControlRate;
78 int32_t ControlTick;
79 int32_t SyncRate;
80 bool DoSync;
81
82public:
83 // configuration
84 bool isLocal() const { return eMode == CM_Local; }
85 bool isNetwork() const { return eMode == CM_Network; }
86 bool isReplay() const { return eMode == CM_Replay; }
87 bool isCtrlHost() const { return fHost; }
88 bool isRecord() const { return !!pRecord; }
89 int32_t ClientID() const { return iClientID; }
90 bool SyncMode() const { return eMode != CM_Local || pRecord; }
91
92 bool NoInput() const { return isReplay(); }
93
94 // initialization
95 void InitLogger();
96 bool InitLocal(C4Client *pLocal);
97 bool InitNetwork(C4Client *pLocal);
98 bool InitReplay(C4Group &rGroup);
99
100 void ChangeToLocal();
101
102 void Clear();
103 void Default();
104
105 // records
106 bool StartRecord(bool fInitial, bool fStreaming);
107 void StopRecord(StdStrBuf *pRecordName = nullptr, uint8_t *pRecordSHA1 = nullptr);
108 void RequestRuntimeRecord();
109 bool IsRuntimeRecordPossible() const;
110 bool RecAddFile(const char *szLocalFilename, const char *szAddAs);
111
112 // execution
113 bool Prepare();
114 void Execute();
115 void Ticks();
116
117 // public helpers
118 bool CtrlTickReached(int32_t iTick);
119 int32_t getCtrlTick(int32_t iFrame) const;
120 int32_t getNextControlTick() const;
121
122 // control rate
123 void AdjustControlRate(int32_t iBy);
124 bool KeyAdjustControlRate(int32_t iBy)
125 {
126 AdjustControlRate(iBy); return true;
127 }
128
129 // activation
130 void SetActivated(bool fActivated);
131
132 // input
133 void DoInput(C4PacketType eCtrlType, C4ControlPacket *pPkt, C4ControlDeliveryType eDelivery);
134 void DbgRec(C4RecordChunkType eType, const uint8_t *pData = nullptr, size_t iSize = 0); // record debug stuff
135 C4ControlDeliveryType DecideControlDelivery();
136
137 // sync check
138 void DoSyncCheck();
139
140 // execute and record control (by self or C4GameControlNetwork)
141 void ExecControl(const C4Control &rCtrl);
142 void ExecControlPacket(C4PacketType eCtrlType, class C4ControlPacket *pPkt);
143 void OnGameSynchronizing(); // start record if desired
144
145 const std::shared_ptr<spdlog::logger> &GetLogger() const noexcept { return logger; }
146
147protected:
148 // sync checks
149 C4ControlSyncCheck *GetSyncCheck(int32_t iTick);
150 void RemoveOldSyncChecks();
151};
152
153C4LOGGERCONFIG_NAME_TYPE(C4GameControl);
154