Skip to content

Commit

Permalink
add NorthstarCN_Updater intergration, fix logging on pdata writes
Browse files Browse the repository at this point in the history
Co-authored-by: ston <[email protected]>
  • Loading branch information
wolf109909 and st0nie committed Nov 12, 2024
1 parent 0027c6b commit 1a9ca77
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 56 deletions.
31 changes: 19 additions & 12 deletions primedev/dllmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,23 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
return TRUE;
}

void CheckWindowsVersion()
{
if(strstr(GetCommandLineA(), "-no_windows_version_check") != NULL)
return;

if (WindowsVersionSupportsUtf8() && !IsUtf8BetaOptionEnabled()) {
if(strstr(GetCommandLineA(), "-dedicated") == NULL)
{
MessageBoxW(nullptr,
L"由于运行库与旧版Windows存在兼容性问题,北极星CN 1.17只能保证在Windows 10 1903以上的版本在系统默认设置的情况下正常运行,若是Windows10 1903以下的系统版本,需要在控制面板-时钟和区域-区域-管理-更改系统区域设置-勾选使用Unicode UTF-8。如果在旧系统版本中不启用UTF-8,北极星CN将无法正确处理Windows中文字符。\n这可能会导致以下问题:\n(1) 带有任何中文路径的Mod无法正常工作或导致游戏崩溃\n(2) 游戏安装路径中存在中文字符时崩溃。\n(3) 系统用户名或用户目录名称存在中文字符时游戏崩溃\n若您的系统版本无Unicode UTF-8 选项,或是启用此选项后其他应用程序或目录出现乱码问题,可以通过以下方法解决:\n(1) 升级操作系统版本至Windows 10 1903或更高版本。\n(2) 手动重命名系统用户名和“文档”目录、游戏安装目录、Mods目录中所有含中文名称的文件夹(如模型和音频替换Mod等)以避免北极星CN出现故障。",
L"警告: 您的操作系统可能不受支持",
MB_OK | MB_ICONWARNING);

}
std::wcout << L"警告:由于运行库与旧版Windows存在兼容性问题,北极星CN 1.17只能保证在Windows 10 1903以上的版本在系统默认设置的情况下正常运行,若是Windows10 1903以下的系统版本,需要在控制面板-时钟和区域-区域-管理-更改系统区域设置-勾选使用Unicode UTF-8。如果在旧系统版本中不启用UTF-8,北极星CN将无法正确处理Windows中文字符。\n这可能会导致以下问题:\n(1) 带有任何中文路径的Mod无法正常工作或导致游戏崩溃\n(2) 游戏安装路径中存在中文字符时崩溃。\n(3) 系统用户名或用户目录名称存在中文字符时游戏崩溃\n若您的系统版本无Unicode UTF-8 选项,或是启用此选项后其他应用程序或目录出现乱码问题,可以通过以下方法解决:\n(1) 升级操作系统版本至Windows 10 1903或更高版本。\n(2) 手动重命名系统用户名和“文档”目录、游戏安装目录、Mods目录中所有含中文名称的文件夹(如模型和音频替换Mod等)以避免北极星CN出现故障。" << std::endl;
}
}

