Decompiled source of TerrainRandomiser v0.1.2

TerrainRandomiser.dll

Decompiled a day ago
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("TerrainRandomiser")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.1.2")]
[assembly: AssemblyInformationalVersion("0.1.2+20229879f969c7b068fd44de5df8fe254f783323")]
[assembly: AssemblyProduct("TerrainRandomiser")]
[assembly: AssemblyTitle("TerrainRandomiser")]
[assembly: AssemblyVersion("0.1.2.0")]
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;
		}
	}
}
namespace TerrainRandomiser
{
	[BepInPlugin("com.snosz.terrainrandomiser", "TerrainRandomiser", "0.1.2")]
	public class Plugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(GUIManager), "Awake")]
		private static class GUIManagerAwakePatch
		{
			private static void Postfix(GUIManager __instance)
			{
				SeedPickerUI seedPickerUI = ((Component)__instance.boardingPass).gameObject.AddComponent<SeedPickerUI>();
				Instance.seedPickerUI = seedPickerUI;
			}
		}

		[HarmonyPatch(typeof(AirportCheckInKiosk), "BeginIslandLoadRPC")]
		public class BeginIslandLoadPatch
		{
			private static void Postfix()
			{
				if (shouldRandomise && PhotonNetwork.IsMasterClient)
				{
					Instance.SetMasterSeed(masterSeed);
				}
			}
		}

		[HarmonyPatch(typeof(MapHandler), "Start")]
		private static class MapHandlerStartPatch
		{
			private static void Prefix(MapHandler __instance)
			{
				if (!shouldRandomise)
				{
					return;
				}
				Debug.LogError((object)$"[TerrainRandomiser] Starting generation with seed: {masterSeed}");
				if (PhotonNetwork.IsMasterClient)
				{
					viewIDsToSend = new List<int>();
				}
				else
				{
					viewsRequiringIDs = new List<PhotonView>();
				}
				Random.InitState(masterSeed);
				for (int i = 0; i < __instance.segments.Length; i++)
				{
					GameObject segmentParent = __instance.segments[i].segmentParent;
					PropGrouper val = ((segmentParent != null) ? segmentParent.GetComponent<PropGrouper>() : null);
					if (val != null)
					{
						val.RunAll(true);
					}
				}
				if (PhotonNetwork.IsMasterClient)
				{
					Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties;
					customProperties[(object)"propViews"] = viewIDsToSend.ToArray();
					PhotonNetwork.CurrentRoom.SetCustomProperties(customProperties, (Hashtable)null, (WebFlags)null);
					Debug.Log((object)$"[TerrainRandomiser] Host sent {viewIDsToSend.Count} ViewIDs to clients.");
				}
			}

			private static void Postfix(MapHandler __instance)
			{
				if (shouldRandomise && !PhotonNetwork.IsMasterClient)
				{
					Debug.Log((object)string.Format("[TerrainRandomiser] Required viewIDs: {0} | Received viewIDs: {1}", viewsRequiringIDs?.Count ?? (-1), (receivedViewIDs == null) ? "null" : receivedViewIDs.Count.ToString()));
				}
			}
		}

		[HarmonyPatch(typeof(PropGrouper), "RunAll")]
		public class PropGrouperPatch
		{
			private static void Postfix(PropGrouper __instance)
			{
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Invalid comparison between Unknown and I4
				//IL_009a: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a0: Invalid comparison between Unknown and I4
				if (!shouldRandomise)
				{
					return;
				}
				List<PropSpawner> list = new List<PropSpawner>();
				List<PropSpawner_Line> list2 = new List<PropSpawner_Line>();
				PropSpawner[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<PropSpawner>();
				PropSpawner_Line[] componentsInChildren2 = ((Component)__instance).GetComponentsInChildren<PropSpawner_Line>();
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					PropGrouper componentInParent = ((Component)componentsInChildren[i]).GetComponentInParent<PropGrouper>();
					if ((Object)(object)componentInParent != (Object)null && (int)componentInParent.timing == 1)
					{
						list.Add(componentsInChildren[i]);
					}
				}
				for (int j = 0; j < componentsInChildren2.Length; j++)
				{
					PropGrouper componentInParent2 = ((Component)componentsInChildren2[j]).GetComponentInParent<PropGrouper>();
					if ((Object)(object)componentInParent2 != (Object)null && (int)componentInParent2.timing == 1)
					{
						list2.Add(componentsInChildren2[j]);
					}
				}
				foreach (PropSpawner item in list)
				{
					item.Go();
				}
				foreach (PropSpawner_Line item2 in list2)
				{
					item2.Go();
				}
			}
		}

		public static class PropSpawnerHelper
		{
			public static Quaternion GetRandomRotationWithUp(Vector3 normal)
			{
				//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_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: 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)
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				Vector3 onUnitSphere = Random.onUnitSphere;
				onUnitSphere.y = 0f;
				onUnitSphere = Vector3.Cross(normal, Vector3.Cross(normal, onUnitSphere));
				return Quaternion.LookRotation(onUnitSphere, normal);
			}

			public static bool TrySpawn<T>(T __instance, SpawnData spawnData, ref GameObject __result, GameObject[] props, List<PropSpawnerMod> modifiers, List<PropSpawnerConstraintPost> postConstraints, Transform parent, GameObject fallback) where T : class
			{
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				//IL_004e: 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_0056: Unknown result type (might be due to invalid IL or missing references)
				GameObject val = props[Random.Range(0, props.Length)];
				PhotonView val2 = default(PhotonView);
				if ((Object)(object)val != (Object)null && val.TryGetComponent<PhotonView>(ref val2))
				{
					BreakableBridge val3 = default(BreakableBridge);
					if (val.TryGetComponent<BreakableBridge>(ref val3))
					{
						__result = fallback;
						return false;
					}
					Quaternion randomRotationWithUp = GetRandomRotationWithUp(Vector3.up);
					GameObject val4 = Object.Instantiate<GameObject>(val, spawnData.pos, randomRotationWithUp, parent);
					Luggage val5 = default(Luggage);
					if (val4.TryGetComponent<Luggage>(ref val5))
					{
						SpineCheck component = val4.GetComponent<SpineCheck>();
						if ((Object)(object)component != (Object)null)
						{
							Object.DestroyImmediate((Object)(object)component);
						}
					}
					foreach (PropSpawnerMod modifier in modifiers)
					{
						modifier.ModifyObject(val4, spawnData);
					}
					foreach (PropSpawnerConstraintPost postConstraint in postConstraints)
					{
						if (!postConstraint.CheckConstraint(val4, spawnData))
						{
							Object.DestroyImmediate((Object)(object)val4);
							__result = null;
							return false;
						}
					}
					if (PhotonNetwork.IsMasterClient)
					{
						int num = PhotonNetwork.AllocateViewID(true);
						viewIDsToSend.Add(num);
						PhotonView component2 = val4.GetComponent<PhotonView>();
						component2.ViewID = num;
					}
					else
					{
						PhotonView component3 = val4.GetComponent<PhotonView>();
						viewsRequiringIDs.Add(component3);
					}
					__result = val4;
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(PropSpawner), "Spawn")]
		public static class PropSpawnerPatch
		{
			private static bool Prefix(PropSpawner __instance, SpawnData spawnData, ref GameObject __result)
			{
				if (shouldRandomise)
				{
					return PropSpawnerHelper.TrySpawn<PropSpawner>(__instance, spawnData, ref __result, __instance.props, __instance.modifiers, __instance.postConstraints, ((Component)__instance).transform, ((Component)__instance).gameObject);
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(PropSpawner_Line), "Spawn")]
		public static class PropSpawner_LinePatch
		{
			private static bool Prefix(PropSpawner_Line __instance, SpawnData spawnData, ref GameObject __result)
			{
				if (shouldRandomise)
				{
					return PropSpawnerHelper.TrySpawn<PropSpawner_Line>(__instance, spawnData, ref __result, __instance.props, __instance.modifiers, __instance.postConstraints, ((Component)__instance).transform, ((Component)__instance).gameObject);
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Spawner), "TrySpawnItems")]
		public static class SpawnerTrySpawnItemsPatch
		{
			private static void Postfix(Spawner __instance, ref List<PhotonView> __result)
			{
				PhotonView item = default(PhotonView);
				if (shouldRandomise && PhotonNetwork.IsMasterClient && __result.Count == 0 && ((Component)__instance).TryGetComponent<PhotonView>(ref item))
				{
					__result.Add(item);
				}
			}
		}

		public static Plugin Instance;

		private static Harmony _harmony;

		public static int masterSeed = 1000;

		public static List<int> viewIDsToSend;

		public static List<PhotonView> viewsRequiringIDs;

		public static List<int> receivedViewIDs;

		public ConfigEntry<int> configSeed;

		public AssetBundle seedPickerUIBundle;

		public SeedPickerUI seedPickerUI;

		public static bool shouldRandomise = true;

		private void Awake()
		{
			Instance = this;
			byte[] seedpicker = Resource1.seedpicker;
			seedPickerUIBundle = AssetBundle.LoadFromMemory(seedpicker);
			configSeed = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Seed", 1000, "Seed to apply.");
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = true;
			masterSeed = configSeed.Value;
			CreateCustomMapHandlerSingleton();
			_harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "com.snosz.terrainrandomiser");
		}

		private void CreateCustomMapHandlerSingleton()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			if ((Object)(object)TerrainRandomiserHandler.Instance == (Object)null)
			{
				GameObject val = new GameObject("CustomMapHandler");
				val.AddComponent<TerrainRandomiserHandler>();
				Object.DontDestroyOnLoad((Object)(object)val);
			}
		}

		public void SetMasterSeed(int newSeed)
		{
			masterSeed = newSeed;
			configSeed.Value = masterSeed;
			Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties;
			customProperties[(object)"seed"] = masterSeed;
			PhotonNetwork.CurrentRoom.SetCustomProperties(customProperties, (Hashtable)null, (WebFlags)null);
			Debug.Log((object)$"[TerrainRandomiser] Seed has been set to: {masterSeed}");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			seedPickerUIBundle.Unload(false);
		}

		public void UpdateRequiredViewIDs()
		{
			if (!shouldRandomise || PhotonNetwork.IsMasterClient || viewsRequiringIDs == null || receivedViewIDs == null)
			{
				return;
			}
			if (viewsRequiringIDs.Count == receivedViewIDs.Count)
			{
				for (int i = 0; i < receivedViewIDs.Count; i++)
				{
					viewsRequiringIDs[i].ViewID = receivedViewIDs[i];
				}
			}
			else
			{
				Debug.LogError((object)"[TerrainRandomiser] ID Count mismatch! Map will be out of sync!");
			}
		}
	}
	[GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
	[DebuggerNonUserCode]
	[CompilerGenerated]
	internal class Resource1
	{
		private static ResourceManager resourceMan;

		private static CultureInfo resourceCulture;

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static ResourceManager ResourceManager
		{
			get
			{
				if (resourceMan == null)
				{
					ResourceManager resourceManager = new ResourceManager("TerrainRandomiser.Resource1", typeof(Resource1).Assembly);
					resourceMan = resourceManager;
				}
				return resourceMan;
			}
		}

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static CultureInfo Culture
		{
			get
			{
				return resourceCulture;
			}
			set
			{
				resourceCulture = value;
			}
		}

		internal static byte[] seedpicker
		{
			get
			{
				object @object = ResourceManager.GetObject("seedpicker", resourceCulture);
				return (byte[])@object;
			}
		}

		internal Resource1()
		{
		}
	}
	public class SeedPickerUI : MonoBehaviour
	{
		private GameObject seedPickerInstance;

		private GameObject seedPickerUIPrefab;

		private Button setButton;

		private Button randomSeedButton;

		private TMP_InputField seedInputField;

		private Toggle enableRandomiserToggle;

		private int inputSeed;

		private TMP_FontAsset textFontAsset;

		private void Awake()
		{
			//IL_00a8: 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_028f: Expected O, but got Unknown
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Expected O, but got Unknown
			if ((Object)(object)seedPickerUIPrefab == (Object)null)
			{
				seedPickerUIPrefab = Plugin.Instance.seedPickerUIBundle.LoadAsset<GameObject>("SeedPicker2");
			}
			TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
			TMP_FontAsset[] array2 = array;
			foreach (TMP_FontAsset val in array2)
			{
				if (((Object)val).name.Contains("DarumaDropOne"))
				{
					textFontAsset = val;
					break;
				}
			}
			seedPickerInstance = Object.Instantiate<GameObject>(seedPickerUIPrefab, ((Component)this).transform.Find("BoardingPass"));
			seedPickerInstance.transform.localPosition = new Vector3(2.34f, 175.4367f, 0f);
			Transform obj = seedPickerInstance.transform.Find("RandomSeedButton");
			randomSeedButton = ((obj != null) ? ((Component)obj).GetComponent<Button>() : null);
			Transform obj2 = seedPickerInstance.transform.Find("SeedInputField");
			seedInputField = ((obj2 != null) ? ((Component)obj2).GetComponent<TMP_InputField>() : null);
			if ((Object)(object)seedInputField != (Object)null)
			{
				inputSeed = Plugin.Instance.configSeed.Value;
				seedInputField.text = Plugin.Instance.configSeed.Value.ToString();
				seedInputField.characterLimit = 6;
				seedInputField.characterValidation = (CharacterValidation)2;
				TextMeshProUGUI[] componentsInChildren = ((Component)seedInputField).GetComponentsInChildren<TextMeshProUGUI>();
				for (int j = 0; j < componentsInChildren.Length; j++)
				{
					((TMP_Text)componentsInChildren[j]).font = textFontAsset;
					((TMP_Text)componentsInChildren[j]).fontSharedMaterial = ((TMP_Asset)textFontAsset).material;
				}
			}
			Transform obj3 = seedPickerInstance.transform.Find("SetSeedButton");
			setButton = ((obj3 != null) ? ((Component)obj3).GetComponent<Button>() : null);
			Transform obj4 = seedPickerInstance.transform.Find("Toggle");
			enableRandomiserToggle = ((obj4 != null) ? ((Component)obj4).GetComponent<Toggle>() : null);
			if ((Object)(object)enableRandomiserToggle != (Object)null)
			{
				((TMP_Text)((Component)enableRandomiserToggle).GetComponentInChildren<TextMeshProUGUI>()).font = textFontAsset;
				((TMP_Text)((Component)enableRandomiserToggle).GetComponentInChildren<TextMeshProUGUI>()).fontSharedMaterial = ((TMP_Asset)textFontAsset).material;
				enableRandomiserToggle.isOn = Plugin.shouldRandomise;
			}
			if ((Object)(object)randomSeedButton != (Object)null)
			{
				((UnityEvent)randomSeedButton.onClick).AddListener(new UnityAction(OnRandomSeedClicked));
			}
			if ((Object)(object)setButton != (Object)null)
			{
				((TMP_Text)((Component)setButton).GetComponentInChildren<TextMeshProUGUI>()).font = textFontAsset;
				((TMP_Text)((Component)setButton).GetComponentInChildren<TextMeshProUGUI>()).fontSharedMaterial = ((TMP_Asset)textFontAsset).material;
				((UnityEvent)setButton.onClick).AddListener(new UnityAction(OnSetSeedClicked));
			}
			if ((Object)(object)enableRandomiserToggle != (Object)null)
			{
				((UnityEvent<bool>)(object)enableRandomiserToggle.onValueChanged).AddListener((UnityAction<bool>)OnToggleChanged);
			}
		}

		private void OnRandomSeedClicked()
		{
			Plugin.Instance.SetMasterSeed(Random.Range(1, 10001));
			seedInputField.text = Plugin.masterSeed.ToString();
			inputSeed = Plugin.masterSeed;
		}

		private void OnSetSeedClicked()
		{
			if (int.TryParse(seedInputField.text, out var result))
			{
				if (PhotonNetwork.IsMasterClient)
				{
					Plugin.Instance.SetMasterSeed(result);
				}
			}
			else
			{
				Debug.LogWarning((object)"[TerrainRandomiser] Invalid seed input");
			}
		}

		private void OnToggleChanged(bool value)
		{
			Debug.Log((object)$"[TerrainRandomiser] Randomiser enabled: {value}");
			Plugin.shouldRandomise = value;
		}
	}
	public class TerrainRandomiserHandler : MonoBehaviourPunCallbacks
	{
		public static TerrainRandomiserHandler Instance { get; private set; }

		private void Awake()
		{
			if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			Debug.Log((object)"[TerrainRandomiserHandler] Singleton initialized");
		}

		public override void OnJoinedRoom()
		{
			Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties;
			if (((Dictionary<object, object>)(object)customProperties).ContainsKey((object)"seed") && customProperties[(object)"seed"] is int num)
			{
				Plugin.masterSeed = num;
				Debug.Log((object)$"[TerrainRandomiserHandler] Initialized with seed: {num}");
			}
			if (!PhotonNetwork.IsMasterClient && ((Dictionary<object, object>)(object)customProperties).ContainsKey((object)"propViews") && customProperties[(object)"propViews"] is int[] source)
			{
				if (Plugin.receivedViewIDs == null)
				{
					Plugin.receivedViewIDs = new List<int>();
				}
				Plugin.receivedViewIDs = source.ToList();
				Plugin.Instance.UpdateRequiredViewIDs();
				Debug.Log((object)$"[TerrainRandomiserHandler] Initialized receivedViewIDs with {Plugin.receivedViewIDs.Count} IDs");
			}
		}

		public override void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged)
		{
			Debug.Log((object)"[TerrainRandomiserHandler] Room properties updated!");
			if (((Dictionary<object, object>)(object)propertiesThatChanged).ContainsKey((object)"seed") && propertiesThatChanged[(object)"seed"] is int num)
			{
				Plugin.masterSeed = num;
				Debug.Log((object)$"[TerrainRandomiserHandler] Updated seed to: {num}");
			}
			if (((Dictionary<object, object>)(object)propertiesThatChanged).ContainsKey((object)"shouldRandomise") && propertiesThatChanged[(object)"shouldRandomise"] is bool flag)
			{
				Plugin.shouldRandomise = flag;
				Debug.Log((object)$"[TerrainRandomiserHandler] ShouldRandomise: {flag}");
			}
			if (!PhotonNetwork.IsMasterClient && ((Dictionary<object, object>)(object)propertiesThatChanged).ContainsKey((object)"propViews") && propertiesThatChanged[(object)"propViews"] is int[] source)
			{
				if (Plugin.receivedViewIDs == null)
				{
					Plugin.receivedViewIDs = new List<int>();
				}
				Plugin.receivedViewIDs = source.ToList();
				Plugin.Instance.UpdateRequiredViewIDs();
				Debug.Log((object)$"[TerrainRandomiserHandler] Updated receivedViewIDs with {Plugin.receivedViewIDs.Count} IDs");
			}
		}
	}
}