aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpg9182 <96569817+pg9182@users.noreply.github.com>2023-05-05 19:45:04 -0400
committerpg9182 <96569817+pg9182@users.noreply.github.com>2023-05-05 19:45:04 -0400
commit97df63bc21e53556f3cc31112f713d1ae63e691a (patch)
tree619eb57b5574e6f0f9541a570bbe537ac9ac0eb8
parent39f73a68730e9336f2469fdf1024dab771a85fb3 (diff)
downloadNorthstarLauncher-temp/test-dedi-crash-plugin.tar.gz
NorthstarLauncher-temp/test-dedi-crash-plugin.zip
Revert "Plugin system v2 (#343)"temp/test-dedi-crash-plugin
This reverts commit 450d0b1ed437cf37b4309af952af8904f3f07768.
-rw-r--r--NorthstarDLL/NorthstarDLL.vcxproj5
-rw-r--r--NorthstarDLL/NorthstarDLL.vcxproj.filters27
-rw-r--r--NorthstarDLL/config/profile.cpp3
-rw-r--r--NorthstarDLL/core/convar/concommand.cpp4
-rw-r--r--NorthstarDLL/core/convar/convar.cpp7
-rw-r--r--NorthstarDLL/core/hooks.cpp2
-rw-r--r--NorthstarDLL/core/math/color.cpp2
-rw-r--r--NorthstarDLL/core/math/color.h2
-rw-r--r--NorthstarDLL/dllmain.cpp135
-rw-r--r--NorthstarDLL/engine/hoststate.cpp4
-rw-r--r--NorthstarDLL/logging/logging.cpp10
-rw-r--r--NorthstarDLL/logging/logging.h3
-rw-r--r--NorthstarDLL/masterserver/masterserver.cpp9
-rw-r--r--NorthstarDLL/masterserver/masterserver.h5
-rw-r--r--NorthstarDLL/mods/modmanager.cpp5
-rw-r--r--NorthstarDLL/mods/modmanager.h2
-rw-r--r--NorthstarDLL/pch.h6
-rw-r--r--NorthstarDLL/plugins/plugin_abi.h192
-rw-r--r--NorthstarDLL/plugins/pluginbackend.cpp94
-rw-r--r--NorthstarDLL/plugins/pluginbackend.h45
-rw-r--r--NorthstarDLL/plugins/plugins.cpp581
-rw-r--r--NorthstarDLL/plugins/plugins.h62
-rw-r--r--NorthstarDLL/scripts/client/scriptserverbrowser.cpp2
-rw-r--r--NorthstarDLL/server/serverpresence.cpp5
-rw-r--r--NorthstarDLL/server/serverpresence.h9
-rw-r--r--NorthstarDLL/shared/gamepresence.cpp81
-rw-r--r--NorthstarDLL/shared/gamepresence.h48
-rw-r--r--NorthstarDLL/squirrel/squirrel.cpp83
-rw-r--r--NorthstarDLL/squirrel/squirrel.h12
-rw-r--r--NorthstarDLL/squirrel/squirrelclasstypes.h1
-rw-r--r--NorthstarLauncher/main.cpp17
31 files changed, 571 insertions, 892 deletions
diff --git a/NorthstarDLL/NorthstarDLL.vcxproj b/NorthstarDLL/NorthstarDLL.vcxproj
index 464c0b58..a0746bd8 100644
--- a/NorthstarDLL/NorthstarDLL.vcxproj
+++ b/NorthstarDLL/NorthstarDLL.vcxproj
@@ -429,8 +429,8 @@
<ClInclude Include="logging\sourceconsole.h" />
<ClInclude Include="masterserver\masterserver.h" />
<ClInclude Include="mods\modmanager.h" />
+ <ClInclude Include="ns_version.h" />
<ClInclude Include="pch.h" />
- <ClInclude Include="plugins\pluginbackend.h" />
<ClInclude Include="plugins\plugins.h" />
<ClInclude Include="plugins\plugin_abi.h" />
<ClInclude Include="scripts\scripthttprequesthandler.h" />
@@ -439,7 +439,6 @@
<ClInclude Include="server\r2server.h" />
<ClInclude Include="server\serverchathooks.h" />
<ClInclude Include="server\serverpresence.h" />
- <ClInclude Include="shared\gamepresence.h" />
<ClInclude Include="shared\keyvalues.h" />
<ClInclude Include="shared\maxplayers.h" />
<ClInclude Include="shared\misccommands.h" />
@@ -507,7 +506,6 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
- <ClCompile Include="plugins\pluginbackend.cpp" />
<ClCompile Include="plugins\plugins.cpp" />
<ClCompile Include="scripts\client\clientchathooks.cpp" />
<ClCompile Include="scripts\client\cursorposition.cpp" />
@@ -535,7 +533,6 @@
<ClCompile Include="shared\exploit_fixes\exploitfixes_lzss.cpp" />
<ClCompile Include="shared\exploit_fixes\exploitfixes_utf8parser.cpp" />
<ClCompile Include="shared\exploit_fixes\ns_limits.cpp" />
- <ClCompile Include="shared\gamepresence.cpp" />
<ClCompile Include="shared\keyvalues.cpp" />
<ClCompile Include="shared\maxplayers.cpp" />
<ClCompile Include="shared\misccommands.cpp" />
diff --git a/NorthstarDLL/NorthstarDLL.vcxproj.filters b/NorthstarDLL/NorthstarDLL.vcxproj.filters
index 7c6de46e..4530f02d 100644
--- a/NorthstarDLL/NorthstarDLL.vcxproj.filters
+++ b/NorthstarDLL/NorthstarDLL.vcxproj.filters
@@ -1029,6 +1029,9 @@
<ClInclude Include="mods\modmanager.h">
<Filter>Header Files\mods</Filter>
</ClInclude>
+ <ClInclude Include="plugins\plugin_abi.h">
+ <Filter>Header Files\plugins</Filter>
+ </ClInclude>
<ClInclude Include="plugins\plugins.h">
<Filter>Header Files\plugins</Filter>
</ClInclude>
@@ -1059,6 +1062,9 @@
<ClInclude Include="dllmain.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="ns_version.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -1152,18 +1158,6 @@
<ClInclude Include="scripts\scripthttprequesthandler.h">
<Filter>Header Files\scripts</Filter>
</ClInclude>
- <ClInclude Include="plugins\plugin_abi.h">
- <Filter>Header Files\plugins</Filter>
- </ClInclude>
- <ClInclude Include="plugins\pluginbackend.h">
- <Filter>Header Files\plugins</Filter>
- </ClInclude>
- <ClInclude Include="shared\gamepresence.h">
- <Filter>Header Files\shared</Filter>
- </ClInclude>
- <ClInclude Include="util\wininfo.h">
- <Filter>Header Files\util</Filter>
- </ClInclude>
<ClInclude Include="shared\maxplayers.h">
<Filter>Header Files\shared</Filter>
</ClInclude>
@@ -1423,15 +1417,6 @@
<ClCompile Include="scripts\scripthttprequesthandler.cpp">
<Filter>Source Files\scripts</Filter>
</ClCompile>
- <ClCompile Include="plugins\pluginbackend.cpp">
- <Filter>Source Files\plugins</Filter>
- </ClCompile>
- <ClCompile Include="shared\gamepresence.cpp">
- <Filter>Source Files\shared</Filter>
- </ClCompile>
- <ClCompile Include="util\wininfo.cpp">
- <Filter>Source Files\util</Filter>
- </ClCompile>
<ClCompile Include="core\sourceinterface.cpp">
<Filter>Source Files\core</Filter>
</ClCompile>
diff --git a/NorthstarDLL/config/profile.cpp b/NorthstarDLL/config/profile.cpp
index d5361efa..08c91208 100644
--- a/NorthstarDLL/config/profile.cpp
+++ b/NorthstarDLL/config/profile.cpp
@@ -17,6 +17,7 @@ void InitialiseNorthstarPrefix()
{
int space = cla.find(" ");
std::string dirname = cla.substr(9, space - 9);
+ spdlog::info("Found profile in command line arguments: " + dirname);
NORTHSTAR_FOLDER_PREFIX = dirname;
}
else
@@ -25,11 +26,13 @@ void InitialiseNorthstarPrefix()
int quote1 = cla.find(quote);
int quote2 = (cla.substr(quote1 + 1)).find(quote);
std::string dirname = cla.substr(quote1 + 1, quote2);
+ spdlog::info("Found profile in command line arguments: " + dirname);
NORTHSTAR_FOLDER_PREFIX = dirname;
}
}
else
{
+ spdlog::info("Profile was not found in command line arguments. Using default: R2Northstar");
NORTHSTAR_FOLDER_PREFIX = "R2Northstar";
}
diff --git a/NorthstarDLL/core/convar/concommand.cpp b/NorthstarDLL/core/convar/concommand.cpp
index 82594f04..67c867f8 100644
--- a/NorthstarDLL/core/convar/concommand.cpp
+++ b/NorthstarDLL/core/convar/concommand.cpp
@@ -2,8 +2,6 @@
#include "shared/misccommands.h"
#include "engine/r2engine.h"
-#include "plugins/pluginbackend.h"
-
#include <iostream>
//-----------------------------------------------------------------------------
@@ -150,6 +148,4 @@ ON_DLL_LOAD("engine.dll", ConCommand, (CModule module))
{
ConCommandConstructor = module.Offset(0x415F60).As<ConCommandConstructorType>();
AddMiscConCommands();
-
- g_pPluginCommunicationhandler->m_sEngineData.ConCommandConstructor = ConCommandConstructor;
}
diff --git a/NorthstarDLL/core/convar/convar.cpp b/NorthstarDLL/core/convar/convar.cpp
index d4efc1a0..1ea27fc0 100644
--- a/NorthstarDLL/core/convar/convar.cpp
+++ b/NorthstarDLL/core/convar/convar.cpp
@@ -3,8 +3,6 @@
#include "convar.h"
#include "core/sourceinterface.h"
-#include "plugins/pluginbackend.h"
-
#include <float.h>
typedef void (*ConVarRegisterType)(
@@ -39,11 +37,6 @@ ON_DLL_LOAD("engine.dll", ConVar, (CModule module))
R2::g_pCVarInterface = new SourceInterface<CCvar>("vstdlib.dll", "VEngineCvar007");
R2::g_pCVar = *R2::g_pCVarInterface;
-
- g_pPluginCommunicationhandler->m_sEngineData.conVarMalloc = conVarMalloc;
- g_pPluginCommunicationhandler->m_sEngineData.conVarRegister = conVarRegister;
- g_pPluginCommunicationhandler->m_sEngineData.ConVar_Vtable = g_pConVar_Vtable;
- g_pPluginCommunicationhandler->m_sEngineData.IConVar_Vtable = g_pIConVar_Vtable;
}
//-----------------------------------------------------------------------------
diff --git a/NorthstarDLL/core/hooks.cpp b/NorthstarDLL/core/hooks.cpp
index 9124d5af..7c70b0a5 100644
--- a/NorthstarDLL/core/hooks.cpp
+++ b/NorthstarDLL/core/hooks.cpp
@@ -274,6 +274,8 @@ AUTOHOOK_ABSOLUTEADDR(_GetCommandLineA, GetCommandLineA, LPSTR, WINAPI, ())
return cmdlineOrg;
}
memcpy(cmdlineModified, args.c_str(), len + 1);
+
+ spdlog::info("Command line: {}", cmdlineModified);
}
return cmdlineModified;
diff --git a/NorthstarDLL/core/math/color.cpp b/NorthstarDLL/core/math/color.cpp
index 7b98043a..9936cc5a 100644
--- a/NorthstarDLL/core/math/color.cpp
+++ b/NorthstarDLL/core/math/color.cpp
@@ -13,8 +13,6 @@ namespace NS::Colors
Color RPAK (255, 190, 0 );
Color NORTHSTAR (66 , 72 , 128);
Color ECHO (150, 150, 159);
- Color PLUGINSYS (244, 60 , 14);
- Color PLUGIN (244, 106, 14);
Color TRACE (0 , 255, 255);
Color DEBUG (0 , 255, 255);
diff --git a/NorthstarDLL/core/math/color.h b/NorthstarDLL/core/math/color.h
index 76cf8a47..4dc9b36e 100644
--- a/NorthstarDLL/core/math/color.h
+++ b/NorthstarDLL/core/math/color.h
@@ -186,8 +186,6 @@ namespace NS::Colors
extern Color RPAK;
extern Color NORTHSTAR;
extern Color ECHO;
- extern Color PLUGINSYS;
- extern Color PLUGIN;
extern Color TRACE;
extern Color DEBUG;
diff --git a/NorthstarDLL/dllmain.cpp b/NorthstarDLL/dllmain.cpp
index 6fc49be8..a697da5b 100644
--- a/NorthstarDLL/dllmain.cpp
+++ b/NorthstarDLL/dllmain.cpp
@@ -7,8 +7,6 @@
#include "plugins/plugins.h"
#include "util/version.h"
#include "squirrel/squirrel.h"
-#include "shared/gamepresence.h"
-#include "server/serverpresence.h"
#include "rapidjson/document.h"
#include "rapidjson/stringbuffer.h"
@@ -18,6 +16,8 @@
#include <string.h>
#include <filesystem>
+typedef void (*initPluginFuncPtr)(void* (*getPluginObject)(PluginObject));
+
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
@@ -32,6 +32,110 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
return TRUE;
}
+void freeLibrary(HMODULE hLib)
+{
+ if (!FreeLibrary(hLib))
+ {
+ spdlog::error("There was an error while trying to free library");
+ }
+}
+
+bool LoadPlugins()
+{
+
+ std::vector<fs::path> paths;
+
+ std::string pluginPath = GetNorthstarPrefix() + "/plugins";
+ if (!fs::exists(pluginPath))
+ {
+ spdlog::warn("Could not find a plugins directory. Skipped loading plugins");
+ return false;
+ }
+ // ensure dirs exist
+ fs::recursive_directory_iterator iterator(pluginPath);
+ if (std::filesystem::begin(iterator) == std::filesystem::end(iterator))
+ {
+ spdlog::warn("Could not find any plugins. Skipped loading plugins");
+ return false;
+ }
+ for (auto const& entry : iterator)
+ {
+ if (fs::is_regular_file(entry) && entry.path().extension() == ".dll")
+ paths.emplace_back(entry.path().filename());
+ }
+ initGameState();
+ for (fs::path path : paths)
+ {
+ std::string pathstring = (pluginPath / path).string();
+ std::wstring wpath = (pluginPath / path).wstring();
+
+ LPCWSTR wpptr = wpath.c_str();
+ HMODULE datafile =
+ LoadLibraryExW(wpptr, 0, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE); // Load the DLL as a data file
+ if (datafile == NULL)
+ {
+ spdlog::info("Failed to load library {}: ", std::system_category().message(GetLastError()));
+ continue;
+ }
+ HRSRC manifestResource = FindResourceW(datafile, MAKEINTRESOURCEW(101), MAKEINTRESOURCEW(RT_RCDATA));
+
+ if (manifestResource == NULL)
+ {
+ spdlog::info("Could not find manifest for library {}", pathstring);
+ freeLibrary(datafile);
+ continue;
+ }
+ spdlog::info("Loading resource from library");
+ HGLOBAL myResourceData = LoadResource(datafile, manifestResource);
+ if (myResourceData == NULL)
+ {
+ spdlog::error("Failed to load resource from library");
+ freeLibrary(datafile);
+ continue;
+ }
+ int manifestSize = SizeofResource(datafile, manifestResource);
+ std::string manifest = std::string((const char*)LockResource(myResourceData), 0, manifestSize);
+ freeLibrary(datafile);
+
+ rapidjson_document manifestJSON;
+ manifestJSON.Parse(manifest.c_str());
+
+ if (manifestJSON.HasParseError())
+ {
+ spdlog::error("Manifest for {} was invalid", pathstring);
+ continue;
+ }
+ if (!manifestJSON.HasMember("api_version"))
+ {
+ spdlog::error("{} does not have a version number in its manifest", pathstring);
+ continue;
+ // spdlog::info(manifestJSON["version"].GetString());
+ }
+ if (strcmp(manifestJSON["api_version"].GetString(), std::to_string(ABI_VERSION).c_str()))
+ {
+ spdlog::error("{} has an incompatible API version number in its manifest", pathstring);
+ continue;
+ }
+ // Passed all checks, going to actually load it now
+
+ HMODULE pluginLib = LoadLibraryW(wpptr); // Load the DLL as a data file
+ if (pluginLib == NULL)
+ {
+ spdlog::info("Failed to load library {}: ", std::system_category().message(GetLastError()));
+ continue;
+ }
+ initPluginFuncPtr initPlugin = (initPluginFuncPtr)GetProcAddress(pluginLib, "initializePlugin");
+ if (initPlugin == NULL)
+ {
+ spdlog::info("Library {} has no function initializePlugin", pathstring);
+ continue;
+ }
+ spdlog::info("Succesfully loaded {}", pathstring);
+ initPlugin(&getPluginObject);
+ }
+ return true;
+}
+
bool InitialiseNorthstar()
{
static bool bInitialised = false;
@@ -40,29 +144,13 @@ bool InitialiseNorthstar()
bInitialised = true;
- 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();
- InitialiseVersion();
- CreateLogFiles();
-
- InitialiseCrashHandler();
-
- // Write launcher version to log
- spdlog::info("NorthstarLauncher version: {}", version);
- spdlog::info("Command line: {}", GetCommandLineA());
- spdlog::info("Using profile: {}", GetNorthstarPrefix());
-
- InstallInitialHooks();
- g_pServerPresence = new ServerPresenceManager();
-
- g_pGameStatePresence = new GameStatePresence();
- g_pPluginManager = new PluginManager();
- g_pPluginManager->LoadPlugins();
+ InitialiseNorthstarPrefix();
+ InitialiseVersion();
InitialiseSquirrelManagers();
@@ -71,6 +159,13 @@ bool InitialiseNorthstar()
curl_global_init_mem(CURL_GLOBAL_DEFAULT, _malloc_base, _free_base, _realloc_base, _strdup_base, _calloc_base);
+ InitialiseCrashHandler();
+ InstallInitialHooks();
+ CreateLogFiles();
+
+ // Write launcher version to log
+ spdlog::info("NorthstarLauncher version: {}", version);
+
// run callbacks for any libraries that are already loaded by now
CallAllPendingDLLLoadCallbacks();
diff --git a/NorthstarDLL/engine/hoststate.cpp b/NorthstarDLL/engine/hoststate.cpp
index 50862e99..bd4a242f 100644
--- a/NorthstarDLL/engine/hoststate.cpp
+++ b/NorthstarDLL/engine/hoststate.cpp
@@ -7,8 +7,6 @@
#include "engine/r2engine.h"
#include "shared/exploit_fixes/ns_limits.h"
#include "squirrel/squirrel.h"
-#include "plugins/plugins.h"
-#include "plugins/pluginbackend.h"
AUTOHOOK_INIT()
@@ -186,8 +184,6 @@ void, __fastcall, (CHostState* self, double flCurrentTime, float flFrameTime))
if (g_pSquirrel<ScriptContext::SERVER>->m_pSQVM != nullptr && g_pSquirrel<ScriptContext::SERVER>->m_pSQVM->sqvm != nullptr)
g_pSquirrel<ScriptContext::SERVER>->ProcessMessageBuffer();
-
- g_pGameStatePresence->RunFrame();
}
ON_DLL_LOAD_RELIESON("engine.dll", HostState, ConVar, (CModule module))
diff --git a/NorthstarDLL/logging/logging.cpp b/NorthstarDLL/logging/logging.cpp
index 53795ef0..f88928e1 100644
--- a/NorthstarDLL/logging/logging.cpp
+++ b/NorthstarDLL/logging/logging.cpp
@@ -28,7 +28,6 @@ namespace NS::log
std::shared_ptr<ColoredLogger> echo;
std::shared_ptr<ColoredLogger> NORTHSTAR;
- std::shared_ptr<ColoredLogger> PLUGINSYS;
}; // namespace NS::log
// This needs to be called after hooks are loaded so we can access the command line args
@@ -149,11 +148,6 @@ void InitialiseConsole()
}
}
-void RegisterLogger(std::shared_ptr<ColoredLogger> logger)
-{
- loggers.push_back(logger);
-}
-
void RegisterCustomSink(std::shared_ptr<CustomSink> sink)
{
for (auto& logger : loggers)
@@ -195,8 +189,6 @@ void InitialiseLogging()
NS::log::rpak = std::make_shared<ColoredLogger>("RPAK_FSYS", NS::Colors::RPAK);
NS::log::echo = std::make_shared<ColoredLogger>("ECHO", NS::Colors::ECHO);
- NS::log::PLUGINSYS = std::make_shared<ColoredLogger>("PLUGINSYS", NS::Colors::PLUGINSYS);
-
loggers.push_back(NS::log::SCRIPT_UI);
loggers.push_back(NS::log::SCRIPT_CL);
loggers.push_back(NS::log::SCRIPT_SV);
@@ -206,8 +198,6 @@ void InitialiseLogging()
loggers.push_back(NS::log::NATIVE_SV);
loggers.push_back(NS::log::NATIVE_EN);
- loggers.push_back(NS::log::PLUGINSYS);
-
loggers.push_back(NS::log::fs);
loggers.push_back(NS::log::rpak);
loggers.push_back(NS::log::echo);
diff --git a/NorthstarDLL/logging/logging.h b/NorthstarDLL/logging/logging.h
index 2efee80b..1cfc6644 100644
--- a/NorthstarDLL/logging/logging.h
+++ b/NorthstarDLL/logging/logging.h
@@ -100,13 +100,10 @@ namespace NS::log
extern std::shared_ptr<ColoredLogger> NORTHSTAR;
- extern std::shared_ptr<ColoredLogger> PLUGINSYS;
-
void FlushLoggers();
}; // namespace NS::log
void RegisterCustomSink(std::shared_ptr<CustomSink> sink);
-void RegisterLogger(std::shared_ptr<ColoredLogger> logger);
inline bool g_bSpdLog_UseAnsiColor = true;
diff --git a/NorthstarDLL/masterserver/masterserver.cpp b/NorthstarDLL/masterserver/masterserver.cpp
index 015670e7..d9838484 100644
--- a/NorthstarDLL/masterserver/masterserver.cpp
+++ b/NorthstarDLL/masterserver/masterserver.cpp
@@ -576,7 +576,7 @@ void MasterServerManager::AuthenticateWithOwnServer(const char* uid, const char*
requestThread.detach();
}
-void MasterServerManager::AuthenticateWithServer(const char* uid, const char* playerToken, RemoteServerInfo server, const char* password)
+void MasterServerManager::AuthenticateWithServer(const char* uid, const char* playerToken, const char* serverId, const char* password)
{
// dont wait, just stop if we're trying to do 2 auth requests at once
if (m_bAuthenticatingWithGameServer)
@@ -589,11 +589,11 @@ void MasterServerManager::AuthenticateWithServer(const char* uid, const char* pl
std::string uidStr(uid);
std::string tokenStr(playerToken);
- std::string serverIdStr(server.id);
+ std::string serverIdStr(serverId);
std::string passwordStr(password);
std::thread requestThread(
- [this, uidStr, tokenStr, serverIdStr, passwordStr, server]()
+ [this, uidStr, tokenStr, serverIdStr, passwordStr]()
{
// esnure that any persistence saving is done, so we know masterserver has newest
while (m_bSavingPersistentData)
@@ -691,9 +691,6 @@ void MasterServerManager::AuthenticateWithServer(const char* uid, const char* pl
m_bHasPendingConnectionInfo = true;
m_bSuccessfullyAuthenticatedWithGameServer = true;
-
- m_currentServer = server;
- m_sCurrentServerPassword = passwordStr;
}
else
{
diff --git a/NorthstarDLL/masterserver/masterserver.h b/NorthstarDLL/masterserver/masterserver.h
index e87b31a2..623d7d43 100644
--- a/NorthstarDLL/masterserver/masterserver.h
+++ b/NorthstarDLL/masterserver/masterserver.h
@@ -114,9 +114,6 @@ class MasterServerManager
bool m_bHasMainMenuPromoData = false;
MainMenuPromoData m_sMainMenuPromoData;
- std::optional<RemoteServerInfo> m_currentServer;
- std::string m_sCurrentServerPassword;
-
std::unordered_set<std::string> m_handledServerConnections;
public:
@@ -127,7 +124,7 @@ class MasterServerManager
void RequestMainMenuPromos();
void AuthenticateOriginWithMasterServer(const char* uid, const char* originToken);
void AuthenticateWithOwnServer(const char* uid, const char* playerToken);
- void AuthenticateWithServer(const char* uid, const char* playerToken, RemoteServerInfo server, const char* password);
+ void AuthenticateWithServer(const char* uid, const char* playerToken, const char* serverId, const char* password);
void WritePlayerPersistentData(const char* playerId, const char* pdata, size_t pdataSize);
void ProcessConnectionlessPacketSigreq1(std::string req);
};
diff --git a/NorthstarDLL/mods/modmanager.cpp b/NorthstarDLL/mods/modmanager.cpp
index 8ac9ac54..3ec922f4 100644
--- a/NorthstarDLL/mods/modmanager.cpp
+++ b/NorthstarDLL/mods/modmanager.cpp
@@ -241,11 +241,6 @@ Mod::Mod(fs::path modDir, char* jsonBuf)
}
}
- if (modJson.HasMember("InitScript") && modJson["InitScript"].IsString())
- {
- initScript = modJson["InitScript"].GetString();
- }
-
if (modJson.HasMember("Localisation") && modJson["Localisation"].IsArray())
{
for (auto& localisationStr : modJson["Localisation"].GetArray())
diff --git a/NorthstarDLL/mods/modmanager.h b/NorthstarDLL/mods/modmanager.h
index a4c72f77..369eb07b 100644
--- a/NorthstarDLL/mods/modmanager.h
+++ b/NorthstarDLL/mods/modmanager.h
@@ -103,8 +103,6 @@ class Mod
std::vector<ModConCommand*> ConCommands;
// custom localisation files created by the mod
std::vector<std::string> LocalisationFiles;
- // custom script init.nut
- std::string initScript;
// other files:
diff --git a/NorthstarDLL/pch.h b/NorthstarDLL/pch.h
index 9ad8378c..55ebba8b 100644
--- a/NorthstarDLL/pch.h
+++ b/NorthstarDLL/pch.h
@@ -20,11 +20,6 @@
namespace fs = std::filesystem;
-#define EXPORT extern "C" __declspec(dllexport)
-
-typedef void (*callable)();
-typedef void (*callable_v)(void* v);
-
// clang-format off
#define assert_msg(exp, msg) assert((exp, msg))
//clang-format on
@@ -33,7 +28,6 @@ typedef void (*callable_v)(void* v);
#include "core/structs.h"
#include "core/math/color.h"
-
#include "spdlog/spdlog.h"
#include "logging/logging.h"
#include "MinHook.h"
diff --git a/NorthstarDLL/plugins/plugin_abi.h b/NorthstarDLL/plugins/plugin_abi.h
index c9fa9d25..4b176a32 100644
--- a/NorthstarDLL/plugins/plugin_abi.h
+++ b/NorthstarDLL/plugins/plugin_abi.h
@@ -1,164 +1,68 @@
#pragma once
#include <string>
-#include "squirrel/squirrelclasstypes.h"
-#define ABI_VERSION 2
-
-enum GameState
+#define ABI_VERSION 1
+/// <summary>
+/// This enum is used for referencing the different types of objects we can pass to a plugin
+/// Anything exposed to a plugin must not a be C++ type, as they could break when compiling with a different compiler.
+/// Any ABI incompatible change must increment the version number.
+/// Nothing must be removed from this enum, only appended. When it absolutely necessary to deprecate an object, it should return UNSUPPORTED
+/// when retrieved
+/// </summary>
+enum PluginObject
{
- LOADING = 0,
- MAINMENU = 1,
- LOBBY = 2,
- INGAME = 3
+ UNSUPPORTED = 0,
+ GAMESTATE = 1,
+ SERVERINFO = 2,
+ PLAYERINFO = 3,
+ DUMMY = 0xFFFF
};
-enum PluginLoadDLL
+enum GameStateInfoType
{
- ENGINE = 0,
- CLIENT,
- SERVER
+ ourScore = 0,
+ secondHighestScore = 1,
+ highestScore = 2,
+ connected = 3,
+ loading = 4,
+ map = 5,
+ mapDisplayName = 6,
+ playlist = 7,
+ playlistDisplayName = 8,
+ players = 9
};
-
-enum ObjectType
+struct GameState
{
- CONCOMMANDS = 0,
- CONVAR = 1,
+ int (*getGameStateChar)(char* out_buf, size_t out_buf_len, GameStateInfoType var);
+ int (*getGameStateInt)(int* out_ptr, GameStateInfoType var);
+ int (*getGameStateBool)(bool* out_ptr, GameStateInfoType var);
};
-struct SquirrelFunctions
+enum ServerInfoType
{
- RegisterSquirrelFuncType RegisterSquirrelFunc;
- sq_defconstType __sq_defconst;
-
- sq_compilebufferType __sq_compilebuffer;
- sq_callType __sq_call;
- sq_raiseerrorType __sq_raiseerror;
-
- sq_newarrayType __sq_newarray;
- sq_arrayappendType __sq_arrayappend;
-
- sq_newtableType __sq_newtable;
- sq_newslotType __sq_newslot;
-
- sq_pushroottableType __sq_pushroottable;
- sq_pushstringType __sq_pushstring;
- sq_pushintegerType __sq_pushinteger;
- sq_pushfloatType __sq_pushfloat;
- sq_pushboolType __sq_pushbool;
- sq_pushassetType __sq_pushasset;
- sq_pushvectorType __sq_pushvector;
- sq_pushobjectType __sq_pushobject;
- sq_getthisentityType __sq_getthisentity;
- sq_getobjectType __sq_getobject;
-
- sq_stackinfosType __sq_stackinfos;
-
- sq_getstringType __sq_getstring;
- sq_getintegerType __sq_getinteger;
- sq_getfloatType __sq_getfloat;
- sq_getboolType __sq_getbool;
- sq_getType __sq_get;
- sq_getassetType __sq_getasset;
- sq_getuserdataType __sq_getuserdata;
- sq_getvectorType __sq_getvector;
-
- sq_createuserdataType __sq_createuserdata;
- sq_setuserdatatypeidType __sq_setuserdatatypeid;
- sq_getfunctionType __sq_getfunction;
-
- sq_schedule_call_externalType __sq_schedule_call_external;
- sq_getentityfrominstanceType __sq_getentityfrominstance;
- sq_GetEntityConstantType __sq_GetEntityConstant_CBaseEntity;
-};
-
-struct MessageSource
-{
- const char* file;
- const char* func;
- int line;
+ id = 0,
+ name = 1,
+ description = 2,
+ password = 3,
+ maxPlayers = 4,
+ roundBased = 5,
+ scoreLimit = 6,
+ endTime = 7
};
-
-// This is a modified version of spdlog::details::log_msg
-// This is so that we can make it cross DLL boundaries
-struct LogMsg
+struct ServerInfo
{
- int level;
- uint64_t timestamp;
- const char* msg;
- MessageSource source;
- int pluginHandle;
+ int (*getServerInfoChar)(char* out_buf, size_t out_buf_len, ServerInfoType var);
+ int (*getServerInfoInt)(int* out_ptr, ServerInfoType var);
+ int (*getServerInfoBool)(bool* out_ptr, ServerInfoType var);
};
-typedef void (*loggerfunc_t)(LogMsg* msg);
-typedef void (*PLUGIN_RELAY_INVITE_TYPE)(const char* invite);
-typedef void* (*CreateObjectFunc)(ObjectType type);
-
-struct PluginNorthstarData
+enum PlayerInfoType
{
- const char* version;
- HMODULE northstarModule;
- int pluginHandle;
+ uid = 0
};
-
-struct PluginInitFuncs
+struct PlayerInfo
{
- loggerfunc_t logger;
- PLUGIN_RELAY_INVITE_TYPE relayInviteFunc;
- CreateObjectFunc createObject;
+ int (*getPlayerInfoChar)(char* out_buf, size_t out_buf_len, PlayerInfoType var);
+ int (*getPlayerInfoInt)(int* out_ptr, PlayerInfoType var);
+ int (*getPlayerInfoBool)(bool* out_ptr, PlayerInfoType var);
};
-
-struct PluginEngineData
-{
- void* ConCommandConstructor;
- void* conVarMalloc;
- void* conVarRegister;
- void* ConVar_Vtable;
- void* IConVar_Vtable;
-};
-
-struct PluginGameStatePresence
-{
- const char* id;
- const char* name;
- const char* description;
- const char* password;
-
- bool isServer;
- bool isLocal;
- GameState state;
-
- const char* map;
- const char* mapDisplayname;
- const char* playlist;
- const char* playlistDisplayname;
-
- int currentPlayers;
- int maxPlayers;
-
- int ownScore;
- int otherHighestScore; // NOTE: The highest score OR the second highest score if we have the highest
- int maxScore;
-
- int timestampEnd;
-};
-
-/// <summary> Async communication within the plugin system
-/// Due to the asynchronous nature of plugins, combined with the limitations of multi-compiler support
-/// and the custom memory allocator used by r2, is it difficult to safely get data across DLL boundaries
-/// from Northstar to plugin unless Northstar can own that memory.
-/// This means that plugins should manage their own memory and can only receive data from northstar using one of the functions below.
-/// These should be exports of the plugin DLL. If they are not exported, they will not be called.
-/// Note that it is not required to have these exports if you do not use them.
-/// </summary>
-
-// Northstar -> Plugin
-typedef void (*PLUGIN_INIT_TYPE)(PluginInitFuncs* funcs, PluginNorthstarData* data);
-typedef void (*PLUGIN_INIT_SQVM_TYPE)(SquirrelFunctions* funcs);
-typedef void (*PLUGIN_INFORM_SQVM_CREATED_TYPE)(ScriptContext context, CSquirrelVM* sqvm);
-typedef void (*PLUGIN_INFORM_SQVM_DESTROYED_TYPE)(ScriptContext context);
-
-// Async Communication types
-
-// Northstar -> Plugin
-typedef void (*PLUGIN_PUSH_PRESENCE_TYPE)(PluginGameStatePresence* data);
-typedef void (*PLUGIN_INFORM_DLL_LOAD_TYPE)(PluginLoadDLL dll, void* data);
diff --git a/NorthstarDLL/plugins/pluginbackend.cpp b/NorthstarDLL/plugins/pluginbackend.cpp
deleted file mode 100644
index b442d702..00000000
--- a/NorthstarDLL/plugins/pluginbackend.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-#include "pch.h"
-#include "pluginbackend.h"
-#include "plugin_abi.h"
-#include "server/serverpresence.h"
-#include "masterserver/masterserver.h"
-#include "squirrel/squirrel.h"
-#include "plugins.h"
-
-#include "core/convar/concommand.h"
-
-#define EXPORT extern "C" __declspec(dllexport)
-
-AUTOHOOK_INIT()
-
-PluginCommunicationHandler* g_pPluginCommunicationhandler;
-
-static PluginDataRequest storedRequest {PluginDataRequestType::END, (PluginRespondDataCallable) nullptr};
-
-void init_plugincommunicationhandler()
-{
- g_pPluginCommunicationhandler = new PluginCommunicationHandler;
- g_pPluginCommunicationhandler->requestQueue = {};
-}
-
-void PluginCommunicationHandler::RunFrame()
-{
- std::lock_guard<std::mutex> lock(requestMutex);
- if (!requestQueue.empty())
- {
- storedRequest = requestQueue.front();
- switch (storedRequest.type)
- {
- default:
- spdlog::error("{} was called with invalid request type '{}'", __FUNCTION__, static_cast<int>(storedRequest.type));
- }
- requestQueue.pop();
- }
-}
-
-void PluginCommunicationHandler::PushRequest(PluginDataRequestType type, PluginRespondDataCallable func)
-{
- std::lock_guard<std::mutex> lock(requestMutex);
- requestQueue.push(PluginDataRequest {type, func});
-}
-
-void PluginCommunicationHandler::GeneratePresenceObjects()
-{
- PluginGameStatePresence presence {};
-
- presence.id = g_pGameStatePresence->id.c_str();
- presence.name = g_pGameStatePresence->name.c_str();
- presence.description = g_pGameStatePresence->description.c_str();
- presence.password = g_pGameStatePresence->password.c_str();
-
- presence.isServer = g_pGameStatePresence->isServer;
- presence.isLocal = g_pGameStatePresence->isLocal;
-
- if (g_pGameStatePresence->isLoading)
- presence.state = GameState::LOADING;
- else if (g_pGameStatePresence->uiMap == "")
- presence.state = GameState::MAINMENU;
- else if (g_pGameStatePresence->map == "mp_lobby" && g_pGameStatePresence->isLocal && g_pGameStatePresence->isLobby)
- presence.state = GameState::LOBBY;
- else
- presence.state = GameState::INGAME;
-
- presence.map = g_pGameStatePresence->map.c_str();
- presence.mapDisplayname = g_pGameStatePresence->mapDisplayname.c_str();
- presence.playlist = g_pGameStatePresence->playlist.c_str();
- presence.playlistDisplayname = g_pGameStatePresence->playlistDisplayname.c_str();
-
- presence.currentPlayers = g_pGameStatePresence->currentPlayers;
- presence.maxPlayers = g_pGameStatePresence->maxPlayers;
- presence.ownScore = g_pGameStatePresence->ownScore;
- presence.otherHighestScore = g_pGameStatePresence->otherHighestScore;
- presence.maxScore = g_pGameStatePresence->maxScore;
- presence.timestampEnd = g_pGameStatePresence->timestampEnd;
- g_pPluginManager->PushPresence(&presence);
-}
-
-ON_DLL_LOAD_RELIESON("engine.dll", PluginBackendEngine, ConCommand, (CModule module))
-{
- g_pPluginManager->InformDLLLoad(PluginLoadDLL::ENGINE, &g_pPluginCommunicationhandler->m_sEngineData);
-}
-
-ON_DLL_LOAD_RELIESON("client.dll", PluginBackendClient, ConCommand, (CModule module))
-{
- g_pPluginManager->InformDLLLoad(PluginLoadDLL::CLIENT, nullptr);
-}
-
-ON_DLL_LOAD_RELIESON("server.dll", PluginBackendServer, ConCommand, (CModule module))
-{
- g_pPluginManager->InformDLLLoad(PluginLoadDLL::SERVER, nullptr);
-}
diff --git a/NorthstarDLL/plugins/pluginbackend.h b/NorthstarDLL/plugins/pluginbackend.h
deleted file mode 100644
index ef42c508..00000000
--- a/NorthstarDLL/plugins/pluginbackend.h
+++ /dev/null
@@ -1,45 +0,0 @@
-#pragma once
-#include "pch.h"
-#include "plugin_abi.h"
-#include "shared/gamepresence.h"
-
-#include <queue>
-#include <mutex>
-
-enum PluginDataRequestType
-{
- END = 0,
-};
-
-union PluginRespondDataCallable
-{
- // Empty for now
- void* UNUSED;
-};
-
-class PluginDataRequest
-{
- public:
- PluginDataRequestType type;
- PluginRespondDataCallable func;
- PluginDataRequest(PluginDataRequestType type, PluginRespondDataCallable func) : type(type), func(func) {}
-};
-
-class PluginCommunicationHandler
-{
- public:
- void RunFrame();
- void PushRequest(PluginDataRequestType type, PluginRespondDataCallable func);
-
- void GeneratePresenceObjects();
-
- public:
- std::queue<PluginDataRequest> requestQueue;
- std::mutex requestMutex;
-
- PluginEngineData m_sEngineData {};
-};
-
-void init_plugincommunicationhandler();
-
-extern PluginCommunicationHandler* g_pPluginCommunicationhandler;
diff --git a/NorthstarDLL/plugins/plugins.cpp b/NorthstarDLL/plugins/plugins.cpp
index 6e3ceb5a..47d27da1 100644
--- a/NorthstarDLL/plugins/plugins.cpp
+++ b/NorthstarDLL/plugins/plugins.cpp
@@ -1,292 +1,421 @@
-#include "plugins.h"
-#include "config/profile.h"
-
#include "squirrel/squirrel.h"
#include "plugins.h"
#include "masterserver/masterserver.h"
#include "core/convar/convar.h"
#include "server/serverpresence.h"
-#include <optional>
-
-#include "util/version.h"
-#include "pluginbackend.h"
-#include "util/wininfo.h"
-#include "logging/logging.h"
-#include "dedicated/dedicated.h"
-PluginManager* g_pPluginManager;
+#include <chrono>
+#include <windows.h>
-void freeLibrary(HMODULE hLib)
+/// <summary>
+/// The data is split into two different representations: one for internal, and one for plugins, for thread safety reasons
+/// The struct exposed to plugins contains getter functions for the various data types.
+/// We can safely use C++ types like std::string here since these are only ever handled by Northstar internally
+/// </summary>
+struct InternalGameState
+{
+ int ourScore;
+ int secondHighestScore;
+ int highestScore;
+
+ bool connected;
+ bool loading;
+ std::string map;
+ std::string mapDisplayName;
+ std::string playlist;
+ std::string playlistDisplayName;
+ int players;
+};
+struct InternalServerInfo
+{
+ std::string id;
+ std::string name;
+ std::string description;
+ std::string password;
+ int maxPlayers;
+ bool roundBased;
+ int scoreLimit;
+ int endTime;
+};
+// TODO: need to extend this to include current player data like loadouts
+struct InternalPlayerInfo
+{
+ int uid;
+};
+
+InternalGameState gameState;
+InternalServerInfo serverInfo;
+InternalPlayerInfo playerInfo;
+
+GameState gameStateExport;
+ServerInfo serverInfoExport;
+PlayerInfo playerInfoExport;
+
+/// <summary>
+/// We use SRW Locks because plugins will often be running their own thread
+/// To ensure thread safety, and to make it difficult to fuck up, we force them to use *our* functions to get data
+/// </summary>
+static SRWLOCK gameStateLock;
+static SRWLOCK serverInfoLock;
+static SRWLOCK playerInfoLock;
+
+void* getPluginObject(PluginObject var)
{
- if (!FreeLibrary(hLib))
+ switch (var)
{
- spdlog::error("There was an error while trying to free library");
+ case PluginObject::GAMESTATE:
+ return &gameStateExport;
+ case PluginObject::SERVERINFO:
+ return &serverInfoExport;
+ case PluginObject::PLAYERINFO:
+ return &playerInfoExport;
+ default:
+ return (void*)-1;
}
}
-EXPORT void PLUGIN_LOG(LogMsg* msg)
+void initGameState()
{
- spdlog::source_loc src {};
- src.filename = msg->source.file;
- src.funcname = msg->source.func;
- src.line = msg->source.line;
- auto&& logger = g_pPluginManager->m_vLoadedPlugins[msg->pluginHandle].logger;
- logger->log(src, (spdlog::level::level_enum)msg->level, msg->msg);
+ // Initalize the Slim Reader / Writer locks
+ InitializeSRWLock(&gameStateLock);
+ InitializeSRWLock(&serverInfoLock);
+ InitializeSRWLock(&playerInfoLock);
+
+ gameStateExport.getGameStateChar = &getGameStateChar;
+ gameStateExport.getGameStateInt = &getGameStateInt;
+ gameStateExport.getGameStateBool = &getGameStateBool;
+
+ serverInfoExport.getServerInfoChar = &getServerInfoChar;
+ serverInfoExport.getServerInfoInt = &getServerInfoInt;
+ serverInfoExport.getServerInfoBool = &getServerInfoBool;
+
+ playerInfoExport.getPlayerInfoChar = &getPlayerInfoChar;
+ playerInfoExport.getPlayerInfoInt = &getPlayerInfoInt;
+ playerInfoExport.getPlayerInfoBool = &getPlayerInfoBool;
+
+ serverInfo.id = "";
+ serverInfo.name = "";
+ serverInfo.description = "";
+ serverInfo.password = "";
+ serverInfo.maxPlayers = 0;
+ gameState.connected = false;
+ gameState.loading = false;
+ gameState.map = "";
+ gameState.mapDisplayName = "";
+ gameState.playlist = "";
+ gameState.playlistDisplayName = "";
+ gameState.players = 0;
+
+ playerInfo.uid = 123;
}
-EXPORT void* CreateObject(ObjectType type)
+// string gamemode, string gamemodeName, string map, string mapName, bool connected, bool loading
+SQRESULT SQ_UpdateGameStateUI(HSquirrelVM* sqvm)
{
- switch (type)
- {
- case ObjectType::CONVAR:
- return (void*)new ConVar;
- case ObjectType::CONCOMMANDS:
- return (void*)new ConCommand;
- default:
- return NULL;
- }
+ AcquireSRWLockExclusive(&gameStateLock);
+ gameState.map = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 1);
+ gameState.mapDisplayName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 2);
+ gameState.playlist = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 3);
+ gameState.playlistDisplayName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 4);
+ gameState.connected = g_pSquirrel<ScriptContext::UI>->getbool(sqvm, 5);
+ gameState.loading = g_pSquirrel<ScriptContext::UI>->getbool(sqvm, 6);
+ ReleaseSRWLockExclusive(&gameStateLock);
+ return SQRESULT_NOTNULL;
}
-std::optional<Plugin> PluginManager::LoadPlugin(fs::path path, PluginInitFuncs* funcs, PluginNorthstarData* data)
+// int playerCount, int outScore, int secondHighestScore, int highestScore, bool roundBased, int scoreLimit
+SQRESULT SQ_UpdateGameStateClient(HSquirrelVM* sqvm)
{
+ AcquireSRWLockExclusive(&gameStateLock);
+ AcquireSRWLockExclusive(&serverInfoLock);
+ gameState.players = g_pSquirrel<ScriptContext::CLIENT>->getinteger(sqvm, 1);
+ serverInfo.maxPlayers = g_pSquirrel<ScriptContext::CLIENT>->getinteger(sqvm, 2);
+ gameState.ourScore = g_pSquirrel<ScriptContext::CLIENT>->getinteger(sqvm, 3);
+ gameState.secondHighestScore = g_pSquirrel<ScriptContext::CLIENT>->getinteger(sqvm, 4);
+ gameState.highestScore = g_pSquirrel<ScriptContext::CLIENT>->getinteger(sqvm, 5);
+ serverInfo.roundBased = g_pSquirrel<ScriptContext::CLIENT>->getbool(sqvm, 6);
+ serverInfo.scoreLimit = g_pSquirrel<ScriptContext::CLIENT>->getbool(sqvm, 7);
+ ReleaseSRWLockExclusive(&gameStateLock);
+ ReleaseSRWLockExclusive(&serverInfoLock);
+ return SQRESULT_NOTNULL;
+}
- Plugin plugin {};
+// string id, string name, string password, int players, int maxPlayers, string map, string mapDisplayName, string playlist, string
+// playlistDisplayName
+SQRESULT SQ_UpdateServerInfo(HSquirrelVM* sqvm)
+{
+ AcquireSRWLockExclusive(&gameStateLock);
+ AcquireSRWLockExclusive(&serverInfoLock);
+ serverInfo.id = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 1);
+ serverInfo.name = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 2);
+ serverInfo.password = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 3);
+ gameState.players = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 4);
+ serverInfo.maxPlayers = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 5);
+ gameState.map = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 6);
+ gameState.mapDisplayName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 7);
+ gameState.playlist = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 8);
+ gameState.playlistDisplayName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 9);
+ ReleaseSRWLockExclusive(&gameStateLock);
+ ReleaseSRWLockExclusive(&serverInfoLock);
+ return SQRESULT_NOTNULL;
+}
- std::string pathstring = (pluginPath / path).string();
- std::wstring wpath = (pluginPath / path).wstring();
+// int maxPlayers
+SQRESULT SQ_UpdateServerInfoBetweenRounds(HSquirrelVM* sqvm)
+{
+ AcquireSRWLockExclusive(&serverInfoLock);
+ serverInfo.id = g_pSquirrel<ScriptContext::CLIENT>->getstring(sqvm, 1);
+ serverInfo.name = g_pSquirrel<ScriptContext::CLIENT>->getstring(sqvm, 2);
+ serverInfo.password = g_pSquirrel<ScriptContext::CLIENT>->getstring(sqvm, 3);
+ serverInfo.maxPlayers = g_pSquirrel<ScriptContext::CLIENT>->getinteger(sqvm, 4);
+ ReleaseSRWLockExclusive(&serverInfoLock);
+ return SQRESULT_NOTNULL;
+}
- LPCWSTR wpptr = wpath.c_str();
- HMODULE datafile = LoadLibraryExW(wpptr, 0, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE); // Load the DLL as a data file
- if (datafile == NULL)
- {
- NS::log::PLUGINSYS->info("Failed to load library '{}': ", std::system_category().message(GetLastError()));
- return std::nullopt;
- }
- HRSRC manifestResource = FindResourceW(datafile, MAKEINTRESOURCEW(IDR_RCDATA1), MAKEINTRESOURCEW(RT_RCDATA));
+// float timeInFuture
+SQRESULT SQ_UpdateTimeInfo(HSquirrelVM* sqvm)
+{
+ AcquireSRWLockExclusive(&serverInfoLock);
+ serverInfo.endTime = ceil(g_pSquirrel<ScriptContext::CLIENT>->getfloat(sqvm, 1));
+ ReleaseSRWLockExclusive(&serverInfoLock);
+ return SQRESULT_NOTNULL;
+}
- if (manifestResource == NULL)
- {
- NS::log::PLUGINSYS->info("Could not find manifest for library '{}'", pathstring);
- freeLibrary(datafile);
- return std::nullopt;
- }
- HGLOBAL myResourceData = LoadResource(datafile, manifestResource);
- if (myResourceData == NULL)
- {
- NS::log::PLUGINSYS->error("Failed to load manifest from library '{}'", pathstring);
- freeLibrary(datafile);
- return std::nullopt;
- }
- int manifestSize = SizeofResource(datafile, manifestResource);
- std::string manifest = std::string((const char*)LockResource(myResourceData), 0, manifestSize);
- freeLibrary(datafile);
+// bool loading
+SQRESULT SQ_SetConnected(HSquirrelVM* sqvm)
+{
+ AcquireSRWLockExclusive(&gameStateLock);
+ gameState.loading = g_pSquirrel<ScriptContext::UI>->getbool(sqvm, 1);
+ ReleaseSRWLockExclusive(&gameStateLock);
+ return SQRESULT_NOTNULL;
+}
- rapidjson_document manifestJSON;
- manifestJSON.Parse(manifest.c_str());
+SQRESULT SQ_UpdateListenServer(HSquirrelVM* sqvm)
+{
+ AcquireSRWLockExclusive(&serverInfoLock);
+ serverInfo.id = g_pMasterServerManager->m_sOwnServerId;
+ serverInfo.password = ""; // g_pServerPresence->Cvar_ns_server_password->GetString(); todo this fr
+ ReleaseSRWLockExclusive(&serverInfoLock);
+ return SQRESULT_NOTNULL;
+}
- if (manifestJSON.HasParseError())
- {
- NS::log::PLUGINSYS->error("Manifest for '{}' was invalid", pathstring);
- return std::nullopt;
- }
- if (!manifestJSON.HasMember("name"))
- {
- NS::log::PLUGINSYS->error("'{}' is missing a name in its manifest", pathstring);
- return std::nullopt;
- }
- if (!manifestJSON.HasMember("displayname"))
- {
- NS::log::PLUGINSYS->error("'{}' is missing a displayname in its manifest", pathstring);
- return std::nullopt;
- }
- if (!manifestJSON.HasMember("description"))
- {
- NS::log::PLUGINSYS->error("'{}' is missing a description in its manifest", pathstring);
- return std::nullopt;
- }
- if (!manifestJSON.HasMember("api_version"))
- {
- NS::log::PLUGINSYS->error("'{}' is missing a api_version in its manifest", pathstring);
- return std::nullopt;
- }
- if (!manifestJSON.HasMember("version"))
- {
- NS::log::PLUGINSYS->error("'{}' is missing a version in its manifest", pathstring);
- return std::nullopt;
- }
- if (!manifestJSON.HasMember("run_on_server"))
- {
- NS::log::PLUGINSYS->error("'{}' is missing 'run_on_server' in its manifest", pathstring);
- return std::nullopt;
- }
- if (!manifestJSON.HasMember("run_on_client"))
- {
- NS::log::PLUGINSYS->error("'{}' is missing 'run_on_client' in its manifest", pathstring);
- return std::nullopt;
- }
- auto test = manifestJSON["api_version"].GetString();
- if (strcmp(manifestJSON["api_version"].GetString(), std::to_string(ABI_VERSION).c_str()))
+int getServerInfoChar(char* out_buf, size_t out_buf_len, ServerInfoType var)
+{
+ AcquireSRWLockShared(&serverInfoLock);
+ int n = 0;
+ switch (var)
{
- NS::log::PLUGINSYS->error(
- "'{}' has an incompatible API version number '{}' in its manifest. Current ABI version is '{}'", pathstring, ABI_VERSION);
- return std::nullopt;
+ case ServerInfoType::id:
+ strncpy(out_buf, serverInfo.id.c_str(), out_buf_len);
+ break;
+ case ServerInfoType::name:
+ strncpy(out_buf, serverInfo.name.c_str(), out_buf_len);
+ break;
+ case ServerInfoType::description:
+ strncpy(out_buf, serverInfo.id.c_str(), out_buf_len);
+ break;
+ case ServerInfoType::password:
+ strncpy(out_buf, serverInfo.password.c_str(), out_buf_len);
+ break;
+ default:
+ n = -1;
}
- // Passed all checks, going to actually load it now
- HMODULE pluginLib = LoadLibraryW(wpptr); // Load the DLL as a data file
- if (pluginLib == NULL)
- {
- NS::log::PLUGINSYS->info("Failed to load library '{}': ", std::system_category().message(GetLastError()));
- return std::nullopt;
- }
- plugin.init = (PLUGIN_INIT_TYPE)GetProcAddress(pluginLib, "PLUGIN_INIT");
- if (plugin.init == NULL)
+ ReleaseSRWLockShared(&serverInfoLock);
+
+ return n;
+}
+int getServerInfoInt(int* out_ptr, ServerInfoType var)
+{
+ AcquireSRWLockShared(&serverInfoLock);
+ int n = 0;
+ switch (var)
{
- NS::log::PLUGINSYS->info("Library '{}' has no function 'PLUGIN_INIT'", pathstring);
- return std::nullopt;
+ case ServerInfoType::maxPlayers:
+ *out_ptr = serverInfo.maxPlayers;
+ break;
+ case ServerInfoType::scoreLimit:
+ *out_ptr = serverInfo.scoreLimit;
+ break;
+ case ServerInfoType::endTime:
+ *out_ptr = serverInfo.endTime;
+ break;
+ default:
+ n = -1;
}
- NS::log::PLUGINSYS->info("Succesfully loaded {}", pathstring);
- plugin.name = manifestJSON["name"].GetString();
- plugin.displayName = manifestJSON["displayname"].GetString();
- plugin.description = manifestJSON["description"].GetString();
- plugin.api_version = manifestJSON["api_version"].GetString();
- plugin.version = manifestJSON["version"].GetString();
+ ReleaseSRWLockShared(&serverInfoLock);
- plugin.run_on_client = manifestJSON["run_on_client"].GetBool();
- plugin.run_on_server = manifestJSON["run_on_server"].GetBool();
-
- if (!plugin.run_on_server && IsDedicatedServer())
- return std::nullopt;
-
- if (manifestJSON.HasMember("dependencyName"))
- {
- plugin.dependencyName = manifestJSON["dependencyName"].GetString();
- }
- else
+ return n;
+}
+int getServerInfoBool(bool* out_ptr, ServerInfoType var)
+{
+ AcquireSRWLockShared(&serverInfoLock);
+ int n = 0;
+ switch (var)
{
- plugin.dependencyName = plugin.name;
+ case ServerInfoType::roundBased:
+ *out_ptr = serverInfo.roundBased;
+ break;
+ default:
+ n = -1;
}
- plugin.init_sqvm_client = (PLUGIN_INIT_SQVM_TYPE)GetProcAddress(pluginLib, "PLUGIN_INIT_SQVM_CLIENT");
- plugin.init_sqvm_server = (PLUGIN_INIT_SQVM_TYPE)GetProcAddress(pluginLib, "PLUGIN_INIT_SQVM_SERVER");
- plugin.inform_sqvm_created = (PLUGIN_INFORM_SQVM_CREATED_TYPE)GetProcAddress(pluginLib, "PLUGIN_INFORM_SQVM_CREATED");
- plugin.inform_sqvm_destroyed = (PLUGIN_INFORM_SQVM_DESTROYED_TYPE)GetProcAddress(pluginLib, "PLUGIN_INFORM_SQVM_DESTROYED");
-
- plugin.push_presence = (PLUGIN_PUSH_PRESENCE_TYPE)GetProcAddress(pluginLib, "PLUGIN_RECEIVE_PRESENCE");
-
- plugin.inform_dll_load = (PLUGIN_INFORM_DLL_LOAD_TYPE)GetProcAddress(pluginLib, "PLUGIN_INFORM_DLL_LOAD");
+ ReleaseSRWLockShared(&serverInfoLock);
- plugin.handle = m_vLoadedPlugins.size();
- plugin.logger = std::make_shared<ColoredLogger>(plugin.displayName.c_str(), NS::Colors::PLUGIN);
- RegisterLogger(plugin.logger);
- NS::log::PLUGINSYS->info("Loading plugin {} version {}", plugin.displayName, plugin.version);
- m_vLoadedPlugins.push_back(plugin);
-
- plugin.init(funcs, data);
-
- return plugin;
+ return n;
}
-bool PluginManager::LoadPlugins()
+int getGameStateChar(char* out_buf, size_t out_buf_len, GameStateInfoType var)
{
- std::vector<fs::path> paths;
-
- pluginPath = GetNorthstarPrefix() + "/plugins";
-
- PluginNorthstarData data {};
- std::string ns_version {version};
-
- PluginInitFuncs funcs {};
- funcs.logger = PLUGIN_LOG;
- funcs.relayInviteFunc = nullptr;
- funcs.createObject = CreateObject;
-
- init_plugincommunicationhandler();
-
- data.version = ns_version.c_str();
- data.northstarModule = g_NorthstarModule;
-
- if (!fs::exists(pluginPath))
- {
- NS::log::PLUGINSYS->warn("Could not find a plugins directory. Skipped loading plugins");
- return false;
- }
- // ensure dirs exist
- fs::recursive_directory_iterator iterator(pluginPath);
- if (std::filesystem::begin(iterator) == std::filesystem::end(iterator))
- {
- NS::log::PLUGINSYS->warn("Could not find any plugins. Skipped loading plugins");
- return false;
- }
- for (auto const& entry : iterator)
+ AcquireSRWLockShared(&gameStateLock);
+ int n = 0;
+ switch (var)
{
- if (fs::is_regular_file(entry) && entry.path().extension() == ".dll")
- paths.emplace_back(entry.path().filename());
+ case GameStateInfoType::map:
+ strncpy(out_buf, gameState.map.c_str(), out_buf_len);
+ break;
+ case GameStateInfoType::mapDisplayName:
+ strncpy(out_buf, gameState.mapDisplayName.c_str(), out_buf_len);
+ break;
+ case GameStateInfoType::playlist:
+ strncpy(out_buf, gameState.playlist.c_str(), out_buf_len);
+ break;
+ case GameStateInfoType::playlistDisplayName:
+ strncpy(out_buf, gameState.playlistDisplayName.c_str(), out_buf_len);
+ break;
+ default:
+ n = -1;
}
- for (fs::path path : paths)
+
+ ReleaseSRWLockShared(&gameStateLock);
+
+ return n;
+}
+int getGameStateInt(int* out_ptr, GameStateInfoType var)
+{
+ AcquireSRWLockShared(&gameStateLock);
+ int n = 0;
+ switch (var)
{
- if (LoadPlugin(path, &funcs, &data))
- data.pluginHandle += 1;
+ case GameStateInfoType::ourScore:
+ *out_ptr = gameState.ourScore;
+ break;
+ case GameStateInfoType::secondHighestScore:
+ *out_ptr = gameState.secondHighestScore;
+ break;
+ case GameStateInfoType::highestScore:
+ *out_ptr = gameState.highestScore;
+ break;
+ case GameStateInfoType::players:
+ *out_ptr = gameState.players;
+ break;
+ default:
+ n = -1;
}
- return true;
-}
-void PluginManager::InformSQVMLoad(ScriptContext context, SquirrelFunctions* s)
+ ReleaseSRWLockShared(&gameStateLock);
+
+ return n;
+}
+int getGameStateBool(bool* out_ptr, GameStateInfoType var)
{
- for (auto plugin : m_vLoadedPlugins)
+ AcquireSRWLockShared(&gameStateLock);
+ int n = 0;
+ switch (var)
{
- if (context == ScriptContext::CLIENT && plugin.init_sqvm_client != NULL)
- {
- plugin.init_sqvm_client(s);
- }
- else if (context == ScriptContext::SERVER && plugin.init_sqvm_server != NULL)
- {
- plugin.init_sqvm_server(s);
- }
+ case GameStateInfoType::connected:
+ *out_ptr = gameState.connected;
+ break;
+ case GameStateInfoType::loading:
+ *out_ptr = gameState.loading;
+ break;
+ default:
+ n = -1;
}
+
+ ReleaseSRWLockShared(&gameStateLock);
+
+ return n;
}
-void PluginManager::InformSQVMCreated(ScriptContext context, CSquirrelVM* sqvm)
+int getPlayerInfoChar(char* out_buf, size_t out_buf_len, PlayerInfoType var)
{
- for (auto plugin : m_vLoadedPlugins)
+ AcquireSRWLockShared(&playerInfoLock);
+ int n = 0;
+ switch (var)
{
- if (plugin.inform_sqvm_created != NULL)
- {
- plugin.inform_sqvm_created(context, sqvm);
- }
+ default:
+ n = -1;
}
-}
-void PluginManager::InformSQVMDestroyed(ScriptContext context)
+ ReleaseSRWLockShared(&playerInfoLock);
+
+ return n;
+}
+int getPlayerInfoInt(int* out_ptr, PlayerInfoType var)
{
- for (auto plugin : m_vLoadedPlugins)
+ AcquireSRWLockShared(&playerInfoLock);
+ int n = 0;
+ switch (var)
{
- if (plugin.inform_sqvm_destroyed != NULL)
- {
- plugin.inform_sqvm_destroyed(context);
- }
+ case PlayerInfoType::uid:
+ *out_ptr = playerInfo.uid;
+ break;
+ default:
+ n = -1;
}
-}
-void PluginManager::PushPresence(PluginGameStatePresence* data)
+ ReleaseSRWLockShared(&playerInfoLock);
+
+ return n;
+}
+int getPlayerInfoBool(bool* out_ptr, PlayerInfoType var)
{
- for (auto plugin : m_vLoadedPlugins)
+ AcquireSRWLockShared(&playerInfoLock);
+ int n = 0;
+ switch (var)
{
- if (plugin.push_presence != NULL)
- {
- plugin.push_presence(data);
- }
+ default:
+ n = -1;
}
+
+ ReleaseSRWLockShared(&playerInfoLock);
+
+ return n;
}
-void PluginManager::InformDLLLoad(PluginLoadDLL dll, void* data)
+ON_DLL_LOAD_CLIENT_RELIESON("client.dll", PluginCommands, ClientSquirrel, (CModule module))
{
- for (auto plugin : m_vLoadedPlugins)
+ // i swear there's a way to make this not have be run in 2 contexts but i can't figure it out
+ // some funcs i need are just not available in UI or CLIENT
+
+ if (g_pSquirrel<ScriptContext::UI> && g_pSquirrel<ScriptContext::CLIENT>)
{
- if (plugin.inform_dll_load != NULL)
- {
- plugin.inform_dll_load(dll, data);
- }
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
+ "void",
+ "NSUpdateGameStateUI",
+ "string gamemode, string gamemodeName, string map, string mapName, bool connected, bool loading",
+ "",
+ SQ_UpdateGameStateUI);
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncRegistration(
+ "void",
+ "NSUpdateGameStateClient",
+ "int playerCount, int maxPlayers, int outScore, int secondHighestScore, int highestScore, bool roundBased, int scoreLimit",
+ "",
+ SQ_UpdateGameStateClient);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
+ "void",
+ "NSUpdateServerInfo",
+ "string id, string name, string password, int players, int maxPlayers, string map, string mapDisplayName, string playlist, "
+ "string "
+ "playlistDisplayName",
+ "",
+ SQ_UpdateServerInfo);
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncRegistration(
+ "void", "NSUpdateServerInfoReload", "int maxPlayers", "", SQ_UpdateServerInfoBetweenRounds);
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncRegistration("void", "NSUpdateTimeInfo", "float timeInFuture", "", SQ_UpdateTimeInfo);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("void", "NSSetLoading", "bool loading", "", SQ_SetConnected);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("void", "NSUpdateListenServer", "", "", SQ_UpdateListenServer);
}
}
diff --git a/NorthstarDLL/plugins/plugins.h b/NorthstarDLL/plugins/plugins.h
index ffa277d0..953801a2 100644
--- a/NorthstarDLL/plugins/plugins.h
+++ b/NorthstarDLL/plugins/plugins.h
@@ -1,57 +1,17 @@
#pragma once
#include "plugin_abi.h"
-const int IDR_RCDATA1 = 101;
+int getServerInfoChar(char* out_buf, size_t out_buf_len, ServerInfoType var);
+int getServerInfoInt(int* out_ptr, ServerInfoType var);
+int getServerInfoBool(bool* out_ptr, ServerInfoType var);
-class Plugin
-{
- public:
- std::string name;
- std::string displayName;
- std::string dependencyName;
- std::string description;
+int getGameStateChar(char* out_buf, size_t out_buf_len, GameStateInfoType var);
+int getGameStateInt(int* out_ptr, GameStateInfoType var);
+int getGameStateBool(bool* out_ptr, GameStateInfoType var);
- std::string api_version;
- std::string version;
+int getPlayerInfoChar(char* out_buf, size_t out_buf_len, PlayerInfoType var);
+int getPlayerInfoInt(int* out_ptr, PlayerInfoType var);
+int getPlayerInfoBool(bool* out_ptr, PlayerInfoType var);
- // For now this is just implemented as the index into the plugins array
- // Maybe a bit shit but it works
- int handle;
-
- std::shared_ptr<ColoredLogger> logger;
-
- bool run_on_client = false;
- bool run_on_server = false;
-
- public:
- PLUGIN_INIT_TYPE init;
- PLUGIN_INIT_SQVM_TYPE init_sqvm_client;
- PLUGIN_INIT_SQVM_TYPE init_sqvm_server;
- PLUGIN_INFORM_SQVM_CREATED_TYPE inform_sqvm_created;
- PLUGIN_INFORM_SQVM_DESTROYED_TYPE inform_sqvm_destroyed;
-
- PLUGIN_PUSH_PRESENCE_TYPE push_presence;
- PLUGIN_INFORM_DLL_LOAD_TYPE inform_dll_load;
-};
-
-class PluginManager
-{
- public:
- std::vector<Plugin> m_vLoadedPlugins;
-
- public:
- bool LoadPlugins();
- std::optional<Plugin> LoadPlugin(fs::path path, PluginInitFuncs* funcs, PluginNorthstarData* data);
-
- void InformSQVMLoad(ScriptContext context, SquirrelFunctions* s);
- void InformSQVMCreated(ScriptContext context, CSquirrelVM* sqvm);
- void InformSQVMDestroyed(ScriptContext context);
- void PushPresence(PluginGameStatePresence* data);
-
- void InformDLLLoad(PluginLoadDLL dll, void* data);
-
- private:
- std::string pluginPath;
-};
-
-extern PluginManager* g_pPluginManager;
+void initGameState();
+void* getPluginObject(PluginObject var);
diff --git a/NorthstarDLL/scripts/client/scriptserverbrowser.cpp b/NorthstarDLL/scripts/client/scriptserverbrowser.cpp
index 39279de5..584ec905 100644
--- a/NorthstarDLL/scripts/client/scriptserverbrowser.cpp
+++ b/NorthstarDLL/scripts/client/scriptserverbrowser.cpp
@@ -336,7 +336,7 @@ ADD_SQFUNC("void", NSTryAuthWithServer, "int serverIndex, string password = ''",
g_pMasterServerManager->AuthenticateWithServer(
R2::g_pLocalPlayerUserID,
g_pMasterServerManager->m_sOwnClientAuthToken,
- g_pMasterServerManager->m_vRemoteServers[serverIndex],
+ g_pMasterServerManager->m_vRemoteServers[serverIndex].id,
(char*)password);
return SQRESULT_NULL;
diff --git a/NorthstarDLL/server/serverpresence.cpp b/NorthstarDLL/server/serverpresence.cpp
index 945f5810..c7ef20c3 100644
--- a/NorthstarDLL/server/serverpresence.cpp
+++ b/NorthstarDLL/server/serverpresence.cpp
@@ -71,7 +71,7 @@ std::string UnescapeUnicode(const std::string& str)
return result;
}
-void ServerPresenceManager::CreateConVars()
+ServerPresenceManager::ServerPresenceManager()
{
// clang-format off
// register convars
@@ -223,6 +223,7 @@ void ServerPresenceManager::SetPlayerCount(const int iPlayerCount)
ON_DLL_LOAD_RELIESON("engine.dll", ServerPresence, ConVar, (CModule module))
{
- g_pServerPresence->CreateConVars();
+ g_pServerPresence = new ServerPresenceManager;
+
Cvar_hostname = module.Offset(0x1315BAE8).Deref().As<ConVar*>();
}
diff --git a/NorthstarDLL/server/serverpresence.h b/NorthstarDLL/server/serverpresence.h
index 3aabecde..6b8c2859 100644
--- a/NorthstarDLL/server/serverpresence.h
+++ b/NorthstarDLL/server/serverpresence.h
@@ -3,11 +3,8 @@
struct ServerPresence
{
- public:
int m_iPort;
- std::string m_sServerId;
-
std::string m_sServerName;
std::string m_sServerDesc;
char m_Password[256]; // probably bigger than will ever be used in practice, lol
@@ -28,8 +25,6 @@ struct ServerPresence
{
m_iPort = obj->m_iPort;
- m_sServerId = obj->m_sServerId;
-
m_sServerName = obj->m_sServerName;
m_sServerDesc = obj->m_sServerDesc;
memcpy(m_Password, obj->m_Password, sizeof(m_Password));
@@ -72,9 +67,9 @@ class ServerPresenceManager
ConVar* Cvar_ns_report_sp_server_to_masterserver;
public:
- void AddPresenceReporter(ServerPresenceReporter* reporter);
+ ServerPresenceManager();
- void CreateConVars();
+ void AddPresenceReporter(ServerPresenceReporter* reporter);
void CreatePresence();
void DestroyPresence();
diff --git a/NorthstarDLL/shared/gamepresence.cpp b/NorthstarDLL/shared/gamepresence.cpp
deleted file mode 100644
index 86a87526..00000000
--- a/NorthstarDLL/shared/gamepresence.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-#include "pch.h"
-
-#include "gamepresence.h"
-#include "plugins/pluginbackend.h"
-#include "plugins/plugins.h"
-#include "dedicated/dedicated.h"
-#include "server/serverpresence.h"
-#include "masterserver/masterserver.h"
-#include "squirrel/squirrel.h"
-
-GameStatePresence* g_pGameStatePresence;
-
-GameStatePresence::GameStatePresence()
-{
- g_pServerPresence->AddPresenceReporter(&m_GameStateServerPresenceReporter);
-}
-
-void GameStateServerPresenceReporter::RunFrame(double flCurrentTime, const ServerPresence* pServerPresence)
-{
- g_pGameStatePresence->id = pServerPresence->m_sServerId;
- g_pGameStatePresence->name = pServerPresence->m_sServerName;
- g_pGameStatePresence->description = pServerPresence->m_sServerDesc;
- g_pGameStatePresence->password = pServerPresence->m_Password;
-
- g_pGameStatePresence->map = pServerPresence->m_MapName;
- g_pGameStatePresence->playlist = pServerPresence->m_PlaylistName;
- g_pGameStatePresence->currentPlayers = pServerPresence->m_iPlayerCount;
- g_pGameStatePresence->maxPlayers = pServerPresence->m_iMaxPlayers;
-
- g_pGameStatePresence->isLocal = !IsDedicatedServer();
-}
-
-void GameStatePresence::RunFrame()
-{
- if (g_pSquirrel<ScriptContext::UI>->m_pSQVM != nullptr && g_pSquirrel<ScriptContext::UI>->m_pSQVM->sqvm != nullptr)
- g_pSquirrel<ScriptContext::UI>->Call("NorthstarCodeCallback_GenerateUIPresence");
-
- if (g_pSquirrel<ScriptContext::CLIENT>->m_pSQVM != nullptr && g_pSquirrel<ScriptContext::CLIENT>->m_pSQVM->sqvm != nullptr)
- {
- auto test = g_pSquirrel<ScriptContext::CLIENT>->Call("NorthstarCodeCallback_GenerateGameState");
- }
- g_pPluginCommunicationhandler->GeneratePresenceObjects();
-}
-
-ADD_SQFUNC("void", NSPushGameStateData, "GameStateStruct gamestate", "", ScriptContext::CLIENT)
-{
- SQStructInstance* structInst = g_pSquirrel<ScriptContext::CLIENT>->m_pSQVM->sqvm->_stackOfCurrentFunction[1]._VAL.asStructInstance;
- g_pGameStatePresence->map = structInst->data[0]._VAL.asString->_val;
- g_pGameStatePresence->mapDisplayname = structInst->data[1]._VAL.asString->_val;
- g_pGameStatePresence->playlist = structInst->data[2]._VAL.asString->_val;
- g_pGameStatePresence->playlistDisplayname = structInst->data[3]._VAL.asString->_val;
-
- g_pGameStatePresence->currentPlayers = structInst->data[4]._VAL.asInteger;
- g_pGameStatePresence->maxPlayers = structInst->data[5]._VAL.asInteger;
- g_pGameStatePresence->ownScore = structInst->data[6]._VAL.asInteger;
- g_pGameStatePresence->otherHighestScore = structInst->data[7]._VAL.asInteger;
- g_pGameStatePresence->maxScore = structInst->data[8]._VAL.asInteger;
- g_pGameStatePresence->timestampEnd = ceil(structInst->data[9]._VAL.asFloat);
-
- if (g_pMasterServerManager->m_currentServer)
- {
- g_pGameStatePresence->id = g_pMasterServerManager->m_currentServer->id;
- g_pGameStatePresence->name = g_pMasterServerManager->m_currentServer->name;
- g_pGameStatePresence->description = g_pMasterServerManager->m_currentServer->description;
- g_pGameStatePresence->password = g_pMasterServerManager->m_sCurrentServerPassword;
- }
-
- return SQRESULT_NOTNULL;
-}
-
-ADD_SQFUNC("void", NSPushUIPresence, "UIPresenceStruct presence", "", ScriptContext::UI)
-{
- SQStructInstance* structInst = g_pSquirrel<ScriptContext::UI>->m_pSQVM->sqvm->_stackOfCurrentFunction[1]._VAL.asStructInstance;
-
- g_pGameStatePresence->isLoading = structInst->data[0]._VAL.asInteger;
- g_pGameStatePresence->isLobby = structInst->data[1]._VAL.asInteger;
- g_pGameStatePresence->loadingLevel = structInst->data[2]._VAL.asString->_val;
- g_pGameStatePresence->uiMap = structInst->data[3]._VAL.asString->_val;
-
- return SQRESULT_NOTNULL;
-}
diff --git a/NorthstarDLL/shared/gamepresence.h b/NorthstarDLL/shared/gamepresence.h
deleted file mode 100644
index 167f83ab..00000000
--- a/NorthstarDLL/shared/gamepresence.h
+++ /dev/null
@@ -1,48 +0,0 @@
-
-#pragma once
-#include "pch.h"
-#include "server/serverpresence.h"
-
-class GameStateServerPresenceReporter : public ServerPresenceReporter
-{
- void RunFrame(double flCurrentTime, const ServerPresence* pServerPresence);
-};
-
-class GameStatePresence
-{
- public:
- std::string id;
- std::string name;
- std::string description;
- std::string password; // NOTE: May be empty
-
- bool isServer;
- bool isLocal = false;
- bool isLoading;
- bool isLobby;
- std::string loadingLevel;
-
- std::string uiMap;
-
- std::string map;
- std::string mapDisplayname;
- std::string playlist;
- std::string playlistDisplayname;
-
- int currentPlayers;
- int maxPlayers;
-
- int ownScore;
- int otherHighestScore; // NOTE: The highest score OR the second highest score if we have the highest
- int maxScore;
-
- int timestampEnd;
-
- GameStatePresence();
- void RunFrame();
-
- protected:
- GameStateServerPresenceReporter m_GameStateServerPresenceReporter;
-};
-
-extern GameStatePresence* g_pGameStatePresence;
diff --git a/NorthstarDLL/squirrel/squirrel.cpp b/NorthstarDLL/squirrel/squirrel.cpp
index 62287245..21ce9ae0 100644
--- a/NorthstarDLL/squirrel/squirrel.cpp
+++ b/NorthstarDLL/squirrel/squirrel.cpp
@@ -5,8 +5,6 @@
#include "dedicated/dedicated.h"
#include "engine/r2engine.h"
#include "core/tier0.h"
-#include "plugins/plugin_abi.h"
-#include "plugins/plugins.h"
#include <any>
@@ -154,52 +152,6 @@ const char* SQTypeNameFromID(int type)
return "";
}
-template <ScriptContext context> void SquirrelManager<context>::GenerateSquirrelFunctionsStruct(SquirrelFunctions* s)
-{
- s->RegisterSquirrelFunc = RegisterSquirrelFunc;
- s->__sq_defconst = __sq_defconst;
-
- s->__sq_compilebuffer = __sq_compilebuffer;
- s->__sq_call = __sq_call;
- s->__sq_raiseerror = __sq_raiseerror;
-
- s->__sq_newarray = __sq_newarray;
- s->__sq_arrayappend = __sq_arrayappend;
-
- s->__sq_newtable = __sq_newtable;
- s->__sq_newslot = __sq_newslot;
-
- s->__sq_pushroottable = __sq_pushroottable;
- s->__sq_pushstring = __sq_pushstring;
- s->__sq_pushinteger = __sq_pushinteger;
- s->__sq_pushfloat = __sq_pushfloat;
- s->__sq_pushbool = __sq_pushbool;
- s->__sq_pushasset = __sq_pushasset;
- s->__sq_pushvector = __sq_pushvector;
- s->__sq_pushobject = __sq_pushobject;
- s->__sq_getstring = __sq_getstring;
- s->__sq_getthisentity = __sq_getthisentity;
- s->__sq_getobject = __sq_getobject;
-
- s->__sq_stackinfos = __sq_stackinfos;
-
- s->__sq_getinteger = __sq_getinteger;
- s->__sq_getfloat = __sq_getfloat;
- s->__sq_getbool = __sq_getbool;
- s->__sq_get = __sq_get;
- s->__sq_getasset = __sq_getasset;
- s->__sq_getuserdata = __sq_getuserdata;
- s->__sq_getvector = __sq_getvector;
- s->__sq_createuserdata = __sq_createuserdata;
- s->__sq_setuserdatatypeid = __sq_setuserdatatypeid;
- s->__sq_getfunction = __sq_getfunction;
-
- s->__sq_getentityfrominstance = __sq_getentityfrominstance;
- s->__sq_GetEntityConstant_CBaseEntity = __sq_GetEntityConstant_CBaseEntity;
-
- s->__sq_schedule_call_external = AsyncCall_External;
-}
-
// Allows for generating squirrelmessages from plugins.
// Not used in this version, but will be used later
void AsyncCall_External(ScriptContext context, const char* func_name, SquirrelMessage_External_Pop function)
@@ -256,7 +208,6 @@ template <ScriptContext context> void SquirrelManager<context>::VMCreated(CSquir
defconst(m_pSQVM, pair.first.c_str(), bWasFound);
}
g_pSquirrel<context>->messageBuffer = new SquirrelMessageBuffer();
- g_pPluginManager->InformSQVMCreated(context, newSqvm);
}
template <ScriptContext context> void SquirrelManager<context>::VMDestroyed()
@@ -284,8 +235,6 @@ template <ScriptContext context> void SquirrelManager<context>::VMDestroyed()
}
}
- g_pPluginManager->InformSQVMDestroyed(context);
-
// Discard the previous vm and delete the message buffer.
m_pSQVM = nullptr;
@@ -409,23 +358,6 @@ template <ScriptContext context> CSquirrelVM* __fastcall CreateNewVMHook(void* a
return sqvm;
}
-template <ScriptContext context> bool (*__fastcall CSquirrelVM_init)(CSquirrelVM* vm, ScriptContext realContext, float time);
-template <ScriptContext context> bool __fastcall CSquirrelVM_initHook(CSquirrelVM* vm, ScriptContext realContext, float time)
-{
- bool ret = CSquirrelVM_init<context>(vm, realContext, time);
- for (Mod mod : g_pModManager->m_LoadedMods)
- {
- if (mod.initScript.size() != 0)
- {
- std::string name = mod.initScript.substr(mod.initScript.find_last_of('/') + 1);
- std::string path = std::string("scripts/vscripts/") + mod.initScript;
- if (g_pSquirrel<context>->compilefile(vm, path.c_str(), name.c_str(), 0))
- g_pSquirrel<context>->compilefile(vm, path.c_str(), name.c_str(), 1);
- }
- }
- return ret;
-}
-
template <ScriptContext context> void (*__fastcall DestroyVM)(void* a1, CSquirrelVM* sqvm);
template <ScriptContext context> void __fastcall DestroyVMHook(void* a1, CSquirrelVM* sqvm)
{
@@ -706,10 +638,8 @@ ON_DLL_LOAD_RELIESON("client.dll", ClientSquirrel, ConCommand, (CModule module))
g_pSquirrel<ScriptContext::CLIENT>->__sq_compilebuffer = module.Offset(0x3110).As<sq_compilebufferType>();
g_pSquirrel<ScriptContext::CLIENT>->__sq_pushroottable = module.Offset(0x5860).As<sq_pushroottableType>();
- g_pSquirrel<ScriptContext::CLIENT>->__sq_compilefile = module.Offset(0xF950).As<sq_compilefileType>();
g_pSquirrel<ScriptContext::UI>->__sq_compilebuffer = g_pSquirrel<ScriptContext::CLIENT>->__sq_compilebuffer;
g_pSquirrel<ScriptContext::UI>->__sq_pushroottable = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushroottable;
- g_pSquirrel<ScriptContext::UI>->__sq_compilefile = g_pSquirrel<ScriptContext::CLIENT>->__sq_compilefile;
g_pSquirrel<ScriptContext::CLIENT>->__sq_call = module.Offset(0x8650).As<sq_callType>();
g_pSquirrel<ScriptContext::UI>->__sq_call = g_pSquirrel<ScriptContext::CLIENT>->__sq_call;
@@ -803,8 +733,6 @@ ON_DLL_LOAD_RELIESON("client.dll", ClientSquirrel, ConCommand, (CModule module))
MAKEHOOK(module.Offset(0x10190), &CallScriptInitCallbackHook<ScriptContext::CLIENT>, &CallScriptInitCallback<ScriptContext::CLIENT>);
- MAKEHOOK(module.Offset(0xE3B0), &CSquirrelVM_initHook<ScriptContext::CLIENT>, &CSquirrelVM_init<ScriptContext::CLIENT>);
-
RegisterConCommand("script_client", ConCommand_script<ScriptContext::CLIENT>, "Executes script code on the client vm", FCVAR_CLIENTDLL);
RegisterConCommand("script_ui", ConCommand_script<ScriptContext::UI>, "Executes script code on the ui vm", FCVAR_CLIENTDLL);
@@ -813,10 +741,6 @@ ON_DLL_LOAD_RELIESON("client.dll", ClientSquirrel, ConCommand, (CModule module))
g_pSquirrel<ScriptContext::CLIENT>->__sq_getfunction = module.Offset(0x6CB0).As<sq_getfunctionType>();
g_pSquirrel<ScriptContext::UI>->__sq_getfunction = g_pSquirrel<ScriptContext::CLIENT>->__sq_getfunction;
-
- SquirrelFunctions s = {};
- g_pSquirrel<ScriptContext::CLIENT>->GenerateSquirrelFunctionsStruct(&s);
- g_pPluginManager->InformSQVMLoad(ScriptContext::CLIENT, &s);
}
ON_DLL_LOAD_RELIESON("server.dll", ServerSquirrel, ConCommand, (CModule module))
@@ -828,7 +752,6 @@ ON_DLL_LOAD_RELIESON("server.dll", ServerSquirrel, ConCommand, (CModule module))
g_pSquirrel<ScriptContext::SERVER>->__sq_compilebuffer = module.Offset(0x3110).As<sq_compilebufferType>();
g_pSquirrel<ScriptContext::SERVER>->__sq_pushroottable = module.Offset(0x5840).As<sq_pushroottableType>();
g_pSquirrel<ScriptContext::SERVER>->__sq_call = module.Offset(0x8620).As<sq_callType>();
- g_pSquirrel<ScriptContext::SERVER>->__sq_compilefile = module.Offset(0x1CD80).As<sq_compilefileType>();
g_pSquirrel<ScriptContext::SERVER>->__sq_newarray = module.Offset(0x39F0).As<sq_newarrayType>();
g_pSquirrel<ScriptContext::SERVER>->__sq_arrayappend = module.Offset(0x3C70).As<sq_arrayappendType>();
@@ -881,7 +804,7 @@ ON_DLL_LOAD_RELIESON("server.dll", ServerSquirrel, ConCommand, (CModule module))
MAKEHOOK(module.Offset(0x26E20), &DestroyVMHook<ScriptContext::SERVER>, &DestroyVM<ScriptContext::SERVER>);
MAKEHOOK(module.Offset(0x799E0), &ScriptCompileErrorHook<ScriptContext::SERVER>, &SQCompileError<ScriptContext::SERVER>);
MAKEHOOK(module.Offset(0x1D5C0), &CallScriptInitCallbackHook<ScriptContext::SERVER>, &CallScriptInitCallback<ScriptContext::SERVER>);
- MAKEHOOK(module.Offset(0x17BE0), &CSquirrelVM_initHook<ScriptContext::SERVER>, &CSquirrelVM_init<ScriptContext::SERVER>);
+
// FCVAR_CHEAT and FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS allows clients to execute this, but since it's unsafe we only allow it when cheats
// are enabled for script_client and script_ui, we don't use cheats, so clients can execute them on themselves all they want
RegisterConCommand(
@@ -891,10 +814,6 @@ ON_DLL_LOAD_RELIESON("server.dll", ServerSquirrel, ConCommand, (CModule module))
FCVAR_GAMEDLL | FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS | FCVAR_CHEAT);
StubUnsafeSQFuncs<ScriptContext::SERVER>();
-
- SquirrelFunctions s = {};
- g_pSquirrel<ScriptContext::SERVER>->GenerateSquirrelFunctionsStruct(&s);
- g_pPluginManager->InformSQVMLoad(ScriptContext::SERVER, &s);
}
void InitialiseSquirrelManagers()
diff --git a/NorthstarDLL/squirrel/squirrel.h b/NorthstarDLL/squirrel/squirrel.h
index 9bf3a794..aa728fa5 100644
--- a/NorthstarDLL/squirrel/squirrel.h
+++ b/NorthstarDLL/squirrel/squirrel.h
@@ -3,7 +3,6 @@
#include "squirrelclasstypes.h"
#include "squirrelautobind.h"
#include "core/math/vector.h"
-#include "plugins/plugin_abi.h"
#include "mods/modmanager.h"
// stolen from ttf2sdk: sqvm types
@@ -38,8 +37,6 @@ const char* GetContextName_Short(ScriptContext context);
eSQReturnType SQReturnTypeFromString(const char* pReturnType);
const char* SQTypeNameFromID(const int iTypeId);
-void AsyncCall_External(ScriptContext context, const char* func_name, SquirrelMessage_External_Pop function);
-
ScriptContext ScriptContextFromString(std::string string);
namespace NS::log
@@ -47,6 +44,8 @@ namespace NS::log
template <ScriptContext context> std::shared_ptr<spdlog::logger> squirrel_logger();
}; // namespace NS::log
+void schedule_call_external(ScriptContext context, const char* func_name, SquirrelMessage_External_Pop function);
+
// This base class means that only the templated functions have to be rebuilt for each template instance
// Cuts down on compile time by ~5 seconds
class SquirrelManagerBase
@@ -70,7 +69,6 @@ class SquirrelManagerBase
sq_compilebufferType __sq_compilebuffer;
sq_callType __sq_call;
sq_raiseerrorType __sq_raiseerror;
- sq_compilefileType __sq_compilefile;
sq_newarrayType __sq_newarray;
sq_arrayappendType __sq_arrayappend;
@@ -131,11 +129,6 @@ class SquirrelManagerBase
return __sq_raiseerror(sqvm, sError);
}
- inline bool compilefile(CSquirrelVM* sqvm, const char* path, const char* name, int a4)
- {
- return __sq_compilefile(sqvm, path, name, a4);
- }
-
inline void newarray(HSquirrelVM* sqvm, const SQInteger stackpos = 0)
{
__sq_newarray(sqvm, stackpos);
@@ -391,7 +384,6 @@ template <ScriptContext context> class SquirrelManager : public virtual Squirrel
SQRESULT setupfunc(const SQChar* funcname);
void AddFuncOverride(std::string name, SQFunction func);
void ProcessMessageBuffer();
- void GenerateSquirrelFunctionsStruct(SquirrelFunctions* s);
};
template <ScriptContext context> SquirrelManager<context>* g_pSquirrel;
diff --git a/NorthstarDLL/squirrel/squirrelclasstypes.h b/NorthstarDLL/squirrel/squirrelclasstypes.h
index 67f69827..68b57bae 100644
--- a/NorthstarDLL/squirrel/squirrelclasstypes.h
+++ b/NorthstarDLL/squirrel/squirrelclasstypes.h
@@ -192,7 +192,6 @@ typedef SQRESULT (*sq_compilebufferType)(
HSquirrelVM* sqvm, CompileBufferState* compileBuffer, const char* file, int a1, SQBool bShouldThrowError);
typedef SQRESULT (*sq_callType)(HSquirrelVM* sqvm, SQInteger iArgs, SQBool bShouldReturn, SQBool bThrowError);
typedef SQInteger (*sq_raiseerrorType)(HSquirrelVM* sqvm, const SQChar* pError);
-typedef bool (*sq_compilefileType)(CSquirrelVM* sqvm, const char* path, const char* name, int a4);
// sq stack array funcs
typedef void (*sq_newarrayType)(HSquirrelVM* sqvm, SQInteger iStackpos);
diff --git a/NorthstarLauncher/main.cpp b/NorthstarLauncher/main.cpp
index dd3b68f5..17128e5b 100644
--- a/NorthstarLauncher/main.cpp
+++ b/NorthstarLauncher/main.cpp
@@ -27,6 +27,8 @@ HMODULE hTier0Module;
wchar_t exePath[4096];
wchar_t buffer[8192];
+bool noLoadPlugins = false;
+
DWORD GetProcessByName(std::wstring processName)
{
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
@@ -290,6 +292,19 @@ bool LoadNorthstar()
}
((bool (*)())Hook_Init)();
+ FARPROC LoadPlugins = nullptr;
+ if (!noLoadPlugins)
+ {
+ LoadPlugins = GetProcAddress(hHookModule, "LoadPlugins");
+ if (!hHookModule || LoadPlugins == nullptr)
+ {
+ std::cout << "Failed to get function pointer to LoadPlugins of Northstar.dll" << std::endl;
+ LibraryLoadError(GetLastError(), L"Northstar.dll", buffer);
+ return false;
+ }
+ ((bool (*)())LoadPlugins)();
+ }
+
return true;
}
@@ -341,6 +356,8 @@ int main(int argc, char* argv[])
dedicated = true;
else if (!strcmp(argv[i], "-nostubs"))
nostubs = true;
+ else if (!strcmp(argv[i], "-noplugins"))
+ noLoadPlugins = true;
if (!noOriginStartup && !dedicated)
{