Decompiled source of Ship Customizer v0.3.0
VoidCrewShipCustomizer.dll
Decompiled 16 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using CG; using CG.Client; using CG.Client.Utils; using CG.Game.Configuration; using CG.Game.SpaceObjects.Controllers; using CG.Objects; using CG.Profile; using CG.Ship.Hull; using CG.Ship.Modules; using CG.Ship.Object; using CG.Space; using CG.UI.MainMenu; using Client.Player.Interactions; using ExitGames.Client.Photon; using Gameplay.Chat; using Gameplay.CompositeWeapons; using Gameplay.Hub; using HarmonyLib; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Photon.Pun; using Photon.Realtime; using ResourceAssets; using UI; using UI.Core; using UI.Core.Audio; using UI.PowerTerminal; using UI.ShipLoadoutTerminal; using UnityEngine; using UnityEngine.Localization; using UnityEngine.UIElements; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Void Crew Ship Customizer")] [assembly: AssemblyDescription("BepInEx plugin that adds a Custom ship loadout to Void Crew's ship loadout terminal")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("CaptainChunck")] [assembly: AssemblyProduct("VoidCrewShipCustomizer")] [assembly: AssemblyCopyright("Copyright © CaptainChunck 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("6c0b5e1a-3d2f-4b8e-9c47-5a1e0f2d7b93")] [assembly: AssemblyFileVersion("0.3.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("0.3.0.0")] namespace VoidCrewShipCustomizer; internal enum OptionKind { Module, Weapon, Item, WeaponCrate } internal sealed class Option { public string Code; public OptionKind Kind; public GUIDUnion Guid; public GUIDUnion PrefabGuid; public string Name; public ContextInfo Context; public Sprite Icon; public RarityType Rarity; public string Category; public int CategoryOrder; public bool HasSize; public BuildSize Size; public bool SingleInstance; public Type ModuleType; } internal sealed class SocketInfo { public int Index; public BuildSize Size; public Vector3[] Cells = (Vector3[])(object)new Vector3[0]; public readonly List<int> Overlaps = new List<int>(); public int Group; } internal sealed class ShelfInfo { public int CoreIndex; public GUIDUnion ModuleGuid; public string Name; public List<CarryablesSocket> Slots = new List<CarryablesSocket>(); public readonly Dictionary<string, bool> AcceptCache = new Dictionary<string, bool>(); } internal sealed class HullInfo { public GUIDUnion ShipGuid; public string Name; public ShipLoadoutDataDef BasePreset; public readonly List<ShipLoadoutDataDef> Presets = new List<ShipLoadoutDataDef>(); public readonly List<ShipLoadoutDataDef> RegularPresets = new List<ShipLoadoutDataDef>(); public readonly List<SocketInfo> Sockets = new List<SocketInfo>(); public readonly List<ShelfInfo> Shelves = new List<ShelfInfo>(); public int GroupCount; } internal static class Catalog { private static readonly Dictionary<GUIDUnion, HullInfo> Hulls = new Dictionary<GUIDUnion, HullInfo>(); private static readonly HashSet<GUIDUnion> FailedHulls = new HashSet<GUIDUnion>(); private static readonly Dictionary<string, Option> ByCode = new Dictionary<string, Option>(); private static readonly Dictionary<GUIDUnion, JObject> PresetContents = new Dictionary<GUIDUnion, JObject>(); private static List<Option> _slotOptions; private static List<Option> _itemOptions; private static List<Option> _homunculusOptions; private static bool _presetContentsRead; private static GUIDUnion _weaponCrate; private static bool _weaponCrateRead; private static readonly FieldInfo CompareMethodField = AccessTools.Field(typeof(CsObjectReference), "compareMethod"); private static readonly FieldInfo PrefabRuleField = AccessTools.Field(typeof(CsObjectReference), "orbitObjectRef"); public static List<Option> SlotOptions { get { if (_slotOptions != null) { return _slotOptions; } Stopwatch stopwatch = Stopwatch.StartNew(); List<Option> list = new List<Option>(); AddWeaponOptions(list); AddModuleOptions(list); _slotOptions = (from o in list orderby o.CategoryOrder, ((int)o.Rarity != 0) ? ((int)o.Rarity) : 0 select o).ThenBy<Option, string>((Option o) => o.Name, StringComparer.OrdinalIgnoreCase).ToList(); foreach (Option slotOption in _slotOptions) { ByCode[slotOption.Code] = slotOption; } Log.Info($"Found {_slotOptions.Count((Option o) => o.Kind == OptionKind.Weapon)} weapons and {_slotOptions.Count((Option o) => o.Kind == OptionKind.Module)} modules that fit in hardpoints ({stopwatch.ElapsedMilliseconds} ms)."); return _slotOptions; } } public static List<Option> ItemOptions { get { if (_itemOptions != null) { return _itemOptions; } Stopwatch stopwatch = Stopwatch.StartNew(); List<Option> list = new List<Option>(); AddItemOptions(list); _itemOptions = (from o in list orderby o.CategoryOrder, ((int)o.Rarity != 0) ? ((int)o.Rarity) : 0 select o).ThenBy<Option, string>((Option o) => o.Name, StringComparer.OrdinalIgnoreCase).ToList(); foreach (Option itemOption in _itemOptions) { ByCode[itemOption.Code] = itemOption; } Log.Info($"Found {_itemOptions.Count} items for the storage racks ({stopwatch.ElapsedMilliseconds} ms)."); return _itemOptions; } } public static List<Option> HomunculusOptions { get { //IL_005b: 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) if (_homunculusOptions != null) { return _homunculusOptions; } HashSet<GUIDUnion> hashSet = new HashSet<GUIDUnion>(); List<Option> list = new List<Option>(); foreach (ShipLoadoutDataDef assetDescription in ((ResourceAssetContainer<ShipLoadoutDataContainer, ShipLoadoutData, ShipLoadoutDataDef>)(object)ResourceAssetContainer<ShipLoadoutDataContainer, ShipLoadoutData, ShipLoadoutDataDef>.Instance).AssetDescriptions) { try { CarryableRef homunculusOverride = ((ResourceAssetDef<ShipLoadoutData>)(object)assetDescription).Asset.ShipLoadout.HomunculusOverride; if (!((ResourceAssetRef)(object)homunculusOverride == (ResourceAssetRef)null) && !((ResourceAssetRef)homunculusOverride).IsNull && hashSet.Add(((ResourceAssetRef)homunculusOverride).AssetGuid)) { Option option = ItemOption(((ResourceAssetRef)homunculusOverride).AssetGuid, "HOMUNCULUS", 0); if (option != null) { list.Add(option); } } } catch (Exception ex) { Log.Verbose("Skipped a loadout's homunculus: " + ex.Message); } } _homunculusOptions = list.OrderBy<Option, string>((Option o) => o.Name, StringComparer.OrdinalIgnoreCase).ToList(); foreach (Option homunculusOption in _homunculusOptions) { ByCode[homunculusOption.Code] = homunculusOption; } return _homunculusOptions; } } public static GUIDUnion WeaponCrateGuid { get { //IL_0007: 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_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) if (_weaponCrateRead) { return _weaponCrate; } _weaponCrateRead = true; try { _weaponCrate = ((ResourceAssetDef<CarryableObject>)(object)ResourceAssetContainer<CarryableContainer, CarryableObject, CarryableDef>.Instance.WeaponBuildBox).AssetGuid; } catch (Exception ex) { Log.Warn("Could not find the game's weapon crate, so weapons can't be put on storage racks: " + ex.Message); } return _weaponCrate; } } public static List<GUIDUnion> ShipGuids() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) List<GUIDUnion> list = new List<GUIDUnion>(); foreach (MonoBehaviourRef ship in ResourceAssetContainer<ShipLoadoutDataContainer, ShipLoadoutData, ShipLoadoutDataDef>.Instance.Ships) { if ((ResourceAssetRef)(object)ship != (ResourceAssetRef)null && !((ResourceAssetRef)ship).IsNull) { list.Add(((ResourceAssetRef)ship).AssetGuid); } } return list; } public unsafe static bool TryGetHull(GUIDUnion shipGuid, out HullInfo hull) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: 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_00d3: 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_0030: 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) if (Hulls.TryGetValue(shipGuid, out hull)) { return true; } if (((GUIDUnion)(ref shipGuid)).IsNull || FailedHulls.Contains(shipGuid)) { return false; } try { Stopwatch stopwatch = Stopwatch.StartNew(); hull = BuildHull(shipGuid); Hulls[shipGuid] = hull; Log.Info($"Read the {hull.Name}: {hull.Sockets.Count} hardpoint positions in {hull.GroupCount} hardpoints, {hull.Shelves.Count} storage racks, {hull.Presets.Count} loadouts ({stopwatch.ElapsedMilliseconds} ms)."); return true; } catch (Exception ex) { FailedHulls.Add(shipGuid); GUIDUnion val = shipGuid; Log.Error("Could not read ship " + ((object)(*(GUIDUnion*)(&val))/*cast due to .constrained prefix*/).ToString() + ", so it gets no CUSTOM loadout: " + ex); hull = null; return false; } } private static HullInfo BuildHull(GUIDUnion shipGuid) { //IL_000c: 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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Unknown result type (might be due to invalid IL or missing references) HullInfo hullInfo = new HullInfo { ShipGuid = shipGuid, Name = HeaderOf(ContextOf(shipGuid), "SHIP") }; List<ShipLoadoutDataDef> list = new List<ShipLoadoutDataDef>(); foreach (ShipLoadoutDataDef assetDescription in ((ResourceAssetContainer<ShipLoadoutDataContainer, ShipLoadoutData, ShipLoadoutDataDef>)(object)ResourceAssetContainer<ShipLoadoutDataContainer, ShipLoadoutData, ShipLoadoutDataDef>.Instance).AssetDescriptions) { try { if (assetDescription != null && !((ResourceAssetDef<ShipLoadoutData>)(object)assetDescription).IsNull && (Object)(object)((ResourceAssetDef<ShipLoadoutData>)(object)assetDescription).Asset != (Object)null && ((ResourceAssetDef<ShipLoadoutData>)(object)assetDescription).Asset.ShipLoadout != null && assetDescription.ShipGuid == shipGuid) { list.Add(assetDescription); } } catch (Exception ex) { Log.Verbose("Skipped a loadout while reading " + hullInfo.Name + ": " + ex.Message); } } if (list.Count == 0) { throw new InvalidOperationException("the game has no loadouts for this ship"); } ShipLoadoutDataContainer instance = ResourceAssetContainer<ShipLoadoutDataContainer, ShipLoadoutData, ShipLoadoutDataDef>.Instance; List<ShipLoadoutDataDef> listed = new List<ShipLoadoutDataDef>(); try { listed.AddRange(instance.GetUnlockedShipDefinitionsFromHighestRankPlayer()); listed.AddRange(instance.GetLockedShipDefinitionsFromHighestRankPlayer()); } catch (Exception ex2) { Log.Warn("Could not read which loadouts the terminal lists: " + ex2.Message); } hullInfo.RegularPresets.AddRange(list.Where(listed.Contains).OrderBy(RankRequirement)); hullInfo.Presets.AddRange(hullInfo.RegularPresets); hullInfo.Presets.AddRange(list.Where((ShipLoadoutDataDef p) => !listed.Contains(p))); ShipLoadoutDataDef val = null; try { val = ((DefaultableResourceAssetContainer<ShipLoadoutDataContainer, ShipLoadoutData, ShipLoadoutDataDef>)(object)instance).GetDefault(); } catch { } hullInfo.BasePreset = (ShipLoadoutDataDef)((val != null && list.Contains(val)) ? ((object)val) : ((object)(hullInfo.RegularPresets.FirstOrDefault() ?? list[0]))); MonoBehaviour asset = ((ResourceAssetRef<MonoBehaviourContainer, MonoBehaviour, MonoBehaviourDef>)(object)((ResourceAssetDef<ShipLoadoutData>)(object)hullInfo.BasePreset).Asset.ShipLoadout.ReferenceShip).Asset; if ((Object)(object)asset == (Object)null) { throw new InvalidOperationException("the ship prefab could not be loaded"); } BuildSocketController component = ((Component)asset).GetComponent<BuildSocketController>(); List<BuildSocket> list2 = (((Object)(object)component != (Object)null && component.Sockets != null && component.Sockets.Count > 0) ? component.Sockets : new List<BuildSocket>(((Component)asset).GetComponentsInChildren<BuildSocket>(true))); for (int num = 0; num < list2.Count; num++) { SocketInfo socketInfo = new SocketInfo { Index = num }; if ((Object)(object)list2[num] != (Object)null) { socketInfo.Size = list2[num].Size; socketInfo.Cells = CellsOf(list2[num]); } hullInfo.Sockets.Add(socketInfo); } hullInfo.GroupCount = Hardpoints.LinkOverlaps(hullInfo.Sockets); PlayerControlledShip component2 = ((Component)asset).GetComponent<PlayerControlledShip>(); CellModule[] array = (((Object)(object)component2 != (Object)null) ? component2.CoreSystems : null); if (array != null) { for (int num2 = 0; num2 < array.Length; num2++) { CarryablesShelf val2 = (((Object)(object)array[num2] != (Object)null) ? ((Component)array[num2]).GetComponent<CarryablesShelf>() : null); if (!((Object)(object)val2 == (Object)null)) { ShelfInfo shelfInfo = new ShelfInfo { CoreIndex = num2, ModuleGuid = ((AbstractCloneStarObject)val2).assetGuid }; shelfInfo.Slots.AddRange(((CellModule)val2).CarryablesSockets.Where((CarryablesSocket s) => (Object)(object)s != (Object)null)); shelfInfo.Name = "STORAGE RACK " + (hullInfo.Shelves.Count + 1); hullInfo.Shelves.Add(shelfInfo); } } } return hullInfo; } private static Vector3[] CellsOf(BuildSocket socket) { //IL_0008: 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_0014: 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) Transform transform = ((Component)socket).transform; return Hardpoints.CellsFor(socket.Size, transform.position, transform.right, transform.forward); } private static int RankRequirement(ShipLoadoutDataDef def) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) try { UnlockItemDef assetDefById = ((ResourceAssetContainer<UnlockContainer, Object, UnlockItemDef>)(object)ResourceAssetContainer<UnlockContainer, Object, UnlockItemDef>.Instance).GetAssetDefById(((ResourceAssetDef<ShipLoadoutData>)(object)def).AssetGuid, false); return (assetDefById != null) ? assetDefById.UnlockOptions.RankRequirement : int.MaxValue; } catch { return int.MaxValue; } } public static bool TryGetOption(string code, out Option option) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) option = null; if (string.IsNullOrEmpty(code)) { return false; } if (ByCode.TryGetValue(code, out option)) { return true; } if (code.StartsWith("m:") || code.StartsWith("w:")) { _ = SlotOptions; } else { _ = ItemOptions; } if (ByCode.TryGetValue(code, out option)) { return true; } if (code.Length > 2 && GUIDUnion.IsValidString(code.Substring(2))) { GUIDUnion guid = default(GUIDUnion); ((GUIDUnion)(ref guid))..ctor(code.Substring(2)); if (code.StartsWith("m:")) { option = RawModuleOption(guid); } else if (code.StartsWith("i:")) { option = ItemOption(guid, "OTHER", 99); } if (option != null) { ByCode[code] = option; } } return option != null; } public static bool CanSpawn(GUIDUnion guid) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (!((GUIDUnion)(ref guid)).IsNull) { return ((ResourceAssetContainer<CloneStarObjectContainer, AbstractCloneStarObject, CloneStarObjectDef>)(object)ResourceAssetContainer<CloneStarObjectContainer, AbstractCloneStarObject, CloneStarObjectDef>.Instance).HasItem(guid); } return false; } private static Option RawModuleOption(GUIDUnion guid) { //IL_0000: 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_0035: 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_003c: 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) //IL_0073: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) if (!CanSpawn(guid)) { return null; } ContextInfo val = ContextOf(guid); Option option = new Option { Code = "m:" + ((GUIDUnion)(ref guid)).AsHex(), Kind = OptionKind.Module, Guid = guid, PrefabGuid = guid, Name = HeaderOf(val, "Module"), Context = val, Icon = (((Object)(object)val != (Object)null) ? val.Icon : null), Rarity = RarityOf(guid), Category = "OTHER", CategoryOrder = 9 }; try { CellModule val2 = ((ResourceAssetDef<CellModule>)(object)((ResourceAssetContainer<ModuleContainer, CellModule, ModuleDef>)(object)ResourceAssetContainer<ModuleContainer, CellModule, ModuleDef>.Instance).GetAssetDefById(guid, false))?.Asset; if ((Object)(object)val2 != (Object)null && TryGetSize(val2.BuildingConstraints, out var size)) { option.HasSize = true; option.Size = size; option.SingleInstance = val2.BuildingConstraints.AllowOnlySingleInstance; option.ModuleType = ((object)val2).GetType(); } } catch (Exception ex) { Log.Verbose("Could not read the size of module " + option.Name + ": " + ex.Message); } return option; } private static void AddWeaponOptions(List<Option> list) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) foreach (CompositeWeaponDataDef assetDescription in ((ResourceAssetContainer<CompositeWeaponDataContainer, CompositeWeaponData, CompositeWeaponDataDef>)(object)ResourceAssetContainer<CompositeWeaponDataContainer, CompositeWeaponData, CompositeWeaponDataDef>.Instance).AssetDescriptions) { try { if (assetDescription == null || ((ResourceAssetDef<CompositeWeaponData>)(object)assetDescription).IsNull) { continue; } CompositeWeaponData asset = ((ResourceAssetDef<CompositeWeaponData>)(object)assetDescription).Asset; if ((Object)(object)asset == (Object)null || asset.Data == null || (ResourceAssetRef)(object)asset.Data.CoreElement == (ResourceAssetRef)null || ((ResourceAssetRef)asset.Data.CoreElement).IsNull || !CanSpawn(((ResourceAssetRef)asset.Data.CoreElement).AssetGuid)) { continue; } CompositeWeaponModule asset2 = ((ResourceAssetRef<WeaponCoreContainer, CompositeWeaponModule, WeaponCoreDef>)(object)asset.Data.CoreElement).Asset; if (!((Object)(object)asset2 == (Object)null) && TryGetSize(((CellModule)asset2).BuildingConstraints, out var size)) { IResourceAssetContextInfo contextInfo = ((PurchasableResourceAssetDef<CompositeWeaponData>)(object)assetDescription).ContextInfo; ContextInfo val = (ContextInfo)(object)((contextInfo is ContextInfo) ? contextInfo : null); if (!IsMissing(val)) { Option option = new Option(); GUIDUnion assetGuid = ((ResourceAssetDef<CompositeWeaponData>)(object)assetDescription).AssetGuid; option.Code = "w:" + ((GUIDUnion)(ref assetGuid)).AsHex(); option.Kind = OptionKind.Weapon; option.Guid = ((ResourceAssetDef<CompositeWeaponData>)(object)assetDescription).AssetGuid; option.PrefabGuid = ((ResourceAssetRef)asset.Data.CoreElement).AssetGuid; option.Name = HeaderOf(val, ((Object)asset).name); option.Context = val; option.Icon = val.Icon; option.Rarity = RarityOf(((ResourceAssetDef<CompositeWeaponData>)(object)assetDescription).AssetGuid); option.Category = CategoryName((ECategory)1); option.CategoryOrder = 1; option.HasSize = true; option.Size = size; option.SingleInstance = ((CellModule)asset2).BuildingConstraints.AllowOnlySingleInstance; option.ModuleType = ((object)asset2).GetType(); list.Add(option); } } } catch (Exception ex) { Log.Verbose("Skipped weapon " + ((assetDescription != null) ? ((ResourceAssetDef<CompositeWeaponData>)(object)assetDescription).Path : "?") + ": " + ex.Message); } } } private static void AddModuleOptions(List<Option> list) { //IL_0029: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //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) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Expected I4, but got Unknown //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) foreach (ModuleDef assetDescription in ((ResourceAssetContainer<ModuleContainer, CellModule, ModuleDef>)(object)ResourceAssetContainer<ModuleContainer, CellModule, ModuleDef>.Instance).AssetDescriptions) { try { if (assetDescription == null || ((ResourceAssetDef<CellModule>)(object)assetDescription).IsNull || (int)assetDescription.Category == 0 || !CanSpawn(((ResourceAssetDef<CellModule>)(object)assetDescription).AssetGuid)) { continue; } CellModule asset = ((ResourceAssetDef<CellModule>)(object)assetDescription).Asset; if (!((Object)(object)asset == (Object)null) && !(asset is CompositeWeaponModule) && !((Object)(object)((Component)asset).GetComponent<CarryablesShelf>() != (Object)null) && TryGetSize(asset.BuildingConstraints, out var size)) { ContextInfo val = ContextOf(((ResourceAssetDef<CellModule>)(object)assetDescription).AssetGuid); if (!IsMissing(val)) { Option option = new Option(); GUIDUnion assetGuid = ((ResourceAssetDef<CellModule>)(object)assetDescription).AssetGuid; option.Code = "m:" + ((GUIDUnion)(ref assetGuid)).AsHex(); option.Kind = OptionKind.Module; option.Guid = ((ResourceAssetDef<CellModule>)(object)assetDescription).AssetGuid; option.PrefabGuid = ((ResourceAssetDef<CellModule>)(object)assetDescription).AssetGuid; option.Name = HeaderOf(val, ((Object)asset).name); option.Context = val; option.Icon = val.Icon; option.Rarity = RarityOf(((ResourceAssetDef<CellModule>)(object)assetDescription).AssetGuid); option.Category = CategoryName(assetDescription.Category); option.CategoryOrder = (int)assetDescription.Category; option.HasSize = true; option.Size = size; option.SingleInstance = asset.BuildingConstraints.AllowOnlySingleInstance; option.ModuleType = ((object)asset).GetType(); list.Add(option); } } } catch (Exception ex) { Log.Verbose("Skipped module " + ((assetDescription != null) ? ((ResourceAssetDef<CellModule>)(object)assetDescription).Path : "?") + ": " + ex.Message); } } } private static void AddItemOptions(List<Option> list) { //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_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: 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_0034: 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_0046: Invalid comparison between Unknown and I4 //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) CarryableContainer instance = ResourceAssetContainer<CarryableContainer, CarryableObject, CarryableDef>.Instance; GUIDUnion weaponCrateGuid = WeaponCrateGuid; foreach (CarryableDef assetDescription in ((ResourceAssetContainer<CarryableContainer, CarryableObject, CarryableDef>)(object)instance).AssetDescriptions) { try { if (assetDescription != null && !((ResourceAssetDef<CarryableObject>)(object)assetDescription).IsNull && !(((ResourceAssetDef<CarryableObject>)(object)assetDescription).AssetGuid == weaponCrateGuid) && ((int)((PurchasableResourceAssetDef<CarryableObject>)(object)assetDescription).Category != 65 || Settings.ShowQuestItems.Value)) { Option option = ItemOption(((ResourceAssetDef<CarryableObject>)(object)assetDescription).AssetGuid, ItemCategoryName(((PurchasableResourceAssetDef<CarryableObject>)(object)assetDescription).Category), ItemCategoryOrder(((PurchasableResourceAssetDef<CarryableObject>)(object)assetDescription).Category)); if (option != null) { list.Add(option); } } } catch (Exception ex) { Log.Verbose("Skipped item " + ((assetDescription != null) ? ((ResourceAssetDef<CarryableObject>)(object)assetDescription).Path : "?") + ": " + ex.Message); } } if (((GUIDUnion)(ref weaponCrateGuid)).IsNull || !CanSpawn(weaponCrateGuid)) { return; } foreach (Option item in SlotOptions.Where((Option o) => o.Kind == OptionKind.Weapon)) { Sprite icon = item.Icon; try { icon = ((ResourceAssetContainer<CompositeWeaponDataContainer, CompositeWeaponData, CompositeWeaponDataDef>)(object)ResourceAssetContainer<CompositeWeaponDataContainer, CompositeWeaponData, CompositeWeaponDataDef>.Instance).GetAssetDefById(item.Guid, true).BuildBoxIcon; } catch { } list.Add(new Option { Code = "c:" + ((GUIDUnion)(ref item.Guid)).AsHex(), Kind = OptionKind.WeaponCrate, Guid = item.Guid, PrefabGuid = weaponCrateGuid, Name = item.Name, Context = item.Context, Icon = icon, Rarity = item.Rarity, Category = "WEAPON CRATES", CategoryOrder = 5 }); } } private static Option ItemOption(GUIDUnion guid, string category, int order) { //IL_0000: 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_003f: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) if (!CanSpawn(guid)) { return null; } ContextInfo val = ContextOf(guid); if (IsMissing(val)) { return null; } return new Option { Code = "i:" + ((GUIDUnion)(ref guid)).AsHex(), Kind = OptionKind.Item, Guid = guid, PrefabGuid = guid, Name = HeaderOf(val, "Item"), Context = val, Icon = val.Icon, Rarity = RarityOf(guid), Category = category, CategoryOrder = order }; } private static string ItemCategoryName(PurchasableItemSubCategory category) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 //IL_0005: 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_000a: Invalid comparison between Unknown and I4 //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 //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) //IL_0021: Expected I4, but got Unknown //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) //IL_0032: Invalid comparison between Unknown and I4 if ((int)category <= 35) { if (category - 17 <= 3) { return "ANIMUS CRATES"; } switch (category - 33) { case 0: return "AMMO & POWER"; case 1: return "SUPPORT"; case 2: return "MATERIALS"; } } else { if ((int)category == 49) { return "WEAPON MODS"; } if ((int)category == 50) { return "RELICS"; } if (category - 65 <= 1) { return "SPECIAL"; } } return "OTHER"; } private static int ItemCategoryOrder(PurchasableItemSubCategory category) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return ItemCategoryName(category) switch { "AMMO & POWER" => 1, "SUPPORT" => 2, "MATERIALS" => 3, "ANIMUS CRATES" => 4, "WEAPON MODS" => 6, "RELICS" => 7, "SPECIAL" => 8, _ => 9, }; } private unsafe static string CategoryName(ECategory category) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) try { string text = ECategoryExtension.ToStringLocalized(category); if (!string.IsNullOrEmpty(text)) { return text.ToUpperInvariant(); } } catch { } return ((object)(*(ECategory*)(&category))/*cast due to .constrained prefix*/).ToString().ToUpperInvariant(); } public static bool ShelfAccepts(ShelfInfo shelf, Option item) { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: 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) if (shelf.Slots.Count == 0) { return true; } string key = ((item.Kind == OptionKind.WeaponCrate) ? "crate" : item.Code); if (shelf.AcceptCache.TryGetValue(key, out var value)) { return value; } value = true; try { CarryablesSocket val = shelf.Slots[0]; bool flag = false; if (val.rejectedList != null) { CsObjectReference[] rejectedList = val.rejectedList; for (int i = 0; i < rejectedList.Length; i++) { bool? flag2 = QuickMatch(rejectedList[i], item.PrefabGuid); if (flag2 == true) { value = false; } if (!flag2.HasValue) { flag = true; } } } if (value) { bool? flag3 = QuickMatch(val.accepted, item.PrefabGuid); if (flag3 == false) { value = false; } if (!flag3.HasValue) { flag = true; } } if (value && flag) { ISelfReferencingResourceAsset asset = (ISelfReferencingResourceAsset)(object)((ResourceAssetDef<CarryableObject>)(object)((ResourceAssetContainer<CarryableContainer, CarryableObject, CarryableDef>)(object)ResourceAssetContainer<CarryableContainer, CarryableObject, CarryableDef>.Instance).GetAssetDefById(item.PrefabGuid, false))?.Asset; if (asset != null) { if (val.rejectedList != null && val.rejectedList.Any((CsObjectReference r) => r != null && r.IsInstanceOf(asset))) { value = false; } else if (val.accepted != null) { value = val.accepted.IsInstanceOf(asset); } } } } catch (Exception ex) { Log.Verbose("Could not check whether " + shelf.Name + " takes " + item.Name + ": " + ex.Message); value = true; } shelf.AcceptCache[key] = value; return value; } private static bool? QuickMatch(CsObjectReference rule, GUIDUnion item) { //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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Invalid comparison between Unknown and I4 //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) if (rule == null) { return false; } if (CompareMethodField == null) { return null; } Comparison val = (Comparison)CompareMethodField.GetValue(rule); if ((int)val != 0) { if ((int)val != 2) { if ((int)val == 5) { return true; } return null; } ResourceAssetRef val2 = (ResourceAssetRef)((PrefabRuleField != null) ? /*isinst with value type is only supported in some contexts*/: null); return val2 != (ResourceAssetRef)null && !val2.IsNull && val2.AssetGuid == item; } return false; } public static Option OptionFor(ShipSocketEntry entry) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (entry == null || (ResourceAssetRef)(object)entry.Module == (ResourceAssetRef)null || ((ResourceAssetRef)entry.Module).IsNull) { return null; } GUIDUnion val = WeaponGuidOf(entry.ExtraData); if (!((GUIDUnion)(ref val)).IsNull && TryGetOption("w:" + ((GUIDUnion)(ref val)).AsHex(), out var option)) { return option; } if (TryGetOption("m:" + ((GUIDUnion)(ref ((ResourceAssetRef)entry.Module).AssetGuid)).AsHex(), out option)) { return option; } return null; } public static string CodeFor(ShipAssetRef item) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_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) if (item == null || item.AssetRef == (ResourceAssetRef)null || item.IsNull) { return ""; } GUIDUnion val = WeaponGuidOf(item.ExtraData); if (!((GUIDUnion)(ref val)).IsNull) { return "c:" + ((GUIDUnion)(ref val)).AsHex(); } GUIDUnion assetGuid = item.AssetGuid; return "i:" + ((GUIDUnion)(ref assetGuid)).AsHex(); } public static GUIDUnion WeaponGuidOf(JObject extraData) { //IL_0012: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) JToken val = default(JToken); if (extraData == null || !extraData.TryGetValue("AssetGuid", ref val)) { return GUIDUnion.Empty(); } GUIDUnion val2 = default(GUIDUnion); ((GUIDUnion)(ref val2))..ctor(((object)val).ToString()); if (!((ResourceAssetContainer<CompositeWeaponDataContainer, CompositeWeaponData, CompositeWeaponDataDef>)(object)ResourceAssetContainer<CompositeWeaponDataContainer, CompositeWeaponData, CompositeWeaponDataDef>.Instance).HasItem(val2)) { return GUIDUnion.Empty(); } return val2; } public static bool TryGetPresetContents(GUIDUnion moduleOrWeapon, out JObject entry) { //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) if (!_presetContentsRead) { _presetContentsRead = true; foreach (ShipLoadoutDataDef assetDescription in ((ResourceAssetContainer<ShipLoadoutDataContainer, ShipLoadoutData, ShipLoadoutDataDef>)(object)ResourceAssetContainer<ShipLoadoutDataContainer, ShipLoadoutData, ShipLoadoutDataDef>.Instance).AssetDescriptions) { try { foreach (ShipSocketEntry socket in ((ResourceAssetDef<ShipLoadoutData>)(object)assetDescription).Asset.ShipLoadout.Sockets) { if (socket != null && !((ResourceAssetRef)(object)socket.Module == (ResourceAssetRef)null) && !((ResourceAssetRef)socket.Module).IsNull) { GUIDUnion key = WeaponGuidOf(socket.ExtraData); if (((GUIDUnion)(ref key)).IsNull) { key = ((ResourceAssetRef)socket.Module).AssetGuid; } bool flag = socket.Upgrades != null && socket.Upgrades.Any((ShipAssetRef u) => u != null && !u.IsNull); if (!PresetContents.TryGetValue(key, out var value) || (flag && !HasContents(value))) { PresetContents[key] = JObject.FromObject((object)socket); } } } } catch (Exception ex) { Log.Verbose("Skipped a loadout while reading module contents: " + ex.Message); } } } return PresetContents.TryGetValue(moduleOrWeapon, out entry); } private static bool HasContents(JObject entry) { JToken obj = entry["Upgrades"]; return ((IEnumerable<JToken>)((obj is JArray) ? obj : null))?.Any(delegate(JToken u) { //IL_0025: 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_0045: Unknown result type (might be due to invalid IL or missing references) if (u is JObject && u[(object)"AssetRef"] is JObject) { GUIDUnion val = new GUIDUnion(((object)((JObject)u[(object)"AssetRef"])["AssetGuid"])?.ToString()); return !((GUIDUnion)(ref val)).IsNull; } return false; }) ?? false; } public static ContextInfo ContextOf(GUIDUnion guid) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (((GUIDUnion)(ref guid)).IsNull) { return null; } IResourceAssetContextInfo context = ResourceAssetContainer<CloneStarObjectContainer, AbstractCloneStarObject, CloneStarObjectDef>.Instance.GetContext(guid); return (ContextInfo)(object)((context is ContextInfo) ? context : null); } public static string HeaderOf(ContextInfo context, string fallback) { try { string text = (((Object)(object)context != (Object)null) ? context.HeaderText : null); return string.IsNullOrEmpty(text) ? fallback : text; } catch { return fallback; } } private static bool IsMissing(ContextInfo context) { if ((Object)(object)context == (Object)null) { return true; } try { return (Object)(object)context == (Object)(object)DataTable<DefaultAssetTable>.Instance.MissingContextInfo; } catch { return false; } } public static RarityType RarityOf(GUIDUnion guid) { //IL_0005: 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_000b: 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_0013: Unknown result type (might be due to invalid IL or missing references) try { return ResourceAssetContainer<UnlockContainer, Object, UnlockItemDef>.Instance.GetRarity(guid); } catch { return (RarityType)0; } } private static bool TryGetSize(BuildingConstraints constraints, out BuildSize size) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected I4, but got Unknown size = (BuildSize)0; if (constraints == null) { return false; } try { size = (BuildSize)(int)BuildSizeExtensions.GetSize(constraints.Width, constraints.Height, constraints.Depth); return true; } catch { return false; } } public static string SizeName(BuildSize size) { //IL_0000: 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_0005: Invalid comparison between Unknown and I4 if ((int)size != 0) { if ((int)size == 1) { return "2x1"; } return "2x2"; } return "1x1"; } } internal static class CustomLoadouts { private sealed class Entry { public HullInfo Hull; public GUIDUnion Guid; public ShipLoadoutDataDef Def; public ShipLoadoutData Data; } public const string Header = "CUSTOM"; private static readonly Dictionary<GUIDUnion, Entry> ByShip = new Dictionary<GUIDUnion, Entry>(); private static readonly Dictionary<GUIDUnion, Entry> ByGuid = new Dictionary<GUIDUnion, Entry>(); private static readonly FieldInfo HeaderTextField = AccessTools.Field(typeof(ContextInfo), "headerTextDefaultable"); private static readonly FieldInfo BodyTextField = AccessTools.Field(typeof(ContextInfo), "bodyTextDefaultable"); public static bool Available; public static GUIDUnion ActiveShip = GUIDUnion.Empty(); public static HullConfig RemoteConfig; public static GUIDUnion ResumeShip = GUIDUnion.Empty(); public static bool IsActive => !((GUIDUnion)(ref ActiveShip)).IsNull; public static bool IsCustom(ShipLoadoutDataDef def) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (def != null) { return ByGuid.ContainsKey(((ResourceAssetDef<ShipLoadoutData>)(object)def).AssetGuid); } return false; } public static bool TryGetHullOfCustomGuid(GUIDUnion guid, out HullInfo hull) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) hull = (ByGuid.TryGetValue(guid, out var value) ? value.Hull : null); return hull != null; } public static bool TryGetHull(ShipLoadoutDataDef customDef, out HullInfo hull) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) hull = null; if (customDef != null) { return TryGetHullOfCustomGuid(((ResourceAssetDef<ShipLoadoutData>)(object)customDef).AssetGuid, out hull); } return false; } public static bool TryGetDef(GUIDUnion shipGuid, out ShipLoadoutDataDef def) { //IL_001a: 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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) def = null; if (!Available || ((GUIDUnion)(ref shipGuid)).IsNull) { return false; } if (!ByShip.TryGetValue(shipGuid, out var value)) { if (!Catalog.TryGetHull(shipGuid, out var hull)) { return false; } try { value = Create(hull); } catch (Exception ex) { Log.Error("Could not create the CUSTOM loadout for the " + hull.Name + ": " + ex); return false; } ByShip[shipGuid] = value; ByGuid[value.Guid] = value; } def = value.Def; return true; } private static Entry Create(HullInfo hull) { //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_000b: 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_004e: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_00d4: 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_005b: Unknown result type (might be due to invalid IL or missing references) GUIDUnion val = CustomGuidFor(hull.ShipGuid); ShipLoadoutData val2 = ScriptableObject.CreateInstance<ShipLoadoutData>(); ((Object)val2).name = "ShipCustomizer " + hull.Name; ((Object)val2).hideFlags = (HideFlags)32; ((SelfReferencingScriptableObject)val2).ContainerGuid = val; val2.ShipLoadout = Build(hull, ConfigToShow(hull)); if (!RuntimeAssetsRegister.Instance.HasAsset(val)) { RuntimeAssetsRegister.Instance.RegisterAsset(val, (Object)(object)val2, (SessionModificationEffect)0, (RuntimeAssetInfo)null); } ShipLoadoutDataDef val3 = new ShipLoadoutDataDef(val, ""); ((ResourceAssetDef<ShipLoadoutData>)(object)val3).Ref.IsRuntime = true; val3.LoadoutContextInfo = MakeContext(hull); Log.Info("Added a CUSTOM loadout for the " + hull.Name + " (shown to other players as " + LoadoutStore.PresetName(hull.BasePreset) + ")."); return new Entry { Hull = hull, Guid = val, Def = val3, Data = val2 }; } private static GUIDUnion CustomGuidFor(GUIDUnion ship) { //IL_0000: 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_0018: 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_0030: Unknown result type (might be due to invalid IL or missing references) return new GUIDUnion(ship.m_Value0 ^ 0x50494853, ship.m_Value1 ^ 0x54535543, ship.m_Value2 ^ 0x5A494D4F, ship.m_Value3 ^ 0x21215245); } private static ShipLoadoutContextInfo MakeContext(HullInfo hull) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown ShipLoadoutContextInfo val = Object.Instantiate<ShipLoadoutContextInfo>(hull.BasePreset.LoadoutContextInfo); ((Object)val).name = "ShipCustomizer CUSTOM " + hull.Name; ((Object)val).hideFlags = (HideFlags)32; string text = "<b>Custom Loadout</b>\n<i>Click a hardpoint on the ship, or use HARDPOINTS, to fit any module or weapon.</i>\nMissions flown with it are marked modded and earn no XP or rewards."; if (HeaderTextField != null) { HeaderTextField.SetValue(val, (object?)new DefaultableLocalizedString("CUSTOM", (LocalizedString)null)); } if (BodyTextField != null) { BodyTextField.SetValue(val, (object?)new DefaultableLocalizedString(text, (LocalizedString)null)); } return val; } public static HullConfig ConfigToShow(HullInfo hull) { //IL_000e: 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) if (!PhotonNetwork.IsMasterClient && RemoteConfig != null && ActiveShip == hull.ShipGuid) { return RemoteConfig; } return LoadoutStore.Get(hull); } public static bool CanEdit(HullInfo hull) { //IL_000e: 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) if (!PhotonNetwork.IsMasterClient && RemoteConfig != null) { return ActiveShip != hull.ShipGuid; } return true; } public static void Refresh(HullInfo hull) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (!ByShip.TryGetValue(hull.ShipGuid, out var value)) { return; } try { value.Data.ShipLoadout = Build(hull, ConfigToShow(hull)); } catch (Exception e) { Log.Failure("Rebuilding the CUSTOM loadout of the " + hull.Name, e); } } public static void RefreshAll() { foreach (Entry value in ByShip.Values) { Refresh(value.Hull); } } public unsafe static ShipLoadout Build(HullInfo hull, HullConfig config) { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Expected O, but got Unknown //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Expected O, but got Unknown //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Expected O, but got Unknown //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Expected O, but got Unknown //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Expected O, but got Unknown //IL_0348: Unknown result type (might be due to invalid IL or missing references) //IL_0356: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Unknown result type (might be due to invalid IL or missing references) //IL_0365: Expected O, but got Unknown ShipLoadout val = ShipLoadout.FromJObject(((ResourceAssetDef<ShipLoadoutData>)(object)hull.BasePreset).Asset.ShipLoadout.AsJObject()); val.Sockets = new List<ShipSocketEntry>(); HashSet<int> hashSet = new HashSet<int>(); foreach (KeyValuePair<int, string> slot in config.Slots) { if (slot.Key < 0 || slot.Key >= hull.Sockets.Count) { continue; } Option option; if (hull.Sockets[slot.Key].Overlaps.Any(hashSet.Contains)) { GUIDUnion shipGuid = hull.ShipGuid; Log.WarnOnce("overlap " + ((object)(*(GUIDUnion*)(&shipGuid))/*cast due to .constrained prefix*/).ToString() + slot.Key, "Hardpoint position " + slot.Key + " of the " + hull.Name + " overlaps a module that is already fitted, so it is left empty."); } else if (!Catalog.TryGetOption(slot.Value, out option) || (option.Kind != OptionKind.Module && option.Kind != OptionKind.Weapon) || !Catalog.CanSpawn(option.PrefabGuid)) { Log.WarnOnce("unknown " + slot.Value, "The CUSTOM " + hull.Name + " has a module the game no longer has (" + slot.Value + "); that hardpoint is left empty."); } else { ShipSocketEntry val2 = SocketEntryFor(option, slot.Key); if (val2 != null) { val.Sockets.Add(val2); hashSet.Add(slot.Key); } } } foreach (ShelfInfo shelf in hull.Shelves) { config.Storage.TryGetValue(shelf.CoreIndex, out var value); ShipSocketEntry val3 = ((IEnumerable<ShipSocketEntry>)val.CoreSystemSockets).FirstOrDefault((Func<ShipSocketEntry, bool>)((ShipSocketEntry c) => c != null && c.SocketId == shelf.CoreIndex)); if (val3 == null) { if (!Catalog.CanSpawn(shelf.ModuleGuid)) { continue; } val3 = new ShipSocketEntry { SocketId = shelf.CoreIndex, Module = new GameObjectRef(new ResourceAssetRef(shelf.ModuleGuid, false)), BuildBox = new CarryableRef(), Upgrades = (ShipAssetRef[])(object)new ShipAssetRef[0] }; val.CoreSystemSockets.Add(val3); } ShipAssetRef[] array = (ShipAssetRef[])(object)new ShipAssetRef[shelf.Slots.Count]; for (int num = 0; num < array.Length; num++) { array[num] = ItemFor((value != null && num < value.Count) ? value[num] : "", hull); } val3.Upgrades = array; } val.HomunculusOverride = new CarryableRef(); if (!string.IsNullOrEmpty(config.Homunculus) && Catalog.TryGetOption(config.Homunculus, out var option2) && Catalog.CanSpawn(option2.Guid)) { val.HomunculusOverride = new CarryableRef(option2.Guid); } return val; } private static ShipSocketEntry SocketEntryFor(Option option, int socketIndex) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_006b: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_00cf: Unknown result type (might be due to invalid IL or missing references) ShipSocketEntry val = null; if (Settings.CopyPresetModuleContents.Value && Catalog.TryGetPresetContents(option.Guid, out var entry)) { try { val = ((JToken)entry).ToObject<ShipSocketEntry>(); } catch (Exception ex) { Log.Verbose("Could not copy the contents of " + option.Name + " from the game's loadouts: " + ex.Message); } } if (val == null) { val = new ShipSocketEntry(); } val.SocketId = socketIndex; val.Module = new GameObjectRef(new ResourceAssetRef(option.PrefabGuid, false)); val.BuildBox = new CarryableRef(); if (val.Upgrades == null) { val.Upgrades = (ShipAssetRef[])(object)new ShipAssetRef[0]; } val.Upgrades = val.Upgrades.Select((ShipAssetRef u) => (ShipAssetRef)((u == null || u.IsNull || !Catalog.CanSpawn(u.AssetGuid)) ? ((object)new ShipAssetRef()) : ((object)u))).ToArray(); if (option.Kind == OptionKind.Weapon) { val.ExtraData = WeaponData(option.Guid); } return val; } private static ShipAssetRef ItemFor(string code, HullInfo hull) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0068: 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_00b9: Expected O, but got Unknown //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Expected O, but got Unknown //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Expected O, but got Unknown if (!string.IsNullOrEmpty(code)) { if (!Catalog.TryGetOption(code, out var option)) { Log.WarnOnce("unknown " + code, "The CUSTOM " + hull.Name + " has a storage item the game no longer has (" + code + "); that rack slot is left empty."); return new ShipAssetRef(); } if (option.Kind == OptionKind.WeaponCrate) { if (Catalog.CanSpawn(option.PrefabGuid)) { return new ShipAssetRef(new ResourceAssetRef(option.PrefabGuid, false)) { ExtraData = WeaponData(option.Guid) }; } return new ShipAssetRef(); } if (option.Kind == OptionKind.Item && Catalog.CanSpawn(option.Guid)) { return new ShipAssetRef(new ResourceAssetRef(option.Guid, false)); } return new ShipAssetRef(); } return new ShipAssetRef(); } private static JObject WeaponData(GUIDUnion weapon) { //IL_0005: 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_001b: Expected O, but got Unknown return JObject.FromObject((object)new CompositeWeaponDataRef(((ResourceAssetDef<CompositeWeaponData>)(object)((ResourceAssetContainer<CompositeWeaponDataContainer, CompositeWeaponData, CompositeWeaponDataDef>)(object)ResourceAssetContainer<CompositeWeaponDataContainer, CompositeWeaponData, CompositeWeaponDataDef>.Instance).GetAssetDefById(weapon, true)).Ref)); } public static bool TryMapToCustom(ShipLoadoutDataDef selected, out ShipLoadoutDataDef custom) { //IL_001c: 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_004a: Unknown result type (might be due to invalid IL or missing references) custom = null; if (selected == null || !IsActive || IsCustom(selected)) { return false; } if (!ByShip.TryGetValue(ActiveShip, out var value) || value.Hull.BasePreset == null) { return false; } if (((ResourceAssetDef<ShipLoadoutData>)(object)selected).AssetGuid != ((ResourceAssetDef<ShipLoadoutData>)(object)value.Hull.BasePreset).AssetGuid) { return false; } custom = value.Def; return true; } public static void ActivateAsHost(HullInfo hull) { //IL_0000: 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_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) bool num = ActiveShip != hull.ShipGuid; ActiveShip = hull.ShipGuid; RemoteConfig = null; Refresh(hull); RoomSync.PublishCustom(hull, LoadoutStore.Get(hull)); ModdingUtils.RegisterSessionMod(); if (num) { Log.Info("The room's loadout is now your CUSTOM " + hull.Name + " (" + Describe(LoadoutStore.Get(hull)) + ")."); } } public static void DeactivateAsHost() { //IL_0008: 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) if (IsActive) { HullInfo hull; string text = (Catalog.TryGetHull(ActiveShip, out hull) ? hull.Name : "ship"); ActiveShip = GUIDUnion.Empty(); RoomSync.ClearCustom(); Log.Info("The room's loadout is no longer the CUSTOM " + text + "."); } } public static void OnEdited(HullInfo hull) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) Refresh(hull); if (PhotonNetwork.IsMasterClient && ActiveShip == hull.ShipGuid) { RoomSync.PublishCustom(hull, LoadoutStore.Get(hull)); } } public static void OnMissionStarting(GameSession session, PreservedGameSession preserved) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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) if (!PhotonNetwork.IsMasterClient || session == null) { return; } bool flag = false; HullInfo hull; if (preserved != null) { flag = LoadoutStore.WasCustomRun(preserved.GameSessionID); if (flag) { Log.Info("Continuing a saved run that was started with a CUSTOM loadout; progression stays paused."); } } else if (IsActive && session.ToLoadShipData != null && Catalog.TryGetHull(ActiveShip, out hull) && hull.BasePreset != null && session.ToLoadShipGuid == ((ResourceAssetDef<ShipLoadoutData>)(object)hull.BasePreset).AssetGuid) { List<string> list = RoomSync.PlayersWithoutMod(giveJoinersTime: false); if (list.Count > 0) { Notice.Show("This mission starts with " + LoadoutStore.PresetName(hull.BasePreset) + " instead of CUSTOM: " + string.Join(", ", list.ToArray()) + " doesn't have Ship Customizer, and nobody may earn progression in a CUSTOM run."); } else if (!EnsureRoomMarkedModded()) { Notice.Show("This mission starts with " + LoadoutStore.PresetName(hull.BasePreset) + " instead of CUSTOM: the room is not marked [mod_session] yet."); } else { HullConfig config = LoadoutStore.Get(hull); session.ToLoadShipData = Build(hull, config); flag = true; Log.Info("Starting the mission with your CUSTOM " + hull.Name + ": " + Describe(config) + "."); } } if (flag && preserved != null) { List<string> list2 = RoomSync.PlayersWithoutMod(giveJoinersTime: false); if (list2.Count > 0) { Log.Warn("Continuing a saved CUSTOM run while " + string.Join(", ", list2.ToArray()) + " doesn't have Ship Customizer; their progression can't be paused."); } } ResumeShip = ((flag && preserved == null) ? ActiveShip : GUIDUnion.Empty()); ProgressionGuard.SetHostRun(flag); if (flag) { ModdingUtils.RegisterSessionMod(); RoomSync.CloseForCustomMission(); } } public static bool EnsureRoomMarkedModded() { if (ModdingUtils.IsCurrentSessionModded()) { return true; } ModdingUtils.RegisterSessionMod(); return ModdingUtils.IsCurrentSessionModded(); } public static void OnHubLoaded(HubShipManager manager) { //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_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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_004f: 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) if (PhotonNetwork.IsMasterClient && !((GUIDUnion)(ref ResumeShip)).IsNull && !((Object)(object)manager == (Object)null)) { GUIDUnion resumeShip = ResumeShip; ResumeShip = GUIDUnion.Empty(); if (Catalog.TryGetHull(resumeShip, out var hull) && !(manager.SelectedShipGuid != ((ResourceAssetDef<ShipLoadoutData>)(object)hull.BasePreset).AssetGuid) && TryGetDef(resumeShip, out var def)) { GUIDUnion assetGuid = ((ResourceAssetDef<ShipLoadoutData>)(object)def).AssetGuid; manager.SelectShip(((GUIDUnion)(ref assetGuid)).AsIntArray()); } } } public static void OnRoomChanged() { //IL_0000: 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_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) ActiveShip = GUIDUnion.Empty(); RemoteConfig = null; ResumeShip = GUIDUnion.Empty(); RefreshAll(); } public static string Describe(HullConfig config) { List<string> list = new List<string>(); foreach (string value in config.Slots.Values) { list.Add(Catalog.TryGetOption(value, out var option) ? option.Name : value); } return ((list.Count == 0) ? "no modules" : string.Join(", ", list.ToArray())) + "; " + config.StoredCount + " items in storage"; } } internal sealed class CustomizerRuntime : MonoBehaviour { private const float PollSeconds = 0.25f; private float _nextPoll; public static bool GameReady; private void Start() { if (!CustomLoadouts.Available) { return; } try { ModdingUtils.RegisterSessionMod(); Log.Info("Rooms you host are marked [mod_session] (the game's tag for mods that change the session), as Void Crew's modding guidelines ask."); } catch (Exception e) { Log.Failure("Marking hosted rooms as [mod_session]", e); } } private void Update() { if (!GameReady || Time.unscaledTime < _nextPoll) { return; } _nextPoll = Time.unscaledTime + 0.25f; try { RoomSync.Poll(); } catch (Exception e) { Log.Failure("Reading the room's ship customizer info", e); } try { ProgressionGuard.Poll(); } catch (Exception e2) { Log.Failure("Updating the progression pause", e2); } } } internal static class GameDataReport { private const int MaxLayoutLines = 600; public unsafe static void Write(VisualElement terminalRoot) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) string text = Path.Combine(LoadoutStore.Folder, "game-data.txt"); try { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("Void Crew Ship Customizer 0.3.0 game-data report"); stringBuilder.AppendLine("Written " + DateTime.Now.ToString("yyyy-MM-dd HH:mm") + " | game " + Application.version + " | Unity " + Application.unityVersion); stringBuilder.AppendLine(); stringBuilder.AppendLine("== SHIPS =="); foreach (GUIDUnion item in Catalog.ShipGuids()) { if (!Catalog.TryGetHull(item, out var hull)) { GUIDUnion val = item; stringBuilder.AppendLine("(could not read ship " + ((object)(*(GUIDUnion*)(&val))/*cast due to .constrained prefix*/).ToString() + ")"); } else { WriteHull(stringBuilder, hull); } } stringBuilder.AppendLine("== WEAPONS AND MODULES (" + Catalog.SlotOptions.Count + ") =="); foreach (Option slotOption in Catalog.SlotOptions) { stringBuilder.AppendLine(string.Format(" {0,-9} {1,-4} {2,-10} {3} {4}{5}", slotOption.Category, slotOption.HasSize ? Catalog.SizeName(slotOption.Size) : "?", Ui.RarityName(slotOption.Rarity), slotOption.Name, slotOption.Code, slotOption.SingleInstance ? " (one per ship)" : "")); } stringBuilder.AppendLine(); stringBuilder.AppendLine("== STORAGE ITEMS (" + Catalog.ItemOptions.Count + ") =="); foreach (Option itemOption in Catalog.ItemOptions) { stringBuilder.AppendLine($" {itemOption.Category,-14} {Ui.RarityName(itemOption.Rarity),-10} {itemOption.Name} {itemOption.Code}"); } stringBuilder.AppendLine(); stringBuilder.AppendLine("== HOMUNCULUS VARIANTS IN GAME LOADOUTS =="); foreach (Option homunculusOption in Catalog.HomunculusOptions) { stringBuilder.AppendLine(" " + homunculusOption.Name + " " + homunculusOption.Code); } stringBuilder.AppendLine(); stringBuilder.AppendLine("== TERMINAL SCREEN LAYOUT =="); if (terminalRoot != null) { int lines = 0; WriteTree(stringBuilder, terminalRoot, 0, ref lines); } else { stringBuilder.AppendLine(" (terminal not available)"); } Directory.CreateDirectory(LoadoutStore.Folder); File.WriteAllText(text, stringBuilder.ToString()); Log.Info("Wrote the game-data report to " + text + "."); } catch (Exception e) { Log.Failure("Writing the game-data report to " + text, e); } } private unsafe static void WriteHull(StringBuilder text, HullInfo hull) { //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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_0615: Unknown result type (might be due to invalid IL or missing references) //IL_056a: Unknown result type (might be due to invalid IL or missing references) //IL_056f: Unknown result type (might be due to invalid IL or missing references) string name = hull.Name; GUIDUnion shipGuid = hull.ShipGuid; text.AppendLine(name + " [" + ((object)(*(GUIDUnion*)(&shipGuid))/*cast due to .constrained prefix*/).ToString() + "]"); text.AppendLine(" CUSTOM is built on, and shown to other players as: " + LoadoutStore.PresetName(hull.BasePreset) + " [" + ((object)((ResourceAssetDef<ShipLoadoutData>)(object)hull.BasePreset).AssetGuid/*cast due to .constrained prefix*/).ToString() + "]"); text.AppendLine(" Loadouts (the terminal's list first, lowest rank first; then challenge and other loadouts):"); foreach (ShipLoadoutDataDef preset in hull.Presets) { text.AppendLine(" " + (hull.RegularPresets.Contains(preset) ? "" : "(not listed) ") + LoadoutStore.PresetName(preset) + " [" + ((object)((ResourceAssetDef<ShipLoadoutData>)(object)preset).AssetGuid/*cast due to .constrained prefix*/).ToString() + "]"); } text.AppendLine(" Hardpoint positions (" + hull.Sockets.Count + " in " + hull.GroupCount + " hardpoints):"); foreach (SocketInfo socket in hull.Sockets) { text.AppendLine(string.Format(" #{0,-2} {1} hardpoint {2} overlaps [{3}] cells {4}", socket.Index, Catalog.SizeName(socket.Size), socket.Group + 1, string.Join(",", socket.Overlaps.Select((int i) => i.ToString()).ToArray()), string.Join(" ", socket.Cells.Select((Vector3 c) => "(" + c.x.ToString("0.#") + "," + c.y.ToString("0.#") + "," + c.z.ToString("0.#") + ")").ToArray()))); } text.AppendLine(" Storage racks:"); foreach (ShelfInfo shelf in hull.Shelves) { CarryablesSocket val = shelf.Slots.FirstOrDefault(); text.AppendLine(string.Format(" {0}: core system #{1} [{2}] {3} slots; accepts {4}; rejects {5}", shelf.Name, shelf.CoreIndex, shelf.ModuleGuid, shelf.Slots.Count, ((Object)(object)val != (Object)null) ? Describe(val.accepted) : "?", ((Object)(object)val != (Object)null && val.rejectedList != null && val.rejectedList.Length != 0) ? string.Join(", ", val.rejectedList.Select(Describe).ToArray()) : "nothing")); } text.AppendLine(" Game loadouts' contents:"); foreach (ShipLoadoutDataDef preset2 in hull.Presets) { try { ShipLoadout shipLoadout = ((ResourceAssetDef<ShipLoadoutData>)(object)preset2).Asset.ShipLoadout; text.AppendLine(" " + LoadoutStore.PresetName(preset2) + ":"); foreach (ShipSocketEntry socket2 in shipLoadout.Sockets) { if (socket2 != null && !((ResourceAssetRef)(object)socket2.Module == (ResourceAssetRef)null) && !((ResourceAssetRef)socket2.Module).IsNull) { Option option = Catalog.OptionFor(socket2); int num = ((socket2.Upgrades != null) ? socket2.Upgrades.Count((ShipAssetRef u) => u != null && !u.IsNull) : 0); text.AppendLine(string.Format(" hardpoint #{0}: {1} ({2}){3}", socket2.SocketId, (option != null) ? option.Name : "?", (option != null) ? option.Code : ((object)Unsafe.As<GUIDUnion, GUIDUnion>(ref ((ResourceAssetRef)socket2.Module).AssetGuid)/*cast due to .constrained prefix*/).ToString(), (num > 0) ? (", stocked with " + string.Join(", ", (from u in socket2.Upgrades where u != null && !u.IsNull select NameOfItem(Catalog.CodeFor(u))).ToArray())) : "")); if ((ResourceAssetRef)(object)socket2.BuildBox != (ResourceAssetRef)null && !((ResourceAssetRef)socket2.BuildBox).IsNull) { string text2 = socket2.SocketId.ToString(); shipGuid = ((ResourceAssetRef)socket2.BuildBox).AssetGuid; text.AppendLine(" hardpoint #" + text2 + " also has a crate: " + ((object)(*(GUIDUnion*)(&shipGuid))/*cast due to .constrained prefix*/).ToString()); } } } foreach (ShipSocketEntry coreSystemSocket in shipLoadout.CoreSystemSockets) { if (coreSystemSocket.Upgrades != null && !coreSystemSocket.Upgrades.All((ShipAssetRef u) => u == null || u.IsNull)) { text.AppendLine(string.Format(" core system #{0} ({1}): {2}", coreSystemSocket.SocketId, Catalog.HeaderOf(Catalog.ContextOf(((ResourceAssetRef)coreSystemSocket.Module).AssetGuid), ((object)Unsafe.As<GUIDUnion, GUIDUnion>(ref ((ResourceAssetRef)coreSystemSocket.Module).AssetGuid)/*cast due to .constrained prefix*/).ToString()), string.Join(", ", coreSystemSocket.Upgrades.Select((ShipAssetRef u) => (u != null && !u.IsNull) ? NameOfItem(Catalog.CodeFor(u)) : "-").ToArray()))); } } if ((ResourceAssetRef)(object)shipLoadout.HomunculusOverride != (ResourceAssetRef)null && !((ResourceAssetRef)shipLoadout.HomunculusOverride).IsNull) { text.AppendLine(" homunculus: " + NameOfItem("i:" + ((GUIDUnion)(ref ((ResourceAssetRef)shipLoadout.HomunculusOverride).AssetGuid)).AsHex())); } if (shipLoadout.AdditionalAssets != null && shipLoadout.AdditionalAssets.Count > 0) { text.AppendLine(" extra loose items: " + shipLoadout.AdditionalAssets.Count); } } catch (Exception ex) { text.AppendLine(" (could not read: " + ex.Message + ")"); } } text.AppendLine(); } private static string NameOfItem(string code) { if (!Catalog.TryGetOption(code, out var option)) { return code; } return option.Name; } private static string Describe(CsObjectReference reference) { if (reference == null) { return "?"; } try { Traverse val = Traverse.Create((object)reference); object value = val.Field("compareMethod").GetValue(); string text = ""; if (value != null && value.ToString() == "Type") { object value2 = val.Field("type").Property("Type", (object[])null).GetValue(); text = " " + ((value2 != null) ? value2.ToString() : "?"); } else if (value != null && value.ToString() == "Prefab") { object value3 = val.Field("orbitObjectRef").GetValue(); ResourceAssetRef val2 = (ResourceAssetRef)((value3 is ResourceAssetRef) ? value3 : null); text = " " + ((val2 != (ResourceAssetRef)null) ? NameOfItem("i:" + ((GUIDUnion)(ref val2.AssetGuid)).AsHex()) : "?"); } return ((value != null) ? value.ToString() : "?") + text; } catch (Exception ex) { return "? (" + ex.Message + ")"; } } private static void WriteTree(StringBuilder text, VisualElement element, int depth, ref int lines) { //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_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Invalid comparison between Unknown and I4 if (lines >= 600 || element == null || (element.name != null && element.name.StartsWith("ShipCustomizer"))) { return; } Rect worldBound = element.worldBound; string text2 = string.Join(" ", element.GetClasses().ToArray()); text.AppendLine(string.Format("{0}{1} \"{2}\" [{3}] x{4:0} y{5:0} w{6:0} h{7:0}{8}", new string(' ', 2 + depth * 2), ((object)element).GetType().Name, element.name, text2, ((Rect)(ref worldBound)).x, ((Rect)(ref worldBound)).y, ((Rect)(ref worldBound)).width, ((Rect)(ref worldBound)).height, ((int)element.resolvedStyle.display == 1) ? " hidden" : "")); lines++; if (depth >= 12) { return; } foreach (VisualElement item in element.Children()) { WriteTree(text, item, depth + 1, ref lines); } } } internal static class Hardpoints { public const float CellSize = 4f; public static Vector3[] CellsFor(BuildSize size, Vector3 position, Vector3 right, Vector3 forward) { //IL_0000: 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_0052: 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_0063: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) int num = default(int); int num2 = default(int); int num3 = default(int); BuildSizeExtensions.GetDimensions(size, ref num, ref num2, ref num3); float num4 = (float)(num / 2) - 0.5f * (float)(1 - num % 2); float num5 = (float)(num3 / 2) - 0.5f * (float)(1 - num3 % 2); Vector3[] array = (Vector3[])(object)new Vector3[num * num3]; int num6 = 0; for (int i = 0; i < num3; i++) { for (int j = 0; j < num; j++) { array[num6++] = position + right * (((float)j - num4) * 4f) + forward * (((float)i - num5) * 4f); } } return array; } public static int LinkOverlaps(List<SocketInfo> sockets) { foreach (SocketInfo socket in sockets) { socket.Overlaps.Clear(); socket.Group = -1; } for (int i = 0; i < sockets.Count; i++) { for (int j = i + 1; j < sockets.Count; j++) { if (CellsOverlap(sockets[i], sockets[j])) { sockets[i].Overlaps.Add(j); sockets[j].Overlaps.Add(i); } } } int num = 0; foreach (SocketInfo socket2 in sockets) { if (socket2.Group >= 0) { continue; } Stack<SocketInfo> stack = new Stack<SocketInfo>(); socket2.Group = num; stack.Push(socket2); while (stack.Count > 0) { foreach (int overlap in stack.Pop().Overlaps) { if (sockets[overlap].Group < 0) { sockets[overlap].Group = num; stack.Push(sockets[overlap]); } } } num++; } return num; } private static bool CellsOverlap(SocketInfo a, SocketInfo b) { //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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_002a: 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) Vector3[] cells = a.Cells; foreach (Vector3 val in cells) { Vector3[] cells2 = b.Cells; foreach (Vector3 val2 in cells2) { Vector3 val3 = val - val2; if (((Vector3)(ref val3)).sqrMagnitude < 4f) { return true; } } } return false; } public static HashSet<int> OfferedEmpty(List<SocketInfo> sockets, ICollection<int> fitted, int drawnCount) { HashSet<int> hashSet = new HashSet<int>(); foreach (SocketInfo item in from s in sockets orderby (int)s.Size descending, s.Index select s) { if (item.Index < drawnCount && !fitted.Contains(item.Index) && !item.Overlaps.Any(fitted.Contains) && !item.Overlaps.Any(hashSet.Contains)) { hashSet.Add(item.Index); } } return hashSet; } public static SocketInfo TargetFor(BuildSize size, SocketInfo clicked, List<SocketInfo> sockets, ICollection<int> fitted, int drawnCount) { //IL_000e: 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_0024: 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) if (clicked.Size == size) { return clicked; } return (from i in clicked.Overlaps select sockets[i] into s where s.Size == size && s.Index < drawnCount orderby fitted.Count((int k) => k == s.Index || s.Overlaps.Contains(k)), s.Index select s).FirstOrDefault(); } public static List<int> Displaced(SocketInfo target, ICollection<int> fitted) { return fitted.Where((int k) => k == target.Index || target.Overlaps.Contains(k)).ToList(); } } internal sealed class HullConfig { public SortedDictionary<int, string> Slots = new SortedDictionary<int, string>(); public SortedDictionary<int, List<string>> Storage = new SortedDictionary<int, List<string>>(); public string Homunculus = ""; public string CopiedFrom = ""; public int FittedCount => Slots.Count; public int StoredCount => Storage.Values.Sum((List<string> rack) => rack.Count((string code) => !string.IsNullOrEmpty(code))); public HullConfig Clone() { return JsonConvert.DeserializeObject<HullConfig>(JsonConvert.SerializeObject((object)this)); } } internal static class LoadoutStore { private sealed class StoreFile { public int Version = 1; public Dictionary<string, HullConfig> Ships = new Dictionary<string, HullConfig>(); public List<string> CustomRuns = new List<string>(); } private const int MaxRememberedRuns = 50; private static StoreFile _file; public static string Folder => Path.Combine(Application.persistentDataPath, "ShipCustomizer"); private static string FilePath => Path.Combine(Folder, "custom-loadouts.json"); private static StoreFile File { get { if (_file != null) { return _file; } try { if (System.IO.File.Exists(FilePath)) { _file = JsonConvert.DeserializeObject<StoreFile>(System.IO.File.ReadAllText(FilePath)); Log.Info("Loaded your Custom loadouts from " + FilePath + "."); } } catch (Exception ex) { string text = FilePath + ".broken"; Log.Error("Could not read " + FilePath + ", so the Custom loadouts start fresh. The old file is kept as " + text + ". Details: " + ex.Message); try { System.IO.File.Copy(FilePath, text, overwrite: true); } catch { } } if (_file == null) { _file = new StoreFile(); } if (_file.Ships == null) { _file.Ships = new Dictionary<string, HullConfig>(); } if (_file.CustomRuns == null) { _file.CustomRuns = new List<string>(); } return _file; } } public static HullConfig Get(HullInfo hull) { if (File.Ships.TryGetValue(((GUIDUnion)(ref hull.ShipGuid)).AsHex(), out var value) && value != null) { if (value.Slots == null) { value.Slots = new SortedDictionary<int, string>(); } if (value.Storage == null) { value.Storage = new SortedDictionary<int, List<string>>(); } if (value.Homunculus == null) { value.Homunculus = ""; } return value; } value = FromGameLoadout(hull, hull.BasePreset); File.Ships[((GUIDUnion)(ref hull.ShipGuid)).AsHex()] = value; return value; } public static void Set(HullInfo hull, HullConfig config) { File.Ships[((GUIDUnion)(ref hull.ShipGuid)).AsHex()] = config; Save(); } public static void Save() { try { Directory.CreateDirectory(Folder); string text = FilePath + ".tmp"; System.IO.File.WriteAllText(text, JsonConvert.SerializeObject((object)File, (Formatting)1)); if (System.IO.File.Exists(FilePath)) { System.IO.File.Delete(FilePath); } System.IO.File.Move(text, FilePath); } catch (Exception e) { Log.Failure("Saving the Custom loadouts to " + FilePath, e); } } public static HullConfig FromGameLoadout(HullInfo hull, ShipLoadoutDataDef preset) { HullConfig hullConfig = new HullConfig { CopiedFrom = PresetName(preset) }; ShipLoadout shipLoadout = ((ResourceAssetDef<ShipLoadoutData>)(object)preset).Asset.ShipLoadout; foreach (ShipSocketEntry socket in shipLoadout.Sockets) { if (socket != null && !((ResourceAssetRef)(object)socket.Module == (ResourceAssetRef)null) && !((ResourceAssetRef)socket.Module).IsNull && socket.SocketId >= 0 && socket.SocketId < hull.Sockets.Count) { Option option = Catalog.OptionFor(socket); if (option != null) { hullConfig.Slots[socket.SocketId] = option.Code; continue; } Log.Warn("The " + hullConfig.CopiedFrom + " loadout has a module the customizer doesn't know (" + ((object)socket)?.ToString() + "); it is left out of the copy."); } } foreach (ShelfInfo shelf in hull.Shelves) { ShipSocketEntry val = ((IEnumerable<ShipSocketEntry>)shipLoadout.CoreSystemSockets).FirstOrDefault((Func<ShipSocketEntry, bool>)((ShipSocketEntry c) => c != null && c.SocketId == shelf.CoreIndex)); List<string> list = new List<string>(); for (int num = 0; num < shelf.Slots.Count; num++) { list.Add((val != null && val.Upgrades != null && num < val.Upgrades.Length) ? Catalog.CodeFor(val.Upgrades[num]) : ""); } hullConfig.Storage[shelf.CoreIndex] = list; } CarryableRef homunculusOverride = shipLoadout.HomunculusOverride; hullConfig.Homunculus = (((ResourceAssetRef)(object)homunculusOverride != (ResourceAssetRef)null && !((ResourceAssetRef)homunculusOverride).IsNull) ? ("i:" + ((GUIDUnion)(ref ((ResourceAssetRef)homunculusOverride).AssetGuid)).AsHex()) : ""); return hullConfig; } public static string PresetName(ShipLoadoutDataDef preset) { try { string text = (((Object)(object)preset.LoadoutContextInfo != (Object)null) ? ((ContextInfo)preset.LoadoutContextInfo).HeaderText : null); if (!string.IsNullOrEmpty(text)) { return text; } } catch { } try { return ((Object)(object)((ResourceAssetDef<ShipLoadoutData>)(object)preset).Asset != (Object)null) ? ((Object)((ResourceAssetDef<ShipLoadoutData>)(object)preset).Asset).name : "loadout"; } catch { return "loadout"; } } public static void RememberCustomRun(string gameSessionId) { if (!string.IsNullOrEmpty(gameSessionId) && !File.CustomRuns.Contains(gameSessionId)) { File.CustomRuns.Add(gameSessionId); while (File.CustomRuns.Count > 50) { File.CustomRuns.RemoveAt(0); } Save(); } } public static bool WasCustomRun(string gameSessionId) { if (!string.IsNullOrEmpty(gameSessionId)) { return File.CustomRuns.Contains(gameSessionId); } return false; } } internal static class Log { private static ManualLogSource _source; private static readonly HashSet<string> OnceKeys = new HashSet<string>(); private static readonly Dictionary<string, int> FailureCounts = new Dictionary<string, int>(); public static void Init(ManualLogSource source) { _source = source; } public static void Info(string message) { _source.LogInfo((object)message); } public static void Warn(string message) { _source.LogWarning((object)message); } public static void Error(string message) { _source.LogError((object)message); } public static void Verbose(string message) { if (Settings.VerboseLogging != null && Settings.VerboseLogging.Value) { _source.LogInfo((object)("[verbose] " + message)); } } public static void InfoOnce(string key, string message) { if (OnceKeys.Add(key)) { Info(message); } } public static void WarnOnce(string key, string message) { if (OnceKeys.Add(key)) { Warn(message); } } public static void Failure(string operation, Exception e) { FailureCounts.TryGetValue(operation, out var value); value = (FailureCounts[operation] = value + 1); switch (value) { case 1: Error(operation + " failed: " + e); break; default: if (value % 1000 != 0) { break; } goto case 10; case 10: Error(operation + " has now failed " + value + " times. Latest: " + e.GetType().Name + ": " + e.Message); break; } } } internal static class Notice { private const string Sender = "Ship Customizer"; public static void Show(string message) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) Log.Info(message); try { if ((Object)(object)TextChat.Instance != (Object)null) { TextChat.Instance.AddLog(new LogEntry("Ship Customizer", message)); } } catch (Exception ex) { Log.Verbose("Could not show a notice in the chat: " + ex.Message); } TerminalUi.ShowToast(message); } } internal static class Patches { private static Harmony _harmony; private static FieldRef<HubShipManager, ShipLoadoutDataDef> _currentShip; private static FieldInfo _selectionChanged; public static void Apply(Harmony harmony) { _harmony = harmony; bool num = Patch("HubShipManager", "SelectShip", "SelectShipPrefix", null) & Patch("HubShipManager", "get_CurrentShipSelected", null, "CurrentShipSelectedPostfix") & Patch("CG.GameLoopStateMachine.GameStates.GSIngame", "TransitionTo", "TransitionToPrefix", null) & Patch("UI.ShipLoadoutTerminal.LoadoutList", "SetSource", "SetSourcePrefix", null) & Patch("UI.ShipLoadoutTerminal.LoadoutList", "Sort", "SortPrefix", null) & Patch("UI.ShipLoadoutTerminal.LoadoutList", "BindItem", "BindItemPrefix", null) & Patch("UI.ShipLoadoutTerminal.ModuleLayout", "Show", null, "ModuleLayoutShowPostfix") & Patch("UI.ShipLoadoutTerminal.ShipLoadoutTerminal", "Display", null, "DisplayPostfix") & Patch("CG.Profile.PlayerRewardsCollection", "AddItem", "BlockRewardsPrefix", null); _currentShip = AccessTools.FieldRefAccess<HubShipManager, ShipLoadoutDataDef>("_currentShipSelected"); _selectionChanged = AccessTools.Field(typeof(HubShipManager), "ShipSelectionChanged"); if (_currentShip != null && _selectionChanged != null) { Patch("HubShipManager", "NotifyShipSelected", "NotifyShipSelectedPrefix", null); } else { Log.Warn("Could not find HubShipManager's selection fields; the terminal will show the stand-in loadout as chosen instead of CUSTOM."); } Patch("HubShipManager", "Start", null, "HubStartPostfix"); Patch("Gameplay.Hub.HubQuestManager", "SelectPreservedSessionQuest", "SelectSavedRunPrefix", null); Patch("UI.ShipLoadoutTerminal.ShipLoadoutTerminal", "OnDestroy", "TerminalDestroyPrefix", null); Patch("UI.ShipLoadoutTerminal.ShipLoadoutTerminal", "OnLeaveUI", null, "TerminalLeavePostfix"); Patch("CG.Cloud.CloudRewardsProfileSync", "AddItem", "BlockRewardsPrefix", null); Patch("CG.Profile.PlayerAchievements", "SetAchievementComplete", "BlockAchievementsPrefix", null); Patch("SteamPlayerAchievementsSync", "SetAchievementComplete", "BlockAchievementsPrefix", null); Patch("CG.Cloud.CloudPlayerAchievementsSync", "SetAchievementComplete", "BlockAchievementsPrefix", null); Patch("CG.Profile.PlayerProfileData", "AddQuestProgress", "BlockQuestProgressPrefix", null); Patch("CG.Cloud.CloudPlayerProfileDataSync", "AddQuestProgress", "BlockQuestProgressPrefix", null); Patch("CG.Profile.PhotonPlayerDataSync", "AddQuestProgress", "BlockQuestProgressPrefix", null); CustomLoadouts.Available = num; if (num) { Log.Info("All game patches are in; the CUSTOM loadout is available at the ship loadout terminal."); } else { Log.Error("Some patches the CUSTOM loadout needs could not be applied (see above), so it is turned off. The game itself is unaffected."); } } private static bool Patch(string typeName, string methodName, string prefix, string postfix) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown try { Type type = AccessTools.TypeByName(typeName); if (type == null) { throw new MissingMemberException("type " + typeName + " not found"); } MethodBase methodBase = AccessTools.Method(type, methodName, (Type[])null, (Type[])null); if (methodBase == null) { throw new MissingMethodException(typeName, methodName); } PatchProcessor val = _harmony.CreateProcessor(methodBase); if (prefix != null) { val.AddPrefix(new HarmonyMethod(AccessTools.Method(typeof(Patches), prefix, (Type[])null, (Type[])null))); } if (postfix != null) { val.AddPostfix(new HarmonyMethod(AccessTools.Method(typeof(Patches), postfix, (Type[])null, (Type[])null))); } val.Patch(); Log.Verbose("Patched " + typeName + "." + methodName + "."); return true; } catch (Exception ex) { Log.Error("Could not patch " + typeName + "." + methodName + " (the game may have changed): " + ex.Message); return false; } } private static bool SelectShipPrefix(HubShipManager __instance, ref int[] guid) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) try { if (CustomLoadouts.TryGetHullOfCustomGuid(new GUIDUnion(guid), out var hull)) { if (!CustomLoadouts.Available) { return false; } if (!PhotonNetwork.IsMasterClient) { TerminalUi.Toast("Only the host can choose the CUSTOM loadout."); return false; } List<string> list = RoomSync.PlayersWithoutMod(giveJoinersTime: false); if (list.Count > 0) { Notice.Show("Everyone in the room needs Ship Customizer for CUSTOM. Not yet: " + string.Join(", ", list.ToArray()) + ". (Just joined? Try again in a few seconds.)"); return false; } if (!CustomLoadouts.EnsureRoomMarkedModded()) { TerminalUi.Toast("Marking the room [mod_session] first; choose CUSTOM again in a moment."); return false; } CustomLoadouts.ActivateAsHost(hull); GUIDUnion assetGuid = ((ResourceAssetDef<ShipLoadoutData>)(object)hull.BasePreset).AssetGuid; guid = ((GUIDUnion)(ref assetGuid)).AsIntArray(); return true; } if (PhotonNetwork.IsMasterClient) { CustomLoadouts.DeactivateAsHost(); } } catch (Exception e) { Log.Failure("Choosing a ship loadout", e); } return true; } private static bool NotifyShipSelectedPrefix(HubShipManager __instance, int[] guid) { //IL_0008: 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_0020: 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_001d: 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) ShipLoadoutDataDef obj; try { GUIDUnion assetGuid = default(GUIDUnion); ((GUIDUnion)(ref assetGuid))..ctor(guid); if (CustomLoadouts.TryGetHullOfCustomGuid(assetGuid, out var hull)) { assetGuid = ((ResourceAssetDef<ShipLoadoutData>)(object)hull.BasePreset).AssetGuid; } __instance.SelectedShipGuid = assetGuid; ShipLoadoutDataDef val = (((GUIDUnion)(ref assetGuid)).IsNull ? null : ((ResourceAssetContainer<ShipLoadoutDataContainer, ShipLoadoutData, ShipLoadoutDataDef>)(object)ResourceAssetContainer<ShipLoadoutDataContainer, ShipLoadoutData, ShipLoadoutDataDef>.Instance).GetAssetDefById(assetGuid, true)); _currentShip.Invoke(__instance) = val; obj = (CustomLoadouts.TryMapToCustom(val, out var custom) ? custom : val); } catch (Exception e) { Log.Failure("Showing the chosen ship loadout", e); return true; } if (_selectionChanged.GetValue(__instance) is Action<ShipLoadoutDataDef> action) { action(obj); } return false; } private static void CurrentShipSelectedPostfix(ref ShipLoadoutDataDef __result) { try { if (__result != null && CustomLoadouts.TryMapToCustom(__result, out var custom)) { __result = custom; } } catch (Exception e) { Log.Failure("Reading the chosen ship loadout", e); } } private static void TransitionToPrefix(GameSession gameSession, PreservedGameSession preservedGameSession) { try { CustomizerRuntime.GameReady = true; CustomLoadouts.OnMissionStarting(gameSession, preservedGameSession); } catch (Exception e) { Log.Failure("Swapping in the CUSTOM ship at mission start (the mission starts with the stand-in loadout instead)", e); } } priv