Compare commits

..

9 Commits

17 changed files with 224 additions and 32 deletions

View File

@@ -23,6 +23,7 @@ namespace undead_universal_patch_il2cpp.Core.Config
public static ConfigEntry<bool> RegistrationPatch;
public static ConfigEntry<bool> AFKPatch;
public static ConfigEntry<bool> RefreshTokenFix;
public static ConfigEntry<bool> ProtonDeviceIdFix;
}
public static class PatchConfigDefaults
{
@@ -33,6 +34,7 @@ namespace undead_universal_patch_il2cpp.Core.Config
public static bool RegistrationPatch = false;
public static bool AFKPatch = false;
public static bool RefreshTokenFix = false;
public static bool ProtonDeviceIdFix = false;
}
public static class ServerPatchesConfig
{

View File

@@ -16,6 +16,8 @@ public class RecNetInteractions
public static List<Action> postAuthenticationActions = [];
public static List<Action> postLocalAccountActions = [];
public static List<Action> onNotificationsOpen = [];
public static List<Action> onLogout = [];
public static List<Action> onPlatformInitialize = [];
public static Il2CppSystem.Uri CreateServiceUri(Service service, string pathAndQuery)
{

View File

@@ -43,6 +43,7 @@ public class Initialization
UniversalPatchPlugin.Log.LogInfo("PATCH LIST END =========================");
}
// to be removed in a future update
try
{
CacheChangePatchConfigs();
@@ -62,8 +63,9 @@ public class Initialization
{
UniversalPatchPlugin.Log.LogInfo("Attaching game objects");
if (ServerPatchesConfig.CustomEmotes.Value) UniversalPatchPlugin.Instance.AddComponent<CustomEmotes>();
UniversalPatchPlugin.Instance.AddComponent<SteamPlatform>();
UniversalPatchPlugin.Instance.AddComponent<CustomPhoton>();
if (ServerPatchesConfig.CustomEmotes.Value) UniversalPatchPlugin.Instance.AddComponent<CustomEmotes>();
if (ServerPatchesConfig.CustomKnownDlls.Value) UniversalPatchPlugin.Instance.AddComponent<CustomCheatManager>();
if (ServerPatchesConfig.CustomGameConfigurations.Value) UniversalPatchPlugin.Instance.AddComponent<CustomGameManager>();
}
@@ -93,6 +95,8 @@ public class Initialization
PatchConfig.RefreshTokenFix = UniversalPatchPlugin.Instance.Config.Bind("Patches", "RefreshTokenFix", PatchConfigDefaults.RefreshTokenFix,
"Fix for the game needlessly requesting a refresh token in a loop. Cause for this issue is unknown." +
"\nDon't enable unless you know what this does.");
PatchConfig.ProtonDeviceIdFix = UniversalPatchPlugin.Instance.Config.Bind("Patches", "ProtonDeviceIdFix", PatchConfigDefaults.ProtonDeviceIdFix,
"Fix for device IDs on Wine/Proton. Enable if you get a null reference exception related to cryptography APIs during connect/token.");
ServerPatchesConfig.CustomEmotes = UniversalPatchPlugin.Instance.Config.Bind("ServerPatches", "CustomEmotes", ServerPatchesConfigDefaults.CustomEmotes,
"Modify the game's emote text with a configuration from the server.");

14
Core/PluginHash.cs Normal file
View File

@@ -0,0 +1,14 @@
using System;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;
namespace undead_universal_patch_il2cpp.Core;
public class PluginHash
{
public static string GetHash()
{
return BitConverter.ToString(MD5.Create().ComputeHash(File.OpenRead(Assembly.GetExecutingAssembly().Location))).Replace("-", "").ToLowerInvariant();
}
}

46
Core/SteamPlatform.cs Normal file
View File

@@ -0,0 +1,46 @@
using Il2CppInterop.Runtime;
using Steamworks;
using System;
using undead_universal_patch_il2cpp.Core.Content.CustomRecNet;
using UnityEngine;
namespace undead_universal_patch_il2cpp.Core;
public class SteamPlatform : MonoBehaviour
{
public static string AuthTicket { get; set; } = null;
void GetAuthTicket() {
SteamPlatformManager manager = PlatformManager.Instance.GetComponentInChildren<SteamPlatformManager>();
manager.GetAuthSessionTicket().Then(
DelegateSupport.ConvertDelegate<Il2CppSystem.Action<SteamPlatformManager.AuthSessionTicket>>((SteamPlatformManager.AuthSessionTicket ticket) =>
{
if (!string.IsNullOrEmpty(ticket.Error)) UniversalPatchPlugin.Log.LogError($"Could not get Steam auth ticket!: {ticket.Error}");
else
{
AuthTicket = BitConverter.ToString(ticket.Ticket).Replace("-", "").ToUpperInvariant().TrimEnd('0');
Util.ConditionalDebug($"Got new Steam auth ticket");
}
}));
}
void Start()
{
RecNetInteractions.onLogout.Add(GetAuthTicket);
RecNetInteractions.onPlatformInitialize.Add(GetAuthTicket);
/*
Every time the user logs out of matchmaking
or when PlatformManager initializes, fetch a new ticket.
The user might be logging out to the account selection screen
where they might create a new one; a Steam auth ticket is added to
the auth params in the create request and it must be valid.
It *is* possible (though very unlikely) that the user creates a new account
before the first ticket is fetched, since the method that gets a ticket is
an IPromise.
If this way of doing things isn't the best, fix it and I'll merge
*/
}
}

View File

@@ -2,6 +2,8 @@
[<-- Back to README.md](./README.md)
**Linux support is currently broken due to Proton bugs with .NET cryptography APIs. This may be resolved in a future update.**
No native Linux build exists for the game. Proton, however, works just fine. You can install it using the instructions below.
Reminder that EAC or Referee builds will never be supported by Undead Universal Patch.

View File

@@ -1,11 +1,12 @@
using System;
using System.Reflection;
using System.Security.Cryptography;
using System.Threading.Tasks;
using BestHTTP;
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Tls;
using BestHTTP.Forms;
using HarmonyLib;
using undead_universal_patch_il2cpp.Core;
using undead_universal_patch_il2cpp.Core.Config;
using UnityEngine;
namespace undead_universal_patch_il2cpp.Patches
{
@@ -24,6 +25,8 @@ namespace undead_universal_patch_il2cpp.Patches
static readonly MethodInfo getHeaderMethod = requestType?.GetMethod("GetFirstHeaderValue");
static readonly MethodInfo addHeaderMethod = requestType?.GetMethod("AddHeader");
static readonly MethodInfo getFormFields = requestType?.GetMethod("GetFormFields");
static readonly PropertyInfo formImplProp = requestType?.GetProperty("FormImpl");
static readonly PropertyInfo methodTypeProp = requestType?.GetProperty("MethodType");
static readonly PropertyInfo uriProp = requestType?.GetProperty("Uri");
static readonly PropertyInfo customCertProp = requestType?.GetProperty("CustomCertificateVerifyer");
@@ -32,13 +35,13 @@ namespace undead_universal_patch_il2cpp.Patches
getHeaderMethod,
addHeaderMethod,
methodTypeProp,
getFormFields,
formImplProp,
uriProp,
customCertProp
]).Success;
static MethodBase TargetMethod() => patchResult.Method;
[HarmonyPrefix]
static void Prefix(ref object request)
{
if (PatchConfig.CertificatePatch.Value) customCertProp.GetSetMethod().Invoke(request, [null]);
@@ -61,6 +64,16 @@ namespace undead_universal_patch_il2cpp.Patches
if (newUri.Host.Contains("ns.rec.net")) newUri = new Il2CppSystem.Uri(NameserverConfig.NewUrl.Value);
bool isAccCreate = newUri.PathAndQuery.Contains("account/create");
if (isAccCreate && SteamPlatform.AuthTicket != null)
{
HTTPFormBase form = (HTTPFormBase)formImplProp.GetValue(request, null);
form.AddField("x-steam-ticket", SteamPlatform.AuthTicket);
Util.ConditionalDebug("Added Steam ticket to create request");
}
else if (isAccCreate) UniversalPatchPlugin.Log.LogError("The Steam auth ticket has not yet been fetched, account creation might fail!");
// Finish request changes
string afterUrl = newUri.ToString();
@@ -73,9 +86,8 @@ namespace undead_universal_patch_il2cpp.Patches
$" URL After : {(beforeUrl == afterUrl ? "(unmodified)" : afterUrl)}\n" +
$" Method : {method}\n" +
$" Content-Type : {contentType ?? "(not set)"}");
else UniversalPatchPlugin.Log.LogInfo("BestHTTPProxy Request Log\n" +
$" Before : {beforeUrl}\n" +
$" After : {afterUrl}");
else UniversalPatchPlugin.Log.LogInfo("BestHTTPProxy Request\n" +
$" {method} {afterUrl}");
}
}
}

