Decompiled source of BoardRoles v1.2.1

BoardRoles.dll

Decompiled an hour ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.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 BoardRoles
{
	internal class Boards
	{
		private static readonly FieldInfo StickersFI = AccessTools.Field(typeof(OrderStickersDesk), "orderStickers");

		private static readonly FieldInfo PanelFI = AccessTools.Field(typeof(OrderStickersDesk), "stickersPanel");

		private static readonly FieldInfo PrefabFI = AccessTools.Field(typeof(OrderStickersDesk), "orderStickerPrefab");

		private static readonly FieldInfo BgFI = AccessTools.Field(typeof(OrderSticker), "bgImage");

		private static readonly FieldInfo TextFI = AccessTools.Field(typeof(OrderSticker), "stickerText");

		private static readonly MethodInfo OnOrderAddedMI = AccessTools.Method(typeof(OrderStickersDesk), "OnOrderAdded", (Type[])null, (Type[])null);

		private readonly Plugin _p;

		private readonly HashSet<OrderStickersDesk> _desks = new HashSet<OrderStickersDesk>();

		private readonly Dictionary<OrderStickersDesk, TextMeshProUGUI> _plates = new Dictionary<OrderStickersDesk, TextMeshProUGUI>();

		private readonly Dictionary<ushort, Role> _itemRole = new Dictionary<ushort, Role>();

		private string _lastSig = string.Empty;

		private float _nextTick;

		private bool _rebuilding;

		private Role _claimed;

		private Role _onMenu;

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

		private readonly Vector3[] _corners = (Vector3[])(object)new Vector3[4];

		public IEnumerable<OrderStickersDesk> Desks => _desks.Where((OrderStickersDesk d) => (Object)(object)d != (Object)null);

		public Role UnclaimedOnMenu => _onMenu & ~_claimed;

		public Boards(Plugin p)
		{
			_p = p;
		}

		private static List<OrderSticker> StickersRef(OrderStickersDesk o)
		{
			if ((Object)(object)o == (Object)null || StickersFI == null)
			{
				return null;
			}
			return (List<OrderSticker>)StickersFI.GetValue(o);
		}

		private static Transform PanelRef(OrderStickersDesk o)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			if ((Object)(object)o == (Object)null || PanelFI == null)
			{
				return null;
			}
			return (Transform)PanelFI.GetValue(o);
		}

		private static OrderSticker PrefabRef(OrderStickersDesk o)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			if ((Object)(object)o == (Object)null || PrefabFI == null)
			{
				return null;
			}
			return (OrderSticker)PrefabFI.GetValue(o);
		}

		private static Image BgRef(OrderSticker o)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			if ((Object)(object)o == (Object)null || BgFI == null)
			{
				return null;
			}
			return (Image)BgFI.GetValue(o);
		}

		private static TextMeshProUGUI TextRef(OrderSticker o)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			if ((Object)(object)o == (Object)null || TextFI == null)
			{
				return null;
			}
			return (TextMeshProUGUI)TextFI.GetValue(o);
		}

		public void OnDeskSpawn(OrderStickersDesk d)
		{
			_desks.Add(d);
			_lastSig = string.Empty;
		}

		public void OnDeskDespawn(OrderStickersDesk d)
		{
			_desks.Remove(d);
			if (_plates.TryGetValue(d, out var value))
			{
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)value).gameObject);
				}
				_plates.Remove(d);
			}
		}

		public static string KeyOf(OrderStickersDesk d)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)d).transform.position;
			return Mathf.Round(position.x * 10f) / 10f + "," + Mathf.Round(position.y * 10f) / 10f + "," + Mathf.Round(position.z * 10f) / 10f;
		}

		public void Tick()
		{
			if (Time.unscaledTime < _nextTick)
			{
				return;
			}
			_nextTick = Time.unscaledTime + 0.5f;
			_desks.RemoveWhere((OrderStickersDesk d) => (Object)(object)d == (Object)null);
			if ((Object)(object)GameStatus.Instance == (Object)null)
			{
				_itemRole.Clear();
				return;
			}
			_present = Net.PresentPlayers();
			_claimed = Role.None;
			foreach (string item in _present)
			{
				_claimed |= _p.State.RolesOf(item);
			}
			_onMenu = MenuRoles();
			string[] obj = new string[7]
			{
				_p.State.Version.ToString(),
				"|",
				string.Join(",", _present.ToArray()),
				"|",
				null,
				null,
				null
			};
			int onMenu = (int)_onMenu;
			obj[4] = onMenu.ToString();
			obj[5] = "|";
			obj[6] = _desks.Count.ToString();
			string text = string.Concat(obj);
			if (text != _lastSig)
			{
				_lastSig = text;
				foreach (OrderStickersDesk desk in Desks)
				{
					Rebuild(desk);
				}
			}
			foreach (OrderStickersDesk desk2 in Desks)
			{
				PlacePlate(desk2);
			}
		}

		public Role RoleOfItem(ushort itemId)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if (_itemRole.TryGetValue(itemId, out var value))
			{
				return value;
			}
			value = Role.None;
			try
			{
				RecipeData val = default(RecipeData);
				if ((Object)(object)RecipeManager.Instance != (Object)null && RecipeManager.Instance.GetRecipeDataByProductItemDataId(itemId, ref val) && (Object)(object)val != (Object)null)
				{
					value = Roles.FromRecipeType(val.type);
				}
			}
			catch
			{
			}
			if ((Object)(object)RecipeManager.Instance != (Object)null)
			{
				_itemRole[itemId] = value;
			}
			return value;
		}

		private Role MenuRoles()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			Role role = Role.None;
			try
			{
				RecipeManager instance = RecipeManager.Instance;
				if ((Object)(object)instance == (Object)null || instance.menuRecipes == null)
				{
					return role;
				}
				for (int i = 0; i < instance.menuRecipes.Count; i++)
				{
					RecipeData recipeDataById = instance.GetRecipeDataById(instance.menuRecipes[i]);
					if ((Object)(object)recipeDataById != (Object)null)
					{
						role |= Roles.FromRecipeType(recipeDataById.type);
					}
				}
			}
			catch
			{
			}
			return role;
		}

		private string Owner(OrderStickersDesk d)
		{
			return _p.State.BoardOwner(KeyOf(d));
		}

		public bool ShouldShow(OrderStickersDesk d, ushort itemId, out bool unclaimed)
		{
			Role role = RoleOfItem(itemId);
			unclaimed = role != Role.None && (_claimed & role) == 0;
			string text = Owner(d);
			if (text == null || !_present.Contains(text))
			{
				return true;
			}
			if ((role == Role.None) | unclaimed)
			{
				return true;
			}
			return (_p.State.RolesOf(text) & role) != 0;
		}

		public void TintLast(OrderStickersDesk d)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			if (!_p.TintUnclaimed.Value)
			{
				return;
			}
			List<OrderSticker> list = StickersRef(d);
			if (list == null || list.Count == 0)
			{
				return;
			}
			OrderSticker val = list[list.Count - 1];
			if (!((Object)(object)val == (Object)null))
			{
				Image val2 = BgRef(val);
				if ((Object)(object)val2 != (Object)null)
				{
					((Graphic)val2).color = new Color(1f, 0.62f, 0.55f, ((Graphic)val2).color.a);
				}
			}
		}

		public List<OrderSticker> StickersOf(OrderStickersDesk d)
		{
			return StickersRef(d);
		}

		private void Rebuild(OrderStickersDesk d)
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			if (_rebuilding || (Object)(object)d == (Object)null || (Object)(object)OrdersManager.Instance == (Object)null || OnOrderAddedMI == null)
			{
				return;
			}
			_rebuilding = true;
			try
			{
				List<OrderSticker> list = StickersRef(d);
				if (list != null)
				{
					foreach (OrderSticker item in list)
					{
						if ((Object)(object)item != (Object)null)
						{
							Object.Destroy((Object)(object)((Component)item).gameObject);
						}
					}
					list.Clear();
				}
				NetworkList<V3Ushort> clientOrders = OrdersManager.Instance.clientOrders;
				for (int i = 0; i < clientOrders.Count; i++)
				{
					V3Ushort val = clientOrders[i];
					OnOrderAddedMI.Invoke(d, new object[2]
					{
						val.y,
						val.z != 0
					});
				}
				UpdatePlate(d);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Rebuild failed: " + ex));
			}
			finally
			{
				_rebuilding = false;
			}
		}

		private void UpdatePlate(OrderStickersDesk d)
		{
			TextMeshProUGUI plate = GetPlate(d);
			if ((Object)(object)plate == (Object)null)
			{
				return;
			}
			string text = Owner(d);
			StringBuilder stringBuilder = new StringBuilder();
			if (text == null)
			{
				stringBuilder.Append("<size=75%>Everyone</size>");
			}
			else
			{
				bool num = _present.Contains(text);
				stringBuilder.Append("<b>").Append(text).Append("</b>");
				if (!num)
				{
					stringBuilder.Append(" <size=70%>(not here, showing all)</size>");
				}
				stringBuilder.Append("\n<size=70%>").Append(Roles.List(_p.State.RolesOf(text))).Append("</size>");
			}
			Role unclaimedOnMenu = UnclaimedOnMenu;
			if (unclaimedOnMenu != Role.None)
			{
				stringBuilder.Append("\n<color=#FF6A50><size=70%>Nobody is on: ").Append(Roles.List(unclaimedOnMenu)).Append("</size></color>");
			}
			((TMP_Text)plate).text = stringBuilder.ToString();
		}

		private TextMeshProUGUI GetPlate(OrderStickersDesk d)
		{
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			if (_plates.TryGetValue(d, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			Transform val = PanelRef(d);
			if ((Object)(object)val == (Object)null || (Object)(object)val.parent == (Object)null)
			{
				return null;
			}
			GameObject val2 = new GameObject("BoardRolesNameplate", new Type[1] { typeof(RectTransform) });
			val2.transform.SetParent(val.parent, false);
			val2.layer = ((Component)val).gameObject.layer;
			val2.AddComponent<LayoutElement>().ignoreLayout = true;
			value = val2.AddComponent<TextMeshProUGUI>();
			((TMP_Text)value).alignment = (TextAlignmentOptions)1026;
			((TMP_Text)value).enableWordWrapping = false;
			((TMP_Text)value).overflowMode = (TextOverflowModes)0;
			((Graphic)value).raycastTarget = false;
			TextMeshProUGUI val3 = null;
			try
			{
				OrderSticker val4 = PrefabRef(d);
				if ((Object)(object)val4 != (Object)null)
				{
					val3 = TextRef(val4);
				}
			}
			catch
			{
			}
			if ((Object)(object)val3 != (Object)null)
			{
				((TMP_Text)value).font = ((TMP_Text)val3).font;
				((TMP_Text)value).fontSharedMaterial = ((TMP_Text)val3).fontSharedMaterial;
				((Graphic)value).color = ((Graphic)val3).color;
				((TMP_Text)value).fontSize = ((TMP_Text)val3).fontSize * _p.NameplateTextScale.Value;
			}
			else
			{
				((TMP_Text)value).fontSize = 36f;
			}
			_plates[d] = value;
			PlacePlate(d);
			return value;
		}

		private void PlacePlate(OrderStickersDesk d)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00a9: 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)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: 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_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			if (_plates.TryGetValue(d, out var value) && !((Object)(object)value == (Object)null))
			{
				Transform val = PanelRef(d);
				RectTransform val2 = ((!((Object)(object)val != (Object)null)) ? null : ((Component)val).GetComponent<RectTransform>());
				Transform parent = ((Transform)((TMP_Text)value).rectTransform).parent;
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)parent == (Object)null))
				{
					val2.GetWorldCorners(_corners);
					Vector3 val3 = parent.InverseTransformPoint(_corners[1]);
					Vector3 val4 = parent.InverseTransformPoint(_corners[2]);
					RectTransform rectTransform = ((TMP_Text)value).rectTransform;
					Vector2 val5 = default(Vector2);
					((Vector2)(ref val5))..ctor(0.5f, 0.5f);
					rectTransform.anchorMax = val5;
					Vector2 anchorMin = val5;
					rectTransform.anchorMin = anchorMin;
					rectTransform.pivot = new Vector2(0.5f, 0f);
					rectTransform.sizeDelta = new Vector2(Mathf.Max(100f, Mathf.Abs(val4.x - val3.x)), 10f);
					((Transform)rectTransform).localPosition = (val3 + val4) * 0.5f + new Vector3(0f, _p.NameplateOffset.Value, 0f);
					((Transform)rectTransform).localRotation = Quaternion.identity;
					((Transform)rectTransform).localScale = Vector3.one;
				}
			}
		}

		public OrderStickersDesk FindLookedAtDesk()
		{
			//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_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			Camera main = Camera.main;
			if ((Object)(object)main == (Object)null)
			{
				return null;
			}
			OrderStickersDesk result = null;
			float num = _p.InteractAngle.Value;
			foreach (OrderStickersDesk desk in Desks)
			{
				Vector3 val = ((Component)desk).transform.position;
				Transform val2 = PanelRef(desk);
				RectTransform val3 = ((!((Object)(object)val2 != (Object)null)) ? null : ((Component)val2).GetComponent<RectTransform>());
				if ((Object)(object)val3 != (Object)null)
				{
					val3.GetWorldCorners(_corners);
					val = (_corners[0] + _corners[2]) * 0.5f;
				}
				Vector3 val4 = val - ((Component)main).transform.position;
				if (!(((Vector3)(ref val4)).magnitude > _p.InteractDistance.Value))
				{
					float num2 = Vector3.Angle(((Component)main).transform.forward, val4);
					if (num2 < num)
					{
						num = num2;
						result = desk;
					}
				}
			}
			return result;
		}
	}
	[HarmonyPatch(typeof(OrderStickersDesk), "OnNetworkSpawn")]
	internal static class DeskSpawnPatch
	{
		private static void Postfix(OrderStickersDesk __instance)
		{
			Plugin.Inst.Boards.OnDeskSpawn(__instance);
		}
	}
	[HarmonyPatch(typeof(OrderStickersDesk), "OnNetworkDespawn")]
	internal static class DeskDespawnPatch
	{
		private static void Prefix(OrderStickersDesk __instance)
		{
			Plugin.Inst.Boards.OnDeskDespawn(__instance);
		}
	}
	[HarmonyPatch(typeof(OrderStickersDesk), "OnOrderAdded")]
	internal static class OrderAddedPatch
	{
		private static bool Prefix(OrderStickersDesk __instance, ushort itemId, ref int __state)
		{
			__state = -1;
			try
			{
				if (!Plugin.Inst.Boards.ShouldShow(__instance, itemId, out var unclaimed))
				{
					return false;
				}
				if (unclaimed)
				{
					__state = Plugin.Inst.Boards.StickersOf(__instance)?.Count ?? (-1);
				}
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)ex);
				return true;
			}
		}

		private static void Postfix(OrderStickersDesk __instance, int __state)
		{
			if (__state < 0)
			{
				return;
			}
			try
			{
				List<OrderSticker> list = Plugin.Inst.Boards.StickersOf(__instance);
				if (list != null && list.Count > __state)
				{
					Plugin.Inst.Boards.TintLast(__instance);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)ex);
			}
		}
	}
	internal class Net
	{
		private const string MsgReq = "BoardRoles/Req";

		private const string MsgRoles = "BoardRoles/SetRoles";

		private const string MsgBoard = "BoardRoles/SetBoard";

		private const string MsgState = "BoardRoles/State";

		private readonly Plugin _p;

		private NetworkManager _registeredOn;

		private bool _inSession;

		private float _reqSentAt;

		private bool _gotHostState;

		private string _tavern;

		private bool _hostChanged;

		private float _nextNameCheck;

		private int _reqTries;

		public bool LocalOnly { get; private set; }

		private static NetworkManager NM => NetworkManager.Singleton;

		public bool IsHost
		{
			get
			{
				if ((Object)(object)NM != (Object)null)
				{
					return NM.IsServer;
				}
				return false;
			}
		}

		public bool Ready
		{
			get
			{
				if ((Object)(object)NM != (Object)null && NM.IsListening && NM.CustomMessagingManager != null && (Object)(object)GameStatus.Instance != (Object)null)
				{
					return (Object)(object)PlayerManager.Instance != (Object)null;
				}
				return false;
			}
		}

		public Net(Plugin p)
		{
			_p = p;
		}

		public void Tick()
		{
			if (!Ready)
			{
				if (_inSession)
				{
					EndSession();
				}
				return;
			}
			if (!_inSession || (Object)(object)_registeredOn != (Object)(object)NM)
			{
				StartSession();
			}
			if (!IsHost && !_gotHostState && !LocalOnly && Time.unscaledTime - _reqSentAt > 3f)
			{
				if (_reqTries >= 3)
				{
					LocalOnly = true;
					Plugin.Log.LogWarning((object)"Host didn't answer. The host probably doesn't have Board Roles, so assignments stay on this computer only.");
				}
				else
				{
					SendReq();
				}
			}
			if (IsHost && !_hostChanged && Time.unscaledTime > _nextNameCheck)
			{
				_nextNameCheck = Time.unscaledTime + 2f;
				string text = TavernName();
				if (text != _tavern)
				{
					_tavern = text;
					_p.State.LoadFor(_tavern);
					Broadcast();
				}
			}
		}

		private void StartSession()
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Expected O, but got Unknown
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Expected O, but got Unknown
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Expected O, but got Unknown
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Expected O, but got Unknown
			_inSession = true;
			_registeredOn = NM;
			_gotHostState = false;
			LocalOnly = false;
			_reqSentAt = 0f;
			_reqTries = 0;
			_hostChanged = false;
			_nextNameCheck = 0f;
			CustomMessagingManager customMessagingManager = NM.CustomMessagingManager;
			string[] array = new string[4] { "BoardRoles/Req", "BoardRoles/SetRoles", "BoardRoles/SetBoard", "BoardRoles/State" };
			foreach (string text in array)
			{
				try
				{
					customMessagingManager.UnregisterNamedMessageHandler(text);
				}
				catch
				{
				}
			}
			customMessagingManager.RegisterNamedMessageHandler("BoardRoles/Req", new HandleNamedMessageDelegate(OnReq));
			customMessagingManager.RegisterNamedMessageHandler("BoardRoles/SetRoles", new HandleNamedMessageDelegate(OnSetRoles));
			customMessagingManager.RegisterNamedMessageHandler("BoardRoles/SetBoard", new HandleNamedMessageDelegate(OnSetBoard));
			customMessagingManager.RegisterNamedMessageHandler("BoardRoles/State", new HandleNamedMessageDelegate(OnState));
			if (IsHost)
			{
				_tavern = TavernName();
				_p.State.LoadFor(_tavern);
			}
			else
			{
				_p.State.Replace(new Assignments());
			}
		}

		private void EndSession()
		{
			_inSession = false;
			_registeredOn = null;
			_p.State.Replace(new Assignments());
		}

		public void RequestSetRoles(Role mask)
		{
			string player = LocalName();
			if (IsHost || LocalOnly)
			{
				ApplyRoles(player, mask);
				return;
			}
			int num = (int)mask;
			Send("BoardRoles/SetRoles", num.ToString(), 0uL);
		}

		public void RequestSetBoard(string key, string player)
		{
			if (IsHost || LocalOnly)
			{
				ApplyBoard(key, player);
			}
			else
			{
				Send("BoardRoles/SetBoard", key + "|" + (player ?? string.Empty), 0uL);
			}
		}

		private void ApplyRoles(string player, Role mask)
		{
			_p.State.SetRoles(player, mask);
			AfterHostChange();
		}

		private void ApplyBoard(string key, string player)
		{
			_p.State.SetBoard(key, player);
			AfterHostChange();
		}

		private void AfterHostChange()
		{
			if (IsHost)
			{
				_hostChanged = true;
				_p.State.SaveFor(_tavern);
				Broadcast();
			}
		}

		public void Broadcast()
		{
			if (IsHost && Ready)
			{
				string payload = JsonConvert.SerializeObject((object)_p.State.Current);
				List<ulong> list = NM.ConnectedClientsIds.Where((ulong id) => id != NM.LocalClientId).ToList();
				if (list.Count > 0)
				{
					Send("BoardRoles/State", payload, list);
				}
			}
		}

		private void OnReq(ulong sender, FastBufferReader r)
		{
			if (IsHost)
			{
				Send("BoardRoles/State", JsonConvert.SerializeObject((object)_p.State.Current), sender);
			}
		}

		private void OnSetRoles(ulong sender, FastBufferReader r)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (IsHost && int.TryParse(Read(r), out var result))
			{
				ApplyRoles(NameOf(sender), (Role)result);
			}
		}

		private void OnSetBoard(ulong sender, FastBufferReader r)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (IsHost)
			{
				string text = Read(r);
				int num = text.LastIndexOf('|');
				if (num > 0)
				{
					ApplyBoard(text.Substring(0, num), text.Substring(num + 1));
				}
			}
		}

		private void OnState(ulong sender, FastBufferReader r)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (IsHost)
			{
				return;
			}
			try
			{
				_p.State.Replace(JsonConvert.DeserializeObject<Assignments>(Read(r)));
				_gotHostState = true;
				LocalOnly = false;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Bad state from host: " + ex.Message));
			}
		}

		private void SendReq()
		{
			_reqSentAt = Time.unscaledTime;
			_reqTries++;
			Send("BoardRoles/Req", string.Empty, 0uL);
		}

		private static string Read(FastBufferReader r)
		{
			string text = default(string);
			((FastBufferReader)(ref r)).ReadValueSafe(ref text, false);
			return text ?? string.Empty;
		}

		private unsafe static void Send(string msg, string payload, ulong to)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				int num = FastBufferWriter.GetWriteSize(payload, false) + 16;
				FastBufferWriter val = default(FastBufferWriter);
				((FastBufferWriter)(ref val))..ctor(num, (Allocator)2, Math.Max(num, 65536));
				try
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(payload, false);
					NM.CustomMessagingManager.SendNamedMessage(msg, to, val, (NetworkDelivery)4);
				}
				finally
				{
					((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Send " + msg + " failed: " + ex.Message));
			}
		}

		private unsafe static void Send(string msg, string payload, List<ulong> to)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				int num = FastBufferWriter.GetWriteSize(payload, false) + 16;
				FastBufferWriter val = default(FastBufferWriter);
				((FastBufferWriter)(ref val))..ctor(num, (Allocator)2, Math.Max(num, 65536));
				try
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(payload, false);
					NM.CustomMessagingManager.SendNamedMessage(msg, (IReadOnlyList<ulong>)to, val, (NetworkDelivery)4);
				}
				finally
				{
					((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Send " + msg + " failed: " + ex.Message));
			}
		}

		public static string NameOf(ulong clientId)
		{
			try
			{
				return PlayerManager.Instance.GetPlayerName(clientId);
			}
			catch
			{
				return "Player " + clientId;
			}
		}

		public static string LocalName()
		{
			if ((Object)(object)NM != (Object)null)
			{
				return NameOf(NM.LocalClientId);
			}
			return null;
		}

		public static List<string> PresentPlayers()
		{
			List<string> list = new List<string>();
			try
			{
				foreach (ulong item in PlayerManager.Instance.players.Keys.OrderBy((ulong k) => k))
				{
					string text = NameOf(item);
					if (!string.IsNullOrEmpty(text) && !list.Contains(text))
					{
						list.Add(text);
					}
				}
			}
			catch
			{
			}
			return list;
		}

		private static string TavernName()
		{
			try
			{
				FieldInfo field = typeof(GameStatus).GetField("tavernName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				object obj = ((!(field != null)) ? null : field.GetValue(GameStatus.Instance));
				if (obj == null)
				{
					return string.Empty;
				}
				PropertyInfo property = obj.GetType().GetProperty("Value");
				object obj2 = ((!(property != null)) ? obj : property.GetValue(obj, null));
				return (obj2 == null) ? string.Empty : obj2.ToString();
			}
			catch
			{
				return string.Empty;
			}
		}
	}
	[BepInPlugin("aletale.boardroles", "Board Roles", "1.2.1")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "aletale.boardroles";

		public const string Name = "Board Roles";

		public const string Version = "1.2.1";

		internal static Plugin Inst;

		internal static ManualLogSource Log;

		internal ConfigEntry<KeyCode> InteractKey;

		internal ConfigEntry<KeyCode> RolesKey;

		internal ConfigEntry<float> InteractDistance;

		internal ConfigEntry<float> InteractAngle;

		internal ConfigEntry<float> NameplateOffset;

		internal ConfigEntry<float> NameplateTextScale;

		internal ConfigEntry<bool> TintUnclaimed;

		internal RolesState State;

		internal Net Net;

		internal Boards Boards;

		internal RolesUI UI;

		private void Awake()
		{
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			Inst = this;
			Log = ((BaseUnityPlugin)this).Logger;
			InteractKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "BoardKey", (KeyCode)101, "Press while looking at an order board to assign it.");
			RolesKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "RolesKey", (KeyCode)288, "Open the roles window from anywhere.");
			InteractDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Board", "InteractDistance", 4f, "How close you need to be to an order board (meters).");
			InteractAngle = ((BaseUnityPlugin)this).Config.Bind<float>("Board", "InteractAngle", 15f, "How directly you need to look at the board (degrees).");
			NameplateOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Board", "NameplateOffset", 30f, "Gap between the top of the stickers and the name, in board units. Raise it if the name overlaps stickers.");
			NameplateTextScale = ((BaseUnityPlugin)this).Config.Bind<float>("Board", "NameplateTextScale", 1.4f, "Name text size relative to sticker text.");
			TintUnclaimed = ((BaseUnityPlugin)this).Config.Bind<bool>("Board", "TintUnclaimed", true, "Tint stickers for orders nobody has a role for.");
			State = new RolesState(Path.Combine(Paths.ConfigPath, "BoardRoles_saved.json"));
			Net = new Net(this);
			Boards = new Boards(this);
			UI = new RolesUI(this);
			new Harmony("aletale.boardroles").PatchAll(typeof(Plugin).Assembly);
			Log.LogInfo((object)"Board Roles 1.2.1 loaded");
		}

		private void Update()
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Net.Tick();
				Boards.Tick();
				if (!UI.IsOpen)
				{
					if (!RolesUI.PlayerIsFree())
					{
						return;
					}
					if (Input.GetKeyDown(InteractKey.Value))
					{
						OrderStickersDesk val = Boards.FindLookedAtDesk();
						if ((Object)(object)val != (Object)null)
						{
							UI.OpenForBoard(val);
						}
					}
					else if (Input.GetKeyDown(RolesKey.Value) && (Object)(object)Game.Instance != (Object)null)
					{
						UI.OpenRoles();
					}
				}
				else if (Input.GetKeyDown((KeyCode)27) || Input.GetKeyDown(RolesKey.Value))
				{
					UI.Close();
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)ex);
			}
		}

		private void LateUpdate()
		{
			UI.LateUpdate();
		}

		private void OnGUI()
		{
			UI.Draw();
		}
	}
	internal class RolesUI
	{
		private readonly Plugin _p;

		private OrderStickersDesk _desk;

		private bool _open;

		private Rect _win = new Rect(0f, 0f, 420f, 10f);

		private CursorLockMode _prevLock;

		private bool _prevVisible;

		private GUIStyle _h;

		private GUIStyle _small;

		private GUIStyle _warn;

		private GUIStyle _sel;

		private bool _wasBoard;

		private bool _blocking;

		private bool _restorePending;

		public bool IsOpen => _open;

		public RolesUI(Plugin p)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			_p = p;
		}

		public void OpenForBoard(OrderStickersDesk d)
		{
			_desk = d;
			Open();
		}

		public void OpenRoles()
		{
			_desk = null;
			Open();
		}

		internal static bool PlayerIsFree()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			PlayerInventory instance = PlayerInventory.Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				return (int)instance.state == 0;
			}
			return true;
		}

		private void Open()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			_open = true;
			_wasBoard = (Object)(object)_desk != (Object)null;
			_prevLock = Cursor.lockState;
			_prevVisible = Cursor.visible;
			_win = new Rect((float)Screen.width / 2f - 210f, (float)Screen.height / 2f - 200f, 420f, 10f);
			_restorePending = false;
			_blocking = false;
			PlayerInventory instance = PlayerInventory.Instance;
			if ((Object)(object)instance != (Object)null && (int)instance.state == 0)
			{
				instance.SetState((State)1);
				_blocking = true;
			}
		}

		public void Close()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			_open = false;
			_desk = null;
			Cursor.lockState = _prevLock;
			Cursor.visible = _prevVisible;
			if (_blocking)
			{
				_restorePending = true;
			}
			_blocking = false;
		}

		public void LateUpdate()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Invalid comparison between Unknown and I4
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Invalid comparison between Unknown and I4
			if (_restorePending)
			{
				_restorePending = false;
				PlayerInventory instance = PlayerInventory.Instance;
				if ((Object)(object)instance != (Object)null && (int)instance.state == 1)
				{
					instance.SetState((State)0);
				}
			}
			if (!_open)
			{
				return;
			}
			if ((Object)(object)Game.Instance == (Object)null || ((Object)(object)_desk == (Object)null && _wasBoard))
			{
				Close();
				return;
			}
			if (_blocking)
			{
				PlayerInventory instance2 = PlayerInventory.Instance;
				if ((Object)(object)instance2 == (Object)null || (int)instance2.state != 1)
				{
					_blocking = false;
					Close();
					return;
				}
			}
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
		}

		public void Draw()
		{
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Expected O, but got Unknown
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			if (_open)
			{
				if (_h == null)
				{
					_h = new GUIStyle(GUI.skin.label)
					{
						fontSize = 15,
						fontStyle = (FontStyle)1
					};
					_small = new GUIStyle(GUI.skin.label)
					{
						fontSize = 12,
						wordWrap = true
					};
					_warn = new GUIStyle(_small);
					_warn.normal.textColor = new Color(1f, 0.5f, 0.42f);
					_sel = new GUIStyle(GUI.skin.button)
					{
						fontStyle = (FontStyle)1
					};
					_sel.normal.textColor = new Color(1f, 0.85f, 0.4f);
				}
				_wasBoard = (Object)(object)_desk != (Object)null;
				_win = GUILayout.Window(723501, _win, new WindowFunction(Window), (!((Object)(object)_desk != (Object)null)) ? "Kitchen roles" : "Order board", Array.Empty<GUILayoutOption>());
			}
		}

		private void Window(int id)
		{
			//IL_0379: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = Net.PresentPlayers();
			string text = Net.LocalName();
			if ((Object)(object)_desk != (Object)null)
			{
				string key = Boards.KeyOf(_desk);
				string text2 = _p.State.BoardOwner(key);
				GUILayout.Label("Whose board is this?", _h, Array.Empty<GUILayoutOption>());
				GUILayout.Label("The board shows that player's orders, plus anything nobody has a role for.", _small, Array.Empty<GUILayoutOption>());
				if (GUILayout.Button("Everyone (show all orders)", (text2 != null) ? GUI.skin.button : _sel, Array.Empty<GUILayoutOption>()))
				{
					_p.Net.RequestSetBoard(key, null);
				}
				foreach (string item in list)
				{
					if (GUILayout.Button(item + "   (" + Roles.List(_p.State.RolesOf(item)) + ")", (!(item == text2)) ? GUI.skin.button : _sel, Array.Empty<GUILayoutOption>()))
					{
						_p.Net.RequestSetBoard(key, item);
					}
				}
				if (text2 != null && !list.Contains(text2))
				{
					GUILayout.Label("Currently assigned to " + text2 + ", who isn't in the game. It shows all orders until they're back.", _small, Array.Empty<GUILayoutOption>());
				}
				GUILayout.Space(10f);
			}
			GUILayout.Label("Your roles" + ((!string.IsNullOrEmpty(text)) ? (" (" + text + ")") : string.Empty), _h, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Pick any number. Two people can share a role.", _small, Array.Empty<GUILayoutOption>());
			Role role = _p.State.RolesOf(text);
			Role[] all = Roles.All;
			foreach (Role role2 in all)
			{
				bool flag = (role & role2) != 0;
				bool flag2 = GUILayout.Toggle(flag, " " + Roles.Label(role2) + "  (" + Roles.Hint(role2) + ")", Array.Empty<GUILayoutOption>());
				if (flag2 != flag)
				{
					_p.Net.RequestSetRoles((!flag2) ? (role & ~role2) : (role | role2));
				}
			}
			GUILayout.Space(8f);
			GUILayout.Label("Everyone", _h, Array.Empty<GUILayoutOption>());
			foreach (string item2 in list)
			{
				GUILayout.Label(item2 + ": " + Roles.List(_p.State.RolesOf(item2)), _small, Array.Empty<GUILayoutOption>());
			}
			Role unclaimedOnMenu = _p.Boards.UnclaimedOnMenu;
			if (unclaimedOnMenu != Role.None)
			{
				GUILayout.Label("Nobody is on: " + Roles.List(unclaimedOnMenu) + ". Those orders go to every board.", _warn, Array.Empty<GUILayoutOption>());
			}
			if (_p.Net.LocalOnly)
			{
				GUILayout.Label("The host doesn't have Board Roles, so these settings only apply on your screen.", _warn, Array.Empty<GUILayoutOption>());
			}
			GUILayout.Space(6f);
			if (GUILayout.Button("Close (Esc)", Array.Empty<GUILayoutOption>()))
			{
				Close();
			}
			GUI.DragWindow(new Rect(0f, 0f, 10000f, 22f));
		}
	}
	[Flags]
	public enum Role
	{
		None = 0,
		FryCook = 1,
		SoupCook = 2,
		Baker = 4,
		Bartender = 8,
		Grinder = 0x10
	}
	public static class Roles
	{
		public static readonly Role[] All = new Role[5]
		{
			Role.FryCook,
			Role.SoupCook,
			Role.Baker,
			Role.Bartender,
			Role.Grinder
		};

		public static string Label(Role r)
		{
			return r switch
			{
				Role.FryCook => "Fry cook", 
				Role.SoupCook => "Soup cook", 
				Role.Baker => "Baker", 
				Role.Bartender => "Bartender", 
				Role.Grinder => "Grinder", 
				_ => r.ToString(), 
			};
		}

		public static string Hint(Role r)
		{
			return r switch
			{
				Role.FryCook => "fried dishes", 
				Role.SoupCook => "soups, stews, boiled dishes", 
				Role.Baker => "breads, pies, baked dishes", 
				Role.Bartender => "drinks", 
				Role.Grinder => "tartars, applesauce, candies", 
				_ => string.Empty, 
			};
		}

		public static string List(Role mask)
		{
			string[] array = All.Where((Role r) => (mask & r) != 0).Select(Label).ToArray();
			if (array.Length == 0)
			{
				return "no roles";
			}
			return string.Join(", ", array);
		}

		public static Role FromRecipeType(Type t)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected I4, but got Unknown
			return (t - 1) switch
			{
				1 => Role.FryCook, 
				0 => Role.SoupCook, 
				2 => Role.Baker, 
				3 => Role.Bartender, 
				4 => Role.Grinder, 
				_ => Role.None, 
			};
		}
	}
	public class Assignments
	{
		public Dictionary<string, string> Boards = new Dictionary<string, string>();

		public Dictionary<string, int> Roles = new Dictionary<string, int>();
	}
	public class RolesState
	{
		public Assignments Current = new Assignments();

		public int Version;

		private readonly string _path;

		private Dictionary<string, Assignments> _saved = new Dictionary<string, Assignments>();

		public RolesState(string path)
		{
			_path = path;
			try
			{
				if (File.Exists(path))
				{
					_saved = JsonConvert.DeserializeObject<Dictionary<string, Assignments>>(File.ReadAllText(path)) ?? _saved;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not read saved roles: " + ex.Message));
			}
		}

		public Role RolesOf(string player)
		{
			if (player == null || !Current.Roles.TryGetValue(player, out var value))
			{
				return Role.None;
			}
			return (Role)value;
		}

		public string BoardOwner(string key)
		{
			if (key != null && Current.Boards.TryGetValue(key, out var value))
			{
				return value;
			}
			return null;
		}

		public void SetRoles(string player, Role mask)
		{
			if (!string.IsNullOrEmpty(player))
			{
				Current.Roles[player] = (int)mask;
				Version++;
			}
		}

		public void SetBoard(string key, string player)
		{
			if (!string.IsNullOrEmpty(key))
			{
				if (string.IsNullOrEmpty(player))
				{
					Current.Boards.Remove(key);
				}
				else
				{
					Current.Boards[key] = player;
				}
				Version++;
			}
		}

		public void Replace(Assignments a)
		{
			Current = a ?? new Assignments();
			Version++;
		}

		public void LoadFor(string tavern)
		{
			Current = ((!_saved.TryGetValue(tavern ?? string.Empty, out var value)) ? new Assignments() : value);
			Version++;
		}

		public void SaveFor(string tavern)
		{
			_saved[tavern ?? string.Empty] = Current;
			try
			{
				string text = _path + ".tmp";
				File.WriteAllText(text, JsonConvert.SerializeObject((object)_saved, (Formatting)1));
				if (File.Exists(_path))
				{
					File.Delete(_path);
				}
				File.Move(text, _path);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not save roles: " + ex.Message));
			}
		}
	}
}