diff options
author | BobTheBob <32057864+BobTheBob9@users.noreply.github.com> | 2021-08-06 05:25:47 +0100 |
---|---|---|
committer | BobTheBob <32057864+BobTheBob9@users.noreply.github.com> | 2021-08-06 05:25:47 +0100 |
commit | 4d0e4679d05b146e5e43a1a707708c6451099c54 (patch) | |
tree | 111c18c310feeaf2096855e4072dea46f8f20eb6 | |
parent | 02e422166baa12bbdc8af8806376cb2340fef896 (diff) | |
download | NorthstarLauncher-4d0e4679d05b146e5e43a1a707708c6451099c54.tar.gz NorthstarLauncher-4d0e4679d05b146e5e43a1a707708c6451099c54.zip |
add support for connecting to servers from masterserver
-rw-r--r-- | NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj | 4 | ||||
-rw-r--r-- | NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters | 30 | ||||
-rw-r--r-- | NorthstarDedicatedTest/chatcommand.cpp | 25 | ||||
-rw-r--r-- | NorthstarDedicatedTest/chatcommand.h | 3 | ||||
-rw-r--r-- | NorthstarDedicatedTest/dllmain.cpp | 5 | ||||
-rw-r--r-- | NorthstarDedicatedTest/gameutils.cpp | 13 | ||||
-rw-r--r-- | NorthstarDedicatedTest/gameutils.h | 57 | ||||
-rw-r--r-- | NorthstarDedicatedTest/masterserver.cpp | 120 | ||||
-rw-r--r-- | NorthstarDedicatedTest/masterserver.h | 27 | ||||
-rw-r--r-- | NorthstarDedicatedTest/modmanager.cpp | 19 | ||||
-rw-r--r-- | NorthstarDedicatedTest/scriptserverbrowser.cpp | 94 |
11 files changed, 330 insertions, 67 deletions
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj index 889cae30..234894fa 100644 --- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj +++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj @@ -170,11 +170,13 @@ </PreBuildEvent> </ItemDefinitionGroup> <ItemGroup> + <ClInclude Include="chatcommand.h" /> <ClInclude Include="concommand.h" /> <ClInclude Include="context.h" /> <ClInclude Include="convar.h" /> <ClInclude Include="dedicated.h" /> <ClInclude Include="filesystem.h" /> + <ClInclude Include="gameutils.h" /> <ClInclude Include="hooks.h" /> <ClInclude Include="hookutils.h" /> <ClInclude Include="include\httplib.h" /> @@ -321,12 +323,14 @@ <ClInclude Include="tier0.h" /> </ItemGroup> <ItemGroup> + <ClCompile Include="chatcommand.cpp" /> <ClCompile Include="concommand.cpp" /> <ClCompile Include="context.cpp" /> <ClCompile Include="convar.cpp" /> <ClCompile Include="dedicated.cpp" /> <ClCompile Include="dllmain.cpp" /> <ClCompile Include="filesystem.cpp" /> + <ClCompile Include="gameutils.cpp" /> <ClCompile Include="hooks.cpp" /> <ClCompile Include="hookutils.cpp" /> <ClCompile Include="keyvalues.cpp" /> diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters index a9ae995b..0da3d860 100644 --- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters +++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters @@ -100,6 +100,12 @@ <Filter Include="Header Files\Server\Authentication"> <UniqueIdentifier>{24fd0855-9288-4129-93ba-c6cafdc98d1b}</UniqueIdentifier> </Filter> + <Filter Include="Source Files\Shared\Game Functions"> + <UniqueIdentifier>{2cbddb28-0b17-4881-847d-8773da52b268}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files\Shared\Game Functions"> + <UniqueIdentifier>{0c93d909-e0d6-4c35-a8a4-a13f681a1012}</UniqueIdentifier> + </Filter> </ItemGroup> <ItemGroup> <ClInclude Include="pch.h"> @@ -114,9 +120,6 @@ <ClInclude Include="hookutils.h"> <Filter>Header Files\Shared\Hooks</Filter> </ClInclude> - <ClInclude Include="tier0.h"> - <Filter>Header Files\Shared</Filter> - </ClInclude> <ClInclude Include="main.h"> <Filter>Header Files</Filter> </ClInclude> @@ -549,6 +552,15 @@ <ClInclude Include="masterserver.h"> <Filter>Header Files\Shared</Filter> </ClInclude> + <ClInclude Include="tier0.h"> + <Filter>Header Files\Shared\Game Functions</Filter> + </ClInclude> + <ClInclude Include="gameutils.h"> + <Filter>Header Files\Shared\Game Functions</Filter> + </ClInclude> + <ClInclude Include="chatcommand.h"> + <Filter>Header Files\Client</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="dllmain.cpp"> @@ -560,9 +572,6 @@ <ClCompile Include="hooks.cpp"> <Filter>Source Files\Shared\Hooks</Filter> </ClCompile> - <ClCompile Include="tier0.cpp"> - <Filter>Source Files\Shared</Filter> - </ClCompile> <ClCompile Include="hookutils.cpp"> <Filter>Source Files\Shared\Hooks</Filter> </ClCompile> @@ -617,6 +626,15 @@ <ClCompile Include="masterserver.cpp"> <Filter>Source Files\Shared</Filter> </ClCompile> + <ClCompile Include="tier0.cpp"> + <Filter>Source Files\Shared\Game Functions</Filter> + </ClCompile> + <ClCompile Include="gameutils.cpp"> + <Filter>Source Files\Shared\Game Functions</Filter> + </ClCompile> + <ClCompile Include="chatcommand.cpp"> + <Filter>Source Files\Client</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <None Include="include\spdlog\fmt\bundled\LICENSE.rst"> diff --git a/NorthstarDedicatedTest/chatcommand.cpp b/NorthstarDedicatedTest/chatcommand.cpp new file mode 100644 index 00000000..866a1d79 --- /dev/null +++ b/NorthstarDedicatedTest/chatcommand.cpp @@ -0,0 +1,25 @@ +#include "pch.h" +#include "chatcommand.h" +#include "concommand.h" + +typedef void(__fastcall *ClientSayTextType)(void* a1, const char* message, char unknownAlways1, bool isTeamChat); +ClientSayTextType SayText; + +void ConCommand_say(const CCommand& args) +{ + if (args.ArgC() >= 2) + SayText(nullptr, args.Arg(1), 0, false); +} + +void ConCommand_say_team(const CCommand& args) +{ + if (args.ArgC() >= 2) + SayText(nullptr, args.Arg(1), 0, true); +} + +void InitialiseChatCommands(HMODULE baseAddress) +{ + SayText = (ClientSayTextType)((char*)baseAddress + 0x54780); + RegisterConCommand("say", ConCommand_say, "Enters a message in public chat", FCVAR_CLIENTDLL); + RegisterConCommand("say_team", ConCommand_say_team, "Enters a message in team chat", FCVAR_CLIENTDLL); +}
\ No newline at end of file diff --git a/NorthstarDedicatedTest/chatcommand.h b/NorthstarDedicatedTest/chatcommand.h new file mode 100644 index 00000000..1c095fb7 --- /dev/null +++ b/NorthstarDedicatedTest/chatcommand.h @@ -0,0 +1,3 @@ +#pragma once + +void InitialiseChatCommands(HMODULE baseAddress);
\ No newline at end of file diff --git a/NorthstarDedicatedTest/dllmain.cpp b/NorthstarDedicatedTest/dllmain.cpp index 691b6d53..f5118900 100644 --- a/NorthstarDedicatedTest/dllmain.cpp +++ b/NorthstarDedicatedTest/dllmain.cpp @@ -13,6 +13,8 @@ #include "scriptserverbrowser.h" #include "keyvalues.h" #include "masterserver.h" +#include "gameutils.h" +#include "chatcommand.h" bool initialised = false; @@ -47,6 +49,8 @@ void InitialiseNorthstar() InstallInitialHooks(); InitialiseInterfaceCreationHooks(); + AddDllLoadCallback("engine.dll", InitialiseEngineGameUtilFunctions); + if (IsDedicated()) AddDllLoadCallback("engine.dll", InitialiseDedicated); @@ -58,6 +62,7 @@ void InitialiseNorthstar() AddDllLoadCallback("client.dll", InitialiseClientSquirrel); AddDllLoadCallback("client.dll", InitialiseSourceConsole); + AddDllLoadCallback("engine.dll", InitialiseChatCommands); AddDllLoadCallback("client.dll", InitialiseScriptModMenu); AddDllLoadCallback("client.dll", InitialiseScriptServerBrowser); } diff --git a/NorthstarDedicatedTest/gameutils.cpp b/NorthstarDedicatedTest/gameutils.cpp new file mode 100644 index 00000000..9d61ab0a --- /dev/null +++ b/NorthstarDedicatedTest/gameutils.cpp @@ -0,0 +1,13 @@ +#include "pch.h" +#include "gameutils.h" + +// cmd.h + +Cbuf_GetCurrentPlayerType Cbuf_GetCurrentPlayer; +Cbuf_AddTextType Cbuf_AddText; + +void InitialiseEngineGameUtilFunctions(HMODULE baseAddress) +{ + Cbuf_GetCurrentPlayer = (Cbuf_GetCurrentPlayerType)((char*)baseAddress + 0x120630); + Cbuf_AddText = (Cbuf_AddTextType)((char*)baseAddress + 0x1203B0); +}
\ No newline at end of file diff --git a/NorthstarDedicatedTest/gameutils.h b/NorthstarDedicatedTest/gameutils.h new file mode 100644 index 00000000..4c2254e7 --- /dev/null +++ b/NorthstarDedicatedTest/gameutils.h @@ -0,0 +1,57 @@ +#pragma once + +// cmd.h + +enum class ECommandTarget_t +{ + CBUF_FIRST_PLAYER = 0, + CBUF_LAST_PLAYER = 1, // MAX_SPLITSCREEN_CLIENTS - 1, MAX_SPLITSCREEN_CLIENTS = 2 + CBUF_SERVER = CBUF_LAST_PLAYER + 1, + + CBUF_COUNT, +}; + +enum class cmd_source_t +{ + // Added to the console buffer by gameplay code. Generally unrestricted. + kCommandSrcCode, + + // Sent from code via engine->ClientCmd, which is restricted to commands visible + // via FCVAR_CLIENTCMD_CAN_EXECUTE. + kCommandSrcClientCmd, + + // Typed in at the console or via a user key-bind. Generally unrestricted, although + // the client will throttle commands sent to the server this way to 16 per second. + kCommandSrcUserInput, + + // Came in over a net connection as a clc_stringcmd + // host_client will be valid during this state. + // + // Restricted to FCVAR_GAMEDLL commands (but not convars) and special non-ConCommand + // server commands hardcoded into gameplay code (e.g. "joingame") + kCommandSrcNetClient, + + // Received from the server as the client + // + // Restricted to commands with FCVAR_SERVER_CAN_EXECUTE + kCommandSrcNetServer, + + // Being played back from a demo file + // + // Not currently restricted by convar flag, but some commands manually ignore calls + // from this source. FIXME: Should be heavily restricted as demo commands can come + // from untrusted sources. + kCommandSrcDemoFile, + + // Invalid value used when cleared + kCommandSrcInvalid = -1 +}; + +typedef ECommandTarget_t(*Cbuf_GetCurrentPlayerType)(); +extern Cbuf_GetCurrentPlayerType Cbuf_GetCurrentPlayer; + +// compared to the defs i've seen, this is missing an arg, it could be nTickInterval or source, not sure, guessing it's source +typedef void(*Cbuf_AddTextType)(ECommandTarget_t eTarget, const char* text, cmd_source_t source); +extern Cbuf_AddTextType Cbuf_AddText; + +void InitialiseEngineGameUtilFunctions(HMODULE baseAddress);
\ No newline at end of file diff --git a/NorthstarDedicatedTest/masterserver.cpp b/NorthstarDedicatedTest/masterserver.cpp index dcbed9b4..d8b765ec 100644 --- a/NorthstarDedicatedTest/masterserver.cpp +++ b/NorthstarDedicatedTest/masterserver.cpp @@ -24,8 +24,7 @@ RemoteServerInfo::RemoteServerInfo(const char* newId, const char* newName, const strncpy((char*)name, newName, 63); name[63] = 0; - description = new char[strlen(newDescription) + 1]; - strcpy(description, newDescription); + description = std::string(newDescription); strncpy((char*)map, newMap, 31); map[31] = 0; @@ -46,8 +45,7 @@ RemoteServerInfo::RemoteServerInfo(const char* newId, const char* newName, const strncpy((char*)name, newName, 63); name[63] = 0; - description = new char[strlen(newDescription) + 1]; - strcpy(description, newDescription); + description = std::string(newDescription); strncpy((char*)map, newMap, 31); map[31] = 0; @@ -61,11 +59,6 @@ RemoteServerInfo::RemoteServerInfo(const char* newId, const char* newName, const port = newPort; } -RemoteServerInfo::~RemoteServerInfo() -{ - delete[] description; -} - void MasterServerManager::ClearServerList() { // this doesn't really do anything lol, probably isn't threadsafe @@ -78,6 +71,7 @@ void MasterServerManager::ClearServerList() void MasterServerManager::RequestServerList() { + // do this here so it's instantly set on call for scripts m_scriptRequestingServerList = true; std::thread requestThread([this]() @@ -95,7 +89,7 @@ void MasterServerManager::RequestServerList() spdlog::info("Requesting server list from {}", Cvar_ns_masterserver_hostname->m_pszString); - if (auto result = http.Get("/servers")) + if (auto result = http.Get("/client/servers")) { m_successfullyConnected = true; @@ -105,13 +99,20 @@ void MasterServerManager::RequestServerList() if (serverInfoJson.HasParseError()) { spdlog::error("Failed reading masterserver response: encountered parse error \"{}\"", rapidjson::GetParseError_En(serverInfoJson.GetParseError())); - goto REQUEST_SERVER_LIST_END; + goto REQUEST_END_CLEANUP; + } + + if (serverInfoJson.IsObject() && serverInfoJson.HasMember("error")) + { + spdlog::error("Failed reading masterserver response: got fastify error response"); + spdlog::error(result->body); + goto REQUEST_END_CLEANUP; } if (!serverInfoJson.IsArray()) { spdlog::error("Failed reading masterserver response: root object is not an array"); - goto REQUEST_SERVER_LIST_END; + goto REQUEST_END_CLEANUP; } rapidjson::GenericArray<false, rapidjson::Value> serverArray = serverInfoJson.GetArray(); @@ -123,7 +124,7 @@ void MasterServerManager::RequestServerList() if (!serverObj.IsObject()) { spdlog::error("Failed reading masterserver response: member of server array is not an object"); - goto REQUEST_SERVER_LIST_END; + goto REQUEST_END_CLEANUP; } // todo: verify json props are fine before adding to m_remoteServers @@ -138,7 +139,7 @@ void MasterServerManager::RequestServerList() || !serverObj.HasMember("hasPassword") || !serverObj["hasPassword"].IsBool()) { spdlog::error("Failed reading masterserver response: malformed server object"); - goto REQUEST_SERVER_LIST_END; + goto REQUEST_END_CLEANUP; } bool hasPassword = serverObj["hasPassword"].GetBool(); @@ -147,7 +148,7 @@ void MasterServerManager::RequestServerList() bool createNewServerInfo = true; for (RemoteServerInfo& server : m_remoteServers) { - // server already exists, update info + // if server already exists, update info rather than adding to it if (!strncmp((const char*)server.id, id, 31)) { if (hasPassword) @@ -173,6 +174,12 @@ void MasterServerManager::RequestServerList() m_remoteServers.emplace_back(id, serverObj["name"].GetString(), serverObj["description"].GetString(), serverObj["map"].GetString(), serverObj["playlist"].GetString(), serverObj["playerCount"].GetInt(), serverObj["maxPlayers"].GetInt()); else { + if (!serverObj.HasMember("ip") || !serverObj["ip"].IsUint64() || !serverObj.HasMember("port") || !serverObj["port"].IsNumber()) + { + spdlog::error("Failed reading masterserver response: malformed server object"); + goto REQUEST_END_CLEANUP; + } + in_addr addr; addr.S_un.S_addr = serverObj["ip"].GetUint64(); @@ -190,7 +197,7 @@ void MasterServerManager::RequestServerList() } // we goto this instead of returning so we always hit this - REQUEST_SERVER_LIST_END: + REQUEST_END_CLEANUP: m_requestingServerList = false; m_scriptRequestingServerList = false; }); @@ -198,6 +205,87 @@ void MasterServerManager::RequestServerList() requestThread.detach(); } +void MasterServerManager::TryAuthenticateWithServer(char* serverId, char* password) +{ + // dont wait, just stop if we're trying to do 2 auth requests at once + if (m_authenticatingWithGameServer) + return; + + m_authenticatingWithGameServer = true; + m_scriptAuthenticatingWithGameServer = true; + m_successfullyAuthenticatedWithGameServer = false; + + std::thread requestThread([this, serverId, password]() + { + httplib::Client http(Cvar_ns_masterserver_hostname->m_pszString, Cvar_ns_masterserver_port->m_nValue); + http.set_connection_timeout(20); + + spdlog::info("Attempting authentication with server of id \"{}\"", serverId); + + spdlog::info(fmt::format("/client/auth_with_server?server={}&password={}", serverId, password)); + + if (auto result = http.Post(fmt::format("/client/auth_with_server?server={}&password={}", serverId, password).c_str())) + { + m_successfullyConnected = true; + + rapidjson::Document connectionInfoJson; + connectionInfoJson.Parse(result->body.c_str()); + + if (connectionInfoJson.HasParseError()) + { + spdlog::error("Failed reading masterserver authentication response: encountered parse error \"{}\"", rapidjson::GetParseError_En(connectionInfoJson.GetParseError())); + goto REQUEST_END_CLEANUP; + } + + if (!connectionInfoJson.IsObject()) + { + spdlog::error("Failed reading masterserver authentication response: root object is not an object"); + goto REQUEST_END_CLEANUP; + } + + if (connectionInfoJson.HasMember("error")) + { + spdlog::error("Failed reading masterserver response: got fastify error response"); + spdlog::error(result->body); + goto REQUEST_END_CLEANUP; + } + + if (!connectionInfoJson["success"].IsTrue()) + { + spdlog::error("Authentication with masterserver failed: \"success\" is not true"); + goto REQUEST_END_CLEANUP; + } + + if (!connectionInfoJson.HasMember("success") || !connectionInfoJson.HasMember("ip") || !connectionInfoJson["ip"].IsUint64() || !connectionInfoJson.HasMember("port") || !connectionInfoJson["port"].IsNumber() || !connectionInfoJson.HasMember("authToken") || !connectionInfoJson["authToken"].IsString()) + { + spdlog::error("Failed reading masterserver authentication response: malformed json object"); + goto REQUEST_END_CLEANUP; + } + + m_pendingConnectionInfo.ip.S_un.S_addr = connectionInfoJson["ip"].GetUint64(); + m_pendingConnectionInfo.port = connectionInfoJson["port"].GetInt(); + + strncpy(m_pendingConnectionInfo.authToken, connectionInfoJson["authToken"].GetString(), 31); + m_pendingConnectionInfo.authToken[31] = 0; + + m_hasPendingConnectionInfo = true; + m_successfullyAuthenticatedWithGameServer = true; + } + else + { + spdlog::error("Failed authenticating with server: error {}", result.error()); + m_successfullyConnected = false; + m_successfullyAuthenticatedWithGameServer = false; + } + + REQUEST_END_CLEANUP: + m_authenticatingWithGameServer = false; + m_scriptAuthenticatingWithGameServer = false; + }); + + requestThread.detach(); +} + void ConCommand_ns_fetchservers(const CCommand& args) { g_MasterServerManager->RequestServerList(); diff --git a/NorthstarDedicatedTest/masterserver.h b/NorthstarDedicatedTest/masterserver.h index 1cbc37a5..76e19b48 100644 --- a/NorthstarDedicatedTest/masterserver.h +++ b/NorthstarDedicatedTest/masterserver.h @@ -9,7 +9,7 @@ public: // server info char name[64]; - char* description; + std::string description; char map[32]; char playlist[16]; @@ -24,22 +24,39 @@ public: public: RemoteServerInfo(const char* newId, const char* newName, const char* newDescription, const char* newMap, const char* newPlaylist, int newPlayerCount, int newMaxPlayers); RemoteServerInfo(const char* newId, const char* newName, const char* newDescription, const char* newMap, const char* newPlaylist, int newPlayerCount, int newMaxPlayers, in_addr newIp, int newPort); - ~RemoteServerInfo(); +}; + +struct RemoteServerConnectionInfo +{ +public: + char authToken[32]; + + in_addr ip; + int port; }; class MasterServerManager { private: - bool m_requestingServerList; + bool m_requestingServerList = false; + bool m_authenticatingWithGameServer = false; public: - bool m_scriptRequestingServerList; + bool m_scriptRequestingServerList = false; bool m_successfullyConnected = true; - std::list<RemoteServerInfo> m_remoteServers; + + bool m_scriptAuthenticatingWithGameServer = false; + bool m_successfullyAuthenticatedWithGameServer = false; + + bool m_hasPendingConnectionInfo = false; + RemoteServerConnectionInfo m_pendingConnectionInfo; + + std::vector<RemoteServerInfo> m_remoteServers; public: void ClearServerList(); void RequestServerList(); + void TryAuthenticateWithServer(char* serverId, char* password); }; void InitialiseSharedMasterServer(HMODULE baseAddress); diff --git a/NorthstarDedicatedTest/modmanager.cpp b/NorthstarDedicatedTest/modmanager.cpp index 537ea150..342736e6 100644 --- a/NorthstarDedicatedTest/modmanager.cpp +++ b/NorthstarDedicatedTest/modmanager.cpp @@ -219,14 +219,8 @@ void ModManager::LoadMods() return a->LoadPriority > b->LoadPriority; }); - // do we need to dealloc individual entries in m_modFiles? idk, rework - m_modFiles.clear(); - fs::remove_all(COMPILED_ASSETS_PATH); - for (Mod* mod : m_loadedMods) { - mod->KeyValuesHash.clear(); - if (!mod->Enabled) continue; @@ -285,11 +279,20 @@ void ModManager::UnloadMods() { // clean up stuff from mods before we unload - // remove all built kvs + // do we need to dealloc individual entries in m_modFiles? idk, rework + m_modFiles.clear(); + fs::remove_all(COMPILED_ASSETS_PATH); + for (Mod* mod : m_loadedMods) + { + // remove all built kvs for (std::string kvPaths : mod->KeyValues) fs::remove(COMPILED_ASSETS_PATH / fs::path(kvPaths).lexically_relative(mod->ModDirectory)); + mod->KeyValuesHash.clear(); + mod->KeyValues.clear(); + } + // do we need to dealloc individual entries in m_loadedMods? idk, rework m_loadedMods.clear(); } @@ -300,7 +303,7 @@ void ModManager::CompileAssetsForFile(const char* filename) if (!path.filename().compare("scripts.rson")) BuildScriptsRson(); - else if (!strcmp((filename + strlen(filename)) - 3, "txt")) // check if it's a .txt + else //if (!strcmp((filename + strlen(filename)) - 3, "txt")) // check if it's a .txt { // check if we should build keyvalues, depending on whether any of our mods have patch kvs for this file for (Mod* mod : m_loadedMods) diff --git a/NorthstarDedicatedTest/scriptserverbrowser.cpp b/NorthstarDedicatedTest/scriptserverbrowser.cpp index 7f7bd369..419ed274 100644 --- a/NorthstarDedicatedTest/scriptserverbrowser.cpp +++ b/NorthstarDedicatedTest/scriptserverbrowser.cpp @@ -2,6 +2,7 @@ #include "scriptserverbrowser.h" #include "squirrel.h" #include "masterserver.h" +#include "gameutils.h" // functions for viewing server browser @@ -44,10 +45,7 @@ SQInteger SQ_GetServerName(void* sqvm) return 0; } - auto iterator = g_MasterServerManager->m_remoteServers.begin(); - std::advance(iterator, serverIndex); - - ClientSq_pushstring(sqvm, iterator->name, -1); + ClientSq_pushstring(sqvm, g_MasterServerManager->m_remoteServers[serverIndex].name, -1); return 1; } @@ -62,10 +60,7 @@ SQInteger SQ_GetServerMap(void* sqvm) return 0; } - auto iterator = g_MasterServerManager->m_remoteServers.begin(); - std::advance(iterator, serverIndex); - - ClientSq_pushstring(sqvm, iterator->map, -1); + ClientSq_pushstring(sqvm, g_MasterServerManager->m_remoteServers[serverIndex].map, -1); return 1; } @@ -80,10 +75,7 @@ SQInteger SQ_GetServerPlaylist(void* sqvm) return 0; } - auto iterator = g_MasterServerManager->m_remoteServers.begin(); - std::advance(iterator, serverIndex); - - ClientSq_pushstring(sqvm, iterator->playlist, -1); + ClientSq_pushstring(sqvm, g_MasterServerManager->m_remoteServers[serverIndex].playlist, -1); return 1; } @@ -98,10 +90,21 @@ SQInteger SQ_GetServerID(void* sqvm) return 0; } - auto iterator = g_MasterServerManager->m_remoteServers.begin(); - std::advance(iterator, serverIndex); + ClientSq_pushstring(sqvm, g_MasterServerManager->m_remoteServers[serverIndex].id, -1); + return 1; +} - ClientSq_pushstring(sqvm, iterator->id, -1); +SQInteger SQ_ServerRequiresPassword(void* sqvm) +{ + SQInteger serverIndex = ClientSq_getinteger(sqvm, 1); + + if (serverIndex >= g_MasterServerManager->m_remoteServers.size()) + { + spdlog::warn("Tried to get hasPassword of server index {} when only {} servers are available", serverIndex, g_MasterServerManager->m_remoteServers.size()); + return 0; + } + + ClientSq_pushbool(sqvm, g_MasterServerManager->m_remoteServers[serverIndex].requiresPassword); return 1; } @@ -115,27 +118,57 @@ SQInteger SQ_ClearRecievedServerList(void* sqvm) // functions for authenticating with servers -// void function NSTryAuthWithServer( string serverId ) +// void function NSTryAuthWithServer( int serverIndex, string password = "" ) SQInteger SQ_TryAuthWithServer(void* sqvm) { + SQInteger serverIndex = ClientSq_getinteger(sqvm, 1); + const SQChar* password = ClientSq_getstring(sqvm, 2); + + if (serverIndex >= g_MasterServerManager->m_remoteServers.size()) + { + spdlog::warn("Tried to auth with server index {} when only {} servers are available", serverIndex, g_MasterServerManager->m_remoteServers.size()); + return 0; + } + + // do auth + g_MasterServerManager->TryAuthenticateWithServer(g_MasterServerManager->m_remoteServers[serverIndex].id, (char*)password); + return 0; } -// int function NSWasAuthSuccessful() -SQInteger SQ_WasAuthSuccessful(void* sqvm) +// bool function NSIsAuthenticatingWithServer() +SQInteger SQ_IsAuthComplete(void* sqvm) { - return 0; + ClientSq_pushbool(sqvm, g_MasterServerManager->m_scriptAuthenticatingWithGameServer); + return 1; } -// string function NSTryGetAuthedServerAddress() -SQInteger SQ_TryGetAuthedServerAddress(void* sqvm) +// bool function NSWasAuthSuccessful() +SQInteger SQ_WasAuthSuccessful(void* sqvm) { - return 0; + ClientSq_pushbool(sqvm, g_MasterServerManager->m_successfullyAuthenticatedWithGameServer); + return 1; } -// string function NSTryGetAuthedServerToken() -SQInteger SQ_TryGetAuthedServerToken(void* sqvm) +// void function NSConnectToAuthedServer() +SQInteger SQ_ConnectToAuthedServer(void* sqvm) { + if (!g_MasterServerManager->m_hasPendingConnectionInfo) + { + spdlog::error("Tried to connect to authed server before any pending connection info was available"); + return 0; + } + + RemoteServerConnectionInfo info = g_MasterServerManager->m_pendingConnectionInfo; + + // set auth token, then try to connect + // i'm honestly not entirely sure how silentconnect works regarding ports and encryption so using connect for now + Cbuf_AddText(Cbuf_GetCurrentPlayer(), fmt::format("serverfilter {}", info.authToken).c_str(), cmd_source_t::kCommandSrcCode); + Cbuf_AddText(Cbuf_GetCurrentPlayer(), fmt::format("connect {}.{}.{}.{}:{}", info.ip.S_un.S_un_b.s_b1, info.ip.S_un.S_un_b.s_b2, info.ip.S_un.S_un_b.s_b3, info.ip.S_un.S_un_b.s_b4, info.port).c_str(), cmd_source_t::kCommandSrcCode); + + spdlog::info(fmt::format("connect {}.{}.{}.{}:{}", info.ip.S_un.S_un_b.s_b1, info.ip.S_un.S_un_b.s_b2, info.ip.S_un.S_un_b.s_b3, info.ip.S_un.S_un_b.s_b4, info.port)); + + g_MasterServerManager->m_hasPendingConnectionInfo = false; return 0; } @@ -151,13 +184,10 @@ void InitialiseScriptServerBrowser(HMODULE baseAddress) g_UISquirrelManager->AddFuncRegistration("string", "NSGetServerMap", "int serverIndex", "", SQ_GetServerMap); g_UISquirrelManager->AddFuncRegistration("string", "NSGetServerPlaylist", "int serverIndex", "", SQ_GetServerPlaylist); g_UISquirrelManager->AddFuncRegistration("string", "NSGetServerID", "int serverIndex", "", SQ_GetServerID); + g_UISquirrelManager->AddFuncRegistration("bool", "NSServerRequiresPassword", "int serverIndex", "", SQ_ServerRequiresPassword); - //g_UISquirrelManager->AddFuncRegistration("bool", "NSPollServerPage", "int page", "", SQ_PollServerPage); - //g_UISquirrelManager->AddFuncRegistration("int", "NSGetNumServersOnPage", "int page", "", SQ_GetNumServersOnPage); - //g_UISquirrelManager->AddFuncRegistration("string", "NSGetServerName", "int page, int serverIndex", "", SQ_GetServerName); - //g_UISquirrelManager->AddFuncRegistration("string", "NSGetServerMap", "int page, int serverIndex", "", SQ_GetServerMap); - //g_UISquirrelManager->AddFuncRegistration("string", "NSGetServerMode", "int page, int serverIndex", "", SQ_GetServerMode); - //g_UISquirrelManager->AddFuncRegistration("void", "NSResetRecievedServers", "", "", SQ_ResetRecievedServers); - // - //g_UISquirrelManager->AddFuncRegistration("string", "NSTryGetAuthedServerToken", "", "", SQ_TryGetAuthedServerToken); + g_UISquirrelManager->AddFuncRegistration("void", "NSTryAuthWithServer", "int serverIndex, string password = \"\"", "", SQ_TryAuthWithServer); + g_UISquirrelManager->AddFuncRegistration("bool", "NSIsAuthenticatingWithServer", "", "", SQ_IsAuthComplete); + g_UISquirrelManager->AddFuncRegistration("bool", "NSWasAuthSuccessful", "", "", SQ_WasAuthSuccessful); + g_UISquirrelManager->AddFuncRegistration("void", "NSConnectToAuthedServer", "", "", SQ_ConnectToAuthedServer); }
\ No newline at end of file |