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 GAME_SERVER_GAMECONTEXT_H
4#define GAME_SERVER_GAMECONTEXT_H
5
6#include "eventhandler.h"
7#include "gameworld.h"
8#include "teehistorian.h"
9
10#include <engine/console.h>
11#include <engine/server.h>
12
13#include <generated/protocol.h>
14
15#include <game/collision.h>
16#include <game/layers.h>
17#include <game/mapbugs.h>
18#include <game/voting.h>
19
20#include <map>
21#include <memory>
22#include <string>
23
24/*
25 Tick
26 Game Context (CGameContext::tick)
27 Game World (GAMEWORLD::tick)
28 Reset world if requested (GAMEWORLD::reset)
29 All entities in the world (ENTITY::tick)
30 All entities in the world (ENTITY::tick_deferred)
31 Remove entities marked for deletion (GAMEWORLD::remove_entities)
32 Game Controller (GAMECONTROLLER::tick)
33 All players (CPlayer::tick)
34
35
36 Snap
37 Game Context (CGameContext::snap)
38 Game World (GAMEWORLD::snap)
39 All entities in the world (ENTITY::snap)
40 Game Controller (GAMECONTROLLER::snap)
41 Events handler (EVENT_HANDLER::snap)
42 All players (CPlayer::snap)
43
44*/
45
46class CCharacter;
47class IConfigManager;
48class CConfig;
49class CHeap;
50class CPlayer;
51class CScore;
52class CUnpacker;
53class IAntibot;
54class IGameController;
55class IEngine;
56class IStorage;
57struct CAntibotRoundData;
58struct CScoreRandomMapResult;
59
60struct CSnapContext
61{
62 CSnapContext(int Version, bool Sixup, int ClientId) :
63 m_ClientVersion(Version), m_Sixup(Sixup), m_ClientId(ClientId)
64 {
65 }
66
67 int GetClientVersion() const { return m_ClientVersion; }
68 bool IsSixup() const { return m_Sixup; }
69 bool ClientId() const { return m_ClientId; }
70
71private:
72 int m_ClientVersion;
73 bool m_Sixup;
74 int m_ClientId;
75};
76
77class CMute
78{
79public:
80 int64_t m_Expire;
81 bool m_Initialized = false;
82 bool m_InitialDelay;
83 char m_aReason[128];
84
85 int SecondsLeft() const;
86};
87
88class CMutes
89{
90public:
91 CMutes(const char *pSystemName);
92
93 bool Mute(const NETADDR *pAddr, int Seconds, const char *pReason, bool InitialDelay);
94 void UnmuteIndex(int Index);
95 void UnmuteAddr(const NETADDR *pAddr);
96 void UnmuteExpired();
97 std::optional<CMute> IsMuted(const NETADDR *pAddr, bool RespectInitialDelay) const;
98 void Print(int Page) const;
99
100private:
101 const char *m_pSystemName;
102 std::map<NETADDR, CMute> m_Mutes;
103};
104
105class CGameContext : public IGameServer
106{
107 IServer *m_pServer;
108 IConfigManager *m_pConfigManager;
109 CConfig *m_pConfig;
110 IConsole *m_pConsole;
111 IEngine *m_pEngine;
112 IStorage *m_pStorage;
113 IAntibot *m_pAntibot;
114 CLayers m_Layers;
115 CCollision m_Collision;
116 protocol7::CNetObjHandler m_NetObjHandler7;
117 CNetObjHandler m_NetObjHandler;
118 CTuningParams m_aTuningList[TuneZone::NUM];
119 std::vector<std::string> m_vCensorlist;
120
121 bool m_TeeHistorianActive;
122 CTeeHistorian m_TeeHistorian;
123 ASYNCIO *m_pTeeHistorianFile;
124 CUuid m_GameUuid;
125 CMapBugs m_MapBugs;
126 CPrng m_Prng;
127
128 bool m_Resetting;
129
130 static void CommandCallback(int ClientId, int FlagMask, const char *pCmd, IConsole::IResult *pResult, void *pUser);
131 static void TeeHistorianWrite(const void *pData, int DataSize, void *pUser);
132
133 static void ConTuneParam(IConsole::IResult *pResult, void *pUserData);
134 static void ConToggleTuneParam(IConsole::IResult *pResult, void *pUserData);
135 static void ConTuneReset(IConsole::IResult *pResult, void *pUserData);
136 static void ConTunes(IConsole::IResult *pResult, void *pUserData);
137 static void ConTuneZone(IConsole::IResult *pResult, void *pUserData);
138 static void ConTuneDumpZone(IConsole::IResult *pResult, void *pUserData);
139 static void ConTuneResetZone(IConsole::IResult *pResult, void *pUserData);
140 static void ConTuneSetZoneMsgEnter(IConsole::IResult *pResult, void *pUserData);
141 static void ConTuneSetZoneMsgLeave(IConsole::IResult *pResult, void *pUserData);
142 static void ConMapbug(IConsole::IResult *pResult, void *pUserData);
143 static void ConSwitchOpen(IConsole::IResult *pResult, void *pUserData);
144 static void ConPause(IConsole::IResult *pResult, void *pUserData);
145 static void ConChangeMap(IConsole::IResult *pResult, void *pUserData);
146 static void ConRandomMap(IConsole::IResult *pResult, void *pUserData);
147 static void ConRandomUnfinishedMap(IConsole::IResult *pResult, void *pUserData);
148 static void ConRestart(IConsole::IResult *pResult, void *pUserData);
149 static void ConServerAlert(IConsole::IResult *pResult, void *pUserData);
150 static void ConModAlert(IConsole::IResult *pResult, void *pUserData);
151 static void ConBroadcast(IConsole::IResult *pResult, void *pUserData);
152 static void ConSay(IConsole::IResult *pResult, void *pUserData);
153 static void ConSetTeam(IConsole::IResult *pResult, void *pUserData);
154 static void ConSetTeamAll(IConsole::IResult *pResult, void *pUserData);
155 static void ConHotReload(IConsole::IResult *pResult, void *pUserData);
156 static void ConAddVote(IConsole::IResult *pResult, void *pUserData);
157 static void ConRemoveVote(IConsole::IResult *pResult, void *pUserData);
158 static void ConForceVote(IConsole::IResult *pResult, void *pUserData);
159 static void ConClearVotes(IConsole::IResult *pResult, void *pUserData);
160 static void ConAddMapVotes(IConsole::IResult *pResult, void *pUserData);
161 static void ConVote(IConsole::IResult *pResult, void *pUserData);
162 static void ConVotes(IConsole::IResult *pResult, void *pUserData);
163 static void ConVoteNo(IConsole::IResult *pResult, void *pUserData);
164 static void ConDrySave(IConsole::IResult *pResult, void *pUserData);
165 static void ConDumpAntibot(IConsole::IResult *pResult, void *pUserData);
166 static void ConAntibot(IConsole::IResult *pResult, void *pUserData);
167 static void ConchainSpecialMotdupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
168 static void ConchainSettingUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
169 static void ConchainPracticeByDefaultUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
170 static void ConDumpLog(IConsole::IResult *pResult, void *pUserData);
171
172 void AddVote(const char *pDescription, const char *pCommand);
173 static int MapScan(const char *pName, int IsDir, int DirType, void *pUserData);
174
175 struct CPersistentData
176 {
177 CUuid m_PrevGameUuid;
178 };
179
180 struct CPersistentClientData
181 {
182 bool m_IsSpectator;
183 bool m_IsAfk;
184 int m_LastWhisperTo;
185 };
186
187public:
188 IServer *Server() const { return m_pServer; }
189 IConfigManager *ConfigManager() const { return m_pConfigManager; }
190 CConfig *Config() { return m_pConfig; }
191 IConsole *Console() { return m_pConsole; }
192 IEngine *Engine() { return m_pEngine; }
193 IStorage *Storage() { return m_pStorage; }
194 CCollision *Collision() { return &m_Collision; }
195 CTuningParams *GlobalTuning() { return &m_aTuningList[0]; }
196 CTuningParams *TuningList() { return m_aTuningList; }
197 IAntibot *Antibot() { return m_pAntibot; }
198 CTeeHistorian *TeeHistorian() { return &m_TeeHistorian; }
199 bool TeeHistorianActive() const { return m_TeeHistorianActive; }
200 CNetObjHandler *GetNetObjHandler() override { return &m_NetObjHandler; }
201 protocol7::CNetObjHandler *GetNetObjHandler7() override { return &m_NetObjHandler7; }
202
203 CGameContext(bool Resetting = false);
204 ~CGameContext() override;
205
206 void Clear();
207
208 CEventHandler m_Events;
209 CPlayer *m_apPlayers[MAX_CLIENTS];
210 // keep last input to always apply when none is sent
211 CNetObj_PlayerInput m_aLastPlayerInput[MAX_CLIENTS];
212 bool m_aPlayerHasInput[MAX_CLIENTS];
213 CSaveTeam *m_apSavedTeams[MAX_CLIENTS];
214 CSaveHotReloadTee *m_apSavedTees[MAX_CLIENTS];
215 int m_aTeamMapping[MAX_CLIENTS];
216
217 // returns last input if available otherwise nulled PlayerInput object
218 // ClientId has to be valid
219 CNetObj_PlayerInput GetLastPlayerInput(int ClientId) const;
220
221 IGameController *m_pController;
222 CGameWorld m_World;
223
224 // helper functions
225 CCharacter *GetPlayerChar(int ClientId);
226 const CCharacter *GetPlayerChar(int ClientId) const;
227 bool EmulateBug(int Bug) const;
228 std::vector<SSwitchers> &Switchers() { return m_World.m_Core.m_vSwitchers; }
229
230 // voting
231 void StartVote(const char *pDesc, const char *pCommand, const char *pReason, const char *pSixupDesc);
232 void EndVote();
233 void SendVoteSet(int ClientId);
234 void SendVoteStatus(int ClientId, int Total, int Yes, int No);
235 void AbortVoteKickOnDisconnect(int ClientId);
236
237 int m_VoteCreator;
238 int m_VoteType;
239 int64_t m_VoteCloseTime;
240 bool m_VoteUpdate;
241 int m_VotePos;
242 char m_aVoteDescription[VOTE_DESC_LENGTH];
243 char m_aSixupVoteDescription[VOTE_DESC_LENGTH];
244 char m_aVoteCommand[VOTE_CMD_LENGTH];
245 char m_aVoteReason[VOTE_REASON_LENGTH];
246 int m_NumVoteOptions;
247 int m_VoteEnforce;
248 char m_aaZoneEnterMsg[TuneZone::NUM][256]; // 0 is used for switching from or to area without tunings
249 char m_aaZoneLeaveMsg[TuneZone::NUM][256];
250
251 void CreateAllEntities(bool Initial);
252 CPlayer *CreatePlayer(int ClientId, int StartTeam, bool Afk, int LastWhisperTo);
253
254 char m_aDeleteTempfile[128];
255 void DeleteTempfile();
256
257 enum
258 {
259 VOTE_ENFORCE_UNKNOWN = 0,
260 VOTE_ENFORCE_NO,
261 VOTE_ENFORCE_YES,
262 VOTE_ENFORCE_NO_ADMIN,
263 VOTE_ENFORCE_YES_ADMIN,
264 VOTE_ENFORCE_ABORT,
265 VOTE_ENFORCE_CANCEL,
266 };
267 CHeap *m_pVoteOptionHeap;
268 CVoteOptionServer *m_pVoteOptionFirst;
269 CVoteOptionServer *m_pVoteOptionLast;
270
271 // helper functions
272 void CreateDamageInd(vec2 Pos, float AngleMod, int Amount, CClientMask Mask = CClientMask().set());
273 void CreateExplosion(vec2 Pos, int Owner, int Weapon, bool NoDamage, int ActivatedTeam, CClientMask Mask = CClientMask().set());
274 void CreateHammerHit(vec2 Pos, CClientMask Mask = CClientMask().set());
275 void CreatePlayerSpawn(vec2 Pos, CClientMask Mask = CClientMask().set());
276 void CreateDeath(vec2 Pos, int ClientId, CClientMask Mask = CClientMask().set());
277 void CreateBirthdayEffect(vec2 Pos, CClientMask Mask = CClientMask().set());
278 void CreateFinishEffect(vec2 Pos, CClientMask Mask = CClientMask().set());
279 void CreateSound(vec2 Pos, int Sound, CClientMask Mask = CClientMask().set());
280 void CreateSoundGlobal(int Sound, int Target = -1) const;
281
282 void SnapSwitchers(int SnappingClient);
283 bool SnapLaserObject(const CSnapContext &Context, int SnapId, const vec2 &To, const vec2 &From, int StartTick, int Owner = -1, int LaserType = -1, int Subtype = -1, int SwitchNumber = -1) const;
284 bool SnapPickup(const CSnapContext &Context, int SnapId, const vec2 &Pos, int Type, int SubType, int SwitchNumber, int Flags) const;
285
286 enum
287 {
288 FLAG_SIX = 1 << 0,
289 FLAG_SIXUP = 1 << 1,
290 };
291
292 // network
293 void CallVote(int ClientId, const char *pDesc, const char *pCmd, const char *pReason, const char *pChatmsg, const char *pSixupDesc = nullptr);
294 void SendChatTarget(int To, const char *pText, int VersionFlags = FLAG_SIX | FLAG_SIXUP) const;
295 void SendChatTeam(int Team, const char *pText) const;
296 void SendChat(int ClientId, int Team, const char *pText, int SpamProtectionClientId = -1, int VersionFlags = FLAG_SIX | FLAG_SIXUP);
297 void SendStartWarning(int ClientId, const char *pMessage);
298 void SendEmoticon(int ClientId, int Emoticon, int TargetClientId) const;
299 void SendWeaponPickup(int ClientId, int Weapon) const;
300 void SendMotd(int ClientId) const;
301 void SendSettings(int ClientId) const;
302 void SendServerAlert(const char *pMessage);
303 void SendModeratorAlert(const char *pMessage, int ToClientId);
304 void SendBroadcast(const char *pText, int ClientId, bool IsImportant = true);
305
306 void List(int ClientId, const char *pFilter);
307
308 //
309 void CheckPureTuning();
310 void SendTuningParams(int ClientId, int Zone = 0);
311
312 const CVoteOptionServer *GetVoteOption(int Index) const;
313 void ProgressVoteOptions(int ClientId);
314
315 //
316 void LoadMapSettings();
317
318 // engine events
319 void OnInit(const void *pPersistentData) override;
320 void OnConsoleInit() override;
321 void RegisterDDRaceCommands();
322 void RegisterChatCommands();
323 [[nodiscard]] bool OnMapChange(char *pNewMapName, int MapNameSize) override;
324 void OnShutdown(void *pPersistentData) override;
325
326 void OnTick() override;
327 void OnSnap(int ClientId, bool GlobalSnap) override;
328 void OnPostGlobalSnap() override;
329
330 void UpdatePlayerMaps();
331
332 void *PreProcessMsg(int *pMsgId, CUnpacker *pUnpacker, int ClientId);
333 void CensorMessage(char *pCensoredMessage, const char *pMessage, int Size);
334 void OnMessage(int MsgId, CUnpacker *pUnpacker, int ClientId) override;
335 void OnSayNetMessage(const CNetMsg_Cl_Say *pMsg, int ClientId, const CUnpacker *pUnpacker);
336 void OnCallVoteNetMessage(const CNetMsg_Cl_CallVote *pMsg, int ClientId);
337 void OnVoteNetMessage(const CNetMsg_Cl_Vote *pMsg, int ClientId);
338 void OnSetTeamNetMessage(const CNetMsg_Cl_SetTeam *pMsg, int ClientId);
339 void OnIsDDNetLegacyNetMessage(const CNetMsg_Cl_IsDDNetLegacy *pMsg, int ClientId, CUnpacker *pUnpacker);
340 void OnShowOthersLegacyNetMessage(const CNetMsg_Cl_ShowOthersLegacy *pMsg, int ClientId);
341 void OnShowOthersNetMessage(const CNetMsg_Cl_ShowOthers *pMsg, int ClientId);
342 void OnShowDistanceNetMessage(const CNetMsg_Cl_ShowDistance *pMsg, int ClientId);
343 void OnCameraInfoNetMessage(const CNetMsg_Cl_CameraInfo *pMsg, int ClientId);
344 void OnSetSpectatorModeNetMessage(const CNetMsg_Cl_SetSpectatorMode *pMsg, int ClientId);
345 void OnChangeInfoNetMessage(const CNetMsg_Cl_ChangeInfo *pMsg, int ClientId);
346 void OnEmoticonNetMessage(const CNetMsg_Cl_Emoticon *pMsg, int ClientId);
347 void OnKillNetMessage(const CNetMsg_Cl_Kill *pMsg, int ClientId);
348 void OnEnableSpectatorCountNetMessage(const CNetMsg_Cl_EnableSpectatorCount *pMsg, int ClientId);
349 void OnStartInfoNetMessage(const CNetMsg_Cl_StartInfo *pMsg, int ClientId);
350
351 bool OnClientDataPersist(int ClientId, void *pData) override;
352 void OnClientConnected(int ClientId, void *pData) override;
353 void OnClientEnter(int ClientId) override;
354 void OnClientDrop(int ClientId, const char *pReason) override;
355 void OnClientPrepareInput(int ClientId, void *pInput) override;
356 void OnClientDirectInput(int ClientId, const void *pInput) override;
357 void OnClientPredictedInput(int ClientId, const void *pInput) override;
358 void OnClientPredictedEarlyInput(int ClientId, const void *pInput) override;
359
360 void PreInputClients(int ClientId, bool *pClients) override;
361
362 void TeehistorianRecordAntibot(const void *pData, int DataSize) override;
363 void TeehistorianRecordPlayerJoin(int ClientId, bool Sixup) override;
364 void TeehistorianRecordPlayerDrop(int ClientId, const char *pReason) override;
365 void TeehistorianRecordPlayerRejoin(int ClientId) override;
366 void TeehistorianRecordPlayerName(int ClientId, const char *pName) override;
367 void TeehistorianRecordPlayerFinish(int ClientId, int TimeTicks) override;
368 void TeehistorianRecordTeamFinish(int TeamId, int TimeTicks) override;
369 void TeehistorianRecordAuthLogin(int ClientId, int Level, const char *pAuthName) override;
370
371 bool IsClientReady(int ClientId) const override;
372 bool IsClientPlayer(int ClientId) const override;
373 // Whether the client is allowed to have high bandwidth.
374 bool IsClientHighBandwidth(int ClientId) const override;
375 int PersistentDataSize() const override { return sizeof(CPersistentData); }
376 int PersistentClientDataSize() const override { return sizeof(CPersistentClientData); }
377
378 CUuid GameUuid() const override;
379 const char *GameType() const override;
380 const char *Version() const override;
381 const char *NetVersion() const override;
382
383 // DDRace
384 void OnPreTickTeehistorian() override;
385 bool OnClientDDNetVersionKnown(int ClientId);
386 void FillAntibot(CAntibotRoundData *pData) override;
387 bool ProcessSpamProtection(int ClientId, bool RespectChatInitialDelay = true);
388 int GetDDRaceTeam(int ClientId) const;
389 // Describes the time when the first player joined the server.
390 int64_t m_NonEmptySince;
391 int64_t m_LastMapVote;
392 int GetClientVersion(int ClientId) const;
393 CClientMask ClientsMaskExcludeClientVersionAndHigher(int Version) const;
394 bool PlayerExists(int ClientId) const override { return m_apPlayers[ClientId]; }
395 // Returns true if someone is actively moderating.
396 bool PlayerModerating() const;
397 void ForceVote(int EnforcerId, bool Success);
398
399 // Checks if player can vote and notify them about the reason
400 bool RateLimitPlayerVote(int ClientId);
401 bool RateLimitPlayerMapVote(int ClientId) const;
402
403 void OnUpdatePlayerServerInfo(CJsonWriter *pJsonWriter, int ClientId) override;
404 void ReadCensorList();
405
406 bool PracticeByDefault() const;
407
408 std::shared_ptr<CScoreRandomMapResult> m_SqlRandomMapResult;
409
410private:
411 // starting 1 to make 0 the special value "no client id"
412 uint32_t m_NextUniqueClientId = 1;
413 bool m_VoteWillPass;
414 CScore *m_pScore;
415
416 // DDRace Console Commands
417
418 static void ConKillPlayer(IConsole::IResult *pResult, void *pUserData);
419
420 static void ConNinja(IConsole::IResult *pResult, void *pUserData);
421 static void ConUnNinja(IConsole::IResult *pResult, void *pUserData);
422 static void ConEndlessHook(IConsole::IResult *pResult, void *pUserData);
423 static void ConUnEndlessHook(IConsole::IResult *pResult, void *pUserData);
424 static void ConSolo(IConsole::IResult *pResult, void *pUserData);
425 static void ConUnSolo(IConsole::IResult *pResult, void *pUserData);
426 static void ConFreeze(IConsole::IResult *pResult, void *pUserData);
427 static void ConUnFreeze(IConsole::IResult *pResult, void *pUserData);
428 static void ConDeep(IConsole::IResult *pResult, void *pUserData);
429 static void ConUnDeep(IConsole::IResult *pResult, void *pUserData);
430 static void ConLiveFreeze(IConsole::IResult *pResult, void *pUserData);
431 static void ConUnLiveFreeze(IConsole::IResult *pResult, void *pUserData);
432 static void ConUnSuper(IConsole::IResult *pResult, void *pUserData);
433 static void ConSuper(IConsole::IResult *pResult, void *pUserData);
434 static void ConToggleInvincible(IConsole::IResult *pResult, void *pUserData);
435 static void ConShotgun(IConsole::IResult *pResult, void *pUserData);
436 static void ConGrenade(IConsole::IResult *pResult, void *pUserData);
437 static void ConLaser(IConsole::IResult *pResult, void *pUserData);
438 static void ConJetpack(IConsole::IResult *pResult, void *pUserData);
439 static void ConEndlessJump(IConsole::IResult *pResult, void *pUserData);
440 static void ConSetJumps(IConsole::IResult *pResult, void *pUserData);
441 static void ConWeapons(IConsole::IResult *pResult, void *pUserData);
442 static void ConUnShotgun(IConsole::IResult *pResult, void *pUserData);
443 static void ConUnGrenade(IConsole::IResult *pResult, void *pUserData);
444 static void ConUnLaser(IConsole::IResult *pResult, void *pUserData);
445 static void ConUnJetpack(IConsole::IResult *pResult, void *pUserData);
446 static void ConUnEndlessJump(IConsole::IResult *pResult, void *pUserData);
447 static void ConUnWeapons(IConsole::IResult *pResult, void *pUserData);
448 static void ConAddWeapon(IConsole::IResult *pResult, void *pUserData);
449 static void ConRemoveWeapon(IConsole::IResult *pResult, void *pUserData);
450 void ModifyWeapons(IConsole::IResult *pResult, void *pUserData, int Weapon, bool Remove);
451 void MoveCharacter(int ClientId, int X, int Y, bool Raw = false);
452 static void ConGoLeft(IConsole::IResult *pResult, void *pUserData);
453 static void ConGoRight(IConsole::IResult *pResult, void *pUserData);
454 static void ConGoUp(IConsole::IResult *pResult, void *pUserData);
455 static void ConGoDown(IConsole::IResult *pResult, void *pUserData);
456 static void ConMove(IConsole::IResult *pResult, void *pUserData);
457 static void ConMoveRaw(IConsole::IResult *pResult, void *pUserData);
458
459 static void ConToTeleporter(IConsole::IResult *pResult, void *pUserData);
460 static void ConToCheckTeleporter(IConsole::IResult *pResult, void *pUserData);
461 void Teleport(CCharacter *pChr, vec2 Pos);
462 static void ConTeleport(IConsole::IResult *pResult, void *pUserData);
463
464 static void ConCredits(IConsole::IResult *pResult, void *pUserData);
465 static void ConInfo(IConsole::IResult *pResult, void *pUserData);
466 static void ConHelp(IConsole::IResult *pResult, void *pUserData);
467 static void ConSettings(IConsole::IResult *pResult, void *pUserData);
468 static void ConRules(IConsole::IResult *pResult, void *pUserData);
469 static void ConKill(IConsole::IResult *pResult, void *pUserData);
470 static void ConTogglePause(IConsole::IResult *pResult, void *pUserData);
471 static void ConTogglePauseVoted(IConsole::IResult *pResult, void *pUserData);
472 static void ConToggleSpec(IConsole::IResult *pResult, void *pUserData);
473 static void ConToggleSpecVoted(IConsole::IResult *pResult, void *pUserData);
474 static void ConForcePause(IConsole::IResult *pResult, void *pUserData);
475 static void ConTeamTop5(IConsole::IResult *pResult, void *pUserData);
476 static void ConTop(IConsole::IResult *pResult, void *pUserData);
477 static void ConTimes(IConsole::IResult *pResult, void *pUserData);
478 static void ConPoints(IConsole::IResult *pResult, void *pUserData);
479 static void ConTopPoints(IConsole::IResult *pResult, void *pUserData);
480 static void ConTimeCP(IConsole::IResult *pResult, void *pUserData);
481
482 static void ConDND(IConsole::IResult *pResult, void *pUserData);
483 static void ConWhispers(IConsole::IResult *pResult, void *pUserData);
484 static void ConMapInfo(IConsole::IResult *pResult, void *pUserData);
485 static void ConTimeout(IConsole::IResult *pResult, void *pUserData);
486 static void ConPractice(IConsole::IResult *pResult, void *pUserData);
487 static void ConUnPractice(IConsole::IResult *pResult, void *pUserData);
488 static void ConPracticeCmdList(IConsole::IResult *pResult, void *pUserData);
489 static void ConSwap(IConsole::IResult *pResult, void *pUserData);
490 static void ConCancelSwap(IConsole::IResult *pResult, void *pUserData);
491 static void ConSave(IConsole::IResult *pResult, void *pUserData);
492 static void ConLoad(IConsole::IResult *pResult, void *pUserData);
493 static void ConMap(IConsole::IResult *pResult, void *pUserData);
494 static void ConTeamRank(IConsole::IResult *pResult, void *pUserData);
495 static void ConRank(IConsole::IResult *pResult, void *pUserData);
496 static void ConTeam(IConsole::IResult *pResult, void *pUserData);
497 static void ConLock(IConsole::IResult *pResult, void *pUserData);
498 static void ConUnlock(IConsole::IResult *pResult, void *pUserData);
499 static void ConInvite(IConsole::IResult *pResult, void *pUserData);
500 static void ConJoin(IConsole::IResult *pResult, void *pUserData);
501 static void ConTeam0Mode(IConsole::IResult *pResult, void *pUserData);
502 static void ConWhisper(IConsole::IResult *pResult, void *pUserData);
503 static void ConConverse(IConsole::IResult *pResult, void *pUserData);
504 static void ConSetEyeEmote(IConsole::IResult *pResult, void *pUserData);
505 static void ConEyeEmote(IConsole::IResult *pResult, void *pUserData);
506 static void ConShowOthers(IConsole::IResult *pResult, void *pUserData);
507 static void ConShowAll(IConsole::IResult *pResult, void *pUserData);
508 static void ConSpecTeam(IConsole::IResult *pResult, void *pUserData);
509 static void ConNinjaJetpack(IConsole::IResult *pResult, void *pUserData);
510 static void ConSayTime(IConsole::IResult *pResult, void *pUserData);
511 static void ConSayTimeAll(IConsole::IResult *pResult, void *pUserData);
512 static void ConTime(IConsole::IResult *pResult, void *pUserData);
513 static void ConSetTimerType(IConsole::IResult *pResult, void *pUserData);
514 static void ConRescue(IConsole::IResult *pResult, void *pUserData);
515 static void ConRescueMode(IConsole::IResult *pResult, void *pUserData);
516 static void ConBack(IConsole::IResult *pResult, void *pUserData);
517 static void ConTeleTo(IConsole::IResult *pResult, void *pUserData);
518 static void ConTeleXY(IConsole::IResult *pResult, void *pUserData);
519 static void ConTeleCursor(IConsole::IResult *pResult, void *pUserData);
520 static void ConLastTele(IConsole::IResult *pResult, void *pUserData);
521
522 // Chat commands for practice mode
523 static void ConPracticeToTeleporter(IConsole::IResult *pResult, void *pUserData);
524 static void ConPracticeToCheckTeleporter(IConsole::IResult *pResult, void *pUserData);
525 static void ConPracticeUnSolo(IConsole::IResult *pResult, void *pUserData);
526 static void ConPracticeSolo(IConsole::IResult *pResult, void *pUserData);
527 static void ConPracticeUnDeep(IConsole::IResult *pResult, void *pUserData);
528 static void ConPracticeDeep(IConsole::IResult *pResult, void *pUserData);
529 static void ConPracticeUnLiveFreeze(IConsole::IResult *pResult, void *pUserData);
530 static void ConPracticeLiveFreeze(IConsole::IResult *pResult, void *pUserData);
531 static void ConPracticeShotgun(IConsole::IResult *pResult, void *pUserData);
532 static void ConPracticeGrenade(IConsole::IResult *pResult, void *pUserData);
533 static void ConPracticeLaser(IConsole::IResult *pResult, void *pUserData);
534 static void ConPracticeJetpack(IConsole::IResult *pResult, void *pUserData);
535 static void ConPracticeEndlessJump(IConsole::IResult *pResult, void *pUserData);
536 static void ConPracticeSetJumps(IConsole::IResult *pResult, void *pUserData);
537 static void ConPracticeWeapons(IConsole::IResult *pResult, void *pUserData);
538 static void ConPracticeUnShotgun(IConsole::IResult *pResult, void *pUserData);
539 static void ConPracticeUnGrenade(IConsole::IResult *pResult, void *pUserData);
540 static void ConPracticeUnLaser(IConsole::IResult *pResult, void *pUserData);
541 static void ConPracticeUnJetpack(IConsole::IResult *pResult, void *pUserData);
542 static void ConPracticeUnEndlessJump(IConsole::IResult *pResult, void *pUserData);
543 static void ConPracticeUnWeapons(IConsole::IResult *pResult, void *pUserData);
544 static void ConPracticeNinja(IConsole::IResult *pResult, void *pUserData);
545 static void ConPracticeUnNinja(IConsole::IResult *pResult, void *pUserData);
546 static void ConPracticeEndlessHook(IConsole::IResult *pResult, void *pUserData);
547 static void ConPracticeUnEndlessHook(IConsole::IResult *pResult, void *pUserData);
548 static void ConPracticeToggleInvincible(IConsole::IResult *pResult, void *pUserData);
549 static void ConPracticeToggleCollision(IConsole::IResult *pResult, void *pUserData);
550 static void ConPracticeToggleHookCollision(IConsole::IResult *pResult, void *pUserData);
551 static void ConPracticeToggleHitOthers(IConsole::IResult *pResult, void *pUserData);
552
553 static void ConPracticeAddWeapon(IConsole::IResult *pResult, void *pUserData);
554 static void ConPracticeRemoveWeapon(IConsole::IResult *pResult, void *pUserData);
555
556 static void ConProtectedKill(IConsole::IResult *pResult, void *pUserData);
557 static void ConModerate(IConsole::IResult *pResult, void *pUserData);
558
559 static void ConList(IConsole::IResult *pResult, void *pUserData);
560 static void ConSetDDRTeam(IConsole::IResult *pResult, void *pUserData);
561 static void ConUninvite(IConsole::IResult *pResult, void *pUserData);
562
563 static void ConReloadCensorlist(IConsole::IResult *pResult, void *pUserData);
564
565 CCharacter *GetPracticeCharacter(IConsole::IResult *pResult);
566
567 CMutes m_Mutes;
568 CMutes m_VoteMutes;
569 void MuteWithMessage(const NETADDR *pAddr, int Seconds, const char *pReason, const char *pDisplayName);
570 void VoteMuteWithMessage(const NETADDR *pAddr, int Seconds, const char *pReason, const char *pDisplayName);
571
572 static void ConMute(IConsole::IResult *pResult, void *pUserData);
573 static void ConMuteId(IConsole::IResult *pResult, void *pUserData);
574 static void ConMuteIp(IConsole::IResult *pResult, void *pUserData);
575 static void ConUnmute(IConsole::IResult *pResult, void *pUserData);
576 static void ConUnmuteId(IConsole::IResult *pResult, void *pUserData);
577 static void ConUnmuteIp(IConsole::IResult *pResult, void *pUserData);
578 static void ConMutes(IConsole::IResult *pResult, void *pUserData);
579
580 static void ConVoteMute(IConsole::IResult *pResult, void *pUserData);
581 static void ConVoteMuteId(IConsole::IResult *pResult, void *pUserData);
582 static void ConVoteMuteIp(IConsole::IResult *pResult, void *pUserData);
583 static void ConVoteUnmute(IConsole::IResult *pResult, void *pUserData);
584 static void ConVoteUnmuteId(IConsole::IResult *pResult, void *pUserData);
585 static void ConVoteUnmuteIp(IConsole::IResult *pResult, void *pUserData);
586 static void ConVoteMutes(IConsole::IResult *pResult, void *pUserData);
587
588 void Whisper(int ClientId, char *pStr);
589 void WhisperId(int ClientId, int VictimId, const char *pMessage);
590 void Converse(int ClientId, char *pStr);
591 bool IsVersionBanned(int Version);
592 void UnlockTeam(int ClientId, int Team) const;
593 void AttemptJoinTeam(int ClientId, int Team);
594
595 enum
596 {
597 MAX_LOG_SECONDS = 600,
598 MAX_LOGS = 512,
599 };
600 struct CLog
601 {
602 int64_t m_Timestamp;
603 bool m_FromServer;
604 char m_aDescription[256 + 8];
605 int m_ClientVersion;
606 char m_aClientName[MAX_NAME_LENGTH];
607 char m_aClientAddrStr[NETADDR_MAXSTRSIZE];
608 };
609 CLog m_aLogs[MAX_LOGS];
610 int m_LatestLog;
611
612 void LogEvent(const char *Description, int ClientId);
613
614public:
615 CLayers *Layers() { return &m_Layers; }
616 CScore *Score() { return m_pScore; }
617
618 enum
619 {
620 VOTE_TYPE_UNKNOWN = 0,
621 VOTE_TYPE_OPTION,
622 VOTE_TYPE_KICK,
623 VOTE_TYPE_SPECTATE,
624 };
625 int m_VoteVictim;
626
627 bool IsOptionVote() const { return m_VoteType == VOTE_TYPE_OPTION; }
628 bool IsKickVote() const { return m_VoteType == VOTE_TYPE_KICK; }
629 bool IsSpecVote() const { return m_VoteType == VOTE_TYPE_SPECTATE; }
630
631 bool IsRunningVote(int ClientId) const;
632 bool IsRunningKickOrSpecVote(int ClientId) const;
633
634 void SendRecord(int ClientId);
635 void SendFinish(int ClientId, float Time, float PreviousBestTime);
636 void SendSaveCode(int Team, int TeamSize, int State, const char *pError, const char *pSaveRequester, const char *pServerName, const char *pGeneratedCode, const char *pCode);
637 void OnSetAuthed(int ClientId, int Level) override;
638
639 void ResetTuning();
640};
641
642static inline bool CheckClientId(int ClientId)
643{
644 return ClientId >= 0 && ClientId < MAX_CLIENTS;
645}
646
647#endif
648