aboutsummaryrefslogtreecommitdiff
path: root/primedev
diff options
context:
space:
mode:
authorGeckoEidechse <40122905+GeckoEidechse@users.noreply.github.com>2024-08-09 23:12:12 +0200
committerGitHub <noreply@github.com>2024-08-09 23:12:12 +0200
commitd679e05049db1e70c40923aac6cefccd3fbe9ca0 (patch)
tree834c5fb41c20b3029b118ee62f1bde15eb0869d4 /primedev
parent59d19a8b539801b0b0ed614f343f12d22a762f07 (diff)
parenta28c1cb10cc805907d22b656ccc300b39b720a88 (diff)
downloadNorthstarLauncher-d679e05049db1e70c40923aac6cefccd3fbe9ca0.tar.gz
NorthstarLauncher-d679e05049db1e70c40923aac6cefccd3fbe9ca0.zip
Merge branch 'main' into feat/whitelist-safeio-file-extensions
Diffstat (limited to 'primedev')
-rw-r--r--primedev/CMakeLists.txt2
-rw-r--r--primedev/Northstar.cmake12
-rw-r--r--primedev/client/audio.cpp33
-rw-r--r--primedev/client/audio.h6
-rw-r--r--primedev/client/languagehooks.cpp4
-rw-r--r--primedev/client/latencyflex.cpp4
-rw-r--r--primedev/core/hooks.cpp6
-rw-r--r--primedev/core/hooks.h4
-rw-r--r--primedev/core/memalloc.cpp36
-rw-r--r--primedev/core/memalloc.h16
-rw-r--r--primedev/dedicated/dedicatedlogtoclient.h2
-rw-r--r--primedev/logging/logging.cpp6
-rw-r--r--primedev/logging/sourceconsole.h2
-rw-r--r--primedev/mods/autodownload/moddownloader.cpp31
-rw-r--r--primedev/mods/autodownload/moddownloader.h4
-rw-r--r--primedev/mods/modmanager.cpp30
-rw-r--r--primedev/mods/modmanager.h2
-rw-r--r--primedev/pch.h5
-rw-r--r--primedev/plugins/interfaces/interface.h2
-rw-r--r--primedev/plugins/pluginmanager.cpp2
-rw-r--r--primedev/plugins/pluginmanager.h2
-rw-r--r--primedev/plugins/plugins.cpp8
-rw-r--r--primedev/primelauncher/CMakeLists.txt (renamed from primedev/Launcher.cmake)4
-rw-r--r--primedev/scripts/client/scriptmodmenu.cpp17
-rw-r--r--primedev/scripts/scriptjson.cpp4
-rw-r--r--primedev/server/buildainfile.cpp2
-rw-r--r--primedev/server/serverpresence.cpp4
-rw-r--r--primedev/server/serverpresence.h5
-rw-r--r--primedev/shared/exploit_fixes/exploitfixes.cpp36
-rw-r--r--primedev/shared/keyvalues.cpp12
-rw-r--r--primedev/squirrel/squirrel.cpp16
-rw-r--r--primedev/squirrel/squirrel.h7
-rw-r--r--primedev/squirrel/squirrelclasstypes.h1
-rw-r--r--primedev/thirdparty/rapidjson/document.h4
-rw-r--r--primedev/wsockproxy/CMakeLists.txt11
-rw-r--r--primedev/wsockproxy/dllmain.cpp1
-rw-r--r--primedev/wsockproxy/loader.cpp2
-rw-r--r--primedev/wsockproxy/loader.h2
-rw-r--r--primedev/wsockproxy/pch.h16
-rw-r--r--primedev/wsockproxy/wsock32.def1
40 files changed, 250 insertions, 114 deletions
diff --git a/primedev/CMakeLists.txt b/primedev/CMakeLists.txt
index 31dda4b2..a33fd351 100644
--- a/primedev/CMakeLists.txt
+++ b/primedev/CMakeLists.txt
@@ -1,3 +1,3 @@
include(Northstar.cmake)
-include(Launcher.cmake)
+add_subdirectory(primelauncher)
add_subdirectory(wsockproxy)
diff --git a/primedev/Northstar.cmake b/primedev/Northstar.cmake
index aef630c8..40583d28 100644
--- a/primedev/Northstar.cmake
+++ b/primedev/Northstar.cmake
@@ -172,13 +172,13 @@ target_link_libraries(
libcurl
minizip
silver-bun
- WS2_32.lib
- Crypt32.lib
- Cryptui.lib
+ ws2_32.lib
+ crypt32.lib
+ cryptui.lib
dbghelp.lib
- Wldap32.lib
- Normaliz.lib
- Bcrypt.lib
+ wldap32.lib
+ normaliz.lib
+ bcrypt.lib
version.lib
)
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 35ca5659..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)();
@@ -41,7 +43,7 @@ std::vector<std::string> file_list(fs::path dir, std::regex ext_pattern)
std::string GetAnyInstalledAudioLanguage()
{
for (const auto& lang : file_list("r2\\sound\\", std::regex(".*?general_([a-z]+)_patch_1\\.mstr")))
- if (lang != "general" || lang != "")
+ if (lang != "general" && lang != "" && lang != "stream")
return lang;
return "NO LANGUAGE DETECTED";
}
diff --git a/primedev/client/latencyflex.cpp b/primedev/client/latencyflex.cpp
index 25e38c7a..39557870 100644
--- a/primedev/client/latencyflex.cpp
+++ b/primedev/client/latencyflex.cpp
@@ -24,10 +24,10 @@ ON_DLL_LOAD_CLIENT_RELIESON("client.dll", LatencyFlex, ConVar, (CModule module))
// https://ishitatsuyuki.github.io/post/latencyflex/
HMODULE pLfxModule;
- if (pLfxModule = LoadLibraryA("latencyflex_layer.dll"))
+ if ((pLfxModule = LoadLibraryA("latencyflex_layer.dll")))
m_winelfx_WaitAndBeginFrame =
reinterpret_cast<void (*)()>(reinterpret_cast<void*>(GetProcAddress(pLfxModule, "lfx_WaitAndBeginFrame")));
- else if (pLfxModule = LoadLibraryA("latencyflex_wine.dll"))
+ else if ((pLfxModule = LoadLibraryA("latencyflex_wine.dll")))
m_winelfx_WaitAndBeginFrame =
reinterpret_cast<void (*)()>(reinterpret_cast<void*>(GetProcAddress(pLfxModule, "winelfx_WaitAndBeginFrame")));
else
diff --git a/primedev/core/hooks.cpp b/primedev/core/hooks.cpp
index 20f0cbef..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
@@ -104,7 +106,9 @@ bool ManualHook::Dispatch(LPVOID addr, LPVOID* orig)
if (orig)
ppOrigFunc = orig;
- if (MH_CreateHook(addr, pHookFunc, ppOrigFunc) == MH_OK)
+ if (!addr)
+ spdlog::error("Address for hook {} is invalid", pFuncName);
+ else if (MH_CreateHook(addr, pHookFunc, ppOrigFunc) == MH_OK)
{
if (MH_EnableHook(addr) == MH_OK)
{
diff --git a/primedev/core/hooks.h b/primedev/core/hooks.h
index f842afbb..e5a65354 100644
--- a/primedev/core/hooks.h
+++ b/primedev/core/hooks.h
@@ -201,7 +201,9 @@ public:
}
}
- if (MH_CreateHook(targetAddr, pHookFunc, ppOrigFunc) == MH_OK)
+ if (!targetAddr)
+ spdlog::error("Address for hook {} is invalid", pFuncName);
+ else if (MH_CreateHook(targetAddr, pHookFunc, ppOrigFunc) == MH_OK)
{
if (MH_EnableHook(targetAddr) == MH_OK)
spdlog::info("Enabling hook {}", pFuncName);
diff --git a/primedev/core/memalloc.cpp b/primedev/core/memalloc.cpp
index 0a75bc2b..51167717 100644
--- a/primedev/core/memalloc.cpp
+++ b/primedev/core/memalloc.cpp
@@ -3,7 +3,7 @@
// TODO: rename to malloc and free after removing statically compiled .libs
-extern "C" void* _malloc_base(size_t n)
+void* _malloc_base(size_t n)
{
// allocate into static buffer if g_pMemAllocSingleton isn't initialised
if (!g_pMemAllocSingleton)
@@ -17,7 +17,7 @@ extern "C" void* _malloc_base(size_t n)
return _malloc_base(n);
}*/
-extern "C" void _free_base(void* p)
+void _free_base(void* p)
{
if (!g_pMemAllocSingleton)
TryCreateGlobalMemAlloc();
@@ -25,7 +25,7 @@ extern "C" void _free_base(void* p)
g_pMemAllocSingleton->m_vtable->Free(g_pMemAllocSingleton, p);
}
-extern "C" void* _realloc_base(void* oldPtr, size_t size)
+void* _realloc_base(void* oldPtr, size_t size)
{
if (!g_pMemAllocSingleton)
TryCreateGlobalMemAlloc();
@@ -33,7 +33,7 @@ extern "C" void* _realloc_base(void* oldPtr, size_t size)
return g_pMemAllocSingleton->m_vtable->Realloc(g_pMemAllocSingleton, oldPtr, size);
}
-extern "C" void* _calloc_base(size_t n, size_t size)
+void* _calloc_base(size_t n, size_t size)
{
size_t bytes = n * size;
void* memory = _malloc_base(bytes);
@@ -44,7 +44,33 @@ extern "C" void* _calloc_base(size_t n, size_t size)
return memory;
}
-extern "C" char* _strdup_base(const char* src)
+void* _recalloc_base(void* const block, size_t const count, size_t const size)
+{
+ if (!block)
+ return _calloc_base(count, size);
+
+ const size_t new_size = count * size;
+ const size_t old_size = _msize(block);
+
+ void* const memory = _realloc_base(block, new_size);
+
+ if (memory && old_size < new_size)
+ {
+ memset(static_cast<char*>(memory) + old_size, 0, new_size - old_size);
+ }
+
+ return memory;
+}
+
+size_t _msize(void* const block)
+{
+ if (!g_pMemAllocSingleton)
+ TryCreateGlobalMemAlloc();
+
+ return g_pMemAllocSingleton->m_vtable->GetSize(g_pMemAllocSingleton, block);
+}
+
+char* _strdup_base(const char* src)
{
char* str;
char* p;
diff --git a/primedev/core/memalloc.h b/primedev/core/memalloc.h
index 2f383335..73e078f5 100644
--- a/primedev/core/memalloc.h
+++ b/primedev/core/memalloc.h
@@ -1,14 +1,18 @@
#pragma once
+#include <malloc.h>
+
#include "rapidjson/document.h"
// #include "include/rapidjson/allocators.h"
-extern "C" void* _malloc_base(size_t size);
-extern "C" void* _calloc_base(size_t const count, size_t const size);
-extern "C" void* _realloc_base(void* block, size_t size);
-extern "C" void* _recalloc_base(void* const block, size_t const count, size_t const size);
-extern "C" void _free_base(void* const block);
-extern "C" char* _strdup_base(const char* src);
+// The prelude is needed for these to be usable by the CRT
+extern "C" __declspec(noinline) void* __cdecl _malloc_base(size_t const size);
+extern "C" __declspec(noinline) void* __cdecl _calloc_base(size_t const count, size_t const size);
+extern "C" __declspec(noinline) void* __cdecl _realloc_base(void* const block, size_t const size);
+extern "C" __declspec(noinline) void* __cdecl _recalloc_base(void* const block, size_t const count, size_t const size);
+extern "C" __declspec(noinline) void __cdecl _free_base(void* const block);
+extern "C" __declspec(noinline) size_t __cdecl _msize(void* const block);
+extern "C" __declspec(noinline) char* __cdecl _strdup_base(const char* src);
void* operator new(size_t n);
void operator delete(void* p) noexcept;
diff --git a/primedev/dedicated/dedicatedlogtoclient.h b/primedev/dedicated/dedicatedlogtoclient.h
index 82f4c56b..5678982e 100644
--- a/primedev/dedicated/dedicatedlogtoclient.h
+++ b/primedev/dedicated/dedicatedlogtoclient.h
@@ -5,7 +5,7 @@
class DedicatedServerLogToClientSink : public CustomSink
{
protected:
- void custom_sink_it_(const custom_log_msg& msg);
+ void custom_sink_it_(const custom_log_msg& msg) override;
void sink_it_(const spdlog::details::log_msg& msg) override;
void flush_() override;
};
diff --git a/primedev/logging/logging.cpp b/primedev/logging/logging.cpp
index 72171e25..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 (AllocConsole() == FALSE)
- {
- std::cout << "[*] Failed to create a console window, maybe a console already exists?" << std::endl;
- }
- else
+ if (AllocConsole() != FALSE)
{
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
diff --git a/primedev/logging/sourceconsole.h b/primedev/logging/sourceconsole.h
index 44d73843..215dae1a 100644
--- a/primedev/logging/sourceconsole.h
+++ b/primedev/logging/sourceconsole.h
@@ -77,7 +77,7 @@ private:
{spdlog::level::off, NS::Colors::OFF.ToSourceColor()}};
protected:
- void custom_sink_it_(const custom_log_msg& msg);
+ void custom_sink_it_(const custom_log_msg& msg) override;
void sink_it_(const spdlog::details::log_msg& msg) override;
void flush_() override;
};
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 268a65a5..45eddd3e 100644
--- a/primedev/mods/modmanager.cpp
+++ b/primedev/mods/modmanager.cpp
@@ -601,6 +601,8 @@ auto ModConCommandCallback(const CCommand& command)
case ScriptContext::UI:
ModConCommandCallback_Internal<ScriptContext::UI>(found->Function, command);
break;
+ default:
+ spdlog::error("ModConCommandCallback on invalid Context {}", found->Context);
};
}
@@ -746,7 +748,7 @@ void ModManager::LoadMods()
continue;
// Add mod entry to enabledmods.json if it doesn't exist
- if (!mod.m_bIsRemote && !m_EnabledModsCfg.HasMember(mod.Name.c_str()))
+ if (!mod.m_bIsRemote && m_bHasEnabledModsCfg && !m_EnabledModsCfg.HasMember(mod.Name.c_str()))
{
m_EnabledModsCfg.AddMember(rapidjson_document::StringRefType(mod.Name.c_str()), true, m_EnabledModsCfg.GetAllocator());
newModsDetected = true;
@@ -864,16 +866,24 @@ void ModManager::LoadMods()
if (fs::is_regular_file(file) && file.path().extension() == ".rpak")
{
std::string pakName(file.path().filename().string());
-
ModRpakEntry& modPak = mod.Rpaks.emplace_back();
- modPak.m_bAutoLoad =
- !bUseRpakJson || (dRpakJson.HasMember("Preload") && dRpakJson["Preload"].IsObject() &&
- dRpakJson["Preload"].HasMember(pakName) && dRpakJson["Preload"][pakName].IsTrue());
- // postload things
- if (!bUseRpakJson ||
- (dRpakJson.HasMember("Postload") && dRpakJson["Postload"].IsObject() && dRpakJson["Postload"].HasMember(pakName)))
- modPak.m_sLoadAfterPak = dRpakJson["Postload"][pakName].GetString();
+ if (!bUseRpakJson)
+ {
+ spdlog::warn("Mod {} contains rpaks without valid rpak.json, rpaks might not be loaded", mod.Name);
+ }
+ else
+ {
+ modPak.m_bAutoLoad =
+ (dRpakJson.HasMember("Preload") && dRpakJson["Preload"].IsObject() && dRpakJson["Preload"].HasMember(pakName) &&
+ dRpakJson["Preload"][pakName].IsTrue());
+
+ // postload things
+ if (dRpakJson.HasMember("Postload") && dRpakJson["Postload"].IsObject() && dRpakJson["Postload"].HasMember(pakName))
+ {
+ modPak.m_sLoadAfterPak = dRpakJson["Postload"][pakName].GetString();
+ }
+ }
modPak.m_sPakName = pakName;
@@ -970,7 +980,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 233f004d..95a8fe12 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 MOD_FOLDER_SUFFIX = "\\mods";
const std::string THUNDERSTORE_MOD_FOLDER_SUFFIX = "\\packages";
const std::string REMOTE_MOD_FOLDER_SUFFIX = "\\runtime\\remote\\mods";
diff --git a/primedev/pch.h b/primedev/pch.h
index 577f803c..bfd25597 100644
--- a/primedev/pch.h
+++ b/primedev/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
diff --git a/primedev/plugins/interfaces/interface.h b/primedev/plugins/interfaces/interface.h
index 440db5b2..c4f8b6ae 100644
--- a/primedev/plugins/interfaces/interface.h
+++ b/primedev/plugins/interfaces/interface.h
@@ -34,6 +34,6 @@ public:
static className __g_##className##_singleton; \
EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, __g_##className##_singleton)
-EXPORT void* CreateInterface(const char* pName, InterfaceStatus* pReturnCode);
+extern "C" __declspec(dllexport) void* CreateInterface(const char* pName, InterfaceStatus* pReturnCode);
#endif
diff --git a/primedev/plugins/pluginmanager.cpp b/primedev/plugins/pluginmanager.cpp
index 718e6956..14d5692b 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/plugins/plugins.cpp b/primedev/plugins/plugins.cpp
index ae6fd0cb..03dd2c9e 100644
--- a/primedev/plugins/plugins.cpp
+++ b/primedev/plugins/plugins.cpp
@@ -45,15 +45,15 @@ Plugin::Plugin(std::string path) : m_location(path)
m_initData = {.pluginHandle = m_handle};
- CreateInterfaceFn CreatePluginInterface = (CreateInterfaceFn)GetProcAddress(m_handle, "CreateInterface");
+ m_pCreateInterface = (CreateInterfaceFn)GetProcAddress(m_handle, "CreateInterface");
- if (!CreatePluginInterface)
+ if (!m_pCreateInterface)
{
NS::log::PLUGINSYS->error("Plugin at '{}' does not expose CreateInterface()", path);
return;
}
- m_pluginId = (IPluginId*)CreatePluginInterface(PLUGIN_ID_VERSION, 0);
+ m_pluginId = (IPluginId*)m_pCreateInterface(PLUGIN_ID_VERSION, 0);
if (!m_pluginId)
{
@@ -97,7 +97,7 @@ Plugin::Plugin(std::string path) : m_location(path)
return;
}
- m_callbacks = (IPluginCallbacks*)CreatePluginInterface("PluginCallbacks001", 0);
+ m_callbacks = (IPluginCallbacks*)m_pCreateInterface("PluginCallbacks001", 0);
if (!m_callbacks)
{
diff --git a/primedev/Launcher.cmake b/primedev/primelauncher/CMakeLists.txt
index c04fc70b..f36781a9 100644
--- a/primedev/Launcher.cmake
+++ b/primedev/primelauncher/CMakeLists.txt
@@ -1,6 +1,6 @@
# NorthstarLauncher
-add_executable(NorthstarLauncher "primelauncher/main.cpp" "primelauncher/resources.rc")
+add_executable(NorthstarLauncher "main.cpp" "resources.rc")
target_compile_definitions(NorthstarLauncher PRIVATE UNICODE _UNICODE)
@@ -19,7 +19,7 @@ target_link_libraries(
uuid.lib
odbc32.lib
odbccp32.lib
- WS2_32.lib
+ ws2_32.lib
)
set_target_properties(
diff --git a/primedev/scripts/client/scriptmodmenu.cpp b/primedev/scripts/client/scriptmodmenu.cpp
index 2e877db4..5ffe0fdf 100644
--- a/primedev/scripts/client/scriptmodmenu.cpp
+++ b/primedev/scripts/client/scriptmodmenu.cpp
@@ -49,6 +49,23 @@ ADD_SQFUNC("void", NSSetModEnabled, "string modName, bool enabled", "", ScriptCo
return SQRESULT_NULL;
}
+ADD_SQFUNC("bool", NSIsModRemote, "string modName", "", ScriptContext::SERVER | ScriptContext::CLIENT | ScriptContext::UI)
+{
+ const SQChar* modName = g_pSquirrel<context>->getstring(sqvm, 1);
+
+ // manual lookup, not super performant but eh not a big deal
+ for (Mod& mod : g_pModManager->m_LoadedMods)
+ {
+ if (!mod.Name.compare(modName))
+ {
+ g_pSquirrel<context>->pushbool(sqvm, mod.m_bIsRemote);
+ return SQRESULT_NOTNULL;
+ }
+ }
+
+ return SQRESULT_NULL;
+}
+
ADD_SQFUNC("string", NSGetModDescriptionByModName, "string modName", "", ScriptContext::SERVER | ScriptContext::CLIENT | ScriptContext::UI)
{
const SQChar* modName = g_pSquirrel<context>->getstring(sqvm, 1);
diff --git a/primedev/scripts/scriptjson.cpp b/primedev/scripts/scriptjson.cpp
index 06bda6f4..8959bf47 100644
--- a/primedev/scripts/scriptjson.cpp
+++ b/primedev/scripts/scriptjson.cpp
@@ -42,6 +42,8 @@ DecodeJsonArray(HSquirrelVM* sqvm, rapidjson::GenericValue<rapidjson::UTF8<char>
g_pSquirrel<context>->pushinteger(sqvm, itr.GetInt());
g_pSquirrel<context>->arrayappend(sqvm, -2);
break;
+ case rapidjson::kNullType:
+ break;
}
}
}
@@ -92,6 +94,8 @@ DecodeJsonTable(HSquirrelVM* sqvm, rapidjson::GenericValue<rapidjson::UTF8<char>
}
g_pSquirrel<context>->newslot(sqvm, -3, false);
break;
+ case rapidjson::kNullType:
+ break;
}
}
}
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/server/serverpresence.cpp b/primedev/server/serverpresence.cpp
index 509243f0..099f6e64 100644
--- a/primedev/server/serverpresence.cpp
+++ b/primedev/server/serverpresence.cpp
@@ -78,7 +78,7 @@ void ServerPresenceManager::CreateConVars()
Cvar_ns_server_presence_update_rate = new ConVar(
"ns_server_presence_update_rate", "5000", FCVAR_GAMEDLL, "How often we update our server's presence on server lists in ms");
- Cvar_ns_server_name = new ConVar("ns_server_name", "Unnamed Northstar Server", FCVAR_GAMEDLL, "This server's name", false, 0, false, 0, [](ConVar* cvar, const char* pOldValue, float flOldValue) {
+ Cvar_ns_server_name = new ConVar("ns_server_name", "Unnamed Northstar Server", FCVAR_GAMEDLL | FCVAR_REPLICATED, "This server's name", false, 0, false, 0, [](ConVar* cvar, const char* pOldValue, float flOldValue) {
NOTE_UNUSED(cvar);
NOTE_UNUSED(pOldValue);
NOTE_UNUSED(flOldValue);
@@ -88,7 +88,7 @@ void ServerPresenceManager::CreateConVars()
Cvar_hostname->SetValue(g_pServerPresence->Cvar_ns_server_name->GetString());
});
- Cvar_ns_server_desc = new ConVar("ns_server_desc", "Default server description", FCVAR_GAMEDLL, "This server's description", false, 0, false, 0, [](ConVar* cvar, const char* pOldValue, float flOldValue) {
+ Cvar_ns_server_desc = new ConVar("ns_server_desc", "Default server description", FCVAR_GAMEDLL | FCVAR_REPLICATED, "This server's description", false, 0, false, 0, [](ConVar* cvar, const char* pOldValue, float flOldValue) {
NOTE_UNUSED(cvar);
NOTE_UNUSED(pOldValue);
NOTE_UNUSED(flOldValue);
diff --git a/primedev/server/serverpresence.h b/primedev/server/serverpresence.h
index 94ecfe6a..07c6fb55 100644
--- a/primedev/server/serverpresence.h
+++ b/primedev/server/serverpresence.h
@@ -19,10 +19,7 @@ public:
int m_iPlayerCount;
int m_iMaxPlayers;
- ServerPresence()
- {
- memset(this, 0, sizeof(this));
- }
+ ServerPresence() {}
ServerPresence(const ServerPresence* obj)
{
diff --git a/primedev/shared/exploit_fixes/exploitfixes.cpp b/primedev/shared/exploit_fixes/exploitfixes.cpp
index d96bc41e..1b3069f5 100644
--- a/primedev/shared/exploit_fixes/exploitfixes.cpp
+++ b/primedev/shared/exploit_fixes/exploitfixes.cpp
@@ -120,19 +120,31 @@ bool, __fastcall, (void* pMsg)) // 48 8B D1 48 8B 49 18 48 8B 01 48 FF 60 10
if (!nameValid || !valValid)
return BLOCKED_INFO("Missing null terminators");
- ConVar* pVar = g_pCVar->FindVar(entry->name);
-
- if (pVar)
+ // we only need to check if these cvars are valid on client as it will set actual cvars there
+ // on server this won't set any actual convars, only keyvalues in the player, which doesn't have really any potential for dumb
+ // stuff
+ if (!bIsServerFrame)
{
- memcpy(
- entry->name,
- pVar->m_ConCommandBase.m_pszName,
- strlen(pVar->m_ConCommandBase.m_pszName) + 1); // Force name to match case
-
- int iFlags = bIsServerFrame ? FCVAR_USERINFO : FCVAR_REPLICATED;
- if (!pVar->IsFlagSet(iFlags))
- return BLOCKED_INFO(
- "Invalid flags (" << std::hex << "0x" << pVar->m_ConCommandBase.m_nFlags << "), var is " << entry->name);
+ ConVar* pVar = g_pCVar->FindVar(entry->name);
+ if (pVar)
+ {
+ memcpy(
+ entry->name,
+ pVar->m_ConCommandBase.m_pszName,
+ strlen(pVar->m_ConCommandBase.m_pszName) + 1); // Force name to match case
+
+ if (!pVar->IsFlagSet(FCVAR_REPLICATED))
+ {
+ spdlog::warn(
+ "Blocking replication of remote cvar {} from server (server's var has flag REPLICATED, while ours does not)",
+ entry->name);
+
+ // don't block, as non-malicious servers might send bad cvars, and we still want those clients to be able to
+ // connect
+ memset(entry->name, 0, ENTRY_STR_LEN);
+ memset(entry->val, 0, ENTRY_STR_LEN);
+ }
+ }
}
}
else
diff --git a/primedev/shared/keyvalues.cpp b/primedev/shared/keyvalues.cpp
index 36f891eb..46ce4e04 100644
--- a/primedev/shared/keyvalues.cpp
+++ b/primedev/shared/keyvalues.cpp
@@ -511,7 +511,7 @@ bool KeyValues::IsEmpty(const char* pszKeyName)
KeyValues* KeyValues::GetFirstTrueSubKey(void) const
{
assert_msg(this, "Member function called on NULL KeyValues");
- KeyValues* pRet = this ? m_pSub : nullptr;
+ KeyValues* pRet = m_pSub;
while (pRet && pRet->m_iDataType != TYPE_NONE)
pRet = pRet->m_pPeer;
@@ -525,7 +525,7 @@ KeyValues* KeyValues::GetFirstTrueSubKey(void) const
KeyValues* KeyValues::GetNextTrueSubKey(void) const
{
assert_msg(this, "Member function called on NULL KeyValues");
- KeyValues* pRet = this ? m_pPeer : nullptr;
+ KeyValues* pRet = m_pPeer;
while (pRet && pRet->m_iDataType != TYPE_NONE)
pRet = pRet->m_pPeer;
@@ -539,7 +539,7 @@ KeyValues* KeyValues::GetNextTrueSubKey(void) const
KeyValues* KeyValues::GetFirstValue(void) const
{
assert_msg(this, "Member function called on NULL KeyValues");
- KeyValues* pRet = this ? m_pSub : nullptr;
+ KeyValues* pRet = m_pSub;
while (pRet && pRet->m_iDataType == TYPE_NONE)
pRet = pRet->m_pPeer;
@@ -553,7 +553,7 @@ KeyValues* KeyValues::GetFirstValue(void) const
KeyValues* KeyValues::GetNextValue(void) const
{
assert_msg(this, "Member function called on NULL KeyValues");
- KeyValues* pRet = this ? m_pPeer : nullptr;
+ KeyValues* pRet = m_pPeer;
while (pRet && pRet->m_iDataType == TYPE_NONE)
pRet = pRet->m_pPeer;
@@ -566,7 +566,7 @@ KeyValues* KeyValues::GetNextValue(void) const
KeyValues* KeyValues::GetFirstSubKey() const
{
assert_msg(this, "Member function called on NULL KeyValues");
- return this ? m_pSub : nullptr;
+ return m_pSub;
}
//-----------------------------------------------------------------------------
@@ -575,7 +575,7 @@ KeyValues* KeyValues::GetFirstSubKey() const
KeyValues* KeyValues::GetNextKey() const
{
assert_msg(this, "Member function called on NULL KeyValues");
- return this ? m_pPeer : nullptr;
+ return m_pPeer;
}
//-----------------------------------------------------------------------------
diff --git a/primedev/squirrel/squirrel.cpp b/primedev/squirrel/squirrel.cpp
index 41a6a782..29540cce 100644
--- a/primedev/squirrel/squirrel.cpp
+++ b/primedev/squirrel/squirrel.cpp
@@ -157,11 +157,6 @@ const char* SQTypeNameFromID(int type)
return "";
}
-// needed to define implementations for squirrelmanager outside of squirrel.h without compiler errors
-template class SquirrelManager<ScriptContext::SERVER>;
-template class SquirrelManager<ScriptContext::CLIENT>;
-template class SquirrelManager<ScriptContext::UI>;
-
template <ScriptContext context> void SquirrelManager<context>::VMCreated(CSquirrelVM* newSqvm)
{
m_pSQVM = newSqvm;
@@ -712,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;
@@ -805,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
@@ -845,3 +842,12 @@ void InitialiseSquirrelManagers()
g_pSquirrel<ScriptContext::UI> = new SquirrelManager<ScriptContext::UI>;
g_pSquirrel<ScriptContext::SERVER> = new SquirrelManager<ScriptContext::SERVER>;
}
+
+// needed to define implementations for squirrelmanager outside of squirrel.h without compiler errors
+template class SquirrelManager<ScriptContext::SERVER>;
+template class SquirrelManager<ScriptContext::CLIENT>;
+template class SquirrelManager<ScriptContext::UI>;
+
+template std::shared_ptr<spdlog::logger> NS::log::squirrel_logger<ScriptContext::SERVER>();
+template std::shared_ptr<spdlog::logger> NS::log::squirrel_logger<ScriptContext::CLIENT>();
+template std::shared_ptr<spdlog::logger> NS::log::squirrel_logger<ScriptContext::UI>();
diff --git a/primedev/squirrel/squirrel.h b/primedev/squirrel/squirrel.h
index 0c1f24d3..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;
@@ -136,7 +139,7 @@ public:
inline SQRESULT _call(HSquirrelVM* sqvm, const SQInteger args)
{
- return __sq_call(sqvm, args + 1, false, false);
+ return __sq_call(sqvm, args + 1, false, true);
}
inline SQInteger raiseerror(HSquirrelVM* sqvm, const SQChar* sError)
@@ -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);
diff --git a/primedev/thirdparty/rapidjson/document.h b/primedev/thirdparty/rapidjson/document.h
index 22fb2f56..a5465a3c 100644
--- a/primedev/thirdparty/rapidjson/document.h
+++ b/primedev/thirdparty/rapidjson/document.h
@@ -318,8 +318,6 @@ struct GenericStringRef {
GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {}
- GenericStringRef& operator=(const GenericStringRef& rhs) { s = rhs.s; length = rhs.length; }
-
//! implicit conversion to plain CharType pointer
operator const Ch *() const { return s; }
@@ -330,6 +328,8 @@ private:
//! Disallow construction from non-const array
template<SizeType N>
GenericStringRef(CharType (&str)[N]) /* = delete */;
+ //! Copy assignment operator not permitted - immutable type
+ GenericStringRef& operator=(const GenericStringRef& rhs) /* = delete */;
};
//! Mark a character pointer as constant string
diff --git a/primedev/wsockproxy/CMakeLists.txt b/primedev/wsockproxy/CMakeLists.txt
index 0dbac745..3f6bce45 100644
--- a/primedev/wsockproxy/CMakeLists.txt
+++ b/primedev/wsockproxy/CMakeLists.txt
@@ -15,7 +15,7 @@ target_link_libraries(
PRIVATE minhook
mswsock.lib
ws2_32.lib
- ShLwApi.lib
+ shlwapi.lib
imagehlp.lib
dbghelp.lib
kernel32.lib
@@ -32,14 +32,13 @@ target_link_libraries(
odbccp32.lib
)
-target_precompile_headers(
+target_compile_definitions(
loader_wsock32_proxy
- PRIVATE
- pch.h
+ PRIVATE UNICODE
+ _UNICODE
+ WIN32_LEAN_AND_MEAN
)
-target_compile_definitions(loader_wsock32_proxy PRIVATE UNICODE _UNICODE)
-
set_target_properties(
loader_wsock32_proxy
PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${NS_BINARY_DIR}/bin/x64_retail
diff --git a/primedev/wsockproxy/dllmain.cpp b/primedev/wsockproxy/dllmain.cpp
index 5a606e45..9716c1b8 100644
--- a/primedev/wsockproxy/dllmain.cpp
+++ b/primedev/wsockproxy/dllmain.cpp
@@ -1,5 +1,6 @@
#include "loader.h"
+#include <windows.h>
#include <filesystem>
FARPROC p[73];
diff --git a/primedev/wsockproxy/loader.cpp b/primedev/wsockproxy/loader.cpp
index a3abf11c..4664c20c 100644
--- a/primedev/wsockproxy/loader.cpp
+++ b/primedev/wsockproxy/loader.cpp
@@ -7,6 +7,8 @@
#include <filesystem>
#include <iostream>
+#include "MinHook.h"
+
namespace fs = std::filesystem;
static wchar_t northstarPath[8192];
diff --git a/primedev/wsockproxy/loader.h b/primedev/wsockproxy/loader.h
index 0c6fb053..6287e515 100644
--- a/primedev/wsockproxy/loader.h
+++ b/primedev/wsockproxy/loader.h
@@ -1,5 +1,7 @@
#pragma once
+#include <windows.h>
+
extern wchar_t exePath[4096];
extern wchar_t buffer1[8192];
extern wchar_t buffer2[12288];
diff --git a/primedev/wsockproxy/pch.h b/primedev/wsockproxy/pch.h
deleted file mode 100644
index ebc29547..00000000
--- a/primedev/wsockproxy/pch.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// pch.h: This is a precompiled header file.
-// Files listed below are compiled only once, improving build performance for future builds.
-// This also affects IntelliSense performance, including code completion and many code browsing features.
-// However, files listed here are ALL re-compiled if any one of them is updated between builds.
-// Do not add files here that you will be updating frequently as this negates the performance advantage.
-
-#ifndef PCH_H
-#define PCH_H
-
-#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
-// Windows Header Files
-#include <windows.h>
-
-#include "MinHook.h"
-
-#endif // PCH_H
diff --git a/primedev/wsockproxy/wsock32.def b/primedev/wsockproxy/wsock32.def
index 448440b4..187b2959 100644
--- a/primedev/wsockproxy/wsock32.def
+++ b/primedev/wsockproxy/wsock32.def
@@ -69,7 +69,6 @@ EXPORTS
rresvport=ws2_32.rresvport
s_perror=PROXY_s_perror
select=ws2_32.select @18
- select=ws2_32.select @18
send=ws2_32.send @19
sendto=ws2_32.sendto @20
sethostname=ws2_32.sethostname