extern "C" bool InitialiseNorthstar()
{
Expand All @@ -81,26 +98,16 @@ extern "C" bool InitialiseNorthstar()

bInitialised = true;


CheckWindowsVersion();

InitialiseNorthstarPrefix();

// initialise the console if needed (-northstar needs this)
InitialiseConsole();
// initialise logging before most other things so that they can use spdlog and it have the proper formatting
InitialiseLogging();


if (WindowsVersionSupportsUtf8() && !IsUtf8BetaOptionEnabled()) {
if(strstr(GetCommandLineA(), "-dedicated") == NULL)
{
MessageBoxW(nullptr,
L"由于运行库与旧版Windows存在兼容性问题,北极星CN 1.17只能保证在Windows 10 1903以上的版本在系统默认设置的情况下正常运行,若是Windows10 1903以下的系统版本,需要在控制面板-时钟和区域-区域-管理-更改系统区域设置-勾选使用Unicode UTF-8。如果在旧系统版本中不启用UTF-8,北极星CN将无法正确处理Windows中文字符。\n这可能会导致以下问题:\n(1) 带有任何中文路径的Mod无法正常工作或导致游戏崩溃\n(2) 游戏安装路径中存在中文字符时崩溃。\n(3) 系统用户名或用户目录名称存在中文字符时游戏崩溃\n若您的系统版本无Unicode UTF-8 选项,或是启用此选项后其他应用程序或目录出现乱码问题,可以通过以下方法解决:\n(1) 升级操作系统版本至Windows 10 1903或更高版本。\n(2) 手动重命名系统用户名和“文档”目录、游戏安装目录、Mods目录中所有含中文名称的文件夹(如模型和音频替换Mod等)以避免北极星CN出现故障。",
L"警告: 您的操作系统可能不受支持",
MB_OK | MB_ICONWARNING);

}
std::wcout << L"警告:由于运行库与旧版Windows存在兼容性问题,北极星CN 1.17只能保证在Windows 10 1903以上的版本在系统默认设置的情况下正常运行,若是Windows10 1903以下的系统版本,需要在控制面板-时钟和区域-区域-管理-更改系统区域设置-勾选使用Unicode UTF-8。如果在旧系统版本中不启用UTF-8,北极星CN将无法正确处理Windows中文字符。\n这可能会导致以下问题:\n(1) 带有任何中文路径的Mod无法正常工作或导致游戏崩溃\n(2) 游戏安装路径中存在中文字符时崩溃。\n(3) 系统用户名或用户目录名称存在中文字符时游戏崩溃\n若您的系统版本无Unicode UTF-8 选项,或是启用此选项后其他应用程序或目录出现乱码问题,可以通过以下方法解决:\n(1) 升级操作系统版本至Windows 10 1903或更高版本。\n(2) 手动重命名系统用户名和“文档”目录、游戏安装目录、Mods目录中所有含中文名称的文件夹(如模型和音频替换Mod等)以避免北极星CN出现故障。" << std::endl;
}

InitialiseVersion();
CreateLogFiles();
Expand Down
88 changes: 47 additions & 41 deletions primedev/masterserver/masterserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
#include <regex>
#include <random>


using namespace std::chrono_literals;
MasterServerManager* g_pMasterServerManager;
ClientAnticheatSystem g_ClientAnticheatSystem;
Expand Down Expand Up @@ -80,8 +79,8 @@ void SetCommonHttpClientOptions(CURL* curl)
curl_easy_setopt(curl, CURLOPT_RESOLVE, host);
}
else
{
//spdlog::warn("[DOH] service is not available. falling back to DNS");
{
// spdlog::warn("[DOH] service is not available. falling back to DNS");
}
}
else
Expand All @@ -94,7 +93,6 @@ void SetCommonHttpClientOptions(CURL* curl)
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
}


httplib::Client SetupHttpClient()
{
std::string ms_addr = Cvar_ns_masterserver_hostname->GetString();
Expand All @@ -105,10 +103,10 @@ httplib::Client SetupHttpClient()
cli.set_decompress(true);
cli.set_read_timeout(10, 0);
cli.set_write_timeout(10, 0);
//cli.enable_server_certificate_verification(false);
// cli.enable_server_certificate_verification(false);

cli.load_ca_cert_store(cabundle, sizeof(cabundle));
//cli.set_ca_cert_path("ca-bundle.crt");
// cli.set_ca_cert_path("ca-bundle.crt");
if (!strstr(GetCommandLineA(), "-disabledoh"))
{
std::string doh_result = g_DohWorker->GetDOHResolve(ms_addr);
Expand All @@ -118,7 +116,7 @@ httplib::Client SetupHttpClient()
}
else
{
//spdlog::warn("[DOH] service is not available. falling back to DNS");
// spdlog::warn("[DOH] service is not available. falling back to DNS");
}
}
return cli;
Expand All @@ -142,7 +140,7 @@ httplib::Client SetupMatchmakerHttpClient()
}
else
{
//spdlog::warn("[DOH] service is not available. falling back to DNS");
// spdlog::warn("[DOH] service is not available. falling back to DNS");
}
}
return cli;
Expand Down Expand Up @@ -180,16 +178,16 @@ bool MasterServerManager::StartMatchmaking(MatchmakeInfo* status)
}
std::string query =
fmt::format(fmt::runtime(query_fmt_str), Cvar_ns_matchmaker_hostname->GetString(), local_uid_escaped, token_escaped, "true")
.c_str(); // TODO: add working AA selection
//spdlog::warn("{}", query);
//return false;
.c_str(); // TODO: add working AA selection
// spdlog::warn("{}", query);
// return false;
curl_easy_setopt(curl, CURLOPT_URL, query.c_str());
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &read_buffer);

