Decompiled source of Dragon Industries ANEXCAL Relations v1.0.1

Dragon Industries - ANEXCAL Relations.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;
using System.Text;
using System.Xml;
using BepInEx;
using BepInEx.Configuration;
using EquinoxsModUtils;
using EquinoxsModUtils.Additions;
using FluffyUnderware.Curvy;
using HarmonyLib;
using UnityEngine;

[assembly: TargetFramework(".NETFramework,Version=v4.0", FrameworkDisplayName = ".NET Framework 4")]
[assembly: CompilationRelaxations(8)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
namespace ReikaKalseki.DIANEXCAL;

public class Config<E>
{
	private readonly string filename;

	private readonly Dictionary<string, float> data = new Dictionary<string, float>();

	private readonly Dictionary<string, string> dataString = new Dictionary<string, string>();

	private readonly Dictionary<E, ConfigEntry> entryCache = new Dictionary<E, ConfigEntry>();

	private readonly Assembly owner;

	private bool loaded = false;

	private readonly Dictionary<string, Func<float, float>> overrides = new Dictionary<string, Func<float, float>>();

	private readonly Dictionary<string, Func<string, string>> overridesString = new Dictionary<string, Func<string, string>>();

	public Config(Assembly owner)
	{
		this.owner = owner;
		filename = owner.GetName().Name + "_Config.xml";
		populateDefaults();
	}

	public void attachOverride(E key, bool val)
	{
		attachOverride(key, val ? 1 : 0);
	}

	public void attachOverride(E key, float val)
	{
		attachOverride(key, (float f) => val);
	}

	public void attachOverride(E key, Func<bool, bool> val)
	{
		attachOverride(key, (float f) => val((double)f > 0.001) ? 1 : 0);
	}

	public void attachOverride(E key, Func<float, float> val)
	{
		string key2 = getKey(key);
		overrides[key2] = val;
	}

	public void attachOverride(E key, Func<string, string> val)
	{
		string key2 = getKey(key);
		overridesString[key2] = val;
	}

	private void populateDefaults()
	{
		foreach (E value in Enum.GetValues(typeof(E)))
		{
			string name = Enum.GetName(typeof(E), value);
			ConfigEntry entry = getEntry(value);
			entry.enumIndex = name;
			data[name] = entry.defaultValue;
		}
	}

	public void load(bool force = false)
	{
		if (loaded && !force)
		{
			return;
		}
		string text = Path.Combine(Path.GetDirectoryName(owner.Location), "Config");
		Directory.CreateDirectory(text);
		string text2 = Path.Combine(text, filename);
		if (File.Exists(text2))
		{
			TTUtil.log("Loading config file at " + text2, owner);
			try
			{
				XmlDocument xmlDocument = new XmlDocument();
				xmlDocument.Load(text2);
				XmlElement xmlElement = (XmlElement)xmlDocument.GetElementsByTagName("Settings")[0];
				HashSet<string> hashSet = new HashSet<string>(data.Keys);
				foreach (XmlNode childNode in xmlElement.ChildNodes)
				{
					if (!(childNode is XmlElement))
					{
						continue;
					}
					string name = childNode.Name;
					try
					{
						XmlElement xmlElement2 = (XmlElement)(childNode as XmlElement).GetElementsByTagName("value")[0];
						E key = (E)Enum.Parse(typeof(E), name);
						ConfigEntry entry = getEntry(key);
						float num = entry.parse(xmlElement2.InnerText);
						float val = num;
						if (!entry.validate(ref val))
						{
							TTUtil.log("Chosen " + name + " value (" + num + ") was out of bounds, clamped to " + val, owner);
						}
						data[name] = val;
						dataString[name] = xmlElement2.InnerText;
						hashSet.Remove(name);
					}
					catch (Exception ex)
					{
						TTUtil.log("Config entry " + name + " failed to load: " + ex.ToString(), owner);
					}
				}
				string text3 = string.Join(";", data.Select((KeyValuePair<string, float> x) => x.Key + "=" + x.Value).ToArray());
				TTUtil.log("Config successfully loaded: " + text3, owner);
				if (hashSet.Count > 0)
				{
					string text4 = string.Join(";", hashSet.ToArray());
					TTUtil.log("Note: " + hashSet.Count + " entries were missing from the config and so stayed the default values.", owner);
					TTUtil.log("Missing keys: " + text4, owner);
					TTUtil.log("Your config will be regenerated (keeping your changes) to add them to the file.", owner);
					File.Delete(text2);
					generateFile(text2, (ConfigEntry e) => getFloat(getEnum(e)));
				}
			}
			catch (Exception ex)
			{
				TTUtil.log("Config failed to load: " + ex.ToString(), owner);
			}
		}
		else
		{
			TTUtil.log("Config file does not exist at " + text2 + "; generating.", owner);
			generateFile(text2, (ConfigEntry e) => e.defaultValue);
		}
		loaded = true;
	}

	private void generateFile(string path, Func<ConfigEntry, float> valGetter)
	{
		try
		{
			XmlDocument xmlDocument = new XmlDocument();
			XmlElement xmlElement = xmlDocument.CreateElement("Settings");
			xmlDocument.AppendChild(xmlElement);
			foreach (E value in Enum.GetValues(typeof(E)))
			{
				try
				{
					createNode(xmlDocument, xmlElement, value, valGetter);
				}
				catch (Exception ex)
				{
					TTUtil.log(string.Concat("Could not generate XML node for ", value, ": ", ex.ToString()), owner);
				}
			}
			xmlDocument.Save(path);
			TTUtil.log("Config successfully generated at " + path, owner);
		}
		catch (Exception ex2)
		{
			TTUtil.log("Config failed to generate: " + ex2.ToString(), owner);
		}
	}

	private void createNode(XmlDocument doc, XmlElement root, E key, Func<ConfigEntry, float> valGetter)
	{
		ConfigEntry entry = getEntry(key);
		XmlElement xmlElement = doc.CreateElement(Enum.GetName(typeof(E), key));
		XmlComment newChild = doc.CreateComment(entry.desc);
		XmlElement xmlElement2 = doc.CreateElement("value");
		float value = valGetter(entry);
		xmlElement2.InnerText = entry.formatValue(value);
		xmlElement.AppendChild(xmlElement2);
		XmlElement xmlElement3 = doc.CreateElement("defaultValue");
		xmlElement3.InnerText = entry.formatValue(entry.defaultValue);
		xmlElement.AppendChild(xmlElement3);
		if (!float.IsNaN(entry.vanillaValue))
		{
			XmlElement xmlElement4 = doc.CreateElement("vanillaValue");
			xmlElement4.InnerText = entry.formatValue(entry.vanillaValue);
			xmlElement.AppendChild(xmlElement4);
		}
		if (entry.type != typeof(bool))
		{
			XmlElement xmlElement5 = doc.CreateElement("minimumValue");
			xmlElement5.InnerText = entry.formatValue(entry.minValue);
			xmlElement.AppendChild(xmlElement5);
			XmlElement xmlElement6 = doc.CreateElement("maximumValue");
			xmlElement6.InnerText = entry.formatValue(entry.maxValue);
			xmlElement.AppendChild(xmlElement6);
		}
		root.AppendChild(newChild);
		root.AppendChild(xmlElement);
	}

	private float getValue(string key)
	{
		float num = (data.ContainsKey(key) ? data[key] : 0f);
		if (overrides.ContainsKey(key))
		{
			num = overrides[key](num);
		}
		return num;
	}

	private string getStringValue(string key)
	{
		string text = (dataString.ContainsKey(key) ? dataString[key] : null);
		if (overridesString.ContainsKey(key))
		{
			text = overridesString[key](text);
		}
		return text;
	}

	public bool getBoolean(E key)
	{
		float @float = getFloat(key);
		return (double)@float > 0.001;
	}

	public int getInt(E key)
	{
		float @float = getFloat(key);
		return (int)Math.Floor(@float);
	}

	public float getFloat(E key)
	{
		return getValue(getKey(key));
	}

	public string getString(E key)
	{
		return getStringValue(getKey(key));
	}

	private string getKey(E key)
	{
		return Enum.GetName(typeof(E), key);
	}

	public ConfigEntry getEntry(E key)
	{
		if (!entryCache.ContainsKey(key))
		{
			entryCache[key] = lookupEntry(key);
		}
		return entryCache[key];
	}

	private ConfigEntry lookupEntry(E key)
	{
		MemberInfo field = typeof(E).GetField(Enum.GetName(typeof(E), key));
		return (ConfigEntry)Attribute.GetCustomAttribute(field, typeof(ConfigEntry));
	}

	private E getEnum(ConfigEntry e)
	{
		if (e.enumIndex == null)
		{
			throw new Exception(string.Concat("Missing index - could not lookup matching enum for ", e, " hash = ", RuntimeHelpers.GetHashCode(e)));
		}
		return (E)Enum.Parse(typeof(E), e.enumIndex);
	}
}
public class ConfigEntry : Attribute
{
	public readonly string desc;

	public readonly Type type;

	public readonly float minValue;

	public readonly float maxValue;

	public readonly float defaultValue;

	public readonly float vanillaValue;

	internal string enumIndex;

	public readonly List<ConfigEntry> children = new List<ConfigEntry>();

	public ConfigEntry(string d, bool flag, bool includeVan = false)
		: this(d, typeof(bool), flag ? 1 : 0, 0f, 1f, includeVan ? 0f : float.NaN)
	{
	}

	public ConfigEntry(string d, Type t, float def, float v)
		: this(d, t, def, float.MinValue, float.MaxValue, v)
	{
	}

	public ConfigEntry(string d, Type t, float def, float min, float max, float v)
	{
		desc = d;
		type = t;
		defaultValue = def;
		minValue = min;
		maxValue = max;
		vanillaValue = v;
	}

	public bool validate(ref float val)
	{
		if (type == typeof(string) || type == typeof(bool))
		{
			return true;
		}
		bool result = true;
		if (val < minValue)
		{
			val = minValue;
			result = false;
		}
		else if (val > maxValue)
		{
			val = maxValue;
			result = false;
		}
		return result;
	}

	public float parse(string text)
	{
		if (type == typeof(string))
		{
			return 0f;
		}
		if (type == typeof(bool))
		{
			return (text.ToLowerInvariant() == "true") ? 1 : 0;
		}
		return float.Parse(text);
	}

	public string formatValue(float value)
	{
		if (type == typeof(bool))
		{
			return (value > 0f).ToString();
		}
		if (type == typeof(int) || type == typeof(uint) || type == typeof(byte) || type == typeof(long) || type == typeof(ulong))
		{
			return ((int)value).ToString();
		}
		return value.ToString("0.00");
	}
}
public class DIConfig
{
	public enum ConfigEntries
	{
		[ConfigEntry("Metal ore smelting/threshing is 1:1 rather than 2:1", false, false)]
		EFFICIENTMETAL
	}
}
[BepInPlugin("ReikaKalseki.DIMod", "Dragon Industries ANEXCAL Relations", "1.0.0")]
public class DIMod : BaseUnityPlugin
{
	public static DIMod instance;

	private static bool definesLoadedFired;

	private static bool techsLoadedFired;

	public static readonly Config<DIConfig.ConfigEntries> config = new Config<DIConfig.ConfigEntries>(TTUtil.diDLL);

	public static bool protectionZonesActive = true;

	public static event Action onRecipesLoaded;

	public static event Action onDefinesLoadedFirstTime;

	public static event Action onTechsLoadedFirstTime;

	public static event Action<int> onTechActivatedEvent;

	public static event Action<int> onTechDeactivatedEvent;

	public DIMod()
	{
		instance = this;
		TTUtil.log("Constructed DI object", TTUtil.diDLL);
	}

	public void Awake()
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Expected O, but got Unknown
		TTUtil.log("Begin Initializing Dragon Industries", TTUtil.diDLL);
		try
		{
			config.load();
			Harmony val = new Harmony("Dragon Industries");
			Harmony.DEBUG = true;
			FileLog.logPath = Path.Combine(Path.GetDirectoryName(TTUtil.diDLL.Location), "harmony-log_" + Path.GetFileName(Assembly.GetExecutingAssembly().Location) + ".txt");
			FileLog.Log("Ran mod register, started harmony (harmony log)");
			TTUtil.log("Ran mod register, started harmony", TTUtil.diDLL);
			try
			{
				val.PatchAll(TTUtil.diDLL);
			}
			catch (Exception ex)
			{
				FileLog.Log("Caught exception when running patchers!");
				FileLog.Log(ex.Message);
				FileLog.Log(ex.StackTrace);
				FileLog.Log(ex.ToString());
			}
			Events.GameDefinesLoaded += onDefinesLoaded;
			Events.TechTreeStateLoaded += onTechsLoaded;
			Events.GameLoaded += delegate
			{
				resyncResearchCoreUse((Predicate<Unlock>)((Unlock u) => false));
			};
		}
		catch (Exception ex2)
		{
			TTUtil.log("Failed to load DI: " + ex2, TTUtil.diDLL);
		}
		TTUtil.log("Finished Initializing Dragon Industries", TTUtil.diDLL);
	}

	private static void onDefinesLoaded()
	{
		if (definesLoadedFired)
		{
			return;
		}
		ResourceInfo resourceInfoByName = Resources.GetResourceInfoByName("Spectral Cube (Colorless) X100", false);
		resourceInfoByName.rawName = "Spectral Cube (Prismatic)";
		resourceInfoByName.rawSprite = TextureManager.createSprite(TextureManager.getTexture(TTUtil.diDLL, "Textures/WhiteCubeT2"));
		resourceInfoByName.description = "Artifact derived from those of local origin. Contains strange energies.";
		if (DIMod.onDefinesLoadedFirstTime != null)
		{
			try
			{
				DIMod.onDefinesLoadedFirstTime();
			}
			catch (Exception ex)
			{
				TTUtil.log("Exception caught when handling one-time defines load: " + ex, TTUtil.diDLL);
			}
		}
		definesLoadedFired = true;
	}

	private static void onTechsLoaded()
	{
		FieldInfo[] fields = typeof(Unlocks).GetFields();
		foreach (FieldInfo fieldInfo in fields)
		{
			string text = (string)fieldInfo.GetValue(null);
			Unlock unlock = TTUtil.getUnlock(text);
			RenderUtil.dumpTexture(TTUtil.diDLL, text, unlock.sprite.texture);
		}
		if (techsLoadedFired)
		{
			return;
		}
		if (DIMod.onTechsLoadedFirstTime != null)
		{
			try
			{
				DIMod.onTechsLoadedFirstTime();
			}
			catch (Exception ex)
			{
				TTUtil.log("Exception caught when handling one-time techs load: " + ex, TTUtil.diDLL);
			}
		}
		techsLoadedFired = true;
	}

	public static void onRecipeDataLoaded()
	{
		TTUtil.log("Recipe data loaded, running hooks", TTUtil.diDLL);
		TTUtil.buildRecipeCache();
		if (config.getBoolean(DIConfig.ConfigEntries.EFFICIENTMETAL))
		{
			doubleRecipe(TTUtil.getSmelterRecipe("Iron Ore"));
			doubleRecipe(TTUtil.getSmelterRecipe("Copper Ore"));
			doubleRecipe(TTUtil.getSmelterRecipe("Gold Ore"));
			doubleRecipe(GameDefines.instance.GetThreshingRecipeForResource(Resources.GetResourceIDByName("Iron Ore", false)));
			doubleRecipe(GameDefines.instance.GetThreshingRecipeForResource(Resources.GetResourceIDByName("Copper Ore", false)));
			doubleRecipe(GameDefines.instance.GetThreshingRecipeForResource(Resources.GetResourceIDByName("Atlantum Ore", false)));
		}
		if (DIMod.onRecipesLoaded != null)
		{
			try
			{
				DIMod.onRecipesLoaded();
			}
			catch (Exception ex)
			{
				TTUtil.log("Exception caught when handling recipe loading: " + ex, TTUtil.diDLL);
			}
		}
	}

	private static void doubleRecipe(SchematicsRecipeData rec)
	{
		if (!((Object)(object)rec == (Object)null))
		{
			TTUtil.log("Doubling yield for recipe " + rec.toDebugString(), TTUtil.diDLL);
			for (int i = 0; i < rec.outputQuantities.Length; i++)
			{
				rec.outputQuantities[i] = rec.outputQuantities[i] * 2;
			}
		}
	}

	public static void initializeAccumulatorSettings(AccumulatorDefinition def)
	{
	}

	public static bool interceptProtection(bool prot)
	{
		return prot && protectionZonesActive;
	}

	public static void setMassScanRange(int r = 0)
	{
		Type typeBySimpleName = InstructionHandlers.getTypeBySimpleName("MassScan.MassScan");
		if (typeBySimpleName == null)
		{
			TTUtil.log("No mass scan DLL found", TTUtil.diDLL);
			return;
		}
		FieldInfo field = typeBySimpleName.GetField("ScanRange", BindingFlags.Static | BindingFlags.NonPublic);
		ConfigEntry<int> val = (ConfigEntry<int>)field.GetValue(null);
		TTUtil.log("Changing mass scan range from " + val.Value + " to " + r);
		val.Value = r;
	}

	public static void onTechActivated(int id)
	{
		if (DIMod.onTechActivatedEvent != null)
		{
			try
			{
				DIMod.onTechActivatedEvent(id);
			}
			catch (Exception ex)
			{
				TTUtil.log("Exception caught when handling tech activation: " + ex, TTUtil.diDLL);
			}
		}
	}

	public static void onTechDeactivated(int id)
	{
		if (DIMod.onTechDeactivatedEvent != null)
		{
			try
			{
				DIMod.onTechDeactivatedEvent(id);
			}
			catch (Exception ex)
			{
				TTUtil.log("Exception caught when handling tech deactivation: " + ex, TTUtil.diDLL);
			}
		}
	}

	public static void setupUpgradeCosts(ref ResourceRequirementData[] arr, ref float nrg, ref Inventory inv, GatedDoorConfiguration cfg, bool valid, EGameModeSettingType resMult = 0, EGameModeSettingType nrgMult = 0)
	{
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)cfg == (Object)null)
		{
			return;
		}
		TTUtil.log("Intercepting upgrade cost setup for " + ((Object)cfg).name, TTUtil.diDLL);
		TTUtil.log("PRE: " + cfg.reqTypes.Select((ResourceInfo res) => res.toDebugString()).toDebugString() + " => " + arr.Select((ResourceRequirementData res) => res.resType.toDebugString()).toDebugString(), TTUtil.diDLL);
		RepairableElevatorInstance.SetResourceRequirements(ref arr, ref nrg, ref inv, cfg, valid, resMult, nrgMult);
		TTUtil.log("POST: " + cfg.reqTypes.Select((ResourceInfo res) => res.toDebugString()).toDebugString() + " => " + arr.Select((ResourceRequirementData res) => res.resType.toDebugString()).toDebugString(), TTUtil.diDLL);
		bool flag = false;
		for (int i = 0; i < cfg.reqTypes.Length; i++)
		{
			bool flag2 = false;
		}
		bool flag3 = false;
		bool flag4 = false;
		if (flag3 || flag4 || flag)
		{
			TTUtil.log("FIXED: " + cfg.reqTypes.Select((ResourceInfo res) => res.toDebugString()).toDebugString() + " => " + arr.Select((ResourceRequirementData res) => res.resType.toDebugString()).toDebugString(), TTUtil.diDLL);
		}
	}

	public static void resyncResearchCoreUse()
	{
		resyncResearchCoreUse((Predicate<Unlock>)((Unlock u) => true));
	}

	public static void resyncResearchCoreUse(CoreType type)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		resyncResearchCoreUse((Predicate<Unlock>)((Unlock u) => (Object)(object)u != (Object)null && u.coresNeeded != null && u.coresNeeded.Count > 0 && u.coresNeeded[0].type == type));
	}

	public static void resyncResearchCoreUse(Predicate<Unlock> log)
	{
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Expected I4, but got Unknown
		//IL_0164: Expected I4, but got Unknown
		//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d7: Expected I4, but got Unknown
		TTUtil.log("Rebuilding core usage counts", TTUtil.diDLL);
		List<int> usedResearchCores = TechTreeState.instance.usedResearchCores;
		TechTreeState.instance.usedResearchCores = new List<int>();
		foreach (CoreType value in Enum.GetValues(typeof(CoreType)))
		{
			TechTreeState.instance.usedResearchCores.Add(0);
		}
		UnlockState[] unlockStates = TechTreeState.instance.unlockStates;
		for (int i = 0; i < unlockStates.Length; i++)
		{
			UnlockState val2 = unlockStates[i];
			if (!val2.exists || !val2.isActive)
			{
				continue;
			}
			if (log(val2.unlockRef))
			{
				TTUtil.log("Handling tech " + val2.unlockRef.toDebugString(), TTUtil.diDLL);
			}
			foreach (RequiredCores item in val2.unlockRef.coresNeeded)
			{
				List<int> usedResearchCores2;
				List<int> list = (usedResearchCores2 = TechTreeState.instance.usedResearchCores);
				CoreType type = item.type;
				int index = (int)type;
				list[(int)type] = usedResearchCores2[index] + item.number;
				if (log(val2.unlockRef))
				{
					TTUtil.log(string.Concat("Adding ", item.number, " ", item.type, " cores, total is now ", TechTreeState.instance.usedResearchCores[(int)item.type]), TTUtil.diDLL);
				}
			}
			if (log(val2.unlockRef))
			{
				TTUtil.log("Total is now " + ((IEnumerable<int>)TechTreeState.instance.usedResearchCores).toDebugString(), TTUtil.diDLL);
			}
		}
		while (TechTreeState.instance.usedResearchCores.Count > usedResearchCores.Count && FHG_Utils.Last<int>(TechTreeState.instance.usedResearchCores) == 0)
		{
			TechTreeState.instance.usedResearchCores.RemoveAt(TechTreeState.instance.usedResearchCores.Count - 1);
		}
		TTUtil.log("Core indices: Purple,Green,Blue,Gold,Lemon,Ultraviolet", TTUtil.diDLL);
		TTUtil.log("Original value: " + ((IEnumerable<int>)usedResearchCores).toDebugString(), TTUtil.diDLL);
		printCoreBudget();
	}

	public static void printCoreBudget()
	{
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Expected I4, but got Unknown
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		TTUtil.log("Total of used cores: " + ((IEnumerable<int>)TechTreeState.instance.usedResearchCores).toDebugString(), TTUtil.diDLL);
		List<int> list = new List<int>();
		List<int> list2 = new List<int>();
		foreach (CoreType value in Enum.GetValues(typeof(CoreType)))
		{
			int num = TechTreeState.instance.NumCoresOfTypePlaced((int)value);
			list.Add(num);
			list2.Add(FHG_Utils.FloorToInt((float)num * TechTreeState.coreEffiencyMultipliers[value]));
		}
		TTUtil.log("Placed cores: " + ((IEnumerable<int>)list).toDebugString(), TTUtil.diDLL);
		TTUtil.log("Spendable cores: " + ((IEnumerable<int>)list2).toDebugString(), TTUtil.diDLL);
		List<int> list3 = new List<int>();
		for (int i = 0; i < list2.Count; i++)
		{
			list3.Add(list2[i] - ((TechTreeState.instance.usedResearchCores.Count > i) ? TechTreeState.instance.usedResearchCores[i] : 0));
		}
		TTUtil.log("Final core budget: " + ((IEnumerable<int>)list3).toDebugString(), TTUtil.diDLL);
	}

	public static void onBuildDrillInspector(DrillInspectorItem gui, ref DrillInstance drill)
	{
	}
}
public interface Unlockable
{
	Unlock unlock { get; }
}
public class CustomTech : NewUnlockDetails, Unlockable
{
	public Action finalFixes;

