From 829e122cead5521d5ffa57daa7e9fbd10755d68f Mon Sep 17 00:00:00 2001
From: IcePixelx <41352111+PixieCore@users.noreply.github.com>
Date: Sat, 15 Jan 2022 15:25:19 +0100
Subject: [PATCH] SQ Serverbrowser V1 push. Clean-up following after @r-ex
fixed SQ things.
---
r5dev/gameui/IBrowser.cpp | 52 ++++++-
r5dev/gameui/IBrowser.h | 6 +-
r5dev/r5dev.vcxproj | 2 +
r5dev/r5dev.vcxproj.filters | 6 +
r5dev/squirrel/sqapi.h | 6 +
r5dev/squirrel/sqnativefunctions.cpp | 207 +++++++++++++++++++++++++++
r5dev/squirrel/sqnativefunctions.h | 20 +++
r5dev/squirrel/sqvm.cpp | 29 ++++
r5dev/squirrel/sqvm.h | 15 +-
r5dev/tier0/cvar.cpp | 2 +-
10 files changed, 338 insertions(+), 7 deletions(-)
create mode 100644 r5dev/squirrel/sqnativefunctions.cpp
create mode 100644 r5dev/squirrel/sqnativefunctions.h
diff --git a/r5dev/gameui/IBrowser.cpp b/r5dev/gameui/IBrowser.cpp
index ffd91627..1d7a68b0 100644
--- a/r5dev/gameui/IBrowser.cpp
+++ b/r5dev/gameui/IBrowser.cpp
@@ -29,6 +29,7 @@ History:
#include "vpc/keyvalues.h"
#include "squirrel/sqinit.h"
#include "gameui/IBrowser.h"
+#include "squirrel/sqapi.h"
//-----------------------------------------------------------------------------
// Purpose:
@@ -88,6 +89,32 @@ IBrowser::~IBrowser()
//delete r5net;
}
+//-----------------------------------------------------------------------------
+// Purpose: Sets needed create game vars
+//-----------------------------------------------------------------------------
+void IBrowser::SetMenuVars(std::string name, std::string vis)
+{
+ if (vis == "Public")
+ {
+ m_Server.bHidden = false;
+ eServerVisibility = EServerVisibility::PUBLIC;
+ }
+ else if (vis == "Private")
+ {
+ eServerVisibility = EServerVisibility::HIDDEN;
+ m_Server.bHidden = true;
+ }
+ else
+ {
+ m_Server.bHidden = true;
+ eServerVisibility = EServerVisibility::OFFLINE;
+ }
+
+ m_Server.svServerName = name;
+
+ UpdateHostingStatus();
+}
+
//-----------------------------------------------------------------------------
// Purpose: draws the main browser front-end
//-----------------------------------------------------------------------------
@@ -272,6 +299,16 @@ void IBrowser::RefreshServerList()
}
}
+//-----------------------------------------------------------------------------
+// Purpose: get server list from pylon.
+//-----------------------------------------------------------------------------
+void IBrowser::GetServerList()
+{
+ m_vServerList.clear();
+ m_szServerListMessage.clear();
+ m_vServerList = g_pR5net->GetServersList(m_szServerListMessage);
+}
+
//-----------------------------------------------------------------------------
// Purpose: connects to specified server
//-----------------------------------------------------------------------------
@@ -302,6 +339,14 @@ void IBrowser::ConnectToServer(const std::string connString, const std::string e
ProcessCommand(cmd.str().c_str());
}
+//-----------------------------------------------------------------------------
+// Purpose: Load playlist into KeyValues.
+//-----------------------------------------------------------------------------
+void IBrowser::LoadPlaylist(const char* playlistName)
+{
+ KeyValues_LoadPlaylist(playlistName);
+}
+
//-----------------------------------------------------------------------------
// Purpose: draws the hidden private server modal
//-----------------------------------------------------------------------------
@@ -445,7 +490,7 @@ void IBrowser::HostServerSection()
* Playlist gets parsed in two instances, first in LoadPlaylist all the neccessary values.
* Then when you would normally call launchplaylist which calls StartPlaylist it would cmd call mp_gamemode which parses the gamemode specific part of the playlist..
*/
- KeyValues_LoadPlaylist(m_Server.svPlaylist.c_str());
+ LoadPlaylist(m_Server.svPlaylist.c_str());
std::stringstream cgmd;
cgmd << "mp_gamemode " << m_Server.svPlaylist;
ProcessCommand(cgmd.str().c_str());
@@ -488,7 +533,7 @@ void IBrowser::HostServerSection()
* Playlist gets parsed in two instances, first in LoadPlaylist all the neccessary values.
* Then when you would normally call launchplaylist which calls StartPlaylist it would cmd call mp_gamemode which parses the gamemode specific part of the playlist..
*/
- KeyValues_LoadPlaylist(m_Server.svPlaylist.c_str());
+ LoadPlaylist(m_Server.svPlaylist.c_str());
std::stringstream cgmd;
cgmd << "mp_gamemode " << m_Server.svPlaylist;
ProcessCommand(cgmd.str().c_str());
@@ -761,5 +806,4 @@ void IBrowser::SetStyleVar()
style.WindowPadding = ImVec2(5, 5);
}
-
-IBrowser* g_pIBrowser = new IBrowser();
+IBrowser* g_pIBrowser = new IBrowser();
\ No newline at end of file
diff --git a/r5dev/gameui/IBrowser.h b/r5dev/gameui/IBrowser.h
index f5dcd5ed..c0833069 100644
--- a/r5dev/gameui/IBrowser.h
+++ b/r5dev/gameui/IBrowser.h
@@ -16,8 +16,11 @@ public:
void ServerBrowserSection();
void RefreshServerList();
+ void GetServerList();
+
void ConnectToServer(const std::string ip, const std::string port, const std::string encKey);
void ConnectToServer(const std::string connString, const std::string encKey);
+ void SetMenuVars(std::string name, std::string vis);
void HiddenServersModal();
void HostServerSection();
@@ -26,6 +29,7 @@ public:
void SendHostingPostRequest();
void ProcessCommand(const char* command_line);
+ void LoadPlaylist(const char* playlistName);
void SettingsSection();
void RegenerateEncryptionKey();
@@ -113,4 +117,4 @@ public:
};
extern IBrowser* g_pIBrowser;
-#endif
+#endif
\ No newline at end of file
diff --git a/r5dev/r5dev.vcxproj b/r5dev/r5dev.vcxproj
index 7b28127d..2a8d82b6 100644
--- a/r5dev/r5dev.vcxproj
+++ b/r5dev/r5dev.vcxproj
@@ -59,6 +59,7 @@
+
NotUsing
@@ -265,6 +266,7 @@
+
diff --git a/r5dev/r5dev.vcxproj.filters b/r5dev/r5dev.vcxproj.filters
index c26cd15c..4f646e83 100644
--- a/r5dev/r5dev.vcxproj.filters
+++ b/r5dev/r5dev.vcxproj.filters
@@ -405,6 +405,9 @@
core
+
+ sdk\squirrel
+
@@ -1046,6 +1049,9 @@
core
+
+ sdk\squirrel
+
diff --git a/r5dev/squirrel/sqapi.h b/r5dev/squirrel/sqapi.h
index 8dce4f0d..cc1f8533 100644
--- a/r5dev/squirrel/sqapi.h
+++ b/r5dev/squirrel/sqapi.h
@@ -48,6 +48,12 @@ void hsq_newslot(void* sqvm, int idx);
void SQAPI_Attach();
void SQAPI_Detach();
+typedef int SQRESULT;
+#define SQ_OK (1)
+#define SQ_ERROR (-1)
+#define SQ_FAILED(res) (res<0)
+#define SQ_SUCCEEDED(res) (res>=0)
+
///////////////////////////////////////////////////////////////////////////////
class HSqapi : public IDetour
{
diff --git a/r5dev/squirrel/sqnativefunctions.cpp b/r5dev/squirrel/sqnativefunctions.cpp
new file mode 100644
index 00000000..a22eaa7c
--- /dev/null
+++ b/r5dev/squirrel/sqnativefunctions.cpp
@@ -0,0 +1,207 @@
+#include "core/stdafx.h"
+#include "squirrel/sqnativefunctions.h"
+
+#include "engine/sys_utils.h"
+#include "gameui/IBrowser.h"
+
+namespace SQNativeFunctions
+{
+ namespace IBrowser
+ {
+ SQRESULT GetServerName(void* sqvm)
+ {
+ int svIndex = hsq_getinteger(sqvm, 1);
+ std::string svName = g_pIBrowser->m_vServerList[svIndex].svServerName;
+
+ hsq_pushstring(sqvm, svName.c_str(), -1);
+
+ return SQ_OK;
+ }
+
+ SQRESULT GetServerPlaylist(void* sqvm)
+ {
+ int svIndex = hsq_getinteger(sqvm, 1);
+ std::string svPlaylist = g_pIBrowser->m_vServerList[svIndex].svPlaylist;
+
+ hsq_pushstring(sqvm, svPlaylist.c_str(), -1);
+
+ return SQ_OK;
+ }
+
+ SQRESULT GetServerMap(void* sqvm)
+ {
+ int svIndex = hsq_getinteger(sqvm, 1);
+ std::string svMapName = g_pIBrowser->m_vServerList[svIndex].svMapName;
+
+ hsq_pushstring(sqvm, svMapName.c_str(), -1);
+
+ return SQ_OK;
+ }
+
+ SQRESULT GetServerAmount(void* sqvm)
+ {
+ g_pIBrowser->GetServerList(); // Refresh server list.
+
+ hsq_pushinteger(sqvm, g_pIBrowser->m_vServerList.size() - 1); // please fix the -1 rexx okay thank you.
+
+ return SQ_OK;
+ }
+
+ SQRESULT GetSDKVersion(void* sqvm)
+ {
+ hsq_pushstring(sqvm, g_pR5net->GetSDKVersion().c_str(), -1);
+
+ return SQ_OK;
+ }
+
+ SQRESULT GetPromoData(void* sqvm)
+ {
+ enum class R5RPromoData : int
+ {
+ PromoLargeTitle,
+ PromoLargeDesc,
+ PromoLeftTitle,
+ PromoLeftDesc,
+ PromoRightTitle,
+ PromoRightDesc
+ };
+
+ R5RPromoData prIndex = (R5RPromoData)hsq_getinteger(sqvm, 1);
+
+ std::string prStr = std::string();
+
+ switch (prIndex)
+ {
+ case R5RPromoData::PromoLargeTitle:
+ {
+ prStr = "Welcome To R5Reloaded!";
+ break;
+ }
+ case R5RPromoData::PromoLargeDesc:
+ {
+ prStr = "Make sure to join the discord! discord.gg/r5reloaded";
+ break;
+ }
+ case R5RPromoData::PromoLeftTitle:
+ {
+ prStr = "Yes";
+ break;
+ }
+ case R5RPromoData::PromoLeftDesc:
+ {
+ prStr = "Your ad could be here";
+ break;
+ }
+ case R5RPromoData::PromoRightTitle:
+ {
+ prStr = "Yes2";
+ break;
+ }
+ case R5RPromoData::PromoRightDesc:
+ {
+ prStr = "Yes3";
+ break;
+ }
+ default:
+ {
+ prStr = "You should not see this.";
+ break;
+ }
+ }
+
+ hsq_pushstring(sqvm, prStr.c_str(), -1);
+
+ return SQ_OK;
+ }
+
+ SQRESULT SetEncKeyAndConnect(void* sqvm)
+ {
+ int svIndex = hsq_getinteger(sqvm, 1);
+
+ g_pIBrowser->ConnectToServer(g_pIBrowser->m_vServerList[svIndex].svIpAddress, g_pIBrowser->m_vServerList[svIndex].svPort, g_pIBrowser->m_vServerList[svIndex].svEncryptionKey);
+
+ return SQ_OK;
+ }
+
+ SQRESULT CreateServerFromMenu(void* sqvm)
+ {
+ std::string svName = hsq_getstring(sqvm, 1);
+ std::string svMapName = hsq_getstring(sqvm, 2);
+ std::string svPlaylist = hsq_getstring(sqvm, 3);
+ std::string svVisibility = hsq_getstring(sqvm, 4); // Rexx please change this to an integer, so we don't have that ghetto switch case in SetMenuVars.
+
+ if (svMapName.empty() || svPlaylist.empty() || svVisibility.empty())
+ return SQ_OK;
+
+ g_pIBrowser->SetMenuVars(svName, svVisibility); // Pass integer instead
+
+
+ /* Changing this up to call a IBrowser method eventually. */
+ DevMsg(eDLL_T::ENGINE, "Starting Server with map '%s' and playlist '%s'\n", svMapName.c_str(), svPlaylist.c_str());
+
+ g_pIBrowser->LoadPlaylist(svPlaylist.c_str());
+ std::stringstream cgmd;
+ cgmd << "mp_gamemode " << svPlaylist;
+ g_pIBrowser->ProcessCommand(cgmd.str().c_str());
+
+ // This is to avoid svIndex race condition.
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ std::stringstream cmd;
+ cmd << "map " << svMapName;
+ g_pIBrowser->ProcessCommand(cmd.str().c_str());
+
+ return SQ_OK;
+ }
+
+ SQRESULT JoinPrivateServerFromMenu(void* sqvm)
+ {
+ std::string m_szHiddenServerRequestMessage;
+
+ std::string token = hsq_getstring(sqvm, 1);
+
+ ServerListing server;
+ bool result = g_pR5net->GetServerByToken(server, m_szHiddenServerRequestMessage, token); // Send token connect request.
+ if (result)
+ {
+ g_pIBrowser->ConnectToServer(server.svIpAddress, server.svPort, server.svEncryptionKey);
+ }
+
+ return SQ_OK;
+ }
+
+ SQRESULT GetPrivateServerMessage(void* sqvm)
+ {
+ std::string m_szHiddenServerRequestMessage;
+
+ std::string token = hsq_getstring(sqvm, 1);
+
+ ServerListing server;
+ bool result = g_pR5net->GetServerByToken(server, m_szHiddenServerRequestMessage, token); // Send token connect request.
+ if (!server.svServerName.empty())
+ {
+ m_szHiddenServerRequestMessage = "Found Server: " + server.svServerName;
+
+ hsq_pushstring(sqvm, m_szHiddenServerRequestMessage.c_str(), -1);
+ }
+ else
+ {
+ m_szHiddenServerRequestMessage = "Error: Server Not Found";
+
+ hsq_pushstring(sqvm, m_szHiddenServerRequestMessage.c_str(), -1);
+ }
+
+ return SQ_OK;
+ }
+
+ SQRESULT ConnectToIPFromMenu(void* sqvm)
+ {
+ std::string ip = hsq_getstring(sqvm, 1);
+ std::string key = hsq_getstring(sqvm, 2);
+
+ g_pIBrowser->ConnectToServer(ip, key);
+
+ return SQ_OK;
+ }
+ }
+}
\ No newline at end of file
diff --git a/r5dev/squirrel/sqnativefunctions.h b/r5dev/squirrel/sqnativefunctions.h
new file mode 100644
index 00000000..29579027
--- /dev/null
+++ b/r5dev/squirrel/sqnativefunctions.h
@@ -0,0 +1,20 @@
+#pragma once
+#include "squirrel/sqapi.h"
+
+namespace SQNativeFunctions
+{
+ namespace IBrowser
+ {
+ SQRESULT GetServerName(void* sqvm);
+ SQRESULT GetServerPlaylist(void* sqvm);
+ SQRESULT GetServerMap(void* sqvm);
+ SQRESULT GetServerAmount(void* sqvm);
+ SQRESULT GetSDKVersion(void* sqvm);
+ SQRESULT GetPromoData(void* sqvm);
+ SQRESULT SetEncKeyAndConnect(void* sqvm);
+ SQRESULT CreateServerFromMenu(void* sqvm);
+ SQRESULT JoinPrivateServerFromMenu(void* sqvm);
+ SQRESULT GetPrivateServerMessage(void* sqvm);
+ SQRESULT ConnectToIPFromMenu(void* sqvm);
+ }
+}
\ No newline at end of file
diff --git a/r5dev/squirrel/sqvm.cpp b/r5dev/squirrel/sqvm.cpp
index fe7567c6..bc071458 100644
--- a/r5dev/squirrel/sqvm.cpp
+++ b/r5dev/squirrel/sqvm.cpp
@@ -14,6 +14,7 @@
#include "vgui/CEngineVGui.h"
#include "gameui/IConsole.h"
#include "squirrel/sqvm.h"
+#include "squirrel/sqnativefunctions.h"
//---------------------------------------------------------------------------------
// Purpose: prints the output of each VM to the console
@@ -248,6 +249,22 @@ int HSQVM_NativeTest(void* sqvm)
void RegisterUIScriptFunctions(void* sqvm)
{
HSQVM_RegisterFunction(sqvm, "UINativeTest", "native ui function", "void", "", &HSQVM_NativeTest);
+ //Server Browser Data
+ HSQVM_RegisterFunction(sqvm, "GetServerName", "native ui function", "string", "int", &SQNativeFunctions::IBrowser::GetServerName);
+ HSQVM_RegisterFunction(sqvm, "GetServerPlaylist", "native ui function", "string", "int", &SQNativeFunctions::IBrowser::GetServerPlaylist);
+ HSQVM_RegisterFunction(sqvm, "GetServerMap", "native ui function", "string", "int", &SQNativeFunctions::IBrowser::GetServerMap);
+ HSQVM_RegisterFunction(sqvm, "GetServerAmmount", "native ui function", "int", "", &SQNativeFunctions::IBrowser::GetServerAmount);
+
+ //Main Menu Data
+ HSQVM_RegisterFunction(sqvm, "GetSDKVersion", "native ui function", "string", "", &SQNativeFunctions::IBrowser::GetSDKVersion);
+ HSQVM_RegisterFunction(sqvm, "GetPromoData", "native ui function", "string", "int", &SQNativeFunctions::IBrowser::GetPromoData);
+
+ //Connecting To Servers
+ HSQVM_RegisterFunction(sqvm, "CreateServer", "native ui function", "void", "string,string,string,string", &SQNativeFunctions::IBrowser::CreateServerFromMenu);
+ HSQVM_RegisterFunction(sqvm, "SetEncKeyAndConnect", "native ui function", "void", "int", &SQNativeFunctions::IBrowser::SetEncKeyAndConnect);
+ HSQVM_RegisterFunction(sqvm, "JoinPrivateServerFromMenu", "native ui function", "void", "string", &SQNativeFunctions::IBrowser::JoinPrivateServerFromMenu);
+ HSQVM_RegisterFunction(sqvm, "GetPrivateServerMessage", "native ui function", "string", "string", &SQNativeFunctions::IBrowser::GetPrivateServerMessage);
+ HSQVM_RegisterFunction(sqvm, "ConnectToIPFromMenu", "native ui function", "void", "string,string", &SQNativeFunctions::IBrowser::ConnectToIPFromMenu);
}
void RegisterClientScriptFunctions(void* sqvm)
@@ -260,12 +277,23 @@ void RegisterServerScriptFunctions(void* sqvm)
HSQVM_RegisterFunction(sqvm, "ServerNativeTest", "native server function", "void", "", &HSQVM_NativeTest);
}
+void HSQVM_RegisterOriginFuncs(void* sqvm)
+{
+ if (sqvm == *p_SQVM_UIVM.RCast())
+ RegisterUIScriptFunctions(sqvm);
+ else
+ RegisterClientScriptFunctions(sqvm);
+
+ return SQVM_RegisterOriginFuncs(sqvm);
+}
+
void SQVM_Attach()
{
DetourAttach((LPVOID*)&SQVM_PrintFunc, &HSQVM_PrintFunc);
DetourAttach((LPVOID*)&SQVM_WarningFunc, &HSQVM_WarningFunc);
DetourAttach((LPVOID*)&SQVM_LoadRson, &HSQVM_LoadRson);
DetourAttach((LPVOID*)&SQVM_LoadScript, &HSQVM_LoadScript);
+ DetourAttach((LPVOID*)&SQVM_RegisterOriginFuncs, &HSQVM_RegisterOriginFuncs);
}
void SQVM_Detach()
@@ -274,6 +302,7 @@ void SQVM_Detach()
DetourDetach((LPVOID*)&SQVM_WarningFunc, &HSQVM_WarningFunc);
DetourDetach((LPVOID*)&SQVM_LoadRson, &HSQVM_LoadRson);
DetourDetach((LPVOID*)&SQVM_LoadScript, &HSQVM_LoadScript);
+ DetourDetach((LPVOID*)&SQVM_RegisterOriginFuncs, &HSQVM_RegisterOriginFuncs);
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/r5dev/squirrel/sqvm.h b/r5dev/squirrel/sqvm.h
index d3d5e57a..a74c39a9 100644
--- a/r5dev/squirrel/sqvm.h
+++ b/r5dev/squirrel/sqvm.h
@@ -43,6 +43,12 @@ const static std::string SQVM_ANSI_LOG_T[4] =
"\u001b[90mScript(X):"
};
+typedef int SQRESULT;
+#define SQ_OK (1)
+#define SQ_ERROR (-1)
+#define SQ_FAILED(res) (res<0)
+#define SQ_SUCCEEDED(res) (res>=0)
+
namespace
{
/* ==== SQUIRREL ======================================================================================================================================================== */
@@ -66,6 +72,13 @@ namespace
ADDRESS p_SQVM_RegisterFunc = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x83\xEC\x38\x45\x0F\xB6\xC8", "xxxxxxxx"); /*48 83 EC 38 45 0F B6 C8*/
void* (*SQVM_RegisterFunc)(void* sqvm, SQFuncRegistration* sqFunc, int a1) = (void* (*)(void*, SQFuncRegistration*, int))p_SQVM_RegisterFunc.GetPtr();
+
+ ADDRESS p_SQVM_CreateUIVM = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x48\x83\xEC\x20\x48\x8B\x1D\x00\x00\x00\x00\xC6\x05\x00\x00\x00\x00\x00", "xxxxxxxxx????xx?????"); /*40 53 48 83 EC 20 48 8B 1D ? ? ? ? C6 05 ? ? ? ? ?*/
+ bool (*SQVM_CreateUIVM)() = (bool(*)())p_SQVM_CreateUIVM.GetPtr();
+ ADDRESS p_SQVM_UIVM = (void*)p_SQVM_CreateUIVM.FindPatternSelf("48 8B 1D", ADDRESS::Direction::DOWN, 50).ResolveRelativeAddressSelf(0x3, 0x7).GetPtr();
+
+ ADDRESS p_SQVM_RegisterOriginFuncs = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\xE8\x00\x00\x00\x00\x48\x8B\x0D\x00\x00\x00\x00\x48\x8D\x15\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x48\x8B\x05\x00\x00\x00\x00\xC7\x05\x00\x00\x00\x00\x00\x00\x00\x00", "x????xxx????xxx????x????xxx????xx????????"); /*E8 ? ? ? ? 48 8B 0D ? ? ? ? 48 8D 15 ? ? ? ? E8 ? ? ? ? 48 8B 05 ? ? ? ? C7 05 ? ? ? ? ? ? ? ?*/
+ void (*SQVM_RegisterOriginFuncs)(void* sqvm) = (void(*)(void*))p_SQVM_RegisterOriginFuncs.FollowNearCall().GetPtr();
}
void* HSQVM_PrintFunc(void* sqvm, char* fmt, ...);
@@ -74,7 +87,7 @@ bool HSQVM_LoadScript(void* sqvm, const char* szScriptPath, const char* szScript
void HSQVM_RegisterFunction(void* sqvm, const char* szName, const char* szHelpString, const char* szRetValType, const char* szArgTypes, void* pFunction);
int HSQVM_NativeTest(void* sqvm);
-
+void HSQVM_RegisterOriginFuncs(void* sqvm);
void SQVM_Attach();
void SQVM_Detach();
diff --git a/r5dev/tier0/cvar.cpp b/r5dev/tier0/cvar.cpp
index df4ce362..9c7e35b9 100644
--- a/r5dev/tier0/cvar.cpp
+++ b/r5dev/tier0/cvar.cpp
@@ -96,7 +96,7 @@ CCVarIteratorInternal* CCVar::FactoryInternalIterator()
std::unordered_map CCVar::DumpToMap()
{
std::stringstream ss;
- CCVarIteratorInternal* itint = FactoryInternalIterator(); // Allocatd new InternalIterator.
+ CCVarIteratorInternal* itint = FactoryInternalIterator(); // Allocate new InternalIterator.
std::unordered_map allConVars;