diff options
author | Maya <malte.hoermeyer@web.de> | 2022-08-23 03:54:54 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-23 02:54:54 +0100 |
commit | 4f6f182d26094b7b7512d656b5085f80e8af3dc9 (patch) | |
tree | 0a30acbb9c3f47f67887834620e5c182b7b46e09 /NorthstarDLL | |
parent | 86ea43ef2c32104f92e12c80231ff9271ebeb6e2 (diff) | |
download | NorthstarLauncher-4f6f182d26094b7b7512d656b5085f80e8af3dc9.tar.gz NorthstarLauncher-4f6f182d26094b7b7512d656b5085f80e8af3dc9.zip |
Add ability to load Datatables from files (#238)
* first version of kinda working custom datatables
* Fix copy error
* Finish custom datatables
* Fix Merge
* Fix line endings
* Add fallback to rpak when ns_prefere_datatable_from_disk is true
* fix typo
* Bug fixess
* Fix Function Registration hook
* Set convar value
* Fix Client and Ui VM
* enable server auth with ms agian
* Add Filters
* FIx unused import
* Merge remote-tracking branch 'upsteam/bobs-big-refactor-pr' into datatables
Co-authored-by: RoyalBlue1 <realEmail@veryRealURL.com>
Diffstat (limited to 'NorthstarDLL')
-rw-r--r-- | NorthstarDLL/NorthstarDLL.vcxproj | 4 | ||||
-rw-r--r-- | NorthstarDLL/NorthstarDLL.vcxproj.filters | 26 | ||||
-rw-r--r-- | NorthstarDLL/clientchathooks.cpp | 18 | ||||
-rw-r--r-- | NorthstarDLL/filesystem.h | 3 | ||||
-rw-r--r-- | NorthstarDLL/masterserver.cpp | 1 | ||||
-rw-r--r-- | NorthstarDLL/misccommands.cpp | 2 | ||||
-rw-r--r-- | NorthstarDLL/miscserverscript.cpp | 8 | ||||
-rw-r--r-- | NorthstarDLL/plugins.cpp | 14 | ||||
-rw-r--r-- | NorthstarDLL/rpakfilesystem.cpp | 9 | ||||
-rw-r--r-- | NorthstarDLL/rpakfilesystem.h | 77 | ||||
-rw-r--r-- | NorthstarDLL/scriptdatatables.cpp | 923 | ||||
-rw-r--r-- | NorthstarDLL/scriptjson.cpp | 12 | ||||
-rw-r--r-- | NorthstarDLL/scriptmainmenupromos.cpp | 6 | ||||
-rw-r--r-- | NorthstarDLL/scriptmodmenu.cpp | 20 | ||||
-rw-r--r-- | NorthstarDLL/scriptserverbrowser.cpp | 48 | ||||
-rw-r--r-- | NorthstarDLL/scriptservertoclientstringcommand.cpp | 6 | ||||
-rw-r--r-- | NorthstarDLL/scriptutility.cpp | 2 | ||||
-rw-r--r-- | NorthstarDLL/serverchathooks.cpp | 12 | ||||
-rw-r--r-- | NorthstarDLL/squirrel.cpp | 258 | ||||
-rw-r--r-- | NorthstarDLL/squirrel.h | 625 | ||||
-rw-r--r-- | NorthstarDLL/squirreldatatypes.h | 484 |
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]; +}; |