	private string unlockPositionReferenceTier;

	private string unlockPositionReferenceColumn;

	private string spriteSource;

	private bool spriteFromUnlock;

	public string name => base.displayName;

	public Assembly ownerMod { get; private set; }

	public Unlock unlock { get; private set; }

	public bool isUnlocked => (Object)(object)unlock != (Object)null && TechTreeState.instance.IsUnlockActive(((UniqueIdScriptableObject)unlock).uniqueId);

	public CustomTech(TechCategory cat, string name, string desc, RequiredCores cores)
		: this(cat, name, desc, cores.type, cores.number)
	{
	}//IL_0001: Unknown result type (might be due to invalid IL or missing references)
	//IL_0006: Unknown result type (might be due to invalid IL or missing references)


	public CustomTech(TechCategory cat, string name, string desc, CoreType type, int cores)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		base.category = cat;
		base.coreTypeNeeded = type;
		base.coreCountNeeded = cores;
		base.displayName = name;
		base.description = desc;
		base.requiredTier = (ResearchTier)1;
		base.treePosition = 0;
		ownerMod = TTUtil.tryGetModDLL();
	}

	public CustomTech setPosition(string positionRef)
	{
		return setPosition(positionRef, positionRef);
	}

	public CustomTech setPosition(string tier, string col)
	{
		unlockPositionReferenceTier = tier;
		unlockPositionReferenceColumn = col;
		return this;
	}

	public CustomTech setPosition(ResearchTier tier, TTUtil.TechColumns slot)
	{
		//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)
		base.requiredTier = tier;
		base.treePosition = (int)slot;
		return this;
	}

	public CustomTech setSprite(string name, bool isUnlock = true)
	{
		spriteSource = name;
		spriteFromUnlock = isUnlock;
		return this;
	}

	public CustomTech setDependencies(CustomTech dep1, CustomTech dep2 = null)
	{
		return setDependencies(dep1.name, dep2?.name);
	}

	public CustomTech setDependencies(string dep1, string dep2 = null)
	{
		base.dependencyNames.Clear();
		base.dependencyNames.Add(dep1);
		if (!string.IsNullOrEmpty(dep2))
		{
			base.dependencyNames.Add(dep2);
		}
		TTUtil.log(string.Concat("Setting dependencies for tech ", this, ": ", ((IEnumerable<string>)base.dependencyNames).toDebugString()), ownerMod);
		return this;
	}

	public void register()
	{
		if (string.IsNullOrEmpty(name))
		{
			throw new Exception("Invalid tech with empty name: " + this);
		}
		if (string.IsNullOrEmpty(base.description))
		{
			throw new Exception("Invalid tech with empty description: " + this);
		}
		try
		{
			EMUAdditions.AddNewUnlock((NewUnlockDetails)(object)this, true);
			DIMod.onTechsLoadedFirstTime += delegate
			{
				//IL_010a: 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)
				unlock = TTUtil.getUnlock(base.displayName, throwIfNone: false);
				if ((Object)(object)unlock == (Object)null)
				{
					throw new Exception(string.Concat("Tech ", this, " failed to find its registered counterpart"));
				}
				TTUtil.log("Tech " + name + " injected: " + unlock.toDebugString(), ownerMod);
				if (unlockPositionReferenceTier != null)
				{
					TTUtil.log(string.Concat("Aligning tech ", this, " to unlock '", unlockPositionReferenceTier, "/", unlockPositionReferenceColumn, "'"), ownerMod);
					Unlock val = TTUtil.getUnlock(unlockPositionReferenceTier);
					Unlock val2 = TTUtil.getUnlock(unlockPositionReferenceColumn);
					unlock.treePosition = val2.treePosition;
					unlock.requiredTier = val.requiredTier;
				}
				if (!string.IsNullOrEmpty(spriteSource))
				{
					TTUtil.log(string.Concat("Fetching sprite for tech ", this, " from: '", spriteSource, "' (", spriteFromUnlock, ")"), ownerMod);
					if (spriteFromUnlock)
					{
						Unlock val3 = TTUtil.getUnlock(spriteSource, throwIfNone: false);
						if ((Object)(object)val3 != (Object)null)
						{
							unlock.sprite = val3.sprite;
							if ((Object)(object)val3.sprite == (Object)null)
							{
								TTUtil.log("Target unlock has no sprite either!", ownerMod);
							}
						}
						else
						{
							TTUtil.log("No unlock found by that name, searching for item", ownerMod);
							ResourceInfo resourceInfoByName = Resources.GetResourceInfoByName(spriteSource, false);
							if (!((Object)(object)resourceInfoByName != (Object)null))
							{
								throw new Exception("Source was neither the name of an unlock nor an item");
							}
							unlock.sprite = resourceInfoByName.sprite;
						}
					}
					else
					{
						unlock.sprite = TextureManager.createSprite(TextureManager.getTexture(TTUtil.tryGetModDLL(acceptDI: true), "Textures/" + spriteSource));
					}
					if ((Object)(object)unlock.sprite == (Object)null)
					{
						TTUtil.log("No sprite found!", ownerMod);
					}
				}
				if (finalFixes != null)
				{
					finalFixes();
				}
			};
			TTUtil.log("Registered tech " + this, ownerMod);
		}
		catch (Exception ex)
		{
			TTUtil.log("Failed to register " + this, ownerMod);
			throw ex;
		}
	}

	public void setRecipes(IEnumerable<CustomRecipe> recipes)
	{
		setRecipes(recipes.ToArray());
	}

	public void setRecipes(params CustomRecipe[] recipes)
	{
		Events.TechTreeStateLoaded += delegate
		{
			setRecipes(recipes.Select((CustomRecipe cr) => cr.recipe).ToArray());
		};
		TTUtil.log(string.Concat("Linking tech ", this, " to recipes ", ((IEnumerable<CustomRecipe>)recipes).toDebugString()), ownerMod);
	}

	public void setRecipes(params SchematicsRecipeData[] recipes)
	{
		TTUtil.setUnlockRecipes(name, recipes);
	}

	public sealed override string ToString()
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		return base.displayName + " = " + Enum.GetName(typeof(CoreType), base.coreTypeNeeded) + "x" + base.coreCountNeeded;
	}
}
public class CoreBoostTech : CustomTech
{
	public readonly int effectValue;

