diff options
-rw-r--r-- | CONTRIBUTORS | 1 | ||||
-rw-r--r-- | Install/MCServer_high_detail_debug.cmd | 2 | ||||
-rw-r--r-- | Install/MCServer_medium_detail_debug.cmd | 2 | ||||
-rw-r--r-- | src/ClientHandle.cpp | 58 | ||||
-rw-r--r-- | src/ClientHandle.h | 4 | ||||
-rw-r--r-- | src/Defines.h | 11 | ||||
-rw-r--r-- | src/Entities/Player.h | 21 | ||||
-rw-r--r-- | src/Protocol/Protocol.h | 6 | ||||
-rw-r--r-- | src/Protocol/Protocol17x.cpp | 56 | ||||
-rw-r--r-- | src/Protocol/Protocol17x.h | 6 | ||||
-rw-r--r-- | src/Protocol/Protocol18x.cpp | 60 | ||||
-rw-r--r-- | src/Protocol/Protocol18x.h | 6 | ||||
-rw-r--r-- | src/Protocol/ProtocolRecognizer.cpp | 60 | ||||
-rw-r--r-- | src/Protocol/ProtocolRecognizer.h | 6 | ||||
-rw-r--r-- | src/main.cpp | 171 |
15 files changed, 362 insertions, 108 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS index cd84a8dd5..82ae6a7a8 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -10,6 +10,7 @@ Duralex FakeTruth (founder) HaoTNN Howaner +jan64 jasperarmstrong keyboard Lapayo diff --git a/Install/MCServer_high_detail_debug.cmd b/Install/MCServer_high_detail_debug.cmd index 384189c42..d94af8150 100644 --- a/Install/MCServer_high_detail_debug.cmd +++ b/Install/MCServer_high_detail_debug.cmd @@ -1 +1 @@ -MCServer /cdf
\ No newline at end of file +MCServer --crash-dump-full diff --git a/Install/MCServer_medium_detail_debug.cmd b/Install/MCServer_medium_detail_debug.cmd index b5bb0954c..0a33c27fd 100644 --- a/Install/MCServer_medium_detail_debug.cmd +++ b/Install/MCServer_medium_detail_debug.cmd @@ -1 +1 @@ -MCServer /cdg
\ No newline at end of file +MCServer --crash-dump-globals diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index e3f63b091..d89f7ab77 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -2113,6 +2113,64 @@ void cClientHandle::SendChat(const cCompositeChat & a_Message) +void cClientHandle::SendChatAboveActionBar(const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData) +{ + cWorld * World = GetPlayer()->GetWorld(); + if (World == nullptr) + { + World = cRoot::Get()->GetWorld(GetPlayer()->GetLoadedWorldName()); + if (World == nullptr) + { + World = cRoot::Get()->GetDefaultWorld(); + } + } + + AString Message = FormatMessageType(World->ShouldUseChatPrefixes(), a_ChatPrefix, a_AdditionalData); + m_Protocol->SendChatAboveActionBar(Message.append(a_Message)); +} + + + + + +void cClientHandle::SendChatAboveActionBar(const cCompositeChat & a_Message) +{ + m_Protocol->SendChatAboveActionBar(a_Message); +} + + + + + +void cClientHandle::SendChatSystem(const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData) +{ + cWorld * World = GetPlayer()->GetWorld(); + if (World == nullptr) + { + World = cRoot::Get()->GetWorld(GetPlayer()->GetLoadedWorldName()); + if (World == nullptr) + { + World = cRoot::Get()->GetDefaultWorld(); + } + } + + AString Message = FormatMessageType(World->ShouldUseChatPrefixes(), a_ChatPrefix, a_AdditionalData); + m_Protocol->SendChatSystem(Message.append(a_Message)); +} + + + + + +void cClientHandle::SendChatSystem(const cCompositeChat & a_Message) +{ + m_Protocol->SendChatSystem(a_Message); +} + + + + + void cClientHandle::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) { ASSERT(m_Player != nullptr); diff --git a/src/ClientHandle.h b/src/ClientHandle.h index bcfa55825..13b5f87e4 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -150,6 +150,10 @@ public: // tolua_export void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes); void SendChat (const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData = ""); void SendChat (const cCompositeChat & a_Message); + void SendChatAboveActionBar (const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData = ""); + void SendChatAboveActionBar (const cCompositeChat & a_Message); + void SendChatSystem (const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData = ""); + void SendChatSystem (const cCompositeChat & a_Message); void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer); void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player); void SendDestroyEntity (const cEntity & a_Entity); diff --git a/src/Defines.h b/src/Defines.h index 4005c84dd..b167f69e3 100644 --- a/src/Defines.h +++ b/src/Defines.h @@ -133,6 +133,17 @@ enum eGameMode +enum eChatType +{ + ctChatBox = 0, + ctSystem = 1, + ctAboveActionBar = 2, +} ; + + + + + enum eWeather { eWeather_Sunny = 0, diff --git a/src/Entities/Player.h b/src/Entities/Player.h index a84fdd0c7..799990bf2 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -235,14 +235,19 @@ public: // tolua_begin - void SendMessage (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtCustom); } - void SendMessageInfo (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtInformation); } - void SendMessageFailure (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtFailure); } - void SendMessageSuccess (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtSuccess); } - void SendMessageWarning (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtWarning); } - void SendMessageFatal (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtFailure); } - void SendMessagePrivateMsg(const AString & a_Message, const AString & a_Sender) { m_ClientHandle->SendChat(a_Message, mtPrivateMessage, a_Sender); } - void SendMessage (const cCompositeChat & a_Message) { m_ClientHandle->SendChat(a_Message); } + void SendMessage (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtCustom); } + void SendMessageInfo (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtInformation); } + void SendMessageFailure (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtFailure); } + void SendMessageSuccess (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtSuccess); } + void SendMessageWarning (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtWarning); } + void SendMessageFatal (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtFailure); } + void SendMessagePrivateMsg (const AString & a_Message, const AString & a_Sender) { m_ClientHandle->SendChat(a_Message, mtPrivateMessage, a_Sender); } + void SendMessage (const cCompositeChat & a_Message) { m_ClientHandle->SendChat(a_Message); } + + void SendSystemMessage (const AString & a_Message) { m_ClientHandle->SendChatSystem(a_Message, mtCustom); } + void SendAboveActionBarMessage(const AString & a_Message) { m_ClientHandle->SendChatAboveActionBar(a_Message, mtCustom); } + void SendSystemMessage (const cCompositeChat & a_Message) { m_ClientHandle->SendChatSystem(a_Message); } + void SendAboveActionBarMessage(const cCompositeChat & a_Message) { m_ClientHandle->SendChatAboveActionBar(a_Message); } const AString & GetName(void) const { return m_PlayerName; } void SetName(const AString & a_Name) { m_PlayerName = a_Name; } diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index 7be72014a..1a19249bf 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -70,6 +70,12 @@ public: virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) = 0; virtual void SendChat (const AString & a_Message) = 0; virtual void SendChat (const cCompositeChat & a_Message) = 0; + virtual void SendChatAboveActionBar (const AString & a_Message) = 0; + virtual void SendChatAboveActionBar (const cCompositeChat & a_Message) = 0; + virtual void SendChatSystem (const AString & a_Message) = 0; + virtual void SendChatSystem (const cCompositeChat & a_Message) = 0; + virtual void SendChatType (const AString & a_Message, eChatType type) = 0; + virtual void SendChatType (const cCompositeChat & a_Message, eChatType type) = 0; virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) = 0; virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) = 0; virtual void SendDestroyEntity (const cEntity & a_Entity) = 0; diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 6aa36e2a5..71c68c071 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -247,6 +247,60 @@ void cProtocol172::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockV void cProtocol172::SendChat(const AString & a_Message) { + this->SendChatType(a_Message, ctChatBox); +} + + + + + +void cProtocol172::SendChat(const cCompositeChat & a_Message) +{ + this->SendChatType(a_Message, ctChatBox); +} + + + + + +void cProtocol172::SendChatSystem(const AString & a_Message) +{ + this->SendChatType(a_Message, ctSystem); +} + + + + + +void cProtocol172::SendChatSystem(const cCompositeChat & a_Message) +{ + this->SendChatType(a_Message, ctSystem); +} + + + + + +void cProtocol172::SendChatAboveActionBar(const AString & a_Message) +{ + this->SendChatType(a_Message, ctAboveActionBar); +} + + + + + +void cProtocol172::SendChatAboveActionBar(const cCompositeChat & a_Message) +{ + this->SendChatType(a_Message, ctAboveActionBar); +} + + + + + +void cProtocol172::SendChatType(const AString & a_Message, eChatType type) +{ ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, 0x02); // Chat Message packet @@ -257,7 +311,7 @@ void cProtocol172::SendChat(const AString & a_Message) -void cProtocol172::SendChat(const cCompositeChat & a_Message) +void cProtocol172::SendChatType(const cCompositeChat & a_Message, eChatType type) { ASSERT(m_State == 3); // In game mode? diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index ead2935b0..b07fa9ed9 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -68,6 +68,12 @@ public: virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; virtual void SendChat (const AString & a_Message) override; virtual void SendChat (const cCompositeChat & a_Message) override; + virtual void SendChatAboveActionBar (const AString & a_Message) override; + virtual void SendChatAboveActionBar (const cCompositeChat & a_Message) override; + virtual void SendChatSystem (const AString & a_Message) override; + virtual void SendChatSystem (const cCompositeChat & a_Message) override; + virtual void SendChatType (const AString & a_Message, eChatType type) override; + virtual void SendChatType (const cCompositeChat & a_Message, eChatType type) override; virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override; virtual void SendDestroyEntity (const cEntity & a_Entity) override; diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index d06022ce0..d9449283b 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -234,18 +234,72 @@ void cProtocol180::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockV void cProtocol180::SendChat(const AString & a_Message) { + this->SendChatType(a_Message, ctChatBox); +} + + + + + +void cProtocol180::SendChat(const cCompositeChat & a_Message) +{ + this->SendChatType(a_Message, ctChatBox); +} + + + + + +void cProtocol180::SendChatSystem(const AString & a_Message) +{ + this->SendChatType(a_Message, ctSystem); +} + + + + + +void cProtocol180::SendChatSystem(const cCompositeChat & a_Message) +{ + this->SendChatType(a_Message, ctSystem); +} + + + + + +void cProtocol180::SendChatAboveActionBar(const AString & a_Message) +{ + this->SendChatType(a_Message, ctAboveActionBar); +} + + + + + +void cProtocol180::SendChatAboveActionBar(const cCompositeChat & a_Message) +{ + this->SendChatType(a_Message, ctAboveActionBar); +} + + + + + +void cProtocol180::SendChatType(const AString & a_Message, eChatType type) +{ ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, 0x02); // Chat Message packet Pkt.WriteString(Printf("{\"text\":\"%s\"}", EscapeString(a_Message).c_str())); - Pkt.WriteBEInt8(0); + Pkt.WriteBEInt8(type); } -void cProtocol180::SendChat(const cCompositeChat & a_Message) +void cProtocol180::SendChatType(const cCompositeChat & a_Message, eChatType type) { ASSERT(m_State == 3); // In game mode? @@ -255,7 +309,7 @@ void cProtocol180::SendChat(const cCompositeChat & a_Message) // Send the message to the client: cPacketizer Pkt(*this, 0x02); Pkt.WriteString(a_Message.CreateJsonString(ShouldUseChatPrefixes)); - Pkt.WriteBEInt8(0); + Pkt.WriteBEInt8(type); } diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h index 6143e8b4e..36ed251fe 100644 --- a/src/Protocol/Protocol18x.h +++ b/src/Protocol/Protocol18x.h @@ -67,6 +67,12 @@ public: virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; virtual void SendChat (const AString & a_Message) override; virtual void SendChat (const cCompositeChat & a_Message) override; + virtual void SendChatAboveActionBar (const AString & a_Message) override; + virtual void SendChatAboveActionBar (const cCompositeChat & a_Message) override; + virtual void SendChatSystem (const AString & a_Message) override; + virtual void SendChatSystem (const cCompositeChat & a_Message) override; + virtual void SendChatType (const AString & a_Message, eChatType type) override; + virtual void SendChatType (const cCompositeChat & a_Message, eChatType type) override; virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override; virtual void SendDestroyEntity (const cEntity & a_Entity) override; diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp index 477f2d71e..c89c745a4 100644 --- a/src/Protocol/ProtocolRecognizer.cpp +++ b/src/Protocol/ProtocolRecognizer.cpp @@ -158,6 +158,66 @@ void cProtocolRecognizer::SendChat(const cCompositeChat & a_Message) +void cProtocolRecognizer::SendChatAboveActionBar(const AString & a_Message) +{ + ASSERT(m_Protocol != nullptr); + m_Protocol->SendChatAboveActionBar(a_Message); +} + + + + + +void cProtocolRecognizer::SendChatAboveActionBar(const cCompositeChat & a_Message) +{ + ASSERT(m_Protocol != nullptr); + m_Protocol->SendChatAboveActionBar(a_Message); +} + + + + + +void cProtocolRecognizer::SendChatSystem(const AString & a_Message) +{ + ASSERT(m_Protocol != nullptr); + m_Protocol->SendChatSystem(a_Message); +} + + + + + +void cProtocolRecognizer::SendChatSystem(const cCompositeChat & a_Message) +{ + ASSERT(m_Protocol != nullptr); + m_Protocol->SendChatSystem(a_Message); +} + + + + + +void cProtocolRecognizer::SendChatType(const AString & a_Message, eChatType type) +{ + ASSERT(m_Protocol != nullptr); + m_Protocol->SendChatType(a_Message, type); +} + + + + + +void cProtocolRecognizer::SendChatType(const cCompositeChat & a_Message, eChatType type) +{ + ASSERT(m_Protocol != nullptr); + m_Protocol->SendChatType(a_Message, type); +} + + + + + void cProtocolRecognizer::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) { ASSERT(m_Protocol != nullptr); diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h index 956b5dcc0..29eddcbc9 100644 --- a/src/Protocol/ProtocolRecognizer.h +++ b/src/Protocol/ProtocolRecognizer.h @@ -55,6 +55,12 @@ public: virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; virtual void SendChat (const AString & a_Message) override; virtual void SendChat (const cCompositeChat & a_Message) override; + virtual void SendChatAboveActionBar (const AString & a_Message) override; + virtual void SendChatAboveActionBar (const cCompositeChat & a_Message) override; + virtual void SendChatSystem (const AString & a_Message) override; + virtual void SendChatSystem (const cCompositeChat & a_Message) override; + virtual void SendChatType (const AString & a_Message, eChatType type) override; + virtual void SendChatType (const cCompositeChat & a_Message, eChatType type) override; virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override; virtual void SendDestroyEntity (const cEntity & a_Entity) override; diff --git a/src/main.cpp b/src/main.cpp index d5c39cecd..152339e12 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -39,7 +39,7 @@ bool cRoot::m_RunAsService = false; #if defined(_WIN32) - SERVICE_STATUS_HANDLE g_StatusHandle = NULL; + SERVICE_STATUS_HANDLE g_StatusHandle = nullptr; HANDLE g_ServiceThread = INVALID_HANDLE_VALUE; #define SERVICE_NAME "MCServerService" #endif @@ -145,7 +145,7 @@ Its purpose is to create the crashdump using the dbghlp DLLs */ LONG WINAPI LastChanceExceptionFilter(__in struct _EXCEPTION_POINTERS * a_ExceptionInfo) { - char * newStack = &g_ExceptionStack[sizeof(g_ExceptionStack)]; + char * newStack = &g_ExceptionStack[sizeof(g_ExceptionStack) - 1]; char * oldStack; // Use the substitute stack: @@ -249,6 +249,7 @@ void universalMain(std::unique_ptr<cSettingsRepositoryInterface> overridesRepo) + #if defined(_WIN32) //////////////////////////////////////////////////////////////////////////////// // serviceWorkerThread: Keep the service alive @@ -266,6 +267,7 @@ DWORD WINAPI serviceWorkerThread(LPVOID lpParam) + //////////////////////////////////////////////////////////////////////////////// // serviceSetState: Set the internal status of the service @@ -319,14 +321,10 @@ void WINAPI serviceCtrlHandler(DWORD CtrlCode) void WINAPI serviceMain(DWORD argc, TCHAR *argv[]) { - #if defined(_DEBUG) && defined(DEBUG_SERVICE_STARTUP) - Sleep(10000); - #endif - char applicationFilename[MAX_PATH]; char applicationDirectory[MAX_PATH]; - GetModuleFileName(NULL, applicationFilename, sizeof(applicationFilename)); // This binary's file path. + GetModuleFileName(nullptr, applicationFilename, sizeof(applicationFilename)); // This binary's file path. // Strip off the filename, keep only the path: strncpy_s(applicationDirectory, sizeof(applicationDirectory), applicationFilename, (strrchr(applicationFilename, '\\') - applicationFilename)); @@ -337,8 +335,7 @@ void WINAPI serviceMain(DWORD argc, TCHAR *argv[]) SetCurrentDirectory(applicationDirectory); g_StatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, serviceCtrlHandler); - - if (g_StatusHandle == NULL) + if (g_StatusHandle == nullptr) { OutputDebugStringA("RegisterServiceCtrlHandler() failed\n"); serviceSetState(0, SERVICE_STOPPED, GetLastError()); @@ -347,8 +344,9 @@ void WINAPI serviceMain(DWORD argc, TCHAR *argv[]) serviceSetState(SERVICE_ACCEPT_STOP, SERVICE_RUNNING, 0); - g_ServiceThread = CreateThread(NULL, 0, serviceWorkerThread, NULL, 0, NULL); - if (g_ServiceThread == NULL) + DWORD ThreadID; + g_ServiceThread = CreateThread(nullptr, 0, serviceWorkerThread, nullptr, 0, &ThreadID); + if (g_ServiceThread == nullptr) { OutputDebugStringA("CreateThread() failed\n"); serviceSetState(0, SERVICE_STOPPED, GetLastError()); @@ -364,50 +362,39 @@ void WINAPI serviceMain(DWORD argc, TCHAR *argv[]) + + std::unique_ptr<cMemorySettingsRepository> parseArguments(int argc, char **argv) { try { + // Parse the comand line args: TCLAP::CmdLine cmd("MCServer"); - - TCLAP::ValueArg<int> slotsArg("s", "max-players", "Maximum number of slots for the server to use, overrides setting in setting.ini", false, -1, "number", cmd); - - TCLAP::MultiArg<int> portsArg("p", "port", "The port number the server should listen to", false, "port", cmd); - - TCLAP::SwitchArg commLogArg("", "log-comm", "Log server client communications to file", cmd); - - TCLAP::SwitchArg commLogInArg("", "log-comm-in", "Log inbound server client communications to file", cmd); - - TCLAP::SwitchArg commLogOutArg("", "log-comm-out", "Log outbound server client communications to file", cmd); - - TCLAP::SwitchArg noBufArg("", "no-output-buffering", "Disable output buffering", cmd); - - TCLAP::SwitchArg runAsServiceArg("d", "run-as-service", "Run as a service on Windows", cmd); - - cmd.ignoreUnmatched(true); - + TCLAP::ValueArg<int> slotsArg ("s", "max-players", "Maximum number of slots for the server to use, overrides setting in setting.ini", false, -1, "number", cmd); + TCLAP::MultiArg<int> portsArg ("p", "port", "The port number the server should listen to", false, "port", cmd); + TCLAP::SwitchArg commLogArg ("", "log-comm", "Log server client communications to file", cmd); + TCLAP::SwitchArg commLogInArg ("", "log-comm-in", "Log inbound server client communications to file", cmd); + TCLAP::SwitchArg commLogOutArg ("", "log-comm-out", "Log outbound server client communications to file", cmd); + TCLAP::SwitchArg crashDumpFull ("", "crash-dump-full", "Crashdumps created by the server will contain full server memory", cmd); + TCLAP::SwitchArg crashDumpGlobals("", "crash-dump-globals", "Crashdumps created by the server will contain the global variables' values", cmd); + TCLAP::SwitchArg noBufArg ("", "no-output-buffering", "Disable output buffering", cmd); + TCLAP::SwitchArg runAsServiceArg ("d", "run-as-service", "Run as a service on Windows", cmd); cmd.parse(argc, argv); + // Copy the parsed args' values into a settings repository: auto repo = cpp14::make_unique<cMemorySettingsRepository>(); - if (slotsArg.isSet()) { - int slots = slotsArg.getValue(); - repo->AddValue("Server", "MaxPlayers", static_cast<Int64>(slots)); - } - if (portsArg.isSet()) { - std::vector<int> ports = portsArg.getValue(); - for (auto port : ports) + for (auto port: portsArg.getValue()) { repo->AddValue("Server", "Port", static_cast<Int64>(port)); } } - if (commLogArg.getValue()) { g_ShouldLogCommIn = true; @@ -418,115 +405,111 @@ std::unique_ptr<cMemorySettingsRepository> parseArguments(int argc, char **argv) g_ShouldLogCommIn = commLogInArg.getValue(); g_ShouldLogCommOut = commLogOutArg.getValue(); } - if (noBufArg.getValue()) { setvbuf(stdout, nullptr, _IONBF, 0); } + repo->SetReadOnly(); + // Set the service flag directly to cRoot: if (runAsServiceArg.getValue()) { cRoot::m_RunAsService = true; } - repo->SetReadOnly(); + // Apply the CrashDump flags for platforms that support them: + #if defined(_WIN32) && !defined(_WIN64) && defined(_MSC_VER) // 32-bit Windows app compiled in MSVC + if (crashDumpGlobals.getValue()) + { + g_DumpFlags = static_cast<MINIDUMP_TYPE>(g_DumpFlags | MiniDumpWithDataSegs); + } + if (crashDumpFull.getValue()) + { + g_DumpFlags = static_cast<MINIDUMP_TYPE>(g_DumpFlags | MiniDumpWithFullMemory); + } + #endif // 32-bit Windows app compiled in MSVC return repo; } - catch (TCLAP::ArgException &e) + catch (const TCLAP::ArgException & exc) { - printf("error reading command line %s for arg %s", e.error().c_str(), e.argId().c_str()); + printf("Error reading command line %s for arg %s", exc.error().c_str(), exc.argId().c_str()); return cpp14::make_unique<cMemorySettingsRepository>(); } } + + + //////////////////////////////////////////////////////////////////////////////// // main: int main(int argc, char **argv) { - #if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER) - InitLeakFinder(); + InitLeakFinder(); #endif // Magic code to produce dump-files on Windows if the server crashes: - #if defined(_WIN32) && !defined(_WIN64) && defined(_MSC_VER) - HINSTANCE hDbgHelp = LoadLibrary("DBGHELP.DLL"); - g_WriteMiniDump = (pMiniDumpWriteDump)GetProcAddress(hDbgHelp, "MiniDumpWriteDump"); - if (g_WriteMiniDump != nullptr) - { - _snprintf_s(g_DumpFileName, ARRAYCOUNT(g_DumpFileName), _TRUNCATE, "crash_mcs_%x.dmp", GetCurrentProcessId()); - SetUnhandledExceptionFilter(LastChanceExceptionFilter); - - // Parse arguments for minidump flags: - for (int i = 0; i < argc; i++) + #if defined(_WIN32) && !defined(_WIN64) && defined(_MSC_VER) // 32-bit Windows app compiled in MSVC + HINSTANCE hDbgHelp = LoadLibrary("DBGHELP.DLL"); + g_WriteMiniDump = (pMiniDumpWriteDump)GetProcAddress(hDbgHelp, "MiniDumpWriteDump"); + if (g_WriteMiniDump != nullptr) { - if (_stricmp(argv[i], "/cdg") == 0) - { - // Add globals to the dump - g_DumpFlags = (MINIDUMP_TYPE)(g_DumpFlags | MiniDumpWithDataSegs); - } - else if (_stricmp(argv[i], "/cdf") == 0) - { - // Add full memory to the dump (HUUUGE file) - g_DumpFlags = (MINIDUMP_TYPE)(g_DumpFlags | MiniDumpWithFullMemory); - } - } // for i - argv[] - } - #endif // _WIN32 && !_WIN64 + _snprintf_s(g_DumpFileName, ARRAYCOUNT(g_DumpFileName), _TRUNCATE, "crash_mcs_%x.dmp", GetCurrentProcessId()); + SetUnhandledExceptionFilter(LastChanceExceptionFilter); + } + #endif // 32-bit Windows app compiled in MSVC // End of dump-file magic + #if defined(_DEBUG) && defined(_MSC_VER) - _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); + _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); - // _X: The simple built-in CRT leak finder - simply break when allocating the Nth block ({N} is listed in the leak output) - // Only useful when the leak is in the same sequence all the time - // _CrtSetBreakAlloc(85950); + // _X: The simple built-in CRT leak finder - simply break when allocating the Nth block ({N} is listed in the leak output) + // Only useful when the leak is in the same sequence all the time + // _CrtSetBreakAlloc(85950); #endif // _DEBUG && _MSC_VER #ifndef _DEBUG - std::signal(SIGSEGV, NonCtrlHandler); - std::signal(SIGTERM, NonCtrlHandler); - std::signal(SIGINT, NonCtrlHandler); - std::signal(SIGABRT, NonCtrlHandler); - #ifdef SIGABRT_COMPAT - std::signal(SIGABRT_COMPAT, NonCtrlHandler); - #endif // SIGABRT_COMPAT + std::signal(SIGSEGV, NonCtrlHandler); + std::signal(SIGTERM, NonCtrlHandler); + std::signal(SIGINT, NonCtrlHandler); + std::signal(SIGABRT, NonCtrlHandler); + #ifdef SIGABRT_COMPAT + std::signal(SIGABRT_COMPAT, NonCtrlHandler); + #endif // SIGABRT_COMPAT #endif - // DEBUG: test the dumpfile creation: - // *((int *)0) = 0; - auto argsRepo = parseArguments(argc, argv); #if defined(_WIN32) - // Attempt to run as a service - if (cRoot::m_RunAsService) - { - SERVICE_TABLE_ENTRY ServiceTable[] = + // Attempt to run as a service + if (cRoot::m_RunAsService) { - { SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)serviceMain }, - { NULL, NULL } - }; + SERVICE_TABLE_ENTRY ServiceTable[] = + { + { SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)serviceMain }, + { nullptr, nullptr } + }; - if (StartServiceCtrlDispatcher(ServiceTable) == FALSE) - { - LOGERROR("Attempted, but failed, service startup."); - return GetLastError(); + if (StartServiceCtrlDispatcher(ServiceTable) == FALSE) + { + LOGERROR("Attempted, but failed, service startup."); + return GetLastError(); + } } - } - else + else #endif { - // Not running as a service, do normal startup + // Not running as a Windows service, do normal startup universalMain(std::move(argsRepo)); } #if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER) - DeinitLeakFinder(); + DeinitLeakFinder(); #endif return EXIT_SUCCESS; |