aboutsummaryrefslogtreecommitdiff
path: root/NorthstarDLL/scripts
diff options
context:
space:
mode:
authorJack <66967891+ASpoonPlaysGames@users.noreply.github.com>2023-12-27 00:32:01 +0000
committerGitHub <noreply@github.com>2023-12-27 01:32:01 +0100
commitf5ab6fb5e8be7b73e6003d4145081d5e0c0ce287 (patch)
tree90f2c6a4885dbd181799e2325cf33588697674e1 /NorthstarDLL/scripts
parentbb8ed59f6891b1196c5f5bbe7346cd171c8215fa (diff)
downloadNorthstarLauncher-f5ab6fb5e8be7b73e6003d4145081d5e0c0ce287.tar.gz
NorthstarLauncher-f5ab6fb5e8be7b73e6003d4145081d5e0c0ce287.zip
Folder restructuring from primedev (#624)v1.21.2-rc3v1.21.2
Copies of over the primedev folder structure for easier cherry-picking of further changes Co-authored-by: F1F7Y <filip.bartos07@proton.me>
Diffstat (limited to 'NorthstarDLL/scripts')
-rw-r--r--NorthstarDLL/scripts/client/clientchathooks.cpp72
-rw-r--r--NorthstarDLL/scripts/client/cursorposition.cpp22
-rw-r--r--NorthstarDLL/scripts/client/scriptbrowserhooks.cpp24
-rw-r--r--NorthstarDLL/scripts/client/scriptmainmenupromos.cpp123
-rw-r--r--NorthstarDLL/scripts/client/scriptmodmenu.cpp165
-rw-r--r--NorthstarDLL/scripts/client/scriptoriginauth.cpp35
-rw-r--r--NorthstarDLL/scripts/client/scriptserverbrowser.cpp209
-rw-r--r--NorthstarDLL/scripts/client/scriptservertoclientstringcommand.cpp18
-rw-r--r--NorthstarDLL/scripts/scriptdatatables.cpp909
-rw-r--r--NorthstarDLL/scripts/scripthttprequesthandler.cpp585
-rw-r--r--NorthstarDLL/scripts/scripthttprequesthandler.h130
-rw-r--r--NorthstarDLL/scripts/scriptjson.cpp250
-rw-r--r--NorthstarDLL/scripts/scriptjson.h13
-rw-r--r--NorthstarDLL/scripts/scriptutility.cpp28
-rw-r--r--NorthstarDLL/scripts/server/miscserverfixes.cpp6
-rw-r--r--NorthstarDLL/scripts/server/miscserverscript.cpp100
-rw-r--r--NorthstarDLL/scripts/server/scriptuserinfo.cpp104
17 files changed, 0 insertions, 2793 deletions
diff --git a/NorthstarDLL/scripts/client/clientchathooks.cpp b/NorthstarDLL/scripts/client/clientchathooks.cpp
deleted file mode 100644
index e084f47e..00000000
--- a/NorthstarDLL/scripts/client/clientchathooks.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-#include "squirrel/squirrel.h"
-#include "util/utils.h"
-
-#include "server/serverchathooks.h"
-#include "client/localchatwriter.h"
-
-#include <rapidjson/document.h>
-
-AUTOHOOK_INIT()
-
-// clang-format off
-AUTOHOOK(CHudChat__AddGameLine, client.dll + 0x22E580,
-void, __fastcall, (void* self, const char* message, int inboxId, bool isTeam, bool isDead))
-// clang-format on
-{
- // This hook is called for each HUD, but we only want our logic to run once.
- if (self != *CHudChat::allHuds)
- return;
-
- int senderId = inboxId & CUSTOM_MESSAGE_INDEX_MASK;
- bool isAnonymous = senderId == 0;
- bool isCustom = isAnonymous || (inboxId & CUSTOM_MESSAGE_INDEX_BIT);
-
- // Type is set to 0 for non-custom messages, custom messages have a type encoded as the first byte
- int type = 0;
- const char* payload = message;
- if (isCustom)
- {
- type = message[0];
- payload = message + 1;
- }
-
- RemoveAsciiControlSequences(const_cast<char*>(message), true);
-
- SQRESULT result = g_pSquirrel<ScriptContext::CLIENT>->Call(
- "CHudChat_ProcessMessageStartThread", static_cast<int>(senderId) - 1, payload, isTeam, isDead, type);
- if (result == SQRESULT_ERROR)
- for (CHudChat* hud = *CHudChat::allHuds; hud != NULL; hud = hud->next)
- CHudChat__AddGameLine(hud, message, inboxId, isTeam, isDead);
-}
-
-ADD_SQFUNC("void", NSChatWrite, "int context, string text", "", ScriptContext::CLIENT)
-{
- int chatContext = g_pSquirrel<ScriptContext::CLIENT>->getinteger(sqvm, 1);
- const char* str = g_pSquirrel<ScriptContext::CLIENT>->getstring(sqvm, 2);
-
- LocalChatWriter((LocalChatWriter::Context)chatContext).Write(str);
- return SQRESULT_NULL;
-}
-
-ADD_SQFUNC("void", NSChatWriteRaw, "int context, string text", "", ScriptContext::CLIENT)
-{
- int chatContext = g_pSquirrel<ScriptContext::CLIENT>->getinteger(sqvm, 1);
- const char* str = g_pSquirrel<ScriptContext::CLIENT>->getstring(sqvm, 2);
-
- LocalChatWriter((LocalChatWriter::Context)chatContext).InsertText(str);
- return SQRESULT_NULL;
-}
-
-ADD_SQFUNC("void", NSChatWriteLine, "int context, string text", "", ScriptContext::CLIENT)
-{
- int chatContext = g_pSquirrel<ScriptContext::CLIENT>->getinteger(sqvm, 1);
- const char* str = g_pSquirrel<ScriptContext::CLIENT>->getstring(sqvm, 2);
-
- LocalChatWriter((LocalChatWriter::Context)chatContext).WriteLine(str);
- return SQRESULT_NULL;
-}
-
-ON_DLL_LOAD_CLIENT("client.dll", ClientChatHooks, (CModule module))
-{
- AUTOHOOK_DISPATCH()
-}
diff --git a/NorthstarDLL/scripts/client/cursorposition.cpp b/NorthstarDLL/scripts/client/cursorposition.cpp
deleted file mode 100644
index c0e8623c..00000000
--- a/NorthstarDLL/scripts/client/cursorposition.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#include "squirrel/squirrel.h"
-#include "util/wininfo.h"
-
-ADD_SQFUNC("vector ornull", NSGetCursorPosition, "", "", ScriptContext::UI)
-{
- RECT rcClient;
- POINT p;
- if (GetCursorPos(&p) && ScreenToClient(*g_gameHWND, &p) && GetClientRect(*g_gameHWND, &rcClient))
- {
- if (GetAncestor(GetForegroundWindow(), GA_ROOTOWNER) != *g_gameHWND)
- return SQRESULT_NULL;
-
- g_pSquirrel<context>->pushvector(
- sqvm,
- {p.x > 0 ? p.x > rcClient.right ? rcClient.right : (float)p.x : 0,
- p.y > 0 ? p.y > rcClient.bottom ? rcClient.bottom : (float)p.y : 0,
- 0});
- return SQRESULT_NOTNULL;
- }
- g_pSquirrel<context>->raiseerror(sqvm, "Failed retrieving cursor position of game window");
- return SQRESULT_ERROR;
-}
diff --git a/NorthstarDLL/scripts/client/scriptbrowserhooks.cpp b/NorthstarDLL/scripts/client/scriptbrowserhooks.cpp
deleted file mode 100644
index 86b4a356..00000000
--- a/NorthstarDLL/scripts/client/scriptbrowserhooks.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-
-AUTOHOOK_INIT()
-
-bool* bIsOriginOverlayEnabled;
-
-// clang-format off
-AUTOHOOK(OpenExternalWebBrowser, engine.dll + 0x184E40,
-void, __fastcall, (char* pUrl, char flags))
-// clang-format on
-{
- bool bIsOriginOverlayEnabledOriginal = *bIsOriginOverlayEnabled;
- if (flags & 2 && !strncmp(pUrl, "http", 4)) // custom force external browser flag
- *bIsOriginOverlayEnabled = false; // if this bool is false, game will use an external browser rather than the origin overlay one
-
- OpenExternalWebBrowser(pUrl, flags);
- *bIsOriginOverlayEnabled = bIsOriginOverlayEnabledOriginal;
-}
-
-ON_DLL_LOAD_CLIENT("engine.dll", ScriptExternalBrowserHooks, (CModule module))
-{
- AUTOHOOK_DISPATCH()
-
- bIsOriginOverlayEnabled = module.Offset(0x13978255).RCast<bool*>();
-}
diff --git a/NorthstarDLL/scripts/client/scriptmainmenupromos.cpp b/NorthstarDLL/scripts/client/scriptmainmenupromos.cpp
deleted file mode 100644
index ecb47af7..00000000
--- a/NorthstarDLL/scripts/client/scriptmainmenupromos.cpp
+++ /dev/null
@@ -1,123 +0,0 @@
-#include "squirrel/squirrel.h"
-#include "masterserver/masterserver.h"
-
-// mirror this in script
-enum eMainMenuPromoDataProperty
-{
- newInfoTitle1,
- newInfoTitle2,
- newInfoTitle3,
-
- largeButtonTitle,
- largeButtonText,
- largeButtonUrl,
- largeButtonImageIndex,
-
- smallButton1Title,
- smallButton1Url,
- smallButton1ImageIndex,
-
- smallButton2Title,
- smallButton2Url,
- smallButton2ImageIndex
-};
-ADD_SQFUNC("void", NSRequestCustomMainMenuPromos, "", "", ScriptContext::UI)
-{
- g_pMasterServerManager->RequestMainMenuPromos();
- return SQRESULT_NULL;
-}
-
-ADD_SQFUNC("bool", NSHasCustomMainMenuPromoData, "", "", ScriptContext::UI)
-{
- g_pSquirrel<ScriptContext::UI>->pushbool(sqvm, g_pMasterServerManager->m_bHasMainMenuPromoData);
- return SQRESULT_NOTNULL;
-}
-
-ADD_SQFUNC("var", NSGetCustomMainMenuPromoData, "int promoDataKey", "", ScriptContext::UI)
-{
- if (!g_pMasterServerManager->m_bHasMainMenuPromoData)
- return SQRESULT_NULL;
-
- switch (g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1))
- {
- case eMainMenuPromoDataProperty::newInfoTitle1:
- {
- g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.newInfoTitle1.c_str());
- break;
- }
-
- case eMainMenuPromoDataProperty::newInfoTitle2:
- {
- g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.newInfoTitle2.c_str());
- break;
- }
-
- case eMainMenuPromoDataProperty::newInfoTitle3:
- {
- g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.newInfoTitle3.c_str());
- break;
- }
-
- case eMainMenuPromoDataProperty::largeButtonTitle:
- {
- g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.largeButtonTitle.c_str());
- break;
- }
-
- case eMainMenuPromoDataProperty::largeButtonText:
- {
- g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.largeButtonText.c_str());
- break;
- }
-
- case eMainMenuPromoDataProperty::largeButtonUrl:
- {
- g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.largeButtonUrl.c_str());
- break;
- }
-
- case eMainMenuPromoDataProperty::largeButtonImageIndex:
- {
- g_pSquirrel<ScriptContext::UI>->pushinteger(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.largeButtonImageIndex);
- break;
- }
-
- case eMainMenuPromoDataProperty::smallButton1Title:
- {
- g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.smallButton1Title.c_str());
- break;
- }
-
- case eMainMenuPromoDataProperty::smallButton1Url:
- {
- g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.smallButton1Url.c_str());
- break;
- }
-
- case eMainMenuPromoDataProperty::smallButton1ImageIndex:
- {
- g_pSquirrel<ScriptContext::UI>->pushinteger(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.smallButton1ImageIndex);
- break;
- }
-
- case eMainMenuPromoDataProperty::smallButton2Title:
- {
- g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.smallButton2Title.c_str());
- break;
- }
-
- case eMainMenuPromoDataProperty::smallButton2Url:
- {
- g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.smallButton2Url.c_str());
- break;
- }
-
- case eMainMenuPromoDataProperty::smallButton2ImageIndex:
- {
- g_pSquirrel<ScriptContext::UI>->pushinteger(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.smallButton2ImageIndex);
- break;
- }
- }
-
- return SQRESULT_NOTNULL;
-}
diff --git a/NorthstarDLL/scripts/client/scriptmodmenu.cpp b/NorthstarDLL/scripts/client/scriptmodmenu.cpp
deleted file mode 100644
index a88478fb..00000000
--- a/NorthstarDLL/scripts/client/scriptmodmenu.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
-#include "mods/modmanager.h"
-#include "squirrel/squirrel.h"
-
-ADD_SQFUNC("array<string>", NSGetModNames, "", "", ScriptContext::SERVER | ScriptContext::CLIENT | ScriptContext::UI)
-{
- g_pSquirrel<context>->newarray(sqvm, 0);
-
- for (Mod& mod : g_pModManager->m_LoadedMods)
- {
- g_pSquirrel<context>->pushstring(sqvm, mod.Name.c_str());
- g_pSquirrel<context>->arrayappend(sqvm, -2);
- }
-
- return SQRESULT_NOTNULL;
-}
-
-ADD_SQFUNC("bool", NSIsModEnabled, "string modName", "", ScriptContext::SERVER | ScriptContext::CLIENT | ScriptContext::UI)
-{
- const SQChar* modName = g_pSquirrel<context>->getstring(sqvm, 1);
-
- // manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_pModManager->m_LoadedMods)
- {
- if (!mod.Name.compare(modName))
- {
- g_pSquirrel<context>->pushbool(sqvm, mod.m_bEnabled);
- return SQRESULT_NOTNULL;
- }
- }
-
- return SQRESULT_NULL;
-}
-
-ADD_SQFUNC("void", NSSetModEnabled, "string modName, bool enabled", "", ScriptContext::SERVER | ScriptContext::CLIENT | ScriptContext::UI)
-{
- const SQChar* modName = g_pSquirrel<context>->getstring(sqvm, 1);
- const SQBool enabled = g_pSquirrel<context>->getbool(sqvm, 2);
-
- // manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_pModManager->m_LoadedMods)
- {
- if (!mod.Name.compare(modName))
- {
- mod.m_bEnabled = enabled;
- return SQRESULT_NULL;
- }
- }
-
- return SQRESULT_NULL;
-}
-
-ADD_SQFUNC("string", NSGetModDescriptionByModName, "string modName", "", ScriptContext::SERVER | ScriptContext::CLIENT | ScriptContext::UI)
-{
- const SQChar* modName = g_pSquirrel<context>->getstring(sqvm, 1);
-
- // manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_pModManager->m_LoadedMods)
- {
- if (!mod.Name.compare(modName))
- {
- g_pSquirrel<context>->pushstring(sqvm, mod.Description.c_str());
- return SQRESULT_NOTNULL;
- }
- }
-
- return SQRESULT_NULL;
-}
-
-ADD_SQFUNC("string", NSGetModVersionByModName, "string modName", "", ScriptContext::SERVER | ScriptContext::CLIENT | ScriptContext::UI)
-{
- const SQChar* modName = g_pSquirrel<context>->getstring(sqvm, 1);
-
- // manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_pModManager->m_LoadedMods)
- {
- if (!mod.Name.compare(modName))
- {
- g_pSquirrel<context>->pushstring(sqvm, mod.Version.c_str());
- return SQRESULT_NOTNULL;
- }
- }
-
- return SQRESULT_NULL;
-}
-
-ADD_SQFUNC("string", NSGetModDownloadLinkByModName, "string modName", "", ScriptContext::SERVER | ScriptContext::CLIENT | ScriptContext::UI)
-{
- const SQChar* modName = g_pSquirrel<context>->getstring(sqvm, 1);
-
- // manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_pModManager->m_LoadedMods)
- {
- if (!mod.Name.compare(modName))
- {
- g_pSquirrel<context>->pushstring(sqvm, mod.DownloadLink.c_str());
- return SQRESULT_NOTNULL;
- }
- }
-
- return SQRESULT_NULL;
-}
-
-ADD_SQFUNC("int", NSGetModLoadPriority, "string modName", "", ScriptContext::SERVER | ScriptContext::CLIENT | ScriptContext::UI)
-{
- const SQChar* modName = g_pSquirrel<context>->getstring(sqvm, 1);
-
- // manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_pModManager->m_LoadedMods)
- {
- if (!mod.Name.compare(modName))
- {
- g_pSquirrel<context>->pushinteger(sqvm, mod.LoadPriority);
- return SQRESULT_NOTNULL;
- }
- }
-
- return SQRESULT_NULL;
-}
-
-ADD_SQFUNC("bool", NSIsModRequiredOnClient, "string modName", "", ScriptContext::SERVER | ScriptContext::CLIENT | ScriptContext::UI)
-{
- const SQChar* modName = g_pSquirrel<context>->getstring(sqvm, 1);
-
- // manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_pModManager->m_LoadedMods)
- {
- if (!mod.Name.compare(modName))
- {
- g_pSquirrel<context>->pushbool(sqvm, mod.RequiredOnClient);
- return SQRESULT_NOTNULL;
- }
- }
-
- return SQRESULT_NULL;
-}
-
-ADD_SQFUNC(
- "array<string>", NSGetModConvarsByModName, "string modName", "", ScriptContext::SERVER | ScriptContext::CLIENT | ScriptContext::UI)
-{
- const SQChar* modName = g_pSquirrel<context>->getstring(sqvm, 1);
- g_pSquirrel<context>->newarray(sqvm, 0);
-
- // manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_pModManager->m_LoadedMods)
- {
- if (!mod.Name.compare(modName))
- {
- for (ModConVar* cvar : mod.ConVars)
- {
- g_pSquirrel<context>->pushstring(sqvm, cvar->Name.c_str());
- g_pSquirrel<context>->arrayappend(sqvm, -2);
- }
-
- return SQRESULT_NOTNULL;
- }
- }
-
- return SQRESULT_NOTNULL; // return empty array
-}
-
-ADD_SQFUNC("void", NSReloadMods, "", "", ScriptContext::UI)
-{
- g_pModManager->LoadMods();
- return SQRESULT_NULL;
-}
diff --git a/NorthstarDLL/scripts/client/scriptoriginauth.cpp b/NorthstarDLL/scripts/client/scriptoriginauth.cpp
deleted file mode 100644
index 420c4872..00000000
--- a/NorthstarDLL/scripts/client/scriptoriginauth.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-#include "squirrel/squirrel.h"
-#include "masterserver/masterserver.h"
-#include "engine/r2engine.h"
-#include "client/r2client.h"
-
-ADD_SQFUNC("bool", NSIsMasterServerAuthenticated, "", "", ScriptContext::UI)
-{
- g_pSquirrel<context>->pushbool(sqvm, g_pMasterServerManager->m_bOriginAuthWithMasterServerDone);
- return SQRESULT_NOTNULL;
-}
-
-/*
-global struct MasterServerAuthResult
-{
- bool success
- string errorCode
- string errorMessage
-}
-*/
-
-ADD_SQFUNC("MasterServerAuthResult", NSGetMasterServerAuthResult, "", "", ScriptContext::UI)
-{
- g_pSquirrel<context>->pushnewstructinstance(sqvm, 3);
-
- g_pSquirrel<context>->pushbool(sqvm, g_pMasterServerManager->m_bOriginAuthWithMasterServerSuccessful);
- g_pSquirrel<context>->sealstructslot(sqvm, 0);
-
- g_pSquirrel<context>->pushstring(sqvm, g_pMasterServerManager->m_sOriginAuthWithMasterServerErrorCode.c_str(), -1);
- g_pSquirrel<context>->sealstructslot(sqvm, 1);
-
- g_pSquirrel<context>->pushstring(sqvm, g_pMasterServerManager->m_sOriginAuthWithMasterServerErrorMessage.c_str(), -1);
- g_pSquirrel<context>->sealstructslot(sqvm, 2);
-
- return SQRESULT_NOTNULL;
-}
diff --git a/NorthstarDLL/scripts/client/scriptserverbrowser.cpp b/NorthstarDLL/scripts/client/scriptserverbrowser.cpp
deleted file mode 100644
index a142c3f4..00000000
--- a/NorthstarDLL/scripts/client/scriptserverbrowser.cpp
+++ /dev/null
@@ -1,209 +0,0 @@
-#include "squirrel/squirrel.h"
-#include "masterserver/masterserver.h"
-#include "server/auth/serverauthentication.h"
-#include "engine/r2engine.h"
-#include "client/r2client.h"
-
-// functions for viewing server browser
-
-ADD_SQFUNC("void", NSRequestServerList, "", "", ScriptContext::UI)
-{
- g_pMasterServerManager->RequestServerList();
- return SQRESULT_NULL;
-}
-
-ADD_SQFUNC("bool", NSIsRequestingServerList, "", "", ScriptContext::UI)
-{
- g_pSquirrel<context>->pushbool(sqvm, g_pMasterServerManager->m_bScriptRequestingServerList);
- return SQRESULT_NOTNULL;
-}
-
-ADD_SQFUNC("bool", NSMasterServerConnectionSuccessful, "", "", ScriptContext::UI)
-{
- g_pSquirrel<context>->pushbool(sqvm, g_pMasterServerManager->m_bSuccessfullyConnected);
- return SQRESULT_NOTNULL;
-}
-
-ADD_SQFUNC("int", NSGetServerCount, "", "", ScriptContext::UI)
-{
- g_pSquirrel<context>->pushinteger(sqvm, g_pMasterServerManager->m_vRemoteServers.size());
- return SQRESULT_NOTNULL;
-}
-
-ADD_SQFUNC("void", NSClearRecievedServerList, "", "", ScriptContext::UI)
-{
- g_pMasterServerManager->ClearServerList();
- return SQRESULT_NULL;
-}
-
-// functions for authenticating with servers
-
-ADD_SQFUNC("void", NSTryAuthWithServer, "int serverIndex, string password = ''", "", ScriptContext::UI)
-{
- SQInteger serverIndex = g_pSquirrel<context>->getinteger(sqvm, 1);
- const SQChar* password = g_pSquirrel<context>->getstring(sqvm, 2);
-
- if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
- {
- g_pSquirrel<context>->raiseerror(
- sqvm,
- fmt::format(
- "Tried to auth with server index {} when only {} servers are available",
- serverIndex,
- g_pMasterServerManager->m_vRemoteServers.size())
- .c_str());
- return SQRESULT_ERROR;
- }
-
- // send off persistent data first, don't worry about server/client stuff, since m_additionalPlayerData should only have entries when
- // we're a local server note: this seems like it could create a race condition, test later
- for (auto& pair : g_pServerAuthentication->m_PlayerAuthenticationData)
- g_pServerAuthentication->WritePersistentData(pair.first);
-
- // do auth
- g_pMasterServerManager->AuthenticateWithServer(
- g_pLocalPlayerUserID,
- g_pMasterServerManager->m_sOwnClientAuthToken,
- g_pMasterServerManager->m_vRemoteServers[serverIndex],
- (char*)password);
-
- return SQRESULT_NULL;
-}
-
-ADD_SQFUNC("bool", NSIsAuthenticatingWithServer, "", "", ScriptContext::UI)
-{
- g_pSquirrel<context>->pushbool(sqvm, g_pMasterServerManager->m_bScriptAuthenticatingWithGameServer);
- return SQRESULT_NOTNULL;
-}
-
-ADD_SQFUNC("bool", NSWasAuthSuccessful, "", "", ScriptContext::UI)
-{
- g_pSquirrel<context>->pushbool(sqvm, g_pMasterServerManager->m_bSuccessfullyAuthenticatedWithGameServer);
- return SQRESULT_NOTNULL;
-}
-
-ADD_SQFUNC("void", NSConnectToAuthedServer, "", "", ScriptContext::UI)
-{
- if (!g_pMasterServerManager->m_bHasPendingConnectionInfo)
- {
- g_pSquirrel<context>->raiseerror(
- sqvm, fmt::format("Tried to connect to authed server before any pending connection info was available").c_str());
- return SQRESULT_ERROR;
- }
-
- RemoteServerConnectionInfo& info = g_pMasterServerManager->m_pendingConnectionInfo;
-
- // set auth token, then try to connect
- // i'm honestly not entirely sure how silentconnect works regarding ports and encryption so using connect for now
- g_pCVar->FindVar("serverfilter")->SetValue(info.authToken);
- Cbuf_AddText(
- Cbuf_GetCurrentPlayer(),
- fmt::format(
- "connect {}.{}.{}.{}:{}",
- info.ip.S_un.S_un_b.s_b1,
- info.ip.S_un.S_un_b.s_b2,
- info.ip.S_un.S_un_b.s_b3,
- info.ip.S_un.S_un_b.s_b4,
- info.port)
- .c_str(),
- cmd_source_t::kCommandSrcCode);
-
- g_pMasterServerManager->m_bHasPendingConnectionInfo = false;
- return SQRESULT_NULL;
-}
-
-ADD_SQFUNC("void", NSTryAuthWithLocalServer, "", "", ScriptContext::UI)
-{
- // do auth request
- g_pMasterServerManager->AuthenticateWithOwnServer(g_pLocalPlayerUserID, g_pMasterServerManager->m_sOwnClientAuthToken);
-
- return SQRESULT_NULL;
-}
-
-ADD_SQFUNC("void", NSCompleteAuthWithLocalServer, "", "", ScriptContext::UI)
-{
- // literally just set serverfilter
- // note: this assumes we have no authdata other than our own
- if (g_pServerAuthentication->m_RemoteAuthenticationData.size())
- g_pCVar->FindVar("serverfilter")->SetValue(g_pServerAuthentication->m_RemoteAuthenticationData.begin()->first.c_str());
-
- return SQRESULT_NULL;
-}
-
-ADD_SQFUNC("string", NSGetAuthFailReason, "", "", ScriptContext::UI)
-{
- g_pSquirrel<context>->pushstring(sqvm, g_pMasterServerManager->m_sAuthFailureReason.c_str(), -1);
- return SQRESULT_NOTNULL;
-}
-
-ADD_SQFUNC("array<ServerInfo>", NSGetGameServers, "", "", ScriptContext::UI)
-{
- g_pSquirrel<context>->newarray(sqvm, 0);
- for (size_t i = 0; i < g_pMasterServerManager->m_vRemoteServers.size(); i++)
- {
- const RemoteServerInfo& remoteServer = g_pMasterServerManager->m_vRemoteServers[i];
-
- g_pSquirrel<context>->pushnewstructinstance(sqvm, 11);
-
- // index
- g_pSquirrel<context>->pushinteger(sqvm, i);
- g_pSquirrel<context>->sealstructslot(sqvm, 0);
-
- // id
- g_pSquirrel<context>->pushstring(sqvm, remoteServer.id, -1);
- g_pSquirrel<context>->sealstructslot(sqvm, 1);
-
- // name
- g_pSquirrel<context>->pushstring(sqvm, remoteServer.name, -1);
- g_pSquirrel<context>->sealstructslot(sqvm, 2);
-
- // description
- g_pSquirrel<context>->pushstring(sqvm, remoteServer.description.c_str(), -1);
- g_pSquirrel<context>->sealstructslot(sqvm, 3);
-
- // map
- g_pSquirrel<context>->pushstring(sqvm, remoteServer.map, -1);
- g_pSquirrel<context>->sealstructslot(sqvm, 4);
-
- // playlist
- g_pSquirrel<context>->pushstring(sqvm, remoteServer.playlist, -1);
- g_pSquirrel<context>->sealstructslot(sqvm, 5);
-
- // playerCount
- g_pSquirrel<context>->pushinteger(sqvm, remoteServer.playerCount);
- g_pSquirrel<context>->sealstructslot(sqvm, 6);
-
- // maxPlayerCount
- g_pSquirrel<context>->pushinteger(sqvm, remoteServer.maxPlayers);
- g_pSquirrel<context>->sealstructslot(sqvm, 7);
-
- // requiresPassword
- g_pSquirrel<context>->pushbool(sqvm, remoteServer.requiresPassword);
- g_pSquirrel<context>->sealstructslot(sqvm, 8);
-
- // region
- g_pSquirrel<context>->pushstring(sqvm, remoteServer.region, -1);
- g_pSquirrel<context>->sealstructslot(sqvm, 9);
-
- // requiredMods
- g_pSquirrel<context>->newarray(sqvm);
- for (const RemoteModInfo& mod : remoteServer.requiredMods)
- {
- g_pSquirrel<context>->pushnewstructinstance(sqvm, 2);
-
- // name
- g_pSquirrel<context>->pushstring(sqvm, mod.Name.c_str(), -1);
- g_pSquirrel<context>->sealstructslot(sqvm, 0);
-
- // version
- g_pSquirrel<context>->pushstring(sqvm, mod.Version.c_str(), -1);
- g_pSquirrel<context>->sealstructslot(sqvm, 1);
-
- g_pSquirrel<context>->arrayappend(sqvm, -2);
- }
- g_pSquirrel<context>->sealstructslot(sqvm, 10);
-
- g_pSquirrel<context>->arrayappend(sqvm, -2);
- }
- return SQRESULT_NOTNULL;
-}
diff --git a/NorthstarDLL/scripts/client/scriptservertoclientstringcommand.cpp b/NorthstarDLL/scripts/client/scriptservertoclientstringcommand.cpp
deleted file mode 100644
index a3a81c8a..00000000
--- a/NorthstarDLL/scripts/client/scriptservertoclientstringcommand.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-#include "squirrel/squirrel.h"
-#include "core/convar/convar.h"
-#include "core/convar/concommand.h"
-
-void ConCommand_ns_script_servertoclientstringcommand(const CCommand& arg)
-{
- if (g_pSquirrel<ScriptContext::CLIENT>->m_pSQVM)
- g_pSquirrel<ScriptContext::CLIENT>->Call("NSClientCodeCallback_RecievedServerToClientStringCommand", arg.ArgS());
-}
-
-ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ScriptServerToClientStringCommand, ClientSquirrel, (CModule module))
-{
- RegisterConCommand(
- "ns_script_servertoclientstringcommand",
- ConCommand_ns_script_servertoclientstringcommand,
- "",
- FCVAR_CLIENTDLL | FCVAR_SERVER_CAN_EXECUTE);
-}
diff --git a/NorthstarDLL/scripts/scriptdatatables.cpp b/NorthstarDLL/scripts/scriptdatatables.cpp
deleted file mode 100644
index 87a26dca..00000000
--- a/NorthstarDLL/scripts/scriptdatatables.cpp
+++ /dev/null
@@ -1,909 +0,0 @@
-#include "squirrel/squirrel.h"
-#include "core/filesystem/rpakfilesystem.h"
-#include "core/convar/convar.h"
-#include "dedicated/dedicated.h"
-#include "core/filesystem/filesystem.h"
-#include "core/math/vector.h"
-#include "core/tier0.h"
-#include "engine/r2engine.h"
-#include <iostream>
-#include <sstream>
-#include <map>
-#include <fstream>
-#include <filesystem>
-
-const uint64_t USERDATA_TYPE_DATATABLE = 0xFFF7FFF700000004;
-const uint64_t USERDATA_TYPE_DATATABLE_CUSTOM = 0xFFFCFFFC12345678;
-
-enum class DatatableType : int
-{
- BOOL = 0,
- INT,
- FLOAT,
- VECTOR,
- STRING,
- ASSET,
- UNK_STRING // unknown but deffo a string type
-};
-
-struct ColumnInfo
-{
- char* name;
- DatatableType type;
- int offset;
-};
-
-struct Datatable
-{
- int numColumns;
- int numRows;
- ColumnInfo* columnInfo;
- char* data; // actually data pointer
- int rowInfo;
-};
-
-ConVar* Cvar_ns_prefer_datatable_from_disk;
-
-template <ScriptContext context> Datatable* (*SQ_GetDatatableInternal)(HSquirrelVM* sqvm);
-
-struct CSVData
-{
- std::string m_sAssetName;
- std::string m_sCSVString;
- char* m_pDataBuf;
- size_t m_nDataBufSize;
-
- std::vector<char*> columns;
- std::vector<std::vector<char*>> dataPointers;
-};
-
-std::unordered_map<std::string, CSVData> CSVCache;
-
-Vector3 StringToVector(char* pString)
-{
- Vector3 vRet;
-
- int length = 0;
- while (pString[length])
- {
- if ((pString[length] == '<') || (pString[length] == '>'))
- pString[length] = '\0';
- length++;
- }
-
- int startOfFloat = 1;
- int currentIndex = 1;
-
- while (pString[currentIndex] && (pString[currentIndex] != ','))
- currentIndex++;
- pString[currentIndex] = '\0';
- vRet.x = std::stof(&pString[startOfFloat]);
- startOfFloat = ++currentIndex;
-
- while (pString[currentIndex] && (pString[currentIndex] != ','))
- currentIndex++;
- pString[currentIndex] = '\0';
- vRet.y = std::stof(&pString[startOfFloat]);
- startOfFloat = ++currentIndex;
-
- while (pString[currentIndex] && (pString[currentIndex] != ','))
- currentIndex++;
- pString[currentIndex] = '\0';
- vRet.z = std::stof(&pString[startOfFloat]);
- startOfFloat = ++currentIndex;
-
- return vRet;
-}
-
-// var function GetDataTable( asset path )
-REPLACE_SQFUNC(GetDataTable, (ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER))
-{
- const char* pAssetName;
- g_pSquirrel<context>->getasset(sqvm, 2, &pAssetName);
-
- if (strncmp(pAssetName, "datatable/", 10))
- {
- g_pSquirrel<context>->raiseerror(sqvm, fmt::format("Asset \"{}\" doesn't start with \"datatable/\"", pAssetName).c_str());
- return SQRESULT_ERROR;
- }
- else if (!Cvar_ns_prefer_datatable_from_disk->GetBool() && g_pPakLoadManager->LoadFile(pAssetName))
- return g_pSquirrel<context>->m_funcOriginals["GetDataTable"](sqvm);
- // either we prefer disk datatables, or we're loading a datatable that wasn't found in rpak
- else
- {
- std::string sAssetPath(fmt::format("scripts/{}", pAssetName));
-
- // first, check the cache
- if (CSVCache.find(pAssetName) != CSVCache.end())
- {
- CSVData** pUserdata = g_pSquirrel<context>->template createuserdata<CSVData*>(sqvm, sizeof(CSVData*));
- g_pSquirrel<context>->setuserdatatypeid(sqvm, -1, USERDATA_TYPE_DATATABLE_CUSTOM);
- *pUserdata = &CSVCache[pAssetName];
-
- return SQRESULT_NOTNULL;
- }
-
- // check files on disk
- // we don't use .rpak as the extension for on-disk datatables, so we need to replace .rpak with .csv in the filename we're reading
- fs::path diskAssetPath("scripts");
- if (fs::path(pAssetName).extension() == ".rpak")
- diskAssetPath /= fs::path(pAssetName).remove_filename() / (fs::path(pAssetName).stem().string() + ".csv");
- else
- diskAssetPath /= fs::path(pAssetName);
-
- std::string sDiskAssetPath(diskAssetPath.string());
- if ((*g_pFilesystem)->m_vtable2->FileExists(&(*g_pFilesystem)->m_vtable2, sDiskAssetPath.c_str(), "GAME"))
- {
- std::string sTableCSV = ReadVPKFile(sDiskAssetPath.c_str());
- if (!sTableCSV.size())
- {
- g_pSquirrel<context>->raiseerror(sqvm, fmt::format("Datatable \"{}\" is empty", pAssetName).c_str());
- return SQRESULT_ERROR;
- }
-
- // somewhat shit, but ensure we end with a newline to make parsing easier
- if (sTableCSV[sTableCSV.length() - 1] != '\n')
- sTableCSV += '\n';
-
- CSVData csv;
- csv.m_sAssetName = pAssetName;
- csv.m_sCSVString = sTableCSV;
- csv.m_nDataBufSize = sTableCSV.size();
- csv.m_pDataBuf = new char[csv.m_nDataBufSize];
- memcpy(csv.m_pDataBuf, &sTableCSV[0], csv.m_nDataBufSize);
-
- // parse the csv
- // csvs are essentially comma and newline-deliniated sets of strings for parsing, only thing we need to worry about is quoted
- // entries when we parse an element of the csv, rather than allocating an entry for it, we just convert that element to a
- // null-terminated string i.e., store the ptr to the first char of it, then make the comma that delinates it a nullchar
-
- bool bHasColumns = false;
- bool bInQuotes = false;
-
- std::vector<char*> vCurrentRow;
- char* pElemStart = csv.m_pDataBuf;
- char* pElemEnd = nullptr;
-
- for (int i = 0; i < csv.m_nDataBufSize; i++)
- {
- if (csv.m_pDataBuf[i] == '\r' && csv.m_pDataBuf[i + 1] == '\n')
- {
- if (!pElemEnd)
- pElemEnd = csv.m_pDataBuf + i;
-
- continue; // next iteration can handle the \n
- }
-
- // newline, end of a row
- if (csv.m_pDataBuf[i] == '\n')
- {
- // shouldn't have newline in string
- if (bInQuotes)
- {
- g_pSquirrel<context>->raiseerror(sqvm, "Unexpected \\n in string");
- return SQRESULT_ERROR;
- }
-
- // push last entry to current row
- if (pElemEnd)
- *pElemEnd = '\0';
- else
- csv.m_pDataBuf[i] = '\0';
-
- vCurrentRow.push_back(pElemStart);
-
- // newline, push last line to csv data and go from there
- if (!bHasColumns)
- {
- bHasColumns = true;
- csv.columns = vCurrentRow;
- }
- else
- csv.dataPointers.push_back(vCurrentRow);
-
- vCurrentRow.clear();
- // put start of current element at char after newline
- pElemStart = csv.m_pDataBuf + i + 1;
- pElemEnd = nullptr;
- }
- // we're starting or ending a quoted string
- else if (csv.m_pDataBuf[i] == '"')
- {
- // start quoted string
- if (!bInQuotes)
- {
- // shouldn't have quoted strings in column names
- if (!bHasColumns)
- {
- g_pSquirrel<context>->raiseerror(sqvm, "Unexpected \" in column name");
- return SQRESULT_ERROR;
- }
-
- bInQuotes = true;
- // put start of current element at char after string begin
- pElemStart = csv.m_pDataBuf + i + 1;
- }
- // end quoted string
- else
- {
- pElemEnd = csv.m_pDataBuf + i;
- bInQuotes = false;
- }
- }
- // don't parse commas in quotes
- else if (bInQuotes)
- {
- continue;
- }
- // comma, push new entry to current row
- else if (csv.m_pDataBuf[i] == ',')
- {
- if (pElemEnd)
- *pElemEnd = '\0';
- else
- csv.m_pDataBuf[i] = '\0';
-
- vCurrentRow.push_back(pElemStart);
- // put start of next element at char after comma
- pElemStart = csv.m_pDataBuf + i + 1;
- pElemEnd = nullptr;
- }
- }
-
- // add to cache and return
- CSVData** pUserdata = g_pSquirrel<context>->template createuserdata<CSVData*>(sqvm, sizeof(CSVData*));
- g_pSquirrel<context>->setuserdatatypeid(sqvm, -1, USERDATA_TYPE_DATATABLE_CUSTOM);
- CSVCache[pAssetName] = csv;
- *pUserdata = &CSVCache[pAssetName];
-
- return SQRESULT_NOTNULL;
- }
- // the file doesn't exist on disk, check rpak if we haven't already
- else if (Cvar_ns_prefer_datatable_from_disk->GetBool() && g_pPakLoadManager->LoadFile(pAssetName))
- return g_pSquirrel<context>->m_funcOriginals["GetDataTable"](sqvm);
- // the file doesn't exist at all, error
- else
- {
- g_pSquirrel<context>->raiseerror(sqvm, fmt::format("Datatable {} not found", pAssetName).c_str());
- return SQRESULT_ERROR;
- }
- }
-}
-
-// int function GetDataTableColumnByName( var datatable, string columnName )
-REPLACE_SQFUNC(GetDataTableColumnByName, (ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER))
-{
- CSVData** pData;
- uint64_t typeId;
- g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
-
- if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
- return g_pSquirrel<context>->m_funcOriginals["GetDataTableColumnByName"](sqvm);
-
- CSVData* csv = *pData;
- const char* pColumnName = g_pSquirrel<context>->getstring(sqvm, 2);
-
- for (int i = 0; i < csv->columns.size(); i++)
- {
- if (!strcmp(csv->columns[i], pColumnName))
- {
- g_pSquirrel<context>->pushinteger(sqvm, i);
- return SQRESULT_NOTNULL;
- }
- }
-
- // column not found
- g_pSquirrel<context>->pushinteger(sqvm, -1);
- return SQRESULT_NOTNULL;
-}
-
-// int function GetDataTableRowCount( var datatable )
-REPLACE_SQFUNC(GetDataTableRowCount, (ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER))
-{
- CSVData** pData;
- uint64_t typeId;
- g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
-
- if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
- return g_pSquirrel<context>->m_funcOriginals["GetDatatableRowCount"](sqvm);
-
- CSVData* csv = *pData;
- g_pSquirrel<context>->pushinteger(sqvm, csv->dataPointers.size());
- return SQRESULT_NOTNULL;
-}
-
-// string function GetDataTableString( var datatable, int row, int col )
-REPLACE_SQFUNC(GetDataTableString, (ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER))
-{
- CSVData** pData;
- uint64_t typeId;
- g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
-
- if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
- return g_pSquirrel<context>->m_funcOriginals["GetDataTableString"](sqvm);
-
- CSVData* csv = *pData;
- const int nRow = g_pSquirrel<context>->getinteger(sqvm, 2);
- const int nCol = g_pSquirrel<context>->getinteger(sqvm, 3);
- if (nRow >= csv->dataPointers.size() || nCol >= csv->dataPointers[nRow].size())
- {
- g_pSquirrel<context>->raiseerror(
- sqvm,
- fmt::format(
- "row {} and col {} are outside of range row {} and col {}", nRow, nCol, csv->dataPointers.size(), csv->columns.size())
- .c_str());
- return SQRESULT_ERROR;
- }
-
- g_pSquirrel<context>->pushstring(sqvm, csv->dataPointers[nRow][nCol], -1);
- return SQRESULT_NOTNULL;
-}
-
-// asset function GetDataTableAsset( var datatable, int row, int col )
-REPLACE_SQFUNC(GetDataTableAsset, (ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER))
-{
- CSVData** pData;
- uint64_t typeId;
- g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
-
- if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
- return g_pSquirrel<context>->m_funcOriginals["GetDataTableAsset"](sqvm);
-
- CSVData* csv = *pData;
- const int nRow = g_pSquirrel<context>->getinteger(sqvm, 2);
- const int nCol = g_pSquirrel<context>->getinteger(sqvm, 3);
- if (nRow >= csv->dataPointers.size() || nCol >= csv->dataPointers[nRow].size())
- {
- g_pSquirrel<context>->raiseerror(
- sqvm,
- fmt::format(
- "row {} and col {} are outside of range row {} and col {}", nRow, nCol, csv->dataPointers.size(), csv->columns.size())
- .c_str());
- return SQRESULT_ERROR;
- }
-
- g_pSquirrel<context>->pushasset(sqvm, csv->dataPointers[nRow][nCol], -1);
- return SQRESULT_NOTNULL;
-}
-
-// int function GetDataTableInt( var datatable, int row, int col )
-REPLACE_SQFUNC(GetDataTableInt, (ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER))
-{
- CSVData** pData;
- uint64_t typeId;
- g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
-
- if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
- return g_pSquirrel<context>->m_funcOriginals["GetDataTableInt"](sqvm);
-
- CSVData* csv = *pData;
- const int nRow = g_pSquirrel<context>->getinteger(sqvm, 2);
- const int nCol = g_pSquirrel<context>->getinteger(sqvm, 3);
- if (nRow >= csv->dataPointers.size() || nCol >= csv->dataPointers[nRow].size())
- {
- g_pSquirrel<context>->raiseerror(
- sqvm,
- fmt::format(
- "row {} and col {} are outside of range row {} and col {}", nRow, nCol, csv->dataPointers.size(), csv->columns.size())
- .c_str());
- return SQRESULT_ERROR;
- }
-
- g_pSquirrel<context>->pushinteger(sqvm, std::stoi(csv->dataPointers[nRow][nCol]));
- return SQRESULT_NOTNULL;
-}
-
-// float function GetDataTableFloat( var datatable, int row, int col )
-REPLACE_SQFUNC(GetDataTableFloat, (ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER))
-{
- CSVData** pData;
- uint64_t typeId;
- g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
-
- if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
- return g_pSquirrel<context>->m_funcOriginals["GetDataTableFloat"](sqvm);
-
- CSVData* csv = *pData;
- const int nRow = g_pSquirrel<context>->getinteger(sqvm, 2);
- const int nCol = g_pSquirrel<context>->getinteger(sqvm, 3);
- if (nRow >= csv->dataPointers.size() || nCol >= csv->dataPointers[nRow].size())
- {
- g_pSquirrel<context>->raiseerror(
- sqvm,
- fmt::format(
- "row {} and col {} are outside of range row {} and col {}", nRow, nCol, csv->dataPointers.size(), csv->columns.size())
- .c_str());
- return SQRESULT_ERROR;
- }
-
- g_pSquirrel<context>->pushfloat(sqvm, std::stof(csv->dataPointers[nRow][nCol]));
- return SQRESULT_NOTNULL;
-}
-
-// bool function GetDataTableBool( var datatable, int row, int col )
-REPLACE_SQFUNC(GetDataTableBool, (ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER))
-{
- CSVData** pData;
- uint64_t typeId;
- g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
-
- if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
- return g_pSquirrel<context>->m_funcOriginals["GetDataTableBool"](sqvm);
-
- CSVData* csv = *pData;
- const int nRow = g_pSquirrel<context>->getinteger(sqvm, 2);
- const int nCol = g_pSquirrel<context>->getinteger(sqvm, 3);
- if (nRow >= csv->dataPointers.size() || nCol >= csv->dataPointers[nRow].size())
- {
- g_pSquirrel<context>->raiseerror(
- sqvm,
- fmt::format(
- "row {} and col {} are outside of range row {} and col {}", nRow, nCol, csv->dataPointers.size(), csv->columns.size())
- .c_str());
- return SQRESULT_ERROR;
- }
-
- g_pSquirrel<context>->pushbool(sqvm, std::stoi(csv->dataPointers[nRow][nCol]));
- return SQRESULT_NOTNULL;
-}
-
-// vector function GetDataTableVector( var datatable, int row, int col )
-REPLACE_SQFUNC(GetDataTableVector, (ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER))
-{
- CSVData** pData;
- uint64_t typeId;
- g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
-
- if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
- return g_pSquirrel<context>->m_funcOriginals["GetDataTableVector"](sqvm);
-
- CSVData* csv = *pData;
- const int nRow = g_pSquirrel<context>->getinteger(sqvm, 2);
- const int nCol = g_pSquirrel<context>->getinteger(sqvm, 3);
- if (nRow >= csv->dataPointers.size() || nCol >= csv->dataPointers[nRow].size())
- {
- g_pSquirrel<context>->raiseerror(
- sqvm,
- fmt::format(
- "row {} and col {} are outside of range row {} and col {}", nRow, nCol, csv->dataPointers.size(), csv->columns.size())
- .c_str());
- return SQRESULT_ERROR;
- }
-
- g_pSquirrel<context>->pushvector(sqvm, StringToVector(csv->dataPointers[nRow][nCol]));
- return SQRESULT_NOTNULL;
-}
-
-// int function GetDataTableRowMatchingStringValue( var datatable, int col, string value )
-REPLACE_SQFUNC(GetDataTableRowMatchingStringValue, (ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER))
-{
- CSVData** pData;
- uint64_t typeId;
- g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
-
- if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
- return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowMatchingStringValue"](sqvm);
-
- CSVData* csv = *pData;
- int nCol = g_pSquirrel<context>->getinteger(sqvm, 2);
- const char* pStringVal = g_pSquirrel<context>->getstring(sqvm, 3);
- for (int i = 0; i < csv->dataPointers.size(); i++)
- {
- if (!strcmp(csv->dataPointers[i][nCol], pStringVal))
- {
- g_pSquirrel<context>->pushinteger(sqvm, i);
- return SQRESULT_NOTNULL;
- }
- }
-
- g_pSquirrel<context>->pushinteger(sqvm, -1);
- return SQRESULT_NOTNULL;
-}
-
-// int function GetDataTableRowMatchingAssetValue( var datatable, int col, asset value )
-REPLACE_SQFUNC(GetDataTableMatchingAssetValue, (ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER))
-{
- CSVData** pData;
- uint64_t typeId;
- g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
-
- if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
- return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowMatchingAssetValue"](sqvm);
-
- CSVData* csv = *pData;
- int nCol = g_pSquirrel<context>->getinteger(sqvm, 2);
- const char* pStringVal;
- g_pSquirrel<context>->getasset(sqvm, 3, &pStringVal);
- for (int i = 0; i < csv->dataPointers.size(); i++)
- {
- if (!strcmp(csv->dataPointers[i][nCol], pStringVal))
- {
- g_pSquirrel<context>->pushinteger(sqvm, i);
- return SQRESULT_NOTNULL;
- }
- }
-
- g_pSquirrel<context>->pushinteger(sqvm, -1);
- return SQRESULT_NOTNULL;
-}
-
-// int function GetDataTableRowMatchingFloatValue( var datatable, int col, float value )
-REPLACE_SQFUNC(GetDataTableRowMatchingFloatValue, (ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER))
-{
- CSVData** pData;
- uint64_t typeId;
- g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
-
- if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
- return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowMatchingFloatValue"](sqvm);
-
- CSVData* csv = *pData;
- int nCol = g_pSquirrel<context>->getinteger(sqvm, 2);
- const float flFloatVal = g_pSquirrel<context>->getfloat(sqvm, 3);
- for (int i = 0; i < csv->dataPointers.size(); i++)
- {
- if (flFloatVal == std::stof(csv->dataPointers[i][nCol]))
- {
- g_pSquirrel<context>->pushinteger(sqvm, i);
- return SQRESULT_NOTNULL;
- }
- }
-
- g_pSquirrel<context>->pushinteger(sqvm, -1);
- return SQRESULT_NOTNULL;
-}
-
-// int function GetDataTableRowMatchingIntValue( var datatable, int col, int value )
-REPLACE_SQFUNC(GetDataTableRowMatchingIntValue, (ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER))
-{
- CSVData** pData;
- uint64_t typeId;
- g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
-
- if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
- return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowMatchingIntValue"](sqvm);
-
- CSVData* csv = *pData;
- int nCol = g_pSquirrel<context>->getinteger(sqvm, 2);
- const int nIntVal = g_pSquirrel<context>->getinteger(sqvm, 3);
- for (int i = 0; i < csv->dataPointers.size(); i++)
- {
- if (nIntVal == std::stoi(csv->dataPointers[i][nCol]))
- {
- g_pSquirrel<context>->pushinteger(sqvm, i);
- return SQRESULT_NOTNULL;
- }
- }
-
- g_pSquirrel<context>->pushinteger(sqvm, -1);
- return SQRESULT_NOTNULL;
-}
-
-// int function GetDataTableRowMatchingVectorValue( var datatable, int col, vector value )
-REPLACE_SQFUNC(GetDataTableRowMatchingVectorValue, (ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER))
-{
- CSVData** pData;
- uint64_t typeId;
- g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
-
- if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
- return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowMatchingVectorValue"](sqvm);
-
- CSVData* csv = *pData;
- int nCol = g_pSquirrel<context>->getinteger(sqvm, 2);
- const Vector3 vVectorVal = g_pSquirrel<context>->getvector(sqvm, 3);
-
- for (int i = 0; i < csv->dataPointers.size(); i++)
- {
- if (vVectorVal == StringToVector(csv->dataPointers[i][nCol]))
- {
- g_pSquirrel<context>->pushinteger(sqvm, i);
- return SQRESULT_NOTNULL;
- }
- }
-
- g_pSquirrel<context>->pushinteger(sqvm, -1);
- return SQRESULT_NOTNULL;
-}
-
-// int function GetDataTableRowGreaterThanOrEqualToIntValue( var datatable, int col, int value )
-REPLACE_SQFUNC(GetDataTableRowGreaterThanOrEqualToIntValue, (ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER))
-{
- CSVData** pData;
- uint64_t typeId;
- g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
-
- if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
- return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowGreaterThanOrEqualToIntValue"](sqvm);
-
- CSVData* csv = *pData;
- int nCol = g_pSquirrel<context>->getinteger(sqvm, 2);
- const int nIntVal = g_pSquirrel<context>->getinteger(sqvm, 3);
- for (int i = 0; i < csv->dataPointers.size(); i++)
- {
- if (nIntVal >= std::stoi(csv->dataPointers[i][nCol]))
- {
- spdlog::info("datatable not loaded");
- g_pSquirrel<context>->pushinteger(sqvm, 1);
- return SQRESULT_NOTNULL;
- }
- }
-
- g_pSquirrel<context>->pushinteger(sqvm, -1);
- return SQRESULT_NOTNULL;
-}
-
-// int function GetDataTableRowLessThanOrEqualToIntValue( var datatable, int col, int value )
-REPLACE_SQFUNC(GetDataTableRowLessThanOrEqualToIntValue, (ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER))
-{
- CSVData** pData;
- uint64_t typeId;
- g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
-
- if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
- return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowLessThanOrEqualToIntValue"](sqvm);
-
- CSVData* csv = *pData;
- int nCol = g_pSquirrel<context>->getinteger(sqvm, 2);
- const int nIntVal = g_pSquirrel<context>->getinteger(sqvm, 3);
- for (int i = 0; i < csv->dataPointers.size(); i++)
- {
- if (nIntVal <= std::stoi(csv->dataPointers[i][nCol]))
- {
- g_pSquirrel<context>->pushinteger(sqvm, i);
- return SQRESULT_NOTNULL;
- }
- }
-
- g_pSquirrel<context>->pushinteger(sqvm, -1);
- return SQRESULT_NOTNULL;
-}
-
-// int function GetDataTableRowGreaterThanOrEqualToFloatValue( var datatable, int col, float value )
-REPLACE_SQFUNC(GetDataTableRowGreaterThanOrEqualToFloatValue, (ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER))
-{
- CSVData** pData;
- uint64_t typeId;
- g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
-
- if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
- return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowGreaterThanOrEqualToFloatValue"](sqvm);
-
- CSVData* csv = *pData;
- int nCol = g_pSquirrel<context>->getinteger(sqvm, 2);
- const float flFloatVal = g_pSquirrel<context>->getfloat(sqvm, 3);
- for (int i = 0; i < csv->dataPointers.size(); i++)
- {
- if (flFloatVal >= std::stof(csv->dataPointers[i][nCol]))
- {
- g_pSquirrel<context>->pushinteger(sqvm, i);
- return SQRESULT_NOTNULL;
- }
- }
-
- g_pSquirrel<context>->pushinteger(sqvm, -1);
- return SQRESULT_NOTNULL;
-}
-
-// int function GetDataTableRowLessThanOrEqualToFloatValue( var datatable, int col, float value )
-REPLACE_SQFUNC(GetDataTableRowLessThanOrEqualToFloatValue, (ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER))
-{
- CSVData** pData;
- uint64_t typeId;
- g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
-
- if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
- return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowLessThanOrEqualToFloatValue"](sqvm);
-
- CSVData* csv = *pData;
- int nCol = g_pSquirrel<context>->getinteger(sqvm, 2);
- const float flFloatVal = g_pSquirrel<context>->getfloat(sqvm, 3);
- for (int i = 0; i < csv->dataPointers.size(); i++)
- {
- if (flFloatVal <= std::stof(csv->dataPointers[i][nCol]))
- {
- g_pSquirrel<context>->pushinteger(sqvm, i);
- return SQRESULT_NOTNULL;
- }
- }
-
- g_pSquirrel<context>->pushinteger(sqvm, -1);
- return SQRESULT_NOTNULL;
-}
-
-std::string DataTableToString(Datatable* datatable)
-{
- std::string sCSVString;
-
- // write columns
- bool bShouldComma = false;
- for (int i = 0; i < datatable->numColumns; i++)
- {
- if (bShouldComma)
- sCSVString += ',';
- else
- bShouldComma = true;
-
- sCSVString += datatable->columnInfo[i].name;
- }
-
- // write rows
- for (int row = 0; row < datatable->numRows; row++)
- {
- sCSVString += '\n';
-
- bool bShouldComma = false;
- for (int col = 0; col < datatable->numColumns; col++)
- {
- if (bShouldComma)
- sCSVString += ',';
- else
- bShouldComma = true;
-
- // output typed data
- ColumnInfo column = datatable->columnInfo[col];
- const void* pUntypedVal = datatable->data + column.offset + row * datatable->rowInfo;
- switch (column.type)
- {
- case DatatableType::BOOL:
- {
- sCSVString += *(bool*)pUntypedVal ? '1' : '0';
- break;
- }
-
- case DatatableType::INT:
- {
- sCSVString += std::to_string(*(int*)pUntypedVal);
- break;
- }
-
- case DatatableType::FLOAT:
- {
- sCSVString += std::to_string(*(float*)pUntypedVal);
- break;
- }
-
- case DatatableType::VECTOR:
- {
- Vector3* pVector = (Vector3*)(pUntypedVal);
- sCSVString += fmt::format("<{},{},{}>", pVector->x, pVector->y, pVector->z);
- break;
- }
-
- case DatatableType::STRING:
- case DatatableType::ASSET:
- case DatatableType::UNK_STRING:
- {
- sCSVString += fmt::format("\"{}\"", *(char**)pUntypedVal);
- break;
- }
- }
- }
- }
-
- return sCSVString;
-}
-
-void DumpDatatable(const char* pDatatablePath)
-{
- Datatable* pDatatable = (Datatable*)g_pPakLoadManager->LoadFile(pDatatablePath);
- if (!pDatatable)
- {
- spdlog::error("couldn't load datatable {} (rpak containing it may not be loaded?)", pDatatablePath);
- return;
- }
-
- std::string sOutputPath(fmt::format("{}/scripts/datatable/{}.csv", g_pModName, fs::path(pDatatablePath).stem().string()));
- std::string sDatatableContents(DataTableToString(pDatatable));
-
- fs::create_directories(fs::path(sOutputPath).remove_filename());
- std::ofstream outputStream(sOutputPath);
- outputStream.write(sDatatableContents.c_str(), sDatatableContents.size());
- outputStream.close();
-
- spdlog::info("dumped datatable {} {} to {}", pDatatablePath, (void*)pDatatable, sOutputPath);
-}
-
-void ConCommand_dump_datatable(const CCommand& args)
-{
- if (args.ArgC() < 2)
- {
- spdlog::info("usage: dump_datatable datatable/tablename.rpak");
- return;
- }
-
- DumpDatatable(args.Arg(1));
-}
-
-void ConCommand_dump_datatables(const CCommand& args)
-{
- // likely not a comprehensive list, might be missing a couple?
- static const std::vector<const char*> VANILLA_DATATABLE_PATHS = {
- "datatable/burn_meter_rewards.rpak",
- "datatable/burn_meter_store.rpak",
- "datatable/calling_cards.rpak",
- "datatable/callsign_icons.rpak",
- "datatable/camo_skins.rpak",
- "datatable/default_pilot_loadouts.rpak",
- "datatable/default_titan_loadouts.rpak",
- "datatable/faction_leaders.rpak",
- "datatable/fd_awards.rpak",
- "datatable/features_mp.rpak",
- "datatable/non_loadout_weapons.rpak",
- "datatable/pilot_abilities.rpak",
- "datatable/pilot_executions.rpak",
- "datatable/pilot_passives.rpak",
- "datatable/pilot_properties.rpak",
- "datatable/pilot_weapons.rpak",
- "datatable/pilot_weapon_features.rpak",
- "datatable/pilot_weapon_mods.rpak",
- "datatable/pilot_weapon_mods_common.rpak",
- "datatable/playlist_items.rpak",
- "datatable/titans_mp.rpak",
- "datatable/titan_abilities.rpak",
- "datatable/titan_executions.rpak",
- "datatable/titan_fd_upgrades.rpak",
- "datatable/titan_nose_art.rpak",
- "datatable/titan_passives.rpak",
- "datatable/titan_primary_mods.rpak",
- "datatable/titan_primary_mods_common.rpak",
- "datatable/titan_primary_weapons.rpak",
- "datatable/titan_properties.rpak",
- "datatable/titan_skins.rpak",
- "datatable/titan_voices.rpak",
- "datatable/unlocks_faction_level.rpak",
- "datatable/unlocks_fd_titan_level.rpak",
- "datatable/unlocks_player_level.rpak",
- "datatable/unlocks_random.rpak",
- "datatable/unlocks_titan_level.rpak",
- "datatable/unlocks_weapon_level_pilot.rpak",
- "datatable/weapon_skins.rpak",
- "datatable/xp_per_faction_level.rpak",
- "datatable/xp_per_fd_titan_level.rpak",
- "datatable/xp_per_player_level.rpak",
- "datatable/xp_per_titan_level.rpak",
- "datatable/xp_per_weapon_level.rpak",
- "datatable/faction_leaders_dropship_anims.rpak",
- "datatable/score_events.rpak",
- "datatable/startpoints.rpak",
- "datatable/sp_levels.rpak",
- "datatable/community_entries.rpak",
- "datatable/spotlight_images.rpak",
- "datatable/death_hints_mp.rpak",
- "datatable/flightpath_assets.rpak",
- "datatable/earn_meter_mp.rpak",
- "datatable/battle_chatter_voices.rpak",
- "datatable/battle_chatter.rpak",
- "datatable/titan_os_conversations.rpak",
- "datatable/faction_dialogue.rpak",
- "datatable/grunt_chatter_mp.rpak",
- "datatable/spectre_chatter_mp.rpak",
- "datatable/pain_death_sounds.rpak",
- "datatable/caller_ids_mp.rpak"};
-
- for (const char* datatable : VANILLA_DATATABLE_PATHS)
- DumpDatatable(datatable);
-}
-
-ON_DLL_LOAD_RELIESON("server.dll", ServerScriptDatatables, ServerSquirrel, (CModule module))
-{
- SQ_GetDatatableInternal<ScriptContext::SERVER> = module.Offset(0x1250f0).RCast<Datatable* (*)(HSquirrelVM*)>();
-}
-
-ON_DLL_LOAD_RELIESON("client.dll", ClientScriptDatatables, ClientSquirrel, (CModule module))
-{
- SQ_GetDatatableInternal<ScriptContext::CLIENT> = module.Offset(0x1C9070).RCast<Datatable* (*)(HSquirrelVM*)>();
- SQ_GetDatatableInternal<ScriptContext::UI> = SQ_GetDatatableInternal<ScriptContext::CLIENT>;
-}
-
-ON_DLL_LOAD_RELIESON("engine.dll", SharedScriptDataTables, ConVar, (CModule module))
-{
- Cvar_ns_prefer_datatable_from_disk = new ConVar(
- "ns_prefer_datatable_from_disk",
- IsDedicatedServer() && CommandLine()->CheckParm("-nopakdedi") ? "1" : "0",
- FCVAR_NONE,
- "whether to prefer loading datatables from disk, rather than rpak");
-
- RegisterConCommand("dump_datatables", ConCommand_dump_datatables, "dumps all datatables from a hardcoded list", FCVAR_NONE);
- RegisterConCommand("dump_datatable", ConCommand_dump_datatable, "dump a datatable", FCVAR_NONE);
-}
diff --git a/NorthstarDLL/scripts/scripthttprequesthandler.cpp b/NorthstarDLL/scripts/scripthttprequesthandler.cpp
deleted file mode 100644
index aa75127a..00000000
--- a/NorthstarDLL/scripts/scripthttprequesthandler.cpp
+++ /dev/null
@@ -1,585 +0,0 @@
-#include "scripthttprequesthandler.h"
-#include "util/version.h"
-#include "squirrel/squirrel.h"
-#include "core/tier0.h"
-
-HttpRequestHandler* g_httpRequestHandler;
-
-bool IsHttpDisabled()
-{
- const static bool bIsHttpDisabled = CommandLine()->FindParm("-disablehttprequests");
- return bIsHttpDisabled;
-}
-
-bool IsLocalHttpAllowed()
-{
- const static bool bIsLocalHttpAllowed = CommandLine()->FindParm("-allowlocalhttp");
- return bIsLocalHttpAllowed;
-}
-
-bool DisableHttpSsl()
-{
- const static bool bDisableHttpSsl = CommandLine()->FindParm("-disablehttpssl");
- return bDisableHttpSsl;
-}
-
-HttpRequestHandler::HttpRequestHandler()
-{
- // Cache the launch parameters as early as possible in order to avoid possible exploits that change them at runtime.
- IsHttpDisabled();
- IsLocalHttpAllowed();
- DisableHttpSsl();
-}
-
-void HttpRequestHandler::StartHttpRequestHandler()
-{
- if (IsRunning())
- {
- spdlog::warn("%s was called while IsRunning() is true!", __FUNCTION__);
- return;
- }
-
- m_bIsHttpRequestHandlerRunning = true;
- spdlog::info("HttpRequestHandler started.");
-}
-
-void HttpRequestHandler::StopHttpRequestHandler()
-{
- if (!IsRunning())
- {
- spdlog::warn("%s was called while IsRunning() is false", __FUNCTION__);
- return;
- }
-
- m_bIsHttpRequestHandlerRunning = false;
- spdlog::info("HttpRequestHandler stopped.");
-}
-
-bool IsHttpDestinationHostAllowed(const std::string& host, std::string& outHostname, std::string& outAddress, std::string& outPort)
-{
- CURLU* url = curl_url();
- if (!url)
- {
- spdlog::error("Failed to call curl_url() for http request.");
- return false;
- }
-
- if (curl_url_set(url, CURLUPART_URL, host.c_str(), CURLU_DEFAULT_SCHEME) != CURLUE_OK)
- {
- spdlog::error("Failed to parse destination URL for http request.");
-
- curl_url_cleanup(url);
- return false;
- }
-
- char* urlHostname = nullptr;
- if (curl_url_get(url, CURLUPART_HOST, &urlHostname, 0) != CURLUE_OK)
- {
- spdlog::error("Failed to parse hostname from destination URL for http request.");
-
- curl_url_cleanup(url);
- return false;
- }
-
- char* urlScheme = nullptr;
- if (curl_url_get(url, CURLUPART_SCHEME, &urlScheme, CURLU_DEFAULT_SCHEME) != CURLUE_OK)
- {
- spdlog::error("Failed to parse scheme from destination URL for http request.");
-
- curl_url_cleanup(url);
- curl_free(urlHostname);
- return false;
- }
-
- char* urlPort = nullptr;
- if (curl_url_get(url, CURLUPART_PORT, &urlPort, CURLU_DEFAULT_PORT) != CURLUE_OK)
- {
- spdlog::error("Failed to parse port from destination URL for http request.");
-
- curl_url_cleanup(url);
- curl_free(urlHostname);
- curl_free(urlScheme);
- return false;
- }
-
- // Resolve the hostname into an address.
- addrinfo* result;
- addrinfo hints;
- std::memset(&hints, 0, sizeof(addrinfo));
- hints.ai_family = AF_UNSPEC;
-
- if (getaddrinfo(urlHostname, urlScheme, &hints, &result) != 0)
- {
- spdlog::error("Failed to resolve http request destination {} using getaddrinfo().", urlHostname);
-
- curl_url_cleanup(url);
- curl_free(urlHostname);
- curl_free(urlScheme);
- curl_free(urlPort);
- return false;
- }
-
- bool bFoundIPv6 = false;
- sockaddr_in* sockaddr_ipv4 = nullptr;
- for (addrinfo* info = result; info; info = info->ai_next)
- {
- if (info->ai_family == AF_INET)
- {
- sockaddr_ipv4 = (sockaddr_in*)info->ai_addr;
- break;
- }
-
- bFoundIPv6 = bFoundIPv6 || info->ai_family == AF_INET6;
- }
-
- if (sockaddr_ipv4 == nullptr)
- {
- if (bFoundIPv6)
- {
- spdlog::error("Only IPv4 destinations are supported for HTTP requests. To allow IPv6, launch the game using -allowlocalhttp.");
- }
- else
- {
- spdlog::error("Failed to resolve http request destination {} into a valid IPv4 address.", urlHostname);
- }
-
- curl_free(urlHostname);
- curl_free(urlScheme);
- curl_free(urlPort);
- curl_url_cleanup(url);
-
- return false;
- }
-
- // Fast checks for private ranges of IPv4.
- // clang-format off
- {
- auto addrBytes = sockaddr_ipv4->sin_addr.S_un.S_un_b;
-
- if (addrBytes.s_b1 == 10 // 10.0.0.0 - 10.255.255.255 (Class A Private)
- || addrBytes.s_b1 == 172 && addrBytes.s_b2 >= 16 && addrBytes.s_b2 <= 31 // 172.16.0.0 - 172.31.255.255 (Class B Private)
- || addrBytes.s_b1 == 192 && addrBytes.s_b2 == 168 // 192.168.0.0 - 192.168.255.255 (Class C Private)
- || addrBytes.s_b1 == 192 && addrBytes.s_b2 == 0 && addrBytes.s_b3 == 0 // 192.0.0.0 - 192.0.0.255 (IETF Assignment)
- || addrBytes.s_b1 == 192 && addrBytes.s_b2 == 0 && addrBytes.s_b3 == 2 // 192.0.2.0 - 192.0.2.255 (TEST-NET-1)
- || addrBytes.s_b1 == 192 && addrBytes.s_b2 == 88 && addrBytes.s_b3 == 99 // 192.88.99.0 - 192.88.99.255 (IPv4-IPv6 Relay)
- || addrBytes.s_b1 == 192 && addrBytes.s_b2 >= 18 && addrBytes.s_b2 <= 19 // 192.18.0.0 - 192.19.255.255 (Internet Benchmark)
- || addrBytes.s_b1 == 192 && addrBytes.s_b2 == 51 && addrBytes.s_b3 == 100 // 192.51.100.0 - 192.51.100.255 (TEST-NET-2)
- || addrBytes.s_b1 == 203 && addrBytes.s_b2 == 0 && addrBytes.s_b3 == 113 // 203.0.113.0 - 203.0.113.255 (TEST-NET-3)
- || addrBytes.s_b1 == 169 && addrBytes.s_b2 == 254 // 169.254.00 - 169.254.255.255 (Link-local/APIPA)
- || addrBytes.s_b1 == 127 // 127.0.0.0 - 127.255.255.255 (Loopback)
- || addrBytes.s_b1 == 0 // 0.0.0.0 - 0.255.255.255 (Current network)
- || addrBytes.s_b1 == 100 && addrBytes.s_b2 >= 64 && addrBytes.s_b2 <= 127 // 100.64.0.0 - 100.127.255.255 (Shared address space)
- || sockaddr_ipv4->sin_addr.S_un.S_addr == 0xFFFFFFFF // 255.255.255.255 (Broadcast)
- || addrBytes.s_b1 >= 224 && addrBytes.s_b2 <= 239 // 224.0.0.0 - 239.255.255.255 (Multicast)
- || addrBytes.s_b1 == 233 && addrBytes.s_b2 == 252 && addrBytes.s_b3 == 0 // 233.252.0.0 - 233.252.0.255 (MCAST-TEST-NET)
- || addrBytes.s_b1 >= 240 && addrBytes.s_b4 <= 254) // 240.0.0.0 - 255.255.255.254 (Future Use Class E)
- {
- curl_free(urlHostname);
- curl_free(urlScheme);
- curl_free(urlPort);
- curl_url_cleanup(url);
-
- return false;
- }
- }
-
- // clang-format on
-
- char resolvedStr[INET_ADDRSTRLEN];
- inet_ntop(AF_INET, &sockaddr_ipv4->sin_addr, resolvedStr, INET_ADDRSTRLEN);
-
- // Use the resolved address as the new request host.
- outHostname = urlHostname;
- outAddress = resolvedStr;
- outPort = urlPort;
-
- freeaddrinfo(result);
-
- curl_free(urlHostname);
- curl_free(urlScheme);
- curl_free(urlPort);
- curl_url_cleanup(url);
-
- return true;
-}
-
-size_t HttpCurlWriteToStringBufferCallback(char* contents, size_t size, size_t nmemb, void* userp)
-{
- ((std::string*)userp)->append((char*)contents, size * nmemb);
- return size * nmemb;
-}
-
-template <ScriptContext context> int HttpRequestHandler::MakeHttpRequest(const HttpRequest& requestParameters)
-{
- if (!IsRunning())
- {
- spdlog::warn("%s was called while IsRunning() is false!", __FUNCTION__);
- return -1;
- }
-
- if (IsHttpDisabled())
- {
- spdlog::warn("NS_InternalMakeHttpRequest called while the game is running with -disablehttprequests."
- " Please check if requests are allowed using NSIsHttpEnabled() first.");
- return -1;
- }
-
- bool bAllowLocalHttp = IsLocalHttpAllowed();
-
- // This handle will be returned to Squirrel so it can wait for the response and assign a callback for it.
- int handle = ++m_iLastRequestHandle;
-
- std::thread requestThread(
- [this, handle, requestParameters, bAllowLocalHttp]()
- {
- std::string hostname, resolvedAddress, resolvedPort;
-
- if (!bAllowLocalHttp)
- {
- if (!IsHttpDestinationHostAllowed(requestParameters.baseUrl, hostname, resolvedAddress, resolvedPort))
- {
- spdlog::warn(
- "HttpRequestHandler::MakeHttpRequest attempted to make a request to a private network. This is only allowed when "
- "running the game with -allowlocalhttp.");
- g_pSquirrel<context>->AsyncCall(
- "NSHandleFailedHttpRequest",
- handle,
- (int)0,
- "Cannot make HTTP requests to private network hosts without -allowlocalhttp. Check your console for more "
- "information.");
- return;
- }
- }
-
- CURL* curl = curl_easy_init();
- if (!curl)
- {
- spdlog::error("HttpRequestHandler::MakeHttpRequest failed to init libcurl for request.");
- g_pSquirrel<context>->AsyncCall(
- "NSHandleFailedHttpRequest", handle, static_cast<int>(CURLE_FAILED_INIT), curl_easy_strerror(CURLE_FAILED_INIT));
- return;
- }
-
- // HEAD has no body.
- if (requestParameters.method == HttpRequestMethod::HRM_HEAD)
- {
- curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
- }
-
- curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, HttpRequestMethod::ToString(requestParameters.method).c_str());
-
- // Only resolve to IPv4 if we don't allow private network requests.
- curl_slist* host = nullptr;
- if (!bAllowLocalHttp)
- {
- curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
- host = curl_slist_append(host, fmt::format("{}:{}:{}", hostname, resolvedPort, resolvedAddress).c_str());
- curl_easy_setopt(curl, CURLOPT_RESOLVE, host);
- }
-
- // Ensure we only allow HTTP or HTTPS.
- curl_easy_setopt(curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
-
- // Allow redirects
- curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
- curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 3L);
-
- // Check if the url already contains a query.
- // If so, we'll know to append with & instead of start with ?
- std::string queryUrl = requestParameters.baseUrl;
- bool bUrlContainsQuery = false;
-
- // If this fails, just ignore the parsing and trust what the user wants to query.
- // Probably will fail but handling it here would be annoying.
- CURLU* curlUrl = curl_url();
- if (curlUrl)
- {
- if (curl_url_set(curlUrl, CURLUPART_URL, queryUrl.c_str(), CURLU_DEFAULT_SCHEME) == CURLUE_OK)
- {
- char* currentQuery;
- if (curl_url_get(curlUrl, CURLUPART_QUERY, &currentQuery, 0) == CURLUE_OK)
- {
- if (currentQuery && std::strlen(currentQuery) != 0)
- {
- bUrlContainsQuery = true;
- }
- }
-
- curl_free(currentQuery);
- }
-
- curl_url_cleanup(curlUrl);
- }
-
- // GET requests, or POST-like requests with an empty body, can have query parameters.
- // Append them to the base url.
- if (HttpRequestMethod::CanHaveQueryParameters(requestParameters.method) &&
- !HttpRequestMethod::UsesCurlPostOptions(requestParameters.method) ||
- requestParameters.body.empty())
- {
- bool isFirstValue = true;
- for (const auto& kv : requestParameters.queryParameters)
- {
- char* key = curl_easy_escape(curl, kv.first.c_str(), kv.first.length());
-
- for (const std::string& queryValue : kv.second)
- {
- char* value = curl_easy_escape(curl, queryValue.c_str(), queryValue.length());
-
- if (isFirstValue && !bUrlContainsQuery)
- {
- queryUrl.append(fmt::format("?{}={}", key, value));
- isFirstValue = false;
- }
- else
- {
- queryUrl.append(fmt::format("&{}={}", key, value));
- }
-
- curl_free(value);
- }
-
- curl_free(key);
- }
- }
-
- // If this method uses POST-like curl options, set those and set the body.
- // The body won't be sent if it's empty anyway, meaning the query parameters above, if any, would be.
- if (HttpRequestMethod::UsesCurlPostOptions(requestParameters.method))
- {
- // Grab the body and set it as a POST field
- curl_easy_setopt(curl, CURLOPT_POST, 1L);
-
- curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, requestParameters.body.length());
- curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, requestParameters.body.c_str());
- }
-
- // Set the full URL for this http request.
- curl_easy_setopt(curl, CURLOPT_URL, queryUrl.c_str());
-
- std::string bodyBuffer;
- std::string headerBuffer;
-
- // Set up buffers to write the response headers and body.
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HttpCurlWriteToStringBufferCallback);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, &bodyBuffer);
- curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, HttpCurlWriteToStringBufferCallback);
- curl_easy_setopt(curl, CURLOPT_HEADERDATA, &headerBuffer);
-
- // Add all the headers for the request.
- curl_slist* headers = nullptr;
-
- // Content-Type header for POST-like requests.
- if (HttpRequestMethod::UsesCurlPostOptions(requestParameters.method) && !requestParameters.body.empty())
- {
- headers = curl_slist_append(headers, fmt::format("Content-Type: {}", requestParameters.contentType).c_str());
- }
-
- for (const auto& kv : requestParameters.headers)
- {
- for (const std::string& headerValue : kv.second)
- {
- headers = curl_slist_append(headers, fmt::format("{}: {}", kv.first, headerValue).c_str());
- }
- }
-
- if (headers != nullptr)
- {
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
- }
-
- // Disable SSL checks if requested by the user.
- if (DisableHttpSsl())
- {
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYSTATUS, 0L);
- }
-
- // Enforce the Northstar user agent, unless an override was specified.
- if (requestParameters.userAgent.empty())
- {
- curl_easy_setopt(curl, CURLOPT_USERAGENT, &NSUserAgent);
- }
- else
- {
- curl_easy_setopt(curl, CURLOPT_USERAGENT, requestParameters.userAgent.c_str());
- }
-
- // Set the timeout for this request. Max 60 seconds so mods can't just spin up native threads all the time.
- curl_easy_setopt(curl, CURLOPT_TIMEOUT, std::clamp<long>(requestParameters.timeout, 1, 60));
-
- CURLcode result = curl_easy_perform(curl);
- if (IsRunning())
- {
- if (result == CURLE_OK)
- {
- // While the curl request is OK, it could return a non success code.
- // Squirrel side will handle firing the correct callback.
- long httpCode = 0;
- curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
- g_pSquirrel<context>->AsyncCall(
- "NSHandleSuccessfulHttpRequest", handle, static_cast<int>(httpCode), bodyBuffer, headerBuffer);
- }
- else
- {
- // Pass CURL result code & error.
- spdlog::error(
- "curl_easy_perform() failed with code {}, error: {}", static_cast<int>(result), curl_easy_strerror(result));
-
- // If it's an SSL issue, tell the user they may disable SSL checks using -disablehttpssl.
- if (result == CURLE_PEER_FAILED_VERIFICATION || result == CURLE_SSL_CERTPROBLEM ||
- result == CURLE_SSL_INVALIDCERTSTATUS)
- {
- spdlog::error("You can try disabling SSL verifications for this issue using the -disablehttpssl launch argument. "
- "Keep in mind this is potentially dangerous!");
- }
-
- g_pSquirrel<context>->AsyncCall(
- "NSHandleFailedHttpRequest", handle, static_cast<int>(result), curl_easy_strerror(result));
- }
- }
-
- curl_easy_cleanup(curl);
- curl_slist_free_all(headers);
- curl_slist_free_all(host);
- });
-
- requestThread.detach();
- return handle;
-}
-
-// int NS_InternalMakeHttpRequest(int method, string baseUrl, table<string, string> headers, table<string, string> queryParams,
-// string contentType, string body, int timeout, string userAgent)
-template <ScriptContext context> SQRESULT SQ_InternalMakeHttpRequest(HSquirrelVM* sqvm)
-{
- if (!g_httpRequestHandler || !g_httpRequestHandler->IsRunning())
- {
- spdlog::warn("NS_InternalMakeHttpRequest called while the http request handler isn't running.");
- g_pSquirrel<context>->pushinteger(sqvm, -1);
- return SQRESULT_NOTNULL;
- }
-
- if (IsHttpDisabled())
- {
- spdlog::warn("NS_InternalMakeHttpRequest called while the game is running with -disablehttprequests."
- " Please check if requests are allowed using NSIsHttpEnabled() first.");
- g_pSquirrel<context>->pushinteger(sqvm, -1);
- return SQRESULT_NOTNULL;
- }
-
- HttpRequest request;
- request.method = static_cast<HttpRequestMethod::Type>(g_pSquirrel<context>->getinteger(sqvm, 1));
- request.baseUrl = g_pSquirrel<context>->getstring(sqvm, 2);
-
- // Read the tables for headers and query parameters.
- SQTable* headerTable = sqvm->_stackOfCurrentFunction[3]._VAL.asTable;
- for (int idx = 0; idx < headerTable->_numOfNodes; ++idx)
- {
- tableNode* node = &headerTable->_nodes[idx];
-
- if (node->key._Type == OT_STRING && node->val._Type == OT_ARRAY)
- {
- SQArray* valueArray = node->val._VAL.asArray;
- std::vector<std::string> headerValues;
-
- for (int vIdx = 0; vIdx < valueArray->_usedSlots; ++vIdx)
- {
- if (valueArray->_values[vIdx]._Type == OT_STRING)
- {
- headerValues.push_back(valueArray->_values[vIdx]._VAL.asString->_val);
- }
- }
-
- request.headers[node->key._VAL.asString->_val] = headerValues;
- }
- }
-
- SQTable* queryTable = sqvm->_stackOfCurrentFunction[4]._VAL.asTable;
- for (int idx = 0; idx < queryTable->_numOfNodes; ++idx)
- {
- tableNode* node = &queryTable->_nodes[idx];
-
- if (node->key._Type == OT_STRING && node->val._Type == OT_ARRAY)
- {
- SQArray* valueArray = node->val._VAL.asArray;
- std::vector<std::string> queryValues;
-
- for (int vIdx = 0; vIdx < valueArray->_usedSlots; ++vIdx)
- {
- if (valueArray->_values[vIdx]._Type == OT_STRING)
- {
- queryValues.push_back(valueArray->_values[vIdx]._VAL.asString->_val);
- }
- }
-
- request.queryParameters[node->key._VAL.asString->_val] = queryValues;
- }
- }
-
- request.contentType = g_pSquirrel<context>->getstring(sqvm, 5);
- request.body = g_pSquirrel<context>->getstring(sqvm, 6);
- request.timeout = g_pSquirrel<context>->getinteger(sqvm, 7);
- request.userAgent = g_pSquirrel<context>->getstring(sqvm, 8);
-
- int handle = g_httpRequestHandler->MakeHttpRequest<context>(request);
- g_pSquirrel<context>->pushinteger(sqvm, handle);
- return SQRESULT_NOTNULL;
-}
-
-// bool NSIsHttpEnabled()
-template <ScriptContext context> SQRESULT SQ_IsHttpEnabled(HSquirrelVM* sqvm)
-{
- g_pSquirrel<context>->pushbool(sqvm, !IsHttpDisabled());
- return SQRESULT_NOTNULL;
-}
-
-// bool NSIsLocalHttpAllowed()
-template <ScriptContext context> SQRESULT SQ_IsLocalHttpAllowed(HSquirrelVM* sqvm)
-{
- g_pSquirrel<context>->pushbool(sqvm, IsLocalHttpAllowed());
- return SQRESULT_NOTNULL;
-}
-
-template <ScriptContext context> void HttpRequestHandler::RegisterSQFuncs()
-{
- g_pSquirrel<context>->AddFuncRegistration(
- "int",
- "NS_InternalMakeHttpRequest",
- "int method, string baseUrl, table<string, array<string> > headers, table<string, array<string> > queryParams, string contentType, "
- "string body, "
- "int timeout, string userAgent",
- "[Internal use only] Passes the HttpRequest struct fields to be reconstructed in native and used for an http request",
- SQ_InternalMakeHttpRequest<context>);
-
- g_pSquirrel<context>->AddFuncRegistration(
- "bool",
- "NSIsHttpEnabled",
- "",
- "Whether or not HTTP requests are enabled. You can opt-out by starting the game with -disablehttprequests.",
- SQ_IsHttpEnabled<context>);
-
- g_pSquirrel<context>->AddFuncRegistration(
- "bool",
- "NSIsLocalHttpAllowed",
- "",
- "Whether or not HTTP requests can be made to a private network address. You can enable this by starting the game with "
- "-allowlocalhttp.",
- SQ_IsLocalHttpAllowed<context>);
-}
-
-ON_DLL_LOAD_RELIESON("client.dll", HttpRequestHandler_ClientInit, ClientSquirrel, (CModule module))
-{
- g_httpRequestHandler->RegisterSQFuncs<ScriptContext::CLIENT>();
- g_httpRequestHandler->RegisterSQFuncs<ScriptContext::UI>();
-}
-
-ON_DLL_LOAD_RELIESON("server.dll", HttpRequestHandler_ServerInit, ServerSquirrel, (CModule module))
-{
- g_httpRequestHandler->RegisterSQFuncs<ScriptContext::SERVER>();
-}
-
-ON_DLL_LOAD("engine.dll", HttpRequestHandler_Init, (CModule module))
-{
- g_httpRequestHandler = new HttpRequestHandler;
- g_httpRequestHandler->StartHttpRequestHandler();
-}
diff --git a/NorthstarDLL/scripts/scripthttprequesthandler.h b/NorthstarDLL/scripts/scripthttprequesthandler.h
deleted file mode 100644
index f3921f4e..00000000
--- a/NorthstarDLL/scripts/scripthttprequesthandler.h
+++ /dev/null
@@ -1,130 +0,0 @@
-#pragma once
-
-enum class ScriptContext;
-
-// These definitions below should match on the Squirrel side so we can easily pass them along through a function.
-
-/**
- * Allowed methods for an HttpRequest.
- */
-namespace HttpRequestMethod
-{
- enum Type
- {
- HRM_GET = 0,
- HRM_POST = 1,
- HRM_HEAD = 2,
- HRM_PUT = 3,
- HRM_DELETE = 4,
- HRM_PATCH = 5,
- HRM_OPTIONS = 6,
- };
-
- /** Returns the HTTP string representation of the given method. */
- inline std::string ToString(HttpRequestMethod::Type method)
- {
- switch (method)
- {
- case HttpRequestMethod::HRM_GET:
- return "GET";
- case HttpRequestMethod::HRM_POST:
- return "POST";
- case HttpRequestMethod::HRM_HEAD:
- return "HEAD";
- case HttpRequestMethod::HRM_PUT:
- return "PUT";
- case HttpRequestMethod::HRM_DELETE:
- return "DELETE";
- case HttpRequestMethod::HRM_PATCH:
- return "PATCH";
- case HttpRequestMethod::HRM_OPTIONS:
- return "OPTIONS";
- default:
- return "INVALID";
- }
- }
-
- /** Whether or not the given method should be treated like a POST for curlopts. */
- bool UsesCurlPostOptions(HttpRequestMethod::Type method)
- {
- switch (method)
- {
- case HttpRequestMethod::HRM_POST:
- case HttpRequestMethod::HRM_PUT:
- case HttpRequestMethod::HRM_DELETE:
- case HttpRequestMethod::HRM_PATCH:
- return true;
- default:
- return false;
- }
- }
-
- /** Whether or not the given http request method can have query parameters in the URL. */
- bool CanHaveQueryParameters(HttpRequestMethod::Type method)
- {
- return method == HttpRequestMethod::HRM_GET || UsesCurlPostOptions(method);
- }
-}; // namespace HttpRequestMethod
-
-/** Contains data about an http request that has been queued. */
-struct HttpRequest
-{
- /** Method used for this http request. */
- HttpRequestMethod::Type method;
-
- /** Base URL of this http request. */
- std::string baseUrl;
-
- /** Headers used for this http request. Some may get overridden or ignored. */
- std::unordered_map<std::string, std::vector<std::string>> headers;
-
- /** Query parameters for this http request. */
- std::unordered_map<std::string, std::vector<std::string>> queryParameters;
-
- /** The content type of this http request. Defaults to text/plain & UTF-8 charset. */
- std::string contentType = "text/plain; charset=utf-8";
-
- /** The body of this http request. If set, will override queryParameters.*/
- std::string body;
-
- /** The timeout for the http request, in seconds. Must be between 1 and 60. */
- int timeout;
-
- /** If set, the override to use for the User-Agent header. */
- std::string userAgent;
-};
-
-/**
- * Handles making HTTP requests and sending the responses back to Squirrel.
- */
-class HttpRequestHandler
-{
-public:
- HttpRequestHandler();
-
- // Start/Stop the HTTP request handler. Right now this doesn't do much.
- void StartHttpRequestHandler();
- void StopHttpRequestHandler();
-
- // Whether or not this http request handler is currently running.
- bool IsRunning() const
- {
- return m_bIsHttpRequestHandlerRunning;
- }
-
- /**
- * Creates a new thread to execute an HTTP request.
- * @param requestParameters The parameters to use for this http request.
- * @returns The handle for the http request being sent, or -1 if the request failed.
- */
- template <ScriptContext context> int MakeHttpRequest(const HttpRequest& requestParameters);
-
- /** Registers the HTTP request Squirrel functions for the given script context. */
- template <ScriptContext context> void RegisterSQFuncs();
-
-private:
- int m_iLastRequestHandle = 0;
- std::atomic_bool m_bIsHttpRequestHandlerRunning = false;
-};
-
-extern HttpRequestHandler* g_httpRequestHandler;
diff --git a/NorthstarDLL/scripts/scriptjson.cpp b/NorthstarDLL/scripts/scriptjson.cpp
deleted file mode 100644
index 06bda6f4..00000000
--- a/NorthstarDLL/scripts/scriptjson.cpp
+++ /dev/null
@@ -1,250 +0,0 @@
-#include "squirrel/squirrel.h"
-
-#include "rapidjson/error/en.h"
-#include "rapidjson/document.h"
-#include "rapidjson/writer.h"
-#include "rapidjson/stringbuffer.h"
-
-#ifdef _MSC_VER
-#undef GetObject // fuck microsoft developers
-#endif
-
-template <ScriptContext context> void
-DecodeJsonArray(HSquirrelVM* sqvm, rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>* arr)
-{
- g_pSquirrel<context>->newarray(sqvm, 0);
-
- for (auto& itr : arr->GetArray())
- {
- switch (itr.GetType())
- {
- case rapidjson::kObjectType:
- DecodeJsonTable<context>(sqvm, &itr);
- g_pSquirrel<context>->arrayappend(sqvm, -2);
- break;
- case rapidjson::kArrayType:
- DecodeJsonArray<context>(sqvm, &itr);
- g_pSquirrel<context>->arrayappend(sqvm, -2);
- break;
- case rapidjson::kStringType:
- g_pSquirrel<context>->pushstring(sqvm, itr.GetString(), -1);
- g_pSquirrel<context>->arrayappend(sqvm, -2);
- break;
- case rapidjson::kTrueType:
- case rapidjson::kFalseType:
- g_pSquirrel<context>->pushbool(sqvm, itr.GetBool());
- g_pSquirrel<context>->arrayappend(sqvm, -2);
- break;
- case rapidjson::kNumberType:
- if (itr.IsDouble() || itr.IsFloat())
- g_pSquirrel<context>->pushfloat(sqvm, itr.GetFloat());
- else
- g_pSquirrel<context>->pushinteger(sqvm, itr.GetInt());
- g_pSquirrel<context>->arrayappend(sqvm, -2);
- break;
- }
- }
-}
-
-template <ScriptContext context> void
-DecodeJsonTable(HSquirrelVM* sqvm, rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>* obj)
-{
- g_pSquirrel<context>->newtable(sqvm);
-
- for (auto itr = obj->MemberBegin(); itr != obj->MemberEnd(); itr++)
- {
- switch (itr->value.GetType())
- {
- case rapidjson::kObjectType:
- g_pSquirrel<context>->pushstring(sqvm, itr->name.GetString(), -1);
- DecodeJsonTable<context>(
- sqvm, (rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>*)&itr->value);
- g_pSquirrel<context>->newslot(sqvm, -3, false);
- break;
- case rapidjson::kArrayType:
- g_pSquirrel<context>->pushstring(sqvm, itr->name.GetString(), -1);
- DecodeJsonArray<context>(
- sqvm, (rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>*)&itr->value);
- g_pSquirrel<context>->newslot(sqvm, -3, false);
- break;
- case rapidjson::kStringType:
- g_pSquirrel<context>->pushstring(sqvm, itr->name.GetString(), -1);
- g_pSquirrel<context>->pushstring(sqvm, itr->value.GetString(), -1);
-
- g_pSquirrel<context>->newslot(sqvm, -3, false);
- break;
- case rapidjson::kTrueType:
- case rapidjson::kFalseType:
- g_pSquirrel<context>->pushstring(sqvm, itr->name.GetString(), -1);
- g_pSquirrel<context>->pushbool(sqvm, itr->value.GetBool());
- g_pSquirrel<context>->newslot(sqvm, -3, false);
- break;
- case rapidjson::kNumberType:
- if (itr->value.IsDouble() || itr->value.IsFloat())
- {
- g_pSquirrel<context>->pushstring(sqvm, itr->name.GetString(), -1);
- g_pSquirrel<context>->pushfloat(sqvm, itr->value.GetFloat());
- }
- else
- {
- g_pSquirrel<context>->pushstring(sqvm, itr->name.GetString(), -1);
- g_pSquirrel<context>->pushinteger(sqvm, itr->value.GetInt());
- }
- g_pSquirrel<context>->newslot(sqvm, -3, false);
- break;
- }
- }
-}
-
-template <ScriptContext context> void EncodeJSONTable(
- SQTable* table,
- rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>* obj,
- rapidjson::MemoryPoolAllocator<SourceAllocator>& allocator)
-{
- for (int i = 0; i < table->_numOfNodes; i++)
- {
- tableNode* node = &table->_nodes[i];
- if (node->key._Type == OT_STRING)
- {
- rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>> newObj(rapidjson::kObjectType);
- rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>> newArray(rapidjson::kArrayType);
-
- switch (node->val._Type)
- {
- case OT_STRING:
- obj->AddMember(
- rapidjson::StringRef(node->key._VAL.asString->_val), rapidjson::StringRef(node->val._VAL.asString->_val), allocator);
- break;
- case OT_INTEGER:
- obj->AddMember(rapidjson::StringRef(node->key._VAL.asString->_val), node->val._VAL.asInteger, allocator);
- break;
- case OT_FLOAT:
- obj->AddMember(rapidjson::StringRef(node->key._VAL.asString->_val), node->val._VAL.asFloat, allocator);
- break;
- case OT_BOOL:
- if (node->val._VAL.asInteger)
- {
- obj->AddMember(rapidjson::StringRef(node->key._VAL.asString->_val), true, allocator);
- }
- else
- {
- obj->AddMember(rapidjson::StringRef(node->key._VAL.asString->_val), false, allocator);
- }
- break;
- case OT_TABLE:
- EncodeJSONTable<context>(node->val._VAL.asTable, &newObj, allocator);
- obj->AddMember(rapidjson::StringRef(node->key._VAL.asString->_val), newObj, allocator);
- break;
- case OT_ARRAY:
- EncodeJSONArray<context>(node->val._VAL.asArray, &newArray, allocator);
- obj->AddMember(rapidjson::StringRef(node->key._VAL.asString->_val), newArray, allocator);
- break;
- default:
- spdlog::warn("SQ_EncodeJSON: squirrel type {} not supported", SQTypeNameFromID(node->val._Type));
- break;
- }
- }
- }
-}
-
-template <ScriptContext context> void EncodeJSONArray(
- SQArray* arr,
- rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>* obj,
- rapidjson::MemoryPoolAllocator<SourceAllocator>& allocator)
-{
- for (int i = 0; i < arr->_usedSlots; i++)
- {
- SQObject* node = &arr->_values[i];
-
- rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>> newObj(rapidjson::kObjectType);
- rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>> newArray(rapidjson::kArrayType);
-
- switch (node->_Type)
- {
- case OT_STRING:
- obj->PushBack(rapidjson::StringRef(node->_VAL.asString->_val), allocator);
- break;
- case OT_INTEGER:
- obj->PushBack(node->_VAL.asInteger, allocator);
- break;
- case OT_FLOAT:
- obj->PushBack(node->_VAL.asFloat, allocator);
- break;
- case OT_BOOL:
- if (node->_VAL.asInteger)
- obj->PushBack(rapidjson::StringRef("true"), allocator);
- else
- obj->PushBack(rapidjson::StringRef("false"), allocator);
- break;
- case OT_TABLE:
- EncodeJSONTable<context>(node->_VAL.asTable, &newObj, allocator);
- obj->PushBack(newObj, allocator);
- break;
- case OT_ARRAY:
- EncodeJSONArray<context>(node->_VAL.asArray, &newArray, allocator);
- obj->PushBack(newArray, allocator);
- break;
- default:
- spdlog::info("SQ encode Json type {} not supported", SQTypeNameFromID(node->_Type));
- }
- }
-}
-
-ADD_SQFUNC(
- "table",
- DecodeJSON,
- "string json, bool fatalParseErrors = false",
- "converts a json string to a squirrel table",
- ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER)
-{
- const char* pJson = g_pSquirrel<context>->getstring(sqvm, 1);
- const bool bFatalParseErrors = g_pSquirrel<context>->getbool(sqvm, 2);
-
- rapidjson_document doc;
- doc.Parse(pJson);
- if (doc.HasParseError())
- {
- g_pSquirrel<context>->newtable(sqvm);
-
- std::string sErrorString = fmt::format(
- "Failed parsing json file: encountered parse error \"{}\" at offset {}",
- GetParseError_En(doc.GetParseError()),
- doc.GetErrorOffset());
-
- if (bFatalParseErrors)
- {
- g_pSquirrel<context>->raiseerror(sqvm, sErrorString.c_str());
- return SQRESULT_ERROR;
- }
-
- spdlog::warn(sErrorString);
- return SQRESULT_NOTNULL;
- }
-
- DecodeJsonTable<context>(sqvm, (rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>*)&doc);
- return SQRESULT_NOTNULL;
-}
-
-ADD_SQFUNC(
- "string",
- EncodeJSON,
- "table data",
- "converts a squirrel table to a json string",
- ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER)
-{
- rapidjson_document doc;
- doc.SetObject();
-
- // temp until this is just the func parameter type
- HSquirrelVM* vm = (HSquirrelVM*)sqvm;
- SQTable* table = vm->_stackOfCurrentFunction[1]._VAL.asTable;
- EncodeJSONTable<context>(table, &doc, doc.GetAllocator());
-
- rapidjson::StringBuffer buffer;
- rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
- doc.Accept(writer);
- const char* pJsonString = buffer.GetString();
-
- g_pSquirrel<context>->pushstring(sqvm, pJsonString, -1);
- return SQRESULT_NOTNULL;
-}
diff --git a/NorthstarDLL/scripts/scriptjson.h b/NorthstarDLL/scripts/scriptjson.h
deleted file mode 100644
index b747106b..00000000
--- a/NorthstarDLL/scripts/scriptjson.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-
-#include "rapidjson/document.h"
-#include "rapidjson/writer.h"
-#include "rapidjson/stringbuffer.h"
-
-template <ScriptContext context> void EncodeJSONTable(
- SQTable* table,
- rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>* obj,
- rapidjson::MemoryPoolAllocator<SourceAllocator>& allocator);
-
-template <ScriptContext context> void
-DecodeJsonTable(HSquirrelVM* sqvm, rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>* obj);
diff --git a/NorthstarDLL/scripts/scriptutility.cpp b/NorthstarDLL/scripts/scriptutility.cpp
deleted file mode 100644
index 4b92fa02..00000000
--- a/NorthstarDLL/scripts/scriptutility.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-#include "squirrel/squirrel.h"
-#include "client/r2client.h"
-#include "engine/r2engine.h"
-
-// asset function StringToAsset( string assetName )
-ADD_SQFUNC(
- "asset",
- StringToAsset,
- "string assetName",
- "converts a given string to an asset",
- ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER)
-{
- g_pSquirrel<context>->pushasset(sqvm, g_pSquirrel<context>->getstring(sqvm, 1), -1);
- return SQRESULT_NOTNULL;
-}
-
-// string function NSGetLocalPlayerUID()
-ADD_SQFUNC(
- "string", NSGetLocalPlayerUID, "", "Returns the local player's uid.", ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER)
-{
- if (g_pLocalPlayerUserID)
- {
- g_pSquirrel<context>->pushstring(sqvm, g_pLocalPlayerUserID);
- return SQRESULT_NOTNULL;
- }
-
- return SQRESULT_NULL;
-}
diff --git a/NorthstarDLL/scripts/server/miscserverfixes.cpp b/NorthstarDLL/scripts/server/miscserverfixes.cpp
deleted file mode 100644
index 48c2c111..00000000
--- a/NorthstarDLL/scripts/server/miscserverfixes.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-
-ON_DLL_LOAD("server.dll", MiscServerFixes, (CModule module))
-{
- // nop out call to VGUI shutdown since it crashes the game when quitting from the console
- module.Offset(0x154A96).NOP(5);
-}
diff --git a/NorthstarDLL/scripts/server/miscserverscript.cpp b/NorthstarDLL/scripts/server/miscserverscript.cpp
deleted file mode 100644
index ed6e4800..00000000
--- a/NorthstarDLL/scripts/server/miscserverscript.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-#include "squirrel/squirrel.h"
-#include "masterserver/masterserver.h"
-#include "server/auth/serverauthentication.h"
-#include "dedicated/dedicated.h"
-#include "client/r2client.h"
-#include "server/r2server.h"
-
-#include <filesystem>
-
-ADD_SQFUNC("void", NSEarlyWritePlayerPersistenceForLeave, "entity player", "", ScriptContext::SERVER)
-{
- const CBasePlayer* pPlayer = g_pSquirrel<context>->template getentity<CBasePlayer>(sqvm, 1);
- if (!pPlayer)
- {
- spdlog::warn("NSEarlyWritePlayerPersistenceForLeave got null player");
-
- g_pSquirrel<context>->pushbool(sqvm, false);
- return SQRESULT_NOTNULL;
- }
-
- CBaseClient* pClient = &g_pClientArray[pPlayer->m_nPlayerIndex - 1];
- if (g_pServerAuthentication->m_PlayerAuthenticationData.find(pClient) == g_pServerAuthentication->m_PlayerAuthenticationData.end())
- {
- g_pSquirrel<context>->pushbool(sqvm, false);
- return SQRESULT_NOTNULL;
- }
-
- g_pServerAuthentication->m_PlayerAuthenticationData[pClient].needPersistenceWriteOnLeave = false;
- g_pServerAuthentication->WritePersistentData(pClient);
- return SQRESULT_NULL;
-}
-
-ADD_SQFUNC("bool", NSIsWritingPlayerPersistence, "", "", ScriptContext::SERVER)
-{
- g_pSquirrel<context>->pushbool(sqvm, g_pMasterServerManager->m_bSavingPersistentData);
- return SQRESULT_NOTNULL;
-}
-
-ADD_SQFUNC("bool", NSIsPlayerLocalPlayer, "entity player", "", ScriptContext::SERVER)
-{
- const CBasePlayer* pPlayer = g_pSquirrel<ScriptContext::SERVER>->template getentity<CBasePlayer>(sqvm, 1);
- if (!pPlayer)
- {
- spdlog::warn("NSIsPlayerLocalPlayer got null player");
-
- g_pSquirrel<context>->pushbool(sqvm, false);
- return SQRESULT_NOTNULL;
- }
-
- CBaseClient* pClient = &g_pClientArray[pPlayer->m_nPlayerIndex - 1];
- g_pSquirrel<context>->pushbool(sqvm, !strcmp(g_pLocalPlayerUserID, pClient->m_UID));
- return SQRESULT_NOTNULL;
-}
-
-ADD_SQFUNC("bool", NSIsDedicated, "", "", ScriptContext::SERVER)
-{
- g_pSquirrel<context>->pushbool(sqvm, IsDedicatedServer());
- return SQRESULT_NOTNULL;
-}
-
-ADD_SQFUNC(
- "bool",
- NSDisconnectPlayer,
- "entity player, string reason",
- "Disconnects the player from the server with the given reason",
- ScriptContext::SERVER)
-{
- const CBasePlayer* pPlayer = g_pSquirrel<context>->template getentity<CBasePlayer>(sqvm, 1);
- const char* reason = g_pSquirrel<context>->getstring(sqvm, 2);
-
- if (!pPlayer)
- {
- spdlog::warn("Attempted to call NSDisconnectPlayer() with null player.");
-
- g_pSquirrel<context>->pushbool(sqvm, false);
- return SQRESULT_NOTNULL;
- }
-
- // Shouldn't happen but I like sanity checks.
- CBaseClient* pClient = &g_pClientArray[pPlayer->m_nPlayerIndex - 1];
- if (!pClient)
- {
- spdlog::warn("NSDisconnectPlayer(): player entity has null CBaseClient!");
-
- g_pSquirrel<context>->pushbool(sqvm, false);
- return SQRESULT_NOTNULL;
- }
-
- if (reason)
- {
- CBaseClient__Disconnect(pClient, 1, reason);
- }
- else
- {
- CBaseClient__Disconnect(pClient, 1, "Disconnected by the server.");
- }
-
- g_pSquirrel<context>->pushbool(sqvm, true);
- return SQRESULT_NOTNULL;
-}
diff --git a/NorthstarDLL/scripts/server/scriptuserinfo.cpp b/NorthstarDLL/scripts/server/scriptuserinfo.cpp
deleted file mode 100644
index c53a9d22..00000000
--- a/NorthstarDLL/scripts/server/scriptuserinfo.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-#include "squirrel/squirrel.h"
-#include "engine/r2engine.h"
-#include "server/r2server.h"
-
-// clang-format off
-ADD_SQFUNC("string", GetUserInfoKVString_Internal, "entity player, string key, string defaultValue = \"\"",
- "Gets the string value of a given player's userinfo convar by name", ScriptContext::SERVER)
-// clang-format on
-{
- const CBasePlayer* pPlayer = g_pSquirrel<ScriptContext::SERVER>->template getentity<CBasePlayer>(sqvm, 1);
- if (!pPlayer)
- {
- g_pSquirrel<ScriptContext::SERVER>->raiseerror(sqvm, "player is null");
- return SQRESULT_ERROR;
- }
-
- const char* pKey = g_pSquirrel<ScriptContext::SERVER>->getstring(sqvm, 2);
- const char* pDefaultValue = g_pSquirrel<ScriptContext::SERVER>->getstring(sqvm, 3);
-
- const char* pResult = g_pClientArray[pPlayer->m_nPlayerIndex - 1].m_ConVars->GetString(pKey, pDefaultValue);
- g_pSquirrel<ScriptContext::SERVER>->pushstring(sqvm, pResult);
- return SQRESULT_NOTNULL;
-}
-
-// clang-format off
-ADD_SQFUNC("asset", GetUserInfoKVAsset_Internal, "entity player, string key, asset defaultValue = $\"\"",
- "Gets the asset value of a given player's userinfo convar by name", ScriptContext::SERVER)
-// clang-format on
-{
- const CBasePlayer* pPlayer = g_pSquirrel<ScriptContext::SERVER>->template getentity<CBasePlayer>(sqvm, 1);
- if (!pPlayer)
- {
- g_pSquirrel<ScriptContext::SERVER>->raiseerror(sqvm, "player is null");
- return SQRESULT_ERROR;
- }
-
- const char* pKey = g_pSquirrel<ScriptContext::SERVER>->getstring(sqvm, 2);
- const char* pDefaultValue;
- g_pSquirrel<ScriptContext::SERVER>->getasset(sqvm, 3, &pDefaultValue);
-
- const char* pResult = g_pClientArray[pPlayer->m_nPlayerIndex - 1].m_ConVars->GetString(pKey, pDefaultValue);
- g_pSquirrel<ScriptContext::SERVER>->pushasset(sqvm, pResult);
- return SQRESULT_NOTNULL;
-}
-
-// clang-format off
-ADD_SQFUNC("int", GetUserInfoKVInt_Internal, "entity player, string key, int defaultValue = 0",
- "Gets the int value of a given player's userinfo convar by name", ScriptContext::SERVER)
-// clang-format on
-{
- const CBasePlayer* pPlayer = g_pSquirrel<ScriptContext::SERVER>->template getentity<CBasePlayer>(sqvm, 1);
- if (!pPlayer)
- {
- g_pSquirrel<ScriptContext::SERVER>->raiseerror(sqvm, "player is null");
- return SQRESULT_ERROR;
- }
-
- const char* pKey = g_pSquirrel<ScriptContext::SERVER>->getstring(sqvm, 2);
- const int iDefaultValue = g_pSquirrel<ScriptContext::SERVER>->getinteger(sqvm, 3);
-
- const int iResult = g_pClientArray[pPlayer->m_nPlayerIndex - 1].m_ConVars->GetInt(pKey, iDefaultValue);
- g_pSquirrel<ScriptContext::SERVER>->pushinteger(sqvm, iResult);
- return SQRESULT_NOTNULL;
-}
-
-// clang-format off
-ADD_SQFUNC("float", GetUserInfoKVFloat_Internal, "entity player, string key, float defaultValue = 0",
- "Gets the float value of a given player's userinfo convar by name", ScriptContext::SERVER)
-// clang-format on
-{
- const CBasePlayer* pPlayer = g_pSquirrel<ScriptContext::SERVER>->getentity<CBasePlayer>(sqvm, 1);
- if (!pPlayer)
- {
- g_pSquirrel<ScriptContext::SERVER>->raiseerror(sqvm, "player is null");
- return SQRESULT_ERROR;
- }
-
- const char* pKey = g_pSquirrel<ScriptContext::SERVER>->getstring(sqvm, 2);
- const float flDefaultValue = g_pSquirrel<ScriptContext::SERVER>->getfloat(sqvm, 3);
-
- const float flResult = g_pClientArray[pPlayer->m_nPlayerIndex - 1].m_ConVars->GetFloat(pKey, flDefaultValue);
- g_pSquirrel<ScriptContext::SERVER>->pushfloat(sqvm, flResult);
- return SQRESULT_NOTNULL;
-}
-
-// clang-format off
-ADD_SQFUNC("bool", GetUserInfoKVBool_Internal, "entity player, string key, bool defaultValue = false",
- "Gets the bool value of a given player's userinfo convar by name", ScriptContext::SERVER)
-// clang-format on
-{
- const CBasePlayer* pPlayer = g_pSquirrel<ScriptContext::SERVER>->getentity<CBasePlayer>(sqvm, 1);
- if (!pPlayer)
- {
- g_pSquirrel<ScriptContext::SERVER>->raiseerror(sqvm, "player is null");
- return SQRESULT_ERROR;
- }
-
- const char* pKey = g_pSquirrel<ScriptContext::SERVER>->getstring(sqvm, 2);
- const bool bDefaultValue = g_pSquirrel<ScriptContext::SERVER>->getbool(sqvm, 3);
-
- const bool bResult = g_pClientArray[pPlayer->m_nPlayerIndex - 1].m_ConVars->GetInt(pKey, bDefaultValue);
- g_pSquirrel<ScriptContext::SERVER>->pushbool(sqvm, bResult);
- return SQRESULT_NOTNULL;
-}