	public float currentEffect => (TechTreeState.instance.freeCores > 0 && base.isUnlocked) ? (TTUtil.getCoreClusterCount() * (float)effectValue / 100f) : 0f;

	public CoreBoostTech(int pct, RequiredCores cores, string otherDep = null)
		: this(pct, cores.type, cores.number, otherDep)
	{
	}//IL_0004: Unknown result type (might be due to invalid IL or missing references)


	public CoreBoostTech(int pct, CoreType type, int cores, string otherDep = null)
		: base((TechCategory)5, null, null, type, cores)
	{
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		effectValue = pct;
		setDependencies("Core Boosting", otherDep);
	}

	public CoreBoostTech setText(string label, string stat)
	{
		((NewUnlockDetails)this).displayName = "Core Boost (" + label + ")";
		((NewUnlockDetails)this).description = "Increases " + stat + " by " + effectValue + "% per Core Cluster.";
		return this;
	}
}
public class CustomItem : NewResourceDetails
{
	public ResourceInfo item { get; private set; }

	public int itemID => ((UniqueIdScriptableObject)item).uniqueId;

	public Assembly ownerMod { get; private set; }

	public CustomItem(string name, string desc, string template, string sprite)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		base.name = name;
		base.description = desc;
		base.parentName = template;
		base.craftingMethod = (CraftingMethod)0;
		base.sprite = TextureManager.createSprite(TextureManager.getTexture(TTUtil.tryGetModDLL(acceptDI: true), "Textures/" + sprite));
		base.maxStackCount = 500;
		base.sortPriority = 998;
		ownerMod = TTUtil.tryGetModDLL();
	}

	public void register()
	{
		try
		{
			EMUAdditions.AddNewResource((NewResourceDetails)(object)this, true);
			DIMod.onDefinesLoadedFirstTime += delegate
			{
				onPatched();
			};
			TTUtil.log("Registered item " + this, ownerMod);
		}
		catch (Exception ex)
		{
			TTUtil.log("Failed to register " + this, ownerMod);
			throw ex;
		}
	}

	public void onPatched()
	{
		item = Resources.GetResourceInfoByName(base.name, false);
		if ((Object)(object)item == (Object)null)
		{
			throw new Exception(string.Concat("Item ", this, " failed to find its registered counterpart"));
		}
		TTUtil.log("Item " + base.name + " injected: " + item.toDebugString(), ownerMod);
		item.rawConveyorResourcePrefab = Resources.GetResourceInfoByName(base.parentName, false).rawConveyorResourcePrefab;
	}

	public sealed override string ToString()
	{
		return "Item '" + base.name + "'";
	}
}
public class CustomMachine<T, V> : Unlockable where T : struct, IMachineInstance<T, V> where V : MachineDefinition<T, V>
{
	private readonly V definition;

	private CustomTech tech;

	private CustomRecipe recipe;

	public string name => ((NewResourceDetails)item).name;

	public CustomItem item { get; private set; }

	public Assembly ownerMod { get; private set; }

	public bool isUnlocked => tech.isUnlocked;

	public Unlock unlock => TTUtil.getUnlock(name);

	public CustomMachine(string name, string desc, string sprite, string unlock, string template)
	{
		item = new CustomItem(name, desc, template, sprite);
		((NewResourceDetails)item).craftTierRequired = 0;
		((NewResourceDetails)item).headerTitle = "Logistics";
		((NewResourceDetails)item).subHeaderTitle = "Utility";
		((NewResourceDetails)item).maxStackCount = 50;
		((NewResourceDetails)item).sortPriority = 998;
		((NewResourceDetails)item).unlockName = unlock;
		definition = ScriptableObject.CreateInstance<V>();
		ownerMod = TTUtil.tryGetModDLL();
	}

	public CustomTech createUnlock(TechCategory cat, CoreType type, int cores)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		tech = new CustomTech(cat, name, ((NewResourceDetails)item).description, type, cores);
		((NewUnlockDetails)tech).sprite = ((NewResourceDetails)item).sprite;
		return tech;
	}

	public CustomRecipe addRecipe(int amt = 1)
	{
		//IL_0042: 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)
		recipe = new CustomRecipe(name, (CraftingMethod)0);
		((NewRecipeDetails)recipe).duration = 1f;
		((NewRecipeDetails)recipe).unlockName = "Basic Logistics";
		((NewRecipeDetails)recipe).outputs = new List<RecipeResourceInfo>
		{
			new RecipeResourceInfo
			{
				name = name,
				quantity = amt
			}
		};
		return recipe;
	}

	public void register()
	{
		try
		{
			EMUAdditions.AddNewMachine<T, V>((MachineDefinition<T, V>)definition, (NewResourceDetails)(object)item, true);
			if (recipe != null)
			{
				recipe.register();
				if (tech != null)
				{
					tech.setRecipes(recipe);
					tech.register();
					Events.GameDefinesLoaded += delegate
					{
						item.onPatched();
						item.item.rawSprite = ((NewResourceDetails)item).sprite;
						item.item.unlock = unlock;
					};
					TTUtil.log("Registered machine " + this, ownerMod);
					return;
				}
				throw new Exception(string.Concat("Machine '", this, "' has no tech!"));
			}
			throw new Exception(string.Concat("Machine '", this, "' has no recipe!"));
		}
		catch (Exception ex)
		{
			TTUtil.log("Failed to register " + this, ownerMod);
			throw ex;
		}
	}

	public sealed override string ToString()
	{
		return $"CustomMachine<{typeof(T).Name}, {typeof(V).Name}> {((NewResourceDetails)item).name}";
	}

	public bool isThisMachine(IMachineInstance<T, V> inst)
	{
		return isThisMachine((MachineDefinition<T, V>)inst.myDef);
	}

	public bool isThisMachine(MachineDefinition<T, V> def)
	{
		return ((ResourceInfo)def).displayName == name;
	}
}
public class CustomRecipe : NewRecipeDetails
{
	public Action finalFixes;

