Decompiled source of Hard Item Randomizer w SceneRandom v1.0.7
plugins/HKSilksong_SceneRandomizer.dll
Decompiled 20 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } public static class RoomMapGenerator { private static readonly bool[,] letters; static RoomMapGenerator() { letters = new bool[128, 25]; string[] array = new string[26] { "01110100011000111111000110001", "11110100011111010001100011111", "01110100011000010000100000111", "11110100011000110001100011110", "11111100001111010000100011111", "11111100001111010000100010000", "01110100011000010111100001111", "10001100011111110001100011000", "01110001000010000100001000111", "00111000100001000100011001100", "10001100101110010010100011000", "10000100001000010000100001111", "10001110111010110001100011000", "10001110011010110011100011000", "01110100011000110001100010111", "11110100011111010000100010000", "01110100011000110001101010101", "11110100011111010010100011001", "01111100000111000001100011110", "11111001000010000100001000010", "10001100011000110001100001110", "10001100011000101010001000100", "10001100011000110101101011010", "10001010100010001010100010001", "10001010100010000100001000010", "11111000100010001000100011111" }; for (int i = 0; i < 26; i++) { string text = array[i]; for (int j = 0; j < 25; j++) { letters[65 + i, j] = text[j] == '1'; } } string[] array2 = new string[10] { "01110100011000110001100010111", "00100011000010000100001000111", "01110100010001000100010001111", "11110000111100000011100011110", "10001100111110000010000100010", "11111100001111000001100011111", "01110100001111010001100010111", "11111000010001000100001000010", "01110100011000101110100010111", "01110100011000101111000011110" }; for (int k = 0; k < 10; k++) { string text2 = array2[k]; for (int l = 0; l < 25; l++) { letters[48 + k, l] = text2[l] == '1'; } } string text3 = "00000000000000000000011111"; for (int m = 0; m < 25; m++) { letters[95, m] = text3[m] == '1'; } } public static bool GenerateFromFile(string connectionsFilePath, string outputImagePath) { if (!File.Exists(connectionsFilePath)) { Debug.LogWarning((object)("File not found: " + connectionsFilePath)); return false; } string[] array = File.ReadAllLines(connectionsFilePath); Dictionary<string, HashSet<string>> dictionary = new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase); string[] array2 = array; for (int i = 0; i < array2.Length; i++) { string text = array2[i]?.Trim(); if (string.IsNullOrEmpty(text) || text.StartsWith("#")) { continue; } string[] array3 = text.Split(new char[1] { '|' }); if (array3.Length != 4) { continue; } string text2 = array3[0]; string text3 = array3[2]; if (!string.IsNullOrEmpty(text2) && !string.IsNullOrEmpty(text3)) { if (!dictionary.ContainsKey(text2)) { dictionary[text2] = new HashSet<string>(StringComparer.OrdinalIgnoreCase); } if (!dictionary.ContainsKey(text3)) { dictionary[text3] = new HashSet<string>(StringComparer.OrdinalIgnoreCase); } dictionary[text2].Add(text3); dictionary[text3].Add(text2); } } if (dictionary.Count == 0) { Debug.LogWarning((object)"No connections found."); return false; } GenerateMapTexture(dictionary, outputImagePath); Debug.Log((object)("Map saved to " + outputImagePath)); return true; } private static void GenerateMapTexture(Dictionary<string, HashSet<string>> graph, string outputPath) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_007d: 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_00de: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) int num = 250; int num2 = 120; int num3 = 100; int num4 = 80; List<string> list = graph.Keys.ToList(); int num5 = (int)Math.Ceiling(Math.Sqrt(list.Count)); int num6 = (int)Math.Ceiling((float)list.Count / (float)num5); int num7 = num5 * (num + num3) + num3; int num8 = num6 * (num2 + num4) + num4; Texture2D val = new Texture2D(num7, num8, (TextureFormat)4, false); Color[] array = (Color[])(object)new Color[num7 * num8]; for (int i = 0; i < array.Length; i++) { array[i] = Color.black; } val.SetPixels(array); Dictionary<string, Vector2> dictionary = new Dictionary<string, Vector2>(); int num9 = 0; int num10 = 0; foreach (string item in list) { dictionary[item] = new Vector2((float)(num3 + num9 * (num + num3)), (float)(num4 + num10 * (num2 + num4))); num9++; if (num9 >= num5) { num9 = 0; num10++; } } foreach (KeyValuePair<string, HashSet<string>> item2 in graph) { if (!dictionary.TryGetValue(item2.Key, out var value)) { continue; } foreach (string item3 in item2.Value) { if (dictionary.TryGetValue(item3, out var value2)) { int num11 = 2; DrawLine(val, (int)(value.x + (float)(num / 2)) + num11, (int)(value.y + (float)(num2 / 2)) + num11, (int)(value2.x + (float)(num / 2)) + num11, (int)(value2.y + (float)(num2 / 2)) + num11, Color.gray, 3); } } } foreach (KeyValuePair<string, Vector2> item4 in dictionary) { DrawEmptyRectangle(val, (int)item4.Value.x, (int)item4.Value.y, num, num2, Color.gray); DrawTextBitmap(val, (int)item4.Value.x + 10, (int)item4.Value.y + 35, item4.Key, Color.white); } val.Apply(); string directoryName = Path.GetDirectoryName(outputPath); if (!string.IsNullOrEmpty(directoryName) && !Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } File.WriteAllBytes(outputPath, ImageConversion.EncodeToPNG(val)); Object.DestroyImmediate((Object)(object)val); } private static void DrawEmptyRectangle(Texture2D tex, int x, int y, int w, int h, Color color) { //IL_0036: 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_0064: 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) for (int i = x; i < x + w; i++) { if (i >= 0 && i < ((Texture)tex).width) { if (y >= 0 && y < ((Texture)tex).height) { tex.SetPixel(i, y, color); } if (y + h - 1 >= 0 && y + h - 1 < ((Texture)tex).height) { tex.SetPixel(i, y + h - 1, color); } } } for (int j = y; j < y + h; j++) { if (j >= 0 && j < ((Texture)tex).height) { if (x >= 0 && x < ((Texture)tex).width) { tex.SetPixel(x, j, color); } if (x + w - 1 >= 0 && x + w - 1 < ((Texture)tex).width) { tex.SetPixel(x + w - 1, j, color); } } } } private static void DrawTextBitmap(Texture2D tex, int x, int y, string text, Color color) { //IL_00f6: Unknown result type (might be due to invalid IL or missing references) int num = x; int num2 = 4; int num3 = 1; string text2 = text.ToUpper(); foreach (char c in text2) { char c2 = c; if ((c2 < 'A' || c2 > 'Z') && (c2 < '0' || c2 > '9') && c2 != '_') { num += 5 * num2 + num2; continue; } for (int j = 0; j < 5; j++) { for (int k = 0; k < 5; k++) { if (!letters[(uint)c2, j * 5 + k]) { continue; } int num4 = ((c2 != '_') ? (4 - j) : (4 - j - num3)); for (int l = 0; l < num2; l++) { for (int m = 0; m < num2; m++) { int num5 = num + k * num2 + l; int num6 = y + num4 * num2 + m; if (num5 >= 0 && num5 < ((Texture)tex).width && num6 >= 0 && num6 < ((Texture)tex).height) { tex.SetPixel(num5, num6, color); } } } } } num += 5 * num2 + num2; } } private static void DrawLine(Texture2D tex, int x0, int y0, int x1, int y1, Color color, int thickness = 2) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) int num = Math.Abs(x1 - x0); int num2 = ((x0 < x1) ? 1 : (-1)); int num3 = -Math.Abs(y1 - y0); int num4 = ((y0 < y1) ? 1 : (-1)); int num5 = num + num3; while (true) { for (int i = -thickness / 2; i <= thickness / 2; i++) { for (int j = -thickness / 2; j <= thickness / 2; j++) { int num6 = x0 + i; int num7 = y0 + j; if (num6 >= 0 && num6 < ((Texture)tex).width && num7 >= 0 && num7 < ((Texture)tex).height) { tex.SetPixel(num6, num7, color); } } } if (x0 == x1 && y0 == y1) { break; } int num8 = 2 * num5; if (num8 >= num3) { num5 += num3; x0 += num2; } if (num8 <= num) { num5 += num; y0 += num4; } } } } namespace HKSilksong_Randomizer { [BepInPlugin("com.yourname.randomsceneloader", "Random Scene Loader", "0.1.1")] public class RandomSceneLoader : BaseUnityPlugin { internal class SceneConfig { public List<string> Exits; public SceneConfig(List<string> exits) { Exits = exits ?? new List<string>(); } } [CompilerGenerated] private sealed class <AutoDiscoverAfterLoad>d__37 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public RandomSceneLoader <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <AutoDiscoverAfterLoad>d__37(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = <>4__this.waitHalfSecond; <>1__state = 1; return true; case 1: <>1__state = -1; <>4__this.DiscoverGatesInCurrentScene(); 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(); } } [CompilerGenerated] private sealed class <DetectEntryGateAfterLoad>d__38 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public RandomSceneLoader <>4__this; private HeroController <hero>5__1; private Vector3 <heroPos>5__2; private GameObject[] <allObjects>5__3; private GameObject[] <>s__4; private int <>s__5; private GameObject <obj>5__6; private string <name>5__7; private Exception <ex>5__8; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DetectEntryGateAfterLoad>d__38(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <hero>5__1 = null; <allObjects>5__3 = null; <>s__4 = null; <obj>5__6 = null; <name>5__7 = null; <ex>5__8 = null; <>1__state = -2; } private bool MoveNext() { //IL_0070: 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_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = <>4__this.waitThirdSecond; <>1__state = 1; return true; case 1: <>1__state = -1; try { <hero>5__1 = HeroController.instance; if ((Object)(object)<hero>5__1 == (Object)null) { return false; } <heroPos>5__2 = ((Component)<hero>5__1).transform.position; <allObjects>5__3 = Object.FindObjectsByType<GameObject>((FindObjectsSortMode)0); <>s__4 = <allObjects>5__3; for (<>s__5 = 0; <>s__5 < <>s__4.Length; <>s__5++) { <obj>5__6 = <>s__4[<>s__5]; <name>5__7 = ((Object)<obj>5__6).name.ToLower(); if ((<name>5__7.StartsWith("left") || <name>5__7.StartsWith("right") || <name>5__7.StartsWith("top") || <name>5__7.StartsWith("bot")) && <name>5__7.Length <= 6 && char.IsDigit(<name>5__7[<name>5__7.Length - 1]) && Vector3.Distance(<heroPos>5__2, <obj>5__6.transform.position) < 10f) { if (string.IsNullOrEmpty(<>4__this.lastEntryGateUsed)) { <>4__this.lastEntryGateUsed = ((Object)<obj>5__6).name; <>4__this.log.LogInfo((object)("Auto-detected entry gate: " + ((Object)<obj>5__6).name)); } break; } <name>5__7 = null; <obj>5__6 = null; } <>s__4 = null; <hero>5__1 = null; <allObjects>5__3 = null; } catch (Exception ex) { <ex>5__8 = ex; <>4__this.log.LogWarning((object)("DetectEntryGate failed: " + <ex>5__8.Message)); } 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(); } } [CompilerGenerated] private sealed class <LoadSceneCoroutine>d__34 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string sceneName; public string entryGate; public RandomSceneLoader <>4__this; private float <timeout>5__1; private float <startTime>5__2; private Exception <ex>5__3; private Exception <ex>5__4; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadSceneCoroutine>d__34(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } <ex>5__3 = null; <ex>5__4 = null; <>1__state = -2; } private bool MoveNext() { //IL_01b6: 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_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: 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) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: 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_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown bool result; try { Scene activeScene; switch (<>1__state) { default: result = false; goto end_IL_0000; case 0: <>1__state = -1; if (!<>4__this.isTransitioning) { <>4__this.loadRequested = false; <>4__this.isTransitioning = true; <>4__this.lastEntryGateUsed = entryGate; <timeout>5__1 = 8f; <startTime>5__2 = Time.time; if (string.IsNullOrEmpty(sceneName) || !((Object)(object)GameManager.instance != (Object)null)) { break; } <>1__state = -3; try { GameManager.instance.BeginSceneTransition(new SceneLoadInfo { SceneName = sceneName, EntryGateName = entryGate, PreventCameraFadeOut = false, WaitForSceneTransitionCameraFade = true, Visualization = (SceneLoadVisualizations)0 }); } catch (Exception ex) { <ex>5__3 = ex; <>4__this.log.LogWarning((object)("BeginSceneTransition failed: " + <ex>5__3.Message)); <>4__this.isTransitioning = false; result = false; goto IL_020f; } goto IL_01b6; } result = false; goto end_IL_0000; case 1: <>1__state = -3; goto IL_01b6; case 2: { <>1__state = -3; <>4__this.isTransitioning = false; result = false; goto IL_020f; } IL_01b6: activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).name != sceneName) { if (Time.time - <startTime>5__2 > <timeout>5__1) { <>4__this.log.LogWarning((object)("LoadSceneCoroutine timeout waiting for scene " + sceneName)); <>4__this.isTransitioning = false; result = false; goto IL_020f; } <>2__current = <>4__this.waitTenthSecond; <>1__state = 1; result = true; } else { <>2__current = <>4__this.waitFifthSecond; <>1__state = 2; result = true; } goto end_IL_0000; IL_020f: <>m__Finally1(); goto end_IL_0000; } try { SceneManager.LoadScene(sceneName); } catch (Exception ex) { <ex>5__4 = ex; <>4__this.log.LogWarning((object)("SceneManager.LoadScene failed: " + <ex>5__4.Message)); } finally { SuppressTransitionPatch = false; <>4__this.isTransitioning = false; } result = false; end_IL_0000:; } 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; SuppressTransitionPatch = false; } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private ManualLogSource log; private Random rng; internal readonly Dictionary<string, SceneConfig> sceneConfigs = new Dictionary<string, SceneConfig>(StringComparer.OrdinalIgnoreCase) { { "Tut_01", new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2", "top1" }) }, { "Tut_01b", new SceneConfig(new List<string> { "left1", "left2", "right1" }) }, { "Tut_02", new SceneConfig(new List<string> { "right1", "right2" }) }, { "Tut_03", new SceneConfig(new List<string> { "right1", "top1" }) }, { "Bonetown", new SceneConfig(new List<string> { "bot1", "bot2", "left1", "left2", "right1", "right2", "top1", "top2", "top3", "top4", "top5", "top6" }) }, { "Weave_02", new SceneConfig(new List<string> { "left2", "left3", "left4", "right1", "right2", "right3" }) }, { "Weave_03", new SceneConfig(new List<string> { "right1" }) }, { "Weave_04", new SceneConfig(new List<string> { "left1", "right2" }) }, { "Weave_05b", new SceneConfig(new List<string> { "left1" }) }, { "Weave_07", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Weave_08", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Weave_10", new SceneConfig(new List<string> { "left1" }) }, { "Weave_11", new SceneConfig(new List<string> { "right1", "top1" }) }, { "Weave_12", new SceneConfig(new List<string> { "left1" }) }, { "Weave_13", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Weave_14", new SceneConfig(new List<string> { "bot1" }) }, { "Bone_01", new SceneConfig(new List<string> { "left2", "right1", "right2", "top2" }) }, { "Bone_04", new SceneConfig(new List<string> { "bot2", "left1", "left2", "right1", "top1" }) }, { "Bone_05", new SceneConfig(new List<string> { "bot1", "left1", "right1" }) }, { "Bone_03", new SceneConfig(new List<string> { "bot1", "left1", "left2", "left4", "right1", "right3", "top1" }) }, { "Bone_05b", new SceneConfig(new List<string> { "left1", "top1" }) }, { "Bone_06", new SceneConfig(new List<string> { "bot1", "left1", "right1" }) }, { "Bone_07", new SceneConfig(new List<string> { "left1", "right1", "right2", "top1" }) }, { "Bone_08", new SceneConfig(new List<string> { "bot1", "left2", "left3", "right2", "right3" }) }, { "Bone_09", new SceneConfig(new List<string> { "left1", "right1", "right2", "top1" }) }, { "Bone_10", new SceneConfig(new List<string> { "bot1", "left1", "right1" }) }, { "Bone_11", new SceneConfig(new List<string> { "bot1", "left1", "right1", "right2", "top1" }) }, { "Bone_14", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Bone_15", new SceneConfig(new List<string> { "bot1", "left1" }) }, { "Bone_16", new SceneConfig(new List<string> { "left1", "right1", "top1" }) }, { "Bone_17", new SceneConfig(new List<string> { "right1" }) }, { "Bone_18", new SceneConfig(new List<string> { "left1" }) }, { "Bone_19", new SceneConfig(new List<string> { "bot1" }) }, { "Bone_East_01", new SceneConfig(new List<string> { "left1", "left2", "right1", "right2", "right3" }) }, { "Bone_East_02", new SceneConfig(new List<string> { "left1", "right1", "top1" }) }, { "Bone_East_04", new SceneConfig(new List<string> { "bot1", "left1", "right1", "right2", "top2" }) }, { "Bone_East_05", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Bone_East_07", new SceneConfig(new List<string> { "left1", "left2", "left3", "left4", "right1", "right2", "right3", "right4", "right5", "top1" }) }, { "Bone_East_09", new SceneConfig(new List<string> { "left2", "left3", "right1", "right2", "top1" }) }, { "Bone_East_10", new SceneConfig(new List<string> { "left1", "left2", "right1", "right2" }) }, { "Bone_East_11", new SceneConfig(new List<string> { "bot1", "left1", "right1", "right2" }) }, { "Bone_East_12", new SceneConfig(new List<string> { "bot1", "left1", "right1" }) }, { "Bone_East_13", new SceneConfig(new List<string> { "left1" }) }, { "Bone_East_14", new SceneConfig(new List<string> { "left1", "left2", "right1", "right2" }) }, { "Bone_East_15", new SceneConfig(new List<string> { "bot1", "left1", "right1" }) }, { "Bone_East_16", new SceneConfig(new List<string> { "bot1", "right1" }) }, { "Bone_East_17", new SceneConfig(new List<string> { "bot1", "left1", "right1" }) }, { "Bone_East_18", new SceneConfig(new List<string> { "left1", "right1", "top1" }) }, { "Bone_East_18b", new SceneConfig(new List<string> { "left1", "top1" }) }, { "Bone_East_18c", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Bone_East_20", new SceneConfig(new List<string> { "right1" }) }, { "Bone_East_22", new SceneConfig(new List<string> { "left1" }) }, { "Bone_East_24", new SceneConfig(new List<string> { "bot1", "left1", "right1" }) }, { "Bone_East_25", new SceneConfig(new List<string> { "left1" }) }, { "Bone_East_26", new SceneConfig(new List<string> { "bot1", "top1" }) }, { "Bone_East_27", new SceneConfig(new List<string> { "bot1", "left1", "right1" }) }, { "Bone_East_04c", new SceneConfig(new List<string> { "left1" }) }, { "Bone_East_04b", new SceneConfig(new List<string> { "left1", "right1", "top1" }) }, { "Bone_East_09b", new SceneConfig(new List<string> { "bot1", "left1", "top1" }) }, { "Bone_East_14b", new SceneConfig(new List<string> { "left1", "left2", "right1" }) }, { "Ant_02", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Ant_03", new SceneConfig(new List<string> { "left2", "right3" }) }, { "Ant_04", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Ant_04_left", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Ant_04_mid", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Ant_05b", new SceneConfig(new List<string> { "bot1", "bot2", "right1" }) }, { "Ant_05c", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Ant_09", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Ant_14", new SceneConfig(new List<string> { "left1", "left2", "left3", "left4", "left5", "right2", "right3" }) }, { "Ant_17", new SceneConfig(new List<string> { "right1" }) }, { "Ant_19", new SceneConfig(new List<string> { "left1" }) }, { "Ant_20", new SceneConfig(new List<string> { "left1" }) }, { "Ant_21", new SceneConfig(new List<string> { "right1" }) }, { "Ant_Merchant", new SceneConfig(new List<string> { "right1" }) }, { "Ant_Queen", new SceneConfig(new List<string> { "left1" }) }, { "Aspid_01", new SceneConfig(new List<string> { "bot1", "bot2", "bot3", "bot4", "bot5", "bot6", "bot7", "bot8", "left1", "left2", "right2", "right3", "right4", "top1", "top2", "top3", "top4", "top5", "top6", "top7" }) }, { "Belltown_04", new SceneConfig(new List<string> { "bot1", "left1", "left2" }) }, { "Belltown_06", new SceneConfig(new List<string> { "left1", "left3", "right1" }) }, { "Belltown_Room_shellwood", new SceneConfig(new List<string> { "left1" }) }, { "Belltown_Shrine", new SceneConfig(new List<string> { "right1", "top1" }) }, { "Belltown_basement_03", new SceneConfig(new List<string> { "left1", "top1" }) }, { "Bellshrine", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Bellshrine_03", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Bonegrave", new SceneConfig(new List<string> { "right1", "right2", "top1" }) }, { "Bone_01c", new SceneConfig(new List<string> { "left1", "left2", "right1" }) }, { "Bone_02", new SceneConfig(new List<string> { "left1", "right1", "top1", "top2" }) }, { "Bellshrine_05", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Bellway_03", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Greymoor_01", new SceneConfig(new List<string> { "bot1", "left1", "left2", "right1", "right2", "right3" }) }, { "Bellshrine_02", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Greymoor_02", new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2", "right3" }) }, { "Greymoor_15", new SceneConfig(new List<string> { "left1", "left3", "right2", "right3" }) }, { "Greymoor_15b", new SceneConfig(new List<string> { "left2", "left3", "right1", "top1" }) }, { "Room_CrowCourt", new SceneConfig(new List<string> { "bot1", "left1" }) }, { "Room_CrowCourt_02", new SceneConfig(new List<string> { "top1" }) }, { "Clover_01", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Greymoor_22", new SceneConfig(new List<string> { "bot1" }) }, { "Greymoor_12", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Greymoor_03", new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2", "right3", "right4", "right5" }) }, { "Dust_01", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Dust_02", new SceneConfig(new List<string> { "left1", "left2", "right1", "right2", "right3", "top1" }) }, { "Dust_03", new SceneConfig(new List<string> { "bot1", "left1", "top1" }) }, { "Dust_Chef", new SceneConfig(new List<string> { "bot1", "left1" }) }, { "Dust_04", new SceneConfig(new List<string> { "left1", "left2", "right1" }) }, { "Dust_Shack", new SceneConfig(new List<string> { "left1" }) }, { "Dust_10", new SceneConfig(new List<string> { "right1" }) }, { "Dust_05", new SceneConfig(new List<string> { "bot1", "left1", "right1" }) }, { "Dust_06", new SceneConfig(new List<string> { "left1", "right1", "right2", "right3" }) }, { "Dust_12", new SceneConfig(new List<string> { "left1" }) }, { "Dust_11", new SceneConfig(new List<string> { "bot1", "left1" }) }, { "Greymoor_17", new SceneConfig(new List<string> { "left1", "top1" }) }, { "Halfway_01", new SceneConfig(new List<string> { "bot1", "left1", "right1" }) }, { "Greymoor_04", new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2" }) }, { "Greymoor_11", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Greymoor_06", new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2", "right3", "right4", "top1" }) }, { "Greymoor_10", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Wisp_03", new SceneConfig(new List<string> { "right1", "top1" }) }, { "Wisp_06", new SceneConfig(new List<string> { "bot1" }) }, { "Greymoor_07", new SceneConfig(new List<string> { "bot1", "left1", "right1", "right2" }) }, { "Greymoor_20b", new SceneConfig(new List<string> { "right1" }) }, { "Greymoor_20c", new SceneConfig(new List<string> { "left1" }) }, { "Greymoor_08", new SceneConfig(new List<string> { "left2", "right1", "top1" }) }, { "Greymoor_16", new SceneConfig(new List<string> { "left1", "top1" }) }, { "Bellway_04", new SceneConfig(new List<string> { "bot1", "left1" }) }, { "Greymoor_05", new SceneConfig(new List<string> { "left1", "left2", "right1", "right2" }) }, { "Belltown", new SceneConfig(new List<string> { "left3", "right2" }) }, { "Memory_Needolin", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Belltown_07", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Shellwood_01", new SceneConfig(new List<string> { "left1", "left2", "right1", "right2" }) }, { "Shellwood_02", new SceneConfig(new List<string> { "left2", "left3", "right1", "right2" }) }, { "Shellwood_16", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Shellwood_03", new SceneConfig(new List<string> { "bot1", "left1", "left3", "right1", "right2", "right3" }) }, { "Shellwood_04b", new SceneConfig(new List<string> { "left1", "right1", "top1", "top2" }) }, { "Shellwood_08c", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Shellwood_04c", new SceneConfig(new List<string> { "bot1", "top1" }) }, { "Shellwood_08", new SceneConfig(new List<string> { "bot1", "left1", "right1" }) }, { "Coral_19", new SceneConfig(new List<string> { "bot1", "bot2", "bot3", "bot4", "bot5", "bot6", "bot7", "right1", "top1", "top2", "top3", "top4", "top5", "top6", "top7", "top8" }) }, { "Shellwood_19", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Shellwood_14", new SceneConfig(new List<string> { "left1" }) }, { "Shellwood_10", new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2", "right3" }) }, { "Shellwood_11", new SceneConfig(new List<string> { "right1", "right2" }) }, { "Shellwood_26", new SceneConfig(new List<string> { "bot1", "left1" }) }, { "Shellwood_18", new SceneConfig(new List<string> { "left1", "right1", "top1" }) }, { "Shellwood_13", new SceneConfig(new List<string> { "left1", "left2", "right1" }) }, { "Shellwood_01b", new SceneConfig(new List<string> { "left1", "left2", "right1", "right2", "right3" }) }, { "Shellwood_20", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Shellwood_Witch", new SceneConfig(new List<string> { "right1" }) }, { "Dock_08", new SceneConfig(new List<string> { "left1", "left2", "right1" }) }, { "Dock_01", new SceneConfig(new List<string> { "left1", "right1", "right2" }) }, { "Bellway_02", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Dock_16", new SceneConfig(new List<string> { "right1" }) }, { "Bone_East_03", new SceneConfig(new List<string> { "left1", "top1" }) }, { "Room_Forge", new SceneConfig(new List<string> { "left1", "right1", "top1" }) }, { "Dock_04", new SceneConfig(new List<string> { "left1", "right1", "right2", "right3" }) }, { "Dock_06_Church", new SceneConfig(new List<string> { "bot1", "right1" }) }, { "Dock_10", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Dock_15", new SceneConfig(new List<string> { "left1", "left2", "right1", "right2", "right3" }) }, { "Dock_13", new SceneConfig(new List<string> { "right1" }) }, { "Dock_11", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Dock_12", new SceneConfig(new List<string> { "left1" }) }, { "Dock_14", new SceneConfig(new List<string> { "left1" }) }, { "Dock_09", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Dock_02", new SceneConfig(new List<string> { "left1", "left2", "right1", "right2", "right3" }) }, { "Dock_02b", new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2" }) }, { "Dock_03c", new SceneConfig(new List<string> { "left2", "top1", "top2" }) }, { "Dock_03", new SceneConfig(new List<string> { "bot1", "left1", "right1" }) }, { "Dock_03b", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Shellwood_15", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Coral_19b", new SceneConfig(new List<string> { "bot1" }) }, { "Coral_02", new SceneConfig(new List<string> { "bot2", "right1" }) }, { "Coral_03", new SceneConfig(new List<string> { "bot1", "bot2", "bot3", "bot4", "bot5", "bot6", "left1", "left2", "left3", "right1", "right2", "right3" }) }, { "Coral_12", new SceneConfig(new List<string> { "left2", "left3", "right1" }) }, { "Coral_11", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Coral_11b", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Coral_34", new SceneConfig(new List<string> { "right1", "top1" }) }, { "Coral_25", new SceneConfig(new List<string> { "bot1", "right1" }) }, { "Coral_23", new SceneConfig(new List<string> { "left1", "left2", "right1" }) }, { "Coral_39", new SceneConfig(new List<string> { "right1" }) }, { "Coral_35b", new SceneConfig(new List<string> { "bot1", "left2", "left3", "left4", "left5", "right1", "right2" }) }, { "Coral_40", new SceneConfig(new List<string> { "right1" }) }, { "Coral_41", new SceneConfig(new List<string> { "right1" }) }, { "Coral_35", new SceneConfig(new List<string> { "left1", "left2", "right1", "right2", "top1" }) }, { "Coral_24", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Coral_26", new SceneConfig(new List<string> { "left1", "left2", "right1" }) }, { "Coral_38", new SceneConfig(new List<string> { "bot1", "left1", "right1" }) }, { "Coral_44", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Coral_29", new SceneConfig(new List<string> { "left1" }) }, { "Coral_27", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Coral_28", new SceneConfig(new List<string> { "right1" }) }, { "Coral_Tower_01", new SceneConfig(new List<string> { "left1" }) }, { "Coral_42", new SceneConfig(new List<string> { "right1" }) }, { "Coral_43", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Bellway_08", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Coral_32", new SceneConfig(new List<string> { "left1", "right1", "top1" }) }, { "Coral_Judge_Arena", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Coral_10", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Song_19_entrance", new SceneConfig(new List<string> { "left1", "right1", "right2" }) }, { "Song_01c", new SceneConfig(new List<string> { "left1", "top1" }) }, { "Song_01", new SceneConfig(new List<string> { "bot1", "right2", "top1" }) }, { "Under_07b", new SceneConfig(new List<string> { "bot1", "left1" }) }, { "Song_01b", new SceneConfig(new List<string> { "bot1", "right1", "top1" }) }, { "Song_05", new SceneConfig(new List<string> { "left3", "left4", "left5", "right2", "right3", "right4" }) }, { "Song_02", new SceneConfig(new List<string> { "left2", "right1" }) }, { "Ward_01", new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2", "right3" }) }, { "Ward_02", new SceneConfig(new List<string> { "bot1", "right1", "top1" }) }, { "Ward_02b", new SceneConfig(new List<string> { "bot1", "right1" }) }, { "Ward_03", new SceneConfig(new List<string> { "bot1", "left1", "top1" }) }, { "Ward_07", new SceneConfig(new List<string> { "bot1" }) }, { "Ward_06", new SceneConfig(new List<string> { "bot1", "top1" }) }, { "Song_07", new SceneConfig(new List<string> { "right1" }) }, { "Song_27", new SceneConfig(new List<string> { "left1", "right1", "top1" }) }, { "Song_20", new SceneConfig(new List<string> { "left1", "left2", "right4", "right5", "right6", "top1" }) }, { "Bellway_City", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Library_13", new SceneConfig(new List<string> { "left1", "right1", "right2" }) }, { "Song_11", new SceneConfig(new List<string> { "left1", "left2", "left3", "left4", "right1", "right2", "right3" }) }, { "Song_15", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Song_17", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Hang_01", new SceneConfig(new List<string> { "right1", "right2" }) }, { "Hang_02", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Hang_03", new SceneConfig(new List<string> { "left1", "left2", "right1", "right2", "top1" }) }, { "Hang_10", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Hang_03_top", new SceneConfig(new List<string> { "bot1" }) }, { "Hang_13", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Hang_08", new SceneConfig(new List<string> { "bot1", "left1", "left2", "left3", "left4", "right1" }) }, { "Hang_09", new SceneConfig(new List<string> { "right1" }) }, { "Hang_16", new SceneConfig(new List<string> { "right1" }) }, { "Hang_06", new SceneConfig(new List<string> { "bot1", "left1", "right1", "top1" }) }, { "Hang_06b", new SceneConfig(new List<string> { "left1" }) }, { "Hang_17b", new SceneConfig(new List<string> { "left1" }) }, { "Hang_04", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Hang_12", new SceneConfig(new List<string> { "right1" }) }, { "Hang_07", new SceneConfig(new List<string> { "bot1", "left1", "right1", "top1" }) }, { "Song_09", new SceneConfig(new List<string> { "bot1", "right1", "top1" }) }, { "Song_09b", new SceneConfig(new List<string> { "left1", "top1" }) }, { "Cog_05", new SceneConfig(new List<string> { "left1", "right2", "top1" }) }, { "Cog_Dancers", new SceneConfig(new List<string> { "bot1", "bot2", "left1", "right1", "top1" }) }, { "Cog_04", new SceneConfig(new List<string> { "left2", "right2", "right3", "top1", "top2" }) }, { "Cog_Bench", new SceneConfig(new List<string> { "left1" }) }, { "Song_25", new SceneConfig(new List<string> { "bot1", "left1", "right1", "top1", "top2" }) }, { "Song_Enclave", new SceneConfig(new List<string> { "bot1", "left1", "left2", "top1" }) }, { "Song_Enclave_Tube", new SceneConfig(new List<string> { "bot1" }) }, { "Under_01", new SceneConfig(new List<string> { "left1", "left2", "left3", "right1" }) }, { "Under_27", new SceneConfig(new List<string> { "left1", "right1", "right2" }) }, { "Shellwood_22", new SceneConfig(new List<string> { "right1" }) }, { "Shellwood_11b", new SceneConfig(new List<string> { "right1" }) }, { "Under_01b", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Under_02", new SceneConfig(new List<string> { "left1", "left3", "right1", "right2", "right3", "right4" }) }, { "Under_14", new SceneConfig(new List<string> { "left1" }) }, { "Under_16", new SceneConfig(new List<string> { "right1" }) }, { "Under_03b", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Under_07", new SceneConfig(new List<string> { "left3", "right2" }) }, { "Under_07c", new SceneConfig(new List<string> { "left2", "top1" }) }, { "Under_06", new SceneConfig(new List<string> { "left1", "right1", "top1" }) }, { "Under_08", new SceneConfig(new List<string> { "bot1", "top1" }) }, { "Under_05", new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2", "right3" }) }, { "Under_11", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Under_23", new SceneConfig(new List<string> { "bot1", "right1" }) }, { "Wisp_09", new SceneConfig(new List<string> { "right1", "top1" }) }, { "Wisp_05", new SceneConfig(new List<string> { "bot1", "left1" }) }, { "Wisp_02", new SceneConfig(new List<string> { "left1", "right1", "top1" }) }, { "Belltown_08", new SceneConfig(new List<string> { "right1" }) }, { "Wisp_04", new SceneConfig(new List<string> { "bot1", "left1", "right1" }) }, { "Wisp_08", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Wisp_07", new SceneConfig(new List<string> { "left1" }) }, { "Under_04", new SceneConfig(new List<string> { "left1", "right1", "top1" }) }, { "Under_03c", new SceneConfig(new List<string> { "left1", "left2", "right1" }) }, { "Under_03", new SceneConfig(new List<string> { "right1" }) }, { "Under_10", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Under_12", new SceneConfig(new List<string> { "left1" }) }, { "Under_13", new SceneConfig(new List<string> { "left1", "left2", "left3", "left4", "right1", "right2", "right3" }) }, { "Under_22", new SceneConfig(new List<string> { "right1" }) }, { "Under_21", new SceneConfig(new List<string> { "right1" }) }, { "Under_19", new SceneConfig(new List<string> { "left1", "top1" }) }, { "Under_19c", new SceneConfig(new List<string> { "bot1", "left1", "left2" }) }, { "Under_19b", new SceneConfig(new List<string> { "right1" }) }, { "Under_18", new SceneConfig(new List<string> { "left1", "right1", "top1", "top2" }) }, { "Under_17", new SceneConfig(new List<string> { "bot1", "bot2", "left1", "right1", "top1" }) }, { "Library_11b", new SceneConfig(new List<string> { "left3", "right1" }) }, { "Library_11", new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2" }) }, { "Library_13b", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Library_04", new SceneConfig(new List<string> { "left1", "left2", "left3", "left4", "right1", "right2", "right3", "right4", "right5", "right6", "top1" }) }, { "Library_16", new SceneConfig(new List<string> { "right1" }) }, { "Library_10", new SceneConfig(new List<string> { "bot1", "left1" }) }, { "Library_12b", new SceneConfig(new List<string> { "left1", "top1" }) }, { "Library_12", new SceneConfig(new List<string> { "left1", "left2", "right1" }) }, { "Library_05", new SceneConfig(new List<string> { "left1", "left2", "right1", "right2" }) }, { "Library_06", new SceneConfig(new List<string> { "left1", "left2", "right1" }) }, { "Library_07", new SceneConfig(new List<string> { "bot1", "bot2", "bot3", "left1", "left2", "top1" }) }, { "Library_08", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Library_09", new SceneConfig(new List<string> { "bot1", "left1" }) }, { "Library_14", new SceneConfig(new List<string> { "left1" }) }, { "Library_01", new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2" }) }, { "Library_15", new SceneConfig(new List<string> { "right1" }) }, { "Library_03", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Song_24", new SceneConfig(new List<string> { "right1" }) }, { "Song_20b", new SceneConfig(new List<string> { "bot1", "left2", "left4", "right2", "right3", "top1" }) }, { "Library_02", new SceneConfig(new List<string> { "left1", "left2", "right1", "right2" }) }, { "Song_29", new SceneConfig(new List<string> { "right1" }) }, { "Arborium_01", new SceneConfig(new List<string> { "bot1", "left1", "left2", "left3", "right1", "right2", "right3", "right4", "right5" }) }, { "Cog_10", new SceneConfig(new List<string> { "bot1" }) }, { "Cog_07", new SceneConfig(new List<string> { "left1" }) }, { "Cog_06", new SceneConfig(new List<string> { "left2", "right1" }) }, { "Arborium_04", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Arborium_03", new SceneConfig(new List<string> { "left1", "left2", "left3", "left4", "right1", "right2" }) }, { "Arborium_02", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Arborium_05", new SceneConfig(new List<string> { "right1", "top1" }) }, { "Arborium_06", new SceneConfig(new List<string> { "bot1", "left1", "right1" }) }, { "Arborium_09", new SceneConfig(new List<string> { "right1", "right2" }) }, { "Arborium_Tube", new SceneConfig(new List<string> { "right1" }) }, { "Arborium_07", new SceneConfig(new List<string> { "left1", "top1" }) }, { "Arborium_08", new SceneConfig(new List<string> { "bot1", "left1" }) }, { "Song_13", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Song_18", new SceneConfig(new List<string> { "bot1", "left1" }) }, { "Song_03", new SceneConfig(new List<string> { "bot1", "top1" }) }, { "Song_04", new SceneConfig(new List<string> { "bot1", "left1", "right1", "right2" }) }, { "Song_10", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Song_12", new SceneConfig(new List<string> { "left1", "left2", "left3", "left4", "right1", "right2", "right3" }) }, { "Song_14", new SceneConfig(new List<string> { "left1" }) }, { "Song_26", new SceneConfig(new List<string> { "right1" }) }, { "Song_28", new SceneConfig(new List<string> { "right1" }) }, { "Song_08", new SceneConfig(new List<string> { "right1" }) }, { "Slab_01", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Slab_02", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Slab_03", new SceneConfig(new List<string> { "left1", "left2", "left3", "left4", "left5", "left6", "left7", "left8", "right1", "right2", "right3", "right4", "right5", "right7", "right8", "right9" }) }, { "Slab_04", new SceneConfig(new List<string> { "bot1", "right1", "top1" }) }, { "Slab_23", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Slab_21", new SceneConfig(new List<string> { "left1", "left3", "top1" }) }, { "Slab_22", new SceneConfig(new List<string> { "bot1", "bot2" }) }, { "Slab_Cell_Creature", new SceneConfig(new List<string> { "left1" }) }, { "Slab_20", new SceneConfig(new List<string> { "left1" }) }, { "Slab_17", new SceneConfig(new List<string> { "left1" }) }, { "Slab_18", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Slab_16", new SceneConfig(new List<string> { "bot1", "left1", "right1", "top1" }) }, { "Slab_15", new SceneConfig(new List<string> { "bot1", "left1", "right1", "top1" }) }, { "Peak_01", new SceneConfig(new List<string> { "left1", "left2", "left3", "left4", "right1", "right2", "right3", "right4", "top1", "top2", "top3", "top4" }) }, { "Slab_14", new SceneConfig(new List<string> { "right1", "top1" }) }, { "Slab_13", new SceneConfig(new List<string> { "bot1", "left1", "right1" }) }, { "Slab_05", new SceneConfig(new List<string> { "bot1", "right1", "top1" }) }, { "Slab_06", new SceneConfig(new List<string> { "left1", "top1" }) }, { "Peak_07", new SceneConfig(new List<string> { "bot1", "bot2", "bot3", "bot4", "bot5", "top1", "top2" }) }, { "Peak_08b", new SceneConfig(new List<string> { "bot4", "bot5", "bot6", "left1", "left2" }) }, { "Peak_08", new SceneConfig(new List<string> { "bot1", "right1", "top1" }) }, { "Peak_05d", new SceneConfig(new List<string> { "bot1" }) }, { "Peak_05", new SceneConfig(new List<string> { "bot1", "right3", "top2" }) }, { "Peak_05c", new SceneConfig(new List<string> { "left2", "right1" }) }, { "Peak_05e", new SceneConfig(new List<string> { "left1", "right1", "right2" }) }, { "Peak_06b", new SceneConfig(new List<string> { "left1" }) }, { "Peak_02", new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2", "right3", "right4" }) }, { "Peak_04d", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Peak_04", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Bellway_Peak", new SceneConfig(new List<string> { "left1", "left2", "right1", "right2", "top1" }) }, { "Bellway_Peak_02", new SceneConfig(new List<string> { "left1" }) }, { "Peak_04c", new SceneConfig(new List<string> { "right1", "right2" }) }, { "Peak_10", new SceneConfig(new List<string> { "right1" }) }, { "Slab_08", new SceneConfig(new List<string> { "left1" }) }, { "Slab_Cell_Quiet", new SceneConfig(new List<string> { "left1", "left2" }) }, { "Slab_19b", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Slab_07", new SceneConfig(new List<string> { "right1", "right2" }) }, { "Slab_12", new SceneConfig(new List<string> { "left1" }) }, { "Slab_10c", new SceneConfig(new List<string> { "left1" }) }, { "Slab_10b", new SceneConfig(new List<string> { "left1" }) }, { "Cog_10_Destroyed", new SceneConfig(new List<string> { "bot1", "left1" }) }, { "Cog_09_Destroyed", new SceneConfig(new List<string> { "right1", "top1" }) }, { "Song_Tower_Destroyed", new SceneConfig(new List<string> { "bot1", "top1" }) }, { "Arborium_10", new SceneConfig(new List<string> { "left1" }) }, { "Arborium_11", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Aqueduct_01", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Aqueduct_02", new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2", "right3" }) }, { "Bellway_Aqueduct", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Aqueduct_07", new SceneConfig(new List<string> { "right1" }) }, { "Aqueduct_04", new SceneConfig(new List<string> { "bot1", "right1" }) }, { "Aqueduct_03", new SceneConfig(new List<string> { "left1", "right1", "top1" }) }, { "Aqueduct_06", new SceneConfig(new List<string> { "bot1", "left1", "left2" }) }, { "Aqueduct_08", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Aqueduct_05", new SceneConfig(new List<string> { "left1" }) }, { "Shadow_01", new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2", "right3", "top1" }) }, { "Shadow_18", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Shadow_12", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Shadow_19", new SceneConfig(new List<string> { "left1", "left2", "right1", "right2" }) }, { "Shadow_24", new SceneConfig(new List<string> { "left1" }) }, { "Shadow_10", new SceneConfig(new List<string> { "bot1", "left1", "right1" }) }, { "Shadow_25", new SceneConfig(new List<string> { "left1" }) }, { "Shadow_08", new SceneConfig(new List<string> { "left1", "top1" }) }, { "Shadow_27", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Shadow_26", new SceneConfig(new List<string> { "left1", "left2", "right1", "right2" }) }, { "Shadow_16", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Shadow_15", new SceneConfig(new List<string> { "right1", "right2" }) }, { "Shadow_14", new SceneConfig(new List<string> { "right1", "right2" }) }, { "Shadow_02", new SceneConfig(new List<string> { "left1", "left2", "right1", "right2", "right3" }) }, { "Shadow_11", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Shadow_13", new SceneConfig(new List<string> { "left1" }) }, { "Shadow_23", new SceneConfig(new List<string> { "left1" }) }, { "Shadow_03", new SceneConfig(new List<string> { "left1", "right1", "top1" }) }, { "Shadow_21", new SceneConfig(new List<string> { "bot1" }) }, { "Shadow_09", new SceneConfig(new List<string> { "left1", "left2", "left3", "right1" }) }, { "Shadow_Weavehome", new SceneConfig(new List<string> { "left1" }) }, { "Shadow_05", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Shadow_04b", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Shadow_04", new SceneConfig(new List<string> { "left1", "right1", "right2", "top1" }) }, { "Shadow_20", new SceneConfig(new List<string> { "bot1", "top1" }) }, { "Bellway_Shadow", new SceneConfig(new List<string> { "left1" }) }, { "Tube_Hub", new SceneConfig(new List<string> { "left1", "left3", "left4" }) }, { "Cradle_01", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Cradle_02", new SceneConfig(new List<string> { "left2", "right1", "right2" }) }, { "Cradle_02b", new SceneConfig(new List<string> { "right1" }) }, { "Cradle_03", new SceneConfig(new List<string> { "left2", "right2" }) }, { "Crawl_04", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Crawl_02", new SceneConfig(new List<string> { "left1", "left2", "right1", "right2", "right3" }) }, { "Crawl_06", new SceneConfig(new List<string> { "left1" }) }, { "Crawl_01", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Crawl_03", new SceneConfig(new List<string> { "bot1", "left1", "right1", "top1" }) }, { "Crawl_08", new SceneConfig(new List<string> { "bot1" }) }, { "Crawl_05", new SceneConfig(new List<string> { "right1" }) }, { "Crawl_03b", new SceneConfig(new List<string> { "bot1", "right1", "top1" }) }, { "Crawl_07", new SceneConfig(new List<string> { "bot1", "left1", "top1" }) }, { "Crawl_09", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Crawl_10", new SceneConfig(new List<string> { "right1" }) }, { "Abyss_12", new SceneConfig(new List<string> { "left1", "right2" }) }, { "Abyss_05", new SceneConfig(new List<string> { "left2", "right1" }) }, { "Abyss_08", new SceneConfig(new List<string> { "left1" }) }, { "Abyss_07", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Abyss_01", new SceneConfig(new List<string> { "left1", "right2", "right3", "right4" }) }, { "Abyss_06", new SceneConfig(new List<string> { "right1" }) }, { "Abyss_04", new SceneConfig(new List<string> { "left1" }) }, { "Abyss_02b", new SceneConfig(new List<string> { "left2", "right1", "top1" }) }, { "Abyss_02", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Abyss_03", new SceneConfig(new List<string> { "left1", "left2" }) }, { "Abyss_13", new SceneConfig(new List<string> { "left1", "right1", "top1" }) }, { "Abyss_11", new SceneConfig(new List<string> { "bot1", "right1" }) }, { "Abyss_09", new SceneConfig(new List<string> { "bot1", "top1" }) }, { "Greymoor_13", new SceneConfig(new List<string> { "bot1", "left1", "right1" }) }, { "Clover_01b", new SceneConfig(new List<string> { "right1" }) }, { "Clover_02c", new SceneConfig(new List<string> { "left1", "left2", "right1" }) }, { "Clover_05c", new SceneConfig(new List<string> { "left1", "left2", "right1", "right2", "right3" }) }, { "Clover_21", new SceneConfig(new List<string> { "right1" }) }, { "Clover_16", new SceneConfig(new List<string> { "right1", "top1" }) }, { "Clover_06", new SceneConfig(new List<string> { "bot1", "bot2" }) }, { "Clover_19", new SceneConfig(new List<string> { "left1", "top1" }) }, { "Clover_04b", new SceneConfig(new List<string> { "left1", "left2", "right1" }) }, { "Clover_11", new SceneConfig(new List<string> { "right1" }) }, { "Clover_03", new SceneConfig(new List<string> { "left1", "left2", "right1" }) }, { "Clover_18", new SceneConfig(new List<string> { "left1" }) }, { "Tut_04", new SceneConfig(new List<string> { "left1", "right1" }) }, { "Cog_09", new SceneConfig(new List<string> { "bot1" }) }, { "Cog_08", new SceneConfig(new List<string> { "bot1", "top1" }) } }; private string lastEntryGateUsed = null; private string previousSceneName = null; private string currentSceneName = "(unknown)"; private bool isTransitioning = false; private bool loadRequested = false; public static bool SuppressTransitionPatch; private bool autoDiscoveryMode = false; private HashSet<string> discoveredScenes = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private string discoveryFilePath; private readonly List<string> preferredSceneSubstrings = new List<string>(); private WaitForSeconds waitHalfSecond; private WaitForSeconds waitThirdSecond; private WaitForSeconds waitTenthSecond; private WaitForSeconds waitFifthSecond; private GUIStyle sceneLabelStyle; private string cachedSceneLabel = ""; private string lastRenderedScene = ""; private ConfigEntry<bool> cfgShowSceneLabel; private ConfigEntry<string> cfgTeleportScene; private ConfigEntry<bool> cfgTeleportConfirm; private HashSet<string> visitedScenesF6 = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private void LoadRandomUniqueScene() { if (isTransitioning) { log.LogInfo((object)"LoadRandomUniqueScene skipped: transition already in progress"); return; } List<string> list = sceneConfigs.Keys.Where((string k) => !string.Equals(k, currentSceneName, StringComparison.OrdinalIgnoreCase) && !visitedScenesF6.Contains(k)).ToList(); if (list.Count == 0) { log.LogInfo((object)"F6: All scenes have been visited already (or no candidates available). Clearing visited list."); return; } List<string> list2 = null; try { List<string> lowered = (from s in preferredSceneSubstrings where !string.IsNullOrWhiteSpace(s) select s.ToLower()).ToList(); list2 = list.Where((string c) => lowered.Any((string sub) => c.ToLower().Contains(sub))).ToList(); } catch { } List<string> list3 = ((list2 != null && list2.Count > 0) ? list2 : list); string text = list3[rng.Next(list3.Count)]; SceneConfig sceneConfig = (sceneConfigs.ContainsKey(text) ? sceneConfigs[text] : null); string text2 = null; if (sceneConfig != null && sceneConfig.Exits != null && sceneConfig.Exits.Count > 0) { text2 = sceneConfig.Exits[rng.Next(sceneConfig.Exits.Count)]; } visitedScenesF6.Add(text); lastEntryGateUsed = text2; log.LogInfo((object)("[F6] Selected unique random scene: " + text + " (enter via gate '" + (text2 ?? "(null)") + "')")); SuppressTransitionPatch = true; ((MonoBehaviour)this).StartCoroutine(LoadSceneCoroutine(text, text2)); } private void Awake() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_003b: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Expected O, but got Unknown //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Expected O, but got Unknown //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Expected O, but got Unknown log = ((BaseUnityPlugin)this).Logger; rng = new Random(); Scene activeScene = SceneManager.GetActiveScene(); currentSceneName = ((Scene)(ref activeScene)).name; waitHalfSecond = new WaitForSeconds(0.5f); waitThirdSecond = new WaitForSeconds(0.3f); waitTenthSecond = new WaitForSeconds(0.1f); waitFifthSecond = new WaitForSeconds(0.2f); sceneLabelStyle = new GUIStyle(); try { cfgShowSceneLabel = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "ShowSceneLabel", true, "Show small scene label in upper-left (toggle)"); } catch { } try { cfgTeleportScene = ((BaseUnityPlugin)this).Config.Bind<string>("Teleport", "TeleportScene", "", "Scene name to teleport to (type exact scene name)"); cfgTeleportConfirm = ((BaseUnityPlugin)this).Config.Bind<bool>("Teleport", "TeleportConfirm", false, "Set to true to teleport to scene in TeleportScene (resets automatically)"); } catch { } discoveryFilePath = Path.Combine(Paths.PluginPath, "discovered_exits.txt"); log.LogInfo((object)("RandomSceneLoader loaded. Current scene: " + currentSceneName + ". F5=random, F7=discover")); try { if (sceneConfigs != null) { discoveredScenes.UnionWith(sceneConfigs.Keys); log.LogInfo((object)$"Preloaded {discoveredScenes.Count} known scenes into discovered set"); } } catch { } if (autoDiscoveryMode) { log.LogInfo((object)("Auto-discovery mode enabled. RoomRando disabled. Results saved to: " + discoveryFilePath)); return; } try { Harmony val = new Harmony("com.yourname.randomsceneloader"); val.PatchAll(); log.LogInfo((object)"Harmony patches applied successfully"); } catch (Exception ex) { log.LogError((object)("Failed to apply Harmony patches: " + ex.Message)); } try { if ((Object)(object)GameObject.Find("__RoomRando") == (Object)null) { GameObject val2 = new GameObject("__RoomRando"); val2.AddComponent<RoomRando>(); Object.DontDestroyOnLoad((Object)(object)val2); } } catch (Exception ex2) { log.LogError((object)("Failed to create RoomRando: " + ex2.Message)); } try { if ((Object)(object)GameObject.Find("__SeedManager") == (Object)null) { GameObject val3 = new GameObject("__SeedManager"); val3.AddComponent<SeedManager>(); Object.DontDestroyOnLoad((Object)(object)val3); } } catch (Exception ex3) { log.LogError((object)("Failed to create SeedManager: " + ex3.Message)); } } private void OnEnable() { SceneManager.sceneLoaded += OnSceneLoaded; SceneManager.activeSceneChanged += OnActiveSceneChanged; } private void OnDisable() { SceneManager.sceneLoaded -= OnSceneLoaded; SceneManager.activeSceneChanged -= OnActiveSceneChanged; } private void Update() { if (Input.GetKeyDown((KeyCode)286)) { LoadRandomScene(); } if (Input.GetKeyDown((KeyCode)288)) { DiscoverGatesInCurrentScene(); } try { if (cfgTeleportConfirm != null && cfgTeleportConfirm.Value) { string text = ((cfgTeleportScene != null) ? cfgTeleportScene.Value : string.Empty); if (!string.IsNullOrEmpty(text)) { TeleportToScene(text); } else { log.LogWarning((object)"TeleportScene is empty in config."); } cfgTeleportConfirm.Value = false; } } catch { } } private void TeleportToScene(string sceneName) { try { if (isTransitioning) { log.LogInfo((object)"Teleport skipped: transition already in progress"); return; } if (string.IsNullOrWhiteSpace(sceneName)) { log.LogWarning((object)"TeleportToScene called with empty scene name"); return; } string text = null; if (sceneConfigs != null && sceneConfigs.TryGetValue(sceneName, out var value)) { if (value.Exits != null && value.Exits.Count > 0) { text = value.Exits[rng.Next(value.Exits.Count)]; } } else { log.LogWarning((object)("TeleportToScene: scene '" + sceneName + "' not found in sceneConfigs. Attempting direct load.")); } log.LogInfo((object)("Teleport: " + sceneName + " (entry '" + (text ?? "(null)") + "')")); SuppressTransitionPatch = true; ((MonoBehaviour)this).StartCoroutine(LoadSceneCoroutine(sceneName, text)); } catch (Exception arg) { log.LogError((object)$"TeleportToScene failed: {arg}"); } } private void DiscoverGatesInCurrentScene() { //IL_010b: Unknown result type (might be due to invalid IL or missing references) log.LogInfo((object)"=== DISCOVERING GATES ==="); log.LogInfo((object)("Scene: " + currentSceneName)); try { GameObject[] source = Object.FindObjectsByType<GameObject>((FindObjectsSortMode)0); List<GameObject> list = source.Where(delegate(GameObject obj) { string text2 = ((Object)obj).name.ToLower(); return (text2.StartsWith("left") || text2.StartsWith("right") || text2.StartsWith("top") || text2.StartsWith("bot")) && text2.Length <= 6 && char.IsDigit(text2[text2.Length - 1]); }).ToList(); log.LogInfo((object)$"Found {list.Count} gates:"); IOrderedEnumerable<IGrouping<string, GameObject>> orderedEnumerable = from g in list group g by ((Object)g).name into g orderby g.Key select g; foreach (IGrouping<string, GameObject> item in orderedEnumerable) { log.LogInfo((object)$" - {item.Key} (count: {item.Count()}, pos: {item.First().transform.position})"); } List<string> list2 = orderedEnumerable.Select((IGrouping<string, GameObject> g) => g.Key).ToList(); if (list2.Count > 0) { string text = "{ \"" + currentSceneName + "\", new SceneConfig(new List<string> { " + string.Join(", ", list2.Select((string e) => "\"" + e + "\"")) + " }) },"; log.LogInfo((object)("Suggested: " + text)); if (autoDiscoveryMode) { SaveDiscoveryToFile(currentSceneName, list2, text); } } } catch (Exception ex) { log.LogError((object)("DiscoverGates failed: " + ex.Message)); } } private void SaveDiscoveryToFile(string sceneName, List<string> exitNames, string configLine) { try { if (!discoveredScenes.Contains(sceneName)) { if (sceneConfigs != null && sceneConfigs.ContainsKey(sceneName)) { log.LogInfo((object)("Discovery skipped for " + sceneName + ": already exists in sceneConfigs.")); discoveredScenes.Add(sceneName); return; } discoveredScenes.Add(sceneName); string text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); string text2 = "\n[" + text + "] " + sceneName + "\n"; text2 = text2 + " Gates found: " + string.Join(", ", exitNames) + "\n"; text2 = text2 + " Config: " + configLine + "\n"; File.AppendAllText(discoveryFilePath, text2); log.LogInfo((object)$"Saved discovery for {sceneName} to file ({exitNames.Count} exits)"); } } catch (Exception ex) { log.LogError((object)("Failed to save discovery to file: " + ex.Message)); } } private void LoadRandomScene() { if (isTransitioning) { log.LogInfo((object)"LoadRandomScene skipped: transition already in progress"); return; } loadRequested = true; List<string> list = sceneConfigs.Keys.Where((string k) => !string.Equals(k, currentSceneName, StringComparison.OrdinalIgnoreCase)).ToList(); if (list.Count == 0) { log.LogWarning((object)"No candidate scenes found in sceneConfigs."); return; } List<string> list2 = null; try { List<string> lowered = (from s in preferredSceneSubstrings where !string.IsNullOrWhiteSpace(s) select s.ToLower()).ToList(); list2 = list.Where((string c) => lowered.Any((string sub) => c.ToLower().Contains(sub))).ToList(); } catch { } List<string> list3 = ((list2 != null && list2.Count > 0) ? list2 : list); string text = list3[rng.Next(list3.Count)]; SceneConfig sceneConfig = (sceneConfigs.ContainsKey(text) ? sceneConfigs[text] : null); string text2 = null; if (sceneConfig != null && sceneConfig.Exits != null && sceneConfig.Exits.Count > 0) { text2 = sceneConfig.Exits[rng.Next(sceneConfig.Exits.Count)]; } lastEntryGateUsed = text2; log.LogInfo((object)("Selected random scene: " + text + " (enter via gate '" + (text2 ?? "(null)") + "')")); SuppressTransitionPatch = true; ((MonoBehaviour)this).StartCoroutine(LoadSceneCoroutine(text, text2)); } [IteratorStateMachine(typeof(<LoadSceneCoroutine>d__34))] private IEnumerator LoadSceneCoroutine(string sceneName, string entryGate) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadSceneCoroutine>d__34(0) { <>4__this = this, sceneName = sceneName, entryGate = entryGate }; } public void SetLastEntryGate(string gateName) { lastEntryGateUsed = gateName; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { currentSceneName = ((Scene)(ref scene)).name; cachedSceneLabel = "Scene: " + currentSceneName; lastRenderedScene = currentSceneName; log.LogInfo((object)("Scene loaded: " + currentSceneName)); if (autoDiscoveryMode) { ((MonoBehaviour)this).StartCoroutine(AutoDiscoverAfterLoad()); } else { ((MonoBehaviour)this).StartCoroutine(DetectEntryGateAfterLoad()); } } [IteratorStateMachine(typeof(<AutoDiscoverAfterLoad>d__37))] private IEnumerator AutoDiscoverAfterLoad() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <AutoDiscoverAfterLoad>d__37(0) { <>4__this = this }; } [IteratorStateMachine(typeof(<DetectEntryGateAfterLoad>d__38))] private IEnumerator DetectEntryGateAfterLoad() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DetectEntryGateAfterLoad>d__38(0) { <>4__this = this }; } private void OnActiveSceneChanged(Scene prev, Scene next) { previousSceneName = currentSceneName; currentSceneName = ((Scene)(ref next)).name; try { GameObject obj = GameObject.Find("__RoomRando"); RoomRando roomRando = ((obj != null) ? obj.GetComponent<RoomRando>() : null); if ((Object)(object)roomRando != (Object)null && !string.IsNullOrEmpty(previousSceneName) && !string.IsNullOrEmpty(lastEntryGateUsed)) { roomRando.OnExitUsed(previousSceneName, lastEntryGateUsed); } } catch (Exception ex) { log.LogWarning((object)("RoomRando notify failed: " + ex.Message)); } lastEntryGateUsed = null; } private void OnGUI() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_0067: Expected O, but got Unknown //IL_00d0: Unknown result type (might be due to invalid IL or missing references) try { if (sceneLabelStyle.normal.textColor != Color.white || sceneLabelStyle.fontSize != 14) { GUIStyle val = new GUIStyle(GUI.skin.label); val.normal.textColor = Color.white; val.fontSize = 14; sceneLabelStyle = val; } if (cfgShowSceneLabel == null || cfgShowSceneLabel.Value) { if (currentSceneName != lastRenderedScene) { cachedSceneLabel = "Scene: " + currentSceneName; lastRenderedScene = currentSceneName; } GUI.Label(new Rect(8f, 8f, 300f, 20f), cachedSceneLabel, sceneLabelStyle); } } catch { } } } public class RoomRando : MonoBehaviour { [CompilerGenerated] private sealed class <WaitForSceneLoader>d__10 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public RoomRando <>4__this; private int <frame>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WaitForSceneLoader>d__10(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <frame>5__1 = 0; break; case 1: <>1__state = -1; break; } if (<frame>5__1++ < 300) { <>4__this.sceneLoader = Object.FindAnyObjectByType<RandomSceneLoader>(); if (!((Object)(object)<>4__this.sceneLoader != (Object)null)) { <>2__current = null; <>1__state = 1; return true; } } if ((Object)(object)<>4__this.sceneLoader == (Object)null) { Debug.LogWarning((object)"RoomRando: timed out waiting for RandomSceneLoader; initialization aborted."); return false; } Debug.Log((object)"RoomRando: found RandomSceneLoader after waiting; continuing initialization."); <>4__this.InitializeRoomRando(); 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(); } } private Dictionary<string, (string targetScene, string targetGate)> connections = new Dictionary<string, (string, string)>(StringComparer.OrdinalIgnoreCase); private List<string> availableScenes = new List<string>(); private bool enableRandomization = true; private RandomSceneLoader sceneLoader; private string saveFilePath; private Random rng = null; private int generationSeed = 0; private bool enableMapGeneration = false; private List<(string beforeScene, string afterScene)> precedencePairs = new List<(string, string)>(); private bool forceExactSeed = false; private void Awake() { sceneLoader = Object.FindAnyObjectByType<RandomSceneLoader>(); if ((Object)(object)sceneLoader == (Object)null) { Debug.LogWarning((object)"RoomRando: RandomSceneLoader not found in Awake; will retry for a short time."); ((MonoBehaviour)this).StartCoroutine(WaitForSceneLoader()); } else { InitializeRoomRando(); } } [IteratorStateMachine(typeof(<WaitForSceneLoader>d__10))] private IEnumerator WaitForSceneLoader() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WaitForSceneLoader>d__10(0) { <>4__this = this }; } private void InitializeRoomRando() { try { availableScenes = sceneLoader.sceneConfigs.Keys.ToList(); } catch (Exception ex) { Debug.LogWarning((object)("RoomRando: failed to populate availableScenes from sceneLoader: " + ex.Message)); } InitializePredefinedConnections(); try { saveFilePath = Path.Combine(Paths.PluginPath, "roomrando_connections.txt"); } catch { saveFilePath = "roomrando_connections.txt"; } Debug.Log((object)$"RoomRando: saveFilePath set to '{saveFilePath}' (exists={File.Exists(saveFilePath)})"); if (enableRandomization) { if (TryLoadConnectionsFromFile()) { Debug.Log((object)("RoomRando: loaded randomized connections from " + saveFilePath)); } else { GenerateAllConnectionsAtStart(); SaveConnectionsToFile(); } if (enableMapGeneration) { TryGenerateMap(); } } } private void GenerateAllConnectionsAtStart() { int num = ((generationSeed == 0) ? Environment.TickCount : generationSeed); int finalConnectionCount = 0; RandomSceneLoader.SceneConfig value7; List<string> list = availableScenes.Where((string s) => (Object)(object)sceneLoader != (Object)null && sceneLoader.sceneConfigs.TryGetValue(s, out value7) && value7.Exits != null && value7.Exits.Count > 0).ToList(); Debug.Log((object)$"RoomRando: {list.Count} scenes have defined exits"); bool flag = false; int num2 = (forceExactSeed ? 1 : 8); for (int i = 0; i < num2; i++) { if (flag) { break; } int num3 = (forceExactSeed ? num : (num + i)); rng = new Random(num3); connections.Clear(); finalConnectionCount = 0; Debug.Log((object)$"RoomRando: generation attempt {i + 1}/{8} using seed={num3}"); InitializePredefinedConnections(); Dictionary<string, List<string>> freeExits = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase); foreach (string item5 in list) { freeExits[item5] = new List<string>(sceneLoader.sceneConfigs[item5].Exits); } foreach (KeyValuePair<string, (string, string)> item6 in connections.ToList()) { string key = item6.Key; int num4 = key.LastIndexOf('_'); if (num4 > 0) { string key2 = key.Substring(0, num4); string item = key.Substring(num4 + 1); if (freeExits.ContainsKey(key2)) { freeExits[key2].Remove(item); } } } try { foreach (var (text, text2) in precedencePairs) { if (!string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(text2) && freeExits.ContainsKey(text) && freeExits.ContainsKey(text2) && freeExits[text].Count != 0 && freeExits[text2].Count != 0) { ConnectScenes(text, text2); } } } catch (Exception ex) { Debug.LogWarning((object)("RoomRando: failed applying precedence pairs: " + ex.Message)); } List<string> list2 = list.OrderBy((string _) => rng.Next()).ToList(); for (int j = 1; j < list2.Count; j++) { string text3 = null; string text4 = null; for (int num5 = j - 1; num5 >= 0; num5--) { if (freeExits[list2[num5]].Count > 0) { text3 = list2[num5]; break; } } for (int k = j; k < list2.Count; k++) { if (freeExits[list2[k]].Count > 0) { text4 = list2[k]; break; } } if (text3 != null && text4 != null && !string.Equals(text3, text4, StringComparison.OrdinalIgnoreCase)) { ConnectScenes(text3, text4); } } Dictionary<string, HashSet<string>> neighbors = new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase); foreach (KeyValuePair<string, (string, string)> connection in connections) { int num6 = connection.Key.LastIndexOf('_'); if (num6 > 0) { string s3 = connection.Key.Substring(0, num6); string item2 = connection.Value.Item1; AddNeighborEdge(s3, item2); } } List<(string, string)> source = freeExits.SelectMany((KeyValuePair<string, List<string>> kv) => kv.Value.Select((string e) => (kv.Key, e))).ToList(); bool flag2 = false; int num7 = 6; for (int l = 0; l < num7; l++) { if (flag2) { break; } List<(string, string)> list3 = source.OrderBy<(string, string), int>(((string scene, string exit) _) => rng.Next()).ToList(); HashSet<int> hashSet = new HashSet<int>(); List<((string, string), (string, string))> list4 = new List<((string, string), (string, string))>(); bool flag3 = false; for (int m = 0; m < list3.Count; m++) { if (hashSet.Contains(m)) { continue; } (string, string) tuple2 = list3[m]; int num8 = -1; int num9 = int.MinValue; for (int num10 = m + 1; num10 < list3.Count; num10++) { if (hashSet.Contains(num10)) { continue; } (string, string) tuple3 = list3[num10]; if (!string.Equals(tuple2.Item1, tuple3.Item1, StringComparison.OrdinalIgnoreCase)) { int num11 = 0; if (!IsOriginalSingle(tuple3.Item1)) { num11 += 20; } if (!IsOriginalSingle(tuple2.Item1)) { num11 += 10; } if (IsOriginalSingle(tuple2.Item1) && IsOriginalSingle(tuple3.Item1)) { num11 -= 1000; } HashSet<string> value; int num12 = (neighbors.TryGetValue(tuple2.Item1, out value) ? value.Count((string n) => IsLeaf(n)) : 0); HashSet<string> value2; int num13 = (neighbors.TryGetValue(tuple3.Item1, out value2) ? value2.Count((string n) => IsLeaf(n)) : 0); bool flag4 = IsLeaf(tuple3.Item1); bool flag5 = IsLeaf(tuple2.Item1); if (num12 + (flag4 ? 1 : 0) > 1) { num11 -= 50; } if (num13 + (flag5 ? 1 : 0) > 1) { num11 -= 50; } if (num11 > num9) { num9 = num11; num8 = num10; } } } if (num8 < 0) { flag3 = true; break; } hashSet.Add(m); hashSet.Add(num8); list4.Add((list3[m], list3[num8])); AddNeighborEdge(list3[m].Item1, list3[num8].Item1); } if (flag3) { neighbors.Clear(); foreach (KeyValuePair<string, (string, string)> connection2 in connections) { int num14 = connection2.Key.LastIndexOf('_'); if (num14 > 0) { AddNeighborEdge(connection2.Key.Substring(0, num14), connection2.Value.Item1); } } continue; } bool flag6 = false; foreach (var item7 in list4) { if (IsOriginalSingle(item7.Item1.Item1) && IsOriginalSingle(item7.Item2.Item1)) { flag6 = true; break; } } Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase); foreach (KeyValuePair<string, HashSet<string>> item8 in neighbors) { dictionary[item8.Key] = item8.Value.Count((string n) => IsLeaf(n)); } foreach (KeyValuePair<string, int> item9 in dictionary) { if (item9.Value > 1) { flag6 = true; break; } } if (flag6) { neighbors.Clear(); foreach (KeyValuePair<string, (string, string)> connection3 in connections) { int num15 = connection3.Key.LastIndexOf('_'); if (num15 > 0) { AddNeighborEdge(connection3.Key.Substring(0, num15), connection3.Value.Item1); } } continue; } foreach (var item10 in list4) { (string, string) item3 = item10.Item1; (string, string) item4 = item10.Item2; string key3 = MakeKey(item3.Item1, item3.Item2); string key4 = MakeKey(item4.Item1, item4.Item2); if (!connections.ContainsKey(key3) && !connections.ContainsKey(key4)) { connections[key3] = (item4.Item1, item4.Item2); connections[key4] = (item3.Item1, item3.Item2); if (freeExits.ContainsKey(item3.Item1)) { freeExits[item3.Item1].Remove(item3.Item2); } if (freeExits.ContainsKey(item4.Item1)) { freeExits[item4.Item1].Remove(item4.Item2); } int num16 = finalConnectionCount; finalConnectionCount = num16 + 1; } } flag2 = true; } if (!flag2) { Debug.LogWarning((object)"RoomRando: intelligent pairing failed to satisfy constraints; falling back to greedy pairing"); List<(string, string)> list5 = (from _ in freeExits.SelectMany((KeyValuePair<string, List<string>> kv) => kv.Value.Select((string e) => (kv.Key, e))) orderby rng.Next() select _).ToList(); for (int num17 = 0; num17 + 1 < list5.Count; num17 += 2) { (string, string) tuple4 = list5[num17]; (string, string) tuple5 = list5[num17 + 1]; if (!string.Equals(tuple4.Item1, tuple5.Item1, StringComparison.OrdinalIgnoreCase)) { string key5 = MakeKey(tuple4.Item1, tuple4.Item2); string key6 = MakeKey(tuple5.Item1, tuple5.Item2); if (!connections.ContainsKey(key5) && !connections.ContainsKey(key6)) { connections[key5] = (tuple5.Item1, tuple5.Item2); connections[key6] = (tuple4.Item1, tuple4.Item2); int num16 = finalConnectionCount; finalConnectionCount = num16 + 1; } } } } neighbors.Clear(); foreach (KeyValuePair<string, (string, string)> connection4 in connections) { int num18 = connection4.Key.LastIndexOf('_'); if (num18 > 0) { AddNeighborEdge(connection4.Key.Substring(0, num18), connection4.Value.Item1); } } bool flag7 = false; int num19 = 3; foreach (string key9 in neighbors.Keys) { int num20 = neighbors[key9].Count((string n) => IsLeaf(n)); if (num20 > num19) { flag7 = true; break; } } if (!flag7) { flag = true; generationSeed = num3; Debug.Log((object)$"RoomRando: generation succeeded with seed={num3}"); } else { Debug.LogWarning((object)$"RoomRando: generation attempt {i + 1} produced hubs with too many leaf neighbors; retrying"); } void AddNeighborEdge(string s1, string s2) { if (!string.Equals(s1, s2, StringComparison.OrdinalIgnoreCase)) { if (!neighbors.TryGetValue(s1, out var value5)) { value5 = new HashSet<string>(StringComparer.OrdinalIgnoreCase); neighbors[s1] = value5; } if (!neighbors.TryGetValue(s2, out var value6)) { value6 = new HashSet<string>(StringComparer.OrdinalIgnoreCase); neighbors[s2] = value6; } value5.Add(s2); value6.Add(s1); } } void ConnectScenes(string a, string b) { if (freeExits.ContainsKey(a) && freeExits.ContainsKey(b) && freeExits[a].Count != 0 && freeExits[b].Count != 0) { string text5 = freeExits[a][rng.Next(freeExits[a].Count)]; string text6 = freeExits[b][rng.Next(freeExits[b].Count)]; string key7 = MakeKey(a, text5); string key8 = MakeKey(b, text6); if (!connections.ContainsKey(key7) && !connections.ContainsKey(key8)) { connections[key7] = (b, text6); connections[key8] = (a, text5); freeExits[a].Remove(text5); freeExits[b].Remove(text6); int num21 = finalConnectionCount; finalConnectionCount = num21 + 1; } } } bool IsLeaf(string scene) { HashSet<string> value3; return neighbors.TryGetValue(scene, out value3) && value3.Count == 1; } } if (!flag) { Debug.LogWarning((object)$"RoomRando: all {8} generation attempts failed to fully satisfy constraints; using last attempt's map and seed={generationSeed}"); } Debug.Log((object)$"RoomRando: Generated {finalConnectionCount} bidirectional connection pairs ({connections.Count} total directional connections)"); bool IsOriginalSingle(string scene) { return OriginalExitCount(scene) == 1; } int OriginalExitCount(string scene) { RandomSceneLoader.SceneConfig value4; return sceneLoader.sceneConfigs.TryGetValue(scene, out value4) ? (value4.Exits?.Count ?? 0) : 0; } } private bool TryLoadConnectionsFromFile() { try { if (string.IsNullOrWhiteSpace(saveFilePath)) { Debug.LogWarning((object)"RoomRando: saveFilePath is empty or null"); return false; } if (!File.Exists(saveFilePath)) { Debug.Log((object)("RoomRando: connections file not found at " + saveFilePath)); return false; } string[] array = File.ReadAllLines(saveFilePath); Debug.Log((object)$"RoomRando: read {array.Length} lines from {saveFilePath}"); int num = 0; for (int i = 0; i < array.Length; i++) { string text = array[i]?.Trim(); if (string.IsNullOrWhiteSpace(text)) { num++; continue; } if (text.StartsWith("#seed|", StringComparison.OrdinalIgnoreCase)) { string[] array2 = text.Split(new char[1] { '|' }); if (array2.Length >= 2 && int.TryParse(array2[1], out var result)) { generationSeed = result; rng = new Random(generationSeed); Debug.Log((object)$"RoomRando: loaded generation seed {generationSeed} from {saveFilePath}"); } num = i + 1; } else { num = i; } break; } int num2 = 0; int num3 = 0; for (int j = num; j < array.Length; j++) { string text2 = array[j]; if (!string.IsNullOrWhiteSpace(text2) && !text2.StartsWith("#")) { string[] array3 = text2.Split(new char[1] { '|' }); if (array3.Length != 4) { num3++; continue; } string key = array3[0] + "_" + array3[1]; string item = array3[2]; string item2 = array3[3]; connections[key] = (item, item2); num2++; } } Debug.Log((object)$"RoomRando: parsed {num2} connection lines, skipped {num3} invalid lines, total connections now {connections.Count}"); if (num2 == 0 && generationSeed != 0) { Debug.Log((object)$"RoomRando: file contained seed {generationSeed} but no explicit connections; will regenerate deterministically using that seed"); return false; } return connections.Count > 0; } catch (Exception ex) { Debug.LogWarning((object)("RoomRando: failed to load connections file: " + ex.Message)); return false; } } private void SaveConnectionsToFile() { try { using (StreamWriter streamWriter = new StreamWriter(saveFilePath, append: false)) { if (generationSeed == 0) { generationSeed = Environment.TickCount; } streamWriter.WriteLine($"#seed|{generationSeed}"); foreach (KeyValuePair<string, (string, string)> connection in connections) { string key = connection.Key; int num = key.LastIndexOf('_'); if (num > 0) { string text = key.Substring(0, num); string text2 = key.Substring(num + 1); string item = connection.Value.Item1; string item2 = connection.Value.Item2; streamWriter.WriteLine(text + "|" + text2 + "|" + item + "|" + item2); } } } Debug.Log((object)$"RoomRando: saved {connections.Count} connections to {saveFilePath}"); } catch (Exception ex) { Debug.LogWarning((object)("RoomRando: failed to save connections: " + ex.Message)); } } private void TryGenerateMap() { if (!enableMapGeneration) { Debug.Log((object)"RoomRando: map generation is disabled"); return; } try { string text = Path.Combine(Paths.PluginPath, "RoomRandoMap.png"); if (RoomMapGenerator.GenerateFromFile(saveFilePath, text)) { Debug.Log((object)("RoomRando: generated map image at " + text)); } else { Debug.LogWarning((object)"RoomRando: map generation reported failure or no data."); } } catch (Exception ex) { Debug.LogWarning((object)("RoomRando: map generation failed: " + ex.Message)); } } private void InitializePredefinedConnections() { List<(string, string, string, string)> list = new List<(string, string, string, string)>(); foreach (var item5 in list) { string item = item5.Item1; string item2 = item5.Item2; string item3 = item5.Item3; string item4 = item5.Item4; string text = MakeKey(item, item2); string text2 = MakeKey(item3, item4); connections[text] = (item3, item4); connections[text2] = (item, item2); Debug.Log((object)("RoomRando: predefined " + text + " <-> " + text2)); } Debug.Log((object)$"RoomRando: initialized with {list.Count} predefined pairs"); } private string MakeKey(string scene, string exit) { return scene + "_" + exit; } public (string targetScene, string targetGate)? GetConnection(string currentScene, string exitName) { if (string.IsNullOrEmpty(exitName)) { return null; } string key = MakeKey(currentScene, exitName); if (connections.TryGetValue(key, out (string, string) value)) { return value; } return null; } public List<string> GetValidExitsForScene(string sceneName) { if ((Object)(object)sceneLoader != (Object)null && sceneLoader.sceneConfigs.TryGetValue(sceneName, out var value)) { return value.Exits ?? new List<string>(); } return new List<string>(); } public void OnExitUsed(string currentScene, string exitName) { if (string.IsNullOrEmpty(exitName)) { Debug.LogWarning((object)("RoomRando: OnExitUsed called with null/empty exitName from " + currentScene)); return; } string text = MakeKey(currentScene, exitName); if (connections.TryGetValue(text, out (string, string) value)) { Debug.Log((object)("RoomRando: using connection " + text + " -> " + value.Item1 + " via " + value.Item2)); LoadScene(value.Item1, value.Item2); } else { Debug.LogWarning((object)("RoomRando: no connection found for " + text + " (this shouldn't happen if all connections were pre-generated)")); } } private void LoadScene(string sceneName, string entryGate) { //IL_0063: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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_0090: Expected O, but got Unknown if ((Object)(object)GameManager.instance == (Object)null) { Debug.LogError((object)"RoomRando: GameManager not available"); return; } try { RandomSceneLoader randomSceneLoader = Object.FindFirstObjectByType<RandomSceneLoader>(); if ((Object)(object)randomSceneLoader != (Object)null) { randomSceneLoader.SetLastEntryGate(entryGate); } } catch (Exception ex) { Debug.LogWarning((object)("RoomRando: failed to notify RandomSceneLoader: " + ex.Message)); } try { GameManager.instance.BeginSceneTransition(new SceneLoadInfo { SceneName = sceneName, EntryGateName = entryGate, PreventCameraFadeOut = false, WaitForSceneTransitionCameraFade = true, Visualization = (SceneLoadVisualizations)0 }); } catch (Exception arg) { Debug.LogError((object)$"RoomRando: BeginSceneTransition failed: {arg}"); } } public void LogAllConnections() { Debug.Log((object)$"RoomRando: {connections.Count} connections:"); foreach (KeyValuePair<string, (string, string)> connection in connections) { Debug.Log((object)(" " + connection.Key + " -> " + connection.Value.Item1 + " (via " + connection.Value.Item2 + ")")); } } public int GetGenerationSeed() { return generationSeed; } public void RegenerateWithSeed(int seed) { generationSeed = seed; rng = new Random(generationSeed); connections.Clear(); forceExactSeed = true; Debug.Log((object)$"RoomRando: regenerating with exact seed {seed}"); GenerateAllConnectionsAtStart(); forceExactSeed = false; SaveConnectionsToFil
plugins/Newtonsoft.Json.dll
Decompiled 20 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Data; using System.Data.SqlTypes; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Dynamic; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Numerics; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters; using System.Runtime.Versioning; using System.Security; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Xml; using System.Xml.Linq; using Microsoft.CodeAnalysis; using Newtonsoft.Json.Bson; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq.JsonPath; using Newtonsoft.Json.Schema; using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Utilities; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AllowPartiallyTrustedCallers] [assembly: InternalsVisibleTo("Newtonsoft.Json.Schema, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")] [assembly: InternalsVisibleTo("Newtonsoft.Json.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")] [assembly: InternalsVisibleTo("Newtonsoft.Json.Dynamic, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cbd8d53b9d7de30f1f1278f636ec462cf9c254991291e66ebb157a885638a517887633b898ccbcf0d5c5ff7be85a6abe9e765d0ac7cd33c68dac67e7e64530e8222101109f154ab14a941c490ac155cd1d4fcba0fabb49016b4ef28593b015cab5937da31172f03f67d09edda404b88a60023f062ae71d0b2e4438b74cc11dc9")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("9ca358aa-317b-4925-8ada-4a29e943a363")] [assembly: CLSCompliant(true)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("Newtonsoft")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © James Newton-King 2008")] [assembly: AssemblyDescription("Json.NET is a popular high-performance JSON framework for .NET")] [assembly: AssemblyFileVersion("13.0.4.30916")] [assembly: AssemblyInformationalVersion("13.0.4+4e13299d4b0ec96bd4df9954ef646bd2d1b5bf2a")] [assembly: AssemblyProduct("Json.NET")] [assembly: AssemblyTitle("Json.NET .NET Standard 2.0")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/JamesNK/Newtonsoft.Json")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: AssemblyVersion("13.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } [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; } } } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, Inherited = false)] internal sealed class DynamicallyAccessedMembersAttribute : Attribute { public DynamicallyAccessedMemberTypes MemberTypes { get; } public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes) { MemberTypes = memberTypes; } } [Flags] internal enum DynamicallyAccessedMemberTypes { None = 0, PublicParameterlessConstructor = 1, PublicConstructors = 3, NonPublicConstructors = 4, PublicMethods = 8, NonPublicMethods = 0x10, PublicFields = 0x20, NonPublicFields = 0x40, PublicNestedTypes = 0x80, NonPublicNestedTypes = 0x100, PublicProperties = 0x200, NonPublicProperties = 0x400, PublicEvents = 0x800, NonPublicEvents = 0x1000, Interfaces = 0x2000, All = -1 } [AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)] internal sealed class FeatureGuardAttribute : Attribute { public Type FeatureType { get; } public FeatureGuardAttribute(Type featureType) { FeatureType = featureType; } } [AttributeUsage(AttributeTargets.Property, Inherited = false)] internal sealed class FeatureSwitchDefinitionAttribute : Attribute { public string SwitchName { get; } public FeatureSwitchDefinitionAttribute(string switchName) { SwitchName = switchName; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true)] internal sealed class NotNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] internal sealed class NotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public NotNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] internal sealed class MaybeNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] internal sealed class AllowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal class DoesNotReturnIfAttribute : Attribute { public bool ParameterValue { get; } public DoesNotReturnIfAttribute(bool parameterValue) { ParameterValue = parameterValue; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Method, Inherited = false)] internal sealed class RequiresDynamicCodeAttribute : Attribute { public string Message { get; } public string? Url { get; set; } public RequiresDynamicCodeAttribute(string message) { Message = message; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Method, Inherited = false)] internal sealed class RequiresUnreferencedCodeAttribute : Attribute { public string Message { get; } public string? Url { get; set; } public RequiresUnreferencedCodeAttribute(string message) { Message = message; } } [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)] internal sealed class UnconditionalSuppressMessageAttribute : Attribute { public string Category { get; } public string CheckId { get; } public string? Scope { get; set; } public string? Target { get; set; } public string? MessageId { get; set; } public string? Justification { get; set; } public UnconditionalSuppressMessageAttribute(string category, string checkId) { Category = category; CheckId = checkId; } } } namespace Newtonsoft.Json { public enum ConstructorHandling { Default, AllowNonPublicDefaultConstructor } public enum DateFormatHandling { IsoDateFormat, MicrosoftDateFormat } public enum DateParseHandling { None, DateTime, DateTimeOffset } public enum DateTimeZoneHandling { Local, Utc, Unspecified, RoundtripKind } public class DefaultJsonNameTable : JsonNameTable { private class Entry { internal readonly string Value; internal readonly int HashCode; internal Entry Next; internal Entry(string value, int hashCode, Entry next) { Value = value; HashCode = hashCode; Next = next; } } private static readonly int HashCodeRandomizer; private int _count; private Entry[] _entries; private int _mask = 31; static DefaultJsonNameTable() { HashCodeRandomizer = Environment.TickCount; } public DefaultJsonNameTable() { _entries = new Entry[_mask + 1]; } public override string? Get(char[] key, int start, int length) { if (length == 0) { return string.Empty; } int num = length + HashCodeRandomizer; num += (num << 7) ^ key[start]; int num2 = start + length; for (int i = start + 1; i < num2; i++) { num += (num << 7) ^ key[i]; } num -= num >> 17; num -= num >> 11; num -= num >> 5; int num3 = Volatile.Read(ref _mask); int num4 = num & num3; for (Entry entry = _entries[num4]; entry != null; entry = entry.Next) { if (entry.HashCode == num && TextEquals(entry.Value, key, start, length)) { return entry.Value; } } return null; } public string Add(string key) { if (key == null) { throw new ArgumentNullException("key"); } int length = key.Length; if (length == 0) { return string.Empty; } int num = length + HashCodeRandomizer; for (int i = 0; i < key.Length; i++) { num += (num << 7) ^ key[i]; } num -= num >> 17; num -= num >> 11; num -= num >> 5; for (Entry entry = _entries[num & _mask]; entry != null; entry = entry.Next) { if (entry.HashCode == num && entry.Value.Equals(key, StringComparison.Ordinal)) { return entry.Value; } } return AddEntry(key, num); } private string AddEntry(string str, int hashCode) { int num = hashCode & _mask; Entry entry = new Entry(str, hashCode, _entries[num]); _entries[num] = entry; if (_count++ == _mask) { Grow(); } return entry.Value; } private void Grow() { Entry[] entries = _entries; int num = _mask * 2 + 1; Entry[] array = new Entry[num + 1]; for (int i = 0; i < entries.Length; i++) { Entry entry = entries[i]; while (entry != null) { int num2 = entry.HashCode & num; Entry next = entry.Next; entry.Next = array[num2]; array[num2] = entry; entry = next; } } _entries = array; Volatile.Write(ref _mask, num); } private static bool TextEquals(string str1, char[] str2, int str2Start, int str2Length) { if (str1.Length != str2Length) { return false; } for (int i = 0; i < str1.Length; i++) { if (str1[i] != str2[str2Start + i]) { return false; } } return true; } } [Flags] public enum DefaultValueHandling { Include = 0, Ignore = 1, Populate = 2, IgnoreAndPopulate = 3 } public enum FloatFormatHandling { String, Symbol, DefaultValue } public enum FloatParseHandling { Double, Decimal } public enum Formatting { None, Indented } public interface IArrayPool<T> { T[] Rent(int minimumLength); void Return(T[]? array); } public interface IJsonLineInfo { int LineNumber { get; } int LinePosition { get; } bool HasLineInfo(); } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public sealed class JsonArrayAttribute : JsonContainerAttribute { private bool _allowNullItems; public bool AllowNullItems { get { return _allowNullItems; } set { _allowNullItems = value; } } public JsonArrayAttribute() { } public JsonArrayAttribute(bool allowNullItems) { _allowNullItems = allowNullItems; } public JsonArrayAttribute(string id) : base(id) { } } [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false)] public sealed class JsonConstructorAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public abstract class JsonContainerAttribute : Attribute { internal bool? _isReference; internal bool? _itemIsReference; internal ReferenceLoopHandling? _itemReferenceLoopHandling; internal TypeNameHandling? _itemTypeNameHandling; private Type? _namingStrategyType; private object[]? _namingStrategyParameters; public string? Id { get; set; } public string? Title { get; set; } public string? Description { get; set; } public Type? ItemConverterType { get; set; } public object[]? ItemConverterParameters { get; set; } public Type? NamingStrategyType { get { return _namingStrategyType; } set { _namingStrategyType = value; NamingStrategyInstance = null; } } public object[]? NamingStrategyParameters { get { return _namingStrategyParameters; } set { _namingStrategyParameters = value; NamingStrategyInstance = null; } } internal NamingStrategy? NamingStrategyInstance { get; set; } public bool IsReference { get { return _isReference.GetValueOrDefault(); } set { _isReference = value; } } public bool ItemIsReference { get { return _itemIsReference.GetValueOrDefault(); } set { _itemIsReference = value; } } public ReferenceLoopHandling ItemReferenceLoopHandling { get { return _itemReferenceLoopHandling.GetValueOrDefault(); } set { _itemReferenceLoopHandling = value; } } public TypeNameHandling ItemTypeNameHandling { get { return _itemTypeNameHandling.GetValueOrDefault(); } set { _itemTypeNameHandling = value; } } protected JsonContainerAttribute() { } protected JsonContainerAttribute(string id) { Id = id; } } public static class JsonConvert { public static readonly string True = "true"; public static readonly string False = "false"; public static readonly string Null = "null"; public static readonly string Undefined = "undefined"; public static readonly string PositiveInfinity = "Infinity"; public static readonly string NegativeInfinity = "-Infinity"; public static readonly string NaN = "NaN"; public static Func<JsonSerializerSettings>? DefaultSettings { get; set; } public static string ToString(DateTime value) { return ToString(value, DateFormatHandling.IsoDateFormat, DateTimeZoneHandling.RoundtripKind); } public static string ToString(DateTime value, DateFormatHandling format, DateTimeZoneHandling timeZoneHandling) { DateTime value2 = DateTimeUtils.EnsureDateTime(value, timeZoneHandling); using StringWriter stringWriter = StringUtils.CreateStringWriter(64); stringWriter.Write('"'); DateTimeUtils.WriteDateTimeString(stringWriter, value2, format, null, CultureInfo.InvariantCulture); stringWriter.Write('"'); return stringWriter.ToString(); } public static string ToString(DateTimeOffset value) { return ToString(value, DateFormatHandling.IsoDateFormat); } public static string ToString(DateTimeOffset value, DateFormatHandling format) { using StringWriter stringWriter = StringUtils.CreateStringWriter(64); stringWriter.Write('"'); DateTimeUtils.WriteDateTimeOffsetString(stringWriter, value, format, null, CultureInfo.InvariantCulture); stringWriter.Write('"'); return stringWriter.ToString(); } public static string ToString(bool value) { if (!value) { return False; } return True; } public static string ToString(char value) { return ToString(char.ToString(value)); } public static string ToString(Enum value) { return value.ToString("D"); } public static string ToString(int value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(short value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(ushort value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(uint value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(long value) { return value.ToString(null, CultureInfo.InvariantCulture); } private static string ToStringInternal(BigInteger value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(ulong value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(float value) { return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); } internal static string ToString(float value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable); } private static string EnsureFloatFormat(double value, string text, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { if (floatFormatHandling == FloatFormatHandling.Symbol || (!double.IsInfinity(value) && !double.IsNaN(value))) { return text; } if (floatFormatHandling == FloatFormatHandling.DefaultValue) { if (nullable) { return Null; } return "0.0"; } return quoteChar + text + quoteChar; } public static string ToString(double value) { return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); } internal static string ToString(double value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable); } private static string EnsureDecimalPlace(double value, string text) { if (double.IsNaN(value) || double.IsInfinity(value) || StringUtils.IndexOf(text, '.') != -1 || StringUtils.IndexOf(text, 'E') != -1 || StringUtils.IndexOf(text, 'e') != -1) { return text; } return text + ".0"; } private static string EnsureDecimalPlace(string text) { if (StringUtils.IndexOf(text, '.') != -1) { return text; } return text + ".0"; } public static string ToString(byte value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(sbyte value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(decimal value) { return EnsureDecimalPlace(value.ToString(null, CultureInfo.InvariantCulture)); } public static string ToString(Guid value) { return ToString(value, '"'); } internal static string ToString(Guid value, char quoteChar) { string text = value.ToString("D", CultureInfo.InvariantCulture); string text2 = quoteChar.ToString(CultureInfo.InvariantCulture); return text2 + text + text2; } public static string ToString(TimeSpan value) { return ToString(value, '"'); } internal static string ToString(TimeSpan value, char quoteChar) { return ToString(value.ToString(), quoteChar); } public static string ToString(Uri? value) { if (value == null) { return Null; } return ToString(value, '"'); } internal static string ToString(Uri value, char quoteChar) { return ToString(value.OriginalString, quoteChar); } public static string ToString(string? value) { return ToString(value, '"'); } public static string ToString(string? value, char delimiter) { return ToString(value, delimiter, StringEscapeHandling.Default); } public static string ToString(string? value, char delimiter, StringEscapeHandling stringEscapeHandling) { if (delimiter != '"' && delimiter != '\'') { throw new ArgumentException("Delimiter must be a single or double quote.", "delimiter"); } return JavaScriptUtils.ToEscapedJavaScriptString(value, delimiter, appendDelimiters: true, stringEscapeHandling); } public static string ToString(object? value) { if (value == null) { return Null; } return ConvertUtils.GetTypeCode(value.GetType()) switch { PrimitiveTypeCode.String => ToString((string)value), PrimitiveTypeCode.Char => ToString((char)value), PrimitiveTypeCode.Boolean => ToString((bool)value), PrimitiveTypeCode.SByte => ToString((sbyte)value), PrimitiveTypeCode.Int16 => ToString((short)value), PrimitiveTypeCode.UInt16 => ToString((ushort)value), PrimitiveTypeCode.Int32 => ToString((int)value), PrimitiveTypeCode.Byte => ToString((byte)value), PrimitiveTypeCode.UInt32 => ToString((uint)value), PrimitiveTypeCode.Int64 => ToString((long)value), PrimitiveTypeCode.UInt64 => ToString((ulong)value), PrimitiveTypeCode.Single => ToString((float)value), PrimitiveTypeCode.Double => ToString((double)value), PrimitiveTypeCode.DateTime => ToString((DateTime)value), PrimitiveTypeCode.Decimal => ToString((decimal)value), PrimitiveTypeCode.DBNull => Null, PrimitiveTypeCode.DateTimeOffset => ToString((DateTimeOffset)value), PrimitiveTypeCode.Guid => ToString((Guid)value), PrimitiveTypeCode.Uri => ToString((Uri)value), PrimitiveTypeCode.TimeSpan => ToString((TimeSpan)value), PrimitiveTypeCode.BigInteger => ToStringInternal((BigInteger)value), _ => throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType())), }; } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeObject(object? value) { return SerializeObject(value, (Type?)null, (JsonSerializerSettings?)null); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeObject(object? value, Formatting formatting) { return SerializeObject(value, formatting, (JsonSerializerSettings?)null); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeObject(object? value, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return SerializeObject(value, null, settings); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeObject(object? value, Formatting formatting, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return SerializeObject(value, null, formatting, settings); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeObject(object? value, JsonSerializerSettings? settings) { return SerializeObject(value, null, settings); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeObject(object? value, Type? type, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); return SerializeObjectInternal(value, type, jsonSerializer); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeObject(object? value, Formatting formatting, JsonSerializerSettings? settings) { return SerializeObject(value, null, formatting, settings); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeObject(object? value, Type? type, Formatting formatting, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); jsonSerializer.Formatting = formatting; return SerializeObjectInternal(value, type, jsonSerializer); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] private static string SerializeObjectInternal(object? value, Type? type, JsonSerializer jsonSerializer) { StringWriter stringWriter = new StringWriter(new StringBuilder(256), CultureInfo.InvariantCulture); using (JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter)) { jsonTextWriter.Formatting = jsonSerializer.Formatting; jsonSerializer.Serialize(jsonTextWriter, value, type); } return stringWriter.ToString(); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static object? DeserializeObject(string value) { return DeserializeObject(value, (Type?)null, (JsonSerializerSettings?)null); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static object? DeserializeObject(string value, JsonSerializerSettings settings) { return DeserializeObject(value, null, settings); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static object? DeserializeObject(string value, Type type) { return DeserializeObject(value, type, (JsonSerializerSettings?)null); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static T? DeserializeObject<T>(string value) { return JsonConvert.DeserializeObject<T>(value, (JsonSerializerSettings?)null); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject) { return DeserializeObject<T>(value); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject, JsonSerializerSettings settings) { return DeserializeObject<T>(value, settings); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static T? DeserializeObject<T>(string value, params JsonConverter[] converters) { return (T)DeserializeObject(value, typeof(T), converters); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static T? DeserializeObject<T>(string value, JsonSerializerSettings? settings) { return (T)DeserializeObject(value, typeof(T), settings); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static object? DeserializeObject(string value, Type type, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return DeserializeObject(value, type, settings); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static object? DeserializeObject(string value, Type? type, JsonSerializerSettings? settings) { ValidationUtils.ArgumentNotNull(value, "value"); JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); if (!jsonSerializer.IsCheckAdditionalContentSet()) { jsonSerializer.CheckAdditionalContent = true; } using JsonTextReader reader = new JsonTextReader(new StringReader(value)); return jsonSerializer.Deserialize(reader, type); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static void PopulateObject(string value, object target) { PopulateObject(value, target, null); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static void PopulateObject(string value, object target, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); using JsonReader jsonReader = new JsonTextReader(new StringReader(value)); jsonSerializer.Populate(jsonReader, target); if (settings == null || !settings.CheckAdditionalContent) { return; } while (jsonReader.Read()) { if (jsonReader.TokenType != JsonToken.Comment) { throw JsonSerializationException.Create(jsonReader, "Additional text found in JSON string after finishing deserializing object."); } } } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeXmlNode(XmlNode? node) { return SerializeXmlNode(node, Formatting.None); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeXmlNode(XmlNode? node, Formatting formatting) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); return SerializeObject(node, formatting, xmlNodeConverter); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeXmlNode(XmlNode? node, Formatting formatting, bool omitRootObject) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter { OmitRootObject = omitRootObject }; return SerializeObject(node, formatting, xmlNodeConverter); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XmlDocument? DeserializeXmlNode(string value) { return DeserializeXmlNode(value, null); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName) { return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute: false); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute) { return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); xmlNodeConverter.DeserializeRootElementName = deserializeRootElementName; xmlNodeConverter.WriteArrayAttribute = writeArrayAttribute; xmlNodeConverter.EncodeSpecialCharacters = encodeSpecialCharacters; return (XmlDocument)DeserializeObject(value, typeof(XmlDocument), xmlNodeConverter); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeXNode(XObject? node) { return SerializeXNode(node, Formatting.None); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeXNode(XObject? node, Formatting formatting) { return SerializeXNode(node, formatting, omitRootObject: false); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeXNode(XObject? node, Formatting formatting, bool omitRootObject) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter { OmitRootObject = omitRootObject }; return SerializeObject(node, formatting, xmlNodeConverter); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XDocument? DeserializeXNode(string value) { return DeserializeXNode(value, null); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName) { return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute: false); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute) { return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); xmlNodeConverter.DeserializeRootElementName = deserializeRootElementName; xmlNodeConverter.WriteArrayAttribute = writeArrayAttribute; xmlNodeConverter.EncodeSpecialCharacters = encodeSpecialCharacters; return (XDocument)DeserializeObject(value, typeof(XDocument), xmlNodeConverter); } } public abstract class JsonConverter { public virtual bool CanRead => true; public virtual bool CanWrite => true; public abstract void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer); public abstract object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer); public abstract bool CanConvert(Type objectType); } public abstract class JsonConverter<T> : JsonConverter { public sealed override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (!((value != null) ? (value is T) : ReflectionUtils.IsNullable(typeof(T)))) { throw new JsonSerializationException("Converter cannot write specified value to JSON. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); } WriteJson(writer, (T)value, serializer); } public abstract void WriteJson(JsonWriter writer, T? value, JsonSerializer serializer); public sealed override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { bool flag = existingValue == null; if (!flag && !(existingValue is T)) { throw new JsonSerializationException("Converter cannot read JSON with the specified existing value. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); } return ReadJson(reader, objectType, flag ? default(T) : ((T)existingValue), !flag, serializer); } public abstract T? ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer); public sealed override bool CanConvert(Type objectType) { return typeof(T).IsAssignableFrom(objectType); } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter, AllowMultiple = false)] public sealed class JsonConverterAttribute : Attribute { private readonly Type _converterType; public Type ConverterType => _converterType; public object[]? ConverterParameters { get; } public JsonConverterAttribute(Type converterType) { if (converterType == null) { throw new ArgumentNullException("converterType"); } _converterType = converterType; } public JsonConverterAttribute(Type converterType, params object[] converterParameters) : this(converterType) { ConverterParameters = converterParameters; } } public class JsonConverterCollection : Collection<JsonConverter> { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public sealed class JsonDictionaryAttribute : JsonContainerAttribute { public JsonDictionaryAttribute() { } public JsonDictionaryAttribute(string id) : base(id) { } } [Serializable] public class JsonException : Exception { public JsonException() { } public JsonException(string message) : base(message) { } public JsonException(string message, Exception? innerException) : base(message, innerException) { } public JsonException(SerializationInfo info, StreamingContext context) : base(info, context) { } internal static JsonException Create(IJsonLineInfo lineInfo, string path, string message) { message = JsonPosition.FormatMessage(lineInfo, path, message); return new JsonException(message); } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public class JsonExtensionDataAttribute : Attribute { public bool WriteData { get; set; } public bool ReadData { get; set; } public JsonExtensionDataAttribute() { WriteData = true; ReadData = true; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public sealed class JsonIgnoreAttribute : Attribute { } public abstract class JsonNameTable { public abstract string? Get(char[] key, int start, int length); } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = false)] public sealed class JsonObjectAttribute : JsonContainerAttribute { private MemberSerialization _memberSerialization; internal MissingMemberHandling? _missingMemberHandling; internal Required? _itemRequired; internal NullValueHandling? _itemNullValueHandling; public MemberSerialization MemberSerialization { get { return _memberSerialization; } set { _memberSerialization = value; } } public MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling.GetValueOrDefault(); } set { _missingMemberHandling = value; } } public NullValueHandling ItemNullValueHandling { get { return _itemNullValueHandling.GetValueOrDefault(); } set { _itemNullValueHandling = value; } } public Required ItemRequired { get { return _itemRequired.GetValueOrDefault(); } set { _itemRequired = value; } } public JsonObjectAttribute() { } public JsonObjectAttribute(MemberSerialization memberSerialization) { MemberSerialization = memberSerialization; } public JsonObjectAttribute(string id) : base(id) { } } internal enum JsonContainerType { None, Object, Array, Constructor } internal struct JsonPosition { private static readonly char[] SpecialCharacters = new char[18] { '.', ' ', '\'', '/', '"', '[', ']', '(', ')', '\t', '\n', '\r', '\f', '\b', '\\', '\u0085', '\u2028', '\u2029' }; internal JsonContainerType Type; internal int Position; internal string? PropertyName; internal bool HasIndex; public JsonPosition(JsonContainerType type) { Type = type; HasIndex = TypeHasIndex(type); Position = -1; PropertyName = null; } internal int CalculateLength() { switch (Type) { case JsonContainerType.Object: return PropertyName.Length + 5; case JsonContainerType.Array: case JsonContainerType.Constructor: return MathUtils.IntLength((ulong)Position) + 2; default: throw new ArgumentOutOfRangeException("Type"); } } internal void WriteTo(StringBuilder sb, ref StringWriter? writer, ref char[]? buffer) { switch (Type) { case JsonContainerType.Object: { string propertyName = PropertyName; if (propertyName.IndexOfAny(SpecialCharacters) != -1) { sb.Append("['"); if (writer == null) { writer = new StringWriter(sb); } JavaScriptUtils.WriteEscapedJavaScriptString(writer, propertyName, '\'', appendDelimiters: false, JavaScriptUtils.SingleQuoteCharEscapeFlags, StringEscapeHandling.Default, null, ref buffer); sb.Append("']"); } else { if (sb.Length > 0) { sb.Append('.'); } sb.Append(propertyName); } break; } case JsonContainerType.Array: case JsonContainerType.Constructor: sb.Append('['); sb.Append(Position); sb.Append(']'); break; } } internal static bool TypeHasIndex(JsonContainerType type) { if (type != JsonContainerType.Array) { return type == JsonContainerType.Constructor; } return true; } internal static string BuildPath(List<JsonPosition> positions, JsonPosition? currentPosition) { int num = 0; if (positions != null) { for (int i = 0; i < positions.Count; i++) { num += positions[i].CalculateLength(); } } if (currentPosition.HasValue) { num += currentPosition.GetValueOrDefault().CalculateLength(); } StringBuilder stringBuilder = new StringBuilder(num); StringWriter writer = null; char[] buffer = null; if (positions != null) { foreach (JsonPosition position in positions) { position.WriteTo(stringBuilder, ref writer, ref buffer); } } currentPosition?.WriteTo(stringBuilder, ref writer, ref buffer); return stringBuilder.ToString(); } internal static string FormatMessage(IJsonLineInfo? lineInfo, string path, string message) { if (!message.EndsWith(Environment.NewLine, StringComparison.Ordinal)) { message = message.Trim(); if (!StringUtils.EndsWith(message, '.')) { message += "."; } message += " "; } message += "Path '{0}'".FormatWith(CultureInfo.InvariantCulture, path); if (lineInfo != null && lineInfo.HasLineInfo()) { message += ", line {0}, position {1}".FormatWith(CultureInfo.InvariantCulture, lineInfo.LineNumber, lineInfo.LinePosition); } message += "."; return message; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)] public sealed class JsonPropertyAttribute : Attribute { internal NullValueHandling? _nullValueHandling; internal DefaultValueHandling? _defaultValueHandling; internal ReferenceLoopHandling? _referenceLoopHandling; internal ObjectCreationHandling? _objectCreationHandling; internal TypeNameHandling? _typeNameHandling; internal bool? _isReference; internal int? _order; internal Required? _required; internal bool? _itemIsReference; internal ReferenceLoopHandling? _itemReferenceLoopHandling; internal TypeNameHandling? _itemTypeNameHandling; public Type? ItemConverterType { get; set; } public object[]? ItemConverterParameters { get; set; } public Type? NamingStrategyType { get; set; } public object[]? NamingStrategyParameters { get; set; } public NullValueHandling NullValueHandling { get { return _nullValueHandling.GetValueOrDefault(); } set { _nullValueHandling = value; } } public DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling.GetValueOrDefault(); } set { _defaultValueHandling = value; } } public ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling.GetValueOrDefault(); } set { _referenceLoopHandling = value; } } public ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling.GetValueOrDefault(); } set { _objectCreationHandling = value; } } public TypeNameHandling TypeNameHandling { get { return _typeNameHandling.GetValueOrDefault(); } set { _typeNameHandling = value; } } public bool IsReference { get { return _isReference.GetValueOrDefault(); } set { _isReference = value; } } public int Order { get { return _order.GetValueOrDefault(); } set { _order = value; } } public Required Required { get { return _required.GetValueOrDefault(); } set { _required = value; } } public string? PropertyName { get; set; } public ReferenceLoopHandling ItemReferenceLoopHandling { get { return _itemReferenceLoopHandling.GetValueOrDefault(); } set { _itemReferenceLoopHandling = value; } } public TypeNameHandling ItemTypeNameHandling { get { return _itemTypeNameHandling.GetValueOrDefault(); } set { _itemTypeNameHandling = value; } } public bool ItemIsReference { get { return _itemIsReference.GetValueOrDefault(); } set { _itemIsReference = value; } } public JsonPropertyAttribute() { } public JsonPropertyAttribute(string propertyName) { PropertyName = propertyName; } } public abstract class JsonReader : IDisposable { protected internal enum State { Start, Complete, Property, ObjectStart, Object, ArrayStart, Array, Closed, PostValue, ConstructorStart, Constructor, Error, Finished } private JsonToken _tokenType; private object? _value; internal char _quoteChar; internal State _currentState; private JsonPosition _currentPosition; private CultureInfo? _culture; private DateTimeZoneHandling _dateTimeZoneHandling; private int? _maxDepth; private bool _hasExceededMaxDepth; internal DateParseHandling _dateParseHandling; internal FloatParseHandling _floatParseHandling; private string? _dateFormatString; private List<JsonPosition>? _stack; protected State CurrentState => _currentState; public bool CloseInput { get; set; } public bool SupportMultipleContent { get; set; } public virtual char QuoteChar { get { return _quoteChar; } protected internal set { _quoteChar = value; } } public DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling; } set { if (value < DateTimeZoneHandling.Local || value > DateTimeZoneHandling.RoundtripKind) { throw new ArgumentOutOfRangeException("value"); } _dateTimeZoneHandling = value; } } public DateParseHandling DateParseHandling { get { return _dateParseHandling; } set { if (value < DateParseHandling.None || value > DateParseHandling.DateTimeOffset) { throw new ArgumentOutOfRangeException("value"); } _dateParseHandling = value; } } public FloatParseHandling FloatParseHandling { get { return _floatParseHandling; } set { if (value < FloatParseHandling.Double || value > FloatParseHandling.Decimal) { throw new ArgumentOutOfRangeException("value"); } _floatParseHandling = value; } } public string? DateFormatString { get { return _dateFormatString; } set { _dateFormatString = value; } } public int? MaxDepth { get { return _maxDepth; } set { if (value <= 0) { throw new ArgumentException("Value must be positive.", "value"); } _maxDepth = value; } } public virtual JsonToken TokenType => _tokenType; public virtual object? Value => _value; public virtual Type? ValueType => _value?.GetType(); public virtual int Depth { get { int num = _stack?.Count ?? 0; if (JsonTokenUtils.IsStartToken(TokenType) || _currentPosition.Type == JsonContainerType.None) { return num; } return num + 1; } } public virtual string Path { get { if (_currentPosition.Type == JsonContainerType.None) { return string.Empty; } JsonPosition? currentPosition = ((_currentState != State.ArrayStart && _currentState != State.ConstructorStart && _currentState != State.ObjectStart) ? new JsonPosition?(_currentPosition) : null); return JsonPosition.BuildPath(_stack, currentPosition); } } public CultureInfo Culture { get { return _culture ?? CultureInfo.InvariantCulture; } set { _culture = value; } } public virtual Task<bool> ReadAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<bool>() ?? Read().ToAsync(); } public async Task SkipAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (TokenType == JsonToken.PropertyName) { await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } if (JsonTokenUtils.IsStartToken(TokenType)) { int depth = Depth; while (await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false) && depth < Depth) { } } } internal async Task ReaderReadAndAssertAsync(CancellationToken cancellationToken) { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw CreateUnexpectedEndException(); } } public virtual Task<bool?> ReadAsBooleanAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<bool?>() ?? Task.FromResult(ReadAsBoolean()); } public virtual Task<byte[]?> ReadAsBytesAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<byte[]>() ?? Task.FromResult(ReadAsBytes()); } internal async Task<byte[]?> ReadArrayIntoByteArrayAsync(CancellationToken cancellationToken) { List<byte> buffer = new List<byte>(); do { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { SetToken(JsonToken.None); } } while (!ReadArrayElementIntoByteArrayReportDone(buffer)); byte[] array = buffer.ToArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } public virtual Task<DateTime?> ReadAsDateTimeAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<DateTime?>() ?? Task.FromResult(ReadAsDateTime()); } public virtual Task<DateTimeOffset?> ReadAsDateTimeOffsetAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<DateTimeOffset?>() ?? Task.FromResult(ReadAsDateTimeOffset()); } public virtual Task<decimal?> ReadAsDecimalAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<decimal?>() ?? Task.FromResult(ReadAsDecimal()); } public virtual Task<double?> ReadAsDoubleAsync(CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(ReadAsDouble()); } public virtual Task<int?> ReadAsInt32Async(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<int?>() ?? Task.FromResult(ReadAsInt32()); } public virtual Task<string?> ReadAsStringAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<string>() ?? Task.FromResult(ReadAsString()); } internal async Task<bool> ReadAndMoveToContentAsync(CancellationToken cancellationToken) { bool flag = await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (flag) { flag = await MoveToContentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } return flag; } internal Task<bool> MoveToContentAsync(CancellationToken cancellationToken) { JsonToken tokenType = TokenType; if (tokenType == JsonToken.None || tokenType == JsonToken.Comment) { return MoveToContentFromNonContentAsync(cancellationToken); } return AsyncUtils.True; } private async Task<bool> MoveToContentFromNonContentAsync(CancellationToken cancellationToken) { JsonToken tokenType; do { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { return false; } tokenType = TokenType; } while (tokenType == JsonToken.None || tokenType == JsonToken.Comment); return true; } internal JsonPosition GetPosition(int depth) { if (_stack != null && depth < _stack.Count) { return _stack[depth]; } return _currentPosition; } protected JsonReader() { _currentState = State.Start; _dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; _dateParseHandling = DateParseHandling.DateTime; _floatParseHandling = FloatParseHandling.Double; _maxDepth = 64; CloseInput = true; } private void Push(JsonContainerType value) { UpdateScopeWithFinishedValue(); if (_currentPosition.Type == JsonContainerType.None) { _currentPosition = new JsonPosition(value); return; } if (_stack == null) { _stack = new List<JsonPosition>(); } _stack.Add(_currentPosition); _currentPosition = new JsonPosition(value); if (!_maxDepth.HasValue || !(Depth + 1 > _maxDepth) || _hasExceededMaxDepth) { return; } _hasExceededMaxDepth = true; throw JsonReaderException.Create(this, "The reader's MaxDepth of {0} has been exceeded.".FormatWith(CultureInfo.InvariantCulture, _maxDepth)); } private JsonContainerType Pop() { JsonPosition currentPosition; if (_stack != null && _stack.Count > 0) { currentPosition = _currentPosition; _currentPosition = _stack[_stack.Count - 1]; _stack.RemoveAt(_stack.Count - 1); } else { currentPosition = _currentPosition; _currentPosition = default(JsonPosition); } if (_maxDepth.HasValue && Depth <= _maxDepth) { _hasExceededMaxDepth = false; } return currentPosition.Type; } private JsonContainerType Peek() { return _currentPosition.Type; } public abstract bool Read(); public virtual int? ReadAsInt32() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is int) { return (int)value; } int num; if (value is BigInteger bigInteger) { num = (int)bigInteger; } else { try { num = Convert.ToInt32(value, CultureInfo.InvariantCulture); } catch (Exception ex) { throw JsonReaderException.Create(this, "Could not convert to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex); } } SetToken(JsonToken.Integer, num, updateIndex: false); return num; } case JsonToken.String: { string s = (string)Value; return ReadInt32String(s); } default: throw JsonReaderException.Create(this, "Error reading integer. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal int? ReadInt32String(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (int.TryParse(s, NumberStyles.Integer, Culture, out var result)) { SetToken(JsonToken.Integer, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual string? ReadAsString() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.String: return (string)Value; default: if (JsonTokenUtils.IsPrimitiveToken(contentToken)) { object value = Value; if (value != null) { string text = ((!(value is IFormattable formattable)) ? ((value is Uri uri) ? uri.OriginalString : value.ToString()) : formattable.ToString(null, Culture)); SetToken(JsonToken.String, text, updateIndex: false); return text; } } throw JsonReaderException.Create(this, "Error reading string. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } public virtual byte[]? ReadAsBytes() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.StartObject: { ReadIntoWrappedTypeObject(); byte[] array2 = ReadAsBytes(); ReaderReadAndAssert(); if (TokenType != JsonToken.EndObject) { throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } SetToken(JsonToken.Bytes, array2, updateIndex: false); return array2; } case JsonToken.String: { string text = (string)Value; Guid g; byte[] array3 = ((text.Length == 0) ? CollectionUtils.ArrayEmpty<byte>() : ((!ConvertUtils.TryConvertGuid(text, out g)) ? Convert.FromBase64String(text) : g.ToByteArray())); SetToken(JsonToken.Bytes, array3, updateIndex: false); return array3; } case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Bytes: if (Value is Guid guid) { byte[] array = guid.ToByteArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } return (byte[])Value; case JsonToken.StartArray: return ReadArrayIntoByteArray(); default: throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal byte[] ReadArrayIntoByteArray() { List<byte> list = new List<byte>(); do { if (!Read()) { SetToken(JsonToken.None); } } while (!ReadArrayElementIntoByteArrayReportDone(list)); byte[] array = list.ToArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } private bool ReadArrayElementIntoByteArrayReportDone(List<byte> buffer) { switch (TokenType) { case JsonToken.None: throw JsonReaderException.Create(this, "Unexpected end when reading bytes."); case JsonToken.Integer: buffer.Add(Convert.ToByte(Value, CultureInfo.InvariantCulture)); return false; case JsonToken.EndArray: return true; case JsonToken.Comment: return false; default: throw JsonReaderException.Create(this, "Unexpected token when reading bytes: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } } public virtual double? ReadAsDouble() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is double) { return (double)value; } double num = ((!(value is BigInteger bigInteger)) ? Convert.ToDouble(value, CultureInfo.InvariantCulture) : ((double)bigInteger)); SetToken(JsonToken.Float, num, updateIndex: false); return num; } case JsonToken.String: return ReadDoubleString((string)Value); default: throw JsonReaderException.Create(this, "Error reading double. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal double? ReadDoubleString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (double.TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, Culture, out var result)) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to double: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual bool? ReadAsBoolean() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { bool flag = ((!(Value is BigInteger bigInteger)) ? Convert.ToBoolean(Value, CultureInfo.InvariantCulture) : (bigInteger != 0L)); SetToken(JsonToken.Boolean, flag, updateIndex: false); return flag; } case JsonToken.String: return ReadBooleanString((string)Value); case JsonToken.Boolean: return (bool)Value; default: throw JsonReaderException.Create(this, "Error reading boolean. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal bool? ReadBooleanString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (bool.TryParse(s, out var result)) { SetToken(JsonToken.Boolean, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to boolean: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual decimal? ReadAsDecimal() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is decimal) { return (decimal)value; } decimal num; if (value is BigInteger bigInteger) { num = (decimal)bigInteger; } else { try { num = Convert.ToDecimal(value, CultureInfo.InvariantCulture); } catch (Exception ex) { throw JsonReaderException.Create(this, "Could not convert to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex); } } SetToken(JsonToken.Float, num, updateIndex: false); return num; } case JsonToken.String: return ReadDecimalString((string)Value); default: throw JsonReaderException.Create(this, "Error reading decimal. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal decimal? ReadDecimalString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (decimal.TryParse(s, NumberStyles.Number, Culture, out var result)) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } if (ConvertUtils.DecimalTryParse(s.ToCharArray(), 0, s.Length, out result) == ParseResult.Success) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual DateTime? ReadAsDateTime() { switch (GetContentToken()) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Date: if (Value is DateTimeOffset dateTimeOffset) { SetToken(JsonToken.Date, dateTimeOffset.DateTime, updateIndex: false); } return (DateTime)Value; case JsonToken.String: return ReadDateTimeString((string)Value); default: throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } } internal DateTime? ReadDateTimeString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (DateTimeUtils.TryParseDateTime(s, DateTimeZoneHandling, _dateFormatString, Culture, out var dt)) { dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } if (DateTime.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt)) { dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } throw JsonReaderException.Create(this, "Could not convert string to DateTime: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual DateTimeOffset? ReadAsDateTimeOffset() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Date: if (Value is DateTime dateTime) { SetToken(JsonToken.Date, new DateTimeOffset(dateTime), updateIndex: false); } return (DateTimeOffset)Value; case JsonToken.String: { string s = (string)Value; return ReadDateTimeOffsetString(s); } default: throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal DateTimeOffset? ReadDateTimeOffsetString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (DateTimeUtils.TryParseDateTimeOffset(s, _dateFormatString, Culture, out var dt)) { SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } if (DateTimeOffset.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt)) { SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to DateTimeOffset: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } internal void ReaderReadAndAssert() { if (!Read()) { throw CreateUnexpectedEndException(); } } internal JsonReaderException CreateUnexpectedEndException() { return JsonReaderException.Create(this, "Unexpected end when reading JSON."); } internal void ReadIntoWrappedTypeObject() { ReaderReadAndAssert(); if (Value != null && Value.ToString() == "$type") { ReaderReadAndAssert(); if (Value != null && Value.ToString().StartsWith("System.Byte[]", StringComparison.Ordinal)) { ReaderReadAndAssert(); if (Value.ToString() == "$value") { return; } } } throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.StartObject)); } public void Skip() { if (TokenType == JsonToken.PropertyName) { Read(); } if (JsonTokenUtils.IsStartToken(TokenType)) { int depth = Depth; while (Read() && depth < Depth) { } } } protected void SetToken(JsonToken newToken) { SetToken(newToken, null, updateIndex: true); } protected void SetToken(JsonToken newToken, object? value) { SetToken(newToken, value, updateIndex: true); } protected void SetToken(JsonToken newToken, object? value, bool updateIndex) { _tokenType = newToken; _value = value; switch (newToken) { case JsonToken.StartObject: _currentState = State.ObjectStart; Push(JsonContainerType.Object); break; case JsonToken.StartArray: _currentState = State.ArrayStart; Push(JsonContainerType.Array); break; case JsonToken.StartConstructor: _currentState = State.ConstructorStart; Push(JsonContainerType.Constructor); break; case JsonToken.EndObject: ValidateEnd(JsonToken.EndObject); break; case JsonToken.EndArray: ValidateEnd(JsonToken.EndArray); break; case JsonToken.EndConstructor: ValidateEnd(JsonToken.EndConstructor); break; case JsonToken.PropertyName: _currentState = State.Property; _currentPosition.PropertyName = (string)value; break; case JsonToken.Raw: case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Null: case JsonToken.Undefined: case JsonToken.Date: case JsonToken.Bytes: SetPostValueState(updateIndex); break; case JsonToken.Comment: break; } } internal void SetPostValueState(bool updateIndex) { if (Peek() != 0 || SupportMultipleContent) { _currentState = State.PostValue; } else { SetFinished(); } if (updateIndex) { UpdateScopeWithFinishedValue(); } } private void UpdateScopeWithFinishedValue() { if (_currentPosition.HasIndex) { _currentPosition.Position++; } } private void ValidateEnd(JsonToken endToken) { JsonContainerType jsonContainerType = Pop(); if (GetTypeForCloseToken(endToken) != jsonContainerType) { throw JsonReaderException.Create(this, "JsonToken {0} is not valid for closing JsonType {1}.".FormatWith(CultureInfo.InvariantCulture, endToken, jsonContainerType)); } if (Peek() != 0 || SupportMultipleContent) { _currentState = State.PostValue; } else { SetFinished(); } } protected void SetStateBasedOnCurrent() { JsonContainerType jsonContainerType = Peek(); switch (jsonContainerType) { case JsonContainerType.Object: _currentState = State.Object; break; case JsonContainerType.Array: _currentState = State.Array; break; case JsonContainerType.Constructor: _currentState = State.Constructor; break; case JsonContainerType.None: SetFinished(); break; default: throw JsonReaderException.Create(this, "While setting the reader state back to current object an unexpected JsonType was encountered: {0}".FormatWith(CultureInfo.InvariantCulture, jsonContainerType)); } } private void SetFinished() { _currentState = ((!SupportMultipleContent) ? State.Finished : State.Start); } private JsonContainerType GetTypeForCloseToken(JsonToken token) { return token switch { JsonToken.EndObject => JsonContainerType.Object, JsonToken.EndArray => JsonContainerType.Array, JsonToken.EndConstructor => JsonContainerType.Constructor, _ => throw JsonReaderException.Create(this, "Not a valid close JsonToken: {0}".FormatWith(CultureInfo.InvariantCulture, token)), }; } void IDisposable.Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (_currentState != State.Closed && disposing) { Close(); } } public virtual void Close() { _currentState = State.Closed; _tokenType = JsonToken.None; _value = null; } internal void ReadAndAssert() { if (!Read()) { throw JsonSerializationException.Create(this, "Unexpected end when reading JSON."); } } internal void ReadForTypeAndAssert(JsonContract? contract, bool hasConverter) { if (!ReadForType(contract, hasConverter)) { throw JsonSerializationException.Create(this, "Unexpected end when reading JSON."); } } internal bool ReadForType(JsonContract? contract, bool hasConverter) { if (hasConverter) { return Read(); } switch (contract?.InternalReadType ?? ReadType.Read) { case ReadType.Read: return ReadAndMoveToContent(); case ReadType.ReadAsInt32: ReadAsInt32(); break; case ReadType.ReadAsInt64: { bool result = ReadAndMoveToContent(); if (TokenType == JsonToken.Undefined) { throw JsonReaderException.Create(this, "An undefined token is not a valid {0}.".FormatWith(CultureInfo.InvariantCulture, contract?.UnderlyingType ?? typeof(long))); } return result; } case ReadType.ReadAsDecimal: ReadAsDecimal(); break; case ReadType.ReadAsDouble: ReadAsDouble(); break; case ReadType.ReadAsBytes: ReadAsBytes(); break; case ReadType.ReadAsBoolean: ReadAsBoolean(); break; case ReadType.ReadAsString: ReadAsString(); break; case ReadType.ReadAsDateTime: ReadAsDateTime(); break; case ReadType.ReadAsDateTimeOffset: ReadAsDateTimeOffset(); break; default: throw new ArgumentOutOfRangeException(); } return TokenType != JsonToken.None; } internal bool ReadAndMoveToContent() { if (Read()) { return MoveToContent(); } return false; } internal bool MoveToContent() { JsonToken tokenType = TokenType; while (tokenType == JsonToken.None || tokenType == JsonToken.Comment) { if (!Read()) { return false; } tokenType = TokenType; } return true; } private JsonToken GetContentToken() { JsonToken tokenType; do { if (!Read()) { SetToken(JsonToken.None); return JsonToken.None; } tokenType = TokenType; } while (tokenType == JsonToken.Comment); return tokenType; } } [Serializable] public class JsonReaderException : JsonException { public int LineNumber { get; } public int LinePosition { get; } public string? Path { get; } public JsonReaderException() { } public JsonReaderException(string message) : base(message) { } public JsonReaderException(string message, Exception innerException) : base(message, innerException) { } public JsonReaderException(SerializationInfo info, StreamingContext context) : base(info, context) { } public JsonReaderException(string message, string path, int lineNumber, int linePosition, Exception? innerException) : base(message, innerException) { Path = path; LineNumber = lineNumber; LinePosition = linePosition; } internal static JsonReaderException Create(JsonReader reader, string message) { return Create(reader, message, null); } internal static JsonReaderException Create(JsonReader reader, string message, Exception? ex) { return Create(reader as IJsonLineInfo, reader.Path, message, ex); } internal static JsonReaderException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex) { message = JsonPosition.FormatMessage(lineInfo, path, message); int lineNumber; int linePosition; if (lineInfo != null && lineInfo.HasLineInfo()) { lineNumber = lineInfo.LineNumber; linePosition = lineInfo.LinePosition; } else { lineNumber = 0; linePosition = 0; } return new JsonReaderException(message, path, lineNumber, linePosition, ex); } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public sealed class JsonRequiredAttribute : Attribute { } [Serializable] public class JsonSerializationException : JsonException { public int LineNumber { get; } public int LinePosition { get; } public string? Path { get; } public JsonSerializationException() { } public JsonSerializationException(string message) : base(message) { } public JsonSerializationException(string message, Exception innerException) : base(message, innerException) { } public JsonSerializationException(SerializationInfo info, StreamingContext context) : base(info, context) { } public JsonSerializationException(string message, string path, int lineNumber, int linePosition, Exception? innerException) : base(message, innerException) { Path = path; LineNumber = lineNumber; LinePosition = linePosition; } internal static JsonSerializationException Create(JsonReader reader, string message) { return Create(reader, message, null); } internal static JsonSerializationException Create(JsonReader reader, string message, Exception? ex) { return Create(reader as IJsonLineInfo, reader.Path, message, ex); } internal static JsonSerializationException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex) { message = JsonPosition.FormatMessage(lineInfo, path, message); int lineNumber; int linePosition; if (lineInfo != null && lineInfo.HasLineInfo()) { lineNumber = lineInfo.LineNumber; linePosition = lineInfo.LinePosition; } else { lineNumber = 0; linePosition = 0; } return new JsonSerializationException(message, path, lineNumber, linePosition, ex); } } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public class JsonSerializer { internal TypeNameHandling _typeNameHandling; internal TypeNameAssemblyFormatHandling _typeNameAssemblyFormatHandling; internal PreserveReferencesHandling _preserveReferencesHandling; internal ReferenceLoopHandling _referenceLoopHandling; internal MissingMemberHandling _missingMemberHandling; internal ObjectCreationHandling _objectCreationHandling; internal NullValueHandling _nullValueHandling; internal DefaultValueHandling _defaultValueHandling; internal ConstructorHandling _constructorHandling; internal MetadataPropertyHandling _metadataPropertyHandling; internal JsonConverterCollection? _converters; internal IContractResolver _contractResolver; internal ITraceWriter? _traceWriter; internal IEqualityComparer? _equalityComparer; internal ISerializationBinder _serializationBinder; internal StreamingContext _context; private IReferenceResolver? _referenceResolver; private Formatting? _formatting; private DateFormatHandling? _dateFormatHandling; private DateTimeZoneHandling? _dateTimeZoneHandling; private DateParseHandling? _dateParseHandling; private FloatFormatHandling? _floatFormatHandling; private FloatParseHandling? _floatParseHandling; private StringEscapeHandling? _stringEscapeHandling; private CultureInfo _culture; private int? _maxDepth; private bool _maxDepthSet; private bool? _checkAdditionalContent; private string? _dateFormatString; private bool _dateFormatStringSet; public virtual IReferenceResolver? ReferenceResolver { get { return GetReferenceResolver(); } set { if (value == null) { throw new ArgumentNullException("value", "Reference resolver cannot be null."); } _referenceResolver = value; } } [Obsolete("Binder is obsolete. Use SerializationBinder instead.")] public virtual SerializationBinder Binder { get { if (_serializationBinder is SerializationBinder result) { return result; } if (_serializationBinder is SerializationBinderAdapter serializationBinderAdapter) { return serializationBinderAdapter.SerializationBinder; } throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set."); } set { if (value == null) { throw new ArgumentNullException("value", "Serialization binder cannot be null."); } _serializationBinder = (value as ISerializationBinder) ?? new SerializationBinderAdapter(value); } } public virtual ISerializationBinder SerializationBinder { get { return _serializationBinder; } set { if (value == null) { throw new ArgumentNullException("value", "Serialization binder cannot be null."); } _serializationBinder = value; } } public virtual ITraceWriter? TraceWriter { get { return _traceWriter; } set { _traceWriter = value; } } public virtual IEqualityComparer? EqualityComparer { get { return _equalityComparer; } set { _equalityComparer = value; } } public virtual TypeNameHandling TypeNameHandling { get { return _typeNameHandling; } set { if (value < TypeNameHandling.None || value > TypeNameHandling.Auto) { throw new ArgumentOutOfRangeException("value"); } _typeNameHandling = value; } } [Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")] public virtual FormatterAssemblyStyle TypeNameAssemblyFormat { get { return (FormatterAssemblyStyle)_typeNameAssemblyFormatHandling; } set { if (value < FormatterAssemblyStyle.Simple || value > FormatterAssemblyStyle.Full) { throw new ArgumentOutOfRangeException("value"); } _typeNameAssemblyFormatHandling = (TypeNameAssemblyFormatHandling)value; } } public virtual TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling { get { return _typeNameAssemblyFormatHandling; } set { if (value < TypeNameAssemblyFormatHandling.Simple || value > TypeNameAssemblyFormatHandling.Full) { throw new ArgumentOutOfRangeException("value"); } _typeNameAssemblyFormatHandling = value; } } public virtual PreserveReferencesHandling PreserveReferencesHandling { get { return _preserveReferencesHandling; } set { if (value < PreserveReferencesHandling.None || value > PreserveReferencesHandling.All) { throw new ArgumentOutOfRangeException("value"); } _preserveReferencesHandling = value; } } public virtual ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling; } set { if (value < ReferenceLoopHandling.Error || value > ReferenceLoopHandling.Serialize) { throw new ArgumentOutOfRangeException("value"); } _referenceLoopHandling = value; } } public virtual MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling; } set { if (value < MissingMemberHandling.Ignore || value > MissingMemberHandling.Error) { throw new ArgumentOutOfRangeException("value"); } _missingMemberHandling = value; } } public virtual NullValueHandling NullValueHandling { get { return _nullValueHandling; } set { if (value < NullValueHandling.Include || value > NullValueHandling.Ignore) { throw new ArgumentOutOfRangeException("value"); } _nullValueHandling = value; } } public virtual DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling; } set { if (value < DefaultValueHandling.Include || value > DefaultValueHandling.IgnoreAndPopulate) { throw new ArgumentOutOfRangeException("value"); } _defaultValueHandling = value; } } public virtual ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling; } set { if (value < ObjectCreationHandling.Auto || value > ObjectCreationHandling.Replace) { throw new ArgumentOutOfRangeException("value"); } _objectCreationHandling = value; } } public virtual ConstructorHandling ConstructorHandling { get { return _constructorHandling; } set { if (value < ConstructorHandling.Default || value > ConstructorHandling.AllowNonPublicDefaultConstructor) { throw new ArgumentOutOfRangeException("value"); } _constructorHandling = value; } } public virtual MetadataPropertyHandling MetadataPropertyHandling { get { return _metadataPropertyHandling; } set { if (value < MetadataPropertyHandling.Default || value > MetadataPropertyHandling.Ignore) { throw new ArgumentOutOfRangeException("value"); } _metadataPropertyHandling = value; } } public virtual JsonConverterCollection Converters { get { if (_converters == null) { _converters = new JsonConverterCollection(); } return _converters; } } public virtual IContractResolver ContractResolver { get { return _contractResolver; } set { _contractResolver = value ?? DefaultContractResolver.Instance; } } public virtual StreamingContext Context { get { return _context; } set { _context = value; } } public virtual Formatting Formatting { get { return _formatting.GetValueOrDefault(); } set { _formatting = value; } } public virtual DateFormatHandling DateFormatHandling { get { return _dateFormatHandling.GetValueOrDefault(); } set { _dateFormatHandling = value; } } public virtual DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling.GetValueOrDefault(DateTimeZoneHandling.RoundtripKind); } set { _dateTimeZoneHandling = value; } } public virtual DateParseHandling DateParseHandling { get { return _dateParseHandling.GetValueOrDefault(DateParseHandling.DateTime); } set { _dateParseHandling = value; } } public virtual FloatParseHandling FloatParseHandling { get { return _floatParseHandling.GetValueOrDefault(); } set { _floatParseHandling = value; } } public virtual FloatFormatHandling FloatFormatHandling { get { return _floatFormatHandling.GetValueOrDefault(); } set { _floatFormatHandling = value; } } public virtual StringEscapeHandling StringEscapeHandling { get { return _stringEscapeHandling.GetValueOrDefault(); } set { _stringEscapeHandling = value; } } public virtual string DateFormatString { get { return _dateFormatString ?? "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; } set { _dateFormatString = value; _dateFormatStringSet = true; } } public virtual CultureInfo Culture { get { return _culture ?? JsonSerializerSettings.DefaultCulture; } set { _culture = value; } } public virtual int? MaxDepth { get { return _maxDepth; } set { if (value <= 0) { throw new ArgumentException("Value must be positive.", "value"); } _maxDepth = value; _maxDepthSet = true; } } public virtual bool CheckAdditionalContent { get { return _checkAdditionalContent.GetValueOrDefault(); } set { _checkAdditionalContent = value; } } public virtual event EventHandler<Newtonsoft.Json.Serialization.ErrorEventArgs>? Error; internal bool IsCheckAdditionalContentSet() { return _checkAdditionalContent.HasValue; } public JsonSerializer() { _referenceLoopHandling = ReferenceLoopHandling.Error; _missingMemberHandling = MissingMemberHandling.Ignore; _nullValueHandling = NullValueHandling.Include; _defaultValueHandling = DefaultValueHandling.Include; _objectCreationHandling = ObjectCreationHandling.Auto; _preserveReferencesHandling = PreserveReferencesHandling.None; _constructorHandling = ConstructorHandling.Default; _typeNameHandling = TypeNameHandling.None; _metadataPropertyHandling = MetadataPropertyHandling.Default; _context = JsonSerializerSettings.DefaultContext; _serializationBinder = DefaultSerializationBinder.Instance; _culture = JsonSerializerSettings.DefaultCulture; _contractResolver = DefaultContractResolver.Instance; } public static JsonSerializer Create() { return new JsonSerializer(); } public static JsonSerializer Create(JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = Create(); if (settings != null) { ApplySerializerSettings(jsonSerializer, settings); } return jsonSerializer; } public static JsonSerializer CreateDefault() { return Create(JsonConvert.DefaultSettings?.Invoke()); } public static JsonSerializer CreateDefault(JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = CreateDefault(); if (settings != null) { ApplySerializerSettings(jsonSerializer, settings); } return jsonSerializer; } private static void ApplySerializerSettings(JsonSerializer serializer, JsonSerializerSettings settings) { if (!CollectionUtils.IsNullOrEmpty(settings.Converters)) { for (int i = 0; i < settings.Converters.Count; i++) { serializer.Converters.Insert(i, settings.Converters[i]); } } if (settings._typeNameHandling.HasValue) { serializer.TypeNameHandling = settings.TypeNameHandling; } if (settings._metadataPropertyHandling.HasValue) { serializer.MetadataPropertyHandling = settings.MetadataPropertyHandling; } if (settings._typeNameAssemblyFormatHandling.HasValue) { serializer.TypeNameAssemblyFormatHandling = settings.TypeNameAssemblyFormatHandling; } if (settings._preserveReferencesHandling.HasValue) { serializer.PreserveReferencesHandling = settings.PreserveReferencesHandling; } if (settings._referenceLoopHandling.HasValue) { serializer.ReferenceLoopHandling = settings.ReferenceLoopHandling; } if (settings._missingMemberHandling.HasValue) { serializer.MissingMemberHandling = settings.MissingMemberHandling; } if (settings._objectCreationHandling.HasValue) { serializer.ObjectCreationHandling = settings.ObjectCreationHandling; } if (settings._nullValueHandling.HasValue) { serializer.NullValueHandling = settings.NullValueHandling; } if (settings._defaultValueHandling.HasValue) { serializer.DefaultValueHandling = settings.DefaultValueHandling; } if (settings._constructorHandling.HasValue) { serializer.ConstructorHandling = settings.ConstructorHandling; } if (settings._context.HasValue) { serializer.Context = settings.Context; } if (settings._checkAdditionalContent.HasValue) { serializer._checkAdditionalContent = settings._checkAdditionalContent; } if (settings.Error != null) { serializer.Error += settings.Error; } if (settings.ContractResolver != null) { serializer.ContractResolver = settings.ContractResolver; } if (settings.ReferenceResolverProvider != null) { serializer.ReferenceResolver = settings.ReferenceResolverProvider(); } if (settings.TraceWriter != null) { serializer.TraceWriter = settings.TraceWriter; } if (settings.EqualityComparer != null) { serializer.EqualityComparer = settings.EqualityComparer; } if (settings.SerializationBinder != null) { serializer.SerializationBinder = settings.SerializationBinder; } if (settings._formatting.HasValue) { serializer._formatting = settings._formatting; } if (settings._dateFormatHandling.HasValue) { serializer._dateFormatHandling = settings._dateFormatHandling; } if (settings._dateTimeZoneHandling.HasValue) { serializer._dateTimeZoneHandling = settings._dateTimeZoneHandling; } if (settings._dateParseHandling.HasValue) { serializer._dateParseHandling = settings._dateParseHandling; } if (settings._dateFormatStringSet) { serializer._dateFormatString = settings._dateFormatString; serializer._dateFormatStringSet = settings._dateFormatStringSet; } if (settings._floatFormatHandling.HasValue) { serializer._floatFormatHandling = settings._floatFormatHandling; } if (settings._floatParseHandling.HasValue) { serializer._floatParseHandling = settings._floatParseHandling; } if (settings._stringEscapeHandling.HasValue) { serializer._stringEscapeHandling = settings._stringEscapeHandling; } if (settings._culture != null) { serializer._culture = settings._culture; } if (settings._maxDepthSet) { serializer._maxDepth = settings._maxDepth; serializer._maxDepthSet = settings._maxDepthSet; } } [DebuggerStepThrough] public void Populate(TextReader reader, object target) { Populate(new JsonTextReader(reader), target); } [DebuggerStepThrough] public void Populate(JsonReader reader, object target) { PopulateInternal(reader, target); } internal virtual void PopulateInternal(JsonReader reader, object target) { ValidationUtils.ArgumentNotNull(reader, "reader"); ValidationUtils.ArgumentNotNull(target, "target"); SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString); TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null); new JsonSerializerInternalReader(this).Populate(traceJsonReader ?? reader, target); if (traceJsonReader != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); } ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); } [DebuggerStepThrough] public object? Deserialize(JsonReader reader) { return Deserialize(reader, null); } [DebuggerStepThrough] public object? Deserialize(TextReader reader, Type objectType) { return Deserialize(new JsonTextReader(reader), objectType); } [DebuggerStepThrough] public T? Deserialize<T>(JsonReader reader) { return (T)Deserialize(reader, typeof(T)); } [DebuggerStepThrough] public object? Deserialize(JsonReader reader, Type? objectType) { return DeserializeInternal(reader, objectType); } internal virtual object? DeserializeInternal(JsonReader reader, Type? objectType) { ValidationUtils.ArgumentNotNull(reader, "reader"); SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString); TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null); object? result = new JsonSerializerInternalReader(this).Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent); if (traceJsonReader != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); } ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); return result; } internal void SetupReader(JsonReader reader, out CultureInfo? previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string? previousDateFormatString) { if (_culture != null && !_culture.Equals(reader.Culture)) { previousCulture = reader.Culture; reader.Culture = _culture; } else { previousCulture = null; } if (_dateTimeZoneHandling.HasValue && reader.DateTimeZoneHandling != _dateTimeZoneHandling) { previousDateTimeZoneHandling
plugins/SilksongItemRandomizer.dll
Decompiled 20 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; 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 BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GlobalEnums; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using SilksongItemRandomizer.Hazard; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("SilksongItemRandomizer")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0")] [assembly: AssemblyProduct("SilksongItemRandomizer")] [assembly: AssemblyTitle("SilksongItemRandomizer")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/YourGitHubUsername/SilksongItemRandomizer")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.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; } } } 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 SilksongItemRandomizer { [HarmonyPatch(typeof(HeroController), "SetBenchRespawn", new Type[] { typeof(RespawnMarker), typeof(string), typeof(int) })] public static class BenchRespawnPatch { [CompilerGenerated] private sealed class <DelayedCrestRefresh>d__3 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public HeroController hero; private object <currentCrestObj>5__1; private string <currentCrest>5__2; private float <last>5__3; private string <targetCrest>5__4; private MethodInfo <setEquippedMethod>5__5; private Exception <ex>5__6; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayedCrestRefresh>d__3(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <currentCrestObj>5__1 = null; <currentCrest>5__2 = null; <targetCrest>5__4 = null; <setEquippedMethod>5__5 = null; <ex>5__6 = null; <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(15f); <>1__state = 1; return true; case 1: <>1__state = -1; try { <currentCrestObj>5__1 = PlayerData.instance.CurrentCrestID; if (<currentCrestObj>5__1 == null) { return false; } <currentCrest>5__2 = <currentCrestObj>5__1.ToString(); if (string.IsNullOrEmpty(<currentCrest>5__2)) { return false; } if (_lastRefreshTime.TryGetValue(<currentCrest>5__2, out <last>5__3) && Time.time - <last>5__3 < 30f) { Plugin.Log.LogInfo((object)("纹章 " + <currentCrest>5__2 + " 在冷却期内,跳过刷新")); return false; } <targetCrest>5__4 = CrestRandomizer.GetMappedCrestName(<currentCrest>5__2); if (string.IsNullOrEmpty(<targetCrest>5__4)) { return false; } if (<currentCrest>5__2 != <targetCrest>5__4) { Plugin.Log.LogInfo((object)("延迟15秒后检测到纹章不一致: 当前=" + <currentCrest>5__2 + ", 目标=" + <targetCrest>5__4 + ",开始刷新")); <setEquippedMethod>5__5 = typeof(ToolItemManager).GetMethod("SetEquippedCrest", new Type[1] { typeof(string) }); if (<setEquippedMethod>5__5 != null) { <setEquippedMethod>5__5.Invoke(null, new object[1] { <targetCrest>5__4 }); } if ((Object)(object)hero != (Object)null) { hero.ResetAllCrestState(); } _lastRefreshTime[<currentCrest>5__2] = Time.time; Plugin.Log.LogInfo((object)("延迟刷新完成,当前装备: " + <targetCrest>5__4)); <setEquippedMethod>5__5 = null; } <currentCrestObj>5__1 = null; <currentCrest>5__2 = null; <targetCrest>5__4 = null; } catch (Exception ex) { <ex>5__6 = ex; Plugin.Log.LogError((object)$"DelayedCrestRefresh异常: {<ex>5__6}"); } 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(); } } private static Dictionary<string, float> _lastRefreshTime = new Dictionary<string, float>(); private const float COOLDOWN = 30f; private static void Postfix(HeroController __instance) { try { if (!((Object)(object)__instance == (Object)null) && PlayerData.instance != null) { ((MonoBehaviour)__instance).StartCoroutine(DelayedCrestRefresh(__instance)); } } catch (Exception arg) { Plugin.Log.LogError((object)$"BenchRespawnPatch异常: {arg}"); } } [IteratorStateMachine(typeof(<DelayedCrestRefresh>d__3))] private static IEnumerator DelayedCrestRefresh(HeroController hero) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DelayedCrestRefresh>d__3(0) { hero = hero }; } public static void ResetCooldown() { _lastRefreshTime.Clear(); Plugin.Log.LogInfo((object)"纹章刷新冷却已清空"); } } [HarmonyPatch(typeof(ToolCrest), "Unlock")] public static class CrestRandomizePatch { private static List<ToolCrest>? _allCrests; private static HashSet<int> _processedInstanceIds = new HashSet<int>(); public static List<ToolCrest>? CrestList => _allCrests; public static void Initialize() { _allCrests = Resources.FindObjectsOfTypeAll<ToolCrest>().ToList(); } public static void ResetProcessedIds() { _processedInstanceIds.Clear(); } [HarmonyPrefix] private static bool Prefix(ToolCrest __instance) { try { if (_processedInstanceIds.Contains(((Object)__instance).GetInstanceID())) { return true; } _processedInstanceIds.Add(((Object)__instance).GetInstanceID()); string name = __instance.name; string mappedCrestName = CrestRandomizer.GetMappedCrestName(name); if (string.IsNullOrEmpty(mappedCrestName)) { return true; } if (mappedCrestName == name) { Plugin.Log.LogInfo((object)("纹章 " + name + " 映射到自身,放行原解锁")); return true; } if (_allCrests == null || _allCrests.Count == 0) { Initialize(); } ToolCrest val = null; if (_allCrests != null) { foreach (ToolCrest allCrest in _allCrests) { if (allCrest.name == mappedCrestName) { val = allCrest; break; } } } if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)("无法找到目标纹章 " + mappedCrestName + ",放行原解锁")); return true; } val.Unlock(); PlayerData instance = PlayerData.instance; if (instance != null && instance.CurrentCrestID == name) { typeof(ToolItemManager).GetMethod("SetEquippedCrest", new Type[1] { typeof(string) })?.Invoke(null, new object[1] { mappedCrestName }); } return false; } catch (Exception arg) { Plugin.Log.LogError((object)$"CrestRandomizePatch异常: {arg}"); return true; } } } public static class CrestRandomizer { private static Dictionary<string, string> _crestMappings = new Dictionary<string, string>(); private static List<ToolCrest>? _allCrests; private static string FilePath => Path.Combine(Paths.ConfigPath, "SilksongItemRandomizer", "crest_mappings.json"); public static List<ToolCrest>? CrestList => _allCrests; public static void Initialize() { _allCrests = Resources.FindObjectsOfTypeAll<ToolCrest>().ToList(); LoadMappings(); if (_allCrests.Count > 0 && _crestMappings.Count < _allCrests.Count) { Plugin.Log.LogInfo((object)$"映射不完整(现有 {_crestMappings.Count}/{_allCrests.Count}),重新生成完整映射"); GenerateAllMappings(); } Plugin.Log.LogInfo((object)$"纹章随机初始化完成,共 {_crestMappings.Count} 个映射"); } public static void ResetMappings() { _crestMappings.Clear(); if (File.Exists(FilePath)) { File.Delete(FilePath); } Plugin.Log.LogInfo((object)"纹章映射已重置"); } private static void LoadMappings() { try { if (File.Exists(FilePath)) { string text = File.ReadAllText(FilePath); _crestMappings = JsonConvert.DeserializeObject<Dictionary<string, string>>(text) ?? new Dictionary<string, string>(); } else { _crestMappings.Clear(); } } catch (Exception arg) { Plugin.Log.LogError((object)$"加载纹章映射失败: {arg}"); _crestMappings.Clear(); } } private static void SaveMappings() { try { string directoryName = Path.GetDirectoryName(FilePath); if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } string contents = JsonConvert.SerializeObject((object)_crestMappings, (Formatting)1); File.WriteAllText(FilePath, contents); } catch (Exception arg) { Plugin.Log.LogError((object)$"保存纹章映射失败: {arg}"); } } private static void GenerateAllMappings() { if (_allCrests == null || _allCrests.Count == 0) { return; } int value = Plugin.RandomSeed.Value; Random rng = new Random(value); List<ToolCrest> source2 = _allCrests.OrderBy((ToolCrest x) => rng.Next()).ToList(); foreach (ToolCrest source in _allCrests) { List<ToolCrest> list = source2.Where((ToolCrest c) => c.name != source.name).ToList(); if (list.Count == 0) { _crestMappings[source.name] = source.name; continue; } int index = rng.Next(list.Count); string name = list[index].name; _crestMappings[source.name] = name; } SaveMappings(); Plugin.Log.LogInfo((object)$"已为所有 {_allCrests.Count} 个纹章预生成映射"); } public static string GetMappedCrestName(string sourceCrestName) { if (_crestMappings.TryGetValue(sourceCrestName, out string value)) { return value; } Plugin.Log.LogWarning((object)("警告:纹章 " + sourceCrestName + " 没有映射,返回自身")); return sourceCrestName; } } [HarmonyPatch(typeof(CurrencyObjectBase), "Collect")] public class CurrencyCollectPatch { private static int _consecutiveMisses; private const int PITY_THRESHOLD = 105; private static int _dropCount; private static bool _hasGivenKey; private const int KEY_GUARANTEE_MAX = 30; private static string keyName; private static int _silkSpearAttempts; private static bool _silkSpearGiven; private const int SILK_SPEAR_PITY = 200; private static SavedItem? _silkSpearItem; static CurrencyCollectPatch() { _consecutiveMisses = 0; _dropCount = 0; _hasGivenKey = false; keyName = "Simple Key"; _silkSpearAttempts = 0; _silkSpearGiven = false; SavedItem[] source = Resources.FindObjectsOfTypeAll<SavedItem>(); _silkSpearItem = ((IEnumerable<SavedItem>)source).FirstOrDefault((Func<SavedItem, bool>)((SavedItem item) => ((Object)item).name == "Silk Spear")); if ((Object)(object)_silkSpearItem == (Object)null) { Plugin.Log.LogWarning((object)"未找到丝矛物品(Silk Spear),丝矛200次保底将禁用。"); } } public static void ResetCounters() { _consecutiveMisses = 0; _dropCount = 0; _hasGivenKey = false; _silkSpearAttempts = 0; _silkSpearGiven = false; Plugin.Log.LogInfo((object)"货币保底计数器已重置"); } private static void Postfix(bool __result) { try { if (!__result) { return; } _dropCount++; _silkSpearAttempts++; if (!_hasGivenKey && _dropCount <= 30) { SavedItem val = ((IEnumerable<SavedItem>)Resources.FindObjectsOfTypeAll<SavedItem>()).FirstOrDefault((Func<SavedItem, bool>)((SavedItem item) => ((Object)item).name == keyName)); if ((Object)(object)val != (Object)null) { val.TryGet(false, true); Plugin.Log.LogInfo((object)$"钥匙保底触发(第{_dropCount}次)"); _hasGivenKey = true; } } if ((Object)(object)_silkSpearItem != (Object)null && !_silkSpearGiven && _silkSpearAttempts >= 200) { Plugin.Log.LogInfo((object)"丝矛保底触发"); if (_silkSpearItem.TryGet(false, true)) { Plugin.Log.LogInfo((object)"丝矛保底成功给予"); Plugin.ShowNotification("获得丝矛!"); _silkSpearGiven = true; } else { Plugin.Log.LogError((object)"丝矛保底失败"); _silkSpearGiven = true; } } else if (_consecutiveMisses >= 104 || ItemRandomizer.RandomChance(1f / 105f)) { SavedItem randomItem = ItemRandomizer.GetRandomItem(); if ((Object)(object)randomItem != (Object)null) { randomItem.TryGet(false, true); } _consecutiveMisses = 0; } else { _consecutiveMisses++; } } catch (Exception arg) { Plugin.Log.LogError((object)$"Exception in CurrencyCollectPatch: {arg}"); } } } public static class ItemRandomizer { private static List<SavedItem>? _allItems; private static Random? _rng; public static readonly HashSet<string> ExcludedNames = new HashSet<string> { "Steel Spines", "Common Spine", "Plasmium", "Sliver Bell", "Seared Organ", "Shredded Organ", "Skewered Organ", "Ragpelt" }; public static Random? Rng => _rng; public static void Initialize(int seed) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) SavedItem[] source = Resources.FindObjectsOfTypeAll<SavedItem>(); _allItems = source.Where((SavedItem item) => (item is CollectableItem || item is ToolBase || item is CollectableRelic) && !ExcludedNames.Contains(((Object)item).name)).ToList(); if (_allItems.Count == 0) { ManualLogSource log = Plugin.Log; Scene activeScene = SceneManager.GetActiveScene(); log.LogWarning((object)("No eligible items found! Current scene: " + ((Scene)(ref activeScene)).name)); } else { _rng = ((seed == 0) ? new Random() : new Random(seed)); } } public static SavedItem? GetRandomItem() { if (_allItems == null || _allItems.Count == 0 || _rng == null) { Plugin.Log.LogWarning((object)"GetRandomItem: _allItems or _rng is null"); return null; } for (int i = 0; i < 100; i++) { int index = _rng.Next(_allItems.Count); SavedItem val = _allItems[index]; if (!((Object)(object)val == (Object)null) && !ExcludedNames.Contains(((Object)val).name)) { return val; } } Plugin.Log.LogWarning((object)"GetRandomItem failed after 100 attempts, returning null"); return null; } public static bool RandomChance(float probability) { if (_rng == null) { return false; } return _rng.NextDouble() < (double)probability; } public static SavedItem? PeekRandomItem(Random rng) { if (_allItems == null || _allItems.Count == 0 || rng == null) { return null; } for (int i = 0; i < 100; i++) { int index = rng.Next(_allItems.Count); SavedItem val = _allItems[index]; if (!((Object)(object)val == (Object)null) && !ExcludedNames.Contains(((Object)val).name)) { return val; } } return null; } public static List<SavedItem> GetAllItems() { return _allItems; } } [HarmonyPatch(typeof(CollectableItemPickup), "DoPickupAction")] public class PickupPatch { private static readonly Dictionary<string, string> ToolToSkillField = new Dictionary<string, string> { { "Silk Spear", "hasNeedleThrow" }, { "Thread Sphere", "hasThreadSphere" }, { "Harpoon Dash", "hasHarpoonDash" }, { "Silk Charge", "hasSilkCharge" }, { "Silk Bomb", "hasSilkBomb" }, { "Silk Boss Needle", "hasSilkBossNeedle" }, { "Needolin", "hasNeedolin" }, { "Dash", "hasDash" }, { "Brolly", "hasBrolly" }, { "DoubleJump", "hasDoubleJump" }, { "Charge Slash", "hasChargeSlash" }, { "SuperJump", "hasSuperJump" }, { "Wall Jump", "hasWallJump" } }; private static void Prefix(CollectableItemPickup __instance, ref bool __runOriginal) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) try { if (!__runOriginal || (Object)(object)__instance == (Object)null) { return; } SavedItem item = __instance.Item; if ((Object)(object)item == (Object)null || ItemRandomizer.ExcludedNames.Contains(((Object)item).name)) { return; } SavedItem randomItem = ItemRandomizer.GetRandomItem(); if ((Object)(object)randomItem == (Object)null) { return; } object[] array = new object[4]; Scene scene = ((Component)__instance).gameObject.scene; array[0] = ((Scene)(ref scene)).name; array[1] = ((Component)__instance).transform.position.x; array[2] = ((Component)__instance).transform.position.y; array[3] = ((Component)__instance).transform.position.z; string key = string.Format("{0}_{1:F1}_{2:F1}_{3:F1}", array); if (item is CollectableRelic || item is ToolItem) { Plugin.AddDestroyedPickupKey(key); Plugin.Log.LogInfo((object)("特殊点 " + ((Object)item).name + " 强制销毁,给予随机物品 " + ((Object)randomItem).name)); bool flag = false; ToolItem val = (ToolItem)(object)((randomItem is ToolItem) ? randomItem : null); if (val != null) { string skillFieldName = GetSkillFieldName(val.name); if (!string.IsNullOrEmpty(skillFieldName)) { PlayerData instance = PlayerData.instance; if (instance != null) { FieldInfo field = ((object)instance).GetType().GetField(skillFieldName, BindingFlags.Instance | BindingFlags.Public); if (field != null && field.FieldType == typeof(bool)) { field.SetValue(instance, true); flag = true; } } } try { MethodInfo methodInfo = typeof(ToolItem).GetMethod("Unlock", new Type[2] { typeof(Action), typeof(PopupFlags) }) ?? typeof(ToolItem).GetMethod("Unlock", Type.EmptyTypes); if (methodInfo != null) { if (methodInfo.GetParameters().Length == 0) { methodInfo.Invoke(val, null); } else { methodInfo.Invoke(val, new object[2] { null, (object)(PopupFlags)3 }); } flag = true; } else { Plugin.Log.LogError((object)"无法找到 ToolItem.Unlock 方法"); } } catch (Exception arg) { Plugin.Log.LogError((object)$"Unlock 调用失败: {arg}"); } } else { flag = randomItem.TryGet(false, true); } if (flag) { RecentItemsUI.AddItem(randomItem); Plugin.Log.LogInfo((object)("特殊点物品 " + ((Object)randomItem).name + " 给予成功")); } else { Plugin.Log.LogError((object)("特殊点物品 " + ((Object)randomItem).name + " 给予失败!")); } __runOriginal = false; Object.Destroy((Object)(object)((Component)__instance).gameObject); } else { Plugin.AddDestroyedPickupKey(key); Plugin.Log.LogInfo((object)("普通点 " + ((Object)item).name + " 强制销毁,给予随机物品 " + ((Object)randomItem).name)); if (randomItem.TryGet(false, true)) { RecentItemsUI.AddItem(randomItem); Plugin.Log.LogInfo((object)("普通点物品 " + ((Object)randomItem).name + " 给予成功")); } else { Plugin.Log.LogError((object)("普通点物品 " + ((Object)randomItem).name + " 给予失败!")); } __runOriginal = false; Object.Destroy((Object)(object)((Component)__instance).gameObject); } } catch (Exception arg2) { Plugin.Log.LogError((object)$"Exception in PickupPatch.Prefix: {arg2}"); } } private static string GetSkillFieldName(string toolName) { ToolToSkillField.TryGetValue(toolName, out string value); return value; } } [HarmonyPatch(typeof(ShopItemStats), "SetPurchased")] public static class ShopItemStats_Purchase_Patch { [CompilerGenerated] private sealed class <DelayedRebuild>d__2 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public ShopMenuStock shop; private MethodInfo <buildMethod>5__1; private Exception <ex>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayedRebuild>d__2(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <buildMethod>5__1 = null; <ex>5__2 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; try { <buildMethod>5__1 = typeof(ShopMenuStock).GetMethod("BuildItemList", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (<buildMethod>5__1 != null) { <buildMethod>5__1.Invoke(shop, null); Plugin.Log.LogInfo((object)"商店重建完成"); } else { Plugin.Log.LogError((object)"未找到 BuildItemList 方法"); } <buildMethod>5__1 = null; } catch (Exception ex) { <ex>5__2 = ex; Plugin.Log.LogError((object)$"商店重建异常: {<ex>5__2}"); } 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(); } } private static void Prefix() { try { ToolUnlockPatch.IsShopPurchase = true; } catch { } } private static void Postfix(ShopItemStats __instance) { try { ToolUnlockPatch.IsShopPurchase = false; if ((Object)(object)((__instance != null) ? __instance.Item : null) == (Object)null) { Plugin.Log.LogWarning((object)"购买实例或物品为空,跳过处理"); return; } string name = ((Object)__instance.Item).name; if (string.IsNullOrEmpty(name) || !name.Contains("_")) { Plugin.Log.LogWarning((object)("永久ID格式错误: " + name + ",仅隐藏物体")); ((Component)__instance).gameObject.SetActive(false); return; } ShopMenuStock_BuildItemList_Patch.SetCount(name, 0); ShopMenuStock componentInParent = ((Component)__instance).GetComponentInParent<ShopMenuStock>(); if ((Object)(object)componentInParent == (Object)null) { Plugin.Log.LogError((object)"无法获取 ShopMenuStock"); return; } ((Component)__instance).gameObject.SetActive(false); ((MonoBehaviour)componentInParent).StartCoroutine(DelayedRebuild(componentInParent)); Plugin.Log.LogInfo((object)("永久ID " + name + " 已购买,触发商店重建")); } catch (Exception arg) { Plugin.Log.LogError((object)$"购买后处理异常: {arg}"); if ((Object)(object)__instance != (Object)null) { ((Component)__instance).gameObject.SetActive(false); } } } [IteratorStateMachine(typeof(<DelayedRebuild>d__2))] private static IEnumerator DelayedRebuild(ShopMenuStock shop) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DelayedRebuild>d__2(0) { shop = shop }; } } [HarmonyPatch(typeof(ShopMenuStock), "BuildItemList")] public static class ShopMenuStock_BuildItemList_Patch { private static Dictionary<string, int> _slotCounts = new Dictionary<string, int>(); private static string FilePath => Path.Combine(Paths.ConfigPath, "SilksongItemRandomizer", "shop_slots.json"); private static void LoadCounts() { try { if (File.Exists(FilePath)) { string text = File.ReadAllText(FilePath); _slotCounts = JsonConvert.DeserializeObject<Dictionary<string, int>>(text) ?? new Dictionary<string, int>(); } else { _slotCounts.Clear(); } } catch (Exception arg) { Plugin.Log.LogError((object)$"加载商店槽位计数失败: {arg}"); _slotCounts.Clear(); } } private static void SaveCounts() { try { string directoryName = Path.GetDirectoryName(FilePath); if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } string contents = JsonConvert.SerializeObject((object)_slotCounts, (Formatting)1); File.WriteAllText(FilePath, contents); } catch (Exception arg) { Plugin.Log.LogError((object)$"保存商店槽位计数失败: {arg}"); } } public static int GetCount(string permanentId) { int value; return (!_slotCounts.TryGetValue(permanentId, out value)) ? 1 : value; } public static void SetCount(string permanentId, int count) { _slotCounts[permanentId] = count; SaveCounts(); } public static void ResetAllCounts() { _slotCounts.Clear(); if (File.Exists(FilePath)) { File.Delete(FilePath); } Plugin.Log.LogInfo((object)"商店槽位计数已重置"); } private static void Postfix(ShopMenuStock __instance) { //IL_0012: 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_0165: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__instance == (Object)null) { return; } Scene activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; LoadCounts(); __instance.availableStock.Clear(); float num = 0f; foreach (ShopItemStats item2 in __instance.spawnedStock) { if ((Object)(object)item2 == (Object)null) { continue; } ShopItem item = item2.Item; string text = ((item != null) ? ((Object)item).name : null); if (string.IsNullOrEmpty(text) || !text.Contains("_")) { int num2 = __instance.spawnedStock.IndexOf(item2); text = $"{name}_{num2}"; } int count = GetCount(text); if (count <= 0) { ((Component)item2).gameObject.SetActive(false); continue; } int price; SavedItem orCreateShopItem = ShopRandomizer.GetOrCreateShopItem(text, out price); if ((Object)(object)orCreateShopItem == (Object)null) { Plugin.Log.LogWarning((object)("商店随机:永久ID " + text + " 获取物品失败,跳过")); continue; } ShopItem val = CreateShopItem(orCreateShopItem, price, text); if (!((Object)(object)val == (Object)null)) { item2.SetItem(val); ((Component)item2).transform.localPosition = new Vector3(0f, num, 0f); item2.ItemNumber = __instance.availableStock.Count; __instance.availableStock.Add(item2); num += __instance.yDistance; ((Component)item2).gameObject.SetActive(true); item2.UpdateAppearance(); Plugin.Log.LogInfo((object)$"商店重建:永久ID {text} -> {((Object)orCreateShopItem).name} 价格 {price}"); } } foreach (ShopSubItemStats spawnedSubItem in __instance.spawnedSubItems) { ((Component)spawnedSubItem).gameObject.SetActive(false); } } catch (Exception arg) { Plugin.Log.LogError((object)$"商店重建补丁异常: {arg}"); } } private static ShopItem CreateShopItem(SavedItem savedItem, int price, string permanentId) { ShopItem val = ShopItem.CreateTemp(((Object)savedItem).name); ((Object)val).name = permanentId; FieldInfo field = typeof(ShopItem).GetField("savedItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { field.SetValue(val, savedItem); FieldInfo field2 = typeof(ShopItem).GetField("cost", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field2 != null) { field2.SetValue(val, price); FieldInfo field3 = typeof(ShopItem).GetField("costReference", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field3 != null) { field3.SetValue(val, null); } FieldInfo field4 = typeof(ShopItem).GetField("currencyType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field4 != null) { field4.SetValue(val, (object)(CurrencyType)0); } ClearField(val, "playerDataBoolName"); ClearField(val, "playerDataIntName"); ClearField(val, "requiredItem"); ClearField(val, "upgradeFromItem"); if (val.questsAppearConditions == null) { val.questsAppearConditions = (QuestTest[])(object)new QuestTest[0]; } return val; } Plugin.Log.LogError((object)"未找到 cost 字段"); return null; } Plugin.Log.LogError((object)"未找到 savedItem 字段"); return null; } private static void ClearField(object obj, string fieldName) { FieldInfo field = obj.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType.IsClass) { field.SetValue(obj, null); } } } public static class ShopRandomizer { private static Dictionary<string, SavedItem> _shopItemCache = new Dictionary<string, SavedItem>(); private static Dictionary<string, int> _shopPriceCache = new Dictionary<string, int>(); public static void ResetCache() { _shopItemCache.Clear(); _shopPriceCache.Clear(); Plugin.Log.LogInfo((object)"商店随机缓存已清空"); } public static SavedItem GetOrCreateShopItem(string permanentId, out int price) { if (_shopItemCache.TryGetValue(permanentId, out SavedItem value)) { if (!IsItemOwned(value)) { price = (_shopPriceCache.TryGetValue(permanentId, out var value2) ? value2 : GetDefaultPrice(value)); return value; } Plugin.Log.LogInfo((object)("商店槽位 " + permanentId + " 的物品 " + ((Object)value).name + " 已拥有,重新生成")); } string[] array = permanentId.Split('_'); string sceneName = string.Join("_", array.Take(array.Length - 1)); int originalIndex = int.Parse(array.Last()); int price2; SavedItem val = GenerateRandomShopItem(sceneName, originalIndex, permanentId, out price2); _shopItemCache[permanentId] = val; _shopPriceCache[permanentId] = price2; price = price2; return val; } public static SavedItem GetOrCreateShopItem(string sceneName, int slotIndex, out int price) { string permanentId = $"{sceneName}_{slotIndex}"; return GetOrCreateShopItem(permanentId, out price); } private static SavedItem GenerateRandomShopItem(string sceneName, int originalIndex, string permanentId, out int price) { int value = Plugin.RandomSeed.Value; int hashCode = permanentId.GetHashCode(); int seed = value ^ hashCode; Random random = new Random(seed); List<SavedItem> allItems = ItemRandomizer.GetAllItems(); if (allItems == null || allItems.Count == 0) { price = 0; return null; } List<SavedItem> list = allItems.Where((SavedItem item) => !IsItemOwned(item) && !(item is ToolCrest)).ToList(); if (list.Count == 0) { Plugin.Log.LogWarning((object)("商店随机池为空,使用所有物品中的第一个 (永久ID: " + permanentId + ")")); price = GetDefaultPrice(allItems[0]); return allItems[0]; } int index = random.Next(list.Count); SavedItem val = list[index]; price = GenerateRandomPrice(val, random); return val; } private static bool IsItemOwned(SavedItem item) { try { if (!item.CanGetMore()) { return true; } } catch { } return false; } private static int GenerateRandomPrice(SavedItem item, Random rng) { int defaultPrice = GetDefaultPrice(item); float num = (float)(rng.NextDouble() * 1.95 + 0.05); return Mathf.RoundToInt((float)defaultPrice * num); } private static int GetDefaultPrice(SavedItem item) { FieldInfo field = ((object)item).GetType().GetField("cost", BindingFlags.Instance | BindingFlags.Public); if (field != null && field.FieldType == typeof(int)) { return (int)field.GetValue(item); } return 100; } } [BepInPlugin("YourName.SilksongItemRandomizer", "Silksong Item Randomizer", "1.0.0.0")] public class Plugin : BaseUnityPlugin { [CompilerGenerated] private sealed class <DestroyMarkedPickups>d__25 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Scene scene; public Plugin <>4__this; private CollectableItemPickup[] <pickups>5__1; private CollectableItemPickup[] <>s__2; private int <>s__3; private CollectableItemPickup <p>5__4; private string <key>5__5; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DestroyMarkedPickups>d__25(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <pickups>5__1 = null; <>s__2 = null; <p>5__4 = null; <key>5__5 = null; <>1__state = -2; } private bool MoveNext() { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; <pickups>5__1 = Resources.FindObjectsOfTypeAll<CollectableItemPickup>(); Log.LogInfo((object)$"[DestroyMarkedPickups] 开始检查场景 {((Scene)(ref scene)).name},已记录键数:{_destroyedPickupKeys.Count}"); <>s__2 = <pickups>5__1; for (<>s__3 = 0; <>s__3 < <>s__2.Length; <>s__3++) { <p>5__4 = <>s__2[<>s__3]; if (!(((Component)<p>5__4).gameObject.scene != scene)) { <key>5__5 = $"{((Scene)(ref scene)).name}_{((Component)<p>5__4).transform.position.x:F1}_{((Component)<p>5__4).transform.position.y:F1}_{((Component)<p>5__4).transform.position.z:F1}"; if (_destroyedPickupKeys.Contains(<key>5__5)) { Object.Destroy((Object)(object)((Component)<p>5__4).gameObject); Log.LogInfo((object)("[DestroyMarkedPickups] 销毁已标记点: " + <key>5__5)); } <key>5__5 = null; <p>5__4 = null; } } <>s__2 = null; 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(); } } [CompilerGenerated] private sealed class <InitializeAfterLoad>d__24 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public int seed; public Plugin <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <InitializeAfterLoad>d__24(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(3f); <>1__state = 1; return true; case 1: <>1__state = -1; ItemRandomizer.Initialize(seed); ToolUnlockPatch.Initialize(); CrestRandomizer.Initialize(); Log.LogInfo((object)$"种子: {seed}"); 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(); } } internal static ManualLogSource Log; private static HashSet<string> _destroyedPickupKeys = new HashSet<string>(); private static string _notificationMessage = null; private static float _notificationEndTime = 0f; private static GUIStyle _notificationStyle; public static ConfigEntry<int> RandomSeed { get; private set; } public static Plugin Instance { get; private set; } private static string DestroyedPickupsFilePath { get { string text = Path.Combine(Paths.ConfigPath, "SilksongItemRandomizer"); if (!Directory.Exists(text)) { Directory.CreateDirectory(text); } return Path.Combine(text, "destroyed_pickups.json"); } } public static void ShowNotification(string message, float duration = 3f) { _notificationMessage = message; _notificationEndTime = Time.time + duration; } private Texture2D MakeTexture(int width, int height, Color col) { //IL_0010: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown Color[] array = (Color[])(object)new Color[width * height]; for (int i = 0; i < array.Length; i++) { array[i] = col; } Texture2D val = new Texture2D(width, height); val.SetPixels(array); val.Apply(); return val; } private void Awake() { Instance = this; Log = ((BaseUnityPlugin)this).Logger; RandomSeed = ((BaseUnityPlugin)this).Config.Bind<int>("General", "RandomSeed", 0, "随机种子 (0 表示随机)"); Harmony.CreateAndPatchAll(typeof(PickupPatch), (string)null); Harmony.CreateAndPatchAll(typeof(CurrencyCollectPatch), (string)null); Harmony.CreateAndPatchAll(typeof(TryGetPatch), (string)null); Harmony.CreateAndPatchAll(typeof(ToolUnlockPatch), (string)null); Harmony.CreateAndPatchAll(typeof(CrestRandomizePatch), (string)null); Harmony.CreateAndPatchAll(typeof(ShopMenuStock_BuildItemList_Patch), (string)null); Harmony.CreateAndPatchAll(typeof(ShopItemStats_Purchase_Patch), (string)null); Harmony.CreateAndPatchAll(typeof(SilkSpearPityPatch), (string)null); Harmony.CreateAndPatchAll(typeof(BenchRespawnPatch), (string)null); HazardSpawner.Initialize(); SceneManager.sceneLoaded += OnSceneLoaded; ((MonoBehaviour)this).StartCoroutine(InitializeAfterLoad(RandomSeed.Value)); LoadDestroyedKeys(); Log.LogInfo((object)"SilksongItemRandomizer loaded"); } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) ((MonoBehaviour)this).StartCoroutine(DestroyMarkedPickups(scene)); } private void LoadDestroyedKeys() { string destroyedPickupsFilePath = DestroyedPickupsFilePath; if (File.Exists(destroyedPickupsFilePath)) { try { string text = File.ReadAllText(destroyedPickupsFilePath); List<string> list = JsonConvert.DeserializeObject<List<string>>(text); _destroyedPickupKeys = ((list != null) ? new HashSet<string>(list) : new HashSet<string>()); return; } catch (Exception arg) { Log.LogError((object)$"加载特殊点消失记录失败: {arg}"); _destroyedPickupKeys = new HashSet<string>(); return; } } _destroyedPickupKeys = new HashSet<string>(); } private void SaveDestroyedKeys() { string destroyedPickupsFilePath = DestroyedPickupsFilePath; try { List<string> list = _destroyedPickupKeys.ToList(); string contents = JsonConvert.SerializeObject((object)list, (Formatting)1); File.WriteAllText(destroyedPickupsFilePath, contents); } catch (Exception arg) { Log.LogError((object)$"保存特殊点消失记录失败: {arg}"); } } public static void AddDestroyedPickupKey(string key) { _destroyedPickupKeys.Add(key); if ((Object)(object)Instance != (Object)null) { Instance.SaveDestroyedKeys(); } else { Log.LogError((object)"AddDestroyedPickupKey: Instance is null"); } } public static void ResetDestroyedPickupKeys() { _destroyedPickupKeys.Clear(); string destroyedPickupsFilePath = DestroyedPickupsFilePath; if (File.Exists(destroyedPickupsFilePath)) { File.Delete(destroyedPickupsFilePath); } } public static void ResetAllStaticData() { CrestRandomizer.ResetMappings(); CrestRandomizePatch.ResetProcessedIds(); CurrencyCollectPatch.ResetCounters(); ResetDestroyedPickupKeys(); ShopRandomizer.ResetCache(); ShopMenuStock_BuildItemList_Patch.ResetAllCounts(); Log.LogInfo((object)"物品随机MOD所有静态数据已重置"); Log.LogInfo((object)"物品随机MOD所有静态数据已重置"); } [IteratorStateMachine(typeof(<InitializeAfterLoad>d__24))] private IEnumerator InitializeAfterLoad(int seed) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <InitializeAfterLoad>d__24(0) { <>4__this = this, seed = seed }; } [IteratorStateMachine(typeof(<DestroyMarkedPickups>d__25))] private IEnumerator DestroyMarkedPickups(Scene scene) { //IL_000e: 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) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DestroyMarkedPickups>d__25(0) { <>4__this = this, scene = scene }; } private void Update() { //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_008f: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) RecentItemsUI.UpdateAutoHide(); if (Input.GetKeyDown((KeyCode)286)) { RecentItemsUI.Toggle(); Log.LogInfo((object)("最近获得物品UI " + (RecentItemsUI.IsVisible ? "显示" : "隐藏"))); } if (Input.GetKeyDown((KeyCode)289)) { DumpAllMappings(); } if (Input.GetKeyDown((KeyCode)290)) { HeroController instance = HeroController.instance; if ((Object)(object)instance != (Object)null) { Vector3 val = instance.transform.position + HazardSpawner.GetSpawnOffset(); HazardSpawner.SpawnCustomHazard(val); Log.LogInfo((object)$"在玩家位置 + 偏移生成 hazard,最终坐标: {val}"); } } } private void OnGUI() { //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_0074: 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) RecentItemsUI.Draw(); HazardSpawner.DrawUI(); if (_notificationMessage != null && Time.time <= _notificationEndTime) { if (_notificationStyle == null) { _notificationStyle = new GUIStyle(GUI.skin.box); _notificationStyle.fontSize = 40; _notificationStyle.alignment = (TextAnchor)4; _notificationStyle.normal.textColor = Color.white; _notificationStyle.normal.background = MakeTexture(2, 2, new Color(0f, 0f, 0f, 0.7f)); } float num = 600f; float num2 = 120f; float num3 = ((float)Screen.width - num) / 2f; float num4 = Screen.height / 2 - 100; GUI.Box(new Rect(num3, num4, num, num2), _notificationMessage, _notificationStyle); } else { _notificationMessage = null; } } private void DumpAllMappings() { //IL_0194: Unknown result type (might be due to invalid IL or missing references) int value = RandomSeed.Value; Log.LogInfo((object)$"===== 当前种子: {value} ====="); List<ToolCrest> crestList = CrestRandomizer.CrestList; if (crestList != null && crestList.Count > 0) { Log.LogInfo((object)"--- 纹章映射 ---"); foreach (ToolCrest item2 in crestList) { string name = item2.name; string mappedCrestName = CrestRandomizer.GetMappedCrestName(name); Log.LogInfo((object)(" " + name + " -> " + mappedCrestName)); } } Log.LogInfo((object)"--- 当前场景拾取点映射 ---"); CollectableItemPickup[] source = Resources.FindObjectsOfTypeAll<CollectableItemPickup>(); List<CollectableItemPickup> list = source.Where(delegate(CollectableItemPickup p) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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) _ = ((Component)p).gameObject.scene; Scene scene = ((Component)p).gameObject.scene; return ((Scene)(ref scene)).isLoaded; }).ToList(); if (list.Count == 0) { Log.LogInfo((object)"当前场景无拾取点。"); } else { foreach (CollectableItemPickup item3 in list) { SavedItem item = item3.Item; if (!((Object)(object)item == (Object)null)) { int seed = value + ((Object)item3).GetInstanceID(); Random rng = new Random(seed); SavedItem val = ItemRandomizer.PeekRandomItem(rng); if ((Object)(object)val != (Object)null) { Log.LogInfo((object)$" {((Object)item).name} (位置 {((Component)item3).transform.position}) -> {((Object)val).name}"); } else { Log.LogInfo((object)(" " + ((Object)item).name + " -> 随机失败")); } } } } Log.LogInfo((object)"==============================="); } } public static class RecentItemsUI { [CompilerGenerated] private static class <>O { public static WindowFunction <0>__DoWindow; } private static Queue<SavedItem> recentItems = new Queue<SavedItem>(); private const int MaxItems = 5; private static Rect windowRect = new Rect(20f, 300f, 700f, 600f); private static bool _showWindow = false; private static float hideTime = 0f; public static bool IsVisible => _showWindow; public static void AddItem(SavedItem item) { if (!((Object)(object)item == (Object)null)) { recentItems.Enqueue(item); while (recentItems.Count > 5) { recentItems.Dequeue(); } _showWindow = true; hideTime = Time.time + 10f; } } public static void Toggle() { _showWindow = !_showWindow; if (_showWindow) { hideTime = float.MaxValue; } } public static void UpdateAutoHide() { if (_showWindow && Time.time >= hideTime) { _showWindow = false; } } public static void Draw() { //IL_0014: 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_0043: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown if (_showWindow) { Rect val = windowRect; object obj = <>O.<0>__DoWindow; if (obj == null) { WindowFunction val2 = DoWindow; <>O.<0>__DoWindow = val2; obj = (object)val2; } windowRect = GUILayout.Window(999, val, (WindowFunction)obj, "最近获得物品", Array.Empty<GUILayoutOption>()); } } private static void DoWindow(int id) { //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: 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_00bf: 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_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Expected O, but got Unknown //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) int fontSize = GUI.skin.label.fontSize; GUI.skin.label.fontSize = 32; GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); SavedItem[] array = recentItems.ToArray(); Rect val3 = default(Rect); foreach (SavedItem val in array) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); Sprite val2 = null; try { val2 = ((val != null) ? val.GetPopupIcon() : null); } catch { } float num = 96f; float num2 = 96f; ((Rect)(ref val3))..ctor(0f, 0f, 1f, 1f); if ((Object)(object)val2 != (Object)null && (Object)(object)val2.texture != (Object)null) { Rect textureRect = val2.textureRect; float num3 = ((Texture)val2.texture).width; float num4 = ((Texture)val2.texture).height; ((Rect)(ref val3))..ctor(((Rect)(ref textureRect)).x / num3, ((Rect)(ref textureRect)).y / num4, ((Rect)(ref textureRect)).width / num3, ((Rect)(ref textureRect)).height / num4); if (((Rect)(ref textureRect)).width > 0f && ((Rect)(ref textureRect)).height > 0f) { num2 = num * (((Rect)(ref textureRect)).height / ((Rect)(ref textureRect)).width); if (num2 > 180f) { num2 = 180f; } } } Rect rect = GUILayoutUtility.GetRect(num, num2, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(num), GUILayout.Height(num2) }); if ((Object)(object)val2 != (Object)null && (Object)(object)val2.texture != (Object)null) { GUI.DrawTextureWithTexCoords(rect, (Texture)(object)val2.texture, val3); } else { GUI.Box(rect, ""); GUI.Label(rect, "?", new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontSize = 36 }); } string text = "未知物品"; try { MethodInfo methodInfo = ((object)val)?.GetType().GetMethod("GetCollectionName", BindingFlags.Instance | BindingFlags.Public); text = ((!(methodInfo != null)) ? ((val != null) ? val.GetPopupName() : null) : (methodInfo.Invoke(val, null) as string)); if (string.IsNullOrEmpty(text)) { text = ((val != null) ? ((Object)val).name : null) ?? "未知物品"; } } catch { text = ((val != null) ? ((Object)val).name : null) ?? "未知物品"; } GUILayout.Label("• " + text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(num2) }); GUILayout.EndHorizontal(); } GUILayout.EndVertical(); GUI.DragWindow(); GUI.skin.label.fontSize = fontSize; } } [HarmonyPatch(typeof(CurrencyObjectBase), "Collect")] public static class SilkSpearPityPatch { private static int _silkSpearAttempts; private static bool _silkSpearGiven; private const int SILK_SPEAR_PITY = 200; private static SavedItem? _silkSpearItem; public static bool IsGivingSilkSpear; static SilkSpearPityPatch() { _silkSpearAttempts = 0; _silkSpearGiven = false; IsGivingSilkSpear = false; SavedItem[] source = Resources.FindObjectsOfTypeAll<SavedItem>(); _silkSpearItem = ((IEnumerable<SavedItem>)source).FirstOrDefault((Func<SavedItem, bool>)((SavedItem item) => ((Object)item).name == "Silk Spear")); if ((Object)(object)_silkSpearItem == (Object)null) { Plugin.Log.LogWarning((object)"[丝矛独立补丁] 未找到丝矛物品,保底将禁用。"); } else { Plugin.Log.LogInfo((object)("[丝矛独立补丁] 丝矛物品已找到: " + ((Object)_silkSpearItem).name)); } } public static void ResetCounter() { _silkSpearAttempts = 0; _silkSpearGiven = false; Plugin.Log.LogInfo((object)"[丝矛独立补丁] 计数器已重置"); } private static void Postfix(bool __result) { if (!__result || (Object)(object)_silkSpearItem == (Object)null || _silkSpearGiven) { return; } _silkSpearAttempts++; if (_silkSpearGiven || _silkSpearAttempts < 200) { return; } Plugin.Log.LogInfo((object)$"[丝矛独立补丁] 保底触发(第{_silkSpearAttempts}次)"); bool flag = false; IsGivingSilkSpear = true; SavedItem? silkSpearItem = _silkSpearItem; ToolItem val = (ToolItem)(object)((silkSpearItem is ToolItem) ? silkSpearItem : null); if (val != null) { try { MethodInfo methodInfo = typeof(ToolItem).GetMethod("Unlock", Type.EmptyTypes) ?? typeof(ToolItem).GetMethod("Unlock", new Type[2] { typeof(Action), typeof(PopupFlags) }); if (methodInfo != null) { if (methodInfo.GetParameters().Length == 0) { methodInfo.Invoke(val, null); } else { methodInfo.Invoke(val, new object[2] { null, (object)(PopupFlags)3 }); } flag = true; } } catch (Exception arg) { Plugin.Log.LogError((object)$"[丝矛独立补丁] Unlock 失败: {arg}"); } } else { flag = _silkSpearItem.TryGet(false, true); } IsGivingSilkSpear = false; if (flag) { Plugin.Log.LogInfo((object)"[丝矛独立补丁] 丝矛成功给予"); Plugin.ShowNotification("获得丝矛!"); _silkSpearGiven = true; } else { Plugin.Log.LogError((object)"[丝矛独立补丁] 丝矛给予失败"); _silkSpearGiven = true; } } } public static class ToolUnlockPatch { private static List<ToolItem>? _allTools; public static bool IsShopPurchase; public static void Initialize() { _allTools = Resources.FindObjectsOfTypeAll<ToolItem>().ToList(); if (_allTools.Count == 0) { Plugin.Log.LogWarning((object)"No ToolItem found! Tool randomizer may not work."); } } [HarmonyPatch(typeof(ToolItem), "Unlock")] [HarmonyPrefix] private static bool Prefix(ToolItem __instance, Action afterTutorialMsg, PopupFlags popupFlags) { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) try { if (IsShopPurchase) { return true; } if (_allTools == null || _allTools.Count == 0) { Initialize(); if (_allTools == null || _allTools.Count == 0) { Plugin.Log.LogWarning((object)"Tool list empty, cannot randomize."); return true; } } ToolItem val = _allTools[ItemRandomizer.Rng.Next(_allTools.Count)]; if ((Object)(object)val == (Object)(object)__instance) { return true; } Plugin.Log.LogInfo((object)("工具随机: " + (((__instance != null) ? __instance.name : null) ?? "null") + " -> " + val.name)); val.Unlock(afterTutorialMsg, popupFlags); return false; } catch (Exception arg) { Plugin.Log.LogError((object)$"Exception in ToolUnlockPatch.Prefix: {arg}"); return true; } } } [HarmonyPatch(typeof(SavedItem), "TryGet")] public class TryGetPatch { private static bool _isProcessing; private static void Postfix(SavedItem __instance, bool __result) { try { if (_isProcessing || !__result) { return; } if (((Object)__instance).name != "Rosary_Set_Frayed") { RecentItemsUI.AddItem(__instance); } _isProcessing = true; try { UnlockRandomAttack(); } catch (Exception arg) { Plugin.Log.LogError((object)$"Error unlocking attack: {arg}"); } finally { _isProcessing = false; } } catch (Exception arg2) { Plugin.Log.LogError((object)$"Unhandled exception in TryGetPatch.Postfix: {arg2}"); } } private static void UnlockRandomAttack() { Type type = Type.GetType("StartingAbilityPicker.Plugin, StartingAbilityPicker"); if (type == null) { return; } FieldInfo field = type.GetField("AllowUpwardAttack", BindingFlags.Static | BindingFlags.Public); FieldInfo field2 = type.GetField("AllowLeftAttack", BindingFlags.Static | BindingFlags.Public); FieldInfo field3 = type.GetField("AllowRightAttack", BindingFlags.Static | BindingFlags.Public); if (field == null || field2 == null || field3 == null) { return; } bool flag = (bool)field.GetValue(null); bool flag2 = (bool)field2.GetValue(null); bool flag3 = (bool)field3.GetValue(null); List<string> list = new List<string>(); if (!flag) { list.Add("upward"); } if (!flag2) { list.Add("left"); } if (!flag3) { list.Add("right"); } if (list.Count == 0 || ItemRandomizer.Rng == null || ItemRandomizer.Rng.NextDouble() > 0.05) { return; } string text = list[ItemRandomizer.Rng.Next(list.Count)]; PlayerData instance = PlayerData.instance; if (instance != null) { switch (text) { case "upward": field.SetValue(null, true); instance.SetBool("AllowUpwardAttack", true); Plugin.Log.LogInfo((object)"Attack direction unlocked via item: upward (saved to PlayerData)"); break; case "left": field2.SetValue(null, true); instance.SetBool("AllowLeftAttack", true); Plugin.Log.LogInfo((object)"Attack direction unlocked via item: left (saved to PlayerData)"); break; case "right": field3.SetValue(null, true); instance.SetBool("AllowRightAttack", true); Plugin.Log.LogInfo((object)"Attack direction unlocked via item: right (saved to PlayerData)"); break; } } } } } namespace SilksongItemRandomizer.Hazard { public class HazardDebug : MonoBehaviour { private void OnTriggerEnter2D(Collider2D other) { if (((Component)other).CompareTag("Hero") || ((Component)other).CompareTag("Player")) { Plugin.Log.LogInfo((object)"【调试】玩家进入 hazard 触发器!"); } } } public static class HazardSpawner { [CompilerGenerated] private static class <>O { public static WindowFunction <0>__DoUIWindow; public static UnityAction<Scene, LoadSceneMode> <1>__OnSceneLoaded; } [CompilerGenerated] private sealed class <>c__DisplayClass28_0 { public Vector3 spawnPos; internal bool <AutoGenerateForSceneCoroutine>b__0(Vector3 pos) { //IL_0000: 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) return Vector3.Distance(pos, spawnPos) < 2f; } } [CompilerGenerated] private sealed class <AutoGenerateForSceneCoroutine>d__28 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string sceneName; private List<Vector3> <positions>5__1; private int <maxAttempts>5__2; private int <generated>5__3; private Random <rand>5__4; private int <attempt>5__5; private Vector3 <center>5__6; private Vector2 <randomPoint>5__7; private RaycastHit2D <hit>5__8; private <>c__DisplayClass28_0 <>8__9; private bool <tooClose>5__10; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <AutoGenerateForSceneCoroutine>d__28(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <positions>5__1 = null; <rand>5__4 = null; <>8__9 = null; <>1__state = -2; } private bool MoveNext() { //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; if (_sceneRecords.ContainsKey(sceneName)) { Plugin.Log.LogInfo((object)("场景 " + sceneName + " 已有记录,跳过生成")); return false; } if (_sceneHazardCount <= 0) { Plugin.Log.LogInfo((object)("场景 " + sceneName + " 生成数量为 0,跳过")); return false; } Plugin.Log.LogInfo((object)$"开始为场景 {sceneName} 自动生成 {_sceneHazardCount} 个 hazard"); <positions>5__1 = new List<Vector3>(); <maxAttempts>5__2 = 200; <generated>5__3 = 0; <rand>5__4 = ((_currentSeed != 0) ? new Random(_currentSeed + sceneName.GetHashCode()) : new Random()); <attempt>5__5 = 0; while (<attempt>5__5 < <maxAttempts>5__2 && <generated>5__3 < _sceneHazardCount) { <center>5__6 = new Vector3(0f, 0f, 0f); if ((Object)(object)Object.FindObjectOfType<HeroController>() != (Object)null) { <center>5__6 = Object.FindObjectOfType<HeroController>().transform.position; } <randomPoint>5__7 = new Vector2(<center>5__6.x + (float)(<rand>5__4.NextDouble() * 100.0 - 50.0), <center>5__6.y + (float)(<rand>5__4.NextDouble() * 100.0 - 50.0)); <hit>5__8 = Physics2D.Raycast(<randomPoint>5__7, Vector2.down, 100f, GROUND_LAYER_MASK); if ((Object)(object)((RaycastHit2D)(ref <hit>5__8)).collider != (Object)null) { <>8__9 = new <>c__DisplayClass28_0(); <>8__9.spawnPos = Vector2.op_Implicit(((RaycastHit2D)(ref <hit>5__8)).point); <>8__9.spawnPos.y += 0.1f; <tooClose>5__10 = <positions>5__1.Any((Vector3 pos) => Vector3.Distance(pos, <>8__9.spawnPos) < 2f); if (!<tooClose>5__10) { SpawnCustomHazard(<>8__9.spawnPos); <positions>5__1.Add(<>8__9.spawnPos); <generated>5__3++; } <>8__9 = null; } <attempt>5__5++; } _sceneRecords[sceneName] = <positions>5__1; SaveSceneRecords(); Plugin.Log.LogInfo((object)$"场景 {sceneName} 自动生成完成,实际生成 {<generated>5__3} 个"); 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(); } } private static List<GameObject> _spawnedHazards = new List<GameObject>(); private static List<Sprite> _lavaSprites = new List<Sprite>(); private static readonly int GROUND_LAYER_MASK = 1049344; private static Vector3 _spawnOffset = Vector3.zero; private static Vector2 _boxSize = new Vector2(6f, 2f); private static Vector2 _boxOffset = new Vector2(0f, 0f); private static int _damage = 2; private static HazardType _hazardType = (HazardType)4; private static Vector2 _visualSize = new Vector2(1.5f, 1.5f); private static Vector2 _visualOffset = new Vector2(0f, -1f); private static bool _sceneHazardMode = true; private static int _sceneHazardCount = 2; private static int _currentSeed; private static Dictionary<string, List<Vector3>> _sceneRecords = new Dictionary<string, List<Vector3>>(); private static string _sceneRecordFilePath; private static bool _sceneLoadedHandlerRegistered = false; private static string _logFilePath; private static readonly object _logLock = new object(); private static bool _uiVisible = false; private static Rect _uiRect = new Rect(0f, 0f, 500f, 500f); public static void ToggleUI() { _uiVisible = !_uiVisible; } public static void DrawUI() { //IL_0014: 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_0043: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown if (_uiVisible) { Rect uiRect = _uiRect; object obj = <>O.<0>__DoUIWindow; if (obj == null) { WindowFunction val = DoUIWindow; <>O.<0>__DoUIWindow = val; obj = (object)val; } _uiRect = GUILayout.Window(999, uiRect, (WindowFunction)obj, "Hazard 参数调整", Array.Empty<GUILayoutOption>()); } } private static void DoUIWindow(int id) { } public static void Initialize() { LoadLocalSprites(); Physics2D.IgnoreLayerCollision(17, 8, false); string text = Path.Combine(Paths.ConfigPath, "SilksongItemRandomizer"); if (!Directory.Exists(text)) { Directory.CreateDirectory(text); } _logFilePath = Path.Combine(text, "HazardSpawnLog.json"); _sceneRecordFilePath = Path.Combine(text, "hazard_scene_records.json"); LoadSceneRecords(); if (!_sceneLoadedHandlerRegistered) { SceneManager.sceneLoaded += OnSceneLoaded; _sceneLoadedHandlerRegistered = true; } Plugin.Log.LogInfo((object)("HazardSpawner 初始化完成,日志文件: " + _logFilePath)); } private static void LoadLocalSprites() { //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) _lavaSprites.Clear(); string text = Path.Combine(Paths.PluginPath, "SilksongItemRandomizer", "Textures", "Lava"); Plugin.Log.LogInfo((object)("[LoadLocalSprites] 路径: " + text)); if (!Directory.Exists(text)) { Plugin.Log.LogError((object)("文件夹不存在!请确保贴图放在: " + text)); return; } string[] array = (from f in Directory.GetFiles(text, "*.*") where f.EndsWith(".jpg") || f.EndsWith(".jpeg") || f.EndsWith(".png") orderby f select f).ToArray(); Plugin.Log.LogInfo((object)$"找到 {array.Length} 个图片文件"); string[] array2 = array; foreach (string text2 in array2) { try { byte[] array3 = File.ReadAllBytes(text2); Texture2D val = new Texture2D(2, 2); if (ImageConversion.LoadImage(val, array3)) { Sprite item = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); _lavaSprites.Add(item); Plugin.Log.LogInfo((object)$"加载成功: {Path.GetFileName(text2)} {((Texture)val).width}x{((Texture)val).height}"); } else { Plugin.Log.LogError((object)("加载失败: " + Path.GetFileName(text2))); } } catch (Exception ex) { Plugin.Log.LogError((object)("加载异常: " + text2 + " - " + ex.Message)); } } Plugin.Log.LogInfo((object)$"共加载 {_lavaSprites.Count} 张精灵"); } private static void LoadSceneRecords() { if (File.Exists(_sceneRecordFilePath)) { try { string text = File.ReadAllText(_sceneRecordFilePath); _sceneRecords = JsonConvert.DeserializeObject<Dictionary<string, List<Vector3>>>(text) ?? new Dictionary<string, List<Vector3>>(); Plugin.Log.LogInfo((object)$"已加载 {_sceneRecords.Count} 个场景的 hazard 记录"); return; } catch (Exception arg) { Plugin.Log.LogError((object)$"加载场景记录失败: {arg}"); _sceneRecords = new Dictionary<string, List<Vector3>>(); return; } } _sceneRecords = new Dictionary<string, List<Vector3>>(); } private static void SaveSceneRecords() { try { string contents = JsonConvert.SerializeObject((object)_sceneRecords, (Formatting)1); File.WriteAllText(_sceneRecordFilePath, contents); Plugin.Log.LogInfo((object)$"已保存 {_sceneRecords.Count} 个场景的 hazard 记录"); } catch (Exception arg) { Plugin.Log.LogError((object)$"保存场景记录失败: {arg}"); } } private static void OnSceneLoaded(Scene scene, LoadSceneMode mode) { if (_sceneHazardMode && !(((Scene)(ref scene)).name == "Menu_Title") && !(((Scene)(ref scene)).name == "Menu") && !(((Scene)(ref scene)).name == "Loading") && !((Scene)(ref scene)).name.Contains("Menu") && (Object)(object)Plugin.Instance != (Object)null) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(AutoGenerateForSceneCoroutine(((Scene)(ref scene)).name)); } } [IteratorStateMachine(typeof(<AutoGenerateForSceneCoroutine>d__28))] private static IEnumerator AutoGenerateForSceneCoroutine(string sceneName) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <AutoGenerateForSceneCoroutine>d__28(0) { sceneName = sceneName }; } public static void SetSceneHazardMode(bool enabled) { _sceneHazardMode = enabled; Plugin.Log.LogInfo((object)$"场景 Hazard 自动生成模式设置为 {enabled}"); } public static void SetSceneHazardCount(int count) { _sceneHazardCount = Mathf.Max(0, count); Plugin.Log.LogInfo((object)$"场景 Hazard 生成数量设置为 {_sceneHazardCount}"); } public static void SetSeed(int seed) { _currentSeed = seed; Plugin.Log.LogInfo((object)$"HazardSpawner 种子已设置为 {seed}"); } public static void ResetSceneRecords() { _sceneRecords.Clear(); SaveSceneRecords(); Plugin.Log.LogInfo((object)"Hazard 场景记录已重置"); } public static void ResetWorld() { ClearAll(); ResetSceneRecords(); Plugin.Log.LogInfo((object)"HazardSpawner 世界已重置"); } public static void SpawnCustomHazard(Vector3 position) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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) Physics2D.IgnoreLayerCollision(17, 8, false); GameObject val = new GameObject("CustomHazard_Manual"); val.transform.position = position; val.layer = 17; DamageHero val2 = val.AddComponent<DamageHero>(); val2.hazardType = _hazardType; val2.damageDealt = _damage; val2.canClashTink = false; val2.OnDamagedHero = new UnityEvent(); BoxCollider2D val3 = val.AddComponent<BoxCollider2D>(); ((Collider2D)val3).isTrigger = true; val3.size = _boxSize; ((Collider2D)val3).offset = _boxOffset; val.AddComponent<HazardDebug>(); val.AddComponent<NonBouncer>(); val.AddComponent<PersonalObjectPool>(); val.AddComponent<DamageEnemies>(); LavaBox val4 = val.AddComponent<LavaBox>(); val4.isLavaFall = false; val.SetActive(false); val.SetActive(true); AddVisual(val); _spawnedHazards.Add(val); Plugin.Log.LogInfo((object)$"生成 hazard 于 {position}"); RecordSpawnToLog(position); } private static void AddVisual(GameObject parent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_003d: 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) //IL_009f: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("LavaVisual"); val.transform.SetParent(parent.transform); val.transform.localPosition = new Vector3(_visualOffset.x, _visualOffset.y, 0f); val.transform.localScale = new Vector3(_visualSize.x, _visualSize.y, 1f); SpriteRenderer val2 = val.AddComponent<SpriteRenderer>(); if (_lavaSprites.Count > 0) { val2.sprite = _lavaSprites[0]; } else { val2.sprite = CreateColorSprite(Color.red); } ((Renderer)val2).sortingLayerName = "Default"; ((Renderer)val2).sortingOrder = 100; } private static Sprite CreateColorSprite(Color color) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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) Texture2D val = new Texture2D(1, 1); val.SetPixel(0, 0, color); val.Apply(); return Sprite.Create(val, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f)); } private static void RecordSpawnToLog(Vector3 position) { //IL_0013: 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) var anon = new { timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), posX = position.x, posY = position.y, posZ = position.z, boxSizeX = _boxSize.x, boxSizeY = _boxSize.y, visualSizeX = _visualSize.x, visualSizeY = _visualSize.y, damage = _damage, hazardType = ((object)(HazardType)(ref _hazardType)).ToString() }; string value = JsonConvert.SerializeObject((object)anon); lock (_logLock) { try { using StreamWriter streamWriter = new StreamWriter(_logFilePath, append: true); streamWriter.WriteLine(value); } catch (Exception ex) { Plugin.Log.LogError((object)("写入日志失败: " + ex.Message)); } } } public static void SpawnAtPlayer() { //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_0022: Unknown result type (might be due to invalid IL or missing references) HeroController instance = HeroController.instance; if ((Object)(object)instance != (Object)null) { SpawnCustomHazard(instance.transform.position + _spawnOffset); } } public static Vector3 GetSpawnOffset() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return _spawnOffset; } public static void ClearAll() { foreach (GameObject spawnedHazard in _spawnedHazards) { if ((Object)(object)spawnedHazard != (Object)null) { Object.Destroy((Object)(object)spawnedHazard); } } _spawnedHazards.Clear(); Plugin.Log.LogInfo((object)"已清除所有生成的 hazard"); } } }
plugins/SkillRandomizerMod.dll
Decompiled 20 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; 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 BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("SkillRandomizerMod")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0")] [assembly: AssemblyProduct("SkillRandomizerMod")] [assembly: AssemblyTitle("SkillRandomizerMod")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/YourName/SkillRandomizerMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.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; } } } 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 SkillTriggerMod { [BepInPlugin("YourName.SkillTriggerMod", "Skill Trigger Mod", "1.0.0.0")] public class Plugin : BaseUnityPlugin { [CompilerGenerated] private sealed class <CreateTriggerDelayed>d__28 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public (string scene, float x, float y, float z) target; public int index; public Plugin <>4__this; private Vector3 <pos>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CreateTriggerDelayed>d__28(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //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_006a: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; <pos>5__1 = new Vector3(target.x, target.y, target.z); <>4__this.CreateTriggerAt(<pos>5__1, target.scene, index); 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(); } } [CompilerGenerated] private sealed class <DisableShrinesAfterStart>d__25 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Plugin <>4__this; private int <i>5__1; private Scene <scene>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DisableShrinesAfterStart>d__25(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0051: 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_0071: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(5f); <>1__state = 1; return true; case 1: <>1__state = -1; <i>5__1 = 0; while (<i>5__1 < SceneManager.sceneCount) { <scene>5__2 = SceneManager.GetSceneAt(<i>5__1); if (((Scene)(ref <scene>5__2)).isLoaded) { <>4__this.DisableShrinesInScene(<scene>5__2); } <i>5__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(); } } [CompilerGenerated] private sealed class <InitializeRandomizer>d__23 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Plugin <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <InitializeRandomizer>d__23(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(3f); <>1__state = 1; return true; case 1: <>1__state = -1; SkillRandomizer.SetSeed(RandomSeed.Value); 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(); } } internal static ManualLogSource Log; internal static HashSet<string> _triggeredRecords = new HashSet<string>(); private static string _notificationMessage = null; private static float _notificationEndTime = 0f; private static GUIStyle _notificationStyle; private readonly List<(string scene, float x, float y, float z)> targetPositions = new List<(string, float, float, float)> { ("Mosstown_02", 86.922f, 52.568f, 0.004f), ("Crawl_05", 23.032f, 16.568f, 0.004f), ("Shellwood_10", 40.643f, 79.57f, 0.004f), ("Greymoor_22", 39.783f, 36.826f, 0.004f), ("Bone_East_05", 100.062f, 13.568f, 0.004f) }; private readonly string[] shrineKeywords = new string[5] { "bind orb", "shrine weaver ability", "weaver_shrine", "bellshrine", "dash shrine" }; public static ConfigEntry<int> RandomSeed { get; private set; } private static string TriggerRecordsPath => Path.Combine(Paths.ConfigPath, "SkillTriggerMod", "trigger_records.json"); internal static Plugin Instance { get; private set; } public static void ShowNotification(string message, float duration = 3f) { _notificationMessage = message; _notificationEndTime = Time.time + duration; } private void OnGUI() { //IL_00f2: 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_004f: Expected O, but got Unknown //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown if (_notificationMessage == null || Time.time > _notificationEndTime) { _notificationMessage = null; return; } if (_notificationStyle == null) { _notificationStyle = new GUIStyle(GUI.skin.box); _notificationStyle.fontSize = 40; _notificationStyle.alignment = (TextAnchor)4; _notificationStyle.normal.textColor = Color.white; _notificationStyle.normal.background = MakeTexture(2, 2, new Color(0f, 0f, 0f, 0.8f)); _notificationStyle.border = new RectOffset(20, 20, 10, 10); } float num = 600f; float num2 = 120f; float num3 = ((float)Screen.width - num) / 2f; float num4 = Screen.height / 2 - 100; GUI.Box(new Rect(num3, num4, num, num2), _notificationMessage, _notificationStyle); } private Texture2D MakeTexture(int width, int height, Color col) { //IL_0010: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown Color[] array = (Color[])(object)new Color[width * height]; for (int i = 0; i < array.Length; i++) { array[i] = col; } Texture2D val = new Texture2D(width, height); val.SetPixels(array); val.Apply(); return val; } private void Awake() { Instance = this; Log = ((BaseUnityPlugin)this).Logger; RandomSeed = ((BaseUnityPlugin)this).Config.Bind<int>("General", "RandomSeed", 0, "随机种子 (0 表示随机)"); LoadTriggerRecords(); SceneManager.sceneLoaded += OnSceneLoaded; ((MonoBehaviour)this).StartCoroutine(DisableShrinesAfterStart()); ((MonoBehaviour)this).StartCoroutine(InitializeRandomizer()); } private void LoadTriggerRecords() { try { if (File.Exists(TriggerRecordsPath)) { string text = File.ReadAllText(TriggerRecordsPath); List<string> list = JsonConvert.DeserializeObject<List<string>>(text); _triggeredRecords = ((list != null) ? new HashSet<string>(list) : new HashSet<string>()); } else { _triggeredRecords.Clear(); } Log.LogInfo((object)$"技能触发器记录已加载,共 {_triggeredRecords.Count} 条"); } catch (Exception arg) { Log.LogError((object)$"加载技能触发器记录失败: {arg}"); _triggeredRecords.Clear(); } } internal void SaveTriggerRecords() { try { string directoryName = Path.GetDirectoryName(TriggerRecordsPath); if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } string contents = JsonConvert.SerializeObject((object)_triggeredRecords.ToList(), (Formatting)1); File.WriteAllText(TriggerRecordsPath, contents); Log.LogInfo((object)$"技能触发器记录已保存,共 {_triggeredRecords.Count} 条"); } catch (Exception arg) { Log.LogError((object)$"保存技能触发器记录失败: {arg}"); } } [IteratorStateMachine(typeof(<InitializeRandomizer>d__23))] private IEnumerator InitializeRandomizer() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <InitializeRandomizer>d__23(0) { <>4__this = this }; } private void OnDestroy() { SceneManager.sceneLoaded -= OnSceneLoaded; } [IteratorStateMachine(typeof(<DisableShrinesAfterStart>d__25))] private IEnumerator DisableShrinesAfterStart() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DisableShrinesAfterStart>d__25(0) { <>4__this = this }; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) DisableShrinesInScene(scene); for (int i = 0; i < targetPositions.Count; i++) { (string, float, float, float) target = targetPositions[i]; if (target.Item1 == ((Scene)(ref scene)).name) { ((MonoBehaviour)this).StartCoroutine(CreateTriggerDelayed(target, i)); break; } } } private void DisableShrinesInScene(Scene scene) { GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects(); GameObject[] array = rootGameObjects; foreach (GameObject val in array) { Transform[] componentsInChildren = val.GetComponentsInChildren<Transform>(true); foreach (Transform val2 in componentsInChildren) { GameObject gameObject = ((Component)val2).gameObject; string text = ((Object)gameObject).name.ToLower(); string[] array2 = shrineKeywords; foreach (string value in array2) { if (text.Contains(value)) { Collider2D[] components = gameObject.GetComponents<Collider2D>(); Collider2D[] array3 = components; foreach (Collider2D val3 in array3) { ((Behaviour)val3).enabled = false; } Collider[] components2 = gameObject.GetComponents<Collider>(); Collider[] array4 = components2; foreach (Collider val4 in array4) { val4.enabled = false; } PlayMakerFSM[] components3 = gameObject.GetComponents<PlayMakerFSM>(); PlayMakerFSM[] array5 = components3; foreach (PlayMakerFSM val5 in array5) { ((Behaviour)val5).enabled = false; } break; } } } } } [IteratorStateMachine(typeof(<CreateTriggerDelayed>d__28))] private IEnumerator CreateTriggerDelayed((string scene, float x, float y, float z) target, int index) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <CreateTriggerDelayed>d__28(0) { <>4__this = this, target = target, index = index }; } private void CreateTriggerAt(Vector3 position, string sceneName, int index) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0047: 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_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_009b: Unknown result type (might be due to invalid IL or missing references) string text = $"SkillTriggered_{sceneName}_{index}"; if (!_triggeredRecords.Contains(text)) { GameObject val = new GameObject($"SkillTrigger_{sceneName}_{index}"); val.transform.position = position; BoxCollider2D val2 = val.AddComponent<BoxCollider2D>(); ((Collider2D)val2).isTrigger = true; val2.size = new Vector2(8f, 8f); SkillTrigger skillTrigger = val.AddComponent<SkillTrigger>(); skillTrigger.SetInfo(sceneName, index, text); Scene sceneByName = SceneManager.GetSceneByName(sceneName); if (((Scene)(ref sceneByName)).IsValid()) { SceneManager.MoveGameObjectToScene(val, sceneByName); Log.LogInfo((object)$"触发器创建: {sceneName} 索引 {index}"); } else { Log.LogError((object)("触发器创建失败: " + sceneName)); Object.Destroy((Object)(object)val); } } } public static void ResetAllRecords() { _triggeredRecords.Clear(); if ((Object)(object)Instance != (Object)null) { Instance.SaveTriggerRecords(); } Log.LogInfo((object)"所有技能触发器记录已重置"); } } public class SkillTrigger : MonoBehaviour { private bool _triggered = false; private string _sceneName; private int _index; private string _recordKey; public void SetInfo(string sceneName, int index, string recordKey) { _sceneName = sceneName; _index = index; _recordKey = recordKey; } private void OnTriggerEnter2D(Collider2D other) { if (!_triggered && (((Component)other).CompareTag("Hero") || ((Component)other).CompareTag("Player"))) { _triggered = true; if (_sceneName == "Shellwood_10") { SkillRandomizer.GiveWallJump(); } else { SkillRandomizer.GiveRandomSkill(); } Plugin._triggeredRecords.Add(_recordKey); Plugin.Instance.SaveTriggerRecords(); Object.Destroy((Object)(object)((Component)this).gameObject); } } } public static class SkillRandomizer { private static readonly Dictionary<string, string> SkillDisplayNames = new Dictionary<string, string> { { "hasNeedleThrow", "飞针" }, { "hasThreadSphere", "丝线球" }, { "hasHarpoonDash", "鱼叉冲刺" }, { "hasSilkCharge", "丝线冲刺" }, { "hasSilkBomb", "丝线炸弹" }, { "hasSilkBossNeedle", "丝线针" }, { "hasNeedolin", "针线" }, { "hasDash", "冲刺" }, { "hasBrolly", "伞" }, { "hasDoubleJump", "二段跳" }, { "hasChargeSlash", "蓄力斩" }, { "hasSuperJump", "超级跳" }, { "hasWallJump", "爬墙" } }; private static readonly List<string> AllSkillFields = SkillDisplayNames.Keys.ToList(); private static Random? _rng; private static int _currentSeed; public static void SetSeed(int seed) { _currentSeed = seed; _rng = ((seed == 0) ? new Random() : new Random(seed)); } private static void EnsureRng() { if (_rng == null) { _rng = new Random(); } } public static void GiveRandomSkill() { EnsureRng(); try { PlayerData instance = PlayerData.instance; if (instance == null) { return; } List<string> list = new List<string>(); foreach (string allSkillField in AllSkillFields) { FieldInfo field = typeof(PlayerData).GetField(allSkillField, BindingFlags.Instance | BindingFlags.Public); if (field != null && field.FieldType == typeof(bool) && !(bool)field.GetValue(instance)) { list.Add(allSkillField); } } if (list.Count == 0) { GiveWallJump(); return; } string text = list[_rng.Next(list.Count)]; FieldInfo field2 = typeof(PlayerData).GetField(text, BindingFlags.Instance | BindingFlags.Public); if (field2 != null) { field2.SetValue(instance, true); string value; string text2 = (SkillDisplayNames.TryGetValue(text, out value) ? value : text.Replace("has", "")); Plugin.ShowNotification("获得技能: " + text2); } } catch (Exception arg) { Plugin.Log.LogError((object)$"SkillRandomizer 出错: {arg}"); } } public static void GiveWallJump() { try { PlayerData instance = PlayerData.instance; if (instance == null) { return; } string[] array = new string[3] { "hasWallJump", "hasWalljump", "hasWallJumpUnlocked" }; string[] array2 = array; foreach (string name in array2) { FieldInfo field = typeof(PlayerData).GetField(name, BindingFlags.Instance | BindingFlags.Public); if (field != null && field.FieldType == typeof(bool)) { if (!(bool)field.GetValue(instance)) { field.SetValue(instance, true); Plugin.ShowNotification("获得技能: 爬墙"); } break; } } } catch (Exception arg) { Plugin.Log.LogError((object)$"GiveWallJump 出错: {arg}"); } } } }
plugins/StartingAbilityPicker.dll
Decompiled 20 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; 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 BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("StartingAbilityPicker")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0")] [assembly: AssemblyProduct("StartingAbilityPicker")] [assembly: AssemblyTitle("StartingAbilityPicker")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/YourGitHubUsername/StartingAbilityPicker")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.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; } } } 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 StartingAbilityPicker { [BepInPlugin("YourName.StartingAbilityPicker", "Starting Ability Picker", "1.0.0.0")] public class Plugin : BaseUnityPlugin { [CompilerGenerated] private sealed class <ShowUIAuto>d__60 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Plugin <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ShowUIAuto>d__60(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; if (<>4__this.currentProfileID != -1) { <>4__this.allowUpward = AllowUpwardAttack; <>4__this.allowLeft = AllowLeftAttack; <>4__this.allowRight = AllowRightAttack; <>4__this.itemCount = StartingItemCount.Value; <>4__this.resetPickups = false; <>4__this.seedInput = RandomSeed.Value.ToString(); <>4__this.showUI = true; Log.LogInfo((object)"加载存档,自动打开开局选项界面"); } 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(); } } internal static ManualLogSource Log; public static bool AllowLeftAttack = false; public static bool AllowRightAttack = false; public static bool AllowUpwardAttack = false; private static Dictionary<string, string> _abilityConfig = new Dictionary<string, string>(); private bool _sceneHazardMode = false; private int _sceneHazardCount = 2; private bool _sceneHazardUIOpen = false; private bool skillMode = false; private int skillTotal = 0; private int skillV = 0; private int skillH = 0; private int skillS = 0; private int skillA = 0; private const int MaxVertical = 5; private const int MaxHorizontal = 4; private const int MaxSpecial = 4; private const int MaxAttack = 5; private bool _lastSceneWasMenu = true; private bool showUI = false; private Rect uiWindowRect; private bool allowUpward = false; private bool allowLeft = false; private bool allowRight = false; private int itemCount = 0; private bool resetPickups = false; private string seedInput = ""; private static HashSet<int> chosenProfileSet = new HashSet<int>(); private static string _notificationMessage = null; private static float _notificationEndTime = 0f; private static GUIStyle _notificationStyle; public static ConfigEntry<string> ChosenProfiles { get; private set; } public static ConfigEntry<int> StartingSkillCount { get; private set; } public static ConfigEntry<int> StartingItemCount { get; private set; } public static ConfigEntry<int> RandomSeed { get; private set; } private static string AbilityConfigPath => Path.Combine(Paths.ConfigPath, "StartingAbilityPicker", "ability_config.json"); private int currentProfileID => ((Object)(object)GameManager.instance != (Object)null) ? GameManager.instance.profileID : (-1); public static void ShowNotification(string message, float duration = 3f) { _notificationMessage = message; _notificationEndTime = Time.time + duration; } private Texture2D MakeTexture(int width, int height, Color col) { //IL_0010: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown Color[] array = (Color[])(object)new Color[width * height]; for (int i = 0; i < array.Length; i++) { array[i] = col; } Texture2D val = new Texture2D(width, height); val.SetPixels(array); val.Apply(); return val; } private void Awake() { Log = ((BaseUnityPlugin)this).Logger; Log.LogInfo((object)"StartingAbilityPicker loaded! Press F7 to open starting options."); ChosenProfiles = ((BaseUnityPlugin)this).Config.Bind<string>("General", "ChosenProfiles", "", "已选择过开局选项的存档ID列表"); StartingSkillCount = ((BaseUnityPlugin)this).Config.Bind<int>("General", "StartingSkillCount", 0, "开局随机技能数量 (0-5)"); StartingItemCount = ((BaseUnityPlugin)this).Config.Bind<int>("General", "StartingItemCount", 0, "开局随机物品数量 (0-5)"); RandomSeed = ((BaseUnityPlugin)this).Config.Bind<int>("General", "RandomSeed", 0, "随机种子 (0 表示随机)"); LoadChosenProfiles(); EnsureRandomSeed(); LoadAbilityConfig(); SceneManager.sceneLoaded += OnSceneLoaded; Harmony.CreateAndPatchAll(typeof(AttackPatch), (string)null); } private void LoadAbilityConfig() { try { if (File.Exists(AbilityConfigPath)) { string text = File.ReadAllText(AbilityConfigPath); _abilityConfig = JsonConvert.DeserializeObject<Dictionary<string, string>>(text) ?? new Dictionary<string, string>(); } else { _abilityConfig.Clear(); } AllowUpwardAttack = _abilityConfig.TryGetValue("AllowUpwardAttack", out string value) && value == "true"; AllowLeftAttack = _abilityConfig.TryGetValue("AllowLeftAttack", out string value2) && value2 == "true"; AllowRightAttack = _abilityConfig.TryGetValue("AllowRightAttack", out string value3) && value3 == "true"; if (_abilityConfig.TryGetValue("SceneHazardMode", out string value4) && bool.TryParse(value4, out var result)) { _sceneHazardMode = result; } else { _sceneHazardMode = false; } if (_abilityConfig.TryGetValue("SceneHazardCount", out string value5) && int.TryParse(value5, out var result2)) { _sceneHazardCount = Mathf.Clamp(result2, 0, 4); } else { _sceneHazardCount = 2; } Log.LogInfo((object)$"[LoadAbilityConfig] Loaded: up={AllowUpwardAttack}, left={AllowLeftAttack}, right={AllowRightAttack}, sceneHazardMode={_sceneHazardMode}, sceneHazardCount={_sceneHazardCount}"); } catch (Exception arg) { Log.LogError((object)$"加载配置失败: {arg}"); } } private void SaveAbilityConfig() { try { _abilityConfig["AllowUpwardAttack"] = AllowUpwardAttack.ToString(); _abilityConfig["AllowLeftAttack"] = AllowLeftAttack.ToString(); _abilityConfig["AllowRightAttack"] = AllowRightAttack.ToString(); _abilityConfig["SceneHazardMode"] = _sceneHazardMode.ToString(); _abilityConfig["SceneHazardCount"] = _sceneHazardCount.ToString(); string directoryName = Path.GetDirectoryName(AbilityConfigPath); if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } string contents = JsonConvert.SerializeObject((object)_abilityConfig, (Formatting)1); File.WriteAllText(AbilityConfigPath, contents); Log.LogInfo((object)$"[SaveAbilityConfig] Saved: up={AllowUpwardAttack}, left={AllowLeftAttack}, right={AllowRightAttack}, sceneHazardMode={_sceneHazardMode}, sceneHazardCount={_sceneHazardCount}"); } catch (Exception arg) { Log.LogError((object)$"保存配置失败: {arg}"); } } private void NotifyHazardSettings() { try { Type type = Type.GetType("SilksongItemRandomizer.Hazard.HazardSpawner, SilksongItemRandomizer"); if (type == null) { Log.LogError((object)"未找到 HazardSpawner 类型"); return; } type.GetMethod("SetSceneHazardMode", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, new object[1] { _sceneHazardMode }); type.GetMethod("SetSceneHazardCount", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, new object[1] { _sceneHazardCount }); Log.LogInfo((object)$"已通知 HazardSpawner: 模式={_sceneHazardMode}, 数量={_sceneHazardCount}"); } catch (Exception arg) { Log.LogError((object)$"反射调用失败: {arg}"); } } private void EnsureRandomSeed() { if (RandomSeed.Value == 0) { int num = new Random().Next(1, int.MaxValue); RandomSeed.Value = num; ((BaseUnityPlugin)this).Config.Save(); Log.LogInfo((object)$"已自动生成真实种子: {num}"); } } private void OnDestroy() { SceneManager.sceneLoaded -= OnSceneLoaded; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { if (((Scene)(ref scene)).name != "Menu_Title" && ((Scene)(ref scene)).name != "Menu" && ((Scene)(ref scene)).name != "Loading" && (Object)(object)HeroController.instance != (Object)null) { if (_lastSceneWasMenu) { ((MonoBehaviour)this).StartCoroutine(ShowUIAuto()); _lastSceneWasMenu = false; } LoadAbilityConfig(); try { PlayerData instance = PlayerData.instance; if (instance != null) { skillMode = instance.GetBool("SkillRandomMode"); skillTotal = instance.GetInt("SkillTotalCount"); skillV = instance.GetInt("SkillVerticalCount"); skillH = instance.GetInt("SkillHorizontalCount"); skillS = instance.GetInt("SkillSpecialCount"); skillA = instance.GetInt("SkillAttackCount"); if (!skillMode && skillTotal == 0) { skillTotal = StartingSkillCount.Value; } } return; } catch (Exception arg) { Log.LogError((object)$"加载技能随机设置失败: {arg}"); return; } } if (((Scene)(ref scene)).name == "Menu_Title" || ((Scene)(ref scene)).name == "Menu") { _lastSceneWasMenu = true; } } [IteratorStateMachine(typeof(<ShowUIAuto>d__60))] private IEnumerator ShowUIAuto() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ShowUIAuto>d__60(0) { <>4__this = this }; } private void LoadChosenProfiles() { chosenProfileSet.Clear(); string[] array = ChosenProfiles.Value.Split(','); foreach (string text in array) { if (int.TryParse(text.Trim(), out var result)) { chosenProfileSet.Add(result); } } } private void SaveChosenProfiles() { ChosenProfiles.Value = string.Join(",", chosenProfileSet); ((BaseUnityPlugin)this).Config.Save(); } private void Update() { if (Input.GetKeyDown((KeyCode)288) && currentProfileID != -1) { showUI = !showUI; if (showUI) { allowUpward = AllowUpwardAttack; allowLeft = AllowLeftAttack; allowRight = AllowRightAttack; itemCount = StartingItemCount.Value; resetPickups = false; seedInput = RandomSeed.Value.ToString(); } } } private void OnGUI() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_0058: Expected O, but got Unknown //IL_0053: 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) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) if (showUI) { uiWindowRect = new Rect(20f, (float)((Screen.height - 950) / 2), 650f, 950f); uiWindowRect = GUILayout.Window(100, uiWindowRect, new WindowFunction(DrawUIWindow), "开局选项", Array.Empty<GUILayoutOption>()); } if (_notificationMessage != null && Time.time <= _notificationEndTime) { if (_notificationStyle == null) { _notificationStyle = new GUIStyle(GUI.skin.box); _notificationStyle.fontSize = 40; _notificationStyle.alignment = (TextAnchor)4; _notificationStyle.normal.textColor = Color.white; _notificationStyle.normal.background = MakeTexture(2, 2, new Color(0f, 0f, 0f, 0.7f)); } float num = 600f; float num2 = 120f; float num3 = ((float)Screen.width - num) / 2f; float num4 = Screen.height / 2 - 100; GUI.Box(new Rect(num3, num4, num, num2), _notificationMessage, _notificationStyle); } else { _notificationMessage = null; } } private void DrawUIWindow(int windowID) { //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_0007: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0285: 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_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_0300: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_10d7: Unknown result type (might be due to invalid IL or missing references) //IL_10f8: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Unknown result type (might be due to invalid IL or missing references) //IL_112d: Unknown result type (might be due to invalid IL or missing references) //IL_1166: Unknown result type (might be due to invalid IL or missing references) //IL_118f: Unknown result type (might be due to invalid IL or missing references) //IL_03aa: Unknown result type (might be due to invalid IL or missing references) //IL_03f8: Unknown result type (might be due to invalid IL or missing references) //IL_03f1: Unknown result type (might be due to invalid IL or missing references) //IL_0455: Unknown result type (might be due to invalid IL or missing references) //IL_044e: Unknown result type (might be due to invalid IL or missing references) //IL_04a3: Unknown result type (might be due to invalid IL or missing references) //IL_0956: Unknown result type (might be due to invalid IL or missing references) //IL_094f: Unknown result type (might be due to invalid IL or missing references) //IL_09ae: Unknown result type (might be due to invalid IL or missing references) //IL_0ca0: Unknown result type (might be due to invalid IL or missing references) //IL_0c99: Unknown result type (might be due to invalid IL or missing references) //IL_0cef: Unknown result type (might be due to invalid IL or missing references) //IL_0d51: Unknown result type (might be due to invalid IL or missing references) //IL_0d07: Unknown result type (might be due to invalid IL or missing references) //IL_0d30: Unknown result type (might be due to invalid IL or missing references) Color color = GUI.color; GUI.color = Color.black; GUI.DrawTexture(new Rect(0f, 0f, ((Rect)(ref uiWindowRect)).width, ((Rect)(ref uiWindowRect)).height), (Texture)(object)Texture2D.whiteTexture); GUI.color = color; GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); GUI.skin.label.fontSize = 20; GUI.skin.toggle.fontSize = 20; GUI.skin.button.fontSize = 24; GUI.skin.horizontalSlider.fontSize = 18; GUI.skin.textField.fontSize = 18; GUILayout.Label("当前存档开局设置:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) }); GUILayout.Space(15f); bool flag = chosenProfileSet.Contains(currentProfileID); if (flag) { GUILayout.Label("(此存档已设置过,只能查看)", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(35f) }); GUI.backgroundColor = new Color(0.8f, 0.5f, 0.2f); if (GUILayout.Button("重置本存档设置", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(45f) })) { chosenProfileSet.Remove(currentProfileID); SaveChosenProfiles(); flag = false; allowUpward = false; allowLeft = false; allowRight = false; itemCount = 0; resetPickups = false; skillMode = false; skillTotal = 0; skillV = (skillH = (skillS = (skillA = 0))); return; } GUI.backgroundColor = Color.white; } GUILayout.Space(20f); GUILayout.Label("攻击方向选择:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(35f) }); GUILayout.Space(5f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUI.color = Color.gray; GUILayout.Label("下劈 (默认)", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(200f), GUILayout.Height(40f) }); GUI.enabled = false; GUILayout.Toggle(true, "", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(40f), GUILayout.Height(40f) }); GUI.enabled = !flag; GUI.color = Color.white; GUILayout.EndHorizontal(); GUI.color = (allowUpward ? Color.green : Color.white); bool flag2 = GUILayout.Toggle(allowUpward, "上劈", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) }); if (flag2 != allowUpward && !flag) { allowUpward = flag2; } GUI.color = (allowLeft ? Color.green : Color.white); bool flag3 = GUILayout.Toggle(allowLeft, "左劈", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) }); if (flag3 != allowLeft && !flag) { allowLeft = flag3; } GUI.color = (allowRight ? Color.green : Color.white); bool flag4 = GUILayout.Toggle(allowRight, "右劈", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) }); if (flag4 != allowRight && !flag) { allowRight = flag4; } GUI.color = Color.white; GUILayout.Space(20f); GUILayout.Label("技能随机模式:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(35f) }); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUI.color = (skillMode ? Color.white : Color.green); if (GUILayout.Button("总随机", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Height(40f), GUILayout.Width(150f) }) && !flag) { skillMode = false; } GUI.color = (skillMode ? Color.green : Color.white); if (GUILayout.Button("分类随机", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Height(40f), GUILayout.Width(150f) }) && !flag) { skillMode = true; } GUI.color = Color.white; GUILayout.EndHorizontal(); GUILayout.Space(10f); if (!skillMode) { GUILayout.Label("开局随机技能总数量:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(35f) }); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(skillTotal.ToString(), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(35f), GUILayout.Height(40f) }); int num = (int)GUILayout.HorizontalSlider((float)skillTotal, 0f, 13f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) }); if (num != skillTotal && !flag) { skillTotal = num; } GUILayout.EndHorizontal(); GUILayout.Space(10f); } else { GUILayout.Label("分类随机数量:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(35f) }); GUILayout.Label($"垂直技能 (0-{5})", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(skillV.ToString(), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(35f), GUILayout.Height(40f) }); int num2 = (int)GUILayout.HorizontalSlider((float)skillV, 0f, 5f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) }); if (num2 != skillV && !flag) { skillV = num2; } GUILayout.EndHorizontal(); GUILayout.Label($"水平技能 (0-{4})", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(skillH.ToString(), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(35f), GUILayout.Height(40f) }); int num3 = (int)GUILayout.HorizontalSlider((float)skillH, 0f, 4f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) }); if (num3 != skillH && !flag) { skillH = num3; } GUILayout.EndHorizontal(); GUILayout.Label($"特殊技能 (0-{4})", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(skillS.ToString(), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(35f), GUILayout.Height(40f) }); int num4 = (int)GUILayout.HorizontalSlider((float)skillS, 0f, 4f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) }); if (num4 != skillS && !flag) { skillS = num4; } GUILayout.EndHorizontal(); GUILayout.Label($"攻击技能 (0-{5})", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(skillA.ToString(), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(35f), GUILayout.Height(40f) }); int num5 = (int)GUILayout.HorizontalSlider((float)skillA, 0f, 5f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) }); if (num5 != skillA && !flag) { skillA = num5; } GUILayout.EndHorizontal(); GUILayout.Space(10f); } GUILayout.Label("开局随机物品数量:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(35f) }); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(itemCount.ToString(), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(35f), GUILayout.Height(40f) }); int num6 = (int)GUILayout.HorizontalSlider((float)itemCount, 0f, 10f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) }); if (num6 != itemCount && !flag) { itemCount = num6; } GUILayout.EndHorizontal(); GUILayout.Space(15f); GUI.color = (_sceneHazardUIOpen ? Color.green : Color.white); if (GUILayout.Button("场景随机" + (_sceneHazardUIOpen ? " ▼" : " ▶"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) })) { _sceneHazardUIOpen = !_sceneHazardUIOpen; } GUI.color = Color.white; if (_sceneHazardUIOpen) { GUILayout.BeginVertical(GUI.skin.box, Array.Empty<GUILayoutOption>()); GUILayout.Space(10f); GUILayout.Label("场景随机设置:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(35f) }); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label("启用:", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(60f), GUILayout.Height(35f) }); bool flag5 = GUILayout.Toggle(_sceneHazardMode, _sceneHazardMode ? "开" : "关", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(35f) }); if (flag5 != _sceneHazardMode && !flag) { _sceneHazardMode = flag5; SaveAbilityConfig(); NotifyHazardSettings(); } GUILayout.EndHorizontal(); if (_sceneHazardMode) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label("每个场景生成数量:", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(150f), GUILayout.Height(35f) }); if (GUILayout.Button("-", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(40f), GUILayout.Height(35f) }) && !flag) { _sceneHazardCount = Mathf.Max(0, _sceneHazardCount - 1); SaveAbilityConfig(); NotifyHazardSettings(); } GUILayout.Label(_sceneHazardCount.ToString(), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(40f), GUILayout.Height(35f) }); if (GUILayout.Button("+", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(40f), GUILayout.Height(35f) }) && !flag) { _sceneHazardCount = Mathf.Min(4, _sceneHazardCount + 1); SaveAbilityConfig(); NotifyHazardSettings(); } GUILayout.Label("(最大 4)", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }); GUILayout.EndHorizontal(); } GUILayout.Space(10f); GUILayout.EndVertical(); } GUILayout.Space(25f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label("种子", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(60f), GUILayout.Height(40f) }); seedInput = GUILayout.TextField(seedInput, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(160f), GUILayout.Height(40f) }); GUILayout.EndHorizontal(); GUILayout.Space(5f); GUI.color = (resetPickups ? Color.red : Color.white); bool flag6 = GUILayout.Toggle(resetPickups, "重置种子世界(含技能触发器)", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) }); if (flag6 != resetPickups && !flag) { resetPickups = flag6; } GUI.color = Color.white; if (resetPickups) { GUI.color = Color.yellow; GUILayout.Label("警告:重置后当前种子世界将重新生成,所有拾取点会重生,技能触发器也会重置。", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(70f) }); GUI.color = Color.white; } GUILayout.Space(35f); GUI.enabled = !flag; GUI.backgroundColor = Color.green; if (GUILayout.Button("确认", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(50f) }) && !flag) { AllowUpwardAttack = allowUpward; AllowLeftAttack = allowLeft; AllowRightAttack = allowRight; SaveAbilityConfig(); try { PlayerData instance = PlayerData.instance; if (instance != null) { instance.SetBool("AllowUpwardAttack", allowUpward); instance.SetBool("AllowLeftAttack", allowLeft); instance.SetBool("AllowRightAttack", allowRight); instance.SetBool("SkillRandomMode", skillMode); instance.SetInt("SkillTotalCount", skillTotal); instance.SetInt("SkillVerticalCount", skillV); instance.SetInt("SkillHorizontalCount", skillH); instance.SetInt("SkillSpecialCount", skillS); instance.SetInt("SkillAttackCount", skillA); } } catch (Exception arg) { Log.LogError((object)$"保存到 PlayerData 失败: {arg}"); } StartingSkillCount.Value = skillTotal; StartingItemCount.Value = itemCount; ((BaseUnityPlugin)this).Config.Save(); chosenProfileSet.Add(currentProfileID); SaveChosenProfiles(); if (resetPickups) { ResetSeedWorld(); } if (!skillMode) { for (int i = 0; i < skillTotal; i++) { SkillRandomizer.GiveRandomSkill(); } } else { for (int j = 0; j < skillV; j++) { SkillRandomizer.GiveRandomSkillFromCategory(SkillRandomizer.VerticalSkills); } for (int k = 0; k < skillH; k++) { SkillRandomizer.GiveRandomSkillFromCategory(SkillRandomizer.HorizontalSkills); } for (int l = 0; l < skillS; l++) { SkillRandomizer.GiveRandomSkillFromCategory(SkillRandomizer.SpecialSkills); } for (int m = 0; m < skillA; m++) { SkillRandomizer.GiveRandomSkillFromCategory(SkillRandomizer.AttackSkills); } } for (int n = 0; n < itemCount; n++) { SavedItem randomItem = ItemRandomizer.GetRandomItem(); if ((Object)(object)randomItem != (Object)null) { randomItem.TryGet(false, true); } } showUI = false; Log.LogInfo((object)string.Format("开局设置已保存: 上劈={0}, 左劈={1}, 右劈={2}, 技能模式={3}, 技能V={4}, H={5}, S={6}, A={7}, 物品={8}, 重置种子={9}, 场景随机启用={10}, 数量={11}", allowUpward, allowLeft, allowRight, skillMode ? "分类" : "总", skillV, skillH, skillS, skillA, itemCount, resetPickups, _sceneHazardMode, _sceneHazardCount)); } GUI.backgroundColor = Color.white; GUI.enabled = true; GUI.backgroundColor = new Color(0.8f, 0.2f, 0.2f); if (GUILayout.Button("关闭", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) })) { showUI = false; } GUI.backgroundColor = Color.white; GUILayout.Space(15f); int fontSize = GUI.skin.label.fontSize; GUI.skin.label.fontSize = 26; GUI.color = Color.yellow; GUILayout.Label("提示: 按 F7 呼出此窗口", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) }); GUI.color = Color.white; GUI.skin.label.fontSize = fontSize; GUILayout.EndVertical(); GUI.DragWindow(); } private void ResetSeedWorld() { int num; if (int.TryParse(seedInput, out var result)) { if (result != RandomSeed.Value) { num = result; } else { num = new Random().Next(1, int.MaxValue); Log.LogInfo((object)$"输入种子与原种子相同,自动生成新种子: {num}"); } } else { num = new Random().Next(1, int.MaxValue); Log.LogInfo((object)$"输入无效,自动生成新种子: {num}"); } seedInput = num.ToString(); RandomSeed.Value = num; ((BaseUnityPlugin)this).Config.Save(); try { string path = Path.Combine(Paths.ConfigPath, "SilksongItemRandomizer", "destroyed_pickups.json"); if (File.Exists(path)) { File.Delete(path); } } catch (Exception arg) { Log.LogError((object)$"删除拾取点记录失败: {arg}"); } try { Type type = Type.GetType("SilksongItemRandomizer.Plugin, SilksongItemRandomizer"); if (type != null) { PropertyInfo property = type.GetProperty("RandomSeed", BindingFlags.Static | BindingFlags.Public); if (property != null) { ConfigEntry<int> val = property.GetValue(null) as ConfigEntry<int>; val.Value = num; } type.GetMethod("ResetDestroyedPickupKeys", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, null); } } catch (Exception arg2) { Log.LogError((object)$"重置物品随机MOD内存数据失败: {arg2}"); } try { string path2 = Path.Combine(Paths.ConfigPath, "SkillTriggerMod", "trigger_records.json"); if (File.Exists(path2)) { File.Delete(path2); } Log.LogInfo((object)"已删除技能触发器记录文件"); } catch (Exception arg3) { Log.LogError((object)$"删除技能触发器记录失败: {arg3}"); } try { Type type2 = Type.GetType("SkillTriggerMod.Plugin, SkillTriggerMod"); if (type2 != null) { PropertyInfo property2 = type2.GetProperty("RandomSeed", BindingFlags.Static | BindingFlags.Public); if (property2 != null) { ConfigEntry<int> val2 = property2.GetValue(null) as ConfigEntry<int>; val2.Value = num; } Type type3 = Type.GetType("SkillTriggerMod.SkillRandomizer, SkillTriggerMod"); if (type3 != null) { type3.GetMethod("SetSeed", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, new object[1] { num }); } } } catch (Exception arg4) { Log.LogError((object)$"重置技能随机MOD种子失败: {arg4}"); } try { Type type4 = Type.GetType("SilksongItemRandomizer.CrestRandomizer, SilksongItemRandomizer"); if (type4 != null) { type4.GetMethod("ResetMappings", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, null); type4.GetMethod("Initialize", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, null); } Type.GetType("SilksongItemRandomizer.CrestRandomizePatch, SilksongItemRandomizer")?.GetMethod("ResetProcessedIds", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, null); Type.GetType("SilksongItemRandomizer.BenchRespawnPatch, SilksongItemRandomizer")?.GetMethod("ResetCooldown", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, null); } catch (Exception arg5) { Log.LogError((object)$"清空纹章相关标记失败: {arg5}"); } try { Type type5 = Type.GetType("SilksongItemRandomizer.Hazard.HazardSpawner, SilksongItemRandomizer"); if (type5 != null) { type5.GetMethod("SetSeed", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, new object[1] { num }); type5.GetMethod("ResetSceneRecords", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, null); type5.GetMethod("SetSceneHazardMode", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, new object[1] { _sceneHazardMode }); type5.GetMethod("SetSceneHazardCount", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, new object[1] { _sceneHazardCount }); Log.LogInfo((object)"已通知 HazardSpawner 重置世界,种子已更新"); } } catch (Exception arg6) { Log.LogError((object)$"重置 HazardSpawner 世界失败: {arg6}"); } Log.LogInfo((object)"请重载当前场景以使所有随机世界重置。"); } } [HarmonyPatch(typeof(HeroController), "DoAttack")] public class AttackPatch { private static void Prefix(HeroController __instance, ref bool __runOriginal) { //IL_0174: Unknown result type (might be due to invalid IL or missing references) try { if (!__runOriginal) { return; } FieldInfo field = typeof(HeroController).GetField("inputHandler", BindingFlags.Instance | BindingFlags.NonPublic); if (field == null) { return; } object value = field.GetValue(__instance); if (value == null) { return; } FieldInfo field2 = value.GetType().GetField("inputActions", BindingFlags.Instance | BindingFlags.Public); if (field2 == null) { return; } object value2 = field2.GetValue(value); if (value2 == null) { return; } FieldInfo field3 = value2.GetType().GetField("Up"); FieldInfo field4 = value2.GetType().GetField("Down"); if (field3 == null || field4 == null) { return; } object value3 = field3.GetValue(value2); object value4 = field4.GetValue(value2); PropertyInfo propertyInfo = value3?.GetType().GetProperty("IsPressed"); if (!(propertyInfo == null)) { bool flag = (bool)propertyInfo.GetValue(value3); bool flag2 = (bool)propertyInfo.GetValue(value4); bool flag3 = true; try { FieldInfo field5 = typeof(HeroController).GetField("facingRight", BindingFlags.Instance | BindingFlags.NonPublic); flag3 = ((!(field5 != null)) ? (__instance.transform.localScale.x > 0f) : ((bool)field5.GetValue(__instance))); } catch { } bool allowUpwardAttack = Plugin.AllowUpwardAttack; bool allowLeftAttack = Plugin.AllowLeftAttack; bool allowRightAttack = Plugin.AllowRightAttack; bool flag4 = true; if (!(flag ? allowUpwardAttack : ((flag2 && (__instance.allowAttackCancellingDownspikeRecovery || !__instance.cState.onGround)) || ((!flag3) ? allowRightAttack : allowLeftAttack)))) { __runOriginal = false; } } } catch (Exception arg) { Plugin.Log.LogError((object)$"Exception in AttackPatch: {arg}"); __runOriginal = true; } } } public static class SkillRandomizer { private static readonly Dictionary<string, string> SkillDisplayNames = new Dictionary<string, string> { { "hasNeedleThrow", "飞针" }, { "hasThreadSphere", "丝线球" }, { "hasHarpoonDash", "鱼叉冲刺" }, { "hasSilkCharge", "丝线冲刺" }, { "hasSilkBomb", "丝线炸弹" }, { "hasSilkBossNeedle", "丝线针" }, { "hasNeedolin", "针线" }, { "hasDash", "冲刺" }, { "hasBrolly", "伞" }, { "hasDoubleJump", "二段跳" }, { "hasChargeSlash", "蓄力斩" }, { "hasSuperJump", "超级跳" }, { "hasWallJump", "爬墙" } }; public static readonly List<string> VerticalSkills = new List<string> { "hasSuperJump", "hasDoubleJump", "hasWallJump", "hasBrolly", "hasHarpoonDash" }; public static readonly List<string> HorizontalSkills = new List<string> { "hasDash", "hasBrolly", "hasHarpoonDash", "hasSilkCharge" }; public static readonly List<string> SpecialSkills = new List<string> { "hasNeedolin", "hasChargeSlash", "hasBrolly", "hasHarpoonDash" }; public static readonly List<string> AttackSkills = new List<string> { "hasSilkBomb", "hasSilkBossNeedle", "hasThreadSphere", "hasSilkSpear", "hasSilkCharge" }; private static readonly List<string> AllSkillFields = SkillDisplayNames.Keys.ToList(); private static Random? _rng; private static int _currentSeed; public static void SetSeed(int seed) { _currentSeed = seed; _rng = ((seed == 0) ? new Random() : new Random(seed)); } public static void ResetSeed() { SetSeed(_currentSeed); } private static void EnsureRng() { if (_rng == null) { _rng = new Random(); Plugin.Log.LogWarning((object)"SkillRandomizer RNG was not initialized, using default seed."); } } public static void GiveRandomSkill() { EnsureRng(); try { PlayerData playerData = PlayerData.instance; if (playerData == null) { return; } List<string> list = AllSkillFields.Where(delegate(string fieldName) { FieldInfo field2 = typeof(PlayerData).GetField(fieldName, BindingFlags.Instance | BindingFlags.Public); if (field2 != null && field2.FieldType == typeof(bool)) { bool flag = (bool)field2.GetValue(playerData); return !flag; } return false; }).ToList(); if (list.Count == 0) { GiveWallJump(); return; } string text = list[_rng.Next(list.Count)]; FieldInfo field = typeof(PlayerData).GetField(text, BindingFlags.Instance | BindingFlags.Public); if (field != null) { field.SetValue(playerData, true); string value; string text2 = (SkillDisplayNames.TryGetValue(text, out value) ? value : text.Replace("has", "")); Plugin.ShowNotification("获得技能: " + text2); } } catch (Exception arg) { Plugin.Log.LogError((object)$"SkillRandomizer 出错: {arg}"); } } public static void GiveRandomSkillFromCategory(List<string> categoryFields) { EnsureRng(); try { PlayerData playerData = PlayerData.instance; if (playerData == null) { return; } List<string> list = categoryFields.Where(delegate(string fieldName) { FieldInfo field2 = typeof(PlayerData).GetField(fieldName, BindingFlags.Instance | BindingFlags.Public); if (field2 != null && field2.FieldType == typeof(bool)) { bool flag = (bool)field2.GetValue(playerData); return !flag; } return false; }).ToList(); if (list.Count != 0) { string text = list[_rng.Next(list.Count)]; FieldInfo field = typeof(PlayerData).GetField(text, BindingFlags.Instance | BindingFlags.Public); if (field != null) { field.SetValue(playerData, true); string value; string text2 = (SkillDisplayNames.TryGetValue(text, out value) ? value : text.Replace("has", "")); Plugin.ShowNotification("获得技能: " + text2); } } } catch (Exception arg) { Plugin.Log.LogError((object)$"SkillRandomizer 出错: {arg}"); } } public static void GiveWallJump() { try { PlayerData instance = PlayerData.instance; if (instance == null) { return; } string[] array = new string[3] { "hasWallJump", "hasWalljump", "hasWallJumpUnlocked" }; string[] array2 = array; foreach (string name in array2) { FieldInfo field = typeof(PlayerData).GetField(name, BindingFlags.Instance | BindingFlags.Public); if (field != null && field.FieldType == typeof(bool)) { if (!(bool)field.GetValue(instance)) { field.SetValue(instance, true); Plugin.ShowNotification("获得技能: 爬墙"); } break; } } } catch (Exception arg) { Plugin.Log.LogError((object)$"GiveWallJump 出错: {arg}"); } } } public static class ItemRandomizer { private static List<SavedItem> _allItems; private static Random _rng = new Random(); public static SavedItem GetRandomItem() { if (_allItems == null) { _allItems = (from item in Resources.FindObjectsOfTypeAll<SavedItem>() where item is CollectableItem || item is ToolBase select item).ToList(); } if (_allItems.Count == 0) { return null; } return _allItems[_rng.Next(_allItems.Count)]; } } }