Decompiled source of CleanShip v1.0.2

CleanShip.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using GameNetcodeStuff;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("CleanShip")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+25c99e96dc6d3a04909db71266aabd3b4f8db979")]
[assembly: AssemblyProduct("CleanShip")]
[assembly: AssemblyTitle("CleanShip")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace CleanShip;

public static class Setting
{
	public static bool bMenu;

	public static bool bCleaning;
}
[Serializable]
public class ItemLocationList
{
	public float winWidth = 600f;

	public float winHeight = 800f;

	public int fontSize = 16;

	public bool onlySortCustom = false;

	public List<ItemData> items = new List<ItemData>();
}
[Serializable]
public class ItemData
{
	public string itemName;

	public float x;

	public float y;

	public float z;
}
[BepInPlugin("me.cleanship.mod", "CleanShip", "1.0.2")]
public class Plugin : BaseUnityPlugin
{
	public static ManualLogSource Log;

	public static Plugin Instance;

	private Rect winRect;

	private bool isMenuOpen = false;

	private Vector2 configScrollPosition = Vector2.zero;

	private Vector2 shipItemsScrollPosition = Vector2.zero;

	private string searchKeyword = "";

	private string configPath;

	public ItemLocationList customLocations = new ItemLocationList();

	private List<string> detectedShipItemNames = new List<string>();

	private InputAction menuKeyAction;

	private void Awake()
	{
		//IL_005f: 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_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Expected O, but got Unknown
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		Log.LogInfo((object)">>> CleanShip 物品整理模组加载中... <<<");
		configPath = Path.Combine(Paths.ConfigPath, "CleanShip_Items.json");
		LoadCustomLocations();
		winRect = new Rect(50f, 50f, customLocations.winWidth, customLocations.winHeight);
		menuKeyAction = new InputAction("OpenCleanShipMenu", (InputActionType)0, "<Keyboard>/equals", (string)null, (string)null, (string)null);
		menuKeyAction.performed += ToggleMenu;
		menuKeyAction.Enable();
	}

	private void ToggleMenu(CallbackContext context)
	{
		isMenuOpen = !isMenuOpen;
		Setting.bMenu = isMenuOpen;
		if (isMenuOpen)
		{
			Cursor.visible = true;
			Cursor.lockState = (CursorLockMode)0;
			RefreshShipItems();
		}
		else
		{
			Cursor.visible = false;
			Cursor.lockState = (CursorLockMode)1;
		}
	}

	private void SaveCustomLocations()
	{
		string contents = JsonUtility.ToJson((object)customLocations, true);
		File.WriteAllText(configPath, contents);
	}

	private void LoadCustomLocations()
	{
		if (File.Exists(configPath))
		{
			try
			{
				string text = File.ReadAllText(configPath);
				customLocations = JsonUtility.FromJson<ItemLocationList>(text);
				return;
			}
			catch
			{
				customLocations = new ItemLocationList();
				return;
			}
		}
		customLocations = new ItemLocationList();
	}

	private void OnGUI()
	{
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: 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)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Expected O, but got Unknown
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		if (!isMenuOpen)
		{
			return;
		}
		int fontSize = customLocations.fontSize;
		GUI.skin.label.fontSize = fontSize;
		GUI.skin.button.fontSize = fontSize;
		GUI.skin.textField.fontSize = fontSize;
		GUI.skin.box.fontSize = fontSize;
		GUI.skin.toggle.fontSize = fontSize;
		GUI.skin.window.fontSize = fontSize + 2;
		GUI.backgroundColor = Color.black;
		if (Mathf.Abs(((Rect)(ref winRect)).width - customLocations.winWidth) > 1f)
		{
			((Rect)(ref winRect)).width = customLocations.winWidth;
		}
		if (Mathf.Abs(((Rect)(ref winRect)).height - customLocations.winHeight) > 1f)
		{
			((Rect)(ref winRect)).height = customLocations.winHeight;
		}
		try
		{
			winRect = GUILayout.Window(9999, winRect, new WindowFunction(WindowFunction), "CleanShip 物品整理控制台", Array.Empty<GUILayoutOption>());
		}
		catch
		{
			GUI.color = Color.white;
			GUI.backgroundColor = Color.white;
		}
	}

	private void WindowFunction(int id)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: 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_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0320: Unknown result type (might be due to invalid IL or missing references)
		//IL_0355: Unknown result type (might be due to invalid IL or missing references)
		//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_03df: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0291: Unknown result type (might be due to invalid IL or missing references)
		//IL_028a: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_059d: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_07a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_050d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0557: Unknown result type (might be due to invalid IL or missing references)
		GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
		GUILayout.Label("--- 基础操作 ---", Array.Empty<GUILayoutOption>());
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		GUI.backgroundColor = (Setting.bCleaning ? Color.green : Color.white);
		if (GUILayout.Button(Setting.bCleaning ? "停止整理" : "整理飞船", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(35f) }))
		{
			if (!Setting.bCleaning)
			{
				((MonoBehaviour)this).StartCoroutine(SortCoroutine());
			}
			else
			{
				Setting.bCleaning = false;
				((MonoBehaviour)this).StopAllCoroutines();
			}
		}
		GUI.backgroundColor = (customLocations.onlySortCustom ? Color.cyan : Color.gray);
		if (GUILayout.Button(customLocations.onlySortCustom ? "模式: 仅自定义" : "模式: 全部整理", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(35f) }))
		{
			customLocations.onlySortCustom = !customLocations.onlySortCustom;
			SaveCustomLocations();
		}
		GUI.backgroundColor = Color.white;
		GUILayout.EndHorizontal();
		GUILayout.Space(15f);
		GUI.color = Color.cyan;
		GUILayout.Label("--- 飞船内物品扫描 ---", Array.Empty<GUILayoutOption>());
		GUI.color = Color.white;
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		if (GUILayout.Button("刷新", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }))
		{
			RefreshShipItems();
		}
		GUILayout.Label("搜:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) });
		searchKeyword = GUILayout.TextField(searchKeyword, Array.Empty<GUILayoutOption>());
		GUILayout.EndHorizontal();
		shipItemsScrollPosition = GUILayout.BeginScrollView(shipItemsScrollPosition, GUI.skin.box, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(180f) });
		List<string> list = detectedShipItemNames.Where((string n) => n?.ToLower().Contains(searchKeyword.ToLower()) ?? false).ToList();
		if (list.Count == 0)
		{
			GUILayout.Label("无匹配物品", Array.Empty<GUILayoutOption>());
		}
		else
		{
			foreach (string itemName in list)
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUI.color = (customLocations.items.Any((ItemData x) => x != null && x.itemName == itemName) ? Color.green : Color.white);
				GUILayout.Label(itemName, Array.Empty<GUILayoutOption>());
				GUI.color = Color.white;
				if (GUILayout.Button("设为脚下", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) }))
				{
					RecordItemByName(itemName);
				}
				GUILayout.EndHorizontal();
			}
		}
		GUILayout.EndScrollView();
		GUILayout.Space(15f);
		GUI.color = Color.yellow;
		GUILayout.Label($"--- 已保存配置 ({customLocations.items.Count}) ---", Array.Empty<GUILayoutOption>());
		GUI.color = Color.white;
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		if (GUILayout.Button("记录手持", Array.Empty<GUILayoutOption>()))
		{
			RecordCurrentItem();
		}
		if (GUILayout.Button("保存配置", Array.Empty<GUILayoutOption>()))
		{
			SaveCustomLocations();
			Log.LogInfo((object)"配置已保存!");
		}
		GUILayout.EndHorizontal();
		configScrollPosition = GUILayout.BeginScrollView(configScrollPosition, GUI.skin.box, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(200f) });
		for (int i = 0; i < customLocations.items.Count; i++)
		{
			ItemData itemData = customLocations.items[i];
			if (itemData != null)
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label(itemData.itemName, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(180f) });
				itemData.x = (float.TryParse(GUILayout.TextField(itemData.x.ToString("F1"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) }), out var result) ? result : itemData.x);
				itemData.y = (float.TryParse(GUILayout.TextField(itemData.y.ToString("F1"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) }), out var result2) ? result2 : itemData.y);
				itemData.z = (float.TryParse(GUILayout.TextField(itemData.z.ToString("F1"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) }), out var result3) ? result3 : itemData.z);
				GUI.backgroundColor = Color.red;
				if (GUILayout.Button("X", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(30f) }))
				{
					customLocations.items.RemoveAt(i);
					SaveCustomLocations();
				}
				GUI.backgroundColor = Color.white;
				GUILayout.EndHorizontal();
			}
		}
		GUILayout.EndScrollView();
		GUILayout.Space(15f);
		GUI.color = Color.magenta;
		GUILayout.Label("--- 界面设置 ---", Array.Empty<GUILayoutOption>());
		GUI.color = Color.white;
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		GUILayout.Label($"字体: {customLocations.fontSize}", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
		int num = (int)GUILayout.HorizontalSlider((float)customLocations.fontSize, 10f, 30f, Array.Empty<GUILayoutOption>());
		if (num != customLocations.fontSize)
		{
			customLocations.fontSize = num;
		}
		GUILayout.EndHorizontal();
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		GUILayout.Label($"宽: {(int)customLocations.winWidth}", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
		float num2 = GUILayout.HorizontalSlider(customLocations.winWidth, 400f, 1000f, Array.Empty<GUILayoutOption>());
		if (Mathf.Abs(num2 - customLocations.winWidth) > 1f)
		{
			customLocations.winWidth = num2;
		}
		GUILayout.EndHorizontal();
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		GUILayout.Label($"高: {(int)customLocations.winHeight}", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
		float num3 = GUILayout.HorizontalSlider(customLocations.winHeight, 600f, 1300f, Array.Empty<GUILayoutOption>());
		if (Mathf.Abs(num3 - customLocations.winHeight) > 1f)
		{
			customLocations.winHeight = num3;
		}
		GUILayout.EndHorizontal();
		if (GUILayout.Button("保存界面设置", Array.Empty<GUILayoutOption>()))
		{
			SaveCustomLocations();
		}
		GUILayout.EndVertical();
		GUI.DragWindow(new Rect(0f, 0f, customLocations.winWidth, 30f));
	}

	private T GetPrivateField<T>(object instance, string fieldName)
	{
		FieldInfo field = instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field != null)
		{
			return (T)field.GetValue(instance);
		}
		return default(T);
	}

	private void SetPrivateField(object instance, string fieldName, object value)
	{
		FieldInfo field = instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field != null)
		{
			field.SetValue(instance, value);
		}
	}

	private void CallPrivateMethod(object instance, string methodName, params object[] args)
	{
		MethodInfo method = instance.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (method != null)
		{
			method.Invoke(instance, args);
		}
	}

	private IEnumerator SortCoroutine()
	{
		Setting.bCleaning = true;
		PlayerControllerB player = GameNetworkManager.Instance?.localPlayerController;
		Transform shipTransform = StartOfRound.Instance?.elevatorTransform;
		if ((Object)(object)shipTransform == (Object)null || (Object)(object)player == (Object)null)
		{
			Setting.bCleaning = false;
			yield break;
		}
		GrabbableObject[] items = Object.FindObjectsByType<GrabbableObject>((FindObjectsSortMode)0);
		GrabbableObject[] array = items;
		foreach (GrabbableObject item in array)
		{
			if (!Setting.bCleaning || player.isPlayerDead || !player.isPlayerControlled || !StartOfRound.Instance.inShipPhase)
			{
				break;
			}
			if ((Object)(object)item == (Object)null || (Object)(object)item.itemProperties == (Object)null)
			{
				continue;
			}
			bool isPhysicallyInShip = Vector3.Distance(((Component)item).transform.position, shipTransform.position) < 18f;
			if (item.isHeld || item.heldByPlayerOnServer || (!item.isInShipRoom && !isPhysicallyInShip))
			{
				continue;
			}
			ItemData customData = customLocations.items.FirstOrDefault((ItemData x) => x != null && x.itemName == item.itemProperties.itemName);
			if (customLocations.onlySortCustom && customData == null)
			{
				continue;
			}
			Vector3 targetPos = new Vector3(-3.3f, 0.5f, -12.7f);
			if (customData != null)
			{
				targetPos = new Vector3(customData.x, customData.y, customData.z);
			}
			if (Vector3.Distance(((Component)item).transform.position, targetPos) > 0.2f)
			{
				yield return (object)new WaitUntil((Func<bool>)(() => player.isPlayerDead || !GetPrivateField<bool>(player, "isThrowingObject")));
				if (player.isPlayerDead)
				{
					break;
				}
				NetworkObjectReference netObjRef = new NetworkObjectReference(((NetworkBehaviour)item).NetworkObject);
				SetPrivateField(player, "currentlyGrabbingObject", item);
				CallPrivateMethod(player, "GrabObjectServerRpc", netObjRef);
				float waitTimer = 0f;
				yield return (object)new WaitUntil((Func<bool>)delegate
				{
					waitTimer += Time.deltaTime;
					return player.isPlayerDead || (Object)(object)player.currentlyHeldObjectServer == (Object)(object)item || waitTimer > 1f;
				});
				if (!player.isPlayerDead && !((Object)(object)player.currentlyHeldObjectServer != (Object)(object)item))
				{
					player.DiscardHeldObject(true, (NetworkObject)null, targetPos, false);
					((Component)item).transform.rotation = Quaternion.Euler(0f, 0f, 0f);
					yield return (object)new WaitForSeconds(0.1f);
				}
			}
			else if (Quaternion.Angle(((Component)item).transform.rotation, Quaternion.Euler(0f, 0f, 0f)) > 5f)
			{
				((Component)item).transform.rotation = Quaternion.Euler(0f, 0f, 0f);
			}
		}
		Setting.bCleaning = false;
	}

	private void RefreshShipItems()
	{
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		detectedShipItemNames.Clear();
		if ((Object)(object)StartOfRound.Instance == (Object)null || (Object)(object)StartOfRound.Instance.elevatorTransform == (Object)null)
		{
			return;
		}
		Transform elevatorTransform = StartOfRound.Instance.elevatorTransform;
		GrabbableObject[] array = Object.FindObjectsByType<GrabbableObject>((FindObjectsSortMode)0);
		GrabbableObject[] array2 = array;
		foreach (GrabbableObject val in array2)
		{
			if (!val.isHeld && !val.heldByPlayerOnServer && !(Vector3.Distance(((Component)val).transform.position, elevatorTransform.position) > 20f))
			{
				string text = val.itemProperties?.itemName;
				if (text != null && !detectedShipItemNames.Contains(text))
				{
					detectedShipItemNames.Add(text);
				}
			}
		}
		detectedShipItemNames.Sort();
	}

	private void RecordItemByName(string itemName)
	{
		//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_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
		if (!((Object)(object)val == (Object)null))
		{
			Vector3 position = ((Component)val).transform.position;
			ItemData itemData = customLocations.items.FirstOrDefault((ItemData x) => x != null && x.itemName == itemName);
			if (itemData != null)
			{
				itemData.x = position.x;
				itemData.y = position.y;
				itemData.z = position.z;
			}
			else
			{
				customLocations.items.Add(new ItemData
				{
					itemName = itemName,
					x = position.x,
					y = position.y,
					z = position.z
				});
			}
			SaveCustomLocations();
		}
	}

	private void RecordCurrentItem()
	{
		PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
		if (!((Object)(object)val == (Object)null) && !((Object)(object)val.currentlyHeldObjectServer == (Object)null) && !((Object)(object)val.currentlyHeldObjectServer.itemProperties == (Object)null))
		{
			RecordItemByName(val.currentlyHeldObjectServer.itemProperties.itemName);
		}
	}
}