1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2013-2016, The OpenClonk 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 /* control management */
17 
18 #ifndef INC_C4GameControl
19 #define INC_C4GameControl
20 
21 #include "control/C4Control.h"
22 #include "control/C4Record.h"
23 
24 enum C4ControlMode
25 {
26 	CM_None,
27 	CM_Local,         // control = input
28 	CM_Network,       // control = input + network input
29 	CM_Replay       // control = replay
30 };
31 
32 enum C4ControlDeliveryType
33 {
34 	CDT_Queue   = 0,  // Send in control queue (sync)
35 	CDT_Sync    = 1,  // Send, delay execution until net is sync (sync)
36 	CDT_Direct  = 2,  // Send directly to all clients (not sync)
37 	CDT_Private = 3,  // Send only to some clients (not sync, obviously)
38 
39 	CDT_Decide        // Use whatever sync mode seems fastest atm (sync)
40 };
41 
42 // Additional notes / requirements:
43 // * Direct control always reaches all clients faster than queue control.
44 // * Sync is the only synchronous control mode were it's garantueed that
45 //   the control is actually executed within a fixed time.
46 // * CDT_Decide is guesswork, control isn't garantueed to be faster.
47 
48 #include "network/C4GameControlNetwork.h"
49 
50 #ifdef _DEBUG
51 const int32_t C4SyncCheckRate = 1,
52 #else
53 const int32_t C4SyncCheckRate = 100,
54 #endif
55                                 C4SyncCheckMaxKeep = 50;
56 
57 class C4GameControl
58 {
59 	friend class C4ControlSyncCheck;
60 	friend class C4GameControlNetwork;
61 public:
62 	C4GameControl();
63 	~C4GameControl();
64 
65 public:
66 	C4Control           Input;
67 	C4GameControlNetwork Network;
68 
69 protected:
70 	C4ControlMode       eMode;
71 	bool                fInitComplete;
72 	bool                fHost;              // (set for local, too)
73 	bool                fActivated;
74 	bool                fRecordNeeded;
75 	int32_t             iClientID;
76 
77 	C4Record            *pRecord;
78 	C4Playback          *pPlayback;
79 
80 	C4Control           SyncChecks;
81 
82 	C4GameControlClient *pClients;
83 
84 	C4Control           *pExecutingControl; // Control that is in the process of being executed - needed by non-initial records
85 
86 public:
87 	// ticks
88 	int32_t             ControlRate;
89 	int32_t             ControlTick;
90 	int32_t             SyncRate;
91 	bool                DoSync;
92 
93 public:
94 
95 	// configuration
isLocal()96 	bool isLocal() const { return eMode == CM_Local; }
isNetwork()97 	bool isNetwork() const { return eMode == CM_Network; }
isReplay()98 	bool isReplay() const { return eMode == CM_Replay; }
isCtrlHost()99 	bool isCtrlHost() const { return fHost; }
isRecord()100 	bool isRecord() const { return !! pRecord; }
GetRecord()101 	C4Record * GetRecord() { return pRecord; }
ClientID()102 	int32_t  ClientID() const { return iClientID; }
SyncMode()103 	bool SyncMode() const { return eMode != CM_Local || pRecord; }
104 
NoInput()105 	bool NoInput() const { return isReplay(); }
106 
107 	// client list
108 	C4GameControlClient *getClient(int32_t iID);
109 	C4GameControlClient *getClient(const char *szName);
110 
111 	// initialization
112 	bool InitLocal(C4Client *pLocal);
113 	bool InitNetwork(C4Client *pLocal);
114 	bool InitReplay(C4Group &rGroup);
115 
116 	void ChangeToLocal();
117 
118 	void Clear();
119 	void Default();
120 
121 	// records
122 	bool StartRecord(bool fInitial, bool fStreaming);
123 	void StopRecord(StdStrBuf *pRecordName = nullptr, BYTE *pRecordSHA1 = nullptr);
124 	void RequestRuntimeRecord();
125 	bool IsRuntimeRecordPossible() const;
126 	bool RecAddFile(const char *szLocalFilename, const char *szAddAs);
127 
128 	// execution
129 	bool Prepare();
130 	void Execute();
131 	void Ticks();
132 
133 	// public helpers
134 	bool CtrlTickReached(int32_t iTick);
135 	int32_t getCtrlTick(int32_t iFrame) const;
136 	int32_t getNextControlTick() const;
137 
138 	// control rate
139 	void AdjustControlRate(int32_t iBy);
KeyAdjustControlRate(int32_t iBy)140 	bool KeyAdjustControlRate(int32_t iBy)
141 	{ AdjustControlRate(iBy); return true; }
142 
143 	// activation
144 	void SetActivated(bool fActivated);
145 
146 	// input
147 	void DoInput(C4PacketType eCtrlType, C4ControlPacket *pPkt, C4ControlDeliveryType eDelivery);
148 	void DbgRec(C4RecordChunkType eType, const uint8_t *pData=nullptr, size_t iSize=0); // record debug stuff
149 	C4ControlDeliveryType DecideControlDelivery();
150 
151 	// sync check
152 	void DoSyncCheck();
153 
154 	// execute and record control (by self or C4GameControlNetwork)
155 	void ExecControl(const C4Control &rCtrl);
156 	void ExecControlPacket(C4PacketType eCtrlType, class C4ControlPacket *pPkt);
157 	void OnGameSynchronizing(); // start record if desired
158 
159 protected:
160 
161 	// sync checks
162 	C4ControlSyncCheck *GetSyncCheck(int32_t iTick);
163 	void RemoveOldSyncChecks();
164 
165 	// add per-controlframe input
166 	void PrepareInput();
167 
168 };
169 extern C4GameControl Control;
170 
171 #endif // INC_C4GameControl
172