	public SchematicsRecipeData recipe { get; private set; }

	public Assembly ownerMod { get; private set; }

	public CustomRecipe(string id, CraftingMethod cm = 0)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		base.GUID = id;
		base.craftingMethod = cm;
		base.duration = 1f;
		base.sortPriority = 10;
		ownerMod = TTUtil.tryGetModDLL();
	}

	public CustomRecipe setInputs(params object[] args)
	{
		TTUtil.setIngredients((NewRecipeDetails)(object)this, args);
		return this;
	}

	public CustomRecipe setOutputs(params object[] args)
	{
		TTUtil.setProducts((NewRecipeDetails)(object)this, args);
		return this;
	}

	public void register()
	{
		try
		{
			EMUAdditions.AddNewRecipe((NewRecipeDetails)(object)this, true);
			DIMod.onRecipesLoaded += delegate
			{
				//IL_006a: 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)
				recipe = lookupRecipe();
				if ((Object)(object)recipe == (Object)null)
				{
					throw new Exception(string.Concat("Recipe ", this, " failed to find registered counterpart"));
				}
				TTUtil.log("Recipe " + base.GUID + " injected: " + recipe.toDebugString(), ownerMod);
				if (!GameDefines.instance.GetPossibleRecipes(base.craftingMethod, 9999, TTUtil.getMaxAllowedInputs(base.craftingMethod), false).Contains(recipe))
				{
					throw new Exception(string.Concat("Recipe ", this, " was not available to its machine"));
				}
				if (finalFixes != null)
				{
					finalFixes();
				}
			};
			TTUtil.log("Registered recipe " + this, ownerMod);
		}
		catch (Exception ex)
		{
			TTUtil.log("Failed to register " + this, ownerMod);
			throw ex;
		}
	}

	private SchematicsRecipeData lookupRecipe()
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Expected I4, but got Unknown
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: 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)
		CraftingMethod craftingMethod = base.craftingMethod;
		return (SchematicsRecipeData)((int)craftingMethod switch
		{
			0 => TTUtil.getRecipesByOutput(base.outputs[0].name)[0], 
			1 => null, 
			2 => GameDefines.instance.GetValidSmelterRecipesForSingle(Resources.GetResourceIDByName(base.ingredients[0].name, false), 9999, 9999, false)[0], 
			3 => GameDefines.instance.GetThreshingRecipeForResource(Resources.GetResourceIDByName(base.ingredients[0].name, false)), 
			4 => GameDefines.instance.GetValidBlastSmelterRecipesForSingle(Resources.GetResourceIDByName(base.ingredients[0].name, false), 9999, 9999, false)[0], 
			5 => GameDefines.instance.GetPlanterRecipeBySeedInputId(Resources.GetResourceIDByName(base.ingredients[0].name, false)), 
			6 => GameDefines.instance.GetValidCrusherRecipes(base.ingredients.Select((RecipeResourceInfo i) => Resources.GetResourceIDByName(i.name, false)).ToList(), 9999, 9999, false)[0], 
			_ => null, 
		});
	}

	public sealed override string ToString()
	{
		return "Recipe " + base.GUID;
	}
}
public static class DIExtensions
{
	private static Dictionary<string, string> customTranslations;

	public static string setLeadingCase(this string s, bool upper)
	{
		return (upper ? char.ToUpperInvariant(s[0]) : char.ToLowerInvariant(s[0])) + s.Substring(1);
	}

