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 ENGINE_SHARED_CONSOLE_H
4#define ENGINE_SHARED_CONSOLE_H
5
6#include "memheap.h"
7
8#include <engine/console.h>
9#include <engine/storage.h>
10
11#include <optional>
12#include <vector>
13
14class CConsole : public IConsole
15{
16 class CCommand : public ICommandInfo
17 {
18 EAccessLevel m_AccessLevel;
19 CCommand *m_pNext;
20
21 public:
22 const char *m_pName;
23 const char *m_pHelp;
24 const char *m_pParams;
25
26 const CCommand *Next() const { return m_pNext; }
27 CCommand *Next() { return m_pNext; }
28 void SetNext(CCommand *pNext) { m_pNext = pNext; }
29 int m_Flags;
30 bool m_Temp;
31 FCommandCallback m_pfnCallback;
32 void *m_pUserData;
33
34 const char *Name() const override { return m_pName; }
35 const char *Help() const override { return m_pHelp; }
36 const char *Params() const override { return m_pParams; }
37 int Flags() const override { return m_Flags; }
38 EAccessLevel GetAccessLevel() const override { return m_AccessLevel; }
39 void SetAccessLevel(EAccessLevel AccessLevel);
40 };
41
42 class CChain
43 {
44 public:
45 FChainCommandCallback m_pfnChainCallback;
46 FCommandCallback m_pfnCallback;
47 void *m_pCallbackUserData;
48 void *m_pUserData;
49 };
50
51 int m_FlagMask;
52 bool m_StoreCommands;
53 const char *m_apStrokeStr[2];
54 CCommand *m_pFirstCommand;
55
56 class CExecFile
57 {
58 public:
59 const char *m_pFilename;
60 CExecFile *m_pPrev;
61 };
62
63 CExecFile *m_pFirstExec;
64 IStorage *m_pStorage;
65
66 CCommand *m_pRecycleList;
67 CHeap m_TempCommands;
68
69 static void TraverseChain(FCommandCallback *ppfnCallback, void **ppUserData);
70
71 static void Con_Chain(IResult *pResult, void *pUserData);
72 static void Con_Echo(IResult *pResult, void *pUserData);
73 static void Con_Exec(IResult *pResult, void *pUserData);
74 static void ConCommandAccess(IResult *pResult, void *pUser);
75 static void ConCommandStatus(IConsole::IResult *pResult, void *pUser);
76
77 void ExecuteLineStroked(int Stroke, const char *pStr, int ClientId = IConsole::CLIENT_ID_UNSPECIFIED, bool InterpretSemicolons = true) override;
78
79 FTeeHistorianCommandCallback m_pfnTeeHistorianCommandCallback;
80 void *m_pTeeHistorianCommandUserdata;
81
82 FUnknownCommandCallback m_pfnUnknownCommandCallback = EmptyUnknownCommandCallback;
83 void *m_pUnknownCommandUserdata = nullptr;
84
85 FCanUseCommandCallback m_pfnCanUseCommandCallback = nullptr;
86 void *m_pCanUseCommandUserData;
87
88 bool CanUseCommand(int ClientId, const IConsole::ICommandInfo *pCommand) const;
89
90 enum
91 {
92 CONSOLE_MAX_STR_LENGTH = 8192,
93 MAX_PARTS = (CONSOLE_MAX_STR_LENGTH + 1) / 2
94 };
95
96 class CResult : public IResult
97 {
98 public:
99 char m_aStringStorage[CONSOLE_MAX_STR_LENGTH + 1];
100 char *m_pArgsStart;
101
102 const char *m_pCommand;
103 const char *m_apArgs[MAX_PARTS];
104
105 CResult(int ClientId);
106 CResult(const CResult &Other);
107
108 void AddArgument(const char *pArg);
109 void RemoveArgument(unsigned Index) override;
110
111 const char *GetString(unsigned Index) const override;
112 int GetInteger(unsigned Index) const override;
113 float GetFloat(unsigned Index) const override;
114 ColorHSLA GetColor(unsigned Index, float DarkestLighting) const override;
115
116 // DDRace
117
118 enum
119 {
120 VICTIM_NONE = -3,
121 VICTIM_ME = -2,
122 VICTIM_ALL = -1,
123 };
124
125 int m_Victim;
126 void ResetVictim();
127 bool HasVictim() const;
128 void SetVictim(int Victim);
129 void SetVictim(const char *pVictim);
130 int GetVictim() const override;
131 };
132
133 int ParseStart(CResult *pResult, const char *pString, int Length);
134
135 enum
136 {
137 PARSEARGS_OK = 0,
138 PARSEARGS_MISSING_VALUE,
139 PARSEARGS_INVALID_INTEGER,
140 PARSEARGS_INVALID_COLOR,
141 PARSEARGS_INVALID_FLOAT,
142 };
143
144 int ParseArgs(CResult *pResult, const char *pFormat, bool IsColor = false);
145
146 /*
147 this function will set pFormat to the next parameter (i,s,r,v,?) it contains and
148 return the parameter; descriptions in brackets like [file] will be skipped;
149 returns '\0' if there is no next parameter; expects pFormat to point at a
150 parameter
151 */
152 char NextParam(const char *&pFormat);
153
154 class CExecutionQueueEntry
155 {
156 public:
157 CCommand *m_pCommand;
158 CResult m_Result;
159 CExecutionQueueEntry(CCommand *pCommand, const CResult &Result) :
160 m_pCommand(pCommand),
161 m_Result(Result) {}
162 };
163 std::vector<CExecutionQueueEntry> m_vExecutionQueue;
164
165 void AddCommandSorted(CCommand *pCommand);
166 CCommand *FindCommand(const char *pName, int FlagMask);
167
168 bool m_Cheated;
169
170public:
171 CConsole(int FlagMask);
172 ~CConsole() override;
173
174 void Init() override;
175 const ICommandInfo *FirstCommandInfo(int ClientId, int FlagMask) const override;
176 const ICommandInfo *NextCommandInfo(const IConsole::ICommandInfo *pInfo, int ClientId, int FlagMask) const override;
177 const ICommandInfo *GetCommandInfo(const char *pName, int FlagMask, bool Temp) override;
178 int PossibleCommands(const char *pStr, int FlagMask, bool Temp, FPossibleCallback pfnCallback, void *pUser) override;
179
180 void ParseArguments(int NumArgs, const char **ppArguments) override;
181 void Register(const char *pName, const char *pParams, int Flags, FCommandCallback pfnFunc, void *pUser, const char *pHelp) override;
182 void RegisterTemp(const char *pName, const char *pParams, int Flags, const char *pHelp) override;
183 void DeregisterTemp(const char *pName) override;
184 void DeregisterTempAll() override;
185 void Chain(const char *pName, FChainCommandCallback pfnChainFunc, void *pUser) override;
186 void StoreCommands(bool Store) override;
187
188 bool LineIsValid(const char *pStr) override;
189 void ExecuteLine(const char *pStr, int ClientId = IConsole::CLIENT_ID_UNSPECIFIED, bool InterpretSemicolons = true) override;
190 void ExecuteLineFlag(const char *pStr, int FlagMask, int ClientId = IConsole::CLIENT_ID_UNSPECIFIED, bool InterpretSemicolons = true) override;
191 bool ExecuteFile(const char *pFilename, int ClientId = IConsole::CLIENT_ID_UNSPECIFIED, bool LogFailure = false, int StorageType = IStorage::TYPE_ALL) override;
192
193 void Print(int Level, const char *pFrom, const char *pStr, ColorRGBA PrintColor = gs_ConsoleDefaultColor) const override;
194 void SetTeeHistorianCommandCallback(FTeeHistorianCommandCallback pfnCallback, void *pUser) override;
195 void SetUnknownCommandCallback(FUnknownCommandCallback pfnCallback, void *pUser) override;
196 void SetCanUseCommandCallback(FCanUseCommandCallback pfnCallback, void *pUser) override;
197 void InitChecksum(CChecksumData *pData) const override;
198
199 /**
200 * Converts access level string to access level enum.
201 *
202 * @param pAccessLevel should be either "admin", "mod", "moderator", "helper" or "user".
203 * @return `std::nullopt` on error otherwise one of the auth enums such as `EAccessLevel::ADMIN`.
204 */
205 static std::optional<EAccessLevel> AccessLevelToEnum(const char *pAccessLevel);
206
207 /**
208 * Converts access level enum to access level string.
209 *
210 * @param AccessLevel should be one of these: `EAccessLevel::ADMIN`, `EAccessLevel::MODERATOR`, `EAccessLevel::HELPER` or `EAccessLevel::USER`.
211 * @return `nullptr` on error or access level string like "admin".
212 */
213 static const char *AccessLevelToString(EAccessLevel AccessLevel);
214
215 static std::optional<ColorHSLA> ColorParse(const char *pStr, float DarkestLighting);
216
217 // DDRace
218
219 static void ConUserCommandStatus(IConsole::IResult *pResult, void *pUser);
220
221 bool Cheated() const override { return m_Cheated; }
222
223 int FlagMask() const override { return m_FlagMask; }
224 void SetFlagMask(int FlagMask) override { m_FlagMask = FlagMask; }
225};
226
227#endif
228