View File

@@ -0,0 +1,29 @@
using System.Reflection;
using System.Text;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using undead_universal_patch_il2cpp.Core;
using undead_universal_patch_il2cpp.Core.Config;
namespace undead_universal_patch_il2cpp.Patches.Internals;
[HarmonyPatch]
public class DeviceIdBuilder
{
static PatchTypesResult typesResult = Util.ConfigPreparePatchTypes(
PatchConfig.ProtonDeviceIdFix,
"Proton quickfix for device ID errors",
"RecRoom.Utils.DeviceIdBuilder",
"CalculateOtherDeviceId"
);
static MethodBase TargetMethod() => typesResult.Method;
static bool Prepare() => typesResult.Success;
static bool Prefix(ref Il2CppStructArray<byte> __result)
{
Util.ConditionalDebug("Device ID patched");
__result = new Il2CppStructArray<byte>(Encoding.UTF8.GetBytes("Wine/Proton"));
return false;
}
}

View File

@@ -0,0 +1,30 @@
using BestHTTP.Forms;
using HarmonyLib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using undead_universal_patch_il2cpp.Core;
namespace undead_universal_patch_il2cpp.Patches.Internals;
[HarmonyPatch]
public class LoginHelperFieldsPatch
{
static PatchTypesResult typesResult = Util.PreparePatchTypes(
"Add patch hash to the login form",
"RecNet.Login",
"LoginHelper"
);
static MethodBase TargetMethod() => typesResult.Method;
static bool Prepare() => typesResult.Success;
static void Prefix(ref HTTPUrlEncodedForm loginParams)
{
loginParams.AddField("x-patch-plugin-hash", PluginHash.GetHash());
Util.ConditionalDebug("Added hash to login form");
}
}

