Decompiled source of ModernizationPortFullAuto v0.9.4

BepInEx/plugins/ModernizationPort/ModernizationPort.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DM;
using HarmonyLib;
using Landfall.TABS;
using Landfall.TABS.UnitPlacement;
using Microsoft.CodeAnalysis;
using ModernizationPort;
using ModernizationPort.Legacy;
using TFBGames;
using TMPro;
using UModLoader;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyFileVersion("0.9.4.0")]
[assembly: AssemblyTitle("modernization port by lil zalupa")]
[assembly: AssemblyProduct("modernization port by lil zalupa")]
[assembly: AssemblyCompany("lilzalupa")]
[assembly: AssemblyVersion("0.9.4.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace UModLoader
{
	public static class ULoader
	{
		internal static ContentDatabase Content;

		internal static LandfallContentDatabase Native;

		internal static readonly List<UnitBlueprint> CreatedUnits = new List<UnitBlueprint>();

		internal static readonly List<Faction> CreatedFactions = new List<Faction>();

		internal static readonly Dictionary<DatabaseID, string> Names = new Dictionary<DatabaseID, string>();

		private static Dictionary<string, string> language;

		private const int ModId = 1459449901;

		public static Dictionary<string, Dictionary<string, object>> VDic { get; private set; }

		public static Dictionary<string, Dictionary<string, Dictionary<string, object>>> MDic { get; private set; }

		internal static void Prepare(ContentDatabase content)
		{
			Content = content;
			Native = content.LandfallContentDatabase;
			VDic = new Dictionary<string, Dictionary<string, object>>();
			string[] array = new string[6] { "blueprints", "weapons", "clothes", "moves", "bases", "explosions" };
			foreach (string key in array)
			{
				VDic.Add(key, new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase));
			}
			MDic = new Dictionary<string, Dictionary<string, Dictionary<string, object>>> { 
			{
				"Modernization",
				new Dictionary<string, Dictionary<string, object>>
				{
					{
						"blueprints",
						new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase)
					},
					{
						"factions",
						new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase)
					}
				}
			} };
			language = Localizer.GetLanguage((Language)0);
			foreach (UnitBlueprint unitBlueprint in Native.GetUnitBlueprints())
			{
				Add("blueprints", unitBlueprint.Entity.Name, unitBlueprint);
				if (language.TryGetValue(unitBlueprint.Entity.Name, out var value))
				{
					Add("blueprints", value, unitBlueprint);
				}
			}
			Index("weapons", Native.GetWeapons());
			Index("clothes", Native.GetCharacterProps());
			Index("moves", Native.GetCombatMoves());
			Index("bases", Native.GetUnitBases());
			foreach (GameObject projectile in Native.GetProjectiles())
			{
				if (Object.op_Implicit((Object)(object)projectile))
				{
					Add("projectiles-unused", ((Object)projectile).name, projectile);
				}
			}
			Explosion[] array2 = Resources.FindObjectsOfTypeAll<Explosion>();
			foreach (Explosion val in array2)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					Add("explosions", ((Object)((Component)val).gameObject).name, ((Component)val).gameObject);
				}
			}
			Alias("blueprints", "CavalryKnight", "Cavalry", "Cavalry Knight");
			NativeTemplateAdapter.Apply();
			string[] array3 = (from pair in RequiredTemplates.Items
				where !VDic[pair[0]].ContainsKey(pair[1])
				select pair[0] + "/" + pair[1]).ToArray();
			if (array3.Length != 0)
			{
				throw new MissingMemberException("Vanilla templates unavailable: " + string.Join(", ", array3));
			}
			PortPlugin.Info("Template preflight complete: " + RequiredTemplates.Items.Length + " required names resolved.");
		}

		private static void Index(string category, IEnumerable<GameObject> objects)
		{
			foreach (GameObject @object in objects)
			{
				if (!Object.op_Implicit((Object)(object)@object))
				{
					continue;
				}
				Add(category, ((Object)@object).name, @object);
				Component[] componentsInChildren = @object.GetComponentsInChildren<Component>(true);
				foreach (Component obj in componentsInChildren)
				{
					IDatabaseEntity val = (IDatabaseEntity)(object)((obj is IDatabaseEntity) ? obj : null);
					if (val != null && val.Entity != null)
					{
						Add(category, val.Entity.Name, @object);
						if (language.TryGetValue(val.Entity.Name, out var value))
						{
							Add(category, value, @object);
						}
					}
				}
			}
		}

		private static void Add(string category, string key, object value)
		{
			if (string.IsNullOrEmpty(key) || !VDic.TryGetValue(category, out var value2))
			{
				return;
			}
			key = key.Replace("(Clone)", "").Trim();
			if (!value2.ContainsKey(key))
			{
				value2.Add(key, value);
			}
			string text = key;
			bool flag;
			do
			{
				flag = false;
				string[] array = new string[7] { "CP_", "P_", "W_", "WP_", "Move_", "E_", "B_" };
				foreach (string text2 in array)
				{
					if (text.StartsWith(text2, StringComparison.OrdinalIgnoreCase))
					{
						text = text.Substring(text2.Length);
						flag = true;
						break;
					}
				}
			}
			while (flag);
			if (!value2.ContainsKey(text))
			{
				value2.Add(text, value);
			}
			string key2 = text.Replace(" ", "");
			if (!value2.ContainsKey(key2))
			{
				value2.Add(key2, value);
			}
			string key3 = key.Replace(" ", "");
			if (!value2.ContainsKey(key3))
			{
				value2.Add(key3, value);
			}
		}

		internal static void Alias(string category, string key, params string[] alternatives)
		{
			Dictionary<string, object> dictionary = VDic[category];
			if (dictionary.ContainsKey(key))
			{
				return;
			}
			foreach (string key2 in alternatives)
			{
				if (dictionary.TryGetValue(key2, out var value))
				{
					dictionary.Add(key, value);
					break;
				}
			}
		}

		private static int StableId(string text)
		{
			uint num = 2166136261u;
			foreach (char c in text)
			{
				num ^= c;
				num *= 16777619;
			}
			return (int)(num & 0x7FFFFFFF);
		}

		internal static void Identity(IDatabaseEntity owner, string kind, string name)
		{
			//IL_0023: 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)
			DatabaseEntity val = owner.Entity.ShallowCopy();
			val.GUID = new DatabaseID(1459449901, StableId(kind + "/" + name));
			val.Name = name;
			AccessTools.Field(typeof(DatabaseEntity), "m_unlockKey").SetValue(val, "");
			AccessTools.Field(((object)owner).GetType(), "m_entity").SetValue(owner, val);
			Names.Add(val.GUID, name);
		}

		internal static void Register(IDatabaseEntity entity, Object obj, string field)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			IDictionary dictionary = (IDictionary)AccessTools.Field(typeof(LandfallContentDatabase), field).GetValue(Native);
			IDictionary dictionary2 = (IDictionary)AccessTools.Field(((object)Content.AssetLoader).GetType(), "m_nonStreamableAssets").GetValue(Content.AssetLoader);
			if (dictionary.Contains(entity.Entity.GUID) || dictionary2.Contains(entity.Entity.GUID))
			{
				throw new InvalidOperationException("Modernization ID already registered: " + entity.Entity.Name);
			}
			dictionary.Add(entity.Entity.GUID, obj);
			try
			{
				dictionary2.Add(entity.Entity.GUID, obj);
			}
			catch
			{
				dictionary.Remove(entity.Entity.GUID);
				throw;
			}
		}

		internal static void Rollback()
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			if (Content == null)
			{
				return;
			}
			IDictionary dictionary = (IDictionary)AccessTools.Field(((object)Content.AssetLoader).GetType(), "m_nonStreamableAssets").GetValue(Content.AssetLoader);
			foreach (UnitBlueprint createdUnit in CreatedUnits)
			{
				((IDictionary)AccessTools.Field(typeof(LandfallContentDatabase), "m_unitBlueprints").GetValue(Native)).Remove(createdUnit.Entity.GUID);
				dictionary.Remove(createdUnit.Entity.GUID);
				Object.Destroy((Object)(object)createdUnit);
			}
			foreach (Faction createdFaction in CreatedFactions)
			{
				((IDictionary)AccessTools.Field(typeof(LandfallContentDatabase), "m_factions").GetValue(Native)).Remove(createdFaction.Entity.GUID);
				dictionary.Remove(createdFaction.Entity.GUID);
				Object.Destroy((Object)(object)createdFaction);
			}
			CreatedUnits.Clear();
			CreatedFactions.Clear();
			Names.Clear();
		}
	}
	public static class UFunctions
	{
		public static string AssemName()
		{
			return "Modernization";
		}

		public static string ModNamify(string name)
		{
			return "Modernization/" + name;
		}

		public static string ModName(DatabaseEntity entity)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (entity == null || !ULoader.Names.TryGetValue(entity.GUID, out var value))
			{
				if (entity != null)
				{
					return entity.Name;
				}
				return "";
			}
			return ModNamify(value);
		}

		public static Faction CreateFaction(string name, UnitBlueprint[] units, Sprite icon)
		{
			Faction val = Object.Instantiate<Faction>(ULoader.Native.GetFactions().First((Faction x) => Object.op_Implicit((Object)(object)x) && x.m_displayFaction));
			ULoader.Identity((IDatabaseEntity)(object)val, "faction", name);
			((Object)val).name = "Modernization/" + name;
			val.Units = (UnitBlueprint[])(((object)units) ?? ((object)new UnitBlueprint[0]));
			val.m_displayFaction = true;
			val.index = ULoader.Native.GetFactions().Count();
			if (Object.op_Implicit((Object)(object)icon))
			{
				val.Entity.SetSpriteIcon(icon);
			}
			ULoader.Register((IDatabaseEntity)(object)val, (Object)(object)val, "m_factions");
			ULoader.CreatedFactions.Add(val);
			ULoader.MDic[AssemName()]["factions"].Add(name, val);
			return val;
		}

		public static UnitBlueprint CreateUnit(string name, UnitBlueprint original, Faction faction, Sprite icon)
		{
			UnitBlueprint val = Object.Instantiate<UnitBlueprint>(original);
			ULoader.Identity((IDatabaseEntity)(object)val, "unit", name);
			((Object)val).name = "Modernization/" + name;
			if (Object.op_Implicit((Object)(object)original.voiceBundle))
			{
				val.voiceBundle = Object.Instantiate<VoiceBundle>(original.voiceBundle);
				((Object)val.voiceBundle).hideFlags = (HideFlags)52;
			}
			val.SetNoCustomRider();
			if (Object.op_Implicit((Object)(object)icon))
			{
				val.Entity.SetSpriteIcon(icon);
			}
			ULoader.Register((IDatabaseEntity)(object)val, (Object)(object)val, "m_unitBlueprints");
			ULoader.CreatedUnits.Add(val);
			ULoader.MDic[AssemName()]["blueprints"].Add(name, val);
			List<UnitBlueprint> list = faction.Units.ToList();
			list.Add(val);
			faction.Units = list.ToArray();
			return val;
		}
	}
	public sealed class UPool
	{
		private static UPool instance;

		private readonly Dictionary<string, GameObject> objects = new Dictionary<string, GameObject>(StringComparer.OrdinalIgnoreCase);

		private readonly GameObject root;

		public static UPool MyPool => instance ?? (instance = new UPool());

		private UPool()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			root = new GameObject("Modernization prefab pool");
			root.SetActive(false);
			((Object)root).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)root);
		}

		public GameObject AddObject(string name, GameObject original, bool clone = true, HideFlags flags = (HideFlags)52)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = (clone ? Object.Instantiate<GameObject>(original, root.transform) : original);
			val.transform.SetParent(root.transform, false);
			((Object)val).name = "Modernization/" + name;
			((Object)val).hideFlags = flags;
			objects.Add(name, val);
			return val;
		}

		public GameObject GetObject(string name)
		{
			return objects[name];
		}

		internal GameObject ClonePrivate(GameObject original)
		{
			GameObject obj = Object.Instantiate<GameObject>(original, root.transform);
			((Object)obj).hideFlags = (HideFlags)52;
			return obj;
		}
	}
	public enum TriggerType
	{
		OnStart,
		OnTimer,
		OnGround
	}
	public sealed class USpawner : MonoBehaviour
	{
		public UnitBlueprint[] unitsToSpawn;

		public int u_numOfObjects = 1;

		public float u_startDelay;

		public float u_cd;

		public TriggerType u_triggerType;

		private bool triggered;

		private Vector3 previous;

		private void Start()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			previous = ((Component)this).transform.position;
			if (u_triggerType != TriggerType.OnGround)
			{
				Begin();
			}
		}

		private void Update()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: 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)
			if (!triggered && u_triggerType == TriggerType.OnGround)
			{
				Vector3 position = ((Component)this).transform.position;
				Vector3 val = position - previous;
				RaycastHit val2 = default(RaycastHit);
				if (((Vector3)(ref val)).sqrMagnitude > 0.0001f && Physics.Raycast(previous, ((Vector3)(ref val)).normalized, ref val2, ((Vector3)(ref val)).magnitude + 0.05f) && !Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<Unit>()))
				{
					Begin();
				}
				else if (Physics.Raycast(position, Vector3.down, ref val2, 0.3f) && !Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<Unit>()))
				{
					Begin();
				}
				previous = position;
			}
		}

		private void OnCollisionEnter(Collision collision)
		{
			if (u_triggerType == TriggerType.OnGround && !Object.op_Implicit((Object)(object)((Component)collision.collider).GetComponentInParent<Unit>()))
			{
				Begin();
			}
		}

		private void OnTriggerEnter(Collider collider)
		{
			if (u_triggerType == TriggerType.OnGround && !Object.op_Implicit((Object)(object)((Component)collider).GetComponentInParent<Unit>()))
			{
				Begin();
			}
		}

		private void Begin()
		{
			if (!triggered)
			{
				triggered = true;
				((MonoBehaviour)this).StartCoroutine(Spawn());
			}
		}

		private IEnumerator Spawn()
		{
			if (u_startDelay > 0f)
			{
				yield return (object)new WaitForSeconds(u_startDelay);
			}
			if (unitsToSpawn == null || unitsToSpawn.Length == 0)
			{
				yield break;
			}
			TeamHolder componentInParent = ((Component)this).GetComponentInParent<TeamHolder>();
			Unit componentInParent2 = ((Component)this).GetComponentInParent<Unit>();
			Team team = (Team)((!Object.op_Implicit((Object)(object)componentInParent)) ? (Object.op_Implicit((Object)(object)componentInParent2) ? ((int)componentInParent2.data.team) : 0) : ((int)componentInParent.team));
			for (int i = 0; i < Math.Min(u_numOfObjects, 64); i++)
			{
				if (!Object.op_Implicit((Object)(object)this))
				{
					break;
				}
				if (!Object.op_Implicit((Object)(object)((Component)this).gameObject))
				{
					break;
				}
				UnitBlueprint val = unitsToSpawn[i % unitsToSpawn.Length];
				if (Object.op_Implicit((Object)(object)val))
				{
					PortRuntime.SpawnNative(val, ((Component)this).transform.position, ((Component)this).transform.rotation, team);
				}
				if (u_cd > 0f)
				{
					yield return (object)new WaitForSeconds(u_cd);
				}
			}
		}
	}
}
namespace ModernizationPort
{
	public sealed class PortVisual : MonoBehaviour
	{
	}
	public static class PinaCollada
	{
		internal sealed class Model
		{
			internal Mesh Mesh;

