1#ifndef GAME_SERVER_PLAYERMAPPING_H
2#define GAME_SERVER_PLAYERMAPPING_H
3
4#include <engine/shared/protocol.h>
5
6#include <generated/protocol7.h>
7
8#include <game/teamscore.h>
9
10class CGameContext;
11class CPlayer;
12
13// The teeworlds 0.7 client and older ddnet clients
14// only support up to 64 clients. And also only up to 64 client ids (0-63).
15// The CPlayerMapping class manages a mapping of real server internal
16// client ids in the range of 0-127 and the fake client ids send to clients
17// in the range of 0-63.
18//
19// If a client does not support 128 slots the server will only show the 63 (64-1 for empty client for chat)
20// closest players (that closest selection currently tries to minimize changes by only changing when really required)
21// to the client. Because these 64 closest players are not
22// guaranteed to have client ids in the range of 0-63 we need to maintain a
23// fake client id list for every old client.
24//
25// Additionally there is the "See Others" feature which lets you cycle through a list of
26// all players manually in pause or spectator mode by holding right shift (+spectate).
27
28class CPlayerMapping
29{
30 class CGameContext *m_pGameServer;
31 class CConfig *m_pConfig;
32 class IServer *m_pServer;
33
34 // Number of players per page for see others feature in +spectate
35 static constexpr int ms_MaxNumSeeOthers = 34;
36 // Teams are messy. Dont highlight teams bigger than 10 tees in playermapping so that big teams wont break anything
37 static constexpr int ms_MaxTeamSizePlayerMap = 10;
38
39 int m_aTeamSizes[NUM_DDRACE_TEAMS];
40 char m_aSeeOthersName[MAX_NAME_LENGTH];
41
42 class CPlayerMap
43 {
44 public:
45 void Init(int ClientId, CPlayerMapping *pPlayerMapping);
46 void InitPlayer(bool Timeout);
47 CPlayerMapping *m_pPlayerMapping;
48 CPlayer *Player() const;
49 int m_ClientId;
50 int m_NumReserved;
51 bool m_UpdateTeamsState;
52 bool m_aReserved[MAX_CLIENTS];
53 bool m_ResortReserved;
54 int *m_pMap;
55 int *m_pReverseMap;
56 void Update();
57 void Add(int MapId, int ClientId);
58 int Remove(int MapId);
59 void InsertNextEmpty(int ClientId);
60 int MapSize() const { return LEGACY_MAX_CLIENTS - m_NumReserved; }
61 // See others
62 int m_SeeOthersPage;
63 int m_TotalOverhang;
64 int m_NumPages;
65 int m_NumSeeOthers;
66 bool m_aWasSeeOthers[MAX_CLIENTS];
67 bool m_DoSeeOthersByVote;
68 void DoSeeOthers();
69 void CycleSeeOthers();
70 void UpdateSeeOthers() const;
71 void ResetSeeOthers();
72 } m_aMap[MAX_CLIENTS];
73 void UpdatePlayerMap(int ClientId);
74
75public:
76 class CGameContext *GameServer() { return m_pGameServer; }
77 class CConfig *Config() { return m_pConfig; }
78 class IServer *Server() { return m_pServer; }
79
80 void Init(CGameContext *pGameServer);
81 void Tick();
82
83 void InitPlayerMap(int ClientId, bool Timeout = false) { m_aMap[ClientId].InitPlayer(Timeout); }
84 void UpdateTeamsState(int ClientId) { m_aMap[ClientId].m_UpdateTeamsState = true; }
85 void ForceInsertPlayer(int Insert, int ClientId) { m_aMap[ClientId].InsertNextEmpty(ClientId: Insert); }
86
87 enum class ESeeOthersInd
88 {
89 NONE = -1,
90 PLAYER = 0,
91 BUTTON = 1,
92 };
93 int SeeOthersId() const;
94 bool DoSeeOthers(int ClientId, int SelectedId, bool DoByVote = false);
95 void ResetSeeOthers(int ClientId);
96 int TotalOverhang(int ClientId) const;
97 ESeeOthersInd SeeOthersInd(int ClientId, int MapId) const;
98 const char *SeeOthersName(int ClientId);
99 bool ReserveTeamSlots(int DDTeam) const;
100};
101
102#endif
103