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_CONSOLE_H
4#define GAME_CLIENT_COMPONENTS_CONSOLE_H
5
6#include <base/lock.h>
7
8#include <engine/console.h>
9#include <engine/shared/ringbuffer.h>
10
11#include <game/client/component.h>
12#include <game/client/lineinput.h>
13
14enum
15{
16 CONSOLE_CLOSED,
17 CONSOLE_OPENING,
18 CONSOLE_OPEN,
19 CONSOLE_CLOSING,
20};
21
22class CConsoleLogger;
23
24class CGameConsole : public CComponent
25{
26 friend class CConsoleLogger;
27 class CInstance
28 {
29 public:
30 struct CBacklogEntry
31 {
32 float m_YOffset;
33 int m_LineCount;
34 ColorRGBA m_PrintColor;
35 size_t m_Length;
36 char m_aText[1];
37 };
38 CStaticRingBuffer<CBacklogEntry, 1024 * 1024, CRingBufferBase::FLAG_RECYCLE> m_Backlog;
39 CLock m_BacklogPendingLock;
40 CStaticRingBuffer<CBacklogEntry, 1024 * 1024, CRingBufferBase::FLAG_RECYCLE> m_BacklogPending GUARDED_BY(m_BacklogPendingLock);
41 CStaticRingBuffer<char, 64 * 1024, CRingBufferBase::FLAG_RECYCLE> m_History;
42 char *m_pHistoryEntry;
43
44 CLineInputBuffered<IConsole::CMDLINE_LENGTH> m_Input;
45 const char *m_pName;
46 int m_Type;
47 int m_BacklogCurLine;
48 int m_BacklogLastActiveLine = -1;
49 int m_LinesRendered;
50
51 STextBoundingBox m_BoundingBox = {.m_X: 0.0f, .m_Y: 0.0f, .m_W: 0.0f, .m_H: 0.0f};
52 float m_LastInputHeight = 0.0f;
53
54 bool m_MouseIsPress = false;
55 vec2 m_MousePress = vec2(0.0f, 0.0f);
56 vec2 m_MouseRelease = vec2(0.0f, 0.0f);
57 int m_CurSelStart = 0;
58 int m_CurSelEnd = 0;
59 bool m_HasSelection = false;
60 int m_NewLineCounter = 0;
61
62 CGameConsole *m_pGameConsole;
63
64 char m_aCompletionBuffer[IConsole::CMDLINE_LENGTH];
65 int m_CompletionChosen;
66 char m_aCompletionBufferArgument[IConsole::CMDLINE_LENGTH];
67 int m_CompletionChosenArgument;
68 int m_CompletionFlagmask;
69 float m_CompletionRenderOffset;
70 float m_CompletionRenderOffsetChange;
71 int m_CompletionArgumentPosition;
72
73 char m_aUser[32];
74 bool m_UserGot;
75 bool m_UsernameReq;
76
77 bool m_IsCommand;
78 const char *m_pCommandName;
79 const char *m_pCommandHelp;
80 const char *m_pCommandParams;
81
82 bool m_Searching = false;
83 struct SSearchMatch
84 {
85 int m_Pos;
86 int m_StartLine;
87 int m_EndLine;
88 int m_EntryLine;
89
90 SSearchMatch(int Pos, int StartLine, int EndLine, int EntryLine) :
91 m_Pos(Pos), m_StartLine(StartLine), m_EndLine(EndLine), m_EntryLine(EntryLine) {}
92 };
93 int m_CurrentMatchIndex;
94 char m_aCurrentSearchString[IConsole::CMDLINE_LENGTH];
95 std::vector<SSearchMatch> m_vSearchMatches;
96
97 CInstance(int t);
98 void Init(CGameConsole *pGameConsole);
99
100 void ClearBacklog() REQUIRES(!m_BacklogPendingLock);
101 void UpdateBacklogTextAttributes();
102 void PumpBacklogPending() REQUIRES(!m_BacklogPendingLock);
103 void ClearHistory();
104 void Reset();
105
106 void ExecuteLine(const char *pLine);
107
108 bool OnInput(const IInput::CEvent &Event);
109 void PrintLine(const char *pLine, int Len, ColorRGBA PrintColor) REQUIRES(!m_BacklogPendingLock);
110 int GetLinesToScroll(int Direction, int LinesToScroll);
111 void ScrollToCenter(int StartLine, int EndLine);
112 void ClearSearch();
113 void Dump() REQUIRES(!m_BacklogPendingLock);
114
115 const char *GetString() const { return m_Input.GetString(); }
116 static void PossibleCommandsCompleteCallback(int Index, const char *pStr, void *pUser);
117 static void PossibleArgumentsCompleteCallback(int Index, const char *pStr, void *pUser);
118
119 void UpdateEntryTextAttributes(CBacklogEntry *pEntry) const;
120
121 private:
122 void UpdateSearch();
123
124 friend class CGameConsole;
125 };
126
127 class IConsole *m_pConsole;
128 CConsoleLogger *m_pConsoleLogger = nullptr;
129
130 CInstance m_LocalConsole;
131 CInstance m_RemoteConsole;
132
133 CInstance *CurrentConsole();
134
135 int m_ConsoleType;
136 int m_ConsoleState;
137 float m_StateChangeEnd;
138 float m_StateChangeDuration;
139
140 bool m_WantsSelectionCopy = false;
141
142 static const ColorRGBA ms_SearchHighlightColor;
143 static const ColorRGBA ms_SearchSelectedColor;
144
145 void Toggle(int Type);
146
147 static void PossibleCommandsRenderCallback(int Index, const char *pStr, void *pUser);
148 static void ConToggleLocalConsole(IConsole::IResult *pResult, void *pUserData);
149 static void ConToggleRemoteConsole(IConsole::IResult *pResult, void *pUserData);
150 static void ConClearLocalConsole(IConsole::IResult *pResult, void *pUserData);
151 static void ConClearRemoteConsole(IConsole::IResult *pResult, void *pUserData);
152 static void ConDumpLocalConsole(IConsole::IResult *pResult, void *pUserData);
153 static void ConDumpRemoteConsole(IConsole::IResult *pResult, void *pUserData);
154 static void ConConsolePageUp(IConsole::IResult *pResult, void *pUserData);
155 static void ConConsolePageDown(IConsole::IResult *pResult, void *pUserData);
156 static void ConchainConsoleOutputLevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
157
158public:
159 enum
160 {
161 CONSOLETYPE_LOCAL = 0,
162 CONSOLETYPE_REMOTE,
163 };
164
165 CGameConsole();
166 ~CGameConsole();
167 virtual int Sizeof() const override { return sizeof(*this); }
168
169 void PrintLine(int Type, const char *pLine);
170 void RequireUsername(bool UsernameReq);
171
172 virtual void OnStateChange(int NewState, int OldState) override;
173 virtual void OnConsoleInit() override;
174 virtual void OnInit() override;
175 virtual void OnReset() override;
176 virtual void OnRender() override;
177 virtual void OnMessage(int MsgType, void *pRawMsg) override;
178 virtual bool OnInput(const IInput::CEvent &Event) override;
179 void Prompt(char (&aPrompt)[32]);
180
181 bool IsClosed() { return m_ConsoleState == CONSOLE_CLOSED; }
182};
183#endif
184