using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Peak;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.SceneManagement;
using Zorro.Core;
[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("NadirMod")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("NadirMod")]
[assembly: AssemblyTitle("NadirMod")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[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]
[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 NadirMod
{
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "NadirMod";
public const string PLUGIN_NAME = "NadirMod";
public const string PLUGIN_VERSION = "1.0.0";
}
}
namespace TrueFinalAscentNadirFix
{
[BepInPlugin("com.custom.peak.truefinalascent.nadirfix", "True Final Ascent - Procedural Nadir Fix", "1.0.4")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class NadirFixPlugin : BaseUnityPlugin
{
public const string ModGuid = "com.custom.peak.truefinalascent.nadirfix";
public const string ModName = "True Final Ascent - Procedural Nadir Fix";
public const string ModVersion = "1.0.4";
internal static ManualLogSource Log;
private Harmony? _harmony;
private void Awake()
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
_harmony = new Harmony("com.custom.peak.truefinalascent.nadirfix");
_harmony.PatchAll();
Log.LogInfo((object)"[True Final Ascent - Procedural Nadir Fix] loaded successfully (v1.0.4).");
}
private void OnDestroy()
{
Harmony? harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
}
public static class NadirGenerator
{
private const string Tag = "[NadirFix]";
public static bool IsGeneratingNadir;
private static bool _generatedThisScene;
public static bool HasGenerated => _generatedThisScene;
static NadirGenerator()
{
IsGeneratingNadir = false;
_generatedThisScene = false;
SceneManager.sceneLoaded += delegate
{
_generatedThisScene = false;
};
}
public static bool HasUnpackedNadirFromHost()
{
GameObject val = FindVoidRoot();
if ((Object)(object)val == (Object)null)
{
return false;
}
Transform[] componentsInChildren = val.GetComponentsInChildren<Transform>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
if (((Object)componentsInChildren[i]).name.EndsWith("(Clone)"))
{
_generatedThisScene = true;
return true;
}
}
return false;
}
public static GameObject? FindVoidRoot()
{
try
{
Type type = AccessTools.TypeByName("TrueFinalAscent.FinalAscentVoid");
if (type != null)
{
MethodInfo methodInfo = AccessTools.Method(type, "Find", (Type[])null, (Type[])null);
if (methodInfo != null)
{
object? obj = methodInfo.Invoke(null, null);
GameObject val = (GameObject)((obj is GameObject) ? obj : null);
if ((Object)(object)val != (Object)null)
{
return val;
}
}
}
}
catch
{
}
VoidBiome[] array = Object.FindObjectsByType<VoidBiome>((FindObjectsInactive)1, (FindObjectsSortMode)0);
VoidBiome[] array2 = array;
foreach (VoidBiome val2 in array2)
{
if ((Object)(object)val2 != (Object)null)
{
return ((Component)val2).gameObject;
}
}
MapHandler instance = Singleton<MapHandler>.Instance;
if ((Object)(object)instance != (Object)null)
{
for (int j = 0; j < ((Component)instance).transform.childCount; j++)
{
Transform child = ((Component)instance).transform.GetChild(j);
if (((Object)child).name.IndexOf("VOID", StringComparison.OrdinalIgnoreCase) >= 0)
{
return ((Component)child).gameObject;
}
}
}
return GameObject.Find("VOID");
}
public static void SetVoidBiomeActive(bool active)
{
GameObject val = FindVoidRoot();
if ((Object)(object)val != (Object)null && val.activeSelf != active)
{
val.SetActive(active);
}
try
{
MethodInfo methodInfo = AccessTools.Property(typeof(VoidBiome), "VoidBiomeActive")?.GetSetMethod(nonPublic: true);
if (methodInfo != null)
{
methodInfo.Invoke(null, new object[1] { active });
return;
}
FieldInfo fieldInfo = AccessTools.Field(typeof(VoidBiome), "VoidBiomeActive") ?? AccessTools.Field(typeof(VoidBiome), "_voidBiomeActive") ?? AccessTools.Field(typeof(VoidBiome), "m_VoidBiomeActive") ?? AccessTools.Field(typeof(VoidBiome), "<VoidBiomeActive>k__BackingField");
if (fieldInfo != null)
{
fieldInfo.SetValue(null, active);
}
}
catch
{
}
}
public static int GetCurrentSeed()
{
try
{
Type type = AccessTools.TypeByName("TrueFinalAscent.FinalAscent");
if (type != null)
{
PropertyInfo propertyInfo = AccessTools.Property(type, "Seed");
if (propertyInfo != null && propertyInfo.GetValue(null) is int num && num != 0)
{
return num;
}
}
}
catch
{
}
try
{
if (PhotonNetwork.InRoom)
{
Room currentRoom = PhotonNetwork.CurrentRoom;
if (((currentRoom != null) ? ((RoomInfo)currentRoom).CustomProperties : null) != null && ((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).TryGetValue((object)"FAs", out object value) && value is int num2 && true && num2 != 0)
{
return num2;
}
}
}
catch
{
}
try
{
LevelGeneration val = Object.FindFirstObjectByType<LevelGeneration>();
if ((Object)(object)val != (Object)null)
{
FieldInfo fieldInfo = AccessTools.Field(typeof(LevelGeneration), "seed");
if (fieldInfo != null && fieldInfo.GetValue(val) is int num3 && num3 != 0)
{
return num3;
}
}
}
catch
{
}
return 1337;
}
public static bool IsFinalAscentActive()
{
try
{
Type type = AccessTools.TypeByName("TrueFinalAscent.FinalAscent");
if (type != null)
{
PropertyInfo propertyInfo = AccessTools.Property(type, "Active");
if (propertyInfo != null && propertyInfo.GetValue(null) is bool result)
{
return result;
}
}
}
catch
{
}
return false;
}
public static bool IsInNadir()
{
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Invalid comparison between Unknown and I4
if (VoidBiome.VoidBiomeActive)
{
return true;
}
MapHandler instance = Singleton<MapHandler>.Instance;
if ((Object)(object)instance != (Object)null)
{
if (instance.inNadir)
{
return true;
}
if ((int)MapHandler.CurrentSegmentNumber == 6)
{
return true;
}
}
try
{
if (PhotonNetwork.InRoom)
{
Room currentRoom = PhotonNetwork.CurrentRoom;
if (((currentRoom != null) ? ((RoomInfo)currentRoom).CustomProperties : null) != null && ((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).TryGetValue((object)"FAe", out object value) && value is int num && true && num >= 96)
{
return true;
}
}
}
catch
{
}
return false;
}
public static void GenerateNadir(int baseSeed)
{
//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
//IL_01be: Invalid comparison between Unknown and I4
if (_generatedThisScene)
{
NadirFixPlugin.Log.LogInfo((object)"[NadirFix] Nadir already generated for this scene; skipping.");
return;
}
GameObject val = FindVoidRoot();
if ((Object)(object)val == (Object)null)
{
NadirFixPlugin.Log.LogWarning((object)"[NadirFix] Void root could not be located; aborting Nadir generation.");
return;
}
NadirFixPlugin.Log.LogInfo((object)string.Format("{0} Beginning procedural generation for Nadir with seed {1}...", "[NadirFix]", baseSeed));
List<GameObject> disabled = new List<GameObject>();
IsolateVoid(val, disabled);
try
{
IsGeneratingNadir = true;
bool activeSelf = val.activeSelf;
val.SetActive(true);
EnablingSubstep[] componentsInChildren = val.GetComponentsInChildren<EnablingSubstep>(true);
EnablingSubstep[] array = componentsInChildren;
foreach (EnablingSubstep val2 in array)
{
if ((Object)(object)val2 != (Object)null)
{
((Component)val2).gameObject.SetActive(true);
}
}
Physics.SyncTransforms();
int num = baseSeed ^ 0x4E414449;
IGenConfigStep[] componentsInChildren2 = val.GetComponentsInChildren<IGenConfigStep>(true);
for (int j = 0; j < componentsInChildren2.Length; j++)
{
if (componentsInChildren2[j] != null)
{
try
{
Random.InitState(num ^ (j * 31));
componentsInChildren2[j].RunStep();
}
catch (Exception ex)
{
NadirFixPlugin.Log.LogWarning((object)("[NadirFix] IGenConfigStep " + ((object)componentsInChildren2[j]).GetType().Name + " failed: " + ex.Message));
}
}
}
LevelGenStep[] componentsInChildren3 = val.GetComponentsInChildren<LevelGenStep>(true);
List<LevelGenStep> list = new List<LevelGenStep>();
List<LevelGenStep> list2 = new List<LevelGenStep>();
LevelGenStep[] array2 = componentsInChildren3;
foreach (LevelGenStep val3 in array2)
{
if (!((Object)(object)val3 == (Object)null))
{
PropGrouper componentInParent = ((Component)val3).GetComponentInParent<PropGrouper>(true);
if ((Object)(object)componentInParent != (Object)null && (int)componentInParent.timing == 1)
{
list2.Add(val3);
}
else
{
list.Add(val3);
}
}
}
LevelGenStep[] array3 = componentsInChildren3;
foreach (LevelGenStep val4 in array3)
{
if ((Object)(object)val4 != (Object)null)
{
try
{
val4.Clear();
}
catch
{
}
}
}
Physics.SyncTransforms();
List<IDeferredStep> list3 = new List<IDeferredStep>();
ExecuteStepBatch(list, num, list3);
Physics.SyncTransforms();
RunDeferredBatch(list3);
list3.Clear();
Physics.SyncTransforms();
ExecuteStepBatch(list2, num, list3);
Physics.SyncTransforms();
RunDeferredBatch(list3);
list3.Clear();
Physics.SyncTransforms();
ILevelGenFinalizer[] componentsInChildren4 = val.GetComponentsInChildren<ILevelGenFinalizer>(true);
ILevelGenFinalizer[] array4 = componentsInChildren4;
foreach (ILevelGenFinalizer val5 in array4)
{
if (val5 != null)
{
try
{
val5.OnLevelGenFinished();
}
catch (Exception ex2)
{
NadirFixPlugin.Log.LogWarning((object)("[NadirFix] Finalizer " + ((object)val5).GetType().Name + " threw: " + ex2.Message));
}
}
}
SpawnZone[] componentsInChildren5 = val.GetComponentsInChildren<SpawnZone>(true);
SpawnZone[] array5 = componentsInChildren5;
foreach (SpawnZone val6 in array5)
{
if ((Object)(object)val6 != (Object)null)
{
Collider[] components = ((Component)val6).GetComponents<Collider>();
for (int num2 = 0; num2 < components.Length; num2++)
{
Object.Destroy((Object)(object)components[num2]);
}
}
}
val.SetActive(activeSelf);
_generatedThisScene = true;
NadirFixPlugin.Log.LogInfo((object)string.Format("{0} Successfully generated procedural Nadir ({1} level-gen steps executed).", "[NadirFix]", componentsInChildren3.Length));
}
catch (Exception arg)
{
NadirFixPlugin.Log.LogError((object)string.Format("{0} Error generating Nadir: {1}", "[NadirFix]", arg));
}
finally
{
IsGeneratingNadir = false;
RestoreIsolation(disabled);
Physics.SyncTransforms();
}
}
private static void ExecuteStepBatch(List<LevelGenStep> batch, int baseSeed, List<IDeferredStep> deferredList)
{
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Invalid comparison between Unknown and I4
foreach (LevelGenStep item in batch)
{
if ((Object)(object)item == (Object)null)
{
continue;
}
int num = baseSeed ^ StableHash(GetPath(((Component)item).transform));
Random.InitState(num);
try
{
item.Clear();
IEnumerator enumerator2 = item.Execute();
while (enumerator2 != null && enumerator2.MoveNext())
{
}
}
catch (Exception ex)
{
NadirFixPlugin.Log.LogWarning((object)("[NadirFix] Step '" + ((Object)item).name + "' failed: " + ex.Message));
}
if ((int)item.DeferredTiming > 0)
{
try
{
IDeferredStep val = item.ConstructDeferred((IMayHaveDeferredStep)(object)item);
if (val != null)
{
deferredList.Add(val);
}
}
catch
{
}
}
Physics.SyncTransforms();
}
}
private static void RunDeferredBatch(List<IDeferredStep> deferredList)
{
foreach (IDeferredStep deferred in deferredList)
{
if (deferred != null)
{
try
{
deferred.DeferredGo();
}
catch (Exception ex)
{
NadirFixPlugin.Log.LogWarning((object)("[NadirFix] Deferred step failed: " + ex.Message));
}
}
}
}
private static void IsolateVoid(GameObject voidRoot, List<GameObject> disabled)
{
MapHandler instance = Singleton<MapHandler>.Instance;
if ((Object)(object)instance != (Object)null)
{
for (int i = 0; i < ((Component)instance).transform.childCount; i++)
{
Transform child = ((Component)instance).transform.GetChild(i);
if ((Object)(object)((Component)child).gameObject != (Object)(object)voidRoot && ((Component)child).gameObject.activeSelf && !child.IsChildOf(voidRoot.transform))
{
((Component)child).gameObject.SetActive(false);
disabled.Add(((Component)child).gameObject);
}
}
}
LevelGeneration val = Object.FindFirstObjectByType<LevelGeneration>();
if (!((Object)(object)val != (Object)null))
{
return;
}
for (int j = 0; j < ((Component)val).transform.childCount; j++)
{
Transform child2 = ((Component)val).transform.GetChild(j);
if ((Object)(object)((Component)child2).gameObject != (Object)(object)voidRoot && ((Component)child2).gameObject.activeSelf && !child2.IsChildOf(voidRoot.transform))
{
((Component)child2).gameObject.SetActive(false);
disabled.Add(((Component)child2).gameObject);
}
}
}
private static void RestoreIsolation(List<GameObject> disabled)
{
foreach (GameObject item in disabled)
{
if ((Object)(object)item != (Object)null)
{
item.SetActive(true);
}
}
}
private static int StableHash(string text)
{
if (string.IsNullOrEmpty(text))
{
return 0;
}
uint num = 2166136261u;
foreach (char c in text)
{
num = (num ^ c) * 16777619;
}
return (int)num;
}
private static string GetPath(Transform? t)
{
if ((Object)(object)t == (Object)null)
{
return "";
}
StringBuilder stringBuilder = new StringBuilder(((Object)t).name);
Transform parent = t.parent;
while ((Object)(object)parent != (Object)null)
{
stringBuilder.Insert(0, '/').Insert(0, ((Object)parent).name);
parent = parent.parent;
}
return stringBuilder.ToString();
}
}
[HarmonyPatch]
public static class Patch_FinalAscentVoidGuard
{
public static MethodBase? TargetMethod()
{
Type type = AccessTools.TypeByName("TrueFinalAscent.FinalAscentVoidGuard");
return (type != null) ? AccessTools.Method(type, "Prefix", (Type[])null, (Type[])null) : null;
}
[HarmonyPrefix]
public static bool Prefix(ref bool __result)
{
__result = true;
return false;
}
}
[HarmonyPatch]
public static class Patch_FinalAscentVoid_Wake
{
public static MethodBase? TargetMethod()
{
Type type = AccessTools.TypeByName("TrueFinalAscent.FinalAscentVoid");
return (type != null) ? AccessTools.Method(type, "Wake", (Type[])null, (Type[])null) : null;
}
[HarmonyPostfix]
public static void Postfix()
{
if (NadirGenerator.IsFinalAscentActive() && (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient))
{
int currentSeed = NadirGenerator.GetCurrentSeed();
NadirGenerator.GenerateNadir(currentSeed);
}
}
}
[HarmonyPatch]
public static class Patch_FinalAscentBuilder_MarkReady
{
public static MethodBase? TargetMethod()
{
Type type = AccessTools.TypeByName("TrueFinalAscent.FinalAscentBuilder");
return (type != null) ? AccessTools.Method(type, "MarkReady", (Type[])null, (Type[])null) : null;
}
[HarmonyPrefix]
public static void Prefix()
{
if (NadirGenerator.IsFinalAscentActive() && !NadirGenerator.HasGenerated && !NadirGenerator.HasUnpackedNadirFromHost())
{
int currentSeed = NadirGenerator.GetCurrentSeed();
NadirGenerator.GenerateNadir(currentSeed);
}
}
}
[HarmonyPatch]
public static class Patch_FixNadirSpawnPoint
{
public static MethodBase? TargetMethod()
{
Type type = AccessTools.TypeByName("TrueFinalAscent.FinalAscentBaseCampPatch");
return (type != null) ? AccessTools.Method(type, "Prefix", (Type[])null, (Type[])null) : null;
}
[HarmonyPrefix]
public static bool Prefix(ref bool __result)
{
if (NadirGenerator.IsInNadir())
{
__result = true;
return false;
}
return true;
}
}
[HarmonyPatch]
public static class Patch_FixNadirJumpGate
{
public static MethodBase? TargetMethod()
{
Type type = AccessTools.TypeByName("TrueFinalAscent.FinalAscentJumpGate");
return (type != null) ? AccessTools.Method(type, "Prefix", (Type[])null, (Type[])null) : null;
}
[HarmonyPrefix]
public static bool Prefix(Segment newSegment, ref bool __result)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Invalid comparison between Unknown and I4
if ((int)newSegment == 6)
{
NadirGenerator.SetVoidBiomeActive(active: true);
__result = true;
return false;
}
return true;
}
}
[HarmonyPatch]
public static class Patch_FixNadirSoftLanding
{
public static MethodBase? TargetMethod()
{
Type type = AccessTools.TypeByName("TrueFinalAscent.FinalAscentSoftLanding");
return (type != null) ? AccessTools.Method(type, "Begin", (Type[])null, (Type[])null) : null;
}
[HarmonyPrefix]
public static bool Prefix()
{
if (NadirGenerator.IsInNadir())
{
NadirFixPlugin.Log.LogInfo((object)"[NadirFix] In Nadir: suppressed SoftLanding warp to mountain basecamp.");
return false;
}
return true;
}
}
}