Decompiled source of MapLoader v1.0.2

MapLoader.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Mirror;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.SceneManagement;
using maploader;

[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("MapLoader")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+1844e4af7a3013f889414ec204fa6b50ef91f0d6")]
[assembly: AssemblyProduct("MapLoader")]
[assembly: AssemblyTitle("MapLoader")]
[assembly: AssemblyVersion("1.0.0.0")]
public class PortalSync
{
	[HarmonyPatch(typeof(ChatBehaviour), "UserCode_Cmd_SendChatMessage__String__ChatChannel")]
	public static class SendSecretMessages
	{
		public static bool Prefix(ChatBehaviour __instance, string _message, ChatChannel _chatChannel)
		{
			if (_message.Contains("<>#CAPTION#"))
			{
				if (rpcChatMethod != null)
				{
					rpcChatMethod.Invoke(__instance, new object[3]
					{
						_message,
						true,
						(object)(ChatChannel)3
					});
					MapLoader.Logger.LogInfo((object)"Sent caption info in a secret message");
				}
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(ChatBehaviour), "UserCode_Rpc_RecieveChatMessage__String__Boolean__ChatChannel")]
	public static class ReceiveSecretMessages
	{
		public static bool Prefix(string message, bool _isEmoteMessage, ChatChannel _chatChannel)
		{
			if (message.Contains("<>#CAPTION#"))
			{
				MapLoader.Logger.LogInfo((object)("Got a secret message: " + message));
				string text = Regex.Replace(message, "<.*?>", string.Empty);
				string[] array = text.Split('#', StringSplitOptions.RemoveEmptyEntries);
				if (array.Length < 3)
				{
					MapLoader.Logger.LogWarning((object)"Secret message had too few arguments!");
					return false;
				}
				if (!int.TryParse(array[1], out var result))
				{
					MapLoader.Logger.LogWarning((object)("Couldn't parse index from: " + array[1]));
					return false;
				}
				string value = array[2];
				if (Instance != null)
				{
					Instance.receivedPortalCaptions[result] = value;
				}
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Player), "Start")]
	public static class HostCaptionSender
	{
		public static void Postfix(Player __instance)
		{
			MapLoader.Logger.LogInfo((object)"Postfix Player called!");
			if (NetworkServer.active)
			{
				MapLoader.Logger.LogInfo((object)"Sending captions");
				if (Instance != null)
				{
					Instance.SendLocalCaptions();
				}
			}
			else
			{
				MapLoader.Logger.LogInfo((object)"Not host. Host will send caption data.");
			}
		}
	}

	public Dictionary<int, string> localPortalCaptions;

	public Dictionary<int, string> receivedPortalCaptions;

	public static MethodInfo rpcChatMethod = typeof(ChatBehaviour).GetMethod("Rpc_RecieveChatMessage", BindingFlags.Instance | BindingFlags.NonPublic);

	public static PortalSync Instance { get; private set; }

	public PortalSync()
	{
		localPortalCaptions = new Dictionary<int, string>();
		receivedPortalCaptions = new Dictionary<int, string>();
		Instance = this;
		MapLoader.MapBundles.Sort((AssetBundle x, AssetBundle y) => ((Object)x).name.CompareTo(((Object)y).name));
		int num = 0;
		foreach (AssetBundle mapBundle in MapLoader.MapBundles)
		{
			localPortalCaptions.Add(num, Path.GetFileNameWithoutExtension(mapBundle.GetAllScenePaths()[0]));
			num++;
		}
		MapLoader.Logger.LogInfo((object)"Caption syncer created!");
	}

	public void SendLocalCaptions()
	{
		foreach (KeyValuePair<int, string> localPortalCaption in localPortalCaptions)
		{
			string text = $"<>#CAPTION#{localPortalCaption.Key}#{localPortalCaption.Value}";
			try
			{
				Player._mainPlayer._cB.Cmd_SendChatMessage(text, (ChatChannel)3);
			}
			catch
			{
				MapLoader.Logger.LogError((object)"cmd_sendchatmessage failed! Caption not sent");
			}
		}
	}

	public void SetReceivedCaptions()
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		Portal[] array = Object.FindObjectsOfType<Portal>();
		Portal[] array2 = array;
		foreach (Portal val in array2)
		{
			if (!MapLoader.portalLocations.Contains(((Component)val).gameObject.transform.position))
			{
				continue;
			}
			MapLoader.Logger.LogInfo((object)"Found modded portal to sync");
			if (receivedPortalCaptions.TryGetValue(MapLoader.portalLocations.IndexOf(((Component)val).gameObject.transform.position), out var value))
			{
				MapLoader.Logger.LogInfo((object)("Successfully synced portal with caption " + value));
				if (MapLoader.modSceneNames.Contains(value))
				{
					val._scenePortal._portalCaptionTitle = value;
					continue;
				}
				MapLoader.Logger.LogInfo((object)("We don't have " + value + "! Attempting to delete portal on client's side!"));
				Object.Destroy((Object)(object)((Component)val).gameObject);
			}
			else
			{
				MapLoader.Logger.LogWarning((object)"No caption data received for portal, its destination is unknown!");
			}
		}
	}
}
namespace maploader;

[BepInPlugin("firenoobsta.maploader", "Map Loader", "1.0.2")]
public class MapLoader : BaseUnityPlugin
{
	[HarmonyPatch(typeof(MainMenuManager), "Start")]
	public class RegisterPortalPrefab
	{
		[HarmonyPostfix]
		private static void Postfix(MainMenuManager __instance)
		{
			Logger.LogInfo((object)"Registering portal prefab");
			Portal component = PortalPrefab.GetComponent<Portal>();
			component._isPortalOpen = true;
			component._disableIfSoloMode = false;
			component._openPortalIfOnQuest = false;
			component._openPortalIfQuestComplete = false;
			component._netDisablePortal = false;
			component.Toggle_NetDisabler(false);
			NetworkClient.RegisterPrefab(PortalPrefab);
			Logger.LogInfo((object)"Portal Prefab Registered");
			captionSyncer.receivedPortalCaptions.Clear();
		}
	}

	[HarmonyPatch(typeof(MapInstance), "Start")]
	public class CreatePortalEntity
	{
		[HarmonyPostfix]
		private static void Postfix(MapInstance __instance)
		{
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Expected O, but got Unknown
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			Logger.LogInfo((object)"Postfix MapInstance Start Called!");
			if (__instance._mapName == "Sanctum")
			{
				if (!NetworkServer.active)
				{
					Logger.LogInfo((object)"Not server host, attempting to set my portal captions. (Should have already received them by now)");
					captionSyncer.SetReceivedCaptions();
					return;
				}
				MapBundles.Sort((AssetBundle x, AssetBundle y) => ((Object)x).name.CompareTo(((Object)y).name));
				int num = 0;
				foreach (AssetBundle mapBundle in MapBundles)
				{
					if (num >= portalLocations.Count)
					{
						Logger.LogWarning((object)"I ran out of locations to put portals!");
						Logger.LogWarning((object)"Aborting placement of other portals");
						break;
					}
					if (mapBundle.GetAllScenePaths().Length == 0)
					{
						Logger.LogError((object)("Bundle " + ((Object)mapBundle).name + " had no scenes to load!"));
						continue;
					}
					ScenePortalData scenePortal = new ScenePortalData
					{
						_portalType = (PortalType)0,
						_subScene = mapBundle.GetAllScenePaths()[0],
						_portalCaptionTitle = Path.GetFileNameWithoutExtension(mapBundle.GetAllScenePaths()[0]),
						_spawnPointTag = "spawnPoint"
					};
					GameObject val = Object.Instantiate<GameObject>(PortalPrefab);
					val.GetComponent<Portal>()._scenePortal = scenePortal;
					val.transform.SetPositionAndRotation(portalLocations[num], Quaternion.identity);
					SceneManager.MoveGameObjectToScene(val, __instance._loadedScene);
					val.SetActive(true);
					NetworkServer.Spawn(val, (NetworkConnection)null);
					Logger.LogInfo((object)("Portal to " + val.GetComponent<Portal>()._scenePortal._portalCaptionTitle + " created!"));
					num++;
				}
			}
			AudioMixer val2 = Resources.Load<AudioMixer>("_sound/_mixer/_mixerMain");
			if ((Object)(object)val2 == (Object)null)
			{
				Logger.LogWarning((object)"Couldn't load main mixer from resources!");
				return;
			}
			AudioSource[] array = Object.FindObjectsOfType<AudioSource>();
			foreach (AudioSource val3 in array)
			{
				List<string> modSceneNames = MapLoader.modSceneNames;
				Scene scene = ((Component)val3).gameObject.scene;
				if (modSceneNames.Contains(((Scene)(ref scene)).name))
				{
					val3.outputAudioMixerGroup = val2.FindMatchingGroups(((Object)val3.outputAudioMixerGroup).name)[0];
				}
			}
			Logger.LogInfo((object)"Updated audio source mixers!");
		}
	}

	[HarmonyPatch(typeof(GameManager), "Cache_ScriptableAssets")]
	public class AddExtraScriptables
	{
		[HarmonyPostfix]
		private static void Postfix(GameManager __instance)
		{
			Logger.LogInfo((object)"Postfix cache scriptables called!");
			if (typeof(GameManager).GetField("_cachedScriptableCreeps", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance) is Dictionary<string, ScriptableCreep> dictionary)
			{
				Logger.LogInfo((object)"Successfully got creep cache");
				foreach (ScriptableCreep modCreep in modCreeps)
				{
					dictionary.Add(modCreep._creepName, modCreep);
					Logger.LogInfo((object)("Added " + modCreep._creepName + " to creep cache"));
				}
			}
			if (typeof(GameManager).GetField("_cachedScriptableItems", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance) is Dictionary<string, ScriptableItem> dictionary2)
			{
				Logger.LogInfo((object)"Successfully got item cache");
				foreach (ScriptableItem modItem in modItems)
				{
					dictionary2.Add(modItem._itemName, modItem);
					Logger.LogInfo((object)("Added " + modItem._itemName + " to item cache"));
				}
			}
			if (!(typeof(GameManager).GetField("_cachedScriptableConditions", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance) is Dictionary<string, ScriptableCondition> dictionary3))
			{
				return;
			}
			Logger.LogInfo((object)"Successfully got condition cache");
			foreach (ScriptableCondition modCondition in modConditions)
			{
				dictionary3.Add($"{modCondition._conditionName}_{modCondition._conditionRank}", modCondition);
				Logger.LogInfo((object)("Added " + modCondition._conditionName + " to condition cache"));
			}
		}
	}

	internal static ManualLogSource Logger;

	public static string PluginFolderPath;

	public static List<string> modSceneNames;

	public static List<ScriptableCreep> modCreeps;

	public static List<ScriptableItem> modItems;

	public static List<ScriptableCondition> modConditions;

	public static List<GameObject> PortalPrefabs;

	public static GameObject PortalPrefab;

	public static List<Vector3> portalLocations;

	public static PortalSync captionSyncer;

	public static MapLoader Instance { get; private set; }

	public static AssetBundle MyAssetBundle { get; private set; }

	public static List<AssetBundle> MapBundles { get; private set; }

	public static List<AssetBundle> ScriptableBundles { get; private set; }

	private void Awake()
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected O, but got Unknown
		//IL_006d: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_0165: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
		Logger = ((BaseUnityPlugin)this).Logger;
		Harmony val = new Harmony("firenoobsta.maploader");
		val.PatchAll();
		Instance = this;
		PluginFolderPath = Paths.PluginPath;
		MapBundles = new List<AssetBundle>();
		ScriptableBundles = new List<AssetBundle>();
		PortalPrefabs = new List<GameObject>();
		portalLocations = new List<Vector3>();
		portalLocations.Add(new Vector3(-74f, 5f, 162f));
		portalLocations.Add(new Vector3(-82f, 5f, 173f));
		portalLocations.Add(new Vector3(-89f, 5f, 200f));
		portalLocations.Add(new Vector3(-89f, 5f, 217f));
		portalLocations.Add(new Vector3(58f, 5f, 162f));
		portalLocations.Add(new Vector3(68f, 5f, 173f));
		portalLocations.Add(new Vector3(69f, 5f, 200f));
		portalLocations.Add(new Vector3(69f, 5f, 217f));
		portalLocations.Add(new Vector3(56f, 5f, 244f));
		portalLocations.Add(new Vector3(47f, 5f, 253f));
		portalLocations.Add(new Vector3(37f, 5f, 261f));
		portalLocations.Add(new Vector3(23f, 5f, 268f));
		modSceneNames = new List<string>();
		modCreeps = new List<ScriptableCreep>();
		modItems = new List<ScriptableItem>();
		modConditions = new List<ScriptableCondition>();
		Logger.LogInfo((object)("Plugin Folder Path: " + PluginFolderPath));
		if (Directory.Exists(PluginFolderPath))
		{
			CheckDirectory(PluginFolderPath);
		}
		PortalPrefab = Resources.Load<GameObject>("_prefab/_entity/_portal/_entity_portal");
		if ((Object)(object)PortalPrefab == (Object)null)
		{
			Logger.LogError((object)"Couldn't load portal prefab from resources!");
			return;
		}
		foreach (AssetBundle mapBundle in MapBundles)
		{
			string[] allScenePaths = mapBundle.GetAllScenePaths();
			foreach (string path in allScenePaths)
			{
				modSceneNames.Add(Path.GetFileNameWithoutExtension(path));
			}
		}
		Logger.LogInfo((object)"Scene Names: ");
		foreach (string modSceneName in modSceneNames)
		{
			Logger.LogInfo((object)modSceneName);
		}
		captionSyncer = new PortalSync();
	}

	private void Start()
	{
		Logger.LogInfo((object)"Map Loader Loaded!");
		Logger.LogInfo((object)"Version 1.0.2");
		Logger.LogInfo((object)"Current loaded bundles: ");
		foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles())
		{
			Logger.LogInfo((object)((Object)allLoadedAssetBundle).name);
		}
	}

	public static void CheckDirectory(string dirPath)
	{
		string[] files = Directory.GetFiles(dirPath);
		string[] array = files;
		foreach (string filePath in array)
		{
			CheckFile(filePath);
		}
		string[] directories = Directory.GetDirectories(dirPath);
		string[] array2 = directories;
		foreach (string dirPath2 in array2)
		{
			CheckDirectory(dirPath2);
		}
	}

	public static void CheckFile(string filePath)
	{
		if (filePath.EndsWith(".mapbundle"))
		{
			Logger.LogInfo((object)("Loading map asset bundle: " + Path.GetFileName(filePath)));
			AssetBundle val = AssetBundle.LoadFromFile(filePath);
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogError((object)("Failed to load asset bundle: " + Path.GetFileName(filePath)));
				return;
			}
			Logger.LogInfo((object)"Adding to map bundle list");
			MapBundles.Add(val);
			Logger.LogInfo((object)"Successfully loaded bundle!");
		}
		else
		{
			if (!filePath.EndsWith(".scriptable"))
			{
				return;
			}
			Logger.LogInfo((object)("Loading scriptables asset bundle: " + Path.GetFileName(filePath)));
			AssetBundle val2 = AssetBundle.LoadFromFile(filePath);
			if ((Object)(object)val2 == (Object)null)
			{
				Logger.LogError((object)("Failed to load asset bundle: " + Path.GetFileName(filePath)));
				return;
			}
			Logger.LogInfo((object)"Adding to scriptable bundle list");
			ScriptableBundles.Add(val2);
			ScriptableCreep[] array = val2.LoadAllAssets<ScriptableCreep>();
			foreach (ScriptableCreep val3 in array)
			{
				Logger.LogInfo((object)(val3._creepName + " creep found in bundle! Logging it"));
				modCreeps.Add(val3);
			}
			ScriptableItem[] array2 = val2.LoadAllAssets<ScriptableItem>();
			foreach (ScriptableItem val4 in array2)
			{
				Logger.LogInfo((object)(val4._itemName + " item found in bundle! Logging it"));
				modItems.Add(val4);
			}
			ScriptableCondition[] array3 = val2.LoadAllAssets<ScriptableCondition>();
			foreach (ScriptableCondition val5 in array3)
			{
				Logger.LogInfo((object)(val5._conditionName + " condition found in bundle! Logging it"));
				modConditions.Add(val5);
			}
			Logger.LogInfo((object)"Successfully loaded bundle!");
		}
	}
}