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.14
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.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 GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; 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.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: IgnoresAccessChecksTo("0Harmony")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("baer1.ChatCommandAPI")] [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("Debug")] [assembly: AssemblyDescription("made by Asta")] [assembly: AssemblyFileVersion("1.2.1.0")] [assembly: AssemblyInformationalVersion("1.2.1+644f591bb1e79799e329bdb84240036f1945b788")] [assembly: AssemblyProduct("QuickSort")] [assembly: AssemblyTitle("QuickSort")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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") { string text2 = "Commands: "; text2 += string.Join(", ", ChatCommand.Commands); Log.Chat(text2); 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; Argument[] array2 = array; foreach (Argument argument in array2) { if (argument.name == name) { return ((Argument<T>)argument).value; } } return default(T); } public T Get<T>(int name) { Argument[] array = arguments; Argument[] array2 = array; foreach (Argument argument in array2) { 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])); } } ChatArgs result = default(ChatArgs); result.arguments = list.ToArray(); result.help = help; return result; } public override string ToString() { return keyword; } } 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.ToLower().Replace(" ", "_").Replace("-", "_") .Trim(); } 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[1] { "산탄총" }), ("ammo", new string[1] { "탄약" }), ("clipboard", new string[1] { "클립보드" }), ("sticky_note", new string[3] { "스티커 메모", "스티커메모", "sticky note" }) }; (string, string[])[] array2 = array; for (int i = 0; i < array2.Length; i++) { (string, string[]) tuple = array2[i]; AddAliases(tuple.Item1, tuple.Item2); } (string, string[])[] array3 = 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", "사제 섬광탄" }) }; (string, string[])[] array4 = array3; for (int j = 0; j < array4.Length; j++) { (string, string[]) tuple2 = array4[j]; AddAliases(tuple2.Item1, tuple2.Item2); } (string, string[])[] array5 = 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" }) }; (string, string[])[] array6 = array5; for (int k = 0; k < array6.Length; k++) { (string, string[]) tuple3 = array6[k]; 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) { foreach (string localized2 in aliases) { Add(localized2, canonicalKey); } } } } public static string NormalizeName(string s) { string text = NormalizeKeyNoAlias(s); string value; return NameAliases.TryGetValue(text, out value) ? value : text; } 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_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Expected O, but got Unknown //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Expected O, but got Unknown //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Expected O, but got Unknown //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Expected O, but got Unknown //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Expected O, but got Unknown //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: 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) { return op == OpCodes.Stloc || op == OpCodes.Stloc_S || op == OpCodes.Stloc_0 || op == OpCodes.Stloc_1 || op == OpCodes.Stloc_2 || op == OpCodes.Stloc_3; } } 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; return (Object)(object)currentlyHeldObjectServer != (Object)null && (Object)(object)currentlyHeldObjectServer != (Object)(object)targetItem; } public static bool MoveItemOnShip(GrabbableObject item, Vector3 worldPos, int floorYRot = -1) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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) 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_00e6: 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_00b6: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_009d: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) if ((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); } val.ThrowObjectServerRpc(NetworkObjectReference.op_Implicit(((NetworkBehaviour)item).NetworkObject), true, true, shipLocalPos, floorYRot); } catch { } try { val.PlaceGrabbableObject(val2.transform, shipLocalPos, false, 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_0020: 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_0045: 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 { [CompilerGenerated] private sealed class <StartGrabbingObject>d__5 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public GrabbableObject grabbableObject; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <StartGrabbingObject>d__5(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (CanGrabObject(grabbableObject)) { overrideObject = grabbableObject; Local.BeginGrabObject(); <>2__current = Local.grabObjectCoroutine; <>1__state = 1; return true; } break; case 1: <>1__state = -1; break; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <StartMovingObject>d__6 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public GrabbableObject item; public Vector3 position; public NetworkObject parent; private int <frames>5__1; private Exception <e>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <StartMovingObject>d__6(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <e>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_015d: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = StartGrabbingObject(item); <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)Local == (Object)null) { return false; } <frames>5__1 = 0; break; case 2: <>1__state = -1; break; } if (<frames>5__1 < 30 && ((Object)(object)Local.currentlyHeldObjectServer == (Object)null || (Object)(object)Local.currentlyHeldObjectServer != (Object)(object)item)) { <frames>5__1++; <>2__current = null; <>1__state = 2; return true; } 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."); return false; } try { item.floorYRot = -1; Local.DiscardHeldObject(true, parent, position, false); } catch (Exception ex) { <e>5__2 = ex; Log.Exception(<e>5__2); } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } 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; } [IteratorStateMachine(typeof(<StartGrabbingObject>d__5))] public static IEnumerator StartGrabbingObject(GrabbableObject grabbableObject) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <StartGrabbingObject>d__5(0) { grabbableObject = grabbableObject }; } [IteratorStateMachine(typeof(<StartMovingObject>d__6))] 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 decompiler failed: Unexpected instruction in Iterator.Dispose() return new <StartMovingObject>d__6(0) { item = item, position = position, parent = parent }; } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("pasta.quicksort", "QuickSort", "0.1.8")] public class Plugin : BaseUnityPlugin { private const string CurrentConfigSchemaVersion = "0.1.8"; public static ManualLogSource Log; public static ConfigFile config; public static ConfigEntry<string> configVersion; private static Harmony harmony; public static GameObject sorterObject; private static bool applicationIsQuitting; public static Plugin Instance { get; private set; } private void Awake() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_0388: Unknown result type (might be due to invalid IL or missing references) //IL_0392: Expected O, but got Unknown //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Expected O, but got Unknown //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Expected O, but got Unknown applicationIsQuitting = false; Instance = this; Log = ((BaseUnityPlugin)this).Logger; config = ((BaseUnityPlugin)this).Config; bool flag = File.Exists(config.ConfigFilePath); ConfigEntry<string> val = default(ConfigEntry<string>); bool flag2 = config.TryGetEntry<string>(new ConfigDefinition("General", "configVersion"), ref val); configVersion = config.Bind<string>("General", "configVersion", "0.1.8", "Config schema version (used for internal migrations)."); bool flag3 = false; string text = configVersion.Value ?? ""; if (string.IsNullOrWhiteSpace(text)) { text = "0.0.0"; configVersion.Value = text; flag3 = true; } bool flag4 = flag && (!flag2 || IsVersionLessThan(text, "0.1.8")); if (flag4 && (!flag2 || 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; flag3 = true; } ConfigEntry<string> val3 = config.Bind<string>("Sorter", "skippedItems", "body, clipboard, sticky_note, boombox, shovel, jetpack, flashlight, pro_flashlight, key, stun_grenade, lockpicker, mapper, extension_ladder, tzp_inhalant, walkie_talkie, zap_gun, kitchen_knife, weed_killer, radar_booster, spray_paint, belt_bag, shotgun, ammo", "Global skip list (comma-separated, substring match). Applies to all grabbable items."); string text2 = AddTokensToCommaList(val3.Value, "shotgun", "ammo"); if (!string.Equals(text2, val3.Value, StringComparison.Ordinal)) { val3.Value = text2; flag3 = true; } } ConfigEntry<string> val4 = default(ConfigEntry<string>); if (flag4 && (!flag2 || IsVersionLessThan(text, "0.1.7")) && config.TryGetEntry<string>(new ConfigDefinition("Sorter", "skippedItems"), ref val4) && IsOnlyShotgunAmmo(val4.Value)) { val4.Value = "body, clipboard, sticky_note, boombox, shovel, jetpack, flashlight, pro_flashlight, key, stun_grenade, lockpicker, mapper, extension_ladder, tzp_inhalant, walkie_talkie, zap_gun, kitchen_knife, weed_killer, radar_booster, spray_paint, belt_bag, shotgun, ammo"; flag3 = true; } if (flag4 && !string.Equals(configVersion.Value, "0.1.8", StringComparison.Ordinal)) { configVersion.Value = "0.1.8"; flag3 = true; } if (flag3) { config.Save(); } QuickSort.Log.Init(((BaseUnityPlugin)this).Logger); QuickSort.Log.Info("QuickSort - Item Sorter loading..."); SortShortcuts.EnsureFileExists(); SortPositions.EnsureFileExists(); harmony = new Harmony("pasta.quicksort"); harmony.PatchAll(typeof(Ship)); harmony.PatchAll(typeof(Startup)); harmony.PatchAll(typeof(GrabPatch)); harmony.PatchAll(typeof(InteractionLockPatch)); try { new SortCommand(); new SortBindCommand(); new SortSetCommand(); new SortResetCommand(); new SortPositionsCommand(); new SortBindingsListCommand(); new SortSkipCommand(); new PileCommand(); 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>(); Object.DontDestroyOnLoad((Object)(object)sorterObject); QuickSort.Log.Info("Sorter initialized in Awake"); } } 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; } 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; } } private static string AddTokensToCommaList(string? list, params string[] tokensToAdd) { List<string> tokens = new List<string>(); HashSet<string> seen = new HashSet<string>(); if (!string.IsNullOrWhiteSpace(list)) { string[] array = list.Split(','); foreach (string raw2 in array) { Add(raw2); } } if (tokensToAdd != null) { foreach (string raw3 in tokensToAdd) { Add(raw3); } } return string.Join(", ", tokens); void Add(string raw) { string text = (raw ?? "").Trim(); if (!string.IsNullOrWhiteSpace(text)) { text = Extensions.NormalizeName(text).Trim('_'); if (!string.IsNullOrWhiteSpace(text) && seen.Add(text)) { tokens.Add(text); } } } } private static bool IsOnlyShotgunAmmo(string? list) { HashSet<string> seen = new HashSet<string>(); if (!string.IsNullOrWhiteSpace(list)) { string[] array = list.Split(','); foreach (string raw2 in array) { Add(raw2); } } return seen.Count == 2 && seen.Contains("shotgun") && seen.Contains("ammo"); void Add(string raw) { string text = (raw ?? "").Trim(); if (!string.IsNullOrWhiteSpace(text)) { text = Extensions.NormalizeName(text).Trim('_'); if (!string.IsNullOrWhiteSpace(text)) { seen.Add(text); } } } } } public static class Startup { private static bool commandRegistered; [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void OnLocalPlayerCreated(PlayerControllerB __instance) { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown if ((Object)(object)__instance != (Object)(object)StartOfRound.Instance.localPlayerController) { return; } if (!commandRegistered) { try { new SortCommand(); new SortBindCommand(); new SortSetCommand(); new SortResetCommand(); new SortPositionsCommand(); new SortBindingsListCommand(); new SortSkipCommand(); new PileCommand(); commandRegistered = true; Log.Info("Sort command registered"); } catch (Exception ex) { Log.Error("Failed to register sort command: " + ex.Message); } } if ((Object)(object)Plugin.sorterObject != (Object)null) { Object.Destroy((Object)(object)Plugin.sorterObject); } Plugin.sorterObject = new GameObject("PastaSorter"); Plugin.sorterObject.AddComponent<Sorter>(); Object.DontDestroyOnLoad((Object)(object)Plugin.sorterObject); } } public static class Ship { public static Action OnShipOrbit; public static Action OnShipTouchdown; public static Action OnShipAscent; public static Action OnShipDescent; private static readonly Dictionary<string, FieldInfo?> _startOfRoundBoolFields = new Dictionary<string, FieldInfo>(); private static readonly Dictionary<string, PropertyInfo?> _startOfRoundBoolProps = new Dictionary<string, PropertyInfo>(); private static readonly Dictionary<string, MemberInfo?> _startOfRoundBoolFuzzy = new Dictionary<string, MemberInfo>(); public static bool Stationary { get { if (GetStartOfRoundBool("shipHasLanded", "ShipHasLanded", "hasLanded", "HasLanded").GetValueOrDefault()) { return true; } if (GetStartOfRoundBool("inShipPhase", "InShipPhase", "shipPhase", "ShipPhase").GetValueOrDefault() && !GetStartOfRoundBool("shipIsLeaving", "ShipIsLeaving", "isShipLeaving", "IsShipLeaving", "shipLeaving").GetValueOrDefault()) { return true; } return false; } } public static bool CanSortNow { get { if (GetStartOfRoundBool("shipHasLanded", "ShipHasLanded", "hasLanded", "HasLanded").GetValueOrDefault()) { return true; } if (GetStartOfRoundBool("inShipPhase", "InShipPhase", "shipPhase", "ShipPhase").GetValueOrDefault()) { return true; } return InOrbit || Stationary; } } public static bool InOrbit => GetStartOfRoundBool("inShipPhase", "InShipPhase", "shipPhase", "ShipPhase").GetValueOrDefault() && !GetStartOfRoundBool("shipHasLanded", "ShipHasLanded", "hasLanded", "HasLanded").GetValueOrDefault(); private static bool? GetStartOfRoundBoolExact(string name) { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null) { return null; } Type type = ((object)instance).GetType(); if (!_startOfRoundBoolFields.TryGetValue(name, out FieldInfo value)) { value = AccessTools.Field(type, name); _startOfRoundBoolFields[name] = value; } if (value != null) { try { object value2 = value.GetValue(instance); if (value2 is bool) { bool value3 = (bool)value2; if (true) { return value3; } } } catch { } } if (!_startOfRoundBoolProps.TryGetValue(name, out PropertyInfo value4)) { value4 = AccessTools.Property(type, name); _startOfRoundBoolProps[name] = value4; } if (value4 != null && value4.PropertyType == typeof(bool) && value4.GetIndexParameters().Length == 0) { try { object value2 = value4.GetValue(instance, null); if (value2 is bool) { bool value5 = (bool)value2; if (true) { return value5; } } } catch { } } return null; } private static bool? GetStartOfRoundBoolFuzzy(string containsOrAltName) { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null) { return null; } Type type = ((object)instance).GetType(); if (!_startOfRoundBoolFuzzy.TryGetValue(containsOrAltName, out MemberInfo value)) { string needle = containsOrAltName; FieldInfo fieldInfo = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((FieldInfo f) => f.FieldType == typeof(bool) && string.Equals(f.Name, needle, StringComparison.OrdinalIgnoreCase)); if (fieldInfo != null) { value = fieldInfo; } else { PropertyInfo propertyInfo = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((PropertyInfo p) => p.PropertyType == typeof(bool) && p.GetIndexParameters().Length == 0 && string.Equals(p.Name, needle, StringComparison.OrdinalIgnoreCase)); value = propertyInfo; } if (value == null) { FieldInfo fieldInfo2 = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((FieldInfo f) => f.FieldType == typeof(bool) && f.Name.IndexOf(needle, StringComparison.OrdinalIgnoreCase) >= 0); if (fieldInfo2 != null) { value = fieldInfo2; } else { PropertyInfo propertyInfo2 = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((PropertyInfo p) => p.PropertyType == typeof(bool) && p.GetIndexParameters().Length == 0 && p.Name.IndexOf(needle, StringComparison.OrdinalIgnoreCase) >= 0); value = propertyInfo2; } } _startOfRoundBoolFuzzy[containsOrAltName] = value; } try { if (value is FieldInfo fieldInfo3 && fieldInfo3.FieldType == typeof(bool)) { return (bool)fieldInfo3.GetValue(instance); } if (value is PropertyInfo propertyInfo3 && propertyInfo3.PropertyType == typeof(bool) && propertyInfo3.GetIndexParameters().Length == 0) { return (bool)propertyInfo3.GetValue(instance, null); } } catch { } return null; } private static bool? GetStartOfRoundBool(params string[] candidates) { foreach (string text in candidates) { if (!string.IsNullOrWhiteSpace(text)) { bool? startOfRoundBoolExact = GetStartOfRoundBoolExact(text); if (startOfRoundBoolExact.HasValue) { return startOfRoundBoolExact; } } } foreach (string text2 in candidates) { if (!string.IsNullOrWhiteSpace(text2)) { bool? startOfRoundBoolFuzzy = GetStartOfRoundBoolFuzzy(text2); if (startOfRoundBoolFuzzy.HasValue) { return startOfRoundBoolFuzzy; } } } return null; } [HarmonyPatch(typeof(StartOfRound), "ShipLeave")] [HarmonyPostfix] [HarmonyWrapSafe] public static void OnShipLeave() { OnShipAscent?.Invoke(); OnShipDescent?.Invoke(); } [HarmonyPatch(typeof(StartOfRound), "OnShipLandedMiscEvents")] [HarmonyPostfix] [HarmonyWrapSafe] public static void OnShipLanded() { OnShipTouchdown?.Invoke(); OnShipOrbit?.Invoke(); } } public class Sorter : MonoBehaviour { private sealed class DisposeAction : IDisposable { private readonly Action _onDispose; private bool _disposed; public DisposeAction(Action onDispose) { _onDispose = onDispose; } public void Dispose() { if (!_disposed) { _disposed = true; _onDispose?.Invoke(); } } } [CompilerGenerated] private sealed class <DropHeldItemIfAny>d__37 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public GameObject ship; public Sorter <>4__this; private PlayerControllerB <player>5__1; private GrabbableObject <held>5__2; private NetworkObject <shipNetObj>5__3; private Vector3 <dropLocal>5__4; private float <groundYLocal>5__5; private int <frames>5__6; private float <vOff>5__7; private IDisposable <>s__8; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DropHeldItemIfAny>d__37(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <player>5__1 = null; <held>5__2 = null; <shipNetObj>5__3 = null; <>s__8 = null; <>1__state = -2; } private bool MoveNext() { //IL_016e: 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_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: { <>1__state = -1; <player>5__1 = Player.Local; if ((Object)(object)<player>5__1 == (Object)null) { return false; } <held>5__2 = <player>5__1.currentlyHeldObjectServer; if ((Object)(object)<held>5__2 == (Object)null) { return false; } <shipNetObj>5__3 = (((Object)(object)ship != (Object)null) ? ship.GetComponent<NetworkObject>() : null); <dropLocal>5__4 = ship.transform.InverseTransformPoint(((Component)<player>5__1).transform.position + ((Component)<player>5__1).transform.forward * 0.75f); if (<>4__this.TryGetGroundYLocalAt(<dropLocal>5__4, out <groundYLocal>5__5, out string _)) { <vOff>5__7 = 0f; try { if ((Object)(object)<held>5__2.itemProperties != (Object)null) { <vOff>5__7 = <held>5__2.itemProperties.verticalOffset - 0.05f; } } catch { } <dropLocal>5__4.y = <groundYLocal>5__5 + <vOff>5__7; } <>s__8 = BeginInteractionBypass(); try { <held>5__2.floorYRot = -1; <player>5__1.DiscardHeldObject(true, <shipNetObj>5__3, <dropLocal>5__4, false); } finally { if (<>s__8 != null) { <>s__8.Dispose(); } } <>s__8 = null; <frames>5__6 = 0; break; } case 1: <>1__state = -1; break; } if (<frames>5__6 < 30 && (Object)(object)<player>5__1.currentlyHeldObjectServer != (Object)null) { <frames>5__6++; <>2__current = null; <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <GrabbableRetry>d__51 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public GrabbableObject item; public Sorter <>4__this; private int <retry>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <GrabbableRetry>d__51(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <retry>5__1 = 15; break; case 1: <>1__state = -1; <retry>5__1--; break; } if (!Player.CanGrabObject(item) && <retry>5__1 > 0) { <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <MoveItemsOfTypeToPosition>d__48 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string itemKey; public Vector3 targetCenterShipLocal; public bool force; public bool announce; public bool ignoreSkipLists; public bool applyTwoHandedSortYOffset; public bool dropHeldFirst; public Sorter <>4__this; private GameObject <ship>5__1; private Dictionary<string, List<GrabbableObject>> <groupedItems>5__2; private List<GrabbableObject> <items>5__3; private Vector3 <pileCenterLocal>5__4; private float <extraYOffset>5__5; private float <groundYLocal>5__6; private GrabbableObject <held>5__7; private List<GrabbableObject> <itemsToMove>5__8; private int <moved>5__9; private GrabbableObject <heldBeforeDrop>5__10; private List<GrabbableObject>.Enumerator <>s__11; private GrabbableObject <item>5__12; private string <name>5__13; private List<GrabbableObject> <list>5__14; private Vector3 <rayStartCenter>5__15; private RaycastHit <hitCenter>5__16; private int <stackIndex>5__17; private GrabbableObject <item>5__18; private float <pileX>5__19; private float <pileZ>5__20; private float <pileY>5__21; private Vector3 <targetLocal>5__22; private Vector3 <worldPos>5__23; private int <cols>5__24; private int <rows>5__25; private int <perLayer>5__26; private int <layer>5__27; private int <inLayer>5__28; private int <r>5__29; private int <c>5__30; private int <retry>5__31; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <MoveItemsOfTypeToPosition>d__48(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <ship>5__1 = null; <groupedItems>5__2 = null; <items>5__3 = null; <held>5__7 = null; <itemsToMove>5__8 = null; <heldBeforeDrop>5__10 = null; <>s__11 = default(List<GrabbableObject>.Enumerator); <item>5__12 = null; <name>5__13 = null; <list>5__14 = null; <item>5__18 = null; <>1__state = -2; } private bool MoveNext() { //IL_07b6: Unknown result type (might be due to invalid IL or missing references) //IL_0821: Unknown result type (might be due to invalid IL or missing references) //IL_082b: Expected O, but got Unknown //IL_0664: Unknown result type (might be due to invalid IL or missing references) //IL_0669: Unknown result type (might be due to invalid IL or missing references) //IL_067b: Unknown result type (might be due to invalid IL or missing references) //IL_0680: Unknown result type (might be due to invalid IL or missing references) //IL_0685: Unknown result type (might be due to invalid IL or missing references) //IL_0693: Unknown result type (might be due to invalid IL or missing references) //IL_06a3: Unknown result type (might be due to invalid IL or missing references) //IL_0345: 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_037f: 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_038e: Unknown result type (might be due to invalid IL or missing references) //IL_0393: Unknown result type (might be due to invalid IL or missing references) //IL_0398: Unknown result type (might be due to invalid IL or missing references) //IL_039d: Unknown result type (might be due to invalid IL or missing references) //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_03a8: Unknown result type (might be due to invalid IL or missing references) //IL_03dc: Unknown result type (might be due to invalid IL or missing references) //IL_03e1: Unknown result type (might be due to invalid IL or missing references) //IL_06ff: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; inProgress = true; if (announce) { Log.Chat("Moving '" + itemKey + "' to your position... Press [Escape] to cancel", "FFFF00"); } if ((Object)(object)Player.Local == (Object)null) { Log.NotifyPlayer("Sorter Error", "Local player not ready yet", isWarning: true); inProgress = false; return false; } <ship>5__1 = GameObject.Find("Environment/HangarShip"); if ((Object)(object)<ship>5__1 == (Object)null) { Log.NotifyPlayer("Sorter Error", "Ship not found", isWarning: true); inProgress = false; return false; } if (dropHeldFirst) { <heldBeforeDrop>5__10 = Player.Local.currentlyHeldObjectServer; <>2__current = <>4__this.DropHeldItemIfAny(<ship>5__1); <>1__state = 1; return true; } goto IL_01ca; case 1: <>1__state = -1; <>4__this.CategorizeItems(includeSkippedItems: true); if ((Object)(object)<heldBeforeDrop>5__10 != (Object)null && <heldBeforeDrop>5__10.Name() == itemKey && <heldBeforeDrop>5__10.isInShipRoom) { if (<>4__this.scrap == null) { <>4__this.scrap = new List<GrabbableObject>(); } if (!<>4__this.scrap.Contains(<heldBeforeDrop>5__10)) { <>4__this.scrap.Add(<heldBeforeDrop>5__10); } } <heldBeforeDrop>5__10 = null; goto IL_01ca; case 2: <>1__state = -1; goto IL_0888; case 3: <>1__state = -1; if (!(ignoreSkipLists ? <>4__this.ShouldSkipExplicitQuery(<item>5__18) : <>4__this.ShouldSkip(<item>5__18))) { <item>5__18.floorYRot = -1; if (!MoveUtils.MoveItemOnShipLocal(<item>5__18, <targetLocal>5__22, <item>5__18.floorYRot)) { Log.Warning("Failed to move " + (<item>5__18.itemProperties?.itemName ?? ((Object)<item>5__18).name)); } <retry>5__31 = 15; goto IL_084e; } goto IL_0880; case 4: { <>1__state = -1; <retry>5__31--; goto IL_084e; } IL_089a: if (<stackIndex>5__17 < <itemsToMove>5__8.Count) { <item>5__18 = <itemsToMove>5__8[<stackIndex>5__17]; if (<>4__this.ShouldBreak(<item>5__18)) { Log.NotifyPlayer("Sorter Stopping", "Operation cancelled or ship is in motion", isWarning: true); inProgress = false; return false; } <pileX>5__19 = 0f; <pileZ>5__20 = 0f; if (<>4__this.stackSameTypeTogether.Value) { <pileY>5__21 = (float)<stackIndex>5__17 * Mathf.Max(0f, <>4__this.sameTypeStackStepY.Value); } else { <cols>5__24 = Mathf.Max(1, <>4__this.itemsPerRow.Value); <rows>5__25 = <cols>5__24; <perLayer>5__26 = <cols>5__24 * <rows>5__25; <layer>5__27 = <stackIndex>5__17 / <perLayer>5__26; <inLayer>5__28 = <stackIndex>5__17 % <perLayer>5__26; <r>5__29 = <inLayer>5__28 / <cols>5__24; <c>5__30 = <inLayer>5__28 % <cols>5__24; <pileX>5__19 = ((float)<c>5__30 - (float)(<cols>5__24 - 1) / 2f) * 0.1f; <pileZ>5__20 = ((float)<r>5__29 - (float)(<rows>5__25 - 1) / 2f) * 0.1f; <pileY>5__21 = (float)<layer>5__27 * 0.07f; } <targetLocal>5__22 = new Vector3(<pileCenterLocal>5__4.x + <pileX>5__19, <groundYLocal>5__6 + (<item>5__18.itemProperties.verticalOffset - 0.05f) + <extraYOffset>5__5 + <pileY>5__21, <pileCenterLocal>5__4.z + <pileZ>5__20); <worldPos>5__23 = <ship>5__1.transform.TransformPoint(<targetLocal>5__22); if (!force && Vector3.Distance(<worldPos>5__23, ((Component)<item>5__18).transform.position) < 0.25f) { goto IL_0888; } if ((Object)(object)<held>5__7 != (Object)null && (Object)(object)<item>5__18 == (Object)(object)<held>5__7) { <item>5__18.floorYRot = -1; MoveUtils.MoveItemOnShipLocal(<item>5__18, <targetLocal>5__22, <item>5__18.floorYRot); <moved>5__9++; <>2__current = null; <>1__state = 2; return true; } <>2__current = <>4__this.GrabbableRetry(<item>5__18); <>1__state = 3; return true; } Log.Chat($"Moved '{itemKey}' ({<moved>5__9} items)", "00FF00"); inProgress = false; return false; IL_084e: if (!Player.CanGrabObject(<item>5__18) && <retry>5__31 > 0) { <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 4; return true; } <moved>5__9++; goto IL_0880; IL_01ca: BeginOperationLock(); <groupedItems>5__2 = new Dictionary<string, List<GrabbableObject>>(); <>s__11 = <>4__this.scrap.GetEnumerator(); try { while (<>s__11.MoveNext()) { <item>5__12 = <>s__11.Current; if (!(ignoreSkipLists ? <>4__this.ShouldSkipExplicitQuery(<item>5__12) : <>4__this.ShouldSkip(<item>5__12))) { <name>5__13 = <item>5__12.Name(); if (!<groupedItems>5__2.TryGetValue(<name>5__13, out <list>5__14)) { <list>5__14 = new List<GrabbableObject>(); <groupedItems>5__2[<name>5__13] = <list>5__14; } <list>5__14.Add(<item>5__12); <name>5__13 = null; <list>5__14 = null; <item>5__12 = null; } } } finally { ((IDisposable)<>s__11).Dispose(); } <>s__11 = default(List<GrabbableObject>.Enumerator); if (!<groupedItems>5__2.TryGetValue(itemKey, out <items>5__3) || <items>5__3.Count == 0) { <items>5__3 = new List<GrabbableObject>(); } <pileCenterLocal>5__4 = new Vector3(targetCenterShipLocal.x, 0f, targetCenterShipLocal.z); <extraYOffset>5__5 = targetCenterShipLocal.y; <groundYLocal>5__6 = <pileCenterLocal>5__4.y; <rayStartCenter>5__15 = <ship>5__1.transform.TransformPoint(<pileCenterLocal>5__4 + Vector3.up * 2f); if (Physics.Raycast(<rayStartCenter>5__15, Vector3.down, ref <hitCenter>5__16, 80f, 268437761, (QueryTriggerInteraction)1)) { <groundYLocal>5__6 = <ship>5__1.transform.InverseTransformPoint(((RaycastHit)(ref <hitCenter>5__16)).point).y; } <held>5__7 = (((Object)(object)Player.Local != (Object)null) ? Player.Local.currentlyHeldObjectServer : null); <itemsToMove>5__8 = new List<GrabbableObject>(<items>5__3); if ((Object)(object)<held>5__7 != (Object)null && <held>5__7.Name() == itemKey && !<itemsToMove>5__8.Contains(<held>5__7)) { <itemsToMove>5__8.Insert(0, <held>5__7); } <moved>5__9 = 0; <stackIndex>5__17 = 0; goto IL_089a; IL_0888: <stackIndex>5__17++; goto IL_089a; IL_0880: <item>5__18 = null; goto IL_0888; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <SortItems>d__40 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public bool force; public bool ignoreSkippedItems; public bool includeSavedPositionTypesEvenIfSkipped; public Sorter <>4__this; private GameObject <ship>5__1; private Vector3 <originLocal>5__2; private HashSet<string> <savedTypes>5__3; private List<(string itemKey, Vector3 shipLocalPos)> <savedPositions>5__4; private string <posListError>5__5; private Dictionary<string, List<GrabbableObject>> <groupedItems>5__6; private List<KeyValuePair<string, List<GrabbableObject>>> <orderedGroups>5__7; private List<string> <orderedTypeNames>5__8; private HashSet<string> <reservedTypes>5__9; private Dictionary<string, Vector3> <layout>5__10; private List<GrabbableObject>.Enumerator <>s__11; private GrabbableObject <item>5__12; private string <itemName>5__13; private bool <ignoreSkipTokensForThisItem>5__14; private List<KeyValuePair<string, List<GrabbableObject>>>.Enumerator <>s__15; private KeyValuePair<string, List<GrabbableObject>> <group>5__16; private string <itemName>5__17; private List<GrabbableObject> <items>5__18; private Vector3 <typePos>5__19; private bool <hasCustomPos>5__20; private Vector3 <customShipLocal>5__21; private string <posError>5__22; private bool <ignoreSkipTokensForThisType>5__23; private Vector3 <pileCenterLocal>5__24; private float <customYOffset>5__25; private float <typeLayerYOffset>5__26; private float <originYOffset>5__27; private float <groundYLocal>5__28; private Vector3 <rayStartCenter>5__29; private RaycastHit <hitCenter>5__30; private int <stackIndex>5__31; private GrabbableObject <item>5__32; private float <pileX>5__33; private float <pileZ>5__34; private float <pileY>5__35; private Vector3 <targetLocal>5__36; private Vector3 <worldPos>5__37; private int <cols>5__38; private int <rows>5__39; private int <perLayer>5__40; private int <layer>5__41; private int <inLayer>5__42; private int <r>5__43; private int <c>5__44; private int <retry>5__45; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SortItems>d__40(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } <ship>5__1 = null; <savedTypes>5__3 = null; <savedPositions>5__4 = null; <posListError>5__5 = null; <groupedItems>5__6 = null; <orderedGroups>5__7 = null; <orderedTypeNames>5__8 = null; <reservedTypes>5__9 = null; <layout>5__10 = null; <>s__11 = default(List<GrabbableObject>.Enumerator); <item>5__12 = null; <itemName>5__13 = null; <>s__15 = default(List<KeyValuePair<string, List<GrabbableObject>>>.Enumerator); <group>5__16 = default(KeyValuePair<string, List<GrabbableObject>>); <itemName>5__17 = null; <items>5__18 = null; <posError>5__22 = null; <item>5__32 = null; <>1__state = -2; } private bool MoveNext() { //IL_082c: 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_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_0897: Unknown result type (might be due to invalid IL or missing references) //IL_08a1: Expected O, but got Unknown //IL_03a6: Unknown result type (might be due to invalid IL or missing references) //IL_0393: Unknown result type (might be due to invalid IL or missing references) //IL_03ab: Unknown result type (might be due to invalid IL or missing references) //IL_0762: Unknown result type (might be due to invalid IL or missing references) //IL_0767: Unknown result type (might be due to invalid IL or missing references) //IL_0779: Unknown result type (might be due to invalid IL or missing references) //IL_077e: Unknown result type (might be due to invalid IL or missing references) //IL_0783: Unknown result type (might be due to invalid IL or missing references) //IL_0791: Unknown result type (might be due to invalid IL or missing references) //IL_07a1: Unknown result type (might be due to invalid IL or missing references) //IL_0457: Unknown result type (might be due to invalid IL or missing references) //IL_0410: Unknown result type (might be due to invalid IL or missing references) //IL_0430: Unknown result type (might be due to invalid IL or missing references) //IL_0435: Unknown result type (might be due to invalid IL or missing references) //IL_045c: Unknown result type (might be due to invalid IL or missing references) //IL_04e0: Unknown result type (might be due to invalid IL or missing references) //IL_04e5: Unknown result type (might be due to invalid IL or missing references) //IL_04ef: Unknown result type (might be due to invalid IL or missing references) //IL_04f4: Unknown result type (might be due to invalid IL or missing references) //IL_04f9: Unknown result type (might be due to invalid IL or missing references) //IL_04fe: Unknown result type (might be due to invalid IL or missing references) //IL_0504: Unknown result type (might be due to invalid IL or missing references) //IL_0509: Unknown result type (might be due to invalid IL or missing references) //IL_053d: 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) bool result; try { switch (<>1__state) { default: result = false; break; case 0: <>1__state = -1; inProgress = true; Log.Chat("Press [Escape] to cancel sorting", "FFFF00"); if ((Object)(object)Player.Local == (Object)null) { Log.NotifyPlayer("Sorter Error", "Local player not ready yet", isWarning: true); inProgress = false; result = false; break; } <ship>5__1 = GameObject.Find("Environment/HangarShip"); if ((Object)(object)<ship>5__1 == (Object)null) { Log.NotifyPlayer("Sorter Error", "Ship not found", isWarning: true); inProgress = false; result = false; break; } BeginOperationLock(); <originLocal>5__2 = <>4__this.SortOrigin; <savedTypes>5__3 = null; <savedPositions>5__4 = SortPositions.ListAll(out <posListError>5__5); if (<posListError>5__5 != null) { Log.Warning(<posListError>5__5); } else { <savedTypes>5__3 = new HashSet<string>(<savedPositions>5__4.Select<(string, Vector3), string>(((string itemKey, Vector3 shipLocalPos) p) => p.itemKey)); } <groupedItems>5__6 = new Dictionary<string, List<GrabbableObject>>(); <>s__11 = <>4__this.scrap.GetEnumerator(); try { while (<>s__11.MoveNext()) { <item>5__12 = <>s__11.Current; <itemName>5__13 = <item>5__12.Name(); <ignoreSkipTokensForThisItem>5__14 = ignoreSkippedItems || (includeSavedPositionTypesEvenIfSkipped && <savedTypes>5__3 != null && <savedTypes>5__3.Contains(<itemName>5__13)); if (!<>4__this.ShouldSkipFullSort(<item>5__12, <ignoreSkipTokensForThisItem>5__14)) { if (!<groupedItems>5__6.ContainsKey(<itemName>5__13)) { <groupedItems>5__6[<itemName>5__13] = new List<GrabbableObject>(); } <groupedItems>5__6[<itemName>5__13].Add(<item>5__12); <itemName>5__13 = null; <item>5__12 = null; } } } finally { ((IDisposable)<>s__11).Dispose(); } <>s__11 = default(List<GrabbableObject>.Enumerator); <orderedGroups>5__7 = (from kvp in <groupedItems>5__6 orderby kvp.Value != null && kvp.Value.Any(IsTwoHandedItem) descending, kvp.Key select kvp).ToList(); <orderedTypeNames>5__8 = <orderedGroups>5__7.Select((KeyValuePair<string, List<GrabbableObject>> kvp) => kvp.Key).ToList(); <reservedTypes>5__9 = <savedTypes>5__3; <layout>5__10 = <>4__this.CreateLayout(<orderedTypeNames>5__8, <reservedTypes>5__9); <>s__15 = <orderedGroups>5__7.GetEnumerator(); <>1__state = -3; goto IL_0942; case 1: <>1__state = -3; if (!<>4__this.ShouldSkipFullSort(<item>5__32, ignoreSkippedItems | <ignoreSkipTokensForThisType>5__23)) { <item>5__32.floorYRot = -1; if (!MoveUtils.MoveItemOnShipLocal(<item>5__32, <targetLocal>5__36, <item>5__32.floorYRot)) { Log.Warning("Failed to move " + (<item>5__32.itemProperties?.itemName ?? ((Object)<item>5__32).name)); } <retry>5__45 = 15; goto IL_08ca; } goto IL_08ea; case 2: { <>1__state = -3; <retry>5__45--; goto IL_08ca; } IL_08ca: if (!Player.CanGrabObject(<item>5__32) && <retry>5__45 > 0) { <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 2; result = true; break; } goto IL_08ea; IL_08ea: <item>5__32 = null; goto IL_08f2; IL_0904: if (<stackIndex>5__31 < <items>5__18.Count) { <item>5__32 = <items>5__18[<stackIndex>5__31]; if (<>4__this.ShouldBreak(<item>5__32)) { Log.NotifyPlayer("Sorter Stopping", "Operation cancelled or ship is in motion", isWarning: true); inProgress = false; result = false; <>m__Finally1(); break; } <pileX>5__33 = 0f; <pileZ>5__34 = 0f; if (<>4__this.stackSameTypeTogether.Value) { <pileY>5__35 = (float)<stackIndex>5__31 * Mathf.Max(0f, <>4__this.sameTypeStackStepY.Value); } else { <cols>5__38 = Mathf.Max(1, <>4__this.itemsPerRow.Value); <rows>5__39 = <cols>5__38; <perLayer>5__40 = <cols>5__38 * <rows>5__39; <layer>5__41 = <stackIndex>5__31 / <perLayer>5__40; <inLayer>5__42 = <stackIndex>5__31 % <perLayer>5__40; <r>5__43 = <inLayer>5__42 / <cols>5__38; <c>5__44 = <inLayer>5__42 % <cols>5__38; <pileX>5__33 = ((float)<c>5__44 - (float)(<cols>5__38 - 1) / 2f) * 0.1f; <pileZ>5__34 = ((float)<r>5__43 - (float)(<rows>5__39 - 1) / 2f) * 0.1f; <pileY>5__35 = (float)<layer>5__41 * 0.07f; } <targetLocal>5__36 = new Vector3(<pileCenterLocal>5__24.x + <pileX>5__33, <groundYLocal>5__28 + <originYOffset>5__27 + (<item>5__32.itemProperties.verticalOffset - 0.1f) + (<typeLayerYOffset>5__26 + <customYOffset>5__25) + <pileY>5__35 - (ShouldLowerYOffset(<item>5__32) ? 0.2f : 0f), <pileCenterLocal>5__24.z + <pileZ>5__34); <worldPos>5__37 = <ship>5__1.transform.TransformPoint(<targetLocal>5__36); if (!force && Vector3.Distance(<worldPos>5__37, ((Component)<item>5__32).transform.position) < 0.25f) { goto IL_08f2; } <>2__current = <>4__this.GrabbableRetry(<item>5__32); <>1__state = 1; result = true; break; } <itemName>5__17 = null; <items>5__18 = null; <posError>5__22 = null; <group>5__16 = default(KeyValuePair<string, List<GrabbableObject>>); goto IL_0942; IL_08f2: <stackIndex>5__31++; goto IL_0904; IL_0942: if (<>s__15.MoveNext()) { <group>5__16 = <>s__15.Current; <itemName>5__17 = <group>5__16.Key; <items>5__18 = <group>5__16.Value; <typePos>5__19 = (<layout>5__10.ContainsKey(<itemName>5__17) ? <layout>5__10[<itemName>5__17] : Vector3.zero); <hasCustomPos>5__20 = SortPositions.TryGet(<itemName>5__17, out <customShipLocal>5__21, out <posError>5__22); if (<posError>5__22 != null) { Log.Warning(<posError>5__22); } <ignoreSkipTokensForThisType>5__23 = includeSavedPositionTypesEvenIfSkipped & <hasCustomPos>5__20; <pileCenterLocal>5__24 = (Vector3)(<hasCustomPos>5__20 ? new Vector3(<customShipLocal>5__21.x, 0f, <customShipLocal>5__21.z) : (<originLocal>5__2 + new Vector3(<typePos>5__19.x, 0f, <typePos>5__19.z))); <customYOffset>5__25 = (<hasCustomPos>5__20 ? <customShipLocal>5__21.y : 0f); <typeLayerYOffset>5__26 = (<hasCustomPos>5__20 ? 0f : <typePos>5__19.y); <originYOffset>5__27 = (<hasCustomPos>5__20 ? 0f : <originLocal>5__2.y); <groundYLocal>5__28 = <pileCenterLocal>5__24.y; <rayStartCenter>5__29 = <ship>5__1.transform.TransformPoint(<pileCenterLocal>5__24 + Vector3.up * 2f); if (Physics.Raycast(<rayStartCenter>5__29, Vector3.down, ref <hitCenter>5__30, 80f, 268437761, (QueryTriggerInteraction)1)) { <groundYLocal>5__28 = <ship>5__1.transform.InverseTransformPoint(((RaycastHit)(ref <hitCenter>5__30)).point).y; } <stackIndex>5__31 = 0; goto IL_0904; } <>m__Finally1(); <>s__15 = default(List<KeyValuePair<string, List<GrabbableObject>>>.Enumerator); Log.Chat("Sorting complete!", "00FF00"); inProgress = false; result = false; break; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>s__15).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string DefaultSkippedItems = "body, clipboard, sticky_note, boombox, shovel, jetpack, flashlight, pro_flashlight, key, stun_grenade, lockpicker, mapper, extension_ladder, tzp_inhalant, walkie_talkie, zap_gun, kitchen_knife, weed_killer, radar_booster, spray_paint, belt_bag, shotgun, ammo"; private static readonly HashSet<string> LowerYOffsetTypes = new HashSet<string> { "toilet_paper", "chemical_jug", "cash_register", "fancy_lamp", "large_axle", "v_type_engine" }; public ConfigEntry<float> sortOriginX; public ConfigEntry<float> sortOriginY; public ConfigEntry<float> sortOriginZ; public ConfigEntry<float> itemSpacing; public ConfigEntry<float> rowSpacing; public ConfigEntry<int> itemsPerRow; public ConfigEntry<string> skippedItems; public ConfigEntry<float> sortAreaWidth; public ConfigEntry<float> sortAreaDepth; public ConfigEntry<float> wallPadding; public ConfigEntry<bool> stackSameTypeTogether; public ConfigEntry<float> sameTypeStackStepY; private List<GrabbableObject> scrap; public static bool inProgress; private static bool _interactionLocked; private static int _interactionBypassCount; private static List<(string name, bool isProperty, float value)>? _savedWeight; private Vector3 SortOrigin => new Vector3(sortOriginX.Value, sortOriginY.Value, sortOriginZ.Value); private bool CanSort => true; internal static bool IsInteractionLocked => _interactionLocked; internal static bool IsInteractionBypassActive => _interactionBypassCount > 0; private static bool ShouldLowerYOffset(GrabbableObject item) { if ((Object)(object)item == (Object)null) { return false; } string text = item.Name(); if (string.IsNullOrWhiteSpace(text)) { return false; } return LowerYOffsetTypes.Contains(text); } private static string ApplyDefaultInputAliases(string normalizedKey) { if (string.IsNullOrWhiteSpace(normalizedKey)) { return normalizedKey; } if (1 == 0) { } string result = ((normalizedKey == "double_barrel") ? "shotgun" : ((!(normalizedKey == "shotgun_shell")) ? normalizedKey : "ammo")); if (1 == 0) { } return result; } internal static bool EnsureLocalPlayerInShip(out string? error) { //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) error = null; PlayerControllerB local = Player.Local; if ((Object)(object)local == (Object)null) { error = "Local player not ready yet"; return false; } try { Type type2 = ((object)local).GetType(); string[] array = new string[6] { "isInHangarShipRoom", "IsInHangarShipRoom", "isInShipRoom", "IsInShipRoom", "inShipRoom", "InShipRoom" }; string[] array2 = array; foreach (string name2 in array2) { bool? flag = TryGetBool(local, type2, name2); if (flag.HasValue) { if (!flag.Value) { error = "You must be inside the ship to use this command."; return false; } return true; } } } catch { } GameObject val = GameObject.Find("Environment/HangarShip"); if ((Object)(object)val == (Object)null) { error = "Ship not found"; return false; } Vector3 val2 = val.transform.InverseTransformPoint(((Component)local).transform.position); if (!(val2.x >= -10f) || !(val2.x <= 10f) || !(val2.z >= -20f) || !(val2.z <= 10f) || !(val2.y >= -6f) || !(val2.y <= 10f)) { error = "You must be inside the ship to use this command."; return false; } return true; static bool? TryGetBool(object obj, Type type, string name) { FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(bool)) { return (bool)field.GetValue(obj); } PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.PropertyType == typeof(bool) && property.GetIndexParameters().Length == 0) { return (bool)property.GetValue(obj, null); } return null; } } private void Awake() { sortOriginX = Plugin.config.Bind<float>("Sorter", "sortOriginX", -2.8f, "X coordinate of the origin position for sorting items (relative to ship)"); sortOriginY = Plugin.config.Bind<float>("Sorter", "sortOriginY", 0.1f, "Y coordinate of the origin position for sorting items (relative to ship)"); sortOriginZ = Plugin.config.Bind<float>("Sorter", "sortOriginZ", -4.8f, "Z coordinate of the origin position for sorting items (relative to ship)"); itemSpacing = Plugin.config.Bind<float>("Sorter", "itemSpacing", 0.8f, "Spacing between items horizontally"); rowSpacing = Plugin.config.Bind<float>("Sorter", "rowSpacing", 0.8f, "Spacing between rows vertically"); itemsPerRow = Plugin.config.Bind<int>("Sorter", "itemsPerRow", 9, "Number of items per row"); skippedItems = Plugin.config.Bind<string>("Sorter", "skippedItems", "body, clipboard, sticky_note, boombox, shovel, jetpack, flashlight, pro_flashlight, key, stun_grenade, lockpicker, mapper, extension_ladder, tzp_inhalant, walkie_talkie, zap_gun, kitchen_knife, weed_killer, radar_booster, spray_paint, belt_bag, shotgun, ammo", "Global skip list (comma-separated, substring match). Applies to all grabbable items."); skippedItems.Value = NormalizeSkipListConfig(skippedItems.Value); sortAreaWidth = Plugin.config.Bind<float>("Sorter", "sortAreaWidth", 9f, "Reserved: used only for future bounding. (Keeping for compatibility)"); sortAreaDepth = Plugin.config.Bind<float>("Sorter", "sortAreaDepth", 6f, "How far forward (Z) types are allowed to expand from sortOriginZ before starting a new type-layer above."); wallPadding = Plugin.config.Bind<float>("Sorter", "wallPadding", 0.25f, "Padding used for depth calculation (prevents placing type rows into doors/walls)."); stackSameTypeTogether = Plugin.config.Bind<bool>("Sorter", "stackSameTypeTogether", true, "If true, items of the same type will be stacked at the exact same X/Z position (only Y increases), instead of being spread in a small grid."); sameTypeStackStepY = Plugin.config.Bind<float>("Sorter", "sameTypeStackStepY", 0f, "Vertical spacing between items when stackSameTypeTogether is enabled. Set to 0 for exact overlap; increase (e.g. 0.1~0.2) if physics makes items push apart."); } internal static IDisposable BeginInteractionBypass() { _interactionBypassCount++; return new DisposeAction(delegate { _interactionBypassCount = Math.Max(0, _interactionBypassCount - 1); }); } private static void CapturePlayerWeightIfNeeded() { if (_savedWeight != null) { return; } PlayerControllerB local = Player.Local; if ((Object)(object)local == (Object)null) { return; } Type type = ((object)local).GetType(); List<(string, bool, float)> list = new List<(string, bool, float)>(); try { FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (!(fieldInfo.FieldType != typeof(float)) && IsCarryWeightName(fieldInfo.Name)) { list.Add((fieldInfo.Name, false, (float)fieldInfo.GetValue(local))); } } } catch { } try { PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo propertyInfo in properties) { if (!(propertyInfo.PropertyType != typeof(float)) && propertyInfo.GetIndexParameters().Length == 0 && propertyInfo.CanRead && propertyInfo.CanWrite && IsCarryWeightName(propertyInfo.Name)) { list.Add((propertyInfo.Name, true, (float)propertyInfo.GetValue(local, null))); } } } catch { } if (list.Count > 0) { _savedWeight = list; } static bool IsCarryWeightName(string n) { return n != null && n.IndexOf("carry", StringComparison.OrdinalIgnoreCase) >= 0 && n.IndexOf("weight", StringComparison.OrdinalIgnoreCase) >= 0; } } private static void RestorePlayerWeightIfNeeded() { if (_savedWeight == null) { return; } PlayerControllerB local = Player.Local; if ((Object)(object)local == (Object)null) { _savedWeight = null; return; } Type type = ((object)local).GetType(); foreach (var item in _savedWeight) { try { if (!item.isProperty) { FieldInfo field = type.GetField(item.name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(float)) { field.SetValue(local, item.value); } } else { PropertyInfo property = type.GetProperty(item.name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.PropertyType == typeof(float) && property.GetIndexParameters().Length == 0 && property.CanWrite) { property.SetValue(local, item.value, null); } } } catch { } } _savedWeight = null; } private static void BeginOperationLock() { if (!_interactionLocked) { CapturePlayerWeightIfNeeded(); _interactionLocked = true; } } private static void EndOperationLock() { _interactionLocked = false; _interactionBypassCount = 0; RestorePlayerWeightIfNeeded(); } [IteratorStateMachine(typeof(<DropHeldItemIfAny>d__37))] private IEnumerator DropHeldItemIfAny(GameObject ship) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DropHeldItemIfAny>d__37(0) { <>4__this = this, ship = ship }; } private void Update() { if (inProgress && ((ButtonControl)Keyboard.current.escapeKey).wasPressedThisFrame) { inProgress = false; Log.Chat("Sorting cancelled", "FF0000"); } if (_interactionLocked && !inProgress) { EndOperationLock(); } } private void SortCommandHandler(string[] args) { if (args.Length != 0 && args[0] == "help") { Log.Chat("Usage: /sort [help]", "FFFF00"); return; } if (inProgress) { Log.NotifyPlayer("Sorter Error", "Operation in progress", isWarning: true); return; } CategorizeItems(); Log.ConfirmSound(); ((MonoBehaviour)this).StartCoroutine(SortItems(force: false)); } [IteratorStateMachine(typeof(<SortItems>d__40))] public IEnumerator SortItems(bool force, bool ignoreSkippedItems = false, bool includeSavedPositionTypesEvenIfSkipped = false) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SortItems>d__40(0) { <>4__this = this, force = force, ignoreSkippedItems = ignoreSkippedItems, includeSavedPositionTypesEvenIfSkipped = includeSavedPositionTypesEvenIfSkipped }; } private static bool IsTwoHandedItem(GrabbableObject item) { try { if ((Object)(object)item == (Object)null) { return false; } Item itemProperties = item.itemProperties; if ((Object)(object)itemProperties == (Object)null) { return false; } Type type = ((object)itemProperties).GetType(); FieldInfo fieldInfo = type.GetField("twoHanded", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetField("isTwoHanded", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetField("twoHandedItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetField("<twoHanded>k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetField("<isTwoHanded>k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetField("<twoHandedItem>k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (fieldInfo != null && fieldInfo.FieldType == typeof(bool)) { return (bool)fieldInfo.GetValue(itemProperties); } PropertyInfo propertyInfo = type.GetProperty("twoHanded", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetProperty("isTwoHanded", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetProperty("twoHandedItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (propertyInfo != null && propertyInfo.PropertyType == typeof(bool) && propertyInfo.GetIndexParameters().Length == 0) { return (bool)propertyInfo.GetValue(itemProperties, null); } FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo2 in fields) { if (!(fieldInfo2.FieldType != typeof(bool)) && fieldInfo2.Name.IndexOf("twohand", StringComparison.OrdinalIgnoreCase) >= 0) { return (bool)fieldInfo2.GetValue(itemProperties); } } PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo propertyInfo2 in properties) { if (!(propertyInfo2.PropertyType != typeof(bool)) && propertyInfo2.GetIndexParameters().Length == 0 && propertyInfo2.Name.IndexOf("twohand", StringComparison.OrdinalIgnoreCase) >= 0) { return (bool)propertyInfo2.GetValue(itemProperties, null); } } return false; } catch { return false; } } public bool TryStartGatherByQuery(string query, bool force, out string? error) { //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) error = null; if (inProgress) { error = "Operation in progress"; return false; } if (string.IsNullOrWhiteSpace(query)) { error = "Missing item name"; return false; } CategorizeItems(includeSkippedItems: true); if (scrap == null || scrap.Count == 0) { error = "No items found in ship"; return false; } Dictionary<string, List<GrabbableObject>> dictionary = new Dictionary<string, List<GrabbableObject>>(); foreach (GrabbableObject item in scrap) { if (!ShouldSkipExplicitQuery(item)) { string key = item.Name(); if (!dictionary.TryGetValue(key, out var value)) { value = (dictionary[key] = new List<GrabbableObject>()); } value.Add(item); } } if (!TryResolveItemKeyFromGrouped(dictionary, query, out string resolvedKey, out error)) { return false; } if (!TryGetPlayerShipLocalTarget(out var shipLocalTarget, out error)) { return false; } if (!TryGetGroundYLocalAt(shipLocalTarget, out float groundYLocal, out string error2)) { error = error2; return false; } Vector3 targetCenterShipLocal = default(Vector3); ((Vector3)(ref targetCenterShipLocal))..ctor(shipLocalTarget.x, shipLocalTarget.y - groundYLocal, shipLocalTarget.z); ((MonoBehaviour)this).StartCoroutine(MoveItemsOfTypeToPosition(resolvedKey, targetCenterShipLocal, force, announce: true, ignoreSkipLists: true, applyTwoHandedSortYOffset: true)); return true; } public bool TryStartPileByQueryOrHeld(string? queryOrNull, bool force, out string? error) { //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) error = null; if (inProgress) { error = "Operation in progress"; return false; } GrabbableObject val = (((Object)(object)Player.Local != (Object)null) ? Player.Local.currentlyHeldObjectServer : null); string text = ((!string.IsNullOrWhiteSpace(queryOrNull)) ? queryOrNull : (((Object)(object)val != (Object)null) ? val.Name() : "")); bool dropHeldFirst = string.IsNullOrWhiteSpace(queryOrNull); if (string.IsNullOrWhiteSpace(text)) { error = "Missing item name (hold the item or provide a name)."; return false; } CategorizeItems(includeSkippedItems: true); Dictionary<string, List<GrabbableObject>> dictionary = new Dictionary<string, List<GrabbableObject>>(); if (scrap != null) { foreach (GrabbableObject item in scrap) { if (!ShouldSkipExplicitQuery(item)) { string key = item.Name(); if (!dictionary.TryGetValue(key, out var value)) { value = (dictionary[key] = new List<GrabbableObject>()); } value.Add(item); } } } if ((Object)(object)val != (Object)null && !ShouldSkipExplicitQuery(val)) { string key2 = val.Name(); if (!dictionary.TryGetValue(key2, out var value2)) { value2 = (dictionary[key2] = new List<GrabbableObject>()); } if (!value2.Contains(val)) { value2.Add(val); } } if (dictionary.Count == 0) { error = "No items found in ship"; return false; } if (!TryResolveItemKeyFromGrouped(dictionary, text, out string resolvedKey, out error)) { return false; } if (!TryGetPlayerShipLocalTarget(out var shipLocalTarget, out error)) { return false; } if (!TryGetGroundYLocalAt(shipLocalTarget, out float groundYLocal, out string error2)) { error = error2; return false; } Vector3 targetCenterShipLocal = default(Vector3); ((Vector3)(ref targetCenterShipLocal))..ctor(shipLocalTarget.x, shipLocalTarget.y - groundYLocal, shipLocalTarget.z); (