Decompiled source of LycansDeadVoice v1.0.1

plugins/LycansMod.DeadVoice.dll

Decompiled 12 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Fusion;
using LycansMods.Shared;
using Microsoft.CodeAnalysis;
using On;
using Photon.Realtime;
using Photon.Voice;
using TMPro;
using UnityEngine;
using UnityEngine.Localization;
using UnityEngine.Localization.Settings;
using UnityEngine.Localization.Tables;
using UnityEngine.Networking;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("LycansMod.DeadVoice")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+9f1127ee94e580dfff5f8f337ace05459408f4d4")]
[assembly: AssemblyProduct("LycansMod.DeadVoice")]
[assembly: AssemblyTitle("LycansMod.DeadVoice")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[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 LycansMods.Shared
{
	public static class AbilityHud
	{
		private sealed class Watcher : MonoBehaviour
		{
			private void LateUpdate()
			{
				if ((Object)(object)_root != (Object)null && ((Component)_root).gameObject.activeSelf && Time.unscaledTime - _shownAt > 0.25f)
				{
					((Component)_root).gameObject.SetActive(false);
				}
			}
		}

		private static RectTransform _root;

		private static Image _ring;

		private static TextMeshProUGUI _icon;

		private static TextMeshProUGUI _title;

		private static TextMeshProUGUI _detail;

		private static TextMeshProUGUI _badge;

		private static GameObject _badgeGo;

		private static float _shownAt;

		private static Sprite _circle;

		public static void Show(string icon, string title, string detail, Color color, float fill, string badge = null)
		{
			//IL_0042: 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_005e: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			if (Build())
			{
				_shownAt = Time.unscaledTime;
				((Component)_root).gameObject.SetActive(true);
				Place();
				((TMP_Text)_icon).text = icon;
				((TMP_Text)_title).text = title;
				((Graphic)_title).color = color;
				((TMP_Text)_detail).text = detail;
				((Graphic)_ring).color = new Color(color.r, color.g, color.b, (fill >= 0.999f) ? 1f : 0.85f);
				_ring.fillAmount = Mathf.Clamp01(fill);
				((Graphic)_icon).color = (Color)((fill >= 0.999f) ? Color.white : new Color(1f, 1f, 1f, 0.55f));
				_badgeGo.SetActive(!string.IsNullOrEmpty(badge));
				if (_badgeGo.activeSelf)
				{
					((TMP_Text)_badge).text = badge;
				}
			}
		}

		private static bool Build()
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: 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_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_0372: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03df: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fd: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_root != (Object)null)
			{
				return true;
			}
			GameUI val = (((Object)(object)GameManager.Instance != (Object)null) ? GameManager.Instance.gameUI : null);
			RectTransform val2 = Anchor(val);
			if ((Object)(object)val2 == (Object)null || (Object)(object)((Transform)val2).parent == (Object)null)
			{
				return false;
			}
			TMP_FontAsset font = (((Object)(object)val.actionShortcut != (Object)null && (Object)(object)((Component)val.actionShortcut).GetComponent<TextMeshProUGUI>() != (Object)null) ? ((TMP_Text)((Component)val.actionShortcut).GetComponent<TextMeshProUGUI>()).font : null);
			_root = new GameObject("LycansAbilityHud", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
			((Transform)_root).SetParent(((Transform)val2).parent, false);
			((Component)_root).gameObject.AddComponent<Watcher>();
			_root.sizeDelta = new Vector2(330f, 64f);
			RectTransform root = _root;
			RectTransform root2 = _root;
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			root2.anchorMax = val3;
			root.anchorMin = val3;
			_root.pivot = new Vector2(0f, 0.5f);
			Image obj = Circle(_root, "Back", new Color(0f, 0f, 0f, 0.55f), 60f, new Vector2(30f, 0f));
			_ring = Circle(((Graphic)obj).rectTransform, "Ring", Color.white, 60f, Vector2.zero);
			_ring.type = (Type)3;
			_ring.fillMethod = (FillMethod)4;
			_ring.fillOrigin = 2;
			_ring.fillClockwise = true;
			_icon = Label(((Graphic)Circle(((Graphic)obj).rectTransform, "Core", new Color(0.08f, 0.06f, 0.05f, 0.92f), 48f, Vector2.zero)).rectTransform, font, 24f, (TextAlignmentOptions)514, (FontStyles)1);
			((TMP_Text)_icon).rectTransform.sizeDelta = new Vector2(48f, 48f);
			Image obj2 = Circle(((Graphic)obj).rectTransform, "Badge", new Color(0.12f, 0.09f, 0.07f, 0.95f), 24f, new Vector2(22f, 22f));
			_badgeGo = ((Component)obj2).gameObject;
			_badge = Label(((Graphic)obj2).rectTransform, font, 13f, (TextAlignmentOptions)514, (FontStyles)1);
			((TMP_Text)_badge).rectTransform.sizeDelta = new Vector2(24f, 24f);
			_title = Label(_root, font, 18f, (TextAlignmentOptions)1025, (FontStyles)1);
			RectTransform rectTransform = ((TMP_Text)_title).rectTransform;
			RectTransform rectTransform2 = ((TMP_Text)_title).rectTransform;
			((Vector2)(ref val3))..ctor(0f, 0.5f);
			rectTransform2.anchorMax = val3;
			rectTransform.anchorMin = val3;
			((TMP_Text)_title).rectTransform.pivot = new Vector2(0f, 0f);
			((TMP_Text)_title).rectTransform.anchoredPosition = new Vector2(70f, 2f);
			((TMP_Text)_title).rectTransform.sizeDelta = new Vector2(260f, 24f);
			_detail = Label(_root, font, 15f, (TextAlignmentOptions)257, (FontStyles)0);
			((Graphic)_detail).color = new Color(1f, 1f, 1f, 0.88f);
			RectTransform rectTransform3 = ((TMP_Text)_detail).rectTransform;
			RectTransform rectTransform4 = ((TMP_Text)_detail).rectTransform;
			((Vector2)(ref val3))..ctor(0f, 0.5f);
			rectTransform4.anchorMax = val3;
			rectTransform3.anchorMin = val3;
			((TMP_Text)_detail).rectTransform.pivot = new Vector2(0f, 1f);
			((TMP_Text)_detail).rectTransform.anchoredPosition = new Vector2(70f, -2f);
			((TMP_Text)_detail).rectTransform.sizeDelta = new Vector2(260f, 24f);
			((Component)_root).gameObject.SetActive(false);
			return true;
		}

		private static RectTransform Anchor(GameUI ui)
		{
			if ((Object)(object)ui == (Object)null)
			{
				return null;
			}
			if ((Object)(object)ui.hungerProgressMask != (Object)null)
			{
				return ((Graphic)ui.hungerProgressMask).rectTransform;
			}
			if (!((Object)(object)ui.actionShortcut != (Object)null))
			{
				return null;
			}
			return ((Component)ui.actionShortcut).GetComponent<RectTransform>();
		}

		private static void Place()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: 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)
			RectTransform val = Anchor(((Object)(object)GameManager.Instance != (Object)null) ? GameManager.Instance.gameUI : null);
			Transform parent = ((Transform)_root).parent;
			RectTransform val2 = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null))
			{
				Canvas componentInParent = ((Component)val2).GetComponentInParent<Canvas>();
				Camera val3 = (((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode != 0) ? componentInParent.worldCamera : null);
				Vector3[] array = (Vector3[])(object)new Vector3[4];
				val.GetWorldCorners(array);
				Vector2 val4 = RectTransformUtility.WorldToScreenPoint(val3, new Vector3(array[2].x, (array[0].y + array[2].y) / 2f, array[0].z));
				Vector2 val5 = RectTransformUtility.WorldToScreenPoint(val3, new Vector3(array[0].x, (array[0].y + array[2].y) / 2f, array[0].z));
				float num = (((Object)(object)componentInParent != (Object)null) ? componentInParent.scaleFactor : 1f);
				Vector2 val6 = ((val4.x + (20f + _root.sizeDelta.x) * num < (float)Screen.width) ? (val4 + new Vector2(20f * num, 0f)) : (val5 - new Vector2((20f + _root.sizeDelta.x) * num, 0f)));
				Vector2 val7 = default(Vector2);
				if (RectTransformUtility.ScreenPointToLocalPointInRectangle(val2, val6, val3, ref val7))
				{
					_root.pivot = new Vector2(0f, 0.5f);
					((Transform)_root).localPosition = new Vector3(val7.x, val7.y, 0f);
				}
			}
		}

		private static Image Circle(RectTransform parent, string name, Color color, float size, Vector2 position)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = new GameObject(name, new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
			((Transform)component).SetParent((Transform)(object)parent, false);
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(((Object)(object)parent == (Object)(object)_root) ? 0f : 0.5f, 0.5f);
			component.anchorMax = val;
			component.anchorMin = val;
			component.sizeDelta = new Vector2(size, size);
			component.anchoredPosition = position;
			Image obj = ((Component)component).gameObject.AddComponent<Image>();
			obj.sprite = CircleSprite();
			((Graphic)obj).color = color;
			((Graphic)obj).raycastTarget = false;
			return obj;
		}

		private static TextMeshProUGUI Label(RectTransform parent, TMP_FontAsset font, float size, TextAlignmentOptions align, FontStyles style)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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)
			RectTransform component = new GameObject("Text", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
			((Transform)component).SetParent((Transform)(object)parent, false);
			TextMeshProUGUI val = ((Component)component).gameObject.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)font != (Object)null)
			{
				((TMP_Text)val).font = font;
			}
			((TMP_Text)val).fontSize = size;
			((TMP_Text)val).alignment = align;
			((TMP_Text)val).fontStyle = style;
			((TMP_Text)val).enableWordWrapping = false;
			((Graphic)val).raycastTarget = false;
			((Graphic)val).color = Color.white;
			return val;
		}

		private static Sprite CircleSprite()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_circle != (Object)null)
			{
				return _circle;
			}
			Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false)
			{
				wrapMode = (TextureWrapMode)1,
				filterMode = (FilterMode)1
			};
			Color32[] array = (Color32[])(object)new Color32[16384];
			float num = 63f;
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 128; j++)
				{
					float num2 = Mathf.Sqrt(((float)j + 0.5f - 64f) * ((float)j + 0.5f - 64f) + ((float)i + 0.5f - 64f) * ((float)i + 0.5f - 64f));
					array[i * 128 + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)(Mathf.Clamp01(num - num2 + 0.5f) * 255f));
				}
			}
			val.SetPixels32(array);
			val.Apply();
			_circle = Sprite.Create(val, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f), 100f);
			return _circle;
		}
	}
	public static class Achievements
	{
		private const string ApplyKey = "lycans.achievements.apply";

		private const string PendingKey = "lycans.achievements.pending";

		public const string ReportAction = "achievements.report";

		private const string SoloKey = "lycans.victory.solo";

		public static int[] SoloWinners => AppDomain.CurrentDomain.GetData("lycans.victory.solo") as int[];

		public static void Increment(string key, long n = 1L)
		{
			Apply("inc", key, null, n);
		}

		public static void SetMax(string key, long value)
		{
			Apply("max", key, null, value);
		}

		public static void AddToSet(string key, string value)
		{
			Apply("set", key, value, 1L);
		}

		public static void AddProgress(string achievementId, long n = 1L)
		{
			Apply("progress", achievementId, null, n);
		}

		public static void Unlock(string achievementId)
		{
			Apply("unlock", achievementId, null, 1L);
		}

		public static void ReportTo(PlayerController player, string op, string key, long n = 1L)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)player == (Object)null) && !string.IsNullOrEmpty(key))
			{
				if ((Object)(object)player == (Object)(object)PlayerController.Local)
				{
					Apply(op, key, null, n);
				}
				else if (AppDomain.CurrentDomain.GetData("lycans.achievements.apply") != null)
				{
					ActionRequests.Broadcast("achievements.report", player, ModProposals.Hash(op + "|" + key), new Vector3((float)n, 0f, 0f));
				}
			}
		}

		private static void Apply(string op, string key, string value, long n)
		{
			if (string.IsNullOrEmpty(key))
			{
				return;
			}
			if (AppDomain.CurrentDomain.GetData("lycans.achievements.apply") is Action<string, string, string, long> action)
			{
				action(op, key, value, n);
				return;
			}
			ArrayList arrayList = AppDomain.CurrentDomain.GetData("lycans.achievements.pending") as ArrayList;
			if (arrayList == null)
			{
				arrayList = new ArrayList();
				AppDomain.CurrentDomain.SetData("lycans.achievements.pending", arrayList);
			}
			if (arrayList.Count < 2000)
			{
				arrayList.Add(new object[4] { op, key, value, n });
			}
		}

		public static void SetSoloWinners(int[] playerIndices)
		{
			AppDomain.CurrentDomain.SetData("lycans.victory.solo", playerIndices);
		}

		public static void Publish(Action<string, string, string, long> apply)
		{
			AppDomain.CurrentDomain.SetData("lycans.achievements.apply", apply);
			if (AppDomain.CurrentDomain.GetData("lycans.achievements.pending") is ArrayList arrayList)
			{
				object[] array = arrayList.ToArray();
				for (int i = 0; i < array.Length; i++)
				{
					object[] array2 = (object[])array[i];
					apply((string)array2[0], (string)array2[1], (string)array2[2], (long)array2[3]);
				}
				arrayList.Clear();
			}
		}
	}
	public static class ActionRequests
	{
		private const string HandlersKey = "lycans.mods.actions.handlers";

		private const string SendKey = "lycans.mods.actions.send";

		public static void Register(string action, Action<PlayerController, int, Vector3> handler)
		{
			Handlers()[ModProposals.Hash(action)] = handler;
		}

		public static bool Request(string action, PlayerController actor, int value, Vector3 position = default(Vector3))
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			return Send(broadcast: false, action, actor, value, position);
		}

		public static bool Broadcast(string action, PlayerController actor, int value, Vector3 position = default(Vector3))
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			return Send(broadcast: true, action, actor, value, position);
		}

		public static bool ShouldSendFrom(PlayerController actor)
		{
			if ((Object)(object)actor != (Object)null && ((SimulationBehaviour)actor).HasInputAuthority && (Object)(object)((SimulationBehaviour)actor).Runner != (Object)null)
			{
				return ((SimulationBehaviour)actor).Runner.IsForward;
			}
			return false;
		}

		public static void PublishSender(Action<bool, int, int, int, Vector3> send)
		{
			AppDomain.CurrentDomain.SetData("lycans.mods.actions.send", send);
		}

		public static void Dispatch(int hash, int actorIndex, int value, Vector3 position)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			if (!Handlers().TryGetValue(hash, out var value2))
			{
				Log.Warning("[ActionRequests] Action inconnue (" + hash + ") : mod absent chez ce joueur ?");
				return;
			}
			PlayerController actor = null;
			PlayerRegistry.ForEach((Action<PlayerController>)delegate(PlayerController p)
			{
				if ((Object)(object)actor == (Object)null && (Object)(object)p != (Object)null && p.Index == actorIndex)
				{
					actor = p;
				}
			});
			try
			{
				value2(actor, value, position);
			}
			catch (Exception ex)
			{
				Log.Error("[ActionRequests] Action en erreur : " + ex);
			}
		}

		private static bool Send(bool broadcast, string action, PlayerController actor, int value, Vector3 position)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			if (!(AppDomain.CurrentDomain.GetData("lycans.mods.actions.send") is Action<bool, int, int, int, Vector3> action2))
			{
				Log.Warning("[ActionRequests] « " + action + " » ignorée : mod_core absent.");
				return false;
			}
			action2(broadcast, ModProposals.Hash(action), ((Object)(object)actor != (Object)null) ? actor.Index : (-1), value, position);
			return true;
		}

		private static Dictionary<int, Action<PlayerController, int, Vector3>> Handlers()
		{
			if (AppDomain.CurrentDomain.GetData("lycans.mods.actions.handlers") is Dictionary<int, Action<PlayerController, int, Vector3>> result)
			{
				return result;
			}
			Dictionary<int, Action<PlayerController, int, Vector3>> dictionary = new Dictionary<int, Action<PlayerController, int, Vector3>>();
			AppDomain.CurrentDomain.SetData("lycans.mods.actions.handlers", dictionary);
			return dictionary;
		}
	}
	public static class AdminCommands
	{
		private const string Key = "lycans.mods.admin.commands";

		public static void Register(string category, string label, Action run, Func<bool> available = null)
		{
			List<object[]> list = All();
			lock (list)
			{
				list.Add(new object[4] { category, label, run, available });
			}
		}

		public static List<object[]> All()
		{
			if (AppDomain.CurrentDomain.GetData("lycans.mods.admin.commands") is List<object[]> result)
			{
				return result;
			}
			List<object[]> list = new List<object[]>();
			AppDomain.CurrentDomain.SetData("lycans.mods.admin.commands", list);
			return list;
		}
	}
	public static class AppearanceHooks
	{
		private const string CurrentKey = "lycans.appearance.skin.current";

		private const string ChooseKey = "lycans.appearance.skin.choose";

		private const string ColorKey = "lycans.appearance.color.request";

		private const string PreviewKey = "lycans.appearance.preview.wolf";

		public static bool SkinsAvailable => AppDomain.CurrentDomain.GetData("lycans.appearance.skin.choose") is Action<bool, string>;

		public static bool ColorsAvailable => AppDomain.CurrentDomain.GetData("lycans.appearance.color.request") is Action<int>;

		public static bool PreviewWolf
		{
			get
			{
				if (AppDomain.CurrentDomain.GetData("lycans.appearance.preview.wolf") is bool[] array)
				{
					return array[0];
				}
				return false;
			}
			set
			{
				bool[] array = AppDomain.CurrentDomain.GetData("lycans.appearance.preview.wolf") as bool[];
				if (array == null)
				{
					AppDomain.CurrentDomain.SetData("lycans.appearance.preview.wolf", array = new bool[1]);
				}
				array[0] = value;
			}
		}

		public static string CurrentSkin(bool werewolf)
		{
			if (!(AppDomain.CurrentDomain.GetData("lycans.appearance.skin.current") is Func<bool, string> func))
			{
				return null;
			}
			return func(werewolf);
		}

		public static void ChooseSkin(bool werewolf, string key)
		{
			if (AppDomain.CurrentDomain.GetData("lycans.appearance.skin.choose") is Action<bool, string> action)
			{
				action(werewolf, key);
			}
		}

		public static void RequestColor(int color)
		{
			if (AppDomain.CurrentDomain.GetData("lycans.appearance.color.request") is Action<int> action)
			{
				action(color);
			}
		}

		public static void PublishSkins(Func<bool, string> current, Action<bool, string> choose)
		{
			AppDomain.CurrentDomain.SetData("lycans.appearance.skin.current", current);
			AppDomain.CurrentDomain.SetData("lycans.appearance.skin.choose", choose);
		}

		public static void PublishColorRequest(Action<int> request)
		{
			AppDomain.CurrentDomain.SetData("lycans.appearance.color.request", request);
		}
	}
	public static class AudioBank
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static hook_Spawned <>9__3_0;

			internal void <LoadEmbedded>b__3_0(orig_Spawned orig, GameManager self)
			{
				orig.Invoke(self);
				if (_loaded)
				{
					return;
				}
				_loaded = true;
				string[] manifestResourceNames = _assembly.GetManifestResourceNames();
				foreach (string text in manifestResourceNames)
				{
					if (text.StartsWith("LycansAudio.", StringComparison.Ordinal))
					{
						((MonoBehaviour)self).StartCoroutine(Load(text));
					}
				}
			}
		}

		public const string ResourcePrefix = "LycansAudio.";

		private static Assembly _assembly;

		private static bool _loaded;

		public static string TempDir => Path.Combine(Path.GetTempPath(), "LycansModsAudio", Process.GetCurrentProcess().Id.ToString());

		public static void LoadEmbedded(Assembly assembly)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			if (_assembly != null)
			{
				return;
			}
			_assembly = assembly;
			object obj = <>c.<>9__3_0;
			if (obj == null)
			{
				hook_Spawned val = delegate(orig_Spawned orig, GameManager self)
				{
					orig.Invoke(self);
					if (!_loaded)
					{
						_loaded = true;
						string[] manifestResourceNames = _assembly.GetManifestResourceNames();
						foreach (string text in manifestResourceNames)
						{
							if (text.StartsWith("LycansAudio.", StringComparison.Ordinal))
							{
								((MonoBehaviour)self).StartCoroutine(Load(text));
							}
						}
					}
				};
				<>c.<>9__3_0 = val;
				obj = (object)val;
			}
			GameManager.Spawned += (hook_Spawned)obj;
		}

		private static IEnumerator Load(string resource)
		{
			string fileName = resource.Substring("LycansAudio.".Length);
			string text;
			try
			{
				string tempDir = TempDir;
				Directory.CreateDirectory(tempDir);
				text = Path.Combine(tempDir, fileName);
				using Stream stream = _assembly.GetManifestResourceStream(resource);
				using FileStream destination = File.Create(text);
				stream.CopyTo(destination);
			}
			catch (Exception ex)
			{
				Log.Error("[AudioBank] Extraction impossible de " + fileName + " : " + ex.Message);
				yield break;
			}
			string name = Path.GetFileNameWithoutExtension(fileName);
			bool split = name.EndsWith("__split", StringComparison.OrdinalIgnoreCase);
			UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip("file://" + text.Replace("\\", "/"), TypeOf(text));
			try
			{
				if (split)
				{
					DownloadHandler downloadHandler = request.downloadHandler;
					DownloadHandlerAudioClip val = (DownloadHandlerAudioClip)(object)((downloadHandler is DownloadHandlerAudioClip) ? downloadHandler : null);
					if (val != null)
					{
						val.streamAudio = false;
					}
				}
				yield return request.SendWebRequest();
				if ((int)request.result != 1)
				{
					Log.Error("[AudioBank] Lecture impossible de " + fileName + " : " + request.error);
					yield break;
				}
				AudioClip content = DownloadHandlerAudioClip.GetContent(request);
				AudioManager instance = AudioManager.Instance;
				if ((Object)(object)content == (Object)null || instance?.soundBank?.dictionary == null)
				{
					Log.Error("[AudioBank] " + fileName + " : son ou banque de sons du jeu indisponible.");
					yield break;
				}
				if (split)
				{
					AddSplit(instance, content, name.Substring(0, name.Length - "__split".Length).ToUpperInvariant());
					yield break;
				}
				string text2 = (((Object)content).name = name.ToUpperInvariant());
				instance.soundBank.dictionary[text2] = content;
				Log.Info("[AudioBank] Son « " + text2 + " » ajouté.");
			}
			finally
			{
				((IDisposable)request)?.Dispose();
			}
		}

		private static void AddSplit(AudioManager audio, AudioClip clip, string baseKey)
		{
			int num = Math.Max(1, clip.channels);
			float[] array = new float[clip.samples * num];
			clip.GetData(array, 0);
			List<int[]> list = DetectSegments(array, num, clip.frequency);
			if (list.Count == 0)
			{
				((Object)clip).name = baseKey;
				audio.soundBank.dictionary[baseKey] = clip;
				Log.Warning("[AudioBank] « " + baseKey + " » : aucun segment, son entier ajouté.");
				return;
			}
			for (int i = 0; i < list.Count; i++)
			{
				int num2 = list[i][0];
				int num3 = list[i][1] - list[i][0];
				float[] array2 = new float[num3 * num];
				Array.Copy(array, num2 * num, array2, 0, num3 * num);
				string text = baseKey + "_" + (i + 1);
				AudioClip val = AudioClip.Create(text, num3, num, clip.frequency, false);
				val.SetData(array2, 0);
				audio.soundBank.dictionary[text] = val;
			}
			Log.Info("[AudioBank] « " + baseKey + " » découpé en " + list.Count + " son(s).");
		}

		private static List<int[]> DetectSegments(float[] data, int channels, int frequency)
		{
			int num = data.Length / channels;
			float num2 = 0f;
			foreach (float num3 in data)
			{
				num2 = Mathf.Max(num2, Mathf.Abs(num3));
			}
			float num4 = Mathf.Max(0.02f, num2 * 0.08f);
			int num5 = Mathf.Max(1, (int)((float)frequency * 0.12f));
			int minSegment = Mathf.Max(1, (int)((float)frequency * 0.05f));
			int pad = (int)((float)frequency * 0.02f);
			List<int[]> list = new List<int[]>();
			bool flag = false;
			int start = 0;
			int num6 = 0;
			for (int j = 0; j < num; j++)
			{
				float num7 = 0f;
				for (int k = 0; k < channels; k++)
				{
					num7 = Mathf.Max(num7, Mathf.Abs(data[j * channels + k]));
				}
				if (num7 >= num4)
				{
					if (!flag)
					{
						flag = true;
						start = j;
					}
					num6 = 0;
				}
				else if (flag && ++num6 >= num5)
				{
					AddSegment(list, start, j - num6 + 1, num, minSegment, pad);
					flag = false;
				}
			}
			if (flag)
			{
				AddSegment(list, start, num, num, minSegment, pad);
			}
			return list;
		}

		private static void AddSegment(List<int[]> segments, int start, int end, int frames, int minSegment, int pad)
		{
			start = Math.Max(0, start - pad);
			end = Math.Min(frames, end + pad);
			if (end - start >= minSegment)
			{
				segments.Add(new int[2] { start, end });
			}
		}

		private static AudioType TypeOf(string path)
		{
			return (AudioType)(Path.GetExtension(path).ToLowerInvariant() switch
			{
				".mp3" => 13, 
				".ogg" => 14, 
				".wav" => 20, 
				_ => 0, 
			});
		}
	}
	public static class CandleHooks
	{
		private const string InLightKey = "lycans.candles.inLight";

		private const string NearestKey = "lycans.candles.nearest";

		public static bool InLight(Vector3 point)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (AppDomain.CurrentDomain.GetData("lycans.candles.inLight") is Func<Vector3, bool> func)
			{
				return func(point);
			}
			return false;
		}

		public static Vector3? Nearest(Vector3 point)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if (!(AppDomain.CurrentDomain.GetData("lycans.candles.nearest") is Func<Vector3, Vector3?> func))
			{
				return null;
			}
			return func(point);
		}

		public static void Publish(Func<Vector3, bool> inLight, Func<Vector3, Vector3?> nearest)
		{
			AppDomain.CurrentDomain.SetData("lycans.candles.inLight", inLight);
			AppDomain.CurrentDomain.SetData("lycans.candles.nearest", nearest);
		}
	}
	public enum CanMoveDecision
	{
		NoOpinion,
		Allow,
		Deny
	}
	public static class CanMoveRules
	{
		public const string Method = "PlayerController.IsCanMove";

		private const string DecisionKey = "decision";

		private static readonly object[] Boxed = new object[3] { 0, 1, 2 };

		public static void Decide(int priority, string owner, Func<PlayerController, CanMoveDecision> step)
		{
			HookPipeline.Register("PlayerController.IsCanMove", priority, owner, HookPhase.Before, delegate(IDictionary<string, object> data)
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Expected O, but got Unknown
				CanMoveDecision canMoveDecision = step((PlayerController)data["player"]);
				if (canMoveDecision != CanMoveDecision.NoOpinion)
				{
					data["decision"] = Boxed[(int)canMoveDecision];
					data["cancel"] = HookPipeline.True;
				}
			});
		}

		public static IDictionary<string, object> NewData()
		{
			return new Dictionary<string, object>();
		}

		public static int Run(IDictionary<string, object> data, PlayerController player)
		{
			data["player"] = player;
			data["decision"] = Boxed[0];
			data["cancel"] = HookPipeline.False;
			HookPipeline.RunBefore("PlayerController.IsCanMove", data);
			return (int)data["decision"];
		}
	}
	public static class ChestHooks
	{
		private const string ApiKey = "lycans.chests.api";

		private const string RefillKey = "lycans.chests.onRefill";

		private const string OpenKey = "lycans.chests.beforeOpen";

		private static Hashtable Api => AppDomain.CurrentDomain.GetData("lycans.chests.api") as Hashtable;

		public static int Count
		{
			get
			{
				if (!(Api?["count"] is Func<int> func))
				{
					return 0;
				}
				return func();
			}
		}

		public static Vector3 Position(int chest)
		{
			//IL_0027: 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)
			if (!(Api?["position"] is Func<int, Vector3> func))
			{
				return Vector3.zero;
			}
			return func(chest);
		}

		public static Transform Root(int chest)
		{
			if (!(Api?["root"] is Func<int, Transform> func))
			{
				return null;
			}
			return func(chest);
		}

		public static Transform Lid(int chest)
		{
			if (!(Api?["lid"] is Func<int, Transform> func))
			{
				return null;
			}
			return func(chest);
		}

		public static bool IsOpen(int chest)
		{
			if (Api?["isOpen"] is Func<int, bool> func)
			{
				return func(chest);
			}
			return false;
		}

		public static bool PutRareLoot(int chest, int slot)
		{
			if (Api?["putRare"] is Func<int, int, bool> func)
			{
				return func(chest, slot);
			}
			return false;
		}

		public static void OnRefill(Action<bool> step)
		{
			List("lycans.chests.onRefill").Add(step);
		}

		public static void BeforeOpen(Func<PlayerController, int, bool> step)
		{
			List("lycans.chests.beforeOpen").Add(step);
		}

		public static void Publish(Hashtable api)
		{
			AppDomain.CurrentDomain.SetData("lycans.chests.api", api);
		}

		public static void RaiseRefill(bool night)
		{
			object[] array = List("lycans.chests.onRefill").ToArray();
			foreach (object obj in array)
			{
				try
				{
					(obj as Action<bool>)?.Invoke(night);
				}
				catch (Exception ex)
				{
					Log.Error("[ChestHooks] Abonné au remplissage en erreur : " + ex);
				}
			}
		}

		public static bool RaiseBeforeOpen(PlayerController player, int chest)
		{
			object[] array = List("lycans.chests.beforeOpen").ToArray();
			foreach (object obj in array)
			{
				try
				{
					if (obj is Func<PlayerController, int, bool> func && func(player, chest))
					{
						return true;
					}
				}
				catch (Exception ex)
				{
					Log.Error("[ChestHooks] Abonné à l'ouverture en erreur : " + ex);
				}
			}
			return false;
		}

		private static ArrayList List(string key)
		{
			ArrayList arrayList = AppDomain.CurrentDomain.GetData(key) as ArrayList;
			if (arrayList == null)
			{
				arrayList = new ArrayList();
				AppDomain.CurrentDomain.SetData(key, arrayList);
			}
			return arrayList;
		}
	}
	public static class CursorControl
	{
		private const string CountKey = "lycans.mods.cursor.count";

		private const string PreviousKey = "lycans.mods.cursor.previous";

		private static readonly object Lock = new object();

		private static int Count
		{
			get
			{
				object data = AppDomain.CurrentDomain.GetData("lycans.mods.cursor.count");
				if (data is int)
				{
					return (int)data;
				}
				return 0;
			}
		}

		public static bool AnyPanelOpen => Count > 0;

		public static void Request()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Invalid comparison between Unknown and I4
			lock (Lock)
			{
				int count = Count;
				if (count == 0)
				{
					AppDomain.CurrentDomain.SetData("lycans.mods.cursor.previous", new bool[2]
					{
						Cursor.visible,
						(int)Cursor.lockState == 1
					});
					Cursor.lockState = (CursorLockMode)0;
					Cursor.visible = true;
					Log.Info("[CursorControl] Curseur libéré (premier panneau ouvert).");
				}
				AppDomain.CurrentDomain.SetData("lycans.mods.cursor.count", count + 1);
			}
		}

		public static void Release()
		{
			lock (Lock)
			{
				int num = Math.Max(0, Count - 1);
				AppDomain.CurrentDomain.SetData("lycans.mods.cursor.count", num);
				if (num == 0)
				{
					if (AppDomain.CurrentDomain.GetData("lycans.mods.cursor.previous") is bool[] array && array.Length == 2)
					{
						Cursor.visible = array[0];
						Cursor.lockState = (CursorLockMode)(array[1] ? 1 : 0);
					}
					Log.Info("[CursorControl] Curseur restauré (dernier panneau fermé).");
				}
			}
		}
	}
	public static class CustomAnimations
	{
		private const string DefinitionsKey = "lycans.mods.animations.definitions";

		private const string AnimatorsKey = "lycans.mods.animations.animators";

		private const string PlayKey = "lycans.mods.animations.play";

		private const string StopKey = "lycans.mods.animations.stop";

		private const string PlayingKey = "lycans.mods.animations.playing";

		public static IEnumerable<string> Ids => Definitions().Keys;

		public static void Define(string id, AnimationClip[] clips, int holdIndex = -1)
		{
			if (string.IsNullOrEmpty(id) || clips == null || clips.Length == 0 || Array.IndexOf(clips, null) >= 0)
			{
				Log.Warning("[CustomAnimations] « " + id + " » ignorée : clip manquant.");
				return;
			}
			Definitions()[id] = new object[2] { clips, holdIndex };
		}

		public static void Play(PlayerController player, string id)
		{
			if ((Object)(object)player != (Object)null && AppDomain.CurrentDomain.GetData("lycans.mods.animations.play") is Action<PlayerController, string> action)
			{
				action(player, id);
			}
		}

		public static void Stop(PlayerController player)
		{
			if ((Object)(object)player != (Object)null && AppDomain.CurrentDomain.GetData("lycans.mods.animations.stop") is Action<PlayerController> action)
			{
				action(player);
			}
		}

		public static bool IsPlaying(PlayerController player)
		{
			if ((Object)(object)player != (Object)null && AppDomain.CurrentDomain.GetData("lycans.mods.animations.playing") is Func<PlayerController, bool> func)
			{
				return func(player);
			}
			return false;
		}

		public static void RegisterExtraAnimator(string key, Func<PlayerController, Animator> animator)
		{
			Animators()[key] = animator;
		}

		public static void PublishImplementation(Action<PlayerController, string> play, Action<PlayerController> stop, Func<PlayerController, bool> playing)
		{
			AppDomain.CurrentDomain.SetData("lycans.mods.animations.play", play);
			AppDomain.CurrentDomain.SetData("lycans.mods.animations.stop", stop);
			AppDomain.CurrentDomain.SetData("lycans.mods.animations.playing", playing);
		}

		public static SortedDictionary<string, object[]> Definitions()
		{
			return GetOrCreate<SortedDictionary<string, object[]>>("lycans.mods.animations.definitions");
		}

		public static Dictionary<string, Func<PlayerController, Animator>> Animators()
		{
			return GetOrCreate<Dictionary<string, Func<PlayerController, Animator>>>("lycans.mods.animations.animators");
		}

		private static T GetOrCreate<T>(string key) where T : class, new()
		{
			if (AppDomain.CurrentDomain.GetData(key) is T result)
			{
				return result;
			}
			T val = new T();
			AppDomain.CurrentDomain.SetData(key, val);
			return val;
		}
	}
	public static class CustomEffects
	{
		private const string DefinitionsKey = "lycans.mods.effects.definitions";

		private const string ApplyKey = "lycans.mods.effects.apply";

		public static void Define(string key, Type effectType, Func<bool> enabled, Func<float> duration, Action<PlayerController, bool> onDrink = null)
		{
			Definitions()[key] = new object[4] { effectType, enabled, duration, onDrink };
		}

		public static void Apply(string key, PlayerController target, float duration)
		{
			if ((Object)(object)target != (Object)null && AppDomain.CurrentDomain.GetData("lycans.mods.effects.apply") is Action<string, PlayerController, float> action)
			{
				action(key, target, duration);
			}
		}

		public static void PublishApply(Action<string, PlayerController, float> apply)
		{
			AppDomain.CurrentDomain.SetData("lycans.mods.effects.apply", apply);
		}

		public static SortedDictionary<string, object[]> Definitions()
		{
			if (AppDomain.CurrentDomain.GetData("lycans.mods.effects.definitions") is SortedDictionary<string, object[]> result)
			{
				return result;
			}
			SortedDictionary<string, object[]> sortedDictionary = new SortedDictionary<string, object[]>(StringComparer.Ordinal);
			AppDomain.CurrentDomain.SetData("lycans.mods.effects.definitions", sortedDictionary);
			return sortedDictionary;
		}
	}
	public sealed class PotionPoolContext
	{
		private readonly IDictionary<string, object> _data;

		public List<Effect> NativeEffects => (List<Effect>)_data["native"];

		internal PotionPoolContext(IDictionary<string, object> data)
		{
			_data = data;
		}
	}
	public static class PotionRules
	{
		public const string Method = "GameManager.GenerateEffects";

		public static void Before(int priority, string owner, Action<PotionPoolContext> step)
		{
			HookPipeline.Register("GameManager.GenerateEffects", priority, owner, HookPhase.Before, delegate(IDictionary<string, object> data)
			{
				step(new PotionPoolContext(data));
			});
		}

		public static IDictionary<string, object> NewData(List<Effect> native)
		{
			return new Dictionary<string, object>
			{
				["native"] = native,
				["cancel"] = HookPipeline.False
			};
		}
	}
	public static class CustomItems
	{
		private const string DefinitionsKey = "lycans.mods.items.definitions";

		private const string SpawnKey = "lycans.mods.items.spawn";

		private const string IconsKey = "lycans.mods.items.icons";

		public static void Define(string key, Type itemType, Func<GameObject> visual, float visualScale, Func<bool> enabled)
		{
			Definitions()[key] = new object[4] { itemType, visual, visualScale, enabled };
		}

		public static void DefineInfo(string key, Func<Sprite> icon, string nameFr, string nameEn)
		{
			Infos()[key] = new object[3] { icon, nameFr, nameEn };
		}

		public static Sprite IconOf(string key)
		{
			if (key == null || !Infos().TryGetValue(key, out var value) || !(value[0] is Func<Sprite> func))
			{
				return null;
			}
			return func();
		}

		public static string NameOf(string key)
		{
			if (key == null || !Infos().TryGetValue(key, out var value))
			{
				return key;
			}
			return Translations.Text((string)value[1], (string)value[2]);
		}

		private static Dictionary<string, object[]> Infos()
		{
			if (AppDomain.CurrentDomain.GetData("lycans.mods.items.icons") is Dictionary<string, object[]> result)
			{
				return result;
			}
			Dictionary<string, object[]> dictionary = new Dictionary<string, object[]>();
			AppDomain.CurrentDomain.SetData("lycans.mods.items.icons", dictionary);
			return dictionary;
		}

		public static Item Spawn(string key, Vector3 position, Quaternion rotation)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (!(AppDomain.CurrentDomain.GetData("lycans.mods.items.spawn") is Func<string, Vector3, Quaternion, Item> func))
			{
				return null;
			}
			return func(key, position, rotation);
		}

		public static string KeyOf(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return null;
			}
			foreach (KeyValuePair<string, object[]> item2 in Definitions())
			{
				if ((Type)item2.Value[0] == ((object)item).GetType())
				{
					return item2.Key;
				}
			}
			return null;
		}

		public static void PublishSpawn(Func<string, Vector3, Quaternion, Item> spawn)
		{
			AppDomain.CurrentDomain.SetData("lycans.mods.items.spawn", spawn);
		}

		public static SortedDictionary<string, object[]> Definitions()
		{
			if (AppDomain.CurrentDomain.GetData("lycans.mods.items.definitions") is SortedDictionary<string, object[]> result)
			{
				return result;
			}
			SortedDictionary<string, object[]> sortedDictionary = new SortedDictionary<string, object[]>(StringComparer.Ordinal);
			AppDomain.CurrentDomain.SetData("lycans.mods.items.definitions", sortedDictionary);
			return sortedDictionary;
		}
	}
	public static class DevMode
	{
		private const string LoadedDevKey = "lycans.mods.devmode.loaded";

		private const string SkippedKey = "lycans.mods.devmode.skipped";

		private static bool? _enabled;

		public static bool Enabled
		{
			get
			{
				if (_enabled.HasValue)
				{
					return _enabled.Value;
				}
				_enabled = false;
				try
				{
					string path = Path.Combine(Paths.ConfigPath, "lycans.core.cfg");
					if (File.Exists(path))
					{
						string[] array = File.ReadAllLines(path);
						for (int i = 0; i < array.Length; i++)
						{
							string[] array2 = array[i].Split(new char[1] { '=' });
							if (array2.Length == 2 && array2[0].Trim() == "ModeDev")
							{
								_enabled = array2[1].Trim().Equals("true", StringComparison.OrdinalIgnoreCase);
							}
						}
					}
				}
				catch (Exception ex)
				{
					Log.Warning("[DevMode] Lecture de lycans.core.cfg impossible : " + ex.Message);
				}
				return _enabled.Value;
			}
		}

		public static IReadOnlyCollection<string> Skipped => List("lycans.mods.devmode.skipped");

		public static bool IsDevOnly(string status)
		{
			if (!(status == "dev"))
			{
				return status == "private";
			}
			return true;
		}

		public static bool Guard(BaseUnityPlugin plugin, string modName, string status)
		{
			KeepAlive(plugin);
			if (!IsDevOnly(status))
			{
				return true;
			}
			if (!Enabled)
			{
				List("lycans.mods.devmode.skipped").Add(modName);
				((Behaviour)plugin).enabled = false;
				Log.Info("[DevMode] « " + modName + " » (" + status + ") non chargé : mode DEV désactivé (ModeDev dans lycans.core.cfg).");
				return false;
			}
			List("lycans.mods.devmode.loaded").Add(modName);
			return true;
		}

		private static void KeepAlive(BaseUnityPlugin plugin)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			if (!((Object)(object)plugin == (Object)null))
			{
				GameObject gameObject = ((Component)plugin).gameObject;
				if ((int)((Object)gameObject).hideFlags != 61)
				{
					((Object)gameObject).hideFlags = (HideFlags)61;
					Object.DontDestroyOnLoad((Object)(object)gameObject);
				}
			}
		}

		public static bool IsLoadedDevMod(string modName)
		{
			return List("lycans.mods.devmode.loaded").Contains(modName);
		}

		private static HashSet<string> List(string key)
		{
			if (AppDomain.CurrentDomain.GetData(key) is HashSet<string> result)
			{
				return result;
			}
			HashSet<string> hashSet = new HashSet<string>();
			AppDomain.CurrentDomain.SetData(key, hashSet);
			return hashSet;
		}
	}
	public static class Disease
	{
		private const string EnabledKey = "lycans.mods.disease.enabled";

		private const string InfectKey = "lycans.mods.disease.infect";

		private const string CureKey = "lycans.mods.disease.cure";

		private const string StageKey = "lycans.mods.disease.stage";

		public static bool IsEnabled
		{
			get
			{
				if (AppDomain.CurrentDomain.GetData("lycans.mods.disease.enabled") is Func<bool> func)
				{
					return func();
				}
				return false;
			}
		}

		public static void PublishImplementation(Func<bool> enabled, Action<PlayerController> infect, Action<PlayerController> cure, Func<PlayerController, int> stage)
		{
			AppDomain.CurrentDomain.SetData("lycans.mods.disease.enabled", enabled);
			AppDomain.CurrentDomain.SetData("lycans.mods.disease.infect", infect);
			AppDomain.CurrentDomain.SetData("lycans.mods.disease.cure", cure);
			AppDomain.CurrentDomain.SetData("lycans.mods.disease.stage", stage);
		}

		public static void Infect(PlayerController player)
		{
			if (AppDomain.CurrentDomain.GetData("lycans.mods.disease.infect") is Action<PlayerController> action)
			{
				action(player);
			}
		}

		public static void Cure(PlayerController player)
		{
			if (AppDomain.CurrentDomain.GetData("lycans.mods.disease.cure") is Action<PlayerController> action)
			{
				action(player);
			}
		}

		public static int Stage(PlayerController player)
		{
			if (!(AppDomain.CurrentDomain.GetData("lycans.mods.disease.stage") is Func<PlayerController, int> func))
			{
				return 0;
			}
			return func(player);
		}
	}
	public static class EventLock
	{
		private const string Key = "lycans.events.active";

		private const string CycleKey = "lycans.events.cycle";

		private const string HookKey = "lycans.events.cyclehook";

		private const int ResetPriority = 2;

		public const string Necromancer = "necromancer";

		public const string DemonCar = "demon-car";

		public const string WildHunt = "wild-hunt";

		public static void Publish(string name, Func<bool> active)
		{
			Table()[name] = active;
			InstallCycleReset();
		}

		public static void MarkStarted(string name)
		{
			Cycle()[0] = name;
		}

		public static string UsedThisCycle(string self)
		{
			string text = Cycle()[0];
			if (text == null || !(text != self))
			{
				return null;
			}
			return Label(text);
		}

		private static string[] Cycle()
		{
			string[] array = AppDomain.CurrentDomain.GetData("lycans.events.cycle") as string[];
			if (array == null)
			{
				array = new string[1];
				AppDomain.CurrentDomain.SetData("lycans.events.cycle", array);
			}
			return array;
		}

		private static void InstallCycleReset()
		{
			object data = AppDomain.CurrentDomain.GetData("lycans.events.cyclehook");
			bool flag = default(bool);
			int num;
			if (data is bool)
			{
				flag = (bool)data;
				num = 1;
			}
			else
			{
				num = 0;
			}
			if (((uint)num & (flag ? 1u : 0u)) != 0)
			{
				return;
			}
			AppDomain.CurrentDomain.SetData("lycans.events.cyclehook", true);
			EGameState[] array = new EGameState[3];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			EGameState[] array2 = (EGameState[])(object)array;
			for (int i = 0; i < array2.Length; i++)
			{
				GameStateRules.AfterEnter(array2[i], 2, "EventLock (un événement par cycle)", delegate(StateEnterContext ctx)
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					//IL_0007: Invalid comparison between Unknown and I4
					//IL_000a: Unknown result type (might be due to invalid IL or missing references)
					//IL_0010: Invalid comparison between Unknown and I4
					if ((int)ctx.Entered != 2 || (int)ctx.From == 1)
					{
						Cycle()[0] = null;
					}
				});
			}
		}

		public static string OtherActive(string self)
		{
			foreach (DictionaryEntry item in Table())
			{
				if (!((string)item.Key == self) && item.Value is Func<bool> func)
				{
					bool flag;
					try
					{
						flag = func();
					}
					catch
					{
						flag = false;
					}
					if (flag)
					{
						return Label((string)item.Key);
					}
				}
			}
			return null;
		}

		public static string Label(string name)
		{
			return name switch
			{
				"wild-hunt" => Translations.Text("la Chasse sauvage", "the Wild Hunt"), 
				"demon-car" => Translations.Text("la Ka Maudite", "the Cursed Ka"), 
				"necromancer" => Translations.Text("la Bête", "the Beast"), 
				_ => name, 
			};
		}

		private static Hashtable Table()
		{
			Hashtable hashtable = AppDomain.CurrentDomain.GetData("lycans.events.active") as Hashtable;
			if (hashtable == null)
			{
				hashtable = Hashtable.Synchronized(new Hashtable());
				AppDomain.CurrentDomain.SetData("lycans.events.active", hashtable);
			}
			return hashtable;
		}
	}
	public enum ExtendedRole
	{
		Villager,
		Alchemist,
		Hunter,
		Wolf,
		Porcupines,
		Knight,
		Alpha,
		Snake,
		LittleGirl,
		Rat,
		None,
		Maire,
		BigWolf,
		Chef,
		Judge,
		Hermit,
		Saboteur,
		Carpenter,
		Merchant,
		Necromancer,
		Beast
	}
	public static class ExtendedRoles
	{
		public enum SecondaryCamp
		{
			Village,
			Wolves,
			All
		}

		private const string GetKey = "lycans.mods.roles.get";

		private const string SetKey = "lycans.mods.roles.set";

		private const string SlotCountKey = "lycans.mods.roles.slotcount";

		private const string DisplayKey = "lycans.mods.roles.display";

		private const string SecondaryGetKey = "lycans.mods.roles.secondary.get";

		private const string SecondarySetKey = "lycans.mods.roles.secondary.set";

		private const string SecondaryDefsKey = "lycans.mods.roles.secondary.defs";

		public static bool IsAvailable => AppDomain.CurrentDomain.GetData("lycans.mods.roles.get") != null;

		public static int SlotCount
		{
			get
			{
				object data = AppDomain.CurrentDomain.GetData("lycans.mods.roles.slotcount");
				if (data is int)
				{
					return (int)data;
				}
				return 0;
			}
		}

		public static void PublishImplementation(Func<int, ExtendedRole> get, Action<int, ExtendedRole> set, int slotCount)
		{
			AppDomain.CurrentDomain.SetData("lycans.mods.roles.get", (Func<int, int>)((int index) => (int)get(index)));
			AppDomain.CurrentDomain.SetData("lycans.mods.roles.set", (Action<int, int>)delegate(int index, int role)
			{
				set(index, (ExtendedRole)role);
			});
			AppDomain.CurrentDomain.SetData("lycans.mods.roles.slotcount", slotCount);
		}

		public static ExtendedRole Get(int playerIndex)
		{
			if (AppDomain.CurrentDomain.GetData("lycans.mods.roles.get") is Func<int, int> func)
			{
				return (ExtendedRole)func(playerIndex);
			}
			return ExtendedRole.None;
		}

		public static ExtendedRole Get(PlayerController player)
		{
			if (!((Object)(object)player != (Object)null))
			{
				return ExtendedRole.None;
			}
			return Get((int)player.Index);
		}

		public static void RegisterDisplay(ExtendedRole role, string translationKey, Color color, bool wolfTeam, Func<bool> showMates = null, Func<string> suffix = null)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			Displays()[(int)role] = new object[5] { translationKey, color, wolfTeam, showMates, suffix };
		}

		public static bool TryGetDisplay(ExtendedRole role, out string translationKey, out Color color, out bool wolfTeam, out Func<bool> showMates, out Func<string> suffix)
		{
			//IL_004d: 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_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if (Displays().TryGetValue((int)role, out var value))
			{
				translationKey = (string)value[0];
				color = (Color)value[1];
				wolfTeam = (bool)value[2];
				showMates = (Func<bool>)value[3];
				suffix = (Func<string>)value[4];
				return true;
			}
			translationKey = null;
			color = Color.white;
			wolfTeam = false;
			showMates = null;
			suffix = null;
			return false;
		}

		public static bool IsWolfTeam(PlayerController player)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			if ((int)player.Role == 1)
			{
				return true;
			}
			string translationKey;
			Color color;
			bool wolfTeam;
			Func<bool> showMates;
			Func<string> suffix;
			return TryGetDisplay(Get(player), out translationKey, out color, out wolfTeam, out showMates, out suffix) && wolfTeam;
		}

		private static Dictionary<int, object[]> Displays()
		{
			if (AppDomain.CurrentDomain.GetData("lycans.mods.roles.display") is Dictionary<int, object[]> result)
			{
				return result;
			}
			Dictionary<int, object[]> dictionary = new Dictionary<int, object[]>();
			AppDomain.CurrentDomain.SetData("lycans.mods.roles.display", dictionary);
			return dictionary;
		}

		public static void RegisterSecondary(ExtendedRole role, SecondaryCamp camp, Func<bool> enabled)
		{
			SecondaryDefinitions()[(int)role] = new object[2]
			{
				(int)camp,
				enabled
			};
		}

		public static Dictionary<int, object[]> SecondaryDefinitions()
		{
			if (AppDomain.CurrentDomain.GetData("lycans.mods.roles.secondary.defs") is Dictionary<int, object[]> result)
			{
				return result;
			}
			Dictionary<int, object[]> dictionary = new Dictionary<int, object[]>();
			AppDomain.CurrentDomain.SetData("lycans.mods.roles.secondary.defs", dictionary);
			return dictionary;
		}

		public static void PublishSecondary(Func<int, int> get, Action<int, int> set)
		{
			AppDomain.CurrentDomain.SetData("lycans.mods.roles.secondary.get", get);
			AppDomain.CurrentDomain.SetData("lycans.mods.roles.secondary.set", set);
		}

		public static ExtendedRole GetSecondary(PlayerController player)
		{
			if (!((Object)(object)player != (Object)null) || !(AppDomain.CurrentDomain.GetData("lycans.mods.roles.secondary.get") is Func<int, int> func))
			{
				return ExtendedRole.Villager;
			}
			return (ExtendedRole)func(player.Index);
		}

		public static bool Has(PlayerController player, ExtendedRole role)
		{
			if ((Object)(object)player != (Object)null)
			{
				if (Get(player) != role)
				{
					return GetSecondary(player) == role;
				}
				return true;
			}
			return false;
		}

		public static void SetSecondary(int playerIndex, ExtendedRole role)
		{
			if (AppDomain.CurrentDomain.GetData("lycans.mods.roles.secondary.set") is Action<int, int> action)
			{
				action(playerIndex, (int)role);
			}
		}

		public static void Set(int playerIndex, ExtendedRole role)
		{
			if (AppDomain.CurrentDomain.GetData("lycans.mods.roles.set") is Action<int, int> action)
			{
				action(playerIndex, (int)role);
			}
			else
			{
				Log.Warning("[ExtendedRoles] Set ignoré : mod_roles non chargé.");
			}
		}
	}
	public static class GamePhases
	{
		private static NetworkRunner Runner => ((SimulationBehaviour)(GameManager.Instance?)).Runner;

		private static bool InPlay
		{
			get
			{
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Invalid comparison between Unknown and I4
				//IL_0045: Unknown result type (might be due to invalid IL or missing references)
				//IL_0056: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)Runner != (Object)null && Runner.IsServer && (Object)(object)GameManager.State != (Object)null && (int)GameManager.State.Current == 2 && (Object)(object)GameManager.LightingManager != (Object)null && !NetworkBool.op_Implicit(GameManager.LightingManager.IsTransition))
				{
					return !NetworkBool.op_Implicit(GameManager.Instance.IsFinished);
				}
				return false;
			}
		}

		public static bool CanStartNight
		{
			get
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				if (InPlay)
				{
					return !NetworkBool.op_Implicit(GameManager.LightingManager.IsNight);
				}
				return false;
			}
		}

		public static bool CanStartDawn
		{
			get
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				if (InPlay)
				{
					return NetworkBool.op_Implicit(GameManager.LightingManager.IsNight);
				}
				return false;
			}
		}

		public static bool CanEndVote
		{
			get
			{
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Invalid comparison between Unknown and I4
				if ((Object)(object)Runner != (Object)null && Runner.IsServer && (Object)(object)GameManager.State != (Object)null)
				{
					return (int)GameManager.State.Current == 4;
				}
				return false;
			}
		}

		public static void Transition()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (InPlay)
			{
				GameManager.Rpc_Transition(Runner);
				GameManager.LightingManager.IsTransition = NetworkBool.op_Implicit(true);
				Log.Info("[GamePhases] Transition forcée (" + (NetworkBool.op_Implicit(GameManager.LightingManager.IsNight) ? "aube" : "tombée de la nuit") + ").");
			}
		}

		public static void StartNight()
		{
			if (CanStartNight)
			{
				Transition();
			}
		}

		public static void EndVote()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (CanEndVote)
			{
				GameManager.Instance.VoteTimer = TickTimer.CreateFromSeconds(Runner, 0.1f);
				Log.Info("[GamePhases] Fin du vote forcée.");
			}
		}
	}
	public sealed class StateEnterContext
	{
		private readonly IDictionary<string, object> _data;

		public EGameState Entered => (EGameState)_data["entered"];

		public EGameState From => (EGameState)_data["from"];

		public bool IsServer => (bool)_data["server"];

		public bool IsPlayer => (bool)_data["player"];

		public bool Cancel
		{
			get
			{
				return HookPipeline.IsCancelled(_data);
			}
			set
			{
				_data["cancel"] = HookPipeline.Box(value);
			}
		}

		internal StateEnterContext(IDictionary<string, object> data)
		{
			_data = data;
		}
	}
	public static class GameStateRules
	{
		public unsafe static string Method(EGameState state)
		{
			return "GameState.Enter." + ((object)(*(EGameState*)(&state))/*cast due to .constrained prefix*/).ToString();
		}

		public static void BeforeEnter(EGameState state, int priority, string owner, Action<StateEnterContext> step)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			HookPipeline.Register(Method(state), priority, owner, HookPhase.Before, delegate(IDictionary<string, object> data)
			{
				step(new StateEnterContext(data));
			});
		}

		public static void AfterEnter(EGameState state, int priority, string owner, Action<StateEnterContext> step)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			HookPipeline.Register(Method(state), priority, owner, HookPhase.After, delegate(IDictionary<string, object> data)
			{
				step(new StateEnterContext(data));
			});
		}

		public static void OnRoundStartServer(int priority, string owner, Action step)
		{
			AfterEnter((EGameState)2, priority, owner, delegate(StateEnterContext ctx)
			{
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Invalid comparison between Unknown and I4
				if (ctx.IsServer && (int)ctx.From == 1)
				{
					step();
				}
			});
		}

		public static IDictionary<string, object> NewData(EGameState entered, EGameState from, bool isServer, bool isPlayer)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			return new Dictionary<string, object>
			{
				["entered"] = entered,
				["from"] = from,
				["server"] = HookPipeline.Box(isServer),
				["player"] = HookPipeline.Box(isPlayer),
				["cancel"] = HookPipeline.False
			};
		}
	}
	public static class GhostHooks
	{
		private const string RevenantKey = "lycans.ghosts.revenant";

		private const string DriverKey = "lycans.ghosts.driver";

		public static bool IsRevenant(int playerIndex)
		{
			if (AppDomain.CurrentDomain.GetData("lycans.ghosts.revenant") is Func<int, bool> func)
			{
				return func(playerIndex);
			}
			return false;
		}

		public static bool IsDriving(int playerIndex)
		{
			if (AppDomain.CurrentDomain.GetData("lycans.ghosts.driver") is Func<int, bool> func)
			{
				return func(playerIndex);
			}
			return false;
		}

		public static void PublishRevenants(Func<int, bool> isRevenant)
		{
			AppDomain.CurrentDomain.SetData("lycans.ghosts.revenant", isRevenant);
		}

		public static void PublishDriver(Func<int, bool> isDriving)
		{
			AppDomain.CurrentDomain.SetData("lycans.ghosts.driver", isDriving);
		}
	}
	public enum HookPhase
	{
		Before,
		After
	}
	public static class HookPipeline
	{
		public const string CancelKey = "cancel";

		public static readonly object True = true;

		public static readonly object False = false;

		private const string StepsKey = "lycans.mods.hooks.steps";

		private const string ConflictsKey = "lycans.mods.hooks.conflicts";

		private const string CacheKey = "lycans.mods.hooks.cache";

		private static readonly object Lock = new object();

		public static IReadOnlyList<string> ConflictMessages
		{
			get
			{
				lock (Lock)
				{
					return Conflicts().ToArray();
				}
			}
		}

		public static void Register(string method, int priority, string owner, HookPhase phase, Action<IDictionary<string, object>> step)
		{
			lock (Lock)
			{
				Dictionary<string, List<Tuple<int, string, int, Action<IDictionary<string, object>>>>> dictionary = Steps();
				if (!dictionary.TryGetValue(method, out var value))
				{
					value = (dictionary[method] = new List<Tuple<int, string, int, Action<IDictionary<string, object>>>>());
				}
				value.RemoveAll((Tuple<int, string, int, Action<IDictionary<string, object>>> s) => s.Item1 == priority && s.Item2 == owner);
				Tuple<int, string, int, Action<IDictionary<string, object>>> tuple = value.Find((Tuple<int, string, int, Action<IDictionary<string, object>>> s) => s.Item1 == priority);
				if (tuple != null)
				{
					string text = method + " : priorité " + priority + " demandée par « " + owner + " » mais déjà prise par « " + tuple.Item2 + " ». Les deux étapes sont désactivées — change la priorité de l'un des deux mods.";
					Conflicts().Add(text);
					Log.Error("[HookPipeline] " + text);
				}
				value.Add(Tuple.Create(priority, owner, (int)phase, step));
				value.Sort((Tuple<int, string, int, Action<IDictionary<string, object>>> a, Tuple<int, string, int, Action<IDictionary<string, object>>> b) => a.Item1.CompareTo(b.Item1));
				Cache().Clear();
			}
		}

		public static bool RunBefore(string method, IDictionary<string, object> data)
		{
			Tuple<int, string, int, Action<IDictionary<string, object>>>[] array = Active(method, HookPhase.Before);
			foreach (Tuple<int, string, int, Action<IDictionary<string, object>>> tuple in array)
			{
				try
				{
					tuple.Item4(data);
				}
				catch (Exception ex)
				{
					Log.Error("[HookPipeline] " + method + " / « " + tuple.Item2 + " » (priorité " + tuple.Item1 + ") en erreur : " + ex);
				}
				if (IsCancelled(data))
				{
					return true;
				}
			}
			return false;
		}

		public static void RunAfter(string method, IDictionary<string, object> data)
		{
			Tuple<int, string, int, Action<IDictionary<string, object>>>[] array = Active(method, HookPhase.After);
			foreach (Tuple<int, string, int, Action<IDictionary<string, object>>> tuple in array)
			{
				try
				{
					tuple.Item4(data);
				}
				catch (Exception ex)
				{
					Log.Error("[HookPipeline] " + method + " / « " + tuple.Item2 + " » (priorité " + tuple.Item1 + ") en erreur : " + ex);
				}
			}
		}

		public static bool IsCancelled(IDictionary<string, object> data)
		{
			bool flag = default(bool);
			int num;
			if (data.TryGetValue("cancel", out var value))
			{
				if (value is bool)
				{
					flag = (bool)value;
					num = 1;
				}
				else
				{
					num = 0;
				}
			}
			else
			{
				num = 0;
			}
			return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
		}

		public static object Box(bool value)
		{
			if (!value)
			{
				return False;
			}
			return True;
		}

		public static IReadOnlyList<string> Describe(string method)
		{
			lock (Lock)
			{
				List<string> list = new List<string>();
				if (Steps().TryGetValue(method, out var value))
				{
					foreach (Tuple<int, string, int, Action<IDictionary<string, object>>> item in value)
					{
						list.Add(item.Item1 + " · " + item.Item2 + " · " + ((HookPhase)item.Item3/*cast due to .constrained prefix*/).ToString() + (IsDuplicate(value, item.Item1) ? " · CONFLIT (désactivée)" : ""));
					}
				}
				return list;
			}
		}

		private static Tuple<int, string, int, Action<IDictionary<string, object>>>[] Active(string method, HookPhase phase)
		{
			lock (Lock)
			{
				Dictionary<string, Tuple<int, string, int, Action<IDictionary<string, object>>>[][]> dictionary = Cache();
				if (!dictionary.TryGetValue(method, out var value))
				{
					value = (dictionary[method] = new Tuple<int, string, int, Action<IDictionary<string, object>>>[2][]);
				}
				if (value[(int)phase] != null)
				{
					return value[(int)phase];
				}
				List<Tuple<int, string, int, Action<IDictionary<string, object>>>> list = new List<Tuple<int, string, int, Action<IDictionary<string, object>>>>();
				if (Steps().TryGetValue(method, out var value2))
				{
					foreach (Tuple<int, string, int, Action<IDictionary<string, object>>> item in value2)
					{
						if (item.Item3 == (int)phase && !IsDuplicate(value2, item.Item1))
						{
							list.Add(item);
						}
					}
				}
				value[(int)phase] = list.ToArray();
				return value[(int)phase];
			}
		}

		private static bool IsDuplicate(List<Tuple<int, string, int, Action<IDictionary<string, object>>>> list, int priority)
		{
			return list.FindAll((Tuple<int, string, int, Action<IDictionary<string, object>>> s) => s.Item1 == priority).Count > 1;
		}

		private static Dictionary<string, List<Tuple<int, string, int, Action<IDictionary<string, object>>>>> Steps()
		{
			return GetOrCreate<Dictionary<string, List<Tuple<int, string, int, Action<IDictionary<string, object>>>>>>("lycans.mods.hooks.steps");
		}

		private static List<string> Conflicts()
		{
			return GetOrCreate<List<string>>("lycans.mods.hooks.conflicts");
		}

		private static Dictionary<string, Tuple<int, string, int, Action<IDictionary<string, object>>>[][]> Cache()
		{
			return GetOrCreate<Dictionary<string, Tuple<int, string, int, Action<IDictionary<string, object>>>[][]>>("lycans.mods.hooks.cache");
		}

		private static T GetOrCreate<T>(string key) where T : class, new()
		{
			if (AppDomain.CurrentDomain.GetData(key) is T result)
			{
				return result;
			}
			T val = new T();
			AppDomain.CurrentDomain.SetData(key, val);
			return val;
		}
	}
	public sealed class InteractRayContext
	{
		private readonly IDictionary<string, object> _data;

		public PlayerController Player => (PlayerController)_data["player"];

		public float Distance
		{
			get
			{
				return ((float[])_data["values"])[0];
			}
			set
			{
				((float[])_data["values"])[0] = value;
			}
		}

		public bool IsMeeting => (int)GameManager.LocalGameState == 4;

		internal InteractRayContext(IDictionary<string, object> data)
		{
			_data = data;
		}
	}
	public static class InteractRayRules
	{
		public const string Method = "PlayerInteract.Update";

		public static void AdjustDistance(int priority, string owner, Action<InteractRayContext> step)
		{
			HookPipeline.Register("PlayerInteract.Update", priority, owner, HookPhase.Before, delegate(IDictionary<string, object> data)
			{
				step(new InteractRayContext(data));
			});
		}

		public static IDictionary<string, object> NewData()
		{
			return new Dictionary<string, object> { ["values"] = new float[1] };
		}

		public static void Reset(IDictionary<string, object> data, PlayerController player, float distance)
		{
			data["player"] = player;
			data["cancel"] = HookPipeline.False;
			((float[])data["values"])[0] = distance;
		}
	}
	public sealed class InteractContext
	{
		private readonly IDictionary<string, object> _data;

		public PlayerController Player => (PlayerController)_data["player"];

		public bool IsPrimary => (bool)_data["primary"];

		public GameObject Target => (GameObject)_data["target"];

		public PlayerController TargetPlayer
		{
			get
			{
				if (!((Object)(object)Target != (Object)null))
				{
					return null;
				}
				return Target.GetComponentInParent<PlayerController>();
			}
		}

		public bool Handled
		{
			get
			{
				return HookPipeline.IsCancelled(_data);
			}
			set
			{
				_data["cancel"] = HookPipeline.Box(value);
			}
		}

		internal InteractContext(IDictionary<string, object> data)
		{
			_data = data;
		}
	}
	public static class InteractRules
	{
		public const string Method = "PlayerController.Interact";

		public static void Before(int priority, string owner, Action<InteractContext> step)
		{
			HookPipeline.Register("PlayerController.Interact", priority, owner, HookPhase.Before, delegate(IDictionary<string, object> data)
			{
				step(new InteractContext(data));
			});
		}

		public static void After(int priority, string owner, Action<InteractContext> step)
		{
			HookPipeline.Register("PlayerController.Interact", priority, owner, HookPhase.After, delegate(IDictionary<string, object> data)
			{
				step(new InteractContext(data));
			});
		}

		public static IDictionary<string, object> NewData(PlayerController player, bool isPrimary)
		{
			return new Dictionary<string, object>
			{
				["player"] = player,
				["primary"] = HookPipeline.Box(isPrimary),
				["target"] = player._targetObject,
				["cancel"] = HookPipeline.False
			};
		}
	}
	public sealed class ItemSpawnContext
	{
		private readonly IDictionary<string, object> _data;

		public GameManager Game => (GameManager)_data["game"];

		public List<Item> Prefabs => (List<Item>)_data["prefabs"];

		public Dictionary<string, Action<Vector3, Quaternion>> CustomItems => (Dictionary<string, Action<Vector3, Quaternion>>)_data["custom"];

		public bool BulletsAllowed
		{
			get
			{
				return (bool)_data["bullets"];
			}
			set
			{
				_data["bullets"] = HookPipeline.Box(value);
			}
		}

		internal ItemSpawnContext(IDictionary<string, object> data)
		{
			_data = data;
		}
	}
	public static class ItemSpawnRules
	{
		public const string Method = "GameManager.SpawnRandomItems";

		public static void Before(int priority, string owner, Action<ItemSpawnContext> step)
		{
			HookPipeline.Register("GameManager.SpawnRandomItems", priority, owner, HookPhase.Before, delegate(IDictionary<string, object> data)
			{
				step(new ItemSpawnContext(data));
			});
		}

		public static IDictionary<string, object> NewData(GameManager game)
		{
			return new Dictionary<string, object>
			{
				["game"] = game,
				["prefabs"] = new List<Item>(game.spawnableItemPrefabs),
				["custom"] = new Dictionary<string, Action<Vector3, Quaternion>>(),
				["bullets"] = HookPipeline.True,
				["cancel"] = HookPipeline.False
			};
		}
	}
	public sealed class LightingContext
	{
		private readonly IDictionary<string, object> _data;

		public LightingManager Manager => (LightingManager)_data["manager"];

		public float TimeOfDay => Manager._localTimeOfDay;

		public bool IsNightTime
		{
			get
			{
				if (!(TimeOfDay >= 18f))
				{
					return TimeOfDay < 6f;
				}
				return true;
			}
		}

		public bool IsServer
		{
			get
			{
				if ((Object)(object)((SimulationBehaviour)Manager).Runner != (Object)null)
				{
					return ((SimulationBehaviour)Manager).Runner.IsServer;
				}
				return false;
			}
		}

		public bool FlatAmbient
		{
			get
			{
				return (bool)_data["flat"];
			}
			set
			{
				_data["flat"] = HookPipeline.Box(value);
			}
		}

		internal LightingContext(IDictionary<string, object> data)
		{
			_data = data;
		}
	}
	public static class LightingRules
	{
		public const string UpdateMethod = "LightingManager.UpdateLighting";

		public const string NightMethod = "LightingManager.NightChanged";

		public const string AmbientMethod = "LightingManager.FlatAmbient";

		public static void OnUpdate(int priority, string owner, Action<LightingContext> step)
		{
			HookPipeline.Register("LightingManager.UpdateLighting", priority, owner, HookPhase.After, delegate(IDictionary<string, object> data)
			{
				step(new LightingContext(data));
			});
		}

		public static void OnNightChanged(int priority, string owner, Action<LightingContext> step)
		{
			HookPipeline.Register("LightingManager.NightChanged", priority, owner, HookPhase.After, delegate(IDictionary<string, object> data)
			{
				step(new LightingContext(data));
			});
		}

		public static void ForceFlatAmbient(int priority, string owner, Func<LightingContext, bool> wantsFlat)
		{
			HookPipeline.Register("LightingManager.FlatAmbient", priority, owner, HookPhase.After, delegate(IDictionary<string, object> data)
			{
				LightingContext lightingContext = new LightingContext(data);
				if (!lightingContext.FlatAmbient && wantsFlat(lightingContext))
				{
					lightingContext.FlatAmbient = true;
				}
			});
		}

		public static IDictionary<string, object> NewData()
		{
			return new Dictionary<string, object>();
		}

		public static void Reset(IDictionary<string, object> data, LightingManager manager)
		{
			data["manager"] = manager;
			data["flat"] = HookPipeline.False;
			data["cancel"] = HookPipeline.False;
		}
	}
	public static class Log
	{
		private static ManualLogSource _source;

		private static readonly Dictionary<string, float> _lastThrottled = new Dictionary<string, float>();

		public static void Use(ManualLogSource source)
		{
			_source = source;
		}

		public static void Info(string message)
		{
			if (_source != null)
			{
				_source.LogInfo((object)message);
			}
			else
			{
				Console.WriteLine("[Info] " + message);
			}
		}

		public static void Warning(string message)
		{
			if (_source != null)
			{
				_source.LogWarning((object)message);
			}
			else
			{
				Console.WriteLine("[Warning] " + message);
			}
		}

		public static void Error(string message)
		{
			if (_source != null)
			{
				_source.LogError((object)message);
			}
			else
			{
				Console.WriteLine("[Error] " + message);
			}
		}

		public static void Throttled(string key, float intervalSeconds, string message)
		{
			float unscaledTime = Time.unscaledTime;
			if (!_lastThrottled.TryGetValue(key, out var value) || !(unscaledTime - value < intervalSeconds))
			{
				_lastThrottled[key] = unscaledTime;
				Info(message);
			}
		}
	}
	public static class LootHooks
	{
		private const string RefillKey = "lycans.loot.chestsRefill";

		public static int RefillChestsNear(Vector3 center, float radius, int chancePercent)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (!(AppDomain.CurrentDomain.GetData("lycans.loot.chestsRefill") is Func<Vector3, float, int, int> func))
			{
				return 0;
			}
			return func(center, radius, chancePercent);
		}

		public static void PublishChests(Func<Vector3, float, int, int> refillNear)
		{
			AppDomain.CurrentDomain.SetData("lycans.loot.chestsRefill", refillNear);
		}
	}
	public sealed class LootCollectContext
	{
		private readonly IDictionary<string, object> _data;

		public PlayerController Player => (PlayerController)_data["player"];

		public Loot Loot => (Loot)_data["loot"];

		public int Score
		{
			get
			{
				return (int)_data["score"];
			}
			set
			{
				_data["score"] = value;
			}
		}

		public int Hunger
		{
			get
			{
				return (int)_data["hunger"];
			}
			set
			{
				_data["hunger"] = value;
			}
		}

		public bool Cancel
		{
			get
			{
				return HookPipeline.IsCancelled(_data);
			}
			set
			{
				_data["cancel"] = HookPipeline.Box(value);
			}
		}

		internal LootCollectContext(IDictionary<string, object> data)
		{
			_data = data;
		}
	}
	public static class LootRules
	{
		public const string Method = "Loot.Rpc_Collect";

		public static void Before(int priority, string owner, Action<LootCollectContext> step)
		{
			HookPipeline.Register("Loot.Rpc_Collect", priority, owner, HookPhase.Before, delegate(IDictionary<string, object> data)
			{
				step(new LootCollectContext(data));
			});
		}

		public static void After(int priority, string owner, Action<LootCollectContext> step)
		{
			HookPipeline.Register("Loot.Rpc_Collect", priority, owner, HookPhase.After, delegate(IDictionary<string, object> data)
			{
				step(new LootCollectContext(data));
			});
		}

		public static IDictionary<string, object> NewData(PlayerController player, Loot loot)
		{
			return new Dictionary<string, object>
			{
				["player"] = player,
				["loot"] = loot,
				["score"] = loot.ScoreValue,
				["hunger"] = loot.HungerValue,
				["cancel"] = HookPipeline.False
			};
		}
	}
	public static class ModAssets
	{
		private static readonly Dictionary<string, AssetBundle> Bundles = new Dictionary<string, AssetBundle>();

		private static readonly Dictionary<string, Sprite> Icons = new Dictionary<string, Sprite>();

		public static AssetBundle Bundle(Assembly assembly, string fileName)
		{
			if (Bundles.TryGetValue(fileName, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			byte[] array = Read(assembly, "LycansBundle." + fileName);
			if (array == null)
			{
				return null;
			}
			AssetBundle val = AssetBundle.LoadFromMemory(array);
			if ((Object)(object)val == (Object)null)
			{
				foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles())
				{
					if ((Object)(object)allLoadedAssetBundle != (Object)null && string.Equals(((Object)allLoadedAssetBundle).name, Path.GetFileNameWithoutExtension(fileName), StringComparison.OrdinalIgnoreCase))
					{
						val = allLoadedAssetBundle;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				Log.Warning("[ModAssets] Bundle illisible : " + fileName);
			}
			Bundles[fileName] = val;
			return val;
		}

		public static GameObject FirstPrefab(Assembly assembly, string fileName)
		{
			AssetBundle val = Bundle(assembly, fileName);
			GameObject[] array = (((Object)(object)val != (Object)null) ? val.LoadAllAssets<GameObject>() : null);
			if (array == null || array.Length == 0)
			{
				return null;
			}
			return array[0];
		}

		public static T FirstAsset<T>(Assembly assembly, string fileName) where T : Object
		{
			AssetBundle val = Bundle(assembly, fileName);
			T[] array = (((Object)(object)val != (Object)null) ? val.LoadAllAssets<T>() : null);
			if (array == null || array.Length == 0)
			{
				Log.Warning("[ModAssets] Aucun " + typeof(T).Name + " dans " + fileName);
				return default(T);
			}
			return array[0];
		}

		public static Sprite Icon(Assembly assembly, string fileName)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			if (Icons.TryGetValue(fileName, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			byte[] array = Read(assembly, "LycansIcon." + fileName);
			if (array == null)
			{
				return null;
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!ImageConversion.LoadImage(val, array))
			{
				Log.Warning("[ModAssets] Icône illisible : " + fileName);
				return null;
			}
			Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
			Icons[fileName] = val2;
			return val2;
		}

		private static byte[] Read(Assembly assembly, string resource)
		{
			using Stream stream = assembly.GetManifestResourceStream(resource);
			if (stream == null)
			{
				Log.Warning("[ModAssets] Ressource absente de la DLL : " + resource);
				return null;
			}
			MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			return memoryStream.ToArray();
		}
	}
	public static class ModConfigPanel
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static hook_Spawned <>9__7_0;

			internal void <EnsureInstalled>b__7_0(orig_Spawned orig, GameManager self)
			{
				orig.Invoke(self);
				CreateCarrierIfNeeded();
			}
		}

		private const string HookInstalledKey = "lycans.mods.config.panelhookinstalled";

		private const string ReplacedKey = "lycans.mods.config.panelreplaced";

		private static readonly object Lock = new object();

		private static GameObject _carrier;

		public static bool Replaced
		{
			get
			{
				object data = AppDomain.CurrentDomain.GetData("lycans.mods.config.panelreplaced");
				bool flag = default(bool);
				int num;
				if (data is bool)
				{
					flag = (bool)data;
					num = 1;
				}
				else
				{
					num = 0;
				}
				return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			}
			set
			{
				AppDomain.CurrentDomain.SetData("lycans.mods.config.panelreplaced", value);
			}
		}

		public static void EnsureInstalled()
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			lock (Lock)
			{
				object data = AppDomain.CurrentDomain.GetData("lycans.mods.config.panelhookinstalled");
				bool flag = default(bool);
				int num;
				if (data is bool)
				{
					flag = (bool)data;
					num = 1;
				}
				else
				{
					num = 0;
				}
				if (((uint)num & (flag ? 1u : 0u)) != 0)
				{
					return;
				}
				AppDomain.CurrentDomain.SetData("lycans.mods.config.panelhookinstalled", true);
				object obj = <>c.<>9__7_0;
				if (obj == null)
				{
					hook_Spawned val = delegate(orig_Spawned orig, GameManager self)
					{
						orig.Invoke(self);
						CreateCarrierIfNeeded();
					};
					<>c.<>9__7_0 = val;
					obj = (object)val;
				}
				GameManager.Spawned += (hook_Spawned)obj;
				Log.Info("[ModConfigPanel] Hook GameManager.Spawned installé, carrier créé au premier démarrage de partie.");
			}
		}

		private static void CreateCarrierIfNeeded()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			if (!((Object)(object)_carrier != (Object)null))
			{
				_carrier = new GameObject("LycansModConfigPanel");
				Object.DontDestroyOnLoad((Object)(object)_carrier);
				_carrier.AddComponent<ModConfigPanelBehaviour>();
				Log.Info("[ModConfigPanel] Carrier créé (" + ((Object)_carrier).name + ").");
			}
		}
	}
	internal sealed class ModConfigPanelBehaviour : MonoBehaviour
	{
		private const KeyCode ToggleKey = (KeyCode)290;

		private const string CouncilTabId = "\0council";

		private bool _open;

		private bool _loggedFirstOnGui;

		private Rect _rect = new Rect(20f, 20f, 560f, 440f);

		private Vector2 _tabScroll;

		private Vector2 _contentScroll;

		private string _search = "";

		private string _selectedMod;

		private static GUIStyle _richLabel;

		private static GUIStyle RichLabel
		{
			get
			{
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: 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_002c: Expected O, but got Unknown
				object obj = _richLabel;
				if (obj == null)
				{
					GUIStyle val = new GUIStyle(GUI.skin.label)
					{
						richText = true,
						wordWrap = true
					};
					_richLabel = val;
					obj = (object)val;
				}
				return (GUIStyle)obj;
			}
		}

		private void Awake()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			Log.Info("[ModConfigPanel] Awake : composant créé, en attente de " + ((object)(KeyCode)290/*cast due to .constrained prefix*/).ToString() + ".");
		}

		private void OnEnable()
		{
			Log.Info("[ModConfigPanel] OnEnable.");
		}

		private void OnDisable()
		{
			Log.Info("[ModConfigPanel] OnDisable (le composant vient d'être désactivé !).");
		}

		private void OnDestroy()
		{
			Log.Info("[ModConfigPanel] OnDestroy (le composant vient d'être détruit !).");
			if (_open)
			{
				CursorControl.Release();
			}
		}

		private void Update()
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			string reason;
			bool flag = CanConfigure(out reason);
			Log.Throttled("modconfigpanel.state", 3f, "[ModConfigPanel] CanConfigure=" + flag + " (" + reason + ")");
			if (ModConfigPanel.Replaced)
			{
				SetOpen(value: false);
				return;
			}
			if (Input.GetKeyDown((KeyCode)290))
			{
				Log.Info("[ModConfigPanel] " + ((object)(KeyCode)290/*cast due to .constrained prefix*/).ToString() + " détecté (appui). CanConfigure=" + flag + " (" + reason + ")");
				if (flag)
				{
					SetOpen(!_open);
				}
				else
				{
					Log.Info("[ModConfigPanel] Touche ignorée : condition non remplie (" + reason + ").");
				}
			}
			if (!flag)
			{
				SetOpen(value: false);
			}
		}

		private void SetOpen(bool value)
		{
			if (_open != value)
			{
				_open = value;
				if (value)
				{
					CursorControl.Request();
				}
				else
				{
					CursorControl.Release();
				}
			}
		}

		private static bool CanConfigure(out string reason)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Invalid comparison between Unknown and I4
			GameManager instance = GameManager.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				reason = "GameManager.Instance == null (pas en partie ?)";
				return false;
			}
			if ((Object)(object)((SimulationBehaviour)instance).Runner == (Object)null)
			{
				reason = "Runner == null";
				return false;
			}
			if (!((SimulationBehaviour)instance).Runner.IsRunning)
			{
				reason = "Runner.IsRunning == false";
				return false;
			}
			if ((int)GameManager.LocalGameState != 1)
			{
				reason = "état de partie = " + ((object)Unsafe.As<EGameState, EGameState>(ref GameManager.LocalGameState)/*cast due to .constrained prefix*/).ToString() + " (attendu Pregame)";
				return false;
			}
			reason = "ok";
			return true;
		}

		private static bool IsHost()
		{
			GameManager instance = GameManager.Instance;
			if (instance == null)
			{
				return false;
			}
			NetworkRunner runner = ((SimulationBehaviour)instance).Runner;
			return ((runner != null) ? new bool?(runner.IsServer) : ((bool?)null)) == true;
		}

		private void OnGUI()
		{
			//IL_003d: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			if (!_loggedFirstOnGui)
			{
				_loggedFirstOnGui = true;
				Log.Info("[ModConfigPanel] OnGUI appelé pour la première fois (Unity invoque bien ce composant).");
			}
			if (_open)
			{
				string text = (IsHost() ? "hôte" : "joueur — tes changements deviennent des propositions");
				_rect = GUILayout.Window(113755157, _rect, new WindowFunction(DrawWindow), "Configuration des mods · " + text + " (" + ((object)(KeyCode)290/*cast due to .constrained prefix*/).ToString() + " pour fermer)", Array.Empty<GUILayoutOption>());
			}
		}

		private void DrawWindow(int id)
		{
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			IReadOnlyList<ModConfigSection> sections = ModConfigRegistry.Sections;
			IReadOnlyList<string> conflictMessages = HookPipeline.ConflictMessages;
			if (conflictMessages.Count > 0)
			{
				Color color = GUI.color;
				GUI.color = new Color(1f, 0.35f, 0.35f);
				foreach (string item in conflictMessages)
				{
					GUILayout.Label("ERREUR — " + item, Array.Empty<GUILayoutOption>());
				}
				GUI.color = color;
				GUILayout.Space(6f);
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(170f) });
			GUILayout.Label("Recherche", Array.Empty<GUILayoutOption>());
			_search = GUILayout.TextField(_search, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(160f) });
			GUILayout.Space(6f);
			_tabScroll = GUILayout.BeginScrollView(_tabScroll, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(170f),
				GUILayout.Height(330f)
			});
			string text = _search.Trim().ToLowerInvariant();
			foreach (ModConfigSection item2 in sections)
			{
				if (text.Length <= 0 || item2.ModName.ToLowerInvariant().IndexOf(text, StringComparison.Ordinal) >= 0)
				{
					DrawTabButton(item2.ModName, item2.ModName);
				}
			}
			GUILayout.EndScrollView();
			GUILayout.Space(6f);
			DrawTabButton("\0council", "Conseil");
			GUILayout.EndVertical();
			GUILayout.Space(10f);
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			_contentScroll = GUILayout.BeginScrollView(_contentScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(380f) });
			DrawSelectedContent(sections);
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
			GUILayout.EndHorizontal();
			GUI.DragWindow(new Rect(0f, 0f, 10000f, 20f));
		}

		private void DrawTabButton(string id, string label)
		{
			bool flag = _selectedMod == id;
			if (GUILayout.Toggle(flag, label, GUIStyle.op_Implicit("Button"), Array.Empty<GUILayoutOption>()))
			{
				_selectedMod = id;
			}
			else if (flag)
			{
				_selectedMod = null;
			}
		}

		private void DrawSelectedContent(IReadOnlyList<ModConfigSection> sections)
		{
			if (_selectedMod == null)
			{
				GUILayout.Label("Choisis un mod à gauche (ou cherche son nom).", Array.Empty<GUILayoutOption>());
				return;
			}
			if (_selectedMod == "\0council")
			{
				DrawCouncil();
				return;
			}
			ModConfigSection modConfigSection = null;
			foreach (ModConfigSection section in sections)
			{
				if (section.ModName == _selectedMod)
				{
					modConfigSection = section;
					break;
				}
			}
			if (modConfigSection == null)
			{
				GUILayout.Label("Ce mod n'est plus chargé.", Array.Empty<GUILayoutOption>());
				return;
			}
			bool flag = modConfigSection.GetEnabled();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			bool flag2 = GUILayout.Toggle(flag, "", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(20f) });
			GUILayout.Label("<b>" + modConfigSection.ModName + "</b>", RichLabel, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			if (flag2 != flag)
			{
				modConfigSection.SetEnabled?.Invoke(flag2);
			}
			if (!flag2)
			{
				GUILayout.Label("Mod désactivé.", Array.Empty<GUILayoutOption>());
				return;
			}
			if (!IsHost())
			{
				GUILayout.Label("Tu n'es pas l'hôte : tes changements ci-dessous deviennent des propositions envoyées au Conseil (onglet à gauche).", RichLabel, Array.Empty<GUILayoutOption>());
				GUILayout.Space(6f);
			}
			GUILayout.Space(8f);
			foreach (ModConfigField field in modConfigSection.Fields)
			{
				DrawField(modConfigSection.ModName, field);
			}
		}

		private static void DrawField(string modName, ModConfigField field)
		{
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Space(20f);
			GUILayout.Label(field.Label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) });
			object obj = field.Get();
			float oldValueRaw = ToRaw(field.Type, obj);
			object obj2 = obj;
			switch (field.Type)
			{
			case ModConfigFieldType.Bool:
				obj2 = GUILayout.Toggle((bool)obj, "", Array.Empty<GUILayoutOption>());
				break;
			case ModConfigFieldType.Int:
			{
				float num3 = GUILayout.HorizontalSlider((float)(int)obj, field.Min, field.Max, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) });
				GUILayout.Label(((int)num3).ToString(), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(32f) });
				obj2 = (int)num3;
				break;
			}
			case ModConfigFieldType.Float:
			{
				float num2 = GUILayout.HorizontalSlider((float)obj, field.Min, field.Max, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) });
				GUILayout.Label(num2.ToString("0.0"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) });
				obj2 = num2;
				break;
			}
			case ModConfigFieldType.Choice:
			{
				string[] options = field.Options;
				int num = ((options == null) ? 1 : options.Length);
				if (GUILayout.Button(field.Format((int)obj), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(160f) }))
				{
					obj2 = ((int)obj + 1) % num;
				}
				break;
			}
			}
			GUILayout.EndHorizontal();
			if (!object.Equals(obj2, obj))
			{
				if (IsHost())
				{
					field.Set(obj2);
					return;
				}
				float newValueRaw = ToRaw(field.Type, obj2);
				ModProposals.Submit(modName, field.Label, oldValueRaw, newValueRaw);
				Log.Info("[ModConfigPanel] Proposition envoyée : " + modName + " / " + field.Label);
			}
		}

		private static float ToRaw(ModConfigFieldType type, object value)
		{
			return type switch
			{
				ModConfigFieldType.Bool => ((bool)value) ? 1f : 0f, 
				ModConfigFieldType.Int => (int)value, 
				ModConfigFieldType.Choice => (int)value, 
				ModConfigFieldType.Float => (float)value, 
				_ => 0f, 
			};
		}

		private void DrawCouncil()
		{
			//IL_006e: 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)
			GUILayout.Label("<b>Conseil</b>", RichLabel, Array.Empty<GUILayoutOption>());
			GUILayout.Space(6f);
			if (!ModProposals.IsAvailable)
			{
				GUILayout.Label("Indisponible : le mod « Lycans Council » n'est pas chargé.", Array.Empty<GUILayoutOption>());
				return;
			}
			IReadOnlyList<ProposalSlot> readOnlyList = ModProposals.List();
			if (readOnlyList.Count == 0)
			{
				GUILayout.Label("Aucune proposition en cours.", Array.Empty<GUILayoutOption>());
				return;
			}
			bool isHost = IsHost();
			int num;
			if (!((Object)(object)PlayerController.Local != (Object)null))
			{
				num = -1;
			}
			else
			{
				PlayerRef val = PlayerController.Local.Ref;
				num = ((PlayerRef)(ref val)).PlayerId;
			}
			int localPlayerId = num;
			foreach (ProposalSlot item in readOnlyList)
			{
				DrawProposal(item, isHost, localPlayerId);
			}
		}

		private static void DrawProposal(ProposalSlot slot, bool isHost, int localPlayerId)
		{
			GUILayout.BeginVertical(GUIStyle.op_Implicit("Box"), Array.Empty<GUILayoutOption>());
			GUILayout.Label("<b>" + slot.ModName + " / " + slot.FieldLabel + "</b>  —  " + DescribeStatus(slot.Status), RichLabel, Array.Empty<GUILayoutOption>());
			string[] obj = new string[6] { "Proposé par le joueur #", null, null, null, null, null };
			int authorPlayerId = slot.AuthorPlayerId;
			obj[1] = authorPlayerId.ToString();
			obj[2] = " : ";
			float oldValueRaw = slot.OldValueRaw;
			obj[3] = oldValueRaw.ToStr