From b1bf7ee7c45f9da7ba985f00f451445b48aa799e Mon Sep 17 00:00:00 2001
From: IcePixelx <41352111+PixieCore@users.noreply.github.com>
Date: Sat, 14 Aug 2021 12:46:52 +0200
Subject: [PATCH] Re-Load playlists from disk after disconnecting or getting
 dropped of server.

---
 r5dev/include/hooks.h          |  3 +++
 r5dev/include/patterns.h       |  8 ++++++++
 r5dev/r5dev.vcxproj            |  1 +
 r5dev/r5dev.vcxproj.filters    |  3 +++
 r5dev/src/hooks/hooks.cpp      |  3 +++
 r5dev/src/hooks/netchannel.cpp | 13 +++++++++++++
 6 files changed, 31 insertions(+)
 create mode 100644 r5dev/src/hooks/netchannel.cpp

diff --git a/r5dev/include/hooks.h b/r5dev/include/hooks.h
index f59366a7..6b33a004 100644
--- a/r5dev/include/hooks.h
+++ b/r5dev/include/hooks.h
@@ -43,6 +43,7 @@ namespace Hooks
 	bool NET_ReceiveDatagram(int sock, void* inpacket, bool raw);
 	unsigned int NET_SendDatagram(SOCKET s, const char* buf, int len, int flags);
 	void NET_PrintFunc(const char* fmt, ...);
+	void NetChanShutdown(void* rcx, const char* reason, unsigned __int8 unk1, char unk2);
 
 	using NET_PrintFuncFn = void(*)(const char* fmt, ...);
 	extern NET_PrintFuncFn originalNET_PrintFunc;
@@ -52,6 +53,8 @@ namespace Hooks
 
 	using NET_SendDatagramFn = unsigned int(*)(SOCKET, const char*, int, int);
 	extern NET_SendDatagramFn originalNET_SendDatagram;
+	using NetChan_ShutDown = void(*)(void*, const char*, unsigned __int8, char);
+	extern NetChan_ShutDown originalNetChanShutDown;
 #pragma endregion
 
 #pragma region ConVar
diff --git a/r5dev/include/patterns.h b/r5dev/include/patterns.h
index 1bced023..592a5c58 100644
--- a/r5dev/include/patterns.h
+++ b/r5dev/include/patterns.h
@@ -14,6 +14,9 @@ namespace
 
 	/*0x14046F490*/
 	FUNC_AT_ADDRESS(addr_ConCommand_IsFlagSet, bool(*)(int*, int), r5_patterns.PatternSearch("85 51 38 0F 95 C0 C3").GetPtr());
+
+	/*0x140279CE0*/
+	FUNC_AT_ADDRESS(addr_downloadPlaylists_Callback, void*, r5_patterns.PatternSearch("33 C9 C6 05 ? ? ? ? ? E9 ? ? ? ?").GetPtr());
 #pragma endregion
 
 #pragma region Squirrel
@@ -39,6 +42,9 @@ namespace
 
 	/*0x1402662D0*/
 	FUNC_AT_ADDRESS(addr_NET_SendDatagram, int(*)(SOCKET, const char*, int, int), r5_patterns.PatternSearch("48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 41 56 41 57 48 81 EC ? 05 ? ?").GetPtr());
+
+	/*0x14025F190*/
+	FUNC_AT_ADDRESS(addr_NetChan_Shutdown, void(*)(void*, const char*, unsigned __int8, char), r5_patterns.StringSearch("Disconnect by server.\n").FindPatternSelf("E8 ? ? ? ? 4C 89 B3 ? ? ? ?", MemoryAddress::Direction::DOWN).FollowNearCall().GetPtr());
 #pragma endregion
 
 #pragma region CHLClient
@@ -68,12 +74,14 @@ namespace
 		PRINT_ADDRESS("CommandExecute", addr_CommandExecute);
 		PRINT_ADDRESS("ConVar_IsFlagSet", addr_ConVar_IsFlagSet);
 		PRINT_ADDRESS("ConCommand_IsFlagSet", addr_ConCommand_IsFlagSet);
+		PRINT_ADDRESS("Downloadplaylists_Callback", addr_downloadPlaylists_Callback);
 		PRINT_ADDRESS("SQVM_Print", addr_SQVM_Print);
 		PRINT_ADDRESS("SQVM_LoadScript", addr_SQVM_LoadScript);
 		PRINT_ADDRESS("SQVM_LoadRson", addr_SQVM_LoadRson);
 		PRINT_ADDRESS("NET_PrintFunc", addr_NET_PrintFunc);
 		PRINT_ADDRESS("NET_ReceiveDatagram", addr_NET_ReceiveDatagram);
 		PRINT_ADDRESS("NET_SendDatagram ", addr_NET_SendDatagram);
