aboutsummaryrefslogtreecommitdiff
path: root/NorthstarDedicatedTest
diff options
context:
space:
mode:
authorKawe Mazidjatari <48657826+Mauler125@users.noreply.github.com>2022-07-17 02:18:23 +0200
committerGitHub <noreply@github.com>2022-07-17 02:18:23 +0200
commit671de14bdaf2ee0178aaeba6d069afb51072e4ec (patch)
tree1e5c8cecc6283b282fdbca60b20468f9fa1848d1 /NorthstarDedicatedTest
parent388b76eca0419a0d1fb691c57e974ad604955dad (diff)
parent85635ad99dbdfa909341e4138f6fdb0c9bf73bf1 (diff)
downloadNorthstarLauncher-671de14bdaf2ee0178aaeba6d069afb51072e4ec.tar.gz
NorthstarLauncher-671de14bdaf2ee0178aaeba6d069afb51072e4ec.zip
Merge branch 'main' into NetCon
Diffstat (limited to 'NorthstarDedicatedTest')
-rw-r--r--NorthstarDedicatedTest/ExploitFixes.cpp70
-rw-r--r--NorthstarDedicatedTest/ExploitFixes.h8
-rw-r--r--NorthstarDedicatedTest/NSMem.h20
-rw-r--r--NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj2
-rw-r--r--NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters6
-rw-r--r--NorthstarDedicatedTest/dllmain.cpp16
-rw-r--r--NorthstarDedicatedTest/modmanager.cpp41
-rw-r--r--NorthstarDedicatedTest/modmanager.h7
-rw-r--r--NorthstarDedicatedTest/rpakfilesystem.cpp19
-rw-r--r--NorthstarDedicatedTest/scriptutility.cpp29
-rw-r--r--NorthstarDedicatedTest/scriptutility.h4
-rw-r--r--NorthstarDedicatedTest/squirrel.cpp36
-rw-r--r--NorthstarDedicatedTest/squirrel.h46
13 files changed, 254 insertions, 50 deletions
diff --git a/NorthstarDedicatedTest/ExploitFixes.cpp b/NorthstarDedicatedTest/ExploitFixes.cpp
index 44b62d55..2f4e2b5c 100644
--- a/NorthstarDedicatedTest/ExploitFixes.cpp
+++ b/NorthstarDedicatedTest/ExploitFixes.cpp
@@ -4,6 +4,7 @@
#include "ExploitFixes_UTF8Parser.h"
#include "NSMem.h"
#include "cvar.h"
+#include "gameutils.h"
ConVar* ns_exploitfixes_log;
#define SHOULD_LOG (ns_exploitfixes_log->m_Value.m_nValue > 0)
@@ -271,14 +272,11 @@ INVALID_CMD:
// basically: by default r2 isn't set as a valve mod, meaning that m_bRestrictServerCommands is false
// this is HORRIBLE for security, because it means servers can run arbitrary concommands on clients
// especially since we have script commands this could theoretically be awful
-#include "gameutils.h"
-
-typedef void (*IsValveModType)();
-IsValveModType IsValveMod;
-
-bool IsValveModHook()
+KHOOK(IsValveMod, ("engine.dll", "48 83 EC 28 48 8B 0D ? ? ? ? 48 8D 15 ? ? ? ? E8 ? ? ? ? 85 C0 74 63"), bool, __fastcall, ())
{
- return !CommandLine()->CheckParm("-norestrictservercommands");
+ bool result = !CommandLine()->CheckParm("-norestrictservercommands");
+ spdlog::info("ExploitFixes: Overriding IsValveMod to {}...", result);
+ return result;
}
// Fix respawn's crappy UTF8 parser so it doesn't crash -_-
@@ -490,36 +488,62 @@ KHOOK(
return oSpecialClientCommand(player, command);
}
-void ExploitFixes::LoadCallback(HMODULE baseAddress)
+void SetupKHook(KHook* hook)
{
- spdlog::info("ExploitFixes::LoadCallback ...");
-
- spdlog::info("\tByte patching...");
- DoBytePatches();
-
- if (KHook::InitAllHooks())
+ if (hook->Setup())
{
- spdlog::info("\tInitialized " + std::to_string(KHook::_allHooks.size()) + " exploit-patch hooks.");
+ spdlog::debug("KHook::Setup(): Hooked at {}", hook->targetFuncAddr);
}
else
{
spdlog::critical("\tFAILED to initialize all exploit patches.");
- // Force exit?
+ // Force exit
MessageBoxA(0, "FAILED to initialize all exploit patches.", "Northstar", MB_ICONERROR);
exit(0);
}
+}
- ns_exploitfixes_log =
- new ConVar("ns_exploitfixes_log", "1", FCVAR_GAMEDLL, "Whether to log whenever ExploitFixes.cpp blocks/corrects something");
+void ExploitFixes::LoadCallback_MultiModule(HMODULE baseAddress)
+{
- HookEnabler hook;
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x2a8a50, &GetEntByIndexHook, reinterpret_cast<LPVOID*>(&GetEntByIndex));
+ spdlog::info("ExploitFixes::LoadCallback_MultiModule({}) ...", (void*)baseAddress);
+
+ int hooksEnabled = 0;
+ for (auto itr = KHook::_allHooks.begin(); itr != KHook::_allHooks.end(); itr++)
+ {
+ auto curHook = *itr;
+ if (GetModuleHandleA(curHook->targetFunc.moduleName) == baseAddress)
+ {
+ SetupKHook(curHook);
+ itr = KHook::_allHooks.erase(itr); // Prevent repeated initialization
+
+ hooksEnabled++;
+
+ if (itr == KHook::_allHooks.end())
+ break;
+ }
+ }
+
+ spdlog::info("\tEnabled {} hooks.", hooksEnabled);
}
-void ExploitFixes::LoadCallbackEngine(HMODULE baseAddress)
+void ExploitFixes::LoadCallback_Full(HMODULE baseAddress)
{
- spdlog::info("ExploitFixes::LoadCallbackEngine ...");
+ spdlog::info("ExploitFixes::LoadCallback_Full ...");
+
+ spdlog::info("\tByte patching...");
+ DoBytePatches();
+
+ for (KHook* hook : KHook::_allHooks)
+ SetupKHook(hook);
+
+ spdlog::info("\tInitialized " + std::to_string(KHook::_allHooks.size()) + " late exploit-patch hooks.");
+ KHook::_allHooks.clear();
+
+ ns_exploitfixes_log =
+ new ConVar("ns_exploitfixes_log", "1", FCVAR_GAMEDLL, "Whether to log whenever ExploitFixes.cpp blocks/corrects something");
+
HookEnabler hook;
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x1C6360, &IsValveModHook, reinterpret_cast<LPVOID*>(&IsValveMod));
+ ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x2a8a50, &GetEntByIndexHook, reinterpret_cast<LPVOID*>(&GetEntByIndex));
} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/ExploitFixes.h b/NorthstarDedicatedTest/ExploitFixes.h
index 1cafe758..d0754d72 100644
--- a/NorthstarDedicatedTest/ExploitFixes.h
+++ b/NorthstarDedicatedTest/ExploitFixes.h
@@ -5,6 +5,8 @@
namespace ExploitFixes
{
- void LoadCallback(HMODULE unused);
- void LoadCallbackEngine(HMODULE baseAddress);
-} // namespace ExploitFixes \ No newline at end of file
+ // This callback will be ran muliple times on multiple module loads
+ void LoadCallback_MultiModule(HMODULE baseAddress);
+
+ void LoadCallback_Full(HMODULE unused);
+} // namespace ExploitFixes
diff --git a/NorthstarDedicatedTest/NSMem.h b/NorthstarDedicatedTest/NSMem.h
index 74df3a84..84bb93db 100644
--- a/NorthstarDedicatedTest/NSMem.h
+++ b/NorthstarDedicatedTest/NSMem.h
@@ -182,25 +182,7 @@ struct KHook
if (!targetFuncAddr)
return false;
- return MH_CreateHook(targetFuncAddr, hookFunc, original) == MH_OK;
- }
-
- // Returns true if succeeded
- static bool InitAllHooks()
- {
- for (KHook* hook : _allHooks)
- {
- if (hook->Setup())
- {
- spdlog::info("KHook hooked at {}", hook->targetFuncAddr);
- }
- else
- {
- return false;
- }
- }
-
- return MH_EnableHook(MH_ALL_HOOKS) == MH_OK;
+ return (MH_CreateHook(targetFuncAddr, hookFunc, original) == MH_OK) && (MH_EnableHook(targetFuncAddr) == MH_OK);
}
};
#define KHOOK(name, funcPatternInfo, returnType, convention, args) \
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
index 4151a7e5..b086965c 100644
--- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
+++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
@@ -128,6 +128,7 @@
<ClInclude Include="net.h" />
<ClInclude Include="NetAdr2.h" />
<ClInclude Include="rcon_shared.h" />
+ <ClInclude Include="scriptutility.h" />
<ClInclude Include="serverchathooks.h" />
<ClInclude Include="clientauthhooks.h" />
<ClInclude Include="color.h" />
@@ -636,6 +637,7 @@
<ClCompile Include="scriptmodmenu.cpp" />
<ClCompile Include="scriptserverbrowser.cpp" />
<ClCompile Include="scriptsrson.cpp" />
+ <ClCompile Include="scriptutility.cpp" />
<ClCompile Include="serverauthentication.cpp" />
<ClCompile Include="miscserverscript.cpp" />
<ClCompile Include="serverchathooks.cpp" />
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
index b3387eab..77c01917 100644
--- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
+++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
@@ -1548,6 +1548,9 @@
<ClInclude Include="NSMem.h">
<Filter>Header Files\Shared\ExploitFixes</Filter>
</ClInclude>
+ <ClInclude Include="scriptutility.h">
+ <Filter>Header Files\Shared</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
@@ -1745,6 +1748,9 @@
<ClCompile Include="clientruihooks.cpp">
<Filter>Source Files\Client</Filter>
</ClCompile>
+ <ClCompile Include="scriptutility.cpp">
+ <Filter>Source Files\Shared</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<MASM Include="audio_asm.asm">
diff --git a/NorthstarDedicatedTest/dllmain.cpp b/NorthstarDedicatedTest/dllmain.cpp
index 67b350de..aa6f4174 100644
--- a/NorthstarDedicatedTest/dllmain.cpp
+++ b/NorthstarDedicatedTest/dllmain.cpp
@@ -44,6 +44,8 @@
#include "debugoverlay.h"
#include "clientvideooverrides.h"
#include "clientruihooks.h"
+#include "version.h"
+#include "scriptutility.h"
#include "rapidjson/document.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
@@ -253,6 +255,7 @@ bool InitialiseNorthstar()
AddDllLoadCallbackForClient("client.dll", InitialiseClientVideoOverrides);
AddDllLoadCallbackForClient("engine.dll", InitialiseEngineClientRUIHooks);
AddDllLoadCallbackForClient("engine.dll", InitialiseDebugOverlay);
+ AddDllLoadCallbackForClient("client.dll", InitialiseClientSquirrelUtilityFunctions);
// audio hooks
AddDllLoadCallbackForClient("client.dll", InitialiseMilesAudioHooks);
}
@@ -265,6 +268,7 @@ bool InitialiseNorthstar()
AddDllLoadCallback("server.dll", InitialiseMiscServerScriptCommand);
AddDllLoadCallback("server.dll", InitialiseMiscServerFixes);
AddDllLoadCallback("server.dll", InitialiseBuildAINFileHooks);
+ AddDllLoadCallback("server.dll", InitialiseServerSquirrelUtilityFunctions);
AddDllLoadCallback("engine.dll", InitializeCHostStateHooks);
AddDllLoadCallback("engine.dll", InitializeRconSystems);
@@ -286,9 +290,15 @@ bool InitialiseNorthstar()
// mod manager after everything else
AddDllLoadCallback("engine.dll", InitialiseModManager);
- // activate exploit fixes
- AddDllLoadCallback("server.dll", ExploitFixes::LoadCallback);
- AddDllLoadCallback("engine.dll", ExploitFixes::LoadCallbackEngine);
+ {
+ // activate multi-module exploitfixes callbacks
+ constexpr const char* EXPLOITFIXES_MULTICALLBACK_MODS[] = {"client.dll", "engine.dll", "server.dll"};
+ for (const char* mod : EXPLOITFIXES_MULTICALLBACK_MODS)
+ AddDllLoadCallback(mod, ExploitFixes::LoadCallback_MultiModule);
+
+ // activate exploit fixes later
+ AddDllLoadCallback("server.dll", ExploitFixes::LoadCallback_Full);
+ }
// run callbacks for any libraries that are already loaded by now
CallAllPendingDLLLoadCallbacks();
diff --git a/NorthstarDedicatedTest/modmanager.cpp b/NorthstarDedicatedTest/modmanager.cpp
index 50c7b371..de45bd23 100644
--- a/NorthstarDedicatedTest/modmanager.cpp
+++ b/NorthstarDedicatedTest/modmanager.cpp
@@ -186,6 +186,26 @@ Mod::Mod(fs::path modDir, char* jsonBuf)
}
}
+ if (modJson.HasMember("Dependencies") && modJson["Dependencies"].IsObject())
+ {
+ for (auto v = modJson["Dependencies"].MemberBegin(); v != modJson["Dependencies"].MemberEnd(); v++)
+ {
+ if (!v->name.IsString() || !v->value.IsString())
+ continue;
+
+ spdlog::info("Constant {} defined by {} for mod {}", v->name.GetString(), Name, v->value.GetString());
+ if (DependencyConstants.find(v->name.GetString()) != DependencyConstants.end() &&
+ v->value.GetString() != DependencyConstants[v->name.GetString()])
+ {
+ spdlog::error("A dependency constant with the same name already exists for another mod. Change the constant name.");
+ return;
+ }
+
+ if (DependencyConstants.find(v->name.GetString()) == DependencyConstants.end())
+ DependencyConstants.emplace(v->name.GetString(), v->value.GetString());
+ }
+ }
+
wasReadSuccessfully = true;
}
@@ -212,6 +232,8 @@ void ModManager::LoadMods()
fs::remove_all(GetCompiledAssetsPath());
fs::create_directories(GetModFolderPath());
+ DependencyConstants.clear();
+
// read enabled mods cfg
std::ifstream enabledModsStream(GetNorthstarPrefix() + "/enabledmods.json");
std::stringstream enabledModsStringStream;
@@ -253,6 +275,18 @@ void ModManager::LoadMods()
Mod mod(modDir, (char*)jsonStringStream.str().c_str());
+ for (auto& pair : mod.DependencyConstants)
+ {
+ if (DependencyConstants.find(pair.first) != DependencyConstants.end() && DependencyConstants[pair.first] != pair.second)
+ {
+ spdlog::error("Constant {} in mod {} already exists in another mod.", pair.first, mod.Name);
+ mod.wasReadSuccessfully = false;
+ break;
+ }
+ if (DependencyConstants.find(pair.first) == DependencyConstants.end())
+ DependencyConstants.emplace(pair);
+ }
+
if (m_hasEnabledModsCfg && m_enabledModsCfg.HasMember(mod.Name.c_str()))
mod.Enabled = m_enabledModsCfg[mod.Name.c_str()].IsTrue();
else
@@ -383,6 +417,13 @@ void ModManager::LoadMods()
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();
+ }
+
modPak.m_sPakName = pakName;
// not using atm because we need to resolve path to rpak
diff --git a/NorthstarDedicatedTest/modmanager.h b/NorthstarDedicatedTest/modmanager.h
index 798c2306..d605eec2 100644
--- a/NorthstarDedicatedTest/modmanager.h
+++ b/NorthstarDedicatedTest/modmanager.h
@@ -57,6 +57,7 @@ struct ModRpakEntry
public:
bool m_bAutoLoad;
std::string m_sPakName;
+ std::string m_sLoadAfterPak;
};
class Mod
@@ -99,6 +100,9 @@ class Mod
std::vector<ModRpakEntry> Rpaks;
std::unordered_map<std::string, std::string>
RpakAliases; // paks we alias to other rpaks, e.g. to load sp_crashsite paks on the map mp_crashsite
+ // iterated over to create squirrel VM constants depending if a mod exists or not.
+ // this only exists because we cannot access g_ModManager whilst mods are being loaded for the first time for some reason.
+ std::unordered_map<std::string, std::string> DependencyConstants;
// other stuff
@@ -129,6 +133,9 @@ class ModManager
public:
std::vector<Mod> m_loadedMods;
std::unordered_map<std::string, ModOverrideFile> m_modFiles;
+ // iterated over to create squirrel VM constants depending if a mod exists or not.
+ // here because constants are global anyways.
+ std::unordered_map<std::string, std::string> DependencyConstants;
public:
ModManager();
diff --git a/NorthstarDedicatedTest/rpakfilesystem.cpp b/NorthstarDedicatedTest/rpakfilesystem.cpp
index b3105996..1a4736a9 100644
--- a/NorthstarDedicatedTest/rpakfilesystem.cpp
+++ b/NorthstarDedicatedTest/rpakfilesystem.cpp
@@ -108,6 +108,23 @@ void LoadPreloadPaks()
}
}
+void LoadPostloadPaks(char** map)
+{
+ // note, loading from ./ is necessary otherwise paks will load from gamedir/r2/paks
+ for (Mod& mod : g_ModManager->m_loadedMods)
+ {
+ if (!mod.Enabled)
+ continue;
+
+ // need to get a relative path of mod to mod folder
+ fs::path modPakPath("./" / mod.ModDirectory / "paks");
+
+ for (ModRpakEntry& pak : mod.Rpaks)
+ if (pak.m_sLoadAfterPak == *map)
+ g_PakLoadManager->LoadPakAsync((modPakPath / pak.m_sPakName).string().c_str(), false);
+ }
+}
+
void LoadCustomMapPaks(char** pakName, bool* bNeedToFreePakName)
{
// whether the vanilla game has this rpak
@@ -212,6 +229,8 @@ int LoadPakAsyncHook(char* path, void* unknownSingleton, int flags, void* callba
// add the hash to the map
g_PakLoadManager->AddLoadedPak(ret, hash);
+ LoadPostloadPaks(&path);
+
if (bNeedToFreePakName)
delete[] path;
diff --git a/NorthstarDedicatedTest/scriptutility.cpp b/NorthstarDedicatedTest/scriptutility.cpp
new file mode 100644
index 00000000..98c6f3a3
--- /dev/null
+++ b/NorthstarDedicatedTest/scriptutility.cpp
@@ -0,0 +1,29 @@
+#include "pch.h"
+#include "scriptutility.h"
+#include "squirrel.h"
+
+template <ScriptContext context> SQRESULT SQ_StringToAsset(void* sqvm)
+{
+ if (context == ScriptContext::SERVER)
+ {
+ const char* asset = ServerSq_getstring(sqvm, 1);
+ ServerSq_pushAsset(sqvm, asset, -1);
+ }
+ else
+ {
+ const char* asset = ClientSq_getstring(sqvm, 1);
+ ClientSq_pushAsset(sqvm, asset, -1);
+ }
+ return SQRESULT_NOTNULL;
+}
+
+void InitialiseClientSquirrelUtilityFunctions(HMODULE baseAddress)
+{
+ g_ClientSquirrelManager->AddFuncRegistration("asset", "StringToAsset", "string assetName", "", SQ_StringToAsset<ScriptContext::CLIENT>);
+ g_UISquirrelManager->AddFuncRegistration("asset", "StringToAsset", "string assetName", "", SQ_StringToAsset<ScriptContext::UI>);
+}
+
+void InitialiseServerSquirrelUtilityFunctions(HMODULE baseAddress)
+{
+ g_ServerSquirrelManager->AddFuncRegistration("asset", "StringToAsset", "string assetName", "", SQ_StringToAsset<ScriptContext::SERVER>);
+} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/scriptutility.h b/NorthstarDedicatedTest/scriptutility.h
new file mode 100644
index 00000000..2b58ebfb
--- /dev/null
+++ b/NorthstarDedicatedTest/scriptutility.h
@@ -0,0 +1,4 @@
+#pragma once
+
+void InitialiseClientSquirrelUtilityFunctions(HMODULE baseAddress);
+void InitialiseServerSquirrelUtilityFunctions(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/squirrel.cpp b/NorthstarDedicatedTest/squirrel.cpp
index 2fd558cd..cba0d880 100644
--- a/NorthstarDedicatedTest/squirrel.cpp
+++ b/NorthstarDedicatedTest/squirrel.cpp
@@ -74,6 +74,12 @@ sq_pushboolType ServerSq_pushbool;
sq_pusherrorType ClientSq_pusherror;
sq_pusherrorType ServerSq_pusherror;
+sq_defconst ClientSq_defconst;
+sq_defconst ServerSq_defconst;
+
+sq_pushAssetType ClientSq_pushAsset;
+sq_pushAssetType ServerSq_pushAsset;
+
// sq stack get funcs
sq_getstringType ClientSq_getstring;
sq_getstringType ServerSq_getstring;
@@ -138,6 +144,7 @@ void InitialiseClientSquirrel(HMODULE baseAddress)
ClientSq_pushfloat = (sq_pushfloatType)((char*)baseAddress + 0x3800);
ClientSq_pushbool = (sq_pushboolType)((char*)baseAddress + 0x3710);
ClientSq_pusherror = (sq_pusherrorType)((char*)baseAddress + 0x8470);
+ ClientSq_pushAsset = (sq_pushAssetType)((char*)baseAddress + 0x3560);
ClientSq_getstring = (sq_getstringType)((char*)baseAddress + 0x60C0);
ClientSq_getinteger = (sq_getintegerType)((char*)baseAddress + 0x60E0);
@@ -146,6 +153,8 @@ void InitialiseClientSquirrel(HMODULE baseAddress)
ClientSq_sq_get = (sq_getType)((char*)baseAddress + 0x7C30);
+ ClientSq_defconst = (sq_defconst)((char*)baseAddress + 0x12120);
+
ENABLER_CREATEHOOK(
hook,
(char*)baseAddress + 0x26130,
@@ -192,6 +201,7 @@ void InitialiseServerSquirrel(HMODULE baseAddress)
ServerSq_pushfloat = (sq_pushfloatType)((char*)baseAddress + 0x3800);
ServerSq_pushbool = (sq_pushboolType)((char*)baseAddress + 0x3710);
ServerSq_pusherror = (sq_pusherrorType)((char*)baseAddress + 0x8440);
+ ServerSq_pushAsset = (sq_pushAssetType)((char*)baseAddress + 0x3560);
ServerSq_getstring = (sq_getstringType)((char*)baseAddress + 0x60A0);
ServerSq_getinteger = (sq_getintegerType)((char*)baseAddress + 0x60C0);
@@ -200,6 +210,8 @@ void InitialiseServerSquirrel(HMODULE baseAddress)
ServerSq_sq_get = (sq_getType)((char*)baseAddress + 0x7C00);
+ ServerSq_defconst = (sq_defconst)((char*)baseAddress + 0x1F550);
+
ENABLER_CREATEHOOK(
hook,
(char*)baseAddress + 0x1FE90,
@@ -515,4 +527,28 @@ template <ScriptContext context> int64_t RegisterSquirrelFuncHook(void* sqvm, SQ
return ServerRegisterSquirrelFunc(sqvm, funcReg, unknown);
else
return ClientRegisterSquirrelFunc(sqvm, funcReg, unknown);
+}
+
+SQReturnTypeEnum GetReturnTypeEnumFromString(const char* returnTypeString)
+{
+
+ static std::map<std::string, SQReturnTypeEnum> sqEnumStrMap = {
+ {"bool", SqReturnBoolean},
+ {"float", SqReturnFloat},
+ {"vector", SqReturnVector},
+ {"int", SqReturnInteger},
+ {"entity", SqReturnEntity},
+ {"string", SqReturnString},
+ {"array", SqReturnArrays},
+ {"asset", SqReturnAsset},
+ {"table", SqReturnTable}};
+
+ if (sqEnumStrMap.count(returnTypeString))
+ {
+ return sqEnumStrMap[returnTypeString];
+ }
+ else
+ {
+ return SqReturnDefault; // previous default value
+ }
} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/squirrel.h b/NorthstarDedicatedTest/squirrel.h
index d6dfcc57..0e49c7f8 100644
--- a/NorthstarDedicatedTest/squirrel.h
+++ b/NorthstarDedicatedTest/squirrel.h
@@ -1,3 +1,4 @@
+#include <../modmanager.h>
#pragma once
void InitialiseClientSquirrel(HMODULE baseAddress);
@@ -18,6 +19,20 @@ const SQRESULT SQRESULT_NOTNULL = 1;
typedef SQInteger (*SQFunction)(void* sqvm);
+enum SQReturnTypeEnum
+{
+ SqReturnFloat = 0x1,
+ SqReturnVector = 0x3,
+ SqReturnInteger = 0x5,
+ SqReturnBoolean = 0x6,
+ SqReturnEntity = 0xD,
+ SqReturnString = 0x21,
+ SqReturnDefault = 0x20,
+ SqReturnArrays = 0x25,
+ SqReturnAsset = 0x28,
+ SqReturnTable = 0x26,
+};
+
struct CompileBufferState
{
const SQChar* buffer;
@@ -43,7 +58,7 @@ struct SQFuncRegistration
__int32 devLevel;
const char* shortNameMaybe;
__int32 unknown2;
- __int32 returnTypeEnum;
+ SQReturnTypeEnum returnTypeEnum;
__int32* externalBufferPointer;
__int64 externalBufferSize;
__int64 unknown3;
@@ -53,10 +68,12 @@ struct SQFuncRegistration
SQFuncRegistration()
{
memset(this, 0, sizeof(SQFuncRegistration));
- this->returnTypeEnum = 32;
+ this->returnTypeEnum = SqReturnDefault;
}
};
+SQReturnTypeEnum GetReturnTypeEnumFromString(const char* returnTypeString);
+
// core sqvm funcs
typedef SQRESULT (*sq_compilebufferType)(void* sqvm, CompileBufferState* compileBuffer, const char* file, int a1, ScriptContext a2);
extern sq_compilebufferType ClientSq_compilebuffer;
@@ -105,6 +122,14 @@ typedef SQInteger (*sq_pusherrorType)(void* sqvm, const SQChar* error);
extern sq_pusherrorType ClientSq_pusherror;
extern sq_pusherrorType ServerSq_pusherror;
+typedef void (*sq_defconst)(void* sqvm, const SQChar* name, int value);
+extern sq_defconst ClientSq_defconst;
+extern sq_defconst ServerSq_defconst;
+
+typedef SQRESULT (*sq_pushAssetType)(void* sqvm, const SQChar* assetName, SQInteger nameLength);
+extern sq_pushAssetType ServerSq_pushAsset;
+extern sq_pushAssetType ClientSq_pushAsset;
+
// sq stack get funcs
typedef const SQChar* (*sq_getstringType)(void* sqvm, SQInteger stackpos);
extern sq_getstringType ClientSq_getstring;
@@ -152,6 +177,22 @@ template <ScriptContext context> class SquirrelManager
else
ServerRegisterSquirrelFunc(sqvm, funcReg, 1);
}
+ for (auto& pair : g_ModManager->DependencyConstants)
+ {
+ bool wasFound = false;
+ for (Mod& dependency : g_ModManager->m_loadedMods)
+ {
+ if (dependency.Name == pair.second)
+ {
+ wasFound = dependency.Enabled;
+ break;
+ }
+ }
+ if (context == ScriptContext::SERVER)
+ ServerSq_defconst(sqvm, pair.first.c_str(), wasFound);
+ else
+ ClientSq_defconst(sqvm, pair.first.c_str(), wasFound);
+ }
}
void VMDestroyed()
@@ -277,6 +318,7 @@ template <ScriptContext context> class SquirrelManager
reg->returnTypeString = new char[returnType.size() + 1];
strcpy((char*)reg->returnTypeString, returnType.c_str());
+ reg->returnTypeEnum = GetReturnTypeEnumFromString(returnType.c_str());
reg->argTypes = new char[argTypes.size() + 1];
strcpy((char*)reg->argTypes, argTypes.c_str());