Decompiled source of BronzeAgeChest v1.0.8

plugins\BronzeAgeChest.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Common;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using SimpleJson;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("BronzeAgeChest")]
[assembly: AssemblyDescription("https://thunderstore.io/c/valheim/p/probablykory/BronzeAgeChest/")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyProduct("BronzeAgeChest")]
[assembly: AssemblyCopyright("Copyright probablykory © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("1.0.8")]
[assembly: AssemblyCompany("probablykory")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.8.0")]
[module: <d3f99811-048d-4877-8cce-f85228c1c50b>RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[<140a1b61-9b0f-45d5-865a-7e7a0d70c359>Embedded]
	internal sealed class <140a1b61-9b0f-45d5-865a-7e7a0d70c359>EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[<140a1b61-9b0f-45d5-865a-7e7a0d70c359>Embedded]
	[CompilerGenerated]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class <d3f99811-048d-4877-8cce-f85228c1c50b>RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public <d3f99811-048d-4877-8cce-f85228c1c50b>RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BronzeAgeChest
{
	public static class RequirementsEntry
	{
		public static RequirementConfig[] Deserialize(string reqs)
		{
			return ((IEnumerable<string>)reqs.Split(new char[1] { ',' })).Select((Func<string, RequirementConfig>)delegate(string r)
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: 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_0060: Expected O, but got Unknown
				string[] array = r.Split(new char[1] { ':' });
				int result;
				int result2;
				return new RequirementConfig
				{
					Item = array[0],
					Amount = ((array.Length <= 1 || !int.TryParse(array[1], out result)) ? 1 : result),
					AmountPerLevel = ((array.Length > 2 && int.TryParse(array[2], out result2)) ? result2 : 0),
					Recover = true
				};
			}).ToArray();
		}

		public static string Serialize(RequirementConfig[] reqs)
		{
			return string.Join(",", reqs.Select((RequirementConfig r) => (r.AmountPerLevel <= 0) ? $"{r.Item}:{r.Amount}" : $"{r.Item}:{r.Amount}:{r.AmountPerLevel}"));
		}
	}
	internal class Entries
	{
		private Action<object, EventArgs> _action;

		public string Name { get; set; } = string.Empty;


		public ConfigEntry<string> Table { get; set; }

		public ConfigEntry<int> MinTableLevel { get; set; }

		public ConfigEntry<int> Amount { get; set; }

		public ConfigEntry<string> Requirements { get; set; }

		public static Entries GetFromProps(IPlugin instance, string name, string table, string requirements)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			Entries entries = new Entries();
			entries.Name = name;
			entries.Table = instance.Config(entries.Name, "Table", table, new ConfigDescription("Crafting station needed to construct " + entries.Name + ".", (AcceptableValueBase)(object)CraftingStations.GetAcceptableValueList(), new object[1] { ConfigHelper.GetAdminOnlyFlag() }));
			entries.Requirements = instance.Config(entries.Name, "Requirements", requirements, new ConfigDescription("The required items to construct " + entries.Name + ".", (AcceptableValueBase)(object)new AcceptableValueConfigNote("You must use valid spawn item codes."), new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true,
				CustomDrawer = SharedDrawers.DrawReqConfigTable()
			} }));
			return entries;
		}

		private void OnSettingChanged(object sender, EventArgs e)
		{
			if (_action != null)
			{
				_action(sender, e);
			}
		}

		public void AddSettingsChangedHandler(Action<object, EventArgs> action)
		{
			_action = action;
			Table.SettingChanged += OnSettingChanged;
			MinTableLevel.SettingChanged += OnSettingChanged;
			Amount.SettingChanged += OnSettingChanged;
			Requirements.SettingChanged += OnSettingChanged;
		}

		public void RemoveSettingsChangedHandler()
		{
			Table.SettingChanged -= OnSettingChanged;
			MinTableLevel.SettingChanged -= OnSettingChanged;
			Amount.SettingChanged -= OnSettingChanged;
			Requirements.SettingChanged -= OnSettingChanged;
			_action = null;
		}
	}
	public static class Extensions
	{
		private static Dictionary<string, CustomPiece> dictPieces;

		public static Piece GetPiece(Piece piece)
		{
			Piece val = null;
			foreach (KeyValuePair<string, PieceTable> item in ReflectionHelper.GetPrivateField<Dictionary<string, PieceTable>>((object)PieceManager.Instance, "PieceTableMap"))
			{
				foreach (GameObject piece2 in item.Value.m_pieces)
				{
					Piece component = piece2.GetComponent<Piece>();
					if (!string.IsNullOrEmpty(((Object)component).name) && ((Object)component).name.Equals(((Object)piece).name))
					{
						val = component;
						break;
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					break;
				}
			}
			return val;
		}

		public static bool Update(this CustomPiece piece, PieceConfig newPiece)
		{
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Expected O, but got Unknown
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Expected O, but got Unknown
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				Piece piece2 = GetPiece(piece.Piece);
				if ((Object)(object)piece2 == (Object)null)
				{
					ManualLogSource logger = Get.Plugin.Logger;
					object obj;
					if (piece == null)
					{
						obj = null;
					}
					else
					{
						Piece piece3 = piece.Piece;
						obj = ((piece3 != null) ? ((Object)piece3).name : null);
					}
					logger.LogError((object)("Error updating piece " + (string?)obj + ", did not find existing piece in available piece tables."));
					return false;
				}
				piece2.m_craftingStation = ZNetScene.instance.GetPrefab(newPiece.CraftingStation).GetComponent<CraftingStation>();
				piece2.m_resources = newPiece.GetRequirements();
				Requirement[] resources = piece2.m_resources;
				foreach (Requirement val in resources)
				{
					GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(((Object)val.m_resItem).name.Replace("JVLmock_", ""));
					if ((Object)(object)itemPrefab != (Object)null)
					{
						val.m_resItem = itemPrefab.GetComponent<ItemDrop>();
					}
				}
				if (dictPieces == null)
				{
					Dictionary<string, CustomPiece> privateField = ReflectionHelper.GetPrivateField<Dictionary<string, CustomPiece>>((object)PieceManager.Instance, "Pieces");
					if (privateField != null)
					{
						dictPieces = privateField;
					}
				}
				if (dictPieces != null)
				{
					dictPieces.Remove(((Object)((Component)piece2).gameObject).name);
					dictPieces.Add(((Object)((Component)piece2).gameObject).name, new CustomPiece(((Component)piece2).gameObject, piece.PieceTable, false));
				}
				return true;
			}
			PieceManager.Instance.RemovePiece(((Object)piece.PiecePrefab).name);
			PieceManager.Instance.AddPiece(new CustomPiece(piece.PiecePrefab, false, newPiece));
			return false;
		}
	}
	[BepInPlugin("probablykory.BronzeAgeChest", "BronzeAgeChest", "1.0.8")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal class BronzeAgeChest : BaseUnityPlugin, IPlugin
	{
		public const string PluginAuthor = "probablykory";

		public const string PluginName = "BronzeAgeChest";

		public const string PluginVersion = "1.0.8";

		public const string PluginGUID = "probablykory.BronzeAgeChest";

		internal static BronzeAgeChest Instance;

		internal AssetBundle assetBundle;

		private static ConfigEntry<bool> isDebugEnabled = null;

		private CustomPiece bronzeChest;

		private const string Name = "$piece_chest_bronze";

		private const string PieceTable = "Hammer";

		private const string Category = "Furniture";

		private static Dictionary<string, string> DefaultEnglishLanguageStrings = new Dictionary<string, string> { { "$piece_chest_bronze", "Rugged Chest" } };

		public ManualLogSource Logger { get; private set; } = Logger.CreateLogSource("BronzeAgeChest");


		public bool Debug
		{
			get
			{
				if (isDebugEnabled == null)
				{
					return true;
				}
				return isDebugEnabled.Value;
			}
		}

		public Entries Entry { get; protected set; }

		private void Awake()
		{
			Instance = this;
			assetBundle = AssetUtils.LoadAssetBundleFromResources("bronzechest");
			isDebugEnabled = this.Config("1 - General", "Debugging Enabled", value: false, "If on, mod will output alot more information in the debug log level.");
			InitializeFeatures();
			AddDefaultLocalizations();
			PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable;
			LocalizationManager.OnLocalizationAdded += OnLocalizationAdded;
			SynchronizationManager.OnConfigurationSynchronized += OnConfigurationSynchronized;
			((BaseUnityPlugin)this).Config.ConfigReloaded += OnConfigReloaded;
			new ConfigWatcher(this);
		}

		private void InitializeFeatures()
		{
			Entry = Entries.GetFromProps(Instance, "BronzeChest", "Workbench", "Wood:15,Bronze:1,BronzeNails:10");
		}

		private void UpdateFeatures()
		{
			bronzeChest.Update(getPieceFromEntry(Entry));
		}

		private void OnVanillaPrefabsAvailable()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			this.LogDebugOnly("Vanilla Prefabs Available received.");
			bronzeChest = new CustomPiece(assetBundle, "piece_chest_bronze", true, getPieceFromEntry(Entry));
			PieceManager.Instance.AddPiece(bronzeChest);
			PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable;
		}

		private void OnConfigReloaded(object sender, EventArgs e)
		{
			UpdateFeatures();
		}

		private void OnConfigurationSynchronized(object sender, ConfigurationSynchronizationEventArgs e)
		{
			UpdateFeatures();
		}

		private PieceConfig getPieceFromEntry(Entries entry)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			return new PieceConfig
			{
				Name = "$piece_chest_bronze",
				CraftingStation = CraftingStations.GetInternalName(entry.Table.Value),
				PieceTable = "Hammer",
				Category = "Furniture",
				Requirements = RequirementsEntry.Deserialize(entry.Requirements.Value)
			};
		}

		private void AddDefaultLocalizations()
		{
			this.LogDebugOnly("AddLocalizations called.");
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			string text = "English";
			localization.AddTranslation(ref text, DefaultEnglishLanguageStrings);
		}

		private void OnLocalizationAdded()
		{
			this.LogDebugOnly("Localization Added received.");
			string location = ((object)Instance).GetType().Assembly.Location;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			string text = location.Replace(directorySeparatorChar + "BronzeAgeChest.dll", "");
			if (Paths.PluginPath.Equals(text))
			{
				text = Utility.CombinePaths(new string[2]
				{
					Paths.PluginPath,
					"BronzeAgeChest"
				});
			}
			string text2 = Utility.CombinePaths(new string[4] { text, "Translations", "English", "english.json" });
			string directoryName = Path.GetDirectoryName(text2);
			if (!Directory.Exists(directoryName) || !File.Exists(text2))
			{
				Directory.CreateDirectory(directoryName);
				string contents = SimpleJson.SerializeObject((object)DefaultEnglishLanguageStrings);
				File.WriteAllText(text2, contents);
				this.LogInfo("Default localizations written to " + text2);
			}
			LocalizationManager.OnLocalizationAdded -= OnLocalizationAdded;
		}

		ConfigFile IPlugin.get_Config()
		{
			return ((BaseUnityPlugin)this).Config;
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[Microsoft.CodeAnalysis.Embedded]
	[CompilerGenerated]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	[CompilerGenerated]
	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]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	[Microsoft.CodeAnalysis.Embedded]
	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;
		}
	}
}
namespace Common
{
	internal class AcceptableValueConfigNote : AcceptableValueBase
	{
		public virtual string Note { get; }