	public static bool intersects(this SphereCollider sc, SphereCollider other)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: 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_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: 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_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_0048: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = ((Component)sc).transform.position + sc.center;
		Vector3 val2 = ((Component)other).transform.position + other.center;
		float num = Mathf.Min(sc.radius, other.radius);
		Vector3 val3 = val2 - val;
		return ((Vector3)(ref val3)).sqrMagnitude <= num * num;
	}

	public static Sprite setTexture(this Sprite s, Texture2D tex)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		return Sprite.Create(tex, s.textureRect, s.pivot, s.pixelsPerUnit, 0u, (SpriteMeshType)0, s.border);
	}

	public static Vector4 setXYZ(this Vector4 vec, Vector3 xyz)
	{
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		vec.x = xyz.x;
		vec.y = xyz.y;
		vec.z = xyz.z;
		return new Vector4(xyz.x, xyz.y, xyz.z, vec.w);
	}

	public static Color exponent(this Color c, float exp)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		return new Color(Mathf.Pow(c.r, exp), Mathf.Pow(c.g, exp), Mathf.Pow(c.b, exp), Mathf.Pow(c.a, exp));
	}

	public static Color asColor(this Vector3 c)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		return new Color(c.x, c.y, c.z);
	}

	public static Vector3 exponent(this Vector3 c, float exp)
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: 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)
		return new Vector3(Mathf.Pow(c.x, exp), Mathf.Pow(c.y, exp), Mathf.Pow(c.z, exp));
	}

	public static Color asColor(this Vector4 c)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		return new Color(c.x, c.y, c.z, c.w);
	}

	public static Vector4 exponent(this Vector4 c, float exp)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		return new Vector4(Mathf.Pow(c.x, exp), Mathf.Pow(c.y, exp), Mathf.Pow(c.z, exp), Mathf.Pow(c.w, exp));
	}

	public static Vector3 toVector(this Color c)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		return new Vector3(c.r, c.g, c.b);
	}

	public static Vector4 toVectorA(this Color c)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		return new Vector4(c.r, c.g, c.b, c.a);
	}

	public static int toARGB(this Color c)
	{
		int num = Mathf.RoundToInt(c.a * 255f) & 0xFF;
		int num2 = Mathf.RoundToInt(c.r * 255f) & 0xFF;
		int num3 = Mathf.RoundToInt(c.g * 255f) & 0xFF;
		int num4 = Mathf.RoundToInt(c.b * 255f) & 0xFF;
		return (num << 24) | (num2 << 16) | (num3 << 8) | num4;
	}

	public static Vector3 getXYZ(this Vector4 vec)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		return new Vector3(vec.x, vec.y, vec.z);
	}

	public static Vector3 setLength(this Vector3 vec, double amt)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		return ((Vector3)(ref vec)).normalized * (float)amt;
	}

	public static Vector3 addLength(this Vector3 vec, double amt)
	{
		//IL_0001: 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)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		return vec.setLength((double)((Vector3)(ref vec)).magnitude + amt);
	}

	public static Vector3 setY(this Vector3 vec, double y)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		return new Vector3(vec.x, (float)y, vec.z);
	}

	public static XmlElement addProperty(this XmlNode xml, string name, Quaternion quat)
	{
		XmlElement xmlElement = xml.OwnerDocument.CreateElement(name);
		((XmlNode)xmlElement).addProperty("x", (double)quat.x);
		((XmlNode)xmlElement).addProperty("y", (double)quat.y);
		((XmlNode)xmlElement).addProperty("z", (double)quat.z);
		((XmlNode)xmlElement).addProperty("w", (double)quat.w);
		xml.AppendChild(xmlElement);
		return xmlElement;
	}

	public static XmlElement addProperty(this XmlNode xml, string name, Vector3 vec)
	{
		XmlElement xmlElement = xml.OwnerDocument.CreateElement(name);
		((XmlNode)xmlElement).addProperty("x", (double)vec.x);
		((XmlNode)xmlElement).addProperty("y", (double)vec.y);
		((XmlNode)xmlElement).addProperty("z", (double)vec.z);
		xml.AppendChild(xmlElement);
		return xmlElement;
	}

	public static XmlElement addProperty(this XmlNode xml, string name, Vector4 vec)
	{
		//IL_0003: 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)
		Quaternion quat = default(Quaternion);
		quat.x = vec.x;
		quat.y = vec.y;
		quat.z = vec.z;
		quat.w = vec.w;
		return xml.addProperty(name, quat);
	}

	public static XmlElement addProperty(this XmlNode xml, string name, Color c)
	{
		XmlElement xmlElement = xml.OwnerDocument.CreateElement(name);
		((XmlNode)xmlElement).addProperty("r", (double)c.r);
		((XmlNode)xmlElement).addProperty("g", (double)c.g);
		((XmlNode)xmlElement).addProperty("b", (double)c.b);
		((XmlNode)xmlElement).addProperty("a", (double)c.a);
		xml.AppendChild(xmlElement);
		return xmlElement;
	}

	public static XmlElement addProperty(this XmlNode xml, string name, int value)
	{
		return xml.addProperty(name, value.ToString(CultureInfo.InvariantCulture));
	}

	public static XmlElement addProperty(this XmlNode xml, string name, double value)
	{
		return xml.addProperty(name, value.ToString(CultureInfo.InvariantCulture));
	}

	public static XmlElement addProperty(this XmlNode xml, string name, bool value)
	{
		return xml.addProperty(name, value.ToString(CultureInfo.InvariantCulture));
	}

	public static XmlElement addProperty(this XmlNode xml, string name, string value = null)
	{
		XmlElement xmlElement = xml.OwnerDocument.CreateElement(name);
		if (value != null)
		{
			xmlElement.InnerText = value;
		}
		xml.AppendChild(xmlElement);
		return xmlElement;
	}

	public static double getFloat(this XmlElement xml, string name, double fallback)
	{
		string property = xml.getProperty(name, allowNull: true);
		if (string.IsNullOrEmpty(property))
		{
			if (double.IsNaN(fallback))
			{
				throw new Exception("No matching tag '" + name + "'! " + xml.format());
			}
			return fallback;
		}
		return double.Parse(xml.getProperty(name), CultureInfo.InvariantCulture);
	}

	public static int getInt(this XmlElement xml, string name, int fallback, bool allowFallback = true)
	{
		string property = xml.getProperty(name, allowFallback);
		bool flag = string.IsNullOrEmpty(property);
		if (flag && !allowFallback)
		{
			throw new Exception("No matching tag '" + name + "'! " + xml.format());
		}
		return flag ? fallback : int.Parse(property, CultureInfo.InvariantCulture);
	}

	public static bool getBoolean(this XmlElement xml, string name)
	{
		XmlElement elem;
		return xml.getBoolean(name, out elem);
	}

	public static bool getBoolean(this XmlElement xml, string name, out XmlElement elem)
	{
		string property = xml.getProperty(name, out elem, allowNull: true);
		return !string.IsNullOrEmpty(property) && bool.Parse(property);
	}

	public static string getProperty(this XmlElement xml, string name, bool allowNull = false)
	{
		XmlElement elem;
		return xml.getProperty(name, out elem, allowNull);
	}

	public static int getRandomInt(this XmlElement xml, string name)
	{
		List<XmlElement> directElementsByTagName = xml.getDirectElementsByTagName(name);
		if (directElementsByTagName.Count == 1)
		{
			int @int = directElementsByTagName[0].getInt("min", 0);
			int int2 = directElementsByTagName[0].getInt("max", -1, allowFallback: false);
			return Random.Range(@int, int2);
		}
		throw new Exception("You must have exactly one matching named element for getRandomInt '" + name + "'! " + xml.format());
	}

	public static float getRandomFloat(this XmlElement xml, string name)
	{
		List<XmlElement> directElementsByTagName = xml.getDirectElementsByTagName(name);
		if (directElementsByTagName.Count == 1)
		{
			double @float = directElementsByTagName[0].getFloat("min", double.NaN);
			double float2 = directElementsByTagName[0].getFloat("max", double.NaN);
			return Random.Range((float)@float, (float)float2);
		}
		throw new Exception("You must have exactly one matching named element for getRandomFloat '" + name + "'! " + xml.format());
	}

	public static string getProperty(this XmlElement xml, string name, out XmlElement elem, bool allowNull = false)
	{
		List<XmlElement> directElementsByTagName = xml.getDirectElementsByTagName(name);
		if (directElementsByTagName.Count == 1)
		{
			elem = directElementsByTagName[0];
			return directElementsByTagName[0].InnerText;
		}
		if (directElementsByTagName.Count == 0 && allowNull)
		{
			elem = null;
			return null;
		}
		throw new Exception("You must have exactly one matching named tag for getProperty '" + name + "'! " + xml.format());
	}

	public static Vector3? getVector(this XmlElement xml, string name, bool allowNull = false)
	{
		XmlElement elem;
		return xml.getVector(name, out elem, allowNull);
	}

	public static Vector4? getVector4(this XmlElement xml, string name, bool allowNull = false)
	{
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		Quaternion? quaternion = xml.getQuaternion(name, allowNull);
		if (!quaternion.HasValue || !quaternion.HasValue)
		{
			return null;
		}
		Vector4 value = default(Vector4);
		value.x = quaternion.Value.x;
		value.y = quaternion.Value.y;
		value.z = quaternion.Value.z;
		value.w = quaternion.Value.w;
		return value;
	}

	public static Vector3? getVector(this XmlElement xml, string name, out XmlElement elem, bool allowNull = false)
	{
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		List<XmlElement> directElementsByTagName = xml.getDirectElementsByTagName(name);
		if (directElementsByTagName.Count == 1)
		{
			double @float = directElementsByTagName[0].getFloat("x", double.NaN);
			double float2 = directElementsByTagName[0].getFloat("y", double.NaN);
			double float3 = directElementsByTagName[0].getFloat("z", double.NaN);
			elem = directElementsByTagName[0];
			return new Vector3((float)@float, (float)float2, (float)float3);
		}
		if (directElementsByTagName.Count == 0 && allowNull)
		{
			elem = null;
			return null;
		}
		throw new Exception("You must have exactly one matching named element for getVector '" + name + "'! " + xml.format());
	}

	public static Quaternion? getQuaternion(this XmlElement xml, string name, bool allowNull = false)
	{
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		List<XmlElement> directElementsByTagName = xml.getDirectElementsByTagName(name);
		if (directElementsByTagName.Count == 1)
		{
			double @float = directElementsByTagName[0].getFloat("x", double.NaN);
			double float2 = directElementsByTagName[0].getFloat("y", double.NaN);
			double float3 = directElementsByTagName[0].getFloat("z", double.NaN);
			double float4 = directElementsByTagName[0].getFloat("w", double.NaN);
			return new Quaternion((float)@float, (float)float2, (float)float3, (float)float4);
		}
		if (directElementsByTagName.Count == 0 && allowNull)
		{
			return null;
		}
		throw new Exception("You must have exactly one matching named element for getQuaternion '" + name + "'! " + xml.format());
	}

	public static Color? getColor(this XmlElement xml, string name, bool includeAlpha, bool allowNull = false)
	{
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		List<XmlElement> directElementsByTagName = xml.getDirectElementsByTagName(name);
		if (directElementsByTagName.Count == 1)
		{
			double @float = directElementsByTagName[0].getFloat("r", double.NaN);
			double float2 = directElementsByTagName[0].getFloat("g", double.NaN);
			double float3 = directElementsByTagName[0].getFloat("b", double.NaN);
			double num = (includeAlpha ? directElementsByTagName[0].getFloat("a", double.NaN) : 1.0);
			return new Color((float)@float, (float)float2, (float)float3, (float)num);
		}
		if (directElementsByTagName.Count == 0 && allowNull)
		{
			return null;
		}
		throw new Exception("You must have exactly one matching named element for getColor '" + name + "'! " + xml.format());
	}

	public static List<XmlElement> getDirectElementsByTagName(this XmlElement xml, string name)
	{
		List<XmlElement> list = new List<XmlElement>();
		foreach (XmlNode childNode in xml.ChildNodes)
		{
			if (childNode is XmlElement && childNode.Name == name)
			{
				list.Add((XmlElement)childNode);
			}
		}
		return list;
	}

	public static XmlNodeList getAllChildrenIn(this XmlElement xml, string name)
	{
		List<XmlElement> directElementsByTagName = xml.getDirectElementsByTagName(name);
		return (directElementsByTagName.Count == 1) ? directElementsByTagName[0].ChildNodes : null;
	}

	public static bool hasProperty(this XmlElement xml, string name)
	{
		List<XmlElement> directElementsByTagName = xml.getDirectElementsByTagName(name);
		return directElementsByTagName.Count == 1;
	}

	public static string format(this XmlElement xml)
	{
		return xml.OuterXml;
	}

	public static XmlElement addChild(this XmlElement e, string name)
	{
		XmlElement xmlElement = e.OwnerDocument.CreateElement(name);
		e.AppendChild(xmlElement);
		return xmlElement;
	}

	public static bool isEnumerable(this object o)
	{
		if (o == null)
		{
			return false;
		}
		return o is IEnumerable && o.GetType().IsGenericType && o.GetType().GetGenericTypeDefinition().IsAssignableFrom(typeof(IEnumerable<>));
	}

	public static bool isList(this object o)
	{
		if (o == null)
		{
			return false;
		}
		return o is IList && o.GetType().IsGenericType && o.GetType().GetGenericTypeDefinition().IsAssignableFrom(typeof(List<>));
	}

	public static bool isDictionary(this object o)
	{
		if (o == null)
		{
			return false;
		}
		return o is IDictionary && o.GetType().IsGenericType && o.GetType().GetGenericTypeDefinition().IsAssignableFrom(typeof(Dictionary<, >));
	}

	public static string toDebugString<K, V>(this IDictionary<K, V> dict)
	{
		return dict.Count + ":{" + string.Join(",", dict.Select((KeyValuePair<K, V> kv) => stringify(kv.Key) + "=" + stringify(kv.Value)).ToArray()) + "}";
	}

	public static string toDebugString<E>(this IEnumerable<E> c)
	{
		return c.Count() + ":[" + string.Join(",", c.Select((E e) => stringify(e)).ToArray()) + "]";
	}

	public static string toDebugString<T, V>(this MachineDefinition<T, V> def) where T : struct, IMachineInstance<T, V> where V : MachineDefinition<T, V>
	{
		return string.Concat(((ResourceInfo)def).displayName, " [", ((UniqueIdScriptableObject)def).uniqueId, "] @ T", ((BuilderInfo)def).machineTier, ": ", ((object)def).GetType(), ">", typeof(T));
	}

	public static string toDebugString(this SchematicsRecipeData rec)
	{
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		if (rec.ingTypes == null || rec.ingQuantities == null)
		{
			return "Errored null-in recipe " + ((Object)rec).name;
		}
		if (rec.outputTypes == null || rec.outputQuantities == null)
		{
			return "Errored null-out recipe " + ((Object)rec).name;
		}
		if (rec.ingTypes.Length != rec.ingQuantities.Length)
		{
			return "Errored misaligned-in recipe " + ((Object)rec).name + " " + ((IEnumerable<ResourceInfo>)rec.ingTypes).toDebugString() + "/" + ((IEnumerable<int>)rec.ingQuantities).toDebugString();
		}
		if (rec.outputTypes.Length != rec.outputQuantities.Length)
		{
			return "Errored misaligned-out recipe " + ((Object)rec).name + " " + ((IEnumerable<ResourceInfo>)rec.outputTypes).toDebugString() + "/" + ((IEnumerable<int>)rec.outputQuantities).toDebugString();
		}
		string text = string.Concat("[", rec.craftingMethod, "] (", rec.duration.ToString("0.0"), "s) {");
		for (int i = 0; i < rec.ingTypes.Length; i++)
		{
			object obj = text;
			text = string.Concat(obj, ((Object)(object)rec.ingTypes[i] == (Object)null) ? "NULLRESIN" : rec.ingTypes[i].displayName, "x", rec.ingQuantities[i]);
			if (i < rec.ingTypes.Length - 1)
			{
				text += "+";
			}
		}
		text += " > ";
		for (int i = 0; i < rec.outputTypes.Length; i++)
		{
			object obj = text;
			text = string.Concat(obj, ((Object)(object)rec.outputTypes[i] == (Object)null) ? "NULLRESOUT" : rec.outputTypes[i].displayName, "x", rec.outputQuantities[i]);
			if (i < rec.outputTypes.Length - 1)
			{
				text += "+";
			}
		}
		text += "}";
		if (rec.chargeGeneratedWhenProcessed > 0)
		{
			object obj = text;
			text = string.Concat(obj, " & ", rec.chargeGeneratedWhenProcessed, "kJ, up to ", rec.maxChargeGenerated, " (", rec.maxChargeGenerated / rec.chargeGeneratedWhenProcessed, "x)");
		}
		return text;
	}

	public static string toDebugString(this ResourceInfo res)
	{
		return ((Object)(object)res == (Object)null) ? "NULL" : (((Object)res).name + " (" + res.displayName + ") [" + ((UniqueIdScriptableObject)res).uniqueId + "]");
	}

	public static string toDebugString(this RequiredCores c)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		return string.Concat(c.type, " x", c.number);
	}

	public static string toDebugString(this Unlock u)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		return ((Object)(object)u == (Object)null) ? "NULL" : string.Concat(u.category, "/", ((Object)u).name, " ('", u.getDisplayName(), "') @ ", TTUtil.getTierDescription(u.requiredTier), ",", u.treePosition, " #", ((IEnumerable<RequiredCores>)u.coresNeeded).toDebugString(), " > ", ((IEnumerable<SchematicsRecipeData>)u.unlockedRecipes).toDebugString());
	}

	public static string getDisplayName(this Unlock u)
	{
		return LocsUtility.TranslateStringFromHash(u.displayNameHash, (string)null, (Object)null);
	}

	public static string getDescription(this Unlock u)
	{
		return LocsUtility.TranslateStringFromHash(u.descriptionHash, (string)null, (Object)null);
	}

	public static E pop<E>(this IList<E> c)
	{
		E result = c[0];
		c.RemoveAt(0);
		return result;
	}

	public static Vector3 getClosest(this IEnumerable<Vector3> li, Vector3 pos)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		Vector3 result = Vector3.zero;
		float num = float.PositiveInfinity;
		foreach (Vector3 item in li)
		{
			Vector3 val = item - pos;
			float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
			if (sqrMagnitude < num)
			{
				num = sqrMagnitude;
				result = item;
			}
		}
		return result;
	}

	public static E[] addToArray<E>(this E[] arr, E add)
	{
		List<E> list = new List<E>(arr.ToList());
		list.Add(add);
		return list.ToArray();
	}

	public static bool overlaps<E>(this ICollection<E> c, ICollection<E> other)
	{
		foreach (E item in c)
		{
			if (other.Contains(item))
			{
				return true;
			}
		}
		return false;
	}

	public static string stringify(object obj)
	{
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Expected O, but got Unknown
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Expected O, but got Unknown
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Expected O, but got Unknown
		if (obj == null)
		{
			return "null";
		}
		if (obj.isDictionary())
		{
			return "dict:" + ((IDictionary<object, object>)obj).toDebugString();
		}
		if (obj.isEnumerable())
		{
			return "enumerable:" + ((IEnumerable<object>)obj).toDebugString();
		}
		if (obj is Unlock)
		{
			return DIExtensions.toDebugString((Unlock)obj);
		}
		if (obj is SchematicsRecipeData)
		{
			return DIExtensions.toDebugString((SchematicsRecipeData)obj);
		}
		if (obj is RequiredCores)
		{
			return DIExtensions.toDebugString((RequiredCores)obj);
		}
		if (obj is ResourceInfo)
		{
			return DIExtensions.toDebugString((ResourceInfo)obj);
		}
		return obj.ToString();
	}

	public static T copyObject<T>(this T comp, T from) where T : class
	{
		Type type = comp.GetType();
		Type type2 = from.GetType();
		if (type != type2)
		{
			throw new Exception(string.Concat("Mismatched types on ", comp, " and ", from, ": ", type, " vs ", type2));
		}
		BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
		PropertyInfo[] properties = type.GetProperties(bindingAttr);
		foreach (PropertyInfo propertyInfo in properties)
		{
			if (propertyInfo.CanWrite)
			{
				try
				{
					propertyInfo.SetValue(comp, propertyInfo.GetValue(from, null), null);
				}
				catch
				{
				}
			}
		}
		FieldInfo[] fields = type.GetFields(bindingAttr);
		foreach (FieldInfo fieldInfo in fields)
		{
			fieldInfo.SetValue(comp, fieldInfo.GetValue(from));
		}
		return comp;
	}

	public static C ensureComponent<C>(this GameObject go) where C : Component
	{
		C val = go.GetComponent<C>();
		if (!Object.op_Implicit((Object)(object)val))
		{
			val = go.AddComponent<C>();
		}
		return val;
	}

	public static int multiplyBy(this int num, double fac)
	{
		return (int)Math.Floor(Math.Round((double)num * fac));
	}

	public static void scalePower(this SchematicsRecipeData rec, double f, double maxScale = 1.0)
	{
		rec.chargeGeneratedWhenProcessed = rec.chargeGeneratedWhenProcessed.multiplyBy(f);
		rec.maxChargeGenerated = rec.maxChargeGenerated.multiplyBy(f * maxScale);
		TTUtil.log("Power yield from " + rec.toDebugString() + " after scaled by " + f + "/" + maxScale);
	}

	public static int getCost(this SchematicsRecipeData rec, string name)
	{
		return rec.getCost(Resources.GetResourceIDByName(name, false));
	}

	public static int getCost(this SchematicsRecipeData rec, int id)
	{
		for (int i = 0; i < rec.ingTypes.Length; i++)
		{
			if (((UniqueIdScriptableObject)rec.ingTypes[i]).uniqueId == id)
			{
				return rec.ingQuantities[i];
			}
		}
		return 0;
	}

	public static int getYield(this SchematicsRecipeData rec, string name)
	{
		return rec.getYield(Resources.GetResourceIDByName(name, false));
	}

	public static int getYield(this SchematicsRecipeData rec, int id)
	{
		for (int i = 0; i < rec.outputTypes.Length; i++)
		{
			if (((UniqueIdScriptableObject)rec.outputTypes[i]).uniqueId == id)
			{
				return rec.outputQuantities[i];
			}
		}
		return 0;
	}

	public static void replaceIngredient(this SchematicsRecipeData rec, string from, string put, int amt = 1)
	{
		ResourceInfo resourceInfoByName = Resources.GetResourceInfoByName(from, false);
		for (int i = 0; i < rec.ingTypes.Length; i++)
		{
			if (((UniqueIdScriptableObject)rec.ingTypes[i]).uniqueId == ((UniqueIdScriptableObject)resourceInfoByName).uniqueId)
			{
				rec.ingTypes[i] = Resources.GetResourceInfoByName(put, false);
				float num = (float)rec.runtimeIngQuantities[i] / (float)rec.ingQuantities[i];
				rec.ingQuantities[i] = amt;
				rec.runtimeIngQuantities[i] = FHG_Utils.CeilToInt((float)amt * num);
			}
		}
		TTUtil.log("Replaced " + from + " with " + put + " in " + rec.toDebugString());
	}

	public static void adjustCoreCost(this Unlock u, double f)
	{
		u.coresNeeded = u.coresNeeded.Select(delegate(RequiredCores c)
		{
			//IL_0002: 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)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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)
			RequiredCores result = default(RequiredCores);
			result.type = c.type;
			result.number = c.number.multiplyBy(f);
			return result;
		}).ToList();
		TTUtil.log("Adjusting core cost of " + ((Object)u).name + " to " + ((IEnumerable<RequiredCores>)u.coresNeeded).toDebugString());
	}

	public static void setDescription(this Unlock u, string desc)
	{
		string hashString = LocsUtility.GetHashString(desc);
		u.description = desc;
		u.descriptionHash = hashString;
		if (customTranslations == null)
		{
			customTranslations = (Dictionary<string, string>)typeof(EMUAdditionsPlugin).GetField("customTranslations", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);
		}
		customTranslations[hashString] = desc;
	}
}
public static class InstructionHandlers
{
	private static Action<List<CodeInstruction>> currentPatch;

