Decompiled source of DealManager v1.1.1

CWDealManager.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Localization;
using UnityEngine.Localization.Settings;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("U-FESNOS")]
[assembly: AssemblyProduct("DealManager")]
[assembly: AssemblyTitle("DealManager")]
[assembly: AssemblyCopyright("U-FESNOS")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyVersion("1.1.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CWDealManager
{
	[ContentWarningPlugin("U-FESNOS.DealManager", "1.1.1", true)]
	[BepInPlugin("U-FESNOS.DealManager", "CWDealManager", "1.1.1")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "U-FESNOS.DealManager";

		public const string Name = "CWDealManager";

		public const string Version = "1.1.1";

		internal static Plugin Instance;

		internal static ManualLogSource Log;

		internal static ConfigEntry<Key> PanelKey;

		internal static ConfigEntry<int> MaxConcurrent;

		internal static ConfigEntry<int> MaxAcceptsPerWeek;

		internal static ConfigEntry<float> FeeRate;

		internal static ConfigEntry<int> MinFee;

		internal static ConfigEntry<bool> FreeWithFreeShop;

		internal static ConfigEntry<bool> SoftwareCursor;

		internal static bool PanelOpen;

		private void Awake()
		{
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Lang.Bind(((BaseUnityPlugin)this).Config);
			PanelKey = ((BaseUnityPlugin)this).Config.Bind<Key>("General", "PanelKey", (Key)100, "Key to open / close the quest panel / クエスト管理パネルを開閉するキー");
			MaxConcurrent = ((BaseUnityPlugin)this).Config.Bind<int>("Deals", "MaxConcurrentDeals", 3, "How many quests can be active at once / 同時に受注できるクエストの数");
			MaxAcceptsPerWeek = ((BaseUnityPlugin)this).Config.Bind<int>("Deals", "MaxAcceptsPerWeek", 3, "How many quests can be accepted per week. An accepted offer is replaced by a new one until this limit is reached / 1週間に受注できる数。受注した枠には新しい候補が補充され、この数に達すると候補がなくなる");
			FeeRate = ((BaseUnityPlugin)this).Config.Bind<float>("Delivery", "FeeRate", 0.5f, "Redelivery fee = total shop price of the items x this rate / 再送の送料 = 物資のショップ価格の合計 × この割合");
			MinFee = ((BaseUnityPlugin)this).Config.Bind<int>("Delivery", "MinFee", 20, "Minimum redelivery fee ($) / 再送の送料の最低額");
			FreeWithFreeShop = ((BaseUnityPlugin)this).Config.Bind<bool>("Delivery", "FreeWithFreeShop", true, "Make redelivery free when the FreeShop mod is installed / FreeShop Mod が入っていれば送料を無料にする");
			SoftwareCursor = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "SoftwareCursor", true, "Draw an arrow cursor on the panel (fallback if the system cursor is not visible) / パネル上に矢印カーソルを描画する");
			Harmony val = new Harmony("U-FESNOS.DealManager");
			val.PatchAll(typeof(Patches));
			Log.LogInfo((object)$"CWDealManager loaded. Patched {val.GetPatchedMethods().Count()} methods.");
		}

		private void Start()
		{
			Net.Register();
		}

		private void OnDestroy()
		{
			Net.Unregister();
		}

		internal static void ForceCursor()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if ((int)Cursor.lockState != 0)
			{
				Cursor.lockState = (CursorLockMode)0;
			}
			if (!Cursor.visible)
			{
				Cursor.visible = true;
			}
		}

		private void LateUpdate()
		{
			if (PanelOpen)
			{
				ForceCursor();
			}
		}

		private void Update()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			Keyboard current = Keyboard.current;
			if (current != null)
			{
				if ((int)PanelKey.Value != 0 && ((ButtonControl)current[PanelKey.Value]).wasPressedThisFrame)
				{
					PanelOpen = !PanelOpen && (Object)(object)Player.localPlayer != (Object)null;
				}
				else if (PanelOpen && ((ButtonControl)current[(Key)60]).wasPressedThisFrame)
				{
					PanelOpen = false;
				}
			}
			if (PanelOpen && (Object)(object)Player.localPlayer == (Object)null)
			{
				PanelOpen = false;
			}
			Net.Register();
			Manager.Tick();
		}

		private void OnGUI()
		{
			Ui.Draw();
		}
	}
	internal sealed class Tracked
	{
		public int Id;

		public NetworkDealBase Deal;

		public DEAL_STATE LastState;

		public float NextRedeliverTime;
	}
	internal static class Manager
	{
		internal static readonly List<Tracked> All = new List<Tracked>();

		internal static int AcceptsThisWeek;

		private static int nextId = 1;

		private static bool dirty = true;

		private static float nextBroadcast;

		private static float resyncAt = -1f;

		private static bool? freeShop;

		private static readonly List<DIFFICULTY> AllDifficulties = new List<DIFFICULTY>
		{
			(DIFFICULTY)10,
			(DIFFICULTY)50,
			(DIFFICULTY)100,
			(DIFFICULTY)150,
			(DIFFICULTY)200
		};

		internal static bool IsHost => PhotonNetwork.IsMasterClient;

		internal static NetworkDealBase? Active => NetworkDealBoss.activeDeal;

		internal static bool FreeShopInstalled
		{
			get
			{
				if (!freeShop.HasValue)
				{
					freeShop = Chainloader.PluginInfos.ContainsKey("FreeShop") || Chainloader.PluginInfos.Values.Any((PluginInfo p) => p.Metadata.Name.Replace(" ", string.Empty).Equals("FreeShop", StringComparison.OrdinalIgnoreCase));
				}
				return freeShop.Value;
			}
		}

		internal static bool DeliveryIsFree
		{
			get
			{
				if (FreeShopInstalled)
				{
					return Plugin.FreeWithFreeShop.Value;
				}
				return false;
			}
		}

		internal static void MarkDirty()
		{
			dirty = true;
		}

		internal static Tracked? Find(int id)
		{
			return All.FirstOrDefault((Tracked t) => t.Id == id);
		}

		internal static Tracked? FindDeal(NetworkDealBase? deal)
		{
			if (deal != null)
			{
				return All.FirstOrDefault((Tracked t) => t.Deal == deal);
			}
			return null;
		}

		internal static Tracked Track(NetworkDealBase deal)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			Tracked tracked = FindDeal(deal);
			if (tracked != null)
			{
				return tracked;
			}
			tracked = new Tracked
			{
				Id = nextId++,
				Deal = deal,
				LastState = deal.State
			};
			All.Add(tracked);
			dirty = true;
			return tracked;
		}

		internal static void Clear()
		{
			All.Clear();
			AcceptsThisWeek = 0;
			dirty = true;
		}

		internal static void Tick()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Invalid comparison between Unknown and I4
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Invalid comparison between Unknown and I4
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.InRoom || !IsHost)
			{
				return;
			}
			NetworkDealBase active = Active;
			if (active != null)
			{
				Track(active);
			}
			else if (All.Count > 0 && (Object)(object)NetworkDealBoss.me != (Object)null)
			{
				FocusNext();
			}
			foreach (Tracked item in All)
			{
				DEAL_STATE state = item.Deal.State;
				if (state == item.LastState)
				{
					continue;
				}
				item.LastState = state;
				dirty = true;
				if (item.Deal != Active)
				{
					if ((int)state == 3)
					{
						Ui.Toast(Msg.Of(MsgId.DealSucceeded, Msgs.DealArg(item.Deal), ((object)Plugin.PanelKey.Value/*cast due to .constrained prefix*/).ToString()));
					}
					else if ((int)state == 2)
					{
						Ui.Toast(Msg.Of(MsgId.DealFailed, Msgs.DealArg(item.Deal)));
					}
				}
			}
			if (resyncAt > 0f && Time.unscaledTime >= resyncAt)
			{
				resyncAt = -1f;
				if ((Object)(object)NetworkDealBoss.me != (Object)null && Active != null)
				{
					NetworkDealBoss.me.HardSyncDeal();
				}
			}
			if ((dirty && Time.unscaledTime >= nextBroadcast) || Time.unscaledTime >= nextBroadcast + 5f)
			{
				dirty = false;
				nextBroadcast = Time.unscaledTime + 0.5f;
				Net.BroadcastState();
			}
		}

		internal static IEnumerable<NetworkDealBase> Background()
		{
			NetworkDealBase active = Active;
			return (from t in All
				where t.Deal != active
				select t.Deal).ToList();
		}

		internal static void UpdateBackground()
		{
			foreach (NetworkDealBase item in Background())
			{
				try
				{
					item.Update();
					if (item.IsDirty)
					{
						item.ClearDirty();
						dirty = true;
					}
				}
				catch (Exception arg)
				{
					Plugin.Log.LogError((object)$"Background deal update failed: {arg}");
				}
			}
		}

		internal static void ForEachBackground(Action<NetworkDealBase> action)
		{
			foreach (NetworkDealBase item in Background())
			{
				try
				{
					action(item);
				}
				catch (Exception arg)
				{
					Plugin.Log.LogError((object)$"Background deal event failed: {arg}");
				}
			}
			dirty = true;
		}

		internal static void Focus(Tracked t)
		{
			if (t.Deal != Active)
			{
				NetworkDealBoss.activeDeal = t.Deal;
				NetworkDealBoss me = NetworkDealBoss.me;
				if (me != null)
				{
					me.HardSyncDeal();
				}
				resyncAt = Time.unscaledTime + 1.5f;
				dirty = true;
			}
		}

		internal static void FocusNext()
		{
			if (Active == null && All.Count != 0 && !((Object)(object)NetworkDealBoss.me == (Object)null))
			{
				Focus(All.FirstOrDefault((Tracked t) => t.Deal.IsSuccess) ?? All[0]);
			}
		}

		internal static Msg Accept(int offerIndex, int expectedDealIndex)
		{
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			RoomStatsHolder roomStats = SurfaceNetworkHandler.RoomStats;
			NetworkDealBase[] array = ((roomStats != null) ? roomStats.NetworkDealsToSelect : null);
			if (roomStats == null || array == null || offerIndex < 0 || offerIndex >= array.Length || array[offerIndex] == null)
			{
				return Msg.Of(MsgId.OfferGone);
			}
			NetworkDealBase offer = array[offerIndex];
			if (expectedDealIndex >= 0 && offer.GetIndex() != expectedDealIndex)
			{
				return Msg.Of(MsgId.OffersChanged);
			}
			if ((Object)(object)NetworkDealBoss.me == (Object)null || (Object)(object)ShopHandler.Instance == (Object)null)
			{
				return Msg.Of(MsgId.AcceptOnlyAtBase);
			}
			if (All.Count >= Math.Max(1, Plugin.MaxConcurrent.Value))
			{
				return Msg.Of(MsgId.MaxConcurrent, Plugin.MaxConcurrent.Value.ToString());
			}
			if (AcceptsThisWeek >= Math.Max(1, Plugin.MaxAcceptsPerWeek.Value))
			{
				return Msg.Of(MsgId.WeekLimit);
			}
			if (Active == null)
			{
				NetworkDealBoss.me.AddDeal(offer);
				return Msg.Of(MsgId.Accepted, Msgs.DealArg(offer));
			}
			NetworkDealBase dealFromIndex = SingletonAsset<NetworkDealDataBase>.Instance.GetDealFromIndex((int)offer.GetIndex());
			DealRewardBase rewardFromIndex = SingletonAsset<DealRewardDatabase>.Instance.GetRewardFromIndex((int)offer.reward.GetIndex());
			dealFromIndex.Init(rewardFromIndex, offer.difficulty);
			Track(dealFromIndex);
			try
			{
				dealFromIndex.SpawnSponsorItem();
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"SpawnSponsorItem failed: {arg}");
			}
			AcceptsThisWeek++;
			UpdateOffersAfterAccept(array, (NetworkDealBase o) => o == offer);
			dirty = true;
			return Msg.Of(MsgId.Accepted, Msgs.DealArg(dealFromIndex));
		}

		internal static Msg Cancel(int id)
		{
			Tracked tracked = Find(id);
			if (tracked == null)
			{
				return Msg.Of(MsgId.NotFound);
			}
			string text = Msgs.DealArg(tracked.Deal);
			if (tracked.Deal == Active)
			{
				if ((Object)(object)NetworkDealBoss.me == (Object)null)
				{
					return Msg.Of(MsgId.OnlyAtBase);
				}
				NetworkDealBoss.me.RemoveDeal(tracked.Deal);
			}
			else
			{
				All.Remove(tracked);
			}
			dirty = true;
			return Msg.Of(tracked.Deal.IsFailed ? MsgId.Dismissed : MsgId.Abandoned, text);
		}

		internal static Msg Claim(int id)
		{
			Tracked tracked = Find(id);
			if (tracked == null)
			{
				return Msg.Of(MsgId.NotFound);
			}
			if (!tracked.Deal.IsSuccess)
			{
				return Msg.Of(MsgId.NotDone);
			}
			if ((Object)(object)NetworkDealBoss.me == (Object)null)
			{
				return Msg.Of(MsgId.ClaimOnlyAtBase);
			}
			Focus(tracked);
			NetworkDealBoss.me.ClaimReward();
			return Msg.Of(MsgId.Claimed, Msgs.DealArg(tracked.Deal));
		}

		internal static Msg Show(int id)
		{
			Tracked tracked = Find(id);
			if (tracked == null)
			{
				return Msg.Of(MsgId.NotFound);
			}
			if ((Object)(object)NetworkDealBoss.me == (Object)null)
			{
				return Msg.Of(MsgId.OnlyAtBase);
			}
			Focus(tracked);
			return Msg.Of(MsgId.Shown, Msgs.DealArg(tracked.Deal));
		}

		internal static Msg Redeliver(int id)
		{
			Tracked tracked = Find(id);
			if (tracked == null)
			{
				return Msg.Of(MsgId.NotFound);
			}
			if (tracked.Deal.IsDone)
			{
				return Msg.Of(MsgId.DoneNoRedeliver);
			}
			List<Item> list = Items(tracked.Deal);
			if (list.Count == 0)
			{
				return Msg.Of(MsgId.NoItems);
			}
			ShopHandler instance = ShopHandler.Instance;
			RoomStatsHolder roomStats = SurfaceNetworkHandler.RoomStats;
			if ((Object)(object)instance == (Object)null || roomStats == null)
			{
				return Msg.Of(MsgId.RedeliverOnlyAtBase);
			}
			if (Time.unscaledTime < tracked.NextRedeliverTime)
			{
				return Msg.Of(MsgId.Wait);
			}
			int num = Fee(list);
			if (num > 0)
			{
				if (!roomStats.CanAfford(num))
				{
					return Msg.Of(MsgId.NotEnoughMoney, num.ToString());
				}
				roomStats.RemoveMoney(num);
			}
			object? value = AccessTools.Field(typeof(ShopHandler), "m_PhotonView").GetValue(instance);
			PhotonView val = (PhotonView)((value is PhotonView) ? value : null);
			if ((Object)(object)val == (Object)null)
			{
				return Msg.Of(MsgId.DroneFailed);
			}
			val.RPC("RPCA_SpawnDrone", (RpcTarget)0, new object[1] { list.Select((Item i) => i.id).ToArray() });
			tracked.NextRedeliverTime = Time.unscaledTime + 5f;
			dirty = true;
			if (num <= 0)
			{
				return Msg.Of(MsgId.RedeliveredFree, Msgs.DealArg(tracked.Deal));
			}
			return Msg.Of(MsgId.Redelivered, Msgs.DealArg(tracked.Deal), num.ToString());
		}

		internal static List<Item> Items(NetworkDealBase deal)
		{
			List<Item> list = new List<Item>();
			List<string> list2 = null;
			try
			{
				list2 = deal.PersistentIdOfItem;
			}
			catch
			{
			}
			if (list2 == null)
			{
				return list;
			}
			foreach (string item in list2)
			{
				if (!string.IsNullOrEmpty(item))
				{
					Item val = null;
					if (ItemDatabase.TryGetItemFromPersistentID(new Guid(item), ref val) && (Object)(object)val != (Object)null)
					{
						list.Add(val);
					}
				}
			}
			return list;
		}

		internal static int Fee(List<Item> items)
		{
			if (DeliveryIsFree)
			{
				return 0;
			}
			int num = items.Sum((Item i) => Math.Max(0, i.price));
			return Math.Max(Plugin.MinFee.Value, Mathf.CeilToInt((float)num * Plugin.FeeRate.Value));
		}

		internal static int FeeFor(NetworkDealBase deal)
		{
			List<Item> list = Items(deal);
			if (list.Count != 0)
			{
				return Fee(list);
			}
			return -1;
		}

		internal static void UpdateOffersAfterAccept(NetworkDealBase[] before, Func<NetworkDealBase, bool> isAccepted)
		{
			RoomStatsHolder roomStats = SurfaceNetworkHandler.RoomStats;
			if (roomStats != null && before != null && before.Length != 0)
			{
				List<NetworkDealBase> list = before.Where((NetworkDealBase o) => o != null).ToList();
				NetworkDealBase val = list.FirstOrDefault(isAccepted);
				if (val != null)
				{
					list.Remove(val);
				}
				if (AcceptsThisWeek >= Math.Max(1, Plugin.MaxAcceptsPerWeek.Value))
				{
					list.Clear();
				}
				else
				{
					Refill(list, before.Length);
				}
				roomStats.SetNetworkDealsToSelect(list.ToArray());
			}
		}

		private static void Refill(List<NetworkDealBase> list, int target)
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			NetworkDealDataBase instance = SingletonAsset<NetworkDealDataBase>.Instance;
			for (int i = 0; i < 30; i++)
			{
				if (list.Count >= target)
				{
					break;
				}
				NetworkDealBase candidate = instance.GetWeightedRandomDeal(AllDifficulties, 1, false).FirstOrDefault();
				if (candidate != null)
				{
					if (!list.Any((NetworkDealBase o) => o.GetIndex() == candidate.GetIndex()))
					{
						NetworkDealBase dealFromIndex = instance.GetDealFromIndex((int)candidate.GetIndex());
						List<DIFFICULTY> allowedDifficulties = dealFromIndex.AllowedDifficulties;
						DIFFICULTY val = (DIFFICULTY)((allowedDifficulties == null || allowedDifficulties.Count <= 0) ? 50 : ((int)allowedDifficulties[Random.Range(0, allowedDifficulties.Count)]));
						dealFromIndex.Init(SingletonAsset<DealRewardDatabase>.Instance.GetRandom(), val);
						list.Add(dealFromIndex);
					}
					continue;
				}
				break;
			}
		}
	}
	internal static class Patches
	{
		private static NetworkDealBase[]? offersBeforeAccept;

		[HarmonyPrefix]
		[HarmonyPatch(typeof(NetworkDealBoss), "RPCA_AddDeal")]
		private static void AddDealPrefix()
		{
			if (PhotonNetwork.IsMasterClient)
			{
				RoomStatsHolder roomStats = SurfaceNetworkHandler.RoomStats;
				offersBeforeAccept = ((roomStats == null) ? null : roomStats.NetworkDealsToSelect?.ToArray());
				NetworkDealBase activeDeal = NetworkDealBoss.activeDeal;
				if (activeDeal != null)
				{
					Manager.Track(activeDeal);
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(NetworkDealBoss), "RPCA_AddDeal")]
		private static void AddDealPostfix(byte __0, byte __1, DIFFICULTY __2)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.IsMasterClient)
			{
				return;
			}
			try
			{
				if (NetworkDealBoss.activeDeal != null)
				{
					Manager.Track(NetworkDealBoss.activeDeal);
				}
				Manager.AcceptsThisWeek++;
				NetworkDealBase[] array = offersBeforeAccept;
				offersBeforeAccept = null;
				if (array != null)
				{
					Manager.UpdateOffersAfterAccept(array, (NetworkDealBase o) => o.GetIndex() == __0 && o.reward != null && o.reward.GetIndex() == __1 && o.difficulty == __2);
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"AddDealPostfix: {arg}");
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(NetworkDealBoss), "RPCA_ClaimReward")]
		private static void ClaimPrefix()
		{
			RemoveActiveFromTracking();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(NetworkDealBoss), "RPCA_ClaimReward")]
		private static void ClaimPostfix()
		{
			Manager.FocusNext();
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(NetworkDealBoss), "RPCA_RemoveDeal")]
		private static void RemovePrefix()
		{
			RemoveActiveFromTracking();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(NetworkDealBoss), "RPCA_RemoveDeal")]
		private static void RemovePostfix()
		{
			Manager.FocusNext();
		}

		private static void RemoveActiveFromTracking()
		{
			if (PhotonNetwork.IsMasterClient)
			{
				Tracked tracked = Manager.FindDeal(NetworkDealBoss.activeDeal);
				if (tracked != null)
				{
					Manager.All.Remove(tracked);
					Manager.MarkDirty();
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(NetworkDealBoss), "Cleanup")]
		private static void CleanupPrefix()
		{
			Manager.Clear();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(NetworkDealBoss), "Update")]
		private static void BossUpdatePostfix()
		{
			if (PhotonNetwork.IsMasterClient)
			{
				Manager.UpdateBackground();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(NetworkDealBoss), "ReviewUploadContent")]
		private static void ReviewPostfix(ContentBuffer __0)
		{
			if (PhotonNetwork.IsMasterClient)
			{
				Manager.ForEachBackground(delegate(NetworkDealBase d)
				{
					d.ReviewUploadContent(__0);
				});
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(NetworkDealBoss), "OnStatusUpdated")]
		private static void StatusPostfix()
		{
			if (!PhotonNetwork.IsMasterClient || Manager.All.Count <= 1)
			{
				return;
			}
			foreach (NetworkDealBase item in Manager.Background())
			{
				try
				{
					item.OnStatusUpdated();
				}
				catch (Exception arg)
				{
					Plugin.Log.LogError((object)$"OnStatusUpdated: {arg}");
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(NetworkDealBoss), "OnAddQuota")]
		private static void QuotaPostfix(int __0)
		{
			if (PhotonNetwork.IsMasterClient)
			{
				Manager.ForEachBackground(delegate(NetworkDealBase d)
				{
					d.OnAddQuota(__0);
				});
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(NetworkDealBoss), "OnMoneyRemoved")]
		private static void MoneyPostfix(int __0)
		{
			if (PhotonNetwork.IsMasterClient)
			{
				Manager.ForEachBackground(delegate(NetworkDealBase d)
				{
					d.OnRemovedMoney(__0);
				});
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(NetworkDealBoss), "OnPlayerEnteredRoom")]
		private static void PlayerEnteredPostfix()
		{
			Manager.MarkDirty();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(SurfaceNetworkHandler), "NewWeek")]
		private static void NewWeekPostfix()
		{
			if (PhotonNetwork.IsMasterClient)
			{
				Manager.AcceptsThisWeek = 0;
				Manager.MarkDirty();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(SaveLoadHandler), "FillSaveData")]
		private static void SavePostfix(Save __0)
		{
			try
			{
				if (!PhotonNetwork.IsMasterClient || Manager.All.Count == 0)
				{
					return;
				}
				List<SerializedNetworkDeal> list = new List<SerializedNetworkDeal>();
				NetworkDealBase activeDeal = NetworkDealBoss.activeDeal;
				if (activeDeal != null)
				{
					list.Add(activeDeal.GetSerialized());
				}
				foreach (NetworkDealBase item in Manager.Background())
				{
					list.Add(item.GetSerialized());
				}
				if (list.Count > 1)
				{
					__0.SerializedNetworkDeals = list.ToArray();
					Plugin.Log.LogInfo((object)$"Saved {list.Count} network deals.");
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"SavePostfix: {arg}");
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(SaveLoadHandler), "LoadSaveData")]
		private static void LoadPostfix(Save __0)
		{
			try
			{
				Manager.Clear();
				if (NetworkDealBoss.activeDeal != null)
				{
					Manager.Track(NetworkDealBoss.activeDeal);
				}
				SerializedNetworkDeal[] array = __0?.SerializedNetworkDeals;
				if (array != null)
				{
					for (int i = 1; i < array.Length; i++)
					{
						SerializedNetworkDeal obj = array[i];
						NetworkDealBase val = ((obj != null) ? obj.UnSerialize() : null);
						if (val != null)
						{
							val.Refresh();
							Manager.Track(val);
						}
					}
				}
				Manager.AcceptsThisWeek = Manager.All.Count;
				if (Manager.All.Count > 1)
				{
					Plugin.Log.LogInfo((object)$"Loaded {Manager.All.Count} network deals.");
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"LoadPostfix: {arg}");
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Player), "HasLockedInput")]
		private static void LockInputPostfix(Player __instance, ref bool __result)
		{
			if (Plugin.PanelOpen && __instance == Player.localPlayer)
			{
				__result = true;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(CursorHandler), "Update")]
		private static bool CursorPrefix()
		{
			if (!Plugin.PanelOpen)
			{
				return true;
			}
			Plugin.ForceCursor();
			return false;
		}
	}
	internal sealed class MirrorDeal
	{
		public int Id;

		public bool Focused;

		public int DealIndex;

		public int RewardIndex;

		public int Difficulty;

		public int Progress;

		public DEAL_STATE State;

		public int Fee;

		public NetworkDealBase? Display;
	}
	internal static class Net
	{
		private const byte EvState = 179;

		private const byte EvRequest = 180;

		private const byte EvMessage = 181;

		private const int Version = 3;

		internal const int ActAccept = 1;

		internal const int ActShow = 2;

		internal const int ActCancel = 3;

		internal const int ActClaim = 4;

		internal const int ActRedeliver = 5;

		internal static readonly List<MirrorDeal> Mirror = new List<MirrorDeal>();

		internal static float LastStateTime = -100f;

		internal static int HostMaxConcurrent;

		internal static int HostAcceptsLeft;

		internal static bool HostFree;

		internal static int HostFeePercent = 50;

		internal static int HostMinFee = 20;

		private static bool registered;

		internal static bool HostHasMod
		{
			get
			{
				if (!PhotonNetwork.IsMasterClient)
				{
					return Time.unscaledTime - LastStateTime < 12f;
				}
				return true;
			}
		}

		internal static void Register()
		{
			if (!registered && PhotonNetwork.NetworkingClient != null)
			{
				PhotonNetwork.NetworkingClient.EventReceived += OnEvent;
				registered = true;
			}
		}

		internal static void Unregister()
		{
			if (registered && PhotonNetwork.NetworkingClient != null)
			{
				PhotonNetwork.NetworkingClient.EventReceived -= OnEvent;
			}
			registered = false;
		}

		internal static void BroadcastState()
		{
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Expected O, but got Unknown
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Expected I4, but got Unknown
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Expected I4, but got Unknown
			if (!PhotonNetwork.InRoom || PhotonNetwork.OfflineMode || PhotonNetwork.CurrentRoom == null || PhotonNetwork.CurrentRoom.PlayerCount <= 1)
			{
				return;
			}
			List<int> list = new List<int>
			{
				3,
				Plugin.MaxConcurrent.Value,
				Math.Max(0, Plugin.MaxAcceptsPerWeek.Value - Manager.AcceptsThisWeek),
				Manager.DeliveryIsFree ? 1 : 0,
				Mathf.RoundToInt(Plugin.FeeRate.Value * 100f),
				Plugin.MinFee.Value,
				Manager.All.Count
			};
			NetworkDealBase activeDeal = NetworkDealBoss.activeDeal;
			foreach (Tracked item in Manager.All)
			{
				NetworkDealBase deal = item.Deal;
				list.Add(item.Id);
				list.Add((deal == activeDeal) ? 1 : 0);
				list.Add(deal.GetIndex());
				list.Add((deal.reward != null) ? deal.reward.GetIndex() : 0);
				list.Add((int)deal.difficulty);
				list.Add(deal.ProgressInt);
				list.Add((int)deal.State);
				list.Add(Manager.FeeFor(deal));
			}
			PhotonNetwork.RaiseEvent((byte)179, (object)list.ToArray(), new RaiseEventOptions
			{
				Receivers = (ReceiverGroup)0
			}, SendOptions.SendReliable);
		}

		internal static void Request(int action, int arg, int extra = -1)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			if (PhotonNetwork.IsMasterClient)
			{
				Ui.Toast(Execute(action, arg, extra));
				Manager.MarkDirty();
			}
			else if (PhotonNetwork.InRoom)
			{
				PhotonNetwork.RaiseEvent((byte)180, (object)new int[4] { 3, action, arg, extra }, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)2
				}, SendOptions.SendReliable);
			}
		}

		private static Msg Execute(int action, int arg, int extra)
		{
			try
			{
				return action switch
				{
					1 => Manager.Accept(arg, extra), 
					2 => Manager.Show(arg), 
					3 => Manager.Cancel(arg), 
					4 => Manager.Claim(arg), 
					5 => Manager.Redeliver(arg), 
					_ => Msg.Of(MsgId.None), 
				};
			}
			catch (Exception arg2)
			{
				Plugin.Log.LogError((object)$"Action {action} failed: {arg2}");
				return Msg.Of(MsgId.ActionFailed);
			}
		}

		private static void OnEvent(EventData ev)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				switch (ev.Code)
				{
				case 179:
					if (!PhotonNetwork.IsMasterClient && ev.CustomData is int[] s)
					{
						ReadState(s);
					}
					break;
				case 180:
					if (PhotonNetwork.IsMasterClient && ev.CustomData is int[] array && array.Length >= 4 && array[0] == 3)
					{
						Msg msg2 = Execute(array[1], array[2], array[3]);
						Manager.MarkDirty();
						if (msg2.Id != MsgId.None)
						{
							object[] array2 = msg2.ToNetwork();
							RaiseEventOptions val = new RaiseEventOptions();
							val.TargetActors = new int[1] { ev.Sender };
							PhotonNetwork.RaiseEvent((byte)181, (object)array2, val, SendOptions.SendReliable);
						}
					}
					break;
				case 181:
				{
					Msg msg = Msg.FromNetwork(ev.CustomData);
					if (msg.Id != MsgId.None)
					{
						Ui.Toast(msg);
					}
					break;
				}
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"OnEvent: {arg}");
			}
		}

		private static void ReadState(int[] s)
		{
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Invalid comparison between Unknown and I4
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Invalid comparison between Unknown and I4
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			if (s.Length < 7 || s[0] != 3)
			{
				return;
			}
			LastStateTime = Time.unscaledTime;
			HostMaxConcurrent = s[1];
			HostAcceptsLeft = s[2];
			HostFree = s[3] == 1;
			HostFeePercent = s[4];
			HostMinFee = s[5];
			int num = s[6];
			Dictionary<int, MirrorDeal> dictionary = Mirror.ToDictionary((MirrorDeal m) => m.Id);
			Mirror.Clear();
			for (int num2 = 0; num2 < num; num2++)
			{
				int num3 = 7 + num2 * 8;
				if (num3 + 8 > s.Length)
				{
					break;
				}
				MirrorDeal mirrorDeal = new MirrorDeal
				{
					Id = s[num3],
					Focused = (s[num3 + 1] == 1),
					DealIndex = s[num3 + 2],
					RewardIndex = s[num3 + 3],
					Difficulty = s[num3 + 4],
					Progress = s[num3 + 5],
					State = (DEAL_STATE)s[num3 + 6],
					Fee = s[num3 + 7]
				};
				if (dictionary.TryGetValue(mirrorDeal.Id, out var value))
				{
					if (value.DealIndex == mirrorDeal.DealIndex)
					{
						mirrorDeal.Display = value.Display;
					}
					if (value.State != mirrorDeal.State && !mirrorDeal.Focused)
					{
						if ((int)mirrorDeal.State == 3)
						{
							Ui.Toast(Msg.Of(MsgId.DealSucceeded, "#" + mirrorDeal.DealIndex, ((object)Plugin.PanelKey.Value/*cast due to .constrained prefix*/).ToString()));
						}
						else if ((int)mirrorDeal.State == 2)
						{
							Ui.Toast(Msg.Of(MsgId.DealFailed, "#" + mirrorDeal.DealIndex));
						}
					}
				}
				Mirror.Add(mirrorDeal);
			}
		}

		internal static NetworkDealBase? GetDisplay(MirrorDeal m)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (m.Display == null)
				{
					NetworkDealBase dealFromIndex = SingletonAsset<NetworkDealDataBase>.Instance.GetDealFromIndex(m.DealIndex);
					DealRewardBase rewardFromIndex = SingletonAsset<DealRewardDatabase>.Instance.GetRewardFromIndex(m.RewardIndex);
					dealFromIndex.Init(rewardFromIndex, (DIFFICULTY)(byte)m.Difficulty);
					m.Display = dealFromIndex;
				}
				m.Display.ProgressInt = m.Progress;
				m.Display.State = m.State;
				m.Display.ClearDirty();
				return m.Display;
			}
			catch
			{
				return null;
			}
		}
	}
	internal static class Texts
	{
		internal static string Name(NetworkDealBase? deal)
		{
			if (deal == null)
			{
				return "?";
			}
			try
			{
				string dealName_Localized = deal.DealName_Localized;
				return string.IsNullOrEmpty(dealName_Localized) ? deal.DealName : dealName_Localized;
			}
			catch
			{
				return ((object)deal).GetType().Name;
			}
		}

		internal static string Safe(Func<string> f)
		{
			try
			{
				return f() ?? string.Empty;
			}
			catch
			{
				return string.Empty;
			}
		}

		internal static string StateText(DEAL_STATE s)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			if ((int)s != 2)
			{
				if ((int)s == 3)
				{
					return "<color=#7CFC8A>" + Lang.T("達成", "Completed", "已完成", "已完成", "달성") + "</color>";
				}
				return Lang.T("進行中", "In progress", "进行中", "進行中", "진행 중");
			}
			return "<color=#FF7B7B>" + Lang.T("失敗", "Failed", "失败", "失敗", "실패") + "</color>";
		}
	}
	internal sealed class Row
	{
		public int Id;

		public bool Focused;

		public NetworkDealBase? Deal;

		public DEAL_STATE State;

		public int Fee;
	}
	internal static class Ui
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static WindowFunction <0>__DrawWindow;
		}

		private static Rect window = new Rect(0f, 0f, 640f, 520f);

		private static bool positioned;

		private static Vector2 scroll;

		private static GUISkin? skin;

		private static GUIStyle? rich;

		private static GUIStyle? title;

		private static GUIStyle? box;

		private static string toastText = string.Empty;

		private static float toastUntil;

		private static int confirmCancelId = -1;

		private static float confirmUntil;

		private static Texture2D? arrow;

		internal static void Toast(Msg msg)
		{
			Toast(Msgs.Text(msg));
		}

		internal static void Toast(string text)
		{
			if (!string.IsNullOrEmpty(text))
			{
				toastText = text;
				toastUntil = Time.unscaledTime + 5f;
				Plugin.Log.LogInfo((object)text);
			}
		}

		private static void EnsureStyles()
		{
			//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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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_0080: Expected O, but got Unknown
			//IL_008a: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_00a3: Expected O, but got Unknown
			if (!((Object)(object)skin != (Object)null))
			{
				skin = Object.Instantiate<GUISkin>(GUI.skin);
				skin.font = Lang.GetFont();
				rich = new GUIStyle(skin.label)
				{
					richText = true,
					wordWrap = true,
					fontSize = 14
				};
				title = new GUIStyle(skin.label)
				{
					richText = true,
					fontStyle = (FontStyle)1,
					fontSize = 16
				};
				box = new GUIStyle(skin.box)
				{
					padding = new RectOffset(8, 8, 6, 6)
				};
			}
		}

		internal static void Draw()
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Expected O, but got Unknown
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.PanelOpen && Time.unscaledTime > toastUntil)
			{
				return;
			}
			EnsureStyles();
			skin.font = Lang.GetFont();
			GUISkin obj = GUI.skin;
			GUI.skin = skin;
			if (Time.unscaledTime <= toastUntil)
			{
				Rect val = default(Rect);
				((Rect)(ref val))..ctor((float)Screen.width / 2f - 320f, (float)Screen.height - 110f, 640f, 44f);
				GUI.Box(val, string.Empty);
				GUI.Label(new Rect(((Rect)(ref val)).x + 10f, ((Rect)(ref val)).y + 4f, ((Rect)(ref val)).width - 20f, ((Rect)(ref val)).height - 8f), toastText, rich);
			}
			if (Plugin.PanelOpen)
			{
				if (!positioned)
				{
					((Rect)(ref window)).x = ((float)Screen.width - ((Rect)(ref window)).width) / 2f;
					((Rect)(ref window)).y = ((float)Screen.height - ((Rect)(ref window)).height) / 2f;
					positioned = true;
				}
				Plugin.ForceCursor();
				Rect val2 = window;
				object obj2 = <>O.<0>__DrawWindow;
				if (obj2 == null)
				{
					WindowFunction val3 = DrawWindow;
					<>O.<0>__DrawWindow = val3;
					obj2 = (object)val3;
				}
				window = GUI.Window(24225, val2, (WindowFunction)obj2, Lang.T("クエスト管理", "Quest Manager", "任务管理", "任務管理", "퀘스트 관리"));
				Vector2 mousePosition = Event.current.mousePosition;
				if (!((Rect)(ref window)).Contains(mousePosition))
				{
					DrawCursorAt(mousePosition);
				}
			}
			GUI.skin = obj;
		}

		private static Texture2D Arrow()
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Expected O, but got Unknown
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)arrow != (Object)null)
			{
				return arrow;
			}
			string[] array = new string[17]
			{
				"X...........", "XX..........", "XOX.........", "XOOX........", "XOOOX.......", "XOOOOX......", "XOOOOOX.....", "XOOOOOOX....", "XOOOOOOOX...", "XOOOOOOOOX..",
				"XOOOOOXXXXX.", "XOOXOOX.....", "XOX.XOOX....", "XX..XOOX....", "X....XOOX...", ".....XOOX...", "......XX...."
			};
			int length = array[0].Length;
			int num = array.Length;
			arrow = new Texture2D(length, num, (TextureFormat)4, false)
			{
				filterMode = (FilterMode)0
			};
			for (int i = 0; i < num; i++)
			{
				for (int j = 0; j < length; j++)
				{
					char c = array[num - 1 - i][j];
					arrow.SetPixel(j, i, (Color)(c switch
					{
						'O' => Color.white, 
						'X' => Color.black, 
						_ => new Color(0f, 0f, 0f, 0f), 
					}));
				}
			}
			arrow.Apply();
			return arrow;
		}

		private static void DrawCursorAt(Vector2 p)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.SoftwareCursor.Value && (int)Event.current.type == 7)
			{
				GUI.DrawTexture(new Rect(p.x, p.y, 18f, 25.5f), (Texture)(object)Arrow());
			}
		}

		private static List<Row> Rows()
		{
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//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_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			List<Row> list = new List<Row>();
			if (PhotonNetwork.IsMasterClient)
			{
				NetworkDealBase activeDeal = NetworkDealBoss.activeDeal;
				foreach (Tracked item in Manager.All)
				{
					list.Add(new Row
					{
						Id = item.Id,
						Focused = (item.Deal == activeDeal),
						Deal = item.Deal,
						State = item.Deal.State,
						Fee = Manager.FeeFor(item.Deal)
					});
				}
			}
			else if (Net.HostHasMod)
			{
				foreach (MirrorDeal item2 in Net.Mirror)
				{
					list.Add(new Row
					{
						Id = item2.Id,
						Focused = item2.Focused,
						Deal = Net.GetDisplay(item2),
						State = item2.State,
						Fee = item2.Fee
					});
				}
			}
			else if (NetworkDealBoss.activeDeal != null)
			{
				NetworkDealBase activeDeal2 = NetworkDealBoss.activeDeal;
				list.Add(new Row
				{
					Id = -1,
					Focused = true,
					Deal = activeDeal2,
					State = activeDeal2.State,
					Fee = -1
				});
			}
			return (from r in list
				orderby r.Focused descending, r.Id
				select r).ToList();
		}

		private static void DrawWindow(int id)
		{
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0569: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ca: Unknown result type (might be due to invalid IL or missing references)
			bool isMasterClient = PhotonNetwork.IsMasterClient;
			bool hostHasMod = Net.HostHasMod;
			RoomStatsHolder roomStats = SurfaceNetworkHandler.RoomStats;
			int num = (isMasterClient ? Plugin.MaxConcurrent.Value : Net.HostMaxConcurrent);
			int num2 = (isMasterClient ? Math.Max(0, Plugin.MaxAcceptsPerWeek.Value - Manager.AcceptsThisWeek) : Net.HostAcceptsLeft);
			bool flag = (isMasterClient ? Manager.DeliveryIsFree : Net.HostFree);
			int num3 = (isMasterClient ? Mathf.RoundToInt(Plugin.FeeRate.Value * 100f) : Net.HostFeePercent);
			int num4 = (isMasterClient ? Plugin.MinFee.Value : Net.HostMinFee);
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			string text = Lang.T("所持金", "Money", "资金", "資金", "소지금");
			GUILayout.Label((roomStats != null) ? $"{text}: <b>${roomStats.Money}</b>" : (text + ": -"), rich, Array.Empty<GUILayoutOption>());
			GUILayout.FlexibleSpace();
			GUILayout.Label(flag ? ("<color=#7CFC8A>" + Lang.T("FreeShop 導入中: 再送の送料は無料", "FreeShop installed: redelivery is free", "已安装 FreeShop:重新配送免运费", "已安裝 FreeShop:重新配送免運費", "FreeShop 사용 중: 재배송 무료") + "</color>") : string.Format(Lang.T("再送の送料: 物資の価格の{0}% (最低${1})", "Redelivery fee: {0}% of item price (min ${1})", "重新配送运费:物资价格的 {0}%(最低 ${1})", "重新配送運費:物資價格的 {0}%(最低 ${1})", "재배송 배송비: 물자 가격의 {0}% (최소 ${1})"), num3, num4), rich, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			if (!hostHasMod)
			{
				GUILayout.Label("<color=#FFC857>" + Lang.T("ホストがこのModを入れていないため、一覧の表示と操作はできません。", "The host doesn't have this mod, so the list and actions are unavailable.", "房主未安装此模组,无法显示列表或进行操作。", "房主未安裝此模組,無法顯示列表或進行操作。", "호스트가 이 모드를 설치하지 않아 목록 표시와 조작을 할 수 없습니다.") + "</color>", rich, Array.Empty<GUILayoutOption>());
			}
			List<Row> list = Rows();
			scroll = GUILayout.BeginScrollView(scroll, Array.Empty<GUILayoutOption>());
			GUILayout.Label("<b>" + Lang.T("受注中のクエスト", "Active quests", "进行中的任务", "進行中的任務", "진행 중인 퀘스트") + $"</b>  {list.Count}/{num}", title, Array.Empty<GUILayoutOption>());
			if (list.Count == 0)
			{
				GUILayout.Label(Lang.T("受注中のクエストはありません", "No active quests", "没有进行中的任务", "沒有進行中的任務", "진행 중인 퀘스트가 없습니다"), rich, Array.Empty<GUILayoutOption>());
			}
			foreach (Row item in list)
			{
				DrawRow(item, hostHasMod && item.Id >= 0);
			}
			GUILayout.Space(10f);
			GUILayout.Label("<b>" + Lang.T("受注できるクエスト", "Available quests", "可接受的任务", "可接受的任務", "수락 가능한 퀘스트") + "</b>  " + string.Format(Lang.T("今週あと{0}件", "{0} left this week", "本周还可接受 {0} 个", "本週還可接受 {0} 個", "이번 주 {0}개 남음"), num2), title, Array.Empty<GUILayoutOption>());
			NetworkDealBase[] array = ((roomStats != null) ? roomStats.NetworkDealsToSelect : null);
			if (roomStats != null && !roomStats.ComputerRoomDoorUnlocked)
			{
				GUILayout.Label(Lang.T("PC部屋がまだ開いていません", "The computer room isn't open yet", "电脑室尚未开放", "電腦室尚未開放", "컴퓨터실이 아직 열리지 않았습니다"), rich, Array.Empty<GUILayoutOption>());
			}
			else if (array == null || array.Length == 0)
			{
				GUILayout.Label(Lang.T("今は受注できるクエストがありません (次の週に更新されます)", "No quests available right now (refreshes next week)", "目前没有可接受的任务(下周刷新)", "目前沒有可接受的任務(下週刷新)", "지금은 수락할 수 있는 퀘스트가 없습니다 (다음 주에 갱신)"), rich, Array.Empty<GUILayoutOption>());
			}
			else
			{
				for (int i = 0; i < array.Length; i++)
				{
					NetworkDealBase o = array[i];
					if (o != null)
					{
						GUILayout.BeginVertical(box, Array.Empty<GUILayoutOption>());
						GUILayout.Label("<b>" + Texts.Name(o) + "</b>  [" + Texts.Safe((Func<string>)o.GetDifficultyText) + "]", rich, Array.Empty<GUILayoutOption>());
						GUILayout.Label(Texts.Safe((Func<string>)o.DealDescription), rich, Array.Empty<GUILayoutOption>());
						GUILayout.Label(Lang.T("報酬: ", "Reward: ", "奖励:", "獎勵:", "보상: ") + Texts.Safe(() => o.reward.GetRewardDescription()), rich, Array.Empty<GUILayoutOption>());
						GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
						GUILayout.FlexibleSpace();
						GUI.enabled = hostHasMod && list.Count < Math.Max(1, num) && num2 > 0;
						if (GUILayout.Button(Lang.T("受注する", "Accept", "接受", "接受", "수락"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(120f) }))
						{
							Net.Request(1, i, o.GetIndex());
						}
						GUI.enabled = true;
						GUILayout.EndHorizontal();
						GUILayout.EndVertical();
					}
				}
			}
			GUILayout.EndScrollView();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.FlexibleSpace();
			if (GUILayout.Button(Lang.T("閉じる", "Close", "关闭", "關閉", "닫기") + $" ({Plugin.PanelKey.Value})", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(140f) }))
			{
				Plugin.PanelOpen = false;
			}
			GUILayout.EndHorizontal();
			GUILayout.EndVertical();
			DrawCursorAt(Event.current.mousePosition);
			GUI.DragWindow(new Rect(0f, 0f, 10000f, 24f));
		}

		private static void DrawRow(Row row, bool canAct)
		{
			//IL_00a5: 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_015b: Invalid comparison between Unknown and I4
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Invalid comparison between Unknown and I4
			NetworkDealBase d = row.Deal;
			GUILayout.BeginVertical(box, Array.Empty<GUILayoutOption>());
			string text = (row.Focused ? ("<color=#8FD3FF>[" + Lang.T("PCに表示中", "On PC", "电脑显示中", "電腦顯示中", "PC 표시 중") + "]</color> ") : string.Empty);
			GUILayout.Label(text + "<b>" + Texts.Name(d) + "</b>  [" + Texts.Safe(() => d.GetDifficultyText()) + "]  " + Texts.StateText(row.State), rich, Array.Empty<GUILayoutOption>());
			if (d != null)
			{
				string text2 = Texts.Safe((Func<string>)d.GetProgressText);
				if (!string.IsNullOrEmpty(text2))
				{
					GUILayout.Label(text2, rich, Array.Empty<GUILayoutOption>());
				}
				GUILayout.Label(Lang.T("報酬: ", "Reward: ", "奖励:", "獎勵:", "보상: ") + Texts.Safe(() => d.reward.GetRewardDescription()), rich, Array.Empty<GUILayoutOption>());
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.FlexibleSpace();
			GUI.enabled = canAct;
			if ((int)row.State == 3)
			{
				if (GUILayout.Button(Lang.T("報酬を受け取る", "Claim reward", "领取奖励", "領取獎勵", "보상 받기"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(140f) }))
				{
					Net.Request(4, row.Id);
				}
			}
			else if ((int)row.State == 2)
			{
				if (GUILayout.Button(Lang.T("取り下げる", "Dismiss", "移除", "移除", "정리"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(120f) }))
				{
					Net.Request(3, row.Id);
				}
			}
			else
			{
				if (!row.Focused && GUILayout.Button(Lang.T("PCに表示", "Show on PC", "在电脑显示", "在電腦顯示", "PC에 표시"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(100f) }))
				{
					Net.Request(2, row.Id);
				}
				GUI.enabled = canAct && row.Fee >= 0;
				string text3 = Lang.T("再送", "Redeliver", "重新配送", "重新配送", "재배송");
				if (GUILayout.Button((row.Fee < 0) ? (text3 + " (" + Lang.T("物資なし", "no items", "无物资", "無物資", "물자 없음") + ")") : ((row.Fee == 0) ? (text3 + " (" + Lang.T("無料", "free", "免费", "免費", "무료") + ")") : $"{text3} (${row.Fee})"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(130f) }))
				{
					Net.Request(5, row.Id);
				}
				GUI.enabled = canAct;
				bool flag = confirmCancelId == row.Id && Time.unscaledTime < confirmUntil;
				if (GUILayout.Button(flag ? Lang.T("本当に却下する", "Really abandon?", "确定放弃?", "確定放棄?", "정말 포기?") : Lang.T("却下", "Abandon", "放弃", "放棄", "포기"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth((float)(flag ? 130 : 80)) }))
				{
					if (flag)
					{
						confirmCancelId = -1;
						Net.Request(3, row.Id);
					}
					else
					{
						confirmCancelId = row.Id;
						confirmUntil = Time.unscaledTime + 4f;
					}
				}
			}
			GUI.enabled = true;
			GUILayout.EndHorizontal();
			GUILayout.EndVertical();
		}
	}
	internal enum MsgId
	{
		None,
		OfferGone,
		OffersChanged,
		AcceptOnlyAtBase,
		MaxConcurrent,
		WeekLimit,
		Accepted,
		NotFound,
		OnlyAtBase,
		Dismissed,
		Abandoned,
		NotDone,
		ClaimOnlyAtBase,
		Claimed,
		Shown,
		DoneNoRedeliver,
		NoItems,
		RedeliverOnlyAtBase,
		Wait,
		NotEnoughMoney,
		DroneFailed,
		Redelivered,
		RedeliveredFree,
		ActionFailed,
		DealSucceeded,
		DealFailed
	}
	internal readonly struct Msg
	{
		public readonly MsgId Id;

		public readonly string[] Args;

		private Msg(MsgId id, string[] args)
		{
			Id = id;
			Args = args;
		}

		public static Msg Of(MsgId id, params string[] args)
		{
			return new Msg(id, args ?? Array.Empty<string>());
		}

		public object[] ToNetwork()
		{
			return new object[2]
			{
				(int)Id,
				Args
			};
		}

		public static Msg FromNetwork(object data)
		{
			if (data is object[] array && array.Length >= 1 && array[0] is int id)
			{
				string[] args = ((array.Length >= 2 && array[1] is string[] array2) ? array2 : Array.Empty<string>());
				return new Msg((MsgId)id, args);
			}
			return Of(MsgId.None);
		}
	}
	internal static class Msgs
	{
		private static readonly Dictionary<string, string> NameCache = new Dictionary<string, string>();

		internal static string DealArg(NetworkDealBase? deal)
		{
			if (deal != null)
			{
				return "#" + deal.GetIndex();
			}
			return "?";
		}

		private static string Arg(Msg m, int i)
		{
			if (m.Args == null || i >= m.Args.Length)
			{
				return string.Empty;
			}
			string text = m.Args[i] ?? string.Empty;
			if (text.StartsWith("#") && int.TryParse(text.Substring(1), out var result))
			{
				return DealName(result);
			}
			return text;
		}

		internal static string DealName(int index)
		{
			string key = Lang.Current + ":" + index;
			if (NameCache.TryGetValue(key, out string value))
			{
				return value;
			}
			string text;
			try
			{
				NetworkDealBase dealFromIndex = SingletonAsset<NetworkDealDataBase>.Instance.GetDealFromIndex(index);
				dealFromIndex.MakeLocalizedStrings();
				text = Texts.Name(dealFromIndex);
			}
			catch
			{
				text = "#" + index;
			}
			NameCache[key] = text;
			return text;
		}

		internal static string Text(Msg m)
		{
			string arg = Arg(m, 0);
			string arg2 = Arg(m, 1);
			return m.Id switch
			{
				MsgId.OfferGone => Lang.T("そのクエストはもう受注できません", "That quest can no longer be accepted", "该任务已无法接受", "該任務已無法接受", "이 퀘스트는 더 이상 수락할 수 없습니다"), 
				MsgId.OffersChanged => Lang.T("候補が更新されました。もう一度選んでください", "The offers changed. Please choose again", "任务列表已更新,请重新选择", "任務列表已更新,請重新選擇", "후보가 갱신되었습니다. 다시 선택해 주세요"), 
				MsgId.AcceptOnlyAtBase => Lang.T("拠点にいるときだけ受注できます", "Quests can only be accepted at the base", "只能在基地接受任务", "只能在基地接受任務", "기지에 있을 때만 수락할 수 있습니다"), 
				MsgId.MaxConcurrent => string.Format(Lang.T("同時に受けられるのは{0}件までです", "You can only have {0} quests at once", "最多只能同时进行 {0} 个任务", "最多只能同時進行 {0} 個任務", "동시에 진행할 수 있는 퀘스트는 {0}개까지입니다"), arg), 
				MsgId.WeekLimit => Lang.T("今週はこれ以上受注できません", "No more quests can be accepted this week", "本周无法再接受任务", "本週無法再接受任務", "이번 주에는 더 이상 수락할 수 없습니다"), 
				MsgId.Accepted => string.Format(Lang.T("「{0}」を受注しました", "Accepted \"{0}\"", "已接受「{0}」", "已接受「{0}」", "'{0}' 퀘스트를 수락했습니다"), arg), 
				MsgId.NotFound => Lang.T("そのクエストは見つかりません", "Quest not found", "找不到该任务", "找不到該任務", "퀘스트를 찾을 수 없습니다"), 
				MsgId.OnlyAtBase => Lang.T("拠点にいるときだけ操作できます", "This can only be done at the base", "只能在基地操作", "只能在基地操作", "기지에 있을 때만 할 수 있습니다"), 
				MsgId.Dismissed => string.Format(Lang.T("「{0}」を取り下げました", "Dismissed \"{0}\"", "已移除「{0}」", "已移除「{0}」", "'{0}' 퀘스트를 정리했습니다"), arg), 
				MsgId.Abandoned => string.Format(Lang.T("「{0}」を却下しました", "Abandoned \"{0}\"", "已放弃「{0}」", "已放棄「{0}」", "'{0}' 퀘스트를 포기했습니다"), arg), 
				MsgId.NotDone => Lang.T("まだ達成していません", "Not completed yet", "尚未完成", "尚未完成", "아직 달성하지 않았습니다"), 
				MsgId.ClaimOnlyAtBase => Lang.T("拠点にいるときだけ報酬を受け取れます", "Rewards can only be claimed at the base", "只能在基地领取奖励", "只能在基地領取獎勵", "기지에 있을 때만 보상을 받을 수 있습니다"), 
				MsgId.Claimed => string.Format(Lang.T("「{0}」の報酬を受け取りました", "Claimed the reward for \"{0}\"", "已领取「{0}」的奖励", "已領取「{0}」的獎勵", "'{0}' 보상을 받았습니다"), arg), 
				MsgId.Shown => string.Format(Lang.T("「{0}」をPCに表示しました", "\"{0}\" is now shown on the PC", "已在电脑上显示「{0}」", "已在電腦上顯示「{0}」", "'{0}' 퀘스트를 PC에 표시했습니다"), arg), 
				MsgId.DoneNoRedeliver => Lang.T("終わったクエストの物資は再送できません", "Items for finished quests can't be redelivered", "已结束的任务无法重新配送物资", "已結束的任務無法重新配送物資", "끝난 퀘스트의 물자는 재배송할 수 없습니다"), 
				MsgId.NoItems => Lang.T("このクエストには配送物資がありません", "This quest has no delivered items", "该任务没有配送物资", "該任務沒有配送物資", "이 퀘스트에는 배송 물자가 없습니다"), 
				MsgId.RedeliverOnlyAtBase => Lang.T("再送は拠点にいるときだけできます", "Redelivery is only available at the base", "只能在基地重新配送", "只能在基地重新配送", "재배송은 기지에 있을 때만 가능합니다"), 
				MsgId.Wait => Lang.T("少し待ってからもう一度試してください", "Please wait a moment and try again", "请稍后再试", "請稍後再試", "잠시 후 다시 시도해 주세요"), 
				MsgId.NotEnoughMoney => string.Format(Lang.T("所持金が足りません (送料 ${0})", "Not enough money (fee ${0})", "资金不足(运费 ${0})", "資金不足(運費 ${0})", "돈이 부족합니다 (배송비 ${0})"), arg), 
				MsgId.DroneFailed => Lang.T("配送ドローンを呼べませんでした", "Couldn't call the delivery drone", "无法呼叫配送无人机", "無法呼叫配送無人機", "배송 드론을 부를 수 없습니다"), 
				MsgId.Redelivered => string.Format(Lang.T("「{0}」の物資を再送しました (送料 ${1})", "Redelivered items for \"{0}\" (fee ${1})", "已重新配送「{0}」的物资(运费 ${1})", "已重新配送「{0}」的物資(運費 ${1})", "'{0}' 물자를 재배송했습니다 (배송비 ${1})"), arg, arg2), 
				MsgId.RedeliveredFree => string.Format(Lang.T("「{0}」の物資を再送しました (送料無料)", "Redelivered items for \"{0}\" (free)", "已重新配送「{0}」的物资(免运费)", "已重新配送「{0}」的物資(免運費)", "'{0}' 물자를 재배송했습니다 (무료)"), arg), 
				MsgId.ActionFailed => Lang.T("操作に失敗しました (LogOutput.log を確認してください)", "Action failed (see LogOutput.log)", "操作失败(请查看 LogOutput.log)", "操作失敗(請查看 LogOutput.log)", "작업에 실패했습니다 (LogOutput.log 확인)"), 
				MsgId.DealSucceeded => string.Format(Lang.T("クエスト「{0}」を達成しました。パネル({1})で報酬を受け取れます", "Quest \"{0}\" completed. Claim the reward in the panel ({1})", "任务「{0}」已完成,可在面板({1})中领取奖励", "任務「{0}」已完成,可在面板({1})中領取獎勵", "퀘스트 '{0}' 달성! 패널({1})에서 보상을 받으세요"), arg, arg2), 
				MsgId.DealFailed => string.Format(Lang.T("クエスト「{0}」に失敗しました", "Quest \"{0}\" failed", "任务「{0}」失败", "任務「{0}」失敗", "퀘스트 '{0}' 실패"), arg), 
				_ => string.Empty, 
			};
		}
	}
	internal static class Lang
	{
		internal const string Ja = "ja";

		internal const string En = "en";

		internal const string ZhHans = "zh-Hans";

		internal const string ZhHant = "zh-Hant";

		internal const string Ko = "ko";

		private static readonly string[] Choices = new string[6] { "Auto", "ja", "en", "zh-Hans", "zh-Hant", "ko" };

		private static readonly Dictionary<string, Font> Fonts = new Dictionary<string, Font>();

		private static ConfigEntry<string>? setting;

		private static string current = "en";

		private static float nextCheck = -1f;

		internal static string Current
		{
			get
			{
				if (Time.unscaledTime >= nextCheck)
				{
					nextCheck = Time.unscaledTime + 1f;
					current = Detect();
				}
				return current;
			}
		}

		internal static void Bind(ConfigFile config)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			setting = config.Bind<string>("General", "Language", "Auto", new ConfigDescription("Display language. Auto follows the game's language. / 表示言語。Auto はゲームの言語設定に合わせる", (AcceptableValueBase)(object)new AcceptableValueList<string>(Choices), Array.Empty<object>()));
		}

		internal static string T(string ja, string en, string zhHans, string zhHant, string ko)
		{
			return Current switch
			{
				"ja" => ja, 
				"zh-Hans" => zhHans, 
				"zh-Hant" => zhHant, 
				"ko" => ko, 
				_ => en, 
			};
		}

		internal static Font GetFont()
		{
			string text = Current;
			if (!Fonts.TryGetValue(text, out Font value) || (Object)(object)value == (Object)null)
			{
				value = Font.CreateDynamicFontFromOSFont(FontNames(text), 16);
				Fonts[text] = value;
			}
			return value;
		}

		private static string[] FontNames(string lang)
		{
			return lang switch
			{
				"ja" => new string[8] { "Yu Gothic UI", "Meiryo UI", "Meiryo", "MS UI Gothic", "Microsoft YaHei UI", "Malgun Gothic", "Segoe UI", "Arial" }, 
				"zh-Hans" => new string[8] { "Microsoft YaHei UI", "Microsoft YaHei", "SimHei", "Microsoft JhengHei UI", "Yu Gothic UI", "Malgun Gothic", "Segoe UI", "Arial" }, 
				"zh-Hant" => new string[8] { "Microsoft JhengHei UI", "Microsoft JhengHei", "PMingLiU", "Microsoft YaHei UI", "Yu Gothic UI", "Malgun Gothic", "Segoe UI", "Arial" }, 
				"ko" => new string[6] { "Malgun Gothic", "Gulim", "Yu Gothic UI", "Microsoft YaHei UI", "Segoe UI", "Arial" }, 
				_ => new string[5] { "Segoe UI", "Arial", "Yu Gothic UI", "Microsoft YaHei UI", "Malgun Gothic" }, 
			};
		}

		private static string Detect()
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			string text = setting?.Value ?? "Auto";
			if (string.IsNullOrEmpty(text) || text.Equals("Auto", StringComparison.OrdinalIgnoreCase))
			{
				text = string.Empty;
				try
				{
					Locale selectedLocale = LocalizationSettings.SelectedLocale;
					object obj;
					if (selectedLocale == null)
					{
						obj = null;
					}
					else
					{
						LocaleIdentifier identifier = selectedLocale.Identifier;
						obj = ((LocaleIdentifier)(ref identifier)).Code;
					}
					if (obj == null)
					{
						obj = string.Empty;
					}
					text = (string)obj;
				}
				catch
				{
				}
				if (string.IsNullOrEmpty(text))
				{
					text = FromSystem(Application.systemLanguage);
				}
			}
			return Normalize(text);
		}

		private static string Normalize(string code)
		{
			string text = code.Trim().ToLowerInvariant();
			if (text.StartsWith("ja"))
			{
				return "ja";
			}
			if (text.StartsWith("ko"))
			{
				return "ko";
			}
			if (text.StartsWith("zh"))
			{
				if (!text.Contains("hant") && !text.Contains("tw") && !text.Contains("hk") && !text.Contains("mo"))
				{
					return "zh-Hans";
				}
				return "zh-Hant";
			}
			return "en";
		}

		private static string FromSystem(SystemLanguage language)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Invalid comparison between Unknown and I4
			if ((int)language <= 22)
			{
				if ((int)language == 6)
				{
					goto IL_0033;
				}
				if ((int)language == 22)
				{
					return "ja";
				}
			}
			else
			{
				if ((int)language == 23)
				{
					return "ko";
				}
				if ((int)language == 40)
				{
					goto IL_0033;
				}
				if ((int)language == 41)
				{
					return "zh-Hant";
				}
			}
			return "en";
			IL_0033:
			return "zh-Hans";
		}
	}
}