aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj2
-rw-r--r--NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters6
-rw-r--r--NorthstarDedicatedTest/dllmain.cpp4
-rw-r--r--NorthstarDedicatedTest/filesystem.cpp12
-rw-r--r--NorthstarDedicatedTest/modmanager.cpp8
-rw-r--r--NorthstarDedicatedTest/scriptmodmenu.cpp124
-rw-r--r--NorthstarDedicatedTest/scriptmodmenu.h3
-rw-r--r--NorthstarDedicatedTest/scriptsrson.cpp2
-rw-r--r--NorthstarDedicatedTest/serverauthentication.cpp14
-rw-r--r--NorthstarDedicatedTest/squirrel.cpp54
-rw-r--r--NorthstarDedicatedTest/squirrel.h42
11 files changed, 267 insertions, 4 deletions
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
index 87ea35a2..203edbb3 100644
--- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
+++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
@@ -307,6 +307,7 @@
<ClInclude Include="main.h" />
<ClInclude Include="modmanager.h" />
<ClInclude Include="pch.h" />
+ <ClInclude Include="scriptmodmenu.h" />
<ClInclude Include="scriptsrson.h" />
<ClInclude Include="serverauthentication.h" />
<ClInclude Include="sigscanning.h" />
@@ -332,6 +333,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
+ <ClCompile Include="scriptmodmenu.cpp" />
<ClCompile Include="scriptsrson.cpp" />
<ClCompile Include="serverauthentication.cpp" />
<ClCompile Include="sigscanning.cpp" />
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
index f6ff5453..71bae5bc 100644
--- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
+++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
@@ -534,6 +534,9 @@
<ClInclude Include="serverauthentication.h">
<Filter>Header Files\Server\Authentication</Filter>
</ClInclude>
+ <ClInclude Include="scriptmodmenu.h">
+ <Filter>Header Files\Client</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
@@ -590,6 +593,9 @@
<ClCompile Include="serverauthentication.cpp">
<Filter>Source Files\Server\Authentication</Filter>
</ClCompile>
+ <ClCompile Include="scriptmodmenu.cpp">
+ <Filter>Source Files\Client</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="include\spdlog\fmt\bundled\LICENSE.rst">
diff --git a/NorthstarDedicatedTest/dllmain.cpp b/NorthstarDedicatedTest/dllmain.cpp
index cc40a00c..b0040598 100644
--- a/NorthstarDedicatedTest/dllmain.cpp
+++ b/NorthstarDedicatedTest/dllmain.cpp
@@ -9,7 +9,7 @@
#include "modmanager.h"
#include "filesystem.h"
#include "serverauthentication.h"
-#include <iostream>
+#include "scriptmodmenu.h"
bool initialised = false;
@@ -53,7 +53,9 @@ void InitialiseNorthstar()
if (!IsDedicated())
{
AddDllLoadCallback("client.dll", InitialiseClientSquirrel);
+
AddDllLoadCallback("client.dll", InitialiseSourceConsole);
+ AddDllLoadCallback("client.dll", InitialiseScriptModMenu);
}
AddDllLoadCallback("server.dll", InitialiseServerSquirrel);
diff --git a/NorthstarDedicatedTest/filesystem.cpp b/NorthstarDedicatedTest/filesystem.cpp
index 1a2fb993..323b8756 100644
--- a/NorthstarDedicatedTest/filesystem.cpp
+++ b/NorthstarDedicatedTest/filesystem.cpp
@@ -21,6 +21,10 @@ typedef void(*AddSearchPathType)(IFileSystem* fileSystem, const char* pPath, con
AddSearchPathType addSearchPathOriginal;
void AddSearchPathHook(IFileSystem* fileSystem, const char* pPath, const char* pathID, SearchPathAdd_t addType);
+typedef FileHandle_t(*ReadFileFromFilesystemType)(IFileSystem* filesystem, const char* pPath, const char* pOptions, int64_t a4, uint32_t a5);
+ReadFileFromFilesystemType readFileFromFilesystem;
+FileHandle_t ReadFileFromFilesystemHook(IFileSystem* filesystem, const char* pPath, const char* pOptions, int64_t a4, uint32_t a5);
+
bool readingOriginalFile;
std::string currentModPath;
SourceInterface<IFileSystem>* g_Filesystem;
@@ -34,6 +38,7 @@ void InitialiseFilesystem(HMODULE baseAddress)
ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x5CBA0, &ReadFileFromVPKHook, reinterpret_cast<LPVOID*>(&readFileFromVPK));
ENABLER_CREATEHOOK(hook, (*g_Filesystem)->m_vtable->ReadFromCache, &ReadFromCacheHook, reinterpret_cast<LPVOID*>(&readFromCache));
ENABLER_CREATEHOOK(hook, (*g_Filesystem)->m_vtable->AddSearchPath, &AddSearchPathHook, reinterpret_cast<LPVOID*>(&addSearchPathOriginal));
+ ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x15F20, &ReadFileFromFilesystemHook, reinterpret_cast<LPVOID*>(&readFileFromFilesystem));
}
std::string ReadVPKFile(const char* path)
@@ -136,4 +141,11 @@ void AddSearchPathHook(IFileSystem* fileSystem, const char* pPath, const char* p
addSearchPathOriginal(fileSystem, currentModPath.c_str(), "GAME", PATH_ADD_TO_HEAD);
addSearchPathOriginal(fileSystem, COMPILED_ASSETS_PATH.string().c_str(), "GAME", PATH_ADD_TO_HEAD);
}
+}
+
+FileHandle_t ReadFileFromFilesystemHook(IFileSystem* filesystem, const char* pPath, const char* pOptions, int64_t a4, uint32_t a5)
+{
+ // this isn't super efficient, but it's necessary, since calling addsearchpath in readfilefromvpk doesn't work, possibly refactor later
+ TryReplaceFile((char*)pPath);
+ return readFileFromFilesystem(filesystem, pPath, pOptions, a4, a5);
} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/modmanager.cpp b/NorthstarDedicatedTest/modmanager.cpp
index 964d37ae..ae1ad98a 100644
--- a/NorthstarDedicatedTest/modmanager.cpp
+++ b/NorthstarDedicatedTest/modmanager.cpp
@@ -1,6 +1,7 @@
#include "pch.h"
#include "modmanager.h"
#include "convar.h"
+#include "concommand.h"
#include "rapidjson/error/en.h"
#include "rapidjson/document.h"
@@ -272,7 +273,14 @@ void ModManager::CompileAssetsForFile(const char* filename)
}
+void ReloadModsCommand(const CCommand& args)
+{
+ g_ModManager->LoadMods();
+}
+
void InitialiseModManager(HMODULE baseAddress)
{
g_ModManager = new ModManager();
+
+ RegisterConCommand("reload_mods", ReloadModsCommand, "idk", FCVAR_NONE);
} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/scriptmodmenu.cpp b/NorthstarDedicatedTest/scriptmodmenu.cpp
new file mode 100644
index 00000000..f65b3a8c
--- /dev/null
+++ b/NorthstarDedicatedTest/scriptmodmenu.cpp
@@ -0,0 +1,124 @@
+#include "pch.h"
+#include "scriptmodmenu.h"
+#include "modmanager.h"
+#include "squirrel.h"
+
+// array<string> NSGetModNames()
+SQInteger SQ_GetModNames(void* sqvm)
+{
+ ClientSq_newarray(sqvm, 0);
+
+ for (Mod* mod : g_ModManager->m_loadedMods)
+ {
+ ClientSq_pushstring(sqvm, mod->Name.c_str(), -1);
+ ClientSq_arrayappend(sqvm, -2);
+ }
+
+ return 1;
+}
+
+// string NSGetModDescriptionByModName(string modName)
+SQInteger SQ_GetModDescription(void* sqvm)
+{
+ const SQChar* modName = ClientSq_getstring(sqvm, 1);
+
+ // manual lookup, not super performant but eh not a big deal
+ for (Mod* mod : g_ModManager->m_loadedMods)
+ {
+ if (!mod->Name.compare(modName))
+ {
+ ClientSq_pushstring(sqvm, mod->Description.c_str(), -1);
+ return 1;
+ }
+ }
+
+ return 0; // return null
+}
+
+// string NSGetModVersionByModName(string modName)
+SQInteger SQ_GetModVersion(void* sqvm)
+{
+ const SQChar* modName = ClientSq_getstring(sqvm, 1);
+
+ // manual lookup, not super performant but eh not a big deal
+ for (Mod* mod : g_ModManager->m_loadedMods)
+ {
+ if (!mod->Name.compare(modName))
+ {
+ ClientSq_pushstring(sqvm, mod->Version.c_str(), -1);
+ return 1;
+ }
+ }
+
+ return 0; // return null
+}
+
+// string NSGetModDownloadLinkByModName(string modName)
+SQInteger SQ_GetModDownloadLink(void* sqvm)
+{
+ const SQChar* modName = ClientSq_getstring(sqvm, 1);
+
+ // manual lookup, not super performant but eh not a big deal
+ for (Mod* mod : g_ModManager->m_loadedMods)
+ {
+ if (!mod->Name.compare(modName))
+ {
+ ClientSq_pushstring(sqvm, mod->DownloadLink.c_str(), -1);
+ return 1;
+ }
+ }
+
+ return 0; // return null
+}
+
+// int NSGetModLoadPriority(string modName)
+SQInteger SQ_GetModLoadPriority(void* sqvm)
+{
+ const SQChar* modName = ClientSq_getstring(sqvm, 1);
+
+ // manual lookup, not super performant but eh not a big deal
+ for (Mod* mod : g_ModManager->m_loadedMods)
+ {
+ if (!mod->Name.compare(modName))
+ {
+ ClientSq_pushinteger(sqvm, mod->LoadPriority);
+ return 1;
+ }
+ }
+
+ return 0; // return null
+}
+
+// array<string> NSGetModConvarsByModName(string modName)
+SQInteger SQ_GetModConvars(void* sqvm)
+{
+ const SQChar* modName = ClientSq_getstring(sqvm, 1);
+ ClientSq_newarray(sqvm, 0);
+
+ // manual lookup, not super performant but eh not a big deal
+ for (Mod* mod : g_ModManager->m_loadedMods)
+ {
+ if (!mod->Name.compare(modName))
+ {
+ for (ModConVar* cvar : mod->ConVars)
+ {
+ ClientSq_pushstring(sqvm, cvar->Name.c_str(), -1);
+ ClientSq_arrayappend(sqvm, -2);
+ }
+
+ return 1;
+ }
+ }
+
+ return 1; // return empty array
+}
+
+void InitialiseScriptModMenu(HMODULE baseAddress)
+{
+ g_UISquirrelManager->AddFuncRegistration("array<string>", "NSGetModNames", "", "Returns the names of all loaded mods", SQ_GetModNames);
+ g_UISquirrelManager->AddFuncRegistration("string", "NSGetModDescriptionByModName", "asset modName", "Returns a given mod's description", SQ_GetModDescription);
+ g_UISquirrelManager->AddFuncRegistration("string", "NSGetModVersionByModName", "string modName", "Returns a given mod's version", SQ_GetModVersion);
+ g_UISquirrelManager->AddFuncRegistration("string", "NSGetModDownloadLinkByModName", "string modName", "Returns a given mod's download link", SQ_GetModVersion);
+ g_UISquirrelManager->AddFuncRegistration("int", "NSGetModLoadPriority", "string modName", "Returns a given mod's load priority", SQ_GetModLoadPriority);
+ g_UISquirrelManager->AddFuncRegistration("array<string>", "NSGetModConvarsByModName", "string modName", "Returns the names of all a given mod's cvars", SQ_GetModConvars);
+} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/scriptmodmenu.h b/NorthstarDedicatedTest/scriptmodmenu.h
new file mode 100644
index 00000000..019346d3
--- /dev/null
+++ b/NorthstarDedicatedTest/scriptmodmenu.h
@@ -0,0 +1,3 @@
+#pragma once
+
+void InitialiseScriptModMenu(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/scriptsrson.cpp b/NorthstarDedicatedTest/scriptsrson.cpp
index b5aef421..9c590280 100644
--- a/NorthstarDedicatedTest/scriptsrson.cpp
+++ b/NorthstarDedicatedTest/scriptsrson.cpp
@@ -15,7 +15,7 @@ void ModManager::BuildScriptsRson()
// not really important since it doesn't affect actual functionality at all, but the rson we output is really weird
// has a shitload of newlines added, even in places where we don't modify it at all
- std::string scriptsRson = ReadVPKOriginalFile("scripts/vscripts/scripts.rson");
+ std::string scriptsRson = ReadVPKOriginalFile(VPK_SCRIPTS_RSON_PATH);
scriptsRson += "\n\n// START MODDED SCRIPT CONTENT\n\n"; // newline before we start custom stuff
for (Mod* mod : m_loadedMods)
diff --git a/NorthstarDedicatedTest/serverauthentication.cpp b/NorthstarDedicatedTest/serverauthentication.cpp
index a856c00f..d6f3b2b2 100644
--- a/NorthstarDedicatedTest/serverauthentication.cpp
+++ b/NorthstarDedicatedTest/serverauthentication.cpp
@@ -19,11 +19,15 @@ CBaseClient__ActivatePlayerType CBaseClient__ActivatePlayer;
typedef void(*CBaseClient__DisconnectType)(void* self, uint32_t unknownButAlways1, const char* reason, ...);
CBaseClient__DisconnectType CBaseClient__Disconnect;
+typedef char(*CGameClient__ExecuteStringCommandType)(void* self, uint32_t unknown, const char* pCommandString);
+CGameClient__ExecuteStringCommandType CGameClient__ExecuteStringCommand;
+
// global vars
ServerAuthenticationManager* g_ServerAuthenticationManager;
ConVar* CVar_ns_auth_allow_insecure;
ConVar* CVar_ns_auth_allow_insecure_write;
+ConVar* CVar_sv_quota_stringcmdspersecond;
void ServerAuthenticationManager::AddPlayerAuth(char* authToken, char* uid, char* pdata, size_t pdataSize)
{
@@ -167,18 +171,28 @@ void CBaseClient__DisconnectHook(void* self, uint32_t unknownButAlways1, const c
CBaseClient__Disconnect(self, unknownButAlways1, buf);
}
+// maybe this should be done outside of auth code, but effort to refactor rn and it sorta fits
+char CGameClient__ExecuteStringCommandHook(void* self, uint32_t unknown, const char* pCommandString)
+{
+ // todo later, basically just limit to CVar_sv_quota_stringcmdspersecond->m_nValue stringcmds per client per second
+ return CGameClient__ExecuteStringCommand(self, unknown, pCommandString);
+}
+
void InitialiseServerAuthentication(HMODULE baseAddress)
{
g_ServerAuthenticationManager = new ServerAuthenticationManager;
CVar_ns_auth_allow_insecure = RegisterConVar("ns_auth_allow_insecure", "0", FCVAR_GAMEDLL, "Whether this server will allow unauthenicated players to connect");
CVar_ns_auth_allow_insecure_write = RegisterConVar("ns_auth_allow_insecure_write", "0", FCVAR_GAMEDLL, "Whether the pdata of unauthenticated clients will be written to disk when changed");
+ // literally just stolen from a fix valve used in csgo
+ CVar_sv_quota_stringcmdspersecond = RegisterConVar("sv_quota_stringcmdspersecond", "40", FCVAR_NONE, "How many string commands per second clients are allowed to submit, 0 to disallow all string commands");
HookEnabler hook;
ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x114430, &CBaseServer__ConnectClientHook, reinterpret_cast<LPVOID*>(&CBaseServer__ConnectClient));
ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x101740, &CBaseClient__ConnectHook, reinterpret_cast<LPVOID*>(&CBaseClient__Connect));
ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x100F80, &CBaseClient__ActivatePlayerHook, reinterpret_cast<LPVOID*>(&CBaseClient__ActivatePlayer));
ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x1012C0, &CBaseClient__DisconnectHook, reinterpret_cast<LPVOID*>(&CBaseClient__Disconnect));
+ ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x1022E0, &CGameClient__ExecuteStringCommandHook, reinterpret_cast<LPVOID*>(&CGameClient__ExecuteStringCommand));
// patch to disable kicking based on incorrect serverfilter in connectclient, since we repurpose it for use as an auth token
{
diff --git a/NorthstarDedicatedTest/squirrel.cpp b/NorthstarDedicatedTest/squirrel.cpp
index b57e22ae..17758282 100644
--- a/NorthstarDedicatedTest/squirrel.cpp
+++ b/NorthstarDedicatedTest/squirrel.cpp
@@ -34,6 +34,7 @@ CallScriptInitCallbackType ClientCallScriptInitCallback;
CallScriptInitCallbackType ServerCallScriptInitCallback;
template<Context context> char CallScriptInitCallbackHook(void* sqvm, const char* callback);
+// core sqvm funcs
sq_compilebufferType ClientSq_compilebuffer;
sq_compilebufferType ServerSq_compilebuffer;
@@ -46,6 +47,37 @@ sq_callType ServerSq_call;
RegisterSquirrelFuncType ClientRegisterSquirrelFunc;
RegisterSquirrelFuncType ServerRegisterSquirrelFunc;
+
+// sq stack array funcs
+sq_newarrayType ClientSq_newarray;
+sq_newarrayType ServerSq_newarray;
+
+sq_arrayappendType ClientSq_arrayappend;
+sq_arrayappendType ServerSq_arrayappend;
+
+
+// sq stack push funcs
+sq_pushstringType ClientSq_pushstring;
+sq_pushstringType ServerSq_pushstring;
+
+sq_pushintegerType ClientSq_pushinteger;
+sq_pushintegerType ServerSq_pushinteger;
+
+sq_pushfloatType ClientSq_pushfloat;
+sq_pushfloatType ServerSq_pushfloat;
+
+
+// sq stack get funcs
+sq_getstringType ClientSq_getstring;
+sq_getstringType ServerSq_getstring;
+
+sq_getintegerType ClientSq_getinteger;
+sq_getintegerType ServerSq_getinteger;
+
+sq_getfloatType ClientSq_getfloat;
+sq_getfloatType ServerSq_getfloat;
+
+
template<Context context> void ExecuteCodeCommand(const CCommand& args);
// inits
@@ -80,6 +112,17 @@ void InitialiseClientSquirrel(HMODULE baseAddress)
ClientSq_call = (sq_callType)((char*)baseAddress + 0x8650);
ClientRegisterSquirrelFunc = (RegisterSquirrelFuncType)((char*)baseAddress + 0x108E0);
+ ClientSq_newarray = (sq_newarrayType)((char*)baseAddress + 0x39F0);
+ ClientSq_arrayappend = (sq_arrayappendType)((char*)baseAddress + 0x3C70);
+
+ ClientSq_pushstring = (sq_pushstringType)((char*)baseAddress + 0x3440);
+ ClientSq_pushinteger = (sq_pushintegerType)((char*)baseAddress + 0x36A0);
+ ClientSq_pushfloat = (sq_pushfloatType)((char*)baseAddress + 0x3800);
+
+ ClientSq_getstring = (sq_getstringType)((char*)baseAddress + 0x60C0);
+ ClientSq_getinteger = (sq_getintegerType)((char*)baseAddress + 0x60E0);
+ ClientSq_getfloat = (sq_getfloatType)((char*)baseAddress + 0x6100);
+
ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x26130, &CreateNewVMHook<CLIENT>, reinterpret_cast<LPVOID*>(&ClientCreateNewVM)); // client createnewvm function
ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x26E70, &DestroyVMHook<CLIENT>, reinterpret_cast<LPVOID*>(&ClientDestroyVM)); // client destroyvm function
ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x79A50, &ScriptCompileErrorHook<CLIENT>, reinterpret_cast<LPVOID*>(&ClientSQCompileError)); // client compileerror function
@@ -98,6 +141,17 @@ void InitialiseServerSquirrel(HMODULE baseAddress)
ServerSq_call = (sq_callType)((char*)baseAddress + 0x8620);
ServerRegisterSquirrelFunc = (RegisterSquirrelFuncType)((char*)baseAddress + 0x1DD10);
+ ServerSq_newarray = (sq_newarrayType)((char*)baseAddress + 0x39F0);
+ ServerSq_arrayappend = (sq_arrayappendType)((char*)baseAddress + 0x3C70);
+
+ ServerSq_pushstring = (sq_pushstringType)((char*)baseAddress + 0x3440);
+ ServerSq_pushinteger = (sq_pushintegerType)((char*)baseAddress + 0x36A0);
+ ServerSq_pushfloat = (sq_pushfloatType)((char*)baseAddress + 0x3800);
+
+ ServerSq_getstring = (sq_getstringType)((char*)baseAddress + 0x60A0);
+ ServerSq_getinteger = (sq_getintegerType)((char*)baseAddress + 0x60C0);
+ ServerSq_getfloat = (sq_getfloatType)((char*)baseAddress + 0x60E0);
+
ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x1FE90, &SQPrintHook<SERVER>, reinterpret_cast<LPVOID*>(&ServerSQPrint)); // server print function
ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x260E0, &CreateNewVMHook<SERVER>, reinterpret_cast<LPVOID*>(&ServerCreateNewVM)); // server createnewvm function
ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x26E20, &DestroyVMHook<SERVER>, reinterpret_cast<LPVOID*>(&ServerDestroyVM)); // server destroyvm function
diff --git a/NorthstarDedicatedTest/squirrel.h b/NorthstarDedicatedTest/squirrel.h
index 2704dbc7..b094dbaf 100644
--- a/NorthstarDedicatedTest/squirrel.h
+++ b/NorthstarDedicatedTest/squirrel.h
@@ -12,6 +12,8 @@ typedef char SQChar;
typedef SQUnsignedInteger SQBool;
typedef SQInteger SQRESULT;
+typedef SQInteger(*SQFunction)(void* sqvm);
+
struct CompileBufferState
{
const SQChar* buffer;
@@ -53,6 +55,7 @@ struct SQFuncRegistration
}
};
+// core sqvm funcs
typedef SQRESULT(*sq_compilebufferType)(void* sqvm, CompileBufferState* compileBuffer, const char* file, int a1, int a2);
extern sq_compilebufferType ClientSq_compilebuffer;
extern sq_compilebufferType ServerSq_compilebuffer;
@@ -69,9 +72,44 @@ typedef int64_t(*RegisterSquirrelFuncType)(void* sqvm, SQFuncRegistration* funcR
extern RegisterSquirrelFuncType ClientRegisterSquirrelFunc;
extern RegisterSquirrelFuncType ServerRegisterSquirrelFunc;
-//template<Context context> void ExecuteSQCode(SquirrelManager<context> sqManager, const char* code); // need this because we can't do template class functions in the .cpp file
+// sq stack array funcs
+typedef void(*sq_newarrayType)(void* sqvm, SQInteger stackpos);
+extern sq_newarrayType ClientSq_newarray;
+extern sq_newarrayType ServerSq_newarray;
+
+typedef SQRESULT(*sq_arrayappendType)(void* sqvm, SQInteger stackpos);
+extern sq_arrayappendType ClientSq_arrayappend;
+extern sq_arrayappendType ServerSq_arrayappend;
+
+
+// sq stack push funcs
+typedef void(*sq_pushstringType)(void* sqvm, const SQChar* str, SQInteger stackpos);
+extern sq_pushstringType ClientSq_pushstring;
+extern sq_pushstringType ServerSq_pushstring;
+
+// weird how these don't take a stackpos arg?
+typedef void(*sq_pushintegerType)(void* sqvm, SQInteger i);
+extern sq_pushintegerType ClientSq_pushinteger;
+extern sq_pushintegerType ServerSq_pushinteger;
+
+typedef void(*sq_pushfloatType)(void* sqvm, SQFloat f);
+extern sq_pushfloatType ClientSq_pushfloat;
+extern sq_pushfloatType ServerSq_pushfloat;
+
+
+// sq stack get funcs
+typedef const SQChar*(*sq_getstringType)(void* sqvm, SQInteger stackpos);
+extern sq_getstringType ClientSq_getstring;
+extern sq_getstringType ServerSq_getstring;
+
+typedef SQInteger(*sq_getintegerType)(void* sqvm, SQInteger stackpos);
+extern sq_getintegerType ClientSq_getinteger;
+extern sq_getintegerType ServerSq_getinteger;
+
+typedef SQFloat(*sq_getfloatType)(void*, SQInteger stackpos);
+extern sq_getfloatType ClientSq_getfloat;
+extern sq_getfloatType ServerSq_getfloat;
-typedef SQInteger(*SQFunction)(void* sqvm);
template<Context context> class SquirrelManager
{