Decompiled source of Dragon Industries ANEXCAL Relations v1.0.1
Dragon Industries - ANEXCAL Relations.dll
Decompiled 2 months ago
The result has been truncated due to the large size, download it to view full contents!
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,