const CURLcode result = curl_easy_perform(curl);
//spdlog::info("[Matchmaker] JOIN: Result:{},buffer:{}", result, read_buffer.c_str());
// spdlog::info("[Matchmaker] JOIN: Result:{},buffer:{}", result, read_buffer.c_str());
if (result == CURLcode::CURLE_OK)
{
try
Expand Down Expand Up @@ -238,18 +236,16 @@ bool MasterServerManager::CancelMatchmaking()
curl_easy_setopt(
curl,
CURLOPT_URL,
fmt::format("{}/quit?id={}&token={}", Cvar_ns_matchmaker_hostname->GetString(), local_uid_escaped, token_escaped)
.c_str());
fmt::format("{}/quit?id={}&token={}", Cvar_ns_matchmaker_hostname->GetString(), local_uid_escaped, token_escaped).c_str());
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &read_buffer);

const CURLcode result = curl_easy_perform(curl);


if (result == CURLcode::CURLE_OK)
{
//spdlog::info("[Matchmaker] Result:{},buffer:{}", result, read_buffer.c_str());
// spdlog::info("[Matchmaker] Result:{},buffer:{}", result, read_buffer.c_str());
try
{
nlohmann::json resjson = nlohmann::json::parse(read_buffer);
Expand Down Expand Up @@ -300,8 +296,7 @@ bool MasterServerManager::UpdateMatchmakingStatus(MatchmakeInfo* status)
curl_easy_setopt(
curl,
CURLOPT_URL,
fmt::format("{}/state?id={}&token={}", Cvar_ns_matchmaker_hostname->GetString(), local_uid_escaped, token_escaped)
.c_str());
fmt::format("{}/state?id={}&token={}", Cvar_ns_matchmaker_hostname->GetString(), local_uid_escaped, token_escaped).c_str());
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &read_buffer);
Expand All @@ -310,25 +305,25 @@ bool MasterServerManager::UpdateMatchmakingStatus(MatchmakeInfo* status)

