using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ChatCommandAPI; using ChatCommandAPI.Old; using ChatCommandAPI.Utils; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("baer1.ShipSort")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("4.0.2.0")] [assembly: AssemblyInformationalVersion("4.0.2+25d2ee586970f13edc069483ea8944e8f258fa04")] [assembly: AssemblyProduct("LethalShipSort")] [assembly: AssemblyTitle("baer1.ShipSort")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("4.0.2.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LethalShipSort { public class AutoSortToggle : LegacyToggleCommand { public override string Name => "AutoSort"; public override string ToggleDescription => "Toggles automatic item sorting when leaving a planet"; public override bool Value { get { return LethalShipSort.Instance.AutoSort; } set { LethalShipSort.Instance.AutoSort = value; } } } public struct ItemPosition { public struct Flags { public const char NO_AUTO_SORT = 'A'; public bool NoAutoSort; public const char KEEP_ON_CRUISER = 'C'; public bool KeepOnCruiser; public const char IGNORE = 'N'; public bool Ignore; public const char PARENT = 'P'; public bool Parent; public const char EXACT = 'X'; public bool Exact; public Flags(string s) { NoAutoSort = false; KeepOnCruiser = false; Ignore = false; Parent = false; Exact = false; foreach (char c in s) { switch (c) { case 'A': NoAutoSort = true; break; case 'C': KeepOnCruiser = true; break; case 'N': Ignore = true; break; case 'P': Parent = true; break; case 'X': Exact = true; break; default: throw new ArgumentException($"Unknown flag ({c})"); } } } public override string ToString() { return $"{(NoAutoSort ? ((object)'A') : string.Empty)}{(KeepOnCruiser ? ((object)'C') : string.Empty)}{(Ignore ? ((object)'N') : string.Empty)}{(Parent ? ((object)'P') : string.Empty)}{(Exact ? ((object)'X') : string.Empty)}"; } public Flags FilterPositionRelated() { return this & new Flags { Parent = true, Exact = true }; } public Flags FilterFilteringRelated() { return this & new Flags { NoAutoSort = true, KeepOnCruiser = true, Ignore = true }; } public static Flags operator |(Flags _this, Flags other) { return new Flags { NoAutoSort = (_this.NoAutoSort || other.NoAutoSort), KeepOnCruiser = (_this.KeepOnCruiser || other.KeepOnCruiser), Ignore = (_this.Ignore || other.Ignore), Parent = (_this.Parent || other.Parent), Exact = (_this.Exact || other.Exact) }; } public static Flags operator &(Flags _this, Flags other) { return new Flags { NoAutoSort = (_this.NoAutoSort && other.NoAutoSort), KeepOnCruiser = (_this.KeepOnCruiser && other.KeepOnCruiser), Ignore = (_this.Ignore && other.Ignore), Parent = (_this.Parent && other.Parent), Exact = (_this.Exact && other.Exact) }; } } public Vector3? position; public Vector3? positionOffset; public GameObject? parentTo; public int? floorYRot; public int? rotationOffset; public float? randomOffset; public Flags flags; public ItemPosition(string s) { //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) position = null; positionOffset = null; parentTo = null; floorYRot = null; rotationOffset = null; randomOffset = null; Match match = new Regex("(?:([\\w/\\\\]+):)?(?:(-?\\d+(?:\\.\\d+)?)([+-]\\d+(?:\\.\\d+)?)?,)(?:(-?\\d+(?:\\.\\d+)?)([+-]\\d+(?:\\.\\d+)?)?,)(-?\\d+(?:\\.\\d+)?)([+-]\\d+(?:\\.\\d+)?)?(?:,(\\d+)([+-]\\d+)?)?(?:,(\\d+(?:\\.\\d+)?))?(?::([A-Z]+))?$", RegexOptions.Multiline).Match(s); if (!match.Success) { Match match2 = new Regex("([A-Z]+)$", RegexOptions.Multiline).Match(s); if (!match2.Success) { throw new ArgumentException("Invalid format (" + s + ")"); } StringBuilder stringBuilder = new StringBuilder(">> ItemPosition init flags \"" + s + "\""); flags = new Flags(match2.Groups[1].Value); LethalShipSort.Logger.LogDebug((object)stringBuilder.ToString()); return; } StringBuilder stringBuilder2 = new StringBuilder(">> ItemPosition init \"" + s + "\""); string value = match.Groups[2].Value; string value2 = match.Groups[4].Value; string value3 = match.Groups[6].Value; if (!float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { throw new ArgumentException("Invalid x value (" + value + ")"); } if (!float.TryParse(value2, NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) { throw new ArgumentException("Invalid y value (" + value2 + ")"); } if (!float.TryParse(value3, NumberStyles.Float, CultureInfo.InvariantCulture, out var result3)) { throw new ArgumentException("Invalid z value (" + value3 + ")"); } position = new Vector3(result, result2, result3); stringBuilder2.Append($"\n position is {position}"); string value4 = match.Groups[3].Value; string value5 = match.Groups[5].Value; string value6 = match.Groups[7].Value; float? num = null; float? num2 = null; float? num3 = null; if (match.Groups[3].Success) { if (!float.TryParse(value4, NumberStyles.Float, CultureInfo.InvariantCulture, out var result4)) { throw new ArgumentException("Invalid xoffset value (" + value4 + ")"); } num = result4; } if (match.Groups[5].Success) { if (!float.TryParse(value5, NumberStyles.Float, CultureInfo.InvariantCulture, out var result5)) { throw new ArgumentException("Invalid yoffset value (" + value2 + ")"); } num2 = result5; } if (match.Groups[7].Success) { if (!float.TryParse(value6, NumberStyles.Float, CultureInfo.InvariantCulture, out var result6)) { throw new ArgumentException("Invalid zoffset value (" + value3 + ")"); } num3 = result6; } if (num.HasValue || num2.HasValue || num3.HasValue) { positionOffset = new Vector3(num.GetValueOrDefault(), num2.GetValueOrDefault(), num3.GetValueOrDefault()); stringBuilder2.Append($"\n fixed positional offset is {positionOffset}"); } else { stringBuilder2.Append("\n fixed positional offset is not specified"); } string value7 = match.Groups[8].Value; if (match.Groups[8].Success) { if (!int.TryParse(value7, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result7)) { throw new ArgumentException("Invalid floorYRot value (" + value7 + ")"); } floorYRot = result7; stringBuilder2.Append($"\n rotation is {floorYRot}"); } else { stringBuilder2.Append("\n rotation not specified"); } string value8 = match.Groups[9].Value; if (match.Groups[9].Success) { if (!int.TryParse(value8, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result8)) { throw new ArgumentException("Invalid roffset value (" + value8 + ")"); } rotationOffset = ((result8 == 0) ? ((int?)null) : new int?(result8)); stringBuilder2.Append($"\n rotational offset is {result8}"); } else { stringBuilder2.Append("\n rotational offset not specified"); } string value9 = match.Groups[10].Value; if (match.Groups[10].Success) { if (!float.TryParse(value9, NumberStyles.Float, CultureInfo.InvariantCulture, out var result9)) { throw new ArgumentException("Invalid randomOffset value (" + value9 + ")"); } randomOffset = result9; stringBuilder2.Append($"\n random positional offset is {randomOffset}"); } else { stringBuilder2.Append("\n random positional offset not specified"); } flags = new Flags(match.Groups[11].Value); stringBuilder2.Append($"\n flags are {flags}"); string value10 = match.Groups[1].Value; if (match.Groups[1].Success) { switch (value10.ToLower().Trim('/', '\\')) { case "cupboard": case "storage": case "closet": case "storagecloset": stringBuilder2.Append("\n parent object is closet"); parentTo = GameObject.Find("Environment/HangarShip/StorageCloset"); if ((Object)(object)parentTo == (Object)null) { throw new Exception("Storage closet not found"); } break; case "file": case "filecabinet": case "filecabinets": stringBuilder2.Append("\n parent object is file cabinet"); parentTo = GameObject.Find("Environment/HangarShip/FileCabinet"); if ((Object)(object)parentTo == (Object)null) { throw new Exception("File cabinet not found"); } break; case "bunkbeds": case "bunkbed": stringBuilder2.Append("\n parent object is bunkbeds"); parentTo = GameObject.Find("Environment/HangarShip/Bunkbeds"); if ((Object)(object)parentTo == (Object)null) { throw new Exception("Bunkbeds not found"); } break; case "ship": stringBuilder2.Append("\n parent object is ship"); parentTo = null; break; case "none": case "environment": stringBuilder2.Append("\n parent object is none (environment)"); parentTo = GameObject.Find("Environment"); if ((Object)(object)parentTo == (Object)null) { throw new Exception("Environment not found"); } break; default: stringBuilder2.Append("\n parent object is custom (" + value10 + ") "); parentTo = GameObject.Find(value10); if ((Object)(object)parentTo == (Object)null) { throw new ArgumentException("Invalid parent object"); } stringBuilder2.Append(((object)parentTo).ToString()); break; } } else { stringBuilder2.Append("\n parent object not specified"); } LethalShipSort.Logger.LogDebug((object)stringBuilder2.ToString()); } public override string ToString() { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) string text = ""; if ((Object)(object)parentTo != (Object)null) { text = ((Object)parentTo).name; Transform parent = parentTo.transform.parent; while ((Object)(object)parent != (Object)null) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } text += ":"; } string[] obj = new string[6] { text, position.HasValue ? string.Format(CultureInfo.InvariantCulture, "{0},{1},{2}", position.Value.x, position.Value.y, position.Value.z) : string.Empty, floorYRot.HasValue ? string.Format(CultureInfo.InvariantCulture, ",{0}", floorYRot) : ((!randomOffset.HasValue) ? ",0" : string.Empty), (!rotationOffset.HasValue) ? string.Empty : string.Format(CultureInfo.InvariantCulture, "{0}{1}", (rotationOffset < 0) ? "-" : "+", Math.Abs(rotationOffset.Value)), ((this.flags.ToString().Length > 0) ? ((object)':') : string.Empty)?.ToString(), null }; Flags flags = this.flags; obj[5] = flags.ToString(); return string.Concat(obj); } } [BepInPlugin("baer1.ShipSort", "LethalShipSort", "4.0.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class LethalShipSort : BaseUnityPlugin { [HarmonyPatch(typeof(NetworkManager), "StartClient")] [HarmonyPatch(typeof(NetworkManager), "StartServer")] [HarmonyPatch(typeof(NetworkManager), "StartHost")] internal class RoundOverrideResetPatch { private static void Postfix() { int count = Instance.roundOverrides.Count; Instance.roundOverrides.Clear(); Logger.LogDebug((object)$"roundOverrides cleared (was {count} items)"); } } [HarmonyPatch(typeof(HUDManager), "Start")] internal class HUDManager_Start { private static void Postfix() { if (Instance.ConfigVersion < Instance.CurrentConfigVersion) { Chat.PrintWarning("[LethalShipSort] Your configuration file is outdated.\nPlease verify your configuration file and update it accordingly.\n" + $"Expected: v{Instance.CurrentConfigVersion}\n" + $"Config: v{Instance.ConfigVersion}"); Logger.LogWarning((object)$"Config file outdated: Expected v{Instance.CurrentConfigVersion}, got v{Instance.ConfigVersion}"); } else if (Instance.ConfigVersion > Instance.CurrentConfigVersion) { Chat.PrintWarning("[LethalShipSort] Your configuration file is using a newer, unsupported format.\nThere have been changes to the configuration file format which could cause errors.\nPlease verify your configuration file and mod version.\n" + $"Expected: v{Instance.CurrentConfigVersion}\n" + $"Config: v{Instance.ConfigVersion}"); Logger.LogWarning((object)$"Config file unsupported: Expected v{Instance.CurrentConfigVersion}, got v{Instance.ConfigVersion}"); } } } private ConfigEntry configVersion; private ConfigEntry autoSort; private ConfigEntry sortDelay; private ConfigEntry defaultOneHand; private ConfigEntry defaultTwoHand; private ConfigEntry defaultTool; private ConfigEntry customItemPositions; internal Dictionary> itemPositions = new Dictionary>(); internal Dictionary> modItemPositions = new Dictionary>(); internal Dictionary vanillaItems = new Dictionary(); internal Dictionary modItems = new Dictionary(); internal Dictionary roundOverrides = new Dictionary(); public const float CUPBOARD_ABOVE = 3.2f; public const float CUPBOARD_TOP = 2.4f; public const float CUPBOARD_MIDDLE_1 = 2f; public const float CUPBOARD_MIDDLE_2 = 1.5f; public const float CUPBOARD_BOTTOM = 0.5f; public static LethalShipSort Instance { get; private set; } internal static ManualLogSource Logger { get; private set; } internal static Harmony? Harmony { get; set; } public int ConfigVersion => configVersion.Value; public int CurrentConfigVersion => (int)((ConfigEntryBase)configVersion).DefaultValue; public bool AutoSort { get { return autoSort.Value; } set { autoSort.Value = value; } } public uint SortDelay { get { return sortDelay.Value; } set { sortDelay.Value = value; } } [Obsolete("Direct modifications of the modItemPositions list is not recommended, use the ItemPositionConfig functions instead")] public Dictionary> modItemPositionsList => modItemPositions; public ItemPosition DefaultOneHand { get { try { return new ItemPosition(defaultOneHand.Value); } catch (ArgumentException) { Logger.LogError((object)("Invalid DefaultOneHand position (" + defaultOneHand.Value + "), using fallback")); return new ItemPosition((string)((ConfigEntryBase)defaultOneHand).DefaultValue); } } set { defaultOneHand.Value = value.ToString(); } } public ItemPosition DefaultTwoHand { get { try { return new ItemPosition(defaultTwoHand.Value); } catch (ArgumentException) { Logger.LogError((object)("Invalid DefaultTwoHand position (" + defaultTwoHand.Value + "), using fallback")); return new ItemPosition((string)((ConfigEntryBase)defaultTwoHand).DefaultValue); } } set { defaultTwoHand.Value = value.ToString(); } } public ItemPosition DefaultTool { get { try { return new ItemPosition(defaultTool.Value); } catch (ArgumentException) { Logger.LogError((object)("Invalid DefaultTool position (" + defaultTool.Value + "), using fallback")); return new ItemPosition((string)((ConfigEntryBase)defaultTool).DefaultValue); } } set { defaultTool.Value = value.ToString(); } } public Dictionary CustomItemPositions { get { Dictionary dictionary = new Dictionary(); string[] array = customItemPositions.Value.Split(';'); foreach (string text in array) { string[] array2 = text.Split(":", 2); if (array2.Length != 2) { Logger.LogDebug((object)"split.Length != 2"); goto IL_00a8; } if (dictionary.ContainsKey(array2[0])) { Logger.LogWarning((object)("Multiple CustomItemPositions for item " + array2[0])); } try { dictionary[array2[0]] = new ItemPosition(array2[1]); } catch (ArgumentException arg) { Logger.LogDebug((object)$"{array2[0]} {array2[1]} {arg}"); goto IL_00a8; } continue; IL_00a8: Logger.LogError((object)("Invalid custom item position (" + text + ")")); } return dictionary; } } public Dictionary VanillaItemPositions { get { Dictionary dictionary = new Dictionary(); foreach (KeyValuePair> itemPosition in itemPositions) { try { dictionary[itemPosition.Key] = (string.IsNullOrWhiteSpace(itemPosition.Value.Value) ? ((ItemPosition?)null) : new ItemPosition?(new ItemPosition(itemPosition.Value.Value))); } catch (ArgumentException) { Logger.LogError((object)("Invalid item position for " + itemPosition.Key + " (" + itemPosition.Value.Value + "), using fallback")); dictionary[itemPosition.Key] = (string.IsNullOrWhiteSpace((string)((ConfigEntryBase)itemPosition.Value).DefaultValue) ? ((ItemPosition?)null) : new ItemPosition?(new ItemPosition((string)((ConfigEntryBase)itemPosition.Value).DefaultValue))); } } return dictionary; } } public Dictionary ModItemPositions { get { Dictionary dictionary = new Dictionary(); foreach (KeyValuePair> modItemPosition in modItemPositions) { try { dictionary[modItemPosition.Key] = (string.IsNullOrWhiteSpace(modItemPosition.Value.Value) ? ((ItemPosition?)null) : new ItemPosition?(new ItemPosition(modItemPosition.Value.Value))); } catch (ArgumentException) { Logger.LogError((object)("Invalid mod item position for " + modItemPosition.Key + " (" + modItemPosition.Value.Value + "), using fallback")); dictionary[modItemPosition.Key] = (string.IsNullOrWhiteSpace((string)((ConfigEntryBase)modItemPosition.Value).DefaultValue) ? ((ItemPosition?)null) : new ItemPosition?(new ItemPosition((string)((ConfigEntryBase)modItemPosition.Value).DefaultValue))); } } return dictionary; } } public ItemPosition GetPosition(GrabbableObject item) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) string text = Utils.ItemKey(item); ItemPosition? itemPosition = null; Logger.LogDebug((object)string.Format(">> {0}({1}) {2}:{3} {4}:{5} {6}:{7}", "GetPosition", item, "itemName", text, "isScrap", item.itemProperties.isScrap, "twoHanded", item.itemProperties.twoHanded)); ConfigEntry value2; ItemPosition value3; if (roundOverrides.TryGetValue(text.ToLower(), out (Vector3, GameObject) value)) { itemPosition = new ItemPosition { position = value.Item1, parentTo = value.Item2 }; Logger.LogDebug((object)string.Format("<< {0} ({1}) {2} ({3}, {4})", "GetPosition", "roundOverrides", itemPosition, value.Item1, value.Item2)); } else if (itemPositions.TryGetValue(text, out value2)) { try { if (!Utility.IsNullOrWhiteSpace(value2.Value)) { itemPosition = new ItemPosition(value2.Value); Logger.LogDebug((object)string.Format("<< {0} ({1}) {2} ({3})", "GetPosition", "itemPositions", itemPosition, value2.Value)); } } catch (ArgumentException) { Logger.LogError((object)("Invalid item position for " + text + " (" + value2.Value + "), using fallback")); if (!Utility.IsNullOrWhiteSpace((string)((ConfigEntryBase)value2).DefaultValue)) { itemPosition = new ItemPosition((string)((ConfigEntryBase)value2).DefaultValue); Logger.LogDebug((object)string.Format("<< {0} ({1} - {2}) {3} ({4})", "GetPosition", "itemPositions", "DefaultValue", itemPosition, ((ConfigEntryBase)value2).DefaultValue)); } } } else if (modItemPositions.TryGetValue(text, out value2)) { try { if (!Utility.IsNullOrWhiteSpace(value2.Value)) { itemPosition = new ItemPosition(value2.Value); Logger.LogDebug((object)string.Format("<< {0} ({1}) {2} ({3})", "GetPosition", "modItemPositions", itemPosition, value2.Value)); } } catch (ArgumentException) { Logger.LogError((object)("Invalid mod item position for " + text + " (" + value2.Value + "), using fallback")); try { if (!Utility.IsNullOrWhiteSpace((string)((ConfigEntryBase)value2).DefaultValue)) { itemPosition = new ItemPosition((string)((ConfigEntryBase)value2).DefaultValue); Logger.LogDebug((object)string.Format("<< {0} ({1} - {2}) {3} ({4})", "GetPosition", "modItemPositions", "DefaultValue", itemPosition, ((ConfigEntryBase)value2).DefaultValue)); } } catch (ArgumentException ex3) { Logger.LogError((object)("Invalid default mod item position for " + text + " (" + value2.Value + "). The mod developer seems to have screwed something up")); Logger.LogError((object)ex3); } } } else if (CustomItemPositions.TryGetValue(text, out value3)) { itemPosition = value3; Logger.LogDebug((object)string.Format("<< {0} ({1}) {2}", "GetPosition", "CustomItemPositions", itemPosition)); } if (!itemPosition.HasValue) { itemPosition = ((!item.itemProperties.isScrap) ? DefaultTool : (item.itemProperties.twoHanded ? DefaultTwoHand : DefaultOneHand)); Logger.LogDebug((object)string.Format("<< {0} ({1}) {2}", "GetPosition", (!item.itemProperties.isScrap) ? "DefaultTool" : (item.itemProperties.twoHanded ? "DefaultTwoHand" : "DefaultOneHand"), itemPosition)); } else if (!itemPosition.Value.position.HasValue) { ItemPosition itemPosition2 = ((!item.itemProperties.isScrap) ? DefaultTool : (item.itemProperties.twoHanded ? DefaultTwoHand : DefaultOneHand)); itemPosition = new ItemPosition { flags = (itemPosition.Value.flags.FilterFilteringRelated() | itemPosition2.flags.FilterPositionRelated()), position = itemPosition2.position, parentTo = itemPosition2.parentTo }; Logger.LogDebug((object)string.Format("<< {0} ({1} with flags) {2}", "GetPosition", (!item.itemProperties.isScrap) ? "DefaultTool" : (item.itemProperties.twoHanded ? "DefaultTwoHand" : "DefaultOneHand"), itemPosition)); } return itemPosition.Value; } private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; Instance = this; configVersion = ((BaseUnityPlugin)this).Config.Bind("General", "ConfigVersion", 6, "The version of this config file"); autoSort = ((BaseUnityPlugin)this).Config.Bind("General", "AutoSort", false, "Whether to automatically sort the ship when leaving a planet (toggle ingame with /autosort)"); sortDelay = ((BaseUnityPlugin)this).Config.Bind("General", "SortDelay", 0u, "The amount of milliseconds to wait between moving items, mostly for the satisfying visual effect.\nYou can't pick anything up while sorting items."); BindItemPositionConfigs(); Patch(); new SortItemsCommand(); new AutoSortToggle(); new SetItemPositionCommand(); new PrintItemNames(); Logger.LogInfo((object)"baer1.ShipSort v4.0.2 has loaded!"); static void Patch() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown if (Harmony == null) { Harmony = new Harmony("baer1.ShipSort"); } Logger.LogDebug((object)"Patching..."); Harmony.PatchAll(); Logger.LogDebug((object)"Finished patching!"); } } private void BindItemPositionConfigs() { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_03fb: Unknown result type (might be due to invalid IL or missing references) //IL_046f: Unknown result type (might be due to invalid IL or missing references) //IL_0670: Unknown result type (might be due to invalid IL or missing references) //IL_06b6: Unknown result type (might be due to invalid IL or missing references) //IL_0701: Unknown result type (might be due to invalid IL or missing references) //IL_0746: Unknown result type (might be due to invalid IL or missing references) //IL_08b4: Unknown result type (might be due to invalid IL or missing references) //IL_090e: Unknown result type (might be due to invalid IL or missing references) //IL_094e: Unknown result type (might be due to invalid IL or missing references) //IL_098e: Unknown result type (might be due to invalid IL or missing references) //IL_09ce: Unknown result type (might be due to invalid IL or missing references) //IL_0a0e: Unknown result type (might be due to invalid IL or missing references) //IL_0a4e: Unknown result type (might be due to invalid IL or missing references) //IL_0a8e: Unknown result type (might be due to invalid IL or missing references) //IL_0ac9: Unknown result type (might be due to invalid IL or missing references) //IL_0b09: Unknown result type (might be due to invalid IL or missing references) //IL_0b49: Unknown result type (might be due to invalid IL or missing references) //IL_0b89: Unknown result type (might be due to invalid IL or missing references) //IL_0bfd: Unknown result type (might be due to invalid IL or missing references) //IL_0c3d: Unknown result type (might be due to invalid IL or missing references) //IL_0c7d: Unknown result type (might be due to invalid IL or missing references) //IL_0cb8: Unknown result type (might be due to invalid IL or missing references) //IL_0cf8: Unknown result type (might be due to invalid IL or missing references) defaultOneHand = ((BaseUnityPlugin)this).Config.Bind("Items", "DefaultOneHand", "-2.25,3,-5.25,0.05", "Default position for one-handed items."); defaultTwoHand = ((BaseUnityPlugin)this).Config.Bind("Items", "DefaultTwoHand", "-4.5,3,-5.25,0.05", "Default position for two-handed items."); defaultTool = ((BaseUnityPlugin)this).Config.Bind("Items", "DefaultTool", $"cupboard:-2,0.6,{0.5f},0,0.02:{'C'}{'P'}", "Default position for tool items."); VItemPositionConfig("Airhorn"); VItemPositionConfig("LungApparatus", "Apparatice", new Vector3(-6.8f, 4.4f, -6.65f)); itemPositions["LungApparatusTurnedOff"] = itemPositions["LungApparatus"]; VItemPositionConfig("HandBell", "Brass bell"); VItemPositionConfig("BigBolt", "Big bolt"); VItemPositionConfig("Bone"); VItemPositionConfig("BinFullOfBottles", "Bottles"); VItemPositionConfig("Hairbrush", "Hair brush"); VItemPositionConfig("Candy"); VItemPositionConfig("CashRegisterItem", "Cash register"); VItemPositionConfig("ChemicalJug", "Chemical jug"); VItemPositionConfig("Clock"); VItemPositionConfig("Clownhorn", "Clown horn"); VItemPositionConfig("ComedyMask", "Comedy"); VItemPositionConfig("ControlPad", "Control pad"); VItemPositionConfig("CookieMoldPan", "Cookie mold pan"); VItemPositionConfig("Dustpan", "Dust pan"); VItemPositionConfig("Ear"); VItemPositionConfig("EasterEgg", "Easter egg"); VItemPositionConfig("KiwiBabyItem", "Egg", new Vector3(4.85f, 2f, -4f)); VItemPositionConfig("EggBeater", "Egg beater"); VItemPositionConfig("FancyLamp", "Fancy lamp"); VItemPositionConfig("Flask"); VItemPositionConfig("SeveredFootLOD0", "Foot"); VItemPositionConfig("GarbageLid", "Garbage lid"); VItemPositionConfig("GiftBox", "Gift box"); VItemPositionConfig("GoldBar", "Gold Bar"); VItemPositionConfig("FancyGlass", "Golden cup"); VItemPositionConfig("SeveredHandLOD0", "Hand"); VItemPositionConfig("HeartContainer", "Heart"); VItemPositionConfig("Hairdryer"); VItemPositionConfig("RedLocustHive", "Bee hive", new Vector3(-6.8f, 4.4f, -5.65f)); VItemPositionConfig("DiyFlashbang", "Homemade Flashbang"); VItemPositionConfig("PickleJar", "Jar of pickles"); VItemPositionConfig("KnifeItem", "Kitchen knife", new Vector3(-1.9f, 0.6f, 1.5f), isTool: false, true, true, 0); VItemPositionConfig("SeveredThighLOD0", "Knee"); VItemPositionConfig("Cog", "Large axle"); VItemPositionConfig("LaserPointer", "Laser pointer"); VItemPositionConfig("Magic7Ball", "Magic 7 ball"); VItemPositionConfig("MagnifyingGlass", "Magnifying glass"); VItemPositionConfig("MetalSheet", "Tattered metal sheet"); VItemPositionConfig("Mug", "Coffee mug"); VItemPositionConfig("OldPhone", "Old phone"); VItemPositionConfig("Painting"); VItemPositionConfig("PerfumeBottle", "Perfume bottle"); VItemPositionConfig("PillBottle", "Pill bottle"); VItemPositionConfig("PlasticCup", "Plastic cup"); VItemPositionConfig("FishTestProp", "Plastic fish"); VItemPositionConfig("RedSodaCan", "Red soda"); VItemPositionConfig("Remote"); VItemPositionConfig("RibcageBone", "Ribcage"); VItemPositionConfig("FancyRing", "Wedding ring"); VItemPositionConfig("RubberDucky", "Rubber ducky"); Vector3 defaultPosition = new Vector3(8.75f, 2f, -5.5f); bool? defaultKeepOnCruiser = true; int? defaultFloorYRot = 0; VItemPositionConfig("ShotgunItem", "Double-barrel", defaultPosition, isTool: false, null, defaultKeepOnCruiser, defaultFloorYRot); ConfigFile config = ((BaseUnityPlugin)this).Config; Vector3 defaultPosition2 = new Vector3(8.6f, 2f, -5.5f); defaultKeepOnCruiser = true; defaultFloorYRot = 0; ItemPositionConfig(config, "ShotgunItem-1", "Double-barrel (1 bullet)", defaultPosition2, isTool: false, null, defaultKeepOnCruiser, defaultFloorYRot, "ShotgunExtensions"); ConfigFile config2 = ((BaseUnityPlugin)this).Config; Vector3 defaultPosition3 = new Vector3(8.45f, 2f, -5.5f); defaultKeepOnCruiser = true; defaultFloorYRot = 0; ItemPositionConfig(config2, "ShotgunItem-2", "Double-barrel (2 bullets)", defaultPosition3, isTool: false, null, defaultKeepOnCruiser, defaultFloorYRot, "ShotgunExtensions"); VItemPositionConfig("SoccerBall", "Soccer ball", new Vector3(-6.8f, 4.4f, -7.75f)); VItemPositionConfig("SteeringWheel", "Steering wheel"); VItemPositionConfig("StopSign", "Stop sign"); VItemPositionConfig("TeaKettle", "Tea Kettle"); VItemPositionConfig("Dentures", "Teeth"); VItemPositionConfig("ToiletPaperRolls", "Toilet paper"); VItemPositionConfig("Toothpaste"); VItemPositionConfig("Tongue"); VItemPositionConfig("ToyCube", "Toy cube"); VItemPositionConfig("RobotToy", "Robot Toy"); VItemPositionConfig("ToyTrain", "Toy train"); VItemPositionConfig("TragedyMask", "Tragedy"); VItemPositionConfig("EnginePart", "V-type engine"); VItemPositionConfig("WhoopieCushion", "Whoopie cushion", new Vector3(9f, 2f, -8.25f)); VItemPositionConfig("YieldSign", "Yield sign"); VItemPositionConfig("ZeddogPlushie", "Zed Dog", new Vector3(9f, 1.21f, -5.55f)); Vector3 defaultPosition4 = new Vector3(-1.4f, 0.6f, 2.4f); defaultFloorYRot = 0; VItemPositionConfig("WalkieTalkie", "Walkie-talkie", defaultPosition4, isTool: true, null, null, defaultFloorYRot); Vector3 defaultPosition5 = new Vector3(-1.3f, 0.2f, 2f); defaultFloorYRot = 0; VItemPositionConfig("BBFlashlight", "Flashlight", defaultPosition5, isTool: true, null, null, defaultFloorYRot); Vector3 defaultPosition6 = new Vector3(-1.5f, 0.3f, 1.5f); defaultFloorYRot = 0; VItemPositionConfig("ShovelItem", "Shovel", defaultPosition6, isTool: true, null, null, defaultFloorYRot); Vector3 defaultPosition7 = new Vector3(-2f, 0.5f, 2.4f); defaultFloorYRot = 0; VItemPositionConfig("LockPickerItem", "Lockpicker", defaultPosition7, isTool: true, null, null, defaultFloorYRot); Vector3 defaultPosition8 = new Vector3(-1.3f, 0.65f, 2f); defaultFloorYRot = 0; VItemPositionConfig("FlashlightItem", "Pro-flashlight", defaultPosition8, isTool: true, null, null, defaultFloorYRot); Vector3 defaultPosition9 = new Vector3(-1.2f, 0.5f, 2f); defaultFloorYRot = 0; VItemPositionConfig("StunGrenade", "Stun grenade", defaultPosition9, isTool: true, null, null, defaultFloorYRot); Vector3 defaultPosition10 = new Vector3(-0.3f, 0.5f, 3.2f); defaultFloorYRot = 0; VItemPositionConfig("Boombox", defaultPosition10, isTool: true, null, null, defaultFloorYRot); Vector3 defaultPosition11 = new Vector3(-0.55f, 0.2f, 2f); defaultFloorYRot = 0; VItemPositionConfig("TZPChemical", "TZP-Inhalant", defaultPosition11, isTool: true, null, null, defaultFloorYRot); Vector3 defaultPosition12 = new Vector3(-1.1f, 0.6f, 2.4f); defaultFloorYRot = 0; VItemPositionConfig("PatcherGunItem", "Zap gun", defaultPosition12, isTool: true, null, null, defaultFloorYRot); Vector3 defaultPosition13 = new Vector3(-0.3f, 0.2f, 0.5f); defaultFloorYRot = 0; VItemPositionConfig("JetpackItem", "Jetpack", defaultPosition13, isTool: true, null, null, defaultFloorYRot); VItemPositionConfig("ExtensionLadderItem", "Extension ladder", isTool: true); VItemPositionConfig("RadarBoosterDevice", "Radar booster", isTool: true); Vector3 defaultPosition14 = new Vector3(-1.7f, 0.5f, 2f); defaultFloorYRot = 0; VItemPositionConfig("SprayPaintItem", "Spray paint", defaultPosition14, isTool: true, null, null, defaultFloorYRot); Vector3 defaultPosition15 = new Vector3(-2.05f, 0.5f, 2f); defaultFloorYRot = 0; VItemPositionConfig("WeedKillerItem", "Weed killer", defaultPosition15, isTool: true, null, null, defaultFloorYRot); Vector3 defaultPosition16 = new Vector3(-0.35f, 0.5f, 2.3000002f); defaultFloorYRot = 0; VItemPositionConfig("BeltBagItem", "Belt bag", defaultPosition16, isTool: true, null, null, defaultFloorYRot); Vector3 defaultPosition17 = new Vector3(-0.3f, 0.6f, 1.5f); defaultFloorYRot = 0; VItemPositionConfig("Key", defaultPosition17, isTool: true, null, null, defaultFloorYRot); Vector3 defaultPosition18 = new Vector3(-0.3f, 0.6f, 2f); defaultFloorYRot = 0; VItemPositionConfig("ShotgunShell", "Shotgun Shell", defaultPosition18, isTool: true, null, null, defaultFloorYRot); customItemPositions = ((BaseUnityPlugin)this).Config.Bind("Items", "CustomItemPositions", "ClipboardManual:N;StickyNoteItem:N", "Semicolon-separated list of internal item names and their positions."); } private void VItemPositionConfig(string internalName, string itemName, bool isTool = false, bool? defaultKeepOnCruiser = null) { itemPositions[internalName] = ((BaseUnityPlugin)this).Config.Bind(isTool ? "Tools" : "Scrap", internalName, $"{((defaultKeepOnCruiser ?? isTool) ? ((object)'C') : string.Empty)}", "Position for the " + itemName + " item."); vanillaItems[itemName.ToLower()] = internalName.ToLower(); } private void VItemPositionConfig(string itemName, bool isTool = false, bool? defaultKeepOnCruiser = null) { itemPositions[itemName] = ((BaseUnityPlugin)this).Config.Bind(isTool ? "Tools" : "Scrap", itemName, $"{((defaultKeepOnCruiser ?? isTool) ? ((object)'C') : string.Empty)}", "Position for the " + itemName + " item."); vanillaItems[itemName.ToLower()] = itemName.ToLower(); } public void ItemPositionConfig(ConfigFile configFile, string internalName, string itemName, bool isTool = false, bool? defaultKeepOnCruiser = null, string? section = null) { if (modItemPositions.ContainsKey(internalName)) { Logger.LogWarning((object)("Multiple configuration values registered for mod item position " + internalName)); } modItemPositions[internalName] = configFile.Bind(section ?? (isTool ? "Tools" : "Scrap"), internalName, $"{((defaultKeepOnCruiser ?? isTool) ? ((object)'C') : string.Empty)}", "Position for the " + itemName + " item."); modItems[itemName.ToLower()] = internalName.ToLower(); } public void ItemPositionConfig(ConfigFile configFile, string itemName, bool isTool = false, bool? defaultKeepOnCruiser = null, string? section = null) { if (modItemPositions.ContainsKey(itemName)) { Logger.LogWarning((object)("Multiple configuration values registered for mod item position " + itemName)); } modItemPositions[itemName] = configFile.Bind(section ?? (isTool ? "Tools" : "Scrap"), itemName, $"{((defaultKeepOnCruiser ?? isTool) ? ((object)'C') : string.Empty)}", "Position for the " + itemName + " item."); modItems[itemName.ToLower()] = itemName.ToLower(); } private static string Flags(bool keepOnCruiser, bool inCupboard) { if (!(keepOnCruiser || inCupboard)) { return string.Empty; } return $":{(keepOnCruiser ? ((object)'C') : string.Empty)}{(inCupboard ? ((object)'P') : string.Empty)}"; } private void VItemPositionConfig(string internalName, string itemName, Vector3 defaultPosition, bool isTool = false, bool? defaultInCupboard = null, bool? defaultKeepOnCruiser = null, int? defaultFloorYRot = null) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) itemPositions[internalName] = ((BaseUnityPlugin)this).Config.Bind(isTool ? "Tools" : "Scrap", internalName, string.Format(CultureInfo.InvariantCulture, "{0}{1},{2},{3}{4}{5}", (defaultInCupboard ?? isTool) ? "cupboard:" : "", defaultPosition.x, defaultPosition.y, defaultPosition.z, defaultFloorYRot.HasValue ? string.Format(CultureInfo.InvariantCulture, ",{0}", defaultFloorYRot) : string.Empty, Flags(defaultKeepOnCruiser ?? isTool, defaultInCupboard ?? isTool)), "Position for the " + itemName + " item."); vanillaItems[itemName.ToLower()] = internalName.ToLower(); } private void VItemPositionConfig(string itemName, Vector3 defaultPosition, bool isTool = false, bool? defaultInCupboard = null, bool? defaultKeepOnCruiser = null, int? defaultFloorYRot = null) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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) itemPositions[itemName] = ((BaseUnityPlugin)this).Config.Bind(isTool ? "Tools" : "Scrap", itemName, string.Format(CultureInfo.InvariantCulture, "{0}{1},{2},{3}{4}{5}", (defaultInCupboard ?? isTool) ? "cupboard:" : "", defaultPosition.x, defaultPosition.y, defaultPosition.z, defaultFloorYRot.HasValue ? string.Format(CultureInfo.InvariantCulture, ",{0}", defaultFloorYRot) : string.Empty, Flags(defaultKeepOnCruiser ?? isTool, defaultInCupboard ?? isTool)), "Position for the " + itemName + " item."); vanillaItems[itemName.ToLower()] = itemName.ToLower(); } public void ItemPositionConfig(ConfigFile configFile, string internalName, string itemName, Vector3 defaultPosition, bool isTool = false, bool? defaultInCupboard = null, bool? defaultKeepOnCruiser = null, int? defaultFloorYRot = null, string? section = null) { //IL_006e: 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_008c: Unknown result type (might be due to invalid IL or missing references) if (modItemPositions.ContainsKey(internalName)) { Logger.LogWarning((object)("Multiple configuration values registered for mod item position " + internalName)); } modItemPositions[internalName] = configFile.Bind(section ?? (isTool ? "Tools" : "Scrap"), internalName, string.Format(CultureInfo.InvariantCulture, "{0}{1},{2},{3}{4}{5}", (defaultInCupboard ?? isTool) ? "cupboard:" : "", defaultPosition.x, defaultPosition.y, defaultPosition.z, defaultFloorYRot.HasValue ? string.Format(CultureInfo.InvariantCulture, ",{0}", defaultFloorYRot) : string.Empty, Flags(defaultKeepOnCruiser ?? isTool, defaultInCupboard ?? isTool)), "Position for the " + itemName + " item."); modItems[itemName.ToLower()] = internalName.ToLower(); } public void ItemPositionConfig(ConfigFile configFile, string itemName, Vector3 defaultPosition, bool isTool = false, bool? defaultInCupboard = null, bool? defaultKeepOnCruiser = null, int? defaultFloorYRot = null, string? section = null) { //IL_006e: 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_008a: Unknown result type (might be due to invalid IL or missing references) if (modItemPositions.ContainsKey(itemName)) { Logger.LogWarning((object)("Multiple configuration values registered for mod item position " + itemName)); } modItemPositions[itemName] = configFile.Bind(section ?? (isTool ? "Tools" : "Scrap"), itemName, string.Format(CultureInfo.InvariantCulture, "{0}{1},{2},{3}{4}{5}", (defaultInCupboard ?? isTool) ? "cupboard:" : "", defaultPosition.x, defaultPosition.y, defaultPosition.z, defaultFloorYRot.HasValue ? string.Format(CultureInfo.InvariantCulture, ",{0}", defaultFloorYRot) : string.Empty, Flags(defaultKeepOnCruiser ?? isTool, defaultInCupboard ?? isTool)), "Position for the " + itemName + " item."); modItems[itemName.ToLower()] = itemName.ToLower(); } } public class PrintItemNames : LegacyCommand { public override string[] Commands => new string[2] { "itemnames", ((BaseCommand)this).Name }; public override string Description => "Lists all currently loaded item names which do not have assigned sorting positions"; public override string[] Syntax => new string[1] { "[ -a | --all ]" }; public override bool Invoke(string[] args, out string error) { error = "The ship must be in orbit"; if (!StartOfRound.Instance.inShipPhase) { return false; } bool flag = args.Contains("-a") || args.Contains("--all"); error = "No unknown items on the ship"; Dictionary dictionary = new Dictionary(); GrabbableObject[] array = Object.FindObjectsOfType(); foreach (GrabbableObject val in array) { string text = Utils.RemoveClone(((Object)val).name); if (flag || (!LethalShipSort.Instance.vanillaItems.ContainsValue(text.ToLower()) && !LethalShipSort.Instance.modItems.ContainsValue(text.ToLower()))) { dictionary.TryAdd(text, val.itemProperties?.itemName); } } if (dictionary.Count == 0) { return false; } string text2 = string.Join('\n', dictionary.Select((KeyValuePair kvp) => kvp.Key + ((kvp.Value != null) ? (": " + kvp.Value) : "")).OrderBy((string result) => result, StringComparer.CurrentCultureIgnoreCase)); string text3 = "The following" + (flag ? "" : " unknown") + " items are currently on the ship:\n"; Chat.Print(text3 + "" + text2 + "", (Color?)null); LethalShipSort.Logger.LogInfo((object)(text3 + text2)); return true; } } public class SetItemPositionCommand : LegacyCommand { public enum where { here, there, error } public enum when { once, game, always, error } public override string Name => "SetItemPosition"; public override string Description => "Sets the position for an item when sorting"; public override string[] Commands => new string[2] { "put", ((BaseCommand)this).Name }; public override string[] Syntax => new string[1] { "\"\" { here | there } [ once | game | always ]\nExample: /put \"easter egg\" there always" }; public override bool Invoke(string[] args, out string error) { error = "The ship must be in orbit"; if (StartOfRound.Instance.inShipPhase) { return SetItemPosition(args, out error); } return false; } public static bool SetItemPosition(string[] args, out string error) { error = "Invalid arguments"; Utils.objectCount.Clear(); switch (args.Length) { case 2: { string name2 = args[0]; string text2 = args[1].ToLower(); where obj = ((!(text2 == "here")) ? ((text2 == "there") ? where.there : where.error) : where.here); return SetItemPosition(name2, obj, when.once, out error); } case 3: { string name = args[0]; string text = args[1].ToLower(); where obj = ((!(text == "here")) ? ((text == "there") ? where.there : where.error) : where.here); where obj2 = obj; when when; switch (args[2].ToLower()) { case "once": case "now": when = when.once; break; case "game": case "round": when = when.game; break; case "always": case "save": when = when.always; break; default: when = when.error; break; } return SetItemPosition(name, obj2, when, out error); } default: return false; } } public static bool SetItemPosition(string name, where where, when when, out string error) { //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_0238: 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_0391: Unknown result type (might be due to invalid IL or missing references) //IL_0384: Unknown result type (might be due to invalid IL or missing references) //IL_0389: Unknown result type (might be due to invalid IL or missing references) //IL_048d: Unknown result type (might be due to invalid IL or missing references) //IL_0480: Unknown result type (might be due to invalid IL or missing references) //IL_0485: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_0542: Unknown result type (might be due to invalid IL or missing references) error = "Invalid arguments"; if (where == where.error || when == when.error) { return false; } error = "Invalid item name"; if (!LethalShipSort.Instance.vanillaItems.TryGetValue(name.ToLower(), out string internalName)) { if (LethalShipSort.Instance.vanillaItems.ContainsValue(name.ToLower())) { internalName = name; } else if (!LethalShipSort.Instance.modItems.TryGetValue(name.ToLower(), out internalName)) { if (!LethalShipSort.Instance.modItems.ContainsValue(name.ToLower())) { return false; } internalName = name; } } LethalShipSort.Logger.LogDebug((object)("internalName: " + internalName + " (" + name + ")")); ConfigEntry val = null; if (when == when.always) { if (LethalShipSort.Instance.itemPositions.All>>((KeyValuePair> kvp) => !string.Equals(kvp.Key, internalName, StringComparison.CurrentCultureIgnoreCase))) { if (LethalShipSort.Instance.modItemPositions.All>>((KeyValuePair> kvp) => !string.Equals(kvp.Key, internalName, StringComparison.CurrentCultureIgnoreCase))) { return false; } val = LethalShipSort.Instance.modItemPositions.First>>((KeyValuePair> kvp) => string.Equals(kvp.Key, internalName, StringComparison.CurrentCultureIgnoreCase)).Value; } else { val = LethalShipSort.Instance.itemPositions.First>>((KeyValuePair> kvp) => string.Equals(kvp.Key, internalName, StringComparison.CurrentCultureIgnoreCase)).Value; } } error = "Error getting position"; if (!GetPosition(where, out Vector3 position, out GameObject relativeTo)) { return false; } LethalShipSort.Logger.LogDebug((object)string.Format("position: {0} relative to {1} ({2}, {3})", position, relativeTo, ((Object)(object)relativeTo == (Object)null) ? "null" : Utils.GameObjectPath(relativeTo), ((Object)(object)relativeTo == (Object)null) ? "" : ((string)(object)GameObject.Find(Utils.GameObjectPath(relativeTo))))); GrabbableObject[] array; switch (when) { case when.once: Chat.Print($"Moving all items of type {internalName} to position {(((Object)(object)relativeTo == (Object)null) ? position : relativeTo.transform.InverseTransformPoint(position))}", (Color?)null); error = "No items to sort"; array = Object.FindObjectsOfType(); if (array == null) { return false; } array = array.Where((GrabbableObject i) => i != null && i.playerHeldBy == null && !(i is RagdollGrabbableObject) && string.Equals(Utils.RemoveClone(((Object)i).name), internalName, StringComparison.CurrentCultureIgnoreCase)).ToArray(); if (array.Length == 0) { return false; } if (LethalShipSort.Instance.SortDelay < 10) { int num = array.Count(delegate(GrabbableObject item) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) try { return !Utils.MoveItem(item, new ItemPosition { position = position, parentTo = relativeTo }); } catch (Exception ex) { LethalShipSort.Logger.LogError((object)ex); return true; } }); error = $"{num} items couldn't be sorted"; Chat.Print("Finished sorting items", (Color?)null); return num == 0; } if (SortItemsCommand.sorting != null) { ((MonoBehaviour)GameNetworkManager.Instance.localPlayerController).StopCoroutine(SortItemsCommand.sorting); } SortItemsCommand.sorting = ((MonoBehaviour)GameNetworkManager.Instance.localPlayerController).StartCoroutine(SortItemsDelayed(LethalShipSort.Instance.SortDelay, array, position, relativeTo)); return true; case when.game: LethalShipSort.Instance.roundOverrides[internalName.ToLower()] = (position, relativeTo); Chat.Print($"Items of type {internalName} will be put on position {(((Object)(object)relativeTo == (Object)null) ? position : relativeTo.transform.InverseTransformPoint(position))} for this game", (Color?)null); goto IL_04ab; case when.always: { val.Value = (((Object)(object)relativeTo == (Object)null) ? $"none:{position.x},{position.y},{position.z}" : $"{Utils.GameObjectPath(relativeTo)}:{position.x},{position.y},{position.z}"); Chat.Print($"Items of type {internalName} will be put on position {(((Object)(object)relativeTo == (Object)null) ? position : relativeTo.transform.InverseTransformPoint(position))}", (Color?)null); goto IL_04ab; } IL_04ab: array = Object.FindObjectsOfType(); if (array == null) { break; } array = array.Where((GrabbableObject i) => i != null && i.playerHeldBy == null && !(i is RagdollGrabbableObject) && string.Equals(Utils.RemoveClone(((Object)i).name), internalName, StringComparison.CurrentCultureIgnoreCase)).ToArray(); if (array.Length == 0) { break; } if (LethalShipSort.Instance.SortDelay < 10) { int num2 = array.Count(delegate(GrabbableObject item) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) try { return !Utils.MoveItem(item, new ItemPosition { position = position, parentTo = relativeTo }); } catch (Exception ex) { LethalShipSort.Logger.LogError((object)ex); return true; } }); error = $"{num2} items couldn't be sorted"; return num2 == 0; } if (SortItemsCommand.sorting != null) { ((MonoBehaviour)GameNetworkManager.Instance.localPlayerController).StopCoroutine(SortItemsCommand.sorting); } SortItemsCommand.sorting = ((MonoBehaviour)GameNetworkManager.Instance.localPlayerController).StartCoroutine(SortItemsDelayed(LethalShipSort.Instance.SortDelay, array, position, relativeTo)); break; } return true; } private static IEnumerator SortItemsDelayed(uint delay, GrabbableObject[] items, Vector3 position, GameObject? relativeTo, string errorPrefix = "Error running command") { //IL_0015: 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) int itemsFailed = 0; foreach (GrabbableObject item in items) { try { if (!Utils.MoveItem(item, new ItemPosition { position = position, parentTo = relativeTo })) { itemsFailed++; } } catch (Exception ex) { LethalShipSort.Logger.LogError((object)ex); itemsFailed++; } yield return (object)new WaitForSeconds((float)delay / 1000f); } string text = $"{itemsFailed} items couldn't be sorted"; if (itemsFailed != 0) { Chat.PrintError(errorPrefix + ": " + text + ""); } else { Chat.Print("Finished sorting items", (Color?)null); } } private static bool GetPosition(where where, out Vector3 position, out GameObject? relativeTo) { //IL_0001: 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_005d: 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_0076: 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_0080: 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_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) position = default(Vector3); relativeTo = null; RaycastHit val = default(RaycastHit); switch (where) { case where.here: if (Physics.Raycast(((Component)GameNetworkManager.Instance.localPlayerController).transform.position, Vector3.down, ref val, 80f, 268437761, (QueryTriggerInteraction)1)) { position = ((Component)((RaycastHit)(ref val)).collider).gameObject.transform.InverseTransformPoint(((RaycastHit)(ref val)).point + new Vector3(0f, 0.2f, 0f)); relativeTo = ((Component)((RaycastHit)(ref val)).collider).gameObject; return true; } break; case where.there: if (Physics.Raycast(((Component)GameNetworkManager.Instance.localPlayerController.gameplayCamera).transform.position, ((Component)GameNetworkManager.Instance.localPlayerController.gameplayCamera).transform.forward, ref val, 80f, 268437761, (QueryTriggerInteraction)1)) { position = ((Component)((RaycastHit)(ref val)).collider).gameObject.transform.InverseTransformPoint(((RaycastHit)(ref val)).point + new Vector3(0f, 0.2f, 0f)); relativeTo = ((Component)((RaycastHit)(ref val)).collider).gameObject; return true; } break; } return false; } } public class SortItemsCommand : LegacyCommand { private enum ForceLevel { None, IncludeCruiser, IncludeAll } [HarmonyPatch(typeof(StartOfRound), "SetShipReadyToLand")] internal static class AutoSortPatch { private static void Prefix() { if (LethalShipSort.Instance.AutoSort && GameNetworkManager.Instance.localPlayerController.isHostPlayerObject) { AutoSortAllItems(); } } } internal static Coroutine? sorting; public override string Name => "SortItems"; public override string[] Commands => new string[3] { "sort", "ShipSort", ((BaseCommand)this).Name }; public override string Description => "Sorts all items on the ship\n-a: sort all items, even items on cruiser"; public override string[] Syntax => new string[3] { "", "[ -a | -A ]", " { here | there } [ once | game | always ]" }; public override bool Invoke(string[] args, out string error) { error = "The ship must be in orbit"; if (StartOfRound.Instance.inShipPhase) { if (args.Length >= 2) { return SetItemPositionCommand.SetItemPosition(args, out error); } return SortAllItems((args.Contains("-A") || args.Contains("--all", StringComparer.InvariantCultureIgnoreCase)) ? ForceLevel.IncludeAll : (args.Contains("-a") ? ForceLevel.IncludeCruiser : ForceLevel.None), out error); } return false; } private static bool SortAllItems(ForceLevel forceLevel, out string error) { error = "No items to sort"; Utils.objectCount.Clear(); GameNetworkManager.Instance.localPlayerController.DropAllHeldItemsAndSyncNonexact(); GrabbableObject[] array = Object.FindObjectsOfType(); if (array == null) { return false; } array = array.Where((GrabbableObject i) => i != null && i.playerHeldBy == null && !(i is RagdollGrabbableObject)).ToArray(); if (array.Length == 0) { return false; } Chat.Print("Sorting all items...", (Color?)null); VehicleController[] cars = Object.FindObjectsOfType() ?? Array.Empty(); Dictionary dictionary = FilterFlags(array.Where((GrabbableObject i) => i.itemProperties.isScrap).ToDictionary((GrabbableObject i) => i, (GrabbableObject item) => LethalShipSort.Instance.GetPosition(item))); Dictionary dictionary2 = FilterFlags(array.Where((GrabbableObject i) => !i.itemProperties.isScrap).ToDictionary((GrabbableObject i) => i, (GrabbableObject item) => LethalShipSort.Instance.GetPosition(item))); if (LethalShipSort.Instance.SortDelay < 10) { int num = 0; int num2 = 0; if (dictionary.Count != 0) { num = SortItems(dictionary); } if (dictionary2.Count != 0) { num2 = SortItems(dictionary2); } error = ((num > 0) ? string.Format("{0} scrap items {1}", num, (num2 > 0) ? "and " : "") : "") + ((num2 > 0) ? $"{num2} tool items" : "") + " couldn't be sorted"; if (num != 0 || num2 != 0) { return false; } Chat.Print("Finished sorting items", (Color?)null); } else { if (sorting != null) { ((MonoBehaviour)GameNetworkManager.Instance.localPlayerController).StopCoroutine(sorting); } sorting = ((MonoBehaviour)GameNetworkManager.Instance.localPlayerController).StartCoroutine(SortAllItemsDelayed(LethalShipSort.Instance.SortDelay, dictionary, dictionary2)); } return true; Dictionary FilterFlags(Dictionary dict) { return dict.Where>((KeyValuePair kvp) => (forceLevel == ForceLevel.IncludeAll || !kvp.Value.flags.Ignore) && (forceLevel >= ForceLevel.IncludeCruiser || !kvp.Value.flags.KeepOnCruiser || !cars.Any((VehicleController car) => (Object)(object)((Component)kvp.Key).transform.parent == (Object)(object)((Component)car).transform))).ToDictionary((KeyValuePair kvp) => kvp.Key, (KeyValuePair kvp) => kvp.Value); } } private static void AutoSortAllItems() { try { Utils.objectCount.Clear(); GameNetworkManager.Instance.localPlayerController.DropAllHeldItemsAndSyncNonexact(); GrabbableObject[] array = Object.FindObjectsOfType(); if (array == null) { return; } array = array.Where((GrabbableObject i) => i != null && i.playerHeldBy == null && !(i is RagdollGrabbableObject)).ToArray(); if (array.Length == 0) { return; } Chat.Print("Sorting all items...", (Color?)null); VehicleController[] cars = Object.FindObjectsOfType() ?? Array.Empty(); Dictionary dictionary = FilterFlags(array.Where((GrabbableObject i) => i.itemProperties.isScrap).ToDictionary((GrabbableObject i) => i, (GrabbableObject item) => LethalShipSort.Instance.GetPosition(item))); Dictionary dictionary2 = FilterFlags(array.Where((GrabbableObject i) => !i.itemProperties.isScrap).ToDictionary((GrabbableObject i) => i, (GrabbableObject item) => LethalShipSort.Instance.GetPosition(item))); if (LethalShipSort.Instance.SortDelay < 10) { int num = 0; int num2 = 0; if (dictionary.Count != 0) { num = SortItems(dictionary); } if (dictionary2.Count != 0) { num2 = SortItems(dictionary2); } if (num != 0 || num2 != 0) { Chat.PrintError("Automatic sorting failed: " + ((num > 0) ? string.Format("{0} scrap items {1}", num, (num2 > 0) ? "and " : "") : "") + ((num2 > 0) ? $"{num2} tool items" : "") + " couldn't be sorted"); } else { Chat.Print("Finished sorting items", (Color?)null); } } else { if (sorting != null) { ((MonoBehaviour)GameNetworkManager.Instance.localPlayerController).StopCoroutine(sorting); } sorting = ((MonoBehaviour)GameNetworkManager.Instance.localPlayerController).StartCoroutine(SortAllItemsDelayed(LethalShipSort.Instance.SortDelay, dictionary, dictionary2, "Automatic sorting failed")); } Dictionary FilterFlags(Dictionary dict) { return dict.Where>(delegate(KeyValuePair kvp) { ItemPosition.Flags flags = kvp.Value.flags; return !flags.Ignore && !flags.NoAutoSort && (!kvp.Value.flags.KeepOnCruiser || !cars.Any((VehicleController car) => (Object)(object)((Component)kvp.Key).transform.parent == (Object)(object)((Component)car).transform)); }).ToDictionary((KeyValuePair kvp) => kvp.Key, (KeyValuePair kvp) => kvp.Value); } } catch (Exception arg) { Chat.PrintError("Automatic sorting failed due to an internal error, check the log for details"); LethalShipSort.Logger.LogError((object)$"Error while autosorting items: {arg}"); } } public static IEnumerator SortAllItemsDelayed(uint delay, Dictionary scrap, Dictionary tools, string errorPrefix = "Error running command") { int scrapFailed = 0; int toolsFailed = 0; foreach (KeyValuePair item in scrap) { try { if (!Utils.MoveItem(item.Key, item.Value)) { scrapFailed++; } } catch (Exception ex) { LethalShipSort.Logger.LogError((object)ex); scrapFailed++; } yield return (object)new WaitForSeconds((float)delay / 1000f); } foreach (KeyValuePair tool in tools) { try { if (!Utils.MoveItem(tool.Key, tool.Value)) { toolsFailed++; } } catch (Exception ex2) { LethalShipSort.Logger.LogError((object)ex2); toolsFailed++; } yield return (object)new WaitForSeconds((float)delay / 1000f); } string text = ((scrapFailed > 0) ? string.Format("{0} scrap items {1}", scrapFailed, (toolsFailed > 0) ? "and " : "") : "") + ((toolsFailed > 0) ? $"{toolsFailed} tool items" : "") + " couldn't be sorted"; if (scrapFailed != 0 || toolsFailed != 0) { Chat.PrintError(errorPrefix + ": " + text + ""); } else { Chat.Print("Finished sorting items", (Color?)null); } } public static int SortItems(Dictionary items) { return items.Count>(delegate(KeyValuePair kvp) { try { return !Utils.MoveItem(kvp.Key, kvp.Value); } catch (Exception ex) { LethalShipSort.Logger.LogError((object)ex); return true; } }); } } public static class Utils { private const string CLONE = "(Clone)"; internal static readonly Dictionary objectCount = new Dictionary(); internal const int LAYER_MASK = 268437761; public static IReadOnlyDictionary ObjectCount => objectCount; public static string RemoveClone(string name) { if (!name.EndsWith("(Clone)")) { return name; } int length = "(Clone)".Length; return name.Substring(0, name.Length - length); } public static bool MoveItem(GrabbableObject item, ItemPosition position) { //IL_0035: 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_0027: 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_0092: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) if (!position.position.HasValue) { throw new ArgumentNullException("ItemPosition.position can not be null"); } Vector3 positionOffset = (position.positionOffset.HasValue ? (position.positionOffset.Value * (float)GetItemCount(item)) : Vector3.zero); int floorYRot = (position.floorYRot ?? (-1)) + position.rotationOffset.GetValueOrDefault() * GetItemCount(item) % 360; if ((position.flags.Parent && (Object)(object)position.parentTo != (Object)null) ? MoveItem(item, position.position.Value, positionOffset, position.parentTo, floorYRot, position.randomOffset, position.flags) : MoveItemRelativeTo(item, position.position.Value, positionOffset, position.parentTo, floorYRot, position.randomOffset, position.flags)) { return IncreaseItemCount(item); } return false; } private static bool IncreaseItemCount(GrabbableObject item) { string key = ItemKey(item); objectCount[key] = objectCount.GetValueOrDefault(key) + 1; return true; } private static int GetItemCount(GrabbableObject item) { return objectCount.GetValueOrDefault(ItemKey(item)); } public static string ItemKey(GrabbableObject item) { ShotgunItem val = (ShotgunItem)(object)((item is ShotgunItem) ? item : null); if (val != null && val.shellsLoaded > 0) { return string.Format("{0}-{1}", "ShotgunItem", Math.Min(val.shellsLoaded, 2)); } return RemoveClone(((Object)item).name); } public static bool MoveItemRelativeTo(GrabbableObject item, Vector3 position, Vector3 positionOffset, GameObject? relativeTo, int floorYRot, float? randomOffset, ItemPosition.Flags flags) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_013d: 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_015d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: 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_00c7: 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_00d3: 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) LethalShipSort.Logger.LogInfo((object)string.Format(">> Moving item {0} to position {1} relative to {2}", RemoveClone(((Object)item).name), position, ((Object)(object)relativeTo == (Object)null) ? "ship" : RemoveClone(((Object)relativeTo).name))); GameObject val = GameObject.Find("Environment/HangarShip"); if ((Object)(object)val == (Object)null) { LethalShipSort.Logger.LogWarning((object)" Couldn't find ship"); return false; } if ((Object)(object)relativeTo == (Object)null) { relativeTo = val; } if (!flags.Exact) { RaycastHit val2 = default(RaycastHit); if (!Physics.Raycast(relativeTo.transform.TransformPoint(position), Vector3.down, ref val2, 80f, 268437761, (QueryTriggerInteraction)1)) { LethalShipSort.Logger.LogWarning((object)" Raycast unsuccessful"); return false; } position = Randomize(val.transform.InverseTransformPoint(((RaycastHit)(ref val2)).point + item.itemProperties.verticalOffset * Vector3.up + positionOffset), randomOffset); } else { position = Randomize(position + item.itemProperties.verticalOffset * Vector3.up + positionOffset, randomOffset); } LethalShipSort.Logger.LogDebug((object)$" true position: {position}"); GameNetworkManager.Instance.localPlayerController.SetObjectAsNoLongerHeld(true, true, position, item, floorYRot); GameNetworkManager.Instance.localPlayerController.ThrowObjectServerRpc(NetworkObjectReference.op_Implicit(((NetworkBehaviour)item).NetworkObject), true, true, position, floorYRot); return true; } public static bool MoveItem(GrabbableObject item, Vector3 position, Vector3 positionOffset, GameObject parentTo, int floorYRot, float? randomOffset, ItemPosition.Flags flags) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: 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_00b3: Unknown result type (might be due to invalid IL or missing references) LethalShipSort.Logger.LogInfo((object)$">> Moving item {RemoveClone(((Object)item).name)} to position {position} in {RemoveClone(((Object)parentTo).name)}"); if (!flags.Exact) { RaycastHit val = default(RaycastHit); if (!Physics.Raycast(parentTo.transform.TransformPoint(position), Vector3.down, ref val, 80f, 268437761, (QueryTriggerInteraction)1)) { LethalShipSort.Logger.LogWarning((object)" Raycast unsuccessful"); return false; } position = parentTo.transform.InverseTransformPoint(Randomize(((RaycastHit)(ref val)).point + item.itemProperties.verticalOffset * Vector3.up - new Vector3(0f, 0.05f, 0f) + positionOffset, randomOffset)); } else { position = Randomize(position + item.itemProperties.verticalOffset * Vector3.up - new Vector3(0f, 0.05f, 0f) + positionOffset, randomOffset); } LethalShipSort.Logger.LogDebug((object)$" true position: {position}"); GameNetworkManager.Instance.localPlayerController.SetObjectAsNoLongerHeld(true, true, position, item, floorYRot); GameNetworkManager.Instance.localPlayerController.ThrowObjectServerRpc(NetworkObjectReference.op_Implicit(((NetworkBehaviour)item).NetworkObject), true, true, position, floorYRot); GameNetworkManager.Instance.localPlayerController.PlaceGrabbableObject(parentTo.transform, position, false, item); GameNetworkManager.Instance.localPlayerController.PlaceObjectServerRpc(NetworkObjectReference.op_Implicit(((NetworkBehaviour)item).NetworkObject), NetworkObjectReference.op_Implicit(parentTo), position, false); return true; } public static Vector3 Randomize(Vector3 position, float? maxDistance = null) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_0099: Unknown result type (might be due to invalid IL or missing references) if (maxDistance < 0f) { throw new ArgumentException("Invalid randomOffset (must be positive)"); } if (!maxDistance.HasValue || Mathf.Approximately(maxDistance.Value, 0f)) { return position; } Random random = new Random(); return new Vector3(position.x + (float)random.NextDouble() * maxDistance.Value * 2f - maxDistance.Value, position.y, position.z + (float)random.NextDouble() * maxDistance.Value * 2f - maxDistance.Value); } public static string GameObjectPath(GameObject gameObject) { Transform parent = gameObject.transform.parent; string text = ((Object)gameObject).name; while ((Object)(object)parent != (Object)null) { text = ((Object)parent).name + "/" + text; parent = ((Component)parent).transform.parent; } return text; } } public static class MyPluginInfo { public const string PLUGIN_GUID = "baer1.ShipSort"; public const string PLUGIN_NAME = "LethalShipSort"; public const string PLUGIN_VERSION = "4.0.2"; } }