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_CLIENT_COMPONENTS_CHAT_H
4#define GAME_CLIENT_COMPONENTS_CHAT_H
5#include <vector>
6
7#include <engine/console.h>
8#include <engine/shared/config.h>
9#include <engine/shared/protocol.h>
10#include <engine/shared/ringbuffer.h>
11
12#include <game/client/component.h>
13#include <game/client/lineinput.h>
14#include <game/client/skin.h>
15
16class CChat : public CComponent
17{
18 static constexpr float CHAT_HEIGHT_FULL = 200.0f;
19 static constexpr float CHAT_HEIGHT_MIN = 50.0f;
20 static constexpr float CHAT_FONTSIZE_WIDTH_RATIO = 2.5f;
21
22 enum
23 {
24 MAX_LINES = 64,
25 MAX_LINE_LENGTH = 256
26 };
27
28 CLineInputBuffered<MAX_LINE_LENGTH> m_Input;
29 struct CLine
30 {
31 int64_t m_Time;
32 float m_aYOffset[2];
33 int m_ClientId;
34 int m_TeamNumber;
35 bool m_Team;
36 bool m_Whisper;
37 int m_NameColor;
38 char m_aName[64];
39 char m_aText[MAX_LINE_LENGTH];
40 bool m_Friend;
41 bool m_Highlighted;
42
43 STextContainerIndex m_TextContainerIndex;
44 int m_QuadContainerIndex;
45
46 char m_aSkinName[std::size(g_Config.m_ClPlayerSkin)];
47 CSkin::SSkinTextures m_RenderSkin;
48 CSkin::SSkinMetrics m_RenderSkinMetrics;
49 bool m_CustomColoredSkin;
50 ColorRGBA m_ColorBody;
51 ColorRGBA m_ColorFeet;
52
53 bool m_HasRenderTee;
54 float m_TextYOffset;
55
56 int m_TimesRepeated;
57 };
58
59 bool m_PrevScoreBoardShowed;
60 bool m_PrevShowChat;
61
62 CLine m_aLines[MAX_LINES];
63 int m_CurrentLine;
64
65 enum
66 {
67 // client IDs for special messages
68 CLIENT_MSG = -2,
69 SERVER_MSG = -1,
70
71 MODE_NONE = 0,
72 MODE_ALL,
73 MODE_TEAM,
74
75 CHAT_SERVER = 0,
76 CHAT_HIGHLIGHT,
77 CHAT_CLIENT,
78 CHAT_NUM,
79 };
80
81 int m_Mode;
82 bool m_Show;
83 bool m_CompletionUsed;
84 int m_CompletionChosen;
85 char m_aCompletionBuffer[MAX_LINE_LENGTH];
86 int m_PlaceholderOffset;
87 int m_PlaceholderLength;
88 static char ms_aDisplayText[MAX_LINE_LENGTH];
89 struct CRateablePlayer
90 {
91 int ClientId;
92 int Score;
93 };
94 CRateablePlayer m_aPlayerCompletionList[MAX_CLIENTS];
95 int m_PlayerCompletionListLength;
96
97 struct CCommand
98 {
99 char m_aName[IConsole::TEMPCMD_NAME_LENGTH];
100 char m_aParams[IConsole::TEMPCMD_PARAMS_LENGTH];
101 char m_aHelpText[IConsole::TEMPCMD_HELP_LENGTH];
102
103 CCommand() = default;
104 CCommand(const char *pName, const char *pParams, const char *pHelpText)
105 {
106 str_copy(dst&: m_aName, src: pName);
107 str_copy(dst&: m_aParams, src: pParams);
108 str_copy(dst&: m_aHelpText, src: pHelpText);
109 }
110
111 bool operator<(const CCommand &Other) const { return str_comp(a: m_aName, b: Other.m_aName) < 0; }
112 bool operator<=(const CCommand &Other) const { return str_comp(a: m_aName, b: Other.m_aName) <= 0; }
113 bool operator==(const CCommand &Other) const { return str_comp(a: m_aName, b: Other.m_aName) == 0; }
114 };
115
116 std::vector<CCommand> m_vCommands;
117 bool m_CommandsNeedSorting;
118
119 struct CHistoryEntry
120 {
121 int m_Team;
122 char m_aText[1];
123 };
124 CHistoryEntry *m_pHistoryEntry;
125 CStaticRingBuffer<CHistoryEntry, 64 * 1024, CRingBufferBase::FLAG_RECYCLE> m_History;
126 int m_PendingChatCounter;
127 int64_t m_LastChatSend;
128 int64_t m_aLastSoundPlayed[CHAT_NUM];
129 bool m_IsInputCensored;
130 char m_aCurrentInputText[MAX_LINE_LENGTH];
131 bool m_EditingNewLine;
132
133 bool m_ServerSupportsCommandInfo;
134
135 static void ConSay(IConsole::IResult *pResult, void *pUserData);
136 static void ConSayTeam(IConsole::IResult *pResult, void *pUserData);
137 static void ConChat(IConsole::IResult *pResult, void *pUserData);
138 static void ConShowChat(IConsole::IResult *pResult, void *pUserData);
139 static void ConEcho(IConsole::IResult *pResult, void *pUserData);
140
141 static void ConchainChatOld(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
142 static void ConchainChatFontSize(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
143 static void ConchainChatWidth(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
144
145 bool LineShouldHighlight(const char *pLine, const char *pName);
146 void StoreSave(const char *pText);
147
148public:
149 CChat();
150 int Sizeof() const override { return sizeof(*this); }
151
152 static constexpr float MESSAGE_TEE_PADDING_RIGHT = 0.5f;
153
154 bool IsActive() const { return m_Mode != MODE_NONE; }
155 void AddLine(int ClientId, int Team, const char *pLine);
156 void EnableMode(int Team);
157 void DisableMode();
158 void RegisterCommand(const char *pName, const char *pParams, const char *pHelpText);
159 void UnregisterCommand(const char *pName);
160 void Echo(const char *pString);
161
162 void OnWindowResize() override;
163 void OnConsoleInit() override;
164 void OnStateChange(int NewState, int OldState) override;
165 void OnRefreshSkins() override;
166 void OnRender() override;
167 void OnPrepareLines(float y);
168 void Reset();
169 void OnRelease() override;
170 void OnMessage(int MsgType, void *pRawMsg) override;
171 bool OnInput(const IInput::CEvent &Event) override;
172 void OnInit() override;
173
174 void RebuildChat();
175
176 void EnsureCoherentFontSize() const;
177 void EnsureCoherentWidth() const;
178
179 float FontSize() const { return g_Config.m_ClChatFontSize / 10.0f; }
180 float MessagePaddingX() const { return FontSize() * (5 / 6.f); }
181 float MessagePaddingY() const { return FontSize() * (1 / 6.f); }
182 float MessageTeeSize() const { return FontSize() * (7 / 6.f); }
183 float MessageRounding() const { return FontSize() * (1 / 2.f); }
184
185 // ----- send functions -----
186
187 // Sends a chat message to the server.
188 //
189 // @param Team MODE_ALL=0 MODE_TEAM=1
190 // @param pLine the chat message
191 void SendChat(int Team, const char *pLine);
192
193 // Sends a chat message to the server.
194 //
195 // It uses a queue with a maximum of 3 entries
196 // that ensures there is a minimum delay of one second
197 // between sent messages.
198 //
199 // It uses team or public chat depending on m_Mode.
200 void SendChatQueued(const char *pLine);
201};
202#endif
203