using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using LateRepo.Patches; using Microsoft.CodeAnalysis; using MonoMod.RuntimeDetour; using Photon.Pun; using Photon.Realtime; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("LateRepo")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.6.3.0")] [assembly: AssemblyInformationalVersion("1.6.3+9d7dcafb5936c5801908597da461971340dc9791")] [assembly: AssemblyProduct("LateRepo")] [assembly: AssemblyTitle("LateRepo")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.6.3.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LateRepo { [BepInPlugin("chaos.holz.laterepo", "LateRepo", "1.6.4")] public class Plugin : BaseUnityPlugin { private const string modGUID = "chaos.holz.laterepo"; private const string modName = "LateRepo"; private const string modVersion = "1.6.4"; private static readonly Harmony _harmony = new Harmony("LateRepo"); internal static readonly ManualLogSource logger = Logger.CreateLogSource("LateRepo"); internal static ConfigEntry JoinButton; internal static ConfigEntry JoinShop; internal static ConfigEntry splashScreen; internal static ConfigEntry moonPhase; internal static ConfigEntry PlayGamePopup; internal static ConfigEntry StartGamePopup; internal static ConfigEntry LoadSavePopup; internal static ConfigEntry PickRegion; internal static ConfigEntry PasswordSkip; internal static ConfigEntry PasswordSet; private void Awake() { Configs(); LateJoinPatch.InitializeHooks(); PatchAllStuff(); logger.LogInfo((object)"[LateRepo] erfolgreich geladen!"); } private void Configs() { JoinButton = ((BaseUnityPlugin)this).Config.Bind("Late Join", "Invite Button", true, "If true, a button appears in the Escape menu that opens the Steam overlay for inviting players."); JoinShop = ((BaseUnityPlugin)this).Config.Bind("Late Join", "Late Join Shop", false, "If it’s true, players can late join in the shop."); PickRegion = ((BaseUnityPlugin)this).Config.Bind("Lobby Settings", "Auto Region", true, "If true, it automatically picks the best region, so it doesn’t ask you to choose a region anymore."); PasswordSkip = ((BaseUnityPlugin)this).Config.Bind("Lobby Settings", "Passwort Skip", false, "If true, it automatically bypasses the password input screen."); PasswordSet = ((BaseUnityPlugin)this).Config.Bind("Lobby Settings", "SetPasswort", "", "Enter the password you want for your private lobby. If it’s empty, no password will be set. This only works if Password Skip is true."); splashScreen = ((BaseUnityPlugin)this).Config.Bind("Popup", "Splash Screen", true, "If true, the splash screen at the beginning is skipped."); moonPhase = ((BaseUnityPlugin)this).Config.Bind("Popup", "Moon Phase Change", true, "If true,"); PlayGamePopup = ((BaseUnityPlugin)this).Config.Bind("Popup", "Play Game Popup", true, "If true, the pop-ups for “Host a Game?” and “Warning: Playing with random players” are automatically accepted when you click PUBLIC or PRIVATE GAME, so they don’t appear anymore."); LoadSavePopup = ((BaseUnityPlugin)this).Config.Bind("Popup", "Load Save Popup", false, "If true, the pop-up for “Load Save?” is automatically accepted when you click LOAD SAVE, so it doesn’t appear anymore."); StartGamePopup = ((BaseUnityPlugin)this).Config.Bind("Popup", "Start Game Popup", true, "If true, the pop-up for “Start Game” is automatically accepted when you click START GAME, so it doesn’t appear anymore."); } private void PatchAllStuff() { if (splashScreen.Value) { _harmony.PatchAll(typeof(LevelGeneratorPatch)); } if (PickRegion.Value) { _harmony.PatchAll(typeof(MenuPageRegionPatch)); } if (StartGamePopup.Value || PlayGamePopup.Value || LoadSavePopup.Value) { _harmony.PatchAll(typeof(PopUpPatch)); } if (PasswordSkip.Value || !string.IsNullOrEmpty(PasswordSet.Value)) { _harmony.PatchAll(typeof(MenuPagePasswordPatch)); } _harmony.PatchAll(typeof(PlayerNameCheckerUpdatePatch)); _harmony.PatchAll(typeof(MenuPageEscPatch)); if (moonPhase.Value) { _harmony.PatchAll(typeof(MoonUIPatch)); } } } } namespace LateRepo.Patches { [HarmonyPatch(typeof(MenuPageRegions))] internal static class MenuPageRegionPatch { [HarmonyPatch(typeof(MenuPageRegions), "Start")] [HarmonyPrefix] private static void MenuPageRegionStartPatch(MenuPageRegions __instance) { __instance.PickRegion(""); } [HarmonyPatch(typeof(MenuPagePublicGameChoice), "ExitPage")] [HarmonyPrefix] private static bool PublicExitPagePatch() { MenuManager.instance.PageCloseAll(); MenuManager.instance.PageOpen((MenuPageIndex)0, false); return false; } } [HarmonyPatch(typeof(MenuManager))] internal static class PopUpPatch { public static bool isPublicGame; [HarmonyPatch(typeof(MenuManager), "PagePopUpTwoOptions")] [HarmonyPrefix] private static bool PagePopUpTwoOptionsPatch(MenuButtonPopUp menuButtonPopUp, string popUpHeader, Color popUpHeaderColor, string popUpText, string option1Text, string option2Text, bool richText) { if (IsPrivateGamePopup(popUpHeader, popUpText)) { isPublicGame = false; } else if (IsPublicGamePopup(popUpHeader, popUpText)) { isPublicGame = true; } if (Plugin.PlayGamePopup.Value) { if (IsPrivateGamePopup(popUpHeader, popUpText)) { UnityEvent option1Event = menuButtonPopUp.option1Event; if (option1Event != null) { option1Event.Invoke(); } return false; } if (IsPublicGamePopup(popUpHeader, popUpText)) { UnityEvent option1Event2 = menuButtonPopUp.option1Event; if (option1Event2 != null) { option1Event2.Invoke(); } return false; } } if (Plugin.StartGamePopup.Value && IsStartGamePopup(popUpHeader, popUpText)) { UnityEvent option1Event3 = menuButtonPopUp.option1Event; if (option1Event3 != null) { option1Event3.Invoke(); } return false; } if (Plugin.LoadSavePopup.Value && IsLoadSavePopup(popUpHeader, popUpText)) { UnityEvent option1Event4 = menuButtonPopUp.option1Event; if (option1Event4 != null) { option1Event4.Invoke(); } return false; } return true; } private static bool IsPrivateGamePopup(string header, string body) { header = header.ToLower(); body = body.ToLower(); if (!header.Contains("host") && !body.Contains("best computer")) { return body.Contains("are you this friend"); } return true; } private static bool IsPublicGamePopup(string header, string body) { header = header.ToLower(); body = body.ToLower(); if (!header.Contains("warning") && !body.Contains("random players")) { return body.Contains("mean people"); } return true; } private static bool IsStartGamePopup(string header, string body) { header = header.ToLower(); body = body.ToLower(); if (!header.Contains("start") && !body.Contains("everyone ready")) { return body.Contains("once the game"); } return true; } private static bool IsLoadSavePopup(string header, string body) { header = header.ToLower(); body = body.ToLower(); if (!header.Contains("load")) { return body.Contains("load this save"); } return true; } } [HarmonyPatch(typeof(MenuPagePassword))] internal static class MenuPagePasswordPatch { private static bool passwordAlreadySet; [HarmonyPatch(typeof(MenuPagePassword), "Update")] [HarmonyPrefix] private static void PasswordSkipPatch(MenuPagePassword __instance) { if (!Plugin.PasswordSkip.Value) { return; } if (!string.IsNullOrEmpty(Plugin.PasswordSet.Value)) { if (string.IsNullOrEmpty(Plugin.PasswordSet.Value) || passwordAlreadySet) { return; } string text = Plugin.PasswordSet.Value.ToUpper().Replace("\n", "").Replace("\r", "") .Replace(" ", ""); AccessTools.Field(typeof(MenuPagePassword), "password").SetValue(__instance, text); passwordAlreadySet = true; Plugin.logger.LogInfo((object)("[LateRepo] Automatisches Passwort gesetzt: " + text)); } __instance.ConfirmButton(); } [HarmonyPatch(typeof(MenuPagePassword), "Start")] [HarmonyPrefix] private static void PasswortStartPatch() { passwordAlreadySet = false; } } [HarmonyPatch(typeof(MoonUI))] internal static class MoonUIPatch { [HarmonyPatch(typeof(MoonUI), "Check")] [HarmonyPostfix] private static void MoonUICheckPatch(MoonUI __instance) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 if ((int)(State)AccessTools.Field(typeof(MoonUI), "state").GetValue(__instance) > 0) { AccessTools.Field(typeof(MoonUI), "skip").SetValue(__instance, true); __instance.SetState((State)0); } } } [HarmonyPatch(typeof(LevelGenerator))] internal static class LevelGeneratorPatch { [HarmonyPatch(typeof(LevelGenerator), "Start")] [HarmonyPrefix] private static void LevelGeneratorStartPatch() { if (SemiFunc.IsSplashScreen() && Object.op_Implicit((Object)(object)RunManager.instance) && Object.op_Implicit((Object)(object)DataDirector.instance) && DataDirector.instance.SettingValueFetch((Setting)58) == 1) { RunManager.instance.levelCurrent = RunManager.instance.levelMainMenu; } } } internal static class LateJoinPatch { private static readonly FieldInfo removeFilterFieldInfo = AccessTools.Field(typeof(PhotonNetwork), "removeFilter"); private static readonly FieldInfo keyByteSevenFieldInfo = AccessTools.Field(typeof(PhotonNetwork), "keyByteSeven"); private static readonly FieldInfo serverCleanOptionsFieldInfo = AccessTools.Field(typeof(PhotonNetwork), "ServerCleanOptions"); private static readonly MethodInfo raiseEventInternalMethodInfo = AccessTools.Method(typeof(PhotonNetwork), "RaiseEventInternal", (Type[])null, (Type[])null); private static Hook changeLevelHook; private static Hook spawnHook; private static Hook levelGenHook; private static Hook startHook; public static bool canJoin; public static void InitializeHooks() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown changeLevelHook = new Hook((MethodBase)AccessTools.Method(typeof(RunManager), "ChangeLevel", (Type[])null, (Type[])null), typeof(LateJoinPatch).GetMethod("ChangeLevelHook")); spawnHook = new Hook((MethodBase)AccessTools.Method(typeof(PlayerAvatar), "Spawn", (Type[])null, (Type[])null), typeof(LateJoinPatch).GetMethod("SpawnHook")); levelGenHook = new Hook((MethodBase)AccessTools.Method(typeof(LevelGenerator), "Start", (Type[])null, (Type[])null), typeof(LateJoinPatch).GetMethod("LevelGeneratorHook")); startHook = new Hook((MethodBase)AccessTools.Method(typeof(PlayerAvatar), "Start", (Type[])null, (Type[])null), typeof(LateJoinPatch).GetMethod("PlayerAvatarStartHook")); } public static void ChangeLevelHook(Action orig, RunManager self, bool _completedLevel, bool _levelFailed, ChangeLevelType _changeLevelType) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) if (_levelFailed || !PhotonNetwork.IsMasterClient) { orig(self, _completedLevel, _levelFailed, _changeLevelType); return; } object value = AccessTools.Field(typeof(RunManager), "runManagerPUN").GetValue(self); object? value2 = AccessTools.Field(typeof(RunManagerPUN), "photonView").GetValue(value); PhotonNetwork.RemoveBufferedRPCs(((PhotonView)((value2 is PhotonView) ? value2 : null)).ViewID, (string)null, (int[])null); PhotonView[] array = Object.FindObjectsOfType(); foreach (PhotonView val in array) { Scene scene = ((Component)val).gameObject.scene; if (((Scene)(ref scene)).buildIndex != -1) { ClearPhotonCache(val); } } orig(self, _completedLevel, arg3: false, _changeLevelType); canJoin = SemiFunc.RunIsLobbyMenu() || SemiFunc.RunIsLobby() || (SemiFunc.RunIsShop() && Plugin.JoinShop.Value); if (canJoin) { SteamManager.instance.UnlockLobby(true); PhotonNetwork.CurrentRoom.IsOpen = true; Plugin.logger.LogInfo((object)"[LateRepo] Lobbystatus geändert: offen"); if (PopUpPatch.isPublicGame) { Plugin.logger.LogInfo((object)"Public"); PhotonNetwork.CurrentRoom.IsVisible = true; GameManager.instance.SetConnectRandom(true); } } else { SteamManager.instance.LockLobby(); PhotonNetwork.CurrentRoom.IsOpen = false; if (PopUpPatch.isPublicGame) { PhotonNetwork.CurrentRoom.IsVisible = false; GameManager.instance.SetConnectRandom(false); Plugin.logger.LogInfo((object)"nicht Public"); } } } public static void SpawnHook(Action orig, PlayerAvatar self, Vector3 position, Quaternion rotation) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (!(bool)AccessTools.Field(typeof(PlayerAvatar), "spawned").GetValue(self)) { orig(self, position, rotation); } } public static void LevelGeneratorHook(Action orig, LevelGenerator self) { if (PhotonNetwork.IsMasterClient && SemiFunc.RunIsLobby()) { PhotonNetwork.RemoveBufferedRPCs(self.PhotonView.ViewID, (string)null, (int[])null); } orig(self); } public static void PlayerAvatarStartHook(Action orig, PlayerAvatar self) { orig(self); if (PhotonNetwork.IsMasterClient && !SemiFunc.RunIsLobby()) { self.photonView.RPC("LoadingLevelAnimationCompletedRPC", (RpcTarget)3, Array.Empty()); } } private static void ClearPhotonCache(PhotonView photonView) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) try { object? value = removeFilterFieldInfo.GetValue(null); Hashtable val = (Hashtable)((value is Hashtable) ? value : null); object value2 = keyByteSevenFieldInfo.GetValue(null); object? value3 = serverCleanOptionsFieldInfo.GetValue(null); RaiseEventOptions val2 = (RaiseEventOptions)((value3 is RaiseEventOptions) ? value3 : null); val[value2] = photonView.InstantiationId; val2.CachingOption = (EventCaching)6; raiseEventInternalMethodInfo.Invoke(null, new object[4] { (byte)202, val, val2, SendOptions.SendReliable }); } catch (Exception ex) { Plugin.logger.LogError((object)("[LateRepo] ClearPhotonCache Fehler: " + ex.Message)); } } } [HarmonyPatch(typeof(MenuPageEsc))] internal static class MenuPageEscPatch { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__0_0; internal void b__0_0() { SteamManager instance = SteamManager.instance; if (instance != null) { instance.OpenSteamOverlayToInvite(); } } } [CompilerGenerated] private sealed class d__1 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public GameObject inviteGO; public GameObject quitGameGO; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__1(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: { <>1__state = -1; if ((Object)(object)inviteGO == (Object)null || (Object)(object)quitGameGO == (Object)null) { return false; } SetInviteText(inviteGO); RectTransform component = inviteGO.GetComponent(); RectTransform component2 = quitGameGO.GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null) { return false; } component.anchorMin = component2.anchorMin; component.anchorMax = component2.anchorMax; component.pivot = component2.pivot; component.sizeDelta = component2.sizeDelta; ((Transform)component).localScale = ((Transform)component2).localScale; component.anchoredPosition = component2.anchoredPosition + new Vector2(0f, 30f); ResizeButtonToText(inviteGO); return false; } } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [HarmonyPatch("Start")] [HarmonyPostfix] private static void MenuPageStartPatch(MenuPageEsc __instance) { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown if (!Plugin.JoinButton.Value || !LateJoinPatch.canJoin || (Object)(object)__instance == (Object)null) { return; } MenuButton val = FindButtonByLabel(((Component)__instance).transform, "QUIT GAME"); if ((Object)(object)val == (Object)null) { return; } Transform parent = ((Component)val).transform.parent; if ((Object)(object)parent == (Object)null || (Object)(object)parent.Find("InviteButton") != (Object)null) { return; } GameObject val2 = Object.Instantiate(((Component)val).gameObject, parent); MenuButtonPopUp component = val2.GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } SetInviteText(val2); Button component2 = val2.GetComponent