aboutsummaryrefslogtreecommitdiff
path: root/NorthstarDedicatedTest
diff options
context:
space:
mode:
authorBobTheBob <32057864+BobTheBob9@users.noreply.github.com>2021-08-06 05:25:47 +0100
committerBobTheBob <32057864+BobTheBob9@users.noreply.github.com>2021-08-06 05:25:47 +0100
commit4d0e4679d05b146e5e43a1a707708c6451099c54 (patch)
tree111c18c310feeaf2096855e4072dea46f8f20eb6 /NorthstarDedicatedTest
parent02e422166baa12bbdc8af8806376cb2340fef896 (diff)
downloadNorthstarLauncher-4d0e4679d05b146e5e43a1a707708c6451099c54.tar.gz
NorthstarLauncher-4d0e4679d05b146e5e43a1a707708c6451099c54.zip
add support for connecting to servers from masterserver
Diffstat (limited to 'NorthstarDedicatedTest')
-rw-r--r--NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj4
-rw-r--r--NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters30
-rw-r--r--NorthstarDedicatedTest/chatcommand.cpp25
-rw-r--r--NorthstarDedicatedTest/chatcommand.h3
-rw-r--r--NorthstarDedicatedTest/dllmain.cpp5
-rw-r--r--NorthstarDedicatedTest/gameutils.cpp13
-rw-r--r--NorthstarDedicatedTest/gameutils.h57
-rw-r--r--NorthstarDedicatedTest/masterserver.cpp120
-rw-r--r--NorthstarDedicatedTest/masterserver.h27
-rw-r--r--NorthstarDedicatedTest/modmanager.cpp19
-rw-r--r--NorthstarDedicatedTest/scriptserverbrowser.cpp94
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