aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeckoEidechse <gecko.eidechse+git@pm.me>2024-08-07 16:35:39 +0200
committerGeckoEidechse <gecko.eidechse+git@pm.me>2024-08-07 16:35:39 +0200
commitfff09b8b6805f66c87da2ac39ef5509bffb129cf (patch)
tree8a0088e80ba4f409fe1c226f3df54527582d6533
parentd4273d698523f7b8966bbee83beecc8131a21678 (diff)
parent51991cc45f8557dbeedbf6de176285e51a77676f (diff)
downloadNorthstarLauncher-fff09b8b6805f66c87da2ac39ef5509bffb129cf.tar.gz
NorthstarLauncher-fff09b8b6805f66c87da2ac39ef5509bffb129cf.zip
Merge branch 'main' into feat/overhaul-mod-loading-locations
-rw-r--r--primedev/client/audio.cpp33
-rw-r--r--primedev/client/audio.h6
-rw-r--r--primedev/client/languagehooks.cpp2
-rw-r--r--primedev/core/hooks.cpp2
-rw-r--r--primedev/logging/logging.cpp6
-rw-r--r--primedev/mods/autodownload/moddownloader.cpp31
-rw-r--r--primedev/mods/autodownload/moddownloader.h4
-rw-r--r--primedev/mods/modmanager.cpp2
-rw-r--r--primedev/mods/modmanager.h2
-rw-r--r--primedev/plugins/pluginmanager.cpp2
-rw-r--r--primedev/plugins/pluginmanager.h2
-rw-r--r--primedev/server/buildainfile.cpp2
-rw-r--r--primedev/squirrel/squirrel.cpp2
-rw-r--r--primedev/squirrel/squirrel.h5
-rw-r--r--primedev/squirrel/squirrelclasstypes.h1
15 files changed, 89 insertions, 13 deletions
diff --git a/primedev/client/audio.cpp b/primedev/client/audio.cpp
index 099fdcee..63501414 100644
--- a/primedev/client/audio.cpp
+++ b/primedev/client/audio.cpp
@@ -7,6 +7,9 @@
#include <iostream>
#include <sstream>
#include <random>
+#include <ranges>
+
+namespace fs = std::filesystem;
AUTOHOOK_INIT()
@@ -28,7 +31,7 @@ unsigned char EMPTY_WAVE[45] = {0x52, 0x49, 0x46, 0x46, 0x25, 0x00, 0x00, 0x00,
0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x44, 0xAC, 0x00, 0x00, 0x88, 0x58,
0x01, 0x00, 0x02, 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x74, 0x00, 0x00, 0x00, 0x00};
-EventOverrideData::EventOverrideData(const std::string& data, const fs::path& path)
+EventOverrideData::EventOverrideData(const std::string& data, const fs::path& path, const std::vector<std::string>& registeredEvents)
{
if (data.length() <= 0)
{
@@ -191,6 +194,14 @@ EventOverrideData::EventOverrideData(const std::string& data, const fs::path& pa
{
std::string pathString = file.path().string();
+ // Retrieve event id from path (standard?)
+ std::string eventId = file.path().parent_path().filename().string();
+ if (std::find(registeredEvents.begin(), registeredEvents.end(), eventId) != registeredEvents.end())
+ {
+ spdlog::warn("{} couldn't be loaded because {} event has already been overrided, skipping.", pathString, eventId);
+ continue;
+ }
+
// Open the file.
std::ifstream wavStream(pathString, std::ios::binary);
@@ -259,7 +270,7 @@ EventOverrideData::EventOverrideData(const std::string& data, const fs::path& pa
LoadedSuccessfully = true;
}
-bool CustomAudioManager::TryLoadAudioOverride(const fs::path& defPath)
+bool CustomAudioManager::TryLoadAudioOverride(const fs::path& defPath, std::string modName)
{
if (IsDedicatedServer())
return true; // silently fail
@@ -279,19 +290,35 @@ bool CustomAudioManager::TryLoadAudioOverride(const fs::path& defPath)
jsonStream.close();
- std::shared_ptr<EventOverrideData> data = std::make_shared<EventOverrideData>(jsonStringStream.str(), defPath);
+ // Pass the list of overriden events to avoid multiple event registrations crash
+ auto kv = std::views::keys(m_loadedAudioOverrides);
+ std::vector<std::string> keys {kv.begin(), kv.end()};
+ std::shared_ptr<EventOverrideData> data = std::make_shared<EventOverrideData>(jsonStringStream.str(), defPath, keys);
if (!data->LoadedSuccessfully)
return false; // no logging, the constructor has probably already logged
for (const std::string& eventId : data->EventIds)
{
+ if (m_loadedAudioOverrides.contains(eventId))
+ {
+ spdlog::warn("\"{}\" mod tried to override sound event \"{}\" but it is already overriden, skipping.", modName, eventId);
+ continue;
+ }
spdlog::info("Registering sound event {}", eventId);
m_loadedAudioOverrides.insert({eventId, data});
}
for (const auto& eventIdRegexData : data->EventIdsRegex)
{
+ if (m_loadedAudioOverridesRegex.contains(eventIdRegexData.first))
+ {
+ spdlog::warn(
+ "\"{}\" mod tried to override sound event regex \"{}\" but it is already overriden, skipping.",
+ modName,
+ eventIdRegexData.first);
+ continue;
+ }
spdlog::info("Registering sound event regex {}", eventIdRegexData.first);
m_loadedAudioOverridesRegex.insert({eventIdRegexData.first, data});
}
diff --git a/primedev/client/audio.h b/primedev/client/audio.h
index 15fd1a35..22bcf3f0 100644
--- a/primedev/client/audio.h
+++ b/primedev/client/audio.h
@@ -5,6 +5,8 @@
#include <regex>
#include <shared_mutex>
+namespace fs = std::filesystem;
+
enum class AudioSelectionStrategy
{
INVALID = -1,
@@ -15,7 +17,7 @@ enum class AudioSelectionStrategy
class EventOverrideData
{
public:
- EventOverrideData(const std::string&, const fs::path&);
+ EventOverrideData(const std::string&, const fs::path&, const std::vector<std::string>& registeredEvents);
EventOverrideData();
public:
@@ -35,7 +37,7 @@ public:
class CustomAudioManager
{
public:
- bool TryLoadAudioOverride(const fs::path&);
+ bool TryLoadAudioOverride(const fs::path&, std::string modName);
void ClearAudioOverrides();
std::shared_mutex m_loadingMutex;
diff --git a/primedev/client/languagehooks.cpp b/primedev/client/languagehooks.cpp
index 0146d1d4..36b5d5ae 100644
--- a/primedev/client/languagehooks.cpp
+++ b/primedev/client/languagehooks.cpp
@@ -3,6 +3,8 @@
#include <filesystem>
#include <regex>
+namespace fs = std::filesystem;
+
AUTOHOOK_INIT()
typedef LANGID (*Tier0_DetectDefaultLanguageType)();
diff --git a/primedev/core/hooks.cpp b/primedev/core/hooks.cpp
index 6e849291..fef8bbcf 100644
--- a/primedev/core/hooks.cpp
+++ b/primedev/core/hooks.cpp
@@ -12,6 +12,8 @@
#define XINPUT1_3_DLL "XInput1_3.dll"
+namespace fs = std::filesystem;
+
AUTOHOOK_INIT()
// called from the ON_DLL_LOAD macros
diff --git a/primedev/logging/logging.cpp b/primedev/logging/logging.cpp
index 4367b384..6d71eea0 100644
--- a/primedev/logging/logging.cpp
+++ b/primedev/logging/logging.cpp
@@ -124,11 +124,7 @@ void CustomSink::custom_log(const custom_log_msg& msg)
void InitialiseConsole()
{
- if (GetConsoleWindow() == NULL && AllocConsole() == FALSE)
- {
- std::cout << "[*] Failed to create a console window" << std::endl;
- }
- else
+ if (AllocConsole() != FALSE)
{
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
diff --git a/primedev/mods/autodownload/moddownloader.cpp b/primedev/mods/autodownload/moddownloader.cpp
index 3a946263..8e533dec 100644
--- a/primedev/mods/autodownload/moddownloader.cpp
+++ b/primedev/mods/autodownload/moddownloader.cpp
@@ -55,6 +55,8 @@ size_t WriteToString(void* ptr, size_t size, size_t count, void* stream)
void ModDownloader::FetchModsListFromAPI()
{
+ modState.state = MANIFESTO_FETCHING;
+
std::thread requestThread(
[this]()
{
@@ -63,6 +65,9 @@ void ModDownloader::FetchModsListFromAPI()
rapidjson::Document verifiedModsJson;
std::string url = modsListUrl;
+ // Empty verified mods manifesto
+ verifiedMods = {};
+
curl_global_init(CURL_GLOBAL_ALL);
easyhandle = curl_easy_init();
std::string readBuffer;
@@ -75,7 +80,12 @@ void ModDownloader::FetchModsListFromAPI()
curl_easy_setopt(easyhandle, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(easyhandle, CURLOPT_WRITEFUNCTION, WriteToString);
result = curl_easy_perform(easyhandle);
- ScopeGuard cleanup([&] { curl_easy_cleanup(easyhandle); });
+ ScopeGuard cleanup(
+ [&]
+ {
+ curl_easy_cleanup(easyhandle);
+ modState.state = DOWNLOADING;
+ });
if (result == CURLcode::CURLE_OK)
{
@@ -92,6 +102,13 @@ void ModDownloader::FetchModsListFromAPI()
verifiedModsJson.Parse(readBuffer);
for (auto i = verifiedModsJson.MemberBegin(); i != verifiedModsJson.MemberEnd(); ++i)
{
+ // Format testing
+ if (!i->value.HasMember("DependencyPrefix") || !i->value.HasMember("Versions"))
+ {
+ spdlog::warn("Verified mods manifesto format is unrecognized, skipping loading.");
+ return;
+ }
+
std::string name = i->name.GetString();
std::string dependency = i->value["DependencyPrefix"].GetString();
@@ -101,6 +118,13 @@ void ModDownloader::FetchModsListFromAPI()
for (auto& attribute : versions.GetArray())
{
assert(attribute.IsObject());
+ // Format testing
+ if (!attribute.HasMember("Version") || !attribute.HasMember("Checksum"))
+ {
+ spdlog::warn("Verified mods manifesto format is unrecognized, skipping loading.");
+ return;
+ }
+
std::string version = attribute["Version"].GetString();
std::string checksum = attribute["Checksum"].GetString();
modVersions.insert({version, {.checksum = checksum}});
@@ -600,7 +624,12 @@ void ModDownloader::DownloadMod(std::string modName, std::string modVersion)
ON_DLL_LOAD_RELIESON("engine.dll", ModDownloader, (ConCommand), (CModule module))
{
g_pModDownloader = new ModDownloader();
+}
+
+ADD_SQFUNC("void", NSFetchVerifiedModsManifesto, "", "", ScriptContext::SERVER | ScriptContext::CLIENT | ScriptContext::UI)
+{
g_pModDownloader->FetchModsListFromAPI();
+ return SQRESULT_NULL;
}
ADD_SQFUNC(
diff --git a/primedev/mods/autodownload/moddownloader.h b/primedev/mods/autodownload/moddownloader.h
index 10df39ce..98fc27ae 100644
--- a/primedev/mods/autodownload/moddownloader.h
+++ b/primedev/mods/autodownload/moddownloader.h
@@ -1,3 +1,5 @@
+namespace fs = std::filesystem;
+
class ModDownloader
{
private:
@@ -114,6 +116,8 @@ public:
enum ModInstallState
{
+ MANIFESTO_FETCHING,
+
// Normal installation process
DOWNLOADING,
CHECKSUMING,
diff --git a/primedev/mods/modmanager.cpp b/primedev/mods/modmanager.cpp
index b99c8761..b3c8ab7a 100644
--- a/primedev/mods/modmanager.cpp
+++ b/primedev/mods/modmanager.cpp
@@ -989,7 +989,7 @@ void ModManager::LoadMods()
{
if (fs::is_regular_file(file) && file.path().extension().string() == ".json")
{
- if (!g_CustomAudioManager.TryLoadAudioOverride(file.path()))
+ if (!g_CustomAudioManager.TryLoadAudioOverride(file.path(), mod.Name))
{
spdlog::warn("Mod {} has an invalid audio def {}", mod.Name, file.path().filename().string());
continue;
diff --git a/primedev/mods/modmanager.h b/primedev/mods/modmanager.h
index 5f6d07e7..3df7fe53 100644
--- a/primedev/mods/modmanager.h
+++ b/primedev/mods/modmanager.h
@@ -9,6 +9,8 @@
#include <filesystem>
#include <unordered_set>
+namespace fs = std::filesystem;
+
const std::string CORE_MOD_FOLDER_SUFFIX = "\\mods\\core";
const std::string MANUAL_MOD_FOLDER_SUFFIX = "\\mods\\manual";
const std::string THUNDERSTORE_LEGACY_MOD_FOLDER_SUFFIX = "\\mods\\thunderstore-legacy";
diff --git a/primedev/plugins/pluginmanager.cpp b/primedev/plugins/pluginmanager.cpp
index 1abd0def..0b89f76e 100644
--- a/primedev/plugins/pluginmanager.cpp
+++ b/primedev/plugins/pluginmanager.cpp
@@ -5,6 +5,8 @@
#include "config/profile.h"
#include "core/convar/concommand.h"
+namespace fs = std::filesystem;
+
PluginManager* g_pPluginManager;
const std::vector<Plugin>& PluginManager::GetLoadedPlugins() const
diff --git a/primedev/plugins/pluginmanager.h b/primedev/plugins/pluginmanager.h
index 8c021851..7993cbb8 100644
--- a/primedev/plugins/pluginmanager.h
+++ b/primedev/plugins/pluginmanager.h
@@ -3,6 +3,8 @@
#include <windows.h>
+namespace fs = std::filesystem;
+
class Plugin;
class PluginManager
diff --git a/primedev/server/buildainfile.cpp b/primedev/server/buildainfile.cpp
index a7f59961..19a6d0e3 100644
--- a/primedev/server/buildainfile.cpp
+++ b/primedev/server/buildainfile.cpp
@@ -5,6 +5,8 @@
#include <fstream>
#include <filesystem>
+namespace fs = std::filesystem;
+
AUTOHOOK_INIT()
const int AINET_VERSION_NUMBER = 57;
diff --git a/primedev/squirrel/squirrel.cpp b/primedev/squirrel/squirrel.cpp
index f6df0c5f..29540cce 100644
--- a/primedev/squirrel/squirrel.cpp
+++ b/primedev/squirrel/squirrel.cpp
@@ -707,6 +707,7 @@ ON_DLL_LOAD_RELIESON("client.dll", ClientSquirrel, ConCommand, (CModule module))
g_pSquirrel<ScriptContext::CLIENT>->__sq_GetEntityConstant_CBaseEntity = module.Offset(0x3E49B0).RCast<sq_GetEntityConstantType>();
g_pSquirrel<ScriptContext::CLIENT>->__sq_getentityfrominstance = module.Offset(0x114F0).RCast<sq_getentityfrominstanceType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_createscriptinstance = module.Offset(0xC20E0).RCast<sq_createscriptinstanceType>();
g_pSquirrel<ScriptContext::UI>->__sq_GetEntityConstant_CBaseEntity =
g_pSquirrel<ScriptContext::CLIENT>->__sq_GetEntityConstant_CBaseEntity;
g_pSquirrel<ScriptContext::UI>->__sq_getentityfrominstance = g_pSquirrel<ScriptContext::CLIENT>->__sq_getentityfrominstance;
@@ -800,6 +801,7 @@ ON_DLL_LOAD_RELIESON("server.dll", ServerSquirrel, ConCommand, (CModule module))
g_pSquirrel<ScriptContext::SERVER>->__sq_GetEntityConstant_CBaseEntity = module.Offset(0x418AF0).RCast<sq_GetEntityConstantType>();
g_pSquirrel<ScriptContext::SERVER>->__sq_getentityfrominstance = module.Offset(0x1E920).RCast<sq_getentityfrominstanceType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_createscriptinstance = module.Offset(0x43F2F0).RCast<sq_createscriptinstanceType>();
g_pSquirrel<ScriptContext::SERVER>->logger = NS::log::SCRIPT_SV;
// Message buffer stuff
diff --git a/primedev/squirrel/squirrel.h b/primedev/squirrel/squirrel.h
index 1054de7f..547b1efc 100644
--- a/primedev/squirrel/squirrel.h
+++ b/primedev/squirrel/squirrel.h
@@ -5,6 +5,8 @@
#include "core/math/vector.h"
#include "mods/modmanager.h"
+namespace fs = std::filesystem;
+
/*
definitions from hell
required to function
@@ -115,6 +117,7 @@ public:
sq_getfunctionType __sq_getfunction;
sq_getentityfrominstanceType __sq_getentityfrominstance;
+ sq_createscriptinstanceType __sq_createscriptinstance;
sq_GetEntityConstantType __sq_GetEntityConstant_CBaseEntity;
sq_pushnewstructinstanceType __sq_pushnewstructinstance;
@@ -447,7 +450,7 @@ inline VoidFunction SQMessageBufferPushArg(Vector3& arg) {
// Vectors
template <ScriptContext context>
inline VoidFunction SQMessageBufferPushArg(SQObject* arg) {
- return [arg]{ g_pSquirrel<context>->pushSQObject(g_pSquirrel<context>->m_pSQVM->sqvm, arg); };
+ return [arg]{ g_pSquirrel<context>->pushobject(g_pSquirrel<context>->m_pSQVM->sqvm, arg); };
}
// Ints
template <ScriptContext context, typename T>
diff --git a/primedev/squirrel/squirrelclasstypes.h b/primedev/squirrel/squirrelclasstypes.h
index 91c3c468..3a39c957 100644
--- a/primedev/squirrel/squirrelclasstypes.h
+++ b/primedev/squirrel/squirrelclasstypes.h
@@ -227,6 +227,7 @@ typedef SQRESULT (*sq_setuserdatatypeidType)(HSquirrelVM* sqvm, SQInteger iStack
// sq misc entity funcs
typedef void* (*sq_getentityfrominstanceType)(CSquirrelVM* sqvm, SQObject* pInstance, char** ppEntityConstant);
+typedef SQObject* (*sq_createscriptinstanceType)(void* ent);
typedef char** (*sq_GetEntityConstantType)();
typedef int (*sq_getfunctionType)(HSquirrelVM* sqvm, const char* name, SQObject* returnObj, const char* signature);