1/*
2 * LegacyClonk
3 *
4 * Copyright (c) RedWolf Design
5 * Copyright (c) 2001, Sven2
6 * Copyright (c) 2017-2022, The LegacyClonk Team and contributors
7 *
8 * Distributed under the terms of the ISC license; see accompanying file
9 * "COPYING" for details.
10 *
11 * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12 * See accompanying file "TRADEMARK" for details.
13 *
14 * To redistribute this file separately, substitute the full license texts
15 * for the above references.
16 */
17
18// the ingame-lobby
19
20// TODO: Tab: NickCompletion - and can't do this here, because tab is used to cycle controls!
21
22#pragma once
23
24#include "C4Gui.h"
25#include "C4GuiDialogs.h"
26#include "C4Client.h"
27#include "C4Cooldown.h"
28#include "C4PlayerInfo.h"
29
30class C4PlayerInfo;
31class C4PlayerInfoListBox;
32class C4ClientPlayerInfos;
33class C4Network2ResDlg;
34class C4GameOptionsList;
35class C4GameOptionButtons;
36
37namespace C4GameLobby
38{
39
40class MainDlg;
41
42// countdown time from which the elevator sound starts and team selection becomes unavailable
43const int32_t AlmostStartCountdownTime = 10; // seconds
44
45extern bool UserAbort;
46
47// * PID_LobbyCountdown
48// initiates or aborts countdown
49class C4PacketCountdown : public C4PacketBase
50{
51private:
52 int32_t iCountdown; // countdown timer, or zero for abort
53
54public:
55 enum { Abort = -1 };
56
57 C4PacketCountdown(int32_t iaCountdown) : iCountdown(iaCountdown) {}
58 C4PacketCountdown() : iCountdown(Abort) {}
59
60 bool IsAbort() const { return iCountdown == Abort; }
61 int32_t GetCountdown() const { return iCountdown; }
62 std::string GetCountdownMsg(bool fInitialMsg = false) const;
63
64 virtual void CompileFunc(StdCompiler *pComp) override;
65};
66
67// scneario info tab: displays scenario description
68class ScenDesc : public C4GUI::Window
69{
70private:
71 C4GUI::Label *pTitle; // scenario title or warning label if unloaded
72 C4GUI::TextWindow *pDescBox; // scenario description box
73 bool fDescFinished; // if set, scenario resource has been loaded
74
75 C4Sec1TimerCallback<ScenDesc> *pSec1Timer; // engine timer hook for updates
76
77 void Update();
78
79public:
80 ScenDesc(const C4Rect &rcBounds, bool fActive);
81 ~ScenDesc() { Deactivate(); }
82
83 void OnSec1Timer() { Update(); }
84 // activate/deactivate periodic updates
85 void Activate();
86 void Deactivate();
87};
88
89class MainDlg : public C4GUI::FullscreenDialog
90{
91private:
92 C4Sec1TimerCallback<MainDlg> *pSec1Timer; // engine timer hook
93 enum CountdownState { CDS_None = 0, CDS_LongCountdown = 1, CDS_Countdown = 2, CDS_Start = 3 } eCountdownState; // nonzero when a packet was received that the game is about to start (starts elevator sound, etc.)
94 int32_t iBackBufferIndex; // chat message history index
95 C4KeyBinding *pKeyHistoryUp, *pKeyHistoryDown; // keys used to scroll through chat history
96
97 enum { SheetIdx_PlayerList = 0, SheetIdx_Res = 1, SheetIdx_Options = 2, SheetIdx_Scenario = 3, };
98 C4PlayerInfoListBox *pPlayerList;
99 C4Network2ResDlg *pResList;
100 C4GameOptionButtons *pGameOptionButtons;
101 C4GameOptionsList *pOptionsList;
102 ScenDesc *pScenarioInfo;
103 C4GUI::TextWindow *pChatBox;
104 C4GUI::Label *pRightTabLbl;
105 C4GUI::Tabular *pRightTab;
106 C4GUI::Edit *pEdt; // chat input
107 C4GUI::CallbackButton<MainDlg> *btnRun; // host only
108 C4GUI::CallbackButton<MainDlg, C4GUI::IconButton> *btnPlayers, *btnResources, *btnTeams, *btnOptions, *btnScenario, *btnChat; // right list sheet selection
109 C4GUI::CheckBox *checkReady;
110 C4GUI::CallbackButton<MainDlg> *btnPreload{nullptr};
111 C4CooldownSeconds readyButtonCooldown{std::chrono::seconds{2}}; // not in C4Config as it is dependent on
112 bool resourcesLoaded{false};
113
114protected:
115 void OnReadyCheck(C4GUI::Element *pCheckBox); // callback: checkbox ticked
116 void OnRunBtn(C4GUI::Control *btn); // callback: run button pressed
117 void OnExitBtn(C4GUI::Control *btn); // callback: exit button pressed
118 bool KeyHistoryUpDown(bool fUp); // key callback
119 C4GUI::InputResult OnChatInput(C4GUI::Edit *edt, bool fPasting, bool fPastingMore); // callback: chat input performed
120
121 void OnClosed(bool fOK) override; // callback when dlg is closed
122 void OnSec1Timer(); // timer proc; update pings
123
124 C4GUI::ContextMenu *OnRightTabContext(C4GUI::Element *pLabel, int32_t iX, int32_t iY); // open context menu
125 void OnCtxTabPlayers(C4GUI::Element *pListItem) { OnTabPlayers(btn: nullptr); }
126 void OnTabPlayers(C4GUI::Control *btn);
127 void OnCtxTabTeams(C4GUI::Element *pListItem) { OnTabTeams(btn: nullptr); }
128 void OnTabTeams(C4GUI::Control *btn);
129 void OnCtxTabRes(C4GUI::Element *pListItem) { OnTabRes(btn: nullptr); }
130 void OnTabRes(C4GUI::Control *btn);
131 void OnCtxTabOptions(C4GUI::Element *pListItem) { OnTabOptions(btn: nullptr); }
132 void OnTabOptions(C4GUI::Control *btn);
133 void OnTabScenario(C4GUI::Control *btn);
134 void UpdateRightTab(); // update label and tooltips for sheet change
135 void UpdateRightTabTitle();
136 void OnBtnChat(C4GUI::Control *btn);
137 void OnBtnPreload(C4GUI::Control *);
138
139 virtual class C4GUI::Control *GetDefaultControl() override; // def focus chat input
140
141private:
142 void SetCountdownState(CountdownState eToState, int32_t iTimer);
143 void Start(int32_t iCountdownTime); // host only: Do game start with specified countdown time (forwards to network system)
144 int32_t ValidatedCountdownTime(int32_t iTimeout); // correct invalid timeout settings
145
146 void UpdatePlayerList();
147 void UpdateResourceProgress();
148 void UpdatePreloadingGUIState(bool isComplete);
149 bool Preload();
150
151public:
152 MainDlg(bool fHost);
153 ~MainDlg();
154
155 // callback by network system
156 void OnClientJoin(C4Client *pNewClient); // called when a new client joined (connection not necessarily ready)
157 void OnClientConnect(C4Client *pClient, C4Network2IOConnection *pConn); // called when new clinet connection is established (notice of lobby status)
158 void OnClientPart(C4Client *pPartClient); // called when a client disconnects
159 bool OnMessage(C4Client *pOfClient, const char *szMessage); // display message in chat window
160 void OnClientSound(C4Client *pOfClient); // show that someone played a sound
161 void OnLog(const char *szLogMsg, uint32_t dwClr = C4GUI_LogFontClr); // log callback
162 void OnError(const char *szErrMsg); // error sound + log in red
163 void OnPlayersChange() { UpdatePlayerList(); }
164 void OnClientReadyStateChange(C4Client *client);
165 void OnClientAddPlayer(const char *szFilename, int32_t idClient);
166 // packet callbacks from C4Network2
167 void HandlePacket(char cStatus, const C4PacketBase *pBasePkt, C4Network2Client *pClient);
168 void OnCountdownPacket(const C4PacketCountdown &Pkt); // called when a countdown packet is received: Update countdown state
169
170 bool IsCountdown();
171 bool IsLongCountdown() const;
172 void UpdateFairCrew();
173 void UpdatePassword();
174 void UpdatePlayerCountDisplay();
175 void ClearLog();
176 void RequestReadyCheck();
177 void CheckReady(bool check);
178 bool CanBeReady() const { return resourcesLoaded; }
179
180 friend class C4Sec1TimerCallback<MainDlg>;
181};
182
183// helper
184void LobbyError(const char *szErrorMsg);
185
186// lobby countdown: Moves game from lobby to go state. Only created by host.
187class Countdown
188{
189private:
190 C4Sec1TimerCallback<Countdown> *pSec1Timer; // engine timer hook
191 int32_t iStartTimer; // countdown timer for round start; 0 for not started, -1 for start overdue
192
193public:
194 void OnSec1Timer(); // timer proc; count down; send important countdown packets
195
196public:
197 Countdown(int32_t iStartTimer); // Init; sends initial countdown packet
198 ~Countdown();
199
200 void Abort();
201};
202
203}
204