using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using Archipelago.MultiClient.Net; using Archipelago.MultiClient.Net.BounceFeatures.DeathLink; using Archipelago.MultiClient.Net.Enums; using Archipelago.MultiClient.Net.Exceptions; using Archipelago.MultiClient.Net.Helpers; using Archipelago.MultiClient.Net.MessageLog.Messages; using Archipelago.MultiClient.Net.Models; using Archipelago.MultiClient.Net.Packets; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using CupheadArchipelago.AP; using CupheadArchipelago.Config; using CupheadArchipelago.Helpers.FVerParser; using CupheadArchipelago.Hooks; using CupheadArchipelago.Hooks.AssetHooks; using CupheadArchipelago.Hooks.AudioHooks; using CupheadArchipelago.Hooks.CutsceneHooks; using CupheadArchipelago.Hooks.LevelHooks; using CupheadArchipelago.Hooks.MapHooks; using CupheadArchipelago.Hooks.MapHooks.MapNPCHooks; using CupheadArchipelago.Hooks.MapHooks.MapUIHooks; using CupheadArchipelago.Hooks.MenuHooks; using CupheadArchipelago.Hooks.Mitigations; using CupheadArchipelago.Hooks.PlayerHooks; using CupheadArchipelago.Hooks.PlayerHooks.LevelPlayerHooks; using CupheadArchipelago.Hooks.PlayerHooks.PlanePlayerHooks; using CupheadArchipelago.Hooks.ShopHooks; using CupheadArchipelago.Interfaces; using CupheadArchipelago.Mapping; using CupheadArchipelago.Resources; using CupheadArchipelago.TestEnv; using CupheadArchipelago.Unity; using CupheadArchipelago.Util; using FVer; using HarmonyLib; using Microsoft.CodeAnalysis; using Mono.Cecil; using Mono.Cecil.Cil; using MonoMod.Cil; using MonoMod.Utils; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using TMPro; using UnityEngine; using UnityEngine.U2D; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: InternalsVisibleTo("CupheadArchipelago.Tests")] [assembly: AssemblyCompany("CupheadArchipelago")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyCopyright("Copyright 2025-2026 JKLeckr")] [assembly: AssemblyDescription("The Cuphead Archipelago Mod")] [assembly: AssemblyFileVersion("0.2.2.7")] [assembly: AssemblyInformationalVersion("0.2.2.7+bfbb14c69c183d93e4986aa6b388a58a603c0a9d")] [assembly: AssemblyProduct("CupheadArchipelago")] [assembly: AssemblyTitle("CupheadArchipelago")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.2.2.7")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } [CompilerGenerated] [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 FVer { public sealed class FVersion : IComparable { public readonly int Baseline; public readonly int Release; public readonly string Prefix; public readonly string Postfix; private readonly int _revision; public string Revision => IntToRevision(_revision); public int RevisionNumber => _revision; public FVersion(int baseline, string revision, int release = 0, string prefix = "", string postfix = "") { if (baseline < 0 || release < 0) { throw new ArgumentOutOfRangeException("Version numbers must not be negative"); } if (string.IsNullOrEmpty(revision)) { throw new ArgumentNullException("Revision cannot be null or empty"); } _revision = RevisionToInt(revision); Baseline = baseline; Release = release; Prefix = prefix ?? ""; Postfix = postfix ?? ""; } public FVersion(int baseline, int revision, int release = 0, string prefix = "", string postfix = "") { if (baseline < 0 || revision < 0 || release < 0) { throw new ArgumentOutOfRangeException("Version numbers must not be negative"); } _revision = revision; Baseline = baseline; Release = release; Prefix = prefix ?? ""; Postfix = postfix ?? ""; } public FVersion(string version) { if (string.IsNullOrEmpty(version) || version.Trim().Length == 0) { throw new ArgumentNullException("version"); } string postfix = ""; int num = version.IndexOf('-'); if (num >= 0) { postfix = version.Substring(num + 1); version = version.Substring(0, num); } string prefix = ""; int num2 = -1; for (int i = 0; i < version.Length; i++) { if (char.IsDigit(version[i])) { num2 = i; break; } } if (num2 > 0) { prefix = version.Substring(0, num2); } else if (num2 < 0) { throw new FormatException("No baseline digits found in version string."); } version = version.Substring(num2); int j; for (j = 0; j < version.Length && char.IsDigit(version[j]); j++) { } if (j < 2) { throw new FormatException("Baseline must contain at least two digits."); } int baseline = int.Parse(version.Substring(0, j)); int num3 = j; int k; for (k = 0; num3 + k < version.Length && char.IsLetter(version[num3 + k]); k++) { } if (k == 0) { throw new FormatException("No alphabetical revision segment found."); } string rev = version.Substring(num3, k); int release = 0; int l = num3 + k; if (l < version.Length && version[l] == '.') { l++; int num4 = l; for (; l < version.Length && char.IsDigit(version[l]); l++) { } if (num4 == l) { throw new FormatException("Expected release number after '.'"); } release = int.Parse(version.Substring(num4, l - num4)); } if (l < version.Length) { throw new FormatException("Unexpected trailing characters in version string after release number: '" + version.Substring(l) + "'"); } Baseline = baseline; _revision = RevisionToInt(rev); Release = release; Prefix = prefix; Postfix = postfix; } private static int RevisionToInt(string rev) { int num = 0; foreach (char c in rev) { if (c < 'a' || c > 'z') { throw new FormatException("Invalid revision character"); } int num2 = c - 97 + 1; if (num > (int.MaxValue - num2) / 26) { throw new OverflowException("Revision string is too large to fit in Int32"); } num = num * 26 + num2; } return num - 1; } private static string IntToRevision(int i) { if (i < 0) { throw new ArgumentOutOfRangeException("i"); } int num = i + 1; char[] array = new char[16]; int num2 = array.Length; while (num > 0) { num--; array[--num2] = (char)(97 + num % 26); num /= 26; } return new string(array, num2, array.Length - num2); } public static FVersion Zero() { return new FVersion(0, 0); } public int CompareTo(FVersion other) { if (other == null) { return 1; } int num = string.IsNullOrEmpty(Prefix).CompareTo(string.IsNullOrEmpty(other.Prefix)); if (num != 0) { return num; } num = string.Compare(Prefix, other.Prefix, StringComparison.Ordinal); if (num != 0) { return num; } int baseline = Baseline; num = baseline.CompareTo(other.Baseline); if (num != 0) { return num; } num = RevisionToInt(Revision).CompareTo(RevisionToInt(other.Revision)); if (num != 0) { return num; } baseline = Release; num = baseline.CompareTo(other.Release); if (num != 0) { return num; } num = string.IsNullOrEmpty(Postfix).CompareTo(string.IsNullOrEmpty(other.Postfix)); if (num != 0) { return num; } return ComparePostfix(Postfix, other.Postfix); } private static int ComparePostfix(string a, string b) { string[] array = a.Split(new char[1] { '.' }); string[] array2 = b.Split(new char[1] { '.' }); int num = Math.Max(a.Length, b.Length); for (int i = 0; i < num; i++) { bool flag = i >= array.Length; bool flag2 = i >= array2.Length; if (flag && flag2) { return 0; } if (flag) { return -1; } if (flag2) { return 1; } string text = array[i]; string text2 = array2[i]; int result; bool flag3 = int.TryParse(text, out result); int result2; bool flag4 = int.TryParse(text2, out result2); if (flag3 && flag4) { int num2 = result.CompareTo(result2); if (num2 != 0) { return num2; } continue; } if (flag3) { return -1; } if (flag4) { return 1; } if (string.Compare(text, text2, StringComparison.Ordinal) != 0) { return 0; } } return 0; } public override bool Equals(object obj) { if (obj is FVersion fVersion) { return Baseline == fVersion.Baseline && _revision == fVersion._revision && Release == fVersion.Release && Prefix == fVersion.Prefix && Postfix == fVersion.Postfix; } return false; } public override int GetHashCode() { int num = 17; int num2 = num; int baseline = Baseline; num = num2 * (29 + baseline.GetHashCode()); int num3 = num; baseline = _revision; num = num3 * (29 + baseline.GetHashCode()); int num4 = num; baseline = Release; num = num4 * (29 + baseline.GetHashCode()); num *= 29 + (Prefix?.GetHashCode() ?? 0); return num * (29 + (Postfix?.GetHashCode() ?? 0)); } public override string ToString() { string text = string.Format("{0}{1:D2}{2}", Prefix ?? "", Baseline, Revision); if (Release > 0) { text += $".{Release}"; } if (!string.IsNullOrEmpty(Postfix)) { text = text + "-" + Postfix; } return text; } public static bool operator ==(FVersion a, FVersion b) { return a.Equals(b); } public static bool operator !=(FVersion a, FVersion b) { return !(a == b); } public static bool operator <(FVersion a, FVersion b) { return a.CompareTo(b) < 0; } public static bool operator >(FVersion a, FVersion b) { return a.CompareTo(b) > 0; } public static bool operator <=(FVersion a, FVersion b) { return a.CompareTo(b) <= 0; } public static bool operator >=(FVersion a, FVersion b) { return a.CompareTo(b) >= 0; } public static implicit operator string(FVersion v) { return v.ToString(); } } } namespace CupheadArchipelago { public class LogFiles { private const string LOG_FILE_EXTENSION = ".log"; public static string LogDirPath { get; private set; } public static string LogName { get; private set; } public static string LogFile { get; private set; } public static string LogFullPath { get; private set; } public static int LogFileMax { get; private set; } public static void Setup(string logName, string logDirName, int fileMax) { LogName = logName; LogFileMax = fileMax; if (fileMax == 0) { Logging.Log("Mod log file max set to 0. Not logging."); return; } string text = Path.Combine(Paths.BepInExRootPath, "logs"); Directory.CreateDirectory(text); string text2 = Path.Combine(text, logDirName); Directory.CreateDirectory(text2); LogDirPath = text2; SetupLogName(logName, text2, fileMax); } private static void SetupLogName(string logName, string logDir, int fileMax) { Logging.LogDebug(logDir); var list = (from name in Directory.GetFiles(logDir, logName + ".*.log").Select(Path.GetFileName) select new { FileName = name, Number = GetLogFileNumber(name, logName) } into x where x.Number.HasValue orderby x.Number.Value select x).ToList(); while (fileMax > 0 && list.Count >= fileMax) { var anon = list.First(); File.Delete(Path.Combine(logDir, anon.FileName)); list.RemoveAt(0); } uint value; if (list.Any()) { value = list.Last().Number.Value; value++; } else { value = 0u; } LogFile = string.Format("{0}.{1}{2}", logName, value, ".log"); LogFullPath = Path.Combine(LogDirPath, LogFile); } private static uint? GetLogFileNumber(string fileName, string logName) { if (fileName.StartsWith(logName, StringComparison.Ordinal) && fileName.EndsWith(".log", StringComparison.Ordinal)) { string s = fileName.Substring(logName.Length + 1, fileName.Length - logName.Length - ".log".Length - 1); if (uint.TryParse(s, out var result)) { return result; } } return null; } } public class Logging { private static bool init; private static ManualLogSource logSource; private static Action logAction; private static LoggingFlags loggingFlags; private static LoggingFlags permLoggingFlags; internal static void Init(ManualLogSource logSource, LoggingFlags loggingFlags) { if (init) { Console.WriteLine("Reinitializing Logging..."); } Logging.logSource = logSource ?? throw new ArgumentNullException("logSource cannot be null."); logAction = logSource.Log; Logging.loggingFlags = loggingFlags; permLoggingFlags = loggingFlags; init = true; } internal static void Init(Action logAction, LoggingFlags loggingFlags) { if (init) { Console.WriteLine("Reinitializing Logging..."); } logSource = null; Logging.logAction = logAction; Logging.loggingFlags = loggingFlags; permLoggingFlags = loggingFlags; init = true; } internal static bool IsLoggingInitialized() { return init; } public static void Log(object data) { Log(data, (LogLevel)16); } public static void Log(object data, LogLevel logLevel) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Invalid comparison between Unknown and I4 //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_000e: Unknown result type (might be due to invalid IL or missing references) Log(data, ((int)logLevel != 1 && (int)logLevel != 2) ? LoggingFlags.Info : LoggingFlags.None, logLevel); } public static void Log(object data, LoggingFlags requiredFlags) { Log(data, requiredFlags, (LogLevel)16); } public static void Log(object data, LoggingFlags requiredFlags, LogLevel logLevel) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (!init) { throw new Exception("Logging not initialized."); } if (IsLoggingFlagsEnabled(requiredFlags)) { logAction(logLevel, data); } } public static void LogMessage(object data) { LogMessage(data, LoggingFlags.Message); } public static void LogMessage(object data, LoggingFlags requiredFlags) { Log(data, requiredFlags, (LogLevel)8); } public static void LogWarning(object data) { LogWarning(data, LoggingFlags.Warning); } public static void LogWarning(object data, LoggingFlags requiredFlags) { Log(data, requiredFlags, (LogLevel)4); } public static void LogError(object data) { LogError(data, LoggingFlags.None); } public static void LogError(object data, LoggingFlags requiredFlags) { Log(data, requiredFlags, (LogLevel)2); } public static void LogFatal(object data) { LogFatal(data, LoggingFlags.None); } public static void LogFatal(object data, LoggingFlags requiredFlags) { Log(data, requiredFlags, (LogLevel)1); } public static void LogDebug(object data) { LogDebug(data, LoggingFlags.Debug); } public static void LogDebug(object data, LoggingFlags requiredFlags) { Log(data, requiredFlags, (LogLevel)(MConf.IsDebugLogsInfo() ? 16 : 32)); } public static bool IsLoggingFlagsEnabled(LoggingFlags flags) { return (flags & loggingFlags) == flags; } public static bool IsDebugEnabled() { return IsLoggingFlagsEnabled(LoggingFlags.Debug); } internal static void SetLoggingFlags(LoggingFlags flags) { loggingFlags = flags; } internal static void AddLoggingFlags(LoggingFlags flags) { loggingFlags |= flags; } internal static void RemoveLoggingFlags(LoggingFlags flags) { loggingFlags &= (LoggingFlags)(byte)(~(int)flags); } internal static void ResetLoggingFlags() { loggingFlags = permLoggingFlags; } public static string GetLogSourceName() { ManualLogSource obj = logSource; return (obj != null) ? obj.SourceName : null; } } [Flags] public enum LoggingFlags : byte { None = 0, PluginInfo = 1, Info = 2, Message = 4, Warning = 8, Network = 0x10, Debug = 0x20 } public class ModLogListener : ILogListener, IDisposable { public string LogSourceName { get; protected set; } public LogLevel DisplayedLogLevel { get; set; } public TextWriter LogWriter { get; protected set; } public Timer FlushTimer { get; protected set; } public bool WriteFromUnityLog { get; set; } public ModLogListener(string logFile, string logPath, string logSourceName, LogLevel displayedLogLevel = (LogLevel)63, bool includeUnityLog = true) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) LogSourceName = logSourceName; WriteFromUnityLog = includeUnityLog; DisplayedLogLevel = displayedLogLevel; FileStream stream = default(FileStream); if (!Utility.TryOpenFileStream(Path.Combine(logPath, logFile), FileMode.Create, ref stream, FileAccess.Write, FileShare.Read)) { Logging.LogError("Could not open \"" + logFile + "\" for writing. Not logging."); return; } Logging.Log("Logging to " + logFile); LogWriter = TextWriter.Synchronized(new StreamWriter(stream, Utility.UTF8NoBom)); FlushTimer = new Timer(delegate { LogWriter?.Flush(); }, null, 2000, 2000); } public void LogEvent(object sender, LogEventArgs eventArgs) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Invalid comparison between Unknown and I4 if ((WriteFromUnityLog && eventArgs.Source is UnityLogSource) || (eventArgs.Source.SourceName == LogSourceName && (eventArgs.Level & DisplayedLogLevel) > 0)) { LogWriter.WriteLine(((object)eventArgs).ToString()); } } public void Dispose() { FlushTimer?.Dispose(); LogWriter?.Flush(); LogWriter?.Dispose(); } ~ModLogListener() { Dispose(); } } public enum LicenseLogModes { Off = 0, FirstParty = 1, All = 3 } public static class ModInfo { public class ModLicense { public readonly string PLUGIN_NOTICE = "CupheadArchipelago\n Copyright (C) 2025-2026 JKLeckr\n\n The CupheadArchipelago project is free software: you can redistribute it and/or\n modify it under the terms of the GNU General Public License as published by the\n Free Software Foundation, either version 3 of the License, or (at your option)\n any later version.\n\n This program is distributed in the hope that it will be useful, but\n WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with this program.\n If not, see .\n\n ------------------------------------------------------------------------------------------\n\n The assets the CupheadArchipelago project have their own license:\n\n CupheadArchipelago Assets (c) 2025-2026 by JKLeckr is licensed under CC BY-SA 4.0.\n To view a copy of this license, visit https://creativecommons.org/licenses/by-sa/4.0/\n"; public readonly string PLUGIN_LIB_NOTICE = "\n This mod uses third party libraries.\n For their notices, see the accompanying LICENSE.third-party.txt or a copy at\n You can set \"LogLicense = All\" in the config to print the third party notice."; } public class ModLicenseThirdParty { public readonly string PLUGIN_LIB_FULL_NOTICE = "CupheadArchipelago uses third party libraries listed in this document.\n\n FVer\n\n Copyright 2025-2026 JKLeckr\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n\n Archipelago.MultiClient.NET\n\n MIT License\n\n Copyright (c) 2022 Hussein Farran, Jarno Westhof\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in all\n copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n SOFTWARE.\n\n Archipelago.MultiClient.NET also includes:\n\n A modified fork of Newtonsoft Json.NET\n\n The MIT License (MIT)\n\n Copyright (c) 2007 James Newton-King\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in all\n copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n SOFTWARE.\n\n\n native-websocket-sharp\n\n Copyright (c) 2026 JKLeckr\n\n Mozilla Public License Version 2.0\n ==================================\n\n 1. Definitions\n --------------\n\n 1.1. \"Contributor\"\n means each individual or legal entity that creates, contributes to\n the creation of, or owns Covered Software.\n\n 1.2. \"Contributor Version\"\n means the combination of the Contributions of others (if any) used\n by a Contributor and that particular Contributor's Contribution.\n\n 1.3. \"Contribution\"\n means Covered Software of a particular Contributor.\n\n 1.4. \"Covered Software\"\n means Source Code Form to which the initial Contributor has attached\n the notice in Exhibit A, the Executable Form of such Source Code\n Form, and Modifications of such Source Code Form, in each case\n including portions thereof.\n\n 1.5. \"Incompatible With Secondary Licenses\"\n means\n\n (a) that the initial Contributor has attached the notice described\n in Exhibit B to the Covered Software; or\n\n (b) that the Covered Software was made available under the terms of\n version 1.1 or earlier of the License, but not also under the\n terms of a Secondary License.\n\n 1.6. \"Executable Form\"\n means any form of the work other than Source Code Form.\n\n 1.7. \"Larger Work\"\n means a work that combines Covered Software with other material, in\n a separate file or files, that is not Covered Software.\n\n 1.8. \"License\"\n means this document.\n\n 1.9. \"Licensable\"\n means having the right to grant, to the maximum extent possible,\n whether at the time of the initial grant or subsequently, any and\n all of the rights conveyed by this License.\n\n 1.10. \"Modifications\"\n means any of the following:\n\n (a) any file in Source Code Form that results from an addition to,\n deletion from, or modification of the contents of Covered\n Software; or\n\n (b) any new file in Source Code Form that contains any Covered\n Software.\n\n 1.11. \"Patent Claims\" of a Contributor\n means any patent claim(s), including without limitation, method,\n process, and apparatus claims, in any patent Licensable by such\n Contributor that would be infringed, but for the grant of the\n License, by the making, using, selling, offering for sale, having\n made, import, or transfer of either its Contributions or its\n Contributor Version.\n\n 1.12. \"Secondary License\"\n means either the GNU General Public License, Version 2.0, the GNU\n Lesser General Public License, Version 2.1, the GNU Affero General\n Public License, Version 3.0, or any later versions of those\n licenses.\n\n 1.13. \"Source Code Form\"\n means the form of the work preferred for making modifications.\n\n 1.14. \"You\" (or \"Your\")\n means an individual or a legal entity exercising rights under this\n License. For legal entities, \"You\" includes any entity that\n controls, is controlled by, or is under common control with You. For\n purposes of this definition, \"control\" means (a) the power, direct\n or indirect, to cause the direction or management of such entity,\n whether by contract or otherwise, or (b) ownership of more than\n fifty percent (50%) of the outstanding shares or beneficial\n ownership of such entity.\n\n 2. License Grants and Conditions\n --------------------------------\n\n 2.1. Grants\n\n Each Contributor hereby grants You a world-wide, royalty-free,\n non-exclusive license:\n\n (a) under intellectual property rights (other than patent or trademark)\n Licensable by such Contributor to use, reproduce, make available,\n modify, display, perform, distribute, and otherwise exploit its\n Contributions, either on an unmodified basis, with Modifications, or\n as part of a Larger Work; and\n\n (b) under Patent Claims of such Contributor to make, use, sell, offer\n for sale, have made, import, and otherwise transfer either its\n Contributions or its Contributor Version.\n\n 2.2. Effective Date\n\n The licenses granted in Section 2.1 with respect to any Contribution\n become effective for each Contribution on the date the Contributor first\n distributes such Contribution.\n\n 2.3. Limitations on Grant Scope\n\n The licenses granted in this Section 2 are the only rights granted under\n this License. No additional rights or licenses will be implied from the\n distribution or licensing of Covered Software under this License.\n Notwithstanding Section 2.1(b) above, no patent license is granted by a\n Contributor:\n\n (a) for any code that a Contributor has removed from Covered Software;\n or\n\n (b) for infringements caused by: (i) Your and any other third party's\n modifications of Covered Software, or (ii) the combination of its\n Contributions with other software (except as part of its Contributor\n Version); or\n\n (c) under Patent Claims infringed by Covered Software in the absence of\n its Contributions.\n\n This License does not grant any rights in the trademarks, service marks,\n or logos of any Contributor (except as may be necessary to comply with\n the notice requirements in Section 3.4).\n\n 2.4. Subsequent Licenses\n\n No Contributor makes additional grants as a result of Your choice to\n distribute the Covered Software under a subsequent version of this\n License (see Section 10.2) or under the terms of a Secondary License (if\n permitted under the terms of Section 3.3).\n\n 2.5. Representation\n\n Each Contributor represents that the Contributor believes its\n Contributions are its original creation(s) or it has sufficient rights\n to grant the rights to its Contributions conveyed by this License.\n\n 2.6. Fair Use\n\n This License is not intended to limit any rights You have under\n applicable copyright doctrines of fair use, fair dealing, or other\n equivalents.\n\n 2.7. Conditions\n\n Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted\n in Section 2.1.\n\n 3. Responsibilities\n -------------------\n\n 3.1. Distribution of Source Form\n\n All distribution of Covered Software in Source Code Form, including any\n Modifications that You create or to which You contribute, must be under\n the terms of this License. You must inform recipients that the Source\n Code Form of the Covered Software is governed by the terms of this\n License, and how they can obtain a copy of this License. You may not\n attempt to alter or restrict the recipients' rights in the Source Code\n Form.\n\n 3.2. Distribution of Executable Form\n\n If You distribute Covered Software in Executable Form then:\n\n (a) such Covered Software must also be made available in Source Code\n Form, as described in Section 3.1, and You must inform recipients of\n the Executable Form how they can obtain a copy of such Source Code\n Form by reasonable means in a timely manner, at a charge no more\n than the cost of distribution to the recipient; and\n\n (b) You may distribute such Executable Form under the terms of this\n License, or sublicense it under different terms, provided that the\n license for the Executable Form does not attempt to limit or alter\n the recipients' rights in the Source Code Form under this License.\n\n 3.3. Distribution of a Larger Work\n\n You may create and distribute a Larger Work under terms of Your choice,\n provided that You also comply with the requirements of this License for\n the Covered Software. If the Larger Work is a combination of Covered\n Software with a work governed by one or more Secondary Licenses, and the\n Covered Software is not Incompatible With Secondary Licenses, this\n License permits You to additionally distribute such Covered Software\n under the terms of such Secondary License(s), so that the recipient of\n the Larger Work may, at their option, further distribute the Covered\n Software under the terms of either this License or such Secondary\n License(s).\n\n 3.4. Notices\n\n You may not remove or alter the substance of any license notices\n (including copyright notices, patent notices, disclaimers of warranty,\n or limitations of liability) contained within the Source Code Form of\n the Covered Software, except that You may alter any license notices to\n the extent required to remedy known factual inaccuracies.\n\n 3.5. Application of Additional Terms\n\n You may choose to offer, and to charge a fee for, warranty, support,\n indemnity or liability obligations to one or more recipients of Covered\n Software. However, You may do so only on Your own behalf, and not on\n behalf of any Contributor. You must make it absolutely clear that any\n such warranty, support, indemnity, or liability obligation is offered by\n You alone, and You hereby agree to indemnify every Contributor for any\n liability incurred by such Contributor as a result of warranty, support,\n indemnity or liability terms You offer. You may include additional\n disclaimers of warranty and limitations of liability specific to any\n jurisdiction.\n\n 4. Inability to Comply Due to Statute or Regulation\n ---------------------------------------------------\n\n If it is impossible for You to comply with any of the terms of this\n License with respect to some or all of the Covered Software due to\n statute, judicial order, or regulation then You must: (a) comply with\n the terms of this License to the maximum extent possible; and (b)\n describe the limitations and the code they affect. Such description must\n be placed in a text file included with all distributions of the Covered\n Software under this License. Except to the extent prohibited by statute\n or regulation, such description must be sufficiently detailed for a\n recipient of ordinary skill to be able to understand it.\n\n 5. Termination\n --------------\n\n 5.1. The rights granted under this License will terminate automatically\n if You fail to comply with any of its terms. However, if You become\n compliant, then the rights granted under this License from a particular\n Contributor are reinstated (a) provisionally, unless and until such\n Contributor explicitly and finally terminates Your grants, and (b) on an\n ongoing basis, if such Contributor fails to notify You of the\n non-compliance by some reasonable means prior to 60 days after You have\n come back into compliance. Moreover, Your grants from a particular\n Contributor are reinstated on an ongoing basis if such Contributor\n notifies You of the non-compliance by some reasonable means, this is the\n first time You have received notice of non-compliance with this License\n from such Contributor, and You become compliant prior to 30 days after\n Your receipt of the notice.\n\n 5.2. If You initiate litigation against any entity by asserting a patent\n infringement claim (excluding declaratory judgment actions,\n counter-claims, and cross-claims) alleging that a Contributor Version\n directly or indirectly infringes any patent, then the rights granted to\n You by any and all Contributors for the Covered Software under Section\n 2.1 of this License shall terminate.\n\n 5.3. In the event of termination under Sections 5.1 or 5.2 above, all\n end user license agreements (excluding distributors and resellers) which\n have been validly granted by You or Your distributors under this License\n prior to termination shall survive termination.\n\n ************************************************************************\n * *\n * 6. Disclaimer of Warranty *\n * ------------------------- *\n * *\n * Covered Software is provided under this License on an \"as is\" *\n * basis, without warranty of any kind, either expressed, implied, or *\n * statutory, including, without limitation, warranties that the *\n * Covered Software is free of defects, merchantable, fit for a *\n * particular purpose or non-infringing. The entire risk as to the *\n * quality and performance of the Covered Software is with You. *\n * Should any Covered Software prove defective in any respect, You *\n * (not any Contributor) assume the cost of any necessary servicing, *\n * repair, or correction. This disclaimer of warranty constitutes an *\n * essential part of this License. No use of any Covered Software is *\n * authorized under this License except under this disclaimer. *\n * *\n ************************************************************************\n\n ************************************************************************\n * *\n * 7. Limitation of Liability *\n * -------------------------- *\n * *\n * Under no circumstances and under no legal theory, whether tort *\n * (including negligence), contract, or otherwise, shall any *\n * Contributor, or anyone who distributes Covered Software as *\n * permitted above, be liable to You for any direct, indirect, *\n * special, incidental, or consequential damages of any character *\n * including, without limitation, damages for lost profits, loss of *\n * goodwill, work stoppage, computer failure or malfunction, or any *\n * and all other commercial damages or losses, even if such party *\n * shall have been informed of the possibility of such damages. This *\n * limitation of liability shall not apply to liability for death or *\n * personal injury resulting from such party's negligence to the *\n * extent applicable law prohibits such limitation. Some *\n * jurisdictions do not allow the exclusion or limitation of *\n * incidental or consequential damages, so this exclusion and *\n * limitation may not apply to You. *\n * *\n ************************************************************************\n\n 8. Litigation\n -------------\n\n Any litigation relating to this License may be brought only in the\n courts of a jurisdiction where the defendant maintains its principal\n place of business and such litigation shall be governed by laws of that\n jurisdiction, without reference to its conflict-of-law provisions.\n Nothing in this Section shall prevent a party's ability to bring\n cross-claims or counter-claims.\n\n 9. Miscellaneous\n ----------------\n\n This License represents the complete agreement concerning the subject\n matter hereof. If any provision of this License is held to be\n unenforceable, such provision shall be reformed only to the extent\n necessary to make it enforceable. Any law or regulation which provides\n that the language of a contract shall be construed against the drafter\n shall not be used to construe this License against a Contributor.\n\n 10. Versions of the License\n ---------------------------\n\n 10.1. New Versions\n\n Mozilla Foundation is the license steward. Except as provided in Section\n 10.3, no one other than the license steward has the right to modify or\n publish new versions of this License. Each version will be given a\n distinguishing version number.\n\n 10.2. Effect of New Versions\n\n You may distribute the Covered Software under the terms of the version\n of the License under which You originally received the Covered Software,\n or under the terms of any subsequent version published by the license\n steward.\n\n 10.3. Modified Versions\n\n If you create software not governed by this License, and you want to\n create a new license for such software, you may create and use a\n modified version of this License if you rename the license and remove\n any references to the name of the license steward (except to note that\n such modified license differs from this License).\n\n 10.4. Distributing Source Code Form that is Incompatible With Secondary\n Licenses\n\n If You choose to distribute Source Code Form that is Incompatible With\n Secondary Licenses under the terms of this version of the License, the\n notice described in Exhibit B of this License must be attached.\n\n Exhibit A - Source Code Form License Notice\n -------------------------------------------\n\n This Source Code Form is subject to the terms of the Mozilla Public\n License, v. 2.0. If a copy of the MPL was not distributed with this\n file, You can obtain one at https://mozilla.org/MPL/2.0/.\n\n If it is not possible or desirable to put the notice in a particular\n file, then You may include the notice in a location (such as a LICENSE\n file in a relevant directory) where a recipient would be likely to look\n for such a notice.\n\n You may add additional accurate notices of copyright ownership.\n\n Exhibit B - \"Incompatible With Secondary Licenses\" Notice\n ---------------------------------------------------------\n\n This Source Code Form is \"Incompatible With Secondary Licenses\", as\n defined by the Mozilla Public License, v. 2.0.\n\n\n native-websocket-sharp uses the following third party libraries and/or attributions:\n\n For the managed component (websocket-sharp):\n\n Some of native-websocket-sharp is derived from the original websocket-sharp:\n\n The MIT License (MIT)\n\n Copyright (c) 2010-2026 sta.blockhead\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in\n all copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n THE SOFTWARE.\n\n\n For the native component (nativews):\n\n tungstenite-rs (signal fork) 0.27.0\n\n Repository: https://github.com/signalapp/tungstenite-rs\n License: MIT OR Apache-2.0\n\n Included license texts:\n\n MIT\n\n Copyright (c) 2017 Alexey Galakhov\n Copyright (c) 2016 Jason Housley\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in\n all copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n THE SOFTWARE.\n\n rustls 0.23.0\n\n Repository: https://github.com/rustls/rustls\n License: Apache-2.0 OR ISC OR MIT\n\n Included license texts:\n\n MIT\n\n Copyright (c) 2016 Joseph Birr-Pixton \n\n Permission is hereby granted, free of charge, to any\n person obtaining a copy of this software and associated\n documentation files (the \"Software\"), to deal in the\n Software without restriction, including without\n limitation the rights to use, copy, modify, merge,\n publish, distribute, sublicense, and/or sell copies of\n the Software, and to permit persons to whom the Software\n is furnished to do so, subject to the following\n conditions:\n\n The above copyright notice and this permission notice\n shall be included in all copies or substantial portions\n of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF\n ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\n TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\n PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\n SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR\n IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n DEALINGS IN THE SOFTWARE.\n\n\n aws-lc-rs 1.15.4\n\n Repository: https://github.com/aws/aws-lc-rs\n License: Apache-2.0 AND (Apache-2.0 OR ISC)\n\n Included license texts:\n\n Apache-2.0\n\n Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n\n ISC\n\n Copyright Amazon.com, Inc. or its affiliates.\n\n Permission to use, copy, modify, and/or distribute this software for any\n purpose with or without fee is hereby granted, provided that the above\n copyright notice and this permission notice appear in all copies.\n\n THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n Each of these libraries have their own dependencies with their own licenses.\n Visit the repositories for each library for info on their dependencies.\n\n Binary distributions should have a generated nativews-THIRDPARTY.yml that has\n the complete list of libraries with attributions and/or licenses.\n If not, you can generate it using a tool like cargo-bundle-licenses inside the\n c-wspp-rs source project. You can get the source project from\n https://github.com/JKLeckr/native-websocket-sharp.\n\n\n CupheadArchipelago partially uses code from BepInEx for writing its log files\n\n MIT License\n\n Copyright (c) 2018 Bepis\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in all\n copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n SOFTWARE."; } internal static bool IsMacOS() { return Environment.OSVersion.Platform switch { PlatformID.MacOSX => true, PlatformID.Unix => Directory.Exists("/System/Library/CoreServices"), _ => false, }; } } [BepInPlugin("com.JKLeckr.CupheadArchipelago", "CupheadArchipelago", "0.2.2.7")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInProcess("Cuphead.exe")] public class Plugin : BaseUnityPlugin { internal const string DEP_SAVECONFIG_MOD_GUID = "com.JKLeckr.CupheadSaveConfig"; protected const string MOD_NAME = "CupheadArchipelago"; protected const string MOD_GUID = "com.JKLeckr.CupheadArchipelago"; protected const string MOD_BASE_VERSION = "0.2.2.7"; protected const ushort MOD_VERSION_REL = 3; protected const string MOD_VERSION_POSTFIX = ""; protected const string PLUGIN_DIST = ""; protected static readonly string MOD_VERSION = GetModVersion("0.2.2.7", 0, ""); protected static readonly string MOD_FRIENDLY_VERSION = GetFVer("0.2.2.7", 3, ""); private const long CONFIG_VERSION = 1L; private static readonly string verPath = Path.Combine(Path.Combine(Paths.PluginPath, "CupheadArchipelago"), "configver"); private long configVer; private ConfigEntry configEnabled; private MConf config; public static string Name => "CupheadArchipelago"; public static string Version => MOD_VERSION; public static string SimpleFullVersion => MOD_FRIENDLY_VERSION + " (0.2.2.7)"; public static string FullVersion => MOD_FRIENDLY_VERSION + " (" + MOD_VERSION + ")"; public static int State { get; private set; } = 0; public static string StateMessage { get; private set; } = ""; internal static Plugin Current { get; private set; } = null; private void Awake() { if ((Object)(object)Current != (Object)null) { throw new Exception("Plugin is already loaded!"); } Current = this; SetupConfigVersion(); configEnabled = ((BaseUnityPlugin)this).Config.Bind("Main", "Enabled", true, "Mod Master Switch"); if (configEnabled.Value) { config = new MConf(((BaseUnityPlugin)this).Config); SetupLogging(); Logging.Log("----------------------------------------"); Logging.Log("CupheadArchipelago " + FullVersion); if ("".Length > 0) { Logging.Log(" Build"); } Logging.Log("Created by JKLeckr"); Logging.Log("----------------------------------------"); Logging.Log("Game Build Version " + Application.version); if (configVer != 1) { Logging.LogWarning($"Config version changed ({configVer} -> {1L})! You may want to check the config."); configVer = 1L; } if (config.LogLicense > LicenseLogModes.Off) { ModInfo.ModLicense modLicense = new ModInfo.ModLicense(); string text = "License:\n--- LICENSE ---\n" + modLicense.PLUGIN_NOTICE + "\n"; if (config.LogLicense == LicenseLogModes.All) { ModInfo.ModLicenseThirdParty modLicenseThirdParty = new ModInfo.ModLicenseThirdParty(); text = text + "\n -- Third Party --\n" + modLicenseThirdParty.PLUGIN_LIB_FULL_NOTICE + "\n\n -- End Third Party --"; } else { text = text + "\n" + modLicense.PLUGIN_LIB_NOTICE; } text += "\n\n--- END LICENSE"; Logging.Log(text); } if (!IsPluginLoaded("com.JKLeckr.CupheadSaveConfig")) { try { Main.HookSaveKeyUpdater(config.SaveKeyName); Logging.Log("Using Save Key: " + config.SaveKeyName); } catch (Exception e) { Fail(e, -2); } } else { Logging.Log("[CupheadArchipelago] Plugin com.JKLeckr.CupheadSaveConfig is loaded, skipping SaveConfig", LoggingFlags.PluginInfo); } try { SaveData.Init(config.SaveKeyName); Main.HookMain(); ResourceLoader.LoadResources(); } catch (Exception e2) { Fail(e2, -1); } State = 1; StateMessage = ""; Logging.Log("Plugin com.JKLeckr.CupheadArchipelago is loaded!", LoggingFlags.PluginInfo); } else { Logging.Log("Plugin com.JKLeckr.CupheadArchipelago is loaded, but disabled!", LoggingFlags.PluginInfo); } } internal MConf GetConfig() { return config; } private bool IsPluginLoaded(string plugin) { return FindPlugin(plugin) >= 0; } private int FindPlugin(string plugin) { int num = 0; foreach (KeyValuePair pluginInfo in Chainloader.PluginInfos) { BepInPlugin metadata = pluginInfo.Value.Metadata; if (metadata.GUID.Equals(plugin)) { return num; } num++; } return -1; } private static string GetModVersion(string vbase, ushort vrel, string vpostfix) { return vbase + ((vrel > 0) ? $"r{vrel}" : "") + ((vpostfix.Length > 0) ? ("-" + vpostfix) : ""); } private static string GetFVer(string ver, ushort rel, string postfix) { string text = ver + ((postfix.Length > 0) ? "-" : "") + postfix; RawFVer rawFVer = FVerParse.GetRawFVer(text, rel); FVersion fVersion = new FVersion(rawFVer.baseline, rawFVer.revision, rawFVer.release, rawFVer.prefix, rawFVer.postfix); return fVersion; } private void SetupConfigVersion() { if (File.Exists(verPath)) { try { string text = File.ReadAllText(verPath); configVer = (long)JsonConvert.DeserializeObject(text); ((BaseUnityPlugin)this).Logger.Log((LogLevel)16, (object)$"Config version {configVer}"); return; } catch (Exception) { ((BaseUnityPlugin)this).Logger.Log((LogLevel)16, (object)"Config version not found."); } } configVer = 1L; SaveConfigVersion(); ((BaseUnityPlugin)this).Logger.Log((LogLevel)16, (object)$"Config version {configVer}"); } private void SaveConfigVersion() { try { File.WriteAllText(verPath, JsonConvert.SerializeObject((object)configVer)); } catch (Exception) { ((BaseUnityPlugin)this).Logger.Log((LogLevel)16, (object)"Config version could not be written."); } } private void SetupLogging() { Logging.Init(((BaseUnityPlugin)this).Logger, config.LoggingFlags); if (config.ModLogs) { Logging.Log("Setting up mod logging..."); try { LogFiles.Setup("CupheadAPLog", "CupheadArchipelago", config.ModFileMax); } catch (Exception ex) { Logging.LogError("Mod logging set up failure: " + ex.Message); return; } ModLogListener item = new ModLogListener(LogFiles.LogFile, LogFiles.LogDirPath, ((BaseUnityPlugin)this).Logger.SourceName, (LogLevel)63); Logger.Listeners.Add((ILogListener)(object)item); Logging.Log("Mod logging started"); Logging.Log("This mod log is " + LogFiles.LogFile + " in " + LogFiles.LogDirPath); } } private void Fail(Exception e, int failCode) { Logging.LogError("An exception occured while loading."); Logging.LogFatal(string.Format("Plugin {0} failed to load! (Code: {1})", "com.JKLeckr.CupheadArchipelago", failCode)); string message = e.GetBaseException().Message; State = failCode; StateMessage = message; Logging.LogFatal("Exception: " + message); Logging.LogFatal("Throwing Exception..."); throw new Exception("Plugin com.JKLeckr.CupheadArchipelago: Exceptions occurred!", e); } } public static class ModPluginInfo { public const string PLUGIN_GUID = "com.JKLeckr.CupheadArchipelago"; public const string PLUGIN_NAME = "CupheadArchipelago"; public const string PLUGIN_VERSION = "0.2.2.7"; public const string PLUGIN_VERSION_SUFFIX = ""; public const ushort PLUGIN_VERSION_REL = 3; public const string PLUGIN_DIST = ""; } } namespace CupheadArchipelago.Util { public static class Aux { public static string CollectionToString(IEnumerable collection) { bool flag = true; StringBuilder stringBuilder = new StringBuilder("["); foreach (object item in collection) { string text = ((!flag) ? ", " : ""); if (flag) { flag = false; } stringBuilder.Append(text + item.ToString()); } stringBuilder.Append("]"); return stringBuilder.ToString(); } public static int ArrayNullCount(object[] arr) { int num = 0; foreach (object obj in arr) { if (obj == null) { num++; } } return num; } public static T[] ArrayRange(T[] arr, int start, int end) { if (start >= end || start < 0 || end > arr.Length) { throw new IndexOutOfRangeException(); } T[] array = new T[end - start]; for (int i = 0; i < array.Length; i++) { array[i] = arr[start + i]; } return array; } public static T[] ArrayRange(T[] arr, int end) { return ArrayRange(arr, 0, end); } public static bool IsAny(T item, T[] values) { foreach (T val in values) { if (item.Equals(val)) { return true; } } return false; } public static void Shuffle(this IList list, Random rand = null) { if (rand == null) { rand = new Random(); } int num = list.Count; while (num > 1) { num--; int index = rand.Next(num + 1); T value = list[index]; list[index] = list[num]; list[num] = value; } } } internal static class Converter { private static class TypeConverter { internal static readonly Func ConvertTo; static TypeConverter() { Type T_Type = typeof(T); if ((object)T_Type == typeof(string)) { ConvertTo = (object value) => (T)(object)value.ToString(); } else if ((object)T_Type == typeof(bool)) { ConvertTo = (object value) => (T)(object)Convert.ToBoolean((long)value); } else if ((object)T_Type == typeof(sbyte)) { ConvertTo = (object value) => (T)(object)Convert.ToSByte(value); } else if ((object)T_Type == typeof(int)) { ConvertTo = (object value) => (T)(object)Convert.ToInt32(value); } else if (T_Type.IsEnum) { ConvertTo = (object value) => (T)Enum.Parse(T_Type, value.ToString()); } else { ConvertTo = (object value) => (T)value; } } } internal static T ConvertTo(this object value) { return TypeConverter.ConvertTo(value); } } public static class Ext { public static Levels[] LMapped(this Levels[] levels) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected I4, but got Unknown if (!LevelMap.IsInitted()) { Logging.LogWarning("LevelMap is not initted! Returning unmapped levels."); return levels; } Levels[] array = (Levels[])(object)new Levels[levels.Length]; for (int i = 0; i < array.Length; i++) { array[i] = (Levels)(int)LevelMap.GetMappedLevel(levels[i]); } return array; } public static bool CheckAnyLevelComplete(this Levels[] levels) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) PlayerData data = PlayerData.Data; foreach (Levels val in levels) { if (data.CheckLevelCompleted(val)) { return true; } } return false; } public static bool CheckLevelsComplete(this Levels[] levels) { if (levels.Length < 1) { return false; } return PlayerData.Data.CheckLevelsCompleted(levels); } } public static class Reflection { public static Type GetEnumeratorType(MethodBase enumerator) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown if ((object)enumerator == null) { throw new ArgumentNullException("GetEnumeratorType: Argument cannot be null!"); } Type type = null; MethodDefinition definition = new DynamicMethodDefinition(enumerator).Definition; ILContext val = new ILContext(definition); if (((MemberReference)((MethodReference)val.Method).ReturnType).Name.StartsWith("UniTask")) { VariableDefinition? obj = ((IEnumerable)val.Body.Variables).FirstOrDefault(); TypeReference val2 = ((obj != null) ? ((VariableReference)obj).VariableType : null); if (val2 != null && !((MemberReference)val2).Name.Contains(enumerator.Name)) { Logging.LogWarning("GetEnumeratorType: First Var name invalid: " + ((MemberReference)val2).Name); return null; } type = ReflectionHelper.ResolveReflection(val2); } else { MethodReference ctor = null; ILCursor val3 = new ILCursor(val); val3.GotoNext(new Func[1] { (Instruction i) => ILPatternMatchingExt.MatchNewobj(i, ref ctor) }); if (ctor == null || ((MemberReference)ctor).Name != ".ctor") { Logging.LogWarning("GetEnumeratorType: Invalid enumerator ctor: " + GeneralExtensions.FullDescription(enumerator)); } type = ReflectionHelper.ResolveReflection(((MemberReference)ctor).DeclaringType); } return type; } public static bool IsObsolete(this MemberInfo mi, bool inherit = false) { return mi.GetCustomAttributes(typeof(ObsoleteAttribute), inherit) == null; } } } namespace CupheadArchipelago.Unity { internal class APCore { public enum FontType { Bold, ExtraBold, Mono } public static readonly Color TEXT_COLOR = new Color(0.212f, 0.212f, 0.212f, 1f); public static readonly Color TEXT_SELECT_COLOR = new Color(0.676f, 0.212f, 0.212f, 1f); public static readonly Color TEXT_INACTIVE_COLOR = new Color(0.212f, 0.212f, 0.212f, 0.5f); public static Text CreateSettingsTextComponent(GameObject obj, FontType type = FontType.Bold, TextAnchor alignment = (TextAnchor)0, bool wrap = false) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) Text val = obj.AddComponent(); ((Graphic)val).color = TEXT_COLOR; Text val2 = val; if (1 == 0) { } Font font = (Font)(type switch { FontType.ExtraBold => FontLoader.GetFont((FontType)6), FontType.Mono => FontLoader.GetFont((FontType)19), _ => FontLoader.GetFont((FontType)5), }); if (1 == 0) { } val2.font = font; val.fontSize = 32; val.alignment = alignment; val.horizontalOverflow = (HorizontalWrapMode)(!wrap); return val; } } internal class APMain : MonoBehaviour { private static GameObject current; internal static void Create() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown if ((Object)(object)current == (Object)null) { current = new GameObject("APMain", new Type[1] { typeof(APMain) }); } } private void Awake() { Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); } private void OnDestroy() { Logging.Log("Shutting Down"); APClient.CloseArchipelagoSession(reset: false); } } public class APManager : MonoBehaviour { public enum MngrType { Normal, Level, SpecialLevel } [SerializeField] private bool debug = false; [SerializeField] private float levelApplyInterval = 1f; [SerializeField] private float mapApplyInterval = 0.025f; private bool init = false; private bool active = false; private MngrType type = MngrType.Normal; private float timer = 0f; [SerializeField] private bool deathLink = false; [SerializeField] private bool death = false; [SerializeField] private string deathMessage = ""; private bool deathExecuted = false; [SerializeField] private float fastFire = 0f; [SerializeField] private float fingerJam = 0f; [SerializeField] private float slowFire = 0f; public static APManager Current { get; private set; } public void Init(MngrType type) { Init(type, type == MngrType.Level); } public void Init(MngrType type, bool deathLink) { if (init) { return; } if ((Object)(object)Current != (Object)(object)this) { if ((Object)(object)Current != (Object)null) { Object.Destroy((Object)(object)Current); } Current = this; } Logging.Log($"[APManager] Initialized as Current {type}"); this.type = type; this.deathLink = deathLink; init = true; } public bool IsActive() { return active; } public void SetActive(bool active) { this.active = active; } public bool IsDeathTriggered() { return death; } public void TriggerDeath(string message = "Self") { if (type == MngrType.Level) { if (IsDeathTriggered()) { Logging.LogWarning("[APManager] Death already triggered!"); return; } death = true; deathMessage = message ?? "Unknown"; } } public bool IsFastFired() { return fastFire > 0f; } public void FastFire(float addTime = 5f) { if (fastFire < 0f) { fastFire = 0f; } fastFire += addTime; } public bool IsFingerJammed() { return fingerJam > 0f; } public void FingerJam(float addTime = 5f) { if (fingerJam < 0f) { fingerJam = 0f; } fingerJam += addTime; } public bool IsSlowFired() { return slowFire > 0f; } public void SlowFire(float addTime = 8f) { if (slowFire < 0f) { slowFire = 0f; } slowFire += addTime; } private void Update() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Invalid comparison between Unknown and I4 if (!init) { return; } if ((Object)(object)Current != (Object)(object)this) { init = false; Object.Destroy((Object)(object)this); } else { if (!active || (int)PauseManager.state == 1) { return; } if (debug) { Logging.Log($"ReceiveQueue {APClient.ItemReceiveQueueCount()}"); } if (type == MngrType.Level && deathLink && death && !deathExecuted) { Logging.Log("[APManager] Killing Players."); PlayerStatsInterface.KillPlayer((PlayerId)2147483646); Logging.Log("[APManager] " + deathMessage); deathExecuted = true; active = false; return; } if (fastFire > 0f) { fastFire -= Time.deltaTime; if (fastFire < 0f) { fastFire = 0f; } } if (fingerJam > 0f) { fingerJam -= Time.deltaTime; if (fingerJam < 0f) { fingerJam = 0f; } } if (slowFire > 0f) { slowFire -= Time.deltaTime; if (slowFire < 0f) { slowFire = 0f; } } APClient.ItemUpdate(); MngrType mngrType = type; if (1 == 0) { } float num = (((uint)(mngrType - 1) > 1u) ? mapApplyInterval : levelApplyInterval); if (1 == 0) { } float num2 = num; if (type == MngrType.Level || type == MngrType.SpecialLevel) { if (debug) { Logging.Log($"ItemSpecialLevelQueue {APClient.ItemApplySpecialLevelQueueCount()}"); } if (!APClient.ItemApplySpecialLevelQueueIsEmpty()) { if (debug) { Logging.Log("ItemSpecialLevelQueue has item"); } long id = APClient.PeekItemApplySpecialLevelQueue().id; if (APClient.GetAppliedItemCount(id) >= APClient.GetReceivedItemCount(id)) { APClient.PopItemApplySpecialLevelQueue(applyItem: false); } else if (timer >= num2) { if (debug) { Logging.Log("ItemSpecialLevelQueue is applying"); } APClient.PopItemApplySpecialLevelQueue(); AudioManager.Play("level_coin_pickup"); timer = 0f; } } } if (type == MngrType.Level) { if (debug) { Logging.Log($"ItemLevelQueue {APClient.ItemApplyLevelQueueCount()}"); } if (!APClient.ItemApplyLevelQueueIsEmpty()) { if (debug) { Logging.Log("ItemLevelQueue has item"); } long id2 = APClient.PeekItemApplyLevelQueue().id; if (APClient.GetAppliedItemCount(id2) >= APClient.GetReceivedItemCount(id2)) { APClient.PopItemApplyLevelQueue(applyItem: false); } else if (timer >= num2) { if (debug) { Logging.Log("ItemLevelQueue is applying"); } APClient.PopItemApplyLevelQueue(); AudioManager.Play("level_coin_pickup"); timer = 0f; } } } if (debug) { Logging.Log($"ItemQueue {APClient.ItemApplyQueueCount()}"); } if (!APClient.ItemApplyQueueIsEmpty()) { if (debug) { Logging.Log("ItemQueue has item"); } long id3 = APClient.PeekItemApplyQueue().id; if (APClient.GetAppliedItemCount(id3) >= APClient.GetReceivedItemCount(id3)) { APClient.PopItemApplyQueue(applyItem: false); } else if (timer >= num2) { if (debug) { Logging.Log("ItemQueue is applying"); } APClient.PopItemApplyQueue(); AudioManager.Play("level_coin_pickup"); timer = 0f; } } if (timer < num2) { timer += Time.deltaTime; } } } private void OnDestroy() { Logging.Log("[APManager] Destroyed"); init = false; if (Current == this) { Current = null; } } } public class APSetupMenu : MonoBehaviour { private AnyPlayerInput input; private bool initted = false; private bool active = false; private int menuSelection = 0; private Text[] menuText; private Text headerText; private bool menuLocked; private bool promptCooldown = false; private Transform fader; private Transform prompts; private APTypingPrompt typingPrompt; private int slotSelection = 0; private APData apData; [SerializeField] private float menuDelay = 0.05f; private float menuTime = 0f; private static string[] setupFieldLabels = new string[5] { "ENABLED", "ADDRESS", "PORT", "PLAYER", "PASSWORD" }; private void Awake() { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown input = new AnyPlayerInput(false); menuTime = 0f; } private void Update() { if (!initted || !active) { return; } if (typingPrompt.IsActive()) { if (!typingPrompt.IsFinished()) { return; } switch (menuSelection) { case 1: { string text2 = typingPrompt.GetText(); if (text2.Length > 0) { apData.address = text2; break; } Logging.LogWarning("[APSetupMenu] Invalid text for address: cannot be empty."); apData.address = "archipelago.gg"; break; } case 2: try { ushort port = ushort.Parse(typingPrompt.GetText()); apData.port = port; } catch (Exception ex) { Logging.LogWarning("[APSetupMenu] Invalid text for port: " + ex.Message); apData.port = 38281; } break; case 3: { string text = typingPrompt.GetText(); if (text.Length > 0) { apData.player = typingPrompt.GetText(); break; } Logging.LogWarning("[APSetupMenu] Invalid text for player: cannot be empty."); apData.player = "Player"; break; } case 4: apData.password = typingPrompt.GetText(); break; } CloseTypingPrompt(); RefreshSettingsText(); return; } if (promptCooldown) { ((Component)prompts).gameObject.SetActive(true); promptCooldown = false; return; } if (menuSelection == 0 && !menuLocked) { if (input.GetButtonDown((CupheadButton)18) || input.GetButtonDown((CupheadButton)20)) { AudioManager.Play("level_menu_select"); apData.enabled = !apData.enabled; RefreshSettingsText(); } } else if (menuSelection == 1 && input.GetButtonDown((CupheadButton)13)) { AudioManager.Play("level_select"); OpenTypingPrompt(apData.address, APTypingPrompt.TextTypes.Text); } else if (menuSelection == 2 && input.GetButtonDown((CupheadButton)13)) { AudioManager.Play("level_select"); OpenTypingPrompt(apData.port.ToString(), APTypingPrompt.TextTypes.SixDigit); } else if (menuSelection == 3 && input.GetButtonDown((CupheadButton)13)) { AudioManager.Play("level_select"); OpenTypingPrompt(apData.player, APTypingPrompt.TextTypes.Text16); } else if (menuSelection == 4 && input.GetButtonDown((CupheadButton)13)) { AudioManager.Play("level_select"); OpenTypingPrompt(apData.password, APTypingPrompt.TextTypes.Text16); } if (menuTime >= menuDelay) { if (input.GetButtonDown((CupheadButton)16)) { menuTime = 0f; AudioManager.Play("level_menu_move"); menuSelection--; if (menuLocked && menuSelection == 0) { menuSelection = -1; } if (menuSelection < 0) { menuSelection = menuText.Length - 1; } SetSettingsTextColors(); } else if (input.GetButtonDown((CupheadButton)19)) { menuTime = 0f; AudioManager.Play("level_menu_move"); menuSelection++; if (menuSelection >= menuText.Length) { menuSelection = (menuLocked ? 1 : 0); } SetSettingsTextColors(); } } else { menuTime += Time.deltaTime; } } private void OpenTypingPrompt(string initial_str, APTypingPrompt.TextTypes type) { ((Component)prompts).gameObject.SetActive(false); promptCooldown = true; typingPrompt.OpenPrompt(initial_str, type); } private void CloseTypingPrompt() { ((Component)prompts).gameObject.SetActive(true); typingPrompt.ClosePrompt(); } private void SetSettingsTextColors() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < menuText.Length; i++) { if (i == 0 && menuLocked) { ((Graphic)menuText[i]).color = APCore.TEXT_INACTIVE_COLOR; } else { ((Graphic)menuText[i]).color = ((menuSelection == i) ? APCore.TEXT_SELECT_COLOR : APCore.TEXT_COLOR); } } } public bool IsBackSelected() { return menuSelection == 5; } public bool IsTyping() { return typingPrompt?.IsTyping() ?? false; } public void SetState(bool state) { ((Component)this).gameObject.SetActive(state); active = state; CloseTypingPrompt(); if (state) { RefreshMenu(); } menuSelection = (menuLocked ? 1 : 0); SetSettingsTextColors(); } public void SetSlotSelection(int slotSelection) { this.slotSelection = slotSelection; apData = APData.SData[slotSelection]; RefreshMenuLock(); } private void RefreshMenuLock() { menuLocked = !apData.IsEmpty(SaveDataType.Vanilla); } public bool IsInitted() { return initted; } public static void Init(APSetupMenu instance, Transform orig_options, Transform prompts) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Expected O, but got Unknown //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Expected O, but got Unknown //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Expected O, but got Unknown //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Expected O, but got Unknown //IL_02a2: Unknown result type (might be due to invalid IL or missing references) GameObject gameObject = ((Component)instance).gameObject; Transform child = orig_options.GetChild(0); Transform child2 = orig_options.GetChild(1); Transform child3 = child2.GetChild(2); Transform child4 = child2.GetChild(6); instance.prompts = prompts; GameObject val = Object.Instantiate(((Component)child).gameObject, gameObject.transform); ((Object)val).name = ((Object)child).name; RectTransform component = val.GetComponent(); component.sizeDelta = new Vector2(2570f, 1450f); instance.fader = val.transform; GameObject val2 = new GameObject("Card"); RectTransform val3 = val2.AddComponent(); val3.sizeDelta = new Vector2(514f, 299f); val2.transform.SetParent(gameObject.transform); GameObject val4 = Object.Instantiate(((Component)child3).gameObject, val2.transform); ((Object)val4).name = ((Object)child3).name; val4.SetActive(true); GameObject val5 = new GameObject("Header"); RectTransform val6 = val5.AddComponent(); val6.sizeDelta = new Vector2(600f, 64f); val6.anchoredPosition = new Vector2(0f, 190f); val5.transform.SetParent(val2.transform); val5.AddComponent(); Text val7 = APCore.CreateSettingsTextComponent(val5, APCore.FontType.Mono, (TextAnchor)1, wrap: true); val7.fontSize = 24; val7.text = "Seed: 000000000000000"; instance.headerText = val7; GameObject val8 = new GameObject("APMenu"); RectTransform val9 = val8.AddComponent(); val8.AddComponent(); val9.sizeDelta = new Vector2(514f, 299f); val8.transform.SetParent(val2.transform); GameObject val10 = new GameObject("SettingsLabels"); RectTransform val11 = val10.AddComponent(); val11.sizeDelta = new Vector2(514f, 259f); val10.AddComponent(); val10.transform.SetParent(val8.transform); instance.SetupSettingsLabels(val10.transform); instance.menuText = (Text[])(object)new Text[6]; instance.menuLocked = false; GameObject val12 = new GameObject("SettingsTextContainer"); RectTransform val13 = val12.AddComponent(); val13.sizeDelta = new Vector2(514f, 259f); VerticalLayoutGroup val14 = val12.AddComponent(); RectOffset padding = ((LayoutGroup)val14).padding; padding.top += 2; val12.transform.SetParent(val8.transform); GameObject val15 = new GameObject("SettingsText"); RectTransform val16 = val15.AddComponent(); val16.sizeDelta = new Vector2(514f, 259f); VerticalLayoutGroup val17 = val15.AddComponent(); ((HorizontalOrVerticalLayoutGroup)val17).spacing = ((HorizontalOrVerticalLayoutGroup)val17).spacing + 8f; val15.transform.SetParent(val12.transform); instance.SetupSettingsText(val15.transform); GameObject val18 = Object.Instantiate(((Component)child4).gameObject, val2.transform); ((Object)val18).name = ((Object)child4).name; val18.SetActive(true); instance.typingPrompt = APTypingPrompt.CreateTypingPrompt(val2.transform, orig_options); instance.RefreshMenu(); instance.initted = true; Logging.Log("APSetupMenu Initialized"); } private void RefreshMenu() { RefreshMenuLock(); SetSettingsTextColors(); RefreshSettingsText(); } private void RefreshSettingsText() { if ((Object)(object)headerText != (Object)null) { headerText.text = ((!menuLocked) ? "" : (apData.enabled ? ("Seed: " + GetAPSeed()) : "Vanilla Save\nDelete slot to enable Archipelago.")); } if ((Object)(object)menuText[0] != (Object)null) { menuText[0].text = (apData.enabled ? "YES" : "NO") + " " + (menuLocked ? "(Locked)" : ""); } if ((Object)(object)menuText[1] != (Object)null) { menuText[1].text = "[" + GetMenuString(apData.address) + "]"; } if ((Object)(object)menuText[2] != (Object)null) { menuText[2].text = $"[{apData.port}]"; } if ((Object)(object)menuText[3] != (Object)null) { menuText[3].text = "[" + GetMenuString(apData.player) + "]"; } if ((Object)(object)menuText[4] != (Object)null) { string text = new string('*', Mathf.Min(apData.password?.Length ?? 0, 16)); menuText[4].text = "[" + text + "]"; } } private string GetAPSeed() { APData aPData = APData.SData[slotSelection]; return (!aPData.IsEmpty(SaveDataType.Vanilla)) ? aPData.seed : ""; } private static string GetMenuString(string str) { if (str.Length > 14) { return str.Substring(0, 11) + "..."; } return str; } private void SetupSettingsText(Transform parent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Expected O, but got Unknown //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Expected O, but got Unknown //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Expected O, but got Unknown //IL_0220: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Enabled"); RectTransform val2 = val.AddComponent(); val2.sizeDelta = new Vector2(600f, 36f); val.transform.SetParent(((Component)parent).transform); val.AddComponent(); Text val3 = CreateSettingsTextComponent(val, bold: false, (TextAnchor)0); val3.text = "ON"; menuText[0] = val3; GameObject val4 = new GameObject("Address"); RectTransform val5 = val4.AddComponent(); val5.sizeDelta = new Vector2(600f, 40f); val4.transform.SetParent(((Component)parent).transform); val4.AddComponent(); Text val6 = CreateSettingsTextComponent(val4, bold: false, (TextAnchor)0); val6.text = "[ARCHIPELAGOGGG]"; menuText[1] = val6; GameObject val7 = new GameObject("Port"); RectTransform val8 = val7.AddComponent(); val8.sizeDelta = new Vector2(600f, 40f); val7.transform.SetParent(((Component)parent).transform); val7.AddComponent(); Text val9 = CreateSettingsTextComponent(val7, bold: false, (TextAnchor)0); val9.text = "[38281]"; menuText[2] = val9; GameObject val10 = new GameObject("Player"); RectTransform val11 = val10.AddComponent(); val11.sizeDelta = new Vector2(600f, 40f); val10.transform.SetParent(((Component)parent).transform); val10.AddComponent(); Text val12 = CreateSettingsTextComponent(val10, bold: false, (TextAnchor)0); val12.text = "[Player]"; menuText[3] = val12; GameObject val13 = new GameObject("Password"); RectTransform val14 = val13.AddComponent(); val14.sizeDelta = new Vector2(600f, 40f); val13.transform.SetParent(((Component)parent).transform); val13.AddComponent(); Text val15 = CreateSettingsTextComponent(val13, bold: false, (TextAnchor)0); val15.text = "[*****]"; menuText[4] = val15; GameObject val16 = new GameObject("Back"); RectTransform val17 = val16.AddComponent(); val17.sizeDelta = new Vector2(514f, 259f); val16.transform.SetParent(((Component)parent).transform); val16.AddComponent(); Text val18 = CreateSettingsTextComponent(val16, bold: true, (TextAnchor)7); val18.text = "__BACK____________________________"; menuText[5] = val18; } private void SetupSettingsLabels(Transform parent) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) string[] array = setupFieldLabels; foreach (string text in array) { GameObject val = new GameObject(text); RectTransform val2 = val.AddComponent(); val2.sizeDelta = new Vector2(600f, 40f); val.transform.SetParent(((Component)parent).transform); val.AddComponent(); Text val3 = CreateSettingsTextComponent(val, bold: true, (TextAnchor)2); val3.text = text + ": "; } GameObject val4 = new GameObject("Blank"); RectTransform val5 = val4.AddComponent(); val5.sizeDelta = new Vector2(600f, 40f); val4.transform.SetParent(((Component)parent).transform); val4.AddComponent(); CreateSettingsTextComponent(val4, bold: true, (TextAnchor)2).text = " "; } private static Text CreateSettingsTextComponent(GameObject obj, bool bold = false, TextAnchor alignment = (TextAnchor)0) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) APCore.FontType type = (bold ? APCore.FontType.ExtraBold : APCore.FontType.Mono); return APCore.CreateSettingsTextComponent(obj, type, alignment); } } internal class APStatusMain : MonoBehaviour { private bool initted = false; private void Awake() { if (!initted) { if (MConf.IsAPStatsFunctionEnabled(APStatsFunctions.ConnectionIndicator)) { CreateConnectionIndicator(); } initted = true; } } private void CreateConnectionIndicator() { } } public class APTypingPrompt : MonoBehaviour { public enum TextTypes { Text, Text16, SixDigit } private bool initted = false; private bool active = false; private bool typing = false; private TextTypes type; private string text = ""; private InputField inputField; private AnyPlayerInput input; private static readonly char[] badChars = new char[3] { '\t', '\n', '\r' }; private const int TEXT_MAX_LENGTH = 340; private void Awake() { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown input = new AnyPlayerInput(false); } private void Update() { if (initted && active) { if (input.GetButtonDown((CupheadButton)14)) { AudioManager.Play("level_menu_select"); ClosePrompt(); } else if (Input.GetKeyDown((KeyCode)13)) { AudioManager.Play("level_menu_select"); StopTyping(); } } } public void OpenPrompt(string initial_str, TextTypes type = TextTypes.Text) { if (!initted) { throw new Exception("Not initialized!"); } SetInputType(type); text = ClampText(initial_str); inputField.text = text; SetState(state: true); StartTyping(); } public void StartTyping() { if (active && !typing) { typing = true; inputField.ActivateInputField(); } } public void StopTyping(bool saveText = true) { if (active && typing) { typing = false; inputField.DeactivateInputField(); if (saveText) { text = inputField.text; } } } public void ClosePrompt() { if (typing) { StopTyping(saveText: false); } SetState(state: false); } private void SetInputType(TextTypes type) { this.type = type; InputField val = inputField; if (1 == 0) { } int characterLimit = type switch { TextTypes.Text16 => 16, TextTypes.SixDigit => 6, _ => 340, }; if (1 == 0) { } val.characterLimit = characterLimit; if (type == TextTypes.SixDigit) { inputField.contentType = (ContentType)2; } else { inputField.contentType = (ContentType)0; } } private void SetState(bool state) { ((Component)this).gameObject.SetActive(state); active = state; } private string ClampText(string text) { switch (type) { case TextTypes.Text16: return text.Substring(0, Mathf.Min(text.Length, 16)); case TextTypes.SixDigit: { string text2 = text.Substring(0, Mathf.Min(text.Length, 6)); if (int.TryParse(text2, out var _)) { return text2; } return "0"; } default: return text.Substring(0, Mathf.Min(text.Length, 340)); } } public bool IsInitted() { return initted; } public bool IsTyping() { return typing; } public bool IsActive() { return active; } public bool IsFinished() { return active && !typing; } public string GetText() { return text; } public char OnValidateInput(string text, int charIndex, char addedChar) { if (Array.BinarySearch(badChars, addedChar) >= 0) { return '\0'; } return addedChar; } public static APTypingPrompt CreateTypingPrompt(Transform parent, Transform orig_options, Transform orig_fader = null) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("TypingPrompt"); val.SetActive(false); RectTransform val2 = val.AddComponent(); val2.sizeDelta = new Vector2(514f, 299f); APTypingPrompt aPTypingPrompt = val.AddComponent(); ((Component)val2).transform.SetParent(parent); if ((Object)(object)orig_fader != (Object)null) { GameObject val3 = Object.Instantiate(((Component)orig_fader).gameObject, val.transform); ((Object)val3).name = ((Object)orig_fader).name; RectTransform component = val3.GetComponent(); component.sizeDelta = new Vector2(2570f, 1450f); } Init(aPTypingPrompt, orig_options); return aPTypingPrompt; } protected static void Init(APTypingPrompt instance, Transform orig_options) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Expected O, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Expected O, but got Unknown //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Expected O, but got Unknown //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) GameObject gameObject = ((Component)instance).gameObject; Transform child = orig_options.GetChild(1); Transform child2 = child.GetChild(2); Transform child3 = child.GetChild(6); GameObject val = Object.Instantiate(((Component)child2).gameObject, gameObject.transform); ((Object)val).name = ((Object)child2).name; val.SetActive(true); GameObject val2 = new GameObject("Prompt"); RectTransform val3 = val2.AddComponent(); val3.sizeDelta = new Vector2(514f, 299f); val2.transform.SetParent(gameObject.transform); InputField val4 = val2.AddComponent(); val4.lineType = (LineType)0; Color tEXT_SELECT_COLOR = APCore.TEXT_SELECT_COLOR; tEXT_SELECT_COLOR.a = 0.21f; val4.selectionColor = tEXT_SELECT_COLOR; val4.onValidateInput = (OnValidateInput)Delegate.Combine((Delegate?)(object)val4.onValidateInput, (Delegate?)new OnValidateInput(instance.OnValidateInput)); instance.inputField = val4; GameObject val5 = new GameObject("Header"); RectTransform val6 = val5.AddComponent(); val6.sizeDelta = new Vector2(600f, 64f); val6.anchoredPosition = new Vector2(0f, 190f); val5.transform.SetParent(val2.transform); val5.AddComponent(); Text val7 = APCore.CreateSettingsTextComponent(val5, APCore.FontType.Bold, (TextAnchor)1, wrap: true); val7.fontSize = 26; val7.text = "Press [Enter] to Accept,\nPress [Esc] to Cancel. Enter Text:"; GameObject val8 = new GameObject("Field"); RectTransform val9 = val8.AddComponent(); val9.sizeDelta = new Vector2(514f, 500f); val9.anchoredPosition = new Vector2(0f, -15f); val8.transform.SetParent(val2.transform); val8.AddComponent(); Text val10 = APCore.CreateSettingsTextComponent(val8, APCore.FontType.Mono, (TextAnchor)4, wrap: true); val10.fontSize = 24; val10.text = "AAAAAAAA"; val4.textComponent = val10; val4.text = val10.text; GameObject val11 = Object.Instantiate(((Component)child3).gameObject, gameObject.transform); ((Object)val11).name = ((Object)child3).name; val11.SetActive(true); instance.initted = true; Logging.Log("APTypingPrompt Initialized"); } } public class ControlBoard : MonoBehaviour { public bool invincible = false; public static ControlBoard Current { get; private set; } private void Awake() { if ((Object)(object)Current == (Object)null) { Current = this; } else { Logging.Log("Destroying old ControlBoard"); ControlBoard current = Current; Current = this; Object.Destroy((Object)(object)((Component)current).gameObject); } Object.DontDestroyOnLoad((Object)(object)((Component)Current).gameObject); Logging.Log("ControlBoard initialized"); } private void Update() { if (invincible != PlayerStatsManager.DebugInvincible) { PlayerStatsManager.DebugToggleInvincible(); Logging.Log("[ControlBoard] Invincibility: " + (PlayerStatsManager.DebugInvincible ? "on" : "off")); } } private void OnEnable() { } private void OnDisable() { } } internal class DiceGateLevelChalk : MonoBehaviour { private const string DICE_CHALK_TICS_ASSET_NAME = "cap_dicehouse_chalkboard_tics"; private bool _initted = false; [SerializeField] private bool shaderControls = false; [SerializeField] private bool canvasControls = false; private SpriteRenderer bgsr = null; private MaterialPropertyBlock bgmblock = null; private Vector2 bgopos = new Vector2(0.22384f, 0.0743f); private float bgosize = 0.031175f; private float bgotrim = 0.96f; private float cmult = 1f; private RectTransform trect = null; private RectTransform t2rect = null; private Text chalkTxt = null; private Text chalk2Txt = null; public void Init(int contracts, int requiredContracts) { if (!_initted) { CreateChalkOverlay(); chalkTxt.text = $"{contracts}"; chalk2Txt.text = $"{requiredContracts}"; _initted = true; } } private void FixedUpdate() { if (_initted) { if (shaderControls || canvasControls) { ControlUpdate(); } if (shaderControls) { ShaderUpdate(); } if (canvasControls) { CanvasUpdate(); } } } private void CreateChalkOverlay() { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Expected O, but got Unknown //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Expected O, but got Unknown //IL_0304: Unknown result type (might be due to invalid IL or missing references) Transform child = ((Component)this).transform.GetChild(0); Transform child2 = ((Component)this).transform.GetChild(3); Transform child3 = child2.GetChild(3); Transform child4 = child2.GetChild(7); SpriteRenderer component = ((Component)child3).GetComponent(); if (!AssetMngr.IsAssetLoaded("cap_dicehouse_chalkboard_tics")) { Logging.LogWarning("cap_dicehouse_chalkboard_tics is not loaded. Loading."); AssetMngr.LoadAsset("cap_dicehouse_chalkboard_tics"); } Texture2D loadedAsset = AssetMngr.GetLoadedAsset("cap_dicehouse_chalkboard_tics"); ((Renderer)component).material.shader = StaticAssets.OverlayShader; MaterialPropertyBlock val = new MaterialPropertyBlock(); ((Renderer)component).GetPropertyBlock(val); val.SetTexture("_OverlayTex", (Texture)(object)loadedAsset); val.SetVector("_OverlayPos", new Vector4(bgopos.x, bgopos.y, 0f, 0f)); val.SetVector("_OverlaySize", new Vector4(bgosize, bgosize, 0f, 0f)); val.SetFloat("_TrimAlpha", bgotrim); ((Renderer)component).SetPropertyBlock(val); GameObject val2 = Object.Instantiate(((Component)child4).gameObject, child2); ((Object)val2).name = "die_house_chalk_slash"; val2.SetActive(true); val2.transform.SetSiblingIndex(4); val2.transform.position = new Vector3(197.5f, 22f, 0f); TransformExtensions.SetScale(val2.transform, (float?)2.8f, (float?)1.5f, (float?)1f); TransformExtensions.SetEulerAngles(val2.transform, (float?)20f, (float?)20f, (float?)38f); GameObject val3 = new GameObject("die_house_chalk"); RectTransform val4 = val3.AddComponent(); ((Transform)val4).SetParent(child2); ((Transform)val4).SetSiblingIndex(4); Canvas val5 = val3.AddComponent(); val3.AddComponent(); val3.AddComponent(); val5.renderMode = (RenderMode)2; val5.worldCamera = ((Component)child).GetComponent(); val5.sortingOrder = 5; ((Transform)val4).position = Vector3.zero; TransformExtensions.SetScale((Transform)(object)val4, (float?)1f, (float?)1f, (float?)1f); GameObject val6 = new GameObject("ChalkText"); trect = val6.AddComponent(); ((Transform)trect).SetParent((Transform)(object)val4); TransformExtensions.SetPosition(((Component)trect).transform, (float?)96f, (float?)(-1f), (float?)0f); TransformExtensions.SetEulerAngles(((Component)trect).transform, (float?)20f, (float?)20f, (float?)0f); val6.AddComponent(); chalkTxt = val6.AddComponent(); ((Graphic)chalkTxt).color = new Color(1f, 1f, 1f, 0.72f); chalkTxt.font = FontLoader.GetFont((FontType)5); chalkTxt.fontSize = 32; chalkTxt.alignment = (TextAnchor)8; chalkTxt.text = "0"; GameObject val7 = Object.Instantiate(val6, (Transform)(object)val4); t2rect = val7.GetComponent(); TransformExtensions.SetPosition(((Component)t2rect).transform, (float?)204f, (float?)(-90f), (float?)0f); TransformExtensions.SetEulerAngles(((Component)t2rect).transform, (float?)20f, (float?)20f, (float?)0f); ((Object)val7).name = "ChalkText2"; chalk2Txt = val7.GetComponent(); chalk2Txt.alignment = (TextAnchor)0; chalk2Txt.text = "0"; } private void ControlUpdate() { bool flag = false; if (Input.GetKeyDown((KeyCode)110)) { flag = true; cmult -= 0.025f; if (cmult < 0f) { cmult = 0f; } } if (Input.GetKeyDown((KeyCode)109)) { flag = true; cmult += 0.025f; if (cmult > 2f) { cmult = 2f; } } if (Input.GetKeyDown((KeyCode)44)) { flag = true; cmult -= 0.0025f; if (cmult < 0f) { cmult = 0f; } } if (Input.GetKeyDown((KeyCode)46)) { flag = true; cmult += 0.0025f; if (cmult > 255f) { cmult = 2f; } } if (flag) { Logging.Log($"mult: {cmult}"); } } private void ShaderUpdate() { //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) bool flag = false; float num = cmult / 100f; if (Input.GetKey((KeyCode)116)) { flag = true; bgopos.y += num; } if (Input.GetKey((KeyCode)103)) { flag = true; bgopos.y -= num; } if (Input.GetKey((KeyCode)102)) { flag = true; bgopos.x -= num; } if (Input.GetKey((KeyCode)104)) { flag = true; bgopos.x += num; } if (Input.GetKey((KeyCode)105)) { flag = true; bgosize += num; } if (Input.GetKey((KeyCode)107)) { flag = true; bgosize -= num; } if (Input.GetKey((KeyCode)111)) { flag = true; bgotrim += num / 10f; } if (Input.GetKey((KeyCode)108)) { flag = true; bgotrim -= num / 10f; } if (Input.GetKey((KeyCode)118)) { flag = true; ((Renderer)bgsr).GetPropertyBlock(bgmblock); Texture2D loadedAsset = AssetMngr.GetLoadedAsset("cap_dicehouse_chalkboard_tics"); bgmblock.SetTexture("_OverlayTex", (Texture)(object)loadedAsset); ((Renderer)bgsr).SetPropertyBlock(bgmblock); } else if (Input.GetKey((KeyCode)98)) { flag = true; ((Renderer)bgsr).GetPropertyBlock(bgmblock); bgmblock.SetTexture("_OverlayTex", (Texture)(object)Texture2D.whiteTexture); ((Renderer)bgsr).SetPropertyBlock(bgmblock); } else if ((Object)(object)bgsr != (Object)null && bgmblock != null && flag) { ((Renderer)bgsr).GetPropertyBlock(bgmblock); bgmblock.SetVector("_OverlayPos", new Vector4(bgopos.x, bgopos.y, 0f, 0f)); bgmblock.SetVector("_OverlaySize", new Vector4(bgosize, bgosize, 0f, 0f)); bgmblock.SetFloat("_TrimAlpha", bgotrim); ((Renderer)bgsr).SetPropertyBlock(bgmblock); } if (flag) { Logging.Log($"({bgopos.x},{bgopos.y}) ({bgosize}) ({cmult}) ({bgotrim})"); } } private void CanvasUpdate() { //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) bool flag = false; float num = cmult; if (Input.GetKey((KeyCode)116)) { flag = true; TransformExtensions.AddPosition((Transform)(object)trect, 0f, num, 0f); } if (Input.GetKey((KeyCode)103)) { flag = true; TransformExtensions.AddPosition((Transform)(object)trect, 0f, 0f - num, 0f); } if (Input.GetKey((KeyCode)102)) { flag = true; TransformExtensions.AddPosition((Transform)(object)trect, 0f - num, 0f, 0f); } if (Input.GetKey((KeyCode)104)) { flag = true; TransformExtensions.AddPosition((Transform)(object)trect, num, 0f, 0f); } if (Input.GetKey((KeyCode)105)) { flag = true; TransformExtensions.AddPosition((Transform)(object)t2rect, 0f, num, 0f); } if (Input.GetKey((KeyCode)107)) { flag = true; TransformExtensions.AddPosition((Transform)(object)t2rect, 0f, 0f - num, 0f); } if (Input.GetKey((KeyCode)106)) { flag = true; TransformExtensions.AddPosition((Transform)(object)t2rect, 0f - num, 0f, 0f); } if (Input.GetKey((KeyCode)108)) { flag = true; TransformExtensions.AddPosition((Transform)(object)t2rect, num, 0f, 0f); } if (Input.GetKey((KeyCode)118)) { flag = true; } else if (Input.GetKey((KeyCode)98)) { flag = true; } if (flag) { Vector3 position = ((Transform)trect).position; Vector3 position2 = ((Transform)t2rect).position; Logging.Log($"({position.x},{position.y}) ({position2.x},{position2.y}) ({cmult})"); } } } public class Disabler : MonoBehaviour { private bool initted = false; private MonoBehaviour toDisable; public void Init(MonoBehaviour toDisable) { this.toDisable = toDisable; initted = true; } private void Start() { ((MonoBehaviour)this).StartCoroutine(Disable_cr()); } private IEnumerator Disable_cr() { while (!initted) { yield return null; } yield return null; MonoBehaviour obj = toDisable; if (obj != null) { ((Behaviour)obj).enabled = false; } Object.Destroy((Object)(object)this); } } internal class PlayerStatsInterface : MonoBehaviour { private static PlayerStatsInterface current1; private static PlayerStatsInterface current2; private bool initted = false; private PlayerId playerId = (PlayerId)int.MaxValue; private PlayerStatsManager stats; internal void Init(PlayerStatsManager instance) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 //IL_007b: Unknown result type (might be due to invalid IL or missing references) stats = instance; playerId = ((AbstractPlayerComponent)stats).basePlayer.id; if ((int)playerId == 1) { if ((Object)(object)current2 != (Object)null) { Logging.LogWarning("StatsManagerInterface Current2 Exists"); } current2 = this; } else { if ((Object)(object)current1 != (Object)null) { Logging.LogWarning("StatsManagerInterface Current1 Exists"); } current1 = this; } Logging.Log($"[StatsManagerInterface] Initialized for {playerId}"); initted = true; } private void OnDestroy() { Logging.Log("[StatsManagerInterface] Destroyed"); initted = false; if (current1 == this) { current1 = null; } if (current2 == this) { current2 = null; } } public bool IsInitted() { return initted; } internal static PlayerStatsInterface GetInstance(PlayerId playerId) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 return ((int)playerId == 1) ? current2 : current1; } internal void AddEx(float add) { SetSuper(stats.SuperMeter + add); } internal void FillSuper() { SetSuper(50f); } internal void SetSuper(float set) { SetSuper(set, checkCanGainSuper: true); } private void SetSuper(float set, bool checkCanGainSuper) { if (stats.CanGainSuperMeter || !checkCanGainSuper) { PlayerStatsManagerHook.SetSuper(stats, set); } } internal bool IsDead() { return ((AbstractPlayerComponent)stats).basePlayer.IsDead; } internal int GetHealth() { return stats.Health; } internal void AddHealth(int add) { SetHealth(stats.Health + add); } internal void SetHealth(int set) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Invalid comparison between Unknown and I4 //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown if (IsDead()) { return; } if (Level.IsInBossesHub) { PlayersStatsBossesHub val; if (Level.IsDicePalace || Level.IsDicePalaceMain) { Logging.LogDebug("[PlayerStatsInterface] Dice Palace"); if ((int)playerId == 1) { if (DicePalaceMainLevelGameInfo.PLAYER_TWO_STATS == null) { DicePalaceMainLevelGameInfo.PLAYER_TWO_STATS = new PlayersStatsBossesHub(); } val = DicePalaceMainLevelGameInfo.PLAYER_TWO_STATS; } else { if (DicePalaceMainLevelGameInfo.PLAYER_ONE_STATS == null) { DicePalaceMainLevelGameInfo.PLAYER_ONE_STATS = new PlayersStatsBossesHub(); } val = DicePalaceMainLevelGameInfo.PLAYER_ONE_STATS; } } else { val = Level.GetPlayerStats(playerId); } if (val != null) { int num = set.CompareTo(stats.HealerHP); if (num > 0) { PlayersStatsBossesHub obj = val; obj.BonusHP += set; } else if (num < 0) { int num2 = -set; if (val.BonusHP > 0) { if (val.BonusHP <= num2) { num2 -= val.BonusHP; val.BonusHP = 0; } else { PlayersStatsBossesHub obj2 = val; obj2.BonusHP -= num2; num2 = 0; } } if (val.healerHP > 0 && num2 > 0) { val.healerHP = Math.Max(0, val.healerHP - num2); } } } else { Logging.LogError($"[PlayerStatsInterface] Could not find BossesHub PlayerStats {playerId}!"); } } stats.SetHealth(set); } public void KillPlayer() { PlayerStatsManagerHook.IssueStatsCommand(stats, PlayerStatsManagerHook.StatsCommands.Death); } internal void ReverseControls() { PlayerStatsManagerHook.IssueStatsCommand(stats, PlayerStatsManagerHook.StatsCommands.ReverseControls); } public static void AddEx(PlayerId playerId, float add) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) Logging.Log($"Adding Ex for {playerId}"); PlayerStatsInterface instance = GetInstance(playerId); instance?.SetSuper(instance.stats.SuperMeter + add); } public static void FillSuper(PlayerId playerId) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) Logging.Log($"Filling Super for {playerId}"); SetSuper(playerId, 50f); } public static void SetSuper(PlayerId playerId, float set) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) Logging.Log($"Setting Super for {playerId}"); GetInstance(playerId)?.SetSuper(set); } public static int GetHealth(PlayerId playerId) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return GetInstance(playerId)?.GetHealth() ?? 0; } public static void AddHealth(PlayerId playerId, int add) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) Logging.Log($"Adding Health for {playerId}"); GetInstance(playerId)?.AddHealth(add); } public static void SetHealth(PlayerId playerId, int set) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) Logging.Log($"Setting Health for {playerId}"); GetInstance(playerId)?.SetHealth(set); } public static void KillPlayer(PlayerId playerId) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Invalid comparison between Unknown and I4 if ((int)playerId == 0 || (int)playerId == 2147483646) { GetInstance((PlayerId)0)?.KillPlayer(); } if ((int)playerId == 1 || (int)playerId == 2147483646) { GetInstance((PlayerId)1)?.KillPlayer(); } } internal static void ReverseControls(PlayerId playerId) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) GetInstance(playerId)?.ReverseControls(); } } internal static class ComponentExtensions { public static T CopyFrom(this T comp, T other) where T : Component { return comp.CopyFrom(other, inherit: false); } public static T CopyFrom(this T comp, T other, bool inherit) where T : Component { Type type = ((object)comp).GetType(); Type type2 = ((object)other).GetType(); if ((object)type != type2) { throw new ArgumentException($"Type mismatch: {type} and {type2}"); } BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; if (!inherit) { bindingFlags |= BindingFlags.DeclaredOnly; } PropertyInfo[] properties = type.GetProperties(bindingFlags); PropertyInfo[] array = properties; foreach (PropertyInfo propertyInfo in array) { if (propertyInfo.CanWrite && propertyInfo.IsObsolete()) { try { propertyInfo.SetValue(comp, propertyInfo.GetValue(other, null), null); } catch { Logging.LogWarning("Could not copy property " + propertyInfo.Name + " for " + type.Name); } } } FieldInfo[] fields = type.GetFields(bindingFlags); FieldInfo[] array2 = fields; foreach (FieldInfo fieldInfo in array2) { if (fieldInfo.IsObsolete()) { fieldInfo.SetValue(comp, fieldInfo.GetValue(other)); } } return comp; } } } namespace CupheadArchipelago.TestEnv { internal class TestMngr { public static void Init() { CreateTestHUD(); CreateTestObjects(); } private static void CreateTestHUD() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("TestCanvas"); val.AddComponent().renderMode = (RenderMode)0; val.AddComponent(); val.AddComponent(); GameObject val2 = CreateHUDText("TestInfoText", val.transform, new Vector2(0f, 0f), new Vector2(15f, 15f), new Vector2(200f, 100f), "Test Mode\nHold Cancel (ESC) to Quit", (TextAnchor)6, 16, Color.white); } private static GameObject CreateHUDText(string name, Transform parent, Vector2 anchor, Vector2 anchoredPosition, Vector2 sizeDelta, string text, TextAnchor textAlignment, int fontSize, Color color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); val.SetActive(true); RectTransform val2 = val.AddComponent(); val2.anchorMin = new Vector2(anchor.x, anchor.y); val2.anchorMax = new Vector2(anchor.x, anchor.y); val2.pivot = new Vector2(anchor.x, anchor.y); val2.anchoredPosition = new Vector2(anchoredPosition.x, anchoredPosition.y); val2.sizeDelta = new Vector2(sizeDelta.x, sizeDelta.y); Text val3 = val.AddComponent(); val3.alignment = textAlignment; val3.font = FontLoader.GetFont((FontType)5); ((Graphic)val3).color = color; val3.fontSize = fontSize; val3.text = text; val.layer = 5; return val; } private static void CreateTestObjects() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown AssetMngr.LoadBundleAssets("testee"); GameObject val = new GameObject("mainObj"); GameObject val2 = new GameObject("objA"); val2.transform.SetParent(val.transform); SpriteRenderer val3 = val2.AddComponent(); val3.sprite = AssetMngr.GetLoadedAsset("sqar"); GameObject val4 = new GameObject("objB"); val4.transform.SetParent(val.transform); SpriteRenderer val5 = val4.AddComponent(); val5.sprite = AssetMngr.GetLoadedAsset("a"); GameObject val6 = new GameObject("objC"); val6.transform.SetParent(val.transform); SpriteRenderer val7 = val6.AddComponent(); val7.sprite = AssetMngr.GetLoadedAsset("circ"); val6.layer = 5; } } } namespace CupheadArchipelago.Resources { internal class AssetBundleMngr { private static readonly Dictionary loadedBundles = new Dictionary(); internal static IEnumerator LoadPersistentAssetBundlesAsync() { foreach (string bundleName in AssetDefs.GetPersisentAssetBundles()) { if (!loadedBundles.ContainsKey(bundleName)) { yield return LoadAssetBundleAsync(bundleName); } yield return null; } } internal static IEnumerator LoadAssetBundleAsync(string bundleName) { if (loadedBundles.ContainsKey(bundleName)) { Logging.LogError(bundleName + " is already loaded!"); } AssetBundleCreateRequest request = AssetBundle.LoadFromMemoryAsync(ResourceLoader.GetLoadedResource(bundleName)); yield return request; loadedBundles.Add(bundleName, request.assetBundle); } internal static void LoadPersistentAssetBundles() { foreach (string persisentAssetBundle in AssetDefs.GetPersisentAssetBundles()) { if (!loadedBundles.ContainsKey(persisentAssetBundle)) { LoadAssetBundle(persisentAssetBundle); } } } internal static void LoadAssetBundle(string bundleName) { if (loadedBundles.ContainsKey(bundleName)) { Logging.LogError(bundleName + " is already loaded!"); } loadedBundles.Add(bundleName, AssetBundle.LoadFromMemory(ResourceLoader.GetLoadedResource(bundleName))); } internal static void UnloadAssetBundles() { UnloadAssetBundles(unloadPersistent: false); } internal static void UnloadAssetBundles(bool unloadPersistent) { string[] array = loadedBundles.Keys.ToArray(); string[] array2 = array; foreach (string bundleName in array2) { if (!AssetDefs.IsAssetBundlePersistent(bundleName) || unloadPersistent) { UnloadAssetBundle(bundleName); } } } internal static void UnloadAssetBundle(string bundleName) { loadedBundles[bundleName].Unload(false); loadedBundles.Remove(bundleName); } internal static bool IsAssetBundleLoaded(string bundleName) { return loadedBundles.ContainsKey(bundleName); } internal static AssetBundle GetLoadedBundle(string bundleName) { if (!loadedBundles.ContainsKey(bundleName)) { throw new KeyNotFoundException(bundleName + " is not loaded!"); } return loadedBundles[bundleName]; } internal static string GetLoadedAssetBundlesAsString() { return "Loaded RBundles: " + Aux.CollectionToString(loadedBundles); } } public class AssetDefs { private static readonly Dictionary> assetBundleDefs; private static readonly HashSet persistentBundles; private static readonly Dictionary assetDefs; private static readonly HashSet persistentAssets; private static readonly Dictionary assetToBundleMap; static AssetDefs() { assetBundleDefs = new Dictionary> { { "testee", new HashSet { "testee", "sqar", "a", "circ" } }, { "cap_base", new HashSet { "s_Debug", "s_TexOverlay" } }, { "cap_dicehouse", new HashSet { "cap_dicehouse_chalkboard_tics" } } }; persistentBundles = new HashSet { "cap_base" }; assetDefs = new Dictionary { { "testee", new RAsset("testee", RAssetType.Sprite) }, { "sqar", new RAsset("sqar", RAssetType.Sprite) }, { "a", new RAsset("a", RAssetType.Sprite) }, { "circ", new RAsset("circ", RAssetType.Sprite) }, { "s_Debug", new RAsset("Debug", RAssetType.Shader) }, { "s_TexOverlay", new RAsset("TexOverlay", RAssetType.Shader) }, { "cap_dicehouse_chalkboard_tics", new RAsset("cap_dicehouse_chalkboard_tics", RAssetType.Texture2D) } }; persistentAssets = new HashSet { "s_Debug", "s_TexOverlay" }; assetToBundleMap = new Dictionary(); foreach (string key in assetBundleDefs.Keys) { foreach (string item in assetBundleDefs[key]) { assetToBundleMap.Add(item, key); } } } public static IEnumerable GetAllRegisteredBundles() { return assetBundleDefs.Keys; } public static IEnumerable GetAllRegisteredAssets() { return assetDefs.Keys; } public static IEnumerable GetAssetsInBundle(string bundleName) { return assetBundleDefs[bundleName]; } public static IEnumerable GetPersisentAssetBundles() { return persistentBundles; } public static IEnumerable GetPersisentAssets() { return persistentAssets; } public static string GetInternalAssetName(string assetName) { return assetDefs[assetName].name; } public static RAssetType GetAssetType(string assetName) { return assetDefs[assetName].type; } public static string GetBundleFromAsset(string assetName) { return assetToBundleMap.ContainsKey(assetName) ? assetToBundleMap[assetName] : null; } public static bool IsAssetBundlePersistent(string bundleName) { return persistentBundles.Contains(bundleName); } public static bool IsAssetPersistent(string assetName) { return persistentAssets.Contains(assetName); } } internal class AssetMngr { private static readonly Dictionary rAssetTypeMap = new Dictionary { { RAssetType.Object, typeof(Object) }, { RAssetType.GameObject, typeof(GameObject) }, { RAssetType.Texture2D, typeof(Texture2D) }, { RAssetType.Sprite, typeof(Texture2D) }, { RAssetType.Shader, typeof(Shader) } }; private static readonly Dictionary loadedAssets = new Dictionary(); internal unsafe static IEnumerator LoadSceneAssetsAsync(Scenes scene) { return LoadSceneAssetsAsync(((object)(*(Scenes*)(&scene))/*cast due to .constrained prefix*/).ToString()); } internal static IEnumerator LoadSceneAssetsAsync(string sceneName) { if (!SceneAssetMap.IsSceneRegistered(sceneName)) { throw new KeyNotFoundException(sceneName + " is not registered in Resource AssetMap."); } foreach (string assetName in SceneAssetMap.GetSceneAssets(sceneName)) { if (!loadedAssets.ContainsKey(assetName)) { yield return LoadAssetAsync(assetName); } else { Logging.Log(assetName + " is already loaded."); } } } internal static IEnumerator LoadPersistentAssetsAsync() { foreach (string assetName in AssetDefs.GetPersisentAssets()) { if (!loadedAssets.ContainsKey(assetName)) { yield return LoadAssetAsync(assetName); } yield return null; } } internal static IEnumerator LoadBundleAssetsAsync(string bundleName) { if (!AssetBundleMngr.IsAssetBundleLoaded(bundleName)) { yield return AssetBundleMngr.LoadAssetBundleAsync(bundleName); } IEnumerable bundleAssets = AssetDefs.GetAssetsInBundle(bundleName); foreach (string asset in bundleAssets) { if (!loadedAssets.ContainsKey(asset)) { yield return LoadAssetAsync(asset); } else { Logging.Log(asset + " is already loaded."); } } } internal static IEnumerator LoadAssetAsync(string assetName) { if (loadedAssets.ContainsKey(assetName)) { throw new Exception(assetName + " is already loaded!"); } string bundleName = AssetDefs.GetBundleFromAsset(assetName) ?? throw new NullReferenceException(assetName + " does not exist in an asset bundle!"); if (!AssetBundleMngr.IsAssetBundleLoaded(bundleName)) { yield return AssetBundleMngr.LoadAssetBundleAsync(bundleName); } AssetBundle bundle = AssetBundleMngr.GetLoadedBundle(bundleName); RAssetType assetType = AssetDefs.GetAssetType(assetName); AssetBundleRequest request = bundle.LoadAssetAsync(AssetDefs.GetInternalAssetName(assetName), rAssetTypeMap[assetType]); yield return request; if (request.asset == (Object)null) { throw new Exception("Asset \"" + assetName + "\" from Bundle \"" + bundleName + "\" could not be loaded!"); } ProcessAsset(request.asset, assetType, out var asset); loadedAssets.Add(assetName, asset); } internal unsafe static void LoadSceneAssets(Scenes scene) { LoadSceneAssets(((object)(*(Scenes*)(&scene))/*cast due to .constrained prefix*/).ToString()); } internal static void LoadSceneAssets(string sceneName) { if (!SceneAssetMap.IsSceneRegistered(sceneName)) { throw new KeyNotFoundException(sceneName + " is not registered in Resource AssetMap."); } foreach (string sceneAsset in SceneAssetMap.GetSceneAssets(sceneName)) { if (!loadedAssets.ContainsKey(sceneAsset)) { LoadAsset(sceneAsset); } else { Logging.Log(sceneAsset + " is already loaded."); } } } internal static void LoadPersistentAssets() { foreach (string persisentAsset in AssetDefs.GetPersisentAssets()) { if (!loadedAssets.ContainsKey(persisentAsset)) { LoadAsset(persisentAsset); } } } internal static void LoadBundleAssets(string bundleName) { if (!AssetBundleMngr.IsAssetBundleLoaded(bundleName)) { AssetBundleMngr.LoadAssetBundle(bundleName); } IEnumerable assetsInBundle = AssetDefs.GetAssetsInBundle(bundleName); foreach (string item in assetsInBundle) { if (!loadedAssets.ContainsKey(item)) { LoadAsset(item); } else { Logging.Log(item + " is already loaded."); } } } internal static void LoadAsset(string assetName) { if (loadedAssets.ContainsKey(assetName)) { throw new Exception(assetName + " is already loaded!"); } string text = AssetDefs.GetBundleFromAsset(assetName) ?? throw new NullReferenceException(assetName + " does not exist in an asset bundle!"); if (!AssetBundleMngr.IsAssetBundleLoaded(text)) { AssetBundleMngr.LoadAssetBundle(text); } AssetBundle loadedBundle = AssetBundleMngr.GetLoadedBundle(text); Object asset = loadedBundle.LoadAsset(AssetDefs.GetInternalAssetName(assetName), rAssetTypeMap[AssetDefs.GetAssetType(assetName)]) ?? throw new Exception("Asset \"" + assetName + "\" from Bundle \"" + text + "\" could not be loaded!"); ProcessAsset(asset, AssetDefs.GetAssetType(assetName), out var nAsset); loadedAssets.Add(assetName, nAsset); } internal static void UnloadAllAssets() { UnloadAllAssets(unloadPersistent: false); } internal static void UnloadAllAssets(bool unloadPersistent) { string[] array = loadedAssets.Keys.ToArray(); string[] array2 = array; foreach (string assetName in array2) { if (!AssetDefs.IsAssetPersistent(assetName) || unloadPersistent) { UnloadAsset(assetName); } } } internal static void UnloadAssets(params string[] assets) { foreach (string assetName in assets) { UnloadAsset(assetName); } } private static void UnloadAsset(string assetName) { if (loadedAssets.ContainsKey(assetName)) { Object.Destroy(loadedAssets[assetName]); loadedAssets.Remove(assetName); } } internal static bool IsAssetLoaded(string assetName) { return loadedAssets.ContainsKey(assetName); } internal static T GetLoadedAsset(string assetName) { if (IsAssetLoaded(assetName)) { if (loadedAssets[assetName] is T result) { return result; } throw new InvalidCastException($"Cannot load \"{assetName}\" as {typeof(T)}."); } throw new KeyNotFoundException("\"" + assetName + "\" is not loaded."); } internal static string GetLoadedAssetsAsString() { LinkedList linkedList = new LinkedList(); foreach (string key in loadedAssets.Keys) { if (AssetDefs.IsAssetPersistent(key)) { linkedList.AddFirst("*" + key); } else { linkedList.AddLast(key); } } return "Loaded RAssets: " + Aux.CollectionToString(linkedList); } private static bool ProcessAsset(Object asset, RAssetType assetType, out Object nAsset) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (assetType == RAssetType.Sprite) { Texture2D val = (Texture2D)asset; nAsset = (Object)(object)Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); return true; } nAsset = asset; return false; } } public class RAsset(string name, RAssetType type) { public readonly string name = name; public readonly RAssetType type = type; } public enum RAssetType { Object, GameObject, Texture2D, Sprite, Shader } public class ResourceDefs { private static readonly HashSet resources = new HashSet { "testee", "cap_base", "cap_dicehouse" }; public static IEnumerable GetRegisteredResources() { return resources; } public static bool ResourceExists(string resourceName) { return resources.Contains(resourceName); } } internal class ResourceLoader { private static readonly Dictionary loadedResources = new Dictionary(); internal const string RESOURCE_PRE = "CupheadArchipelago.Assets."; public static void LoadResources() { foreach (string registeredResource in ResourceDefs.GetRegisteredResources()) { Logging.LogDebug("Loading resource " + registeredResource + "..."); byte[] resourceBytes = GetResourceBytes("CupheadArchipelago.Assets." + registeredResource); loadedResources.Add(registeredResource, resourceBytes); Logging.LogDebug("Loaded resource " + registeredResource + "."); } Logging.LogDebug("Loading persistent resource assets..."); AssetBundleMngr.LoadPersistentAssetBundles(); AssetMngr.LoadPersistentAssets(); StaticAssets.Init(); } private static byte[] GetResourceBytes(string resourceName) { Assembly assembly = typeof(ResourceLoader).Assembly; byte[] array = new byte[16384]; using Stream stream = assembly.GetManifestResourceStream(resourceName); using MemoryStream memoryStream = new MemoryStream(); int count; while ((count = stream.Read(array, 0, array.Length)) > 0) { memoryStream.Write(array, 0, count); } return memoryStream.ToArray(); } internal static byte[] GetLoadedResource(string name) { if (loadedResources.ContainsKey(name)) { return loadedResources[name]; } throw new KeyNotFoundException("Resource \"" + name + "\" not loaded."); } } internal class SceneAssetMap { private static readonly Dictionary> sceneAssetMap = new Dictionary> { { ((object)(Scenes)57/*cast due to .constrained prefix*/).ToString(), new HashSet { "cap_dicehouse_chalkboard_tics" } } }; public unsafe static bool IsSceneRegistered(Scenes scene) { return IsSceneRegistered(((object)(*(Scenes*)(&scene))/*cast due to .constrained prefix*/).ToString()); } public static bool IsSceneRegistered(string sceneName) { return sceneAssetMap.ContainsKey(sceneName); } public static IEnumerable GetRegisteredScenes() { return sceneAssetMap.Keys; } public unsafe static IEnumerable GetSceneAssets(Scenes scene) { return GetSceneAssets(((object)(*(Scenes*)(&scene))/*cast due to .constrained prefix*/).ToString()); } public static IEnumerable GetSceneAssets(string sceneName) { if (sceneAssetMap.ContainsKey(sceneName)) { return sceneAssetMap[sceneName]; } return new string[0]; } } internal class StaticAssets { internal static bool Initted { get; private set; } internal static Shader StandardSpriteShader { get; private set; } internal static Shader DebugShader { get; private set; } internal static Shader OverlayShader { get; private set; } internal static void Init() { StandardSpriteShader = Shader.Find("Sprites/Default"); DebugShader = AssetMngr.GetLoadedAsset("s_Debug"); OverlayShader = AssetMngr.GetLoadedAsset("s_TexOverlay"); Initted = true; } } } namespace CupheadArchipelago.Mapping { public class CoinIdMap { private static readonly Dictionary idToLoc = new Dictionary { { "scene_level_tutorial::Level_Coin :: a53bbd1a-734e-4e60-ada8-d11c62eabcec", APLocation.level_tutorial_coin }, { "675028e9-b9d6-4d31-8536-8ff8e98e2ddf", APLocation.coin_isle1_secret }, { "scene_level_platforming_1_1F::Level_Coin :: 5fd52d1b-a7f2-43a6-80e2-cb170cbc7d4d", APLocation.level_rungun_forest_coin1 }, { "scene_level_platforming_1_1F::Level_Coin :: 63c021bf-52f0-41de-bedf-c77117d244cc", APLocation.level_rungun_forest_coin2 }, { "scene_level_platforming_1_1F::Level_Coin :: 245037a6-1fa2-4167-a631-0723abff8138", APLocation.level_rungun_forest_coin3 }, { "scene_level_platforming_1_1F::Level_Coin :: eaefb009-c117-4b9a-96c1-7abc5558d213", APLocation.level_rungun_forest_coin4 }, { "scene_level_platforming_1_1F::Level_Coin :: 5526f7bc-a902-4c13-9e7a-1632a5abe378", APLocation.level_rungun_forest_coin5 }, { "scene_level_platforming_1_2F::Level_Coin :: 323989de-349e-4740-a764-dbc12217a27c", APLocation.level_rungun_tree_coin1 }, { "scene_level_platforming_1_2F::Level_Coin :: 55a46261-b14c-4065-9ada-18524eaed9f3", APLocation.level_rungun_tree_coin2 }, { "scene_level_platforming_1_2F::Level_Coin :: da0983f6-62d4-4ace-81f2-cad7181d5fe9", APLocation.level_rungun_tree_coin3 }, { "scene_level_platforming_1_2F::Level_Coin :: 7088ec51-4792-49c0-ab2c-c45ec9deb9f0", APLocation.level_rungun_tree_coin4 }, { "scene_level_platforming_1_2F::Level_Coin :: e02954c1-ff76-4ba4-849f-90aae53a7787", APLocation.level_rungun_tree_coin5 }, { "1782e7b4-2edf-45c0-b312-3083397307bf", APLocation.coin_isle2_secret }, { "scene_level_platforming_2_1F::Level_Coin :: 24ef654a-a65b-4a1c-b5e5-c3c64e250646", APLocation.level_rungun_circus_coin1 }, { "scene_level_platforming_2_1F::Level_Coin :: b8d96f03-d264-4a61-9ab9-07de34f660aa", APLocation.level_rungun_circus_coin2 }, { "scene_level_platforming_2_1F::Level_Coin :: 383d9b3b-c280-4825-a6b3-1a21fe42d0ac", APLocation.level_rungun_circus_coin3 }, { "scene_level_platforming_2_1F::Level_Coin :: f1b99bcd-0fa8-4aac-9a54-f310e173ddf9", APLocation.level_rungun_circus_coin4 }, { "scene_level_platforming_2_1F::Level_Coin :: c763ef21-2ee7-491c-a143-b906856fed6c", APLocation.level_rungun_circus_coin5 }, { "scene_level_platforming_2_2F::Level_Coin :: 9025a0e9-fff1-4f14-93d1-1930eef27405", APLocation.level_rungun_funhouse_coin1 }, { "scene_level_platforming_2_2F::Level_Coin :: 284ea6f9-5db4-4f80-b0e5-1d9513a8acb7", APLocation.level_rungun_funhouse_coin2 }, { "scene_level_platforming_2_2F::Level_Coin :: 43a8fc82-b8b8-4a92-b56f-c3e718b46b2c", APLocation.level_rungun_funhouse_coin3 }, { "scene_level_platforming_2_2F::Level_Coin :: bf86d025-4524-4ce8-ba07-540ef3f61ed8", APLocation.level_rungun_funhouse_coin4 }, { "scene_level_platforming_2_2F::Level_Coin :: a7c0e2b9-9560-4ed7-a3a4-428365222cb9", APLocation.level_rungun_funhouse_coin5 }, { "e312336e-010f-4ea4-975b-922aca63629e", APLocation.coin_isle3_secret }, { "scene_level_platforming_3_1F::Level_Coin :: 26ba2e1d-4b0a-4964-ba4d-f58655ef47db", APLocation.level_rungun_harbour_coin1 }, { "scene_level_platforming_3_1F::Level_Coin :: 0f13fbe6-1041-445f-97ed-1bbe2cb0339e", APLocation.level_rungun_harbour_coin2 }, { "scene_level_platforming_3_1F::Level_Coin :: 0086a9b3-87b8-4406-b97b-b94a1fd60bb0", APLocation.level_rungun_harbour_coin3 }, { "scene_level_platforming_3_1F::Level_Coin :: 0a6fbbe4-5c13-4b17-9b58-91e7bbdacde4", APLocation.level_rungun_harbour_coin4 }, { "scene_level_platforming_3_1F::Level_Coin :: beb664ad-5577-4055-9164-b1b2f77430f3", APLocation.level_rungun_harbour_coin5 }, { "scene_level_platforming_3_2F::Level_Coin :: 5da68904-6505-4841-9684-71d2931c1bd6", APLocation.level_rungun_mountain_coin1 }, { "scene_level_platforming_3_2F::Level_Coin :: 999c9b0d-d554-471d-ad96-ee6d57ccfd19", APLocation.level_rungun_mountain_coin2 }, { "scene_level_platforming_3_2F::Level_Coin :: cf0a7cae-d8d9-4be0-9502-8b8544606e04", APLocation.level_rungun_mountain_coin3 }, { "scene_level_platforming_3_2F::Level_Coin :: e671db16-cf6e-421c-937c-2b6f5c7ad0e7", APLocation.level_rungun_mountain_coin4 }, { "scene_level_platforming_3_2F::Level_Coin :: 084a7b75-e752-452f-8710-687db1e165fe", APLocation.level_rungun_mountain_coin5 }, { "43dfad5b-65dc-42f1-9ab3-25e0174f4ee8", APLocation.coin_isleh_secret }, { "619e92f1-e0fd-4f6e-9c2d-5ce5dbaf393f", APLocation.dlc_coin_isle4_secret }, { "scene_level_chalice_tutorial::Level_Coin :: 578c0218-df9e-4cdd-932a-a1277b5b7129", APLocation.level_dlc_tutorial_coin } }; public static bool CoinIDExists(string coinId) { return idToLoc.ContainsKey(coinId); } public static APLocation GetAPLocation(string coinId) { return idToLoc[coinId]; } } public static class ItemMap { private static readonly Dictionary itemTypes; private static readonly Dictionary idToWeapon; private static readonly Dictionary weaponToId; private static readonly HashSet modularWeapons; private static readonly HashSet weaponExItems; private static readonly HashSet weaponProgressiveItems; private static readonly Dictionary idToCharm; private static readonly Dictionary idToSuper; private static readonly HashSet planeItems; private static readonly HashSet chaliceItems; public static APItemType GetItemType(long item) { if (itemTypes.ContainsKey(item)) { return itemTypes[item]; } Logging.LogWarning($"[APItemMngr] Item Id {item} has an unknown type!"); return APItemType.None; } public static APItemType GetItemType(this APItem item) { return GetItemType(item.id); } public static bool IsItemFiller(long item) { APItemType itemType = GetItemType(item); return itemType == APItemType.None || itemType == APItemType.Level; } public static bool IsItemFiller(this APItem item) { return IsItemFiller(item.id); } public static Weapon GetWeapon(long item) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return idToWeapon[item]; } public static long? GetWeaponItemId(Weapon weapon) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) return weaponToId.ContainsKey(weapon) ? new long?(weaponToId[weapon]) : ((long?)null); } public static IEnumerable GetModularWeapons() { return modularWeapons; } public static bool IsWeaponModular(Weapon weapon) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return modularWeapons.Contains(weapon); } public static bool IsItemModularWeapon(long itemId) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) return idToWeapon.ContainsKey(itemId) && modularWeapons.Contains(idToWeapon[itemId]); } public static bool IsItemModularWeapon(this APItem item) { return IsItemModularWeapon(item.id); } public static bool IsItemWeaponEx(APItem item) { return weaponExItems.Contains(item); } public static bool IsItemWeaponEx(long itemId) { return APItem.IdExists(itemId) && IsItemWeaponEx(APItem.FromId(itemId)); } public static bool IsItemProgressiveWeapon(APItem item) { return weaponProgressiveItems.Contains(item); } public static bool IsItemProgressiveWeapon(long itemId) { return APItem.IdExists(itemId) && IsItemProgressiveWeapon(APItem.FromId(itemId)); } public static Charm GetCharm(long item) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return idToCharm[item]; } public static Super GetSuper(long item) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return idToSuper[item]; } public static bool IsPlaneItem(long item) { return planeItems.Contains(item); } public static bool IsPlaneItem(this APItem item) { return planeItems.Contains(item); } public static bool IsChaliceItem(long item) { return chaliceItems.Contains(item); } public static bool IsChaliceItem(this APItem item) { return chaliceItems.Contains(item); } static ItemMap() { //IL_0ed3: Unknown result type (might be due to invalid IL or missing references) itemTypes = new Dictionary { { APItem.level_generic, APItemType.None }, { APItem.level_extrahealth, APItemType.Level }, { APItem.level_supercharge, APItemType.Level }, { APItem.level_fastfire, APItemType.Level }, { APItem.level_4, APItemType.Level }, { APItem.level_trap_fingerjam, APItemType.Level }, { APItem.level_trap_slowfire, APItemType.Level }, { APItem.level_trap_superdrain, APItemType.Level }, { APItem.level_trap_loadout, APItemType.Level }, { APItem.level_trap_screen, APItemType.Level }, { APItem.coin, APItemType.Essential }, { APItem.coin2, APItemType.Essential }, { APItem.coin3, APItemType.Essential }, { APItem.contract, APItemType.Essential }, { APItem.plane_super, APItemType.Essential }, { APItem.healthupgrade, APItemType.Essential }, { APItem.plane_ex, APItemType.Essential }, { APItem.dlc_boat, APItemType.Essential }, { APItem.dlc_ingredient, APItemType.Essential }, { APItem.dlc_cplane_super, APItemType.Essential }, { APItem.dlc_cplane_ex, APItemType.Essential }, { APItem.plane_gun, APItemType.Weapon }, { APItem.plane_bombs, APItemType.Weapon }, { APItem.dlc_cplane_gun, APItemType.Weapon }, { APItem.dlc_cplane_bombs, APItemType.Weapon }, { APItem.weapon_peashooter, APItemType.Weapon }, { APItem.weapon_spread, APItemType.Weapon }, { APItem.weapon_chaser, APItemType.Weapon }, { APItem.weapon_lobber, APItemType.Weapon }, { APItem.weapon_charge, APItemType.Weapon }, { APItem.weapon_roundabout, APItemType.Weapon }, { APItem.weapon_dlc_crackshot, APItemType.Weapon }, { APItem.weapon_dlc_converge, APItemType.Weapon }, { APItem.weapon_dlc_twistup, APItemType.Weapon }, { APItem.weapon_peashooter_ex, APItemType.Weapon }, { APItem.weapon_spread_ex, APItemType.Weapon }, { APItem.weapon_chaser_ex, APItemType.Weapon }, { APItem.weapon_lobber_ex, APItemType.Weapon }, { APItem.weapon_charge_ex, APItemType.Weapon }, { APItem.weapon_roundabout_ex, APItemType.Weapon }, { APItem.weapon_dlc_crackshot_ex, APItemType.Weapon }, { APItem.weapon_dlc_converge_ex, APItemType.Weapon }, { APItem.weapon_dlc_twistup_ex, APItemType.Weapon }, { APItem.p_weapon_peashooter, APItemType.Weapon }, { APItem.p_weapon_spread, APItemType.Weapon }, { APItem.p_weapon_chaser, APItemType.Weapon }, { APItem.p_weapon_lobber, APItemType.Weapon }, { APItem.p_weapon_charge, APItemType.Weapon }, { APItem.p_weapon_roundabout, APItemType.Weapon }, { APItem.p_weapon_dlc_crackshot, APItemType.Weapon }, { APItem.p_weapon_dlc_converge, APItemType.Weapon }, { APItem.p_weapon_dlc_twistup, APItemType.Weapon }, { APItem.charm_heart, APItemType.Charm }, { APItem.charm_smokebomb, APItemType.Charm }, { APItem.charm_psugar, APItemType.Charm }, { APItem.charm_coffee, APItemType.Charm }, { APItem.charm_twinheart, APItemType.Charm }, { APItem.charm_whetstone, APItemType.Charm }, { APItem.charm_dlc_cookie, APItemType.Charm }, { APItem.charm_dlc_heartring, APItemType.Charm }, { APItem.charm_dlc_broken_relic, APItemType.Charm }, { APItem.super_i, APItemType.Super }, { APItem.super_ii, APItemType.Super }, { APItem.super_iii, APItemType.Super }, { APItem.super_dlc_c_i, APItemType.Super }, { APItem.super_dlc_c_ii, APItemType.Super }, { APItem.super_dlc_c_iii, APItemType.Super }, { APItem.ability_dash, APItemType.Ability }, { APItem.ability_crouch, APItemType.Ability }, { APItem.ability_parry, APItemType.Ability }, { APItem.ability_plane_parry, APItemType.Ability }, { APItem.ability_plane_shrink, APItemType.Ability }, { APItem.ability_dlc_p_cdash, APItemType.Ability }, { APItem.ability_dlc_ccrouch, APItemType.Ability }, { APItem.ability_dlc_cdoublejump, APItemType.Ability }, { APItem.ability_dlc_cplane_parry, APItemType.Ability }, { APItem.ability_dlc_cplane_shrink, APItemType.Ability }, { APItem.ability_aim_left, APItemType.Ability }, { APItem.ability_aim_right, APItemType.Ability }, { APItem.ability_aim_up, APItemType.Ability }, { APItem.ability_aim_down, APItemType.Ability }, { APItem.ability_aim_upleft, APItemType.Ability }, { APItem.ability_aim_upright, APItemType.Ability }, { APItem.ability_aim_downleft, APItemType.Ability }, { APItem.ability_aim_downright, APItemType.Ability }, { APItem.ability_dlc_c_aim_left, APItemType.Ability }, { APItem.ability_dlc_c_aim_right, APItemType.Ability }, { APItem.ability_dlc_c_aim_up, APItemType.Ability }, { APItem.ability_dlc_c_aim_down, APItemType.Ability }, { APItem.ability_dlc_c_aim_upleft, APItemType.Ability }, { APItem.ability_dlc_c_aim_upright, APItemType.Ability }, { APItem.ability_dlc_c_aim_downleft, APItemType.Ability }, { APItem.ability_dlc_c_aim_downright, APItemType.Ability } }; idToWeapon = new Dictionary { { APItem.weapon_peashooter, (Weapon)1456773641 }, { APItem.weapon_spread, (Weapon)1456773649 }, { APItem.weapon_chaser, (Weapon)1460621839 }, { APItem.weapon_lobber, (Weapon)1467024095 }, { APItem.weapon_charge, (Weapon)1466416941 }, { APItem.weapon_roundabout, (Weapon)1466518900 }, { APItem.weapon_dlc_crackshot, (Weapon)1614768724 }, { APItem.weapon_dlc_converge, (Weapon)1487081743 }, { APItem.weapon_dlc_twistup, (Weapon)1568276855 }, { APItem.weapon_peashooter_ex, (Weapon)1456773641 }, { APItem.weapon_spread_ex, (Weapon)1456773649 }, { APItem.weapon_chaser_ex, (Weapon)1460621839 }, { APItem.weapon_lobber_ex, (Weapon)1467024095 }, { APItem.weapon_charge_ex, (Weapon)1466416941 }, { APItem.weapon_roundabout_ex, (Weapon)1466518900 }, { APItem.weapon_dlc_crackshot_ex, (Weapon)1614768724 }, { APItem.weapon_dlc_converge_ex, (Weapon)1487081743 }, { APItem.weapon_dlc_twistup_ex, (Weapon)1568276855 }, { APItem.p_weapon_peashooter, (Weapon)1456773641 }, { APItem.p_weapon_spread, (Weapon)1456773649 }, { APItem.p_weapon_chaser, (Weapon)1460621839 }, { APItem.p_weapon_lobber, (Weapon)1467024095 }, { APItem.p_weapon_charge, (Weapon)1466416941 }, { APItem.p_weapon_roundabout, (Weapon)1466518900 }, { APItem.p_weapon_dlc_crackshot, (Weapon)1614768724 }, { APItem.p_weapon_dlc_converge, (Weapon)1487081743 }, { APItem.p_weapon_dlc_twistup, (Weapon)1568276855 }, { APItem.plane_gun, (Weapon)1457006169 }, { APItem.plane_bombs, (Weapon)1492758857 }, { APItem.dlc_cplane_gun, (Weapon)1527492226 }, { APItem.dlc_cplane_bombs, (Weapon)1600944454 } }; weaponToId = new Dictionary(); modularWeapons = new HashSet { (Weapon)1456773641, (Weapon)1456773649, (Weapon)1460621839, (Weapon)1467024095, (Weapon)1466416941, (Weapon)1466518900, (Weapon)1614768724, (Weapon)1487081743, (Weapon)1568276855 }; weaponExItems = new HashSet { APItem.weapon_peashooter_ex, APItem.weapon_spread_ex, APItem.weapon_chaser_ex, APItem.weapon_lobber_ex, APItem.weapon_charge_ex, APItem.weapon_roundabout_ex, APItem.weapon_dlc_crackshot_ex, APItem.weapon_dlc_converge_ex, APItem.weapon_dlc_twistup_ex }; weaponProgressiveItems = new HashSet { APItem.p_weapon_peashooter, APItem.p_weapon_spread, APItem.p_weapon_chaser, APItem.p_weapon_lobber, APItem.p_weapon_charge, APItem.p_weapon_roundabout, APItem.p_weapon_dlc_crackshot, APItem.p_weapon_dlc_converge, APItem.p_weapon_dlc_twistup }; idToCharm = new Dictionary { { APItem.charm_heart, (Charm)1460832742 }, { APItem.charm_smokebomb, (Charm)1461001046 }, { APItem.charm_psugar, (Charm)1487051212 }, { APItem.charm_coffee, (Charm)1460880866 }, { APItem.charm_twinheart, (Charm)1500641115 }, { APItem.charm_whetstone, (Charm)1500621999 }, { APItem.charm_dlc_heartring, (Charm)1568891766 }, { APItem.charm_dlc_cookie, (Charm)1522153206 }, { APItem.charm_dlc_broken_relic, (Charm)1569309672 } }; idToSuper = new Dictionary { { APItem.super_i, (Super)1456815409 }, { APItem.super_ii, (Super)1495012282 }, { APItem.super_iii, (Super)1467617939 }, { APItem.super_dlc_c_i, (Super)1550226058 }, { APItem.super_dlc_c_ii, (Super)1550562928 }, { APItem.super_dlc_c_iii, (Super)1529501404 } }; planeItems = new HashSet { APItem.plane_gun, APItem.plane_bombs, APItem.plane_super, APItem.plane_ex, APItem.ability_plane_parry, APItem.ability_plane_shrink, APItem.dlc_cplane_gun, APItem.dlc_cplane_bombs, APItem.dlc_cplane_super, APItem.dlc_cplane_ex, APItem.ability_dlc_cplane_parry, APItem.ability_dlc_cplane_shrink }; chaliceItems = new HashSet { APItem.dlc_cplane_super, APItem.dlc_cplane_ex, APItem.dlc_cplane_gun, APItem.dlc_cplane_bombs, APItem.super_dlc_c_i, APItem.super_dlc_c_ii, APItem.super_dlc_c_iii, APItem.ability_dlc_p_cdash, APItem.ability_dlc_ccrouch, APItem.ability_dlc_cdoublejump, APItem.ability_dlc_cplane_parry, APItem.ability_dlc_cplane_shrink, APItem.ability_dlc_c_aim_left, APItem.ability_dlc_c_aim_right, APItem.ability_dlc_c_aim_up, APItem.ability_dlc_c_aim_down, APItem.ability_dlc_c_aim_upleft, APItem.ability_dlc_c_aim_upright, APItem.ability_dlc_c_aim_downleft, APItem.ability_dlc_c_aim_downright }; foreach (KeyValuePair item in idToWeapon) { weaponToId[item.Value] = item.Key; } } } public class LevelLocationMap { private static readonly Dictionary map; static LevelLocationMap() { map = new Dictionary { { (Levels)6, new APLocation[4] { APLocation.level_boss_veggies, APLocation.level_boss_veggies_topgrade, APLocation.level_boss_veggies_dlc_chaliced, APLocation.level_boss_veggies_secret } }, { (Levels)1450863107, new APLocation[3] { APLocation.level_boss_slime, APLocation.level_boss_slime_topgrade, APLocation.level_boss_slime_dlc_chaliced } }, { (Levels)7, new APLocation[3] { APLocation.level_boss_frogs, APLocation.level_boss_frogs_topgrade, APLocation.level_boss_frogs_dlc_chaliced } }, { (Levels)1450266910, new APLocation[3] { APLocation.level_boss_flower, APLocation.level_boss_flower_topgrade, APLocation.level_boss_flower_dlc_chaliced } }, { (Levels)1451300935, new APLocation[3] { APLocation.level_boss_baroness, APLocation.level_boss_baroness_topgrade, APLocation.level_boss_baroness_dlc_chaliced } }, { (Levels)1456125457, new APLocation[3] { APLocation.level_boss_clown, APLocation.level_boss_clown_topgrade, APLocation.level_boss_clown_dlc_chaliced } }, { (Levels)1432722919, new APLocation[3] { APLocation.level_boss_dragon, APLocation.level_boss_dragon_topgrade, APLocation.level_boss_dragon_dlc_chaliced } }, { (Levels)1429976377, new APLocation[3] { APLocation.level_boss_bee, APLocation.level_boss_bee_topgrade, APLocation.level_boss_bee_dlc_chaliced } }, { (Levels)2, new APLocation[3] { APLocation.level_boss_pirate, APLocation.level_boss_pirate_topgrade, APLocation.level_boss_pirate_dlc_chaliced } }, { (Levels)1430652919, new APLocation[3] { APLocation.level_boss_mouse, APLocation.level_boss_mouse_topgrade, APLocation.level_boss_mouse_dlc_chaliced } }, { (Levels)1456740288, new APLocation[4] { APLocation.level_boss_sallystageplay, APLocation.level_boss_sallystageplay_topgrade, APLocation.level_boss_sallystageplay_dlc_chaliced, APLocation.level_boss_sallystageplay_secret } }, { (Levels)5, new APLocation[3] { APLocation.level_boss_train, APLocation.level_boss_train_topgrade, APLocation.level_boss_train_dlc_chaliced } }, { (Levels)1465296077, new APLocation[3] { APLocation.level_boss_kingdice, APLocation.level_boss_kingdice_topgrade, APLocation.level_boss_kingdice_dlc_chaliced } }, { (Levels)1458719430, new APLocation[2] { APLocation.level_dicepalace_boss_booze, APLocation.level_dicepalace_boss_booze_dlc_chaliced } }, { (Levels)1458336090, new APLocation[2] { APLocation.level_dicepalace_boss_chips, APLocation.level_dicepalace_boss_chips_dlc_chaliced } }, { (Levels)1458551456, new APLocation[2] { APLocation.level_dicepalace_boss_cigar, APLocation.level_dicepalace_boss_cigar_dlc_chaliced } }, { (Levels)1458062114, new APLocation[2] { APLocation.level_dicepalace_boss_domino, APLocation.level_dicepalace_boss_domino_dlc_chaliced } }, { (Levels)1459928905, new APLocation[2] { APLocation.level_dicepalace_boss_rabbit, APLocation.level_dicepalace_boss_rabbit_dlc_chaliced } }, { (Levels)1463479514, new APLocation[2] { APLocation.level_dicepalace_boss_plane_horse, APLocation.level_dicepalace_boss_plane_horse_dlc_chaliced } }, { (Levels)1459105708, new APLocation[2] { APLocation.level_dicepalace_boss_roulette, APLocation.level_dicepalace_boss_roulette_dlc_chaliced } }, { (Levels)1468483834, new APLocation[2] { APLocation.level_dicepalace_boss_eightball, APLocation.level_dicepalace_boss_eightball_dlc_chaliced } }, { (Levels)1464322003, new APLocation[2] { APLocation.level_dicepalace_boss_plane_memory, APLocation.level_dicepalace_boss_plane_memory_dlc_chaliced } }, { (Levels)1466688317, new APLocation[3] { APLocation.level_boss_devil, APLocation.level_boss_devil_topgrade, APLocation.level_boss_devil_dlc_chaliced } }, { (Levels)1449745424, new APLocation[3] { APLocation.level_boss_plane_blimp, APLocation.level_boss_plane_blimp_topgrade, APLocation.level_boss_plane_blimp_dlc_chaliced } }, { (Levels)1460200177, new APLocation[4] { APLocation.level_boss_plane_genie, APLocation.level_boss_plane_genie_topgrade, APLocation.level_boss_plane_genie_dlc_chaliced, APLocation.level_boss_plane_genie_secret } }, { (Levels)1428495827, new APLocation[3] { APLocation.level_boss_plane_bird, APLocation.level_boss_plane_bird_topgrade, APLocation.level_boss_plane_bird_dlc_chaliced } }, { (Levels)1446558823, new APLocation[3] { APLocation.level_boss_plane_mermaid, APLocation.level_boss_plane_mermaid_topgrade, APLocation.level_boss_plane_mermaid_dlc_chaliced } }, { (Levels)1452935394, new APLocation[3] { APLocation.level_boss_plane_robot, APLocation.level_boss_plane_robot_topgrade, APLocation.level_boss_plane_robot_dlc_chaliced } }, { (Levels)1464969490, new APLocation[9] { APLocation.level_rungun_forest, APLocation.level_rungun_forest_agrade, APLocation.level_rungun_forest_pacifist, APLocation.level_rungun_forest_dlc_chaliced, APLocation.level_rungun_forest_coin1, APLocation.level_rungun_forest_coin2, APLocation.level_rungun_forest_coin3, APLocation.level_rungun_forest_coin4, APLocation.level_rungun_forest_coin5 } }, { (Levels)1464969491, new APLocation[9] { APLocation.level_rungun_tree, APLocation.level_rungun_tree_agrade, APLocation.level_rungun_tree_pacifist, APLocation.level_rungun_tree_dlc_chaliced, APLocation.level_rungun_tree_coin1, APLocation.level_rungun_tree_coin2, APLocation.level_rungun_tree_coin3, APLocation.level_rungun_tree_coin4, APLocation.level_rungun_tree_coin5 } }, { (Levels)1499704951, new APLocation[9] { APLocation.level_rungun_circus, APLocation.level_rungun_circus_agrade, APLocation.level_rungun_circus_pacifist, APLocation.level_rungun_circus_dlc_chaliced, APLocation.level_rungun_circus_coin1, APLocation.level_rungun_circus_coin2, APLocation.level_rungun_circus_coin3, APLocation.level_rungun_circus_coin4, APLocation.level_rungun_circus_coin5 } }, { (Levels)1496818712, new APLocation[9] { APLocation.level_rungun_funhouse, APLocation.level_rungun_funhouse_agrade, APLocation.level_rungun_funhouse_pacifist, APLocation.level_rungun_funhouse_dlc_chaliced, APLocation.level_rungun_funhouse_coin1, APLocation.level_rungun_funhouse_coin2, APLocation.level_rungun_funhouse_coin3, APLocation.level_rungun_funhouse_coin4, APLocation.level_rungun_funhouse_coin5 } }, { (Levels)1464969492, new APLocation[9] { APLocation.level_rungun_harbour, APLocation.level_rungun_harbour_agrade, APLocation.level_rungun_harbour_pacifist, APLocation.level_rungun_harbour_dlc_chaliced, APLocation.level_rungun_harbour_coin1, APLocation.level_rungun_harbour_coin2, APLocation.level_rungun_harbour_coin3, APLocation.level_rungun_harbour_coin4, APLocation.level_rungun_harbour_coin5 } }, { (Levels)1464969493, new APLocation[9] { APLocation.level_rungun_mountain, APLocation.level_rungun_mountain_agrade, APLocation.level_rungun_mountain_pacifist, APLocation.level_rungun_mountain_dlc_chaliced, APLocation.level_rungun_mountain_coin1, APLocation.level_rungun_mountain_coin2, APLocation.level_rungun_mountain_coin3, APLocation.level_rungun_mountain_coin4, APLocation.level_rungun_mountain_coin5 } }, { (Levels)1523429320, new APLocation[3] { APLocation.level_dlc_boss_oldman, APLocation.level_dlc_boss_oldman_topgrade, APLocation.level_dlc_boss_oldman_dlc_chaliced } }, { (Levels)1518081307, new APLocation[3] { APLocation.level_dlc_boss_rumrunners, APLocation.level_dlc_boss_rumrunners_topgrade, APLocation.level_dlc_boss_rumrunners_dlc_chaliced } }, { (Levels)1527591209, new APLocation[3] { APLocation.level_dlc_boss_snowcult, APLocation.level_dlc_boss_snowcult_topgrade, APLocation.level_dlc_boss_snowcult_dlc_chaliced } }, { (Levels)1511943573, new APLocation[4] { APLocation.level_dlc_boss_airplane, APLocation.level_dlc_boss_airplane_topgrade, APLocation.level_dlc_boss_airplane_dlc_chaliced, APLocation.level_dlc_boss_airplane_secret } }, { (Levels)1530096313, new APLocation[3] { APLocation.level_dlc_boss_plane_cowboy, APLocation.level_dlc_boss_plane_cowboy_topgrade, APLocation.level_dlc_boss_plane_cowboy_dlc_chaliced } }, { (Levels)1573044456, new APLocation[3] { APLocation.level_dlc_boss_saltbaker, APLocation.level_dlc_boss_saltbaker_topgrade, APLocation.level_dlc_boss_saltbaker_dlc_chaliced } }, { (Levels)1562078899, new APLocation[2] { APLocation.level_dlc_chesscastle_pawn, APLocation.level_dlc_chesscastle_pawn_dlc_chaliced } }, { (Levels)1560339521, new APLocation[2] { APLocation.level_dlc_chesscastle_knight, APLocation.level_dlc_chesscastle_knight_dlc_chaliced } }, { (Levels)1526556188, new APLocation[2] { APLocation.level_dlc_chesscastle_bishop, APLocation.level_dlc_chesscastle_bishop_dlc_chaliced } }, { (Levels)1560855325, new APLocation[2] { APLocation.level_dlc_chesscastle_rook, APLocation.level_dlc_chesscastle_rook_dlc_chaliced } }, { (Levels)1561124831, new APLocation[2] { APLocation.level_dlc_chesscastle_queen, APLocation.level_dlc_chesscastle_queen_dlc_chaliced } } }; } public static long GetLocationId(Levels level, int index) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) try { return map[level][index].id; } catch (KeyNotFoundException) { throw new KeyNotFoundException($"Level {level} does not exist."); } catch (IndexOutOfRangeException) { throw new IndexOutOfRangeException($"Index {index} is out of range for Level {level}."); } } public static bool LevelHasLocations(Levels level) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return map.ContainsKey(level); } public static IEnumerable GetKeys() { return map.Keys; } } public class LevelMap { private static readonly Dictionary levelMap; private static readonly Dictionary levelIdMap; private static readonly HashSet bossLevels; private static readonly HashSet rungunLevels; private static readonly HashSet dicePalaceLevels; private static readonly HashSet dlcChessCastleLevels; private static LevelMap instance; private readonly Dictionary shuffleMap; static LevelMap() { //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Unknown result type (might be due to invalid IL or missing references) //IL_034f: Unknown result type (might be due to invalid IL or missing references) //IL_0352: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Unknown result type (might be due to invalid IL or missing references) //IL_037c: Unknown result type (might be due to invalid IL or missing references) //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_03a6: Unknown result type (might be due to invalid IL or missing references) //IL_03da: Unknown result type (might be due to invalid IL or missing references) //IL_03de: Unknown result type (might be due to invalid IL or missing references) //IL_0413: Unknown result type (might be due to invalid IL or missing references) //IL_0417: Unknown result type (might be due to invalid IL or missing references) //IL_044c: Unknown result type (might be due to invalid IL or missing references) //IL_0450: Unknown result type (might be due to invalid IL or missing references) levelMap = new Dictionary { { 0L, (Levels)6 }, { 1L, (Levels)1450863107 }, { 2L, (Levels)7 }, { 3L, (Levels)1450266910 }, { 4L, (Levels)1451300935 }, { 5L, (Levels)1456125457 }, { 6L, (Levels)1432722919 }, { 7L, (Levels)1429976377 }, { 8L, (Levels)2 }, { 9L, (Levels)1430652919 }, { 10L, (Levels)1456740288 }, { 11L, (Levels)5 }, { 12L, (Levels)1449745424 }, { 13L, (Levels)1460200177 }, { 14L, (Levels)1428495827 }, { 15L, (Levels)1446558823 }, { 16L, (Levels)1452935394 }, { 17L, (Levels)1465296077 }, { 18L, (Levels)1466688317 }, { 19L, (Levels)1458719430 }, { 20L, (Levels)1458336090 }, { 21L, (Levels)1458551456 }, { 22L, (Levels)1458062114 }, { 23L, (Levels)1459928905 }, { 24L, (Levels)1463479514 }, { 25L, (Levels)1459105708 }, { 26L, (Levels)1468483834 }, { 27L, (Levels)1464322003 }, { 28L, (Levels)1464969490 }, { 29L, (Levels)1464969491 }, { 30L, (Levels)1499704951 }, { 31L, (Levels)1496818712 }, { 32L, (Levels)1464969492 }, { 33L, (Levels)1464969493 }, { 100L, (Levels)1523429320 }, { 101L, (Levels)1518081307 }, { 102L, (Levels)1527591209 }, { 103L, (Levels)1511943573 }, { 104L, (Levels)1530096313 }, { 105L, (Levels)1573044456 }, { 106L, (Levels)1616405510 }, { 107L, (Levels)1562078899 }, { 108L, (Levels)1560339521 }, { 109L, (Levels)1526556188 }, { 110L, (Levels)1560855325 }, { 111L, (Levels)1561124831 }, { 112L, (Levels)1624358789 } }; levelIdMap = new Dictionary(); instance = null; foreach (long key in levelMap.Keys) { levelIdMap.Add(levelMap[key], key); } HashSet hashSet = new HashSet(); Levels[] world1BossLevels = Level.world1BossLevels; foreach (Levels item in world1BossLevels) { hashSet.Add(item); } Levels[] world2BossLevels = Level.world2BossLevels; foreach (Levels item in world2BossLevels) { hashSet.Add(item); } Levels[] world3BossLevels = Level.world3BossLevels; foreach (Levels item in world3BossLevels) { hashSet.Add(item); } Levels[] worldDLCBossLevels = Level.worldDLCBossLevels; foreach (Levels item in worldDLCBossLevels) { hashSet.Add(item); } bossLevels = hashSet; HashSet hashSet2 = new HashSet(); Levels[] platformingLevels = Level.platformingLevels; foreach (Levels item in platformingLevels) { hashSet2.Add(item); } rungunLevels = hashSet2; HashSet hashSet3 = new HashSet(); Levels[] world4MiniBossLevels = Level.world4MiniBossLevels; foreach (Levels item in world4MiniBossLevels) { hashSet3.Add(item); } dicePalaceLevels = hashSet3; HashSet hashSet4 = new HashSet(); Levels[] kingOfGamesLevels = Level.kingOfGamesLevels; foreach (Levels item in kingOfGamesLevels) { hashSet4.Add(item); } dlcChessCastleLevels = hashSet4; } internal static void Init(LevelMap map) { instance = map; } public static bool IsInitted() { return instance != null; } public static bool LevelIdExists(long id) { return levelMap.ContainsKey(id); } public static bool LevelExists(Levels level) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return levelIdMap.ContainsKey(level); } public static long GetLevelId(Levels level) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return levelIdMap[level]; } public static bool LevelIsBoss(Levels level) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) return bossLevels.Contains(level) && LevelExists(level); } public static bool LevelIsRungun(Levels level) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) return rungunLevels.Contains(level) && LevelExists(level); } public static bool LevelIsDicePalace(Levels level) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) return dicePalaceLevels.Contains(level) && LevelExists(level); } public static bool LevelIsDlcChessCastle(Levels level) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) return dlcChessCastleLevels.Contains(level) && LevelExists(level); } public static Levels GetMappedLevel(Levels orig, bool quiet = false) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (IsInitted()) { return instance.MapLevel(orig, quiet); } Logging.LogError("[LevelMap] Not initted! Cannot Map!"); return orig; } public static bool CheckMappedLevelCompleted(Levels level) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) return PlayerData.Data.CheckLevelCompleted(GetMappedLevel(level, quiet: true)); } public static bool CheckMappedLevelsCompleted(Levels[] levels) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) foreach (Levels level in levels) { if (!CheckMappedLevelCompleted(level)) { return false; } } return true; } public LevelMap(IDictionary map) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: 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_00c7: Unknown result type (might be due to invalid IL or missing references) shuffleMap = new Dictionary(); foreach (long key in levelMap.Keys) { Levels val = levelMap[key]; if (map.ContainsKey(key)) { Levels val2 = levelMap[map[key]]; if ((LevelIsBoss(val) && LevelIsBoss(val2)) || (LevelIsRungun(val) && LevelIsRungun(val2)) || (LevelIsDicePalace(val) && LevelIsDicePalace(val2))) { shuffleMap.Add(val, val2); continue; } if (val != val2) { Logging.LogError($"[LevelMap] Invalid map combination: \"{val} -> {val2}\" Unsupported types!"); throw new ArgumentException("Levels must be mapped to the same type!"); } Logging.Log($"[LevelMap] Skipping map combination: \"{val} -> {val2}\". Unsupported types."); } else { shuffleMap.Add(levelMap[key], levelMap[key]); } } } public Levels MapLevel(Levels orig, bool quiet = false) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (shuffleMap.ContainsKey(orig)) { return shuffleMap[orig]; } if (!quiet) { Logging.Log($"[MapLevel] Level \"{orig}\" is not mapped. Returning original level."); } return orig; } } public class ShopMap { private static readonly Dictionary weaponLocations = new Dictionary { { (Weapon)1460621839, APLocation.shop_weapon1 }, { (Weapon)1456773649, APLocation.shop_weapon2 }, { (Weapon)1466518900, APLocation.shop_weapon3 }, { (Weapon)1467024095, APLocation.shop_weapon4 }, { (Weapon)1466416941, APLocation.shop_weapon5 }, { (Weapon)1487081743, APLocation.shop_dlc_weapon6 }, { (Weapon)1614768724, APLocation.shop_dlc_weapon7 }, { (Weapon)1568276855, APLocation.shop_dlc_weapon8 } }; private static readonly Dictionary charmLocations = new Dictionary { { (Charm)1460832742, APLocation.shop_charm1 }, { (Charm)1461001046, APLocation.shop_charm2 }, { (Charm)1487051212, APLocation.shop_charm3 }, { (Charm)1460880866, APLocation.shop_charm4 }, { (Charm)1500621999, APLocation.shop_charm5 }, { (Charm)1500641115, APLocation.shop_charm6 }, { (Charm)1568891766, APLocation.shop_dlc_charm7 }, { (Charm)1569309672, APLocation.shop_dlc_charm8 } }; private static ShopSet[] shopMap; internal static void SetShopMap(ShopSet[] shopMap) { ShopMap.shopMap = shopMap; } public static ShopSet[] GetShopMap() { return shopMap; } public static long GetAPWeaponLocation(Weapon weapon) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (weaponLocations.ContainsKey(weapon)) { return weaponLocations[weapon]; } throw new KeyNotFoundException($"[GetAPWeaponLocation] Unknown item: {weapon}"); } public static long GetAPCharmLocation(Charm charm) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (charmLocations.ContainsKey(charm)) { return charmLocations[charm]; } throw new KeyNotFoundException($"[GetAPWeaponLocation] Unknown item: {charm}"); } public static long GetAPLocation(ShopSceneItem item) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) long result = -6L; ItemType itemType = item.itemType; ItemType val = itemType; if ((int)val != 0) { if ((int)val == 2) { result = GetAPCharmLocation(item.charm); } else { Logging.LogWarning($"[ShopMap][GetAPLocation] Cannot get item. Invalid Type {item.itemType}"); } } else { result = GetAPWeaponLocation(item.weapon); } return result; } } public readonly struct ShopSet { public int Weapons { get; } public int Charms { get; } public ShopSet(int weapons, int charms) { Weapons = weapons; Charms = charms; } } } namespace CupheadArchipelago.Interfaces { internal interface IPlayerDataItfc { bool IsUnlocked(Weapon weapon); bool IsUnlocked(Charm charm); bool IsUnlocked(Super super); void Gift(Weapon weapon); void Gift(Charm charm); void Gift(Super super); void AddCoins(int count); int GetCoins(); void DoPlaneSecondaryEquipTrigger(); } internal class PlayerDataItfc : IPlayerDataItfc { private static readonly PlayerDataItfc _default = new PlayerDataItfc(); internal static PlayerDataItfc Default => _default; public bool IsUnlocked(Weapon weapon) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return PlayerData.Data.IsUnlocked((PlayerId)0, weapon); } public bool IsUnlocked(Charm charm) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return PlayerData.Data.IsUnlocked((PlayerId)0, charm); } public bool IsUnlocked(Super super) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return PlayerData.Data.IsUnlocked((PlayerId)0, super); } public void Gift(Weapon weapon) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Invalid comparison between Unknown and I4 //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Invalid comparison between Unknown and I4 //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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_0092: Unknown result type (might be due to invalid IL or missing references) if (!PlayerData.Data.IsUnlocked((PlayerId)0, weapon)) { PlayerData.Data.Gift((PlayerId)0, weapon); } if (!PlayerData.Data.IsUnlocked((PlayerId)1, weapon)) { PlayerData.Data.Gift((PlayerId)1, weapon); } PlayerLoadout playerLoadout = PlayerData.Data.Loadouts.GetPlayerLoadout((PlayerId)0); PlayerLoadout playerLoadout2 = PlayerData.Data.Loadouts.GetPlayerLoadout((PlayerId)1); if ((int)playerLoadout.primaryWeapon == int.MaxValue) { playerLoadout.primaryWeapon = weapon; } if ((int)playerLoadout2.primaryWeapon == int.MaxValue) { playerLoadout2.primaryWeapon = weapon; } } public void Gift(Charm charm) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (!PlayerData.Data.IsUnlocked((PlayerId)0, charm)) { PlayerData.Data.Gift((PlayerId)0, charm); } if (!PlayerData.Data.IsUnlocked((PlayerId)1, charm)) { PlayerData.Data.Gift((PlayerId)1, charm); } } public void Gift(Super super) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (!PlayerData.Data.IsUnlocked((PlayerId)0, super)) { PlayerData.Data.Gift((PlayerId)0, super); } if (!PlayerData.Data.IsUnlocked((PlayerId)1, super)) { PlayerData.Data.Gift((PlayerId)1, super); } } public void AddCoins(int count) { PlayerData.Data.AddCurrency((PlayerId)0, count); PlayerData.Data.AddCurrency((PlayerId)1, count); } public int GetCoins() { return PlayerData.Data.GetCurrency((PlayerId)0); } public void DoPlaneSecondaryEquipTrigger() { PlayerData.Data.Loadouts.GetPlayerLoadout((PlayerId)0).HasEquippedSecondarySHMUPWeapon = true; PlayerData.Data.Loadouts.GetPlayerLoadout((PlayerId)1).HasEquippedSecondarySHMUPWeapon = true; } } } namespace CupheadArchipelago.Hooks { internal class AbstractPauseGUIHook { [HarmonyPatch(typeof(AbstractPauseGUI), "UpdateInput")] internal static class UpdateInput { private static bool Prefix(AbstractPauseGUI __instance) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 Paused = (int)__instance.state == 1; return true; } private static IEnumerable Transpiler(IEnumerable instructions) { //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown List list = new List(instructions); bool flag = false; bool flag2 = false; MethodInfo getMethod = typeof(AbstractPauseGUI).GetProperty("CanPause", BindingFlags.Instance | BindingFlags.NonPublic).GetGetMethod(nonPublic: true); MethodInfo method = typeof(UpdateInput).GetMethod("WriteCanPause", BindingFlags.Static | BindingFlags.NonPublic); if (flag2) { Dbg.LogCodeInstructions(list); } for (int i = 0; i < list.Count - 2; i++) { if (list[i].opcode == OpCodes.Ldarg_0 && list[i + 1].opcode == OpCodes.Callvirt && (object)(MethodInfo)list[i + 1].operand == getMethod && list[i + 2].opcode == OpCodes.Brtrue) { list.Insert(i + 2, new CodeInstruction(OpCodes.Call, (object)method)); flag = true; break; } } if (!flag) { throw new Exception("UpdateInput: Patch Failed!"); } if (flag2) { Logging.Log("---"); Dbg.LogCodeInstructions(list); } return list; } private static bool WriteCanPause(bool write) { CanPause = write; return write; } } internal static bool CanPause { get; private set; } internal static bool Paused { get; private set; } internal static void Hook() { Harmony.CreateAndPatchAll(typeof(UpdateInput), (string)null); } } internal class CupheadHook { [HarmonyPatch(typeof(Cuphead), "Awake")] internal static class Awake { private static void Postfix() { APMain.Create(); } } internal static void Hook() { Harmony.CreateAndPatchAll(typeof(Awake), (string)null); } } internal class Dbg { internal static bool DbgT(int num) { Logging.Log($"T:{num}"); return true; } internal static bool C(bool cond) { Logging.Log($"C:{cond}"); return cond; } internal static void LogCodeInstructions(IEnumerable codes) { foreach (CodeInstruction code in codes) { Logging.Log($"{code.opcode}: {code.operand}"); } } internal static void LogCollection(string name, IEnumerable collection) { Logging.Log(name + ":"); Logging.Log(" " + Aux.CollectionToString(collection)); } internal static void LogCollectionDiff(string name, IEnumerable og, IEnumerable nw) { Logging.Log(name + ":"); if (nw != null) { Logging.Log(" Orig: " + Aux.CollectionToString(og)); Logging.Log(" New: " + Aux.CollectionToString(nw)); } else { Logging.Log(" " + Aux.CollectionToString(og)); } } } internal class DLCManagerHook { [HarmonyPatch(typeof(DLCManager), "DLCEnabled")] internal static class DLCEnabled { private static void Postfix(ref bool __result) { if (disableDLC) { __result = false; } } } [HarmonyPatch(typeof(DLCManager), "CheckInstallationStatusChanged")] internal static class CheckInstallationStatusChanged { private static bool Prefix() { return !disableDLC; } } private static bool disableDLC; internal static void Hook() { Harmony.CreateAndPatchAll(typeof(DLCEnabled), (string)null); Harmony.CreateAndPatchAll(typeof(CheckInstallationStatusChanged), (string)null); } internal static void Reset() { disableDLC = false; } internal static void DisableDLC() { disableDLC = true; } internal static bool DLCDisabled() { return disableDLC; } } public class Main { public static void HookMain() { StartScreenHook.Hook(); MitigationMain.Hook(); RuntimeSceneAssetDatabaseHook.Hook(); AssetMain.Hook(); SceneLoaderHook.Hook(); CupheadHook.Hook(); DLCManagerHook.Hook(); PlayerDataHook.Hook(); AbstractPauseGUIHook.Hook(); WinScreenHook.Hook(); AudioMain.Hook(); MenuMain.Hook(); PlayerMain.Hook(); MapMain.Hook(); LevelMain.Hook(); ShopMain.Hook(); CutsceneMain.Hook(); } public static void HookSaveKeyUpdater(string saveKeyName) { SaveKeyUpdaterHook.SetSaveKeyBaseName(saveKeyName); SaveKeyUpdaterHook.Hook(); } } internal class PlayerDataHook { [HarmonyPatch(typeof(PlayerData), "ClearSlot")] internal static class ClearSlot { private static readonly FieldInfo _fi_inventories = typeof(PlayerData).GetField("inventories", BindingFlags.Instance | BindingFlags.NonPublic); private static bool Prefix(int slot, PlayerData[] ____saveFiles) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Invalid comparison between Unknown and I4 //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) if (_APMode) { PlayerData val = ____saveFiles[slot]; PlayerInventories val2 = (PlayerInventories)_fi_inventories.GetValue(val); Logging.Log($"Start Weapon: {APSettings.StartWeapon}"); Weapon startWeapon = APSettings.StartWeapon; if ((int)startWeapon != int.MaxValue) { val2.playerOne._weapons = new List(1) { startWeapon }; val2.playerTwo._weapons = new List(1) { startWeapon }; } else { val2.playerOne._weapons = new List(); val2.playerTwo._weapons = new List(); } val.Loadouts.playerOne.primaryWeapon = startWeapon; val.Loadouts.playerTwo.primaryWeapon = startWeapon; if (APSettings.UseDLC && APSettings.DLCChaliceMode == DlcChaliceModes.Start) { val2.playerOne._charms = new List(1) { (Charm)1522153206 }; val2.playerTwo._charms = new List(1) { (Charm)1522153206 }; } return false; } return true; } } [HarmonyPatch(typeof(PlayerData), "OnLoaded")] internal static class OnLoaded { private static void Postfix() { Logging.Log("Loading..."); APData.LoadData(); } } [HarmonyPatch(typeof(PlayerData), "Save")] internal static class Save { private static bool Prefix(int fileIndex) { Logging.Log($"Save {fileIndex}"); return true; } private static void Postfix(int fileIndex) { if (APData.IsSlotEnabled(fileIndex) || !PlayerData.inGame) { Logging.Log($"Saving APData to slot {fileIndex}..."); APData.Save(fileIndex); } } } [HarmonyPatch(typeof(PlayerData), "AddCurrency")] internal static class AddCurrency { private static bool Prefix() { Logging.Log("AddCurrency"); return true; } } [HarmonyPatch(typeof(PlayerData), "ApplyLevelCoins")] internal static class ApplyLevelCoins { private static bool Prefix(PlayerCoinManager ___coinManager, ref PlayerCoinManager ___levelCoinManager) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown if (APData.IsCurrentSlotEnabled()) { Logging.Log("[ApplyLevelCoins] Disabled."); ___levelCoinManager = new PlayerCoinManager(); return false; } return true; } } [HarmonyPatch(typeof(PlayerData), "NumWeapons")] internal static class NumWeapons { private static void Postfix(PlayerId player, PlayerInventories ___inventories) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) Logging.Log(Aux.CollectionToString(___inventories.GetPlayer(player)._weapons)); } } [HarmonyPatch(typeof(PlayerData), "TryActivateDjimmi")] internal static class TryActivateDjimmi { private static bool Prefix() { return !APData.IsCurrentSlotEnabled() || APSettings.AllowGameDjimmi; } } [HarmonyPatch(typeof(PlayerData), "Gift", new Type[] { typeof(PlayerId), typeof(Weapon) })] [HarmonyPatch(typeof(PlayerData), "Gift", new Type[] { typeof(PlayerId), typeof(Charm) })] [HarmonyPatch(typeof(PlayerData), "Gift", new Type[] { typeof(PlayerId), typeof(Super) })] internal static class Gift { private static bool Prefix(object value) { Logging.Log($"Gifting {value}"); return true; } } private static class PlayerInventoryHook { [HarmonyPatch(/*Could not decode attribute arguments.*/)] internal static class PlayerInventory { private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator il) { //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Expected O, but got Unknown //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Expected O, but got Unknown //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Expected O, but got Unknown //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Expected O, but got Unknown //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Expected O, but got Unknown List list = new List(instructions); bool flag = false; bool flag2 = false; FieldInfo field = typeof(PlayerInventory).GetField("_weapons", BindingFlags.Instance | BindingFlags.Public); MethodInfo method = typeof(PlayerInventory).GetMethod("Add", BindingFlags.Instance | BindingFlags.Public); Label label = il.DefineLabel(); if (flag) { Dbg.LogCodeInstructions(list); } for (int i = 0; i < list.Count - 3; i++) { if (list[i].opcode == OpCodes.Ldarg_0 && list[i + 1].opcode == OpCodes.Ldfld && (object)(FieldInfo)list[i + 1].operand == field && list[i + 2].opcode == OpCodes.Ldc_I4 && list[i + 3].opcode == OpCodes.Callvirt && (object)(MethodInfo)list[i + 3].operand == method) { list[i].labels.Add(label); CodeInstruction[] collection = (CodeInstruction[])(object)new CodeInstruction[7] { CodeInstruction.Call((Expression)(() => IsAPMode())), new CodeInstruction(OpCodes.Brfalse, (object)label), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)field), CodeInstruction.Call((Expression)(() => GetAPStartWeapon())), new CodeInstruction(OpCodes.Callvirt, (object)method), new CodeInstruction(OpCodes.Ret, (object)null) }; list.InsertRange(i, collection); flag2 = true; break; } } if (!flag2) { throw new Exception("PlayerInventory: Patch Failed!"); } if (flag) { Logging.Log("---"); Dbg.LogCodeInstructions(list); } return list; } private static bool IsAPMode() { return _APMode; } private static Weapon GetAPStartWeapon() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return APSettings.StartWeapon; } private static void AddAPWeapon(List weapons) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) Weapon startWeapon = APSettings.StartWeapon; weapons.Add(startWeapon); } } internal static void Hook() { Harmony.CreateAndPatchAll(typeof(PlayerInventory), (string)null); } } private static class PlayerCoinManagerHook { [HarmonyPatch(typeof(PlayerCoinManager), "GetCoinCollected", new Type[] { typeof(string) })] internal static class GetCoinCollected { private static MethodInfo _mi_GetCoin__str = typeof(PlayerCoinManager).GetMethod("GetCoin", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null); private static IEnumerable Transpiler(IEnumerable instructions) { List list = new List(instructions); bool flag = false; bool flag2 = false; if (flag2) { Dbg.LogCodeInstructions(list); } for (int i = 0; i < list.Count - 1; i++) { if (list[i].opcode == OpCodes.Call && (object)(MethodInfo)list[i].operand == _mi_GetCoin__str) { list[i] = CodeInstruction.Call(typeof(GetCoinCollected), "APGetCoinCollected", (Type[])null, (Type[])null); list.RemoveAt(i + 1); flag = true; break; } } if (!flag) { throw new Exception("GetCoinCollected: Patch Failed!"); } if (flag2) { Logging.Log("---"); Dbg.LogCodeInstructions(list); } return list; } private static bool APGetCoinCollected(PlayerCoinManager instance, string coinID) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) return ((PlayerCoinProperties)_mi_GetCoin__str.Invoke(instance, new object[1] { coinID })).collected; } } internal static void Hook() { Harmony.CreateAndPatchAll(typeof(GetCoinCollected), (string)null); } } private static bool _APMode; internal static void Hook() { Harmony.CreateAndPatchAll(typeof(ClearSlot), (string)null); Harmony.CreateAndPatchAll(typeof(OnLoaded), (string)null); Harmony.CreateAndPatchAll(typeof(Save), (string)null); Harmony.CreateAndPatchAll(typeof(ApplyLevelCoins), (string)null); Harmony.CreateAndPatchAll(typeof(TryActivateDjimmi), (string)null); Harmony.CreateAndPatchAll(typeof(Gift), (string)null); } internal static void APSanitizeSlot(int slot) { _APMode = true; PlayerData.ClearSlot(slot); _APMode = false; } } internal class RuntimeSceneAssetDatabaseHook { [HarmonyPatch(/*Could not decode attribute arguments.*/)] internal static class persistentAssets { private static void Postfix(HashSet __result) { Logging.Log("Persistent Assets:"); Logging.Log(" " + Aux.CollectionToString(__result)); } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] internal static class persistentAssetsDLC { private static void Postfix(HashSet __result) { Logging.Log("Persistent DLC Assets:"); Logging.Log(" " + Aux.CollectionToString(__result)); } } internal static void Hook() { Harmony.CreateAndPatchAll(typeof(persistentAssets), (string)null); Harmony.CreateAndPatchAll(typeof(persistentAssetsDLC), (string)null); } } internal class SaveKeyUpdaterHook { [HarmonyPatch(typeof(PlayerData), "OnCloudStorageInitialized")] internal static class OnCloudStorageInitialized { private static IEnumerable Transpiler(IEnumerable instructions) { return DigestKeysInstructions(instructions); } } [HarmonyPatch(typeof(PlayerData), "OnLoaded")] internal static class OnLoaded { private static IEnumerable Transpiler(IEnumerable instructions) { return DigestKeysInstructions(instructions); } } [HarmonyPatch(typeof(PlayerData), "Save")] internal static class Save { private static IEnumerable Transpiler(IEnumerable instructions) { return DigestKeysInstructions(instructions); } } [HarmonyPatch(typeof(PlayerData), "SaveAll")] internal static class SaveAll { private static IEnumerable Transpiler(IEnumerable instructions) { return DigestKeysInstructions(instructions); } } private static string saveKeyBaseName; private static string[] saveKeyNames; private static bool _nameLock; private static FieldInfo _fi_SAVE_FILE_KEYS; static SaveKeyUpdaterHook() { saveKeyBaseName = "cuphead_player_data_v1_ap_slot_"; _nameLock = false; _fi_SAVE_FILE_KEYS = typeof(PlayerData).GetField("SAVE_FILE_KEYS", BindingFlags.Static | BindingFlags.NonPublic); } internal static void SetSaveKeyBaseName(string name) { if (!_nameLock) { saveKeyBaseName = name; } else { Logging.Log("Cannot Set SaveKeyBaseName after Hook", (LogLevel)4); } } internal static void Hook() { _nameLock = true; saveKeyNames = new string[3] { saveKeyBaseName + 0, saveKeyBaseName + 1, saveKeyBaseName + 2 }; Harmony.CreateAndPatchAll(typeof(OnCloudStorageInitialized), (string)null); Harmony.CreateAndPatchAll(typeof(OnLoaded), (string)null); Harmony.CreateAndPatchAll(typeof(Save), (string)null); Harmony.CreateAndPatchAll(typeof(SaveAll), (string)null); } private static List DigestKeysInstructions(IEnumerable instructions) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Expected O, but got Unknown List list = new List(instructions); CodeInstruction[] collection = (CodeInstruction[])(object)new CodeInstruction[14] { new CodeInstruction(OpCodes.Ldc_I4_3, (object)null), new CodeInstruction(OpCodes.Newarr, (object)typeof(string)), new CodeInstruction(OpCodes.Dup, (object)null), new CodeInstruction(OpCodes.Ldc_I4_0, (object)null), new CodeInstruction(OpCodes.Ldstr, (object)saveKeyNames[0]), new CodeInstruction(OpCodes.Stelem_Ref, (object)null), new CodeInstruction(OpCodes.Dup, (object)null), new CodeInstruction(OpCodes.Ldc_I4_1, (object)null), new CodeInstruction(OpCodes.Ldstr, (object)saveKeyNames[1]), new CodeInstruction(OpCodes.Stelem_Ref, (object)null), new CodeInstruction(OpCodes.Dup, (object)null), new CodeInstruction(OpCodes.Ldc_I4_2, (object)null), new CodeInstruction(OpCodes.Ldstr, (object)saveKeyNames[2]), new CodeInstruction(OpCodes.Stelem_Ref, (object)null) }; for (int i = 0; i < list.Count - 1; i++) { if (list[i].opcode == OpCodes.Ldsfld && (object)(FieldInfo)list[i].operand == _fi_SAVE_FILE_KEYS && list[i + 1].opcode != OpCodes.Ldlen) { list.RemoveAt(i); list.InsertRange(i, collection); } } return list; } } internal class SceneLoaderHook { [HarmonyPatch(typeof(SceneLoader), "LoadScene", new Type[] { typeof(Scenes), typeof(Transition), typeof(Transition), typeof(Icon), typeof(Context) })] internal static class LoadScene { private static bool Prefix(Scenes scene) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 if ((int)scene == 1) { APClient.CloseArchipelagoSession(reset: false); DLCManagerHook.Reset(); } return true; } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] internal static class load_cr { private static readonly HashSet dlcAssets = new HashSet { "TitleCards_WDLC" }; private static readonly HashSet titleCardAssets = new HashSet { "TitleCards_W1", "TitleCards_W2", "TitleCards_W3", "TitleCards_WDLC" }; private static readonly Dictionary> sceneAddAtlases = new Dictionary> { { ((object)(Scenes)3/*cast due to .constrained prefix*/).ToString(), titleCardAssets }, { ((object)(Scenes)4/*cast due to .constrained prefix*/).ToString(), titleCardAssets }, { ((object)(Scenes)5/*cast due to .constrained prefix*/).ToString(), titleCardAssets }, { ((object)(Scenes)68/*cast due to .constrained prefix*/).ToString(), titleCardAssets } }; private static readonly Dictionary> sceneAddMusic = new Dictionary>(); private static IEnumerable Transpiler(IEnumerable instructions) { //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Expected O, but got Unknown //IL_03e6: Unknown result type (might be due to invalid IL or missing references) //IL_03f0: Expected O, but got Unknown //IL_03fd: Unknown result type (might be due to invalid IL or missing references) //IL_0407: Expected O, but got Unknown //IL_04e6: Unknown result type (might be due to invalid IL or missing references) //IL_04f0: Expected O, but got Unknown //IL_04fd: Unknown result type (might be due to invalid IL or missing references) //IL_0507: Expected O, but got Unknown //IL_06a1: Unknown result type (might be due to invalid IL or missing references) //IL_06ab: Expected O, but got Unknown //IL_06b8: Unknown result type (might be due to invalid IL or missing references) //IL_06c2: Expected O, but got Unknown List list = new List(instructions); int num = 0; int num2 = 15; bool flag = false; MethodInfo method = typeof(SceneLoader).GetMethod("load_cr", BindingFlags.Instance | BindingFlags.NonPublic); Type enumeratorType = Reflection.GetEnumeratorType(method); FieldInfo field = enumeratorType.GetField("$current", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field2 = enumeratorType.GetField("$disposing", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field3 = enumeratorType.GetField("$PC", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field4 = enumeratorType.GetField("__0", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field5 = enumeratorType.GetField("__0", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field6 = typeof(SceneLoader).GetField("previousSceneName", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo getMethod = typeof(SceneLoader).GetProperty("SceneName", BindingFlags.Static | BindingFlags.Public).GetGetMethod(); MethodInfo method2 = typeof(AssetLoader).GetMethod("GetPreloadAssetNames", BindingFlags.Static | BindingFlags.Public); MethodInfo method3 = typeof(AssetLoader).GetMethod("GetPreloadAssetNames", BindingFlags.Static | BindingFlags.Public); MethodInfo method4 = typeof(load_cr).GetMethod("UnloadResourceAssets", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo method5 = typeof(load_cr).GetMethod("GetPreloadAtlases", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo method6 = typeof(load_cr).GetMethod("GetPreloadMusic", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo method7 = typeof(load_cr).GetMethod("LoadResourceAssets", BindingFlags.Static | BindingFlags.NonPublic); if (flag) { Dbg.LogCodeInstructions(list); } for (int i = 0; i < list.Count - 9; i++) { if ((num & 1) == 0 && i < list.Count - 11 && list[i].opcode == OpCodes.Call && (object)(MethodInfo)list[i].operand == getMethod && list[i + 1].opcode == OpCodes.Ldsfld && (object)(FieldInfo)list[i + 1].operand == field6 && list[i + 2].opcode == OpCodes.Call && list[i + 3].opcode == OpCodes.Brfalse && list[i + 4].opcode == OpCodes.Call && (object)(MethodInfo)list[i + 4].operand == getMethod && list[i + 5].opcode == OpCodes.Ldc_I4_2 && list[i + 8].opcode == OpCodes.Constrained && (object)(Type)list[i + 8].operand == typeof(Scenes) && list[i + 10].opcode == OpCodes.Call && list[i + 11].opcode == OpCodes.Brfalse) { list.Insert(i + 12, new CodeInstruction(OpCodes.Call, (object)method4)); i += 12; num |= 1; } else if ((num & 2) == 0 && list[i].opcode == OpCodes.Ldarg_0 && list[i + 1].opcode == OpCodes.Call && (object)(MethodInfo)list[i + 1].operand == getMethod && list[i + 2].opcode == OpCodes.Call && (object)(MethodInfo)list[i + 2].operand == method2 && list[i + 3].opcode == OpCodes.Stfld && list[i + 3].operand == field4) { list.Insert(i + 3, new CodeInstruction(OpCodes.Call, (object)method5)); list.Insert(i + 1, new CodeInstruction(OpCodes.Call, (object)getMethod)); i += 4; num |= 2; } else if ((num & 4) == 0 && list[i].opcode == OpCodes.Ldarg_0 && list[i + 1].opcode == OpCodes.Call && (object)(MethodInfo)list[i + 1].operand == getMethod && list[i + 2].opcode == OpCodes.Call && (object)(MethodInfo)list[i + 2].operand == method3 && list[i + 3].opcode == OpCodes.Stfld && list[i + 3].operand == field5) { list.Insert(i + 3, new CodeInstruction(OpCodes.Call, (object)method6)); list.Insert(i + 1, new CodeInstruction(OpCodes.Call, (object)getMethod)); i += 4; num |= 4; } else if ((num & 8) == 0 && list[i].opcode == OpCodes.Ldarg_0 && list[i + 1].opcode == OpCodes.Ldnull && list[i + 2].opcode == OpCodes.Stfld && (object)(FieldInfo)list[i + 2].operand == field && list[i + 3].opcode == OpCodes.Ldarg_0 && list[i + 4].opcode == OpCodes.Ldfld && (object)(FieldInfo)list[i + 4].operand == field2 && list[i + 5].opcode == OpCodes.Brtrue && list[i + 6].opcode == OpCodes.Ldarg_0 && list[i + 7].opcode == OpCodes.Ldc_I4_5 && list[i + 8].opcode == OpCodes.Stfld && (object)(FieldInfo)list[i + 8].operand == field3 && list[i + 9].opcode == OpCodes.Br) { list[i + 1] = new CodeInstruction(OpCodes.Call, (object)method7); list.Insert(i + 1, new CodeInstruction(OpCodes.Call, (object)getMethod)); num |= 8; } if (num >= num2) { break; } } if (num != num2) { throw new Exception(string.Format("{0}: Patch Failed! {1}", "load_cr", num)); } if (flag) { Dbg.LogCodeInstructions(list); } return list; } private static void UnloadResourceAssets() { Logging.LogDebug("Unloading resource assets..."); AssetBundleMngr.UnloadAssetBundles(); AssetMngr.UnloadAllAssets(); } private static string[] GetPreloadAtlases(string sceneName, string[] preloadAtlases) { Logging.Log("Scene name: " + sceneName); bool flag = false; HashSet hashSet = new HashSet(); foreach (string item in preloadAtlases) { hashSet.Add(item); } HashSet hashSet2 = hashSet; if (sceneAddAtlases.ContainsKey(sceneName)) { hashSet2.UnionWith(sceneAddAtlases[sceneName]); if (!DLCManager.DLCEnabled()) { hashSet2.ExceptWith(dlcAssets); } flag = true; } Dbg.LogCollectionDiff("Scene Atlases", preloadAtlases, flag ? hashSet2 : null); return hashSet2.ToArray(); } private static string[] GetPreloadMusic(string sceneName, string[] preloadMusic) { bool flag = false; HashSet hashSet = new HashSet(); foreach (string item in preloadMusic) { hashSet.Add(item); } HashSet hashSet2 = hashSet; if (sceneAddMusic.ContainsKey(sceneName)) { hashSet2.UnionWith(sceneAddMusic[sceneName]); flag = true; } Dbg.LogCollectionDiff("Scene Audio", preloadMusic, flag ? hashSet2 : null); return hashSet2.ToArray(); } private static IEnumerator LoadResourceAssets(string sceneName) { if (SceneAssetMap.IsSceneRegistered(sceneName)) { Logging.LogDebug("Loading resource assets..."); Dbg.LogCollection("Resource Assets", SceneAssetMap.GetSceneAssets(sceneName)); yield return AssetMngr.LoadSceneAssetsAsync(sceneName); } yield return null; } private unsafe static bool IsStringSceneName(string str, Scenes scene) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) Scenes val = scene; return str == ((object)(*(Scenes*)(&val))/*cast due to .constrained prefix*/).ToString(); } private static bool IsAnyScene(string name, Scenes[] scenes) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < scenes.Length; i++) { if (name == ((object)scenes[i]/*cast due to .constrained prefix*/).ToString()) { return true; } } return false; } } internal static void Hook() { Harmony.CreateAndPatchAll(typeof(LoadScene), (string)null); Harmony.CreateAndPatchAll(typeof(load_cr), (string)null); } } internal class StartScreenHook { [HarmonyPatch(typeof(StartScreen), "Awake")] internal static class Awake { private static bool Prefix() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown if (Plugin.State < 0) { Logging.LogFatal("Errors occured. Aborting game to prevent damage!"); CreateModErrorText(); input = new AnyPlayerInput(false); return false; } if (MConf.IsTesting()) { Logging.Log("Running in Test Mode: Running in test environment instead of game."); TestMngr.Init(); input = new AnyPlayerInput(false); return false; } return true; } private static void Postfix() { APClient.CloseArchipelagoSession(); } } [HarmonyPatch(typeof(StartScreen), "Start")] internal static class Start { private static bool Prefix() { return Plugin.State >= 0 && !MConf.IsTesting(); } private static void Postfix() { Logging.Log("DLC: " + (DLCManager.DLCEnabled() ? "Enabled" : "Disabled")); } } [HarmonyPatch(typeof(StartScreen), "Update")] internal static class Update { private static readonly CupheadButton[] DISMISS_BUTTONS = (CupheadButton[])(object)new CupheadButton[3] { (CupheadButton)13, (CupheadButton)14, (CupheadButton)8 }; private const float TEST_DISMISS_TIME = 3f; private static float dismissTime = 0f; private static bool Prefix() { if (Plugin.State < 0) { if (GetAnyButtonDown(DISMISS_BUTTONS)) { Application.Quit(); } return false; } if (MConf.IsTesting()) { AnyPlayerInput input = StartScreenHook.input; if (input != null && input.GetButton((CupheadButton)14)) { if (dismissTime < 3f) { dismissTime += Time.deltaTime; } else { Application.Quit(); } } else { dismissTime = 0f; } return false; } return true; } private static bool GetAnyButtonDown(CupheadButton[] buttons) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) foreach (CupheadButton val in buttons) { AnyPlayerInput input = StartScreenHook.input; if (input != null && input.GetButtonDown(val)) { return true; } } return false; } } private static AnyPlayerInput input; internal static void Hook() { Harmony.CreateAndPatchAll(typeof(Start), (string)null); Harmony.CreateAndPatchAll(typeof(Awake), (string)null); Harmony.CreateAndPatchAll(typeof(Update), (string)null); } private static void CreateModErrorText() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("ErrCanvas"); val.AddComponent().renderMode = (RenderMode)0; val.AddComponent(); val.AddComponent(); GameObject val2 = new GameObject("ModErrorText"); val2.transform.SetParent(val.transform, false); val2.SetActive(true); RectTransform val3 = val2.AddComponent(); ((Transform)val3).localPosition = new Vector3(0f, 0f, 0f); val3.sizeDelta = new Vector2(800f, 400f); Text val4 = val2.AddComponent(); val4.alignment = (TextAnchor)4; val4.font = FontLoader.GetFont((FontType)5); ((Graphic)val4).color = Color.red; val4.fontSize = 32; val4.text = $"CupheadArchipelago\nFATAL ERROR (code {Plugin.State})\n{Plugin.StateMessage}\nCheck Log"; val2.layer = 5; } } internal class WinScreenHook { [HarmonyPatch(/*Could not decode attribute arguments.*/)] internal static class main_cr { private static IEnumerable Transpiler(IEnumerable instructions) { //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Expected O, but got Unknown List list = new List(instructions); int num = 0; bool flag = false; MethodInfo getMethod = typeof(Level).GetProperty("PreviousLevel", BindingFlags.Static | BindingFlags.Public).GetGetMethod(); MethodInfo method = typeof(main_cr).GetMethod("APLevelTest", BindingFlags.Static | BindingFlags.NonPublic); if (flag) { Dbg.LogCodeInstructions(list); } for (int i = 0; i < list.Count - 2; i++) { if (list[i].opcode == OpCodes.Call && (object)(MethodInfo)list[i].operand == getMethod && list[i + 1].opcode == OpCodes.Ldc_I4 && list[i + 2].opcode == OpCodes.Bne_Un) { List