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#include <base/math.h>
8#include <base/system.h>
9#include <engine/console.h>
10#include <engine/storage.h>
11
12class CConsole : public IConsole
13{
14 class CCommand : public CCommandInfo
15 {
16 public:
17 CCommand *m_pNext;
18 int m_Flags;
19 bool m_Temp;
20 FCommandCallback m_pfnCallback;
21 void *m_pUserData;
22
23 const CCommandInfo *NextCommandInfo(int AccessLevel, int FlagMask) const override;
24
25 void SetAccessLevel(int AccessLevel) { m_AccessLevel = clamp(val: AccessLevel, lo: (int)(ACCESS_LEVEL_ADMIN), hi: (int)(ACCESS_LEVEL_USER)); }
26 };
27
28 class CChain
29 {
30 public:
31 FChainCommandCallback m_pfnChainCallback;
32 FCommandCallback m_pfnCallback;
33 void *m_pCallbackUserData;
34 void *m_pUserData;
35 };
36
37 int m_FlagMask;
38 bool m_StoreCommands;
39 const char *m_apStrokeStr[2];
40 CCommand *m_pFirstCommand;
41
42 class CExecFile
43 {
44 public:
45 const char *m_pFilename;
46 CExecFile *m_pPrev;
47 };
48
49 CExecFile *m_pFirstExec;
50 IStorage *m_pStorage;
51 int m_AccessLevel;
52
53 CCommand *m_pRecycleList;
54 CHeap m_TempCommands;
55
56 static void TraverseChain(FCommandCallback *ppfnCallback, void **ppUserData);
57
58 static void Con_Chain(IResult *pResult, void *pUserData);
59 static void Con_Echo(IResult *pResult, void *pUserData);
60 static void Con_Exec(IResult *pResult, void *pUserData);
61 static void ConCommandAccess(IResult *pResult, void *pUser);
62 static void ConCommandStatus(IConsole::IResult *pResult, void *pUser);
63
64 void ExecuteLineStroked(int Stroke, const char *pStr, int ClientId = -1, bool InterpretSemicolons = true) override;
65
66 FTeeHistorianCommandCallback m_pfnTeeHistorianCommandCallback;
67 void *m_pTeeHistorianCommandUserdata;
68
69 FUnknownCommandCallback m_pfnUnknownCommandCallback = EmptyUnknownCommandCallback;
70 void *m_pUnknownCommandUserdata = nullptr;
71
72 enum
73 {
74 CONSOLE_MAX_STR_LENGTH = 8192,
75 MAX_PARTS = (CONSOLE_MAX_STR_LENGTH + 1) / 2
76 };
77
78 class CResult : public IResult
79 {
80 public:
81 char m_aStringStorage[CONSOLE_MAX_STR_LENGTH + 1];
82 char *m_pArgsStart;
83
84 const char *m_pCommand;
85 const char *m_apArgs[MAX_PARTS];
86
87 CResult()
88
89 {
90 mem_zero(block: m_aStringStorage, size: sizeof(m_aStringStorage));
91 m_pArgsStart = 0;
92 m_pCommand = 0;
93 mem_zero(block: m_apArgs, size: sizeof(m_apArgs));
94 }
95
96 CResult &operator=(const CResult &Other)
97 {
98 if(this != &Other)
99 {
100 IResult::operator=(Other);
101 mem_copy(dest: m_aStringStorage, source: Other.m_aStringStorage, size: sizeof(m_aStringStorage));
102 m_pArgsStart = m_aStringStorage + (Other.m_pArgsStart - Other.m_aStringStorage);
103 m_pCommand = m_aStringStorage + (Other.m_pCommand - Other.m_aStringStorage);
104 for(unsigned i = 0; i < Other.m_NumArgs; ++i)
105 m_apArgs[i] = m_aStringStorage + (Other.m_apArgs[i] - Other.m_aStringStorage);
106 }
107 return *this;
108 }
109
110 void AddArgument(const char *pArg)
111 {
112 m_apArgs[m_NumArgs++] = pArg;
113 }
114
115 const char *GetString(unsigned Index) const override;
116 int GetInteger(unsigned Index) const override;
117 float GetFloat(unsigned Index) const override;
118 ColorHSLA GetColor(unsigned Index, bool Light) const override;
119
120 void RemoveArgument(unsigned Index) override
121 {
122 dbg_assert(Index < m_NumArgs, "invalid argument index");
123 for(unsigned i = Index; i < m_NumArgs - 1; i++)
124 m_apArgs[i] = m_apArgs[i + 1];
125
126 m_apArgs[m_NumArgs--] = 0;
127 }
128
129 // DDRace
130
131 enum
132 {
133 VICTIM_NONE = -3,
134 VICTIM_ME = -2,
135 VICTIM_ALL = -1,
136 };
137
138 int m_Victim;
139 void ResetVictim();
140 bool HasVictim() const;
141 void SetVictim(int Victim);
142 void SetVictim(const char *pVictim);
143 int GetVictim() const override;
144 };
145
146 int ParseStart(CResult *pResult, const char *pString, int Length);
147 int ParseArgs(CResult *pResult, const char *pFormat);
148
149 /*
150 this function will set pFormat to the next parameter (i,s,r,v,?) it contains and
151 return the parameter; descriptions in brackets like [file] will be skipped;
152 returns '\0' if there is no next parameter; expects pFormat to point at a
153 parameter
154 */
155 char NextParam(const char *&pFormat);
156
157 class CExecutionQueue
158 {
159 CHeap m_Queue;
160
161 public:
162 struct CQueueEntry
163 {
164 CQueueEntry *m_pNext;
165 CCommand *m_pCommand;
166 CResult m_Result;
167 } * m_pFirst, *m_pLast;
168
169 void AddEntry()
170 {
171 CQueueEntry *pEntry = m_Queue.Allocate<CQueueEntry>();
172 pEntry->m_pNext = 0;
173 if(!m_pFirst)
174 m_pFirst = pEntry;
175 if(m_pLast)
176 m_pLast->m_pNext = pEntry;
177 m_pLast = pEntry;
178 (void)new(&(pEntry->m_Result)) CResult;
179 }
180 void Reset()
181 {
182 m_Queue.Reset();
183 m_pFirst = m_pLast = 0;
184 }
185 } m_ExecutionQueue;
186
187 void AddCommandSorted(CCommand *pCommand);
188 CCommand *FindCommand(const char *pName, int FlagMask);
189
190 bool m_Cheated;
191
192public:
193 CConsole(int FlagMask);
194 ~CConsole();
195
196 void Init() override;
197 const CCommandInfo *FirstCommandInfo(int AccessLevel, int FlagMask) const override;
198 const CCommandInfo *GetCommandInfo(const char *pName, int FlagMask, bool Temp) override;
199 int PossibleCommands(const char *pStr, int FlagMask, bool Temp, FPossibleCallback pfnCallback, void *pUser) override;
200
201 void ParseArguments(int NumArgs, const char **ppArguments) override;
202 void Register(const char *pName, const char *pParams, int Flags, FCommandCallback pfnFunc, void *pUser, const char *pHelp) override;
203 void RegisterTemp(const char *pName, const char *pParams, int Flags, const char *pHelp) override;
204 void DeregisterTemp(const char *pName) override;
205 void DeregisterTempAll() override;
206 void Chain(const char *pName, FChainCommandCallback pfnChainFunc, void *pUser) override;
207 void StoreCommands(bool Store) override;
208
209 bool LineIsValid(const char *pStr) override;
210 void ExecuteLine(const char *pStr, int ClientId = -1, bool InterpretSemicolons = true) override;
211 void ExecuteLineFlag(const char *pStr, int FlagMask, int ClientId = -1, bool InterpretSemicolons = true) override;
212 bool ExecuteFile(const char *pFilename, int ClientId = -1, bool LogFailure = false, int StorageType = IStorage::TYPE_ALL) override;
213
214 char *Format(char *pBuf, int Size, const char *pFrom, const char *pStr) override;
215 void Print(int Level, const char *pFrom, const char *pStr, ColorRGBA PrintColor = gs_ConsoleDefaultColor) const override;
216 void SetTeeHistorianCommandCallback(FTeeHistorianCommandCallback pfnCallback, void *pUser) override;
217 void SetUnknownCommandCallback(FUnknownCommandCallback pfnCallback, void *pUser) override;
218 void InitChecksum(CChecksumData *pData) const override;
219
220 void SetAccessLevel(int AccessLevel) override { m_AccessLevel = clamp(val: AccessLevel, lo: (int)(ACCESS_LEVEL_ADMIN), hi: (int)(ACCESS_LEVEL_USER)); }
221
222 // DDRace
223
224 static void ConUserCommandStatus(IConsole::IResult *pResult, void *pUser);
225
226 bool Cheated() const override { return m_Cheated; }
227
228 int FlagMask() const override { return m_FlagMask; }
229 void SetFlagMask(int FlagMask) override { m_FlagMask = FlagMask; }
230};
231
232#endif
233