View File

@@ -0,0 +1,30 @@
using HarmonyLib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using undead_universal_patch_il2cpp.Core;
using undead_universal_patch_il2cpp.Core.Content.CustomRecNet;
namespace undead_universal_patch_il2cpp.Patches.Internals;
[HarmonyPatch]
public class LogoutEvent
{
static PatchTypesResult typesResult = Util.PreparePatchTypes(
"RecNet logout event patch",
"RecNet.Login",
"OnLogout"
);
static MethodBase TargetMethod() => typesResult.Method;
static bool Prepare() => typesResult.Success;
static void Postfix()
{
Util.ConditionalDebug("Running onLogout actions");
foreach (var action in RecNetInteractions.onLogout) action();
}
}

View File

@@ -0,0 +1,29 @@
using HarmonyLib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using undead_universal_patch_il2cpp.Core;
using undead_universal_patch_il2cpp.Core.Content.CustomRecNet;
namespace undead_universal_patch_il2cpp.Patches.Internals;
[HarmonyPatch]
public class SteamPlatformManagerEvent
{
static PatchTypesResult typesResult = Util.PreparePatchTypes(
"On SteamPlatformManager.Initialize",
"SteamPlatformManager",
"Initialize"
);
static MethodBase TargetMethod() => typesResult.Method;
static bool Prepare() => typesResult.Success;
static void Postfix()
{
UniversalPatchPlugin.Log.LogInfo("Running post-steam platform initialize actions");
foreach (var action in RecNetInteractions.onPlatformInitialize) action();
}
}