			internal Material[] Materials;
		}

		internal static readonly Dictionary<string, Model> Models = new Dictionary<string, Model>(StringComparer.OrdinalIgnoreCase);

		internal static readonly Dictionary<string, Texture2D> Textures = new Dictionary<string, Texture2D>(StringComparer.OrdinalIgnoreCase);

		internal static readonly Dictionary<string, SoundEffectInstance> Sounds = new Dictionary<string, SoundEffectInstance>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, Sprite> Sprites = new Dictionary<string, Sprite>(StringComparer.OrdinalIgnoreCase);

		private static bool loaded;

		private static int Count(BinaryReader r, int maximum = 20000000)
		{
			int num = r.ReadInt32();
			if (num < 0 || num > maximum)
			{
				throw new InvalidDataException("Invalid asset count: " + num);
			}
			return num;
		}

		private static string String(BinaryReader r)
		{
			int num = Count(r, 65536);
			byte[] array = r.ReadBytes(num);
			if (array.Length != num)
			{
				throw new EndOfStreamException();
			}
			return Encoding.UTF8.GetString(array);
		}

		private static Vector3[] Vectors3(BinaryReader r)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			Vector3[] array = (Vector3[])(object)new Vector3[Count(r)];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
			}
			return array;
		}

		private static Vector2[] Vectors2(BinaryReader r)
		{
			//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)
			Vector2[] array = (Vector2[])(object)new Vector2[Count(r)];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = new Vector2(r.ReadSingle(), r.ReadSingle());
			}
			return array;
		}

		private static byte[] Bytes(BinaryReader r, int count)
		{
			byte[] array = r.ReadBytes(count);
			if (array.Length != count)
			{
				throw new EndOfStreamException();
			}
			return array;
		}

		public static void EnsureLoaded()
		{
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Expected O, but got Unknown
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Expected O, but got Unknown
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0376: Expected O, but got Unknown
			//IL_0384: Unknown result type (might be due to invalid IL or missing references)
			//IL_0389: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Expected O, but got Unknown
			//IL_045f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0464: Unknown result type (might be due to invalid IL or missing references)
			//IL_046b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0470: Unknown result type (might be due to invalid IL or missing references)
			//IL_0488: Expected O, but got Unknown
			if (loaded)
			{
				return;
			}
			using (FileStream stream = File.OpenRead(Path.Combine(Path.GetDirectoryName(typeof(PinaCollada).Assembly.Location), "Modernization.assets.gz")))
			{
				using GZipStream input = new GZipStream(stream, CompressionMode.Decompress);
				using BinaryReader binaryReader = new BinaryReader(input);
				if (Encoding.ASCII.GetString(Bytes(binaryReader, 8)) != "MODPORT1")
				{
					throw new InvalidDataException("Incorrect Modernization resources.");
				}
				int num = Count(binaryReader, 1000);
				Shader val = Shader.Find("Standard");
				if (!Object.op_Implicit((Object)(object)val))
				{
					val = Shader.Find("Diffuse");
				}
				if (!Object.op_Implicit((Object)(object)val))
				{
					Material val2 = ((IEnumerable<Material>)Resources.FindObjectsOfTypeAll<Material>()).FirstOrDefault((Func<Material, bool>)((Material x) => Object.op_Implicit((Object)(object)x) && Object.op_Implicit((Object)(object)x.shader) && x.HasProperty("_Color") && ((Object)x.shader).name.IndexOf("UI", StringComparison.OrdinalIgnoreCase) < 0));
					if (Object.op_Implicit((Object)(object)val2))
					{
						val = val2.shader;
					}
				}
				if (!Object.op_Implicit((Object)(object)val))
				{
					throw new InvalidOperationException("A material shader is unavailable.");
				}
				Color color = default(Color);
				for (int num2 = 0; num2 < num; num2++)
				{
					string text = String(binaryReader);
					Mesh val3 = new Mesh
					{
						name = "Modernization/" + text,
						hideFlags = (HideFlags)52
					};
					Vector3[] array = Vectors3(binaryReader);
					if (array.Length > 65535)
					{
						val3.indexFormat = (IndexFormat)1;
					}
					val3.vertices = array;
					Vector3[] array2 = Vectors3(binaryReader);
					if (array2.Length != 0)
					{
						val3.normals = array2;
					}
					Vector2[] array3 = Vectors2(binaryReader);
					if (array3.Length != 0)
					{
						val3.uv = array3;
					}
					int num3 = (val3.subMeshCount = Count(binaryReader, 1000));
					for (int num5 = 0; num5 < num3; num5++)
					{
						int[] array4 = new int[Count(binaryReader)];
						for (int num6 = 0; num6 < array4.Length; num6++)
						{
							array4[num6] = binaryReader.ReadInt32();
						}
						val3.SetTriangles(array4, num5, false);
					}
					val3.RecalculateBounds();
					if (array2.Length == 0)
					{
						val3.RecalculateNormals();
					}
					Material[] array5 = (Material[])(object)new Material[Count(binaryReader, 1000)];
					for (int num7 = 0; num7 < array5.Length; num7++)
					{
						((Color)(ref color))..ctor(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
						Material val4 = new Material(val)
						{
							name = "Modernization/" + text + "/" + num7,
							hideFlags = (HideFlags)52,
							color = color
						};
						val4.SetFloat("_Glossiness", 0.12f);
						array5[num7] = val4;
					}
					Models.Add(text, new Model
					{
						Mesh = val3,
						Materials = array5.Take(RuntimeCompatibilityRules.MaterialSlots(num3, array5.Length)).ToArray()
					});
				}
				num = Count(binaryReader, 1000);
				for (int num8 = 0; num8 < num; num8++)
				{
					string text2 = String(binaryReader);
					byte[] array6 = Bytes(binaryReader, Count(binaryReader));
					Texture2D val5 = new Texture2D(2, 2, (TextureFormat)4, false)
					{
						name = "Modernization/" + text2,
						hideFlags = (HideFlags)52,
						filterMode = (FilterMode)0
					};
					if (!ImageConversion.LoadImage(val5, array6))
					{
						throw new InvalidDataException("Invalid texture: " + text2);
					}
					Textures.Add(text2, val5);
				}
				num = Count(binaryReader, 1000);
				for (int num9 = 0; num9 < num; num9++)
				{
					string text3 = String(binaryReader);
					SoundEffectInstance val6 = new SoundEffectInstance
					{
						soundRef = text3
					};
					val6.volume = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
					val6.pitch = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
					val6.maxInstances = binaryReader.ReadInt32();
					val6.cooldown = binaryReader.ReadSingle();
					val6.spatialBlend = binaryReader.ReadSingle();
					val6.reverbZoneMix = binaryReader.ReadSingle();
					val6.minDistance = binaryReader.ReadSingle();
					val6.maxDistance = binaryReader.ReadSingle();
					val6.lengthInMeasures = binaryReader.ReadInt32();
					val6.transitionMeasures = new int[Count(binaryReader, 1000)];
					for (int num10 = 0; num10 < val6.transitionMeasures.Length; num10++)
					{
						val6.transitionMeasures[num10] = binaryReader.ReadInt32();
					}
					val6.clipTypes = (SoundEffectVariations[])(object)new SoundEffectVariations[Count(binaryReader, 1000)];
					for (int num11 = 0; num11 < val6.clipTypes.Length; num11++)
					{
						SoundEffectVariations val7 = new SoundEffectVariations
						{
							materialType = (MaterialType)binaryReader.ReadInt32(),
							clips = (AudioClip[])(object)new AudioClip[Count(binaryReader, 1000)]
						};
						for (int num12 = 0; num12 < val7.clips.Length; num12++)
						{
							string text4 = String(binaryReader);
							int num13 = binaryReader.ReadInt32();
							int num14 = binaryReader.ReadInt32();
							int num15 = binaryReader.ReadInt32();
							int num16 = Count(binaryReader);
							if (num16 != num14 * num15 || num13 <= 0 || num15 < 1 || num15 > 2)
							{
								throw new InvalidDataException("Invalid audio: " + text4);
							}
							float[] array7 = new float[num16];
							byte[] array8 = Bytes(binaryReader, checked(num16 * 4));
							Buffer.BlockCopy(array8, 0, array7, 0, array8.Length);
							AudioClip val8 = AudioClip.Create("Modernization/" + text4, num14, num15, num13, false);
							((Object)val8).hideFlags = (HideFlags)52;
							if (!val8.SetData(array7, 0))
							{
								throw new InvalidDataException("Could not create audio: " + text4);
							}
							val7.clips[num12] = val8;
						}
						val6.clipTypes[num11] = val7;
					}
					Sounds.Add(text3, val6);
				}
				if (Encoding.ASCII.GetString(Bytes(binaryReader, 8)) != "ENDPORT1" || binaryReader.BaseStream.ReadByte() != -1)
				{
					throw new InvalidDataException("Incomplete resource package.");
				}
			}
			Alias(Sounds, "artileryfire", "artillery");
			loaded = true;
			PortPlugin.Info("Original resources ready: " + Models.Count + " models, " + Textures.Count + " images, 29 sound sets.");
		}

		private static void Alias<T>(Dictionary<string, T> items, string name, string original)
		{
			if (!items.ContainsKey(name) && items.ContainsKey(original))
			{
				items.Add(name, items[original]);
			}
		}

		private static string Key(string path)
		{
			int num = path.LastIndexOf('/');
			if (num >= 0)
			{
				return path.Substring(num + 1);
			}
			return path;
		}

		public static Sprite GetSprite(string path, int? size = null, FilterMode filter = (FilterMode)0)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			EnsureLoaded();
			string text = Key(path);
			if (Sprites.TryGetValue(text, out var value))
			{
				return value;
			}
			if (!Textures.TryGetValue(text, out var value2))
			{
				throw new KeyNotFoundException("Original icon missing: " + path);
			}
			((Texture)value2).filterMode = filter;
			value = Sprite.Create(value2, new Rect(0f, 0f, (float)((Texture)value2).width, (float)((Texture)value2).height), new Vector2(0.5f, 0.5f), (float)(size ?? 100));
			((Object)value).name = "Modernization/" + text;
			((Object)value).hideFlags = (HideFlags)52;
			Sprites.Add(text, value);
			return value;
		}

		private static GameObject Attach(Transform parent, string path, float scale, Vector3? rotation, Vector3? position, string name)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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_0047: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: 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_00bc: 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_00df: Expected O, but got Unknown
			EnsureLoaded();
			string key = Key(path);
			if (!Models.TryGetValue(key, out var value))
			{
				throw new KeyNotFoundException("Original mesh missing: " + path);
			}
			GameObject val = new GameObject(name);
			val.AddComponent<PortVisual>();
			val.transform.SetParent(parent, false);
			val.transform.localPosition = (Vector3)(((??)position) ?? Vector3.zero);
			val.transform.localRotation = Quaternion.Euler((Vector3)(((??)rotation) ?? Vector3.zero));
			val.transform.localScale = Vector3.one * scale;
			val.AddComponent<MeshFilter>().sharedMesh = value.Mesh;
			((Renderer)val.AddComponent<MeshRenderer>()).sharedMaterials = value.Materials;
			val.layer = ((Component)parent).gameObject.layer;
			return val;
		}

		public static void SetMeshRenderers(GameObject go, bool enabled)
		{
			Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (!Object.op_Implicit((Object)(object)((Component)val).GetComponentInParent<PortVisual>()))
				{
					val.enabled = enabled;
				}
			}
		}

		public static void SetStaticMesh(GameObject go, string path, float scale, Vector3? rotation = null, Vector3? position = null, string name = "PinaCollada Mesh Object")
		{
			SetMeshRenderers(go, enabled: false);
			Attach(go.transform, path, scale, rotation, position, name);
		}

		public static void SetStaticMeshToBone(GameObject go, string path, float scale, Vector3? rotation, Vector3? position, string name, GearType gear, EquipType equip)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Invalid comparison between Unknown and I4
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Invalid comparison between Unknown and I4
			SetMeshRenderers(go, enabled: false);
			UnitRig val = go.GetComponentInParent<UnitRig>();
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = ((Component)go.transform.root).GetComponentInChildren<UnitRig>();
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				throw new InvalidOperationException("Native unit rig missing: " + path);
			}
			Transform val2 = default(Transform);
			Transform val3 = default(Transform);
			val.GetBonesForEquip(gear, ref val2, ref val3);
			if (!Object.op_Implicit((Object)(object)val2) && !Object.op_Implicit((Object)(object)val3))
			{
				throw new InvalidOperationException("Native attachment bone missing: " + path);
			}
			if (Object.op_Implicit((Object)(object)val2) && ((int)equip == 0 || (int)equip == 1 || !Object.op_Implicit((Object)(object)val3)))
			{
				Attach(val2, path, scale, rotation, position, name);
			}
			if (Object.op_Implicit((Object)(object)val3) && (Object)(object)val3 != (Object)(object)val2 && ((int)equip == 0 || (int)equip == 2))
			{
				Attach(val3, path, scale, rotation, position, name);
			}
		}
	}
	internal sealed class DiscordInviteController : MonoBehaviour
	{
		private static bool shownThisLaunch;

		private ConfigEntry<bool> setting;

		private DiscordInviteWindow window;

		private float stableSince = -1f;

		private float nextPoll;

		internal void Init(ConfigEntry<bool> entry)
		{
			setting = entry;
			setting.SettingChanged += OnSettingChanged;
			((Behaviour)this).enabled = setting.Value && !shownThisLaunch;
		}

		private void Update()
		{
			if (Time.unscaledTime < nextPoll)
			{
				return;
			}
			nextPoll = Time.unscaledTime + 0.25f;
			MainMenuButtons val = Object.FindObjectOfType<MainMenuButtons>();
			bool flag = Object.op_Implicit((Object)(object)val) && ((Behaviour)val).isActiveAndEnabled;
			if (!flag)
			{
				stableSince = -1f;
				return;
			}
			if (stableSince < 0f)
			{
				stableSince = Time.unscaledTime;
			}
			if (!InviteSchedule.ShouldShow(setting.Value, shownThisLaunch, flag, Time.unscaledTime - stableSince))
			{
				return;
			}
			shownThisLaunch = true;
			((Behaviour)this).enabled = false;
			try
			{
				window = DiscordInviteWindow.Create();
			}
			catch (Exception exception)
			{
				PortPlugin.Report("Discord invitation window", exception);
			}
		}

		private void OnSettingChanged(object sender, EventArgs args)
		{
			if (!setting.Value && Object.op_Implicit((Object)(object)window))
			{
				window.Close();
			}
			((Behaviour)this).enabled = setting.Value && !shownThisLaunch;
		}

		private void OnDestroy()
		{
			if (setting != null)
			{
				setting.SettingChanged -= OnSettingChanged;
			}
			if (Object.op_Implicit((Object)(object)window))
			{
				window.Close();
			}
		}
	}
	internal sealed class DiscordInviteWindow : MonoBehaviour
	{
		private static readonly FieldInfo Locale = AccessTools.Field(typeof(Localizer), "m_locale");

		private static Sprite rounded;

		private RectTransform panel;

		private TextMeshProUGUI title;

		private TextMeshProUGUI body;

		private TextMeshProUGUI hint;

		private TextMeshProUGUI joinLabel;

		private TextMeshProUGUI closeLabel;

		private bool registered;

		private bool closing;

		private int reportedLanguage = -1;

		internal static DiscordInviteWindow Create()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Modernization Discord invite", new Type[1] { typeof(RectTransform) });
			Canvas obj = val.AddComponent<Canvas>();
			obj.renderMode = (RenderMode)0;
			obj.sortingOrder = 30000;
			CanvasScaler obj2 = val.AddComponent<CanvasScaler>();
			obj2.uiScaleMode = (ScaleMode)1;
			obj2.referenceResolution = new Vector2(1920f, 1080f);
			obj2.matchWidthOrHeight = 0.5f;
			val.AddComponent<GraphicRaycaster>();
			if (!Object.op_Implicit((Object)(object)EventSystem.current))
			{
				GameObject val2 = new GameObject("Modernization invite events");
				val2.transform.SetParent(val.transform, false);
				val2.AddComponent<EventSystem>();
				val2.AddComponent<StandaloneInputModule>();
			}
			DiscordInviteWindow discordInviteWindow = val.AddComponent<DiscordInviteWindow>();
			discordInviteWindow.Build();
			return discordInviteWindow;
		}

		private static Sprite Rounded()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)rounded))
			{
				return rounded;
			}
			Texture2D val = new Texture2D(32, 32, (TextureFormat)4, false)
			{
				name = "Modernization/invite-rounded",
				hideFlags = (HideFlags)52,
				wrapMode = (TextureWrapMode)1
			};
			Color32[] array = (Color32[])(object)new Color32[1024];
			for (int i = 0; i < 32; i++)
			{
				for (int j = 0; j < 32; j++)
				{
					float num = Mathf.Max(new float[3]
					{
						(float)(10 - j) - 0.5f,
						(float)j + 0.5f - 22f,
						0f
					});
					float num2 = Mathf.Max(new float[3]
					{
						(float)(10 - i) - 0.5f,
						(float)i + 0.5f - 22f,
						0f
					});
					float num3 = Mathf.Clamp01(10f - Mathf.Sqrt(num * num + num2 * num2) + 0.5f);
					array[i * 32 + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)(num3 * 255f));
				}
			}
			val.SetPixels32(array);
			val.Apply(false, true);
			rounded = Sprite.Create(val, new Rect(0f, 0f, 32f, 32f), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4(10f, 10f, 10f, 10f));
			((Object)rounded).name = "Modernization/invite-rounded";
			((Object)rounded).hideFlags = (HideFlags)52;
			return rounded;
		}

		private static RectTransform Child(string name, Transform parent)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			return (RectTransform)val.transform;
		}

		private static Image Box(RectTransform target, Color colour)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			Image obj = ((Component)target).gameObject.AddComponent<Image>();
			obj.sprite = Rounded();
			obj.type = (Type)1;
			((Graphic)obj).color = colour;
			return obj;
		}

		private static TextMeshProUGUI Label(string name, Transform parent, float size, Color colour, FontStyles style)
		{
			//IL_0019: 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)
			TextMeshProUGUI obj = ((Component)Child(name, parent)).gameObject.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj).fontSize = size;
			((Graphic)obj).color = colour;
			((TMP_Text)obj).fontStyle = style;
			((TMP_Text)obj).alignment = (TextAlignmentOptions)514;
			((TMP_Text)obj).enableWordWrapping = true;
			((TMP_Text)obj).overflowMode = (TextOverflowModes)0;
			((Graphic)obj).raycastTarget = false;
			return obj;
		}

		private Button MakeButton(string name, Transform parent, Color colour, out TextMeshProUGUI label, Action onClick)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Expected O, but got Unknown
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Expected O, but got Unknown
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = Child(name, parent);
			Image targetGraphic = Box(val, colour);
			Button obj = ((Component)val).gameObject.AddComponent<Button>();
			((Selectable)obj).targetGraphic = (Graphic)(object)targetGraphic;
			ColorBlock colors = ((Selectable)obj).colors;
			((ColorBlock)(ref colors)).normalColor = new Color(0.9f, 0.9f, 0.9f, 1f);
			((ColorBlock)(ref colors)).highlightedColor = Color.white;
			((ColorBlock)(ref colors)).pressedColor = new Color(0.75f, 0.75f, 0.75f, 1f);
			((ColorBlock)(ref colors)).selectedColor = ((ColorBlock)(ref colors)).highlightedColor;
			((ColorBlock)(ref colors)).fadeDuration = 0.08f;
			((Selectable)obj).colors = colors;
			((UnityEvent)obj.onClick).AddListener((UnityAction)delegate
			{
				onClick();
			});
			VerticalLayoutGroup obj2 = ((Component)val).gameObject.AddComponent<VerticalLayoutGroup>();
			((LayoutGroup)obj2).padding = new RectOffset(12, 12, 9, 9);
			((LayoutGroup)obj2).childAlignment = (TextAnchor)4;
			bool childControlWidth = (((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true);
			((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = childControlWidth;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false;
			LayoutElement obj3 = ((Component)val).gameObject.AddComponent<LayoutElement>();
			obj3.minHeight = 44f;
			obj3.preferredWidth = 10f;
			obj3.flexibleWidth = 1f;
			label = Label("Label", (Transform)(object)val, 19f, Color.white, (FontStyles)1);
			return obj;
		}

		private void Build()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: 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_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Expected O, but got Unknown
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Expected O, but got Unknown
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0351: Unknown result type (might be due to invalid IL or missing references)
			//IL_0353: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_035b: Unknown result type (might be due to invalid IL or missing references)
			//IL_036d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0382: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03db: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_041b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0429: Unknown result type (might be due to invalid IL or missing references)
			//IL_0434: Unknown result type (might be due to invalid IL or missing references)
			//IL_0446: Unknown result type (might be due to invalid IL or missing references)
			//IL_0450: Expected O, but got Unknown
			//IL_048a: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0500: Expected O, but got Unknown
			panel = Child("Panel", ((Component)this).transform);
			RectTransform obj = panel;
			RectTransform obj2 = panel;
			RectTransform obj3 = panel;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(1f, 0f);
			obj3.pivot = val;
			Vector2 anchorMin = (obj2.anchorMax = val);
			obj.anchorMin = anchorMin;
			panel.anchoredPosition = new Vector2(-40f, 40f);
			panel.sizeDelta = new Vector2(440f, 180f);
			Box(panel, new Color(0.11f, 0.12f, 0.14f, 0.96f));
			Outline obj4 = ((Component)panel).gameObject.AddComponent<Outline>();
			((Shadow)obj4).effectColor = new Color(1f, 1f, 1f, 0.12f);
			((Shadow)obj4).effectDistance = new Vector2(1.5f, -1.5f);
			Shadow obj5 = ((Component)panel).gameObject.AddComponent<Shadow>();
			obj5.effectColor = new Color(0f, 0f, 0f, 0.45f);
			obj5.effectDistance = new Vector2(0f, -5f);
			VerticalLayoutGroup obj6 = ((Component)panel).gameObject.AddComponent<VerticalLayoutGroup>();
			((LayoutGroup)obj6).padding = new RectOffset(22, 22, 18, 18);
			((HorizontalOrVerticalLayoutGroup)obj6).spacing = 8f;
			((LayoutGroup)obj6).childAlignment = (TextAnchor)1;
			bool childControlWidth = (((HorizontalOrVerticalLayoutGroup)obj6).childControlHeight = true);
			((HorizontalOrVerticalLayoutGroup)obj6).childControlWidth = childControlWidth;
			((HorizontalOrVerticalLayoutGroup)obj6).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj6).childForceExpandHeight = false;
			ContentSizeFitter obj7 = ((Component)panel).gameObject.AddComponent<ContentSizeFitter>();
			obj7.verticalFit = (FitMode)2;
			obj7.horizontalFit = (FitMode)0;
			title = Label("Title", (Transform)(object)panel, 26f, Color.white, (FontStyles)1);
			((TMP_Text)title).margin = new Vector4(34f, 0f, 34f, 0f);
			body = Label("Description", (Transform)(object)panel, 19f, new Color(0.86f, 0.88f, 0.92f, 1f), (FontStyles)0);
			hint = Label("Hint", (Transform)(object)panel, 14f, new Color(0.62f, 0.65f, 0.7f, 1f), (FontStyles)0);
			RectTransform val3 = Child("Buttons", (Transform)(object)panel);
			HorizontalLayoutGroup obj8 = ((Component)val3).gameObject.AddComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj8).spacing = 12f;
			((LayoutGroup)obj8).padding = new RectOffset(0, 0, 6, 0);
			childControlWidth = (((HorizontalOrVerticalLayoutGroup)obj8).childControlHeight = true);
			((HorizontalOrVerticalLayoutGroup)obj8).childControlWidth = childControlWidth;
			((HorizontalOrVerticalLayoutGroup)obj8).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj8).childForceExpandHeight = true;
			MakeButton("Join Discord", (Transform)(object)val3, Color32.op_Implicit(new Color32((byte)88, (byte)101, (byte)242, byte.MaxValue)), out joinLabel, OpenDiscord);
			MakeButton("Close", (Transform)(object)val3, new Color(0.25f, 0.27f, 0.31f, 1f), out closeLabel, Close);
			RectTransform val4 = Child("Close cross", (Transform)(object)panel);
			((Component)val4).gameObject.AddComponent<LayoutElement>().ignoreLayout = true;
			((Vector2)(ref val))..ctor(1f, 1f);
			val4.pivot = val;
			anchorMin = (val4.anchorMax = val);
			val4.anchorMin = anchorMin;
			val4.anchoredPosition = new Vector2(-10f, -10f);
			val4.sizeDelta = new Vector2(32f, 32f);
			Image targetGraphic = Box(val4, new Color(1f, 1f, 1f, 0f));
			Button obj9 = ((Component)val4).gameObject.AddComponent<Button>();
			((Selectable)obj9).targetGraphic = (Graphic)(object)targetGraphic;
			ColorBlock colors = ((Selectable)obj9).colors;
			((ColorBlock)(ref colors)).normalColor = new Color(1f, 1f, 1f, 0f);
			((ColorBlock)(ref colors)).highlightedColor = new Color(1f, 1f, 1f, 0.14f);
			((ColorBlock)(ref colors)).pressedColor = new Color(1f, 1f, 1f, 0.24f);
			((ColorBlock)(ref colors)).selectedColor = ((ColorBlock)(ref colors)).normalColor;
			((Selectable)obj9).colors = colors;
			((UnityEvent)obj9.onClick).AddListener(new UnityAction(Close));
			float[] array = new float[2] { 45f, -45f };
			foreach (float num in array)
			{
				RectTransform obj10 = Child("Line", (Transform)(object)val4);
				obj10.sizeDelta = new Vector2(18f, 2.5f);
				((Transform)obj10).localRotation = Quaternion.Euler(0f, 0f, num);
				Image obj11 = ((Component)obj10).gameObject.AddComponent<Image>();
				((Graphic)obj11).color = new Color(0.8f, 0.82f, 0.86f, 1f);
				((Graphic)obj11).raycastTarget = false;
			}
			Refresh();
			Localizer.RegisterCallback((MonoBehaviour)(object)this, new UpdateText(Refresh));
			registered = true;
		}

		private static TMP_FontAsset FallbackFont()
		{
			TMP_FontAsset defaultFontAsset = TMP_Settings.defaultFontAsset;
			if (!Object.op_Implicit((Object)(object)defaultFontAsset))
			{
				return Resources.FindObjectsOfTypeAll<TMP_FontAsset>().FirstOrDefault();
			}
			return defaultFontAsset;
		}

		private void Refresh()
		{
			if (closing || !Object.op_Implicit((Object)(object)panel))
			{
				return;
			}
			int num = ((!(Locale == null)) ? Convert.ToInt32(Locale.GetValue(null)) : 0);
			TMP_FontAsset font = Localizer.GetCurrentFont(0);
			if (!Object.op_Implicit((Object)(object)font))
			{
				font = FallbackFont();
			}
			Func<char, bool> fontHas = (char c) => !Object.op_Implicit((Object)(object)font) || font.HasCharacter(c, true, true);
			InviteText inviteText = InviteText.For(num).FitToFont(fontHas);
			if (inviteText == null)
			{
				inviteText = InviteText.English.FitToFont(fontHas) ?? InviteText.English;
				if (reportedLanguage != num)
				{
					reportedLanguage = num;
					PortPlugin.Warn("Discord invitation: the game font lacks glyphs for language " + num + "; English text is shown.");
				}
			}
			TextMeshProUGUI[] array = (TextMeshProUGUI[])(object)new TextMeshProUGUI[5] { title, body, hint, joinLabel, closeLabel };
			foreach (TextMeshProUGUI val in array)
			{
				if (Object.op_Implicit((Object)(object)font))
				{
					((TMP_Text)val).font = font;
				}
				((TMP_Text)val).isRightToLeftText = inviteText.RightToLeft;
			}
			((TMP_Text)title).text = inviteText.Title;
			((TMP_Text)body).text = inviteText.Body;
			((TMP_Text)hint).text = inviteText.Hint;
			((TMP_Text)joinLabel).text = inviteText.Join;
			((TMP_Text)closeLabel).text = inviteText.Close;
			LayoutRebuilder.ForceRebuildLayoutImmediate(panel);
		}

		private void Update()
		{
			if (Input.GetKeyDown((KeyCode)27))
			{
				Close();
			}
		}

		private void OpenDiscord()
		{
			Application.OpenURL("https://discord.gg/8AtrRHEPAT");
			Close();
		}

		internal void Close()
		{
			if (!closing)
			{
				closing = true;
				EventSystem current = EventSystem.current;
				if (Object.op_Implicit((Object)(object)current) && Object.op_Implicit((Object)(object)current.currentSelectedGameObject) && current.currentSelectedGameObject.transform.IsChildOf(((Component)this).transform))
				{
					current.SetSelectedGameObject((GameObject)null);
				}
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		private void OnDestroy()
		{
			closing = true;
			if (registered)
			{
				Localizer.UnregisterCallback((MonoBehaviour)(object)this);
				registered = false;
			}
		}
	}
	internal sealed class InviteText
	{
		internal const string Url = "https://discord.gg/8AtrRHEPAT";

		internal readonly string Code;

		internal readonly string Language;

		internal readonly string Title;

		internal readonly string Body;

		internal readonly string Join;

		internal readonly string Close;

		internal readonly string Hint;

		internal readonly bool RightToLeft;

		internal static readonly InviteText English = new InviteText("LANG_EN_US", "English", "Join us on Discord!", "Mod news, updates and discussions — on our server.", "Join Discord", "Close", "Joining is optional · Esc to close");

		internal static readonly InviteText[] ByLanguage = new InviteText[9]
		{
			English,
			new InviteText("LANG_FR", "Français", "Rejoins-nous sur Discord\u00a0!", "Actus du mod, mises à jour et discussions — sur notre serveur.", "Rejoindre Discord", "Fermer", "Facultatif · Échap pour fermer"),
			new InviteText("LANG_IT", "Italiano", "Unisciti a noi su Discord!", "Novità della mod, aggiornamenti e discussioni — sul nostro server.", "Entra su Discord", "Chiudi", "Facoltativo · Esc per chiudere"),
			new InviteText("LANG_DE", "Deutsch", "Komm auf unseren Discord!", "Mod-News, Updates und Diskussionen — auf unserem Server.", "Discord beitreten", "Schließen", "Beitritt freiwillig · Esc zum Schließen"),
			new InviteText("LANG_ES", "Español", "¡Únete a nuestro Discord!", "Noticias del mod, actualizaciones y debates — en nuestro servidor.", "Unirse a Discord", "Cerrar", "Es opcional · Esc para cerrar"),
			new InviteText("LANG_PT_BR", "Português (Brasil)", "Entre no nosso Discord!", "Novidades do mod, atualizações e discussões — no nosso servidor.", "Entrar no Discord", "Fechar", "É opcional · Esc para fechar"),
			new InviteText("LANG_RU", "Русский", "Присоединяйся в Discord!", "Новости мода, обновления и обсуждения — на нашем сервере.", "Зайти в Discord", "Закрыть", "Вступать необязательно · Esc — закрыть"),
			new InviteText("LANG_CH", "简体中文", "加入我们的 Discord!", "模组新闻、更新和讨论——尽在我们的服务器。", "加入 Discord", "关闭", "加入为可选 · 按 Esc 关闭"),
			new InviteText("LANG_JA", "日本語", "Discordに参加しよう!", "MODのニュース、アップデート、ディスカッションは私たちのサーバーで。", "Discordに参加", "閉じる", "参加は任意です · Escで閉じる")
		};

		private static readonly Dictionary<char, string> Substitutes = new Dictionary<char, string>
		{
			{ '—', "-" },
			{ '–', "-" },
			{ '·', "|" },
			{ '\u00a0', " " },
			{ '!', "!" },
			{ '、', ", " },
			{ '。', ". " },
			{ '¡', "" }
		};

		internal string[] Fields => new string[5] { Title, Body, Join, Close, Hint };

		private InviteText(string code, string language, string title, string body, string join, string close, string hint, bool rightToLeft = false)
		{
			Code = code;
			Language = language;
			Title = title;
			Body = body;
			Join = join;
			Close = close;
			Hint = hint;
			RightToLeft = rightToLeft;
		}

		internal static InviteText For(int language)
		{
			if (language < 0 || language >= ByLanguage.Length)
			{
				return English;
			}
			InviteText inviteText = ByLanguage[language];
			string[] fields = inviteText.Fields;
			for (int i = 0; i < fields.Length; i++)
			{
				if (string.IsNullOrEmpty(fields[i]))
				{
					return English;
				}
			}
			return inviteText;
		}

		internal static string FitToFont(string text, Func<char, bool> fontHas)
		{
			if (string.IsNullOrEmpty(text))
			{
				return text;
			}
			StringBuilder stringBuilder = new StringBuilder(text.Length);
			foreach (char c in text)
			{
				if (c == ' ' || c == '\n' || fontHas(c))
				{
					stringBuilder.Append(c);
					continue;
				}
				if (Substitutes.TryGetValue(c, out var value))
				{
					bool flag = true;
					string text2 = value;
					foreach (char c2 in text2)
					{
						if (c2 != ' ' && !fontHas(c2))
						{
							flag = false;
						}
					}
					if (flag)
					{
						stringBuilder.Append(value);
						continue;
					}
				}
				return null;
			}
			return stringBuilder.ToString().Trim();
		}

		internal InviteText FitToFont(Func<char, bool> fontHas)
		{
			string[] array = new string[5];
			string[] fields = Fields;
			for (int i = 0; i < fields.Length; i++)
			{
				array[i] = FitToFont(fields[i], fontHas);
				if (array[i] == null)
				{
					return null;
				}
			}
			return new InviteText(Code, Language, array[0], array[1], array[2], array[3], array[4], RightToLeft);
		}
	}
	internal static class InviteSchedule
	{
		internal const float MenuSettleSeconds = 1.5f;

		internal static bool ShouldShow(bool enabledInConfig, bool shownThisLaunch, bool mainMenuActive, float menuStableSeconds)
		{
			if (enabledInConfig && !shownThisLaunch && mainMenuActive)
			{
				return menuStableSeconds >= 1.5f;
			}
			return false;
		}
	}
	internal static class NativeTemplateAdapter
	{
		internal static void Apply()
		{
			TemplateCompatibility.Apply(ULoader.VDic, Valid, Replacement, delegate(TemplateAlias rule, object value)
			{
				GameObject val = (GameObject)((value is GameObject) ? value : null);
				PortPlugin.Info(Object.op_Implicit((Object)(object)val) ? ("Template resolved: " + rule.Category + "/" + rule.LegacyName + " -> " + ((Object)val).name) : ("Optional footwear omitted: " + rule.Category + "/" + rule.LegacyName));
			});
		}

		private static bool Valid(TemplateAlias rule, object value)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Invalid comparison between Unknown and I4
			GameObject val = (GameObject)((value is GameObject) ? value : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return false;
			}
			switch (rule.Role)
			{
			case TemplateRole.Ranged:
				return Object.op_Implicit((Object)(object)val.GetComponent<RangeWeapon>());
			case TemplateRole.Melee:
				return Object.op_Implicit((Object)(object)val.GetComponent<MeleeWeapon>());
			case TemplateRole.Shoes:
			{
				CharacterItem componentInChildren2 = val.GetComponentInChildren<CharacterItem>(true);
				if (Object.op_Implicit((Object)(object)componentInChildren2))
				{
					return (int)componentInChildren2.GearT == 9;
				}
				return false;
			}
			case TemplateRole.Shield:
			{
				if (!Object.op_Implicit((Object)(object)val.GetComponent<Weapon>()) || Object.op_Implicit((Object)(object)val.GetComponent<RangeWeapon>()))
				{
					return false;
				}
				if (Object.op_Implicit((Object)(object)val.GetComponentInChildren<ShieldWobble>(true)))
				{
					return true;
				}
				WeaponItem componentInChildren = val.GetComponentInChildren<WeaponItem>(true);
				if (!HasShieldName(((Object)val).name))
				{
					if (Object.op_Implicit((Object)(object)componentInChildren) && ((CharacterItem)componentInChildren).Entity != null)
					{
						return HasShieldName(((CharacterItem)componentInChildren).Entity.Name);
					}
					return false;
				}
				return true;
			}
			default:
				return false;
			}
		}

		private static bool HasShieldName(string name)
		{
			if (name != null)
			{
				return name.IndexOf("shield", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		private static object Replacement(TemplateAlias rule)
		{
			string[] units = rule.Units;
			for (int i = 0; i < units.Length; i++)
			{
				UnitBlueprint unit = NativeUnit(units[i]);
				GameObject val = FromUnit(rule, unit);
				if (Object.op_Implicit((Object)(object)val))
				{
					return val;
				}
			}
			if (rule.Role == TemplateRole.Shoes)
			{
				return (from p in ULoader.Native.GetCharacterProps()
					where Valid(rule, p)
					select p).OrderBy<GameObject, string>((GameObject p) => ((Object)p).name, StringComparer.Ordinal).FirstOrDefault();
			}
			if (rule.LegacyName == "Thrower_WheelBarrowApple")
			{
				units = new string[2] { "SpearThrower", "Musketeer" };
				foreach (string name in units)
				{
					GameObject val2 = FromUnit(rule, NativeUnit(name));
					if (Object.op_Implicit((Object)(object)val2))
					{
						return val2;
					}
				}
			}
			return null;
		}

		private static UnitBlueprint NativeUnit(string name)
		{
			if (!TemplateCompatibility.TryFind(ULoader.VDic["blueprints"], name, out var value))
			{
				return null;
			}
			return (UnitBlueprint)((value is UnitBlueprint) ? value : null);
		}

		private static GameObject FromUnit(TemplateAlias rule, UnitBlueprint unit)
		{
			if (!Object.op_Implicit((Object)(object)unit))
			{
				return null;
			}
			if (rule.Role == TemplateRole.Shoes)
			{
				return ((IEnumerable<GameObject>)(((object)unit.m_props) ?? ((object)new GameObject[0]))).FirstOrDefault((Func<GameObject, bool>)((GameObject p) => Valid(rule, p)));
			}
			return Weapons(unit, new HashSet<UnitBlueprint>()).FirstOrDefault((Func<GameObject, bool>)((GameObject p) => Valid(rule, p)));
		}

		private static IEnumerable<GameObject> Weapons(UnitBlueprint unit, HashSet<UnitBlueprint> seen)
		{
			if (!Object.op_Implicit((Object)(object)unit) || !seen.Add(unit))
			{
				yield break;
			}
			if (Object.op_Implicit((Object)(object)unit.LeftWeapon))
			{
				yield return unit.LeftWeapon;
			}
			if (Object.op_Implicit((Object)(object)unit.RightWeapon))
			{
				yield return unit.RightWeapon;
			}
			UnitBlueprint[] array = (UnitBlueprint[])(((object)unit.UnitRiders) ?? ((object)new UnitBlueprint[0]));
			foreach (UnitBlueprint unit2 in array)
			{
				foreach (GameObject item in Weapons(unit2, seen))
				{
					yield return item;
				}
			}
			if (!Object.op_Implicit((Object)(object)unit.UnitBase))
			{
				yield break;
			}
			Weapon[] componentsInChildren = unit.UnitBase.GetComponentsInChildren<Weapon>(true);
			foreach (Weapon val in componentsInChildren)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					yield return ((Component)val).gameObject;
				}
			}
		}
	}
	[AttributeUsage(AttributeTargets.Class)]
	internal sealed class DiagnosticPatchAttribute : Attribute
	{
	}
	internal static class PortDiagnostics
	{
		private static readonly DiagnosticGate gate = new DiagnosticGate(200);

		internal static string Name(Unit unit)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)unit))
			{
				return "?";
			}
			UnitBlueprint unitBlueprint = unit.unitBlueprint;
			if (Object.op_Implicit((Object)(object)unitBlueprint) && unitBlueprint.Entity != null && ULoader.Names.TryGetValue(unitBlueprint.Entity.GUID, out var value))
			{
				return value;
			}
			return ((Object)unit).name;
		}

		internal static void Info(Unit unit, string issue, string detail)
		{
			string text = gate.Admit(Name(unit), issue, detail);
			if (text != null)
			{
				PortPlugin.Info(text);
			}
		}

		internal static void Warn(Unit unit, string issue, string detail)
		{
			string text = gate.Admit(Name(unit), issue, detail);
			if (text != null)
			{
				PortPlugin.Warn(text);
			}
		}

		internal static void Failure(string method, IEnumerable<Unit> units, Exception exception)
		{
			if (exception == null)
			{
				return;
			}
			try
			{
				Unit[] array = units.Where(PortRuntime.Owns).Distinct().ToArray();
				if (array.Length != 0)
				{
					string unit = string.Join(", ", array.Select(Name).ToArray());
					string text = gate.Admit(unit, method + " threw " + exception.GetType().Name, exception.ToString());
					if (text != null)
					{
						PortPlugin.Error(text);
					}
				}
			}
			catch (Exception exception2)
			{
				PortPlugin.Report("Diagnostics for " + method, exception2);
			}
		}

		internal static Unit Of(Component component)
		{
			if (!Object.op_Implicit((Object)(object)component))
			{
				return null;
			}
			return component.GetComponentInParent<Unit>();
		}

		internal static Unit Of(DataHandler data)
		{
			if (!Object.op_Implicit((Object)(object)data))
			{
				return null;
			}
			return data.unit;
		}
	}
	[HarmonyPatch(typeof(BlockMove), "GetAcceptableRigs")]
	internal static class BlockMoveAnchorHook
	{
		private static readonly FieldInfo Handler = AccessTools.Field(typeof(BlockMove), "weaponHandler");

		private static readonly FieldInfo Rigs = AccessTools.Field(typeof(BlockMove), "acceptableRigs");

		private static bool Prefix(BlockMove __instance)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			Unit val = PortDiagnostics.Of((Component)(object)__instance);
			if (!PortRuntime.Owns(val))
			{
				return true;
			}
			WeaponHandler val2 = (WeaponHandler)Handler.GetValue(__instance);
			List<Rigidbody> list = (List<Rigidbody>)Rigs.GetValue(__instance);
			bool meleeRight = Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.rightWeapon) && Object.op_Implicit((Object)(object)((Component)val2.rightWeapon).GetComponent<MeleeWeapon>());
			bool meleeLeft = Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.leftWeapon) && Object.op_Implicit((Object)(object)((Component)val2.leftWeapon).GetComponent<MeleeWeapon>());
			bool hasLeftHand = Object.op_Implicit((Object)(object)((Component)((Component)__instance).transform.root).GetComponentInChildren<HandLeft>());
			if (!RuntimeCompatibilityRules.NeedsBlockAnchor(Object.op_Implicit((Object)(object)val2), meleeRight, meleeLeft, list?.Count ?? 0, hasLeftHand))
			{
				return true;
			}
			Rigidbody val3 = (Object.op_Implicit((Object)(object)val.data) ? val.data.mainRig : null);
			if (!Object.op_Implicit((Object)(object)val3) || list == null)
			{
				PortDiagnostics.Warn(val, "BlockMove has neither hands nor a main rigidbody", ((Object)__instance).name);
				return true;
			}
			list.Add(val3);
			PortDiagnostics.Info(val, "BlockMove anchored to the vehicle body because its base has no hands", ((Object)__instance).name);
			return false;
		}
	}
	[HarmonyPatch]
	[DiagnosticPatch]
	internal static class MountFailureReport
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(Mount), "Update", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(Mount), "EnterMount", (Type[])null, (Type[])null);
		}

		private static void Finalizer(Exception __exception, Mount __instance, MethodBase __originalMethod)
		{
			if (__exception != null)
			{
				List<Unit> units = new List<Unit>
				{
					PortDiagnostics.Of((Component)(object)__instance),
					PortDiagnostics.Of(Object.op_Implicit((Object)(object)__instance) ? __instance.OtherData : null)
				};
				PortDiagnostics.Failure("Mount." + __originalMethod.Name, units, __exception);
			}
		}
	}
	[HarmonyPatch(typeof(DodgeMove), "DoMove", new Type[]
	{
		typeof(Rigidbody),
		typeof(Rigidbody),
		typeof(DataHandler)
	})]
	[DiagnosticPatch]
	internal static class DodgeMoveFailureReport
	{
		private static void Finalizer(Exception __exception, DodgeMove __instance)
		{
			if (__exception != null)
			{
				PortDiagnostics.Failure("DodgeMove.DoMove", (IEnumerable<Unit>)(object)new Unit[1] { PortDiagnostics.Of((Component)(object)__instance) }, __exception);
			}
		}
	}
	[HarmonyPatch]
	[DiagnosticPatch]
	internal static class DodgeSequenceFailureReport
	{
		private static FieldInfo owner;

		private static MethodBase TargetMethod()
		{
			Type type = typeof(DodgeMove).GetNestedTypes(BindingFlags.NonPublic).Single((Type t) => t.Name.StartsWith("<DoMoveSequence>"));
			owner = AccessTools.Field(type, "<>4__this");
			return AccessTools.Method(type, "MoveNext", (Type[])null, (Type[])null);
		}

		private static void Finalizer(Exception __exception, object __instance)
		{
			if (__exception != null)
			{
				DodgeMove component = (DodgeMove)((owner == null) ? null : /*isinst with value type is only supported in some contexts*/);
				PortDiagnostics.Failure("DodgeMove.DoMoveSequence", (IEnumerable<Unit>)(object)new Unit[1] { PortDiagnostics.Of((Component)(object)component) }, __exception);
			}
		}
	}
	[HarmonyPatch(typeof(BlockMove), "ProjectileBlock")]
	[DiagnosticPatch]
	internal static class BlockMoveFailureReport
	{
		private static void Finalizer(Exception __exception, BlockMove __instance)
		{
			if (__exception != null)
			{
				PortDiagnostics.Failure("BlockMove.ProjectileBlock", (IEnumerable<Unit>)(object)new Unit[1] { PortDiagnostics.Of((Component)(object)__instance) }, __exception);
			}
		}
	}
	[HarmonyPatch(typeof(UnitPlacementBrush), "RemoveUnitInternal")]
	[DiagnosticPatch]
	internal static class RemoveUnitFailureReport
	{
		private static void Finalizer(Exception __exception, Unit unit)
		{
			if (__exception == null)
			{
				return;
			}
			List<Unit> list = new List<Unit> { unit };
			RiderHolder val = (Object.op_Implicit((Object)(object)unit) ? ((Component)unit).GetComponent<RiderHolder>() : null);
			if (Object.op_Implicit((Object)(object)val) && val.riders != null)
			{
				foreach (GameObject rider in val.riders)
				{
					if (Object.op_Implicit((Object)(object)rider))
					{
						list.Add(rider.GetComponent<Unit>());
					}
				}
			}
			PortDiagnostics.Failure("UnitPlacement.RemoveUnitInternal", list, __exception);
		}
	}
	[HarmonyPatch]
	[DiagnosticPatch]
	internal static class CharacterMovementFailureReport
	{
		private static bool Prepare()
		{
			return AccessTools.TypeByName("CharacterMovement") != null;
		}

		private static IEnumerable<MethodBase> TargetMethods()
		{
			Type type = AccessTools.TypeByName("CharacterMovement");
			string[] array = new string[3] { "Start", "Update", "FixedUpdate" };
			foreach (string text in array)
			{
				MethodInfo methodInfo = AccessTools.Method(type, text, (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					yield return methodInfo;
				}
			}
		}

		private static void Finalizer(Exception __exception, MonoBehaviour __instance, MethodBase __originalMethod)
		{
			if (__exception != null)
			{
				PortDiagnostics.Failure("CharacterMovement." + __originalMethod.Name, (IEnumerable<Unit>)(object)new Unit[1] { PortDiagnostics.Of((Component)(object)__instance) }, __exception);
			}
		}
	}
	[BepInPlugin("modernization.port.bepinex", "modernization port by lil zalupa", "0.9.4")]
	public sealed class PortPlugin : BaseUnityPlugin
	{
		public const string Guid = "modernization.port.bepinex";

		public const string Version = "0.9.4";

		internal static readonly UManager Manager = new UManager();

		private static ManualLogSource log;

		internal static bool Ready;

		private bool attempted;

		private float nextCheck;

		private static readonly HashSet<string> errors = new HashSet<string>();

		internal static void Info(string message)
		{
			if (log != null)
			{
				log.LogInfo((object)message);
			}
		}

		internal static void Warn(string message)
		{
			if (log != null)
			{
				log.LogWarning((object)message);
			}
		}

		internal static void Error(string message)
		{
			if (log != null)
			{
				log.LogError((object)message);
			}
		}

		internal static void Report(string context, Exception exception)
		{
			if (log != null && errors.Add(context))
			{
				log.LogError((object)(context + ": " + exception));
			}
		}

		private void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			log = ((BaseUnityPlugin)this).Logger;
			Harmony val = new Harmony("modernization.port.bepinex");
			Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(typeof(PortPlugin).Assembly);
			foreach (Type type in typesFromAssembly)
			{
				if (!type.IsDefined(typeof(HarmonyPatch), inherit: false))
				{
					continue;
				}
				try
				{
					val.CreateClassProcessor(type).Patch();
				}
				catch (Exception exception)
				{
					if (type.IsDefined(typeof(DiagnosticPatchAttribute), inherit: false))
					{
						Report("Diagnostic hook " + type.Name + " unavailable", exception);
						continue;
					}
					attempted = true;
					Report("Could not install native API hook " + type.Name, exception);
				}
			}
			if (!attempted)
			{
				Info("modernization port by lil zalupa 0.9.4 loaded; creator: lilzalupa; waiting for native content.");
			}
			ConfigEntry<bool> entry = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowDiscordInvite", true, "Show a small Discord invitation once per game launch, after the main menu is ready. Set to false to never show it.");
			((Component)this).gameObject.AddComponent<DiscordInviteController>().Init(entry);
		}

		private void Update()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Expected O, but got Unknown
			if (attempted || Time.realtimeSinceStartup < nextCheck)
			{
				return;
			}
			nextCheck = Time.realtimeSinceStartup + 1f;
			ContentDatabase val = (ContentDatabase)AccessTools.Field(typeof(ContentDatabase), "m_instance").GetValue(null);
			if (val == null || val.LandfallContentDatabase == null || !val.LandfallContentDatabase.GetUnitBlueprints().Any() || !val.LandfallContentDatabase.GetFactions().Any((Faction x) => Object.op_Implicit((Object)(object)x) && x.m_displayFaction))
			{
				return;
			}
			SoundPlayer service = ServiceLocator.GetService<SoundPlayer>();
			if (!Object.op_Implicit((Object)(object)service) || !Object.op_Implicit((Object)(object)service.soundBank))
			{
				return;
			}
			attempted = true;
			try
			{
				PinaCollada.EnsureLoaded();
				ULoader.Prepare(val);
				LegacyTemplates.Validate();
				Info("Native weapon/base/turning templates ready; registering Modernization factions.");
				Manager.Init(null);
				foreach (UnitBlueprint createdUnit in ULoader.CreatedUnits)
				{
					Manager.EditBlueprint(createdUnit, ULoader.MDic["Modernization"], null);
					if (createdUnit.m_props == null)
					{
						createdUnit.m_props = (GameObject[])(object)new GameObject[0];
					}
					PropItemData[] propData = createdUnit.m_propData;
					createdUnit.m_propData = (PropItemData[])(object)new PropItemData[createdUnit.m_props.Length];
					for (int num = 0; num < createdUnit.m_propData.Length; num++)
					{
						createdUnit.m_propData[num] = (PropItemData)((propData != null && num < propData.Length && propData[num] != null) ? ((object)propData[num]) : ((object)new PropItemData()));
					}
					createdUnit.rightProjectile = null;
					createdUnit.leftProjectile = null;
					VehicleCompatibility.PrepareBlueprint(createdUnit);
				}
				PortRuntime.RegisterSounds(service.soundBank);
				Ready = true;
				Info("MODERNIZATION READY: " + ULoader.CreatedUnits.Count + " blueprints, " + ULoader.CreatedFactions.Count + " factions; game MVID=" + typeof(UnitBlueprint).Assembly.ManifestModule.ModuleVersionId);
			}
			catch (Exception exception)
			{
				Ready = false;
				ULoader.Rollback();
				Report("Modernization initialization rolled back", exception);
			}
		}
	}
	[HarmonyPatch(typeof(UnitBlueprint), "SetWeapon")]
	internal static class WeaponHook
	{
		private static readonly HashSet<string> gateReports = new HashSet<string>();

		private static void Prefix(Unit unit)
		{
			if (PortRuntime.Owns(unit))
			{
				PortRuntime.SetIdentity(unit);
			}
		}

		private unsafe static void Postfix(Weapon __result, Unit unit, Team team, HandType handType)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			if (!PortPlugin.Ready || !Object.op_Implicit((Object)(object)__result) || !PortRuntime.Owns(unit))
			{
				return;
			}
			string text = Name(unit) + "/" + ((object)(*(HandType*)(&handType))/*cast due to .constrained prefix*/).ToString();
			RangeWeapon val = null;
			try
			{
				val = ((Component)__result).GetComponentInChildren<RangeWeapon>();
				PortPlugin.Manager.EditWeapons(((Component)__result).gameObject, handType, team, unit, ((Component)__result).GetComponentInChildren<MeleeWeapon>(), val, null);
			}
			catch (Exception exception)
			{
				PortPlugin.Report("Weapon setup for " + text, exception);
			}
			try
			{
				PortRuntime.IsolateProjectile(val, unit);
				PortRuntime.RestoreVisuals(((Component)__result).gameObject);
			}
			catch (Exception exception2)
			{
				PortPlugin.Report("Visual setup for " + text, exception2);
			}
			try
			{
				RefreshUnitAttackGate(unit, __result);
			}
			catch (Exception exception3)
			{
				PortPlugin.Report("Attack gate refresh for " + text, exception3);
			}
		}

		private static string Name(Unit unit)
		{
			if (!Object.op_Implicit((Object)(object)unit) || !Object.op_Implicit((Object)(object)unit.unitBlueprint) || unit.unitBlueprint.Entity == null)
			{
				return "?";
			}
			return unit.unitBlueprint.Entity.Name;
		}

		private static void RefreshUnitAttackGate(Unit unit, Weapon weapon)
		{
			if (!Object.op_Implicit((Object)(object)unit))
			{
				return;
			}
			WeaponHandler val = unit.WeaponHandler;
			if (!Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)weapon))
			{
				val = ((Component)weapon).GetComponentInParent<WeaponHandler>();
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			float num = float.PositiveInfinity;
			if (Object.op_Implicit((Object)(object)val.rightWeapon))
			{
				num = Mathf.Min(num, val.rightWeapon.GetLowestAttackTimeOfWeapons());
			}
			if (Object.op_Implicit((Object)(object)val.leftWeapon))
			{
				num = Mathf.Min(num, val.leftWeapon.GetLowestAttackTimeOfWeapons());
			}
			if (!float.IsNaN(num) && !float.IsInfinity(num) && !(num >= unit.lowestAttackTimeOfWeapons))
			{
				unit.lowestAttackTimeOfWeapons = num;
				string text = ((Object.op_Implicit((Object)(object)unit.unitBlueprint) && unit.unitBlueprint.Entity != null) ? unit.unitBlueprint.Entity.Name : "?");
				if (gateReports.Add(text + "|" + num))
				{
					PortPlugin.Info("[rate-gate] " + text + ": lowestAttackTimeOfWeapons -> " + num);
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class SpawnHook
	{
		private static MethodBase TargetMethod()
		{
			return typeof(UnitBlueprint).GetMethods().Single((MethodInfo x) => x.Name == "Spawn" && x.GetParameters().Length == 9);
		}

		private static void Postfix(UnitBlueprint __instance, Unit unitToSpawn)
		{
			if (!PortPlugin.Ready || !PortRuntime.Owns(__instance) || !Object.op_Implicit((Object)(object)unitToSpawn))
			{
				return;
			}
			PortRuntime.SetIdentity(unitToSpawn);
			PortUnitState portUnitState = PortRuntime.Ensure<PortUnitState>(((Component)unitToSpawn).gameObject);
			if (portUnitState.SpawnConfigured)
			{
				return;
			}
			portUnitState.SpawnConfigured = true;
			try
			{
				PortPlugin.Manager.CodeOnSpawn(unitToSpawn, null);
				GameObject[] moves = (GameObject[])(((object)__instance.objectsToSpawnAsChildren) ?? ((object)new GameObject[0]));
				Transform[] source = ((IEnumerable)((Component)unitToSpawn).transform).Cast<Transform>().ToArray();
				HashSet<Transform> used = new HashSet<Transform>();
				int i;
				for (i = 0; i < moves.Length; i++)
				{
					if (Object.op_Implicit((Object)(object)moves[i]))
					{
						Transform val = ((IEnumerable<Transform>)source).FirstOrDefault((Func<Transform, bool>)((Transform x) => !used.Contains(x) && ((Object)x).name.Replace("(Clone)", "") == ((Object)moves[i]).name));
						if (Object.op_Implicit((Object)(object)val))
						{
							used.Add(val);
							PortPlugin.Manager.EditCombatMoves(((Component)val).gameObject, i, unitToSpawn, null);
						}
					}
				}
				PortRuntime.RestoreVisuals(((Component)unitToSpawn).gameObject);
			}
			catch (Exception exception)
			{
				PortPlugin.Report("Abilities for " + __instance.Entity.Name, exception);
			}
		}
	}
	[HarmonyPatch(typeof(UnitRig), "SpawnProps")]
	internal static class PropsHook
	{
		private static void Prefix(UnitRig __instance)
		{
			Unit componentInParent = ((Component)__instance).GetComponentInParent<Unit>();
			if (PortPlugin.Ready && PortRuntime.Owns(componentInParent))
			{
				PortRuntime.SetIdentity(componentInParent);
				PortRuntime.Ensure<PortUnitState>(((Component)componentInParent).gameObject).NextPropIndex = 0;
			}
		}
	}
	[HarmonyPatch(typeof(UnitRig), "SpawnProp")]
	internal static class PropHook
	{
		private static void Prefix(UnitRig __instance, CharacterItem prop, out int __state)
		{
			__state = -1;
			Unit componentInParent = ((Component)__instance).GetComponentInParent<Unit>();
			if (!PortPlugin.Ready || !PortRuntime.Owns(componentInParent) || !Object.op_Implicit((Object)(object)prop))
			{
				return;
			}
			PortUnitState portUnitState = PortRuntime.Ensure<PortUnitState>(((Component)componentInParent).gameObject);
			GameObject[] props = componentInParent.unitBlueprint.m_props;
			int num = portUnitState.NextPropIndex;
			while (props != null && num < props.Length)
			{
				if ((Object)(object)props[num] == (Object)(object)((Component)prop).gameObject)
				{
					__state = num;
					portUnitState.NextPropIndex = num + 1;
					break;
				}
				num++;
			}
		}

		private static void Postfix(UnitRig __instance, GameObject __result, PropItemData propData, int __state)
		{
			if (__state < 0 || !Object.op_Implicit((Object)(object)__result))
			{
				return;
			}
			Unit componentInParent = ((Component)__instance).GetComponentInParent<Unit>();
			try
			{
				PortPlugin.Manager.EditClothes(__result, __result.GetComponent<CharacterItem>(), propData, componentInParent, __state, null);
				PortRuntime.RestoreVisuals(__result);
			}
			catch (Exception exception)
			{
				PortPlugin.Report("Clothing for " + componentInParent.unitBlueprint.Entity.Name + "/" + __state, exception);
			}
		}
	}
	[HarmonyPatch(typeof(Unit), "Start")]
	internal static class UnitStartHook
	{
		private static void Prefix(Unit __instance)
		{
			if (PortRuntime.Owns(__instance))
			{
				PortRuntime.SetIdentity(__instance);
			}
		}

		private static void Postfix(Unit __instance)
		{
			if (!PortPlugin.Ready || !PortRuntime.Owns(__instance))
			{
				return;
			}
			PortUnitState portUnitState = PortRuntime.Ensure<PortUnitState>(((Component)__instance).gameObject);
			if (portUnitState.AfterSpawnConfigured)
			{
				return;
			}
			portUnitState.AfterSpawnConfigured = true;
			try
			{
				PortPlugin.Manager.CodeAfterSpawn(__instance, null);
				PortRuntime.RestoreVisuals(((Component)__instance).gameObject);
			}
			catch (Exception exception)
			{
				PortPlugin.Report("After-spawn setup for " + __instance.unitBlueprint.Entity.Name, exception);
			}
		}
	}
	[HarmonyPatch(typeof(RangeWeapon), "SetProjectileStats")]
	internal static class ProjectileHook
	{
		private static void Prefix(RangeWeapon __instance, GameObject spawnedObject)
		{
			if (!PortPlugin.Ready || !Object.op_Implicit((Object)(object)spawnedObject))
			{
				return;
			}
			Unit val = (Object.op_Implicit((Object)(object)((Weapon)__instance).connectedData) ? ((Weapon)__instance).connectedData.unit : ((Component)__instance).GetComponentInParent<Unit>());
			if (!PortRuntime.Owns(val) || Object.op_Implicit((Object)(object)spawnedObject.GetComponent<PortProjectile>()))
			{
				return;
			}
			spawnedObject.AddComponent<PortProjectile>();
			try
			{
				PortPlugin.Manager.EditProjectiles(spawnedObject, spawnedObject.GetComponentInChildren<ProjectileHit>(), val, null);
				PortRuntime.RestoreVisuals(spawnedObject);
			}
			catch (Exception exception)
			{
				PortPlugin.Report("Projectile setup for " + val.unitBlueprint.Entity.Name, exception);
			}
		}
	}
	[HarmonyPatch(typeof(RangeWeapon), "Start")]
	internal static class MagazineStartHook
	{
		private static void Postfix(RangeWeapon __instance)
		{
			LegacyMagazine component = ((Component)__instance).GetComponent<LegacyMagazine>();
			if (Object.op_Implicit((Object)(object)component) && component.StartingAmmo >= 0)
			{
				AccessTools.Field(typeof(RangeWeapon), "ammo").SetValue(__instance, component.StartingAmmo);
			}
		}
	}
	[HarmonyPatch(typeof(RangeWeapon), "Reload")]
	internal static class ReloadHook
	{
		private static void Prefix(RangeWeapon __instance)
		{
			PortRuntime.PlayReload(((Component)__instance).GetComponent<LegacyMagazine>());
		}
	}
	public sealed class LegacyBlueprint
	{
		private readonly UnitBlueprint unit;

		public UnitBlueprint[] Riders
		{
			get
			{
				return unit.UnitRiders;
			}
			set
			{
				unit.SetNoCustomRider();
				AccessTools.Field(typeof(UnitBlueprint), "Riders").SetValue(unit, value);
			}
		}

		public string VocalRef
		{
			get
			{
				return unit.VocalRef;
			}
			set
			{
				if (!Object.op_Implicit((Object)(object)unit.voiceBundle))
				{
					unit.voiceBundle = ScriptableObject.CreateInstance<VoiceBundle>();
				}
				unit.voiceBundle.VocalRef = value;
				AccessTools.Field(typeof(UnitBlueprint), "vocalPathData").SetValue(unit, null);
			}
		}

		private LegacyBlueprint(UnitBlueprint value)
		{
			unit = value;
		}

		public static LegacyBlueprint For(UnitBlueprint value)
		{
			return new LegacyBlueprint(value);
		}
	}
	public sealed class LegacyMagazine : MonoBehaviour
	{
		internal int StartingAmmo = -1;

		public string ReloadSound;

		private RangeWeapon Weapon => ((Component)this).GetComponent<RangeWeapon>();

		public int InitialAmmo
		{
			get
			{
				return StartingAmmo;
			}
			set
			{
				StartingAmmo = value;
			}
		}

		public int Capacity
		{
			get
			{
				return Weapon.magSize;
			}
			set
			{
				Weapon.magSize = Math.Max(1, value);
			}
		}

		public float ReloadSeconds
		{
			get
			{
				return Weapon.reloadTime;
			}
			set
			{
				Weapon.reloadTime = Math.Max(0f, value);
			}
		}

		public float ShotInterval
		{
			get
			{
				return ((Weapon)Weapon).internalCooldown;
			}
			set
			{
				((Weapon)Weapon).internalCooldown = Math.Max(0.001f, value);
			}
		}

		public static LegacyMagazine For(RangeWeapon weapon)
		{
			if (!Object.op_Implicit((Object)(object)weapon))
			{
				throw new ArgumentNullException("weapon");
			}
			return PortRuntime.Ensure<LegacyMagazine>(((Component)weapon).gameObject);
		}
	}
	public static class LegacyTemplates
	{
		private static UnitBlueprint Named(params string[] names)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			foreach (string key in names)
			{
				if (ULoader.VDic["blueprints"].TryGetValue(key, out var value))
				{
					return (UnitBlueprint)value;
				}
			}
			throw new MissingMemberException("Required vanilla blueprint: " + string.Join(" / ", names));
		}

		public static UnitBlueprint Blueprint(int legacyIndex)
		{
			return (UnitBlueprint)(legacyIndex switch
			{
				17 => Named("Healer"), 
				81 => Named("Valkyrie", "ValkyrieUnit"), 
				_ => throw new NotSupportedException("Unmapped legacy blueprint " + legacyIndex), 
			});
		}

		public static GameObject Base(int legacyIndex)
		{
			return (GameObject)(legacyIndex switch
			{
				4 => Named("Wheelbarrow").UnitBase, 
				12 => Named("CavalryKnight").UnitBase, 
				_ => throw new NotSupportedException("Unmapped legacy base " + legacyIndex), 
			});
		}

		public static GameObject Weapon(int legacyIndex)
		{
			UnitBlueprint val = (UnitBlueprint)(legacyIndex switch
			{
				2 => Named("Archer"), 
				14 => Named("Cannon"), 
				44 => Named("Musketeer"), 
				49 => Named("BombThrower", "Bomb Thrower"), 
				50 => Named("BombCannon", "Bomb Cannon"), 
				70 => Named("Musketeer"), 
				_ => throw new NotSupportedException("Unmapped legacy weapon " + legacyIndex), 
			});
			GameObject val2 = val.RightWeapon;
			if (!Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val.UnitBase))
			{
				RangeWeapon componentInChildren = val.UnitBase.GetComponentInChildren<RangeWeapon>(true);
				if (Object.op_Implicit((Object)(object)componentInChildren))
				{
					val2 = ((Component)componentInChildren).gameObject;
				}
			}
			if (!Object.op_Implicit((Object)(object)val2))
			{
				throw new MissingMemberException("Vanilla weapon unavailable: " + val.Entity.Name);
			}
			return val2;
		}

		internal static void Validate()
		{
			int[] array = new int[6] { 2, 14, 44, 49, 50, 70 };
			for (int i = 0; i < array.Length; i++)
			{
				GameObject val = Weapon(array[i]);
				if (!Object.op_Implicit((Object)(object)val.GetComponent<RangeWeapon>()))
				{
					throw new MissingMemberException("Template is not a ranged weapon: " + ((Object)val).name);
				}
			}
			Base(4);
			Base(12);
			Blueprint(17);
			Blueprint(81);
		}
	}
	public sealed class PortUnitState : MonoBehaviour
	{
		internal bool SpawnConfigured;

		internal bool AfterSpawnConfigured;

		internal int NextPropIndex;

		internal readonly List<GameObject> ProjectilePrefabs = new List<GameObject>();

		private void OnDestroy()
		{
			foreach (GameObject projectilePrefab in ProjectilePrefabs)
			{
				if (Object.op_Implicit((Object)(object)projectilePrefab))
				{
					Object.Destroy((Object)(object)projectilePrefab);
				}
			}
		}
	}
	public sealed class PortProjectile : MonoBehaviour
	{
	}
	public static class PortRuntime
	{
		internal static bool Owns(UnitBlueprint blueprint)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)blueprint) && blueprint.Entity != null)
			{
				return ULoader.Names.ContainsKey(blueprint.Entity.GUID);
			}
			return false;
		}

		internal static bool Owns(Unit unit)
		{
			if (Object.op_Implicit((Object)(object)unit))
			{
				return Owns(unit.unitBlueprint);
			}
			return false;
		}

		internal static void SetIdentity(Unit unit)
		{
			if (Owns(unit))
			{
				AccessTools.Field(typeof(Unit), "m_entity").SetValue(unit, unit.unitBlueprint.Entity.ShallowCopy());
			}
		}

		public static T Ensure<T>(GameObject go) where T : Component
		{
			T component = go.GetComponent<T>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return go.AddComponent<T>();
			}
			return component;
		}

		public static void SetFootSound(UnitSounds sounds, string path)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)sounds))
			{
				return;
			}
			if (string.IsNullOrWhiteSpace(path))
			{
				sounds.FootPathData = null;
				return;
			}
			string[] array = path.Split(new char[1] { '/' });
			if (array.Length != 2)
			{
				throw new FormatException("Invalid foot sound: " + path);
			}
			sounds.FootPathData = new AudioPathData(array[0], array[1], 1f, 1f);
		}

		public static void SetConditionalRange(ConditionalEvent move, float range)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Invalid comparison between Unknown and I4
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Invalid comparison between Unknown and I4
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			move.extraRange = 0f;
			ConditionalEventInstance[] array = (ConditionalEventInstance[])(((object)move.events) ?? ((object)new ConditionalEventInstance[0]));
			for (int i = 0; i < array.Length; i++)
			{
				EventCondition[] array2 = (EventCondition[])(((object)array[i].conditions) ?? ((object)new EventCondition[0]));
				foreach (EventCondition val in array2)
				{
					if ((int)val.conditionType == 1 && (int)val.valueType == 1)
					{
						val.value = range;
						val.rangeType = (RangeType)0;
					}
					if ((int)val.conditionType == 0)
					{
						val.onlyCountWhenUnitInRange = false;
					}
				}
			}
		}

		public static GameObject[] SpawnNative(UnitBlueprint blueprint, Vector3 position, Quaternion rotation, Team team)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			return blueprint.Spawn(position, rotation, team, 1f, (UnitPoolInfo?)null);
		}

		internal static void RestoreVisuals(GameObject go)
		{
			PortVisual[] componentsInChildren = go.GetComponentsInChildren<PortVisual>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Renderer[] componentsInChildren2 = ((Component)componentsInChildren[i]).GetComponentsInChildren<Renderer>(true);
				for (int j = 0; j < componentsInChildren2.Length; j++)
				{
					componentsInChildren2[j].enabled = true;
				}
			}
		}

		internal static void IsolateProjectile(RangeWeapon weapon, Unit owner)
		{
			if (!Object.op_Implicit((Object)(object)weapon) || !Object.op_Implicit((Object)(object)weapon.ObjectToSpawn))
			{
				return;
			}
			GameObject objectToSpawn = weapon.ObjectToSpawn;
			if (Object.op_Implicit((Object)(object)objectToSpawn.GetComponent<PooledProjectile>()))
			{
				GameObject val = UPool.MyPool.ClonePrivate(objectToSpawn);
				PooledProjectile[] componentsInChildren = val.GetComponentsInChildren<PooledProjectile>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
				}
				PortRuntime.Ensure<PortUnitState>(((Component)owner).gameObject).ProjectilePrefabs.Add(val);
				weapon.ObjectToSpawn = val;
			}
		}

		internal static void RegisterSounds(SoundBank bank)
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: 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_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Expected O, but got Unknown
			List<SoundBankCategory> list = ((IEnumerable<SoundBankCategory>)(((object)bank.Categories) ?? ((object)new SoundBankCategory[0]))).ToList();
			if (list.Any((SoundBankCategory x) => x.categoryName == "Modernization"))
			{
				throw new InvalidOperationException("Another Modernization audio category is already installed.");
			}
			SoundBankCategory val = ((IEnumerable<SoundBankCategory>)list).FirstOrDefault((Func<SoundBankCategory, bool>)((SoundBankCategory x) => x.categoryName.IndexOf("weapon", StringComparison.OrdinalIgnoreCase) >= 0)) ?? list.FirstOrDefault();
			List<SoundEffectInstance> list2 = new List<SoundEffectInstance>();
			foreach (KeyValuePair<string, SoundEffectInstance> sound in PinaCollada.Sounds)
			{
				SoundEffectInstance value = sound.Value;
				SoundEffectInstance val2 = new SoundEffectInstance();
				FieldInfo[] fields = typeof(SoundEffectInstance).GetFields();
				foreach (FieldInfo fieldInfo in fields)
				{
					fieldInfo.SetValue(val2, fieldInfo.GetValue(value));
				}
				val2.soundRef = sound.Key;
				list2.Add(val2);
			}
			list.Add(new SoundBankCategory
			{
				categoryName = "Modernization",
				soundEffects = list2.ToArray(),
				categoryMixerGroup = val?.categoryMixerGroup,
				volumeMultiplier = 1f,
				pitchMultiplier = 1f,
				minDistanceMultiplier = 1f,
				maxDistanceMultiplier = 1f
			});
			bank.Categories = list.ToArray();
		}

		internal static void PlayReload(LegacyMagazine magazine)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)magazine) && !string.IsNullOrEmpty(magazine.ReloadSound))
			{
				SoundPlayer service = ServiceLocator.GetService<SoundPlayer>();
				if (Object.op_Implicit((Object)(object)service))
				{
					service.PlaySoundEffect(magazine.ReloadSound, 1f, ((Component)magazine).transform.position, (MaterialType)0, (Transform)null, 1f);
				}
			}
		}
	}
	internal static class RequiredTemplates
	{
		internal static readonly string[][] Items = new string[49][]
		{
			new string[2] { "blueprints", "Cannon" },
			new string[2] { "blueprints", "CavalryKnight" },
			new string[2] { "blueprints", "Clubber" },
			new string[2] { "blueprints", "Healer" },
			new string[2] { "blueprints", "Musketeer" },
			new string[2] { "blueprints", "Wheelbarrow" },
			new string[2] { "clothes", "Ancient_Belt001" },
			new string[2] { "clothes", "Ancient_Belt004" },
			new string[2] { "clothes", "Ancient_ChestArmor003" },
			new string[2] { "clothes", "Ancient_Helmet004" },
			new string[2] { "clothes", "Ancient_Shirt002" },
			new string[2] { "clothes", "Halloween_Archer_Glove002" },
			new string[2] { "clothes", "Halloween_Archer_Wrist" },
			new string[2] { "clothes", "Medieval_Pants002" },
			new string[2] { "clothes", "NinjaShoes001" },
			new string[2] { "clothes", "Renaissance_HandGuard" },
			new string[2] { "clothes", "Renaissance_Shirt005" },
			new string[2] { "explosions", "E_ExplosionBombCannon" },
			new string[2] { "explosions", "E_ExplosionSamuraiGiant" },
			new string[2] { "moves", "BarrelArmor_ArmLeft" },
			new string[2] { "moves", "BarrelArmor_ArmRight" },
			new string[2] { "moves", "BarrelArmor_ElbowLeft" },
			new string[2] { "moves", "BarrelArmor_ElbowRight" },
			new string[2] { "moves", "BarrelArmor_Head" },
			new string[2] { "moves", "BarrelArmor_Hip" },
			new string[2] { "moves", "BarrelArmor_KneeLeft" },
			new string[2] { "moves", "BarrelArmor_KneeRight" },
			new string[2] { "moves", "BarrelArmor_LegLeft" },
			new string[2] { "moves", "BarrelArmor_LegRight" },
			new string[2] { "moves", "BarrelArmor_Torso" },
			new string[2] { "moves", "BlockShogun" },
			new string[2] { "moves", "CavalryCharge" },
			new string[2] { "moves", "Chukonu_Walk" },
			new string[2] { "moves", "Fencer_Dodge" },
			new string[2] { "moves", "FireBreath" },
			new string[2] { "moves", "FireBreath_Wheelbarrow" },
			new string[2] { "moves", "MinotaurCharge" },
			new string[2] { "moves", "SwordArtParry" },
			new string[2] { "moves", "Wings" },
			new string[2] { "weapons", "BrawlerAxe" },
			new string[2] { "weapons", "Chukonu" },
			new string[2] { "weapons", "FanSpear" },
			new string[2] { "weapons", "Musket" },
			new string[2] { "weapons", "PriestStaff" },
			new string[2] { "weapons", "Shield_Tower" },
			new string[2] { "weapons", "Stick" },
			new string[2] { "weapo