Decompiled source of CheatTagCleaner v1.1.0

plugins/CheatTagCleaner.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("CheatTagCleaner")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+5cf585e728f22067a11420e4595efd7a40a09a8f")]
[assembly: AssemblyProduct("CheatTagCleaner")]
[assembly: AssemblyTitle("CheatTagCleaner")]
[assembly: AssemblyVersion("1.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CheatTagCleaner
{
	internal static class Cleaner
	{
		internal struct Result
		{
			public int Items;

			public int Buildings;

			public bool Any
			{
				get
				{
					if (Items <= 0)
					{
						return Buildings > 0;
					}
					return true;
				}
			}
		}

		private static readonly MethodInfo InventoryChanged = AccessTools.Method(typeof(Inventory), "Changed", Type.EmptyTypes, (Type[])null);

		private static readonly MethodInfo ItemDropSave = AccessTools.Method(typeof(ItemDrop), "Save", Type.EmptyTypes, (Type[])null);

		private static readonly FieldInfo ItemDropInstances = AccessTools.Field(typeof(ItemDrop), "s_instances");

		private static readonly MethodInfo TombOwner = AccessTools.Method(typeof(TombStone), "GetOwner", Type.EmptyTypes, (Type[])null);

		private static readonly FieldInfo CurrentContainer = AccessTools.Field(typeof(InventoryGui), "m_currentContainer");

		public static Result CleanAroundPlayer(Player player, long? owner)
		{
			Result result = default(Result);
			result.Items += CleanInventory(((Humanoid)player).GetInventory());
			Container val = OpenContainer();
			if ((Object)(object)val != (Object)null && Owns((Component)(object)val, owner))
			{
				result.Items += CleanInventory(val.GetInventory());
			}
			CraftingStation currentCraftingStation = player.GetCurrentCraftingStation();
			if ((Object)(object)currentCraftingStation != (Object)null && Owns((Component)(object)currentCraftingStation, owner))
			{
				result.Buildings += CleanObject(((Component)currentCraftingStation).GetComponent<ZNetView>());
			}
			return result;
		}

		public static Result CleanNearby(Vector3 center, float radius, long? owner, bool buildings = true, bool items = true)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			Result result = default(Result);
			Container val = OpenContainer();
			List<Piece> list = new List<Piece>();
			Piece.GetAllPiecesInRadius(center, radius, list);
			foreach (Piece item in list)
			{
				if ((Object)(object)item == (Object)null || !Owns((Component)(object)item, owner))
				{
					continue;
				}
				if (buildings)
				{
					result.Buildings += CleanObject(((Component)item).GetComponent<ZNetView>());
				}
				if (!items)
				{
					continue;
				}
				Container component = ((Component)item).GetComponent<Container>();
				if (!((Object)(object)component == (Object)null) && component.GetInventory() != null && (!((Object)(object)component != (Object)(object)val) || !component.IsInUse()))
				{
					ZNetView component2 = ((Component)component).GetComponent<ZNetView>();
					if (HasCheatedItem(component.GetInventory()) && Claim(component2))
					{
						result.Items += CleanInventory(component.GetInventory());
					}
				}
			}
			if (items && ItemDropInstances?.GetValue(null) is List<ItemDrop> list2)
			{
				float num = radius * radius;
				ItemDrop[] array = list2.ToArray();
				foreach (ItemDrop val2 in array)
				{
					if (!((Object)(object)val2 == (Object)null) && val2.m_itemData != null && val2.m_itemData.m_cheated && (!owner.HasValue || val2.m_itemData.m_crafterID == owner.Value))
					{
						Vector3 val3 = ((Component)val2).transform.position - center;
						if (!(((Vector3)(ref val3)).sqrMagnitude > num) && Claim(((Component)val2).GetComponent<ZNetView>()))
						{
							val2.m_itemData.m_cheated = false;
							ItemDropSave?.Invoke(val2, null);
							result.Items++;
						}
					}
				}
			}
			return result;
		}

		private static bool Owns(Component c, long? owner)
		{
			if (!owner.HasValue)
			{
				return true;
			}
			Piece componentInParent = c.GetComponentInParent<Piece>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				return componentInParent.GetCreator() == owner.Value;
			}
			TombStone componentInParent2 = c.GetComponentInParent<TombStone>();
			if ((Object)(object)componentInParent2 != (Object)null && TombOwner != null)
			{
				return (long)TombOwner.Invoke(componentInParent2, null) == owner.Value;
			}
			return false;
		}

		public static int CleanInventory(Inventory inventory)
		{
			if (inventory == null)
			{
				return 0;
			}
			int num = 0;
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (allItem != null && allItem.m_cheated)
				{
					allItem.m_cheated = false;
					num++;
				}
			}
			if (num > 0)
			{
				InventoryChanged?.Invoke(inventory, null);
			}
			return num;
		}

		private static bool HasCheatedItem(Inventory inventory)
		{
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (allItem != null && allItem.m_cheated)
				{
					return true;
				}
			}
			return false;
		}

		private static int CleanObject(ZNetView nview)
		{
			if ((Object)(object)nview == (Object)null || !nview.IsValid())
			{
				return 0;
			}
			if (!nview.GetZDO().GetBool(ZDOVars.s_cheated, false))
			{
				return 0;
			}
			if (!Claim(nview))
			{
				return 0;
			}
			nview.GetZDO().Set(ZDOVars.s_cheated, false);
			return 1;
		}

		private static bool Claim(ZNetView nview)
		{
			if ((Object)(object)nview == (Object)null || !nview.IsValid())
			{
				return false;
			}
			if (!nview.IsOwner())
			{
				nview.ClaimOwnership();
			}
			return nview.IsOwner();
		}

		private static Container OpenContainer()
		{
			if ((Object)(object)InventoryGui.instance == (Object)null || CurrentContainer == null)
			{
				return null;
			}
			try
			{
				object? value = CurrentContainer.GetValue(InventoryGui.instance);
				return (Container)((value is Container) ? value : null);
			}
			catch (Exception)
			{
				return null;
			}
		}
	}
	internal class CleanerBehaviour : MonoBehaviour
	{
		private const float AutoInterval = 0.5f;

		private float _nextAuto;

		private void Update()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			Network.EnsureRegistered();
			Player localPlayer = Player.m_localPlayer;
			if (!Plugin.Enabled.Value || (Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			try
			{
				KeyboardShortcut value = Plugin.PlayerMenuKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					PlayerWindow.Toggle();
					return;
				}
				value = Plugin.AutoCleanToggleKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					Plugin.AutoClean.Value = !Plugin.AutoClean.Value;
					Show(localPlayer, Lang.T(Plugin.AutoClean.Value ? "auto_on" : "auto_off"));
					if (Plugin.AutoClean.Value)
					{
						CleanAuto(localPlayer);
					}
					return;
				}
				value = Plugin.CleanKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					CleanNow(localPlayer);
				}
				else if (Plugin.AutoClean.Value && Time.unscaledTime >= _nextAuto)
				{
					_nextAuto = Time.unscaledTime + 0.5f;
					CleanAuto(localPlayer);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Cleaning failed: " + ex));
				_nextAuto = Time.unscaledTime + 5f;
			}
		}

		private static void CleanNow(Player player)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			long? owner = Ownership.Filter(player);
			Cleaner.Result result = Cleaner.CleanAroundPlayer(player, owner);
			if (Plugin.CleanNearby.Value)
			{
				Cleaner.Result result2 = Cleaner.CleanNearby(((Component)player).transform.position, Plugin.NearbyRadius.Value, owner);
				result.Items += result2.Items;
				result.Buildings += result2.Buildings;
			}
			Plugin.Log.LogInfo((object)$"Cleaned cheat tags: {result.Items} items, {result.Buildings} buildings");
			Show(player, result.Any ? Lang.T("cleaned", result.Items, result.Buildings) : Lang.T("nothing"));
		}

		internal static void CleanAuto(Player player)
		{
			Cleaner.Result result = Cleaner.CleanAroundPlayer(player, Ownership.Filter(player));
			if (result.Any)
			{
				Plugin.Log.LogInfo((object)$"Auto-cleaned cheat tags: {result.Items} items, {result.Buildings} buildings");
			}
		}

		internal static void Show(Player player, string text)
		{
			if (Plugin.ShowMessages.Value)
			{
				((Character)player).Message((MessageType)2, text, 0, (Sprite)null, false);
			}
		}
	}
	[HarmonyPatch]
	internal static class DoCraftingPatch
	{
		private static MethodBase Target => AccessTools.Method(typeof(InventoryGui), "DoCrafting", (Type[])null, (Type[])null);

		private static bool Prepare()
		{
			if (Target != null)
			{
				return true;
			}
			Plugin.Log.LogWarning((object)"InventoryGui.DoCrafting not found - cleaning right before crafting is disabled (auto clean still works).");
			return false;
		}

		private static MethodBase TargetMethod()
		{
			return Target;
		}

		private static void Prefix()
		{
			Player localPlayer = Player.m_localPlayer;
			if (!Plugin.Enabled.Value || !Plugin.AutoClean.Value || (Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			try
			{
				CleanerBehaviour.CleanAuto(localPlayer);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Cleaning before crafting failed: " + ex.Message));
			}
		}
	}
	internal static class Lang
	{
		private static readonly Dictionary<string, string[]> Table = new Dictionary<string, string[]>
		{
			["cleaned"] = new string[2] { "Cheat tags removed: {0} items, {1} buildings", "치트 표시 제거: 아이템 {0}개, 건물 {1}개" },
			["nothing"] = new string[2] { "No cheat tags found", "치트 표시가 붙은 것이 없어요" },
			["auto_on"] = new string[2] { "Auto cheat-tag removal: ON", "치트 표시 자동 제거: 켜짐" },
			["auto_off"] = new string[2] { "Auto cheat-tag removal: OFF", "치트 표시 자동 제거: 꺼짐" },
			["cleaned_by"] = new string[2] { "{0} removed your cheat tags: {1} items, {2} buildings", "{0} 님이 내 치트 표시를 지웠어요: 아이템 {1}개, 건물 {2}개" },
			["remote_done"] = new string[2] { "{0}: cheat tags removed - {1} items, {2} buildings", "{0}: 치트 표시 제거 - 아이템 {1}개, 건물 {2}개" },
			["remote_denied"] = new string[2] { "{0} does not allow others to clean their items", "{0} 님은 다른 사람의 정리를 허용하지 않았어요" },
			["remote_not_ready"] = new string[2] { "{0} is not in the world right now", "{0} 님이 지금 세계에 없어요" },
			["window_title"] = new string[2] { "Cheat Tag Cleaner - Players", "치트 표시 정리 - 플레이어" },
			["window_help"] = new string[2] { "Pick a player and what to clean. Only cheat tags are removed - items stay as they are.", "플레이어와 정리할 대상을 고르세요. 치트 표시만 지우고 아이템은 그대로예요." },
			["players"] = new string[2] { "Players on the server", "접속한 플레이어" },
			["badge_me"] = new string[2] { "(me)", "(나)" },
			["badge_mod"] = new string[2] { "· has the mod", "· 모드 있음" },
			["badge_no_mod"] = new string[2] { "· no mod (buildings only)", "· 모드 없음 (건물만)" },
			["badge_denied"] = new string[2] { "· does not allow", "· 허용 안 함" },
			["what"] = new string[2] { "What to clean", "정리할 대상" },
			["what_inventory"] = new string[2] { "Inventory & equipped items", "인벤토리·장착 아이템" },
			["what_buildings"] = new string[2] { "Buildings & crafting stations they built", "그 사람이 지은 건물·제작대" },
			["what_items"] = new string[2] { "Items in their chests & dropped items they crafted", "그 사람 상자 속 아이템·그 사람이 만든 바닥 아이템" },
			["range"] = new string[2] { "Buildings and items: within {0} m of you (and of them, if they have the mod)", "건물·아이템: 내 주변 {0}m (상대도 모드가 있으면 상대 주변도)" },
			["only_mine"] = new string[2] { "F8 / auto clean: only my things (multiplayer)", "F8·자동 제거는 내 것만 (멀티)" },
			["clean_button"] = new string[2] { "Clean selected player", "선택한 플레이어 정리" },
			["close_button"] = new string[2] { "Close", "닫기" },
			["pick_something"] = new string[2] { "Pick at least one thing to clean", "정리할 대상을 하나 이상 고르세요" },
			["near_me"] = new string[2] { "Near you: {0} items, {1} buildings", "내 주변: 아이템 {0}개, 건물 {1}개" },
			["request_sent"] = new string[2] { "Sent to {0} - waiting for the result...", "{0} 님에게 요청했어요 - 결과를 기다리는 중..." },
			["no_mod_inventory"] = new string[2] { "{0} does not have the mod, so their inventory can't be cleaned", "{0} 님은 모드가 없어서 인벤토리는 정리할 수 없어요" },
			["unknown_owner"] = new string[2] { "Can't tell which buildings are {0}'s - get close to them once", "{0} 님의 건물을 알 수 없어요 - 그 사람 근처에 한 번 가 주세요" }
		};

		private static bool IsKorean
		{
			get
			{
				switch (Plugin.Language.Value)
				{
				case UiLanguage.Korean:
					return true;
				case UiLanguage.English:
					return false;
				default:
					if (Localization.instance == null)
					{
						return false;
					}
					return Traverse.Create((object)Localization.instance).Method("GetSelectedLanguage", Array.Empty<object>()).GetValue() as string == "Korean";
				}
			}
		}

		public static string T(string key, params object[] args)
		{
			if (!Table.TryGetValue(key, out var value))
			{
				return key;
			}
			string text = value[IsKorean ? 1u : 0u];
			if (args.Length != 0)
			{
				return string.Format(text, args);
			}
			return text;
		}
	}
	internal static class Ownership
	{
		public static bool IsMultiplayer
		{
			get
			{
				if ((Object)(object)ZNet.instance != (Object)null)
				{
					if (ZNet.instance.IsServer())
					{
						return ZNet.instance.GetPeers().Count > 0;
					}
					return true;
				}
				return false;
			}
		}

		public static long? Filter(Player player)
		{
			if (!Plugin.OnlyMine.Value || !IsMultiplayer)
			{
				return null;
			}
			return player.GetPlayerID();
		}
	}
	internal static class Network
	{
		internal enum Status
		{
			Ok,
			Denied,
			NotReady
		}

		internal class Peer
		{
			public long PlayerId;

			public bool Allows;

			public float SeenAt;
		}

		public const int Inventory = 1;

		public const int Buildings = 2;

		public const int Items = 4;

		private const string RpcPing = "CheatTagCleaner_Ping";

		private const string RpcPong = "CheatTagCleaner_Pong";

		private const string RpcClean = "CheatTagCleaner_Clean";

		private const string RpcResult = "CheatTagCleaner_Result";

		private const int Protocol = 1;

		public static readonly Dictionary<long, Peer> Modded = new Dictionary<long, Peer>();

		private static ZRoutedRpc _registered;

		public static long MySession => ZDOMan.GetSessionID();

		public static void EnsureRegistered()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != null && instance != _registered)
			{
				_registered = instance;
				Modded.Clear();
				instance.Register<ZPackage>("CheatTagCleaner_Ping", (Action<long, ZPackage>)OnPing);
				instance.Register<ZPackage>("CheatTagCleaner_Pong", (Action<long, ZPackage>)OnPong);
				instance.Register<ZPackage>("CheatTagCleaner_Clean", (Action<long, ZPackage>)OnClean);
				instance.Register<ZPackage>("CheatTagCleaner_Result", (Action<long, ZPackage>)OnResult);
			}
		}

		public static void Ping()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			if (ZRoutedRpc.instance != null)
			{
				ZPackage val = new ZPackage();
				val.Write(1);
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "CheatTagCleaner_Ping", new object[1] { val });
			}
		}

		public static void RequestClean(long session, int flags, float radius)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			if (ZRoutedRpc.instance != null)
			{
				ZPackage val = new ZPackage();
				val.Write(1);
				val.Write(flags);
				val.Write(radius);
				val.Write(((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerName() : "?");
				ZRoutedRpc.instance.InvokeRoutedRPC(session, "CheatTagCleaner_Clean", new object[1] { val });
			}
		}

		private static void OnPing(long sender, ZPackage pkg)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			if (sender != MySession && !((Object)(object)Player.m_localPlayer == (Object)null))
			{
				ZPackage val = new ZPackage();
				val.Write(1);
				val.Write(Player.m_localPlayer.GetPlayerID());
				val.Write(Plugin.Enabled.Value && Plugin.AllowRemoteClean.Value);
				ZRoutedRpc.instance.InvokeRoutedRPC(sender, "CheatTagCleaner_Pong", new object[1] { val });
			}
		}

		private static void OnPong(long sender, ZPackage pkg)
		{
			try
			{
				pkg.ReadInt();
				Modded[sender] = new Peer
				{
					PlayerId = pkg.ReadLong(),
					Allows = pkg.ReadBool(),
					SeenAt = Time.unscaledTime
				};
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Bad pong: " + ex.Message));
			}
		}

		private static void OnClean(long sender, ZPackage pkg)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			int num;
			float radius;
			string text;
			try
			{
				pkg.ReadInt();
				num = pkg.ReadInt();
				radius = Mathf.Clamp(pkg.ReadSingle(), 5f, 100f);
				text = pkg.ReadString();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Bad clean request: " + ex.Message));
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			ZPackage val = new ZPackage();
			if ((Object)(object)localPlayer == (Object)null)
			{
				WriteResult(val, Status.NotReady, default(Cleaner.Result));
			}
			else if (!Plugin.Enabled.Value || !Plugin.AllowRemoteClean.Value)
			{
				WriteResult(val, Status.Denied, default(Cleaner.Result));
				Plugin.Log.LogInfo((object)("Refused a cheat-tag clean request from " + text + " (AllowRemoteClean is off)"));
			}
			else
			{
				Cleaner.Result r = default(Cleaner.Result);
				if ((num & 1) != 0)
				{
					r.Items += Cleaner.CleanInventory(((Humanoid)localPlayer).GetInventory());
				}
				if ((num & 6) != 0)
				{
					Cleaner.Result result = Cleaner.CleanNearby(((Component)localPlayer).transform.position, radius, localPlayer.GetPlayerID(), (num & 2) != 0, (num & 4) != 0);
					r.Items += result.Items;
					r.Buildings += result.Buildings;
				}
				WriteResult(val, Status.Ok, r);
				Plugin.Log.LogInfo((object)$"{text} cleaned my cheat tags: {r.Items} items, {r.Buildings} buildings");
				if (r.Any)
				{
					CleanerBehaviour.Show(localPlayer, Lang.T("cleaned_by", text, r.Items, r.Buildings));
				}
			}
			ZRoutedRpc.instance.InvokeRoutedRPC(sender, "CheatTagCleaner_Result", new object[1] { val });
		}

		private static void WriteResult(ZPackage pkg, Status status, Cleaner.Result r)
		{
			pkg.Write(1);
			pkg.Write((int)status);
			pkg.Write(r.Items);
			pkg.Write(r.Buildings);
			pkg.Write(((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerName() : "?");
		}

		private static void OnResult(long sender, ZPackage pkg)
		{
			try
			{
				pkg.ReadInt();
				Status status = (Status)pkg.ReadInt();
				int num = pkg.ReadInt();
				int num2 = pkg.ReadInt();
				string text = pkg.ReadString();
				string text2 = status switch
				{
					Status.NotReady => Lang.T("remote_not_ready", text), 
					Status.Denied => Lang.T("remote_denied", text), 
					_ => Lang.T("remote_done", text, num, num2), 
				};
				PlayerWindow.SetStatus(text2);
				if ((Object)(object)Player.m_localPlayer != (Object)null)
				{
					CleanerBehaviour.Show(Player.m_localPlayer, text2);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Bad clean result: " + ex.Message));
			}
		}
	}
	internal class PlayerWindow : MonoBehaviour
	{
		private struct Row
		{
			public long Session;

			public string Name;

			public ZDOID Character;
		}

		private const float BaseWidth = 520f;

		private const float BaseHeight = 560f;

		private const float PingInterval = 4f;

		private static PlayerWindow _instance;

		private static string _status = "";

		private bool _open;

		private Rect _rect;

		private Vector2 _scroll;

		private float _scale;

		private float _nextPing;

		private long _selected;

		private bool _inventory = true;

		private bool _buildings = true;

		private bool _items = true;

		private readonly List<Row> _rows = new List<Row>();

		private readonly Dictionary<long, long> _knownIds = new Dictionary<long, long>();

		private GUIStyle _window;

		private GUIStyle _title;

		private GUIStyle _label;

		private GUIStyle _dim;

		private GUIStyle _row;

		private GUIStyle _rowOn;

		private GUIStyle _toggle;

		private GUIStyle _button;

		private GUIStyle _status2;

		private Texture2D _bg;

		private Texture2D _rowBg;

		private Texture2D _rowOnBg;

		private Texture2D _buttonBg;

		private Texture2D _buttonHover;

		public static bool IsOpen
		{
			get
			{
				if ((Object)(object)_instance != (Object)null)
				{
					return _instance._open;
				}
				return false;
			}
		}

		public static void Toggle()
		{
			if (!((Object)(object)_instance == (Object)null))
			{
				if (_instance._open)
				{
					_instance.Close();
				}
				else
				{
					_instance.Open();
				}
			}
		}

		public static void SetStatus(string text)
		{
			_status = text;
		}

		private void Awake()
		{
			_instance = this;
		}

		private void Open()
		{
			if (!((Object)(object)ZNet.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null))
			{
				_open = true;
				_status = "";
				_nextPing = 0f;
				_selected = Network.MySession;
				_scale = 0f;
			}
		}

		private void Close()
		{
			_open = false;
		}

		private void Update()
		{
			if (_open)
			{
				if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null)
				{
					Close();
				}
				else if (Time.unscaledTime >= _nextPing)
				{
					_nextPing = Time.unscaledTime + 4f;
					Network.Ping();
					RefreshPlayers();
				}
			}
		}

		private void RefreshPlayers()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			_rows.Clear();
			ZDOID val;
			foreach (PlayerInfo player in ZNet.instance.GetPlayerList())
			{
				List<Row> rows = _rows;
				Row item = default(Row);
				val = player.m_characterID;
				item.Session = ((ZDOID)(ref val)).UserID;
				item.Name = player.m_name;
				item.Character = player.m_characterID;
				rows.Add(item);
			}
			if (_rows.All((Row r) => r.Session != Network.MySession))
			{
				_rows.Insert(0, new Row
				{
					Session = Network.MySession,
					Name = Player.m_localPlayer.GetPlayerName(),
					Character = ((Character)Player.m_localPlayer).GetZDOID()
				});
			}
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				if ((Object)(object)allPlayer != (Object)null)
				{
					val = ((Character)allPlayer).GetZDOID();
					if (((ZDOID)(ref val)).UserID != 0L)
					{
						Dictionary<long, long> knownIds = _knownIds;
						val = ((Character)allPlayer).GetZDOID();
						knownIds[((ZDOID)(ref val)).UserID] = allPlayer.GetPlayerID();
					}
				}
			}
			if (_rows.All((Row r) => r.Session != _selected))
			{
				_selected = Network.MySession;
			}
		}

		private long? PlayerIdOf(long session)
		{
			if (session == Network.MySession)
			{
				return Player.m_localPlayer.GetPlayerID();
			}
			if (Network.Modded.TryGetValue(session, out var value))
			{
				return value.PlayerId;
			}
			if (!_knownIds.TryGetValue(session, out var value2))
			{
				return null;
			}
			return value2;
		}

		private void CleanSelected()
		{
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			Row row = _rows.FirstOrDefault((Row r) => r.Session == _selected);
			if ((Object)(object)localPlayer == (Object)null || row.Session == 0L)
			{
				return;
			}
			if (!_inventory && !_buildings && !_items)
			{
				_status = Lang.T("pick_something");
				return;
			}
			float value = Plugin.NearbyRadius.Value;
			bool num = row.Session == Network.MySession;
			long? owner = PlayerIdOf(row.Session);
			Cleaner.Result result = default(Cleaner.Result);
			if (num && _inventory)
			{
				result.Items += Cleaner.CleanInventory(((Humanoid)localPlayer).GetInventory());
			}
			if ((_buildings || _items) && owner.HasValue)
			{
				Cleaner.Result result2 = Cleaner.CleanNearby(((Component)localPlayer).transform.position, value, owner, _buildings, _items);
				result.Items += result2.Items;
				result.Buildings += result2.Buildings;
			}
			if (num)
			{
				_status = (result.Any ? Lang.T("cleaned", result.Items, result.Buildings) : Lang.T("nothing"));
				return;
			}
			List<string> list = new List<string>();
			if ((_buildings || _items) && owner.HasValue)
			{
				list.Add(Lang.T("near_me", result.Items, result.Buildings));
			}
			Network.Peer value2;
			bool flag = Network.Modded.TryGetValue(row.Session, out value2);
			if (flag && value2.Allows)
			{
				int flags = (int)((_inventory ? 1u : 0u) | (uint)(_buildings ? 2 : 0)) | (_items ? 4 : 0);
				Network.RequestClean(row.Session, flags, value);
				list.Add(Lang.T("request_sent", row.Name));
			}
			else if (flag)
			{
				list.Add(Lang.T("remote_denied", row.Name));
			}
			else
			{
				if (_inventory)
				{
					list.Add(Lang.T("no_mod_inventory", row.Name));
				}
				if ((_buildings || _items) && !owner.HasValue)
				{
					list.Add(Lang.T("unknown_owner", row.Name));
				}
			}
			_status = string.Join("\n", list);
			Plugin.Log.LogInfo((object)$"Cleaned {row.Name}'s cheat tags near me: {result.Items} items, {result.Buildings} buildings");
		}

		private void OnGUI()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			//IL_006c: 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_008d: Expected O, but got Unknown
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			if (!_open)
			{
				return;
			}
			Event current = Event.current;
			if ((int)current.type == 4 && (int)current.keyCode == 27)
			{
				Close();
				current.Use();
				return;
			}
			float num = Mathf.Max(1f, (float)Screen.height / 1080f);
			if (!Mathf.Approximately(num, _scale))
			{
				BuildStyles(num);
			}
			GUI.depth = -1000;
			_rect = GUI.Window(1129595681, _rect, new WindowFunction(DrawWindow), GUIContent.none, _window);
		}

		private void DrawWindow(int id)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			float scale = _scale;
			GUILayout.Label(Lang.T("window_title"), _title, Array.Empty<GUILayoutOption>());
			GUILayout.Label(Lang.T("window_help"), _dim, Array.Empty<GUILayoutOption>());
			GUILayout.Space(8f * scale);
			GUILayout.Label(Lang.T("players"), _label, Array.Empty<GUILayoutOption>());
			_scroll = GUILayout.BeginScrollView(_scroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(190f * scale) });
			foreach (Row row in _rows)
			{
				bool flag = row.Session == _selected;
				if (GUILayout.Button(row.Name + "   " + Badge(row.Session), flag ? _rowOn : _row, Array.Empty<GUILayoutOption>()))
				{
					_selected = row.Session;
				}
			}
			GUILayout.EndScrollView();
			GUILayout.Space(8f * scale);
			GUILayout.Label(Lang.T("what"), _label, Array.Empty<GUILayoutOption>());
			_inventory = GUILayout.Toggle(_inventory, " " + Lang.T("what_inventory"), _toggle, Array.Empty<GUILayoutOption>());
			_buildings = GUILayout.Toggle(_buildings, " " + Lang.T("what_buildings"), _toggle, Array.Empty<GUILayoutOption>());
			_items = GUILayout.Toggle(_items, " " + Lang.T("what_items"), _toggle, Array.Empty<GUILayoutOption>());
			GUILayout.Label(Lang.T("range", Mathf.RoundToInt(Plugin.NearbyRadius.Value)), _dim, Array.Empty<GUILayoutOption>());
			GUILayout.Space(6f * scale);
			bool flag2 = GUILayout.Toggle(Plugin.OnlyMine.Value, " " + Lang.T("only_mine"), _toggle, Array.Empty<GUILayoutOption>());
			if (flag2 != Plugin.OnlyMine.Value)
			{
				Plugin.OnlyMine.Value = flag2;
			}
			GUILayout.FlexibleSpace();
			if (!string.IsNullOrEmpty(_status))
			{
				GUILayout.Label(_status, _status2, Array.Empty<GUILayoutOption>());
			}
			GUILayout.Space(6f * scale);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button(Lang.T("clean_button"), _button, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f * scale) }))
			{
				CleanSelected();
			}
			GUILayout.Space(8f * scale);
			if (GUILayout.Button(Lang.T("close_button"), _button, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(120f * scale),
				GUILayout.Height(40f * scale)
			}))
			{
				Close();
			}
			GUILayout.EndHorizontal();
			GUI.DragWindow(new Rect(0f, 0f, 10000f, 40f * scale));
		}

		private string Badge(long session)
		{
			if (session == Network.MySession)
			{
				return Lang.T("badge_me");
			}
			if (!Network.Modded.TryGetValue(session, out var value))
			{
				return Lang.T("badge_no_mod");
			}
			if (!value.Allows)
			{
				return Lang.T("badge_denied");
			}
			return Lang.T("badge_mod");
		}

		private void BuildStyles(float scale)
		{
			//IL_0033: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Expected O, but got Unknown
			//IL_0176: Expected O, but got Unknown
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: 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_01d6: Expected O, but got Unknown
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: 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_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Expected O, but got Unknown
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Expected O, but got Unknown
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Expected O, but got Unknown
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Expected O, but got Unknown
			//IL_0315: Expected O, but got Unknown
			//IL_0378: Unknown result type (might be due to invalid IL or missing references)
			//IL_0379: Unknown result type (might be due to invalid IL or missing references)
			//IL_037a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: 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_038b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0399: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a3: Expected O, but got Unknown
			//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0406: Expected O, but got Unknown
			//IL_0432: Unknown result type (might be due to invalid IL or missing references)
			//IL_0433: Unknown result type (might be due to invalid IL or missing references)
			//IL_0434: Unknown result type (might be due to invalid IL or missing references)
			//IL_043b: Unknown result type (might be due to invalid IL or missing references)
			//IL_043d: Unknown result type (might be due to invalid IL or missing references)
			//IL_043e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0445: Unknown result type (might be due to invalid IL or missing references)
			//IL_0447: Unknown result type (might be due to invalid IL or missing references)
			//IL_0448: Unknown result type (might be due to invalid IL or missing references)
			//IL_044f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0461: Unknown result type (might be due to invalid IL or missing references)
			//IL_0466: Unknown result type (might be due to invalid IL or missing references)
			//IL_0478: Unknown result type (might be due to invalid IL or missing references)
			//IL_0484: Expected O, but got Unknown
			//IL_04e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fa: 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)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			_scale = scale;
			_bg = _bg ?? Solid(new Color(0.11f, 0.085f, 0.065f, 0.97f));
			_rowBg = _rowBg ?? Solid(new Color(1f, 1f, 1f, 0.04f));
			_rowOnBg = _rowOnBg ?? Solid(new Color(1f, 0.72f, 0.33f, 0.28f));
			_buttonBg = _buttonBg ?? Solid(new Color(0.36f, 0.25f, 0.14f, 1f));
			_buttonHover = _buttonHover ?? Solid(new Color(0.5f, 0.35f, 0.18f, 1f));
			Color val = default(Color);
			((Color)(ref val))..ctor(1f, 0.8f, 0.4f);
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(0.92f, 0.87f, 0.79f);
			_window = new GUIStyle(GUI.skin.window)
			{
				padding = new RectOffset(F(20f), F(20f), F(16f), F(18f))
			};
			GUIStyleState normal = _window.normal;
			Texture2D background = (_window.onNormal.background = _bg);
			normal.background = background;
			_title = new GUIStyle(GUI.skin.label)
			{
				fontSize = F(22f),
				fontStyle = (FontStyle)1,
				alignment = (TextAnchor)4
			};
			_title.normal.textColor = val;
			_label = new GUIStyle(GUI.skin.label)
			{
				fontSize = F(17f),
				fontStyle = (FontStyle)1
			};
			_label.normal.textColor = val;
			_dim = new GUIStyle(GUI.skin.label)
			{
				fontSize = F(14f),
				wordWrap = true
			};
			_dim.normal.textColor = new Color(0.7f, 0.65f, 0.57f);
			_status2 = new GUIStyle(_dim)
			{
				fontSize = F(15f)
			};
			_status2.normal.textColor = val2;
			_row = new GUIStyle(GUI.skin.button)
			{
				fontSize = F(16f),
				alignment = (TextAnchor)3,
				padding = new RectOffset(F(10f), F(10f), F(6f), F(6f))
			};
			_row.normal.background = _rowBg;
			_row.hover.background = _rowOnBg;
			_row.active.background = _rowOnBg;
			GUIStyleState normal2 = _row.normal;
			GUIStyleState hover = _row.hover;
			Color val3 = (_row.active.textColor = val2);
			Color textColor = (hover.textColor = val3);
			normal2.textColor = textColor;
			_rowOn = new GUIStyle(_row);
			_rowOn.normal.background = _rowOnBg;
			GUIStyleState normal3 = _rowOn.normal;
			textColor = (_rowOn.hover.textColor = val);
			normal3.textColor = textColor;
			_toggle = new GUIStyle(GUI.skin.toggle)
			{
				fontSize = F(16f)
			};
			GUIStyleState normal4 = _toggle.normal;
			GUIStyleState onNormal = _toggle.onNormal;
			GUIStyleState hover2 = _toggle.hover;
			Color val7 = (_toggle.onHover.textColor = val2);
			val3 = (hover2.textColor = val7);
			textColor = (onNormal.textColor = val3);
			normal4.textColor = textColor;
			_button = new GUIStyle(GUI.skin.button)
			{
				fontSize = F(17f),
				fontStyle = (FontStyle)1
			};
			_button.normal.background = _buttonBg;
			_button.hover.background = _buttonHover;
			_button.active.background = _buttonHover;
			GUIStyleState normal5 = _button.normal;
			GUIStyleState hover3 = _button.hover;
			val3 = (_button.active.textColor = val);
			textColor = (hover3.textColor = val3);
			normal5.textColor = textColor;
			float num = 520f * scale;
			float num2 = 560f * scale;
			_rect = new Rect(((float)Screen.width - num) / 2f, ((float)Screen.height - num2) / 2f, num, num2);
			int F(float size)
			{
				return Mathf.RoundToInt(size * scale);
			}
		}

		private static Texture2D Solid(Color c)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			Texture2D val = new Texture2D(1, 1)
			{
				hideFlags = (HideFlags)61
			};
			val.SetPixel(0, 0, c);
			val.Apply();
			return val;
		}
	}
	[HarmonyPatch]
	internal static class WindowBlockTakeInputPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return (from m in ((IEnumerable<Type>)new Type[2]
				{
					typeof(PlayerController),
					typeof(Player)
				}).SelectMany((Func<Type, IEnumerable<MethodInfo>>)AccessTools.GetDeclaredMethods)
				where m.Name == "TakeInput" && m.ReturnType == typeof(bool)
				select m).Cast<MethodBase>();
		}

		private static bool Prepare()
		{
			return TargetMethods().Any();
		}

		private static void Postfix(ref bool __result)
		{
			if (PlayerWindow.IsOpen)
			{
				__result = false;
			}
		}
	}
	[HarmonyPatch]
	internal static class WindowBlockGuiUpdatePatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return (from t in new Type[3]
				{
					typeof(Menu),
					typeof(InventoryGui),
					typeof(Minimap)
				}
				select AccessTools.DeclaredMethod(t, "Update", (Type[])null, (Type[])null) into m
				where m != null
				select m).Cast<MethodBase>();
		}

		private static bool Prepare()
		{
			return TargetMethods().Any();
		}

		private static bool Prefix()
		{
			return !PlayerWindow.IsOpen;
		}
	}
	[HarmonyPatch]
	internal static class WindowMouseCapturePatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return (from m in AccessTools.GetDeclaredMethods(typeof(GameCamera))
				where m.Name == "UpdateMouseCapture"
				select m).Cast<MethodBase>();
		}

		private static bool Prepare()
		{
			return TargetMethods().Any();
		}

		private static void Postfix()
		{
			if (PlayerWindow.IsOpen)
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
		}
	}
	internal enum UiLanguage
	{
		Auto,
		English,
		Korean
	}
	[BepInPlugin("lazly.valheim.cheattagcleaner", "CheatTagCleaner", "1.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string ModGuid = "lazly.valheim.cheattagcleaner";

		public const string ModName = "CheatTagCleaner";

		public const string ModVersion = "1.1.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<KeyboardShortcut> CleanKey;

		internal static ConfigEntry<bool> AutoClean;

		internal static ConfigEntry<KeyboardShortcut> AutoCleanToggleKey;

		internal static ConfigEntry<bool> CleanNearby;

		internal static ConfigEntry<float> NearbyRadius;

		internal static ConfigEntry<bool> OnlyMine;

		internal static ConfigEntry<KeyboardShortcut> PlayerMenuKey;

		internal static ConfigEntry<bool> AllowRemoteClean;

		internal static ConfigEntry<bool> ShowMessages;

		internal static ConfigEntry<UiLanguage> Language;

		private void Awake()
		{
			//IL_0045: 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_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Expected O, but got Unknown
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Expected O, but got Unknown
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch. false = the mod does nothing.");
			CleanKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "CleanKey", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Remove cheat tags now: your inventory, the open chest, the crafting station you use and (if CleanNearby) buildings, chests and dropped items nearby.");
			AutoClean = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AutoClean", false, "Keep removing cheat tags automatically from your inventory, the open chest and the crafting station you use, so new items are never tagged.");
			AutoCleanToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "AutoCleanToggleKey", new KeyboardShortcut((KeyCode)289, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Turn AutoClean on / off in game.");
			CleanNearby = ((BaseUnityPlugin)this).Config.Bind<bool>("Scope", "CleanNearby", true, "CleanKey also cleans buildings (crafting stations etc.), chests and dropped items around you.");
			NearbyRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Scope", "NearbyRadius", 30f, new ConfigDescription("Radius in meters for CleanNearby.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 100f), Array.Empty<object>()));
			OnlyMine = ((BaseUnityPlugin)this).Config.Bind<bool>("Scope", "OnlyMine", true, "Multiplayer: CleanKey and AutoClean only touch buildings, chests and crafting stations you built, and dropped items you crafted. Other players' things are cleaned only when you pick them in the player window. (Single player: everything.)");
			PlayerMenuKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Multiplayer", "PlayerMenuKey", new KeyboardShortcut((KeyCode)289, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Open the player window: pick a player and clean their inventory, buildings, chests and dropped items.");
			AllowRemoteClean = ((BaseUnityPlugin)this).Config.Bind<bool>("Multiplayer", "AllowRemoteClean", true, "Let other players with this mod remove cheat tags from YOUR inventory and the things you built (only cheat tags are touched). false = refuse.");
			ShowMessages = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "ShowMessages", true, "Show a message in the middle of the screen after cleaning.");
			Language = ((BaseUnityPlugin)this).Config.Bind<UiLanguage>("UI", "Language", UiLanguage.Auto, "Auto = Korean when the game language is Korean, otherwise English.");
			GameObject val = new GameObject("CheatTagCleaner");
			Object.DontDestroyOnLoad((Object)val);
			val.AddComponent<CleanerBehaviour>();
			val.AddComponent<PlayerWindow>();
			new Harmony("lazly.valheim.cheattagcleaner").PatchAll(typeof(Plugin).Assembly);
			Log.LogInfo((object)"CheatTagCleaner 1.1.0 loaded");
		}
	}
}