View File

@@ -22,19 +22,13 @@ public class AuthenticationEventPatch
static MethodBase TargetMethod() => patchResult.Method;
private static bool RanPostActions { get; set; } = false;
static void Postfix(ref string accessToken)
{
UniversalPatchPlugin.Log.LogInfo("Intercepted AccessToken");
RecNetInteractions.AccessToken = accessToken;
if (!RanPostActions)
{
bool value = (bool)hasAccessTokenProperty.GetValue(patchResult.Type);
if (value) UniversalPatchPlugin.Log.LogInfo("Running post-authentication actions");
UniversalPatchPlugin.Log.LogInfo("Running post-authentication actions");
foreach (var action in RecNetInteractions.postAuthenticationActions)
action();
}
else RanPostActions = true;
}
}

View File

@@ -8,7 +8,7 @@ using System.Threading.Tasks;
using undead_universal_patch_il2cpp.Core;
using undead_universal_patch_il2cpp.Core.Config;
namespace undead_universal_patch_il2cpp.Patches;
namespace undead_universal_patch_il2cpp.Patches.Internals;
[HarmonyPatch]
public class RefreshTokenFix

View File

@@ -10,22 +10,15 @@ namespace undead_universal_patch_il2cpp.Patches
{
static PatchTypesResult patchResult = Util.ConfigPreparePatchTypes(
PatchConfig.RegistrationPatch,
"Registration patch (to be vetted, might not work)",
"UnityEngine.PlayerPrefs",
"GetInt"
"Registration patch",
"ProfileWatchUIFlow",
"Button_Email"
);
static bool Prepare() => patchResult.Success;
static MethodInfo TargetMethod() => patchResult.Method;
static void Postfix(ref string key, ref int defaultValue, ref int __result)
{
if (key.StartsWith("IncompleteRegistration-"))
{
__result = 0;
UniversalPatchPlugin.Log.LogInfo("Detour'd IncompleteRegistration pref key");
}
}
static bool Prefix() => false;
}
}

View File

@@ -6,7 +6,7 @@ using undead_universal_patch_il2cpp.Core;
namespace undead_universal_patch_il2cpp;
[BepInPlugin("dev.proxnet.recroom.universalpatch.noneac.il2cpp", "Undead Universal Patch", "3.0.0")]
[BepInPlugin("dev.proxnet.recroom.universalpatch.noneac.il2cpp", "Undead Universal Patch", "3.1.0")]
public class UniversalPatchPlugin : BasePlugin
{
public static new readonly ManualLogSource Log = Logger.CreateLogSource("UUPatch");

View File

@@ -1,4 +1,9 @@
# Undead Universal Patch
## Undead Universal Patch
# Moved
Moved to https://gitea.proxnet.dev/GalvanicCorrosion/UndeadUniversalPatch
## Legacy Patch Plugin
Non-EAC, IL2CPP build patcher for Rec Room (Dec 2018\*-*Apr 3 2020)

View File

@@ -4,7 +4,7 @@
<TargetFramework>net6.0</TargetFramework>
<AssemblyName>undead_universal_patch_il2cpp</AssemblyName>
<Description>Non-EAC, IL2CPP build patcher for Rec Room (Late 2018*-*April 2020) </Description>
<Version>3.0.0</Version>
<Version>3.1.0</Version>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>latest</LangVersion>
<RestoreAdditionalProjectSources>