1/*
2 * LegacyClonk
3 *
4 * Copyright (c) RedWolf Design
5 * Copyright (c) 2017-2021, 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#pragma once
18
19#include "C4InputValidation.h"
20#include "C4NetIO.h"
21#include "C4PacketBase.h"
22
23#include <chrono>
24
25// special ids
26const int32_t C4ClientIDUnknown = -1,
27 C4ClientIDHost = 0,
28 C4ClientIDStart = 1;
29
30// client core difference levels
31const int32_t C4ClientCoreDL_None = 0, // identical
32 C4ClientCoreDL_IDMatch = 1, // status change
33 C4ClientCoreDL_IDChange = 2, // identification changed (host only!)
34 C4ClientCoreDL_Different = 3; // really different
35
36class C4ClientCore : public C4PacketBase
37{
38public:
39 C4ClientCore();
40 ~C4ClientCore();
41
42protected:
43 // identification
44 int32_t iID;
45 ValidatedStdStrBuf<C4InVal::VAL_NameNoEmpty> Name, Nick;
46
47 // version info
48 int iVersion[4];
49
50 // status
51 bool fActivated, fObserver, fLobbyReady;
52
53public:
54 // status data
55 int32_t getID() const { return iID; }
56 bool isHost() const { return iID == C4ClientIDHost; }
57 bool isActivated() const { return fActivated; }
58 bool isObserver() const { return fObserver; }
59 bool isLobbyReady() const { return fLobbyReady; }
60 void SetID(int32_t inID) { iID = inID; }
61 void SetName(const char *sznName) { Name.CopyValidated(szFromVal: sznName); }
62 void SetActivated(bool fnActivated) { fActivated = fnActivated; fObserver = false; }
63 void SetObserver(bool fnObserver) { fActivated &= !(fObserver = fnObserver); }
64 void SetLobbyReady(bool fnLobbyReady) { fLobbyReady = fnLobbyReady; }
65
66 // misc
67 const char *getName() const { return Name.getData(); }
68 const char *getNick() const { return Nick.getData(); }
69
70 // initialization
71 void SetLocal(int32_t iID, bool fnActivated, bool fnObserver);
72
73 int32_t getDiffLevel(const C4ClientCore &CCore2) const;
74
75 virtual void CompileFunc(StdCompiler *pComp) override;
76};
77
78class C4Client
79{
80 friend class C4ClientList;
81
82public:
83 C4Client();
84 C4Client(const C4ClientCore &Core);
85 ~C4Client();
86
87private:
88 C4ClientCore Core;
89
90 bool fLocal; // Local, NoSync
91 class C4Network2Client *pNetClient; // Local, NoSync
92 time_t last_lobby_ready_change; // Local, NoSync: Time when the lobby ready state was changed last through the SetLobbyReady call. 0 for never changed.
93 bool muted; // Local, NoSync: whether /sound command is muted
94
95 C4Client *pNext;
96
97public:
98 const C4ClientCore &getCore() const { return Core; }
99 int32_t getID() const { return Core.getID(); }
100 bool isHost() const { return Core.isHost(); }
101 const char *getName() const { return Core.getName(); }
102 const char *getNick() const { return Core.getNick(); }
103 bool isActivated() const { return Core.isActivated(); }
104 bool isObserver() const { return Core.isObserver(); }
105 bool isLobbyReady() const { return Core.isLobbyReady(); }
106 bool isMuted() const { return muted; }
107
108 bool isLocal() const { return fLocal; }
109 C4Network2Client *getNetClient() const { return pNetClient; }
110
111 void SetCore(const C4ClientCore &NewCore) { Core = NewCore; }
112 void SetID(int32_t iID) { Core.SetID(iID); }
113
114 void SetActivated(bool fnActivated);
115 void SetObserver() { Core.SetObserver(true); }
116 void SetLobbyReady(bool lobbyReady);
117 void SetLocal();
118 bool TryAllowSound();
119 void SetMuted(bool muted) { this->muted = muted; }
120 void ToggleMuted() { muted = !muted; }
121
122 void UnlinkNetClient() { pNetClient = nullptr; }
123
124 void Remove();
125
126 void CompileFunc(StdCompiler *pComp);
127};
128
129class C4ClientList
130{
131public:
132 C4ClientList();
133 ~C4ClientList();
134
135 C4ClientList &operator=(const C4ClientList &List);
136
137 void Clear();
138
139protected:
140 // client list
141 C4Client *pFirst;
142
143 // pointer to local client (is nullptr if a recording is played)
144 C4Client *pLocal;
145
146 // network client list (may be nullptr if network is not active)
147 class C4Network2ClientList *pNetClients;
148
149 void Add(C4Client *pClient);
150
151public:
152 C4Client *getClient(const C4Client *pAfter = nullptr) const { return pAfter ? pAfter->pNext : pFirst; }
153 C4Client *getLocal() const { return pLocal; }
154 C4Client *getClientByID(int32_t iID) const;
155 C4Client *getHost() const { return getClientByID(iID: C4ClientIDHost); }
156 C4Client *getClientByName(const char *szName) const;
157
158 int32_t getClientCnt() const;
159
160 const C4ClientCore &getLocalCore() const { return getLocal()->getCore(); }
161 const char *getLocalName() const { return pLocal ? getLocalCore().getName() : "???"; }
162 int32_t getLocalID() const { return pLocal ? getLocalCore().getID() : C4ClientIDUnknown; }
163
164 void Init(int32_t iLocalClientID = C4ClientIDHost);
165 void InitNetwork(class C4Network2ClientList *pNetClients);
166 void ClearNetwork();
167
168 bool Remove(C4Client *pClient, bool fTemporary = false);
169 C4Client *Add(const C4ClientCore &Core);
170 C4Client *AddLocal(int32_t iID, bool fActivated, bool fObserver);
171 void SetLocalID(int32_t iID);
172
173 void CtrlRemove(const C4Client *pClient, const char *szReason);
174
175 void RemoveRemote();
176
177 void CompileFunc(StdCompiler *pComp);
178};
179