		public AcceptableValueConfigNote(string note)
			: base(typeof(string))
		{
			if (string.IsNullOrEmpty(note))
			{
				throw new ArgumentException("A string with atleast 1 character is needed", "Note");
			}
			Note = note;
		}

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

		public override bool IsValid(object value)
		{
			return !string.IsNullOrEmpty(value as string);
		}

		public override string ToDescriptionString()
		{
			return "# Note: " + Note;
		}
	}
	internal static class ConfigHelper
	{
		public static ConfigurationManagerAttributes GetAdminOnlyFlag()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			return new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			};
		}

		public static ConfigurationManagerAttributes GetTags(Action<ConfigEntryBase> action)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			return new ConfigurationManagerAttributes
			{
				CustomDrawer = action
			};
		}

		public static ConfigurationManagerAttributes GetTags()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			return new ConfigurationManagerAttributes();
		}

		public static ConfigEntry<T> Config<T>(this IPlugin instance, string group, string name, T value, ConfigDescription description)
		{
			return instance.Config.Bind<T>(group, name, value, description);
		}

		public static ConfigEntry<T> Config<T>(this IPlugin instance, string group, string name, T value, string description)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			return instance.Config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { GetAdminOnlyFlag() }));
		}
	}
	internal static class RequirementsEntry
	{
		public static RequirementConfig[] Deserialize(string reqs)
		{
			return ((IEnumerable<string>)reqs.Split(new char[1] { ',' })).Select((Func<string, RequirementConfig>)delegate(string r)
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: 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_0060: Expected O, but got Unknown
				string[] array = r.Split(new char[1] { ':' });
				int result;
				int result2;
				return new RequirementConfig
				{
					Item = array[0],
					Amount = ((array.Length <= 1 || !int.TryParse(array[1], out result)) ? 1 : result),
					AmountPerLevel = ((array.Length > 2 && int.TryParse(array[2], out result2)) ? result2 : 0),
					Recover = true
				};
			}).ToArray();
		}

		public static string Serialize(RequirementConfig[] reqs)
		{
			return string.Join(",", reqs.Select((RequirementConfig r) => (r.AmountPerLevel <= 0) ? $"{r.Item}:{r.Amount}" : $"{r.Item}:{r.Amount}:{r.AmountPerLevel}"));
		}
	}
	internal static class SharedDrawers
	{
		private static BaseUnityPlugin configManager;

		private static BaseUnityPlugin GetConfigManager()
		{
			if ((Object)(object)configManager == (Object)null && Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out var value) && Object.op_Implicit((Object)(object)value.Instance))
			{
				configManager = value.Instance;
			}
			return configManager;
		}

		public static int GetRightColumnWidth()
		{
			int result = 130;
			BaseUnityPlugin val = GetConfigManager();
			if ((Object)(object)val != (Object)null)
			{
				PropertyInfo propertyInfo = ((object)val)?.GetType().GetProperty("RightColumnWidth", BindingFlags.Instance | BindingFlags.NonPublic);
				if (propertyInfo != null)
				{
					result = (int)propertyInfo.GetValue(val);
				}
			}
			return result;
		}

		public static void ReloadConfigDisplay()
		{
			BaseUnityPlugin val = GetConfigManager();
			if ((Object)(object)val != (Object)null)
			{
				object obj = ((object)val).GetType()?.GetProperty("DisplayingWindow")?.GetValue(val);
				if (obj is bool && (bool)obj)
				{
					((object)val).GetType().GetMethod("BuildSettingList").Invoke(val, Array.Empty<object>());
				}
			}
		}

		public static Action<ConfigEntryBase> DrawReqConfigTable(bool hasUpgrades = false)
		{
			return delegate(ConfigEntryBase cfg)
			{
				//IL_005c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_008d: Expected O, but got Unknown
				//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ee: Expected O, but got Unknown
				//IL_0163: Unknown result type (might be due to invalid IL or missing references)
				//IL_0168: Unknown result type (might be due to invalid IL or missing references)
				//IL_017d: Expected O, but got Unknown
				//IL_0125: Unknown result type (might be due to invalid IL or missing references)
				//IL_012a: Unknown result type (might be due to invalid IL or missing references)
				//IL_013f: Expected O, but got Unknown
				//IL_0184: Unknown result type (might be due to invalid IL or missing references)
				//IL_0189: Unknown result type (might be due to invalid IL or missing references)
				//IL_0191: Unknown result type (might be due to invalid IL or missing references)
				//IL_0199: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a6: Expected O, but got Unknown
				//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
				//IL_01cf: Expected O, but got Unknown
				//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_01e4: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f0: Expected O, but got Unknown
				List<RequirementConfig> list = new List<RequirementConfig>();
				bool flag = false;
				int rightColumnWidth = GetRightColumnWidth();
				GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
				foreach (RequirementConfig item in RequirementsEntry.Deserialize((string)cfg.BoxedValue).ToList())
				{
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					string text = GUILayout.TextField(item.Item, new GUIStyle(GUI.skin.textField)
					{
						fixedWidth = rightColumnWidth - 33 - (hasUpgrades ? 37 : 0) - 21 - 21 - 12
					}, Array.Empty<GUILayoutOption>());
					string text2 = (string.IsNullOrEmpty(text) ? item.Item : text);
					flag = flag || text2 != item.Item;
					int num = item.Amount;
					if (int.TryParse(GUILayout.TextField(num.ToString(), new GUIStyle(GUI.skin.textField)
					{
						fixedWidth = 33f
					}, Array.Empty<GUILayoutOption>()), out var result) && result != num)
					{
						num = result;
						flag = true;
					}
					int num2 = item.AmountPerLevel;
					if (hasUpgrades && int.TryParse(GUILayout.TextField(num2.ToString(), new GUIStyle(GUI.skin.textField)
					{
						fixedWidth = 33f
					}, Array.Empty<GUILayoutOption>()), out var result2) && result2 != num2)
					{
						num2 = result2;
						flag = true;
					}
					if (GUILayout.Button("x", new GUIStyle(GUI.skin.button)
					{
						fixedWidth = 21f
					}, Array.Empty<GUILayoutOption>()))
					{
						flag = true;
					}
					else
					{
						list.Add(new RequirementConfig
						{
							Item = text2,
							Amount = num,
							AmountPerLevel = num2
						});
					}
					if (GUILayout.Button("+", new GUIStyle(GUI.skin.button)
					{
						fixedWidth = 21f
					}, Array.Empty<GUILayoutOption>()))
					{
						flag = true;
						list.Add(new RequirementConfig
						{
							Item = "<Prefab Name>",
							Amount = 1
						});
					}
					GUILayout.EndHorizontal();
				}
				GUILayout.EndVertical();
				if (flag)
				{
					cfg.BoxedValue = RequirementsEntry.Serialize(list.ToArray());
				}
			};
		}
	}
	internal class ConfigWatcher
	{
		private BaseUnityPlugin configurationManager;

		private IPlugin plugin;

		public ConfigWatcher(IPlugin plugin)
		{
			if (plugin == null)
			{
				throw new ArgumentNullException("plugin");
			}
			this.plugin = plugin;
			CheckForConfigManager();
		}

		private void InitializeWatcher()
		{
			string fileName = Path.GetFileName(plugin.Config.ConfigFilePath);
			new Watcher(Path.GetDirectoryName(plugin.Config.ConfigFilePath), fileName).FileChanged += OnFileChanged;
			Get.Plugin.LogDebugOnly("File system watcher initialized.");
		}

		private void CheckForConfigManager()
		{
			PluginInfo value;
			if (GUIManager.IsHeadless())
			{
				InitializeWatcher();
			}
			else if (Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out value) && Object.op_Implicit((Object)(object)value.Instance))
			{
				configurationManager = value.Instance;
				Get.Plugin.LogDebugOnly("Configuration manager found, hooking DisplayingWindowChanged");
				EventInfo @event = ((object)configurationManager).GetType().GetEvent("DisplayingWindowChanged");
				if (@event != null)
				{
					Action<object, object> action = OnConfigManagerDisplayingWindowChanged;
					Delegate handler = Delegate.CreateDelegate(@event.EventHandlerType, action.Target, action.Method);
					@event.AddEventHandler(configurationManager, handler);
				}
			}
			else
			{
				InitializeWatcher();
			}
		}

		private void OnFileChanged(object sender, FileSystemEventArgs e)
		{
			string configFilePath = plugin.Config.ConfigFilePath;
			if (!File.Exists(configFilePath))
			{
				return;
			}
			try
			{
				plugin.Config.SaveOnConfigSet = false;
				plugin.Config.Reload();
				plugin.Config.SaveOnConfigSet = true;
			}
			catch
			{
				Get.Plugin.LogError("There was an issue with your " + Path.GetFileName(configFilePath) + " file.");
				Get.Plugin.LogError("Please check the format and spelling.");
			}
		}

		private void OnConfigManagerDisplayingWindowChanged(object sender, object e)
		{
			if (!(bool)((object)configurationManager).GetType().GetProperty("DisplayingWindow").GetValue(configurationManager, null))
			{
				plugin.Config.SaveOnConfigSet = false;
				plugin.Config.Reload();
				plugin.Config.SaveOnConfigSet = true;
			}
		}
	}
	internal class CustomSyncedValueBase
	{
		private class Patches
		{
			[HarmonyPatch(typeof(ZNet), "Shutdown")]
			[HarmonyPostfix]
			private static void ZNet_Shutdown()
			{
				if (ZNetExtension.IsClientInstance(ZNet.instance))
				{
					foreach (CustomSyncedValueBase syncedValue in SyncedValues)
					{
						syncedValue.OnResetFromServer();
					}
					return;
				}
				foreach (CustomSyncedValueBase syncedValue2 in SyncedValues)
				{
					syncedValue2.OnServerShutdown();
				}
			}
		}

		public readonly string Name;

		public readonly Type Type;

		private object? boxedValue;

		public object? LocalBaseValue;

		private CustomRPC customRPC;

		private static readonly HashSet<CustomSyncedValueBase> SyncedValues = new HashSet<CustomSyncedValueBase>();

		private static Harmony harmony = null;

		public bool IsSourceOfTruth { get; private set; } = true;


		public object? BoxedValue
		{
			get
			{
				return boxedValue;
			}
			set
			{
				boxedValue = value;
				this.ValueChanged?.Invoke(this, value);
			}
		}

		public event Action<object, object>? ValueChanged;

		protected CustomSyncedValueBase(string name, Type type, object? initialValue)
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			//IL_00af: Expected O, but got Unknown
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			Name = name;
			Type = type;
			SyncedValues.Add(this);
			if (harmony == null)
			{
				harmony = (Harmony)AccessTools.Field(typeof(Main), "Harmony").GetValue(null);
				harmony.PatchAll(typeof(Patches));
				Get.Plugin.LogDebugOnly("Jotunn's harmony instance obtained, CustomSyncedValueBase+Patches applied.");
			}
			boxedValue = initialValue;
			customRPC = NetworkManager.Instance.AddRPC(Name + "_CustomSyncedValue_RPC", new CoroutineHandler(OnServerReceive), new CoroutineHandler(OnClientReceive));
			SynchronizationManager.Instance.AddInitialSynchronization(customRPC, (Func<ZPackage>)GetPackage);
		}

		public void SendPackage()
		{
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				Get.Plugin.LogDebugOnly("SendPackage called but am not connected.");
			}
			if (!SynchronizationManager.Instance.PlayerIsAdmin)
			{
				Get.Plugin.LogDebugOnly("SendPackage called but Player is not admin.");
			}
			if ((Object)(object)ZNet.instance != (Object)null && SynchronizationManager.Instance.PlayerIsAdmin)
			{
				ZPackage package = GetPackage();
				if (ZNetExtension.IsClientInstance(ZNet.instance))
				{
					customRPC.SendPackage(ZRoutedRpc.instance.GetServerPeerID(), package);
				}
				else
				{
					customRPC.SendPackage(ZNet.instance.m_peers, package);
				}
			}
		}

		private ZPackage GetPackage()
		{
			return new PackageEntry
			{
				key = Name,
				type = Type,
				value = boxedValue
			}.ToPackage();
		}

		private IEnumerator OnServerReceive(long sender, ZPackage package)
		{
			Get.Plugin.LogDebugOnly($"Server received RPC: {sender} {package}");
			yield return null;
			ParsedEntries parsedEntries = package.ReadEntries();
			if (parsedEntries.Count > 0 && parsedEntries.TryGetValue(Name, out var value))
			{
				BoxedValue = (LocalBaseValue = value.value);
				Get.Plugin.LogDebugOnly($"Set local and boxed: {value.value}");
				customRPC.SendPackage(ZNet.instance.m_peers.Where((ZNetPeer x) => x.m_uid != sender).ToList(), package);
			}
			else
			{
				OnReceiveError(parsedEntries);
			}
		}

		private IEnumerator OnClientReceive(long sender, ZPackage package)
		{
			Get.Plugin.LogDebugOnly($"Client received RPC: {sender} {package}");
			yield return null;
			ParsedEntries parsedEntries = package.ReadEntries();
			if (parsedEntries.Count > 0 && parsedEntries.TryGetValue(Name, out var value))
			{
				IsSourceOfTruth = false;
				if (LocalBaseValue == null)
				{
					LocalBaseValue = BoxedValue;
				}
				BoxedValue = value.value;
				Get.Plugin.LogDebugOnly($"Set source of truth: {IsSourceOfTruth}, {Environment.NewLine}local: {LocalBaseValue} {Environment.NewLine}boxed: {BoxedValue}");
			}
			else
			{
				OnReceiveError(parsedEntries);
			}
		}

		private void OnReceiveError(ParsedEntries entries)
		{
			Get.Plugin.LogWarning(Name + "_CustomSyncedValue_RPC recieved package without expected key: " + Name);
			string text = "";
			foreach (KeyValuePair<string, PackageEntry> entry in entries)
			{
				text += $"{entry.Key} - {entry.Value.type} - {entry.Value.value?.ToString()} {Environment.NewLine}";
			}
			Get.Plugin.LogWarning("Result: " + Environment.NewLine + text);
		}

		private void OnResetFromServer()
		{
			BoxedValue = LocalBaseValue;
			IsSourceOfTruth = true;
			LocalBaseValue = null;
		}

		private void OnServerShutdown()
		{
		}
	}
	internal sealed class CustomSyncedValue<T> : CustomSyncedValueBase
	{
		public T Value
		{
			get
			{
				return (T)base.BoxedValue;
			}
			set
			{
				base.BoxedValue = value;
				if (base.BoxedValue != null)
				{
					SendPackage();
				}
			}
		}

		public CustomSyncedValue(string name, T value = default(T))
			: base(name, typeof(T), value)
		{
		}

		public void AssignLocalValue(T value)
		{
			if (base.IsSourceOfTruth && SynchronizationManager.Instance.PlayerIsAdmin)
			{
				Value = value;
			}
			else
			{
				LocalBaseValue = value;
			}
		}
	}
	internal class ParsedEntries : Dictionary<string, PackageEntry>
	{
	}
	internal class PackageEntry
	{
		public string key;

		public Type type;

		public object? value;
	}
	internal class InvalidDeserializationTypeException : Exception
	{
		public string expected;

		public string received;

		public string field = "";
	}
	internal static class PackageUtils
	{
		public static string GetPackageTypeString(Type type)
		{
			return type.AssemblyQualifiedName;
		}

		public static void AddValue(this ZPackage package, object? value)
		{
			Type type = value?.GetType();
			if (value is Enum)
			{
				value = ((IConvertible)value).ToType(Enum.GetUnderlyingType(value.GetType()), CultureInfo.InvariantCulture);
			}
			else
			{
				if (value is ICollection collection)
				{
					package.Write(collection.Count);
					{
						foreach (object item in collection)
						{
							package.AddValue(item);
						}
						return;
					}
				}
				if ((object)type != null && type.IsValueType && !type.IsPrimitive)
				{
					FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					package.Write(fields.Length);
					FieldInfo[] array = fields;
					foreach (FieldInfo fieldInfo in array)
					{
						package.Write(GetPackageTypeString(fieldInfo.FieldType));
						package.AddValue(fieldInfo.GetValue(value));
					}
					return;
				}
			}
			ZRpc.Serialize(new object[1] { value }, ref package);
		}

		public static void AddEntry(this ZPackage package, PackageEntry entry)
		{
			package.Write(entry.key);
			package.Write((entry.value == null) ? "" : GetPackageTypeString(entry.type));
			package.AddValue(entry.value);
		}

		public static ZPackage ToPackage(this PackageEntry packageEntry)
		{
			return new List<PackageEntry> { packageEntry }.ToPackage();
		}

		public static ZPackage ToPackage(this IEnumerable<PackageEntry> packageEntries)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(packageEntries?.Count() ?? 0);
			foreach (PackageEntry item in packageEntries ?? Array.Empty<PackageEntry>())
			{
				val.AddEntry(item);
			}
			return val;
		}

		public static object ReadValueWithType(this ZPackage package, Type type)
		{
			if ((object)type != null && type.IsValueType && !type.IsPrimitive && !type.IsEnum)
			{
				FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				int num = package.ReadInt();
				if (num != fields.Length)
				{
					throw new InvalidDeserializationTypeException
					{
						received = $"(field count: {num})",
						expected = $"(field count: {fields.Length})"
					};
				}
				object uninitializedObject = FormatterServices.GetUninitializedObject(type);
				FieldInfo[] array = fields;
				foreach (FieldInfo fieldInfo in array)
				{
					string text = package.ReadString();
					if (text != GetPackageTypeString(fieldInfo.FieldType))
					{
						throw new InvalidDeserializationTypeException
						{
							received = text,
							expected = GetPackageTypeString(fieldInfo.FieldType),
							field = fieldInfo.Name
						};
					}
					fieldInfo.SetValue(uninitializedObject, package.ReadValueWithType(fieldInfo.FieldType));
				}
				return uninitializedObject;
			}
			if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<, >))
			{
				int num2 = package.ReadInt();
				IDictionary dictionary = (IDictionary)Activator.CreateInstance(type);
				Type type2 = typeof(KeyValuePair<, >).MakeGenericType(type.GenericTypeArguments);
				FieldInfo field = type2.GetField("key", BindingFlags.Instance | BindingFlags.NonPublic);
				FieldInfo field2 = type2.GetField("value", BindingFlags.Instance | BindingFlags.NonPublic);
				for (int j = 0; j < num2; j++)
				{
					object obj = package.ReadValueWithType(type2);
					dictionary.Add(field.GetValue(obj), field2.GetValue(obj));
				}
				return dictionary;
			}
			if (type != typeof(List<string>) && type.IsGenericType)
			{
				Type type3 = typeof(ICollection<>).MakeGenericType(type.GenericTypeArguments[0]);
				if ((object)type3 != null && type3.IsAssignableFrom(type))
				{
					int num3 = package.ReadInt();
					object obj2 = Activator.CreateInstance(type);
					MethodInfo method = type3.GetMethod("Add");
					for (int k = 0; k < num3; k++)
					{
						method.Invoke(obj2, new object[1] { package.ReadValueWithType(type.GenericTypeArguments[0]) });
					}
					return obj2;
				}
			}
			ParameterInfo parameterInfo = (ParameterInfo)FormatterServices.GetUninitializedObject(typeof(ParameterInfo));
			AccessTools.DeclaredField(typeof(ParameterInfo), "ClassImpl").SetValue(parameterInfo, type);
			List<object> source = new List<object>();
			ZRpc.Deserialize(new ParameterInfo[2] { null, parameterInfo }, package, ref source);
			return source.FirstOrDefault();
		}

		public static ParsedEntries ReadEntries(this ZPackage package)
		{
			ParsedEntries parsedEntries = new ParsedEntries();
			int num = package.ReadInt();
			for (int i = 0; i < num; i++)
			{
				string key = package.ReadString();
				string text = package.ReadString();
				Type type = Type.GetType(text);
				if (text == "" || type != null)
				{
					object obj;
					try
					{
						obj = ((text == "") ? null : package.ReadValueWithType(type));
					}
					catch (InvalidDeserializationTypeException ex)
					{
						Get.Plugin.LogWarning("Got unexpected struct internal type " + ex.received + " for field " + ex.field + " struct " + text);
						continue;
					}
					if (obj != null)
					{
						parsedEntries[key] = new PackageEntry
						{
							key = key,
							type = type,
							value = obj
						};
					}
					continue;
				}
				Get.Plugin.LogWarning("Got invalid type " + text + ", abort reading of received configs");
				return new ParsedEntries();
			}
			return parsedEntries;
		}

		public static void Test()
		{
		}
	}
	internal interface IPlugin
	{
		ConfigFile Config { get; }

		bool Debug { get; }

		ManualLogSource Logger { get; }
	}
	internal static class LoggingExtensions
	{
		private static readonly Dictionary<string, ManualLogSource> logSources = new Dictionary<string, ManualLogSource>();

		internal static ManualLogSource GetLogger(this IPlugin mod)
		{
			if (mod.Debug)
			{
				Type declaringType = new StackFrame(2).GetMethod().DeclaringType;
				if (!logSources.TryGetValue(declaringType.FullName, out var value))
				{
					value = Logger.CreateLogSource(declaringType.FullName);
					logSources.Add(declaringType.FullName, value);
				}
				return value;
			}
			return mod.Logger;
		}

		public static void LogDebugOnly(this IPlugin mod, object data)
		{
			if (mod.Debug)
			{
				mod.GetLogger().LogDebug(data);
			}
		}

		public static void LogDebug(this IPlugin mod, object data)
		{
			if (mod.Debug)
			{
				mod.GetLogger().LogDebug(data);
			}
			else
			{
				mod.Logger.LogDebug(data);
			}
		}

		public static void LogInfo(this IPlugin mod, object data)
		{
			if (mod.Debug)
			{
				mod.GetLogger().LogInfo(data);
			}
			else
			{
				mod.Logger.LogInfo(data);
			}
		}

		public static void LogMessage(this IPlugin mod, object data)
		{
			if (mod.Debug)
			{
				mod.GetLogger().LogMessage(data);
			}
			else
			{
				mod.Logger.LogMessage(data);
			}
		}

		public static void LogWarning(this IPlugin mod, object data)
		{
			if (mod.Debug)
			{
				mod.GetLogger().LogWarning(data);
			}
			else
			{
				mod.Logger.LogWarning(data);
			}
		}

		public static void LogError(this IPlugin mod, object data)
		{
			if (mod.Debug)
			{
				mod.GetLogger().LogError(data);
			}
			else
			{
				mod.Logger.LogError(data);
			}
		}

		public static void LogFatal(this IPlugin mod, object data)
		{
			if (mod.Debug)
			{
				mod.GetLogger().LogFatal(data);
			}
			else
			{
				mod.Logger.LogFatal(data);
			}
		}
	}
	internal static class Get
	{
		private static IPlugin cachedModRef;

		public static IPlugin Plugin
		{
			get
			{
				if (cachedModRef == null)
				{
					cachedModRef = AccessTools.Field((from p in new StackFrame(0).GetMethod().DeclaringType.Assembly.GetTypes()
						where typeof(IPlugin).IsAssignableFrom(p)
						select p).FirstOrDefault(), "Instance").GetValue(null) as IPlugin;
					cachedModRef.LogDebugOnly("Caching static mod reference");
				}
				return cachedModRef;
			}
		}
	}
	internal class Watcher
	{
		private FileSystemWatcher fileSystemWatcher;

		public bool EnableRaisingEvents
		{
			get
			{
				if (fileSystemWatcher != null)
				{
					return fileSystemWatcher.EnableRaisingEvents;
				}
				return false;
			}
			set
			{
				if (fileSystemWatcher != null)
				{
					fileSystemWatcher.EnableRaisingEvents = value;
				}
			}
		}

		public event Action<object, FileSystemEventArgs>? FileChanged;

		public Watcher(string path, string filter)
		{
			if (path == null)
			{
				throw new ArgumentNullException("path");
			}
			if (filter == null)
			{
				throw new ArgumentNullException("filter");
			}
			Get.Plugin.LogDebugOnly("Watcher created for " + path + ", " + filter);
			fileSystemWatcher = new FileSystemWatcher(path, filter);
			fileSystemWatcher.Changed += OnCreatedChangedOrRenamed;
			fileSystemWatcher.Created += OnCreatedChangedOrRenamed;
			fileSystemWatcher.Renamed += OnCreatedChangedOrRenamed;
			fileSystemWatcher.IncludeSubdirectories = true;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.EnableRaisingEvents = true;
		}

		private void OnCreatedChangedOrRenamed(object sender, FileSystemEventArgs args)
		{
			Get.Plugin.LogDebugOnly($"OnCreatedChangedOrRenamed triggered {args.Name}, {args.ChangeType}");
			this.FileChanged?.Invoke(sender, args);
		}
	}
}