diff --git a/include/Common.h b/include/Common.h index 47b0812..c5e07e1 100644 --- a/include/Common.h +++ b/include/Common.h @@ -75,7 +75,7 @@ public: static void RegisterShutdownHandler(const TShutdownHandler& Handler); // Causes all threads to finish up and exit gracefull gracefully static void GracefullyShutdown(); - static TConsole& Console() { return *mConsole; } + static TConsole& Console() { return mConsole; } static std::string ServerVersionString(); static const Version& ServerVersion() { return mVersion; } static uint8_t ClientMajorVersion() { return 2; } @@ -101,9 +101,7 @@ public: static void SleepSafeSeconds(size_t Seconds); static void InitializeConsole() { - if (!mConsole) { - mConsole = std::make_unique(); - } + mConsole.InitializeCommandline(); } enum class Status { @@ -129,7 +127,7 @@ private: static inline SystemStatusMap mSystemStatusMap {}; static inline std::mutex mSystemStatusMapMutex {}; static inline std::string mPPS; - static inline std::unique_ptr mConsole; + static inline TConsole mConsole; static inline std::shared_mutex mShutdownMtx {}; static inline bool mShutdown { false }; static inline std::mutex mShutdownHandlersMutex {}; diff --git a/include/TConsole.h b/include/TConsole.h index eb733de..1f244ee 100644 --- a/include/TConsole.h +++ b/include/TConsole.h @@ -17,12 +17,15 @@ class TConsole { public: TConsole(); + // Initializes the commandline app to take over I/O + void InitializeCommandline(); + void Write(const std::string& str); void WriteRaw(const std::string& str); void InitializeLuaConsole(TLuaEngine& Engine); void BackupOldLog(); void StartLoggingToFile(); - Commandline& Internal() { return mCommandline; } + Commandline& Internal() { return *mCommandline; } private: void RunAsCommand(const std::string& cmd, bool IgnoreNotACommand = false); @@ -56,7 +59,7 @@ private: { "say", [this](const auto&, const auto&) { Command_Say(""); } }, // shouldn't actually be called }; - Commandline mCommandline; + std::unique_ptr mCommandline { nullptr }; std::vector mCachedLuaHistory; std::vector mCachedRegularHistory; TLuaEngine* mLuaEngine { nullptr }; diff --git a/src/TConsole.cpp b/src/TConsole.cpp index 56d6e05..cde978e 100644 --- a/src/TConsole.cpp +++ b/src/TConsole.cpp @@ -157,13 +157,13 @@ void TConsole::ChangeToLuaConsole(const std::string& LuaStateId) { mIsLuaConsole = true; if (mStateId != mDefaultStateId) { Application::Console().WriteRaw("Attached to Lua state '" + mStateId + "'. For help, type `:help`. To detach, type `:exit`"); - mCommandline.set_prompt("lua @" + LuaStateId + "> "); + mCommandline->set_prompt("lua @" + LuaStateId + "> "); } else { Application::Console().WriteRaw("Attached to Lua. For help, type `:help`. To detach, type `:exit`"); - mCommandline.set_prompt("lua> "); + mCommandline->set_prompt("lua> "); } - mCachedRegularHistory = mCommandline.history(); - mCommandline.set_history(mCachedLuaHistory); + mCachedRegularHistory = mCommandline->history(); + mCommandline->set_history(mCachedLuaHistory); } } @@ -175,9 +175,9 @@ void TConsole::ChangeToRegularConsole() { } else { Application::Console().WriteRaw("Detached from Lua."); } - mCachedLuaHistory = mCommandline.history(); - mCommandline.set_history(mCachedRegularHistory); - mCommandline.set_prompt("> "); + mCachedLuaHistory = mCommandline->history(); + mCommandline->set_history(mCachedRegularHistory); + mCommandline->set_prompt("> "); mStateId = mDefaultStateId; } } @@ -257,7 +257,7 @@ void TConsole::Command_Clear(const std::string&, const std::vector& if (!EnsureArgsCount(args, 0, size_t(-1))) { return; } - mCommandline.write("\x1b[;H\x1b[2J"); + mCommandline->write("\x1b[;H\x1b[2J"); } void TConsole::Command_Kick(const std::string&, const std::vector& args) { @@ -589,16 +589,20 @@ Commands } TConsole::TConsole() { - mCommandline.enable_history(); - mCommandline.set_history_limit(20); - mCommandline.set_prompt("> "); +} + +void TConsole::InitializeCommandline() { + mCommandline = std::make_unique(); + mCommandline->enable_history(); + mCommandline->set_history_limit(20); + mCommandline->set_prompt("> "); BackupOldLog(); - mCommandline.on_command = [this](Commandline& c) { + mCommandline->on_command = [this](Commandline& c) { try { auto TrimmedCmd = c.get_command(); TrimmedCmd = TrimString(TrimmedCmd); auto [cmd, args] = ParseCommand(TrimmedCmd); - mCommandline.write(mCommandline.prompt() + TrimmedCmd); + mCommandline->write(mCommandline->prompt() + TrimmedCmd); if (mIsLuaConsole) { if (!mLuaEngine) { beammp_info("Lua not started yet, please try again in a second"); @@ -633,7 +637,7 @@ TConsole::TConsole() { beammp_error("Console died with: " + std::string(e.what()) + ". This could be a fatal error and could cause the server to terminate."); } }; - mCommandline.on_autocomplete = [this](Commandline&, std::string stub, int) { + mCommandline->on_autocomplete = [this](Commandline&, std::string stub, int) { std::vector suggestions; try { if (mIsLuaConsole) { // if lua @@ -703,11 +707,21 @@ TConsole::TConsole() { void TConsole::Write(const std::string& str) { auto ToWrite = GetDate() + str; - mCommandline.write(ToWrite); + // allows writing to stdout without an initialized console + if (mCommandline) { + mCommandline->write(ToWrite); + } else { + std::cout << ToWrite << std::endl; + } } void TConsole::WriteRaw(const std::string& str) { - mCommandline.write(str); + // allows writing to stdout without an initialized console + if (mCommandline) { + mCommandline->write(str); + } else { + std::cout << str << std::endl; + } } void TConsole::InitializeLuaConsole(TLuaEngine& Engine) { diff --git a/src/main.cpp b/src/main.cpp index 4a027f1..d73c6c1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -69,7 +69,6 @@ int main(int argc, char** argv) { int BeamMPServerMain(MainArguments Arguments) { setlocale(LC_ALL, "C"); - Application::InitializeConsole(); ArgsParser Parser; Parser.RegisterArgument({ "help" }, ArgsParser::NONE); Parser.RegisterArgument({ "version" }, ArgsParser::NONE); @@ -80,12 +79,10 @@ int BeamMPServerMain(MainArguments Arguments) { return 1; } if (Parser.FoundArgument({ "help" })) { - Application::Console().Internal().set_prompt(""); Application::Console().WriteRaw(sCommandlineArguments); return 0; } if (Parser.FoundArgument({ "version" })) { - Application::Console().Internal().set_prompt(""); Application::Console().WriteRaw("BeamMP-Server v" + Application::ServerVersionString()); return 0; } @@ -109,11 +106,22 @@ int BeamMPServerMain(MainArguments Arguments) { } } } + + TConfig Config(ConfigPath); + + if (Config.Failed()) { + beammp_info("Closing in 10 seconds"); + // loop to make it possible to ctrl+c instead + for (size_t i = 0; i < 20; ++i) { + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } + return 1; + } + Application::InitializeConsole(); + Application::Console().StartLoggingToFile(); Application::SetSubsystemStatus("Main", Application::Status::Starting); - Application::Console().StartLoggingToFile(); - SetupSignalHandlers(); bool Shutdown = false; @@ -128,20 +136,11 @@ int BeamMPServerMain(MainArguments Arguments) { }); TServer Server(Arguments.List); - TConfig Config(ConfigPath); + auto LuaEngine = std::make_shared(); LuaEngine->SetServer(&Server); Application::Console().InitializeLuaConsole(*LuaEngine); - if (Config.Failed()) { - beammp_info("Closing in 10 seconds"); - // loop to make it possible to ctrl+c instead - for (size_t i = 0; i < 20; ++i) { - std::this_thread::sleep_for(std::chrono::milliseconds(500)); - } - return 1; - } - RegisterThread("Main"); beammp_trace("Running in debug mode on a debug build");