Skip to content

Commit

Permalink
Merge branch 'main' into feat/overhaul-mod-loading-locations
Browse files Browse the repository at this point in the history
  • Loading branch information
GeckoEidechse committed Aug 7, 2024
2 parents d4273d6 + 51991cc commit fff09b8
Show file tree
Hide file tree
Showing 15 changed files with 89 additions and 13 deletions.
33 changes: 30 additions & 3 deletions primedev/client/audio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
#include <iostream>
#include <sstream>
#include <random>
#include <ranges>

namespace fs = std::filesystem;

AUTOHOOK_INIT()

Expand All @@ -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)
{
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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
Expand All @@ -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});
}
Expand Down
6 changes: 4 additions & 2 deletions primedev/client/audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <regex>
#include <shared_mutex>

namespace fs = std::filesystem;

enum class AudioSelectionStrategy
{
INVALID = -1,
Expand All @@ -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:
Expand All @@ -35,7 +37,7 @@ class EventOverrideData
class CustomAudioManager
{
public:
bool TryLoadAudioOverride(const fs::path&);
bool TryLoadAudioOverride(const fs::path&, std::string modName);
void ClearAudioOverrides();

std::shared_mutex m_loadingMutex;
Expand Down
2 changes: 2 additions & 0 deletions primedev/client/languagehooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include <filesystem>
#include <regex>

namespace fs = std::filesystem;

AUTOHOOK_INIT()

typedef LANGID (*Tier0_DetectDefaultLanguageType)();
Expand Down
2 changes: 2 additions & 0 deletions primedev/core/hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

#define XINPUT1_3_DLL "XInput1_3.dll"

namespace fs = std::filesystem;

AUTOHOOK_INIT()

// called from the ON_DLL_LOAD macros
Expand Down
6 changes: 1 addition & 5 deletions primedev/logging/logging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
31 changes: 30 additions & 1 deletion primedev/mods/autodownload/moddownloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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]()
{
Expand All @@ -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;
Expand All @@ -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)
{
Expand All @@ -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();

Expand All @@ -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}});
Expand Down Expand Up @@ -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(
Expand Down
4 changes: 4 additions & 0 deletions primedev/mods/autodownload/moddownloader.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
namespace fs = std::filesystem;

class ModDownloader
{
private:
Expand Down Expand Up @@ -114,6 +116,8 @@ class ModDownloader

enum ModInstallState
{
MANIFESTO_FETCHING,

// Normal installation process
DOWNLOADING,
CHECKSUMING,
Expand Down
2 changes: 1 addition & 1 deletion primedev/mods/modmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions primedev/mods/modmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
2 changes: 2 additions & 0 deletions primedev/plugins/pluginmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions primedev/plugins/pluginmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

#include <windows.h>

namespace fs = std::filesystem;

class Plugin;

class PluginManager
Expand Down
2 changes: 2 additions & 0 deletions primedev/server/buildainfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <fstream>
#include <filesystem>

namespace fs = std::filesystem;

AUTOHOOK_INIT()

const int AINET_VERSION_NUMBER = 57;
Expand Down
2 changes: 2 additions & 0 deletions primedev/squirrel/squirrel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
5 changes: 4 additions & 1 deletion primedev/squirrel/squirrel.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "core/math/vector.h"
#include "mods/modmanager.h"

namespace fs = std::filesystem;

/*
definitions from hell
required to function
Expand Down Expand Up @@ -115,6 +117,7 @@ class SquirrelManagerBase
sq_getfunctionType __sq_getfunction;

sq_getentityfrominstanceType __sq_getentityfrominstance;
sq_createscriptinstanceType __sq_createscriptinstance;
sq_GetEntityConstantType __sq_GetEntityConstant_CBaseEntity;

sq_pushnewstructinstanceType __sq_pushnewstructinstance;
Expand Down Expand Up @@ -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>
Expand Down
1 change: 1 addition & 0 deletions primedev/squirrel/squirrelclasstypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit fff09b8

Please sign in to comment.