| 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 | |
| 14 | class 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 | |
| 170 | public: |
| 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 | |