using System; using System.Reflection; using HarmonyLib; using undead_universal_patch_il2cpp.Core; namespace undead_universal_patch_il2cpp.Patches { [HarmonyPatch] public class PhotonPatchEvent { static readonly string TargetTypeName = "PhotonNetwork"; static readonly string TargetMethodName = "ConnectUsingSettings"; static readonly string Description = "Photon ConnectUsingSettings patch event"; static readonly Type targetType = AccessTools.TypeByName(TargetTypeName); static bool Prepare() { if (!PhotonConfig.PatchPhotonIds.Value) return false; if (targetType == null) { Plugin.Log.LogWarning($"'{Description}' disabled. The type for this patch was not found."); return false; } if (AccessTools.Method(targetType, TargetMethodName) == null) { Plugin.Log.LogWarning($"'{Description}' disabled. The method for this patch was not found."); return false; } Plugin.Log.LogInfo($"'{Description}' succeeded validation."); return true; } static MethodInfo TargetMethod() => AccessTools.Method(targetType, TargetMethodName); static void Prefix() { if (GenericConfig.PatchDebug.Value) Plugin.Log.LogDebug("Attempting Photon patch"); PhotonPatch.Patch(); } } [HarmonyPatch] public class ForceSelfHostedPhoton { class HarmonyState { public object code; } static readonly string TargetTypeName = "PUNNetworkManager"; static readonly string TargetMethodName = "OnConnectedToMaster"; static readonly string Description = "Force JoinOrCreateRoom when connected to master"; static readonly Type targetType = AccessTools.TypeByName(TargetTypeName); static readonly MethodInfo targetMethod = AccessTools.Method(targetType, TargetMethodName); static bool Prepare() { if (!(PhotonConfig.PatchPhotonIds.Value && PhotonConfig.SelfHosted.Value)) return false; if (targetType == null) { Plugin.Log.LogWarning($"'{Description}' disabled. The type for this patch was not found."); return false; } if (targetMethod == null) { Plugin.Log.LogWarning($"'{Description}' disabled. The method for this patch was not found."); return false; } Plugin.Log.LogInfo($"'{Description}' succeeded validation."); return true; } static MethodBase TargetMethod() => targetMethod; static void Prefix(ref PUNNetworkManager __instance, ref HarmonyState __state) { __state = new HarmonyState(); PropertyInfo targetGameSessionProperty = __instance.GetType().GetRuntimeProperty("targetGameSession"); if (targetGameSessionProperty == null) { Plugin.Log.LogFatal("Cannot force masterserver: targetGameSessionProperty was null."); return; } var targetGameSession = targetGameSessionProperty.GetValue(__instance); if (targetGameSession == null) { Plugin.Log.LogFatal("Cannot force masterserver: targetGameSession was null."); return; } PropertyInfo photonRegionIdProperty = targetGameSession.GetType().GetRuntimeProperty("PhotonRegionId"); if (photonRegionIdProperty == null) { Plugin.Log.LogFatal("Cannot force masterserver: photonRegionIdProperty was null."); return; } __state.code = photonRegionIdProperty.GetValue(targetGameSession); photonRegionIdProperty.SetValue(targetGameSession, 4); if (GenericConfig.PatchDebug.Value) Plugin.Log.LogDebug("Forcing masterserver"); } static void Postfix(ref PUNNetworkManager __instance, ref HarmonyState __state) { PropertyInfo targetGameSessionProperty = __instance.GetType().GetRuntimeProperty("targetGameSession"); if (targetGameSessionProperty == null) { Plugin.Log.LogFatal("Cannot force masterserver postfix: targetGameSessionProperty was null."); return; } var targetGameSession = targetGameSessionProperty.GetValue(__instance); if (targetGameSession == null) { Plugin.Log.LogFatal("Cannot force masterserver postfix: targetGameSession was null."); return; } PropertyInfo photonRegionIdProperty = targetGameSession.GetType().GetRuntimeProperty("PhotonRegionId"); if (photonRegionIdProperty == null) { Plugin.Log.LogFatal("Cannot force masterserver: photonRegionIdProperty was null."); return; } photonRegionIdProperty.SetValue(targetGameSession, __state.code); if (GenericConfig.PatchDebug.Value) Plugin.Log.LogDebug("Masterserver regionId roundtrip"); } } public class PhotonPatch { public static void Patch() { // It's fine to reference enums after we're pretty sure the relevant types exist // i think Type photonNetworkType = AccessTools.TypeByName("PhotonNetwork"); Type serverSettingsType = AccessTools.TypeByName("ServerSettings"); if (photonNetworkType == null || serverSettingsType == null) { Plugin.Log.LogError("Cannot patch Photon: PhotonNetwork or ServerSettings types were not found. Is this build supported?"); return; } PropertyInfo photonServerSettingsProperty = photonNetworkType.GetRuntimeProperty("PhotonServerSettings"); object serverSettings = photonServerSettingsProperty.GetValue(serverSettingsType); if (PhotonConfig.PunLogging.Value) { PropertyInfo loggingProperty = serverSettingsType.GetRuntimeProperty("PunLogging"); loggingProperty.SetValue(serverSettings, PhotonLogLevel.Full); PropertyInfo networkLoggingProperty = serverSettingsType.GetRuntimeProperty("NetworkLogging"); networkLoggingProperty.SetValue(serverSettings, ExitGames.Client.Photon.DebugLevel.ALL); } PropertyInfo appIdProperty = serverSettingsType.GetRuntimeProperty("AppID"); PropertyInfo voiceAppIdProperty = serverSettingsType.GetRuntimeProperty("VoiceAppID"); if (GenericConfig.PatchDebug.Value) Plugin.Log.LogDebug($"New Photon AppID: '{PhotonConfig.AppID.Value}'"); if (GenericConfig.PatchDebug.Value) Plugin.Log.LogDebug($"New Photon AppID: '{PhotonConfig.VoiceAppID.Value}'"); appIdProperty.SetValue(serverSettings, PhotonConfig.AppID.Value); voiceAppIdProperty.SetValue(serverSettings, PhotonConfig.VoiceAppID.Value); if (PhotonConfig.SelfHosted.Value) { MethodInfo useMyServerMethod = serverSettingsType.GetMethod("UseMyServer"); useMyServerMethod.Invoke(serverSettings, [ PhotonConfig.ServerAddress.Value, PhotonConfig.ServerPort.Value, PhotonConfig.AppID.Value, ]); } Type authValuesType = AccessTools.TypeByName("AuthenticationValues"); if (authValuesType != null) { PropertyInfo networkingPeerProperty = photonNetworkType.GetRuntimeProperty("networkingPeer"); if (networkingPeerProperty == null) { Plugin.Log.LogError("Cannot patch Photon: networkingPeerProperty was null. Is this build supported?"); return; } if (networkingPeerProperty.GetValue(null) == null) { Plugin.Log.LogError("Cannot patch Photon: networkingPeerInstance was null. Is this build supported?"); return; } string id = Util.LocalInstanceGuid; if (GenericConfig.PatchDebug.Value) Plugin.Log.LogDebug($"Instance GUID is {id}"); PhotonNetwork.AuthValues = new AuthenticationValues { UserId = id }; if (GenericConfig.PatchDebug.Value) Plugin.Log.LogDebug($"Set the authValues userId to {id}"); } Plugin.Log.LogInfo($"Photon patch ({(PhotonConfig.SelfHosted.Value ? "self-hosted" : "cloud")}) succeeded."); } } }