Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of QuickSort v0.1.26
QuickSort.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ChatCommandAPI; using ChatCommandAPI.Utils; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("0Harmony")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("BepInEx")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")] [assembly: IgnoresAccessChecksTo("UnityEngine.IMGUIModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UI")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("QuickSort")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("made by Asta")] [assembly: AssemblyFileVersion("0.1.26.0")] [assembly: AssemblyInformationalVersion("0.1.26+73d391632d6865e132cc9b45eed99aaef62db280")] [assembly: AssemblyProduct("QuickSort")] [assembly: AssemblyTitle("QuickSort")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.26.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 QuickSort { public static class Chat { [HarmonyPatch(typeof(HUDManager), "SubmitChat_performed")] [HarmonyPrefix] [HarmonyWrapSafe] public static bool OnChatSubmit(HUDManager __instance, CallbackContext context) { if (!((CallbackContext)(ref context)).performed || !Player.Local.isTypingChat) { return true; } string text = __instance.chatTextField.text; if (text == "/help") { Log.Chat("Commands: " + string.Join(", ", ChatCommand.Commands)); CloseChat(__instance); return false; } if (text.StartsWith("/")) { text = text.Substring(1).Trim(); foreach (ChatCommand command in ChatCommand.Commands) { if (text.StartsWith(command.keyword)) { CloseChat(__instance); try { command.action(command.GetArgs(text)); } catch (Exception e) { Log.Exception(e); } return false; } } } return true; } public static void CloseChat(HUDManager instance) { instance.localPlayer.isTypingChat = false; instance.chatTextField.text = ""; EventSystem.current.SetSelectedGameObject((GameObject)null); ((Behaviour)instance.typingIndicator).enabled = false; } } public abstract class Argument { public string name; } public class Argument<T> : Argument { public T value; public Argument(string name, T value) { base.name = name; this.value = value; } public static implicit operator T(Argument<T> arg) { return arg.value; } } public struct ChatArgs { public Argument[] arguments; public string help; public int Length => arguments.Length; public bool Empty => arguments.Length == 0; public bool this[string name] => Get<bool>(name); public string this[int name] => Get<string>(name); public T Get<T>(string name) { Argument[] array = arguments; foreach (Argument argument in array) { if (argument.name == name) { return ((Argument<T>)argument).value; } } return default(T); } public T Get<T>(int name) { Argument[] array = arguments; foreach (Argument argument in array) { if (argument.name == name.ToString()) { return ((Argument<T>)argument).value; } } return default(T); } } public class ChatCommand { public static List<ChatCommand> Commands = new List<ChatCommand>(); public string keyword; public Action<ChatArgs> action; public string help; public ChatCommand(string keyword, string help, Action<ChatArgs> action) { this.keyword = keyword; this.help = help; this.action = action; } public static ChatCommand New(string keyword, string help, Action<ChatArgs> action) { ChatCommand chatCommand = new ChatCommand(keyword, help, action); Commands.Add(chatCommand); return chatCommand; } public ChatArgs GetArgs(string raw) { List<Argument> list = new List<Argument>(); string[] array = raw.Split(' '); keyword = array[0]; for (int i = 1; i < array.Length; i++) { if (array[i].StartsWith("-")) { string name = array[i].Substring(1); list.Add(new Argument<bool>(name, value: true)); } else { list.Add(new Argument<string>((i - 1).ToString(), array[i])); } } return new ChatArgs { arguments = list.ToArray(), help = help }; } public override string ToString() { return keyword; } } internal static class CruiserPositions { [Serializable] private sealed class PositionsFile { public List<PositionEntry> positions = new List<PositionEntry>(); } [Serializable] private sealed class PositionEntry { public string item = ""; public float x; public float y; public float z; public int maxCount = 10; } public static string PositionsPath => Path.Combine(Paths.ConfigPath, "pasta.quicksort.cruiser.positions.json"); public static void EnsureFileExists() { try { if (!File.Exists(PositionsPath)) { Save(new PositionsFile(), out string _); } } catch (Exception ex) { Log.Warning("Failed to create cruiser positions file: " + ex.Message); } } private static PositionsFile Load(out string? error) { error = null; EnsureFileExists(); try { PositionsFile positionsFile = JsonConvert.DeserializeObject<PositionsFile>(File.ReadAllText(PositionsPath, Encoding.UTF8)); if (positionsFile == null || positionsFile.positions == null) { throw new InvalidDataException("Missing positions list."); } return positionsFile; } catch (Exception ex) { error = "Failed to load cruiser positions: " + ex.Message; return new PositionsFile(); } } private static bool Save(PositionsFile data, out string? error) { error = null; string positionsPath = PositionsPath; string text = positionsPath + ".tmp"; try { string directoryName = Path.GetDirectoryName(positionsPath); if (!string.IsNullOrWhiteSpace(directoryName)) { Directory.CreateDirectory(directoryName); } File.WriteAllText(text, JsonConvert.SerializeObject((object)data, (Formatting)1), Encoding.UTF8); if (File.Exists(positionsPath)) { try { File.Replace(text, positionsPath, positionsPath + ".bak", ignoreMetadataErrors: true); } catch { File.Copy(text, positionsPath, overwrite: true); File.Delete(text); } } else { File.Move(text, positionsPath); } return true; } catch (Exception ex) { error = "Failed to save cruiser positions: " + ex.Message; return false; } } private static bool Valid(Vector3 point, int count) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) if (count > 0 && count <= 10000 && !float.IsNaN(point.x) && !float.IsNaN(point.y) && !float.IsNaN(point.z) && !float.IsInfinity(point.x) && !float.IsInfinity(point.y)) { return !float.IsInfinity(point.z); } return false; } public static bool Set(string itemKey, Vector3 cruiserLocalPos, int maxCount, out string? error) { //IL_002b: 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_0086: 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) itemKey = Extensions.NormalizeName(itemKey); if (string.IsNullOrWhiteSpace(itemKey) || !Valid(cruiserLocalPos, maxCount)) { error = "Invalid cruiser item, position, or maximum (1-10000)."; return false; } PositionsFile positionsFile = Load(out error); if (error != null) { return false; } positionsFile.positions.RemoveAll((PositionEntry p) => p != null && Extensions.NormalizeName(p.item) == itemKey); positionsFile.positions.Add(new PositionEntry { item = itemKey, x = cruiserLocalPos.x, y = cruiserLocalPos.y, z = cruiserLocalPos.z, maxCount = maxCount }); return Save(positionsFile, out error); } public static bool Remove(string itemKey, out bool removed, out string? error) { itemKey = Extensions.NormalizeName(itemKey); PositionsFile positionsFile = Load(out error); removed = false; if (error != null) { return false; } removed = positionsFile.positions.RemoveAll((PositionEntry p) => p != null && Extensions.NormalizeName(p.item) == itemKey) > 0; if (removed) { return Save(positionsFile, out error); } return true; } public static List<(string itemKey, Vector3 cruiserLocalPos, int maxCount)> ListAll(out string? error) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) PositionsFile positionsFile = Load(out error); if (error != null) { return new List<(string, Vector3, int)>(); } List<(string, Vector3, int)> list = new List<(string, Vector3, int)>(); HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); Vector3 val = default(Vector3); foreach (PositionEntry position in positionsFile.positions) { if (position != null) { string text = Extensions.NormalizeName(position.item); ((Vector3)(ref val))..ctor(position.x, position.y, position.z); if (string.IsNullOrWhiteSpace(text) || !Valid(val, position.maxCount) || !hashSet.Add(text)) { error = "Invalid or duplicate cruiser position for '" + position.item + "'."; return new List<(string, Vector3, int)>(); } list.Add((text, val, position.maxCount)); } } return list.OrderBy<(string, Vector3, int), string>(((string itemKey, Vector3 cruiserLocalPos, int maxCount) p) => p.itemKey).ToList(); } public static bool ReplaceAll(IEnumerable<(string itemKey, Vector3 cruiserLocalPos, int maxCount)> positions, out string? error) { //IL_0041: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) error = null; if (positions == null) { error = "Cruiser positions are missing."; return false; } List<PositionEntry> list = new List<PositionEntry>(); HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); foreach (var position in positions) { string text = Extensions.NormalizeName(position.itemKey); Vector3 item = position.cruiserLocalPos; if (string.IsNullOrWhiteSpace(text) || !hashSet.Add(text) || !Valid(item, position.maxCount)) { error = "Invalid or duplicate cruiser position for '" + position.itemKey + "'."; return false; } list.Add(new PositionEntry { item = text, x = item.x, y = item.y, z = item.z, maxCount = position.maxCount }); } Load(out error); if (error != null) { return false; } return Save(new PositionsFile { positions = list }, out error); } } internal sealed class CruiserShelfAnchor : MonoBehaviour { private GrabbableObject? item; private Rigidbody? body; private Transform? cargoParent; private Transform? cruiserTransform; private Vector3 localPosition; private Quaternion shelfRotation; private bool originalKinematic; private bool initialized; internal static void Attach(GrabbableObject item, Transform cargoParent, Transform cruiserTransform) { if (!((Object)(object)item == (Object)null) && !((Object)(object)cargoParent == (Object)null) && !((Object)(object)cruiserTransform == (Object)null) && !((Object)(object)((Component)item).transform.parent != (Object)(object)cargoParent) && !item.isHeld) { CruiserShelfAnchor cruiserShelfAnchor = ((Component)item).GetComponent<CruiserShelfAnchor>(); if ((Object)(object)cruiserShelfAnchor == (Object)null) { cruiserShelfAnchor = ((Component)item).gameObject.AddComponent<CruiserShelfAnchor>(); } cruiserShelfAnchor.Configure(item, cargoParent, cruiserTransform); } } internal static void Detach(GrabbableObject item) { if (!((Object)(object)item == (Object)null)) { CruiserShelfAnchor component = ((Component)item).GetComponent<CruiserShelfAnchor>(); if ((Object)(object)component != (Object)null) { component.ReleaseForPickup(); } } } private void Configure(GrabbableObject placedItem, Transform parent, Transform cruiser) { //IL_0059: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_0086: Unknown result type (might be due to invalid IL or missing references) if (!initialized) { item = placedItem; body = ((Component)placedItem).GetComponent<Rigidbody>(); originalKinematic = (Object)(object)body != (Object)null && body.isKinematic; initialized = true; } cargoParent = parent; cruiserTransform = cruiser; localPosition = ((Component)placedItem).transform.localPosition; Vector3 restingRotation = placedItem.itemProperties.restingRotation; shelfRotation = Quaternion.Euler(restingRotation.x, 0f, restingRotation.z); PinItem(); } private void FixedUpdate() { if (!StillOnCruiser()) { Release(); Object.Destroy((Object)(object)this); } else { PinBody(); } } private void LateUpdate() { if (!StillOnCruiser()) { Release(); Object.Destroy((Object)(object)this); } else { PinItem(); } } private bool StillOnCruiser() { if (initialized && (Object)(object)item != (Object)null && (Object)(object)cargoParent != (Object)null && (Object)(object)cruiserTransform != (Object)null && (Object)(object)((Component)item).transform.parent == (Object)(object)cargoParent && !item.isHeld && !item.isPocketed) { return !item.deactivated; } return false; } private void PinItem() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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) if (!((Object)(object)item == (Object)null) && !((Object)(object)cruiserTransform == (Object)null)) { ((Component)item).transform.localPosition = localPosition; ((Component)item).transform.rotation = cruiserTransform.rotation * shelfRotation; item.targetFloorPosition = localPosition; item.startFallingPosition = localPosition; item.fallTime = 1.1f; item.reachedFloorTarget = true; item.hasHitGround = true; PinBody(); } } private void PinBody() { //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_008c: 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_003e: 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) if (!((Object)(object)body == (Object)null) && !((Object)(object)cargoParent == (Object)null) && !((Object)(object)cruiserTransform == (Object)null)) { if (!body.isKinematic) { body.velocity = Vector3.zero; body.angularVelocity = Vector3.zero; body.isKinematic = true; } body.position = cargoParent.TransformPoint(localPosition); body.rotation = cruiserTransform.rotation * shelfRotation; } } private void Release() { if (initialized) { initialized = false; if ((Object)(object)body != (Object)null) { body.isKinematic = originalKinematic; } } } internal void ReleaseForPickup() { Release(); Object.Destroy((Object)(object)this); } private void OnDisable() { Release(); } private void OnDestroy() { Release(); } } internal static class CruiserShelfAnchorPatch { [HarmonyPatch(typeof(PlayerControllerB), "PlaceGrabbableObject")] [HarmonyPostfix] private static void AfterPlacement(Transform parentObject, bool matchRotationOfParent, GrabbableObject placeObject) { //IL_0033: 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_003d: 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) if (!matchRotationOfParent || (Object)(object)parentObject == (Object)null || (Object)(object)placeObject == (Object)null) { return; } VehicleController componentInParent = ((Component)parentObject).GetComponentInParent<VehicleController>(); if (!((Object)(object)componentInParent == (Object)null)) { Vector3 cruiserLocalPosition = ((Component)componentInParent).transform.InverseTransformPoint(((Component)placeObject).transform.position); if (CruiserSorter.IsShelfSlot(placeObject, cruiserLocalPosition)) { PlayerPhysicsRegion componentInChildren = ((Component)componentInParent).GetComponentInChildren<PlayerPhysicsRegion>(); Transform cargoParent = (((Object)(object)componentInChildren != (Object)null && componentInChildren.allowDroppingItems && (Object)(object)componentInChildren.physicsTransform != (Object)null) ? componentInChildren.physicsTransform : ((Component)componentInParent).transform); CruiserShelfAnchor.Attach(placeObject, cargoParent, ((Component)componentInParent).transform); } } } [HarmonyPatch(typeof(PlayerControllerB), "GrabObjectClientRpc")] [HarmonyPrefix] private static void BeforePickup(bool grabValidated, NetworkObjectReference grabbedObject) { NetworkObject val = default(NetworkObject); if (grabValidated && ((NetworkObjectReference)(ref grabbedObject)).TryGet(ref val, (NetworkManager)null)) { CruiserShelfAnchor componentInChildren = ((Component)val).GetComponentInChildren<CruiserShelfAnchor>(); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.ReleaseForPickup(); } } } } internal static class CruiserSorter { private const int MaxShelfZoneSlots = 20; internal const float SavedHeightOffset = 0.3f; private static readonly Dictionary<string, Vector3> Zones = new Dictionary<string, Vector3>(StringComparer.OrdinalIgnoreCase) { ["A1"] = new Vector3(-1.15f, -0.4f, -2.6f), ["A2"] = new Vector3(-1.15f, 0.46f, -2.6f), ["A3"] = new Vector3(-1.15f, 1.22f, -2.6f), ["B1"] = new Vector3(-1.15f, -0.4f, -1.7f), ["B2"] = new Vector3(-1.15f, 0.46f, -1.7f), ["B3"] = new Vector3(-1.15f, 1.22f, -1.7f), ["C1"] = new Vector3(-1.15f, -0.4f, -0.8f), ["C2"] = new Vector3(-1.15f, 0.46f, -0.8f), ["C3"] = new Vector3(-1.15f, 1.22f, -0.8f), ["D1"] = new Vector3(-0.91f, 0f, 0.3f), ["D2"] = new Vector3(0f, -0.5f, -0.55f), ["D3"] = new Vector3(0.82f, 0f, 0.3f), ["E1"] = new Vector3(1.15f, -0.4f, -2.6f), ["E2"] = new Vector3(1.15f, 0.46f, -2.6f), ["E3"] = new Vector3(1.15f, 1.22f, -2.6f), ["F1"] = new Vector3(1.15f, -0.4f, -1.7f), ["F2"] = new Vector3(1.15f, 0.46f, -1.7f), ["F3"] = new Vector3(1.15f, 1.22f, -1.7f), ["G1"] = new Vector3(1.15f, -0.4f, -0.8f), ["G2"] = new Vector3(1.15f, 0.46f, -0.8f), ["G3"] = new Vector3(1.15f, 1.22f, -0.8f) }; private static int cargoParentCacheFrame = -1; private static Transform[] cargoParentCache = Array.Empty<Transform>(); private static int ZoneCapacity(string zone) { if (!(zone == "D2")) { return 20; } return 1; } internal static bool TryGetZone(string? name, out string zoneName, out Vector3 position) { zoneName = (name ?? "").Trim().ToUpperInvariant(); return Zones.TryGetValue(zoneName, out position); } internal static string? ZoneAt(Vector3 position) { //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_0039: 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_0058: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair<string, Vector3> zone in Zones) { if (Mathf.Abs(zone.Value.x - position.x) < 0.001f && Mathf.Abs(zone.Value.z - position.z) < 0.001f && (Mathf.Abs(zone.Value.y - position.y) < 0.001f || Mathf.Abs(zone.Value.y + 0.3f - position.y) < 0.001f)) { return zone.Key; } } return null; } private static VehicleController? FindNearestCruiser() { PlayerControllerB player = Player.Local; if ((Object)(object)player == (Object)null) { return null; } return Object.FindObjectsOfType<VehicleController>().OrderBy(delegate(VehicleController c) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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) Vector3 val = ((Component)c).transform.position - ((Component)player).transform.position; return ((Vector3)(ref val)).sqrMagnitude; }).FirstOrDefault(); } private static VehicleController? FindCruiserNearPlayer() { //IL_006a: 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_0074: 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_0084: 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_00a0: 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_00bc: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB player = Player.Local; if ((Object)(object)player == (Object)null) { return null; } foreach (VehicleController item in Object.FindObjectsOfType<VehicleController>().OrderBy(delegate(VehicleController c) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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) Vector3 val2 = ((Component)c).transform.position - ((Component)player).transform.position; return ((Vector3)(ref val2)).sqrMagnitude; })) { Vector3 val = ((Component)item).transform.InverseTransformPoint(((Component)player).transform.position); if (val.x >= -2.2f && val.x <= 2.2f && val.y >= -2f && val.y <= 3f && val.z >= -4f && val.z <= 1.6f) { return item; } } return null; } internal static bool TryGetPlayerPosition(out VehicleController? cruiser, out Vector3 localPosition, out string? error) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) cruiser = FindCruiserNearPlayer(); localPosition = default(Vector3); error = null; if ((Object)(object)cruiser == (Object)null) { error = "Stand on the cruiser to use this command."; return false; } PlayerControllerB local = Player.Local; if ((Object)(object)local == (Object)null) { error = "Local player not ready yet."; return false; } localPosition = ((Component)cruiser).transform.InverseTransformPoint(((Component)local).transform.position); return true; } internal static bool TryResolveItemKey(string? query, out string key, out string? error) { error = null; key = ""; if (string.IsNullOrWhiteSpace(query)) { GrabbableObject val = Player.Local?.currentlyHeldObjectServer; if ((Object)(object)val == (Object)null) { error = "Hold an item or provide its name."; return false; } key = val.Name(); return true; } string wanted = Extensions.NormalizeName(query); if (string.IsNullOrWhiteSpace(wanted)) { error = "Missing item name."; return false; } HashSet<string> hashSet = KnownItemKeys(); if (hashSet.Contains(wanted)) { key = wanted; return true; } List<string> list = (from n in hashSet where n.Contains(wanted) || n.Replace("_", "").Contains(wanted.Replace("_", "")) orderby n select n).ToList(); if (list.Count == 1) { key = list[0]; return true; } if (list.Count > 1) { error = "Ambiguous item name: " + string.Join(", ", list.Take(8)); return false; } key = wanted; return true; } private static HashSet<string> KnownItemKeys() { HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); List<Item> list = StartOfRound.Instance?.allItemsList?.itemsList; if (list != null) { foreach (Item item in list) { if ((Object)(object)item != (Object)null) { hashSet.Add(item.Name()); } } } GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>(); foreach (GrabbableObject val in array) { if ((Object)(object)val != (Object)null && (Object)(object)val.itemProperties != (Object)null) { hashSet.Add(val.Name()); } } return hashSet; } internal static bool IsExactAvailableItem(string query) { return KnownItemKeys().Contains(Extensions.NormalizeName(query)); } internal static bool TryStart(out string? error) { if (!CheckCruiserReady(out VehicleController cruiser, out error) || (Object)(object)cruiser == (Object)null) { return false; } List<(string, Vector3, int)> list = CruiserPositions.ListAll(out error); if (error != null) { return false; } if (list.Count == 0) { error = "No cruiser positions saved. Use /css [item] [max] while on the cruiser."; return false; } return StartSort(cruiser, list, dropMatchingHeld: false, out error); } internal static bool TryStartScrapPileAtShipRejoinLocation(out string? error) { //IL_0067: 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_0085: 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) //IL_008d: 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_0095: Unknown result type (might be due to invalid IL or missing references) error = null; if (!CheckCruiserReady(out VehicleController cruiser, out error) || (Object)(object)cruiser == (Object)null) { return false; } GameObject val = GameObject.Find("Environment/HangarShip"); if ((Object)(object)val == (Object)null) { error = "Ship not found; cannot locate its rejoin item area."; return false; } Transform[] array = StartOfRound.Instance?.playerSpawnPositions; if (array == null || array.Length <= 1 || (Object)(object)array[1] == (Object)null) { error = "Ship rejoin item area is not available yet."; return false; } Vector3 val2 = array[1].position + new Vector3(0f, 0.5f, 2f); Vector3 targetShipLocalPosition = val.transform.InverseTransformPoint(val2); return StartScrapPileSort(cruiser, targetShipLocalPosition, out error); } internal static bool TryStartRule(VehicleController cruiser, string itemKey, Vector3 localPosition, int maximum, out string? error) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (!CheckCruiserReady(cruiser, out error)) { return false; } List<(string, Vector3, int)> rules = new List<(string, Vector3, int)> { (itemKey, localPosition, maximum) }; return StartSort(cruiser, rules, dropMatchingHeld: true, out error); } private static bool StartSort(VehicleController cruiser, List<(string itemKey, Vector3 cruiserLocalPos, int maxCount)> rules, bool dropMatchingHeld, out string? error) { if (Sorter.inProgress) { error = "Operation in progress."; return false; } if (!TryGetSortHost(out Sorter host, out error) || (Object)(object)host == (Object)null) { return false; } Sorter.inProgress = true; try { if (((MonoBehaviour)host).StartCoroutine(SortCruiser(cruiser, rules, dropMatchingHeld)) == null) { Sorter.inProgress = false; error = "Unable to start cruiser sort."; return false; } return true; } catch (Exception ex) { Sorter.inProgress = false; error = "Unable to start cruiser sort: " + ex.Message; Log.Error(error); return false; } } private static bool StartScrapPileSort(VehicleController cruiser, Vector3 targetShipLocalPosition, out string? error) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) if (Sorter.inProgress) { error = "Operation in progress."; return false; } List<GrabbableObject> list = (from item in CruiserCargoItems(cruiser) where Eligible(item) && item.itemProperties.isScrap select item).ToList(); if (list.Count == 0) { error = "No loose scrap found on the cruiser."; return false; } if (!TryGetSortHost(out Sorter host, out error) || (Object)(object)host == (Object)null) { return false; } Sorter.inProgress = true; try { if (((MonoBehaviour)host).StartCoroutine(SortScrapPile(cruiser, targetShipLocalPosition, list)) == null) { Sorter.inProgress = false; error = "Unable to start cruiser scrap gather."; return false; } Chat.Print($"Gathering {list.Count} cruiser scrap item(s) at the ship's rejoin item area.", (Color?)null); return true; } catch (Exception ex) { Sorter.inProgress = false; error = "Unable to start cruiser scrap gather: " + ex.Message; Log.Error(error); return false; } } private static bool TryGetSortHost(out Sorter? host, out string? error) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown host = null; error = null; try { if ((Object)(object)Plugin.sorterObject == (Object)null) { Plugin.sorterObject = new GameObject("PastaSorter"); Object.DontDestroyOnLoad((Object)(object)Plugin.sorterObject); } host = Plugin.sorterObject.GetComponent<Sorter>(); if ((Object)(object)host == (Object)null) { host = Plugin.sorterObject.AddComponent<Sorter>(); } if ((Object)(object)host == (Object)null || !((Behaviour)host).isActiveAndEnabled) { error = "Cruiser sorter is not active."; return false; } return true; } catch (Exception ex) { error = "Unable to initialize cruiser sorter: " + ex.Message; Log.Error(error); return false; } } internal static bool CheckCruiserReady(out VehicleController? cruiser, out string? error) { cruiser = FindNearestCruiser(); return CheckCruiserReady(cruiser, out error); } internal static bool CheckCruiserReady(VehicleController? cruiser, out string? error) { error = null; if (Sorter.inProgress) { error = "Operation in progress."; return false; } if ((Object)(object)cruiser == (Object)null) { error = "Cruiser not found."; return false; } NetworkObject component = ((Component)cruiser).GetComponent<NetworkObject>(); if ((Object)(object)component == (Object)null || !component.IsSpawned) { error = "Cruiser network object not ready yet."; return false; } return true; } private static bool Eligible(GrabbableObject item) { if ((Object)(object)item != (Object)null && (Object)(object)item.itemProperties != (Object)null && (Object)(object)((NetworkBehaviour)item).NetworkObject != (Object)null && ((NetworkBehaviour)item).NetworkObject.IsSpawned && item.grabbable && !item.deactivated && !item.isHeld) { return !item.isPocketed; } return false; } private static Transform PlacementParent(VehicleController cruiser) { PlayerPhysicsRegion componentInChildren = ((Component)cruiser).GetComponentInChildren<PlayerPhysicsRegion>(); if (!((Object)(object)componentInChildren != (Object)null) || !componentInChildren.allowDroppingItems || !((Object)(object)componentInChildren.physicsTransform != (Object)null)) { return ((Component)cruiser).transform; } return componentInChildren.physicsTransform; } internal static bool IsCruiserCargo(GrabbableObject item) { if ((Object)(object)item == (Object)null || (Object)(object)((Component)item).transform == (Object)null) { return false; } if ((Object)(object)((Component)item).GetComponentInParent<VehicleController>() != (Object)null) { return true; } if (cargoParentCacheFrame != Time.frameCount) { cargoParentCacheFrame = Time.frameCount; cargoParentCache = (from cruiser in Object.FindObjectsOfType<VehicleController>() where (Object)(object)cruiser != (Object)null select cruiser).Select(PlacementParent).Distinct().ToArray(); } Transform[] array = cargoParentCache; foreach (Transform val in array) { if ((Object)(object)val != (Object)null && ((Component)item).transform.IsChildOf(val)) { return true; } } return false; } private static Vector3 PlacementOffset(VehicleController cruiser, Transform parent, Vector3 cruiserLocalPosition) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) return parent.InverseTransformPoint(((Component)cruiser).transform.TransformPoint(cruiserLocalPosition)); } private static List<GrabbableObject> CruiserCargoItems(VehicleController cruiser) { Transform val = PlacementParent(cruiser); return ((Component)cruiser).GetComponentsInChildren<GrabbableObject>().Concat(((Component)val).GetComponentsInChildren<GrabbableObject>()).Distinct() .ToList(); } private static Dictionary<string, int> ReservedZoneSlots(VehicleController cruiser, List<(string itemKey, Vector3 cruiserLocalPos, int maxCount)> movingRules) { //IL_00be: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.Ordinal); HashSet<string> hashSet = new HashSet<string>(movingRules.Select<(string, Vector3, int), string>(((string itemKey, Vector3 cruiserLocalPos, int maxCount) r) => r.itemKey), StringComparer.Ordinal); string error; List<(string, Vector3, int)> list = CruiserPositions.ListAll(out error); if (error != null) { Log.Warning(error); return dictionary; } List<GrabbableObject> source = CruiserCargoItems(cruiser).Where(Eligible).ToList(); foreach (var rule in list) { if (hashSet.Contains(rule.Item1)) { continue; } string text = ZoneAt(rule.Item2); if (text != null) { int num = source.Count((GrabbableObject item) => item.Name() == rule.Item1); if (num > 0) { dictionary[text] = (dictionary.TryGetValue(text, out var value) ? (value + num) : num); } } } return dictionary; } private static bool IsShipCargo(GrabbableObject item, GameObject? ship) { if ((Object)(object)ship == (Object)null || (Object)(object)((Component)item).transform == (Object)null) { return false; } if (((Component)item).transform.IsChildOf(ship.transform)) { return true; } if ((Object)(object)((Component)item).transform.parent != (Object)null) { return ((Object)((Component)item).transform.parent).name == "StorageCloset"; } return false; } private static Vector3 Placement(Vector3 origin, int index) { //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_0016: 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_00bb: 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) string text = ZoneAt(origin); if (text != null && Mathf.Abs(origin.y - Zones[text].y) < 0.001f) { origin.y += 0.3f; } GameObject sorterObject = Plugin.sorterObject; float num = ((sorterObject == null) ? ((float?)null) : sorterObject.GetComponent<Sorter>()?.sameTypeStackStepY?.Value).GetValueOrDefault(); if (float.IsNaN(num) || float.IsInfinity(num)) { num = 0f; } return origin + new Vector3(0f, (float)index * Mathf.Max(0f, num), 0f); } internal static bool IsShelfSlot(GrabbableObject item, Vector3 cruiserLocalPosition) { //IL_00db: 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_00fd: 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_011f: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item == (Object)null || (Object)(object)item.itemProperties == (Object)null) { return false; } string text = item.Name(); string error; List<(string, Vector3, int)> list = CruiserPositions.ListAll(out error); if (error != null) { Log.Warning(error); return false; } GameObject sorterObject = Plugin.sorterObject; float num = ((sorterObject == null) ? ((float?)null) : sorterObject.GetComponent<Sorter>()?.sameTypeStackStepY?.Value).GetValueOrDefault(); if (float.IsNaN(num) || float.IsInfinity(num)) { num = 0f; } num = Mathf.Max(0f, num); foreach (var item2 in list) { if (item2.Item1 != text || Mathf.Abs(item2.Item2.x - cruiserLocalPosition.x) >= 0.03f || Mathf.Abs(item2.Item2.z - cruiserLocalPosition.z) >= 0.03f) { continue; } string text2 = ZoneAt(item2.Item2); float num2 = item2.Item2.y; if (text2 != null && Mathf.Abs(num2 - Zones[text2].y) < 0.001f) { num2 += 0.3f; } int num3 = ((text2 == null) ? item2.Item3 : ZoneCapacity(text2)); if (num3 <= 0) { continue; } float num4 = cruiserLocalPosition.y - num2; if (num <= 0f) { if (Mathf.Abs(num4) < 0.03f) { return true; } continue; } float num5 = num4 / num; if (!(num5 < -0.03f / num) && !(num5 > (float)(num3 - 1) + 0.03f / num)) { int num6 = Mathf.RoundToInt(num5); if (num6 >= 0 && num6 < num3 && Mathf.Abs(num4 - (float)num6 * num) < 0.03f) { return true; } } } return false; } private static bool PlaceOnCruiser(GrabbableObject item, VehicleController cruiser, Vector3 localPosition) { //IL_0144: 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_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0179: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: 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_00c7: 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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: 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_0104: 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_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0117: 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_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB local = Player.Local; NetworkObject component = ((Component)cruiser).GetComponent<NetworkObject>(); if ((Object)(object)local == (Object)null || (Object)(object)component == (Object)null || !component.IsSpawned || !Eligible(item)) { return false; } Transform val = PlacementParent(cruiser); Vector3 val2 = PlacementOffset(cruiser, val, localPosition); Transform parent = ((Component)item).transform.parent; Vector3 position = ((Component)item).transform.position; Quaternion rotation = ((Component)item).transform.rotation; float fallTime = item.fallTime; bool reachedFloorTarget = item.reachedFloorTarget; bool hasHitGround = item.hasHitGround; Vector3 targetFloorPosition = item.targetFloorPosition; Vector3 startFallingPosition = item.startFallingPosition; try { ((Component)item).transform.SetParent(val, true); ((Component)item).transform.localPosition = val2; Vector3 restingRotation = item.itemProperties.restingRotation; ((Component)item).transform.rotation = ((Component)cruiser).transform.rotation * Quaternion.Euler(restingRotation.x, 0f, restingRotation.z); item.fallTime = 1.1f; item.reachedFloorTarget = true; item.hasHitGround = true; item.targetFloorPosition = val2; item.startFallingPosition = val2; local.PlaceObjectServerRpc(NetworkObjectReference.op_Implicit(((NetworkBehaviour)item).NetworkObject), NetworkObjectReference.op_Implicit(component), val2, true); } catch (Exception ex) { ((Component)item).transform.SetParent(parent, true); ((Component)item).transform.position = position; ((Component)item).transform.rotation = rotation; item.fallTime = fallTime; item.reachedFloorTarget = reachedFloorTarget; item.hasHitGround = hasHitGround; item.targetFloorPosition = targetFloorPosition; item.startFallingPosition = startFallingPosition; Log.Warning("Failed to place '" + item.Name() + "' on cruiser: " + ex.Message); return false; } if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsHost) { try { Rigidbody component2 = ((Component)item).GetComponent<Rigidbody>(); if ((Object)(object)component2 != (Object)null) { component2.position = val.TransformPoint(val2); component2.velocity = Vector3.zero; component2.angularVelocity = Vector3.zero; } Physics.SyncTransforms(); } catch (Exception ex2) { Log.Warning("Cruiser physics sync failed for '" + item.Name() + "': " + ex2.Message); } } CruiserShelfAnchor.Attach(item, val, ((Component)cruiser).transform); return true; } private static IEnumerator SortCruiser(VehicleController cruiser, List<(string itemKey, Vector3 cruiserLocalPos, int maxCount)> rules, bool dropMatchingHeld) { Sorter.inProgress = true; int placed = 0; bool shelfCapacityReached = false; try { Dictionary<string, int> zoneSlots = ReservedZoneSlots(cruiser, rules); GrabbableObject droppedHeld = null; int heldSlot = -1; if (dropMatchingHeld && rules.Count == 1 && (Object)(object)cruiser != (Object)null) { (string itemKey, Vector3 cruiserLocalPos, int maxCount) rule = rules[0]; PlayerControllerB player = Player.Local; GrabbableObject held = player?.currentlyHeldObjectServer; int num = CruiserCargoItems(cruiser).Count((GrabbableObject item2) => Eligible(item2) && item2.Name() == rule.itemKey); string text = ZoneAt(rule.cruiserLocalPos); int value; int num2 = ((text != null && zoneSlots.TryGetValue(text, out value)) ? value : 0); if (text != null && (Object)(object)held != (Object)null && held.Name() == rule.itemKey && num < rule.maxCount && num2 + num >= ZoneCapacity(text)) { shelfCapacityReached = true; } if ((Object)(object)player != (Object)null && (Object)(object)held != (Object)null && held.Name() == rule.itemKey && num < rule.maxCount && (text == null || num2 + num < ZoneCapacity(text))) { NetworkObject component = ((Component)cruiser).GetComponent<NetworkObject>(); if ((Object)(object)component != (Object)null && component.IsSpawned && (Object)(object)((NetworkBehaviour)held).NetworkObject != (Object)null && ((NetworkBehaviour)held).NetworkObject.IsSpawned) { heldSlot = num2 + num; bool flag = false; try { using (Sorter.BeginInteractionBypass()) { held.floorYRot = -1; Vector3 cruiserLocalPosition = Placement(rule.cruiserLocalPos, heldSlot); Transform parent = PlacementParent(cruiser); player.DiscardHeldObject(true, component, PlacementOffset(cruiser, parent, cruiserLocalPosition), true); } flag = true; } catch (Exception ex) { Log.Warning("Failed to drop '" + rule.itemKey + "' on cruiser: " + ex.Message); } if (flag) { yield return null; int frames = 0; while (frames++ < 30 && (Object)(object)player != (Object)null && (Object)(object)player.currentlyHeldObjectServer == (Object)(object)held) { yield return null; } if ((Object)(object)player != (Object)null && (Object)(object)player.currentlyHeldObjectServer != (Object)(object)held) { droppedHeld = held; int confirmFrames = 0; while ((Object)(object)held != (Object)null && (Object)(object)cruiser != (Object)null && (held.isHeld || (!((Component)held).transform.IsChildOf(PlacementParent(cruiser)) && !Eligible(held))) && confirmFrames++ < 30) { yield return null; } if ((Object)(object)held != (Object)null && (Object)(object)cruiser != (Object)null && !held.isHeld && ((Component)held).transform.IsChildOf(PlacementParent(cruiser))) { Transform val = PlacementParent(cruiser); Vector3 val2 = PlacementOffset(cruiser, val, Placement(rule.cruiserLocalPos, heldSlot)); ((Component)held).transform.localPosition = val2; held.targetFloorPosition = val2; held.startFallingPosition = val2; held.fallTime = 1.1f; held.reachedFloorTarget = true; held.hasHitGround = true; if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsHost) { try { Rigidbody component2 = ((Component)held).GetComponent<Rigidbody>(); if ((Object)(object)component2 != (Object)null) { component2.position = val.TransformPoint(val2); component2.velocity = Vector3.zero; component2.angularVelocity = Vector3.zero; } Physics.SyncTransforms(); } catch (Exception ex2) { Log.Warning("Cruiser physics sync failed for held '" + rule.itemKey + "': " + ex2.Message); } } CruiserShelfAnchor.Attach(held, val, ((Component)cruiser).transform); placed++; } else if ((Object)(object)held != (Object)null && (Object)(object)cruiser != (Object)null && Eligible(held) && PlaceOnCruiser(held, cruiser, Placement(rule.cruiserLocalPos, heldSlot))) { placed++; } else { Log.Warning("Could not confirm cruiser placement for held '" + rule.itemKey + "'."); } } else { Log.Warning("Held '" + rule.itemKey + "' was not released onto the cruiser."); } } } } } if (!Sorter.inProgress || (Object)(object)cruiser == (Object)null || (Object)(object)Player.Local == (Object)null) { yield break; } GameObject ship = GameObject.Find("Environment/HangarShip"); List<GrabbableObject> cruiserItems = (from val3 in CruiserCargoItems(cruiser) where (Object)(object)val3 != (Object)(object)droppedHeld && Eligible(val3) select val3).ToList(); bool includeOutsideItems = Ship.ShouldSortAllDetectedItems; List<GrabbableObject> sourceItems = (from val3 in Object.FindObjectsOfType<GrabbableObject>() where (Object)(object)val3 != (Object)(object)droppedHeld && Eligible(val3) && !IsCruiserCargo(val3) && (includeOutsideItems || IsShipCargo(val3, ship)) select val3).ToList(); foreach (var rule2 in rules) { if (!Sorter.inProgress || (Object)(object)cruiser == (Object)null || (Object)(object)Player.Local == (Object)null || (Keyboard.current != null && ((ButtonControl)Keyboard.current.escapeKey).wasPressedThisFrame)) { yield break; } int frames = (((Object)(object)droppedHeld != (Object)null && droppedHeld.Name() == rule2.itemKey) ? 1 : 0); string zone = ZoneAt(rule2.cruiserLocalPos); int value2; int confirmFrames = ((zone != null && zoneSlots.TryGetValue(zone, out value2)) ? value2 : 0); int num3 = rule2.maxCount - frames; if (zone != null) { int num4 = Math.Max(0, ZoneCapacity(zone) - confirmFrames - frames); if (num3 > num4) { num3 = num4; shelfCapacityReached = true; } } List<GrabbableObject> list = cruiserItems.Where((GrabbableObject item2) => item2.Name() == rule2.itemKey).Take(num3).ToList(); int count = num3 - list.Count; List<GrabbableObject> second = sourceItems.Where((GrabbableObject item2) => item2.Name() == rule2.itemKey).Take(count).ToList(); List<GrabbableObject> selected = list.Concat(second).ToList(); for (int index = 0; index < selected.Count; index++) { if (!Sorter.inProgress || (Object)(object)cruiser == (Object)null || (Object)(object)Player.Local == (Object)null || (Keyboard.current != null && ((ButtonControl)Keyboard.current.escapeKey).wasPressedThisFrame)) { yield break; } GrabbableObject item = selected[index]; int num5 = confirmFrames + index; if (frames > 0 && num5 >= heldSlot) { num5++; } if (Eligible(item) && PlaceOnCruiser(item, cruiser, Placement(rule2.cruiserLocalPos, num5))) { placed++; } yield return null; } if (zone != null) { zoneSlots[zone] = confirmFrames + selected.Count + frames; } } } finally { Sorter.inProgress = false; Chat.Print($"Cruiser sort finished: placed {placed} item(s)." + (shelfCapacityReached ? $" Shelf zones are limited to {20} items each (D2: 1)." : ""), (Color?)null); } } private static IEnumerator SortScrapPile(VehicleController cruiser, Vector3 targetShipLocalPosition, List<GrabbableObject> scrap) { //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) int moved = 0; int failed = 0; try { for (int index = 0; index < scrap.Count; index++) { if (!Sorter.inProgress) { break; } if ((Object)(object)cruiser == (Object)null) { break; } if ((Object)(object)Player.Local == (Object)null) { break; } if (Keyboard.current != null && ((ButtonControl)Keyboard.current.escapeKey).wasPressedThisFrame) { break; } GrabbableObject val = scrap[index]; if (Eligible(val) && val.itemProperties.isScrap && MoveUtils.MoveItemOnShipLocal(val, targetShipLocalPosition, val.floorYRot)) { moved++; } else { failed++; } yield return null; } } finally { Sorter.inProgress = false; Chat.Print($"Cruiser scrap gather finished: moved {moved} item(s) to the ship" + ((failed > 0) ? $", skipped {failed}." : "."), (Color?)null); } } } public sealed class CruiserSetCommand : QuickSortCommand { public override string Name => "css"; public override string Description => "Save a cruiser position, then immediately place that item type up to its maximum.\nUsage: /css test, /css [item] [max=10], /css <zone> [item] [max=10], /css zones, /css list, /css reset [item]"; protected override bool InvokeParsed(string[] args, out string? error) { //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_0266: 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_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) error = null; if (args.Length != 0 && string.Equals(args[0], "help", StringComparison.OrdinalIgnoreCase)) { Chat.Print(((BaseCommand)this).Description, (Color?)null); return true; } if (args.Length != 0 && string.Equals(args[0], "test", StringComparison.OrdinalIgnoreCase)) { if (args.Length != 1) { error = "Usage: /css test (gathers cruiser scrap to the ship's rejoin item area)."; return false; } return CruiserSorter.TryStartScrapPileAtShipRejoinLocation(out error); } if (args.Length != 0 && string.Equals(args[0], "list", StringComparison.OrdinalIgnoreCase)) { List<(string, Vector3, int)> list = CruiserPositions.ListAll(out error); if (error != null) { return false; } Chat.Print((list.Count == 0) ? "No cruiser positions saved." : string.Join(", ", list.Select<(string, Vector3, int), string>(delegate((string itemKey, Vector3 cruiserLocalPos, int maxCount) r) { //IL_0001: 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) //IL_0025: 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) string arg = CruiserSorter.ZoneAt(r.cruiserLocalPos) ?? $"({r.cruiserLocalPos.x:F1},{r.cruiserLocalPos.y:F1},{r.cruiserLocalPos.z:F1})"; return $"{r.itemKey}={r.maxCount}@{arg}"; })), (Color?)null); return true; } if (args.Length != 0 && string.Equals(args[0], "zones", StringComparison.OrdinalIgnoreCase)) { Chat.Print("Cruiser zones: A1-A3, B1-B3, C1-C3, D1-D3, E1-E3, F1-F3, G1-G3. Side shelves: 1=bottom, 2=middle, 3=top. Use /css A2 [item] [max].", (Color?)null); return true; } if (args.Length != 0 && string.Equals(args[0], "reset", StringComparison.OrdinalIgnoreCase)) { if (!CruiserSorter.TryResolveItemKey((args.Length > 1) ? string.Join(" ", args.Skip(1)) : null, out string key, out error)) { return false; } if (!CruiserPositions.Remove(key, out var removed, out error)) { return false; } Chat.Print(removed ? ("Removed cruiser position for " + key + ".") : ("No cruiser position for " + key + "."), (Color?)null); return true; } string zoneName = null; Vector3 position = default(Vector3); string[] array = args; string zoneName2; Vector3 position2; string zoneName3; Vector3 position3; if (args.Length != 0 && (string.Equals(args[0], "shelf", StringComparison.OrdinalIgnoreCase) || string.Equals(args[0], "zone", StringComparison.OrdinalIgnoreCase))) { if (args.Length < 2 || !CruiserSorter.TryGetZone(args[1], out zoneName, out position)) { error = "Usage: /css shelf <A1-G3 zone> [item name] [max=10]. Use /css zones to list zones."; return false; } array = args.Skip(2).ToArray(); } else if (args.Length != 0 && CruiserSorter.TryGetZone(args[0], out zoneName2, out position2)) { zoneName = zoneName2; position = position2; array = args.Skip(1).ToArray(); } else if (args.Length != 0 && !CruiserSorter.IsExactAvailableItem(string.Join(" ", args)) && CruiserSorter.TryGetZone(args[^1], out zoneName3, out position3)) { zoneName = zoneName3; position = position3; array = args.Take(args.Length - 1).ToArray(); } if (!CruiserSorter.TryGetPlayerPosition(out VehicleController cruiser, out Vector3 localPosition, out error) || (Object)(object)cruiser == (Object)null) { return false; } if (zoneName != null) { localPosition = position; } localPosition += Vector3.up * 0.3f; int num = 10; string[] array2 = array; if (array.Length != 0 && !CruiserSorter.IsExactAvailableItem(string.Join(" ", array)) && int.TryParse(array[^1], out var result)) { num = result; array2 = array.Take(array.Length - 1).ToArray(); } if (num <= 0 || num > 10000) { error = "Maximum must be between 1 and 10000."; return false; } if (!CruiserSorter.TryResolveItemKey((array2.Length != 0) ? string.Join(" ", array2) : null, out string key2, out error)) { return false; } if (!CruiserSorter.CheckCruiserReady(cruiser, out error)) { return false; } if (!CruiserPositions.Set(key2, localPosition, num, out error)) { return false; } if (!CruiserSorter.TryStartRule(cruiser, key2, localPosition, num, out error)) { Log.Warning("Cruiser position for '" + key2 + "' was saved, but placement could not start: " + error); return false; } Chat.Print($"Cruiser position saved: {key2}, max {num}" + ((zoneName == null) ? "." : (" at " + zoneName + ".")) + " Placing items now.", (Color?)null); return true; } } public sealed class CruiserSortCommand : QuickSortCommand { public override string Name => "csort"; public override string[] Commands => new string[2] { "csort", "cs" }; public override string Description => "Sort cruiser cargo up to each saved maximum. Usage: /csort or /cs."; protected override bool InvokeParsed(string[] args, out string? error) { return CruiserSorter.TryStart(out error); } } public static class Extensions { private static readonly Dictionary<string, string> NameAliases = BuildNameAliases(); private static string NormalizeKeyNoAlias(string s) { if (string.IsNullOrWhiteSpace(s)) { return ""; } return s.Trim().ToLowerInvariant().Replace(" ", "_") .Replace("-", "_"); } private static Dictionary<string, string> BuildNameAliases() { Dictionary<string, string> d = new Dictionary<string, string>(); (string, string[])[] array = new(string, string[])[19] { ("boombox", new string[1] { "붐박스" }), ("flashlight", new string[1] { "손전등" }), ("jetpack", new string[1] { "제트팩" }), ("key", new string[1] { "열쇠" }), ("lockpicker", new string[1] { "자물쇠 따개" }), ("apparatus", new string[2] { "장치", "apparatice" }), ("pro_flashlight", new string[2] { "프로 손전등", "pro-flashlight" }), ("shovel", new string[1] { "철제 삽" }), ("stun_grenade", new string[2] { "기절 수류탄", "stun grenade" }), ("extension_ladder", new string[2] { "연장형 사다리", "extension ladder" }), ("tzp_inhalant", new string[2] { "tzp-흡입제", "tzp-inhalant" }), ("walkie_talkie", new string[2] { "무전기", "walkie-talkie" }), ("zap_gun", new string[2] { "잽건", "zap gun" }), ("radar_booster", new string[3] { "레이더 부스터", "radar booster", "radar-booster" }), ("spray_paint", new string[3] { "페인트 스프레이", "스프레이 페인트", "spray paint" }), ("shotgun", new string[4] { "산탄총", "더블 배럴", "double barrel", "double_barrel" }), ("ammo", new string[4] { "탄약", "산탄총 탄약", "shotgun shell", "shotgun_shell" }), ("clipboard", new string[1] { "클립보드" }), ("sticky_note", new string[3] { "스티커 메모", "스티커메모", "sticky note" }) }; for (int i = 0; i < array.Length; i++) { (string, string[]) tuple = array[i]; AddAliases(tuple.Item1, tuple.Item2); } array = new(string, string[])[9] { ("coffee_mug", new string[4] { "mug", "머그잔", "coffee mug", "커피 머그잔" }), ("hair_brush", new string[3] { "brush", "hair brush", "빗" }), ("brass_bell", new string[4] { "bell", "brass bell", "황동 종", "종" }), ("bee_hive", new string[3] { "hive", "bee hive", "벌집" }), ("wedding_ring", new string[3] { "ring", "wedding ring", "반지" }), ("robot_toy", new string[4] { "toy robot", "robot toy", "장난감 로봇", "로봇 장난감" }), ("rubber_ducky", new string[2] { "rubber ducky", "고무 오리" }), ("tattered_metal_sheet", new string[4] { "metal sheet", "tattered metal sheet", "금속 판", "너덜너덜한 금속 판" }), ("homemade_flashbang", new string[2] { "homemade flashbang", "사제 섬광탄" }) }; for (int i = 0; i < array.Length; i++) { (string, string[]) tuple2 = array[i]; AddAliases(tuple2.Item1, tuple2.Item2); } array = new(string, string[])[31] { ("bubblegun", new string[1] { "비눗방울 총" }), ("broken_p88", new string[2] { "망가진 p88", "broken p88" }), ("employee", new string[1] { "직원" }), ("mine", new string[1] { "지뢰" }), ("toothles", new string[2] { "투슬리스", "toothles" }), ("crossbow", new string[2] { "석궁", "crossbow" }), ("physgun", new string[2] { "피직스건", "physgun" }), ("ammo_crate", new string[2] { "탄약 상자", "ammo crate" }), ("drink", new string[1] { "음료수" }), ("radio", new string[1] { "라디오" }), ("mouse", new string[1] { "마우스" }), ("monitor", new string[1] { "모니터" }), ("battery", new string[1] { "건전지" }), ("cannon", new string[1] { "대포" }), ("health_drink", new string[2] { "건강 음료", "health drink" }), ("chemical", new string[1] { "화학 약품" }), ("disinfecting_alcohol", new string[2] { "소독용 알코올", "disinfecting alcohol" }), ("ampoule", new string[1] { "앰풀" }), ("blood_pack", new string[2] { "혈액 팩", "blood pack" }), ("flip_lighter", new string[2] { "라이터", "flip lighter" }), ("rubber_ball", new string[2] { "고무 공", "rubber ball" }), ("video_tape", new string[2] { "비디오 테이프", "video tape" }), ("first_aid_kit", new string[2] { "구급 상자", "first aid kit" }), ("gold_medallion", new string[2] { "금메달", "gold medallion" }), ("steel_pipe", new string[2] { "금속 파이프", "steel pipe" }), ("axe", new string[1] { "도끼" }), ("emergency_hammer", new string[2] { "비상용 망치", "emergency hammer" }), ("katana", new string[1] { "카타나" }), ("silver_medallion", new string[2] { "은메달", "silver medallion" }), ("pocket_radio", new string[2] { "휴대용 라디오", "pocket radio" }), ("teddy_plush", new string[2] { "곰 인형", "teddy plush" }) }; for (int i = 0; i < array.Length; i++) { (string, string[]) tuple3 = array[i]; AddAliases(tuple3.Item1, tuple3.Item2); } Add("마법의 7번 공", "Magic 7 ball"); Add("에어혼", "Airhorn"); Add("황동 종", "Brass bell"); Add("큰 나사", "Big bolt"); Add("병 묶음", "Bottles"); Add("빗", "Hair brush"); Add("사탕", "Candy"); Add("금전 등록기", "Cash register"); Add("화학 용기", "Chemical jug"); Add("광대 나팔", "Clown horn"); Add("대형 축", "Large axle"); Add("틀니", "Teeth"); Add("쓰레받기", "Dust pan"); Add("달걀 거품기", "Egg beater"); Add("v형 엔진", "V-type engine"); Add("황금 컵", "Golden cup"); Add("멋진 램프", "Fancy lamp"); Add("그림", "Painting"); Add("플라스틱 물고기", "Plastic fish"); Add("레이저 포인터", "Laser pointer"); Add("금 주괴", "Gold Bar"); Add("헤어 드라이기", "Hairdryer"); Add("돋보기", "Magnifying glass"); Add("너덜너덜한 금속 판", "Tattered metal sheet"); Add("쿠키 틀", "Cookie mold pan"); Add("머그잔", "Coffee mug"); Add("커피 머그잔", "Coffee mug"); Add("향수 병", "Perfume bottle"); Add("구식 전화기", "Old phone"); Add("피클 병", "Jar of pickles"); Add("약 병", "Pill bottle"); Add("리모컨", "Remote"); Add("결혼 반지", "Wedding ring"); Add("로봇 장난감", "Robot Toy"); Add("고무 오리", "Rubber ducky"); Add("빨간색 소다", "Red soda"); Add("운전대", "Steering wheel"); Add("정지 표지판", "Stop sign"); Add("찻주전자", "Tea Kettle"); Add("치약", "Toothpaste"); Add("장난감 큐브", "Toy cube"); Add("벌집", "Bee hive"); Add("양보 표지판", "Yield sign"); Add("산탄총", "Shotgun"); Add("더블 배럴", "Double-barrel"); Add("산탄총 탄약", "ammo"); Add("탄약", "ammo"); Add("사제 섬광탄", "Homemade Flashbang"); Add("선물", "Gift"); Add("선물 상자", "Gift box"); Add("플라스크", "Flask"); Add("비극", "Tragedy"); Add("희극", "Comedy"); Add("방귀 쿠션", "Whoopie cushion"); Add("방퀴 쿠션", "Whoopie cushion"); Add("식칼", "Kitchen knife"); Add("부활절 달걀", "Easter egg"); Add("제초제", "Weed killer"); Add("벨트 배낭", "Belt bag"); Add("축구공", "Soccer ball"); Add("조작 패드", "Control pad"); Add("쓰레기통 뚜껑", "Garbage lid"); Add("플라스틱 컵", "Plastic cup"); Add("화장실 휴지", "Toilet paper"); Add("장난감 기차", "Toy train"); Add("제드 도그", "Zed Dog"); Add("시계", "Clock"); Add("시체", "Body"); Add("알", "Egg"); Add("열쇠", "Key"); Add("데이터 칩", "Data chip"); Add("교육용 지침서", "Training manual"); Add("장치", "Apparatus"); Add("장치", "Apparatice"); Add("알코올 플라스크", "Alcohol Flask"); Add("모루", "Anvil"); Add("야구 방망이", "Baseball bat"); Add("맥주 캔", "Beer can"); Add("벽돌", "Brick"); Add("망가진 엔진", "Broken engine"); Add("양동이", "Bucket"); Add("페인트 캔", "Can paint"); Add("수통", "Canteen"); Add("자동차 배터리", "Car battery"); Add("조임틀", "Clamp"); Add("멋진 그림", "Fancy Painting"); Add("선풍기", "Fan"); Add("소방 도끼", "Fireaxe"); Add("소화기", "Fire extinguisher"); Add("소화전", "Fire hydrant"); Add("통조림", "Food can"); Add("게임보이", "Gameboy"); Add("쓰레기", "Garbage"); Add("망치", "Hammer"); Add("기름통", "Jerrycan"); Add("키보드", "Keyboard"); Add("랜턴", "Lantern"); Add("도서관 램프", "Library lamp"); Add("식물", "Plant"); Add("플라이어", "Pliers"); Add("뚫어뻥", "Plunger"); Add("레트로 장난감", "Retro Toy"); Add("스크류 드라이버", "Screwdriver"); Add("싱크대", "Sink"); Add("소켓 렌치", "Socket Wrench"); Add("여행 가방", "Suitcase"); Add("토스터기", "Toaster"); Add("공구 상자", "Toolbox"); Add("실크햇", "Top hat"); Add("라바콘", "Traffic cone"); Add("환풍구", "Vent"); Add("물뿌리개", "Watering Can"); Add("바퀴", "Wheel"); Add("와인 병", "Wine bottle"); Add("렌치", "Wrench"); Add("자수정 군집", "Amethyst Cluster"); Add("주사기", "Syringe"); Add("주사기총", "Syringe Gun"); Add("코너 파이프", "Corner Pipe"); Add("작은 파이프", "Small Pipe"); Add("파이프", "Flow Pipe"); Add("뇌가 담긴 병", "Brain Jar"); Add("호두까기 인형 장난감", "Toy Nutcracker"); Add("시험관", "Test Tube"); Add("시험관 랙", "Test Tube Rack"); Add("호두까기 인형 눈", "Nutcracker Eye"); Add("파란색 시험관", "Blue Test Tube"); Add("노란색 시험관", "Yellow Test Tube"); Add("빨간색 시험관", "Red Test Tube"); Add("초록색 시험관", "Green Test Tube"); Add("쇠지렛대", "Crowbar"); Add("플젠", "Plzen"); Add("컵", "Cup"); Add("전자레인지", "Microwave"); Add("hyper acid 실험 기록", "Experiment Log Hyper Acid"); Add("희극 가면 실험 기록", "Experiment Log Comedy Mask"); Add("저주받은 동전 실험 기록", "Experiment Log Cursed Coin"); Add("바이오 hxnv7 실험 기록", "Experiment Log BIO HXNV7"); Add("파란색 폴더", "Blue Folder"); Add("빨간색 폴더", "Red Folder"); Add("코일", "Coil"); Add("타자기", "Typewriter"); Add("서류 더미", "Documents"); Add("스테이플러", "Stapler"); Add("구식 컴퓨터", "Old Computer"); Add("브론즈 트로피", "Bronze Trophy"); Add("바나나", "Banana"); Add("스턴봉", "Stun Baton"); Add("바이오-hxnv7", "BIO-HXNV7"); Add("복구된 비밀 일지", "Recovered Secret Log"); Add("황금 단검 실험 기록", "Experiment Log Golden Dagger"); Add("대합", "Clam"); Add("거북이 등딱지", "Turtle Shell"); Add("생선 뼈", "Fish Bones"); Add("뿔 달린 껍질", "Horned Shell"); Add("도자기 찻잔", "Porcelain Teacup"); Add("대리석", "Marble"); Add("도자기 병", "Porcelain Bottle"); Add("도자기 향수 병", "Porcelain Perfume Bottle"); Add("발광구", "Glowing Orb"); Add("황금 해골", "Golden Skull"); Add("코스모코스 지도", "Map of Cosmocos"); Add("젖은 노트 1", "Wet Note 1"); Add("젖은 노트 2", "Wet Note 2"); Add("젖은 노트 3", "Wet Note 3"); Add("젖은 노트 4", "Wet Note 4"); Add("우주빛 파편", "Cosmic Shard"); Add("우주 생장물", "Cosmic Growth"); Add("천상의 두뇌 덩어리", "Chunk of Celestial Brain"); Add("파편이 든 양동이", "Bucket of Shards"); Add("우주빛 손전등", "Cosmic Flashlight"); Add("잊혀진 일지 1", "Forgotten Log 1"); Add("잊혀진 일지 2", "Forgotten Log 2"); Add("잊혀진 일지 3", "Forgotten Log 3"); Add("안경", "Glasses"); Add("생장한 배양 접시", "Grown Petri Dish"); Add("배양 접시", "Petri Dish"); Add("코스모채드", "Cosmochad"); Add("죽어가는 우주빛 손전등", "Dying Cosmic Flashlight"); Add("죽어가는 우주 생장물", "Dying Cosmic Growth"); Add("혈액 배양 접시", "Blood Petri Dish"); Add("악마 코스모채드", "Evil Cosmochad"); Add("악마 코스모", "Evil Cosmo"); Add("릴 코스모", "Lil Cosmo"); Add("죽어가는 생장물 배양 접시", "Dying Grown Petri Dish"); Add("감시하는 배양 접시", "Watching Petri Dish"); Add("현미경", "Microscope"); Add("원통형 바일", "Round Vile"); Add("사각형 바일", "Square Vile"); Add("타원형 바일", "Oval Vile"); Add("해링턴 일지 1", "Harrington Log 1"); Add("해링턴 일지 2", "Harrington Log 2"); Add("해링턴 일지 3", "Harrington Log 3"); Add("해링턴 일지 4", "Harrington Log 4"); Add("생장물이 든 병", "Jar of Growth"); Add("테이프 플레이어 일지 1", "Tape Player Log 1"); Add("테이프 플레이어 일지 2", "Tape Player Log 2"); Add("테이프 플레이어 일지 3", "Tape Player Log 3"); Add("테이프 플레이어 일지 4", "Tape Player Log 4"); Add("쇼핑 카트", "Shopping Cart"); return d; void Add(string localized, string canonical) { string text = NormalizeKeyNoAlias(localized); string value = NormalizeKeyNoAlias(canonical); if (!string.IsNullOrWhiteSpace(text) && !string.IsNullOrWhiteSpace(value) && !d.ContainsKey(text)) { d.Add(text, value); } } void AddAliases(string canonicalKey, params string[] aliases) { Add(canonicalKey, canonicalKey); if (aliases != null) { for (int j = 0; j < aliases.Length; j++) { Add(aliases[j], canonicalKey); } } } } public static string NormalizeName(string s) { string text = NormalizeKeyNoAlias(s); if (!NameAliases.TryGetValue(text, out string value)) { return text; } return value; } public static string Name(this GrabbableObject item) { return NormalizeName(item.itemProperties.itemName); } public static string Name(this Item item) { return NormalizeName(item.itemName); } } [HarmonyPatch(typeof(PlayerControllerB), "BeginGrabObject")] internal static class GrabPatch { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator ilGenerator) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Expected O, but got Unknown //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Expected O, but got Unknown //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Expected O, but got Unknown //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Expected O, but got Unknown //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Expected O, but got Unknown //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(instructions); CodeMatcher val = new CodeMatcher((IEnumerable<CodeInstruction>)list, ilGenerator); CodeInstruction val2 = null; MethodInfo methodInfo = AccessTools.Method(typeof(NetworkBehaviour), "get_NetworkObject", (Type[])null, (Type[])null); for (int i = 0; i < list.Count - 1; i++) { CodeInstruction val3 = list[i]; if (val3.opcode == OpCodes.Callvirt && val3.operand is MethodInfo methodInfo2 && methodInfo2 == methodInfo) { CodeInstruction val4 = list[i + 1]; if (IsStloc(val4.opcode)) { val2 = val4.Clone(); break; } } } if (val2 == null) { val2 = new CodeInstruction(OpCodes.Stloc_0, (object)null); } Label label = default(Label); return val.MatchForward(true, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.Method(typeof(GrabbableObject), "InteractItem", (Type[])null, (Type[])null), (string)null) }).MatchBack(true, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null) }).Insert((CodeInstruction[])(object)new CodeInstruction[4] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(PlayerControllerB), "currentlyGrabbingObject")), new CodeInstruction(OpCodes.Callvirt, (object)methodInfo), val2 }) .ThrowIfInvalid("QuickSort: BeginGrabObject pattern not found (InteractItem)") .CreateLabel(ref label) .Start() .Insert((CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Player), "OverrideGrabbingObject", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Brtrue, (object)label) }) .InstructionEnumeration(); } private static bool IsStloc(OpCode op) { if (!(op == OpCodes.Stloc) && !(op == OpCodes.Stloc_S) && !(op == OpCodes.Stloc_0) && !(op == OpCodes.Stloc_1) && !(op == OpCodes.Stloc_2)) { return op == OpCodes.Stloc_3; } return true; } } internal static class InteractionLockPatch { [HarmonyPatch(typeof(PlayerControllerB), "BeginGrabObject")] [HarmonyPrefix] private static bool BlockBeginGrabObject() { if (!Sorter.IsInteractionLocked) { return true; } if (Sorter.IsInteractionBypassActive) { return true; } return false; } [HarmonyPatch(typeof(PlayerControllerB), "DiscardHeldObject")] [HarmonyPrefix] private static bool BlockDiscardHeldObject() { if (!Sorter.IsInteractionLocked) { return true; } if (Sorter.IsInteractionBypassActive) { return true; } return false; } } public class Log { private static ManualLogSource _log; public static void Init(ManualLogSource log) { _log = log; } public static void NotifyPlayer(string header, string body = "", bool isWarning = false) { if ((Object)(object)HUDManager.Instance != (Object)null) { HUDManager.Instance.DisplayTip(header, body, isWarning, false, "LC_Tip1"); } Debug(header); Debug(body); } public static void Chat(string body, string color = "FFFFFF") { if ((Object)(object)HUDManager.Instance != (Object)null) { HUDManager.Instance.AddChatMessage("<color=#" + color + ">[Pasta] " + body + "</color>", "", -1, false); } Debug(body); } public static void ConfirmSound() { if ((Object)(object)HUDManager.Instance != (Object)null && (Object)(object)GameNetworkManager.Instance != (Object)null) { HUDManager.Instance.UIAudio.PlayOneShot(GameNetworkManager.Instance.buttonTuneSFX); } } public static void Exception(Exception e) { string message = e.Message; string stackTrace = e.StackTrace; _log.LogError((object)message); _log.LogError((object)stackTrace); } public static void Error(params object[] objects) { _log.LogError((object)string.Join(" ", objects)); } public static void Warning(params object[] objects) { _log.LogWarning((object)string.Join(" ", objects)); } public static void Info(params object[] objects) { _log.LogInfo((object)string.Join(" ", objects)); } public static void Debug(params object[] objects) { _log.LogDebug((object)string.Join(" ", objects)); } } internal static class MoveUtils { private static bool ShouldAvoidHeldSideEffects(PlayerControllerB player, GrabbableObject targetItem) { if ((Object)(object)player == (Object)null) { return true; } if ((Object)(object)targetItem == (Object)null) { return true; } GrabbableObject currentlyHeldObjectServer = player.currentlyHeldObjectServer; if ((Object)(object)currentlyHeldObjectServer != (Object)null) { return (Object)(object)currentlyHeldObjectServer != (Object)(object)targetItem; } return false; } public static bool MoveItemOnShip(GrabbableObject item, Vector3 worldPos, int floorYRot = -1) { //IL_0044: 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) //IL_004a: 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_0072: 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_0063: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item == (Object)null) { return false; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null) { return false; } GameObject val2 = GameObject.Find("Environment/HangarShip"); if ((Object)(object)val2 == (Object)null) { return false; } Vector3 val3 = val2.transform.InverseTransformPoint(worldPos); ((Component)item).transform.position = worldPos; if (!ShouldAvoidHeldSideEffects(val, item)) { val.SetObjectAsNoLongerHeld(true, true, val3, item, floorYRot); } val.ThrowObjectServerRpc(NetworkObjectReference.op_Implicit(((NetworkBehaviour)item).NetworkObject), true, true, val3, floorYRot); return true; } public static bool MoveItemOnShipLocal(GrabbableObject item, Vector3 shipLocalPos, int floorYRot = -1) { //IL_00a7: 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_0076: 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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 ((Object)(object)item == (Object)null) { return false; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null) { return false; } GameObject val2 = GameObject.Find("Environment/HangarShip"); if ((Object)(object)val2 == (Object)null) { return false; } ((Component)item).transform.position = val2.transform.TransformPoint(shipLocalPos); try { if (!ShouldAvoidHeldSideEffects(val, item)) { val.SetObjectAsNoLongerHeld(true, true, shipLocalPos, item, floorYRot); } } catch { } try { val.PlaceGrabbableObject(val2.transform, shipLocalPos, false, item); CruiserShelfAnchor.Detach(item); val.PlaceObjectServerRpc(NetworkObjectReference.op_Implicit(((NetworkBehaviour)item).NetworkObject), NetworkObjectReference.op_Implicit(val2), shipLocalPos, false); } catch { try { val.ThrowObjectServerRpc(NetworkObjectReference.op_Implicit(((NetworkBehaviour)item).NetworkObject), true, true, shipLocalPos, floorYRot); } catch { return false; } } return true; } public static bool TryTeleportToWorld(GameObject go, Vector3 worldPos, Quaternion worldRot) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) GrabbableObject val = (((Object)(object)go != (Object)null) ? go.GetComponent<GrabbableObject>() : null); if ((Object)(object)val != (Object)null) { return MoveItemOnShip(val, worldPos, val.floorYRot); } if ((Object)(object)go == (Object)null) { return false; } go.transform.SetPositionAndRotation(worldPos, worldRot); return true; } } public static class Player { public static GrabbableObject overrideObject; public static PlayerControllerB Local => StartOfRound.Instance?.localPlayerController; public static bool CanGrabObject(GrabbableObject item) { if ((Object)(object)item == (Object)null || !item.grabbable || item.deactivated || item.isHeld || item.isPocketed) { return false; } if ((Object)(object)Local == (Object)null || Local.isPlayerDead || Local.isTypingChat || Local.inTerminalMenu || Local.throwingObject || Local.IsInspectingItem || Local.isGrabbingObjectAnimation || (Object)(object)Local.inAnimationWithEnemy != (Object)null || Local.inSpecialInteractAnimation || Local.jetpackControls || Local.disablingJetpackControls || Local.activatingItem || Local.waitingToDropItem || Local.FirstEmptyItemSlot((GrabbableObject)null) == -1) { return false; } return true; } public static bool OverrideGrabbingObject() { if ((Object)(object)overrideObject == (Object)null) { return false; } Local.currentlyGrabbingObject = overrideObject; overrideObject = null; return true; } public static IEnumerator StartGrabbingObject(GrabbableObject grabbableObject) { if (CanGrabObject(grabbableObject)) { overrideObject = grabbableObject; Local.BeginGrabObject(); yield return Local.grabObjectCoroutine; } } public static IEnumerator StartMovingObject(GrabbableObject item, Vector3 position, NetworkObject? parent = null) { //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) yield return StartGrabbingObject(item); if ((Object)(object)Local == (Object)null) { yield break; } int frames = 0; while (frames < 30 && ((Object)(object)Local.currentlyHeldObjectServer == (Object)null || (Object)(object)Local.currentlyHeldObjectServer != (Object)(object)item)) { frames++; yield return null; } if ((Object)(object)Local.currentlyHeldObjectServer == (Object)null || (Object)(object)Local.currentlyHeldObjectServer != (Object)(object)item) { Log.Warning("Failed to grab " + (item?.itemProperties?.itemName ?? "item") + "; skipping move to avoid crash."); yield break; } try { item.floorYRot = -1; Local.DiscardHeldObject(true, parent, position, false); } catch (Exception e) { Log.Exception(e); } } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("pasta.quicksort", "QuickSort", "0.1.26")] public class Plugin : BaseUnityPlugin { private const string CurrentConfigSchemaVersion = "0.1.10"; public static ManualLogSource Log; public static ConfigFile config; public static ConfigEntry<string> configVersion; public static ConfigEntry<bool> SyncHostProfile; private static Harmony harmony; public static GameObject sorterObject; private static bool applicationIsQuitting; public static Plugin Instance { get; private set; } private void Awake() { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Expected O, but got Unknown //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Expected O, but got Unknown applicationIsQuitting = false; Instance = this; Log = ((BaseUnityPlugin)this).Logger; config = ((BaseUnityPlugin)this).Config; SyncHostProfile = config.Bind<bool>("Profiles", "Sync Host Profile", true, "Automatically select a temporary copy of the host's QuickSort profile while in their lobby. When disabled, /pu host still selects it manually."); SyncHostProfile.SettingChanged -= OnSyncHostProfileSettingChanged; SyncHostProfile.SettingChanged += OnSyncHostProfileSettingChanged; bool num = File.Exists(config.ConfigFilePath); ConfigEntry<string> val = default(ConfigEntry<string>); bool flag = config.TryGetEntry<string>(new ConfigDefinition("General", "configVersion"), ref val); configVersion = config.Bind<string>("General", "configVersion", "0.1.10", "Config schema version (used for internal migrations)."); bool flag2 = false; string text = configVersion.Value ?? ""; if (string.IsNullOrWhiteSpace(text)) { text = "0.0.0"; configVersion.Value = text; flag2 = true; } int num2; if (num) { if (flag) { num2 = (IsVersionLessThan(text, "0.1.10") ? 1 : 0); if (num2 == 0) { goto IL_017a; } } else { num2 = 1; } if (!flag || IsVersionLessThan(text, "0.1.5")) { ConfigEntry<float> val2 = config.Bind<float>("Sorter", "sortOriginY", 0.1f, "Y coordinate of the origin position for sorting items (relative to ship)"); if (Mathf.Abs(val2.Value - 0.5f) < 0.0001f) { val2.Value = 0.1f; flag2 = true; } } } else { num2 = 0; } goto IL_017a; IL_017a: if (num2 != 0 && !string.Equals(configVersion.Value, "0.1.10", StringComparison.Ordinal)) { configVersion.Value = "0.1.10"; flag2 = true; } if (flag2) { config.Save(); } QuickSort.Log.Init(((BaseUnityPlugin)this).Logger); QuickSort.Log.Info("QuickSort - Item Sorter loading..."); SortShortcuts.EnsureFileExists(); SortPositions.EnsureFileExists(); CruiserPositions.EnsureFileExists(); SortProfiles.EnsureFileExists(); harmony = new Harmony("pasta.quicksort"); harmony.PatchAll(typeof(Ship)); harmony.PatchAll(typeof(Startup)); harmony.PatchAll(typeof(GrabPatch)); harmony.PatchAll(typeof(InteractionLockPatch)); harmony.PatchAll(typeof(CruiserShelfAnchorPatch)); try { Startup.RegisterCommandsOnce(); QuickSort.Log.Info("Sort command registered in Awake"); } catch (Exception ex) { QuickSort.Log.Error("Failed to register sort command in Awake: " + ex.Message); QuickSort.Log.Error("Stack trace: " + ex.StackTrace); } try { if ((Object)(object)sorterObject == (Object)null) { sorterObject = new GameObject("PastaSorter"); sorterObject.AddComponent<Sorter>(); sorterObject.AddComponent<ProfileNetworkBehaviour>(); Object.DontDestroyOnLoad((Object)(object)sorterObject); QuickSort.Log.Info("Sorter initialized in Awake"); } else if ((Object)(object)sorterObject.GetComponent<ProfileNetworkBehaviour>() == (Object)null) { sorterObject.AddComponent<ProfileNetworkBehaviour>(); } SortProfiles.RecoverInterruptedHostSession(); SortProfiles.EnsureDefaultProfile(); } catch (Exception ex2) { QuickSort.Log.Error("Failed to initialize Sorter in Awake: " + ex2.Message); QuickSort.Log.Error("Stack trace: " + ex2.StackTrace); } QuickSort.Log.Info("QuickSort - Item Sorter loaded!"); } private void OnDestroy() { if (Instance == this) { Instance = null; } if (!applicationIsQuitting) { QuickSort.Log.Warning("Plugin OnDestroy fired before application quit; skipping cleanup to avoid self-unpatching."); return; } if (harmony != null) { harmony.UnpatchSelf(); } if ((Object)(object)sorterObject != (Object)null) { Object.Destroy((Object)(object)sorterObject); } } private void OnApplicationQuit() { applicationIsQuitting = true; ProfileNetwork.EndSession(); } private static void OnSyncHostProfileSettingChanged(object sender, EventArgs args) { SortProfiles.OnSyncHostProfileChanged(); } private static bool IsVersionLessThan(string a, string b) { int[] array = Parse(a); int[] array2 = Parse(b); for (int i = 0; i < 3; i++) { if (array[i] < array2[i]) { return true; } if (array[i] > array2[i]) { return false; } } return false; static int[] Parse(string s) { if (string.IsNullOrWhiteSpace(s)) { return new int[3]; } string[] array3 = s.Trim().Split('.'); int[] array4 = new int[3]; for (int j = 0; j < 3; j++) { if (j < array3.Length && int.TryParse(array3[j], out var result)) { array4[j] = result; } else { array4[j] = 0; } } return array4; } } } public static class Startup { private static bool commandRegistered; public static void RegisterCommandsOnce() { if (!commandRegistered) { new SortCommand(); new SortBindCommand(); new SortSetCommand(); new SortResetCommand(); new SortPositionsCommand(); new SortBindingsListCommand(); new SortSkipCommand(); new PileCommand(); new CruiserSetCommand(); new CruiserSortCommand(); new ProfileCommand(); new ProfileSaveShortcutCommand(); new ProfileUseShortcutCommand(); new ProfileListShortcutCommand(); new ProfileDeleteShortcutCommand(); commandRegistered = true; } } [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void OnLocalPlayerCreated(PlayerControllerB __instance) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown if ((Object)(object)__instance != (Object)(object)StartOfRound.Instance.localPlayerController) { return; } if (!commandRegistered) { try { RegisterCommandsOnce(); Log.Info("Sort command registered"); } catch (Exception ex) { Log.Error("Failed to register sort command: " + ex.Message); } } if ((Object)(object)Plugin.sorterObject == (Object)null) { Plugin.sorterObject = new GameObject("PastaSorter"); Plugin.sorterObject.AddComponent<Sorter>(); Object.DontDestroyOnLoad((Object)(object)Plugin.sorterObject); } else if ((Object)(object)Plugin.sorterObject.GetComponent<Sorter>() == (Object)null) { Plugin.sorterObject.AddComponent<Sorter>(); } if ((Object)(object)Plugin.sorterObject.GetComponent<ProfileNetworkBehaviour>() == (Object)null) { Plugin.sorterObject.AddComponent<ProfileNetworkBehaviour>(); } SortProfiles.EnsureDefaultProfile(); ProfileNetwork.OnLocalPlayerCreated(); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPrefix] private static void OnLobbyDisconnect() { ProfileNetwork.EndSession(); } } internal static class ProfileNetwork { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnRequest; public static HandleNamedMessageDelegate <1>__OnSnapshot; public static Action<ulong> <2>__OnClientDisconnect; } private const string RequestMessage = "pasta.quicksort.profile.v1.request"; private const string SnapshotMessage = "pasta.quicksort.profile.v1.snapshot"; private const float RetrySeconds = 3f; private const float HostScanSeconds = 2f; private const int MaxSerialize