Compare commits

...

17 Commits

35 changed files with 557 additions and 147 deletions

View File

@@ -22,6 +22,8 @@ namespace undead_universal_patch_il2cpp.Core.Config
public static ConfigEntry<bool> ImageSignaturePatch; public static ConfigEntry<bool> ImageSignaturePatch;
public static ConfigEntry<bool> RegistrationPatch; public static ConfigEntry<bool> RegistrationPatch;
public static ConfigEntry<bool> AFKPatch; public static ConfigEntry<bool> AFKPatch;
public static ConfigEntry<bool> RefreshTokenFix;
public static ConfigEntry<bool> ProtonDeviceIdFix;
} }
public static class PatchConfigDefaults public static class PatchConfigDefaults
{ {
@@ -31,16 +33,24 @@ namespace undead_universal_patch_il2cpp.Core.Config
public static bool ImageSignaturePatch = false; public static bool ImageSignaturePatch = false;
public static bool RegistrationPatch = false; public static bool RegistrationPatch = false;
public static bool AFKPatch = false; public static bool AFKPatch = false;
public static bool RefreshTokenFix = false;
public static bool ProtonDeviceIdFix = false;
} }
public static class ServerPatchesConfig public static class ServerPatchesConfig
{ {
public static ConfigEntry<bool> CustomEmotes; public static ConfigEntry<bool> CustomEmotes;
public static ConfigEntry<bool> CustomPhoton; public static ConfigEntry<bool> CustomPhoton;
public static ConfigEntry<bool> CustomMarquee;
public static ConfigEntry<bool> CustomKnownDlls;
public static ConfigEntry<bool> CustomGameConfigurations;
} }
public static class ServerPatchesConfigDefaults public static class ServerPatchesConfigDefaults
{ {
public static bool CustomEmotes = false; public static bool CustomEmotes = false;
public static bool CustomPhoton = false; public static bool CustomPhoton = false;
public static bool CustomMarquee = false;
public static bool CustomKnownDlls = false;
public static bool CustomGameConfigurations = false;
} }
public static class GameManagerConfig public static class GameManagerConfig
{ {

View File

@@ -37,11 +37,11 @@ public class DediConfig<T>
if (loaded) return cached; if (loaded) return cached;
string data = GetAlways(); string data = GetAlways();
cached = JsonSerializer.Deserialize<T>(data, _options == null ? new JsonSerializerOptions() cached = JsonSerializer.Deserialize<T>(data, _options ?? new JsonSerializerOptions()
{ {
PropertyNameCaseInsensitive = true, PropertyNameCaseInsensitive = true,
AllowTrailingCommas = true AllowTrailingCommas = true
} : _options); });
loaded = true; loaded = true;
return cached; return cached;

View File

@@ -0,0 +1,38 @@
using BestHTTP;
using System.Collections.Generic;
using undead_universal_patch_il2cpp.Core.Config;
using undead_universal_patch_il2cpp.Patches;
using UnityEngine;
namespace undead_universal_patch_il2cpp.Core.Content.CustomRecNet.CheatManager;
public class CustomCheatManager : MonoBehaviour
{
public void Start()
{
if (ServerPatchesConfig.CustomKnownDlls.Value) RecNetInteractions.postNameServerActions.Add(DownloadKnownDlls);
}
void Patch(HTTPResponse _res, List<string> dlls)
{
UniversalPatchPlugin.Log.LogInfo("Setting new KnownDlls (server)");
HilePatch.Patch([.. dlls]);
}
void OnFailed(HTTPResponse _res)
{
if (PatchConfig.HilePatch.Value)
{
UniversalPatchPlugin.Log.LogInfo("Setting new KnownDlls (local fallback)");
HilePatch.Patch();
}
}
void DownloadKnownDlls()
{
RecNetInteractions.SendRequest<List<string>>(HTTPMethods.Get, RecNet.Service.API, "/api/undead/v1/knowndlls", Patch, OnFailed);
}
}

View File

@@ -0,0 +1,30 @@
using System.Collections.Generic;
using System.Runtime.InteropServices;
using BestHTTP;
using undead_universal_patch_il2cpp.Patches.UndeadGameManager;
using UnityEngine;
namespace undead_universal_patch_il2cpp.Core.Content.CustomRecNet.CustomGameManager;
public class CustomFreeSpawns : MonoBehaviour
{
public void Start()
{
RecNetInteractions.postAuthenticationActions.Add(DownloadFreeSpawns);
}
public void OnFailed([Optional] HTTPResponse res)
{
Util.ConditionalDebug($"CustomFreeSpawns failed: HTTP Error {res.StatusCode}");
}
public void Finished(HTTPResponse res, List<string> spawns)
{
FreeSpawnsPatch_Array.spawns = spawns;
}
public void DownloadFreeSpawns()
{
RecNetInteractions.SendRequest<List<string>>(HTTPMethods.Get, RecNet.Service.API, "/api/undead/v1/freespawns", Finished, OnFailed);
}
}

View File

@@ -0,0 +1,31 @@
using System.Collections.Generic;
using System.Runtime.InteropServices;
using BestHTTP;
using undead_universal_patch_il2cpp.Core.Content.UndeadGameManager;
using undead_universal_patch_il2cpp.Patches.UndeadGameManager;
using UnityEngine;
namespace undead_universal_patch_il2cpp.Core.Content.CustomRecNet.CustomGameManager;
public class CustomGameManager : MonoBehaviour
{
public void Start()
{
RecNetInteractions.postAuthenticationActions.Add(DownloadGameConfigAssets);
}
public void OnFailed([Optional] HTTPResponse res)
{
Util.ConditionalDebug($"CustomGameManager failed: HTTP Error {res.StatusCode}");
}
public void Finished(HTTPResponse res, Dictionary<string, GameConfigurationAssetDTO> configs)
{
GameConfiguratorPatch.gameConfig = configs;
}
public void DownloadGameConfigAssets()
{
RecNetInteractions.SendRequest<Dictionary<string, GameConfigurationAssetDTO>>(HTTPMethods.Get, RecNet.Service.API, "/api/undead/v1/gameconfigassets", Finished, OnFailed);
}
}

View File

@@ -1,6 +1,5 @@
using System; using System;
using BestHTTP; using BestHTTP;
using Il2CppInterop.Runtime;
using undead_universal_patch_il2cpp.Core.Config; using undead_universal_patch_il2cpp.Core.Config;
using undead_universal_patch_il2cpp.Patches.Photon; using undead_universal_patch_il2cpp.Patches.Photon;
using UnityEngine; using UnityEngine;
@@ -24,31 +23,32 @@ public class CustomPhoton : MonoBehaviour
public void Start() public void Start()
{ {
RecNetInteractions.postLocalAccountActions.Add(DownloadServerConfig); if (ServerPatchesConfig.CustomPhoton.Value) RecNetInteractions.postLocalAccountActions.Add(DownloadServerConfig);
else if (PhotonConfig.PatchPhotonIds.Value) LocalPatch();
}
void LocalPatch()
{
UniversalPatchPlugin.Log.LogInfo("Attempting Photon patch from local configuration");
PhotonPatch.Patch(new PhotonConfigDTO
{
Logging = PhotonConfig.PunLogging.Value,
AppID = PhotonConfig.AppID.Value,
VoiceAppID = PhotonConfig.VoiceAppID.Value,
SelfHosted = PhotonConfig.SelfHosted.Value,
ServerAddress = PhotonConfig.ServerAddress.Value,
ServerPort = PhotonConfig.ServerPort.Value,
ConnectionProtocol = PhotonConfig.ConnectionProtocol.Value
});
} }
void OnServerConfigFailed(HTTPResponse res) void OnServerConfigFailed(HTTPResponse res)
{ {
ServerConfigFailed = true; ServerConfigFailed = true;
if (PhotonConfig.PatchPhotonIds.Value) if (PhotonConfig.PatchPhotonIds.Value) LocalPatch();
{
UniversalPatchPlugin.Log.LogInfo("Attempting Photon patch from local configuration");
PhotonPatch.Patch(new PhotonConfigDTO
{
Logging = PhotonConfig.PunLogging.Value,
AppID = PhotonConfig.AppID.Value,
VoiceAppID = PhotonConfig.VoiceAppID.Value,
SelfHosted = PhotonConfig.SelfHosted.Value,
ServerAddress = PhotonConfig.ServerAddress.Value,
ServerPort = PhotonConfig.ServerPort.Value,
ConnectionProtocol = PhotonConfig.ConnectionProtocol.Value
});
}
} }
void ApplyPhotonConfig(HTTPResponse res, PhotonConfigDTO photonConfig) void ApplyPhotonConfig(HTTPResponse res, PhotonConfigDTO photonConfig)
{ {
if (!ServerPatchesConfig.CustomPhoton.Value) return;
try try
{ {
UniversalPatchPlugin.Log.LogInfo("Attempting Photon patch from server configuration"); UniversalPatchPlugin.Log.LogInfo("Attempting Photon patch from server configuration");

View File

@@ -15,6 +15,9 @@ public class RecNetInteractions
public static List<Action> postNameServerActions = []; public static List<Action> postNameServerActions = [];
public static List<Action> postAuthenticationActions = []; public static List<Action> postAuthenticationActions = [];
public static List<Action> postLocalAccountActions = []; 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) public static Il2CppSystem.Uri CreateServiceUri(Service service, string pathAndQuery)
{ {

View File

@@ -1,10 +0,0 @@
using System.Collections.Generic;
using undead_universal_patch_il2cpp.Core.Config;
namespace undead_universal_patch_il2cpp.Core.Content.UndeadGameManager;
public static class GameConfigurator
{
static readonly string name = "GameConfigurations";
public static DediConfig<Dictionary<string, GameConfigurationAssetDTO>> config = new(name, "{}", null);
}

View File

@@ -1,10 +0,0 @@
using System.Collections.Generic;
using undead_universal_patch_il2cpp.Core.Config;
namespace undead_universal_patch_il2cpp.Core.Content.UndeadGameManager;
public static class GameFreeSpawns
{
static readonly string name = "GameFreeSpawns";
public static DediConfig<List<string>> config = new(name, "[]", null);
}

View File

@@ -1,10 +1,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Mapster; using Mapster;
using undead_universal_patch_il2cpp.Core.Config; using undead_universal_patch_il2cpp.Core.Config;
using undead_universal_patch_il2cpp.Core.Content.CustomRecNet.CheatManager;
using undead_universal_patch_il2cpp.Core.Content.CustomRecNet.CustomEmotes; using undead_universal_patch_il2cpp.Core.Content.CustomRecNet.CustomEmotes;
using undead_universal_patch_il2cpp.Core.Content.CustomRecNet.CustomGameManager;
using undead_universal_patch_il2cpp.Core.Content.CustomRecNet.CustomPhoton; using undead_universal_patch_il2cpp.Core.Content.CustomRecNet.CustomPhoton;
using undead_universal_patch_il2cpp.Core.Content.UndeadGameManager; using undead_universal_patch_il2cpp.Core.Content.UndeadGameManager;
using undead_universal_patch_il2cpp.Patches.Video; using undead_universal_patch_il2cpp.Patches.Video;
@@ -33,10 +36,14 @@ public class Initialization
{ {
UniversalPatchPlugin.Log.LogInfo("PATCH LIST START ========================="); UniversalPatchPlugin.Log.LogInfo("PATCH LIST START =========================");
foreach (var method in UniversalPatchPlugin.Instance.HarmonyInstance.GetPatchedMethods()) foreach (var method in UniversalPatchPlugin.Instance.HarmonyInstance.GetPatchedMethods())
UniversalPatchPlugin.Log.LogInfo($"- {method.ToString()}"); {
var paramStr = string.Join(" ", [.. method.GetParameters().Select(param => param.ParameterType.FullName)]);
UniversalPatchPlugin.Log.LogInfo($"- {method.DeclaringType.FullName} {method.Name}({paramStr})");
}
UniversalPatchPlugin.Log.LogInfo("PATCH LIST END ========================="); UniversalPatchPlugin.Log.LogInfo("PATCH LIST END =========================");
} }
// to be removed in a future update
try try
{ {
CacheChangePatchConfigs(); CacheChangePatchConfigs();
@@ -49,8 +56,6 @@ public class Initialization
private static void CacheChangePatchConfigs() private static void CacheChangePatchConfigs()
{ {
if (GameManagerConfig.AnyGameFreeSpawn.Value) GameFreeSpawns.config.Get();
if (GameManagerConfig.StaticGameConfig.Value) GameConfigurator.config.Get();
VideoTamperPatch.config.Get(); VideoTamperPatch.config.Get();
} }
@@ -58,8 +63,11 @@ public class Initialization
{ {
UniversalPatchPlugin.Log.LogInfo("Attaching game objects"); UniversalPatchPlugin.Log.LogInfo("Attaching game objects");
if (ServerPatchesConfig.CustomEmotes.Value) UniversalPatchPlugin.Instance.AddComponent<CustomEmotes>(); UniversalPatchPlugin.Instance.AddComponent<SteamPlatform>();
UniversalPatchPlugin.Instance.AddComponent<CustomPhoton>(); 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>();
} }
private static void FetchConfigurations() private static void FetchConfigurations()
@@ -70,20 +78,25 @@ public class Initialization
"Log all BestHTTP requests sent by the game."); "Log all BestHTTP requests sent by the game.");
GenericConfig.VerboseRequestLogs = UniversalPatchPlugin.Instance.Config.Bind("Generic", "VerboseRequestLogs", GenericConfigDefaults.VerboseRequestLogs, GenericConfig.VerboseRequestLogs = UniversalPatchPlugin.Instance.Config.Bind("Generic", "VerboseRequestLogs", GenericConfigDefaults.VerboseRequestLogs,
"Add additional request information to BestHTTPProxy logs. Requires LogAllRequest to be enabled."); "Add additional request information to BestHTTPProxy logs. Requires LogAllRequest to be enabled.");
PatchConfig.CertificatePatch = UniversalPatchPlugin.Instance.Config.Bind("Generic", "CertificatePatch", PatchConfigDefaults.CertificatePatch, PatchConfig.CertificatePatch = UniversalPatchPlugin.Instance.Config.Bind("Patches", "CertificatePatch", PatchConfigDefaults.CertificatePatch,
"The game expects a certain certificate from rec.net when making HTTPS requests. Enable this to allow any valid certificate."); "The game expects a certain certificate from rec.net when making HTTPS requests. Enable this to allow any valid certificate.");
PatchConfig.HilePatch = UniversalPatchPlugin.Instance.Config.Bind("Generic", "HilePatch", PatchConfigDefaults.HilePatch, PatchConfig.HilePatch = UniversalPatchPlugin.Instance.Config.Bind("Patches", "HilePatch", PatchConfigDefaults.HilePatch,
"The game will close after a short period of time if BepInEx is found. Enable to stop this from happening." + "The game will close after a short period of time if BepInEx is found. Enable to stop this from happening." +
"\nThis will also enable the AGRoomRuntimeConfig patch. See the README for more info."); "\nThis will also enable the AGRoomRuntimeConfig patch. See the README for more info.");
PatchConfig.SignalRHandshakeFix = UniversalPatchPlugin.Instance.Config.Bind("Generic", "SignalRHandshakeFix", PatchConfigDefaults.SignalRHandshakeFix, PatchConfig.SignalRHandshakeFix = UniversalPatchPlugin.Instance.Config.Bind("Patches", "SignalRHandshakeFix", PatchConfigDefaults.SignalRHandshakeFix,
"Replace apostrophes with quotes in the initial SignalR handshake."); "Replace apostrophes with quotes in the initial SignalR handshake.");
PatchConfig.ImageSignaturePatch = UniversalPatchPlugin.Instance.Config.Bind("Generic", "ImageSignaturePatch", PatchConfigDefaults.ImageSignaturePatch, PatchConfig.ImageSignaturePatch = UniversalPatchPlugin.Instance.Config.Bind("Patches", "ImageSignaturePatch", PatchConfigDefaults.ImageSignaturePatch,
"When enabled, all image signatures will be valid." + "When enabled, all image signatures will be valid." +
"\nWorks only if the server appends a properly formatted signature header (signature does not need to be valid)"); "\nWorks only if the server appends a properly formatted signature header (signature does not need to be valid)");
PatchConfig.RegistrationPatch = UniversalPatchPlugin.Instance.Config.Bind("Generic", "RegistrationPatch", PatchConfigDefaults.RegistrationPatch, PatchConfig.RegistrationPatch = UniversalPatchPlugin.Instance.Config.Bind("Patches", "RegistrationPatch", PatchConfigDefaults.RegistrationPatch,
"Always disable the registration prompt."); "Always disable the registration prompt.");
PatchConfig.AFKPatch = UniversalPatchPlugin.Instance.Config.Bind("Generic", "AFKPatch", PatchConfigDefaults.AFKPatch, PatchConfig.AFKPatch = UniversalPatchPlugin.Instance.Config.Bind("Patches", "AFKPatch", PatchConfigDefaults.AFKPatch,
"Always present patch. Never get kicked to dorm for being AFK."); "Always present patch. Never get kicked to dorm for being AFK.");
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, ServerPatchesConfig.CustomEmotes = UniversalPatchPlugin.Instance.Config.Bind("ServerPatches", "CustomEmotes", ServerPatchesConfigDefaults.CustomEmotes,
"Modify the game's emote text with a configuration from the server."); "Modify the game's emote text with a configuration from the server.");
@@ -91,11 +104,17 @@ public class Initialization
"Patch Photon ServerSettings values with a configuration from the server." + "Patch Photon ServerSettings values with a configuration from the server." +
"\nWhen the server fails to provide a valid configuration, values from the local config will be used." + "\nWhen the server fails to provide a valid configuration, values from the local config will be used." +
"\nPhoton.PatchPhotonIds must be enabled for this fallback to work."); "\nPhoton.PatchPhotonIds must be enabled for this fallback to work.");
ServerPatchesConfig.CustomMarquee = UniversalPatchPlugin.Instance.Config.Bind("ServerPatches", "CustomMarquee", ServerPatchesConfigDefaults.CustomMarquee,
"Set custom text on the ^reccenter theater marquee.");
ServerPatchesConfig.CustomKnownDlls = UniversalPatchPlugin.Instance.Config.Bind("ServerPatches", "CustomKnownDlls", ServerPatchesConfigDefaults.CustomKnownDlls,
"Add items to the list of known DLLs.");
ServerPatchesConfig.CustomGameConfigurations = UniversalPatchPlugin.Instance.Config.Bind("ServerPatches", "CustomGameConfigurations", ServerPatchesConfigDefaults.CustomGameConfigurations,
"Custom GameAssetConfigurations.");
GameManagerConfig.AnyGameFreeSpawn = UniversalPatchPlugin.Instance.Config.Bind("GameManagerConfig", "AnyGameFreeSpawn", GameManagerConfigDefaults.AnyGameFreeSpawn, GameManagerConfig.AnyGameFreeSpawn = UniversalPatchPlugin.Instance.Config.Bind("GameManagerConfig", "AnyGameFreeSpawn", GameManagerConfigDefaults.AnyGameFreeSpawn,
$"Use patches from '{GameFreeSpawns.config.path}' to spawn in any valid player spawnpoint in specified games. See README.md"); $"Spawn in any valid player spawnpoint in specified games. See README.md");
GameManagerConfig.StaticGameConfig = UniversalPatchPlugin.Instance.Config.Bind("GameManagerConfig", "StaticGameConfig", GameManagerConfigDefaults.StaticGameConfig, GameManagerConfig.StaticGameConfig = UniversalPatchPlugin.Instance.Config.Bind("GameManagerConfig", "StaticGameConfig", GameManagerConfigDefaults.StaticGameConfig,
$"Use patches from '{GameConfigurator.config.path}' to set new configurations for built-in games. See README.md"); $"Set new configurations for built-in games. See README.md");
PhotonConfig.PatchPhotonIds = UniversalPatchPlugin.Instance.Config.Bind("Photon", "PatchPhotonIds", PhotonConfigDefaults.PatchPhotonIds, PhotonConfig.PatchPhotonIds = UniversalPatchPlugin.Instance.Config.Bind("Photon", "PatchPhotonIds", PhotonConfigDefaults.PatchPhotonIds,
"Patch Photon configuration."); "Patch Photon configuration.");

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

@@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2024 proxnet.dev Copyright (c) 2025 proxnet.dev by @zombieb
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@@ -2,6 +2,8 @@
[<-- Back to README.md](./README.md) [<-- 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. 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. Reminder that EAC or Referee builds will never be supported by Undead Universal Patch.

View File

@@ -1,9 +1,12 @@
using System; using System;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks;
using BestHTTP; using BestHTTP;
using BestHTTP.Forms;
using HarmonyLib; using HarmonyLib;
using undead_universal_patch_il2cpp.Core; using undead_universal_patch_il2cpp.Core;
using undead_universal_patch_il2cpp.Core.Config; using undead_universal_patch_il2cpp.Core.Config;
using UnityEngine;
namespace undead_universal_patch_il2cpp.Patches namespace undead_universal_patch_il2cpp.Patches
{ {
@@ -22,6 +25,8 @@ namespace undead_universal_patch_il2cpp.Patches
static readonly MethodInfo getHeaderMethod = requestType?.GetMethod("GetFirstHeaderValue"); static readonly MethodInfo getHeaderMethod = requestType?.GetMethod("GetFirstHeaderValue");
static readonly MethodInfo addHeaderMethod = requestType?.GetMethod("AddHeader"); 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 methodTypeProp = requestType?.GetProperty("MethodType");
static readonly PropertyInfo uriProp = requestType?.GetProperty("Uri"); static readonly PropertyInfo uriProp = requestType?.GetProperty("Uri");
static readonly PropertyInfo customCertProp = requestType?.GetProperty("CustomCertificateVerifyer"); static readonly PropertyInfo customCertProp = requestType?.GetProperty("CustomCertificateVerifyer");
@@ -30,13 +35,13 @@ namespace undead_universal_patch_il2cpp.Patches
getHeaderMethod, getHeaderMethod,
addHeaderMethod, addHeaderMethod,
methodTypeProp, methodTypeProp,
getFormFields,
formImplProp,
uriProp, uriProp,
customCertProp customCertProp
]).Success; ]).Success;
static MethodBase TargetMethod() => patchResult.Method; static MethodBase TargetMethod() => patchResult.Method;
[HarmonyPrefix]
static void Prefix(ref object request) static void Prefix(ref object request)
{ {
if (PatchConfig.CertificatePatch.Value) customCertProp.GetSetMethod().Invoke(request, [null]); if (PatchConfig.CertificatePatch.Value) customCertProp.GetSetMethod().Invoke(request, [null]);
@@ -59,6 +64,16 @@ namespace undead_universal_patch_il2cpp.Patches
if (newUri.Host.Contains("ns.rec.net")) newUri = new Il2CppSystem.Uri(NameserverConfig.NewUrl.Value); 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 // Finish request changes
string afterUrl = newUri.ToString(); string afterUrl = newUri.ToString();
@@ -66,14 +81,13 @@ namespace undead_universal_patch_il2cpp.Patches
if (GenericConfig.LogAllRequests.Value) if (GenericConfig.LogAllRequests.Value)
{ {
if (GenericConfig.VerboseRequestLogs.Value) UniversalPatchPlugin.Log.LogInfo("BestHTTP Request Log\n" + if (GenericConfig.VerboseRequestLogs.Value) UniversalPatchPlugin.Log.LogInfo($"BestHTTP Request Log{(customCertProp.GetGetMethod().Invoke(request, []) == null ? "" : " (verify)")}\n" +
$" URL Before : {beforeUrl}\n" + $" URL Before : {beforeUrl}\n" +
$" URL After : {(beforeUrl == afterUrl ? "(unmodified)" : afterUrl)}\n" + $" URL After : {(beforeUrl == afterUrl ? "(unmodified)" : afterUrl)}\n" +
$" Method : {method}\n" + $" Method : {method}\n" +
$" Content-Type : {contentType ?? "(not set)"}"); $" Content-Type : {contentType ?? "(not set)"}");
else UniversalPatchPlugin.Log.LogInfo("BestHTTPProxy Request Log\n" + else UniversalPatchPlugin.Log.LogInfo("BestHTTPProxy Request\n" +
$" Before : {beforeUrl}\n" + $" {method} {afterUrl}");
$" After : {afterUrl}");
} }
} }
} }

View File

@@ -1,17 +1,15 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using HarmonyLib; using HarmonyLib;
using undead_universal_patch_il2cpp.Core; using undead_universal_patch_il2cpp.Core;
using undead_universal_patch_il2cpp.Core.Config; using undead_universal_patch_il2cpp.Core.Config;
using undead_universal_patch_il2cpp.Core.Content.UndeadGameManager;
namespace undead_universal_patch_il2cpp.Patches.UndeadGameManager; namespace undead_universal_patch_il2cpp.Patches.UndeadGameManager;
[HarmonyPatch] [HarmonyPatch]
public class FreeSpawnsPatch_Array public class FreeSpawnsPatch_Array
{ {
public static List<string> config = GameFreeSpawns.config.Get(); public static List<string> spawns = null;
static PatchTypesResult patchResult = Util.ConfigPreparePatchTypes( static PatchTypesResult patchResult = Util.ConfigPreparePatchTypes(
GameManagerConfig.AnyGameFreeSpawn, GameManagerConfig.AnyGameFreeSpawn,
@@ -26,6 +24,12 @@ public class FreeSpawnsPatch_Array
public static void Postfix(ref GamePlayerSpawnPoint __instance) public static void Postfix(ref GamePlayerSpawnPoint __instance)
{ {
if (spawns == null)
{
Util.ConditionalDebug("FreeSpawns was not yet fetched!");
return;
}
Util.ConditionalDebug("Attempting FreeSpawns patch"); Util.ConditionalDebug("Attempting FreeSpawns patch");
GameManager man = NetworkedSingletonMonoBehaviour<GameManager>.instance; GameManager man = NetworkedSingletonMonoBehaviour<GameManager>.instance;
@@ -39,7 +43,7 @@ public class FreeSpawnsPatch_Array
Util.ConditionalDebug("CurrentGameConfiguration.configurationData was null"); Util.ConditionalDebug("CurrentGameConfiguration.configurationData was null");
return; return;
} }
if (!config.Contains(man.CurrentGameConfiguration.configurationData.Name)) if (!spawns.Contains(man.CurrentGameConfiguration.configurationData.Name))
{ {
Util.ConditionalDebug($"Game '{man.CurrentGameConfiguration.configurationData.Name}' is not specified by GameFreeSpawns"); Util.ConditionalDebug($"Game '{man.CurrentGameConfiguration.configurationData.Name}' is not specified by GameFreeSpawns");
return; return;

View File

@@ -1,4 +1,3 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using HarmonyLib; using HarmonyLib;
@@ -13,7 +12,7 @@ namespace undead_universal_patch_il2cpp.Patches.UndeadGameManager;
[HarmonyPatch] [HarmonyPatch]
public class GameConfiguratorPatch public class GameConfiguratorPatch
{ {
static Dictionary<string, GameConfigurationAssetDTO> gameConfig = GameConfigurator.config.Get(); public static Dictionary<string, GameConfigurationAssetDTO> gameConfig = null;
static PatchTypesResult patchResult = Util.ConfigPreparePatchTypes( static PatchTypesResult patchResult = Util.ConfigPreparePatchTypes(
GameManagerConfig.StaticGameConfig, GameManagerConfig.StaticGameConfig,
@@ -28,6 +27,12 @@ public class GameConfiguratorPatch
public static void Prefix(ref GameConfigurationAsset config, ref bool showNotification) public static void Prefix(ref GameConfigurationAsset config, ref bool showNotification)
{ {
if (gameConfig == null)
{
Util.ConditionalDebug("gameconfigassets was not yet fetched!");
return;
}
var conf = config; var conf = config;
showNotification = GenericConfig.PatchDebug.Value; showNotification = GenericConfig.PatchDebug.Value;

View File

@@ -1,4 +1,6 @@
using System.Reflection; using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using HarmonyLib; using HarmonyLib;
using undead_universal_patch_il2cpp.Core; using undead_universal_patch_il2cpp.Core;
using undead_universal_patch_il2cpp.Core.Config; using undead_universal_patch_il2cpp.Core.Config;
@@ -22,19 +24,16 @@ namespace undead_universal_patch_il2cpp.Patches
static void Prefix() static void Prefix()
{ {
if (PatchConfig.HilePatch.Value) HilePatch.Patch(); if (!ServerPatchesConfig.CustomKnownDlls.Value && PatchConfig.HilePatch.Value) HilePatch.Patch();
} }
} }
public static class HilePatch public static class HilePatch
{ {
public static void Patch() public static void Patch([Optional] string[] dlls)
{ {
GameObject cheatManagerObject = GameObject.Find("[CheatManager]"); Util.ConditionalDebug($"Patching KnownDlls with {(dlls != null ? dlls.Length : 0)} new filenames");
HileManager hileManager = cheatManagerObject.GetComponent<HileManager>(); string[] baseDlls = [
PropertyInfo knownDllsProperty = AccessTools.Property(typeof(HileManager), "KnownDlls");
knownDllsProperty.SetValue(hileManager, new Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppStringArray([
"GameAssembly.dll", "GameAssembly.dll",
"UnityPlayer.dll", "UnityPlayer.dll",
"WinPixEventRuntime.dll", "WinPixEventRuntime.dll",
@@ -46,9 +45,16 @@ namespace undead_universal_patch_il2cpp.Patches
"ddraw.dll", "ddraw.dll",
"dxgi.dll", "dxgi.dll",
"winhttp.dll" "winhttp.dll"
])); ];
if (dlls != null) baseDlls = baseDlls.Concat(dlls).ToArray();
UniversalPatchPlugin.Log.LogInfo("Hile patch succeeded."); GameObject cheatManagerObject = GameObject.Find("[CheatManager]");
HileManager hileManager = cheatManagerObject.GetComponent<HileManager>();
PropertyInfo knownDllsProperty = AccessTools.Property(typeof(HileManager), "KnownDlls");
knownDllsProperty.SetValue(hileManager, new Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppStringArray(baseDlls));
UniversalPatchPlugin.Log.LogInfo($"Hile patch succeeded: {baseDlls.Length} new KnownDlls.");
} }
} }
} }

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 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 UnityEngine;
namespace undead_universal_patch_il2cpp.Patches.Internals
{
/*[HarmonyPatch]
public class LockerroomOOBEFlow
{
static PatchTypesResult patchResult = Util.PreparePatchTypes(
"Event patch for changing marquee text in the reccenter",
"LockerroomOOBEFlow",
"Start"
);
static bool Prepare() => patchResult.Success;
static MethodBase TargetMethod() => patchResult.Method;
static void Postfix()
{
}
}*/
}

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,43 @@
using Il2CppInterop.Runtime;
using System.Collections.Generic;
using System.Linq;
using undead_universal_patch_il2cpp.Core.Config;
using UnityEngine;
namespace undead_universal_patch_il2cpp.Patches.Internals.NotificationTargets
{
public class MarqueeTexts : MonoBehaviour
{
void Start()
{
if (ServerPatchesConfig.CustomMarquee.Value)
{
UniversalPatchPlugin.Log.LogWarning("CustomMarquee patch is unavailable at this time. A future update may resolve this.");
//RecNetInteractions.onNotificationsOpen.Add(OnSocketOpen);
}
}
/*void OnSocketOpen()
{
var d = DelegateSupport.ConvertDelegate<RecNet.Notifications.NotificationHandler>(OnTextChange);
RecNet.Notifications.RegisterHandler("MarqueeTexts", d);
}
void OnTextChange(Dictionary<string, string> args)
{
GameObject go = GameObject.Find("DynamicObjects/[RecCenter_Marquee]");
string[] transforms = ["Text", "Now Playing", "SubText"];
var texts = transforms.Select(str => go.transform.Find(str).GetComponent<TextMesh>()).ToArray();
foreach (var t in transforms)
{
TextMesh tm = go.transform.Find(t).GetComponent<TextMesh>();
args.TryGetValue(t, out string res);
tm.text = res;
}
Core.Util.ConditionalDebug("Replaced marquee texts");
}*/
}
}

View File

@@ -0,0 +1,28 @@
using HarmonyLib;
using Il2CppInterop.Runtime;
using RecNet;
using System.Reflection;
using undead_universal_patch_il2cpp.Core;
using undead_universal_patch_il2cpp.Core.Content.CustomRecNet;
namespace undead_universal_patch_il2cpp.Patches.Internals
{
[HarmonyPatch]
public class Notifications
{
static PatchTypesResult patchResult = Core.Util.PreparePatchTypes(
"Event patch for notification availability",
"RecNet.Notifications",
"OnOpenInternal"
);
static bool Prepare() => patchResult.Success;
static MethodBase TargetMethod() => patchResult.Method;
static void Postfix(ref SignalRHubConnection hub)
{
UniversalPatchPlugin.Log.LogInfo("Running onNotificationsOpen actions");
foreach (var action in RecNetInteractions.onNotificationsOpen) action();
}
}
}

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

View File

@@ -0,0 +1,27 @@
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.Config;
namespace undead_universal_patch_il2cpp.Patches.Internals;
[HarmonyPatch]
public class RefreshTokenFix
{
static PatchTypesResult patchResult = Util.ConfigPreparePatchTypes(
PatchConfig.RefreshTokenFix,
"Refresh token implementation fix for some servers",
"RecNet.Login",
"OnLocalAccountUpdated"
);
static MethodBase TargetMethod() => patchResult.Method;
static bool Prepare() => patchResult.Success;
static bool Prefix() => false;
}

View File

@@ -1,18 +0,0 @@
using System.Reflection;
using HarmonyLib;
using undead_universal_patch_il2cpp.Core;
namespace undead_universal_patch_il2cpp.Patches.Photon;
[HarmonyPatch]
public class NameserverTest
{
static PatchTypesResult patchTypesResult = Util.PreparePatchTypes(
"Photon nameserver test",
"NetworkingPeer",
"GetNameServerAddress"
);
static bool Prepare() => patchTypesResult.Success;
static MethodBase TargetMethod() => patchTypesResult.Method;
}

View File

@@ -37,7 +37,7 @@ public class PhotonPatch
PropertyInfo voiceAppIdProperty = serverSettingsType.GetRuntimeProperty("VoiceAppID"); PropertyInfo voiceAppIdProperty = serverSettingsType.GetRuntimeProperty("VoiceAppID");
Util.ConditionalDebug($"New Photon AppID: '{photonConfig.AppID}'"); Util.ConditionalDebug($"New Photon AppID: '{photonConfig.AppID}'");
Util.ConditionalDebug($"New Photon AppID: '{photonConfig.VoiceAppID}'"); Util.ConditionalDebug($"New Photon VoiceAppID: '{photonConfig.VoiceAppID}'");
appIdProperty.SetValue(serverSettings, photonConfig.AppID); appIdProperty.SetValue(serverSettings, photonConfig.AppID);
voiceAppIdProperty.SetValue(serverSettings, photonConfig.VoiceAppID); voiceAppIdProperty.SetValue(serverSettings, photonConfig.VoiceAppID);

View File

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

View File

@@ -6,7 +6,7 @@ using undead_universal_patch_il2cpp.Core;
namespace undead_universal_patch_il2cpp; namespace undead_universal_patch_il2cpp;
[BepInPlugin("dev.proxnet.recroom.universalpatch.noneac.il2cpp", "Undead Universal Patch", "2.1.1")] [BepInPlugin("dev.proxnet.recroom.universalpatch.noneac.il2cpp", "Undead Universal Patch", "3.1.0")]
public class UniversalPatchPlugin : BasePlugin public class UniversalPatchPlugin : BasePlugin
{ {
public static new readonly ManualLogSource Log = Logger.CreateLogSource("UUPatch"); 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) Non-EAC, IL2CPP build patcher for Rec Room (Dec 2018\*-*Apr 3 2020)
@@ -31,7 +36,9 @@ Run BepInEx interop on your build and add the following assemblies to new folder
- `BepInEx/interop/Il2CppSystem.dll` - `BepInEx/interop/Il2CppSystem.dll`
- `BepInEx/interop/Photon3Unity3D.dll` - `BepInEx/interop/Photon3Unity3D.dll`
- `BepInEx/interop/RecRoom.Datastructures.Runtime` - `BepInEx/interop/RecRoom.Datastructures.Runtime`
- `BepInEx/interop/RecRoom.Promises.Runtime`
- `BepInEx/interop/UnityEngine.CoreModule.dll` - `BepInEx/interop/UnityEngine.CoreModule.dll`
- `BepInEx/interop/UnityEngine.TextRenderingModule.dll`
## Dependencies ## Dependencies

View File

@@ -32,6 +32,14 @@ Voice will go over the same gameserver port as PUN does when selfhosting.
See [the source](./Core/Content/CustomRecNet/CustomPhoton/CustomPhoton.cs) for more information. See [the source](./Core/Content/CustomRecNet/CustomPhoton/CustomPhoton.cs) for more information.
### `API: GET "/api/undead/v1/knowndlls"` (post-nameserver)
Expects: `List<string>`
Add custom DLL filenames to `CheatManager.KnownDlls`. `winhttp.dll` is added by default and does not need to be specified by the server.
When the server patch is enabled at the same time as the local patch (HilePatch), the local patch will be used as a fallback and will add only `winhttp.dll`.
See [the source](./Core/Content/CustomRecNet/CheatManager/CustomCheatManager.cs) for more information.
## DTOs ## DTOs
### `EmoteConfigDTO` ### `EmoteConfigDTO`

View File

@@ -1,28 +0,0 @@
{
"Accessibility": 2,
"AllowsJuniors": true,
"CloningAllowed": false,
"Description": "john madden",
"DisableMicAutoMute": true,
"Name": "splootyneam",
"ReleaseStatus": 2,
"ReplicationId": "fec8e7b3-660e-4df4-9c33-b40eb4093823",
"Scenes": [
{
"CanMatchmakeInto": true,
"IsSandbox": true,
"MaxPlayers": 1,
"Name": "Home",
"ReleaseStatus": 2,
"ReplicationId": "1fdb87da-df23-4c96-a28b-4cb5fd3f7667",
"RoomSceneLocationId": "aafb38f1-beb9-4af3-94e3-2985d502302a",
"SupportsJoinInProgress": false,
"UseAgeBasedMatchmaking": false,
"UseLevelBasedMatchmaking": false,
"UseRecRoyaleMatchmaking": false
}
],
"SupportsLevelVoting": false,
"SupportsTeleportVR": true,
"SupportsWalkVR": true
}

View File

@@ -4,7 +4,7 @@
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyName>undead_universal_patch_il2cpp</AssemblyName> <AssemblyName>undead_universal_patch_il2cpp</AssemblyName>
<Description>Non-EAC, IL2CPP build patcher for Rec Room (Late 2018*-*April 2020) </Description> <Description>Non-EAC, IL2CPP build patcher for Rec Room (Late 2018*-*April 2020) </Description>
<Version>2.1.1</Version> <Version>3.1.0</Version>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<RestoreAdditionalProjectSources> <RestoreAdditionalProjectSources>
@@ -15,6 +15,10 @@
<RootNamespace>undead_universal_patch_il2cpp</RootNamespace> <RootNamespace>undead_universal_patch_il2cpp</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<None Include="Core\Content\CustomRecNet\CheatManager\CustomCheatManager.cs" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.*" IncludeAssets="compile" /> <PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.*" IncludeAssets="compile" />
<PackageReference Include="Mapster" Version="7.4.0" /> <PackageReference Include="Mapster" Version="7.4.0" />
@@ -42,5 +46,8 @@
<Reference Include="UnityEngine.CoreModule"> <Reference Include="UnityEngine.CoreModule">
<HintPath>AssemblyReferences\UnityEngine.CoreModule.dll</HintPath> <HintPath>AssemblyReferences\UnityEngine.CoreModule.dll</HintPath>
</Reference> </Reference>
<Reference Include="UnityEngine.TextRenderingModule">
<HintPath>AssemblyReferences\UnityEngine.TextRenderingModule.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
</Project> </Project>