+		PRINT_ADDRESS("INetChannel::Shutdown", addr_NetChan_Shutdown);
 		PRINT_ADDRESS("CHLClient::FrameStageNotify", addr_CHLClient_FrameStageNotify);
 		PRINT_ADDRESS("CVEngineServer::IsPersistenceDataAvailable", addr_CVEngineServer_IsPersistenceDataAvailable);
 		PRINT_ADDRESS("CBaseFileSystem::FileSystemWarning", addr_CBaseFileSystem_FileSystemWarning);
diff --git a/r5dev/r5dev.vcxproj b/r5dev/r5dev.vcxproj
index 005037e8..60de2c64 100644
--- a/r5dev/r5dev.vcxproj
+++ b/r5dev/r5dev.vcxproj
@@ -384,6 +384,7 @@ if not EXIST $(SolutionDir)r5net\lib\$(Configuration)\r5net.lib (
     <ClCompile Include="src\hooks\iconvar.cpp" />
     <ClCompile Include="src\hooks\msgbox.cpp" />
     <ClCompile Include="src\hooks\net.cpp" />
+    <ClCompile Include="src\hooks\netchannel.cpp" />
     <ClCompile Include="src\hooks\sqvm.cpp" />
     <ClCompile Include="src\hooks\winapi.cpp" />
     <ClCompile Include="src\id3dx.cpp">
diff --git a/r5dev/r5dev.vcxproj.filters b/r5dev/r5dev.vcxproj.filters
index 6edecb61..83ee6880 100644
--- a/r5dev/r5dev.vcxproj.filters
+++ b/r5dev/r5dev.vcxproj.filters
@@ -189,6 +189,9 @@
     <ClCompile Include="src\hooks\cbasefilesystem.cpp">
       <Filter>hooks\src\cbasefilesystem</Filter>
     </ClCompile>
+    <ClCompile Include="src\hooks\netchannel.cpp">
+      <Filter>hooks\src\netchannel</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\external\imgui\include\imgui_impl_win32.h">
diff --git a/r5dev/src/hooks/hooks.cpp b/r5dev/src/hooks/hooks.cpp
index ad0c1801..c255b3ab 100644
--- a/r5dev/src/hooks/hooks.cpp
+++ b/r5dev/src/hooks/hooks.cpp
@@ -31,6 +31,7 @@ void Hooks::InstallHooks()
 	MH_CreateHook(addr_NET_PrintFunc, &Hooks::NET_PrintFunc, reinterpret_cast<void**>(&originalNET_PrintFunc));
 	MH_CreateHook(addr_NET_ReceiveDatagram, &Hooks::NET_ReceiveDatagram, reinterpret_cast<void**>(&originalNET_ReceiveDatagram));
 	MH_CreateHook(addr_NET_SendDatagram, &Hooks::NET_SendDatagram, reinterpret_cast<void**>(&originalNET_SendDatagram));
+	MH_CreateHook(addr_NetChan_Shutdown, &Hooks::NetChanShutdown, reinterpret_cast<void**>(&originalNetChanShutDown));
 
 	///////////////////////////////////////////////////////////////////////////////
 	// Hook ConVar | ConCommand functions.
@@ -81,6 +82,7 @@ void Hooks::InstallHooks()
 	///////////////////////////////////////////////////////////////////////////////
 	// Enable Netchan hooks
 	MH_EnableHook(addr_NET_PrintFunc);
+	MH_EnableHook(addr_NetChan_Shutdown);
 
 	///////////////////////////////////////////////////////////////////////////////
 	// Enable ConVar | ConCommand hooks
@@ -114,6 +116,7 @@ void Hooks::RemoveHooks()
 	MH_RemoveHook(addr_NET_PrintFunc);
 	MH_RemoveHook(addr_NET_ReceiveDatagram);
 	MH_RemoveHook(addr_NET_SendDatagram);
+	MH_RemoveHook(addr_NetChan_Shutdown);
 
 	///////////////////////////////////////////////////////////////////////////////
 	// Unhook ConVar | ConCommand functions.
diff --git a/r5dev/src/hooks/netchannel.cpp b/r5dev/src/hooks/netchannel.cpp
new file mode 100644
index 00000000..2dc45d40
--- /dev/null
+++ b/r5dev/src/hooks/netchannel.cpp
@@ -0,0 +1,13 @@
+#include "pch.h"
+#include "hooks.h"
+
+namespace Hooks
+{
+	NetChan_ShutDown originalNetChanShutDown = nullptr;
+}
+
+void Hooks::NetChanShutdown(void* rcx, const char* reason, unsigned __int8 unk1, char unk2)
+{
+	reinterpret_cast<void(*)()>(addr_downloadPlaylists_Callback)(); // Re-Load playlist from disk after getting dropped or disconnecting off a server.
+	originalNetChanShutDown(rcx, reason, unk1, unk2);
+}
\ No newline at end of file