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 System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using NodeCanvas.Framework;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("DebugTeleportNames")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("DebugTeleportNames")]
[assembly: AssemblyTitle("DebugTeleportNames")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace DebugTeleportNames;
internal sealed class Destination
{
public string Scene;
public int Spawn;
public string Label;
public Kind Kind;
public int BuildOrder;
public override string ToString()
{
return $"{Label} -> {Scene} #{Spawn}";
}
}
internal enum Kind
{
Town,
Region,
Dungeon
}
internal static class Destinations
{
private sealed class SubArea
{
public int Spawn;
public string LocKey;
public string Detail;
}
private static readonly Dictionary<string, SubArea[]> s_subAreas = new Dictionary<string, SubArea[]>
{
["ChersoneseDungeonsSmall"] = (from i in Enumerable.Range(1, 9)
select Small(i)).ToArray(),
["HallowedDungeonsSmall"] = new int[8] { 1, 2, 3, 4, 5, 6, 7, 9 }.Select((int i) => Small(i)).ToArray(),
["AbrassarDungeonsSmall"] = (from i in Enumerable.Range(1, 8)
select Small(i)).ToArray(),
["EmercarDungeonsSmall"] = (from i in Enumerable.Range(1, 9)
select Small(i)).ToArray(),
["AntiqueFieldDungeonsSmall"] = (from i in Enumerable.Range(1, 8)
select Small(i, "Scene_Harmattan_DungeonsSmall" + i)).ToArray(),
["CalderaDungeonsSmall"] = new SubArea[10]
{
Small(0, "Scene_Caldera_SmallDungeon06"),
Small(1, "Scene_Caldera_SmallDungeon01"),
Small(2, "Scene_Caldera_SmallDungeon07"),
Small(3, "Scene_Caldera_SmallDungeon05"),
Small(4, "Scene_Caldera_SmallDungeon02"),
Small(5, "Scene_Caldera_SmallDungeon04"),
Small(6, "Scene_Caldera_SmallDungeon10"),
Small(8, "Scene_Caldera_SmallDungeon08"),
Small(10, "Scene_Caldera_SmallDungeon03"),
Small(11, "Scene_Caldera_SmallDungeon11")
},
["ChersoneseDungeonsBosses"] = new SubArea[3]
{
Arena(0, "Troglodyte Queen"),
Arena(1, "Elite Mantis Shrimp"),
Arena(2, "Brand Squire")
},
["HallowedDungeonsBosses"] = new SubArea[3]
{
Arena(0, "Ash Giant Highmonk"),
Arena(1, "Elite Ash Giants"),
Arena(2, "Elite Alpha Tuanosaur")
},
["AbrassarDungeonsBosses"] = new SubArea[3]
{
Arena(0, "Calixa"),
Arena(1, "Elite Beast Golem"),
Arena(2, "Elite Crescent Sharks")
},
["EmercarDungeonsBosses"] = new SubArea[3]
{
Arena(0, "Light Mender and Plague Doctor"),
Arena(1, "Elite Burning Man"),
Arena(2, "Immaculate Dreamer")
},
["AntiqueFieldDungeonsBosses"] = new SubArea[3]
{
Arena(0, "Immaculate's Bird"),
Arena(1, "Elite Sublime Shell"),
Arena(2, "Elite Boozu")
},
["CalderaDungeonsBosses"] = new SubArea[4]
{
Arena(0, "Grandmother"),
Arena(2, "Elite Crimson Avatar"),
Arena(3, "Elite Gargoyles"),
Arena(4, "Elite Torcrab")
},
["Caldera_Dungeon10"] = new SubArea[3]
{
Entrance(0),
Entrance(1, "Top Entrance"),
Entrance(2, "Bottom Entrance")
}
};
private static SubArea Small(int spawn, string locKey = null)
{
return new SubArea
{
Spawn = spawn,
LocKey = locKey
};
}
private static SubArea Arena(int spawn, string boss)
{
return new SubArea
{
Spawn = spawn,
Detail = boss
};
}
private static SubArea Entrance(int spawn, string which = null)
{
return new SubArea
{
Spawn = spawn,
Detail = which
};
}
internal static List<Destination> Build(IList<string> scenes)
{
List<Destination> list = new List<Destination>();
for (int i = 0; i < scenes.Count; i++)
{
string text = scenes[i];
Area areaFromSceneName = AreaManager.Instance.GetAreaFromSceneName(text);
string text2 = AreaName(text);
Kind kind = KindOf(areaFromSceneName);
if (s_subAreas.TryGetValue(text, out var value))
{
SubArea[] array = value;
foreach (SubArea subArea in array)
{
list.Add(new Destination
{
Scene = text,
Spawn = subArea.Spawn,
Kind = kind,
BuildOrder = i,
Label = SubName(areaFromSceneName, text2, subArea)
});
}
}
else
{
list.Add(new Destination
{
Scene = text,
Spawn = 0,
Kind = kind,
BuildOrder = i,
Label = text2
});
}
}
Disambiguate(list);
if (Plugin.ShowSceneName.Value)
{
foreach (Destination item in list.Where((Destination d) => d.Label != d.Scene))
{
item.Label += ((item.Spawn != 0 || s_subAreas.ContainsKey(item.Scene)) ? $" ({item.Scene} #{item.Spawn})" : (" (" + item.Scene + ")"));
}
}
IOrderedEnumerable<Destination> source = list.OrderBy((Destination d) => d.Kind);
source = (Plugin.SortByName.Value ? source.ThenBy<Destination, string>((Destination d) => d.Label, StringComparer.CurrentCultureIgnoreCase).ThenBy<Destination, string>((Destination d) => d.Scene, StringComparer.Ordinal) : source.ThenBy((Destination d) => d.BuildOrder));
return source.ThenBy((Destination d) => d.Spawn).ToList();
}
private static Kind KindOf(Area area)
{
string text = area?.NameLocKey ?? "";
if (text.EndsWith("_Town", StringComparison.Ordinal))
{
return Kind.Town;
}
if (text.EndsWith("_Open", StringComparison.Ordinal))
{
return Kind.Region;
}
return Kind.Dungeon;
}
private static string SubName(Area area, string areaName, SubArea sub)
{
if (sub.Detail != null)
{
return areaName + ": " + sub.Detail;
}
string text = null;
if (sub.LocKey != null)
{
LocalizationManager.Instance.TryGetLoc(sub.LocKey, ref text);
}
else if (area != null)
{
text = AreaManager.Instance.GetAreaName((AreaEnum)area.ID, sub.Spawn);
}
if (!string.IsNullOrEmpty(text?.Trim()))
{
return text.Trim();
}
return $"{areaName} #{sub.Spawn}";
}
private static void Disambiguate(List<Destination> list)
{
foreach (IGrouping<string, Destination> group in (from d in list
group d by d.Label into g
where g.Count() > 1
select g).ToList())
{
Dictionary<Destination, string> qualifiers = group.ToDictionary((Destination d) => d, (Destination d) => Qualifier(d.Scene, group.Key));
foreach (IGrouping<string, Destination> item in from d in @group
group d by qualifiers[d] into g
where g.Count() > 1
select g)
{
foreach (Destination item2 in item)
{
qualifiers[item2] = ((item2.Spawn == 0) ? item2.Scene : $"{item2.Scene} #{item2.Spawn}");
}
}
foreach (Destination item3 in group)
{
if (qualifiers[item3] != null)
{
item3.Label = item3.Label + " (" + qualifiers[item3] + ")";
}
}
}
}
private static string Qualifier(string scene, string name)
{
string text = AreaManager.Instance.GetAreaFromSceneName(scene)?.DefaultName?.Trim();
if (string.IsNullOrEmpty(text) || string.Equals(text, name, StringComparison.OrdinalIgnoreCase))
{
return null;
}
if (!text.StartsWith(name + " ", StringComparison.OrdinalIgnoreCase))
{
return text;
}
return text.Substring(name.Length + 1);
}
internal static string AreaName(string scene)
{
string text = null;
try
{
Area areaFromSceneName = AreaManager.Instance.GetAreaFromSceneName(scene);
text = ((areaFromSceneName != null) ? areaFromSceneName.GetName() : null);
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("No area name for " + scene + ": " + ex.Message));
}
if (!string.IsNullOrEmpty(text?.Trim()))
{
return text.Trim();
}
return scene;
}
}
[HarmonyPatch]
internal static class ListColumns
{
private const float Margin = 8f;
private const float ColumnGap = 4f;
private static readonly FieldRef<DT_CharacterCheats, Dropdown[]> s_dropdowns = AccessTools.FieldRefAccess<DT_CharacterCheats, Dropdown[]>("m_ddFamilies");
internal static string LastLayout;
private static readonly Vector3[] s_corners = (Vector3[])(object)new Vector3[4];
[HarmonyPostfix]
[HarmonyPatch(typeof(Dropdown), "Show")]
private static void AfterShow(Dropdown __instance)
{
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Expected O, but got Unknown
try
{
DT_CharacterCheats componentInParent = ((Component)__instance).GetComponentInParent<DT_CharacterCheats>();
if ((Object)(object)componentInParent == (Object)null)
{
return;
}
Dropdown[] obj = s_dropdowns.Invoke(componentInParent);
if (obj != null && UnityEngineExtensions.Contains<Dropdown>(obj, __instance))
{
Transform obj2 = ((Component)__instance).transform.Find("Dropdown List");
RectTransform val = (RectTransform)(object)((obj2 is RectTransform) ? obj2 : null);
if (val != null)
{
Arrange(val, (RectTransform)((Component)__instance).transform);
}
}
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("Could not lay out the area list: " + ex));
}
}
private static void Arrange(RectTransform list, RectTransform button)
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: 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_0126: Unknown result type (might be due to invalid IL or missing references)
//IL_012b: Unknown result type (might be due to invalid IL or missing references)
//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
//IL_023d: Unknown result type (might be due to invalid IL or missing references)
//IL_024f: Unknown result type (might be due to invalid IL or missing references)
//IL_0370: Unknown result type (might be due to invalid IL or missing references)
//IL_037e: Unknown result type (might be due to invalid IL or missing references)
//IL_0383: Unknown result type (might be due to invalid IL or missing references)
LayoutRebuilder.ForceRebuildLayoutImmediate(list);
Rect val = default(Rect);
((Rect)(ref val))..ctor(8f, 8f, (float)Screen.width - 16f, (float)Screen.height - 16f);
Rect val2 = WorldRect(list);
if (((Rect)(ref val)).Contains(((Rect)(ref val2)).min) && ((Rect)(ref val)).Contains(((Rect)(ref val2)).max))
{
return;
}
VerticalLayoutGroup component = ((Component)list).GetComponent<VerticalLayoutGroup>();
List<RectTransform> list2 = (from Transform t in (IEnumerable)list
where ((Component)t).gameObject.activeSelf && (Object)(object)((Component)t).GetComponent<Toggle>() != (Object)null
select t).Cast<RectTransform>().ToList();
if (!((Object)(object)component == (Object)null) && list2.Count != 0)
{
float y = ((Transform)list).lossyScale.y;
Rect val3 = WorldRect(button);
float num = ((Rect)(ref val3)).yMax - ((Rect)(ref val)).yMin;
float num2 = ((Rect)(ref val)).yMax - ((Rect)(ref val3)).yMin;
bool flag = num >= num2;
float num3 = Mathf.Max(num, num2) / y;
RectOffset padding = ((LayoutGroup)component).padding;
float spacing = ((HorizontalOrVerticalLayoutGroup)component).spacing;
Rect rect = list.rect;
float num4 = (((Rect)(ref rect)).height - (float)padding.vertical + spacing) / (float)list2.Count;
rect = list.rect;
float num5 = ((Rect)(ref rect)).width - (float)padding.horizontal;
int num6 = Mathf.Max(1, Mathf.FloorToInt((num3 - (float)padding.vertical + spacing) / num4));
int num7 = Mathf.CeilToInt((float)list2.Count / (float)num6);
LastLayout = $"{list2.Count} items, pitch {num4:F1}, padding {padding.vertical}, spacing {spacing}, " + string.Format("room {0:F0} {1}, {2} rows max -> {3} columns", num3, flag ? "below" : "above", num6, num7);
Plugin.Log.LogDebug((object)("Area list: " + LastLayout));
if (num7 > 1)
{
Object.DestroyImmediate((Object)(object)component);
GridLayoutGroup obj = ((Component)list).gameObject.AddComponent<GridLayoutGroup>();
((LayoutGroup)obj).padding = padding;
obj.cellSize = new Vector2(num5, num4 - spacing);
obj.spacing = new Vector2(4f, spacing);
obj.startCorner = (Corner)0;
obj.startAxis = (Axis)1;
((LayoutGroup)obj).childAlignment = (TextAnchor)0;
obj.constraint = (Constraint)1;
obj.constraintCount = num7;
int num8 = Mathf.CeilToInt((float)list2.Count / (float)num7);
list.SetSizeWithCurrentAnchors((Axis)1, (float)padding.vertical + (float)num8 * num4 - spacing);
LayoutRebuilder.ForceRebuildLayoutImmediate(list);
}
val2 = WorldRect(list);
float num9 = (flag ? (((Rect)(ref val3)).yMax - ((Rect)(ref val2)).yMax) : (((Rect)(ref val3)).yMin - ((Rect)(ref val2)).yMin));
float num10 = 0f;
if (((Rect)(ref val2)).xMax > ((Rect)(ref val)).xMax)
{
num10 = ((Rect)(ref val)).xMax - ((Rect)(ref val2)).xMax;
}
if (((Rect)(ref val2)).xMin + num10 < ((Rect)(ref val)).xMin)
{
num10 = ((Rect)(ref val)).xMin - ((Rect)(ref val2)).xMin;
}
if (((Rect)(ref val2)).yMin + num9 < ((Rect)(ref val)).yMin)
{
num9 = ((Rect)(ref val)).yMin - ((Rect)(ref val2)).yMin;
}
if (((Rect)(ref val2)).yMax + num9 > ((Rect)(ref val)).yMax)
{
num9 = ((Rect)(ref val)).yMax - ((Rect)(ref val2)).yMax;
}
((Transform)list).position = ((Transform)list).position + new Vector3(num10, num9, 0f);
}
}
private static Rect WorldRect(RectTransform t)
{
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
t.GetWorldCorners(s_corners);
return Rect.MinMaxRect(s_corners[0].x, s_corners[0].y, s_corners[2].x, s_corners[2].y);
}
}
[BepInPlugin("tchernobill.debugteleportnames", "DebugTeleportNames", "1.1.0")]
public class Plugin : BaseUnityPlugin
{
public const string GUID = "tchernobill.debugteleportnames";
public const string NAME = "DebugTeleportNames";
public const string VERSION = "1.1.0";
internal static ManualLogSource Log;
internal static ConfigEntry<bool> SortByName;
internal static ConfigEntry<bool> ShowSceneName;
private void Awake()
{
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
Log = ((BaseUnityPlugin)this).Logger;
SortByName = ((BaseUnityPlugin)this).Config.Bind<bool>("Area switch", "Sort by name", true, "List each region's dungeons alphabetically, after its town and the region itself (off: build order).");
ShowSceneName = ((BaseUnityPlugin)this).Config.Bind<bool>("Area switch", "Show scene name", false, "Also show the internal scene name (and spawn point) after the name, e.g. \"Ghost Pass (Chersonese_Dungeon3)\".");
Harmony val = new Harmony("tchernobill.debugteleportnames");
val.PatchAll(typeof(AreaSwitchPatches));
val.PatchAll(typeof(ListColumns));
TestHarness.StartIfRequested(((Component)this).gameObject);
}
}
[HarmonyPatch]
internal static class AreaSwitchPatches
{
private static readonly FieldRef<DT_CharacterCheats, List<string>[]> s_scenes = AccessTools.FieldRefAccess<DT_CharacterCheats, List<string>[]>("m_activeScenes");
private static readonly FieldRef<DT_CharacterCheats, Dropdown[]> s_dropdowns = AccessTools.FieldRefAccess<DT_CharacterCheats, Dropdown[]>("m_ddFamilies");
private static readonly FieldRef<DT_CharacterCheats, int> s_lastFamily = AccessTools.FieldRefAccess<DT_CharacterCheats, int>("m_lastSelectedAreaFamilyIndex");
private static readonly FieldRef<DT_CharacterCheats, DeveloperToolManager> s_manager = AccessTools.FieldRefAccess<DT_CharacterCheats, DeveloperToolManager>("m_manager");
private static readonly ConditionalWeakTable<DT_CharacterCheats, List<Destination>[]> s_lists = new ConditionalWeakTable<DT_CharacterCheats, List<Destination>[]>();
[HarmonyPostfix]
[HarmonyPatch(typeof(DT_CharacterCheats), "InitAreaSwitches")]
private static void AfterInit(DT_CharacterCheats __instance)
{
Refresh(__instance);
}
[HarmonyPostfix]
[HarmonyPatch(typeof(DT_CharacterCheats), "Show")]
private static void AfterShow(DT_CharacterCheats __instance)
{
Refresh(__instance);
}
[HarmonyPrefix]
[HarmonyPatch(typeof(DT_CharacterCheats), "OnAreaSwitch")]
private static bool BeforeAreaSwitch(DT_CharacterCheats __instance, int _index)
{
//IL_0024: 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_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
Destination destination = Get(__instance, s_lastFamily.Invoke(__instance), _index);
if (destination == null)
{
return true;
}
DLCs areaDLC = AreaManager.Instance.GetAreaDLC(destination.Scene);
if (!CharacterManager.Instance.GetAllPlayersOwnDLC(areaDLC))
{
((UIElement)__instance).CharacterUI.ShowInfoNotificationLoc("Notification_Interaction_DLCRequiredCOOP", new string[1] { StoreManager.Instance.GetDLCName(areaDLC) });
return false;
}
NetworkLevelLoader.Instance.RequestSwitchArea(destination.Scene, destination.Spawn, 1.5f, false);
DeveloperToolManager obj = s_manager.Invoke(__instance);
if (obj != null)
{
obj.HideCurrentDisplayedTool();
}
return false;
}
internal static Destination Get(DT_CharacterCheats panel, int family, int option)
{
if (option < 1 || !s_lists.TryGetValue(panel, out var value) || family < 0 || family >= value.Length)
{
return null;
}
List<Destination> list = value[family];
Dropdown[] obj = s_dropdowns.Invoke(panel);
Dropdown val = ((obj != null) ? obj[family] : null);
if (list == null || (Object)(object)val == (Object)null || val.options.Count != list.Count + 1 || option > list.Count)
{
return null;
}
return list[option - 1];
}
internal static List<Destination> Get(DT_CharacterCheats panel, int family)
{
if (!s_lists.TryGetValue(panel, out var value) || family < 0 || family >= value.Length)
{
return null;
}
return value[family];
}
internal static void Refresh(DT_CharacterCheats panel)
{
List<string>[] array = s_scenes.Invoke(panel);
Dropdown[] array2 = s_dropdowns.Invoke(panel);
if (array == null || array2 == null || (Object)(object)AreaManager.Instance == (Object)null)
{
return;
}
s_lists.TryGetValue(panel, out var value);
List<Destination>[] array3 = new List<Destination>[array.Length];
for (int i = 0; i < array.Length && i < array2.Length; i++)
{
Dropdown val = array2[i];
if (array[i] == null || (Object)(object)val == (Object)null)
{
continue;
}
int num = ((((value != null) ? value[i] : null) != null) ? (value[i].Count + 1) : (-1));
if (val.options.Count != array[i].Count + 1 && val.options.Count != num)
{
continue;
}
try
{
List<Destination> list = Destinations.Build(array[i]);
val.options.RemoveRange(1, val.options.Count - 1);
val.options.AddRange(((IEnumerable<Destination>)list).Select((Func<Destination, OptionData>)((Destination d) => new OptionData(d.Label))));
val.SetValueWithoutNotify(0);
array3[i] = list;
}
catch (Exception arg)
{
Plugin.Log.LogWarning((object)$"Could not build the destinations of list {i}: {arg}");
}
}
s_lists.Remove(panel);
s_lists.Add(panel, array3);
}
}
[HarmonyPatch]
public class TestHarness : MonoBehaviour
{
private const int CheatPanelIndex = 1;
private string outputDir;
private bool survey;
private static int s_loadsStarted;
private int offScreenLists;
private static readonly string[] SurveyScenes = new string[18]
{
"ChersoneseNewTerrain", "HallowedMarshNewTerrain", "Abrassar", "Emercar", "AntiqueField", "Caldera", "ChersoneseDungeonsSmall", "HallowedDungeonsSmall", "AbrassarDungeonsSmall", "EmercarDungeonsSmall",
"AntiqueFieldDungeonsSmall", "CalderaDungeonsSmall", "ChersoneseDungeonsBosses", "HallowedDungeonsBosses", "AbrassarDungeonsBosses", "EmercarDungeonsBosses", "AntiqueFieldDungeonsBosses", "CalderaDungeonsBosses"
};
private static string ActiveScene
{
get
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
Scene activeScene = SceneManager.GetActiveScene();
return ((Scene)(ref activeScene)).name;
}
}
public static void StartIfRequested(GameObject host)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
string[] commandLineArgs = Environment.GetCommandLineArgs();
if (UnityEngineExtensions.Contains<string>(commandLineArgs, "--dtn-test") || UnityEngineExtensions.Contains<string>(commandLineArgs, "--dtn-survey") || UnityEngineExtensions.Contains<string>(commandLineArgs, "--dtn-probe"))
{
new Harmony("tchernobill.debugteleportnames.test").PatchAll(typeof(TestHarness));
host.AddComponent<TestHarness>().survey = UnityEngineExtensions.Contains<string>(commandLineArgs, "--dtn-survey") || UnityEngineExtensions.Contains<string>(commandLineArgs, "--dtn-probe");
}
}
private void Start()
{
outputDir = Path.Combine(Paths.BepInExRootPath, "DebugTeleportNamesTest");
Directory.CreateDirectory(outputDir);
((MonoBehaviour)this).StartCoroutine(Run());
}
private static void Log(string message)
{
Plugin.Log.LogMessage((object)("dtn-test: " + message));
}
private static string Fail(string reason)
{
Plugin.Log.LogError((object)("dtn-test: FAILED " + reason));
return reason;
}
private static IEnumerator WaitRealtime(float seconds)
{
float end = Time.realtimeSinceStartup + seconds;
while (Time.realtimeSinceStartup < end)
{
yield return null;
}
}
private static bool InGameplay(string scene)
{
if ((Object)(object)NetworkLevelLoader.Instance != (Object)null && NetworkLevelLoader.Instance.IsOverallLoadingDone)
{
return ActiveScene == scene;
}
return false;
}
private IEnumerator Run()
{
Character character = null;
float deadline = Time.realtimeSinceStartup + 900f;
while ((Object)(object)character == (Object)null)
{
if (Time.realtimeSinceStartup > deadline)
{
Fail("not in Berg after 900 s");
yield break;
}
yield return null;
if (InGameplay(survey ? ActiveScene : "Berg"))
{
try
{
CharacterManager instance = CharacterManager.Instance;
character = ((instance != null) ? instance.GetFirstLocalCharacter() : null);
}
catch (NullReferenceException)
{
}
}
}
yield return WaitRealtime(5f);
if (survey)
{
string[] commandLineArgs = Environment.GetCommandLineArgs();
int num = Array.IndexOf(commandLineArgs, "--dtn-probe");
if (num >= 0 && num + 2 < commandLineArgs.Length)
{
yield return Probe(commandLineArgs[num + 1], commandLineArgs[num + 2]);
}
else
{
yield return Survey();
}
yield break;
}
Log($"local character {character.Name} in {ActiveScene}, batchmode {Application.isBatchMode}, screen {Screen.width}x{Screen.height}");
DumpAreas();
DeveloperToolManager tools = ((Component)character.CharacterUI).GetComponentInChildren<DeveloperToolManager>(true);
if ((Object)(object)tools == (Object)null)
{
Fail("no DeveloperToolManager under the CharacterUI");
yield break;
}
Log("toggle keys: " + string.Join(", ", Traverse.Create((object)tools).Field("TOGGLE_KEYS").GetValue<KeyCode[]>()));
Global.CheatsEnabled = true;
MenuManager.Instance.MasterCanvas.alpha = 1f;
MenuManager.Instance.MasterCanvas.interactable = true;
string[] commandLineArgs2 = Environment.GetCommandLineArgs();
int num2 = Array.IndexOf(commandLineArgs2, "--dtn-test-resolution");
if (num2 >= 0 && num2 + 1 < commandLineArgs2.Length)
{
string[] array = commandLineArgs2[num2 + 1].Split(new char[1] { 'x' });
Screen.SetResolution(int.Parse(array[0]), int.Parse(array[1]), false);
yield return WaitRealtime(3f);
Log($"screen now {Screen.width}x{Screen.height}");
}
tools.ShowDeveloperTool(1);
yield return WaitRealtime(2f);
DT_CharacterCheats panel = ((Component)tools).GetComponentInChildren<DT_CharacterCheats>(true);
DumpChain(((Object)(object)panel != (Object)null) ? ((Component)panel).transform : ((Component)tools).transform);
List<string>[] scenes = Traverse.Create((object)panel).Field("m_activeScenes").GetValue<List<string>[]>();
Dropdown[] dropdowns = Traverse.Create((object)panel).Field("m_ddFamilies").GetValue<Dropdown[]>();
if ((Object)(object)panel == (Object)null || scenes == null || dropdowns == null)
{
Fail("no area switch lists in the Character Cheats panel");
yield break;
}
string text = CheckLists(panel, scenes, dropdowns);
if (text != null)
{
Fail(text);
yield break;
}
int berg = Array.FindIndex(AreaManager.AreaFamilies, (AreaFamily f) => f.FamilyName == "Berg");
if (berg < 0 || (Object)(object)dropdowns[berg] == (Object)null)
{
Fail("no Berg list");
yield break;
}
Dropdown dropdown = dropdowns[berg];
yield return Capture("panel");
panel.OnSceneFamilyClicked(berg);
dropdown.Show();
yield return WaitRealtime(1.5f);
yield return Capture("berg_list");
dropdown.Hide();
yield return WaitRealtime(0.5f);
yield return CheckListLayouts(panel, dropdowns);
if (offScreenLists > 0)
{
Fail($"{offScreenLists} lists not fully on screen");
yield break;
}
bool flag = UnityEngineExtensions.Contains<string>(Environment.GetCommandLineArgs(), "--dtn-test-all");
List<(int family, string label)> probes = new List<(int, string)>();
for (int num3 = 0; num3 < scenes.Length; num3++)
{
foreach (Destination item3 in AreaSwitchPatches.Get(panel, num3) ?? new List<Destination>())
{
if (flag ? ((byte)item3.Spawn != 0) : (item3.Label.EndsWith("Immaculate Dreamer") || item3.Label.EndsWith("Elite Boozu") || (item3.Scene == "EmercarDungeonsSmall" && item3.Spawn == 9) || (item3.Scene == "CalderaDungeonsSmall" && item3.Spawn == 11) || item3.Scene == "Chersonese_Dungeon3" || item3.Label.EndsWith("Grandmother") || item3.Scene == "Caldera_Dungeon10"))
{
probes.Add((num3, item3.Label));
}
}
}
Log($"teleport: {probes.Count} destinations to try");
int failures = 0;
foreach (var item4 in probes)
{
int item = item4.family;
string item2 = item4.label;
string result = null;
yield return Teleport(item, item2, delegate(string r)
{
result = r;
});
if (result != null)
{
failures++;
Log("teleport FAILED: " + result);
}
}
if (failures > 0)
{
Fail($"{failures} of {probes.Count} teleports failed");
}
else
{
Log("done");
}
}
private IEnumerator Teleport(int family, string label, Action<string> fail)
{
Character character = CharacterManager.Instance.GetFirstLocalCharacter();
DeveloperToolManager tools = ((Component)character.CharacterUI).GetComponentInChildren<DeveloperToolManager>(true);
tools.ShowDeveloperTool(1);
yield return WaitRealtime(1f);
DT_CharacterCheats componentInChildren = ((Component)tools).GetComponentInChildren<DT_CharacterCheats>(true);
Dropdown dropdown = Traverse.Create((object)componentInChildren).Field("m_ddFamilies").GetValue<Dropdown[]>()[family];
int num = dropdown.options.FindIndex((OptionData o) => o.text == label);
Destination d = AreaSwitchPatches.Get(componentInChildren, family, num);
if (d == null)
{
fail($"\"{label}\" not in list {family}");
yield break;
}
int loads = s_loadsStarted;
componentInChildren.OnSceneFamilyClicked(family);
((Component)dropdown).transform.Find("Dropdown List");
if (d.Label.EndsWith("Grandmother"))
{
dropdown.Show();
yield return WaitRealtime(1f);
Transform obj = ((Component)dropdown).transform.Find("Dropdown List");
Toggle val = ((obj != null) ? ((IEnumerable<Toggle>)((Component)obj).GetComponentsInChildren<Toggle>()).FirstOrDefault((Func<Toggle, bool>)delegate(Toggle t)
{
Text componentInChildren2 = ((Component)t).GetComponentInChildren<Text>();
return ((componentInChildren2 != null) ? componentInChildren2.text : null) == label;
}) : null);
if ((Object)(object)val == (Object)null)
{
fail("\"" + label + "\": no list entry to click");
yield break;
}
Log($"teleport: clicking \"{label}\" at {((Component)val).transform.position:F0}");
ExecuteEvents.Execute<IPointerClickHandler>(((Component)val).gameObject, (BaseEventData)new PointerEventData(EventSystem.current), ExecuteEvents.pointerClickHandler);
}
else
{
dropdown.value = num;
}
yield return null;
if (s_loadsStarted == loads)
{
fail("\"" + label + "\": no area switch requested");
yield break;
}
float deadline = Time.realtimeSinceStartup + 60f;
while (NetworkLevelLoader.Instance.IsOverallLoadingDone && Time.realtimeSinceStartup < deadline)
{
yield return null;
}
deadline = Time.realtimeSinceStartup + 300f;
while (!InGameplay(d.Scene) || (Object)(object)SpawnPointManager.Instance == (Object)null)
{
if (Time.realtimeSinceStartup > deadline)
{
fail("\"" + label + "\": in " + ActiveScene + " after 300 s, expected " + d.Scene);
yield break;
}
yield return null;
}
yield return WaitRealtime(2f);
character = CharacterManager.Instance.GetFirstLocalCharacter();
Transform[] spawns = SpawnPointManager.Instance.SpawnPoints;
float num2 = ((d.Spawn < spawns.Length && (Object)(object)spawns[d.Spawn] != (Object)null) ? Vector3.Distance(spawns[d.Spawn].position, ((Component)character).transform.position) : float.NaN);
int num3 = (from i in Enumerable.Range(0, spawns.Length)
where (Object)(object)spawns[i] != (Object)null
orderby Vector3.Distance(spawns[i].position, ((Component)character).transform.position)
select i).FirstOrDefault();
Log($"teleport: \"{label}\" -> {ActiveScene} #{d.Spawn}, {num2:F1} m from it (nearest spawn {num3}), alive {!character.IsDead}");
if (!(num2 < 30f))
{
fail($"\"{label}\": landed {num2:F0} m from spawn {d.Spawn} of {d.Scene}");
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(NetworkLevelLoader), "RequestSwitchArea", new Type[]
{
typeof(float),
typeof(string),
typeof(int),
typeof(float),
typeof(bool)
})]
private static void CountLoads()
{
s_loadsStarted++;
}
private static void DumpChain(Transform t)
{
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
while ((Object)(object)t != (Object)null)
{
CanvasGroup component = ((Component)t).GetComponent<CanvasGroup>();
Canvas component2 = ((Component)t).GetComponent<Canvas>();
Log($" {((Object)t).name}: active {((Component)t).gameObject.activeSelf}" + (((Object)(object)component != (Object)null) ? $", group alpha {component.alpha}" : "") + (((Object)(object)component2 != (Object)null) ? $", canvas {component2.renderMode} enabled {((Behaviour)component2).enabled} order {component2.sortingOrder}" : "") + $", layer {((Component)t).gameObject.layer}");
t = t.parent;
}
}
private static void DumpAreas()
{
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine("SceneName\tDefaultName\tNameLocKey\tGetName\tDLC\tInBuild");
HashSet<string> hashSet = new HashSet<string>(AreaManager.ActiveScenes ?? new string[0]);
Area[] areas = AreaManager.Instance.Areas;
foreach (Area val in areas)
{
stringBuilder.AppendLine($"{val.SceneName}\t{val.DefaultName}\t{val.NameLocKey}\t{val.GetName()}\t{val.DLCId}\t{hashSet.Contains(val.SceneName)}");
}
File.WriteAllText(Path.Combine(Path.Combine(Paths.BepInExRootPath, "DebugTeleportNamesTest"), "areas.tsv"), stringBuilder.ToString());
Log($"{AreaManager.Instance.Areas.Length} areas dumped, language {LocalizationManager.Instance.CurrentLanguage}");
}
private static string CheckLists(DT_CharacterCheats panel, List<string>[] scenes, Dropdown[] dropdowns)
{
int num = 0;
for (int i = 0; i < scenes.Length; i++)
{
if (scenes[i] == null)
{
continue;
}
Dropdown val = dropdowns[i];
string text = ((i < AreaManager.AreaFamilies.Length) ? AreaManager.AreaFamilies[i].FamilyName : "Others");
List<Destination> list = AreaSwitchPatches.Get(panel, i);
if (list == null)
{
return "list " + text + ": not built";
}
Log($"list {text}: {list.Count} destinations for {scenes[i].Count} scenes");
if (val.options.Count != list.Count + 1 || val.options[0].text != "")
{
return $"list {text}: {val.options.Count} options for {list.Count} destinations";
}
if (val.options.Select((OptionData o) => o.text).Distinct().Count() != val.options.Count)
{
return "list " + text + ": two destinations with the same label";
}
string text2 = scenes[i].FirstOrDefault((string s) => list.All((Destination d) => d.Scene != s));
if (text2 != null)
{
return "list " + text + ": scene " + text2 + " lost";
}
if ((from d in list
group d by (Scene: d.Scene, Spawn: d.Spawn)).Any((IGrouping<(string Scene, int Spawn), Destination> g) => g.Count() > 1))
{
return "list " + text + ": one spawn point listed twice";
}
for (int num2 = 0; num2 < list.Count; num2++)
{
Destination destination = list[num2];
Destination destination2 = ((num2 > 0) ? list[num2 - 1] : null);
Log($" {num2 + 1,2} {destination.Kind,-7} {destination.Label} <- {destination.Scene} #{destination.Spawn}");
if (val.options[num2 + 1].text != destination.Label)
{
return $"list {text}: option {num2 + 1} \"{val.options[num2 + 1].text}\" is not \"{destination.Label}\"";
}
if (destination2 != null && destination2.Kind > destination.Kind)
{
return $"list {text}: {destination2.Kind} \"{destination2.Label}\" before {destination.Kind} \"{destination.Label}\"";
}
if (Plugin.SortByName.Value && destination2 != null && destination2.Kind == destination.Kind && string.Compare(destination2.Label, destination.Label, StringComparison.CurrentCultureIgnoreCase) > 0)
{
return "list " + text + ": \"" + destination2.Label + "\" listed before \"" + destination.Label + "\"";
}
}
if (list.Any((Destination d) => d.Kind == Kind.Town) && list[0].Kind != Kind.Town)
{
return "list " + text + ": the town is not first";
}
num += scenes[i].Count;
}
if (num != AreaManager.ActiveScenes.Count((string s) => AreaManager.Instance.GetAreaFromSceneName(s) != null && s != "Tutorial_Standalone" && StoreManager.Instance.IsDlcInstalled(AreaManager.Instance.GetAreaFromSceneName(s).DLCId)))
{
return $"{num} scenes listed, not every area of the build";
}
return null;
}
private IEnumerator Capture(string label)
{
string file = Path.Combine(outputDir, label + ".png");
if (!Application.isBatchMode)
{
yield return (object)new WaitForEndOfFrame();
Texture2D val = ScreenCapture.CaptureScreenshotAsTexture();
File.WriteAllBytes(file, ImageConversion.EncodeToPNG(val));
Object.Destroy((Object)(object)val);
Log("captured " + file);
}
else
{
Log("batchmode: no screen to capture for " + label);
}
}
private IEnumerator CheckListLayouts(DT_CharacterCheats panel, Dropdown[] dropdowns)
{
offScreenLists = 0;
for (int f = 0; f < dropdowns.Length; f++)
{
Dropdown dropdown = dropdowns[f];
if ((Object)(object)dropdown == (Object)null)
{
continue;
}
string family = ((f < AreaManager.AreaFamilies.Length) ? AreaManager.AreaFamilies[f].FamilyName : "Others");
panel.OnSceneFamilyClicked(f);
ListColumns.LastLayout = "single column";
dropdown.Show();
yield return WaitRealtime(1f);
Transform obj = ((Component)dropdown).transform.Find("Dropdown List");
RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
if ((Object)(object)val == (Object)null)
{
Log("layout " + family + ": no list opened");
offScreenLists++;
continue;
}
if (family == "Sirocco")
{
File.WriteAllText(Path.Combine(outputDir, "list_hierarchy.txt"), Describe((Transform)(object)val, 0, new StringBuilder()).ToString());
}
Toggle[] array = (from t in ((Component)val).GetComponentsInChildren<Toggle>(true)
where ((Component)t).gameObject.activeInHierarchy
select t).ToArray();
int num = 0;
Vector3[] array2 = (Vector3[])(object)new Vector3[4];
Toggle[] array3 = array;
for (int num2 = 0; num2 < array3.Length; num2++)
{
((RectTransform)((Component)array3[num2]).transform).GetWorldCorners(array2);
if (array2.Any((Vector3 c) => c.x < -0.5f || c.y < -0.5f || c.x > (float)Screen.width + 0.5f || c.y > (float)Screen.height + 0.5f))
{
num++;
}
}
val.GetWorldCorners(array2);
Log($"layout {family}: {array.Length} items, {num} off screen, list {array2[0]:F0}-{array2[2]:F0}, {ListColumns.LastLayout}");
if (num > 0)
{
offScreenLists++;
}
yield return Capture("list_" + family);
dropdown.Hide();
yield return WaitRealtime(0.5f);
}
}
private static StringBuilder Describe(Transform t, int depth, StringBuilder sb)
{
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: 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)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_013c: Unknown result type (might be due to invalid IL or missing references)
//IL_0143: Expected O, but got Unknown
RectTransform val = (RectTransform)(object)((t is RectTransform) ? t : null);
sb.Append(' ', depth * 2).Append(((Object)t).name).Append(((Component)t).gameObject.activeSelf ? "" : " (inactive)");
if ((Object)(object)val != (Object)null)
{
object[] obj = new object[6] { val.anchorMin, val.anchorMax, val.pivot, val.anchoredPosition, val.sizeDelta, null };
Rect rect = val.rect;
obj[5] = ((Rect)(ref rect)).size;
sb.Append(string.Format(" anchors {0:F2}-{1:F2} pivot {2:F2} pos {3:F1} size {4:F1} rect {5:F1}", obj));
}
sb.Append(" [").Append(string.Join(", ", from c in ((Component)t).GetComponents<Component>()
where !(c is Transform)
select ((object)c).GetType().Name)).AppendLine("]");
int num = 0;
foreach (Transform item in t)
{
Transform val2 = item;
if ((Object)(object)((Component)val2).GetComponent<Toggle>() == (Object)null || num++ < 1)
{
Describe(val2, depth + 1, sb);
}
}
return sb;
}
private IEnumerator Probe(string scene, string pattern)
{
Log("probe: loading " + scene);
NetworkLevelLoader.Instance.RequestSwitchArea(scene, 0, 1.5f, false);
yield return WaitRealtime(3f);
float deadline = Time.realtimeSinceStartup + 300f;
while (!InGameplay(scene))
{
if (Time.realtimeSinceStartup > deadline)
{
Fail("probe: " + scene + " did not load");
yield break;
}
yield return null;
}
yield return WaitRealtime(4f);
string path = Path.Combine(outputDir, "probe_" + scene + ".txt");
try
{
File.WriteAllText(path, DescribeProbe(scene, pattern));
}
catch (Exception ex)
{
File.WriteAllText(path, ex.ToString());
}
Log("probe: done");
}
private static string DescribeProbe(string scene, string patternList)
{
//IL_0735: Unknown result type (might be due to invalid IL or missing references)
//IL_073a: Unknown result type (might be due to invalid IL or missing references)
//IL_09c8: Unknown result type (might be due to invalid IL or missing references)
string[] array = patternList.Split(new char[1] { '|' });
string pattern = array[0];
StringBuilder stringBuilder = new StringBuilder();
List<GameObject> source = Resources.FindObjectsOfTypeAll<GameObject>().Where(delegate(GameObject g)
{
//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_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
Scene scene3 = g.scene;
if (!(((Scene)(ref scene3)).name == scene))
{
scene3 = g.scene;
return ((Scene)(ref scene3)).name == "DontDestroyOnLoad";
}
return true;
}).ToList();
HashSet<GameObject> hashSet = new HashSet<GameObject>(source.Where(delegate(GameObject g)
{
//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)
Scene scene3 = g.scene;
return ((Scene)(ref scene3)).name == scene && ((Object)g).name.IndexOf(pattern, StringComparison.OrdinalIgnoreCase) >= 0;
}));
stringBuilder.AppendLine($"== objects named *{pattern}* ({hashSet.Count})");
foreach (GameObject item in hashSet.OrderBy((GameObject g) => HierarchyPath(g.transform)))
{
stringBuilder.AppendLine($" {HierarchyPath(item.transform)} self {item.activeSelf} hierarchy {item.activeInHierarchy} " + "[" + string.Join(", ", from c in item.GetComponents<Component>()
where (Object)(object)c != (Object)null && !(c is Transform)
select ((object)c).GetType().Name) + "]");
}
foreach (GameObjectToggleOnQuestEvent item2 in hashSet.SelectMany((GameObject g) => g.GetComponents<GameObjectToggleOnQuestEvent>()))
{
string text = JsonUtility.ToJson((object)item2);
foreach (Match item3 in Regex.Matches(text, "\"m_eventUID\":\"([^\"]+)\""))
{
text += $" [{item3.Groups[1].Value} = {QuestEventDictionary.GetQuestEvent(item3.Groups[1].Value)?.EventName}, stack {QuestEventManager.Instance.GetEventCurrentStack(item3.Groups[1].Value)}]";
}
stringBuilder.AppendLine(" toggle on " + HierarchyPath(((Component)item2).transform) + ": " + text + " ObjectToToggle " + (((Object)(object)item2.ObjectToToggle != (Object)null) ? HierarchyPath(item2.ObjectToToggle.transform) : "null"));
}
stringBuilder.AppendLine("== components referencing them");
foreach (MonoBehaviour item4 in from c in source.Where(delegate(GameObject g)
{
//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)
Scene scene3 = g.scene;
return ((Scene)(ref scene3)).name == scene;
}).SelectMany((GameObject g) => g.GetComponents<MonoBehaviour>())
where (Object)(object)c != (Object)null
select c)
{
foreach (FieldInfo item5 in AccessTools.GetDeclaredFields(((object)item4).GetType()).Concat(BaseFields(((object)item4).GetType())).Distinct())
{
object value;
try
{
value = item5.GetValue(item4);
}
catch
{
continue;
}
List<string> list;
try
{
list = (from g in References(value).Where(hashSet.Contains)
select ((Object)g).name).ToList();
}
catch
{
continue;
}
if (list.Count > 0)
{
stringBuilder.AppendLine(string.Format(" {0} {1}.{2} -> {3} (enabled {4})", HierarchyPath(((Component)item4).transform), ((object)item4).GetType().Name, item5.Name, string.Join(", ", list), ((Behaviour)item4).enabled));
}
}
}
stringBuilder.AppendLine("== components whose serialized data mentions a pattern");
foreach (MonoBehaviour item6 in from c in source.Where(delegate(GameObject g)
{
//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)
Scene scene3 = g.scene;
return ((Scene)(ref scene3)).name == scene;
}).SelectMany((GameObject g) => g.GetComponents<MonoBehaviour>())
where (Object)(object)c != (Object)null
select c)
{
if (!(item6 is GraphOwner))
{
string data;
try
{
data = JsonUtility.ToJson((object)item6);
}
catch
{
continue;
}
if (array.Any((string p) => data.IndexOf(p, StringComparison.OrdinalIgnoreCase) >= 0))
{
stringBuilder.AppendLine(string.Format(" {0} {1} (active {2}): {3}", HierarchyPath(((Component)item6).transform), ((object)item6).GetType().Name, ((Behaviour)item6).isActiveAndEnabled, (data.Length > 1500) ? (data.Substring(0, 1500) + "...") : data));
}
}
}
stringBuilder.AppendLine("== graphs mentioning it");
HashSet<string> hashSet2 = new HashSet<string>();
foreach (GraphOwner item7 in from o in source.SelectMany((GameObject g) => g.GetComponents<GraphOwner>())
where (Object)(object)o != (Object)null
select o)
{
Graph graph = item7.graph;
string value2 = Traverse.Create((object)item7).Field("boundGraphSerialization").GetValue<string>();
string json = ((!string.IsNullOrEmpty(value2)) ? value2 : (((Object)(object)graph != (Object)null) ? Traverse.Create((object)graph).Field("_serializedGraph").GetValue<string>() : null));
if (json == null || !array.Any((string p) => json.IndexOf(p, StringComparison.OrdinalIgnoreCase) >= 0))
{
continue;
}
string[] obj4 = new string[8]
{
" ",
HierarchyPath(((Component)item7).transform),
" (",
null,
null,
null,
null,
null
};
Scene scene2 = ((Component)item7).gameObject.scene;
obj4[3] = ((Scene)(ref scene2)).name;
obj4[4] = ") ";
obj4[5] = ((object)item7).GetType().Name;
obj4[6] = " ";
obj4[7] = $"graph {((graph != null) ? graph.name : null)}, active {((Behaviour)item7).isActiveAndEnabled}:\n{json}\n";
stringBuilder.AppendLine(string.Concat(obj4));
foreach (Match item8 in Regex.Matches(json, "m_eventUID\":\"([^\"]+)\""))
{
hashSet2.Add(item8.Groups[1].Value);
}
}
stringBuilder.AppendLine("== quest events used by those graphs");
foreach (string item9 in hashSet2)
{
QuestEventSignature questEvent = QuestEventDictionary.GetQuestEvent(item9);
stringBuilder.AppendLine(" " + item9 + ": " + ((questEvent == null) ? "?" : $"{questEvent.ParentSection?.Name}/{questEvent.EventName} \"{questEvent.Description}\" timed {questEvent.IsTimedEvent} stackable {questEvent.IsStackable} savable {questEvent.Savable}") + $" stack now {QuestEventManager.Instance.GetEventCurrentStack(item9)}");
}
stringBuilder.AppendLine("== interactions");
foreach (InteractionBase item10 in from i in source.SelectMany((GameObject g) => g.GetComponents<InteractionBase>())
where (Object)(object)i != (Object)null
select i)
{
stringBuilder.AppendLine($" {HierarchyPath(((Component)item10).transform)} {((object)item10).GetType().Name} active {((Component)item10).gameObject.activeInHierarchy} at {((Component)item10).transform.position:F0}");
}
return stringBuilder.ToString();
}
private static IEnumerable<FieldInfo> BaseFields(Type type)
{
type = type.BaseType;
while (type != null && type != typeof(MonoBehaviour))
{
foreach (FieldInfo declaredField in AccessTools.GetDeclaredFields(type))
{
yield return declaredField;
}
type = type.BaseType;
}
}
private static IEnumerable<GameObject> References(object value)
{
GameObject val = (GameObject)((value is GameObject) ? value : null);
if (val == null)
{
Component val2 = (Component)((value is Component) ? value : null);
if (val2 == null)
{
if (value is string)
{
yield break;
}
}
else if ((Object)(object)val2 != (Object)null)
{
yield return val2.gameObject;
yield break;
}
if (!(value is IEnumerable enumerable))
{
yield break;
}
foreach (object item in enumerable)
{
GameObject val3 = (GameObject)((item is GameObject) ? item : null);
if (val3 != null && (Object)(object)val3 != (Object)null)
{
yield return val3;
continue;
}
Component val4 = (Component)((item is Component) ? item : null);
if (val4 != null && (Object)(object)val4 != (Object)null)
{
yield return val4.gameObject;
}
}
}
else if ((Object)(object)val != (Object)null)
{
yield return val;
}
}
private IEnumerator Survey()
{
string file = Path.Combine(outputDir, "survey.txt");
File.WriteAllText(file, "");
string[] commandLineArgs = Environment.GetCommandLineArgs();
int num = Array.IndexOf(commandLineArgs, "--dtn-survey-scenes");
string[] array = ((num >= 0 && num + 1 < commandLineArgs.Length) ? commandLineArgs[num + 1].Split(new char[1] { ',' }) : SurveyScenes);
if (num >= 0 && commandLineArgs[num + 1] == "all")
{
array = AreaManager.ActiveScenes.Where((string s) => AreaManager.Instance.GetAreaFromSceneName(s) != null && s != "Tutorial_Standalone").ToArray();
}
File.AppendAllText(file, DescribeNameTables());
string[] array2 = array;
foreach (string scene in array2)
{
Log("survey: loading " + scene);
NetworkLevelLoader.Instance.RequestSwitchArea(scene, 0, 1.5f, false);
float deadline = Time.realtimeSinceStartup + 300f;
yield return WaitRealtime(3f);
while (!InGameplay(scene))
{
if (Time.realtimeSinceStartup > deadline)
{
Fail("survey: " + scene + " did not load");
yield break;
}
yield return null;
}
yield return WaitRealtime(4f);
try
{
File.AppendAllText(file, DescribeScene(scene));
}
catch (Exception arg)
{
File.AppendAllText(file, $"== {scene}: {arg}\n");
}
}
Log("survey: done");
}
private static string DescribeScene(string scene)
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: 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_01ac: Unknown result type (might be due to invalid IL or missing references)
//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
//IL_0325: Unknown result type (might be due to invalid IL or missing references)
//IL_0331: Unknown result type (might be due to invalid IL or missing references)
//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
//IL_0418: Unknown result type (might be due to invalid IL or missing references)
StringBuilder stringBuilder = new StringBuilder();
Area areaFromSceneName = AreaManager.Instance.GetAreaFromSceneName(scene);
AreaEnum val = (AreaEnum)areaFromSceneName.ID;
stringBuilder.AppendLine($"== {scene} ({val}, \"{areaFromSceneName.GetName()}\")");
Transform[] array = (Transform[])(((Object)(object)SpawnPointManager.Instance != (Object)null) ? ((Array)SpawnPointManager.Instance.SpawnPoints) : ((Array)new Transform[0]));
stringBuilder.AppendLine($"spawn points: {array.Length}");
for (int i = 0; i < array.Length; i++)
{
Transform val2 = array[i];
object arg = i;
string arg2 = (((Object)(object)val2 != (Object)null) ? ((Object)val2).name : "null");
object arg3;
if (!((Object)(object)val2 != (Object)null))
{
arg3 = "-";
}
else
{
Vector3 position = val2.position;
arg3 = ((Vector3)(ref position)).ToString("F0");
}
stringBuilder.AppendLine($" spawn {arg}: {arg2} at {arg3}" + " GetAreaName \"" + AreaManager.Instance.GetAreaName(val, i) + "\"");
}
stringBuilder.AppendLine("doors:");
foreach (InteractionSwitchArea item in Resources.FindObjectsOfTypeAll<InteractionSwitchArea>().Where(delegate(InteractionSwitchArea d)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
Scene scene2 = ((Component)d).gameObject.scene;
return ((Scene)(ref scene2)).name == scene;
}))
{
string value = Traverse.Create((object)item).Field("m_overrideAreaLocKey").GetValue<string>();
Area area = AreaManager.Instance.GetArea(item.Area);
stringBuilder.AppendLine($" {((Component)item).transform.position:F0} -> {item.Area} ({area?.SceneName}) spawn {item.SpawnPoint}" + " name \"" + AreaManager.Instance.GetAreaName(item.Area, item.SpawnPoint) + "\"" + (string.IsNullOrEmpty(value) ? "" : (" override " + value + " \"" + LocalizationManager.Instance.GetLoc(value) + "\"")) + $" active {((Component)item).gameObject.activeInHierarchy} path {HierarchyPath(((Component)item).transform)}");
}
stringBuilder.AppendLine("characters (nearest spawn):");
foreach (Character item2 in CharacterManager.Instance.Characters.Values.Where((Character c) => (Object)(object)c != (Object)null && !c.IsLocalPlayer))
{
int num = -1;
float num2 = float.MaxValue;
for (int num3 = 0; num3 < array.Length; num3++)
{
if (!((Object)(object)array[num3] == (Object)null))
{
float num4 = Vector3.Distance(array[num3].position, ((Component)item2).transform.position);
if (num4 < num2)
{
num2 = num4;
num = num3;
}
}
}
string value2 = Traverse.Create((object)item2).Field("m_nameLocKey").GetValue<string>();
object[] obj = new object[8] { num, num2, item2.Name, value2, item2.UID, null, null, null };
CharacterStats stats = item2.Stats;
obj[5] = ((stats != null) ? new float?(stats.MaxHealth) : ((float?)null));
obj[6] = item2.IsAI;
obj[7] = item2.Faction;
stringBuilder.AppendLine(string.Format(" spawn {0} ({1:F0} m): \"{2}\" key {3} uid {4} hp {5:F0} ai {6} faction {7}", obj) + $" active {((Component)item2).gameObject.activeInHierarchy} at {((Component)item2).transform.position:F0} {((Object)((Component)item2).gameObject).name}");
}
stringBuilder.AppendLine();
return stringBuilder.ToString();
}
private static string DescribeNameTables()
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
StringBuilder stringBuilder = new StringBuilder("== name tables\n");
SmallDungeonName[] smallDungeonNames = AreaManager.Instance.SmallDungeonNames;
foreach (SmallDungeonName val in smallDungeonNames)
{
stringBuilder.AppendLine($" {val.SmallDungeon}: " + string.Join(" | ", val.SpawnIndexLocKey.Select((string key, int num2) => $"[{num2}] {key} \"{LocalizationManager.Instance.GetLoc(key)}\"")));
}
string[] array = new string[3] { "Scene_Harmattan_DungeonsSmall", "Scene_Caldera_SmallDungeon", "Scene_Caldera_SmallDungeon0" };
string text2 = default(string);
foreach (string text in array)
{
for (int num = 0; num <= 14; num++)
{
if (LocalizationManager.Instance.TryGetLoc(text + num, ref text2))
{
stringBuilder.AppendLine(" " + text + num + " \"" + text2 + "\"");
}
}
}
return stringBuilder.AppendLine().ToString();
}
private static string HierarchyPath(Transform t)
{
string text = ((Object)t).name;
t = t.parent;
while ((Object)(object)t != (Object)null)
{
text = ((Object)t).name + "/" + text;
t = t.parent;
}
return text;
}
}