Decompiled source of ServeYouRight v1.0.0

ServeYouRight.dll

Decompiled 11 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.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ServeYouRight")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("sighsorry")]
[assembly: AssemblyProduct("ServeYouRight")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class ExtensionMarkerAttribute : Attribute
	{
		public ExtensionMarkerAttribute(string name)
		{
		}
	}
}
namespace ServerSyncModTemplate
{
	[BepInPlugin("sighsorry.ServeYouRight", "ServeYouRight", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class ServerSyncModTemplatePlugin : BaseUnityPlugin
	{
		public enum Toggle
		{
			On = 1,
			Off = 0
		}

		private class ConfigurationManagerAttributes
		{
			[UsedImplicitly]
			public int? Order = null;

			[UsedImplicitly]
			public bool? Browsable = null;

			[UsedImplicitly]
			public string? Category = null;

			[UsedImplicitly]
			public Action<ConfigEntryBase>? CustomDrawer = null;
		}

		private class AcceptableShortcuts : AcceptableValueBase
		{
			public AcceptableShortcuts()
				: base(typeof(KeyboardShortcut))
			{
			}

			public override object Clamp(object value)
			{
				return value;
			}

			public override bool IsValid(object value)
			{
				return true;
			}

			public override string ToDescriptionString()
			{
				return "# Acceptable values: " + string.Join(", ", UnityInput.Current.SupportedKeyCodes);
			}
		}

		internal const string ModName = "ServeYouRight";

		internal const string ModVersion = "1.0.0";

		internal const string Author = "sighsorry";

		private const string ModGUID = "sighsorry.ServeYouRight";

		private static string ConfigFileName = "sighsorry.ServeYouRight.cfg";

		private static string ConfigFileFullPath;

		private static ServerSyncModTemplatePlugin? _instance;

		private readonly Harmony _harmony = new Harmony("sighsorry.ServeYouRight");

		public static readonly ManualLogSource ServerSyncModTemplateLogger;

		private FileSystemWatcher? _watcher;

		private readonly object _reloadLock = new object();

		private static readonly object DynamicConfigLock;

		private int _skipWatcherEvents;

		private DateTime _lastConfigReloadTime;

		private const long RELOAD_DELAY = 10000000L;

		private static readonly Dictionary<string, PerModCategoryConfig> PerModConfigs;

		private static bool _pendingDynamicConfigSave;

		public void Awake()
		{
			_instance = this;
			bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet;
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			JotunnBridge.InitializeAndEnableModQuery();
			Localization.OnLanguageChange = (Action)Delegate.Combine(Localization.OnLanguageChange, new Action(OnLanguageChange));
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			_harmony.PatchAll(executingAssembly);
			SetupWatcher();
			((BaseUnityPlugin)this).Config.Save();
			if (saveOnConfigSet)
			{
				((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet;
			}
		}

		private void OnDestroy()
		{
			Localization.OnLanguageChange = (Action)Delegate.Remove(Localization.OnLanguageChange, new Action(OnLanguageChange));
			SaveWithRespectToConfigSet();
			_watcher?.Dispose();
		}

		private void OnLanguageChange()
		{
			FeasterFoodInjector.OnLanguageChanged(ObjectDB.instance);
		}

		private void SetupWatcher()
		{
			_watcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName);
			_watcher.Changed += ReadConfigValues;
			_watcher.Created += ReadConfigValues;
			_watcher.Renamed += ReadConfigValues;
			_watcher.IncludeSubdirectories = true;
			_watcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			_watcher.EnableRaisingEvents = true;
		}

		private void ReadConfigValues(object sender, FileSystemEventArgs e)
		{
			if (Interlocked.CompareExchange(ref _skipWatcherEvents, 0, 0) > 0)
			{
				Interlocked.Decrement(ref _skipWatcherEvents);
				return;
			}
			DateTime now = DateTime.Now;
			long num = now.Ticks - _lastConfigReloadTime.Ticks;
			if (num < 10000000)
			{
				return;
			}
			lock (_reloadLock)
			{
				if (!File.Exists(ConfigFileFullPath))
				{
					ServerSyncModTemplateLogger.LogWarning((object)"Config file does not exist. Skipping reload.");
					return;
				}
				try
				{
					ServerSyncModTemplateLogger.LogDebug((object)"Reloading configuration...");
					SaveWithRespectToConfigSet(reload: true);
					ServerSyncModTemplateLogger.LogInfo((object)"Configuration reload complete.");
				}
				catch (Exception ex)
				{
					ServerSyncModTemplateLogger.LogError((object)("Error reloading configuration: " + ex.Message));
				}
			}
			_lastConfigReloadTime = now;
		}

		private void SaveWithRespectToConfigSet(bool reload = false)
		{
			bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet;
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			if (reload)
			{
				((BaseUnityPlugin)this).Config.Reload();
				FeasterFoodInjector.OnConfigReload(ObjectDB.instance);
			}
			SuppressWatcherEvents();
			((BaseUnityPlugin)this).Config.Save();
			if (saveOnConfigSet)
			{
				((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet;
			}
		}

		internal static bool UseModSpecificTab(FoodSourceMod mod, PieceCategory category)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected I4, but got Unknown
			PerModCategoryConfig orCreatePerModConfig = GetOrCreatePerModConfig(mod);
			if (1 == 0)
			{
			}
			bool result = (category - 5) switch
			{
				1 => orCreatePerModConfig.Food.Value.IsOn(), 
				2 => orCreatePerModConfig.Meads.Value.IsOn(), 
				0 => orCreatePerModConfig.Feasts.Value.IsOn(), 
				_ => false, 
			};
			if (1 == 0)
			{
			}
			return result;
		}

		private static PerModCategoryConfig GetOrCreatePerModConfig(FoodSourceMod mod)
		{
			lock (DynamicConfigLock)
			{
				if (PerModConfigs.TryGetValue(mod.Id, out PerModCategoryConfig value))
				{
					return value;
				}
				if ((Object)(object)_instance == (Object)null)
				{
					throw new InvalidOperationException("Plugin instance is not initialized.");
				}
				string group = "ServingTray - " + SanitizeConfigText(mod.DisplayName) + " (" + SanitizeConfigText(mod.Id) + ")";
				PerModCategoryConfig perModCategoryConfig = new PerModCategoryConfig(mod, _instance.config(group, "Food", Toggle.On, "If on, '" + mod.DisplayName + "' Food items go to 'Food - " + mod.DisplayName + "'. If off, they merge into vanilla Food.", 300), _instance.config(group, "Meads", Toggle.On, "If on, '" + mod.DisplayName + "' Mead items go to 'Meads - " + mod.DisplayName + "'. If off, they merge into vanilla Meads.", 200), _instance.config(group, "Feasts", Toggle.On, "If on, '" + mod.DisplayName + "' Feast items go to 'Feasts - " + mod.DisplayName + "'. If off, they merge into vanilla Feasts.", 100));
				PerModConfigs[mod.Id] = perModCategoryConfig;
				_pendingDynamicConfigSave = true;
				return perModCategoryConfig;
			}
		}

		internal static void FlushPendingDynamicConfigSave()
		{
			ServerSyncModTemplatePlugin instance = _instance;
			if (!((Object)(object)instance == (Object)null))
			{
				bool pendingDynamicConfigSave;
				lock (DynamicConfigLock)
				{
					pendingDynamicConfigSave = _pendingDynamicConfigSave;
					_pendingDynamicConfigSave = false;
				}
				if (pendingDynamicConfigSave)
				{
					bool saveOnConfigSet = ((BaseUnityPlugin)instance).Config.SaveOnConfigSet;
					((BaseUnityPlugin)instance).Config.SaveOnConfigSet = false;
					instance.SuppressWatcherEvents();
					((BaseUnityPlugin)instance).Config.Save();
					((BaseUnityPlugin)instance).Config.SaveOnConfigSet = saveOnConfigSet;
				}
			}
		}

		private void SuppressWatcherEvents(int eventCount = 6)
		{
			if (eventCount > 0)
			{
				Interlocked.Add(ref _skipWatcherEvents, eventCount);
			}
		}

		private static string SanitizeConfigText(string text)
		{
			if (string.IsNullOrWhiteSpace(text))
			{
				return "Unknown";
			}
			char[] array = text.ToCharArray();
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i] == '\r' || "=\n\t\\\"'[]".IndexOf(array[i]) >= 0 || char.IsControl(array[i]))
				{
					array[i] = '_';
				}
			}
			string text2 = new string(array).Trim();
			return string.IsNullOrWhiteSpace(text2) ? "Unknown" : text2;
		}

		private ConfigEntry<T> config<T>(string group, string name, T value, ConfigDescription description)
		{
			return ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, description);
		}

		private ConfigEntry<T> config<T>(string group, string name, T value, string description)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()));
		}

		private ConfigEntry<T> config<T>(string group, string name, T value, string description, int order)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			ConfigDescription description2 = new ConfigDescription(description, (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = order
				}
			});
			return config(group, name, value, description2);
		}

		static ServerSyncModTemplatePlugin()
		{
			string configPath = Paths.ConfigPath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName;
			ServerSyncModTemplateLogger = Logger.CreateLogSource("ServeYouRight");
			DynamicConfigLock = new object();
			PerModConfigs = new Dictionary<string, PerModCategoryConfig>(StringComparer.OrdinalIgnoreCase);
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	public static class ObjectDbAwakePatch
	{
		private static void Postfix(ObjectDB __instance)
		{
			FeasterFoodInjector.Inject(__instance);
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
	public static class ObjectDbCopyOtherDbPatch
	{
		private static void Postfix(ObjectDB __instance)
		{
			FeasterFoodInjector.Inject(__instance);
		}
	}
	[HarmonyPatch(typeof(Player), "SetPlaceMode")]
	public static class PlayerSetPlaceModePatch
	{
		private static void Postfix(Player __instance, PieceTable buildPieces)
		{
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !((Object)(object)buildPieces == (Object)null) && buildPieces.m_canRemoveFeasts)
			{
				FeasterFoodInjector.Inject(ObjectDB.instance);
				__instance.UpdateKnownRecipesList();
				__instance.UpdateAvailablePiecesList();
				FeasterFoodInjector.ApplyCustomCategoryLabels(buildPieces);
			}
		}
	}
	[HarmonyPatch(typeof(PieceTable), "UpdateAvailable")]
	public static class PieceTableUpdateAvailablePatch
	{
		private static void Postfix(PieceTable __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && __instance.m_canRemoveFeasts)
			{
				FeasterFoodInjector.ApplyCustomCategoryLabels(__instance);
			}
		}
	}
	internal static class FeasterFoodInjector
	{
		[CompilerGenerated]
		private sealed class <GetFeasterPieceTables>d__8 : IEnumerable<PieceTable>, IEnumerable, IEnumerator<PieceTable>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private PieceTable <>2__current;

			private int <>l__initialThreadId;

			private ObjectDB objectDb;

			public ObjectDB <>3__objectDb;

			private HashSet<PieceTable> <uniqueTables>5__1;

			private List<GameObject>.Enumerator <>s__2;

			private GameObject <itemPrefab>5__3;

			private ItemDrop <itemDrop>5__4;

			private PieceTable <pieceTable>5__5;

			private bool <supportsFoodTabs>5__6;

			PieceTable IEnumerator<PieceTable>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <GetFeasterPieceTables>d__8(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<uniqueTables>5__1 = null;
				<>s__2 = default(List<GameObject>.Enumerator);
				<itemPrefab>5__3 = null;
				<itemDrop>5__4 = null;
				<pieceTable>5__5 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				try
				{
					int num = <>1__state;
					if (num != 0)
					{
						if (num != 1)
						{
							return false;
						}
						<>1__state = -3;
						goto IL_017a;
					}
					<>1__state = -1;
					<uniqueTables>5__1 = new HashSet<PieceTable>();
					<>s__2 = objectDb.m_items.GetEnumerator();
					<>1__state = -3;
					goto IL_0190;
					IL_017a:
					<itemDrop>5__4 = null;
					<pieceTable>5__5 = null;
					<itemPrefab>5__3 = null;
					goto IL_0190;
					IL_0190:
					while (true)
					{
						if (<>s__2.MoveNext())
						{
							<itemPrefab>5__3 = <>s__2.Current;
							if ((Object)(object)<itemPrefab>5__3 == (Object)null)
							{
								continue;
							}
							<itemDrop>5__4 = <itemPrefab>5__3.GetComponent<ItemDrop>();
							<pieceTable>5__5 = <itemDrop>5__4?.m_itemData?.m_shared?.m_buildPieces;
							if (!((Object)(object)<pieceTable>5__5 == (Object)null) && <pieceTable>5__5.m_canRemoveFeasts)
							{
								<supportsFoodTabs>5__6 = <pieceTable>5__5.m_categories.Contains((PieceCategory)6) || <pieceTable>5__5.m_categories.Contains((PieceCategory)7) || <pieceTable>5__5.m_categories.Contains((PieceCategory)5);
								if (<supportsFoodTabs>5__6)
								{
									break;
								}
							}
							continue;
						}
						<>m__Finally1();
						<>s__2 = default(List<GameObject>.Enumerator);
						return false;
					}
					if (<uniqueTables>5__1.Add(<pieceTable>5__5))
					{
						<>2__current = <pieceTable>5__5;
						<>1__state = 1;
						return true;
					}
					goto IL_017a;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				((IDisposable)<>s__2).Dispose();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<PieceTable> IEnumerable<PieceTable>.GetEnumerator()
			{
				<GetFeasterPieceTables>d__8 <GetFeasterPieceTables>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<GetFeasterPieceTables>d__ = this;
				}
				else
				{
					<GetFeasterPieceTables>d__ = new <GetFeasterPieceTables>d__8(0);
				}
				<GetFeasterPieceTables>d__.objectDb = <>3__objectDb;
				return <GetFeasterPieceTables>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<PieceTable>)this).GetEnumerator();
			}
		}

		private static bool _isInjecting;

		private static readonly Dictionary<string, ModCategoryInfo> ModCategoryCache = new Dictionary<string, ModCategoryInfo>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, FoodSourceMod> SourceModHitCache = new Dictionary<string, FoodSourceMod>(StringComparer.OrdinalIgnoreCase);

		private static readonly object ModCategoryLock = new object();

		public static void OnConfigReload(ObjectDB? objectDb)
		{
			Inject(objectDb);
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				Player.m_localPlayer.UpdateKnownRecipesList();
				Player.m_localPlayer.UpdateAvailablePiecesList();
				ApplyCustomCategoryLabels(Player.m_localPlayer.m_buildPieces);
			}
		}

		public static void OnLanguageChanged(ObjectDB? objectDb)
		{
			Inject(objectDb);
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				Player.m_localPlayer.UpdateKnownRecipesList();
				Player.m_localPlayer.UpdateAvailablePiecesList();
				ApplyCustomCategoryLabels(Player.m_localPlayer.m_buildPieces);
			}
		}

		public static void Inject(ObjectDB? objectDb)
		{
			if (_isInjecting || (Object)(object)objectDb == (Object)null)
			{
				return;
			}
			_isInjecting = true;
			try
			{
				List<ItemDrop> candidateFoods = GetCandidateFoods(objectDb);
				if (candidateFoods.Count == 0)
				{
					return;
				}
				foreach (PieceTable feasterPieceTable in GetFeasterPieceTables(objectDb))
				{
					int num = InjectIntoTable(feasterPieceTable, candidateFoods);
					if (num > 0)
					{
						ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogInfo((object)$"Added {num} mod food pieces to feaster table '{((Object)feasterPieceTable).name}'.");
					}
					ApplyCustomCategoryLabels(feasterPieceTable);
				}
			}
			catch (Exception arg)
			{
				ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogError((object)$"Failed to inject feaster foods: {arg}");
			}
			finally
			{
				_isInjecting = false;
				ServerSyncModTemplatePlugin.FlushPendingDynamicConfigSave();
			}
		}

		private static List<ItemDrop> GetCandidateFoods(ObjectDB objectDb)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Invalid comparison between Unknown and I4
			List<ItemDrop> list = new List<ItemDrop>();
			foreach (GameObject item in objectDb.m_items)
			{
				if (!((Object)(object)item == (Object)null))
				{
					ItemDrop component = item.GetComponent<ItemDrop>();
					SharedData val = component?.m_itemData?.m_shared;
					if (!((Object)(object)component == (Object)null) && val != null && (int)val.m_itemType == 2 && (val.m_isDrink || val.m_food > 0f || val.m_foodStamina > 0f || val.m_foodEitr > 0f || (Object)(object)item.GetComponent<Feast>() != (Object)null))
					{
						list.Add(component);
					}
				}
			}
			return list;
		}

		[IteratorStateMachine(typeof(<GetFeasterPieceTables>d__8))]
		private static IEnumerable<PieceTable> GetFeasterPieceTables(ObjectDB objectDb)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <GetFeasterPieceTables>d__8(-2)
			{
				<>3__objectDb = objectDb
			};
		}

		private static int InjectIntoTable(PieceTable table, List<ItemDrop> candidates)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			EnsureBaseCategories(table);
			HashSet<int> hashSet = BuildExistingFoodHashSet(table);
			int num = 0;
			foreach (ItemDrop candidate in candidates)
			{
				GameObject gameObject = ((Component)candidate).gameObject;
				int prefabNameHash = GetPrefabNameHash(gameObject);
				bool flag = hashSet.Contains(prefabNameHash);
				bool flag2 = IsInjectedByServeYouRight(gameObject);
				if (!flag || flag2)
				{
					PieceCategory baseCategory = ResolveCategory(gameObject, candidate.m_itemData.m_shared);
					PieceCategory category = ResolveTargetCategory(table, gameObject, baseCategory);
					if (TryGetTemplate(table, category, out Piece templatePiece, out WearNTear templateWearNTear) && PrepareFoodPrefab(gameObject, candidate, category, templatePiece, templateWearNTear) && !table.m_pieces.Contains(gameObject))
					{
						table.m_pieces.Add(gameObject);
						hashSet.Add(prefabNameHash);
						num++;
					}
				}
			}
			return num;
		}

		private static void EnsureBaseCategories(PieceTable table)
		{
			EnsureBaseCategoryExists(table, (PieceCategory)6, GetBaseCategoryLabel(table, (PieceCategory)6));
			EnsureBaseCategoryExists(table, (PieceCategory)7, GetBaseCategoryLabel(table, (PieceCategory)7));
			EnsureBaseCategoryExists(table, (PieceCategory)5, GetBaseCategoryLabel(table, (PieceCategory)5));
		}

		public static void ApplyCustomCategoryLabels(PieceTable? table)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)table == (Object)null)
			{
				return;
			}
			List<ModCategoryInfo> list;
			lock (ModCategoryLock)
			{
				list = ModCategoryCache.Values.ToList();
			}
			foreach (ModCategoryInfo item in list)
			{
				int num = table.m_categories.IndexOf(item.Category);
				if (num >= 0)
				{
					while (table.m_categoryLabels.Count <= num)
					{
						table.m_categoryLabels.Add(string.Empty);
					}
					string baseCategoryLabel = GetBaseCategoryLabel(table, item.BaseCategory);
					string baseLabel = ResolveCategoryDisplayLabel(item.BaseCategory, baseCategoryLabel);
					table.m_categoryLabels[num] = BuildDisplayCategoryName(baseLabel, item.SourceMod);
				}
			}
		}

		private static bool TryGetTemplate(PieceTable table, PieceCategory category, out Piece templatePiece, out WearNTear? templateWearNTear)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			templatePiece = null;
			templateWearNTear = null;
			foreach (GameObject piece in table.m_pieces)
			{
				if ((Object)(object)piece == (Object)null)
				{
					continue;
				}
				Piece component = piece.GetComponent<Piece>();
				if (!((Object)(object)component == (Object)null) && component.m_category == category && !component.m_repairPiece && !component.m_removePiece)
				{
					templatePiece = component;
					templateWearNTear = piece.GetComponent<WearNTear>();
					if ((Object)(object)templateWearNTear != (Object)null)
					{
						return true;
					}
				}
			}
			foreach (GameObject piece2 in table.m_pieces)
			{
				if ((Object)(object)piece2 == (Object)null)
				{
					continue;
				}
				Piece component2 = piece2.GetComponent<Piece>();
				if (!((Object)(object)component2 == (Object)null) && !component2.m_repairPiece && !component2.m_removePiece)
				{
					templatePiece = component2;
					templateWearNTear = piece2.GetComponent<WearNTear>();
					if ((Object)(object)templateWearNTear != (Object)null)
					{
						return true;
					}
				}
			}
			ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogWarning((object)("No feaster template piece found for table '" + ((Object)table).name + "'."));
			return false;
		}

		private static bool PrepareFoodPrefab(GameObject foodPrefab, ItemDrop sourceItemDrop, PieceCategory category, Piece templatePiece, WearNTear? templateWearNTear)
		{
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Expected O, but got Unknown
			if ((Object)(object)foodPrefab.GetComponent<ZNetView>() == (Object)null)
			{
				ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogWarning((object)("Skipping '" + ((Object)foodPrefab).name + "' because it has no ZNetView."));
				return false;
			}
			Piece val = foodPrefab.GetComponent<Piece>();
			if ((Object)(object)val == (Object)null)
			{
				val = foodPrefab.AddComponent<Piece>();
				CopyFields<Piece>(templatePiece, val);
			}
			WearNTear component = foodPrefab.GetComponent<WearNTear>();
			if ((Object)(object)component == (Object)null)
			{
				component = foodPrefab.AddComponent<WearNTear>();
				if ((Object)(object)templateWearNTear != (Object)null)
				{
					CopyFields<WearNTear>(templateWearNTear, component);
				}
			}
			SharedData shared = sourceItemDrop.m_itemData.m_shared;
			val.m_name = shared.m_name;
			val.m_description = shared.m_description;
			val.m_enabled = true;
			val.m_category = category;
			val.m_repairPiece = false;
			val.m_removePiece = false;
			val.m_resources = (Requirement[])(object)new Requirement[1]
			{
				new Requirement
				{
					m_resItem = sourceItemDrop,
					m_amount = 1,
					m_amountPerLevel = 1,
					m_recover = true
				}
			};
			Sprite[] icons = shared.m_icons;
			if (icons != null && icons.Length > 0)
			{
				val.m_icon = sourceItemDrop.m_itemData.GetIcon();
			}
			if ((Object)(object)foodPrefab.GetComponent<ServeYouRightInjectedPieceMarker>() == (Object)null)
			{
				foodPrefab.AddComponent<ServeYouRightInjectedPieceMarker>();
			}
			return true;
		}

		private static HashSet<int> BuildExistingFoodHashSet(PieceTable table)
		{
			HashSet<int> hashSet = new HashSet<int>();
			foreach (GameObject piece in table.m_pieces)
			{
				if ((Object)(object)piece == (Object)null)
				{
					continue;
				}
				Piece component = piece.GetComponent<Piece>();
				if ((Object)(object)component == (Object)null)
				{
					continue;
				}
				Requirement[] array = component.m_resources ?? Array.Empty<Requirement>();
				foreach (Requirement val in array)
				{
					if ((Object)(object)val?.m_resItem != (Object)null)
					{
						hashSet.Add(GetPrefabNameHash(((Component)val.m_resItem).gameObject));
					}
				}
				ItemDrop component2 = piece.GetComponent<ItemDrop>();
				if ((Object)(object)component2 != (Object)null)
				{
					hashSet.Add(GetPrefabNameHash(((Component)component2).gameObject));
				}
			}
			return hashSet;
		}

		private static PieceCategory ResolveCategory(GameObject foodPrefab, SharedData shared)
		{
			//IL_0013: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)foodPrefab.GetComponent<Feast>() != (Object)null)
			{
				return (PieceCategory)5;
			}
			if (shared.m_isDrink)
			{
				return (PieceCategory)7;
			}
			return (PieceCategory)6;
		}

		private static PieceCategory ResolveTargetCategory(PieceTable table, GameObject foodPrefab, PieceCategory baseCategory)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			string baseCategoryLabel = GetBaseCategoryLabel(table, baseCategory);
			EnsureBaseCategoryExists(table, baseCategory, baseCategoryLabel);
			if (!TryResolveFoodSourceMod(foodPrefab, out var sourceMod))
			{
				return baseCategory;
			}
			if (!ServerSyncModTemplatePlugin.UseModSpecificTab(sourceMod, baseCategory))
			{
				return baseCategory;
			}
			return ResolveOrCreateModCategory(baseCategory, sourceMod);
		}

		private static string GetBaseCategoryLabel(PieceTable table, PieceCategory category)
		{
			//IL_0007: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected I4, but got Unknown
			int num = table.m_categories.IndexOf(category);
			if (num >= 0 && num < table.m_categoryLabels.Count)
			{
				string text = table.m_categoryLabels[num];
				if (!string.IsNullOrWhiteSpace(text))
				{
					return text;
				}
			}
			if (1 == 0)
			{
			}
			string result = (category - 5) switch
			{
				1 => "Food", 
				2 => "Meads", 
				0 => "Feasts", 
				_ => ((object)(PieceCategory)(ref category)).ToString(), 
			};
			if (1 == 0)
			{
			}
			return result;
		}

		private static PieceCategory ResolveOrCreateModCategory(PieceCategory baseCategory, FoodSourceMod sourceMod)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected I4, but got Unknown
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			string key = $"{sourceMod.Id}:{(int)baseCategory}";
			lock (ModCategoryLock)
			{
				if (ModCategoryCache.TryGetValue(key, out ModCategoryInfo value))
				{
					return value.Category;
				}
				string text = BuildStableCategoryKey(baseCategory, sourceMod.Id);
				if (!JotunnBridge.TryAddPieceCategory(text, out var category))
				{
					ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogWarning((object)$"Could not create Jotunn category '{text}'. Falling back to vanilla category '{baseCategory}'.");
					return baseCategory;
				}
				ModCategoryCache[key] = new ModCategoryInfo(category, baseCategory, sourceMod);
				return category;
			}
		}

		private static string ResolveCategoryDisplayLabel(PieceCategory category, string baseLabel)
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			if (!string.IsNullOrWhiteSpace(baseLabel))
			{
				string text = baseLabel.Trim();
				string text2 = text;
				if (LooksLikeLocalizationTokenKey(text) && !text.StartsWith("$", StringComparison.Ordinal))
				{
					text2 = "$" + text;
				}
				if (Localization.instance != null)
				{
					string text3 = Localization.instance.Localize(text2);
					if (!string.IsNullOrWhiteSpace(text3) && !string.Equals(text3, text2, StringComparison.Ordinal))
					{
						return text3.Trim();
					}
				}
				if (LooksLikeLocalizationTokenKey(text))
				{
					return GetFallbackCategoryLabel(category);
				}
				return text;
			}
			return GetFallbackCategoryLabel(category);
		}

		private static bool LooksLikeLocalizationTokenKey(string value)
		{
			if (string.IsNullOrWhiteSpace(value))
			{
				return false;
			}
			if (value.StartsWith("$", StringComparison.Ordinal))
			{
				return true;
			}
			if (value.IndexOfAny(new char[4] { ' ', '\t', '\r', '\n' }) >= 0)
			{
				return false;
			}
			if (!value.Contains("_"))
			{
				return false;
			}
			foreach (char c in value)
			{
				if (!char.IsLetterOrDigit(c) && c != '_' && c != '.' && c != '-')
				{
					return false;
				}
			}
			return true;
		}

		private static string BuildDisplayCategoryName(string baseLabel, FoodSourceMod sourceMod)
		{
			return baseLabel + " - " + sourceMod.DisplayName;
		}

		private static string BuildStableCategoryKey(PieceCategory baseCategory, string modId)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected I4, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected I4, but got Unknown
			if (1 == 0)
			{
			}
			string text = (baseCategory - 5) switch
			{
				1 => "food", 
				2 => "meads", 
				0 => "feasts", 
				_ => $"cat{(int)baseCategory}", 
			};
			if (1 == 0)
			{
			}
			string arg = text;
			int num = StringExtensionMethods.GetStableHashCode(modId ?? string.Empty);
			if (num == int.MinValue)
			{
				num = int.MaxValue;
			}
			num = Math.Abs(num);
			return $"syr_{arg}_{num}";
		}

		private static string GetFallbackCategoryLabel(PieceCategory category)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected I4, but got Unknown
			if (1 == 0)
			{
			}
			string result = (category - 5) switch
			{
				1 => "Food", 
				2 => "Meads", 
				0 => "Feasts", 
				_ => ((object)(PieceCategory)(ref category)).ToString(), 
			};
			if (1 == 0)
			{
			}
			return result;
		}

		private static bool TryResolveFoodSourceMod(GameObject foodPrefab, out FoodSourceMod sourceMod)
		{
			string prefabName = Utils.GetPrefabName(((Object)foodPrefab).name);
			if (SourceModHitCache.TryGetValue(prefabName, out var value))
			{
				sourceMod = value;
				return true;
			}
			if (KnownCloneSourceBridge.TryResolveSourceMod(prefabName, out var sourceMod2))
			{
				sourceMod = sourceMod2;
				SourceModHitCache[prefabName] = sourceMod;
				return true;
			}
			if (JotunnBridge.TryGetPrefabSourceMod(prefabName, out var sourceMod3))
			{
				sourceMod = sourceMod3;
				SourceModHitCache[prefabName] = sourceMod;
				return true;
			}
			sourceMod = default(FoodSourceMod);
			return false;
		}

		private static bool IsInjectedByServeYouRight(GameObject foodPrefab)
		{
			return (Object)(object)foodPrefab.GetComponent<ServeYouRightInjectedPieceMarker>() != (Object)null;
		}

		private static void EnsureBaseCategoryExists(PieceTable table, PieceCategory category, string label)
		{
			//IL_0007: 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)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			int num = table.m_categories.IndexOf(category);
			if (num < 0)
			{
				table.m_categories.Add(category);
				while (table.m_categoryLabels.Count < table.m_categories.Count - 1)
				{
					List<string> categoryLabels = table.m_categoryLabels;
					PieceCategory val = table.m_categories[table.m_categoryLabels.Count];
					categoryLabels.Add(((object)(PieceCategory)(ref val)).ToString());
				}
				table.m_categoryLabels.Add(label);
			}
		}

		private static int GetPrefabNameHash(GameObject prefab)
		{
			string prefabName = Utils.GetPrefabName(((Object)prefab).name);
			return StringExtensionMethods.GetStableHashCode(prefabName);
		}

		private static void CopyFields<T>(T source, T destination) where T : class
		{
			FieldInfo[] fields = typeof(T).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (!fieldInfo.IsStatic && !fieldInfo.IsInitOnly && !fieldInfo.IsLiteral)
				{
					fieldInfo.SetValue(destination, fieldInfo.GetValue(source));
				}
			}
		}
	}
	internal readonly struct FoodSourceMod
	{
		public string Id { get; }

		public string DisplayName { get; }

		public FoodSourceMod(string id, string displayName)
		{
			Id = id;
			DisplayName = displayName;
		}
	}
	internal sealed class ModCategoryInfo
	{
		public PieceCategory Category { get; }

		public PieceCategory BaseCategory { get; }

		public FoodSourceMod SourceMod { get; }

		public ModCategoryInfo(PieceCategory category, PieceCategory baseCategory, FoodSourceMod sourceMod)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			Category = category;
			BaseCategory = baseCategory;
			SourceMod = sourceMod;
		}
	}
	internal sealed class PerModCategoryConfig
	{
		public FoodSourceMod Mod { get; }

		public ConfigEntry<ServerSyncModTemplatePlugin.Toggle> Food { get; }

		public ConfigEntry<ServerSyncModTemplatePlugin.Toggle> Meads { get; }

		public ConfigEntry<ServerSyncModTemplatePlugin.Toggle> Feasts { get; }

		public PerModCategoryConfig(FoodSourceMod mod, ConfigEntry<ServerSyncModTemplatePlugin.Toggle> food, ConfigEntry<ServerSyncModTemplatePlugin.Toggle> meads, ConfigEntry<ServerSyncModTemplatePlugin.Toggle> feasts)
		{
			Mod = mod;
			Food = food;
			Meads = meads;
			Feasts = feasts;
		}
	}
	internal static class KnownCloneSourceBridge
	{
		private const string WackyGuid = "WackyMole.WackysDatabase";

		private const string DefaultWackyName = "WackysDatabase";

		private static bool _initialized;

		private static MethodInfo? _wackyGetClonedMap;

		private static string _wackyDisplayName = "WackysDatabase";

		private static readonly HashSet<string> WackyCloneHitCache = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private static readonly HashSet<string> WackyCloneMissCache = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		public static bool TryResolveSourceMod(string prefabName, out FoodSourceMod sourceMod)
		{
			sourceMod = default(FoodSourceMod);
			EnsureInitialized();
			if (_wackyGetClonedMap == null)
			{
				return false;
			}
			if (WackyCloneHitCache.Contains(prefabName))
			{
				sourceMod = new FoodSourceMod("WackyMole.WackysDatabase", _wackyDisplayName);
				return true;
			}
			if (WackyCloneMissCache.Contains(prefabName))
			{
				return false;
			}
			try
			{
				object obj = _wackyGetClonedMap.Invoke(null, new object[1] { prefabName });
				string value = obj as string;
				if (string.IsNullOrWhiteSpace(value))
				{
					WackyCloneMissCache.Add(prefabName);
					return false;
				}
				WackyCloneHitCache.Add(prefabName);
				sourceMod = new FoodSourceMod("WackyMole.WackysDatabase", _wackyDisplayName);
				return true;
			}
			catch (Exception ex)
			{
				ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogDebug((object)("Known clone source resolution failed for '" + prefabName + "': " + ex.Message));
				return false;
			}
		}

		private static void EnsureInitialized()
		{
			if (_initialized)
			{
				return;
			}
			_initialized = true;
			try
			{
				_wackyGetClonedMap = Type.GetType("API.WackyAPI, WackysDatabase")?.GetMethod("GetClonedMap", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null);
				if (Chainloader.PluginInfos.TryGetValue("WackyMole.WackysDatabase", out var value))
				{
					object obj;
					if (value == null)
					{
						obj = null;
					}
					else
					{
						BepInPlugin metadata = value.Metadata;
						obj = ((metadata != null) ? metadata.Name : null);
					}
					if (obj == null)
					{
						obj = string.Empty;
					}
					string text = (string)obj;
					if (!string.IsNullOrWhiteSpace(text))
					{
						_wackyDisplayName = text;
					}
				}
			}
			catch (Exception ex)
			{
				_wackyGetClonedMap = null;
				ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogDebug((object)("Known clone source bridge init failed: " + ex.Message));
			}
		}
	}
	internal static class JotunnBridge
	{
		private static bool _initialized;

		private static bool _available;

		private static MethodInfo? _modQueryEnable;

		private static MethodInfo? _modQueryGetPrefab;

		private static PropertyInfo? _pieceManagerInstance;

		private static MethodInfo? _pieceManagerAddPieceCategory;

		public static void InitializeAndEnableModQuery()
		{
			if (_initialized)
			{
				EnableModQuery();
				return;
			}
			_initialized = true;
			try
			{
				Type type = Type.GetType("Jotunn.Utils.ModQuery, Jotunn");
				Type type2 = Type.GetType("Jotunn.Managers.PieceManager, Jotunn");
				_modQueryEnable = type?.GetMethod("Enable", BindingFlags.Static | BindingFlags.Public);
				_modQueryGetPrefab = type?.GetMethod("GetPrefab", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null);
				_pieceManagerInstance = type2?.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public);
				_pieceManagerAddPieceCategory = type2?.GetMethod("AddPieceCategory", BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(string) }, null);
				_available = _modQueryEnable != null && _modQueryGetPrefab != null && _pieceManagerInstance != null && _pieceManagerAddPieceCategory != null;
			}
			catch (Exception ex)
			{
				_available = false;
				ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogWarning((object)("Failed to initialize Jotunn bridge: " + ex.Message));
			}
			if (!_available)
			{
				ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogWarning((object)"Jotunn bridge is unavailable. Mod-specific tabs will fall back to vanilla categories.");
			}
			else
			{
				EnableModQuery();
			}
		}

		public static bool TryGetPrefabSourceMod(string prefabName, out FoodSourceMod sourceMod)
		{
			sourceMod = default(FoodSourceMod);
			if (!_available || _modQueryGetPrefab == null)
			{
				return false;
			}
			try
			{
				object obj = _modQueryGetPrefab.Invoke(null, new object[1] { prefabName });
				if (obj == null)
				{
					return false;
				}
				object obj2 = obj.GetType().GetProperty("SourceMod", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj);
				if (obj2 == null)
				{
					return false;
				}
				BepInPlugin val = (BepInPlugin)((obj2 is BepInPlugin) ? obj2 : null);
				if (val != null)
				{
					string displayName = (string.IsNullOrWhiteSpace(val.Name) ? val.GUID : val.Name);
					sourceMod = new FoodSourceMod(val.GUID, displayName);
					return true;
				}
				string text = obj2.GetType().GetProperty("GUID", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj2) as string;
				string text2 = obj2.GetType().GetProperty("Name", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj2) as string;
				string text3 = text ?? string.Empty;
				if (string.IsNullOrWhiteSpace(text3))
				{
					return false;
				}
				string displayName2 = (string.IsNullOrWhiteSpace(text2) ? text3 : text2);
				sourceMod = new FoodSourceMod(text3, displayName2);
				return true;
			}
			catch (Exception ex)
			{
				ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogDebug((object)("ModQuery.GetPrefab failed for '" + prefabName + "': " + ex.Message));
				return false;
			}
		}

		public static bool TryAddPieceCategory(string categoryName, out PieceCategory category)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected I4, but got Unknown
			category = (PieceCategory)6;
			if (!_available || _pieceManagerInstance == null || _pieceManagerAddPieceCategory == null)
			{
				return false;
			}
			try
			{
				object value = _pieceManagerInstance.GetValue(null);
				if (value == null)
				{
					return false;
				}
				object obj = _pieceManagerAddPieceCategory.Invoke(value, new object[1] { categoryName });
				if (obj is PieceCategory val)
				{
					category = (PieceCategory)(int)val;
					return true;
				}
				if (obj is int num)
				{
					category = (PieceCategory)num;
					return true;
				}
				return false;
			}
			catch (Exception ex)
			{
				ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogWarning((object)("Failed to add Jotunn piece category '" + categoryName + "': " + ex.Message));
				return false;
			}
		}

		private static void EnableModQuery()
		{
			if (!_available || _modQueryEnable == null)
			{
				return;
			}
			try
			{
				_modQueryEnable.Invoke(null, null);
			}
			catch (Exception ex)
			{
				ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogWarning((object)("Failed to enable Jotunn ModQuery: " + ex.Message));
			}
		}
	}
	internal sealed class ServeYouRightInjectedPieceMarker : MonoBehaviour
	{
	}
	public static class KeyboardExtensions
	{
		[SpecialName]
		public sealed class <G>$8D1D3E80A18AA9715780B6CB7003B2F1
		{
			[SpecialName]
			public static class <M>$895AB635D4D087636CF1C26BA650BA11
			{
			}

			[ExtensionMarker("<M>$895AB635D4D087636CF1C26BA650BA11")]
			public bool IsKeyDown()
			{
				throw null;
			}

			[ExtensionMarker("<M>$895AB635D4D087636CF1C26BA650BA11")]
			public bool IsKeyHeld()
			{
				throw null;
			}
		}

		public static bool IsKeyDown(this KeyboardShortcut shortcut)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			return (int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey) && ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey);
		}

		public static bool IsKeyHeld(this KeyboardShortcut shortcut)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			return (int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey) && ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey);
		}
	}
	public static class ToggleExtentions
	{
		[SpecialName]
		public sealed class <G>$57ABA57BD1CE54EF9BE00DAABFE926BC
		{
			[SpecialName]
			public static class <M>$C02B13F2B6FFC3465B74B38D50860BED
			{
			}

			[ExtensionMarker("<M>$C02B13F2B6FFC3465B74B38D50860BED")]
			public bool IsOn()
			{
				throw null;
			}

			[ExtensionMarker("<M>$C02B13F2B6FFC3465B74B38D50860BED")]
			public bool IsOff()
			{
				throw null;
			}
		}

		public static bool IsOn(this ServerSyncModTemplatePlugin.Toggle value)
		{
			return value == ServerSyncModTemplatePlugin.Toggle.On;
		}

		public static bool IsOff(this ServerSyncModTemplatePlugin.Toggle value)
		{
			return value == ServerSyncModTemplatePlugin.Toggle.Off;
		}
	}
}