	public static long getIntFromOpcode(CodeInstruction ci)
	{
		return ci.opcode.Name switch
		{
			"ldc.i4.m1" => -1L, 
			"ldc.i4.0" => 0L, 
			"ldc.i4.1" => 1L, 
			"ldc.i4.2" => 2L, 
			"ldc.i4.3" => 3L, 
			"ldc.i4.4" => 4L, 
			"ldc.i4.5" => 5L, 
			"ldc.i4.6" => 6L, 
			"ldc.i4.7" => 7L, 
			"ldc.i4.8" => 8L, 
			"ldc.i4.s" => (sbyte)ci.operand, 
			"ldc.i4" => (int)ci.operand, 
			"ldc.i8" => (long)ci.operand, 
			_ => long.MaxValue, 
		};
	}

	public static void nullInstructions(List<CodeInstruction> li, int begin, int end)
	{
		for (int i = begin; i <= end; i++)
		{
			CodeInstruction val = li[i];
			val.opcode = OpCodes.Nop;
			val.operand = null;
		}
	}

	public static CodeInstruction createMethodCall(string owner, string name, bool instance, params string[] args)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Expected O, but got Unknown
		return new CodeInstruction(OpCodes.Call, (object)convertMethodOperand(owner, name, instance, args));
	}

	public static CodeInstruction createMethodCall(string owner, string name, bool instance, params Type[] args)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Expected O, but got Unknown
		return new CodeInstruction(OpCodes.Call, (object)convertMethodOperand(owner, name, instance, args));
	}

	public static MethodInfo convertMethodOperand(string owner, string name, bool instance, params string[] args)
	{
		Type[] array = new Type[args.Length];
		for (int i = 0; i < args.Length; i++)
		{
			array[i] = AccessTools.TypeByName(args[i]);
		}
		return convertMethodOperand(owner, name, instance, array);
	}

	public static MethodInfo convertMethodOperand(string owner, string name, bool instance, params Type[] args)
	{
		Type type = AccessTools.TypeByName(owner);
		if (type == null)
		{
			throw new Exception("Could not find a type matching name '" + owner + "'!");
		}
		MethodInfo methodInfo = AccessTools.Method(type, name, args, (Type[])null);
		if (methodInfo == null)
		{
			throw new Exception("Could not find a method named '" + name + "' with args " + ((IEnumerable<Type>)args).toDebugString() + " in type '" + owner + "'!");
		}
		return methodInfo;
	}

	public static FieldInfo convertFieldOperand(string owner, string name)
	{
		Type type = AccessTools.TypeByName(owner);
		FieldInfo fieldInfo = AccessTools.Field(type, name);
		if (fieldInfo == null)
		{
			throw new Exception("Could not find a method named '" + name + "' in type '" + owner + "'!");
		}
		return fieldInfo;
	}

	public static int getInstruction(List<CodeInstruction> li, int start, int index, OpCode opcode, params object[] args)
	{
		int num = 0;
		if (index < 0)
		{
			index = -index - 1;
			for (int num2 = li.Count - 1; num2 >= 0; num2--)
			{
				CodeInstruction val = li[num2];
				if (val.opcode == opcode && match(val, args))
				{
					if (num == index)
					{
						return num2;
					}
					num++;
				}
			}
		}
		else
		{
			for (int num2 = start; num2 < li.Count; num2++)
			{
				CodeInstruction val = li[num2];
				if (val.opcode == opcode && match(val, args))
				{
					if (num == index)
					{
						return num2;
					}
					num++;
				}
			}
		}
		throw new Exception(string.Concat("Instruction not found: ", opcode, " #", string.Join(",", args), "\nInstruction list:\n", toString(li)));
	}

	public static int getMethodCallByName(List<CodeInstruction> li, int start, int index, string owner, string name)
	{
		int num = 0;
		if (index < 0)
		{
			index = -index - 1;
			for (int num2 = li.Count - 1; num2 >= 0; num2--)
			{
				CodeInstruction insn = li[num2];
				if (isMethodCall(insn, owner, name))
				{
					if (num == index)
					{
						return num2;
					}
					num++;
				}
			}
		}
		else
		{
			for (int num2 = start; num2 < li.Count; num2++)
			{
				CodeInstruction insn = li[num2];
				if (isMethodCall(insn, owner, name))
				{
					if (num == index)
					{
						return num2;
					}
					num++;
				}
			}
		}
		throw new Exception("Method call not found: " + owner + "::" + name + "\nInstruction list:\n" + toString(li));
	}

	public static int getFirstOpcode(List<CodeInstruction> li, int after, OpCode opcode)
	{
		for (int i = after; i < li.Count; i++)
		{
			CodeInstruction val = li[i];
			if (val.opcode == opcode)
			{
				return i;
			}
		}
		throw new Exception(string.Concat("Instruction not found: ", opcode, "\nInstruction list:\n", toString(li)));
	}

	public static int getLastOpcodeBefore(List<CodeInstruction> li, int before, OpCode opcode)
	{
		if (before > li.Count)
		{
			before = li.Count;
		}
		for (int num = before - 1; num >= 0; num--)
		{
			CodeInstruction val = li[num];
			if (val.opcode == opcode)
			{
				return num;
			}
		}
		throw new Exception(string.Concat("Instruction not found: ", opcode, "\nInstruction list:\n", toString(li)));
	}

	public static int getLastInstructionBefore(List<CodeInstruction> li, int before, OpCode opcode, params object[] args)
	{
		for (int num = before - 1; num >= 0; num--)
		{
			CodeInstruction val = li[num];
			if (val.opcode == opcode && match(val, args))
			{
				return num;
			}
		}
		throw new Exception(string.Concat("Instruction not found: ", opcode, " #", string.Join(",", args), "\nInstruction list:\n", toString(li)));
	}

	public static bool match(CodeInstruction a, CodeInstruction b)
	{
		return a.opcode == b.opcode && matchOperands(a.operand, b.operand);
	}

	public static bool matchOperands(object o1, object o2)
	{
		if (o1 == o2)
		{
			return true;
		}
		if (o1 == null || o2 == null)
		{
			return false;
		}
		if (o1 is LocalBuilder && o2 is LocalBuilder)
		{
			return ((LocalBuilder)o1).LocalIndex == ((LocalBuilder)o2).LocalIndex;
		}
		return o1.Equals(o2);
	}

	public static bool isMethodCall(CodeInstruction insn, string owner, string name)
	{
		if (insn.opcode != OpCodes.Call && insn.opcode != OpCodes.Callvirt && insn.opcode != OpCodes.Calli)
		{
			return false;
		}
		MethodInfo methodInfo = (MethodInfo)insn.operand;
		return methodInfo.Name == name && methodInfo.DeclaringType.FullName == owner;
	}

	public static bool match(CodeInstruction insn, params object[] args)
	{
		if (insn.opcode == OpCodes.Call || insn.opcode == OpCodes.Callvirt)
		{
			MethodInfo methodInfo = convertMethodOperand((string)args[0], (string)args[1], (bool)args[2], (Type[])args[3]);
			return (MethodInfo)insn.operand == methodInfo;
		}
		if (insn.opcode == OpCodes.Isinst || insn.opcode == OpCodes.Newobj)
		{
			return (Type)insn.operand == AccessTools.TypeByName((string)args[0]);
		}
		if (insn.opcode == OpCodes.Ldfld || insn.opcode == OpCodes.Stfld || insn.opcode == OpCodes.Ldsfld || insn.opcode == OpCodes.Stsfld)
		{
			FieldInfo fieldInfo = convertFieldOperand((string)args[0], (string)args[1]);
			return (FieldInfo)insn.operand == fieldInfo;
		}
		if (insn.opcode == OpCodes.Ldarg)
		{
			return insn.operand == args[0];
		}
		if (insn.opcode == OpCodes.Ldc_I4)
		{
			return CodeInstructionExtensions.LoadsConstant(insn, (long)Convert.ToInt32(args[0]));
		}
		if (insn.opcode == OpCodes.Ldc_R4)
		{
			return CodeInstructionExtensions.LoadsConstant(insn, (double)Convert.ToSingle(args[0]));
		}
		if (insn.opcode == OpCodes.Ldc_I8)
		{
			return CodeInstructionExtensions.LoadsConstant(insn, Convert.ToInt64(args[0]));
		}
		if (insn.opcode == OpCodes.Ldc_R8)
		{
			return CodeInstructionExtensions.LoadsConstant(insn, Convert.ToDouble(args[0]));
		}
		if (insn.opcode == OpCodes.Ldloc_S || insn.opcode == OpCodes.Stloc_S)
		{
			LocalBuilder localBuilder = (LocalBuilder)insn.operand;
			return args[0] is int && localBuilder.LocalIndex == (int)args[0];
		}
		if (insn.opcode == OpCodes.Ldstr)
		{
			return (string)insn.operand == (string)args[0];
		}
		return true;
	}

	public static string toString(List<CodeInstruction> li)
	{
		return "\n" + string.Join("\n", li.Select((CodeInstruction p) => toString(p)).ToArray());
	}

	public static string toString(List<CodeInstruction> li, int idx)
	{
		return (idx < 0 || idx >= li.Count) ? ("ERROR: OOB " + idx + "/" + li.Count) : ("#" + Convert.ToString(idx, 16) + " = " + toString(li[idx]));
	}

	public static string toString(CodeInstruction ci)
	{
		return ci.opcode.Name + " " + toOperandString(ci.opcode, ci.operand);
	}

	private static string toOperandString(OpCode code, object operand)
	{
		if (operand is MethodInfo)
		{
			MethodInfo methodInfo = (MethodInfo)operand;
			return string.Concat(methodInfo.DeclaringType, ".", methodInfo.Name, " (", string.Join(", ", from p in methodInfo.GetParameters()
				select p.ParameterType.Name + " " + p.Name), ") [static=", methodInfo.IsStatic, "]");
		}
		if (operand is FieldInfo)
		{
			FieldInfo fieldInfo = (FieldInfo)operand;
			return string.Concat(fieldInfo.DeclaringType, ".", fieldInfo.Name, " [static=", fieldInfo.IsStatic, "]");
		}
		if (operand is LocalBuilder)
		{
			return "localvar " + ((LocalBuilder)operand).LocalIndex;
		}
		if (code == OpCodes.Ldarg_S || code == OpCodes.Ldarg)
		{
			return "arg " + operand;
		}
		if (operand is Type)
		{
			return "type " + ((Type)operand).Name;
		}
		return (operand != null) ? string.Concat(operand, " [", operand.GetType(), "]") : "<null>";
	}

	public static Type getTypeBySimpleName(string name)
	{
		foreach (Assembly item in AppDomain.CurrentDomain.GetAssemblies().Reverse())
		{
			Type type = item.GetType(name);
			if (type != null)
			{
				return type;
			}
		}
		return null;
	}

	public static void patchEveryReturnPre(List<CodeInstruction> codes, params CodeInstruction[] insert)
	{
		patchEveryReturnPre(codes, insert.ToList());
	}

	public static void patchEveryReturnPre(List<CodeInstruction> codes, List<CodeInstruction> insert)
	{
		patchEveryReturnPre(codes, (Action<List<CodeInstruction>, int>)delegate(List<CodeInstruction> li, int idx)
		{
			li.InsertRange(idx, insert);
		});
	}

	public static void patchEveryReturnPre(List<CodeInstruction> codes, Action<List<CodeInstruction>, int> injectHook)
	{
		for (int num = codes.Count - 1; num >= 0; num--)
		{
			if (codes[num].opcode == OpCodes.Ret)
			{
				injectHook(codes, num);
			}
		}
	}

	public static void patchInitialHook(List<CodeInstruction> codes, params CodeInstruction[] insert)
	{
		List<CodeInstruction> list = new List<CodeInstruction>();
		foreach (CodeInstruction item in insert)
		{
			list.Add(item);
		}
		patchInitialHook(codes, list);
	}

	public static void patchInitialHook(List<CodeInstruction> codes, List<CodeInstruction> insert)
	{
		for (int num = insert.Count - 1; num >= 0; num--)
		{
			codes.Insert(0, insert[num]);
		}
	}

	public static List<CodeInstruction> extract(List<CodeInstruction> codes, int from, int to)
	{
		List<CodeInstruction> list = new List<CodeInstruction>();
		for (int i = from; i <= to; i++)
		{
			list.Add(codes[i]);
		}
		codes.RemoveRange(from, to - from + 1);
		return list;
	}

	public static void replaceConstantWithMethodCall(List<CodeInstruction> codes, int val, List<CodeInstruction> put)
	{
		replaceConstantWithMethodCall(codes, val, (CodeInstruction c) => c.opcode == OpCodes.Ldc_I4 && CodeInstructionExtensions.LoadsConstant(c, (long)Convert.ToInt32(val)), put);
	}

	public static void replaceConstantWithMethodCall(List<CodeInstruction> codes, long val, List<CodeInstruction> put)
	{
		replaceConstantWithMethodCall(codes, val, (CodeInstruction c) => c.opcode == OpCodes.Ldc_I8 && CodeInstructionExtensions.LoadsConstant(c, Convert.ToInt64(val)), put);
	}

	public static void replaceConstantWithMethodCall(List<CodeInstruction> codes, float val, List<CodeInstruction> put)
	{
		replaceConstantWithMethodCall(codes, val, (CodeInstruction c) => c.opcode == OpCodes.Ldc_R4 && CodeInstructionExtensions.LoadsConstant(c, (double)Convert.ToSingle(val)), put);
	}

	public static void replaceConstantWithMethodCall(List<CodeInstruction> codes, double val, List<CodeInstruction> put)
	{
		replaceConstantWithMethodCall(codes, val, (CodeInstruction c) => c.opcode == OpCodes.Ldc_R8 && CodeInstructionExtensions.LoadsConstant(c, Convert.ToDouble(val)), put);
	}

	private static void replaceConstantWithMethodCall(List<CodeInstruction> codes, double val, Func<CodeInstruction, bool> f, List<CodeInstruction> put)
	{
		for (int num = codes.Count - 1; num >= 0; num--)
		{
			CodeInstruction arg = codes[num];
			if (f(arg))
			{
				codes.RemoveAt(num);
				codes.InsertRange(num, put);
			}
		}
	}

	public static HarmonyMethod clear()
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Expected O, but got Unknown
		Func<IEnumerable<CodeInstruction>, IEnumerable<CodeInstruction>> func = (IEnumerable<CodeInstruction> codes) => new List<CodeInstruction>
		{
			new CodeInstruction(OpCodes.Ret, (object)null)
		};
		return new HarmonyMethod(func.Method);
	}

	public static void runPatchesIn(Harmony h, Type parent)
	{
		FileLog.logPath = Path.Combine(Path.GetDirectoryName(parent.Assembly.Location), "harmony-log.txt");
		TTUtil.log("Running harmony patches in " + parent.Assembly.GetName().Name + "::" + parent.Name);
		FileLog.Log("Running harmony patches in " + parent.Assembly.GetName().Name + "::" + parent.Name);
		Type[] nestedTypes = parent.GetNestedTypes(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (Type type in nestedTypes)
		{
			FileLog.Log("Running harmony patches in " + type.Name);
			h.PatchAll(type);
		}
	}

	public static void patchMethod(Harmony h, Type methodHolder, string name, Type patchHolder, string patchName)
	{
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Expected O, but got Unknown
		FileLog.logPath = Path.Combine(Path.GetDirectoryName(patchHolder.Assembly.Location), "harmony-log.txt");
		FileLog.Log("Running harmony patch in " + patchHolder.FullName + "::" + patchName + " on " + methodHolder.FullName + "::" + name);
		MethodInfo method = methodHolder.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		if (method == null)
		{
			throw new Exception("Method " + name + " not found in " + methodHolder.AssemblyQualifiedName);
		}
		patchMethod(h, method, new HarmonyMethod(AccessTools.Method(patchHolder, patchName, new Type[1] { typeof(IEnumerable<CodeInstruction>) }, (Type[])null)));
	}

	public static void patchMethod(Harmony h, Type methodHolder, string name, Assembly patchHolder, Action<List<CodeInstruction>> patch)
	{
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Expected O, but got Unknown
		FileLog.logPath = Path.Combine(Path.GetDirectoryName(patchHolder.Location), "harmony-log.txt");
		FileLog.Log("Running harmony patch from " + patchHolder.GetName().Name + " on " + methodHolder.FullName + "::" + name);
		MethodInfo method = methodHolder.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		if (method == null)
		{
			throw new Exception("Method " + name + " not found in " + methodHolder.FullName);
		}
		currentPatch = patch;
		patchMethod(h, method, new HarmonyMethod(AccessTools.Method(MethodBase.GetCurrentMethod().DeclaringType, "patchHook", new Type[1] { typeof(IEnumerable<CodeInstruction>) }, (Type[])null)));
		currentPatch = null;
	}

	public static void patchMethod(Harmony h, MethodInfo m, Assembly patchHolder, Action<List<CodeInstruction>> patch)
	{
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Expected O, but got Unknown
		FileLog.logPath = Path.Combine(Path.GetDirectoryName(patchHolder.Location), "harmony-log.txt");
		FileLog.Log("Running harmony patch from " + patchHolder.GetName().Name + " on " + m.DeclaringType.FullName + "::" + m.Name);
		currentPatch = patch;
		patchMethod(h, m, new HarmonyMethod(AccessTools.Method(MethodBase.GetCurrentMethod().DeclaringType, "patchHook", new Type[1] { typeof(IEnumerable<CodeInstruction>) }, (Type[])null)));
		currentPatch = null;
	}

	private static IEnumerable<CodeInstruction> patchHook(IEnumerable<CodeInstruction> instructions)
	{
		List<CodeInstruction> list = new List<CodeInstruction>(instructions);
		currentPatch(list);
		return list.AsEnumerable();
	}

	private static void patchMethod(Harmony h, MethodInfo m, HarmonyMethod patch)
	{
		try
		{
			h.Patch((MethodBase)m, (HarmonyMethod)null, (HarmonyMethod)null, patch, (HarmonyMethod)null, (HarmonyMethod)null);
			FileLog.Log("Done patch");
		}
		catch (Exception ex)
		{
			FileLog.Log("Caught exception when running patch!");
			FileLog.Log(ex.Message);
			FileLog.Log(ex.StackTrace);
			FileLog.Log(ex.ToString());
		}
	}
}
public static class MathUtil
{
	public static float py3d(Vector3 from, Vector3 to)
	{
		return py3d(from.x, from.y, from.z, to.x, to.y, to.z);
	}