if (result == CURLcode::CURLE_OK)
{
//spdlog::info("[Matchmaker] STATE: Result:{},buffer:{}", result, read_buffer.c_str());
// spdlog::info("[Matchmaker] STATE: Result:{},buffer:{}", result, read_buffer.c_str());
try
{
nlohmann::json server_response = nlohmann::json::parse(read_buffer);
if (server_response.at("success") == true)
{
std::string state_type = server_response.at("state");

if (!strcmp(state_type.c_str(), "#MATCHMAKING_QUEUED"))
{
status->etaSeconds = "";
status->status = state_type;
//spdlog::info("[Matchmaker] MATCHMAKING_QUEUED");
// spdlog::info("[Matchmaker] MATCHMAKING_QUEUED");
curl_easy_cleanup(curl);
return true;
}
if (!strcmp(state_type.c_str(), "#MATCHMAKING_ALLOCATING_SERVER"))
{
//spdlog::info("[Matchmaker] MATCHMAKING_ALLOCATING_SERVER");
// spdlog::info("[Matchmaker] MATCHMAKING_ALLOCATING_SERVER");
status->status = state_type;
curl_easy_cleanup(curl);
return true;
Expand Down Expand Up @@ -485,7 +480,7 @@ void MasterServerManager::RequestServerList()
m_bScriptRequestingServerList = true;

httplib::Client cli = SetupHttpClient();

if (auto res = cli.Get("/client/servers"))
{
m_bSuccessfullyConnected = true;
Expand Down Expand Up @@ -693,7 +688,7 @@ void MasterServerManager::AuthenticateWithServer(
const char* uid, const std::string& playerToken, const std::string& serverId, const char* password)
{
// dont wait, just stop if we're trying to do 2 auth requests at once
if (m_bAuthenticatingWithGameServer|| g_pVanillaCompatibility->GetVanillaCompatibility())
if (m_bAuthenticatingWithGameServer || g_pVanillaCompatibility->GetVanillaCompatibility())
return;
m_sAuthFailureReason = "No error message provided";
m_sAuthFailureMessage = "No error message provided";
Expand Down Expand Up @@ -733,7 +728,7 @@ void MasterServerManager::AuthenticateWithServer(
nlohmann::json connection_info_json = nlohmann::json::parse(res->body);
if (connection_info_json.at("success") == true)
{
//spdlog::info("[auth_with_server] body: {}", res->body);
// spdlog::info("[auth_with_server] body: {}", res->body);
m_pendingConnectionInfo.ip.S_un.S_addr = inet_addr(std::string(connection_info_json.at("ip")).c_str());
m_pendingConnectionInfo.port = static_cast<unsigned short>(connection_info_json.at("port"));
m_pendingConnectionInfo.authToken = connection_info_json.at("authToken");
Expand Down Expand Up @@ -783,13 +778,13 @@ void MasterServerManager::WritePlayerPersistentData(const char* player_id, const
// still call this if we don't have a server id, since lobbies that aren't port forwarded need to be able to call it
if (m_sPlayerPersistenceStates.contains(strPlayerId))
{
spdlog::warn("player {} attempted to write pdata while previous request still exists!");
spdlog::warn("player {} attempted to write pdata while previous request still exists!", strPlayerId);
// player is already requesting for leave, ignore the request.
return;
}
if (!pdata_size)
{
spdlog::warn("attempted to write pdata of size 0!");
spdlog::warn("player {} attempted to write pdata of size 0!", strPlayerId);
return;
}

Expand All @@ -809,10 +804,20 @@ void MasterServerManager::WritePlayerPersistentData(const char* player_id, const
"/accounts/write_persistence?id={}&serverId={}", encode_query_param(strPlayerId), encode_query_param(m_sOwnServerId));
const std::string encoded = base64_encode(str_pdata.data(), pdata_size);
auto res = cli.Post(querystring, encoded, "text/plain");
if (res && res->status == 200)
if (res != nullptr)
{
spdlog::info("[Pdata] Successfully wrote pdata for user: {}", strPlayerId);
m_bSuccessfullyConnected = true;
if (res->status == 200)
{
spdlog::info("[Pdata] Successfully wrote pdata for user: {}", strPlayerId);
m_bSuccessfullyConnected = true;
}
else
{
auto err = res->body;
spdlog::error("[Pdata] Write persistence failed for user: {}, error: {}", strPlayerId, err);

m_bSuccessfullyConnected = true;
}
}
else
{
Expand All @@ -835,7 +840,12 @@ void ConCommand_ns_fetchservers(const CCommand& args)
g_pMasterServerManager->RequestServerList();
}

MasterServerManager::MasterServerManager() : m_sOwnServerId {""}, m_sOwnClientAuthToken {""}, m_pendingConnectionInfo {} {}
MasterServerManager::MasterServerManager()
: m_sOwnServerId {""}
, m_sOwnClientAuthToken {""}
, m_pendingConnectionInfo {}
{
}

ON_DLL_LOAD_RELIESON("engine.dll", MasterServer, (ConCommand, ServerPresence), (CModule module))
{
Expand Down Expand Up @@ -905,14 +915,12 @@ void MasterServerPresenceReporter::DestroyPresence(const ServerPresence* pServer
// Not bothering with better thread safety in this case since DestroyPresence() is called when the game is shutting down.
*g_pMasterServerManager->m_sOwnServerId = 0;


httplib::Client cli = SetupHttpClient();
const std::string querystring = fmt::format(
"/server/remove_server?id={}?serverAuthToken={}",
encode_query_param(g_pMasterServerManager->m_sOwnServerId),
encode_query_param(g_pMasterServerManager->m_sOwnServerAuthToken));
cli.Delete(querystring);

}

void MasterServerPresenceReporter::RunFrame(double flCurrentTime, const ServerPresence* pServerPresence)
Expand Down Expand Up @@ -1048,9 +1056,9 @@ void MasterServerPresenceReporter::InternalAddServer(const ServerPresence* pServ
data.serverAuthToken = server_auth_token;
return data;
};
//spdlog::info("{}", mod_info);
// spdlog::info("{}", mod_info);
auto res = cli.Post(querystring, mod_info, "application/json");

if (res && res->status == 200)
{
try
Expand Down Expand Up @@ -1085,10 +1093,8 @@ void MasterServerPresenceReporter::InternalAddServer(const ServerPresence* pServ
}
else
{
spdlog::error(
"Failed adding self to server list: error {}",
std::to_string(static_cast<int>(res.error())));
if(!res->body.empty())
spdlog::error("Failed adding self to server list: error {}", std::to_string(static_cast<int>(res.error())));
if (!res->body.empty())
spdlog::error("res:{}", res->body);
return return_cleanup(MasterServerReportPresenceResult::FailedNoConnect);
}
Expand Down
Loading

0 comments on commit 1a9ca77

Please sign in to comment.