Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Rando v0.1.3
Silksong.Rando.dll
Decompiled 4 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Xml.Linq; using BepInEx; using BepInEx.Logging; using GlobalEnums; using GlobalSettings; using HarmonyLib; using HutongGames.PlayMaker; using HutongGames.PlayMaker.Actions; using Microsoft.CodeAnalysis; using MonoMod.RuntimeDetour; using Newtonsoft.Json; using PrepatcherPlugin; using QuestPlaymakerActions; using Silksong.DataManager; using Silksong.FsmUtil; using Silksong.Rando.Data; using Silksong.Rando.Data.Extractors; using Silksong.Rando.Locations; using Silksong.Rando.Logic; using Silksong.Rando.Map; using SkongGamemodes; using TeamCherry.Localization; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Networking; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.ResourceManagement.ResourceProviders; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Silksong.Rando")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.3.0")] [assembly: AssemblyInformationalVersion("0.1.3+68feacc47410b7d16861dc9f72980cbd34406e60")] [assembly: AssemblyProduct("Silksong.Rando")] [assembly: AssemblyTitle("Rando")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/timothymarriott/Silksong-Rando")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.3.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } [HarmonyPatch(typeof(Language), "Get", new Type[] { typeof(string), typeof(string) })] internal class Language_Get_Patch { public static bool Prefix(ref string __result, string key, string sheetTitle) { if (sheetTitle == "Rando") { __result = key; return false; } return true; } } [HarmonyPatch(typeof(Language), "Has", new Type[] { typeof(string), typeof(string) })] internal class Language_Has_Patch { public static bool Prefix(ref bool __result, string key, string sheetTitle) { if (sheetTitle == "Rando") { __result = true; return false; } return true; } } namespace BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace Generated { public static class BuildConstants { public const string Version = "0.1.3"; public const string GitHubRepo = "timothymarriott/Silksong-Rando"; } } namespace Silksong.Rando { public static class AssemblyExtensions { public static Sprite LoadEmbeddedSprite(this Assembly asm, string path, float pixelsPerUnit = 64f) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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) using Stream stream = asm.GetManifestResourceStream(path); byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); Texture2D val = new Texture2D(2, 2); ImageConversion.LoadImage(val, array, false); return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), Vector2.one * 0.5f, pixelsPerUnit); } public static string LoadEmbeddedText(this Assembly asm, string path) { using Stream stream = asm.GetManifestResourceStream(path); if (stream == null) { throw new InvalidOperationException("Resource not found: " + path); } using StreamReader streamReader = new StreamReader(stream); return streamReader.ReadToEnd(); } } public abstract class DataBuilder<TResult> { public TResult result; public bool IsBuilt { get; protected set; } } public class ModResources : MonoBehaviour { public static ManualLogSource Logger; private static Dictionary<string, Sprite> Images = new Dictionary<string, Sprite>(); private static Dictionary<string, string> Data = new Dictionary<string, string>(); public Font trajanBold; public Font trajanNormal; public Font arial; public static Sprite LoadSprite(string id, float pixelsPerUnit = 64f) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (!Images.TryGetValue(id, out Sprite value)) { return Sprite.Create(Texture2D.whiteTexture, new Rect(0f, 0f, 4f, 4f), Vector2.one * 0.5f, pixelsPerUnit); } return value; } public static string LoadData(string id) { if (!Data.TryGetValue(id, out string value)) { throw new KeyNotFoundException(id); } return value; } public static Stream GetResourceStream(string id) { string[] manifestResourceNames = Assembly.GetExecutingAssembly().GetManifestResourceNames(); foreach (string text in manifestResourceNames) { if (text.EndsWith(".json") && text.StartsWith("Silksong.Rando.Resources.") && text.Substring("Silksong.Rando.Resources.".Length).Replace(".json", "").Replace(".png", "") .Replace('.', '/') == id) { return Assembly.GetExecutingAssembly().GetManifestResourceStream(text); } } throw new FileNotFoundException(); } public static AssetBundle LoadAssetBundle(string id) { string[] manifestResourceNames = Assembly.GetExecutingAssembly().GetManifestResourceNames(); foreach (string text in manifestResourceNames) { if (text.EndsWith(".bundle") && text.StartsWith("Silksong.Rando.Resources.") && text.Substring("Silksong.Rando.Resources.".Length).Replace(".bundle", "").Replace('.', '/') == id) { Stream manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(text); using MemoryStream memoryStream = new MemoryStream(); manifestResourceStream.CopyTo(memoryStream); return AssetBundle.LoadFromMemory(memoryStream.ToArray()); } } throw new FileNotFoundException(); } public static ModResources LoadResources(ManualLogSource logger) { Logger = logger; string[] manifestResourceNames = Assembly.GetExecutingAssembly().GetManifestResourceNames(); foreach (string text in manifestResourceNames) { if (text.EndsWith(".png") && text.StartsWith("Silksong.Rando.Resources.Images.")) { try { string text2 = text.Substring("Silksong.Rando.Resources.Images.".Length).Replace(".png", "").Replace('.', '/'); Images.Add(text2, Assembly.GetExecutingAssembly().LoadEmbeddedSprite(text)); Logger.LogInfo((object)("Loaded image: " + text2)); } catch (Exception ex) { Logger.LogInfo((object)("Failed to load image: " + text + "\n" + ex.ToString())); } } if (text.EndsWith(".json") && text.StartsWith("Silksong.Rando.Resources.")) { string key = text.Substring("Silksong.Rando.Resources.".Length).Replace(".json", "").Replace('.', '/'); Data.Add(key, Assembly.GetExecutingAssembly().LoadEmbeddedText(text)); } } return ((Component)RandoPlugin.instance).gameObject.AddComponent<ModResources>(); } private void Update() { if (!((Object)(object)trajanBold == (Object)null) && !((Object)(object)trajanNormal == (Object)null) && !((Object)(object)arial == (Object)null)) { return; } Font[] array = Resources.FindObjectsOfTypeAll<Font>(); foreach (Font val in array) { if ((Object)(object)val != (Object)null && ((Object)val).name == "TrajanPro-Bold") { trajanBold = val; } if ((Object)(object)val != (Object)null && ((Object)val).name == "TrajanPro-Regular") { trajanNormal = val; } if ((Object)(object)val != (Object)null && ((Object)val).name == "Perpetua") { arial = val; } } } public static Font GetFont() { return RandoPlugin.instance.resources.arial; } public static GUIStyle GetLabelStyle() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //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) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_002b: Expected O, but got Unknown return new GUIStyle { fontSize = 30, fontStyle = (FontStyle)0, normal = new GUIStyleState { textColor = Color.white } }; } } public class PlayerDataDelegateTestGroup : PlayerDataTest { public delegate bool IsFulfilledCallback(PlayerData data); private static bool initialised; private static Hook? isFulfilledHook; private readonly IsFulfilledCallback callback; public PlayerDataDelegateTestGroup(IsFulfilledCallback callback) { this.callback = callback; if (!initialised) { initialised = true; HookIsFulfilled(); } } private static void HookIsFulfilled() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown isFulfilledHook = new Hook((MethodBase)typeof(PlayerDataTest).GetProperty("IsFulfilled", BindingFlags.Instance | BindingFlags.NonPublic).GetGetMethod(), (Delegate)new Func<Func<PlayerDataTest, bool>, PlayerDataTest, bool>(IsFulfilledDetour)); } private static bool IsFulfilledDetour(Func<PlayerDataTest, bool> orig, PlayerDataTest self) { if (self is PlayerDataDelegateTestGroup playerDataDelegateTestGroup) { return playerDataDelegateTestGroup.callback(RandoPlugin.GM.playerData); } return orig(self); } } public class RandoItem : CollectableItemBasic { public delegate void OnCollectedCallback(RandoItem item); public string targetItem; public string check; public SavedItem wrapped; public OnCollectedCallback? CollectCallback; public override void OnCollected() { ((CollectableItemBasic)this).OnCollected(); RandoPlugin.Log.LogInfo((object)("Collected " + targetItem)); SaveData.Instance.CollectedChecks.Add(check); if ((Object)(object)wrapped != (Object)null) { ((CollectableItem)this).Take(1, false); RandoPlugin.Log.LogInfo((object)("Giving wrapped item: " + ((Object)wrapped).name + " at " + check + "(" + ((wrapped is RandoItem randoItem) ? randoItem.check : "vanilla wrapped") + ")")); wrapped.Get(false); } else if (CollectCallback != null) { CollectCallback(this); } RandoPlugin.instance.map.Refresh(); } public static RandoItem Wrap(string targetItem, string check, SavedItem template) { RandoItemBuilder randoItemBuilder = RandoItemBuilder.Create(targetItem, check); ((Object)randoItemBuilder.result).name = targetItem + "_wrap"; ((CollectableItemBasic)randoItemBuilder.result).icon = template.GetPopupIcon(); ((CollectableItemBasic)randoItemBuilder.result).tinyIcon = template.GetPopupIcon(); if (template is RandoItem randoItem) { randoItem.check = check; } randoItemBuilder.result.wrapped = template; randoItemBuilder.SetDisplayName(template.GetPopupName()); return randoItemBuilder.Build(); } } public class RandoItemBuilder : DataBuilder<RandoItem> { private static List<RandoItemBuilder> created = new List<RandoItemBuilder>(); public static RandoItemBuilder Create(string targetItem, string check) { RandoItemBuilder randoItemBuilder = new RandoItemBuilder(); randoItemBuilder.result = ScriptableObject.CreateInstance<RandoItem>(); ((Object)randoItemBuilder.result).name = targetItem; randoItemBuilder.result.targetItem = targetItem; ((CollectableItem)randoItemBuilder.result).isHidden = true; randoItemBuilder.result.check = check; randoItemBuilder.Setup(); created.Add(randoItemBuilder); return randoItemBuilder; } private void Setup() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) ((CollectableItemBasic)result).isAlwaysUnlocked = true; ((CollectableItemBasic)result).displayButtonPrompt = false; ((CollectableItem)result).useResponses = (UseResponse[])(object)new UseResponse[1] { new UseResponse { UseType = (UseTypes)0 } }; ((CollectableItemBasic)result).setExtraPlayerDataBools = (PlayerDataBoolOperation[])(object)new PlayerDataBoolOperation[0]; ((CollectableItemBasic)result).setExtraPlayerDataInts = (PlayerDataIntOperation[])(object)new PlayerDataIntOperation[0]; } public RandoItemBuilder SetMaxAmount(int amount) { ((CollectableItem)result).customMaxAmount = amount; return this; } public RandoItemBuilder SetDisplayName(string name) { return SetDisplayName("Rando", name); } public RandoItemBuilder SetDisplayName(string sheet, string key) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) return SetDisplayName(new LocalisedString(sheet, key)); } public RandoItemBuilder SetDisplayName(LocalisedString name) { //IL_0006: 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) ((CollectableItemBasic)result).displayName = name; return this; } public RandoItemBuilder SetDescription(string description) { return SetDescription("Rando", description); } public RandoItemBuilder SetDescription(string sheet, string key) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) return SetDescription(new LocalisedString(sheet, key)); } public RandoItemBuilder SetDescription(LocalisedString description) { //IL_0006: 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) ((CollectableItemBasic)result).description = description; return this; } public RandoItemBuilder SetIcon(Sprite sprite) { //IL_000c: 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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_015d: 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) if ((Object)(object)sprite == (Object)null) { return this; } Rect rect = sprite.rect; int num = (int)((Rect)(ref rect)).width; rect = sprite.rect; int num2 = (int)((Rect)(ref rect)).height; if (num <= 120 && num2 <= 120) { ((CollectableItemBasic)result).icon = sprite; ((CollectableItemBasic)result).tinyIcon = sprite; return this; } float num3 = Mathf.Min(120f / (float)num, 120f / (float)num2); int num4 = Mathf.RoundToInt((float)num * num3); int num5 = Mathf.RoundToInt((float)num2 * num3); Texture2D texture = sprite.texture; Rect rect2 = sprite.rect; Color[] pixels = texture.GetPixels((int)((Rect)(ref rect2)).x, (int)((Rect)(ref rect2)).y, (int)((Rect)(ref rect2)).width, (int)((Rect)(ref rect2)).height); Texture2D val = new Texture2D(num4, num5, texture.format, false); ((Texture)val).filterMode = (FilterMode)1; for (int i = 0; i < num5; i++) { for (int j = 0; j < num4; j++) { float num6 = (float)j / (float)(num4 - 1); float num7 = (float)i / (float)(num5 - 1); int num8 = Mathf.RoundToInt(num6 * (float)(num - 1)); int num9 = Mathf.RoundToInt(num7 * (float)(num2 - 1)); val.SetPixel(j, i, pixels[num9 * num + num8]); } } val.Apply(); Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)num4, (float)num5), new Vector2(0.5f, 0.5f), sprite.pixelsPerUnit); ((CollectableItemBasic)result).icon = val2; ((CollectableItemBasic)result).tinyIcon = val2; return this; } public RandoItemBuilder SetIcon(string icon) { return SetIcon(ModResources.LoadSprite(icon)); } public RandoItemBuilder SetTinyIcon(Sprite sprite) { ((CollectableItemBasic)result).tinyIcon = sprite; return this; } public RandoItemBuilder SetTinyIcon(string icon) { return SetTinyIcon(ModResources.LoadSprite(icon)); } public RandoItemBuilder SetCollectCallback(RandoItem.OnCollectedCallback action) { result.CollectCallback = action; return this; } public RandoItem Build() { if (base.IsBuilt) { return result; } base.IsBuilt = true; ((NamedScriptableObjectList<CollectableItem>)(object)ManagerSingleton<CollectableItemManager>.Instance.masterList).Add((CollectableItem)(object)result); return result; } } [BepInPlugin("com.lem00ns.Silksong.Rando", "Randomiser", "0.1.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class RandoPlugin : BaseUnityPlugin, ISaveDataMod<SaveData>, ISaveDataMod { public const string Id = "com.lem00ns.Silksong.Rando"; public const string Name = "Randomiser"; public static RandoPlugin instance; public static GameManager GM; public ModResources resources; public SceneLoader sceneLoader; public RandoMap map; public LogicFile logic; public long versionStatus; private string versionStatusText; private bool versionOutOfDate; private string latestVersion; public List<CollectableItemPickup> PickupsToIgnore = new List<CollectableItemPickup>(); public GameModeData GameMode; public Dictionary<string, SavedItem> AddressableItems = new Dictionary<string, SavedItem>(); public bool ShowSceneDebug; public List<(string target, string check, SavedItem itm)> CollectableCache = new List<(string, string, SavedItem)>(); SaveData? ISaveDataMod<SaveData>.SaveData { get { return SaveData.Instance; } set { SaveData.Instance = value; } } public static ManualLogSource Log => ((BaseUnityPlugin)instance).Logger; public Dictionary<string, string> ItemReplacements => SaveData.Instance.ItemReplacements; private void Awake() { instance = this; resources = ModResources.LoadResources(((BaseUnityPlugin)this).Logger); GameScenes.Load(); sceneLoader = SceneLoader.Setup(); map = ((Component)this).gameObject.AddComponent<RandoMap>(); ((Component)this).gameObject.AddComponent<LocationFinder>(); ((Component)this).gameObject.AddComponent<SceneDumper>(); logic = LogicFile.Load("logic"); GameMode = GameModeManagerPlugin.Instance.Manager.Init((MonoBehaviour)(object)this, "Randomiser", "Basic randomiser", (Color?)null, false, (Sprite)null); MossberryLocation.InstallHooks(); CollectableItemPickupLocation.InstallHooks(); VersionInfo.FetchInfo(delegate(long status, string statusText, bool outOfDate, string latest) { latestVersion = latest; versionOutOfDate = outOfDate; versionStatusText = statusText; versionStatus = status; }); } private void Start() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) new Harmony("com.lem00ns.Silksong.Rando").PatchAll(typeof(RandoPlugin).Assembly); } private void OnGUI() { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: 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_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)GM)) { return; } GUI.skin.font = ModResources.GetFont(); List<(string txt, Color color)> DebugTexts = new List<(string, Color)>(); AddLine("Randomiser by Lem00ns - alpha v0.1.3 - Expect Bugs!"); if (versionStatus == 0L) { AddLine("Fetching latest version info..."); } else if (versionStatus == 200) { if (versionOutOfDate) { AddColoredLine("Randomiser out of date, latest version is " + latestVersion + " your version is 0.1.3 please update the mod.", Color.red); } } else { AddColoredLine(versionStatusText, Color.red); } if (ShowSceneDebug) { AddLine(GM.GetSceneNameString()); } if (PlayerData.instance != null) { if (ShowSceneDebug) { TransitionPoint val = null; float num = float.MaxValue; foreach (TransitionPoint transitionPoint in TransitionPoint.TransitionPoints) { Scene scene = ((Component)transitionPoint).gameObject.scene; if (((Scene)(ref scene)).name == GM.GetSceneNameString()) { float num2 = Vector2.Distance(Vector2.op_Implicit(((Component)transitionPoint).transform.position), Vector2.op_Implicit(GM.hero_ctrl.transform.position)); if (num2 < num) { num = num2; val = transitionPoint; } } } if ((Object)(object)val != (Object)null) { AddLine($"{((Object)val).name} - {num}m"); } } if (PlayerData.instance.isInventoryOpen) { AddLine($"{map.mode} map."); } } for (int i = 0; i < DebugTexts.Count; i++) { GUIStyle labelStyle = ModResources.GetLabelStyle(); GUI.contentColor = DebugTexts[i].color; GUI.Label(new Rect(10f, (float)Screen.height - (40f + (float)(i * 30)), 100f, 100f), DebugTexts[i].txt, labelStyle); } void AddColoredLine(string txt, Color color) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) DebugTexts.Add((txt, color)); } void AddLine(string txt) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) AddColoredLine(txt, Color.white); } } private void Update() { if (Object.op_Implicit((Object)(object)GameManager.SilentInstance) && !Object.op_Implicit((Object)(object)GM)) { GM = GameManager.instance; } if (Input.GetKeyDown((KeyCode)99) && Input.GetKey((KeyCode)292)) { ShowSceneDebug = !ShowSceneDebug; } if (!Input.GetKeyDown((KeyCode)98) || !Input.GetKey((KeyCode)292)) { return; } Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>(); foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles()) { try { dictionary.Add(((Object)allLoadedAssetBundle).name, allLoadedAssetBundle.GetAllAssetNames().ToList()); } catch { } } File.WriteAllText(Application.persistentDataPath + "/rando/bundles.json", JsonConvert.SerializeObject((object)dictionary, (Formatting)1)); } private AssetBundle FindBundleContaining(string req) { foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles()) { try { string[] allAssetNames = allLoadedAssetBundle.GetAllAssetNames(); for (int i = 0; i < allAssetNames.Length; i++) { if (allAssetNames[i].Contains(req)) { return allLoadedAssetBundle; } } } catch { } } return null; } public void LoadFakeCollectables() { AddressableItems.Clear(); FakeCollectable[] array = FindBundleContaining("Fake Collectables").LoadAllAssets<FakeCollectable>(); foreach (FakeCollectable val in array) { AddressableItems.Add(((Object)val).name, (SavedItem)(object)val); } } private void OnDestroy() { if ((Object)(object)instance == (Object)(object)this) { instance = null; } } private static SavedItem CreateCollectableItem(string target, string check) { //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Expected I4, but got Unknown if ((Object)(object)((NamedScriptableObjectList<CollectableItem>)(object)ManagerSingleton<CollectableItemManager>.Instance.masterList).GetByName(target) != (Object)null) { return (SavedItem)(object)RandoItem.Wrap(target, check, (SavedItem)(object)((NamedScriptableObjectList<CollectableItem>)(object)ManagerSingleton<CollectableItemManager>.Instance.masterList).GetByName(target)); } if ((Object)(object)((NamedScriptableObjectList<ToolItem>)(object)ManagerSingleton<ToolItemManager>.Instance.toolItems).GetByName(target) != (Object)null) { return (SavedItem)(object)RandoItem.Wrap(target, check, (SavedItem)(object)((NamedScriptableObjectList<ToolItem>)(object)ManagerSingleton<ToolItemManager>.Instance.toolItems).GetByName(target)); } if ((Object)(object)CollectableRelicManager.GetRelic(target) != (Object)null) { return (SavedItem)(object)RandoItem.Wrap(target, check, (SavedItem)(object)CollectableRelicManager.GetRelic(target)); } if (instance.AddressableItems.ContainsKey(target)) { return (SavedItem)(object)RandoItem.Wrap(target, check, instance.AddressableItems[target]); } if (target.StartsWith("georock_")) { return (SavedItem)(object)RandoItem.Wrap(target, check, (SavedItem)(object)((NamedScriptableObjectList<CollectableItem>)(object)ManagerSingleton<CollectableItemManager>.Instance.masterList).GetByName("Rosary_Set_Small")); } RandoItemBuilder randoItemBuilder = RandoItemBuilder.Create(target, check); randoItemBuilder.SetDisplayName("Invalid Item"); randoItemBuilder.SetDescription("Internal Item for the randomiser"); randoItemBuilder.SetMaxAmount(int.MaxValue); if (target.EndsWith(" Map")) { randoItemBuilder.SetDisplayName(target); randoItemBuilder.SetIcon("Map"); } else { randoItemBuilder.SetIcon("missing"); } RandoItem.OnCollectedCallback onCollectedCallback = null; if (target == "Brolly") { randoItemBuilder.SetDisplayName("Float Cloak"); randoItemBuilder.SetIcon("DriftersCloak"); onCollectedCallback = delegate { GM.playerData.hasBrolly = true; }; } if (target == "Faydown") { randoItemBuilder.SetDisplayName("Faydown Cloak"); randoItemBuilder.SetIcon("FaydownCloak"); onCollectedCallback = delegate { GM.playerData.hasDoubleJump = true; }; } if (target == "melody_Vault") { randoItemBuilder.SetDisplayName("Vaultkeeper's Melody"); randoItemBuilder.SetIcon("VaultkeepersMelody"); onCollectedCallback = delegate { GM.playerData.HasMelodyLibrarian = true; }; } if (target == "melody_Conductor") { randoItemBuilder.SetDisplayName("Conductor's Melody"); randoItemBuilder.SetIcon("ConductorsMelody"); onCollectedCallback = delegate { GM.playerData.HasMelodyConductor = true; }; } if (target == "melody_Architect") { randoItemBuilder.SetDisplayName("Architects's Melody"); randoItemBuilder.SetIcon("ArchitectsMelody"); onCollectedCallback = delegate { GM.playerData.HasMelodyArchitect = true; }; } if (target.StartsWith("ability_")) { WeaverSpireAbility val = Enum.Parse<WeaverSpireAbility>(target.Replace("ability_", "")); switch ((int)val) { case 0: return (SavedItem)(object)RandoItem.Wrap(target, check, (SavedItem)(object)ToolItemManager.GetToolByName("Silk Spear")); case 8: return (SavedItem)(object)RandoItem.Wrap(target, check, (SavedItem)(object)ToolItemManager.GetToolByName("Silk Bomb")); case 4: return (SavedItem)(object)RandoItem.Wrap(target, check, (SavedItem)(object)ToolItemManager.GetToolByName("Silk Charge")); case 2: return (SavedItem)(object)RandoItem.Wrap(target, check, (SavedItem)(object)ToolItemManager.GetToolByName("Thread Sphere")); case 5: randoItemBuilder.SetDisplayName("Clawline"); randoItemBuilder.SetIcon("Icon_SS_Clawline"); onCollectedCallback = delegate { GM.playerData.hasHarpoonDash = true; }; break; case 6: randoItemBuilder.SetDisplayName("Needolin"); randoItemBuilder.SetIcon("Icon_SS_Needolin"); onCollectedCallback = delegate { GM.playerData.hasNeedolin = true; }; break; case 1: randoItemBuilder.SetDisplayName("Swift Step"); randoItemBuilder.SetIcon("Icon_SS_Swift_Step"); onCollectedCallback = delegate { GM.playerData.hasDash = true; }; break; case 7: randoItemBuilder.SetDisplayName("Silk Soar"); randoItemBuilder.SetIcon("Icon_SS_Silk_Soar"); onCollectedCallback = delegate { GM.playerData.hasSuperJump = true; }; break; case 3: randoItemBuilder.SetDisplayName("Cling Grip"); randoItemBuilder.SetIcon("Icon_SS_Cling_Grip"); onCollectedCallback = delegate { GM.playerData.hasWalljump = true; }; break; } } if (onCollectedCallback != null) { randoItemBuilder.SetCollectCallback(onCollectedCallback); } return (SavedItem)(object)randoItemBuilder.Build(); } public static SavedItem GetCollectableItem(string target, string check) { foreach (var item in instance.CollectableCache) { if (item.target == target && item.check == check) { return item.itm; } } SavedItem val = CreateCollectableItem(target, check); instance.CollectableCache.Add((target, check, val)); return val; } } public class SaveData { private static SaveData? _instance; public static SaveData Instance { get { if (_instance == null) { _instance = new SaveData(); } return _instance; } [param: AllowNull] internal set { _instance = value; } } public int RandoSeed { get; set; } = -1; public Dictionary<string, string> ItemReplacements { get; set; } = new Dictionary<string, string>(); public List<string> CollectedChecks { get; set; } = new List<string>(); public static void Clear() { Instance = new SaveData(); } } public class SceneLoader : MonoBehaviour { public delegate void OnSceneCallback(string scene, int index); [CompilerGenerated] private sealed class <LoadAll>d__6 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public List<string> scenes; public SceneLoader <>4__this; public OnSceneCallback OnScene; public Action OnComplete; private int <i>5__2; private string <scn>5__3; private AsyncOperationHandle<SceneInstance> <task>5__4; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadAll>d__6(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) <scn>5__3 = null; <task>5__4 = default(AsyncOperationHandle<SceneInstance>); <>1__state = -2; } private bool MoveNext() { //IL_0153: 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_00ce: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; SceneLoader sceneLoader = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; Log.LogInfo((object)$"Starting task on {scenes.Count} scenes."); if (sceneLoader.IsLoading) { break; } sceneLoader.IsLoading = true; ((Component)GameCameras.instance.mainCamera).GetComponent<tk2dCamera>().ZoomFactor = 0.3f; TimeManager.TimeScale = 0f; Time.timeScale = 0f; <i>5__2 = 0; goto IL_0169; case 1: <>1__state = -1; goto IL_00ec; case 2: <>1__state = -1; if (OnScene != null) { OnScene(<scn>5__3, <i>5__2); } <>2__current = null; <>1__state = 3; return true; case 3: { <>1__state = -1; <scn>5__3 = null; <task>5__4 = default(AsyncOperationHandle<SceneInstance>); <i>5__2++; goto IL_0169; } IL_00ec: if (!<task>5__4.IsDone) { <>2__current = null; <>1__state = 1; return true; } <>2__current = null; <>1__state = 2; return true; IL_0169: if (<i>5__2 < scenes.Count) { <scn>5__3 = scenes[<i>5__2]; <task>5__4 = Addressables.LoadSceneAsync((object)("Scenes/" + <scn>5__3), (LoadSceneMode)0, true, 100, (SceneReleaseMode)0); goto IL_00ec; } TimeManager.TimeScale = 1f; Time.timeScale = 1f; sceneLoader.IsLoading = false; RandoPlugin.GM.ReturnToMainMenuNoSave(); if (OnComplete != null) { OnComplete(); } break; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public bool IsLoading; private static ManualLogSource Log => RandoPlugin.Log; public static SceneLoader Setup() { return ((Component)RandoPlugin.instance).gameObject.AddComponent<SceneLoader>(); } public static void ExecuteLoad(List<string> scenes, OnSceneCallback OnScene, Action? OnComplete = null) { ((MonoBehaviour)RandoPlugin.instance.sceneLoader).StartCoroutine(RandoPlugin.instance.sceneLoader.LoadAll(scenes, OnScene, OnComplete)); } [IteratorStateMachine(typeof(<LoadAll>d__6))] public IEnumerator LoadAll(List<string> scenes, OnSceneCallback OnScene, Action? OnComplete = null) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadAll>d__6(0) { <>4__this = this, scenes = scenes, OnScene = OnScene, OnComplete = OnComplete }; } } public static class VersionInfo { public delegate void OnFetched(long status, string statusText, bool outOfDate, string latest); private sealed class ProjectInfo { public string AssemblyTitle; public string Version; public string GitHubRepo; } [CompilerGenerated] private sealed class <fetchInfo>d__2 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public OnFetched onFetched; private UnityWebRequest <request>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <fetchInfo>d__2(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <request>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Invalid comparison between Unknown and I4 bool result; try { switch (<>1__state) { default: result = false; break; case 0: { <>1__state = -1; string text = "https://raw.githubusercontent.com/timothymarriott/Silksong-Rando/refs/heads/main/Directory.Build.props"; <request>5__2 = UnityWebRequest.Get(text); <>1__state = -3; <request>5__2.timeout = 30; <>2__current = <request>5__2.SendWebRequest(); <>1__state = 1; result = true; break; } case 1: <>1__state = -3; if ((int)<request>5__2.result != 1) { onFetched(<request>5__2.responseCode, "Failed to fetch latest version error code " + <request>5__2.responseCode, outOfDate: false, ""); result = false; } else { ProjectInfo projectInfo = ParseProjectXml(<request>5__2.downloadHandler.text); Version result3; if (!Version.TryParse("0.1.3", out Version result2)) { onFetched(0L, "Current version \"0.1.3\" is invalid.", outOfDate: true, projectInfo.Version); result = false; } else if (!Version.TryParse(projectInfo.Version, out result3)) { onFetched(0L, "Latest version \"" + projectInfo.Version + "\" is invalid.", outOfDate: false, projectInfo.Version); result = false; } else { onFetched(<request>5__2.responseCode, "", result2 < result3, projectInfo.Version); result = false; } } <>m__Finally1(); break; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<request>5__2 != null) { ((IDisposable)<request>5__2).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public static void FetchInfo(OnFetched onFetched) { ((MonoBehaviour)RandoPlugin.instance).StartCoroutine(fetchInfo(onFetched)); } [IteratorStateMachine(typeof(<fetchInfo>d__2))] private static IEnumerator fetchInfo(OnFetched onFetched) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <fetchInfo>d__2(0) { onFetched = onFetched }; } private static ProjectInfo ParseProjectXml(string xml) { XElement xElement = XDocument.Parse(xml).Root?.Element("PropertyGroup"); return new ProjectInfo { AssemblyTitle = xElement.Element("AssemblyTitle")?.Value, Version = xElement.Element("Version")?.Value, GitHubRepo = xElement.Element("GitHubRepo")?.Value }; } } } namespace Silksong.Rando.Data { public static class GameScenes { public static Dictionary<string, SceneInfo> Scenes = new Dictionary<string, SceneInfo>(); public static List<string> SceneNames = new List<string> { "Tut_01", "Tut_01b", "Tut_02", "Tut_03", "Tut_04", "Tut_05", "Mosstown_01", "Mosstown_02", "Mosstown_02c", "Mosstown_03", "Aspid_01", "Crawl_01", "Crawl_02", "Crawl_03", "Crawl_03b", "Crawl_04", "Crawl_05", "Crawl_06", "Crawl_07", "Crawl_08", "Crawl_09", "Crawl_10", "Belltown", "Belltown_04", "Belltown_06", "Belltown_07", "Belltown_08", "Belltown_Shrine", "Belltown_Room_pinsmith", "Belltown_Room_shellwood", "Belltown_Room_doctor", "Belltown_Room_Relic", "Belltown_basement", "Belltown_basement_03", "Bellway_01", "Bellway_01_boss", "Bellway_02", "Bellway_02_boss", "Bellway_03", "Bellway_03_boss", "Bellway_04", "Bellway_04_boss", "Bellway_08", "Bellway_City", "Bellway_Peak", "Bellway_Peak_02", "Bellway_Shadow", "Bellway_Aqueduct", "Bellway_Centipede_Arena", "Bellway_Centipede_additive", "Bellshrine", "Bellshrine_02", "Bellshrine_03", "Bellshrine_05", "Bellshrine_Enclave", "Bellshrine_Coral", "Bellshrine_Lore_Additive", "Bonetown", "Bonegrave", "Bone_01", "Bone_01b", "Bone_01c", "Bone_02", "Bone_03", "Bone_04", "Bone_05", "Bone_05_boss", "Bone_05_bellway", "Bone_05b", "Bone_06", "Bone_07", "Bone_08", "Bone_09", "Bone_10", "Bone_11", "Bone_11b", "Bone_12", "Bone_14", "Bone_15", "Bone_16", "Bone_17", "Bone_18", "Bone_19", "Ant_02", "Ant_03", "Ant_04", "Ant_04_mid", "Ant_04_left", "Ant_05b", "Ant_05c", "Ant_08", "Ant_09", "Ant_14", "Ant_17", "Ant_19", "Ant_20", "Ant_21", "Ant_Merchant", "Ant_Queen", "Dock_01", "Dock_02", "Dock_02b", "Dock_03", "Dock_03b", "Dock_03c", "Dock_03d", "Dock_04", "Dock_05", "Dock_06_Church", "Dock_08", "Dock_09", "Dock_10", "Dock_11", "Dock_12", "Dock_13", "Dock_14", "Dock_15", "Dock_16", "Room_Forge", "Bone_East_01", "Bone_East_02", "Bone_East_02b", "Bone_East_03", "Bone_East_04", "Bone_East_04c", "Bone_East_04b", "Bone_East_05", "Bone_East_07", "Bone_East_08", "Bone_East_09", "Bone_East_09b", "Bone_East_10", "Bone_East_10_Church", "Bone_East_10_Room", "Bone_East_11", "Bone_East_12", "Bone_East_13", "Bone_East_14", "Bone_East_14b", "Bone_East_15", "Bone_East_16", "Bone_East_17", "Bone_East_17b", "Bone_East_18", "Bone_East_18b", "Bone_East_18c", "Bone_East_20", "Bone_East_21", "Bone_East_22", "Bone_East_24", "Bone_East_25", "Bone_East_Weavehome", "Bone_East_Umbrella", "Bone_East_LavaChallenge", "Halfway_01", "Greymoor_01", "Greymoor_02", "Greymoor_03", "Greymoor_04", "Greymoor_05", "Greymoor_05_boss", "Greymoor_06", "Greymoor_07", "Greymoor_08", "Greymoor_08_boss", "Greymoor_08_caravan", "Greymoor_08_mapper", "Greymoor_10", "Greymoor_11", "Greymoor_12", "Greymoor_13", "Greymoor_15", "Greymoor_15b", "Greymoor_16", "Greymoor_17", "Greymoor_20b", "Greymoor_20c", "Greymoor_21", "Greymoor_22", "Greymoor_24", "Dust_01", "Dust_02", "Dust_03", "Dust_04", "Dust_05", "Dust_06", "Dust_09", "Dust_10", "Dust_11", "Dust_12", "Dust_Barb", "Dust_Shack", "Dust_Chef", "Dust_Maze_01", "Dust_Maze_02", "Dust_Maze_03", "Dust_Maze_04", "Dust_Maze_05", "Dust_Maze_06", "Dust_Maze_07", "Dust_Maze_08", "Dust_Maze_crossing", "Dust_Maze_Last_Hall", "Dust_Maze_08_completed", "Dust_Maze_09_entrance", "Organ_01", "Shadow_01", "Shadow_02", "Shadow_03", "Shadow_04", "Shadow_04b", "Shadow_05", "Shadow_09", "Shadow_10", "Shadow_11", "Shadow_12", "Shadow_13", "Shadow_14", "Shadow_15", "Shadow_16", "Shadow_18", "Shadow_19", "Shadow_20", "Shadow_21", "Shadow_22", "Shadow_23", "Shadow_24", "Shadow_25", "Shadow_26", "Shadow_27", "Shadow_28", "Shadow_Weavehome", "Aqueduct_01", "Aqueduct_02", "Aqueduct_03", "Aqueduct_04", "Aqueduct_05", "Aqueduct_06", "Aqueduct_07", "Wisp_02", "Wisp_03", "Wisp_04", "Wisp_05", "Wisp_06", "Wisp_07", "Wisp_08", "Wisp_09", "Shellwood_01", "Shellwood_01b", "Shellwood_02", "Shellwood_03", "Shellwood_04b", "Shellwood_04c", "Shellwood_08", "Shellwood_08c", "Shellwood_10", "Shellwood_11", "Shellwood_11b", "Shellwood_13", "Shellwood_14", "Shellwood_15", "Shellwood_16", "Shellwood_18", "Shellwood_19", "Shellwood_20", "Shellwood_22", "Shellwood_25", "Shellwood_25b", "Shellwood_26", "Shellwood_Witch", "Shellwood_11b_Memory", "Shellgrave", "Coral_02", "Coral_03", "Coral_10", "Coral_11", "Coral_11b", "Coral_12", "Coral_19", "Coral_19b", "Coral_23", "Coral_24", "Coral_25", "Coral_26", "Coral_27", "Coral_28", "Coral_29", "Coral_32", "Coral_33", "Coral_34", "Coral_35", "Coral_35b", "Coral_36", "Coral_37", "Coral_38", "Coral_39", "Coral_40", "Coral_41", "Coral_42", "Coral_43", "Coral_Tower_01", "Coral_Judge_Arena", "Under_01", "Under_01b", "Under_02", "Under_03", "Under_03b", "Under_03c", "Under_03d", "Under_04", "Under_05", "Under_06", "Under_07", "Under_07b", "Under_07c", "Under_08", "Under_10", "Under_11", "Under_12", "Under_13", "Under_14", "Under_16", "Under_17", "Under_18", "Under_19", "Under_19b", "Under_19c", "Under_20", "Under_21", "Under_22", "Under_23", "Song_01", "Song_01b", "Song_01c", "Song_02", "Song_03", "Song_04", "Song_05", "Song_07", "Song_08", "Song_09", "Song_09b", "Song_10", "Song_11", "Song_12", "Song_13", "Song_14", "Song_15", "Song_17", "Song_18", "Song_19_entrance", "Song_20", "Song_20b", "Song_24", "Song_25", "Song_26", "Song_27", "Song_Enclave", "Song_Enclave_Tube", "Tube_Hub", "Ward_01", "Ward_02", "Ward_02b", "Ward_03", "Ward_04", "Ward_05", "Ward_06", "Ward_07", "Library_01", "Library_02", "Library_03", "Library_04", "Library_05", "Library_06", "Library_07", "Library_08", "Library_09", "Library_10", "Library_11", "Library_11b", "Library_12", "Library_12b", "Library_13", "Library_13b", "Library_14", "Library_15", "Library_16", "Hang_01", "Hang_02", "Hang_03", "Hang_03_top", "Hang_04", "Hang_06", "Hang_06b", "Hang_06_bank", "Hang_07", "Hang_08", "Hang_09", "Hang_10", "Hang_12", "Hang_13", "Hang_14", "Hang_15", "Hang_16", "Hang_17b", "Arborium_01", "Arborium_02", "Arborium_03", "Arborium_04", "Arborium_05", "Arborium_06", "Arborium_07", "Arborium_08", "Arborium_09", "Arborium_10", "Arborium_11", "Arborium_Tube", "Cog_04", "Cog_05", "Cog_06", "Cog_07", "Cog_08", "Cog_09", "Cog_10", "Cog_Bench", "Cog_Pass", "Cog_Dancers", "Cog_Dancers_boss", "Cradle_01", "Cradle_02", "Cradle_03", "Song_Tower_01", "Song_Tower_Destroyed", "Cog_09_Destroyed", "Cog_10_Destroyed", "Cradle_01_Destroyed", "Cradle_03_Destroyed", "Cradle_Destroyed_Challenge_Bench", "Cradle_Destroyed_Challenge_01", "Abandoned_town", "Slab_01", "Slab_02", "Slab_03", "Slab_04", "Slab_05", "Slab_06", "Slab_07", "Slab_08", "Slab_10b", "Slab_10c", "Slab_12", "Slab_13", "Slab_14", "Slab_15", "Slab_16", "Slab_17", "Slab_18", "Slab_19b", "Slab_20", "Slab_21", "Slab_22", "Slab_23", "Slab_Cell", "Slab_Cell_Creature", "Slab_Cell_Quiet", "Peak_01", "Peak_02", "Peak_04", "Peak_04c", "Peak_04d", "Peak_05", "Peak_05c", "Peak_05d", "Peak_05e", "Peak_06", "Peak_07", "Peak_08", "Peak_08b", "Peak_10", "Peak_12", "Peak_Mask_Maker", "Weave_02", "Weave_03", "Weave_04", "Weave_05b", "Weave_07", "Weave_08", "Weave_10", "Weave_11", "Weave_12", "Weave_13", "Weave_14", "Clover_01", "Clover_01b", "Clover_02c", "Clover_03", "Clover_04b", "Clover_05c", "Clover_06", "Clover_10", "Clover_10_web", "Clover_11", "Clover_16", "Clover_18", "Clover_19", "Clover_20", "Abyss_01", "Abyss_02", "Abyss_02b", "Abyss_03", "Abyss_04", "Abyss_05", "Abyss_06", "Abyss_07", "Abyss_08", "Abyss_09", "Abyss_11", "Abyss_12", "Abyss_13", "Bonetown_boss", "Room_CrowCourt", "Room_CrowCourt_02", "Room_Pinstress", "Room_Witch", "Room_Caravan_Spa", "Room_Caravan_Interior", "Room_Huntress", "Room_Diving_Bell", "Room_Diving_Bell_Abyss", "Room_Diving_Bell_Abyss_Fixed", "Sprintmaster_Cave", "City_Lace_cutscene", "Chapel_Wanderer", "Memory_Needolin", "Memory_First_Sinner", "Memory_Silk_Heart_BellBeast", "Memory_Silk_Heart_WardBoss", "Memory_Silk_Heart_LaceTower", "Memory_Coral_Tower", "Memory_Ant_Queen", "Belltown_Room_Spare", "Shadow_08", "Cradle_02b", "Slab_16b", "Clover_21", "Pre_Menu_Loader", "Bone_East_08_boss_golem", "Bone_East_08_boss_golem_rest", "Bone_East_08_boss_beastfly", "Song_28", "Song_29", "Aqueduct_08", "Coral_44", "Hang_04_boss", "Shadow_Bilehaven_Room", "Abyss_Cocoon", "Peak_06b", "Bone_East_26", "Bone_East_27", "Memory_Red", "Ward_09", "Bone_Steel_Servant", "Cradle_Destroyed_Challenge_02", "Under_27", "Ward_02_boss" }; public static void Load() { Dictionary<string, SceneInfo> dictionary = JsonConvert.DeserializeObject<Dictionary<string, SceneInfo>>(ModResources.LoadData("scenes")); if (dictionary != null) { Scenes = dictionary; } } } } namespace Silksong.Rando.Data.Extractors { [Serializable] public class SceneInfo { public float width; public float height; public Vector2 Size => new Vector2(width, height); } public class SceneDumper : MonoBehaviour { private void Update() { if (!Input.GetKeyDown((KeyCode)115) || !Input.GetKey((KeyCode)292)) { return; } RandoPlugin.Log.LogInfo((object)"Starting to laod scene sizes"); Dictionary<string, SceneInfo> sceneSizes = new Dictionary<string, SceneInfo>(); SceneLoader.ExecuteLoad(GameScenes.SceneNames, delegate(string scene, int i) { RandoPlugin.Log.LogInfo((object)$"Searching {scene} ({i}/{GameScenes.SceneNames.Count})"); try { sceneSizes.Add(scene, new SceneInfo { width = RandoPlugin.GM.tilemap.width, height = RandoPlugin.GM.tilemap.height }); } catch (Exception ex) { RandoPlugin.Log.LogError((object)ex); } }, delegate { File.WriteAllText(Application.persistentDataPath + "\\rando\\scenes.json", JsonConvert.SerializeObject((object)sceneSizes, (Formatting)1)); }); } } } namespace Silksong.Rando.Map { public enum MapMode { No, Checks, Dev, Spoiler } public class RandoMap : MonoBehaviour { public enum PinColor { Black, Red, Yellow, White, Bronze } public static RandoMap instance; public List<GameObject> CreatedMarkers = new List<GameObject>(); public MapMode mode; public static GameManager GM => RandoPlugin.GM; private void Awake() { instance = this; PlayerDataVariableEvents.OnGetBool += delegate(PlayerData pd, string fieldName, bool current) { if (fieldName == "mapAllRooms") { return true; } return fieldName == "hasQuill" || current; }; } private void Update() { if (PlayerData.instance != null && Input.GetKeyDown((KeyCode)116) && PlayerData.instance.isInventoryOpen) { mode = (MapMode)((int)(mode + 1) % 4); Refresh(); } if (Input.GetKeyDown((KeyCode)114) && Input.GetKey((KeyCode)292)) { int num = Random.Range(0, int.MaxValue); RandoPlugin.Log.LogInfo((object)$"Starting rando with seed {num}"); SaveData.Instance.RandoSeed = num; SaveData.Instance.ItemReplacements = RandoPlugin.instance.logic.GenerateSeed(num); Refresh(); } } private void OnDestroy() { if ((Object)(object)instance == (Object)(object)this) { instance = null; } } public void Refresh() { foreach (GameObject createdMarker in CreatedMarkers) { Object.Destroy((Object)(object)createdMarker); } CreateLocationPins(); } public void CreateMapPin(ItemLocationData loc) { //IL_0041: 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_0063: 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_0079: 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_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Unknown result type (might be due to invalid IL or missing references) //IL_0316: Unknown result type (might be due to invalid IL or missing references) //IL_0321: 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_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) if (mode == MapMode.Checks && !RandoPlugin.instance.logic.HasCheck(loc.GetID())) { return; } GameMapScene val = default(GameMapScene); GameObject val2 = default(GameObject); Vector2 val3 = default(Vector2); GM.gameMap.GetSceneInfo(loc.scene, GM.gameMap.GetMapZoneFromSceneName(loc.scene), ref val, ref val2, ref val3); Vector2 mapPosition = GM.gameMap.GetMapPosition(loc.PositionInScene, val, val2, val3, GameScenes.Scenes[loc.scene].Size); Transform val4 = GM.gameMap.compassIcon.transform.parent; for (int i = 0; i < GM.gameMap.compassIcon.transform.parent.childCount; i++) { if (((Object)((Component)GM.gameMap.compassIcon.transform.parent.GetChild(i)).gameObject).name == "Map Markers") { val4 = GM.gameMap.compassIcon.transform.parent.GetChild(i); } } PinColor pinColor = PinColor.Black; if (RandoPlugin.instance.logic.HasCheck(loc.GetID())) { pinColor = PinColor.White; } GameObject val5 = Object.Instantiate<GameObject>(((Component)val4.GetChild((int)pinColor)).gameObject, val4); CreatedMarkers.Add(val5); val5.transform.localScale = Vector3.one * 0.4f; SpriteRenderer component = val5.GetComponent<SpriteRenderer>(); if (mode == MapMode.Dev) { if (SaveData.Instance.ItemReplacements.ContainsKey(loc.GetID())) { SavedItem collectableItem = RandoPlugin.GetCollectableItem(loc.item, loc.GetID()); component.sprite = collectableItem.GetPopupIcon(); } else { SavedItem collectableItem2 = RandoPlugin.GetCollectableItem(loc.item, loc.GetID()); component.sprite = collectableItem2.GetPopupIcon(); component.color = Color.green; } if (!RandoPlugin.instance.logic.HasCheck(loc.scene + "|" + loc.item)) { component.color = Color.red; } } if (mode == MapMode.Spoiler) { if (SaveData.Instance.ItemReplacements.ContainsKey(loc.GetID())) { SavedItem collectableItem3 = RandoPlugin.GetCollectableItem(SaveData.Instance.ItemReplacements[loc.GetID()], loc.GetID()); component.sprite = collectableItem3.GetPopupIcon(); } else { SavedItem collectableItem4 = RandoPlugin.GetCollectableItem(loc.item, loc.GetID()); component.sprite = collectableItem4.GetPopupIcon(); } } if (mode == MapMode.Checks) { SavedItem collectableItem5 = RandoPlugin.GetCollectableItem(loc.item, loc.GetID()); component.sprite = collectableItem5.GetPopupIcon(); } if (SaveData.Instance.CollectedChecks.Contains(loc.GetID())) { component.color *= new Color(1f, 1f, 1f, 0.5f); } Extensions.SetLocalPosition2D(val5.transform, Vector2.op_Implicit(new Vector3(mapPosition.x, mapPosition.y, -1f))); if (!val5.activeSelf) { val5.SetActive(true); } } public void CreateLocationPins() { if (mode == MapMode.No) { return; } foreach (var (_, loc) in JsonConvert.DeserializeObject<Dictionary<string, ItemLocationData>>(ModResources.LoadData("locations"))) { CreateMapPin(loc); } } } } namespace Silksong.Rando.Map.Hooks { [HarmonyPatch(typeof(GameMap), "Start")] internal class GameMap_Start_Patch { public static void Postfix(GameMap __instance) { RandoMap.instance.CreateLocationPins(); RandoPlugin.GM.UpdateGameMapWithPopup(0f); } } } namespace Silksong.Rando.Logic { [Serializable] public class LogicFile { [CompilerGenerated] private sealed class <ParseReq>d__8 : IEnumerable<string>, IEnumerable, IEnumerator<string>, IEnumerator, IDisposable { private int <>1__state; private string <>2__current; private int <>l__initialThreadId; private string req; public string <>3__req; string IEnumerator<string>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ParseReq>d__8(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (string.IsNullOrWhiteSpace(req) || req == "true") { return false; } <>2__current = req; <>1__state = 1; return true; case 1: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<string> IEnumerable<string>.GetEnumerator() { <ParseReq>d__8 <ParseReq>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <ParseReq>d__ = this; } else { <ParseReq>d__ = new <ParseReq>d__8(0); } <ParseReq>d__.req = <>3__req; return <ParseReq>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<string>)this).GetEnumerator(); } } public string start; public string[] required; public Dictionary<string, LogicNode> nodes; [JsonIgnore] public LogicNode StartNode => nodes[start]; public static LogicFile Load(string name) { return JsonConvert.DeserializeObject<LogicFile>(ModResources.LoadData(name)); } public bool HasCheck(string id) { foreach (var (_, logicNode2) in nodes) { if (logicNode2.checks == null) { continue; } string[] checks = logicNode2.checks; for (int i = 0; i < checks.Length; i++) { if (checks[i] == id) { return true; } } } return false; } public Dictionary<string, string> GenerateSeed(int seed = -1) { Random rng = new Random(); if (seed != -1) { rng = new Random(seed); } Dictionary<string, ItemLocationData>.KeyCollection keys = JsonConvert.DeserializeObject<Dictionary<string, ItemLocationData>>(ModResources.LoadData("locations")).Keys; Dictionary<string, string> placements = new Dictionary<string, string>(); HashSet<string> reachable = new HashSet<string> { start }; Dictionary<string, List<string>> nodeChecks = new Dictionary<string, List<string>>(); string[] checks; foreach (KeyValuePair<string, LogicNode> node in nodes) { node.Deconstruct(out var key, out var value); string key2 = key; LogicNode logicNode = value; List<string> list = new List<string>(); if (logicNode.checks != null) { checks = logicNode.checks; foreach (string text in checks) { if (keys.Contains(text)) { list.Add(text); } } } Shuffle(list, rng); nodeChecks[key2] = list; } HashSet<string> obtainedItems = new HashSet<string>(); HashSet<string> hashSet = new HashSet<string>(); foreach (List<string> value2 in nodeChecks.Values) { foreach (string item2 in value2) { hashSet.Add(item2.Split('|')[1]); } } bool progress2; do { progress2 = false; while (true) { IL_019a: RefreshReachable(ref progress2); checks = reachable.ToArray(); foreach (string key3 in checks) { NodeEdge[] array = nodes[key3].edges ?? Array.Empty<NodeEdge>(); foreach (NodeEdge nodeEdge in array) { if (reachable.Contains(nodeEdge.to)) { continue; } foreach (string item3 in ParseReq(nodeEdge.req)) { if (!obtainedItems.Contains(item3)) { ForcePlaceItem(item3, placements, nodes[key3].checks.ToList(), rng); obtainedItems.Add(item3); progress2 = true; goto IL_019a; } } } } break; } RefreshReachable(ref progress2); } while (progress2); if (reachable.Count != nodes.Count) { throw new Exception("Unreachable nodes remain after placement"); } checks = required; foreach (string text2 in checks) { placements[GetReachableChecks(ref progress2)[0]] = text2; obtainedItems.Add(text2); } List<string> list2 = new List<string>(); foreach (KeyValuePair<string, LogicNode> node2 in nodes) { checks = node2.Value.checks; for (int i = 0; i < checks.Length; i++) { string item = checks[i].Split("|", 2)[1]; if (!obtainedItems.Contains(item)) { list2.Add(item); } } } foreach (string reachableCheck in GetReachableChecks(ref progress2)) { if (!placements.ContainsKey(reachableCheck)) { if (list2.Count > 0) { placements[reachableCheck] = list2[0]; obtainedItems.Add(list2[0]); list2.RemoveAt(0); } else { RandoPlugin.Log.LogWarning((object)"Ran out of items"); } } } return placements; List<string> GetReachableChecks(ref bool progress) { List<string> list3 = new List<string>(); RefreshReachable(ref progress); string[] array2 = reachable.ToArray(); foreach (string key4 in array2) { foreach (string item4 in nodeChecks[key4]) { if (!placements.ContainsKey(item4)) { list3.Add(item4); } } } Shuffle(list3, rng); return list3; } void RefreshReachable(ref bool progress) { string[] array3 = reachable.ToArray(); foreach (string key5 in array3) { NodeEdge[] array4 = nodes[key5].edges ?? Array.Empty<NodeEdge>(); foreach (NodeEdge nodeEdge2 in array4) { if (!reachable.Contains(nodeEdge2.to) && EdgeSatisfied(nodeEdge2, obtainedItems)) { reachable.Add(nodeEdge2.to); progress = true; } } } } } [IteratorStateMachine(typeof(<ParseReq>d__8))] private static IEnumerable<string> ParseReq(string? req) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ParseReq>d__8(-2) { <>3__req = req }; } private static bool ForcePlaceItem(string item, Dictionary<string, string> placements, List<string> reachable, Random rng) { foreach (string item2 in Shuffled(reachable, rng)) { if (!placements.ContainsKey(item2)) { placements[item2] = item; RandoPlugin.Log.LogInfo((object)("Force placed " + item)); return true; } } return false; } private static bool EdgeSatisfied(NodeEdge edge, HashSet<string> obtainedItems) { if (string.IsNullOrWhiteSpace(edge.req) || edge.req == "true") { return true; } if (!obtainedItems.Contains(edge.req)) { return false; } return true; } private static void Shuffle<T>(IList<T> list, Random rng) { for (int num = list.Count - 1; num > 0; num--) { int num2 = rng.Next(num + 1); int index = num; int index2 = num2; T value = list[num2]; T value2 = list[num]; list[index] = value; list[index2] = value2; } } private static IList<T> Shuffled<T>(IList<T> list, Random rng) { List<T> list2 = list.ToList(); Shuffle(list2, rng); return list2; } } [Serializable] public class LogicNode { public NodeEdge[] edges; public string[] checks; } [Serializable] public class NodeEdge { public string to; public string req = "true"; } } namespace Silksong.Rando.Locations { public class BrollyLocation : ItemLocation { private PlayMakerFSM fsm; public BrollyLocation(PlayMakerFSM fsm) { this.fsm = fsm; } public override string GetItem() { return "Brolly"; } public override void SetItem(string item) { //IL_0029: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_005d: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown FsmState state = FsmUtil.GetState(fsm, "Msg"); FsmUtil.RemoveAction(state, 3); FsmUtil.RemoveAction(state, 2); FsmUtil.RemoveAction(state, 1); FsmUtil.AddAction(state, (FsmStateAction)new Wait { time = FsmFloat.op_Implicit(0.5f), realTime = false }); FsmUtil.AddLambdaMethod(state, (Action<Action>)delegate(Action fin) { AwardCollectable(); fin(); }); FsmUtil.AddAction(state, (FsmStateAction)new Wait { time = FsmFloat.op_Implicit(0.5f), realTime = false }); FsmUtil.RemoveTransitionsTo(state, "Fade Up"); FsmUtil.AddTransition(state, "FINISHED", "Fade Up"); } public override GameObject GetObj() { return ((Component)fsm).gameObject; } } public class CollectableItemPickupLocation : ItemLocation { private CollectableItemPickup pickup; public CollectableItemPickupLocation(CollectableItemPickup pickup) { this.pickup = pickup; } public override string GetItem() { return ((Object)pickup.item).name; } public override GameObject GetObj() { return ((Component)pickup).gameObject; } public override void SetItem(string item) { if (IsChecked()) { Object.Destroy((Object)(object)((Component)pickup).gameObject); } else { pickup.SetItem(RandoPlugin.GetCollectableItem(item, GetLocationID()), false); } } public static void InstallHooks() { PlayerDataVariableEvents.OnGetInt += (PlayerData pd, string name, int current) => (name == "dicePilgrimState" && RandoPlugin.instance.GameMode.Enabled) ? 1 : current; } } public class DJLocation : ItemLocation { private PlayMakerFSM fsm; public DJLocation(PlayMakerFSM fsm) { this.fsm = fsm; } public override string GetItem() { return "Faydown"; } public override void SetItem(string item) { //IL_0073: 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_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown FsmState checkState = FsmUtil.GetState(fsm, "Has DJ?"); FsmUtil.RemoveAction(checkState, 0); FsmUtil.AddLambdaMethod(checkState, (Action<Action>)delegate { if (IsChecked()) { fsm.Fsm.Event(checkState.GetTransitionEvent(0)); } else { fsm.Fsm.Event(checkState.GetTransitionEvent(1)); } }); FsmState state = FsmUtil.GetState(fsm, "Msg"); FsmUtil.RemoveAction(state, 13); FsmUtil.RemoveAction(state, 12); FsmUtil.RemoveAction(state, 11); FsmUtil.AddAction(state, (FsmStateAction)new Wait { time = FsmFloat.op_Implicit(0.5f), realTime = false }); FsmUtil.AddLambdaMethod(state, (Action<Action>)delegate(Action fin) { AwardCollectable(); fin(); }); FsmUtil.RemoveTransitionsTo(state, "Fade Back Pause"); FsmUtil.AddTransition(state, "FINISHED", "Fade Back Pause"); } public override GameObject GetObj() { return ((Component)fsm).gameObject; } } public class GeoRockLocation : ItemLocation { private GeoRock rock; public GeoRockLocation(GeoRock rock) { this.rock = rock; } public override string GetItem() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) string id = rock.geoRockData.id; BreakableTypes breakableType = rock.BreakableType; return "georock_" + id + "_" + ((object)(BreakableTypes)(ref breakableType)).ToString(); } public override GameObject GetObj() { return ((Component)rock).gameObject; } public override void SetItem(string item) { base.SetItem(item); Object.Destroy((Object)(object)((Component)rock).gameObject); } } public class HeartPieceLocation : ItemLocation { private PlayMakerFSM fsm; public HeartPieceLocation(PlayMakerFSM fsm) { this.fsm = fsm; } public override string GetItem() { return "Heart Piece"; } public override void SetItem(string item) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown Object.Destroy((Object)(object)((Component)fsm).gameObject.GetComponent<PersistentBoolItem>()); FsmState state = FsmUtil.GetState(fsm, "UI"); FsmUtil.RemoveAction(state, 1); FsmUtil.RemoveAction(state, 0); FsmUtil.AddAction(state, (FsmStateAction)(object)FsmUtil.GetAction<RemoveHeroInputBlocker>(FsmUtil.GetState(fsm, "End"), 0)); FsmUtil.AddAction(state, FsmUtil.GetAction<FsmStateAction>(FsmUtil.GetState(fsm, "End"), 1)); FsmUtil.AddAction(state, (FsmStateAction)new SendEventToRegister { eventName = FsmString.op_Implicit("HEART PIECE COLLECTED") }); FsmUtil.AddLambdaMethod(state, (Action<Action>)delegate(Action fin) { AwardCollectable(); PlayerData.instance.isInvincible = false; PlayerData.instance.disablePause = false; HeroController.instance.StartAnimationControl(); HeroController.instance.RegainControl(); HeroController.instance.AffectedByGravity(true); HeroController.instance.rb2d.gravityScale = HeroController.instance.DEFAULT_GRAVITY; HeroController.instance.currentGravity = HeroController.instance.DEFAULT_GRAVITY; HeroController.instance.prevGravityScale = 0f; fin(); }); FsmUtil.RemoveState(fsm, "Save Collected"); FsmUtil.RemoveTransitions(state); FsmUtil.AddTransition(state, "FINISHED", "End"); } public override GameObject GetObj() { return ((Component)fsm).gameObject; } } [Serializable] public class ItemLocationData { public string locationType; public string item; public string scene; public float positionInSceneX; public float positionInSceneY; public Vector2 PositionInScene => new Vector2(positionInSceneX, positionInSceneY); public string GetID() { return scene + "|" + item; } } public abstract class ItemLocation { public ItemLocationData locationData = new ItemLocationData(); private string replacement; public abstract string GetItem(); public string GetLocationID() { return RandoPlugin.GM.sceneName + "|" + GetItem(); } public void AddToCurrentScene() { //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_0049: 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) locationData.locationType = GetType().Name; locationData.item = GetItem(); locationData.scene = RandoPlugin.GM.sceneName; Vector2 position = GetPosition(); locationData.positionInSceneX = position.x; locationData.positionInSceneY = position.y; if (LocationFinder.IsSearching) { LocationFinder.ItemLocations.TryAdd(GetLocationID(), this); } if (RandoPlugin.instance.GameMode.Enabled && RandoPlugin.instance.ItemReplacements.ContainsKey(GetLocationID())) { if (!SaveData.Instance.CollectedChecks.Contains(GetLocationID())) { SetReplacement(RandoPlugin.instance.ItemReplacements[GetLocationID()]); } else { SetReplacement("Already Collected"); } } } public void SetReplacement(string id) { replacement = id; RandoPlugin.Log.LogInfo((object)(GetLocationID() + " -> " + ((RandoPlugin.instance.map.mode == MapMode.Spoiler) ? replacement : "SPOILERS") + (IsChecked() ? " checked" : " unchecked"))); SetItem(id); } public virtual Vector2 GetPosition() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) return Vector2.op_Implicit(GetObj().transform.position); } public abstract GameObject GetObj(); public virtual void SetItem(string item) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (!IsChecked()) { ((Component)CreateItemPickup(item)).transform.position = GetObj().transform.position; } } public void AwardCollectable() { if (!IsChecked()) { RandoPlugin.GetCollectableItem(replacement, GetLocationID()).Get(1, true); } } public bool IsChecked() { return SaveData.Instance.CollectedChecks.Contains(GetLocationID()); } public CollectableItemPickup CreateItemPickup(string item) { CollectableItemPickup component = Object.Instantiate<GameObject>(((Component)Gameplay.CollectableItemPickupPrefab).gameObject).GetComponent<CollectableItemPickup>(); RandoPlugin.instance.PickupsToIgnore.Add(component); component.SetItem(RandoPlugin.GetCollectableItem(item, GetLocationID()), false); return component; } } public class LocationFinder : MonoBehaviour { public static Dictionary<string, ItemLocation> ItemLocations = new Dictionary<string, ItemLocation>(); public static Dictionary<string, Dictionary<string, Dictionary<string, string>>> RoomChecks = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>(); public static bool IsSearching = false; private void Update() { if (!Input.GetKeyDown((KeyCode)121) || !Input.GetKey((KeyCode)292) || IsSearching) { return; } IsSearching = true; SceneLoader.ExecuteLoad(GameScenes.SceneNames, delegate(string scene, int i) { //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) RandoPlugin.Log.LogInfo((object)$"Searching {scene} ({i}/{GameScenes.SceneNames.Count}) found {ItemLocations.Count} locations."); File.WriteAllLines(Application.persistentDataPath + "\\rando\\locations.txt", ItemLocations.Keys); Dictionary<string, ItemLocationData> dictionary = new Dictionary<string, ItemLocationData>(); foreach (KeyValuePair<string, ItemLocation> itemLocation in ItemLocations) { dictionary.Add(itemLocation.Key, itemLocation.Value.locationData); } File.WriteAllText(Application.persistentDataPath + "\\rando\\locations.json", JsonConvert.SerializeObject((object)dictionary, (Formatting)1)); List<string> list = new List<string>(); foreach (TransitionPoint transitionPoint in TransitionPoint.TransitionPoints) { Scene scene2 = ((Component)transitionPoint).gameObject.scene; if (((Scene)(ref scene2)).name == scene) { list.Add(((Object)transitionPoint).name); } } Dictionary<string, Dictionary<string, string>> dictionary2 = new Dictionary<string, Dictionary<string, string>>(); foreach (string item in list) { Dictionary<string, string> dictionary3 = new Dictionary<string, string>(); foreach (string item2 in list) { dictionary3.Add(item2, "TRANSITION_NOTSET"); } foreach (KeyValuePair<string, ItemLocation> itemLocation2 in ItemLocations) { if (itemLocation2.Value.locationData.scene == scene) { dictionary3.Add(itemLocation2.Value.locationData.item, "ITEM_NOTSET"); } } dictionary2.Add(item, dictionary3); } RoomChecks.Add(scene, dictionary2); File.WriteAllText(Application.persistentDataPath + "\\rando\\room_logic.json", JsonConvert.SerializeObject((object)RoomChecks, (Formatting)1)); }, delegate { IsSearching = false; }); } } public class ArchitectMelodyLocation : ItemLocation { private PlayMakerFSM fsm; public ArchitectMelodyLocation(PlayMakerFSM fsm) { this.fsm = fsm; } public override string GetItem() { return "melody_Architect"; } public override void SetItem(string item) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown //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_00bc: Expected O, but got Unknown bool num = IsChecked(); FsmState state = FsmUtil.GetState(fsm, "Wait For Notify"); if (num) { FsmUtil.GetAction<PlayerDataVariableTest>(state, 0).IsExpectedEvent = state.GetTransitionEvent(2); FsmUtil.GetAction<PlayerDataVariableTest>(state, 0).IsNotExpectedEvent = state.GetTransitionEvent(2); } else { FsmUtil.GetAction<PlayerDataVariableTest>(state, 0).IsExpectedEvent = null; } FsmState state2 = FsmUtil.GetState(fsm, "Show Prompt"); FsmUtil.RemoveAction(state2, 0); FsmUtil.AddAction(state2, (FsmStateAction)new Wait { time = FsmFloat.op_Implicit(1f), realTime = false }); FsmUtil.AddLambdaMethod(state2, (Action<Action>)delegate(Action fin) { HeroController.instance.RelinquishControl(); RandoPlugin.GM.playerData.disableInventory = false; AwardCollectable(); HeroController.instance.RegainControl(); fin(); }); FsmUtil.AddAction(state2, (FsmStateAction)new Wait { time = FsmFloat.op_Implicit(0.5f), realTime = false }); FsmUtil.RemoveTransitionsTo(state2, "Singing End"); FsmUtil.AddTransition(state2, "FINISHED", "Singing End"); } public override GameObject GetObj() { return ((Component)fsm).gameObject; } } public class ConductorMelodyLocation : ItemLocation { private PlayMakerFSM fsm; public ConductorMelodyLocation(PlayMakerFSM fsm) { this.fsm = fsm; } public override string GetItem() { return "melody_Conductor"; } public override void SetItem(string item) { //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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_00a2: 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_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Expected O, but got Unknown FsmUtil.ReplaceAction(FsmUtil.GetState(fsm, "Has Item?"), 3, (FsmStateAction)new SetBoolValue { boolVariable = FsmUtil.GetBoolVariable(fsm, "Is Melody Quest Active"), boolValue = FsmBool.op_Implicit(false) }); FsmUtil.GetAction<CheckQuestStateV2>(FsmUtil.GetState(fsm, "Quest Active?"), 0).NotTrackedEvent = FsmUtil.GetState(fsm, "Quest Active?").GetTransitionEvent(1); FsmTemplateControl fsmTemplateControl = FsmUtil.GetAction<RunFSM>(FsmUtil.GetState(fsm, "Run Melody Play Prompted"), 5).fsmTemplateControl; FsmState state = fsmTemplateControl.RunFsm.GetState("Give Item"); FsmUtil.RemoveAction(state, 0); FsmUtil.AddAction(state, (FsmStateAction)new Wait { time = FsmFloat.op_Implicit(0.5f), realTime = false }); FsmUtil.AddLambdaMethod(state, (Action<Action>)delegate(Action fin) { AwardCollectable(); fin(); }); FsmUtil.AddAction(state, (FsmStateAction)new Wait { time = FsmFloat.op_Implicit(0.5f), realTime = false }); FsmState state2 = fsmTemplateControl.RunFsm.GetState("UI Msg"); FsmUtil.RemoveAction(state2, 4); FsmUtil.RemoveAction(state2, 3); FsmUtil.RemoveAction(state2, 1); FsmUtil.RemoveAction(state2, 0); FsmUtil.RemoveTransitionsTo(state2, "Stop Needolin"); FsmUtil.AddTransition(state2, "FINISHED", "Stop Needolin"); FsmState state3 = fsmTemplateControl.RunFsm.GetState("Stop Needolin"); FsmUtil.RemoveTransitionsTo(state3, "Give Item"); FsmUtil.AddTransition(state3, "FINISHED", "Give Item"); } public override GameObject GetObj() { return ((Component)fsm).gameObject; } } public class VaultMelodyLocation : ItemLocation { private PlayMakerFSM fsm; public VaultMelodyLocation(PlayMakerFSM fsm) { this.fsm = fsm; } public override string GetItem() { return "melody_Vault"; } public override void SetItem(string item) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown FsmTemplateControl fsmTemplateControl = FsmUtil.GetAction<RunFSM>(FsmUtil.GetState(fsm, "Needolin"), 4).fsmTemplateControl; FsmState state = fsmTemplateControl.RunFsm.GetState("Give Item"); FsmUtil.RemoveAction(state, 0); FsmUtil.AddAction(state, (FsmStateAction)new Wait { time = FsmFloat.op_Implicit(0.5f), realTime = false }); FsmUtil.AddLambdaMethod(state, (Action<Action>)delegate(Action fin) { AwardCollectable(); fin(); }); FsmUtil.AddAction(state, (FsmStateAction)new Wait { time = FsmFloat.op_Implicit(0.5f), realTime = false }); FsmState state2 = fsmTemplateControl.RunFsm.GetState("UI Msg"); FsmUtil.RemoveAction(state2, 4); FsmUtil.RemoveAction(state2, 3); FsmUtil.RemoveAction(state2, 1); FsmUtil.RemoveAction(state2, 0); FsmUtil.RemoveTransitionsTo(state2, "Stop Needolin"); FsmUtil.AddTransition(state2, "FINISHED", "Stop Needolin"); FsmState state3 = fsmTemplateControl.RunFsm.GetState("Stop Needolin"); FsmUtil.RemoveTransitionsTo(state3, "Give Item"); FsmUtil.AddTransition(state3, "FINISHED", "Give Item"); } public override GameObject GetObj() { return ((Component)fsm).gameObject; } } public enum MossberryLocationType { Vine, Aspid } public class MossberryLocation : ItemLocation { private MossberryLocationType locType; private PlayMakerFSM fsm; private HealthManager aspid; public MossberryLocation(PlayMakerFSM fsm) { locType = MossberryLocationType.Vine; this.fsm = fsm; } public MossberryLocation(HealthManager aspid, PlayMakerFSM fsm) { locType = MossberryLocationType.Aspid; this.aspid = aspid; this.fsm = fsm; } public override string GetItem() { return "Mossberry"; } public override void SetItem(string item) { Object.Destroy((Object)(object)((Component)fsm).GetComponent<PersistentBoolItem>()); if (locType == MossberryLocationType.Vine) { if (SaveData.Instance.CollectedChecks.Contains(GetLocationID())) { ((Component)fsm).gameObject.SetActive(false); } FsmUtil.InsertLambdaMethod(fsm.fsm.GetState("Init"), 4, (Action<Action>)delegate(Action fin) { FsmState state2 = FsmUtil.GetGameObjectVariable(fsm.fsm, "Fruit").Value.GetComponent<PlayMakerFSM>().fsm.GetState("Collect"); FsmUtil.RemoveAction(state2, 2); FsmUtil.InsertLambdaMethod(state2, 2, (Action<Action>)delegate(Action fin) { AwardCollectable(); fin(); }); fin(); }); } else if (locType == MossberryLocationType.Aspid) { RandoPlugin.Log.LogInfo((object)aspid); RandoPlugin.Log.LogInfo((object)fsm); FsmState state = fsm.fsm.GetState("Collect"); FsmUtil.RemoveAction(state, 2); FsmUtil.InsertLambdaMethod(state, 2, (Action<Action>)delegate(Action fin) { AwardCollectable(); fin(); }); } } public override GameObject GetObj() { if (locType == MossberryLocationType.Vine) { return ((Component)fsm).gameObject; } if (locType == MossberryLocationType.Aspid) { return ((Component)aspid).gameObject; } return ((Component)fsm).gameObject; } public static void InstallHooks() { PlayerDataVariableEvents.OnGetBool += delegate(PlayerData pd, string name, bool current) { if (RandoPlugin.instance.GameMode.Enabled) { switch (name) { case "mosstownAspidBerryCollected": return SaveData.Instance.CollectedChecks.Contains("Bone_05b|Mossberry"); case "bonegraveAspidBerryCollected": return SaveData.Instance.CollectedChecks.Contains("Bonegrave|Mossberry"); case "bonetownAspidBerryCollected": return SaveData.Instance.CollectedChecks.Contains("Bonetown|Mossberry"); } } return current; }; } } public class NeedolinLocation : ItemLocation { private PlayMakerFSM fsm; public NeedolinLocation(PlayMakerFSM fsm) { this.fsm = fsm; } public override string GetItem() { return "ability_Needolin"; } public override void SetItem(string item) { //IL_0030: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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_0085: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown FsmUtil.RemoveAction(FsmUtil.GetState(fsm, "Final Bind Burst"), 3); FsmState state = FsmUtil.GetState(fsm, "Get Needolin"); FsmUtil.RemoveAction(state, 1); FsmUtil.AddAction(state, (FsmStateAction)new Wait { time = FsmFloat.op_Implicit(0.5f), realTime = false }); FsmUtil.AddLambdaMethod(state, (Action<Action>)delegate(Action fin) { AwardCollectable(); PlayerData.instance.spinnerDefeated = true; HeroController.instance.SetSilkRegenBlocked(true); PlayerData.instance.disableInventory = false; fin(); }); FsmUtil.AddAction(state, (FsmStateAction)new Wait { time = FsmFloat.op_Implicit(1f), realTime = false }); FsmUtil.AddAction(state, (FsmStateAction)new QueueMemoryFullHeal()); FsmUtil.AddAction(state, (FsmStateAction)new ToolsCutsceneControl { SetInCutscene = FsmBool.op_Implicit(false) }); BeginSceneTransition action = FsmUtil.GetAction<BeginSceneTransition>(FsmUtil.GetState(fsm, "To Memory Scene"), 2); action.sceneName = FsmString.op_Implicit("Belltown_Shrine"); action.entryGateName = FsmString.op_Implicit("door_wakeOnGround"); } public override GameObject GetObj() { return ((Component)fsm).gameObject; } } public class PollipBulbLocation : ItemLocation { private PlayMakerFSM fsm; public PollipBulbLocation(PlayMakerFSM fsm) { this.fsm = fsm; } public override string GetItem() { return "Shell Flower"; } public override void SetItem(string item) { Object.Destroy((Object)(object)((Component)((Component)fsm).transform.parent).GetComponent<PersistentBoolItem>()); if (IsChecked()) { ((Component)((Component)fsm).transform.parent).gameObject.SetActive(false); } FsmState state = fsm.fsm.GetState("Collect"); FsmUtil.RemoveAction(state, 6); FsmUtil.InsertLambdaMethod(state, 6, (Action<Action>)delegate(Action fin) { AwardCollectable(); fin(); }); } public override GameObject GetObj() { return ((Component)fsm).gameObject; } } public class ShrineWeaverAbilityLocation : ItemLocation { private PlayMakerFSM fsm; public ShrineWeaverAbilityLocation(PlayMakerFSM fsm) { this.fsm = fsm; } public override string GetItem() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) WeaverSpireAbility val = (WeaverSpireAbility)(object)fsm.FsmVariables.EnumVariables[0].Value; return "ability_" + ((object)(WeaverSpireAbility)(ref val)).ToString(); } public override void SetItem(string item) { base.SetItem(item); Object.Destroy((Object)(object)((Component)fsm).GetComponent<PlayMakerNPC>()); Object.Destroy((Object)(object)fsm); } public override GameObject GetObj() { return ((Component)fsm).gameObject; } } } namespace Silksong.Rando.Locations.Hooks { [HarmonyPatch(typeof(CollectableItemPickup), "Start")] internal class CollectableItemPickup_Start_Patch { public static void Prefix(CollectableItemPickup __instance) { if (!(__instance.item is RandoItem) && !RandoPlugin.instance.PickupsToIgnore.Contains(__instance) && ((Object)__instance.item).name != "Trobbio Quill Red" && ((Object)__instance.item).name != "Shiny Bell Goomba") { new CollectableItemPickupLocation(__instance).AddToCurrentScene(); } } } [HarmonyPatch(typeof(GeoRock), "Start")] internal class GeoRock_Start_Patch { public static void Prefix(GeoRock __instance) { } } [HarmonyPatch(typeof(HealthManager), "Start")] internal class HealthManager_Start_Patch { public static void Prefix(HealthManager __instance) { if (!((Object)((Component)__instance).gameObject).name.StartsWith("Aspid Collector")) { return; } for (int i = 0; i < ((Component)__instance).transform.childCount; i++) { if (((Object)((Component)((Component)__instance).transform.GetChild(i)).gameObject).name == "Mossberry Pickup") { new MossberryLocation(__instance, ((Component)((Component)__instance).transform.GetChild(i)).GetComponent<PlayMakerFSM>()).AddToCurrentScene(); } } } } [HarmonyPatch(typeof(PlayMakerFSM), "Start")] internal class PlayMakerFSM_Start_Patch { public static void Prefix(PlayMakerFSM __instance) { if (((Object)__instance).name == "Shrine Weaver Ability") { new ShrineWeaverAbilityLocation(__instance).AddToCurrentScene(); } if (((Object)__instance).name == "Big Flower") { new PollipBulbLocation(((Component)((Component)__instance).transform.GetChild(1)).GetComponent<PlayMakerFSM>()).AddToCurrentScene(); } if (((Object)__instance).name == "moss_berry_fruit") { new MossberryLocation(__instance).AddToCurrentScene(); } if (((Object)__instance).name == "Spinner Boss" && __instance.FsmName == "Control") { new NeedolinLocation(__instance).AddToCurrentScene(); } if (((Object)__instance).name == "Seamstress" && __instance.FsmName == "Dialogue") { new BrollyLocation(__instance).AddToCurrentScene(); } if (((Object)__instance).name == "Librarian" && __instance.FsmName == "Dialogue" && FsmUtil.GetState(__instance, "Open Relic Board") != null) { new VaultMelodyLocation(__instance).AddToCurrentScene(); } if (((Object)__instance).name == "puzzle cylinders" && __instance.FsmName == "Cylinder States") { new ArchitectMelodyLocation(__instance).AddToCurrentScene(); } if (((Object)__instance).name == "Last Conductor NPC" && __instance.FsmName == "Dialogue") { new ConductorMelodyLocation(__instance).AddToCurrentScene(); } if (((Object)__instance).name == "DJ Get Sequence") { new DJLocation(__instance).AddToCurrentScene(); } } } } namespace Silksong.Rando.Hooks { [HarmonyPatch] public class CollectableItemManagerHooks { public static List<string> cachedItems = new List<string>(); [HarmonyPatch(typeof(CollectableItemManager), "Awake")] [HarmonyPrefix] public static void BeginSceneTransition(CollectableItemManager __instance) { Dictionary<string, ItemLocationData> dictionary = JsonConvert.DeserializeObject<Dictionary<string, ItemLocationData>>(ModResources.LoadData("locations")); if (cachedItems.Count == dictionary.Count) { return; } cachedItems.Clear(); foreach (KeyValuePair<string, ItemLocationData> item in dictionary) { cachedItems.Add(((Object)RandoPlugin.GetCollectableItem(item.Value.item, item.Key)).name); } } [HarmonyPatch(typeof(CollectableItemManager), "IsItemInMasterList", new Type[] { typeof(string) })] [HarmonyPrefix] public static bool IsItemInMasterList(CollectableItemManager __instance, ref bool __result, string itemName) { if (cachedItems.Contains(itemName)) { __result = true; return false; } return true; } } [HarmonyPatch] public class GameManagerHooks { [HarmonyPatch(typeof(GameManager), "BeginSceneTransition", new Type[] { typeof(SceneLoadInfo) })] [HarmonyPostfix] public static void BeginSceneTransition(GameManager __instance, SceneLoadInfo info) { if (RandoPlugin.instance.GameMode.Enabled && info.SceneName == "Opening_Sequence" && SaveData.Instance.RandoSeed == -1) { int num = Random.Range(0, int.MaxValue); RandoPlugin.Log.LogInfo((object)$"Starting rando with seed {num}"); SaveData.Instance.RandoSeed = num; SaveData.Instance.ItemReplacements = RandoPlugin.instance.logic.GenerateSeed(num); } } [HarmonyPatch(typeof(GameManager), "ClearSaveFile", new Type[] { typeof(int), typeof(Action<bool>) })] [HarmonyPostfix] public static void ClearSaveFile(GameManager __instance, int saveSlot, Action<bool> callback) { if (RandoPlugin.instance.GameMode.Enabled) { SaveData.Clear(); } } [HarmonyPatch(typeof(GameManager), "Start")] [HarmonyPostfix] public static void Start(GameManager __instance) { RandoPlugin.instance.LoadFakeCollectables(); } } }