aboutsummaryrefslogtreecommitdiff
path: root/NorthstarDLL
diff options
context:
space:
mode:
Diffstat (limited to 'NorthstarDLL')
-rw-r--r--NorthstarDLL/NorthstarDLL.vcxproj4
-rw-r--r--NorthstarDLL/NorthstarDLL.vcxproj.filters26
-rw-r--r--NorthstarDLL/clientchathooks.cpp18
-rw-r--r--NorthstarDLL/filesystem.h3
-rw-r--r--NorthstarDLL/masterserver.cpp1
-rw-r--r--NorthstarDLL/misccommands.cpp2
-rw-r--r--NorthstarDLL/miscserverscript.cpp8
-rw-r--r--NorthstarDLL/plugins.cpp14
-rw-r--r--NorthstarDLL/rpakfilesystem.cpp9
-rw-r--r--NorthstarDLL/rpakfilesystem.h77
-rw-r--r--NorthstarDLL/scriptdatatables.cpp923
-rw-r--r--NorthstarDLL/scriptjson.cpp12
-rw-r--r--NorthstarDLL/scriptmainmenupromos.cpp6
-rw-r--r--NorthstarDLL/scriptmodmenu.cpp20
-rw-r--r--NorthstarDLL/scriptserverbrowser.cpp48
-rw-r--r--NorthstarDLL/scriptservertoclientstringcommand.cpp6
-rw-r--r--NorthstarDLL/scriptutility.cpp2
-rw-r--r--NorthstarDLL/serverchathooks.cpp12
-rw-r--r--NorthstarDLL/squirrel.cpp258
-rw-r--r--NorthstarDLL/squirrel.h625
-rw-r--r--NorthstarDLL/squirreldatatypes.h484
21 files changed, 1833 insertions, 725 deletions
diff --git a/NorthstarDLL/NorthstarDLL.vcxproj b/NorthstarDLL/NorthstarDLL.vcxproj
index f9f11ba7..6aa671ea 100644
--- a/NorthstarDLL/NorthstarDLL.vcxproj
+++ b/NorthstarDLL/NorthstarDLL.vcxproj
@@ -61,7 +61,7 @@
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
- <LanguageStandard>stdcpp17</LanguageStandard>
+ <LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
@@ -120,6 +120,7 @@
<ClInclude Include="bitbuf.h" />
<ClInclude Include="bits.h" />
<ClInclude Include="crashhandler.h" />
+ <ClInclude Include="squirreldatatypes.h" />
<ClInclude Include="limits.h" />
<ClInclude Include="maxplayers.h" />
<ClInclude Include="memory.h" />
@@ -615,6 +616,7 @@
<ClCompile Include="runframe.cpp" />
<ClCompile Include="scriptbrowserhooks.cpp" />
<ClCompile Include="scriptjson.cpp" />
+ <ClCompile Include="scriptdatatables.cpp" />
<ClCompile Include="scriptmainmenupromos.cpp" />
<ClCompile Include="scriptmodmenu.cpp" />
<ClCompile Include="scriptserverbrowser.cpp" />
diff --git a/NorthstarDLL/NorthstarDLL.vcxproj.filters b/NorthstarDLL/NorthstarDLL.vcxproj.filters
index 5f40a53c..f1ece300 100644
--- a/NorthstarDLL/NorthstarDLL.vcxproj.filters
+++ b/NorthstarDLL/NorthstarDLL.vcxproj.filters
@@ -148,8 +148,14 @@
<Filter Include="Header Files\Dedicated Server">
<UniqueIdentifier>{0f1ba4c4-78ee-4b05-afa5-6f598063f5c1}</UniqueIdentifier>
</Filter>
+ <Filter Include="Header Files\Squirrel">
+ <UniqueIdentifier>{ca669b16-b8bb-4654-993f-fffa44c914f1}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Squirrel">
+ <UniqueIdentifier>{26365f16-ff52-4e80-a01b-2ca020376c93}</UniqueIdentifier>
+ </Filter>
<Filter Include="Source Files\Scripted">
- <UniqueIdentifier>{a3afb0d7-6129-40e5-87a5-2f6758f7e4f6}</UniqueIdentifier>
+ <UniqueIdentifier>{7263403a-7550-4aa2-a724-f622ab200eed}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
@@ -1407,9 +1413,6 @@
<ClInclude Include="sourceinterface.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="squirrel.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="bits.h">
<Filter>Header Files\Math</Filter>
</ClInclude>
@@ -1485,6 +1488,12 @@
<ClInclude Include="maxplayers.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="squirrel.h">
+ <Filter>Header Files\Squirrel</Filter>
+ </ClInclude>
+ <ClInclude Include="squirreldatatypes.h">
+ <Filter>Header Files\Squirrel</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
@@ -1592,9 +1601,6 @@
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="squirrel.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="crashhandler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -1691,6 +1697,12 @@
<ClCompile Include="scriptjson.cpp">
<Filter>Source Files\Scripted</Filter>
</ClCompile>
+ <ClCompile Include="squirrel.cpp">
+ <Filter>Source Files\Squirrel</Filter>
+ </ClCompile>
+ <ClCompile Include="scriptdatatables.cpp">
+ <Filter>Source Files\Scripted</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<MASM Include="audio_asm.asm">
diff --git a/NorthstarDLL/clientchathooks.cpp b/NorthstarDLL/clientchathooks.cpp
index 5b1f2e3f..fc7c1f19 100644
--- a/NorthstarDLL/clientchathooks.cpp
+++ b/NorthstarDLL/clientchathooks.cpp
@@ -29,12 +29,12 @@ void,, (void* self, const char* message, int inboxId, bool isTeam, bool isDead))
payload = message + 1;
}
- g_pSquirrel<ScriptContext::CLIENT>->pushinteger(g_pSquirrel<ScriptContext::CLIENT>->sqvm2, (int)senderId - 1);
- g_pSquirrel<ScriptContext::CLIENT>->pushstring(g_pSquirrel<ScriptContext::CLIENT>->sqvm2, payload);
- g_pSquirrel<ScriptContext::CLIENT>->pushbool(g_pSquirrel<ScriptContext::CLIENT>->sqvm2, isTeam);
- g_pSquirrel<ScriptContext::CLIENT>->pushbool(g_pSquirrel<ScriptContext::CLIENT>->sqvm2, isDead);
- g_pSquirrel<ScriptContext::CLIENT>->pushinteger(g_pSquirrel<ScriptContext::CLIENT>->sqvm2, type);
- g_pSquirrel<ScriptContext::CLIENT>->call(g_pSquirrel<ScriptContext::CLIENT>->sqvm2, 5);
+ g_pSquirrel<ScriptContext::CLIENT>->pushinteger(g_pSquirrel<ScriptContext::CLIENT>->sqvm, (int)senderId - 1);
+ g_pSquirrel<ScriptContext::CLIENT>->pushstring(g_pSquirrel<ScriptContext::CLIENT>->sqvm, payload);
+ g_pSquirrel<ScriptContext::CLIENT>->pushbool(g_pSquirrel<ScriptContext::CLIENT>->sqvm, isTeam);
+ g_pSquirrel<ScriptContext::CLIENT>->pushbool(g_pSquirrel<ScriptContext::CLIENT>->sqvm, isDead);
+ g_pSquirrel<ScriptContext::CLIENT>->pushinteger(g_pSquirrel<ScriptContext::CLIENT>->sqvm, type);
+ g_pSquirrel<ScriptContext::CLIENT>->call(g_pSquirrel<ScriptContext::CLIENT>->sqvm, 5);
}
else
for (CHudChat* hud = *CHudChat::allHuds; hud != NULL; hud = hud->next)
@@ -42,7 +42,7 @@ void,, (void* self, const char* message, int inboxId, bool isTeam, bool isDead))
}
// void NSChatWrite( int context, string str )
-SQRESULT SQ_ChatWrite(void* sqvm)
+SQRESULT SQ_ChatWrite(HSquirrelVM* sqvm)
{
int context = g_pSquirrel<ScriptContext::CLIENT>->getinteger(sqvm, 1);
const char* str = g_pSquirrel<ScriptContext::CLIENT>->getstring(sqvm, 2);
@@ -52,7 +52,7 @@ SQRESULT SQ_ChatWrite(void* sqvm)
}
// void NSChatWriteRaw( int context, string str )
-SQRESULT SQ_ChatWriteRaw(void* sqvm)
+SQRESULT SQ_ChatWriteRaw(HSquirrelVM* sqvm)
{
int context = g_pSquirrel<ScriptContext::CLIENT>->getinteger(sqvm, 1);
const char* str = g_pSquirrel<ScriptContext::CLIENT>->getstring(sqvm, 2);
@@ -62,7 +62,7 @@ SQRESULT SQ_ChatWriteRaw(void* sqvm)
}
// void NSChatWriteLine( int context, string str )
-SQRESULT SQ_ChatWriteLine(void* sqvm)
+SQRESULT SQ_ChatWriteLine(HSquirrelVM* sqvm)
{
int context = g_pSquirrel<ScriptContext::CLIENT>->getinteger(sqvm, 1);
const char* str = g_pSquirrel<ScriptContext::CLIENT>->getstring(sqvm, 2);
diff --git a/NorthstarDLL/filesystem.h b/NorthstarDLL/filesystem.h
index abfdd14b..c326b419 100644
--- a/NorthstarDLL/filesystem.h
+++ b/NorthstarDLL/filesystem.h
@@ -59,7 +59,8 @@ class IFileSystem
FileHandle_t (*Open)(
IFileSystem::VTable2** fileSystem, const char* pFileName, const char* pOptions, const char* pathID, int64_t unknown);
void (*Close)(IFileSystem* fileSystem, FileHandle_t file);
- void* unknown2[6];
+ long long (*Seek)(IFileSystem::VTable2** fileSystem, FileHandle_t file, long long offset, long long whence);
+ void* unknown2[5];
bool (*FileExists)(IFileSystem::VTable2** fileSystem, const char* pFileName, const char* pPathID);
};
diff --git a/NorthstarDLL/masterserver.cpp b/NorthstarDLL/masterserver.cpp
index b83170b0..04656b33 100644
--- a/NorthstarDLL/masterserver.cpp
+++ b/NorthstarDLL/masterserver.cpp
@@ -764,6 +764,7 @@ class MasterServerPresenceReporter : public ServerPresenceReporter
void ReportPresence(const ServerPresence* pServerPresence) override
{
// make a copy of presence for multithreading purposes
+
ServerPresence threadedPresence(pServerPresence);
if (!*g_pMasterServerManager->m_sOwnServerId || m_bShouldTryRegisterServer)
diff --git a/NorthstarDLL/misccommands.cpp b/NorthstarDLL/misccommands.cpp
index 739e8921..c61f13ec 100644
--- a/NorthstarDLL/misccommands.cpp
+++ b/NorthstarDLL/misccommands.cpp
@@ -34,7 +34,7 @@ void ConCommand_ns_end_reauth_and_leave_to_lobby(const CCommand& arg)
R2::Cbuf_Execute();
// weird way of checking, but check if client script vm is initialised, mainly just to allow players to cancel this
- if (g_pSquirrel<ScriptContext::CLIENT>->sqvm)
+ if (g_pSquirrel<ScriptContext::CLIENT>->SquirrelVM)
{
g_pServerAuthentication->m_bNeedLocalAuthForNewgame = true;
diff --git a/NorthstarDLL/miscserverscript.cpp b/NorthstarDLL/miscserverscript.cpp
index 83d68ea1..5089d9e8 100644
--- a/NorthstarDLL/miscserverscript.cpp
+++ b/NorthstarDLL/miscserverscript.cpp
@@ -9,7 +9,7 @@
#include <filesystem>
// void function NSEarlyWritePlayerIndexPersistenceForLeave( int playerIndex )
-SQRESULT SQ_EarlyWritePlayerIndexPersistenceForLeave(void* sqvm)
+SQRESULT SQ_EarlyWritePlayerIndexPersistenceForLeave(HSquirrelVM* sqvm)
{
int playerIndex = g_pSquirrel<ScriptContext::SERVER>->getinteger(sqvm, 1);
R2::CBaseClient* player = &R2::g_pClientArray[playerIndex];
@@ -26,14 +26,14 @@ SQRESULT SQ_EarlyWritePlayerIndexPersistenceForLeave(void* sqvm)
}
// bool function NSIsWritingPlayerPersistence()
-SQRESULT SQ_IsWritingPlayerPersistence(void* sqvm)
+SQRESULT SQ_IsWritingPlayerPersistence(HSquirrelVM* sqvm)
{
g_pSquirrel<ScriptContext::SERVER>->pushbool(sqvm, g_pMasterServerManager->m_bSavingPersistentData);
return SQRESULT_NOTNULL;
}
// bool function NSIsPlayerIndexLocalPlayer( int playerIndex )
-SQRESULT SQ_IsPlayerIndexLocalPlayer(void* sqvm)
+SQRESULT SQ_IsPlayerIndexLocalPlayer(HSquirrelVM* sqvm)
{
int playerIndex = g_pSquirrel<ScriptContext::SERVER>->getinteger(sqvm, 1);
R2::CBaseClient* player = &R2::g_pClientArray[playerIndex];
@@ -48,7 +48,7 @@ SQRESULT SQ_IsPlayerIndexLocalPlayer(void* sqvm)
}
// bool function NSIsDedicated()
-SQRESULT SQ_IsDedicated(void* sqvm)
+SQRESULT SQ_IsDedicated(HSquirrelVM* sqvm)
{
g_pSquirrel<ScriptContext::SERVER>->pushbool(sqvm, IsDedicatedServer());
return SQRESULT_NOTNULL;
diff --git a/NorthstarDLL/plugins.cpp b/NorthstarDLL/plugins.cpp
index 5bdf6fa1..e6089f3b 100644
--- a/NorthstarDLL/plugins.cpp
+++ b/NorthstarDLL/plugins.cpp
@@ -111,7 +111,7 @@ void initGameState()
}
// string gamemode, string gamemodeName, string map, string mapName, bool connected, bool loading
-SQRESULT SQ_UpdateGameStateUI(void* sqvm)
+SQRESULT SQ_UpdateGameStateUI(HSquirrelVM* sqvm)
{
AcquireSRWLockExclusive(&gameStateLock);
gameState.map = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 1);
@@ -125,7 +125,7 @@ SQRESULT SQ_UpdateGameStateUI(void* sqvm)
}
// int playerCount, int outScore, int secondHighestScore, int highestScore, bool roundBased, int scoreLimit
-SQRESULT SQ_UpdateGameStateClient(void* sqvm)
+SQRESULT SQ_UpdateGameStateClient(HSquirrelVM* sqvm)
{
AcquireSRWLockExclusive(&gameStateLock);
AcquireSRWLockExclusive(&serverInfoLock);
@@ -143,7 +143,7 @@ SQRESULT SQ_UpdateGameStateClient(void* sqvm)
// string id, string name, string password, int players, int maxPlayers, string map, string mapDisplayName, string playlist, string
// playlistDisplayName
-SQRESULT SQ_UpdateServerInfo(void* sqvm)
+SQRESULT SQ_UpdateServerInfo(HSquirrelVM* sqvm)
{
AcquireSRWLockExclusive(&gameStateLock);
AcquireSRWLockExclusive(&serverInfoLock);
@@ -162,7 +162,7 @@ SQRESULT SQ_UpdateServerInfo(void* sqvm)
}
// int maxPlayers
-SQRESULT SQ_UpdateServerInfoBetweenRounds(void* sqvm)
+SQRESULT SQ_UpdateServerInfoBetweenRounds(HSquirrelVM* sqvm)
{
AcquireSRWLockExclusive(&serverInfoLock);
serverInfo.id = g_pSquirrel<ScriptContext::CLIENT>->getstring(sqvm, 1);
@@ -174,7 +174,7 @@ SQRESULT SQ_UpdateServerInfoBetweenRounds(void* sqvm)
}
// float timeInFuture
-SQRESULT SQ_UpdateTimeInfo(void* sqvm)
+SQRESULT SQ_UpdateTimeInfo(HSquirrelVM* sqvm)
{
AcquireSRWLockExclusive(&serverInfoLock);
serverInfo.endTime = ceil(g_pSquirrel<ScriptContext::CLIENT>->getfloat(sqvm, 1));
@@ -183,7 +183,7 @@ SQRESULT SQ_UpdateTimeInfo(void* sqvm)
}
// bool loading
-SQRESULT SQ_SetConnected(void* sqvm)
+SQRESULT SQ_SetConnected(HSquirrelVM* sqvm)
{
AcquireSRWLockExclusive(&gameStateLock);
gameState.loading = g_pSquirrel<ScriptContext::UI>->getbool(sqvm, 1);
@@ -191,7 +191,7 @@ SQRESULT SQ_SetConnected(void* sqvm)
return SQRESULT_NOTNULL;
}
-SQRESULT SQ_UpdateListenServer(void* sqvm)
+SQRESULT SQ_UpdateListenServer(HSquirrelVM* sqvm)
{
AcquireSRWLockExclusive(&serverInfoLock);
serverInfo.id = g_pMasterServerManager->m_sOwnServerId;
diff --git a/NorthstarDLL/rpakfilesystem.cpp b/NorthstarDLL/rpakfilesystem.cpp
index 6c01a2e0..895cfd79 100644
--- a/NorthstarDLL/rpakfilesystem.cpp
+++ b/NorthstarDLL/rpakfilesystem.cpp
@@ -13,7 +13,9 @@ struct PakLoadFuncs
int (*LoadPakAsync)(const char* pPath, void* unknownSingleton, int flags, void* callback0, void* callback1);
void* unk1[2];
void* (*UnloadPak)(int iPakHandle, void* callback);
- void* unk2[17];
+ void* unk2[6];
+ void* (*LoadFile)(const char* path);//unsure
+ void* unk3[10];
void* (*ReadFileAsync)(const char* pPath, void* a2);
};
@@ -78,6 +80,11 @@ int PakLoadManager::GetPakHandle(const char* pPath)
return GetPakHandle(STR_HASH(pPath));
}
+void* PakLoadManager::LoadFile(const char* path)
+{
+ return g_pakLoadApi->LoadFile(path);
+}
+
void HandlePakAliases(char** map)
{
// convert the pak being loaded to it's aliased one, e.g. aliasing mp_hub_timeshift => sp_hub_timeshift
diff --git a/NorthstarDLL/rpakfilesystem.h b/NorthstarDLL/rpakfilesystem.h
index 4a9a4343..f9039500 100644
--- a/NorthstarDLL/rpakfilesystem.h
+++ b/NorthstarDLL/rpakfilesystem.h
@@ -1,38 +1,39 @@
-#pragma once
-
-enum class ePakLoadSource
-{
- UNTRACKED = -1, // not a pak we loaded, we shouldn't touch this one
-
- CONSTANT, // should be loaded at all times
- MAP // loaded from a map, should be unloaded when the map is unloaded
-};
-
-struct LoadedPak
-{
- ePakLoadSource m_nLoadSource;
- int m_nPakHandle;
- size_t m_nPakNameHash;
-};
-
-class PakLoadManager
-{
- private:
- std::map<int, LoadedPak> m_vLoadedPaks {};
- std::unordered_map<size_t, int> m_HashToPakHandle {};
-
- public:
- int LoadPakAsync(const char* pPath, const ePakLoadSource nLoadSource);
- void UnloadPak(const int nPakHandle);
- void UnloadMapPaks();
-
- LoadedPak* TrackLoadedPak(ePakLoadSource nLoadSource, int nPakHandle, size_t nPakNameHash);
- void RemoveLoadedPak(int nPakHandle);
-
- LoadedPak* GetPakInfo(const int nPakHandle);
-
- int GetPakHandle(const size_t nPakNameHash);
- int GetPakHandle(const char* pPath);
-};
-
-extern PakLoadManager* g_pPakLoadManager;
+#pragma once
+
+enum class ePakLoadSource
+{
+ UNTRACKED = -1, // not a pak we loaded, we shouldn't touch this one
+
+ CONSTANT, // should be loaded at all times
+ MAP // loaded from a map, should be unloaded when the map is unloaded
+};
+
+struct LoadedPak
+{
+ ePakLoadSource m_nLoadSource;
+ int m_nPakHandle;
+ size_t m_nPakNameHash;
+};
+
+class PakLoadManager
+{
+ private:
+ std::map<int, LoadedPak> m_vLoadedPaks {};
+ std::unordered_map<size_t, int> m_HashToPakHandle {};
+
+ public:
+ int LoadPakAsync(const char* pPath, const ePakLoadSource nLoadSource);
+ void UnloadPak(const int nPakHandle);
+ void UnloadMapPaks();
+ void* LoadFile(const char* path); //this is a guess
+
+ LoadedPak* TrackLoadedPak(ePakLoadSource nLoadSource, int nPakHandle, size_t nPakNameHash);
+ void RemoveLoadedPak(int nPakHandle);
+
+ LoadedPak* GetPakInfo(const int nPakHandle);
+
+ int GetPakHandle(const size_t nPakNameHash);
+ int GetPakHandle(const char* pPath);
+};
+
+extern PakLoadManager* g_pPakLoadManager;
diff --git a/NorthstarDLL/scriptdatatables.cpp b/NorthstarDLL/scriptdatatables.cpp
new file mode 100644
index 00000000..053933bd
--- /dev/null
+++ b/NorthstarDLL/scriptdatatables.cpp
@@ -0,0 +1,923 @@
+#include "pch.h"
+#include "squirrel.h"
+#include "rpakfilesystem.h"
+#include "convar.h"
+#include "filesystem.h"
+#include <iostream>
+#include <sstream>
+#include <map>
+#include <fstream>
+#include "tier0.h"
+
+struct ColumnInfo
+{
+ char* name;
+ int type;
+ int offset;
+};
+
+struct DataTable
+{
+ int columnAmount;
+ int rowAmount;
+ ColumnInfo* columnInfo;
+ long long data; // actually data pointer
+ int rowInfo;
+};
+
+ConVar* Cvar_ns_prefer_datatable_from_disk;
+void datatableReleaseHook(void*, int size);
+const long long customDatatableTypeId = 0xFFFCFFFC12345678;
+const long long vanillaDatatableTypeId = 0xFFF7FFF700000004;
+void* (*getDataTableStructure)(HSquirrelVM* sqvm);
+std::string DataTableToString(DataTable* datatable);
+
+struct csvData
+{
+ char* name;
+ std::vector<std::vector<char*>> dataPointers;
+ char* fullData = 0;
+ std::vector<char*> columnNames;
+};
+
+std::unordered_map<std::string, csvData*> cacheMap;
+
+void StringToVector(char* string, float* vector)
+{
+ int length = 0;
+ while (string[length])
+ {
+ if ((string[length] == '<') || (string[length] == '>'))
+ string[length] = '\0';
+ length++;
+ }
+
+ int startOfFloat = 1;
+ int currentIndex = 1;
+ while (string[currentIndex] && (string[currentIndex] != ','))
+ currentIndex++;
+ string[currentIndex] = '\0';
+ vector[0] = std::stof(&string[startOfFloat]);
+ startOfFloat = ++currentIndex;
+ while (string[currentIndex] && (string[currentIndex] != ','))
+ currentIndex++;
+ string[currentIndex] = '\0';
+ vector[1] = std::stof(&string[startOfFloat]);
+ startOfFloat = ++currentIndex;
+ while (string[currentIndex] && (string[currentIndex] != ','))
+ currentIndex++;
+ string[currentIndex] = '\0';
+ vector[2] = std::stof(&string[startOfFloat]);
+ startOfFloat = ++currentIndex;
+}
+
+template <ScriptContext context> SQRESULT GetDatatable(HSquirrelVM* sqvm)
+{
+ const char* assetName;
+ g_pSquirrel<context>->getasset(sqvm, 2, &assetName);
+ SQRESULT result = SQRESULT_ERROR;
+ if (strncmp(assetName, "datatable/", 10) != 0)
+ {
+ spdlog::error("Asset \"{}\" doesn't start with \"datatable/\"", assetName);
+ }
+ else if ((!Cvar_ns_prefer_datatable_from_disk->GetBool()) && g_pPakLoadManager->LoadFile(assetName) )
+ {
+ //spdlog::info("Load Datatable {} from rpak", assetName);
+ result = g_pSquirrel<context>->m_funcOriginals["GetDataTable"](sqvm);
+ }
+ else
+ {
+ char assetPath[250];
+ snprintf(assetPath, 250, "scripts/%s", assetName);
+ if (cacheMap.count(assetName))
+ {
+ //spdlog::info("Loaded custom Datatable {} from cache", assetName);
+ csvData** dataPointer = (csvData**)g_pSquirrel<context>->createuserdata(sqvm, sizeof(csvData*));
+ *dataPointer = cacheMap[assetName];
+ g_pSquirrel<context>->setuserdatatypeid(sqvm, -1, customDatatableTypeId);
+ // sqvm->_stack[sqvm->_top -1]._VAL.asUserdata->releaseHook = datatableReleaseHook;
+ result = SQRESULT_NOTNULL;
+ }
+ else if ((*R2::g_pFilesystem)->m_vtable2->FileExists(&(*R2::g_pFilesystem)->m_vtable2, assetPath, "GAME"))
+ {
+
+ std::string dataFile = R2::ReadVPKFile(assetPath);
+ if (dataFile.size() == 0)
+ return SQRESULT_ERROR;
+ char* csvFullData = (char*)malloc(dataFile.size());
+ memcpy(csvFullData, dataFile.c_str(), dataFile.size());
+
+ csvData* data = new csvData();
+ data->fullData = csvFullData;
+
+ std::vector<char*> currentLine;
+ int startIndex = 0;
+ if (csvFullData[0] == '\"')
+ {
+ currentLine.push_back(&csvFullData[1]);
+ startIndex = 1;
+ int i = 1;
+ while (csvFullData[i] != '\"')
+ i++;
+ csvFullData[i] = '\0';
+ }
+ else
+ {
+ currentLine.push_back(csvFullData);
+ }
+
+ bool firstLine = true;
+ for (int i = startIndex; i < dataFile.size(); i++)
+ {
+ if (csvFullData[i] == ',')
+ {
+ if (csvFullData[i + 1] == '\"')
+ {
+
+ currentLine.push_back(&csvFullData[i + 2]);
+ csvFullData[i] = '\0';
+ csvFullData[i + 1] = '\0';
+ while (true)
+ {
+ if ((csvFullData[i] == '\n') || (csvFullData[i] == '\r'))
+ return SQRESULT_ERROR;
+ if (csvFullData[i] == '\"')
+ break;
+ i++;
+ }
+ csvFullData[i] = '\0';
+ }
+ else
+ {
+ currentLine.push_back(&csvFullData[i + 1]);
+ csvFullData[i] = '\0';
+ }
+ }
+ if ((csvFullData[i] == '\n') || (csvFullData[i] == '\r'))
+ {
+ csvFullData[i] = '\0';
+ if ((csvFullData[i + 1] == '\n') || (csvFullData[i + 1] == '\r'))
+ {
+ i++;
+ csvFullData[i] = '\0';
+ }
+ if (firstLine)
+ {
+ data->columnNames = currentLine;
+ firstLine = false;
+ }
+ else
+ {
+ data->dataPointers.push_back(currentLine);
+ }
+
+ currentLine.clear();
+ if (i + 1 >= dataFile.size())
+ break;
+ if (csvFullData[i + 1] == '\"')
+ {
+
+ currentLine.push_back(&csvFullData[i + 2]);
+ csvFullData[i] = '\0';
+ csvFullData[i + 1] = '\0';
+ while (true)
+ {
+ if ((csvFullData[i] == '\n') || (csvFullData[i] == '\r'))
+ return SQRESULT_ERROR;
+ if (csvFullData[i] == '\"')
+ break;
+ i++;
+ }
+ csvFullData[i] = '\0';
+ }
+ else
+ {
+ currentLine.push_back(&csvFullData[i + 1]);
+ csvFullData[i] = '\0';
+ }
+ }
+ }
+ if (currentLine.size() != 0)
+ {
+ if (firstLine)
+ {
+ data->columnNames = currentLine;
+ }
+ else
+ {
+ data->dataPointers.push_back(currentLine);
+ }
+ }
+ data->name = (char*)malloc(256);
+
+ strncpy(data->name, assetName, 256);
+ csvData** dataPointer = (csvData**)g_pSquirrel<context>->createuserdata(sqvm, sizeof(csvData*));
+ g_pSquirrel<context>->setuserdatatypeid(sqvm, -1, customDatatableTypeId);
+
+ *dataPointer = data;
+ // vm->_stack[vm->_top -1]._VAL.asUserdata->releaseHook = datatableReleaseHook;
+ cacheMap[assetName] = data;
+ //spdlog::info("Loaded custom Datatable from file at {} with pointer {}", assetPath, (void*)data);
+
+ result = SQRESULT_NOTNULL;
+ }
+ else if (Cvar_ns_prefer_datatable_from_disk->GetBool()&&g_pPakLoadManager->LoadFile(assetName))
+ {
+ result = g_pSquirrel<context>->m_funcOriginals["GetDataTable"](sqvm);
+ }
+ else
+ {
+ spdlog::error("Datatable {} not found", assetPath);
+ }
+ }
+ return result;
+}
+
+template <ScriptContext context> SQRESULT GetDatatabeColumnByName(HSquirrelVM* sqvm)
+{
+ //spdlog::info("start getDatatableColumnByName");
+ csvData** dataPointer;
+ long long typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, (void**)&dataPointer, &typeId);
+ csvData* data = *dataPointer;
+ if (typeId == vanillaDatatableTypeId)
+ {
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableColumnByName"](sqvm);
+ }
+
+ if (typeId != customDatatableTypeId)
+ {
+ return SQRESULT_ERROR;
+ }
+ //spdlog::info("GetColumnByName form datatable with pointer {}",(void*)data);
+ const char* searchName = g_pSquirrel<context>->getstring(sqvm, 2);
+ int col = 0;
+ for (auto colName : data->columnNames)
+ {
+ if (!strcmp(colName, searchName))
+ break;
+
+ col++;
+ }
+ if (col == data->columnNames.size())
+ col = -1;
+ //spdlog::info("Datatable CoulumnName {} in column {}", std::string(searchName), col);
+ g_pSquirrel<context>->pushinteger(sqvm, col);
+ return SQRESULT_NOTNULL;
+}
+
+template <ScriptContext context> SQRESULT GetDatatabeRowCount(HSquirrelVM* sqvm)
+{
+ //spdlog::info("start getDatatableRowCount");
+ csvData** dataPointer;
+ long long typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, (void**)&dataPointer, &typeId);
+ csvData* data = *dataPointer;
+ if (typeId == vanillaDatatableTypeId)
+ {
+
+ return g_pSquirrel<context>->m_funcOriginals["GetDatatableRowCount"](sqvm);
+ }
+
+ if (typeId != customDatatableTypeId)
+ {
+ return SQRESULT_ERROR;
+ }
+ g_pSquirrel<context>->pushinteger(sqvm, data->dataPointers.size());
+ return SQRESULT_NOTNULL;
+}
+
+template <ScriptContext context> SQRESULT GetDataTableString(HSquirrelVM* sqvm)
+{
+ //spdlog::info("start getDatatableString");
+ csvData** dataPointer;
+ long long typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, (void**)&dataPointer, &typeId);
+ csvData* data = *dataPointer;
+ if (typeId == vanillaDatatableTypeId)
+ {
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableString"](sqvm);
+ }
+
+ if (typeId != customDatatableTypeId)
+ {
+ return SQRESULT_ERROR;
+ }
+ int row = g_pSquirrel<context>->getinteger(sqvm, 2);
+ int col = g_pSquirrel<context>->getinteger(sqvm, 3);
+ if (row >= data->dataPointers.size() || col >= data->dataPointers[row].size())
+ {
+ spdlog::info( "row {} and col {} are outside of range row {} and col {}", row, col, data->dataPointers.size(), data->columnNames.size());
+ return SQRESULT_ERROR;
+ }
+
+ g_pSquirrel<context>->pushstring(sqvm, data->dataPointers[row][col], -1);
+ return SQRESULT_NOTNULL;
+}
+
+template <ScriptContext context> SQRESULT GetDataTableAsset(HSquirrelVM* sqvm)
+{
+ //spdlog::info("start getDatatableAsset");
+ csvData** dataPointer;
+ long long typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, (void**)&dataPointer, &typeId);
+ csvData* data = *dataPointer;
+ if (typeId == vanillaDatatableTypeId)
+ {
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableAsset"](sqvm);
+ }
+
+ if (typeId != customDatatableTypeId)
+ {
+ return SQRESULT_ERROR;
+ }
+ int row = g_pSquirrel<context>->getinteger(sqvm, 2);
+ int col = g_pSquirrel<context>->getinteger(sqvm, 3);
+ if (row >= data->dataPointers.size() || col >= data->dataPointers[row].size())
+ {
+ spdlog::info( "row {} and col {} are outside of range row {} and col {}", row, col, data->dataPointers.size(), data->columnNames.size());
+ return SQRESULT_ERROR;
+ }
+ char* asset = data->dataPointers[row][col];
+ g_pSquirrel<context>->pushasset(sqvm, asset, -1);
+ return SQRESULT_NOTNULL;
+}
+
+template <ScriptContext context> SQRESULT GetDataTableInt(HSquirrelVM* sqvm)
+{
+ csvData** dataPointer;
+ long long typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, (void**)&dataPointer, &typeId);
+ csvData* data = *dataPointer;
+ if (typeId == vanillaDatatableTypeId)
+ {
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableInt"](sqvm);
+ }
+
+ if (typeId != customDatatableTypeId)
+ {
+ return SQRESULT_ERROR;
+ }
+ int row = g_pSquirrel<context>->getinteger(sqvm, 2);
+ int col = g_pSquirrel<context>->getinteger(sqvm, 3);
+ if (row >= data->dataPointers.size() || col >= data->dataPointers[row].size())
+ {
+ spdlog::info( "row {} and col {} are outside of range row {} and col {}", row, col, data->dataPointers.size(), data->columnNames.size());
+ return SQRESULT_ERROR;
+ }
+ g_pSquirrel<context>->pushinteger(sqvm, std::stoi(data->dataPointers[row][col]));
+ return SQRESULT_NOTNULL;
+}
+
+template <ScriptContext context> SQRESULT GetDataTableFloat(HSquirrelVM* sqvm)
+{
+ //spdlog::info("start getDatatableFloat");
+ csvData** dataPointer;
+ long long typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, (void**)&dataPointer, &typeId);
+ csvData* data = *dataPointer;
+ if (typeId == vanillaDatatableTypeId)
+ {
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableFloat"](sqvm);
+ }
+
+ if (typeId != customDatatableTypeId)
+ {
+ return SQRESULT_ERROR;
+ }
+ int row = g_pSquirrel<context>->getinteger(sqvm, 2);
+ int col = g_pSquirrel<context>->getinteger(sqvm, 3);
+ if (row >= data->dataPointers.size() || col >= data->dataPointers[row].size())
+ {
+ spdlog::info( "row {} and col {} are outside of range row {} and col {}", row, col, data->dataPointers.size(), data->columnNames.size());
+ return SQRESULT_ERROR;
+ }
+ g_pSquirrel<context>->pushfloat(sqvm, std::stof(data->dataPointers[row][col]));
+ return SQRESULT_NOTNULL;
+}
+
+template <ScriptContext context> SQRESULT GetDataTableBool(HSquirrelVM* sqvm)
+{
+ //spdlog::info("start getDatatableBool");
+ csvData** dataPointer;
+ long long typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, (void**)&dataPointer, &typeId);
+ csvData* data = *dataPointer;
+ if (typeId == vanillaDatatableTypeId)
+ {
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableBool"](sqvm);
+ }
+
+ if (typeId != customDatatableTypeId)
+ {
+ return SQRESULT_ERROR;
+ }
+ int row = g_pSquirrel<context>->getinteger(sqvm, 2);
+ int col = g_pSquirrel<context>->getinteger(sqvm, 3);
+ if (row >= data->dataPointers.size() || col >= data->dataPointers[row].size())
+ {
+ spdlog::info( "row {} and col {} are outside of range row {} and col {}", row, col, data->dataPointers.size(), data->columnNames.size());
+ return SQRESULT_ERROR;
+ }
+ g_pSquirrel<context>->pushbool(sqvm, std::stoi(data->dataPointers[row][col]));
+ return SQRESULT_NOTNULL;
+}
+
+template <ScriptContext context> SQRESULT GetDataTableVector(HSquirrelVM* sqvm)
+{
+ //spdlog::info("start getDatatableVector");
+ csvData** dataPointer;
+ long long typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, (void**)&dataPointer, &typeId);
+ csvData* data = *dataPointer;
+ if (typeId == vanillaDatatableTypeId)
+ {
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableVector"](sqvm);
+ }
+
+ if (typeId != customDatatableTypeId)
+ {
+ return SQRESULT_ERROR;
+ }
+ float vector[3];
+
+ int row = g_pSquirrel<context>->getinteger(sqvm, 2);
+ int col = g_pSquirrel<context>->getinteger(sqvm, 3);
+ if (row >= data->dataPointers.size() || col >= data->dataPointers[row].size())
+ {
+ spdlog::info(
+ "row {} and col {} are outside of range row {} and col {}", row, col, data->dataPointers.size(), data->columnNames.size());
+ return SQRESULT_ERROR;
+ }
+
+ StringToVector(data->dataPointers[row][col], vector);
+ g_pSquirrel<context>->pushvector(sqvm, vector);
+
+ return SQRESULT_NOTNULL;
+}
+
+template <ScriptContext context> SQRESULT GetDataTableRowMatchingStringValue(HSquirrelVM* sqvm)
+{
+ csvData** dataPointer;
+ long long typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, (void**)&dataPointer, &typeId);
+ csvData* data = *dataPointer;
+ if (typeId == vanillaDatatableTypeId)
+ {
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowMatchingStringValue"](sqvm);
+ }
+
+ if (typeId != customDatatableTypeId)
+ {
+ return SQRESULT_ERROR;
+ }
+
+ int col = g_pSquirrel<context>->getinteger(sqvm, 2);
+ const char* stringValue = g_pSquirrel<context>->getstring(sqvm, 3);
+
+ for (int i = 0; i < data->dataPointers.size(); i++)
+ {
+ if (!strcmp(data->dataPointers[i][col], stringValue))
+ {
+ g_pSquirrel<context>->pushinteger(sqvm, i);
+ return SQRESULT_NOTNULL;
+ }
+ }
+ g_pSquirrel<context>->pushinteger(sqvm, -1);
+ return SQRESULT_NOTNULL;
+}
+
+template <ScriptContext context> SQRESULT GetDataTableRowMatchingAssetValue(HSquirrelVM* sqvm)
+{
+ //spdlog::info("start getDatatableRowMatchingAsset");
+ csvData** dataPointer;
+ long long typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, (void**)&dataPointer, &typeId);
+ csvData* data = *dataPointer;
+ if (typeId == vanillaDatatableTypeId)
+ {
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowMatchingAssetValue"](sqvm);
+ }
+
+ if (typeId != customDatatableTypeId)
+ {
+ return SQRESULT_ERROR;
+ }
+
+ int col = g_pSquirrel<context>->getinteger(sqvm, 2);
+ const char* stringValue;
+ g_pSquirrel<context>->getasset(sqvm, 3, &stringValue);
+
+ for (int i = 0; i < data->dataPointers.size(); i++)
+ {
+ if (!strcmp(data->dataPointers[i][col], stringValue))
+ {
+ g_pSquirrel<context>->pushinteger(sqvm, i);
+ return SQRESULT_NOTNULL;
+ }
+ }
+ g_pSquirrel<context>->pushinteger(sqvm, -1);
+ return SQRESULT_NOTNULL;
+}
+
+template <ScriptContext context> SQRESULT GetDataTableRowMatchingFloatValue(HSquirrelVM* sqvm)
+{
+ csvData** dataPointer;
+ long long typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, (void**)&dataPointer, &typeId);
+ csvData* data = *dataPointer;
+ if (typeId == vanillaDatatableTypeId)
+ {
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowMatchingFloatValue"](sqvm);
+ }
+
+ if (typeId != customDatatableTypeId)
+ {
+ return SQRESULT_ERROR;
+ }
+
+ int col = g_pSquirrel<context>->getinteger(sqvm, 2);
+ float compareValue = g_pSquirrel<context>->getfloat(sqvm, 3);
+
+ for (int i = 0; i < data->dataPointers.size(); i++)
+ {
+
+ if (compareValue == std::stof(data->dataPointers[i][col]))
+ {
+ g_pSquirrel<context>->pushinteger(sqvm, i);
+ return SQRESULT_NOTNULL;
+ }
+ }
+ g_pSquirrel<context>->pushinteger(sqvm, -1);
+ return SQRESULT_NOTNULL;
+}
+
+template <ScriptContext context> SQRESULT GetDataTableRowMatchingIntValue(HSquirrelVM* sqvm)
+{
+ csvData** dataPointer;
+ long long typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, (void**)&dataPointer, &typeId);
+ csvData* data = *dataPointer;
+ if (typeId == vanillaDatatableTypeId)
+ {
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowMatchingIntValue"](sqvm);
+ }
+
+ if (typeId != customDatatableTypeId)
+ {
+ return SQRESULT_ERROR;
+ }
+
+ int col = g_pSquirrel<context>->getinteger(sqvm, 2);
+ int compareValue = g_pSquirrel<context>->getinteger(sqvm, 3);
+
+ for (int i = 0; i < data->dataPointers.size(); i++)
+ {
+
+ if (compareValue == std::stoi(data->dataPointers[i][col]))
+ {
+ g_pSquirrel<context>->pushinteger(sqvm, i);
+ return SQRESULT_NOTNULL;
+ }
+ }
+ g_pSquirrel<context>->pushinteger(sqvm, -1);
+ return SQRESULT_NOTNULL;
+}
+
+template <ScriptContext context> SQRESULT GetDataTableRowGreaterThanOrEqualToIntValue(HSquirrelVM* sqvm)
+{
+ csvData** dataPointer;
+ long long typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, (void**)&dataPointer, &typeId);
+ csvData* data = *dataPointer;
+ if (typeId == vanillaDatatableTypeId)
+ {
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowGreaterThanOrEqualToIntValue"](sqvm);
+ }
+
+ if (typeId != customDatatableTypeId)
+ {
+ return SQRESULT_ERROR;
+ }
+
+ int col = g_pSquirrel<context>->getinteger(sqvm, 2);
+ int compareValue = g_pSquirrel<context>->getinteger(sqvm, 3);
+
+ for (int i = 0; i < data->dataPointers.size(); i++)
+ {
+
+ if (compareValue >= std::stoi(data->dataPointers[i][col]))
+ {
+ g_pSquirrel<context>->pushinteger(sqvm, i);
+ return SQRESULT_NOTNULL;
+ }
+ }
+ g_pSquirrel<context>->pushinteger(sqvm, -1);
+ return SQRESULT_NOTNULL;
+}
+
+template <ScriptContext context> SQRESULT GetDataTableRowLessThanOrEqualToIntValue(HSquirrelVM* sqvm)
+{
+ csvData** dataPointer;
+ long long typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, (void**)&dataPointer, &typeId);
+ csvData* data = *dataPointer;
+ if (typeId == vanillaDatatableTypeId)
+ {
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowLessThanOrEqualToIntValue"](sqvm);
+ }
+
+ if (typeId != customDatatableTypeId)
+ {
+ return SQRESULT_ERROR;
+ }
+
+ int col = g_pSquirrel<context>->getinteger(sqvm, 2);
+ int compareValue = g_pSquirrel<context>->getinteger(sqvm, 3);
+
+ for (int i = 0; i < data->dataPointers.size(); i++)
+ {
+
+ if (compareValue <= std::stoi(data->dataPointers[i][col]))
+ {
+ g_pSquirrel<context>->pushinteger(sqvm, i);
+ return SQRESULT_NOTNULL;
+ }
+ }
+ g_pSquirrel<context>->pushinteger(sqvm, -1);
+ return SQRESULT_NOTNULL;
+}
+
+template <ScriptContext context> SQRESULT GetDataTableRowGreaterThanOrEqualToFloatValue(HSquirrelVM* sqvm)
+{
+ csvData** dataPointer;
+ long long typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, (void**)&dataPointer, &typeId);
+ csvData* data = *dataPointer;
+ if (typeId == vanillaDatatableTypeId)
+ {
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowGreaterThanOrEqualToFloatValue"](sqvm);
+ }
+
+ if (typeId != customDatatableTypeId)
+ {
+ return SQRESULT_ERROR;
+ }
+
+ int col = g_pSquirrel<context>->getinteger(sqvm, 2);
+ float compareValue = g_pSquirrel<context>->getfloat(sqvm, 3);
+
+ for (int i = 0; i < data->dataPointers.size(); i++)
+ {
+
+ if (compareValue >= std::stof(data->dataPointers[i][col]))
+ {
+ g_pSquirrel<context>->pushinteger(sqvm, i);
+ return SQRESULT_NOTNULL;
+ }
+ }
+ g_pSquirrel<context>->pushinteger(sqvm, -1);
+ return SQRESULT_NOTNULL;
+}
+
+template <ScriptContext context> SQRESULT GetDataTableRowLessThanOrEqualToFloatValue(HSquirrelVM* sqvm)
+{
+ csvData** dataPointer;
+ long long typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, (void**)&dataPointer, &typeId);
+ csvData* data = *dataPointer;
+ if (typeId == vanillaDatatableTypeId)
+ {
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowLessThanOrEqualToFloatValue"](sqvm);
+ }
+
+ if (typeId != customDatatableTypeId)
+ {
+ return SQRESULT_ERROR;
+ }
+
+ int col = g_pSquirrel<context>->getinteger(sqvm, 2);
+ int compareValue = g_pSquirrel<context>->getfloat(sqvm, 3);
+
+ for (int i = 0; i < data->dataPointers.size(); i++)
+ {
+
+ if (compareValue <= std::stof(data->dataPointers[i][col]))
+ {
+ g_pSquirrel<context>->pushinteger(sqvm, i);
+ return SQRESULT_NOTNULL;
+ }
+ }
+ g_pSquirrel<context>->pushinteger(sqvm, -1);
+ return SQRESULT_NOTNULL;
+}
+
+template <ScriptContext context> SQRESULT GetDataTableRowMatchingVectorValue(HSquirrelVM* sqvm)
+{
+ csvData** dataPointer;
+ long long typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, (void**)&dataPointer, &typeId);
+ csvData* data = *dataPointer;
+ if (typeId == vanillaDatatableTypeId)
+ {
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowMatchingVectorValue"](sqvm);
+ }
+
+ if (typeId != customDatatableTypeId)
+ {
+ return SQRESULT_ERROR;
+ }
+
+ int col = g_pSquirrel<context>->getinteger(sqvm, 2);
+ float* compareValue = g_pSquirrel<context>->getvector(sqvm, 3);
+
+ for (int i = 0; i < data->dataPointers.size(); i++)
+ {
+ float dataTableVector[3];
+ StringToVector(data->dataPointers[i][col],dataTableVector);
+ if ((dataTableVector[0] == compareValue[0]) && (dataTableVector[1] == compareValue[1]) && (dataTableVector[2] == compareValue[2]))
+ {
+ g_pSquirrel<context>->pushinteger(sqvm, i);
+ return SQRESULT_NOTNULL;
+ }
+ }
+ g_pSquirrel<context>->pushinteger(sqvm, -1);
+ return SQRESULT_NOTNULL;
+}
+
+template <ScriptContext context> SQRESULT DumpDataTable(HSquirrelVM* sqvm)
+{
+
+ DataTable* datatable = (DataTable*)getDataTableStructure(sqvm);
+ if (datatable == 0)
+ {
+ spdlog::info("datatable not loaded");
+ g_pSquirrel<context>->pushinteger(sqvm, 1);
+ return SQRESULT_NOTNULL;
+ }
+ //spdlog::info("Datatable size row = {} col = {}", datatable->rowAmount, datatable->columnAmount);
+ // std::string header = std::string(datatable->columnInfo[0].name);
+
+ spdlog::info(DataTableToString(datatable));
+
+ return SQRESULT_NULL;
+}
+
+template <ScriptContext context> SQRESULT DumpDataTableToFile(HSquirrelVM* sqvm)
+{
+ DataTable* datatable = (DataTable*)getDataTableStructure(sqvm);
+ if (datatable == 0)
+ {
+ spdlog::info("datatable not loaded");
+ g_pSquirrel<context>->pushinteger(sqvm, 1);
+ return SQRESULT_NOTNULL;
+ }
+ //spdlog::info("Datatable size row = {} col = {}", datatable->rowAmount, datatable->columnAmount);
+ // std::string header = std::string(datatable->columnInfo[0].name);
+ const char* pathName = g_pSquirrel<context>->getstring(sqvm, 2);
+ std::ofstream ofs(pathName);
+ std::string data = DataTableToString(datatable);
+ ofs.write(data.c_str(), data.size());
+ ofs.close();
+ return SQRESULT_NULL;
+}
+
+std::string DataTableToString(DataTable* datatable)
+{
+ std::string line = std::string(datatable->columnInfo[0].name);
+ for (int col = 1; col < datatable->columnAmount; col++)
+ {
+ ColumnInfo* colInfo = &datatable->columnInfo[col];
+ line += "," + std::string(colInfo->name);
+ }
+ line += std::string("\n");
+ for (int row = 0; row < datatable->rowAmount; row++)
+ {
+
+ bool seperator = false;
+ for (int col = 0; col < datatable->columnAmount; col++)
+ {
+ if (seperator)
+ {
+ line += std::string(",");
+ }
+ seperator = true;
+ ColumnInfo* colInfo = &datatable->columnInfo[col];
+ switch (colInfo->type)
+ {
+ case 0:
+ {
+ bool input = *((bool*)(datatable->data + colInfo->offset + row * datatable->rowInfo));
+ if (input)
+ {
+ line += std::string("1");
+ }
+ else
+ {
+ line += std::string("0");
+ }
+ break;
+ }
+ case 1:
+ {
+ int input = *((int*)(datatable->data + colInfo->offset + row * datatable->rowInfo));
+ line += std::to_string(input);
+ break;
+ }
+ case 2:
+ {
+ float input = *((float*)(datatable->data + colInfo->offset + row * datatable->rowInfo));
+ line += std::to_string(input);
+ break;
+ }
+ case 3:
+ {
+ float* input = ((float*)(datatable->data + colInfo->offset + row * datatable->rowInfo));
+ char string[256];
+ snprintf(string, 256, "\"<%f,%f,%f>\"", input[0], input[1], input[2]);
+ line += std::string(string);
+ break;
+ }
+
+ case 4:
+ case 5:
+ case 6:
+ {
+ char* string = *((char**)(datatable->data + colInfo->offset + row * datatable->rowInfo));
+ line += "\"" + std::string(string) + "\"";
+ break;
+ }
+ }
+ }
+ line += std::string("\n");
+ }
+ return line;
+}
+
+void datatableReleaseHook(void* d, int size)
+{
+ csvData* data = *(csvData**)d;
+ free(data->fullData);
+ delete data;
+}
+
+
+template <ScriptContext context> void RegisterDataTableFunctions()
+{
+ g_pSquirrel<context>->AddFuncOverride("GetDataTable", GetDatatable<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableColumnByName", GetDatatabeColumnByName<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDatatableRowCount", GetDatatabeRowCount<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableString", GetDataTableString<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableInt", GetDataTableInt<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableFloat", GetDataTableFloat<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableBool", GetDataTableBool<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableAsset", GetDataTableAsset<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableVector", GetDataTableVector<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableRowMatchingStringValue", GetDataTableRowMatchingStringValue<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableRowMatchingAssetValue", GetDataTableRowMatchingAssetValue<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableRowMatchingFloatValue", GetDataTableRowMatchingFloatValue<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableRowMatchingIntValue", GetDataTableRowMatchingIntValue < context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableRowMatchingVectorValue", GetDataTableRowMatchingVectorValue<context>);
+ g_pSquirrel<context>->AddFuncOverride(
+ "GetDataTableRowLessThanOrEqualToFloatValue", GetDataTableRowLessThanOrEqualToFloatValue<context>);
+ g_pSquirrel<context>->AddFuncOverride(
+ "GetDataTableRowGreaterThanOrEqualToFloatValue", GetDataTableRowGreaterThanOrEqualToFloatValue<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableRowLessThanOrEqualToIntValue", GetDataTableRowLessThanOrEqualToIntValue<context>);
+ g_pSquirrel<context>->AddFuncOverride(
+ "GetDataTableRowGreaterThanOrEqualToFloatValue", GetDataTableRowGreaterThanOrEqualToIntValue<context>);
+
+
+}
+
+ON_DLL_LOAD_RELIESON("server.dll", ServerScriptDatatables, ServerSquirrel, (CModule module))
+{
+ RegisterDataTableFunctions<ScriptContext::SERVER>();
+ g_pSquirrel<ScriptContext::SERVER>->AddFuncRegistration(
+ "void", "DumpDataTable", "var", "Dumps rpak datatable contents to console", DumpDataTable<ScriptContext::SERVER>);
+ // g_pSquirrel<ScriptContext::SERVER>->AddFuncRegistration( "void", "DumpDataTableToFile", "var,string", "Dumps datatable contents to console",
+ // DumpDataTableToFile<ScriptContext::SERVER>);
+
+
+
+ getDataTableStructure = module.Offset(0x1250f0).As<void* (*)(HSquirrelVM*)>();
+}
+
+
+ON_DLL_LOAD_RELIESON("client.dll", ClientScriptDatatables, ClientSquirrel, (CModule module))
+{
+
+ RegisterDataTableFunctions<ScriptContext::CLIENT>();
+ RegisterDataTableFunctions<ScriptContext::UI>();
+}
+
+ON_DLL_LOAD_RELIESON("engine.dll", GeneralScriptDataTables, ConCommand, (CModule module))
+{
+ Cvar_ns_prefer_datatable_from_disk =
+ new ConVar("ns_prefer_datatable_from_disk", "0", FCVAR_NONE, "whether datatables from disk overwrite rpak datatables");
+ if (Tier0::CommandLine()->CheckParm("-nopakdedi"))
+ {
+ Cvar_ns_prefer_datatable_from_disk->SetValue(true);
+ }
+
+
+} \ No newline at end of file
diff --git a/NorthstarDLL/scriptjson.cpp b/NorthstarDLL/scriptjson.cpp
index ff6d5284..9a77d3a2 100644
--- a/NorthstarDLL/scriptjson.cpp
+++ b/NorthstarDLL/scriptjson.cpp
@@ -10,8 +10,8 @@
#undef GetObject // fuck microsoft developers
#endif
-template <ScriptContext context>
-void DecodeJsonArray(void* sqvm, rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>* arr)
+template <ScriptContext context> void
+DecodeJsonArray(HSquirrelVM* sqvm, rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>* arr)
{
g_pSquirrel<context>->newarray(sqvm, 0);
@@ -47,8 +47,8 @@ void DecodeJsonArray(void* sqvm, rapidjson::GenericValue<rapidjson::UTF8<char>,
}
}
-template <ScriptContext context>
-void DecodeJsonTable(void* sqvm, rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>* obj)
+template <ScriptContext context> void
+DecodeJsonTable(HSquirrelVM* sqvm, rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>* obj)
{
g_pSquirrel<context>->newtable(sqvm);
@@ -208,7 +208,7 @@ template <ScriptContext context> void EncodeJSONArray(
// table function DecodeJSON( string json, bool fatalParseErrors = false )
-template <ScriptContext context> SQRESULT SQ_DecodeJSON(void* sqvm)
+template <ScriptContext context> SQRESULT SQ_DecodeJSON(HSquirrelVM* sqvm)
{
const char* pJson = g_pSquirrel<context>->getstring(sqvm, 1);
const bool bFatalParseErrors = g_pSquirrel<context>->getbool(sqvm, 2);
@@ -237,7 +237,7 @@ template <ScriptContext context> SQRESULT SQ_DecodeJSON(void* sqvm)
// string function EncodeJSON( table data )
-template <ScriptContext context> SQRESULT SQ_EncodeJSON(void* sqvm)
+template <ScriptContext context> SQRESULT SQ_EncodeJSON(HSquirrelVM* sqvm)
{
rapidjson_document doc;
doc.SetObject();
diff --git a/NorthstarDLL/scriptmainmenupromos.cpp b/NorthstarDLL/scriptmainmenupromos.cpp
index 31161257..f88cd3e9 100644
--- a/NorthstarDLL/scriptmainmenupromos.cpp
+++ b/NorthstarDLL/scriptmainmenupromos.cpp
@@ -24,21 +24,21 @@ enum eMainMenuPromoDataProperty
};
// void function NSRequestCustomMainMenuPromos()
-SQRESULT SQ_RequestCustomMainMenuPromos(void* sqvm)
+SQRESULT SQ_RequestCustomMainMenuPromos(HSquirrelVM* sqvm)
{
g_pMasterServerManager->RequestMainMenuPromos();
return SQRESULT_NULL;
}
// bool function NSHasCustomMainMenuPromoData()
-SQRESULT SQ_HasCustomMainMenuPromoData(void* sqvm)
+SQRESULT SQ_HasCustomMainMenuPromoData(HSquirrelVM* sqvm)
{
g_pSquirrel<ScriptContext::UI>->pushbool(sqvm, g_pMasterServerManager->m_bHasMainMenuPromoData);
return SQRESULT_NOTNULL;
}
// var function NSGetCustomMainMenuPromoData( int promoDataKey )
-SQRESULT SQ_GetCustomMainMenuPromoData(void* sqvm)
+SQRESULT SQ_GetCustomMainMenuPromoData(HSquirrelVM* sqvm)
{
if (!g_pMasterServerManager->m_bHasMainMenuPromoData)
return SQRESULT_NULL;
diff --git a/NorthstarDLL/scriptmodmenu.cpp b/NorthstarDLL/scriptmodmenu.cpp
index df4c933e..fcd74024 100644
--- a/NorthstarDLL/scriptmodmenu.cpp
+++ b/NorthstarDLL/scriptmodmenu.cpp
@@ -3,7 +3,7 @@
#include "squirrel.h"
// array<string> function NSGetModNames()
-SQRESULT SQ_GetModNames(void* sqvm)
+SQRESULT SQ_GetModNames(HSquirrelVM* sqvm)
{
g_pSquirrel<ScriptContext::UI>->newarray(sqvm, 0);
@@ -17,7 +17,7 @@ SQRESULT SQ_GetModNames(void* sqvm)
}
// bool function NSIsModEnabled(string modName)
-SQRESULT SQ_IsModEnabled(void* sqvm)
+SQRESULT SQ_IsModEnabled(HSquirrelVM* sqvm)
{
const SQChar* modName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 1);
@@ -35,7 +35,7 @@ SQRESULT SQ_IsModEnabled(void* sqvm)
}
// void function NSSetModEnabled(string modName, bool enabled)
-SQRESULT SQ_SetModEnabled(void* sqvm)
+SQRESULT SQ_SetModEnabled(HSquirrelVM* sqvm)
{
const SQChar* modName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 1);
const SQBool enabled = g_pSquirrel<ScriptContext::UI>->getbool(sqvm, 2);
@@ -54,7 +54,7 @@ SQRESULT SQ_SetModEnabled(void* sqvm)
}
// string function NSGetModDescriptionByModName(string modName)
-SQRESULT SQ_GetModDescription(void* sqvm)
+SQRESULT SQ_GetModDescription(HSquirrelVM* sqvm)
{
const SQChar* modName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 1);
@@ -72,7 +72,7 @@ SQRESULT SQ_GetModDescription(void* sqvm)
}
// string function NSGetModVersionByModName(string modName)
-SQRESULT SQ_GetModVersion(void* sqvm)
+SQRESULT SQ_GetModVersion(HSquirrelVM* sqvm)
{
const SQChar* modName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 1);
@@ -90,7 +90,7 @@ SQRESULT SQ_GetModVersion(void* sqvm)
}
// string function NSGetModDownloadLinkByModName(string modName)
-SQRESULT SQ_GetModDownloadLink(void* sqvm)
+SQRESULT SQ_GetModDownloadLink(HSquirrelVM* sqvm)
{
const SQChar* modName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 1);
@@ -108,7 +108,7 @@ SQRESULT SQ_GetModDownloadLink(void* sqvm)
}
// int function NSGetModLoadPriority(string modName)
-SQRESULT SQ_GetModLoadPriority(void* sqvm)
+SQRESULT SQ_GetModLoadPriority(HSquirrelVM* sqvm)
{
const SQChar* modName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 1);
@@ -126,7 +126,7 @@ SQRESULT SQ_GetModLoadPriority(void* sqvm)
}
// bool function NSIsModRequiredOnClient(string modName)
-SQRESULT SQ_IsModRequiredOnClient(void* sqvm)
+SQRESULT SQ_IsModRequiredOnClient(HSquirrelVM* sqvm)
{
const SQChar* modName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 1);
@@ -144,7 +144,7 @@ SQRESULT SQ_IsModRequiredOnClient(void* sqvm)
}
// array<string> function NSGetModConvarsByModName(string modName)
-SQRESULT SQ_GetModConvars(void* sqvm)
+SQRESULT SQ_GetModConvars(HSquirrelVM* sqvm)
{
const SQChar* modName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 1);
g_pSquirrel<ScriptContext::UI>->newarray(sqvm, 0);
@@ -168,7 +168,7 @@ SQRESULT SQ_GetModConvars(void* sqvm)
}
// void function NSReloadMods()
-SQRESULT SQ_ReloadMods(void* sqvm)
+SQRESULT SQ_ReloadMods(HSquirrelVM* sqvm)
{
g_pModManager->LoadMods();
return SQRESULT_NULL;
diff --git a/NorthstarDLL/scriptserverbrowser.cpp b/NorthstarDLL/scriptserverbrowser.cpp
index 0e647f45..bf63e35a 100644
--- a/NorthstarDLL/scriptserverbrowser.cpp
+++ b/NorthstarDLL/scriptserverbrowser.cpp
@@ -8,42 +8,42 @@
// functions for viewing server browser
// bool function NSIsMasterServerAuthenticated()
-SQRESULT SQ_IsMasterServerAuthenticated(void* sqvm)
+SQRESULT SQ_IsMasterServerAuthenticated(HSquirrelVM* sqvm)
{
g_pSquirrel<ScriptContext::UI>->pushbool(sqvm, g_pMasterServerManager->m_bOriginAuthWithMasterServerDone);
return SQRESULT_NOTNULL;
}
// void function NSRequestServerList()
-SQRESULT SQ_RequestServerList(void* sqvm)
+SQRESULT SQ_RequestServerList(HSquirrelVM* sqvm)
{
g_pMasterServerManager->RequestServerList();
return SQRESULT_NULL;
}
// bool function NSIsRequestingServerList()
-SQRESULT SQ_IsRequestingServerList(void* sqvm)
+SQRESULT SQ_IsRequestingServerList(HSquirrelVM* sqvm)
{
g_pSquirrel<ScriptContext::UI>->pushbool(sqvm, g_pMasterServerManager->m_bScriptRequestingServerList);
return SQRESULT_NOTNULL;
}
// bool function NSMasterServerConnectionSuccessful()
-SQRESULT SQ_MasterServerConnectionSuccessful(void* sqvm)
+SQRESULT SQ_MasterServerConnectionSuccessful(HSquirrelVM* sqvm)
{
g_pSquirrel<ScriptContext::UI>->pushbool(sqvm, g_pMasterServerManager->m_bSuccessfullyConnected);
return SQRESULT_NOTNULL;
}
// int function NSGetServerCount()
-SQRESULT SQ_GetServerCount(void* sqvm)
+SQRESULT SQ_GetServerCount(HSquirrelVM* sqvm)
{
g_pSquirrel<ScriptContext::UI>->pushinteger(sqvm, g_pMasterServerManager->m_vRemoteServers.size());
return SQRESULT_NOTNULL;
}
// string function NSGetServerName( int serverIndex )
-SQRESULT SQ_GetServerName(void* sqvm)
+SQRESULT SQ_GetServerName(HSquirrelVM* sqvm)
{
SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
@@ -64,7 +64,7 @@ SQRESULT SQ_GetServerName(void* sqvm)
}
// string function NSGetServerDescription( int serverIndex )
-SQRESULT SQ_GetServerDescription(void* sqvm)
+SQRESULT SQ_GetServerDescription(HSquirrelVM* sqvm)
{
SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
@@ -85,7 +85,7 @@ SQRESULT SQ_GetServerDescription(void* sqvm)
}
// string function NSGetServerMap( int serverIndex )
-SQRESULT SQ_GetServerMap(void* sqvm)
+SQRESULT SQ_GetServerMap(HSquirrelVM* sqvm)
{
SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
@@ -106,7 +106,7 @@ SQRESULT SQ_GetServerMap(void* sqvm)
}
// string function NSGetServerPlaylist( int serverIndex )
-SQRESULT SQ_GetServerPlaylist(void* sqvm)
+SQRESULT SQ_GetServerPlaylist(HSquirrelVM* sqvm)
{
SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
@@ -127,7 +127,7 @@ SQRESULT SQ_GetServerPlaylist(void* sqvm)
}
// int function NSGetServerPlayerCount( int serverIndex )
-SQRESULT SQ_GetServerPlayerCount(void* sqvm)
+SQRESULT SQ_GetServerPlayerCount(HSquirrelVM* sqvm)
{
SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
@@ -148,7 +148,7 @@ SQRESULT SQ_GetServerPlayerCount(void* sqvm)
}
// int function NSGetServerMaxPlayerCount( int serverIndex )
-SQRESULT SQ_GetServerMaxPlayerCount(void* sqvm)
+SQRESULT SQ_GetServerMaxPlayerCount(HSquirrelVM* sqvm)
{
SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
@@ -169,7 +169,7 @@ SQRESULT SQ_GetServerMaxPlayerCount(void* sqvm)
}
// string function NSGetServerID( int serverIndex )
-SQRESULT SQ_GetServerID(void* sqvm)
+SQRESULT SQ_GetServerID(HSquirrelVM* sqvm)
{
SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
@@ -190,7 +190,7 @@ SQRESULT SQ_GetServerID(void* sqvm)
}
// bool function NSServerRequiresPassword( int serverIndex )
-SQRESULT SQ_ServerRequiresPassword(void* sqvm)
+SQRESULT SQ_ServerRequiresPassword(HSquirrelVM* sqvm)
{
SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
@@ -211,7 +211,7 @@ SQRESULT SQ_ServerRequiresPassword(void* sqvm)
}
// int function NSGetServerRequiredModsCount( int serverIndex )
-SQRESULT SQ_GetServerRequiredModsCount(void* sqvm)
+SQRESULT SQ_GetServerRequiredModsCount(HSquirrelVM* sqvm)
{
SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
@@ -232,7 +232,7 @@ SQRESULT SQ_GetServerRequiredModsCount(void* sqvm)
}
// string function NSGetServerRequiredModName( int serverIndex, int modIndex )
-SQRESULT SQ_GetServerRequiredModName(void* sqvm)
+SQRESULT SQ_GetServerRequiredModName(HSquirrelVM* sqvm)
{
SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
SQInteger modIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 2);
@@ -266,7 +266,7 @@ SQRESULT SQ_GetServerRequiredModName(void* sqvm)
}
// string function NSGetServerRequiredModVersion( int serverIndex, int modIndex )
-SQRESULT SQ_GetServerRequiredModVersion(void* sqvm)
+SQRESULT SQ_GetServerRequiredModVersion(HSquirrelVM* sqvm)
{
SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
SQInteger modIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 2);
@@ -300,7 +300,7 @@ SQRESULT SQ_GetServerRequiredModVersion(void* sqvm)
}
// void function NSClearRecievedServerList()
-SQRESULT SQ_ClearRecievedServerList(void* sqvm)
+SQRESULT SQ_ClearRecievedServerList(HSquirrelVM* sqvm)
{
g_pMasterServerManager->ClearServerList();
return SQRESULT_NULL;
@@ -309,7 +309,7 @@ SQRESULT SQ_ClearRecievedServerList(void* sqvm)
// functions for authenticating with servers
// void function NSTryAuthWithServer( int serverIndex, string password = "" )
-SQRESULT SQ_TryAuthWithServer(void* sqvm)
+SQRESULT SQ_TryAuthWithServer(HSquirrelVM* sqvm)
{
SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
const SQChar* password = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 2);
@@ -342,21 +342,21 @@ SQRESULT SQ_TryAuthWithServer(void* sqvm)
}
// bool function NSIsAuthenticatingWithServer()
-SQRESULT SQ_IsAuthComplete(void* sqvm)
+SQRESULT SQ_IsAuthComplete(HSquirrelVM* sqvm)
{
g_pSquirrel<ScriptContext::UI>->pushbool(sqvm, g_pMasterServerManager->m_bScriptAuthenticatingWithGameServer);
return SQRESULT_NOTNULL;
}
// bool function NSWasAuthSuccessful()
-SQRESULT SQ_WasAuthSuccessful(void* sqvm)
+SQRESULT SQ_WasAuthSuccessful(HSquirrelVM* sqvm)
{
g_pSquirrel<ScriptContext::UI>->pushbool(sqvm, g_pMasterServerManager->m_bSuccessfullyAuthenticatedWithGameServer);
return SQRESULT_NOTNULL;
}
// void function NSConnectToAuthedServer()
-SQRESULT SQ_ConnectToAuthedServer(void* sqvm)
+SQRESULT SQ_ConnectToAuthedServer(HSquirrelVM* sqvm)
{
if (!g_pMasterServerManager->m_bHasPendingConnectionInfo)
{
@@ -388,7 +388,7 @@ SQRESULT SQ_ConnectToAuthedServer(void* sqvm)
}
// void function NSTryAuthWithLocalServer()
-SQRESULT SQ_TryAuthWithLocalServer(void* sqvm)
+SQRESULT SQ_TryAuthWithLocalServer(HSquirrelVM* sqvm)
{
// do auth request
g_pMasterServerManager->AuthenticateWithOwnServer(R2::g_pLocalPlayerUserID, g_pMasterServerManager->m_sOwnClientAuthToken);
@@ -397,7 +397,7 @@ SQRESULT SQ_TryAuthWithLocalServer(void* sqvm)
}
// void function NSCompleteAuthWithLocalServer()
-SQRESULT SQ_CompleteAuthWithLocalServer(void* sqvm)
+SQRESULT SQ_CompleteAuthWithLocalServer(HSquirrelVM* sqvm)
{
// literally just set serverfilter
// note: this assumes we have no authdata other than our own
@@ -410,7 +410,7 @@ SQRESULT SQ_CompleteAuthWithLocalServer(void* sqvm)
}
// string function NSGetAuthFailReason()
-SQRESULT SQ_GetAuthFailReason(void* sqvm)
+SQRESULT SQ_GetAuthFailReason(HSquirrelVM* sqvm)
{
g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_sAuthFailureReason.c_str(), -1);
return SQRESULT_NOTNULL;
diff --git a/NorthstarDLL/scriptservertoclientstringcommand.cpp b/NorthstarDLL/scriptservertoclientstringcommand.cpp
index bc6a1cdc..555ea7cf 100644
--- a/NorthstarDLL/scriptservertoclientstringcommand.cpp
+++ b/NorthstarDLL/scriptservertoclientstringcommand.cpp
@@ -5,11 +5,11 @@
void ConCommand_ns_script_servertoclientstringcommand(const CCommand& arg)
{
- if (g_pSquirrel<ScriptContext::CLIENT>->sqvm &&
+ if (g_pSquirrel<ScriptContext::CLIENT>->SquirrelVM &&
g_pSquirrel<ScriptContext::CLIENT>->setupfunc("NSClientCodeCallback_RecievedServerToClientStringCommand") != SQRESULT_ERROR)
{
- g_pSquirrel<ScriptContext::CLIENT>->pushstring(g_pSquirrel<ScriptContext::CLIENT>->sqvm2, arg.ArgS());
- g_pSquirrel<ScriptContext::CLIENT>->call(g_pSquirrel<ScriptContext::CLIENT>->sqvm2, 1); // todo: doesn't throw or log errors from within this, probably not great behaviour
+ g_pSquirrel<ScriptContext::CLIENT>->pushstring(g_pSquirrel<ScriptContext::CLIENT>->sqvm, arg.ArgS());
+ g_pSquirrel<ScriptContext::CLIENT>->call(g_pSquirrel<ScriptContext::CLIENT>->sqvm, 1); // todo: doesn't throw or log errors from within this, probably not great behaviour
}
}
diff --git a/NorthstarDLL/scriptutility.cpp b/NorthstarDLL/scriptutility.cpp
index 1acd8599..cc4c0c00 100644
--- a/NorthstarDLL/scriptutility.cpp
+++ b/NorthstarDLL/scriptutility.cpp
@@ -2,7 +2,7 @@
#include "squirrel.h"
// asset function StringToAsset( string assetName )
-template <ScriptContext context> SQRESULT SQ_StringToAsset(void* sqvm)
+template <ScriptContext context> SQRESULT SQ_StringToAsset(HSquirrelVM* sqvm)
{
g_pSquirrel<context>->pushasset(sqvm, g_pSquirrel<context>->getstring(sqvm, 1), -1);
return SQRESULT_NOTNULL;
diff --git a/NorthstarDLL/serverchathooks.cpp b/NorthstarDLL/serverchathooks.cpp
index b05f3dc3..a87a0034 100644
--- a/NorthstarDLL/serverchathooks.cpp
+++ b/NorthstarDLL/serverchathooks.cpp
@@ -54,10 +54,10 @@ void,, (CServerGameDLL* self, unsigned int senderPlayerId, const char* text, boo
if (g_pSquirrel<ScriptContext::SERVER>->setupfunc("CServerGameDLL_ProcessMessageStartThread") != SQRESULT_ERROR)
{
- g_pSquirrel<ScriptContext::SERVER>->pushinteger(g_pSquirrel<ScriptContext::SERVER>->sqvm2, (int)senderPlayerId - 1);
- g_pSquirrel<ScriptContext::SERVER>->pushstring(g_pSquirrel<ScriptContext::SERVER>->sqvm2, text);
- g_pSquirrel<ScriptContext::SERVER>->pushbool(g_pSquirrel<ScriptContext::SERVER>->sqvm2, isTeam);
- g_pSquirrel<ScriptContext::SERVER>->call(g_pSquirrel<ScriptContext::SERVER>->sqvm2, 3);
+ g_pSquirrel<ScriptContext::SERVER>->pushinteger(g_pSquirrel<ScriptContext::SERVER>->sqvm, (int)senderPlayerId - 1);
+ g_pSquirrel<ScriptContext::SERVER>->pushstring(g_pSquirrel<ScriptContext::SERVER>->sqvm, text);
+ g_pSquirrel<ScriptContext::SERVER>->pushbool(g_pSquirrel<ScriptContext::SERVER>->sqvm, isTeam);
+ g_pSquirrel<ScriptContext::SERVER>->call(g_pSquirrel<ScriptContext::SERVER>->sqvm, 3);
}
else
_CServerGameDLL__OnReceivedSayTextMessage(self, senderPlayerId, text, isTeam);
@@ -115,7 +115,7 @@ void ChatBroadcastMessage(int fromPlayerIndex, int toPlayerIndex, const char* te
}
// void function NSSendMessage( int playerIndex, string text, bool isTeam )
-SQRESULT SQ_SendMessage(void* sqvm)
+SQRESULT SQ_SendMessage(HSquirrelVM* sqvm)
{
int playerIndex = g_pSquirrel<ScriptContext::SERVER>->getinteger(sqvm, 1);
const char* text = g_pSquirrel<ScriptContext::SERVER>->getstring(sqvm, 2);
@@ -127,7 +127,7 @@ SQRESULT SQ_SendMessage(void* sqvm)
}
// void function NSBroadcastMessage( int fromPlayerIndex, int toPlayerIndex, string text, bool isTeam, bool isDead, int messageType )
-SQRESULT SQ_BroadcastMessage(void* sqvm)
+SQRESULT SQ_BroadcastMessage(HSquirrelVM* sqvm)
{
int fromPlayerIndex = g_pSquirrel<ScriptContext::SERVER>->getinteger(sqvm, 1);
int toPlayerIndex = g_pSquirrel<ScriptContext::SERVER>->getinteger(sqvm, 2);
diff --git a/NorthstarDLL/squirrel.cpp b/NorthstarDLL/squirrel.cpp
index 8beee760..7cf46f4f 100644
--- a/NorthstarDLL/squirrel.cpp
+++ b/NorthstarDLL/squirrel.cpp
@@ -17,6 +17,8 @@ const char* GetContextName(ScriptContext context)
return "SERVER";
case ScriptContext::UI:
return "UI";
+ default:
+ return "UNKNOWN";
}
}
@@ -39,73 +41,20 @@ eSQReturnType SQReturnTypeFromString(const char* pReturnType)
return eSQReturnType::Default; // previous default value
}
-const char* SQTypeNameFromID(int iTypeId)
-{
- switch (iTypeId)
- {
- case OT_ASSET:
- return "asset";
- case OT_INTEGER:
- return "int";
- case OT_BOOL:
- return "bool";
- case SQOBJECT_NUMERIC:
- return "float or int";
- case OT_NULL:
- return "null";
- case OT_VECTOR:
- return "vector";
- case 0:
- return "var";
- case OT_USERDATA:
- return "userdata";
- case OT_FLOAT:
- return "float";
- case OT_STRING:
- return "string";
- case 0x8000040:
- return "array";
- case 0x8000200:
- return "function";
- case 0x8100000:
- return "structdef";
- case OT_THREAD:
- return "thread";
- case OT_FUNCPROTO:
- return "function";
- case OT_CLAAS:
- return "class";
- case OT_WEAKREF:
- return "weakref";
- case 0x8080000:
- return "unimplemented function";
- case 0x8200000:
- return "struct instance";
- case 0xA000020:
- return "table";
- case 0xA008000:
- return "instance";
- case 0xA400000:
- return "entity";
- default:
- 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(void* newSqvm)
+template <ScriptContext context> void SquirrelManager<context>::VMCreated(CSquirrelVM* newSqvm)
{
- sqvm = newSqvm;
- sqvm2 = *((void**)((char*)sqvm + 8)); // honestly not 100% sure on what this is, but alot of functions take it
+ SquirrelVM = newSqvm;
+ sqvm = SquirrelVM->sqvm; // honestly not 100% sure on what this is, but alot of functions take it
for (SQFuncRegistration* funcReg : m_funcRegistrations)
{
spdlog::info("Registering {} function {}", GetContextName(context), funcReg->squirrelFuncName);
- RegisterSquirrelFunc(sqvm, funcReg, 1);
+ RegisterSquirrelFunc(SquirrelVM, funcReg, 1);
}
for (auto& pair : g_pModManager->m_DependencyConstants)
@@ -123,18 +72,18 @@ template <ScriptContext context> void SquirrelManager<context>::VMCreated(void*
}
}
- defconst(sqvm, pair.first.c_str(), bWasFound);
+ defconst(SquirrelVM, pair.first.c_str(), bWasFound);
}
}
template <ScriptContext context> void SquirrelManager<context>::VMDestroyed()
{
- sqvm = nullptr;
+ SquirrelVM = nullptr;
}
template <ScriptContext context> void SquirrelManager<context>::ExecuteCode(const char* pCode)
{
- if (!sqvm)
+ if (!SquirrelVM)
{
spdlog::error("Cannot execute code, {} squirrel vm is not initialised", GetContextName(context));
return;
@@ -150,8 +99,8 @@ template <ScriptContext context> void SquirrelManager<context>::ExecuteCode(cons
if (compileResult != SQRESULT_ERROR)
{
- pushroottable(sqvm2);
- SQRESULT callResult = call(sqvm2, 0);
+ pushroottable(sqvm);
+ SQRESULT callResult = call(sqvm, 0);
spdlog::info("sq_call returned {}", PrintSQRESULT.at(callResult));
}
}
@@ -182,22 +131,26 @@ template <ScriptContext context> void SquirrelManager<context>::AddFuncRegistrat
template <ScriptContext context> SQRESULT SquirrelManager<context>::setupfunc(const SQChar* funcname)
{
- pushroottable(sqvm2);
- pushstring(sqvm2, funcname, -1);
+ pushroottable(sqvm);
+ pushstring(sqvm, funcname, -1);
- SQRESULT result = get(sqvm2, -2);
+ SQRESULT result = get(sqvm, -2);
if (result != SQRESULT_ERROR)
- pushroottable(sqvm2);
+ pushroottable(sqvm);
return result;
}
+template <ScriptContext context> void SquirrelManager<context>::AddFuncOverride(std::string name, SQFunction func)
+{
+ m_funcOverrides[name] = func;
+}
// hooks
-template <ScriptContext context> void* (*sq_compiler_create)(void* sqvm, void* a2, void* a3, SQBool bShouldThrowError);
-template <ScriptContext context> void* sq_compiler_createHook(void* sqvm, void* a2, void* a3, SQBool bShouldThrowError)
+template <ScriptContext context> void* (*sq_compiler_create)(HSquirrelVM* sqvm, void* a2, void* a3, SQBool bShouldThrowError);
+template <ScriptContext context> void* sq_compiler_createHook(HSquirrelVM* sqvm, void* a2, void* a3, SQBool bShouldThrowError)
{
// store whether errors generated from this compile should be fatal
- if (context == ScriptContext::CLIENT && sqvm == g_pSquirrel<ScriptContext::UI>->sqvm2)
+ if (context == ScriptContext::CLIENT && sqvm == g_pSquirrel<ScriptContext::UI>->sqvm)
g_pSquirrel<ScriptContext::UI>->m_bCompilationErrorsFatal = bShouldThrowError;
else
g_pSquirrel<context>->m_bCompilationErrorsFatal = bShouldThrowError;
@@ -205,8 +158,8 @@ template <ScriptContext context> void* sq_compiler_createHook(void* sqvm, void*
return sq_compiler_create<context>(sqvm, a2, a3, bShouldThrowError);
}
-template <ScriptContext context> SQInteger (*SQPrint)(void* sqvm, const char* fmt);
-template <ScriptContext context> SQInteger SQPrintHook(void* sqvm, const char* fmt, ...)
+template <ScriptContext context> SQInteger (*SQPrint)(HSquirrelVM* sqvm, const char* fmt);
+template <ScriptContext context> SQInteger SQPrintHook(HSquirrelVM* sqvm, const char* fmt, ...)
{
va_list va;
va_start(va, fmt);
@@ -226,16 +179,16 @@ template <ScriptContext context> SQInteger SQPrintHook(void* sqvm, const char* f
return 0;
}
-template <ScriptContext context> void* (*CreateNewVM)(void* a1, ScriptContext contextArg);
-template <ScriptContext context> void* CreateNewVMHook(void* a1, ScriptContext realContext)
+template <ScriptContext context> CSquirrelVM* (*CreateNewVM)(void* a1, ScriptContext contextArg);
+template <ScriptContext context> CSquirrelVM* CreateNewVMHook(void* a1, ScriptContext realContext)
{
- void* sqvm = CreateNewVM<context>(a1, realContext);
+ CSquirrelVM* sqvm = CreateNewVM<context>(a1, realContext);
if (realContext == ScriptContext::UI)
g_pSquirrel<ScriptContext::UI>->VMCreated(sqvm);
else
g_pSquirrel<context>->VMCreated(sqvm);
- spdlog::info("CreateNewVM {} {}", GetContextName(realContext), sqvm);
+ spdlog::info("CreateNewVM {} {}", GetContextName(realContext), (void*)sqvm);
return sqvm;
}
@@ -259,7 +212,7 @@ template <ScriptContext context> void ScriptCompileErrorHook(void* sqvm, const c
{
bool bIsFatalError = g_pSquirrel<context>->m_bCompilationErrorsFatal;
ScriptContext realContext = context; // ui and client use the same function so we use this for prints
- if (context == ScriptContext::CLIENT && sqvm == g_pSquirrel<ScriptContext::UI>->sqvm2)
+ if (context == ScriptContext::CLIENT && sqvm == g_pSquirrel<ScriptContext::UI>->sqvm)
{
realContext = ScriptContext::UI;
bIsFatalError = g_pSquirrel<ScriptContext::UI>->m_bCompilationErrorsFatal;
@@ -273,7 +226,7 @@ template <ScriptContext context> void ScriptCompileErrorHook(void* sqvm, const c
if (bIsFatalError)
{
// kill dedicated server if we hit this
- if (IsDedicatedServer())
+ if (IsDedicatedServer())
abort();
else
{
@@ -294,9 +247,39 @@ template <ScriptContext context> void ScriptCompileErrorHook(void* sqvm, const c
// dont call the original function since it kills game lol
}
+
+
+
+template <ScriptContext context> int64_t(*RegisterSquirrelFunction)(CSquirrelVM* sqvm, SQFuncRegistration* funcReg, char unknown);
+template <ScriptContext context> int64_t RegisterSquirrelFunctionHook(CSquirrelVM* sqvm, SQFuncRegistration* funcReg, char unknown)
+{
+
+ if (context == ScriptContext::CLIENT && sqvm == g_pSquirrel<ScriptContext::UI>->SquirrelVM)
+ {
+ if (g_pSquirrel<ScriptContext::UI>->m_funcOverrides.count(funcReg->squirrelFuncName))
+ {
+ g_pSquirrel<ScriptContext::UI>->m_funcOriginals[funcReg->squirrelFuncName] = funcReg->funcPtr;
+ funcReg->funcPtr = g_pSquirrel<ScriptContext::UI>->m_funcOverrides[funcReg->squirrelFuncName];
+ spdlog::info("Replacing {} in UI", std::string(funcReg->squirrelFuncName));
+ }
+
+ return g_pSquirrel<ScriptContext::UI>->RegisterSquirrelFunc(sqvm, funcReg, unknown);
+ }
+
+ if (g_pSquirrel<context>->m_funcOverrides.count(funcReg->squirrelFuncName))
+ {
+ g_pSquirrel<context>->m_funcOriginals[funcReg->squirrelFuncName] = funcReg->funcPtr;
+ funcReg->funcPtr = g_pSquirrel<context>->m_funcOverrides[funcReg->squirrelFuncName];
+ spdlog::info("Replacing {} in Client", std::string(funcReg->squirrelFuncName));
+ }
+
+ return g_pSquirrel<context>->RegisterSquirrelFunc(sqvm, funcReg, unknown);
+}
+
template <ScriptContext context> bool (*CallScriptInitCallback)(void* sqvm, const char* callback);
template <ScriptContext context> bool CallScriptInitCallbackHook(void* sqvm, const char* callback)
{
+
ScriptContext realContext = context;
bool bShouldCallCustomCallbacks = true;
@@ -366,6 +349,12 @@ template <ScriptContext context> void ConCommand_script(const CCommand& args)
g_pSquirrel<context>->ExecuteCode(args.ArgS());
}
+SQRESULT SQ_Stub(HSquirrelVM* sqvm)
+{
+ spdlog::info("Stubbed Function called");
+ return SQRESULT_NULL;
+}
+
ON_DLL_LOAD_RELIESON("client.dll", ClientSquirrel, ConCommand, (CModule module))
{
AUTOHOOK_DISPATCH_MODULE(client.dll)
@@ -373,9 +362,9 @@ ON_DLL_LOAD_RELIESON("client.dll", ClientSquirrel, ConCommand, (CModule module))
g_pSquirrel<ScriptContext::CLIENT> = new SquirrelManager<ScriptContext::CLIENT>;
g_pSquirrel<ScriptContext::UI> = new SquirrelManager<ScriptContext::UI>;
- g_pSquirrel<ScriptContext::CLIENT>->RegisterSquirrelFunc = module.Offset(0x108E0).As<RegisterSquirrelFuncType>();
+ //g_pSquirrel<ScriptContext::CLIENT>->RegisterSquirrelFunc = module.Offset(0x108E0).As<RegisterSquirrelFuncType>();
+ //g_pSquirrel<ScriptContext::UI>->RegisterSquirrelFunc = g_pSquirrel<ScriptContext::CLIENT>->RegisterSquirrelFunc;
g_pSquirrel<ScriptContext::CLIENT>->__sq_defconst = module.Offset(0x12120).As<sq_defconstType>();
- g_pSquirrel<ScriptContext::UI>->RegisterSquirrelFunc = g_pSquirrel<ScriptContext::CLIENT>->RegisterSquirrelFunc;
g_pSquirrel<ScriptContext::UI>->__sq_defconst = g_pSquirrel<ScriptContext::CLIENT>->__sq_defconst;
g_pSquirrel<ScriptContext::CLIENT>->__sq_compilebuffer = module.Offset(0x3110).As<sq_compilebufferType>();
@@ -400,25 +389,39 @@ ON_DLL_LOAD_RELIESON("client.dll", ClientSquirrel, ConCommand, (CModule module))
g_pSquirrel<ScriptContext::CLIENT>->__sq_pushinteger = module.Offset(0x36A0).As<sq_pushintegerType>();
g_pSquirrel<ScriptContext::CLIENT>->__sq_pushfloat = module.Offset(0x3800).As<sq_pushfloatType>();
g_pSquirrel<ScriptContext::CLIENT>->__sq_pushbool = module.Offset(0x3710).As<sq_pushboolType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_pushasset = module.Offset(0x3560).As<sq_pushassetType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_pushvector = module.Offset(0x3780).As<sq_pushvectorType>();
g_pSquirrel<ScriptContext::CLIENT>->__sq_raiseerror = module.Offset(0x8470).As<sq_raiseerrorType>();
- g_pSquirrel<ScriptContext::CLIENT>->__sq_pushasset = module.Offset(0x3560).As<sq_pushAssetType>();
g_pSquirrel<ScriptContext::UI>->__sq_pushstring = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushstring;
g_pSquirrel<ScriptContext::UI>->__sq_pushinteger = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushinteger;
g_pSquirrel<ScriptContext::UI>->__sq_pushfloat = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushfloat;
g_pSquirrel<ScriptContext::UI>->__sq_pushbool = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushbool;
- g_pSquirrel<ScriptContext::UI>->__sq_raiseerror = g_pSquirrel<ScriptContext::CLIENT>->__sq_raiseerror;
+ g_pSquirrel<ScriptContext::UI>->__sq_pushvector = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushvector;
g_pSquirrel<ScriptContext::UI>->__sq_pushasset = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushasset;
+ g_pSquirrel<ScriptContext::UI>->__sq_raiseerror = g_pSquirrel<ScriptContext::CLIENT>->__sq_raiseerror;
+
g_pSquirrel<ScriptContext::CLIENT>->__sq_getstring = module.Offset(0x60C0).As<sq_getstringType>();
g_pSquirrel<ScriptContext::CLIENT>->__sq_getinteger = module.Offset(0x60E0).As<sq_getintegerType>();
g_pSquirrel<ScriptContext::CLIENT>->__sq_getfloat = module.Offset(0x6100).As<sq_getfloatType>();
g_pSquirrel<ScriptContext::CLIENT>->__sq_getbool = module.Offset(0x6130).As<sq_getboolType>();
g_pSquirrel<ScriptContext::CLIENT>->__sq_get = module.Offset(0x7C30).As<sq_getType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_getasset = module.Offset(0x6010).As<sq_getassetType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_getuserdata = module.Offset(0x63D0).As<sq_getuserdataType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_getvector = module.Offset(0x6140).As<sq_getvectorType>();
g_pSquirrel<ScriptContext::UI>->__sq_getstring = g_pSquirrel<ScriptContext::CLIENT>->__sq_getstring;
g_pSquirrel<ScriptContext::UI>->__sq_getinteger = g_pSquirrel<ScriptContext::CLIENT>->__sq_getinteger;
g_pSquirrel<ScriptContext::UI>->__sq_getfloat = g_pSquirrel<ScriptContext::CLIENT>->__sq_getfloat;
g_pSquirrel<ScriptContext::UI>->__sq_getbool = g_pSquirrel<ScriptContext::CLIENT>->__sq_getbool;
g_pSquirrel<ScriptContext::UI>->__sq_get = g_pSquirrel<ScriptContext::CLIENT>->__sq_get;
+ g_pSquirrel<ScriptContext::UI>->__sq_getasset = g_pSquirrel<ScriptContext::CLIENT>->__sq_getasset;
+ g_pSquirrel<ScriptContext::UI>->__sq_getuserdata = g_pSquirrel<ScriptContext::CLIENT>->__sq_getuserdata;
+ g_pSquirrel<ScriptContext::UI>->__sq_getvector = g_pSquirrel<ScriptContext::CLIENT>->__sq_getvector;
+
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_createuserdata = module.Offset(0x38D0).As<sq_createuserdataType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_setuserdatatypeid = module.Offset(0x6490).As<sq_setuserdatatypeidType>();
+ g_pSquirrel<ScriptContext::UI>->__sq_createuserdata = g_pSquirrel<ScriptContext::CLIENT>->__sq_createuserdata;
+ g_pSquirrel<ScriptContext::UI>->__sq_setuserdatatypeid = g_pSquirrel<ScriptContext::CLIENT>->__sq_setuserdatatypeid;
// uiscript_reset concommand: don't loop forever if compilation fails
module.Offset(0x3C6E4C).NOP(6);
@@ -442,8 +445,26 @@ ON_DLL_LOAD_RELIESON("client.dll", ClientSquirrel, ConCommand, (CModule module))
&CallScriptInitCallbackHook<ScriptContext::CLIENT>,
&CallScriptInitCallback<ScriptContext::CLIENT>);
+ MAKEHOOK(module.Offset(0x108E0), &RegisterSquirrelFunctionHook<ScriptContext::CLIENT>, &g_pSquirrel<ScriptContext::CLIENT>->RegisterSquirrelFunc);
+
+ g_pSquirrel<ScriptContext::UI>->RegisterSquirrelFunc = g_pSquirrel<ScriptContext::CLIENT>->RegisterSquirrelFunc;
+
RegisterConCommand("script_client", ConCommand_script<ScriptContext::CLIENT>, "Executes script code on the client vm", FCVAR_CLIENTDLL);
RegisterConCommand("script_ui", ConCommand_script<ScriptContext::UI>, "Executes script code on the ui vm", FCVAR_CLIENTDLL);
+
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncOverride("DevTextBufferWrite", SQ_Stub);
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncOverride("DevTextBufferClear", SQ_Stub);
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncOverride("DevTextBufferDumpToFile", SQ_Stub);
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncOverride("Dev_CommandLineAddParam", SQ_Stub);
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncOverride("DevP4Checkout", SQ_Stub);
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncOverride("DevP4Add", SQ_Stub);
+
+ g_pSquirrel<ScriptContext::UI>->AddFuncOverride("DevTextBufferWrite", SQ_Stub);
+ g_pSquirrel<ScriptContext::UI>->AddFuncOverride("DevTextBufferClear", SQ_Stub);
+ g_pSquirrel<ScriptContext::UI>->AddFuncOverride("DevTextBufferDumpToFile", SQ_Stub);
+ g_pSquirrel<ScriptContext::UI>->AddFuncOverride("Dev_CommandLineAddParam", SQ_Stub);
+ g_pSquirrel<ScriptContext::UI>->AddFuncOverride("DevP4Checkout", SQ_Stub);
+ g_pSquirrel<ScriptContext::UI>->AddFuncOverride("DevP4Add", SQ_Stub);
}
ON_DLL_LOAD_RELIESON("server.dll", ServerSquirrel, ConCommand, (CModule module))
@@ -452,7 +473,7 @@ ON_DLL_LOAD_RELIESON("server.dll", ServerSquirrel, ConCommand, (CModule module))
g_pSquirrel<ScriptContext::SERVER> = new SquirrelManager<ScriptContext::SERVER>;
- g_pSquirrel<ScriptContext::SERVER>->RegisterSquirrelFunc = module.Offset(0x1DD10).As<RegisterSquirrelFuncType>();
+ //g_pSquirrel<ScriptContext::SERVER>->RegisterSquirrelFunc = module.Offset(0x1DD10).As<RegisterSquirrelFuncType>();
g_pSquirrel<ScriptContext::SERVER>->__sq_defconst = module.Offset(0x1F550).As<sq_defconstType>();
g_pSquirrel<ScriptContext::SERVER>->__sq_compilebuffer = module.Offset(0x3110).As<sq_compilebufferType>();
@@ -469,14 +490,22 @@ ON_DLL_LOAD_RELIESON("server.dll", ServerSquirrel, ConCommand, (CModule module))
g_pSquirrel<ScriptContext::SERVER>->__sq_pushinteger = module.Offset(0x36A0).As<sq_pushintegerType>();
g_pSquirrel<ScriptContext::SERVER>->__sq_pushfloat = module.Offset(0x3800).As<sq_pushfloatType>();
g_pSquirrel<ScriptContext::SERVER>->__sq_pushbool = module.Offset(0x3710).As<sq_pushboolType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_pushasset = module.Offset(0x3560).As<sq_pushassetType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_pushvector = module.Offset(0x3780).As<sq_pushvectorType>();
g_pSquirrel<ScriptContext::SERVER>->__sq_raiseerror = module.Offset(0x8440).As<sq_raiseerrorType>();
g_pSquirrel<ScriptContext::SERVER>->__sq_getstring = module.Offset(0x60A0).As<sq_getstringType>();
g_pSquirrel<ScriptContext::SERVER>->__sq_getinteger = module.Offset(0x60C0).As<sq_getintegerType>();
g_pSquirrel<ScriptContext::SERVER>->__sq_getfloat = module.Offset(0x60E0).As<sq_getfloatType>();
g_pSquirrel<ScriptContext::SERVER>->__sq_getbool = module.Offset(0x6110).As<sq_getboolType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_getasset = module.Offset(0x5FF0).As<sq_getassetType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_getuserdata = module.Offset(0x63B0).As<sq_getuserdataType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_getvector = module.Offset(0x6120).As<sq_getvectorType>();
g_pSquirrel<ScriptContext::SERVER>->__sq_get = module.Offset(0x7C00).As<sq_getType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_createuserdata = module.Offset(0x38D0).As<sq_createuserdataType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_setuserdatatypeid = module.Offset(0x6470).As<sq_setuserdatatypeidType>();
+
MAKEHOOK(module.Offset(0x8AA0),
&sq_compiler_createHook<ScriptContext::SERVER>,
&sq_compiler_create<ScriptContext::SERVER>);
@@ -493,11 +522,72 @@ ON_DLL_LOAD_RELIESON("server.dll", ServerSquirrel, ConCommand, (CModule module))
&CallScriptInitCallbackHook<ScriptContext::SERVER>,
&CallScriptInitCallback<ScriptContext::SERVER>);
- // FCVAR_CHEAT and FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS allows clients to execute this, but since it's unsafe we only allow it when cheats are enabled
- // for script_client and script_ui, we don't use cheats, so clients can execute them on themselves all they want
+ MAKEHOOK(module.Offset(0x1DD10), &RegisterSquirrelFunctionHook<ScriptContext::SERVER>, &g_pSquirrel<ScriptContext::SERVER>->RegisterSquirrelFunc);
+
+ // FCVAR_CHEAT and FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS allows clients to execute this, but since it's unsafe we only allow it when cheats
+ // are enabled for script_client and script_ui, we don't use cheats, so clients can execute them on themselves all they want
RegisterConCommand(
"script",
ConCommand_script<ScriptContext::SERVER>,
"Executes script code on the server vm",
FCVAR_GAMEDLL | FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS | FCVAR_CHEAT);
+
+ g_pSquirrel<ScriptContext::SERVER>->AddFuncOverride("DevTextBufferWrite", SQ_Stub);
+ g_pSquirrel<ScriptContext::SERVER>->AddFuncOverride("DevTextBufferClear", SQ_Stub);
+ g_pSquirrel<ScriptContext::SERVER>->AddFuncOverride("DevTextBufferDumpToFile", SQ_Stub);
+ g_pSquirrel<ScriptContext::SERVER>->AddFuncOverride("Dev_CommandLineAddParam", SQ_Stub);
+ g_pSquirrel<ScriptContext::SERVER>->AddFuncOverride("DevP4Checkout", SQ_Stub);
+ g_pSquirrel<ScriptContext::SERVER>->AddFuncOverride("DevP4Add", SQ_Stub);
}
+
+const char* SQTypeNameFromID(int type)
+{
+ switch (type)
+ {
+ case OT_ASSET:
+ return "asset";
+ case OT_INTEGER:
+ return "int";
+ case OT_BOOL:
+ return "bool";
+ case SQOBJECT_NUMERIC:
+ return "float or int";
+ case OT_NULL:
+ return "null";
+ case OT_VECTOR:
+ return "vector";
+ case 0:
+ return "var";
+ case OT_USERDATA:
+ return "userdata";
+ case OT_FLOAT:
+ return "float";
+ case OT_STRING:
+ return "string";
+ case OT_ARRAY:
+ return "array";
+ case 0x8000200:
+ return "function";
+ case 0x8100000:
+ return "structdef";
+ case OT_THREAD:
+ return "thread";
+ case OT_FUNCPROTO:
+ return "function";
+ case OT_CLAAS:
+ return "class";
+ case OT_WEAKREF:
+ return "weakref";
+ case 0x8080000:
+ return "unimplemented function";
+ case 0x8200000:
+ return "struct instance";
+ case OT_TABLE:
+ return "table";
+ case 0xA008000:
+ return "instance";
+ case OT_ENTITY:
+ return "entity";
+ }
+ return "";
+} \ No newline at end of file
diff --git a/NorthstarDLL/squirrel.h b/NorthstarDLL/squirrel.h
index a899ed9b..f29ff05d 100644
--- a/NorthstarDLL/squirrel.h
+++ b/NorthstarDLL/squirrel.h
@@ -1,5 +1,6 @@
#pragma once
+#include "squirreldatatypes.h"
// stolen from ttf2sdk: sqvm types
typedef float SQFloat;
typedef long SQInteger;
@@ -14,7 +15,7 @@ enum SQRESULT : SQInteger
SQRESULT_NOTNULL = 1,
};
-typedef SQRESULT (*SQFunction)(void* sqvm);
+typedef SQRESULT (*SQFunction)(HSquirrelVM* sqvm);
enum class eSQReturnType
{
@@ -31,11 +32,13 @@ enum class eSQReturnType
};
const std::map<SQRESULT, const char*> PrintSQRESULT = {
- {SQRESULT_ERROR, "ERROR"},
- {SQRESULT_NULL, "NULL"},
- {SQRESULT_NOTNULL, "NOTNULL"}
+ {SQRESULT_ERROR, "SQRESULT_ERROR"},
+ {SQRESULT_NULL, "SQRESULT_NULL"},
+ {SQRESULT_NOTNULL, "SQRESULT_NOTNULL"}
};
+
+
struct CompileBufferState
{
const SQChar* buffer;
@@ -50,473 +53,6 @@ struct CompileBufferState
}
};
-struct CallInfo;
-struct SQTable;
-struct SQString;
-struct SQFunctionProto;
-struct SQClosure;
-struct SQSharedState;
-struct StringTable;
-struct SQStructInstance;
-struct SQStructDef;
-struct SQNativeClosure;
-struct SQArray;
-struct SQInstruction;
-
-/* 127 */
-enum SQObjectType : uint32_t
-{
- _RT_NULL = 0x1,
- _RT_INTEGER = 0x2,
- _RT_FLOAT = 0x4,
- _RT_BOOL = 0x8,
- _RT_STRING = 0x10,
- _RT_TABLE = 0x20,
- _RT_ARRAY = 0x40,
- _RT_USERDATA = 0x80,
- _RT_CLOSURE = 0x100,
- _RT_NATIVECLOSURE = 0x200,
- _RT_GENERATOR = 0x400,
- OT_USERPOINTER = 0x800,
- _RT_USERPOINTER = 0x800,
- _RT_THREAD = 0x1000,
- _RT_FUNCPROTO = 0x2000,
- _RT_CLASS = 0x4000,
- _RT_INSTANCE = 0x8000,
- _RT_WEAKREF = 0x10000,
- OT_VECTOR = 0x40000,
- SQOBJECT_CANBEFALSE = 0x1000000,
- OT_NULL = 0x1000001,
- OT_BOOL = 0x1000008,
- SQOBJECT_DELEGABLE = 0x2000000,
- SQOBJECT_NUMERIC = 0x4000000,
- OT_INTEGER = 0x5000002,
- OT_FLOAT = 0x5000004,
- SQOBJECT_REF_COUNTED = 0x8000000,
- OT_STRING = 0x8000010,
- OT_ARRAY = 0x8000040,
- OT_CLOSURE = 0x8000100,
- OT_NATIVECLOSURE = 0x8000200,
- OT_ASSET = 0x8000400,
- OT_THREAD = 0x8001000,
- OT_FUNCPROTO = 0x8002000,
- OT_CLAAS = 0x8004000,
- OT_STRUCT = 0x8200000,
- OT_WEAKREF = 0x8010000,
- OT_TABLE = 0xA000020,
- OT_USERDATA = 0xA000080,
- OT_INSTANCE = 0xA008000,
- OT_ENTITY = 0xA400000,
-};
-
-/* 156 */
-union alignas(8) SQObjectValue
-{
- SQString* asString;
- SQTable* asTable;
- SQClosure* asClosure;
- SQFunctionProto* asFuncProto;
- SQStructDef* asStructDef;
- uint64_t asInteger;
- SQStructInstance* asStructInstance;
- float asFloat;
- SQNativeClosure* asNativeClosure;
- SQArray* asArray;
-};
-
-/* 128 */
-struct alignas(8) SQObject
-{
- SQObjectType _Type;
- uint32_t _structOffset;
- SQObjectValue _VAL;
-};
-
-struct tableNode
-{
- SQObject val;
- SQObject key;
- tableNode* next;
-};
-
-/* 138 */
-struct alignas(8) SQString
-{
- void* vftable;
- uint32_t uiRef;
- uint32_t uiRef1;
- SQString* _next_maybe;
- SQSharedState* sharedState;
- uint32_t length;
- uint8_t gap_24[4];
- char _hash[8];
- char _val[1];
-};
-
-/* 137 */
-struct alignas(8) SQTable
-{
- void* vftable;
- uint8_t gap_08[4];
- uint32_t uiRef;
- uint8_t gap_10[8];
- void* pointer_18;
- void* pointer_20;
- void* _sharedState;
- uint64_t field_30;
- tableNode* _nodes;
- uint32_t _numOfNodes;
- uint32_t size;
- uint32_t field_48;
- uint32_t _usedNodes;
- uint8_t _gap_50[20];
- uint32_t field_64;
- uint8_t _gap_68[80];
-};
-
-/* 140 */
-struct alignas(8) SQClosure
-{
- void* vftable;
- uint8_t gap_08[4];
- uint32_t uiRef;
- void* pointer_10;
- void* pointer_18;
- void* pointer_20;
- void* sharedState;
- SQObject obj_30;
- SQObject _function;
- SQObject* _outervalues;
- uint8_t gap_58[8];
- uint8_t gap_60[96];
- SQObject* objectPointer_C0;
-};
-
-/* 139 */
-struct alignas(8) SQFunctionProto
-{
- void* vftable;
- uint8_t gap_08[4];
- uint32_t uiRef;
- uint8_t gap_10[8];
- void* pointer_18;
- void* pointer_20;
- void* sharedState;
- void* pointer_30;
- SQObject fileName;
- SQObject funcName;
- SQObject obj_58;
- uint8_t gap_68[64];
- uint32_t nParameters;
- uint8_t gap_AC[60];
- uint32_t nDefaultParams;
- uint8_t gap_EC[200];
-};
-
-/* 152 */
-struct SQStructDef
-{
- uint8_t gap_0[56];
- SQString* name;
- uint8_t gap_[300];
-};
-
-/* 150 */
-struct SQStructInstance
-{
- void* vftable;
- uint8_t gap_8[16];
- void* pointer_18;
- uint8_t gap_20[8];
- SQSharedState* _sharedState;
- uint8_t gap_30[8];
- SQObject data[1];
-};
-
-/* 157 */
-struct alignas(8) SQNativeClosure
-{
- void* vftable;
- uint8_t gap_08[4];
- uint32_t uiRef;
- uint8_t gap_10[88];
- SQString* _name;
- uint8_t gap_0[300];
-};
-
-/* 148 */
-struct SQSharedState
-{
- uint8_t gap_0[72];
- StringTable* _stringtable;
- uint8_t gap_50[30000];
-};
-
-/* 149 */
-struct StringTable
-{
- uint8_t gap_0[12];
- int _numofslots;
- uint8_t gap_10[200];
-};
-
-/* 129 */
-struct alignas(8) HSquirrelVM
-{
- void* vftable;
- uint32_t uiRef;
- uint8_t gap_8[12];
- void* _toString;
- void* _roottable_pointer;
- void* pointer_28;
- CallInfo* ci;
- CallInfo* _callsstack;
- uint32_t _callsstacksize;
- uint32_t _stackbase;
- SQObject* _stackOfCurrentFunction;
- SQSharedState* sharedState;
- void* pointer_58;
- void* pointer_60;
- uint32_t _top;
- SQObject* _stack;
- uint8_t gap_78[8];
- SQObject* _vargsstack;
- uint8_t gap_88[8];
- SQObject temp_reg;
- uint8_t gapA0[8];
- void* pointer_A8;
- uint8_t gap_B0[8];
- SQObject _roottable_object;
- SQObject _lasterror;
- SQObject _errorHandler;
- uint64_t field_E8;
- uint32_t traps;
- uint8_t gap_F4[12];
- uint32_t _nnativecalls;
- uint32_t _suspended;
- uint32_t _suspended_root;
- uint32_t _callstacksize;
- uint32_t _suspended_target;
- uint32_t field_114;
- uint32_t _suspend_varargs;
- SQObject* _object_pointer_120;
-};
-
-/* 136 */
-struct alignas(8) CallInfo
-{
- SQInstruction* ip;
- SQObject* _literals;
- SQObject obj10;
- SQObject closure;
- uint32_t _etraps[4];
- uint32_t _root;
- short _vargs_size;
- short _vargs_base;
-};
-
-/* 135 */
-enum SQOpcode : int
-{
- _OP_LOAD = 0x0,
- _OP_LOADCOPY = 0x1,
- _OP_LOADINT = 0x2,
- _OP_LOADFLOAT = 0x3,
- _OP_DLOAD = 0x4,
- _OP_TAILCALL = 0x5,
- _OP_CALL = 0x6,
- _OP_PREPCALL = 0x7,
- _OP_PREPCALLK = 0x8,
- _OP_GETK = 0x9,
- _OP_MOVE = 0xA,
- _OP_NEWSLOT = 0xB,
- _OP_DELETE = 0xC,
- _OP_SET = 0xD,
- _OP_GET = 0xE,
- _OP_EQ = 0xF,
- _OP_NE = 0x10,
- _OP_ARITH = 0x11,
- _OP_BITW = 0x12,
- _OP_RETURN = 0x13,
- _OP_LOADNULLS = 0x14,
- _OP_LOADROOTTABLE = 0x15,
- _OP_LOADBOOL = 0x16,
- _OP_DMOVE = 0x17,
- _OP_JMP = 0x18,
- _OP_JNZ = 0x19,
- _OP_JZ = 0x1A,
- _OP_LOADFREEVAR = 0x1B,
- _OP_VARGC = 0x1C,
- _OP_GETVARGV = 0x1D,
- _OP_NEWTABLE = 0x1E,
- _OP_NEWARRAY = 0x1F,
- _OP_APPENDARRAY = 0x20,
- _OP_GETPARENT = 0x21,
- _OP_COMPOUND_ARITH = 0x22,
- _OP_COMPOUND_ARITH_LOCAL = 0x23,
- _OP_INCREMENT_PREFIX = 0x24,
- _OP_INCREMENT_PREFIX_LOCAL = 0x25,
- _OP_INCREMENT_PREFIX_STRUCTFIELD = 0x26,
- _OP_INCREMENT_POSTFIX = 0x27,
- _OP_INCREMENT_POSTFIX_LOCAL = 0x28,
- _OP_INCREMENT_POSTFIX_STRUCTFIELD = 0x29,
- _OP_CMP = 0x2A,
- _OP_EXISTS = 0x2B,
- _OP_INSTANCEOF = 0x2C,
- _OP_NEG = 0x2D,
- _OP_NOT = 0x2E,
- _OP_BWNOT = 0x2F,
- _OP_CLOSURE = 0x30,
- _OP_FOREACH = 0x31,
- _OP_FOREACH_STATICARRAY_START = 0x32,
- _OP_FOREACH_STATICARRAY_NEXT = 0x33,
- _OP_FOREACH_STATICARRAY_NESTEDSTRUCT_START = 0x34,
- _OP_FOREACH_STATICARRAY_NESTEDSTRUCT_NEXT = 0x35,
- _OP_DELEGATE = 0x36,
- _OP_CLONE = 0x37,
- _OP_TYPEOF = 0x38,
- _OP_PUSHTRAP = 0x39,
- _OP_POPTRAP = 0x3A,
- _OP_THROW = 0x3B,
- _OP_CLASS = 0x3C,
- _OP_NEWSLOTA = 0x3D,
- _OP_EQ_LITERAL = 0x3E,
- _OP_NE_LITERAL = 0x3F,
- _OP_FOREACH_SETUP = 0x40,
- _OP_ASSERT_FAILED = 0x41,
- _OP_ADD = 0x42,
- _OP_SUB = 0x43,
- _OP_MUL = 0x44,
- _OP_DIV = 0x45,
- _OP_MOD = 0x46,
- _OP_PREPCALLK_CALL = 0x47,
- _OP_PREPCALLK_MOVE_CALL = 0x48,
- _OP_PREPCALLK_LOADINT_CALL = 0x49,
- _OP_CMP_JZ = 0x4A,
- _OP_INCREMENT_LOCAL_DISCARD_JMP = 0x4B,
- _OP_JZ_RETURN = 0x4C,
- _OP_JZ_LOADBOOL_RETURN = 0x4D,
- _OP_NEWVECTOR = 0x4E,
- _OP_ZEROVECTOR = 0x4F,
- _OP_GET_VECTOR_COMPONENT = 0x50,
- _OP_SET_VECTOR_COMPONENT = 0x51,
- _OP_VECTOR_COMPONENT_MINUSEQ = 0x52,
- _OP_VECTOR_COMPONENT_PLUSEQ = 0x53,
- _OP_VECTOR_COMPONENT_MULEQ = 0x54,
- _OP_VECTOR_COMPONENT_DIVEQ = 0x55,
- _OP_VECTOR_NORMALIZE = 0x56,
- _OP_VECTOR_NORMALIZE_IN_PLACE = 0x57,
- _OP_VECTOR_DOT_PRODUCT = 0x58,
- _OP_VECTOR_DOT_PRODUCT2D = 0x59,
- _OP_VECTOR_CROSS_PRODUCT = 0x5A,
- _OP_VECTOR_CROSS_PRODUCT2D = 0x5B,
- _OP_VECTOR_LENGTH = 0x5C,
- _OP_VECTOR_LENGTHSQR = 0x5D,
- _OP_VECTOR_LENGTH2D = 0x5E,
- _OP_VECTOR_LENGTH2DSQR = 0x5F,
- _OP_VECTOR_DISTANCE = 0x60,
- _OP_VECTOR_DISTANCESQR = 0x61,
- _OP_VECTOR_DISTANCE2D = 0x62,
- _OP_VECTOR_DISTANCE2DSQR = 0x63,
- _OP_INCREMENT_LOCAL_DISCARD = 0x64,
- _OP_FASTCALL = 0x65,
- _OP_FASTCALL_NATIVE = 0x66,
- _OP_FASTCALL_NATIVE_ARGTYPECHECK = 0x67,
- _OP_FASTCALL_ENV = 0x68,
- _OP_FASTCALL_NATIVE_ENV = 0x69,
- _OP_FASTCALL_NATIVE_ENV_ARGTYPECHECK = 0x6A,
- _OP_LOADGLOBALARRAY = 0x6B,
- _OP_GETGLOBAL = 0x6C,
- _OP_SETGLOBAL = 0x6D,
- _OP_COMPOUND_ARITH_GLOBAL = 0x6E,
- _OP_GETSTRUCTFIELD = 0x6F,
- _OP_SETSTRUCTFIELD = 0x70,
- _OP_COMPOUND_ARITH_STRUCTFIELD = 0x71,
- _OP_NEWSTRUCT = 0x72,
- _OP_GETSUBSTRUCT = 0x73,
- _OP_GETSUBSTRUCT_DYNAMIC = 0x74,
- _OP_TYPECAST = 0x75,
- _OP_TYPECHECK = 0x76,
- _OP_TYPECHECK_ORNULL = 0x77,
- _OP_TYPECHECK_NOTNULL = 0x78,
- _OP_CHECK_ENTITY_CLASS = 0x79,
- _OP_UNREACHABLE = 0x7A,
- _OP_ARRAY_RESIZE = 0x7B,
-};
-
-/* 141 */
-struct alignas(8) SQStackInfos
-{
- char* _name;
- char* _sourceName;
- uint32_t _line;
-};
-
-/* 151 */
-struct alignas(4) SQInstruction
-{
- int op;
- int arg1;
- int output;
- uint16_t arg2;
- uint16_t arg3;
-};
-
-/* 154 */
-struct SQLexer
-{
- uint8_t gap_0[112];
-};
-
-/* 153 */
-struct SQCompiler
-{
- uint8_t gap_0[4];
- uint32_t _token;
- uint8_t gap_8[8];
- SQObject object_10;
- SQLexer lexer;
- uint8_t gap_1[768];
-};
-
-/* 155 */
-struct CSquirrelVM
-{
- uint8_t gap_0[8];
- HSquirrelVM* sqvm;
-};
-
-struct SQVector
-{
- SQObjectType _Type;
- float x;
- float y;
- float z;
-};
-
-struct SQArray
-{
- void* vftable;
- uint32_t uiRef;
- uint8_t gap_24[36];
- SQObject* _values;
- uint32_t _usedSlots;
- uint32_t _allocated;
-};
-
-#define SQOBJ_INCREMENT_REFERENCECOUNT(val) \
- if ((val->_Type & SQOBJECT_REF_COUNTED) != 0) \
- ++val->_VAL.asString->uiRef;
-
-#define SQOBJ_DECREMENT_REFERENCECOUNT(val) \
- if ((val->_Type & SQOBJECT_REF_COUNTED) != 0) \
- { \
- if (val->_VAL.asString->uiRef-- == 1) \
- { \
- spdlog::info("Deleted SQObject of type {} with address {:X}", sq_getTypeName(val->_Type), val->_VAL.asInteger); \
- (*(void(__fastcall**)(SQString*))(&val->_VAL.asString->vftable[1]))(val->_VAL.asString); \
- } \
- }
struct SQFuncRegistration
{
@@ -534,7 +70,7 @@ struct SQFuncRegistration
uint64_t externalBufferSize;
uint64_t unknown3;
uint64_t unknown4;
- void* funcPtr;
+ SQFunction funcPtr;
SQFuncRegistration()
{
@@ -555,35 +91,44 @@ eSQReturnType SQReturnTypeFromString(const char* pReturnType);
const char* SQTypeNameFromID(const int iTypeId);
// core sqvm funcs
-typedef int64_t (*RegisterSquirrelFuncType)(void* sqvm, SQFuncRegistration* funcReg, char unknown);
-typedef void (*sq_defconstType)(void* sqvm, const SQChar* name, int value);
+typedef int64_t (*RegisterSquirrelFuncType)(CSquirrelVM* sqvm, SQFuncRegistration* funcReg, char unknown);
+typedef void (*sq_defconstType)(CSquirrelVM* sqvm, const SQChar* name, int value);
-typedef SQRESULT (*sq_compilebufferType)(void* sqvm, CompileBufferState* compileBuffer, const char* file, int a1, SQBool bShouldThrowError);
-typedef SQRESULT (*sq_callType)(void* sqvm, SQInteger iArgs, SQBool bShouldReturn, SQBool bThrowError);
-typedef SQInteger (*sq_raiseerrorType)(void* sqvm, const SQChar* pError);
+typedef SQRESULT (*sq_compilebufferType)(HSquirrelVM* sqvm, CompileBufferState* compileBuffer, const char* file, int a1, SQBool bShouldThrowError);
+typedef SQRESULT (*sq_callType)(HSquirrelVM* sqvm, SQInteger iArgs, SQBool bShouldReturn, SQBool bThrowError);
+typedef SQInteger (*sq_raiseerrorType)(HSquirrelVM* sqvm, const SQChar* pError);
// sq stack array funcs
-typedef void (*sq_newarrayType)(void* sqvm, SQInteger iStackpos);
-typedef SQRESULT (*sq_arrayappendType)(void* sqvm, SQInteger iStackpos);
+typedef void (*sq_newarrayType)(HSquirrelVM* sqvm, SQInteger iStackpos);
+typedef SQRESULT (*sq_arrayappendType)(HSquirrelVM* sqvm, SQInteger iStackpos);
// sq table funcs
-typedef SQRESULT (*sq_newtableType)(void* sqvm);
-typedef SQRESULT (*sq_newslotType)(void* sqvm, SQInteger idx, SQBool bStatic);
+typedef SQRESULT (*sq_newtableType)(HSquirrelVM* sqvm);
+typedef SQRESULT (*sq_newslotType)(HSquirrelVM* sqvm, SQInteger idx, SQBool bStatic);
// sq stack push funcs
-typedef void (*sq_pushroottableType)(void* sqvm);
-typedef void (*sq_pushstringType)(void* sqvm, const SQChar* pStr, SQInteger iLength);
-typedef void (*sq_pushintegerType)(void* sqvm, SQInteger i);
-typedef void (*sq_pushfloatType)(void* sqvm, SQFloat f);
-typedef void (*sq_pushboolType)(void* sqvm, SQBool b);
-typedef void (*sq_pushAssetType)(void* sqvm, const SQChar* pName, SQInteger iLength);
+typedef void (*sq_pushroottableType)(HSquirrelVM* sqvm);
+typedef void (*sq_pushstringType)(HSquirrelVM* sqvm, const SQChar* pStr, SQInteger iLength);
+typedef void (*sq_pushintegerType)(HSquirrelVM* sqvm, SQInteger i);
+typedef void (*sq_pushfloatType)(HSquirrelVM* sqvm, SQFloat f);
+typedef void (*sq_pushboolType)(HSquirrelVM* sqvm, SQBool b);
+typedef void (*sq_pushassetType)(HSquirrelVM* sqvm, const SQChar* str, SQInteger iLength);
+typedef void (*sq_pushvectorType)(HSquirrelVM* sqvm, const SQFloat* pVec);
+
// sq stack get funcs
-typedef const SQChar* (*sq_getstringType)(void* sqvm, SQInteger stackpos);
-typedef SQInteger (*sq_getintegerType)(void* sqvm, SQInteger stackpos);
-typedef SQFloat (*sq_getfloatType)(void*, SQInteger stackpos);
-typedef SQBool (*sq_getboolType)(void*, SQInteger stackpos);
-typedef SQRESULT (*sq_getType)(void* sqvm, SQInteger stackpos);
+typedef const SQChar* (*sq_getstringType)(HSquirrelVM* sqvm, SQInteger iStackpos);
+typedef SQInteger (*sq_getintegerType)(HSquirrelVM* sqvm, SQInteger iStackpos);
+typedef SQFloat (*sq_getfloatType)(HSquirrelVM*, SQInteger iStackpos);
+typedef SQBool (*sq_getboolType)(HSquirrelVM*, SQInteger iStackpos);
+typedef SQRESULT (*sq_getType)(HSquirrelVM* sqvm, SQInteger iStackpos);
+typedef SQRESULT (*sq_getassetType)(HSquirrelVM* sqvm, SQInteger iStackpos, const char** pResult);
+typedef SQRESULT (*sq_getuserdataType)(HSquirrelVM* sqvm, SQInteger iStackpos, void** pData, long long* pTypeId);
+typedef SQFloat* (*sq_getvectorType)(HSquirrelVM* sqvm, SQInteger iStackpos);
+
+// sq stack userpointer funcs
+typedef void* (*sq_createuserdataType)(HSquirrelVM* sqvm, SQInteger iSize);
+typedef SQRESULT (*sq_setuserdatatypeidType)(HSquirrelVM* sqvm, SQInteger iStackpos, long long iTypeId);
template <ScriptContext context> class SquirrelManager
{
@@ -591,8 +136,10 @@ template <ScriptContext context> class SquirrelManager
std::vector<SQFuncRegistration*> m_funcRegistrations;
public:
- void* sqvm;
- void* sqvm2;
+ CSquirrelVM* SquirrelVM;
+ HSquirrelVM* sqvm;
+ std::map<std::string, SQFunction> m_funcOverrides = {};
+ std::map<std::string, SQFunction> m_funcOriginals = {};
bool m_bCompilationErrorsFatal = false;
@@ -615,120 +162,160 @@ template <ScriptContext context> class SquirrelManager
sq_pushintegerType __sq_pushinteger;
sq_pushfloatType __sq_pushfloat;
sq_pushboolType __sq_pushbool;
- sq_pushAssetType __sq_pushasset;
+ sq_pushassetType __sq_pushasset;
+ sq_pushvectorType __sq_pushvector;
sq_getstringType __sq_getstring;
sq_getintegerType __sq_getinteger;
sq_getfloatType __sq_getfloat;
sq_getboolType __sq_getbool;
sq_getType __sq_get;
- #pragma endregion
+ sq_getassetType __sq_getasset;
+ sq_getuserdataType __sq_getuserdata;
+ sq_getvectorType __sq_getvector;
+
+ sq_createuserdataType __sq_createuserdata;
+ sq_setuserdatatypeidType __sq_setuserdatatypeid;
+#pragma endregion
public:
- SquirrelManager() : sqvm(nullptr) {}
+ SquirrelManager() : SquirrelVM(nullptr) {}
- void VMCreated(void* newSqvm);
+ void VMCreated(CSquirrelVM* newSqvm);
void VMDestroyed();
void ExecuteCode(const char* code);
void AddFuncRegistration(std::string returnType, std::string name, std::string argTypes, std::string helpText, SQFunction func);
SQRESULT setupfunc(const SQChar* funcname);
+ void AddFuncOverride(std::string name, SQFunction func);
#pragma region SQVM func wrappers
- inline void defconst(void* sqvm, const SQChar* pName, int nValue)
+ inline void defconst(CSquirrelVM* sqvm, const SQChar* pName, int nValue)
{
__sq_defconst(sqvm, pName, nValue);
}
- inline SQRESULT compilebuffer(CompileBufferState* bufferState, const SQChar* bufferName = "unnamedbuffer", const SQBool bShouldThrowError = false)
+ inline SQRESULT
+ compilebuffer(CompileBufferState* bufferState, const SQChar* bufferName = "unnamedbuffer", const SQBool bShouldThrowError = false)
{
- return __sq_compilebuffer(sqvm2, bufferState, bufferName, -1, bShouldThrowError);
+ return __sq_compilebuffer(sqvm, bufferState, bufferName, -1, bShouldThrowError);
}
- inline SQRESULT call(void* sqvm, const SQInteger args)
+ inline SQRESULT call(HSquirrelVM* sqvm, const SQInteger args)
{
return __sq_call(sqvm, args + 1, false, false);
}
- inline SQInteger raiseerror(void* sqvm, const const SQChar* sError)
+ inline SQInteger raiseerror(HSquirrelVM* sqvm, const const SQChar* sError)
{
return __sq_raiseerror(sqvm, sError);
}
- inline void newarray(void* sqvm, const SQInteger stackpos = 0)
+ inline void newarray(HSquirrelVM* sqvm, const SQInteger stackpos = 0)
{
__sq_newarray(sqvm, stackpos);
}
- inline SQRESULT arrayappend(void* sqvm, const SQInteger stackpos)
+ inline SQRESULT arrayappend(HSquirrelVM* sqvm, const SQInteger stackpos)
{
return __sq_arrayappend(sqvm, stackpos);
}
- inline SQRESULT newtable(void* sqvm)
+ inline SQRESULT newtable(HSquirrelVM* sqvm)
{
return __sq_newtable(sqvm);
}
- inline SQRESULT newslot(void* sqvm, SQInteger idx, SQBool bStatic)
+ inline SQRESULT newslot(HSquirrelVM* sqvm, SQInteger idx, SQBool bStatic)
{
return __sq_newslot(sqvm, idx, bStatic);
}
- inline void pushroottable(void* sqvm)
+ inline void pushroottable(HSquirrelVM* sqvm)
{
__sq_pushroottable(sqvm);
}
- inline void pushstring(void* sqvm, const SQChar* sVal, int length = -1)
+ inline void pushstring(HSquirrelVM* sqvm, const SQChar* sVal, int length = -1)
{
__sq_pushstring(sqvm, sVal, length);
}
- inline void pushinteger(void* sqvm, const SQInteger iVal)
+ inline void pushinteger(HSquirrelVM* sqvm, const SQInteger iVal)
{
__sq_pushinteger(sqvm, iVal);
}
- inline void pushfloat(void* sqvm, const SQFloat flVal)
+ inline void pushfloat(HSquirrelVM* sqvm, const SQFloat flVal)
{
__sq_pushfloat(sqvm, flVal);
}
- inline void pushbool(void* sqvm, const SQBool bVal)
+ inline void pushbool(HSquirrelVM* sqvm, const SQBool bVal)
{
__sq_pushbool(sqvm, bVal);
}
- inline void pushasset(void* sqvm, const SQChar* sVal, int length = -1)
+ inline void pushasset(HSquirrelVM* sqvm, const SQChar* sVal, int length = -1)
{
__sq_pushasset(sqvm, sVal, length);
}
+ inline void pushvector(HSquirrelVM* sqvm, const SQFloat* pVal)
+ {
+ __sq_pushvector(sqvm, pVal);
+ }
- inline const SQChar* getstring(void* sqvm, const SQInteger stackpos)
+ inline const SQChar* getstring(HSquirrelVM* sqvm, const SQInteger stackpos)
{
return __sq_getstring(sqvm, stackpos);
}
- inline SQInteger getinteger(void* sqvm, const SQInteger stackpos)
+ inline SQInteger getinteger(HSquirrelVM* sqvm, const SQInteger stackpos)
{
return __sq_getinteger(sqvm, stackpos);
}
- inline SQFloat getfloat(void* sqvm, const SQInteger stackpos)
+ inline SQFloat getfloat(HSquirrelVM* sqvm, const SQInteger stackpos)
{
return __sq_getfloat(sqvm, stackpos);
}
- inline SQBool getbool(void* sqvm, const SQInteger stackpos)
+ inline SQBool getbool(HSquirrelVM* sqvm, const SQInteger stackpos)
{
return __sq_getbool(sqvm, stackpos);
}
- inline SQRESULT get(void* sqvm, const SQInteger stackpos)
+ inline SQRESULT get(HSquirrelVM* sqvm, const SQInteger stackpos)
{
return __sq_get(sqvm, stackpos);
}
- #pragma endregion
+
+ inline SQFloat* getvector(HSquirrelVM* sqvm, const SQInteger stackpos)
+ {
+ return __sq_getvector(sqvm, stackpos);
+ }
+
+ inline SQRESULT getasset(HSquirrelVM* sqvm, const SQInteger stackpos, const char** result)
+ {
+ return __sq_getasset(sqvm, stackpos, result);
+ }
+
+ inline SQRESULT getuserdata(HSquirrelVM* sqvm, const SQInteger stackpos, void** data, long long* typeId)
+ {
+ return __sq_getuserdata(sqvm, stackpos, data, typeId); // this sometimes crashes idk
+ }
+
+ inline void* createuserdata(HSquirrelVM* sqvm, SQInteger size)
+ {
+ void* ret = __sq_createuserdata(sqvm, size);
+ memset(ret, 0, size);
+ return ret;
+ }
+
+ SQRESULT setuserdatatypeid(HSquirrelVM* sqvm, const SQInteger stackpos, long long typeId)
+ {
+ return __sq_setuserdatatypeid(sqvm, stackpos, typeId);
+ }
+#pragma endregion
};
template <ScriptContext context> SquirrelManager<context>* g_pSquirrel;
diff --git a/NorthstarDLL/squirreldatatypes.h b/NorthstarDLL/squirreldatatypes.h
new file mode 100644
index 00000000..95d079bf
--- /dev/null
+++ b/NorthstarDLL/squirreldatatypes.h
@@ -0,0 +1,484 @@
+#pragma once
+/*
+ This file has been generated by IDA.
+ It contains local type definitions from
+ the type library 'server.dll'
+*/
+
+struct HSquirrelVM;
+struct CallInfo;
+struct SQTable;
+struct SQString;
+struct SQFunctionProto;
+struct SQClosure;
+struct SQSharedState;
+struct StringTable;
+struct SQStructInstance;
+struct SQStructDef;
+struct SQNativeClosure;
+struct SQArray;
+struct tableNode;
+struct SQUserData;
+
+typedef void (*releasehookType)(void* val, int size);
+
+/* 127 */
+enum SQObjectType : int
+{
+ _RT_NULL = 0x1,
+ _RT_INTEGER = 0x2,
+ _RT_FLOAT = 0x4,
+ _RT_BOOL = 0x8,
+ _RT_STRING = 0x10,
+ _RT_TABLE = 0x20,
+ _RT_ARRAY = 0x40,
+ _RT_USERDATA = 0x80,
+ _RT_CLOSURE = 0x100,
+ _RT_NATIVECLOSURE = 0x200,
+ _RT_GENERATOR = 0x400,
+ OT_USERPOINTER = 0x800,
+ _RT_USERPOINTER = 0x800,
+ _RT_THREAD = 0x1000,
+ _RT_FUNCPROTO = 0x2000,
+ _RT_CLASS = 0x4000,
+ _RT_INSTANCE = 0x8000,
+ _RT_WEAKREF = 0x10000,
+ OT_VECTOR = 0x40000,
+ SQOBJECT_CANBEFALSE = 0x1000000,
+ OT_NULL = 0x1000001,
+ OT_BOOL = 0x1000008,
+ SQOBJECT_DELEGABLE = 0x2000000,
+ SQOBJECT_NUMERIC = 0x4000000,
+ OT_INTEGER = 0x5000002,
+ OT_FLOAT = 0x5000004,
+ SQOBJECT_REF_COUNTED = 0x8000000,
+ OT_STRING = 0x8000010,
+ OT_ARRAY = 0x8000040,
+ OT_CLOSURE = 0x8000100,
+ OT_NATIVECLOSURE = 0x8000200,
+ OT_ASSET = 0x8000400,
+ OT_THREAD = 0x8001000,
+ OT_FUNCPROTO = 0x8002000,
+ OT_CLAAS = 0x8004000,
+ OT_STRUCT = 0x8200000,
+ OT_WEAKREF = 0x8010000,
+ OT_TABLE = 0xA000020,
+ OT_USERDATA = 0xA000080,
+ OT_INSTANCE = 0xA008000,
+ OT_ENTITY = 0xA400000,
+};
+
+/* 156 */
+union SQObjectValue
+{
+ SQString* asString;
+ SQTable* asTable;
+ SQClosure* asClosure;
+ SQFunctionProto* asFuncProto;
+ SQStructDef* asStructDef;
+ long long as64Integer;
+ SQNativeClosure* asNativeClosure;
+ SQArray* asArray;
+ HSquirrelVM* asThread;
+ float asFloat;
+ int asInteger;
+ SQUserData* asUserdata;
+};
+
+/* 160 */
+struct SQVector
+{
+ SQObjectType _Type;
+ float x;
+ float y;
+ float z;
+};
+
+/* 128 */
+struct SQObject
+{
+ SQObjectType _Type;
+ int structNumber;
+ SQObjectValue _VAL;
+};
+
+/* 138 */
+struct __declspec(align(8)) SQString
+{
+ void* vftable;
+ int uiRef;
+ int padding;
+ SQString* _next_maybe;
+ SQSharedState* sharedState;
+ int length;
+ unsigned char gap_24[4];
+ char _hash[8];
+ char _val[1];
+};
+
+/* 137 */
+struct __declspec(align(8)) SQTable
+{
+ void* vftable;
+ unsigned char gap_08[4];
+ int uiRef;
+ unsigned char gap_10[8];
+ void* pointer_18;
+ void* pointer_20;
+ void* _sharedState;
+ long long field_30;
+ tableNode* _nodes;
+ int _numOfNodes;
+ int size;
+ int field_48;
+ int _usedNodes;
+ unsigned char _gap_50[20];
+ int field_64;
+ unsigned char _gap_68[80];
+};
+
+/* 140 */
+struct __declspec(align(8)) SQClosure
+{
+ void* vftable;
+ unsigned char gap_08[4];
+ int uiRef;
+ void* pointer_10;
+ void* pointer_18;
+ void* pointer_20;
+ void* sharedState;
+ SQObject obj_30;
+ SQObject _function;
+ SQObject* _outervalues;
+ unsigned char gap_58[8];
+ unsigned char gap_60[96];
+ SQObject* objectPointer_C0;
+ unsigned char gap_C8[16];
+};
+
+/* 139 */
+struct __declspec(align(8)) SQFunctionProto
+{
+ void* vftable;
+ unsigned char gap_08[4];
+ int uiRef;
+ unsigned char gap_10[8];
+ void* pointer_18;
+ void* pointer_20;
+ void* sharedState;
+ void* pointer_30;
+ SQObjectType _fileNameType;
+ SQString* _fileName;
+ SQObjectType _funcNameType;
+ SQString* _funcName;
+ SQObject obj_58;
+ unsigned char gap_68[12];
+ int _stacksize;
+ unsigned char gap_78[48];
+ int nParameters;
+ unsigned char gap_AC[60];
+ int nDefaultParams;
+ unsigned char gap_EC[200];
+};
+
+/* 152 */
+struct SQStructDef
+{
+ void* vtable;
+ int uiRef;
+ unsigned char padding_C[4];
+ unsigned char unknown[24];
+ SQSharedState* sharedState;
+ SQObjectType _nameType;
+ SQString* _name;
+ unsigned char gap_38[16];
+ SQObjectType _variableNamesType;
+ SQTable* _variableNames;
+ unsigned char gap_[32];
+};
+
+/* 157 */
+struct __declspec(align(8)) SQNativeClosure
+{
+ void* vftable;
+ int uiRef;
+ unsigned char gap_C[4];
+ long long value_10;
+ long long value_18;
+ long long value_20;
+ SQSharedState* sharedState;
+ char unknown_30;
+ unsigned char padding_34[7];
+ long long value_38;
+ long long value_40;
+ long long value_48;
+ long long value_50;
+ long long value_58;
+ SQObjectType _nameType;
+ SQString* _name;
+ long long value_70;
+ long long value_78;
+ unsigned char justInCaseGap_80[300];
+};
+
+/* 162 */
+struct SQArray
+{
+ void* vftable;
+ int uiRef;
+ unsigned char gap_24[36];
+ SQObject* _values;
+ int _usedSlots;
+ int _allocated;
+};
+
+/* 129 */
+struct __declspec(align(8)) HSquirrelVM
+{
+ void* vftable;
+ int uiRef;
+ unsigned char gap_8[12];
+ void* _toString;
+ void* _roottable_pointer;
+ void* pointer_28;
+ CallInfo* ci;
+ CallInfo* _callstack;
+ int _callsstacksize;
+ int _stackbase;
+ SQObject* _stackOfCurrentFunction;
+ SQSharedState* sharedState;
+ void* pointer_58;
+ void* pointer_60;
+ int _top;
+ SQObject* _stack;
+ unsigned char gap_78[8];
+ SQObject* _vargvstack;
+ unsigned char gap_88[8];
+ SQObject temp_reg;
+ unsigned char gapA0[8];
+ void* pointer_A8;
+ unsigned char gap_B0[8];
+ SQObject _roottable_object;
+ SQObject _lasterror;
+ SQObject _errorHandler;
+ long long field_E8;
+ int traps;
+ unsigned char gap_F4[12];
+ int _nnativecalls;
+ int _suspended;
+ int _suspended_root;
+ int _callstacksize;
+ int _suspended_target;
+ int trapAmount;
+ int _suspend_varargs;
+ int unknown_field_11C;
+ SQObject object_120;
+};
+
+/* 150 */
+struct SQStructInstance
+{
+ void* vftable;
+ unsigned char gap_8[16];
+ void* pointer_18;
+ unsigned char gap_20[8];
+ SQSharedState* _sharedState;
+ unsigned char gap[8];
+ SQObject data[20];
+};
+
+/* 148 */
+struct SQSharedState
+{
+ unsigned char gap_0[72];
+ void* unknown;
+ unsigned char gap_50[16344];
+ SQObjectType _unknownTableType00;
+ long long _unknownTableValue00;
+ unsigned char gap_4038[16];
+ StringTable* _stringTable;
+ unsigned char gap_4050[32];
+ SQObjectType _unknownTableType0;
+ long long _unknownTableValue0;
+ SQObjectType _unknownObjectType1;
+ long long _unknownObjectValue1;
+ unsigned char gap_4090[8];
+ SQObjectType _unknownArrayType2;
+ long long _unknownArrayValue2;
+ SQObjectType _gobalsArrayType;
+ SQStructInstance* _globalsArray;
+ unsigned char gap_40B8[16];
+ SQObjectType _nativeClosuresType;
+ SQTable* _nativeClosures;
+ SQObjectType _typedConstantsType;
+ SQTable* _typedConstants;
+ SQObjectType _untypedConstantsType;
+ SQTable* _untypedConstants;
+ SQObjectType _globalsMaybeType;
+ SQTable* _globals;
+ SQObjectType _functionsType;
+ SQTable* _functions;
+ SQObjectType _structsType;
+ SQTable* _structs;
+ SQObjectType _typeDefsType;
+ SQTable* _typeDefs;
+ SQObjectType unknownTableType;
+ SQTable* unknownTable;
+ SQObjectType _squirrelFilesType;
+ SQTable* _squirrelFiles;
+ unsigned char gap_4158[80];
+ SQObjectType _nativeClosures2Type;
+ SQTable* _nativeClosures2;
+ SQObjectType _entityTypesMaybeType;
+ SQTable* _entityTypesMaybe;
+ SQObjectType unknownTable2Type;
+ SQTable* unknownTable2;
+ unsigned char gap_41D8[72];
+ SQObjectType _compilerKeywordsType;
+ SQTable* _compilerKeywords;
+ HSquirrelVM* _currentThreadMaybe;
+ unsigned char gap_4238[8];
+ SQObjectType unknownTable3Type;
+ SQTable* unknownTable3;
+ unsigned char gap_4250[16];
+ SQObjectType unknownThreadType;
+ SQTable* unknownThread;
+ SQObjectType _tableNativeFunctionsType;
+ SQTable* _tableNativeFunctions;
+ SQObjectType _unknownTableType4;
+ long long _unknownObjectValue4;
+ SQObjectType _unknownObjectType5;
+ long long _unknownObjectValue5;
+ SQObjectType _unknownObjectType6;
+ long long _unknownObjectValue6;
+ SQObjectType _unknownObjectType7;
+ long long _unknownObjectValue7;
+ SQObjectType _unknownObjectType8;
+ long long _unknownObjectValue8;
+ SQObjectType _unknownObjectType9;
+ long long _unknownObjectValue9;
+ SQObjectType _unknownObjectType10;
+ long long _unknownObjectValue10;
+ SQObjectType _unknownObjectType11;
+ long long _unknownObjectValue11;
+ SQObjectType _unknownObjectType12;
+ long long _unknownObjectValue12;
+ SQObjectType _unknownObjectType13;
+ long long _unknownObjectValue13;
+ SQObjectType _unknownObjectType14;
+ long long _unknownObjectValue14;
+ SQObjectType _unknownObjectType15;
+ long long _unknownObjectValue15;
+ unsigned char gap_4340[16];
+ void* printFunction;
+ unsigned char gap_4358[16];
+ void* logEntityFunction;
+ unsigned char gap_4370[40];
+ SQObjectType _waitStringType;
+ SQString* _waitStringValue;
+ SQObjectType _SpinOffAndWaitForStringType;
+ SQString* _SpinOffAndWaitForStringValue;
+ SQObjectType _SpinOffAndWaitForSoloStringType;
+ SQString* _SpinOffAndWaitForSoloStringValue;
+ SQObjectType _SpinOffStringType;
+ SQString* _SpinOffStringValue;
+ SQObjectType _SpinOffDelayedStringType;
+ SQString* _SpinOffDelayedStringValue;
+ unsigned char gap_43E8[8];
+ bool enableDebugInfo; // functionality stripped
+ unsigned char gap_43F1[23];
+};
+
+/* 165 */
+struct tableNode
+{
+ SQObject val;
+ SQObject key;
+ tableNode* next;
+};
+
+/* 136 */
+struct __declspec(align(8)) CallInfo
+{
+ long long ip;
+ SQObject* _literals;
+ SQObject obj10;
+ SQObject closure;
+ int _etraps[4];
+ int _root;
+ short _vargs_size;
+ short _vargs_base;
+ unsigned char gap[16];
+};
+
+/* 149 */
+struct StringTable
+{
+ unsigned char gap_0[12];
+ int _numofslots;
+ unsigned char gap_10[200];
+};
+
+/* 141 */
+struct __declspec(align(8)) SQStackInfos
+{
+ char* _name;
+ char* _sourceName;
+ int _line;
+};
+
+/* 151 */
+struct __declspec(align(4)) SQInstruction
+{
+ int op;
+ int arg1;
+ int output;
+ short arg2;
+ short arg3;
+};
+
+/* 154 */
+struct SQLexer
+{
+ unsigned char gap_0[112];
+};
+
+/* 153 */
+struct SQCompiler
+{
+ unsigned char gap_0[4];
+ int _token;
+ unsigned char gap_8[8];
+ SQObject object_10;
+ SQLexer lexer;
+ unsigned char gap_90[752];
+ HSquirrelVM* sqvm;
+ unsigned char gap_288[8];
+};
+
+/* 155 */
+struct CSquirrelVM
+{
+ unsigned char gap_0[8];
+ HSquirrelVM* sqvm;
+ unsigned char gap_10[44];
+ int loadEnumFromFileMaybe;
+ unsigned char gap_40[200];
+};
+
+struct SQUserData
+{
+ void* vftable;
+ int uiRef;
+ char gap_12[4];
+ long long unknown_10;
+ long long unknown_18;
+ long long unknown_20;
+ long long sharedState;
+ long long unknown_30;
+ int size;
+ char padding1[4];
+ releasehookType releaseHook;
+ long long typeId;
+ char data[1];
+};