	public static float py3d(float rawX, float rawY, float rawZ, float rawX2, float rawY2, float rawZ2)
	{
		float dx = rawX2 - rawX;
		float dy = rawY2 - rawY;
		float dz = rawZ2 - rawZ;
		return py3d(dx, dy, dz);
	}

	public static float py3d(float dx, float dy, float dz)
	{
		return Mathf.Sqrt(py3dS(dx, dy, dz));
	}

	public static float py3dS(float rawX, float rawY, float rawZ, float rawX2, float rawY2, float rawZ2)
	{
		float dx = rawX2 - rawX;
		float dy = rawY2 - rawY;
		float dz = rawZ2 - rawZ;
		return py3dS(dx, dy, dz);
	}

	public static float py3dS(float dx, float dy, float dz)
	{
		return dx * dx + dy * dy + dz * dz;
	}

	public static int intpow2(int v, int pow)
	{
		int num = 1;
		for (int i = 0; i < pow; i++)
		{
			num *= v;
		}
		return num;
	}

	public static Vector3 findRandomPointInsideEllipse(Vector3 center, float length, float width)
	{
		//IL_0029: 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_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		Rect rec = default(Rect);
		((Rect)(ref rec))..ctor(center.x - length / 2f, center.z - width / 2f, length, width);
		Vector2 randomVectorInside = getRandomVectorInside(rec);
		int num = 0;
		while (!isPointInsideEllipse(randomVectorInside.x - center.x, 0f, randomVectorInside.y - center.z, length / 2f, 0f, width / 2f))
		{
			float num2 = length / 2f;
			float num3 = width / 2f;
			float num4 = randomVectorInside.x - center.x;
			float num5 = randomVectorInside.y - center.z;
			randomVectorInside = getRandomVectorInside(rec);
			num++;
		}
		return new Vector3(randomVectorInside.x, center.y, randomVectorInside.y);
	}

