aboutsummaryrefslogtreecommitdiff
path: root/NorthstarDedicatedTest
diff options
context:
space:
mode:
Diffstat (limited to 'NorthstarDedicatedTest')
-rw-r--r--NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj6
-rw-r--r--NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters7
-rw-r--r--NorthstarDedicatedTest/dllmain.cpp2
-rw-r--r--NorthstarDedicatedTest/logging.cpp160
-rw-r--r--NorthstarDedicatedTest/masterserver.cpp69
-rw-r--r--NorthstarDedicatedTest/miscserverfixes.cpp13
-rw-r--r--NorthstarDedicatedTest/miscserverfixes.h1
-rw-r--r--NorthstarDedicatedTest/playlist.cpp51
-rw-r--r--NorthstarDedicatedTest/serverauthentication.cpp2
9 files changed, 296 insertions, 15 deletions
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
index 14fb634f..c324d60f 100644
--- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
+++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
@@ -136,7 +136,7 @@
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
- <AdditionalDependencies>$(ProjectDir)include\MinHook.x64.lib;$(ProjectDir)include\libcrypto_static.lib;$(ProjectDir)include\libssl_static.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(ProjectDir)include\MinHook.x64.lib;$(ProjectDir)include\libcrypto_static.lib;$(ProjectDir)include\libssl_static.lib;dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ForceSymbolReferences>
</ForceSymbolReferences>
</Link>
@@ -164,7 +164,7 @@
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
- <AdditionalDependencies>$(ProjectDir)include\MinHook.x64.lib;$(ProjectDir)include\libcrypto_static.lib;$(ProjectDir)include\libssl_static.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(ProjectDir)include\MinHook.x64.lib;$(ProjectDir)include\libcrypto_static.lib;$(ProjectDir)include\libssl_static.lib;dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ForceSymbolReferences>
</ForceSymbolReferences>
</Link>
@@ -580,6 +580,7 @@
<ClInclude Include="memalloc.h" />
<ClInclude Include="miscclientfixes.h" />
<ClInclude Include="misccommands.h" />
+ <ClInclude Include="miscserverfixes.h" />
<ClInclude Include="modlocalisation.h" />
<ClInclude Include="modmanager.h" />
<ClInclude Include="pch.h" />
@@ -616,6 +617,7 @@
<ClCompile Include="memalloc.cpp" />
<ClCompile Include="miscclientfixes.cpp" />
<ClCompile Include="misccommands.cpp" />
+ <ClCompile Include="miscserverfixes.cpp" />
<ClCompile Include="modlocalisation.cpp" />
<ClCompile Include="logging.cpp" />
<ClCompile Include="masterserver.cpp" />
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
index a3c17054..5b287ad1 100644
--- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
+++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
@@ -1386,8 +1386,8 @@
<ClInclude Include="include\internal\unicode.h">
<Filter>Header Files\include\openssl\internal</Filter>
</ClInclude>
- <ClInclude Include="maxplayers.h">
- <Filter>Header Files\Shared</Filter>
+ <ClInclude Include="miscserverfixes.h">
+ <Filter>Header Files\Server</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
@@ -1496,9 +1496,6 @@
<ClCompile Include="miscclientfixes.cpp">
<Filter>Source Files\Client</Filter>
</ClCompile>
- <ClCompile Include="maxplayers.cpp">
- <Filter>Source Files\Shared</Filter>
- </ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="include\spdlog\fmt\bundled\LICENSE.rst">
diff --git a/NorthstarDedicatedTest/dllmain.cpp b/NorthstarDedicatedTest/dllmain.cpp
index c8f29550..1eafef7f 100644
--- a/NorthstarDedicatedTest/dllmain.cpp
+++ b/NorthstarDedicatedTest/dllmain.cpp
@@ -24,6 +24,7 @@
#include "scriptbrowserhooks.h"
#include "scriptmainmenupromos.h"
#include "miscclientfixes.h"
+#include "miscserverfixes.h"
#include "memalloc.h"
#include "maxplayers.h"
@@ -111,6 +112,7 @@ void InitialiseNorthstar()
AddDllLoadCallback("engine.dll", InitialiseServerAuthentication);
AddDllLoadCallback("engine.dll", InitialiseSharedMasterServer);
AddDllLoadCallback("server.dll", InitialiseMiscServerScriptCommand);
+ AddDllLoadCallback("server.dll", InitialiseMiscServerFixes);
AddDllLoadCallback("engine.dll", InitialisePlaylistHooks);
diff --git a/NorthstarDedicatedTest/logging.cpp b/NorthstarDedicatedTest/logging.cpp
index 55627fb2..09ae6961 100644
--- a/NorthstarDedicatedTest/logging.cpp
+++ b/NorthstarDedicatedTest/logging.cpp
@@ -4,11 +4,171 @@
#include "spdlog/sinks/basic_file_sink.h"
#include "hookutils.h"
#include "gameutils.h"
+#include "dedicated.h"
#include <iomanip>
#include <sstream>
+#include <Psapi.h>
+#include <minidumpapiset.h>
+
+long __stdcall ExceptionFilter(EXCEPTION_POINTERS* exceptionInfo)
+{
+ static bool logged = false;
+ if (logged)
+ return EXCEPTION_CONTINUE_SEARCH;
+
+ if (!IsDebuggerPresent())
+ {
+ const DWORD exceptionCode = exceptionInfo->ExceptionRecord->ExceptionCode;
+ if (exceptionCode != EXCEPTION_ACCESS_VIOLATION && exceptionCode != EXCEPTION_ARRAY_BOUNDS_EXCEEDED &&
+ exceptionCode != EXCEPTION_DATATYPE_MISALIGNMENT && exceptionCode != EXCEPTION_FLT_DENORMAL_OPERAND &&
+ exceptionCode != EXCEPTION_FLT_DIVIDE_BY_ZERO && exceptionCode != EXCEPTION_FLT_INEXACT_RESULT &&
+ exceptionCode != EXCEPTION_FLT_INVALID_OPERATION && exceptionCode != EXCEPTION_FLT_OVERFLOW &&
+ exceptionCode != EXCEPTION_FLT_STACK_CHECK && exceptionCode != EXCEPTION_FLT_UNDERFLOW &&
+ exceptionCode != EXCEPTION_ILLEGAL_INSTRUCTION && exceptionCode != EXCEPTION_IN_PAGE_ERROR &&
+ exceptionCode != EXCEPTION_INT_DIVIDE_BY_ZERO && exceptionCode != EXCEPTION_INT_OVERFLOW &&
+ exceptionCode != EXCEPTION_INVALID_DISPOSITION && exceptionCode != EXCEPTION_NONCONTINUABLE_EXCEPTION &&
+ exceptionCode != EXCEPTION_PRIV_INSTRUCTION && exceptionCode != EXCEPTION_STACK_OVERFLOW)
+ return EXCEPTION_CONTINUE_SEARCH;
+
+ std::stringstream exceptionCause;
+ switch (exceptionCode)
+ {
+ case EXCEPTION_ACCESS_VIOLATION:
+ case EXCEPTION_IN_PAGE_ERROR:
+ {
+ exceptionCause << "Cause: Access Violation" << std::endl;
+
+ auto exceptionInfo0 = exceptionInfo->ExceptionRecord->ExceptionInformation[0];
+ auto exceptionInfo1 = exceptionInfo->ExceptionRecord->ExceptionInformation[1];
+
+ if (!exceptionInfo0)
+ exceptionCause << "Attempted to read from: 0x" << std::setw(8) << std::setfill('0') << std::hex << exceptionInfo1;
+ else if (exceptionInfo0 == 1)
+ exceptionCause << "Attempted to write to: 0x" << std::setw(8) << std::setfill('0') << std::hex << exceptionInfo1;
+ else if (exceptionInfo0 == 8)
+ exceptionCause << "Data Execution Prevention (DEP) at: 0x" << std::setw(8) << std::setfill('0') << std::hex << exceptionInfo1;
+ else
+ exceptionCause << "Unknown access violation at: 0x" << std::setw(8) << std::setfill('0') << std::hex << exceptionInfo1;
+
+ break;
+ }
+ case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+ exceptionCause << "Cause: Array bounds exceeded";
+ break;
+ case EXCEPTION_DATATYPE_MISALIGNMENT:
+ exceptionCause << "Cause: Datatype misalignment";
+ break;
+ case EXCEPTION_FLT_DENORMAL_OPERAND:
+ exceptionCause << "Cause: Denormal operand";
+ break;
+ case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+ case EXCEPTION_INT_DIVIDE_BY_ZERO:
+ exceptionCause << "Cause: Divide by zero";
+ break;
+ case EXCEPTION_FLT_INEXACT_RESULT:
+ exceptionCause << "Cause: Inexact result";
+ break;
+ case EXCEPTION_FLT_INVALID_OPERATION:
+ exceptionCause << "Cause: invalid operation";
+ break;
+ case EXCEPTION_FLT_OVERFLOW:
+ case EXCEPTION_INT_OVERFLOW:
+ exceptionCause << "Cause: Numeric overflow";
+ break;
+ case EXCEPTION_FLT_UNDERFLOW:
+ exceptionCause << "Cause: Numeric underflow";
+ break;
+ case EXCEPTION_FLT_STACK_CHECK:
+ exceptionCause << "Cause: Stack check";
+ break;
+ case EXCEPTION_ILLEGAL_INSTRUCTION:
+ exceptionCause << "Cause: Illegal instruction";
+ break;
+ case EXCEPTION_INVALID_DISPOSITION:
+ exceptionCause << "Cause: Invalid disposition";
+ break;
+ case EXCEPTION_NONCONTINUABLE_EXCEPTION:
+ exceptionCause << "Cause: Noncontinuable exception";
+ break;
+ case EXCEPTION_PRIV_INSTRUCTION:
+ exceptionCause << "Cause: Priv instruction";
+ break;
+ case EXCEPTION_STACK_OVERFLOW:
+ exceptionCause << "Cause: Stack overflow";
+ break;
+ default:
+ exceptionCause << "Cause: Unknown";
+ break;
+ }
+
+ void* exceptionAddress = exceptionInfo->ExceptionRecord->ExceptionAddress;
+
+ HMODULE crashedModuleHandle;
+ GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, static_cast<LPCSTR>(exceptionAddress), &crashedModuleHandle);
+
+ MODULEINFO crashedModuleInfo;
+ GetModuleInformation(GetCurrentProcess(), crashedModuleHandle, &crashedModuleInfo, sizeof(crashedModuleInfo));
+
+ char crashedModuleFullName[MAX_PATH];
+ GetModuleFileNameExA(GetCurrentProcess(), crashedModuleHandle, crashedModuleFullName, MAX_PATH);
+ char* crashedModuleName = strrchr(crashedModuleFullName, '\\') + 1;
+
+ DWORD crashedModuleOffset = ((DWORD)exceptionAddress) - ((DWORD)crashedModuleInfo.lpBaseOfDll);
+ CONTEXT* exceptionContext = exceptionInfo->ContextRecord;
+
+ spdlog::error("Northstar has crashed! a minidump has been written and exception info is available below:");
+ spdlog::error(exceptionCause.str());
+ spdlog::error("Address: {} + 0x{0:x}", crashedModuleName, crashedModuleOffset);
+ spdlog::error("RAX: 0x{0:x}", exceptionContext->Rax);
+ spdlog::error("RBX: 0x{0:x}", exceptionContext->Rbx);
+ spdlog::error("RCX: 0x{0:x}", exceptionContext->Rcx);
+ spdlog::error("RDX: 0x{0:x}", exceptionContext->Rdx);
+ spdlog::error("RSI: 0x{0:x}", exceptionContext->Rsi);
+ spdlog::error("RDI: 0x{0:x}", exceptionContext->Rdi);
+ spdlog::error("RBP: 0x{0:x}", exceptionContext->Rbp);
+ spdlog::error("RSP: 0x{0:x}", exceptionContext->Rsp);
+ spdlog::error("R8: 0x{0:x}", exceptionContext->R8);
+ spdlog::error("R9: 0x{0:x}", exceptionContext->R9);
+ spdlog::error("R10: 0x{0:x}", exceptionContext->R10);
+ spdlog::error("R11: 0x{0:x}", exceptionContext->R11);
+ spdlog::error("R12: 0x{0:x}", exceptionContext->R12);
+ spdlog::error("R13: 0x{0:x}", exceptionContext->R13);
+ spdlog::error("R14: 0x{0:x}", exceptionContext->R14);
+ spdlog::error("R15: 0x{0:x}", exceptionContext->R15);
+
+ time_t time = std::time(nullptr);
+ tm currentTime = *std::localtime(&time);
+ std::stringstream stream;
+ stream << std::put_time(&currentTime, "R2Northstar/logs/nsdump%d-%m-%Y %H-%M-%S.dmp");
+
+ auto hMinidumpFile = CreateFileA(stream.str().c_str(), GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+ if (hMinidumpFile)
+ {
+ MINIDUMP_EXCEPTION_INFORMATION dumpExceptionInfo;
+ dumpExceptionInfo.ThreadId = GetCurrentThreadId();
+ dumpExceptionInfo.ExceptionPointers = exceptionInfo;
+ dumpExceptionInfo.ClientPointers = false;
+
+ MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hMinidumpFile, MINIDUMP_TYPE(MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory), &dumpExceptionInfo, nullptr, nullptr);
+ CloseHandle(hMinidumpFile);
+ }
+ else
+ spdlog::error("Failed to write minidump file {}!", stream.str());
+
+ if (!IsDedicated())
+ MessageBoxA(0, "Northstar has crashed! A crash log and dump can be found in R2Northstar/logs", "Northstar has crashed!", MB_ICONERROR | MB_OK);
+
+ }
+
+ logged = true;
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
void InitialiseLogging()
{
+ AddVectoredExceptionHandler(TRUE, ExceptionFilter);
+
AllocConsole();
freopen("CONOUT$", "w", stdout);
diff --git a/NorthstarDedicatedTest/masterserver.cpp b/NorthstarDedicatedTest/masterserver.cpp
index fa918c5c..706f60ec 100644
--- a/NorthstarDedicatedTest/masterserver.cpp
+++ b/NorthstarDedicatedTest/masterserver.cpp
@@ -35,6 +35,39 @@ CHostState__State_ChangeLevelSPType CHostState__State_ChangeLevelSP;
typedef void(*CHostState__State_GameShutdownType)(CHostState* hostState);
CHostState__State_GameShutdownType CHostState__State_GameShutdown;
+const char* HttplibErrorToString(httplib::Error error)
+{
+ switch (error)
+ {
+ case httplib::Error::Success:
+ return "httplib::Error::Success";
+ case httplib::Error::Unknown:
+ return "httplib::Error::Unknown";
+ case httplib::Error::Connection:
+ return "httplib::Error::Connection";
+ case httplib::Error::BindIPAddress:
+ return "httplib::Error::BindIPAddress";
+ case httplib::Error::Read:
+ return "httplib::Error::Read";
+ case httplib::Error::Write:
+ return "httplib::Error::Write";
+ case httplib::Error::ExceedRedirectCount:
+ return "httplib::Error::ExceedRedirectCount";
+ case httplib::Error::Canceled:
+ return "httplib::Error::Canceled";
+ case httplib::Error::SSLConnection:
+ return "httplib::Error::SSLConnection";
+ case httplib::Error::SSLLoadingCerts:
+ return "httplib::Error::SSLLoadingCerts";
+ case httplib::Error::SSLServerVerification:
+ return "httplib::Error::SSLServerVerification";
+ case httplib::Error::UnsupportedMultipartBoundaryChars:
+ return "httplib::Error::UnsupportedMultipartBoundaryChars";
+ }
+
+ return "";
+}
+
RemoteServerInfo::RemoteServerInfo(const char* newId, const char* newName, const char* newDescription, const char* newMap, const char* newPlaylist, int newPlayerCount, int newMaxPlayers, bool newRequiresPassword)
{
// passworded servers don't have public ips
@@ -80,6 +113,8 @@ void MasterServerManager::AuthenticateOriginWithMasterServer(char* uid, char* or
{
httplib::Client http(Cvar_ns_masterserver_hostname->m_pszString);
http.set_connection_timeout(25);
+ http.set_read_timeout(25);
+ http.set_write_timeout(25);
spdlog::info("Trying to authenticate with northstar masterserver for user {}", uidStr);
@@ -113,7 +148,7 @@ void MasterServerManager::AuthenticateOriginWithMasterServer(char* uid, char* or
}
else
{
- spdlog::error("Failed performing northstar origin auth: error {}", result.error());
+ spdlog::error("Failed performing northstar origin auth: error {}", HttplibErrorToString(result.error()));
m_successfullyConnected = false;
}
@@ -143,6 +178,8 @@ void MasterServerManager::RequestServerList()
httplib::Client http(Cvar_ns_masterserver_hostname->m_pszString);
http.set_connection_timeout(25);
+ http.set_read_timeout(25);
+ http.set_write_timeout(25);
spdlog::info("Requesting server list from {}", Cvar_ns_masterserver_hostname->m_pszString);
@@ -248,7 +285,7 @@ void MasterServerManager::RequestServerList()
}
else
{
- spdlog::error("Failed requesting servers: error {}", result.error());
+ spdlog::error("Failed requesting servers: error {}", HttplibErrorToString(result.error()));
m_successfullyConnected = false;
}
@@ -272,6 +309,8 @@ void MasterServerManager::RequestMainMenuPromos()
httplib::Client http(Cvar_ns_masterserver_hostname->m_pszString);
http.set_connection_timeout(25);
+ http.set_read_timeout(25);
+ http.set_write_timeout(25);
if (auto result = http.Get("/client/mainmenupromos"))
{
@@ -345,7 +384,7 @@ void MasterServerManager::RequestMainMenuPromos()
}
else
{
- spdlog::error("Failed requesting main menu promos: error {}", result.error());
+ spdlog::error("Failed requesting main menu promos: error {}", HttplibErrorToString(result.error()));
m_successfullyConnected = false;
}
@@ -371,6 +410,8 @@ void MasterServerManager::AuthenticateWithOwnServer(char* uid, char* playerToken
{
httplib::Client http(Cvar_ns_masterserver_hostname->m_pszString);
http.set_connection_timeout(25);
+ http.set_read_timeout(25);
+ http.set_write_timeout(25);
if (auto result = http.Post(fmt::format("/client/auth_with_self?id={}&playerToken={}", uid, playerToken).c_str()))
{
@@ -440,7 +481,7 @@ void MasterServerManager::AuthenticateWithOwnServer(char* uid, char* playerToken
}
else
{
- spdlog::error("Failed authenticating with own server: error {}", result.error());
+ spdlog::error("Failed authenticating with own server: error {}", HttplibErrorToString(result.error()));
m_successfullyConnected = false;
m_successfullyAuthenticatedWithGameServer = false;
m_scriptAuthenticatingWithGameServer = false;
@@ -479,6 +520,8 @@ void MasterServerManager::AuthenticateWithServer(char* uid, char* playerToken, c
httplib::Client http(Cvar_ns_masterserver_hostname->m_pszString);
http.set_connection_timeout(25);
+ http.set_read_timeout(25);
+ http.set_write_timeout(25);
spdlog::info("Attempting authentication with server of id \"{}\"", serverId);
@@ -531,7 +574,7 @@ void MasterServerManager::AuthenticateWithServer(char* uid, char* playerToken, c
}
else
{
- spdlog::error("Failed authenticating with server: error {}", result.error());
+ spdlog::error("Failed authenticating with server: error {}", HttplibErrorToString(result.error()));
m_successfullyConnected = false;
m_successfullyAuthenticatedWithGameServer = false;
m_scriptAuthenticatingWithGameServer = false;
@@ -561,6 +604,8 @@ void MasterServerManager::AddSelfToServerList(int port, int authPort, char* name
std::thread requestThread([this, port, authPort, name, description, map, playlist, maxPlayers, password] {
httplib::Client http(Cvar_ns_masterserver_hostname->m_pszString);
http.set_connection_timeout(25);
+ http.set_read_timeout(25);
+ http.set_write_timeout(25);
m_ownServerId[0] = 0;
@@ -647,6 +692,8 @@ void MasterServerManager::AddSelfToServerList(int port, int authPort, char* name
std::thread heartbeatThread([this] {
httplib::Client http(Cvar_ns_masterserver_hostname->m_pszString);
http.set_connection_timeout(25);
+ http.set_read_timeout(25);
+ http.set_write_timeout(25);
while (*m_ownServerId)
{
@@ -659,7 +706,7 @@ void MasterServerManager::AddSelfToServerList(int port, int authPort, char* name
}
else
{
- spdlog::error("Failed authenticating with server: error {}", result.error());
+ spdlog::error("Failed adding self to server list: error {}", HttplibErrorToString(result.error()));
m_successfullyConnected = false;
}
});
@@ -676,6 +723,8 @@ void MasterServerManager::UpdateServerMapAndPlaylist(char* map, char* playlist,
std::thread requestThread([this, map, playlist, maxPlayers] {
httplib::Client http(Cvar_ns_masterserver_hostname->m_pszString);
http.set_connection_timeout(25);
+ http.set_read_timeout(25);
+ http.set_write_timeout(25);
// we dont process this at all atm, maybe do later, but atm not necessary
if (auto result = http.Post(fmt::format("/server/update_values?id={}&map={}&playlist={}&maxPlayers={}", m_ownServerId, map, playlist, maxPlayers).c_str()))
@@ -700,6 +749,8 @@ void MasterServerManager::UpdateServerPlayerCount(int playerCount)
std::thread requestThread([this, playerCount] {
httplib::Client http(Cvar_ns_masterserver_hostname->m_pszString);
http.set_connection_timeout(25);
+ http.set_read_timeout(25);
+ http.set_write_timeout(25);
// we dont process this at all atm, maybe do later, but atm not necessary
if (auto result = http.Post(fmt::format("/server/update_values?id={}&playerCount={}", m_ownServerId, playerCount).c_str()))
@@ -728,7 +779,9 @@ void MasterServerManager::WritePlayerPersistentData(char* playerId, char* pdata,
std::string playerIdTemp(playerId);
std::thread requestThread([this, playerIdTemp, pdata, pdataSize] {
httplib::Client http(Cvar_ns_masterserver_hostname->m_pszString);
- http.set_connection_timeout(25);
+ http.set_connection_timeout(25);
+ http.set_read_timeout(25);
+ http.set_write_timeout(25);
httplib::MultipartFormDataItems requestItems = {
{ "pdata", std::string(pdata, pdataSize), "file.pdata", "application/octet-stream"}
@@ -759,6 +812,8 @@ void MasterServerManager::RemoveSelfFromServerList()
std::thread requestThread([this] {
httplib::Client http(Cvar_ns_masterserver_hostname->m_pszString);
http.set_connection_timeout(25);
+ http.set_read_timeout(25);
+ http.set_write_timeout(25);
// we dont process this at all atm, maybe do later, but atm not necessary
if (auto result = http.Delete(fmt::format("/server/remove_server?id={}", m_ownServerId).c_str()))
diff --git a/NorthstarDedicatedTest/miscserverfixes.cpp b/NorthstarDedicatedTest/miscserverfixes.cpp
new file mode 100644
index 00000000..2007a30c
--- /dev/null
+++ b/NorthstarDedicatedTest/miscserverfixes.cpp
@@ -0,0 +1,13 @@
+#include "pch.h"
+#include "miscserverfixes.h"
+#include "hookutils.h"
+
+void InitialiseMiscServerFixes(HMODULE baseAddress)
+{
+ // ret at the start of the concommand GenerateObjFile as it can crash servers
+ {
+ void* ptr = (char*)baseAddress + 0x38D920;
+ TempReadWrite rw(ptr);
+ *((char*)ptr) = (char)0xC3;
+ }
+} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/miscserverfixes.h b/NorthstarDedicatedTest/miscserverfixes.h
new file mode 100644
index 00000000..d1c05a6b
--- /dev/null
+++ b/NorthstarDedicatedTest/miscserverfixes.h
@@ -0,0 +1 @@
+void InitialiseMiscServerFixes(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/playlist.cpp b/NorthstarDedicatedTest/playlist.cpp
index b853a40a..47fb109c 100644
--- a/NorthstarDedicatedTest/playlist.cpp
+++ b/NorthstarDedicatedTest/playlist.cpp
@@ -5,11 +5,17 @@
#include "gameutils.h"
#include "hookutils.h"
#include "dedicated.h"
+#include "squirrel.h"
typedef char(*Onclc_SetPlaylistVarOverrideType)(void* a1, void* a2);
Onclc_SetPlaylistVarOverrideType Onclc_SetPlaylistVarOverride;
+
+typedef int(*GetCurrentGamemodeMaxPlayersType)();
+GetCurrentGamemodeMaxPlayersType GetCurrentGamemodeMaxPlayers;
+
// function type defined in gameutils.h
SetPlaylistVarOverrideType SetPlaylistVarOverrideOriginal;
+GetCurrentPlaylistVarType GetCurrentPlaylistVarOriginal;
ConVar* Cvar_ns_use_clc_SetPlaylistVarOverride;
@@ -21,6 +27,15 @@ void SetPlaylistCommand(const CCommand& args)
SetCurrentPlaylist(args.Arg(1));
}
+void SetPlaylistVarOverrideCommand(const CCommand& args)
+{
+ if (args.ArgC() < 3)
+ return;
+
+ for (int i = 1; i < args.ArgC(); i += 2)
+ SetPlaylistVarOverride(args.Arg(i), args.Arg(i + 1));
+}
+
char Onclc_SetPlaylistVarOverrideHook(void* a1, void* a2)
{
// the private_match playlist is the only situation where there should be any legitimate sending of this netmessage
@@ -39,9 +54,30 @@ void SetPlaylistVarOverrideHook(const char* varName, const char* value)
SetPlaylistVarOverrideOriginal(varName, value);
}
+char* GetCurrentPlaylistVarHook(const char* varName, bool useOverrides)
+{
+ if (!useOverrides && !strcmp(varName, "max_players"))
+ useOverrides = true;
+
+ return GetCurrentPlaylistVarOriginal(varName, useOverrides);
+}
+
+int GetCurrentGamemodeMaxPlayersHook()
+{
+ char* maxPlayersStr = GetCurrentPlaylistVar("max_players", 0);
+ if (!maxPlayersStr)
+ return GetCurrentGamemodeMaxPlayers();
+
+ int maxPlayers = atoi(maxPlayersStr);
+ spdlog::info("Overwrote max_players to {}", maxPlayers);
+
+ return maxPlayers;
+}
+
void InitialisePlaylistHooks(HMODULE baseAddress)
{
RegisterConCommand("setplaylist", SetPlaylistCommand, "Sets the current playlist", FCVAR_NONE);
+ RegisterConCommand("setplaylistvaroverrides", SetPlaylistVarOverrideCommand, "sets a playlist var override", FCVAR_NONE);
// note: clc_SetPlaylistVarOverride is pretty insecure, since it allows for entirely arbitrary playlist var overrides to be sent to the server
// this is somewhat restricted on custom servers to prevent it being done outside of private matches, but ideally it should be disabled altogether, since the custom menus won't use it anyway
// this should only really be accepted if you want vanilla client compatibility
@@ -50,6 +86,8 @@ void InitialisePlaylistHooks(HMODULE baseAddress)
HookEnabler hook;
ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x222180, &Onclc_SetPlaylistVarOverrideHook, reinterpret_cast<LPVOID*>(&Onclc_SetPlaylistVarOverride));
ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x18ED00, &SetPlaylistVarOverrideHook, reinterpret_cast<LPVOID*>(&SetPlaylistVarOverrideOriginal));
+ ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x18C680, &GetCurrentPlaylistVarHook, reinterpret_cast<LPVOID*>(&GetCurrentPlaylistVarOriginal));
+ ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x18C430, &GetCurrentGamemodeMaxPlayersHook, reinterpret_cast<LPVOID*>(&GetCurrentGamemodeMaxPlayers));
// patch to prevent clc_SetPlaylistVarOverride from being able to crash servers if we reach max overrides due to a call to Error (why is this possible respawn, wtf)
// todo: add a warning for this
@@ -58,4 +96,17 @@ void InitialisePlaylistHooks(HMODULE baseAddress)
TempReadWrite rw(ptr);
*((char*)ptr) = 0xC3; // jmp => ret
}
+
+ if (IsDedicated())
+ {
+ // patch to allow setplaylistvaroverride to be called before map init on dedicated
+ void* ptr = (char*)baseAddress + 0x18ED17;
+ TempReadWrite rw(ptr);
+ *((char*)ptr) = (char)0x90;
+ *((char*)ptr + 1) = (char)0x90;
+ *((char*)ptr + 2) = (char)0x90;
+ *((char*)ptr + 3) = (char)0x90;
+ *((char*)ptr + 4) = (char)0x90;
+ *((char*)ptr + 5) = (char)0x90;
+ }
} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/serverauthentication.cpp b/NorthstarDedicatedTest/serverauthentication.cpp
index 21be404c..5351dfdc 100644
--- a/NorthstarDedicatedTest/serverauthentication.cpp
+++ b/NorthstarDedicatedTest/serverauthentication.cpp
@@ -437,7 +437,7 @@ void InitialiseServerAuthentication(HMODULE baseAddress)
Cvar_net_chan_limit_mode = RegisterConVar("net_chan_limit_mode", "0", FCVAR_GAMEDLL, "The mode for netchan processing limits: 0 = none, 1 = kick, 2 = log");
Cvar_net_chan_limit_msec_per_sec = RegisterConVar("net_chan_limit_msec_per_sec", "0", FCVAR_GAMEDLL, "Netchannel processing is limited to so many milliseconds, abort connection if exceeding budget");
Cvar_ns_player_auth_port = RegisterConVar("ns_player_auth_port", "8081", FCVAR_GAMEDLL, "");
- Cvar_sv_querylimit_per_sec = RegisterConVar("sv_querylimit_per_sec", "10", FCVAR_GAMEDLL, "");
+ Cvar_sv_querylimit_per_sec = RegisterConVar("sv_querylimit_per_sec", "15", FCVAR_GAMEDLL, "");
HookEnabler hook;
ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x114430, &CBaseServer__ConnectClientHook, reinterpret_cast<LPVOID*>(&CBaseServer__ConnectClient));