/* * Copyright (c) Contributors to the Open 3D Engine Project. * For complete copyright and license terms please see the LICENSE at the root of this distribution. * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ #ifndef CRYINCLUDE_CRYSYSTEM_XCONSOLE_H #define CRYINCLUDE_CRYSYSTEM_XCONSOLE_H #pragma once #include #include #include #include #include #include #include //forward declaration struct INetwork; class CSystem; struct IFFont; #define MAX_HISTORY_ENTRIES 50 #define LINE_BORDER 10 enum ScrollDir { sdDOWN, sdUP, sdNONE }; ////////////////////////////////////////////////////////////////////////// // Console command holds information about commands registered to console. ////////////////////////////////////////////////////////////////////////// struct CConsoleCommand { AZStd::string m_sName; // Console command name AZStd::string m_sCommand; // lua code that is executed when this command is invoked AZStd::string m_sHelp; // optional help string - can be shown in the console with " ?" int m_nFlags; // bitmask consist of flag starting with VF_ e.g. VF_CHEAT ConsoleCommandFunc m_func; // Pointer to console command. ////////////////////////////////////////////////////////////////////////// CConsoleCommand() : m_func(nullptr) , m_nFlags(0) {} size_t sizeofThis () const {return sizeof(*this) + m_sName.capacity() + 1 + m_sCommand.capacity() + 1; } }; ////////////////////////////////////////////////////////////////////////// // Implements IConsoleCmdArgs. ////////////////////////////////////////////////////////////////////////// struct CConsoleCommandArgs : public IConsoleCmdArgs { CConsoleCommandArgs(AZStd::string& line, std::vector& args) : m_line(line) , m_args(args) {}; int GetArgCount() const override { return static_cast(m_args.size()); }; // Get argument by index, nIndex must be in 0 <= nIndex < GetArgCount() const char* GetArg(int nIndex) const override { assert(nIndex >= 0 && nIndex < GetArgCount()); if (!(nIndex >= 0 && nIndex < GetArgCount())) { return nullptr; } return m_args[nIndex].c_str(); } const char* GetCommandLine() const override { return m_line.c_str(); } private: std::vector& m_args; AZStd::string& m_line; }; struct string_nocase_lt { bool operator()(const AZStd::string& s1, const AZStd::string& s2) const { return azstricmp(s1.c_str(), s2.c_str()) < 0; } }; //forward declarations class ITexture; struct IRenderer; /*! engine console implementation @see IConsole */ class CXConsole : public IConsole , public IRemoteConsoleListener , public AzFramework::ConsoleRequestBus::Handler , public AzFramework::CommandRegistrationBus::Handler { public: using ConsoleBuffer = std::deque; using ConsoleBufferItor = ConsoleBuffer::iterator; using ConsoleBufferRItor = ConsoleBuffer::reverse_iterator; // constructor CXConsole(); // destructor virtual ~CXConsole(); void SetStatus(bool bActive){ m_bConsoleActive = bActive; } bool GetStatus() const { return m_bConsoleActive; } // void FreeRenderResources(); // void Copy(); void Paste(); // interface IConsole --------------------------------------------------------- void Release() override; void Init(ISystem* pSystem) override; ICVar* RegisterString(const char* sName, const char* sValue, int nFlags, const char* help = "", ConsoleVarFunc pChangeFunc = 0) override; ICVar* RegisterInt(const char* sName, int iValue, int nFlags, const char* help = "", ConsoleVarFunc pChangeFunc = 0) override; ICVar* RegisterFloat(const char* sName, float fValue, int nFlags, const char* help = "", ConsoleVarFunc pChangeFunc = 0) override; ICVar* Register(const char* name, float* src, float defaultvalue, int flags = 0, const char* help = "", ConsoleVarFunc pChangeFunc = 0, bool allowModify = true) override; ICVar* Register(const char* name, int* src, int defaultvalue, int flags = 0, const char* help = "", ConsoleVarFunc pChangeFunc = 0, bool allowModify = true) override; ICVar* Register(const char* name, const char** src, const char* defaultvalue, int flags = 0, const char* help = "", ConsoleVarFunc pChangeFunc = 0, bool allowModify = true) override; void UnregisterVariable(const char* sVarName, bool bDelete = false) override; void SetScrollMax(int value) override; void AddOutputPrintSink(IOutputPrintSink* inpSink) override; void RemoveOutputPrintSink(IOutputPrintSink* inpSink) override; void ShowConsole(bool show, int iRequestScrollMax = -1) override; void DumpCVars(ICVarDumpSink* pCallback, unsigned int nFlagsFilter = 0) override; void DumpKeyBinds(IKeyBindDumpSink* pCallback) override; void CreateKeyBind(const char* sCmd, const char* sRes) override; const char* FindKeyBind(const char* sCmd) const override; bool GetLineNo(int indwLineNo, char* outszBuffer, int indwBufferSize) const override; int GetLineCount() const override; ICVar* GetCVar(const char* name) override; char* GetVariable(const char* szVarName, const char* szFileName, const char* def_val) override; float GetVariable(const char* szVarName, const char* szFileName, float def_val) override; void PrintLine(AZStd::string_view s) override; void PrintLineAppendWithPrevLine(AZStd::string_view s) override; bool GetStatus() override; void Clear() override; void Update() override; bool AddCommand(const char* sCommand, ConsoleCommandFunc func, int nFlags = 0, const char* sHelp = NULL) override; bool AddCommand(const char* sName, const char* sScriptFunc, int nFlags = 0, const char* sHelp = NULL) override; void RemoveCommand(const char* sName) override; void ExecuteString(const char* command, bool bSilentMode, bool bDeferExecution = false) override; void ExecuteConsoleCommand(const char* command) override; void ResetCVarsToDefaults() override; void Exit(const char* command, ...) override PRINTF_PARAMS(2, 3); bool IsOpened() override; int GetNumVars() override; int GetNumVisibleVars() override; size_t GetSortedVars(AZStd::vector& pszArray, const char* szPrefix = 0) override; void FindVar(const char* substr); const char* AutoComplete(const char* substr) override; const char* AutoCompletePrev(const char* substr) override; const char* ProcessCompletion(const char* szInputBuffer) override; void RegisterAutoComplete(const char* sVarOrCommand, IConsoleArgumentAutoComplete* pArgAutoComplete) override; void UnRegisterAutoComplete(const char* sVarOrCommand) override; void ResetAutoCompletion() override; void AddConsoleVarSink(IConsoleVarSink* pSink) override; void RemoveConsoleVarSink(IConsoleVarSink* pSink) override; const char* GetHistoryElement(bool bUpOrDown) override; void AddCommandToHistory(const char* szCommand) override; void SetInputLine(const char* szLine) override; void LoadConfigVar(const char* sVariable, const char* sValue) override; void EnableActivationKey(bool bEnable) override; void SetClientDataProbeString(const char* pName, const char* pValue) override; // interface IRemoteConsoleListener ------------------------------------------------------------------ void OnConsoleCommand(const char* cmd) override; // interface IConsoleVarSink ---------------------------------------------------------------------- virtual bool OnBeforeVarChange(ICVar* pVar, const char* sNewValue); virtual void OnAfterVarChange(ICVar* pVar); // interface CommandRegistration -------------------------------------------------------------------- bool RegisterCommand(AZStd::string_view identifier, AZStd::string_view helpText, AZ::u32 commandFlags, AzFramework::CommandFunction callback) override; bool UnregisterCommand(AZStd::string_view identifier) override; void ExecuteRegisteredCommand(IConsoleCmdArgs* pArg); ////////////////////////////////////////////////////////////////////////// void SetProcessingGroup(bool isGroup) { m_bIsProcessingGroup = isGroup; } bool GetIsProcessingGroup() const { return m_bIsProcessingGroup; } protected: // ---------------------------------------------------------------------------------------- void RegisterVar(ICVar* pCVar, ConsoleVarFunc pChangeFunc = nullptr); void AddLine(AZStd::string_view inputStr); void AddLineAppendWithPrevLine(AZStd::string_view inputStr); void AddInputUTF8(const AZStd::string& textUTF8); void RemoveInputChar(bool bBackSpace); void ExecuteInputBuffer(); void ExecuteCommand(CConsoleCommand& cmd, AZStd::string& params, bool bIgnoreDevMode = false); void ScrollConsole(); // CommandRegistration usage struct CommandRegistrationEntry { AzFramework::CommandFunction m_callback; AZStd::string m_id; AZStd::string m_helpText; }; AZStd::unordered_map m_commandRegistrationMap; #if ALLOW_AUDIT_CVARS void AuditCVars(IConsoleCmdArgs* pArg); #endif // ALLOW_AUDIT_CVARS #ifndef _RELEASE // will be removed once the HTML version is good enough void DumpCommandsVarsTxt(const char* prefix); void DumpVarsTxt(const bool includeCheat); #endif void ConsoleLogInputResponse(const char* szFormat, ...) PRINTF_PARAMS(2, 3); void ConsoleLogInput(const char* szFormat, ...) PRINTF_PARAMS(2, 3); void ConsoleWarning(const char* szFormat, ...) PRINTF_PARAMS(2, 3); void DisplayHelp(const char* help, const char* name); void DisplayVarValue(ICVar* pVar); // Arguments: // bFromConsole - true=from console, false=from outside void SplitCommands(const char* line, std::list& split); void ExecuteStringInternal(const char* command, const bool bFromConsole, const bool bSilentMode = false); void ExecuteDeferredCommands(); static const char* GetFlagsString(const uint32 dwFlags); private: // ---------------------------------------------------------- typedef std::map ConsoleVariablesMap; // key points into string stored in ICVar or in .exe/.dll typedef ConsoleVariablesMap::iterator ConsoleVariablesMapItor; using ConsoleVariablesVector = std::vector >; void LogChangeMessage(const char* name, const bool isConst, const bool isCheat, const bool isReadOnly, const bool isDeprecated, const char* oldValue, const char* newValue, const bool isProcessingGroup, const bool allowChange); void AddCheckedCVar(ConsoleVariablesVector& vector, const ConsoleVariablesVector::value_type& value); void RemoveCheckedCVar(ConsoleVariablesVector& vector, const ConsoleVariablesVector::value_type& value); static bool CVarNameLess(const std::pair& lhs, const std::pair& rhs); typedef std::map ConsoleCommandsMap; typedef ConsoleCommandsMap::iterator ConsoleCommandsMapItor; typedef std::map ConsoleBindsMap; typedef ConsoleBindsMap::iterator ConsoleBindsMapItor; typedef std::map > ArgumentAutoCompleteMap; struct SConfigVar { AZStd::string m_value; bool m_partOfGroup; }; typedef std::map ConfigVars; struct SDeferredCommand { AZStd::string command; bool silentMode; SDeferredCommand(const AZStd::string& _command, bool _silentMode) : command(_command) , silentMode(_silentMode) {} }; using TDeferredCommandList = std::list; using ConsoleVarSinks = std::list; // -------------------------------------------------------------------------------- ConsoleBuffer m_dqConsoleBuffer; ConsoleBuffer m_dqHistory; bool m_bStaticBackground; int m_nLoadingBackTexID; int m_nProgress; int m_nProgressRange; AZStd::string m_sInputBuffer; AZStd::string m_sReturnString; AZStd::string m_sPrevTab; int m_nTabCount; ConsoleCommandsMap m_mapCommands; // ConsoleBindsMap m_mapBinds; // ConsoleVariablesMap m_mapVariables; // ConsoleVariablesVector m_randomCheckedVariables; ConsoleVariablesVector m_alwaysCheckedVariables; std::vector m_OutputSinks; // objects in this vector are not released template struct FunctorWrapper { FunctorWrapper(const char* name, const char* desc, T initialValue) : proxyValue(AZStd::move(initialValue)) , m_functor(name, desc, AZ::ConsoleFunctorFlags::DontDuplicate, AZ::AzTypeInfo::Uuid(), proxyValue, ArgToValue) { } T proxyValue; AZ::ConsoleFunctor m_functor; private: static void ArgToValue(T& outValue, const AZ::ConsoleCommandContainer& arguments) { AZ::ConsoleTypeHelpers::ToValue(outValue, arguments); } }; AZStd::vector> m_floatWrappers; AZStd::vector> m_intWrappers; AZStd::vector> m_stringWrappers; TDeferredCommandList m_deferredCommands; // A fifo of deferred commands bool m_deferredExecution; // True when deferred commands are processed int m_waitFrames; // A counter which is used by wait_frames command CTimeValue m_waitSeconds; // An absolute timestamp which is used by wait_seconds command int m_blockCounter; // This counter is incremented whenever a blocker command (VF_BLOCKFRAME) is executed. ArgumentAutoCompleteMap m_mapArgumentAutoComplete; ConsoleVarSinks m_consoleVarSinks; ConfigVars m_configVars; // temporary data of cvars that haven't been created yet int m_nScrollPos; int m_nTempScrollMax; // for currently opened console, reset to m_nScrollMax int m_nScrollMax; // int m_nScrollLine; int m_nHistoryPos; size_t m_nCursorPos; // x position in characters ITexture* m_pImage; float m_fRepeatTimer; // relative, next repeat even in .. decreses over time, repeats when 0, only valid if m_nRepeatEvent.keyId != eKI_Unknown float m_fCursorBlinkTimer; // relative, increases over time, bool m_bDrawCursor; ScrollDir m_sdScrollDir; bool m_bConsoleActive; bool m_bActivationKeyEnable; bool m_bIsProcessingGroup; bool m_bIsConsoleKeyPressed; size_t m_nCheatHashRangeFirst; size_t m_nCheatHashRangeLast; bool m_bCheatHashDirty; uint64 m_nCheatHash; CSystem* m_pSystem; ICVar* m_pSysDeactivateConsole; static int con_display_last_messages; static int con_line_buffer_size; static int con_showonload; static int con_debug; static int con_restricted; friend void Command_SetWaitSeconds(IConsoleCmdArgs* Cmd); friend void Command_SetWaitFrames(IConsoleCmdArgs* Cmd); #if ALLOW_AUDIT_CVARS friend void Command_AuditCVars(IConsoleCmdArgs* pArg); #endif // ALLOW_AUDIT_CVARS friend void Command_DumpCommandsVars(IConsoleCmdArgs* Cmd); friend void Command_DumpVars(IConsoleCmdArgs* Cmd); }; #endif // CRYINCLUDE_CRYSYSTEM_XCONSOLE_H