	public static Vector2 getRandomVectorInside(Rect rec)
	{
		//IL_002b: 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_0033: Unknown result type (might be due to invalid IL or missing references)
		float num = Random.Range(((Rect)(ref rec)).xMin, ((Rect)(ref rec)).xMax);
		float num2 = Random.Range(((Rect)(ref rec)).yMin, ((Rect)(ref rec)).yMax);
		return new Vector2(num, num2);
	}

	public static bool isPointInsideEllipse(float x, float y, float z, float ra, float rb, float rc)
	{
		return ((ra > 0f) ? (x * x / (ra * ra)) : 0f) + ((rb > 0f) ? (y * y / (rb * rb)) : 0f) + ((rc > 0f) ? (z * z / (rc * rc)) : 0f) <= 1f;
	}

	public static bool isPointInCylinder(Vector3 center, Vector3 point, float r, float h)
	{
		//IL_0018: 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_001a: 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_002d: Unknown result type (might be due to invalid IL or missing references)
		int result;
		if (Math.Abs(point.y - center.y) <= h)
		{
			Vector3 val = (center - point).setY(0.0);
			result = ((((Vector3)(ref val)).magnitude <= r) ? 1 : 0);
		}
		else
		{
			result = 0;
		}
		return (byte)result != 0;
	}

	public static void rotateObjectAround(GameObject go, Vector3 point, float amt)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		go.transform.RotateAround(point, Vector3.up, amt);
	}

	public static Vector3 getRandomVectorBetween(Vector3 min, Vector3 max)
	{
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: 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)
		return new Vector3(Random.Range(min.x, max.x), Random.Range(min.y, max.y), Random.Range(min.z, max.z));
	}

	public static Vector3 getRandomVectorAround(Vector3 pos, float range)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		return getRandomVectorAround(pos, new Vector3(range, range, range));
	}

	public static Vector3 getRandomVectorAround(Vector3 pos, Vector3 range)
	{
		//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)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		return getRandomVectorBetween(pos - range, pos + range);
	}

	public static Vector3 getRandomVectorAround(Vector3 pos, float r0, float r1)
	{
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: 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_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		float num = Random.Range(r0, r1);
		float num2 = Random.Range(0f, 360f);
		float num3 = (float)Math.Cos((double)num2 * Math.PI / 180.0);
		float num4 = (float)Math.Sin((double)num2 * Math.PI / 180.0);
		return pos + num * new Vector3(num3, 0f, num4);
	}

	public static float getDistanceToLine(Vector3 point, Vector3 a, Vector3 b)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return getDistanceToLine(point, a.x, a.y, a.z, b.x, b.y, b.z);
	}

	public static float getDistanceToLine(Vector3 point, float x1, float y1, float z1, float x2, float y2, float z2)
	{
		float num = (x2 - x1) * (x2 - x1) + (z2 - z1) * (z2 - z1);
		float num2 = (x2 - x1) * (z1 - point.z) - (x1 - point.x) * (z2 - z1);
		return Mathf.Abs(num2) / Mathf.Sqrt(num);
	}

	public static float getDistanceToLineSegment(Vector3 point, Vector3 a, Vector3 b)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return getDistanceToLineSegment(point, a.x, a.y, a.z, b.x, b.y, b.z);
	}

	public static float getScalarOfClosestPointToLineSegment(Vector3 point, float x1, float y1, float z1, float x2, float y2, float z2)
	{
		float num = py3dS(x1, y1, z1, x2, y2, z2);
		if ((double)num <= 0.001)
		{
			return py3d(point.x, point.y, point.z, x1, y1, z1);
		}
		float num2 = ((point.x - x1) * (x2 - x1) + (point.y - y1) * (y2 - y1) + (point.z - z1) * (z2 - z1)) / num;
		return Mathf.Clamp(num2, 0f, 1f);
	}

	public static Vector3 getClosestPointToLineSegment(Vector3 point, Vector3 p1, Vector3 p2)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: 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_0034: Unknown result type (might be due to invalid IL or missing references)
		return getClosestPointToLineSegment(point, p1.x, p1.y, p1.z, p2.x, p2.y, p2.z);
	}

	public static Vector3 getClosestPointToLineSegment(Vector3 point, float x1, float y1, float z1, float x2, float y2, float z2)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: 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_0034: Unknown result type (might be due to invalid IL or missing references)
		float num = getScalarOfClosestPointToLineSegment(point, x1, y1, z1, x2, y2, z2);
		return Vector3.Lerp(new Vector3(x1, y1, z1), new Vector3(x2, y2, z2), num);
	}

	public static float getDistanceToLineSegment(Vector3 point, float x1, float y1, float z1, float x2, float y2, float z2)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		float scalarOfClosestPointToLineSegment = getScalarOfClosestPointToLineSegment(point, x1, y1, z1, x2, y2, z2);
		return py3d(point.x, point.y, point.z, x1 + scalarOfClosestPointToLineSegment * (x2 - x1), y1 + scalarOfClosestPointToLineSegment * (y2 - y1), z1 + scalarOfClosestPointToLineSegment * (z2 - z1));
	}

	public static float linterpolate(float x, float x1, float x2, float y1, float y2, bool clamp = false)
	{
		if (clamp && x <= x1)
		{
			return y1;
		}
		if (clamp && x >= x2)
		{
			return y2;
		}
		return y1 + (x - x1) / (x2 - x1) * (y2 - y1);
	}

	public static Vector3 interpolate(Vector3 a, Vector3 b, float amt)
	{
		//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)
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		return a + (b - a) * amt;
	}

	public static float getRandomPlusMinus(float val, float range)
	{
		return Random.Range(val - range, val + range);
	}

	public static int getRandomPlusMinus(int val, int range)
	{
		return Random.Range(val - range, val + range);
	}

	public static Bounds getBounds(float x1, float y1, float z1, float x2, float y2, float z2)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: 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_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = default(Vector3);
		((Vector3)(ref val))..ctor(x1, y1, z1);
		Vector3 val2 = default(Vector3);
		((Vector3)(ref val2))..ctor(x2, y2, z2);
		Bounds result = default(Bounds);
		((Bounds)(ref result))..ctor(Vector3.zero, Vector3.zero);
		((Bounds)(ref result)).SetMinMax(val, val2);
		return result;
	}

	public static int getNthDecimalPlace(float value, int place)
	{
		value = Mathf.Abs(value) * Mathf.Pow(10f, (float)place);
		return (int)value % 10;
	}

	public static Quaternion unitVecToRotation(Vector3 unit)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		return Quaternion.FromToRotation(Vector3.up, unit);
	}

	public static Vector3 rotateVectorAroundAxis(Vector3 input, Vector3 axis, float angle)
	{
		//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)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		return Quaternion.AngleAxis(angle, axis) * input;
	}

	public static Vector3 getRandomPointAtSetDistance(Vector3 pos, float dist)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: 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_0043: Unknown result type (might be due to invalid IL or missing references)
		return pos + DIExtensions.setLength(new Vector3(Random.Range(-1f, 1f), Random.Range(-1f, 1f), Random.Range(-1f, 1f)), dist);
	}

	public static int roundDownToX(int val, int multiple)
	{
		int num = val - val % multiple;
		if (val < 0)
		{
			num -= multiple;
		}
		return num;
	}

	public static int roundUpToX(int val, int multiple)
	{
		return roundDownToX(val, multiple) + multiple;
	}

	public static int roundToNearestX(int val, int multiple)
	{
		return (val + multiple / 2 * Math.Sign(val)) / multiple * multiple;
	}
}
public static class ObjectUtil
{
	public static bool debugMode;

	public static void stripAllExcept(GameObject go, params Type[] except)
	{
		HashSet<Type> hashSet = except.ToHashSet();
		Component[] componentsInChildren = go.GetComponentsInChildren<Component>();
		foreach (Component val in componentsInChildren)
		{
			if (!(val is Transform) && !hashSet.Contains(((object)val).GetType()))
			{
				Object.DestroyImmediate((Object)(object)val);
			}
		}
	}

	public static void removeComponent(GameObject go, Type tt, bool immediate = true)
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		Component[] componentsInChildren = go.GetComponentsInChildren(tt);
		foreach (Component val in componentsInChildren)
		{
			if (val is MonoBehaviour)
			{
				((Behaviour)(MonoBehaviour)val).enabled = false;
			}
			if (immediate)
			{
				Object.DestroyImmediate((Object)(object)val);
			}
			else
			{
				Object.Destroy((Object)(object)val);
			}
		}
	}

	public static void removeComponent<C>(GameObject go, bool immediate = true) where C : Component
	{
		applyToComponents<C>(go, (!immediate) ? 1 : 2, setA: true, setTo: true);
	}

	public static void setActive<C>(GameObject go, bool active) where C : Component
	{
		applyToComponents<C>(go, 0, setA: true, active);
	}

	private static void applyToComponents<C>(GameObject go, int destroy, bool setA, bool setTo) where C : Component
	{
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		C[] componentsInChildren = go.GetComponentsInChildren<C>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			Component val = (Component)(object)componentsInChildren[i];
			if (debugMode)
			{
				TTUtil.log(string.Concat("Affecting component ", val, " in ", go, " @ ", go.transform.position, ": D=", destroy, "/", setTo, "(", setA, ")"), TTUtil.diDLL);
			}
			if (val is MonoBehaviour && setA)
			{
				((Behaviour)(MonoBehaviour)val).enabled = setTo;
			}
			switch (destroy)
			{
			case 2:
				Object.DestroyImmediate((Object)(object)val);
				break;
			case 1:
				Object.Destroy((Object)(object)val);
				break;
			}
		}
	}

	public static void dumpObjectData(GameObject go, bool includeChildren = true)
	{
		dumpObjectData(go, 0, includeChildren);
	}

	private static void dumpObjectData(GameObject go, int indent, bool includeChildren = true)
	{
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)go))
		{
			TTUtil.log("null object");
			return;
		}
		TTUtil.log("object " + go, TTUtil.diDLL, indent);
		TTUtil.log("components: " + string.Join(", ", (object?[])go.GetComponents<Component>()), TTUtil.diDLL, indent);
		TTUtil.log("transform: " + go.transform, TTUtil.diDLL,