Decompiled source of MarsarahTweaks v1.8.3

MarsarahTweaks.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using JetBrains.Annotations;
using MarsarahTweaks.Managers;
using MarsarahTweaks.Patches.Balance;
using MarsarahTweaks.Patches.Features;
using MarsarahTweaks.Patches.Grind;
using MarsarahTweaks.Patches.QOL;
using Microsoft.CodeAnalysis;
using ServerSync;
using TMPro;
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("MarsarahTweaks")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MarsarahTweaks")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("831fc141-e3fa-4e67-9d2f-5e56cf6f3935")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace MarsarahTweaks
{
	[BepInPlugin("Marsarah.MarsarahTweaks", "MarsarahTweaks", "1.8.3")]
	public class MarsarahTweaks : BaseUnityPlugin
	{
		internal const string ModName = "MarsarahTweaks";

		internal const string ModVersion = "1.8.3";

		internal const string Author = "Marsarah";

		public const string ModGUID = "Marsarah.MarsarahTweaks";

		private readonly Harmony harmony = new Harmony("Marsarah.MarsarahTweaks");

		private void Awake()
		{
			LogManager.SetGlobalLogLevel(LogManager.LogLevel.Warning);
			ConfigManager.Init(((BaseUnityPlugin)this).Config);
			harmony.PatchAll();
		}

		private void Start()
		{
			CompatibilityManager.Initialize();
			CompatibilityManager.UpdateIncompatibilities();
		}

		private void OnDestroy()
		{
			((BaseUnityPlugin)this).Config.Save();
		}
	}
}
namespace MarsarahTweaks.Patches
{
	public static class GlobalKeyChecker
	{
		[HarmonyPatch(typeof(ZoneSystem), "Update")]
		private class BossStatusUpdate_Patch
		{
			private static void Postfix(ZoneSystem __instance)
			{
				UpdateDefeatedStates(__instance);
				EikthyrDefeated = CheckGlobalKey("defeated_eikthyr");
				ElderDefeated = CheckGlobalKey("defeated_gdking");
				BonemassDefeated = CheckGlobalKey("defeated_bonemass");
				ModerDefeated = CheckGlobalKey("defeated_dragon");
				YagluthDefeated = CheckGlobalKey("defeated_goblinking");
				QueenDefeated = CheckGlobalKey("defeated_queen");
				FaderDefeated = CheckGlobalKey("defeated_fader");
				BrennaDefeated = CheckGlobalKey("hildir1");
				GeirrhafaDefeated = CheckGlobalKey("hildir2");
				ThungrNZilDefeated = CheckGlobalKey("hildir3");
			}
		}

		private static readonly LogManager log = new LogManager("Global Key Checker", LogManager.LogLevel.Warning);

		public static bool EikthyrDefeated = false;

		public static bool ElderDefeated = false;

		public static bool BonemassDefeated = false;

		public static bool ModerDefeated = false;

		public static bool YagluthDefeated = false;

		public static bool QueenDefeated = false;

		public static bool FaderDefeated = false;

		public static bool BrennaDefeated = false;

		public static bool GeirrhafaDefeated = false;

		public static bool ThungrNZilDefeated = false;

		private static string lastGlobalKeysSnapshot = null;

		private static readonly Dictionary<string, bool> globalKeyStates = new Dictionary<string, bool>
		{
			{ "defeated_eikthyr", false },
			{ "defeated_gdking", false },
			{ "defeated_bonemass", false },
			{ "defeated_dragon", false },
			{ "defeated_goblinking", false },
			{ "defeated_queen", false },
			{ "defeated_fader", false },
			{ "hildir1", false },
			{ "hildir2", false },
			{ "hildir3", false }
		};

		private static readonly Dictionary<string, string> bossToGlobalKey = new Dictionary<string, string>
		{
			{ "Eikthyr", "defeated_eikthyr" },
			{ "The Elder", "defeated_gdking" },
			{ "Bonemass", "defeated_bonemass" },
			{ "Moder", "defeated_dragon" },
			{ "Yagluth", "defeated_goblinking" },
			{ "The Queen", "defeated_queen" },
			{ "Fader", "defeated_fader" },
			{ "Brenna", "hildir1" },
			{ "Geirrhafa", "hildir2" },
			{ "ThungrNZil", "hildir3" }
		};

		private static void UpdateDefeatedStates(ZoneSystem zoneSystem)
		{
			List<string> globalKeys = zoneSystem.GetGlobalKeys();
			string text = string.Join(", ", globalKeys.OrderBy((string key) => key));
			bool flag = text != lastGlobalKeysSnapshot;
			if (flag)
			{
				log.Info($"=== Global Keys ({globalKeys.Count}) ===");
				log.Info((globalKeys.Count > 0) ? text : "(none)");
			}
			foreach (string item in globalKeyStates.Keys.ToList())
			{
				bool flag2 = globalKeys.Contains(item);
				if (globalKeyStates[item] != flag2)
				{
					log.Info($"Key state changed: {item} | {globalKeyStates[item]} -> {flag2}");
					globalKeyStates[item] = flag2;
				}
			}
			if (!flag)
			{
				return;
			}
			log.Info("=== Expected Key States ===");
			foreach (KeyValuePair<string, bool> globalKeyState in globalKeyStates)
			{
				log.Info($"{globalKeyState.Key}: {globalKeyState.Value}");
			}
			log.Info("=== End Global Keys ===");
			lastGlobalKeysSnapshot = text;
		}

		private static bool CheckGlobalKey(string globalKey)
		{
			return globalKeyStates.ContainsKey(globalKey) && globalKeyStates[globalKey];
		}

		public static bool IsBossDefeated(string boss)
		{
			if (bossToGlobalKey.TryGetValue(boss, out var value))
			{
				return CheckGlobalKey(value);
			}
			log.Warn("IsBossDefeated called with unknown boss: " + boss);
			return false;
		}
	}
}
namespace MarsarahTweaks.Patches.QOL
{
	internal static class HoeRadiusChanges
	{
		[HarmonyPatch(typeof(Player), "UpdatePlacement")]
		private static class Player_UpdatePlacement_Patch
		{
			private static void Prefix(Player __instance, bool takeInput, PieceTable ___m_buildPieces, GameObject ___m_placementGhost)
			{
				interceptPlacementScroll = false;
				if (!ConfigManager.AdjustableHoeRadiusEnabled.Value || !TryGetSupportedOperation(__instance, ___m_buildPieces, out var operation))
				{
					RestoreOriginalSettings();
					return;
				}
				if ((Object)(object)activeOperation != (Object)(object)operation)
				{
					SelectOperation(operation);
				}
				if ((Object)(object)activeOperation == (Object)null)
				{
					return;
				}
				UpdatePreview(___m_placementGhost);
				if (!takeInput || Hud.IsPieceSelectionVisible())
				{
					return;
				}
				float mouseScrollWheel = ZInput.GetMouseScrollWheel();
				if (!(Mathf.Abs(mouseScrollWheel) < 0.001f))
				{
					interceptPlacementScroll = true;
					float num = Mathf.Clamp(currentRadius + Mathf.Sign(mouseScrollWheel) * 1f, GetMinimumRadius(activeOperation), 7f);
					if (!Mathf.Approximately(num, currentRadius))
					{
						currentRadius = num;
						savedRadii[((Object)((Component)activeOperation).gameObject).name] = currentRadius;
						ApplyRadius(activeOperation.m_settings, currentRadius / defaultRadius);
						UpdatePreview(___m_placementGhost);
						log.Info($"Adjusted '{((Object)activeOperation).name}' radius to {currentRadius:0.##}m.");
					}
				}
			}

			private static void Postfix()
			{
				interceptPlacementScroll = false;
			}

			private static Exception Finalizer(Exception __exception)
			{
				interceptPlacementScroll = false;
				return __exception;
			}
		}

		[HarmonyPatch(typeof(ZInput), "GetMouseScrollWheel")]
		private static class ZInput_GetMouseScrollWheel_Patch
		{
			private static void Postfix(ref float __result)
			{
				if (interceptPlacementScroll || suppressCameraZoom)
				{
					__result = 0f;
				}
			}
		}

		[HarmonyPatch(typeof(Player), "Update")]
		private static class Player_Update_Patch
		{
			private static void Postfix(Player __instance)
			{
				if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && (!ConfigManager.AdjustableHoeRadiusEnabled.Value || !((Character)__instance).InPlaceMode()))
				{
					RestoreOriginalSettings();
				}
			}
		}

		[HarmonyPatch(typeof(GameCamera), "UpdateCamera")]
		private static class GameCamera_UpdateCamera_Patch
		{
			private static void Prefix()
			{
				suppressCameraZoom = false;
				Player localPlayer = Player.m_localPlayer;
				if (!((Object)(object)localPlayer == (Object)null) && ConfigManager.AdjustableHoeRadiusEnabled.Value && ((Character)localPlayer).InPlaceMode() && !Hud.IsPieceSelectionVisible())
				{
					suppressCameraZoom = TryGetSupportedOperation(localPlayer, buildPiecesRef.Invoke(localPlayer), out var _);
				}
			}

			private static Exception Finalizer(Exception __exception)
			{
				suppressCameraZoom = false;
				return __exception;
			}
		}

		[HarmonyPatch(typeof(Settings), "Serialize")]
		private static class TerrainSettings_Serialize_Patch
		{
			private static void Postfix(ZPackage __0, GameObject __1)
			{
				if (!ConfigManager.AdjustableHoeRadiusEnabled.Value || (Object)(object)activeOperation == (Object)null || __0 == null || (Object)(object)__1 == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
				{
					return;
				}
				string text = ((Object)__1).name;
				if (text.EndsWith("(Clone)", StringComparison.Ordinal))
				{
					text = text.Substring(0, text.Length - "(Clone)".Length);
				}
				if (!(text != ((Object)activeOperation).name))
				{
					int stableHashCode = StringExtensionMethods.GetStableHashCode(text);
					if (SupportedTerrainHashes.Contains(stableHashCode))
					{
						__0.Write(1297371720);
						__0.Write(1);
						__0.Write(stableHashCode);
						__0.Write(currentRadius);
						log.Info($"Sent terrain radius: Piece={text}, Radius={currentRadius:0.##}m, Hash={stableHashCode}.");
					}
				}
			}
		}

		[HarmonyPatch(typeof(Settings), "Deserialize")]
		private static class TerrainSettings_Deserialize_Patch
		{
			private static void Postfix(ZPackage __0, ref Settings __result)
			{
				if (!ConfigManager.AdjustableHoeRadiusEnabled.Value || __0 == null || __result == null)
				{
					return;
				}
				int pos = __0.GetPos();
				if (pos < 4 || __0.Size() - pos < 4)
				{
					return;
				}
				if (__0.ReadInt() != 1297371720)
				{
					__0.SetPos(pos);
					return;
				}
				if (__0.Size() - __0.GetPos() < 12)
				{
					log.Warn("Received incomplete terrain radius data. Using vanilla settings.");
					__0.SetPos(pos);
					return;
				}
				int num = __0.ReadInt();
				int num2 = __0.ReadInt();
				float num3 = __0.ReadSingle();
				int pos2 = __0.GetPos();
				__0.SetPos(pos - 4);
				int num4 = __0.ReadInt();
				__0.SetPos(pos2);
				float num5 = ((num2 == StringExtensionMethods.GetStableHashCode("path_v2")) ? 2f : 1f);
				if (num != 1 || num4 != num2 || !SupportedTerrainHashes.Contains(num2) || float.IsNaN(num3) || float.IsInfinity(num3) || num3 < num5 || num3 > 7f)
				{
					log.Warn("Rejected invalid terrain radius data. Using vanilla settings.");
					__0.SetPos(pos);
					return;
				}
				if (__result.m_raise || (!__result.m_level && !__result.m_smooth && !__result.m_paintCleared))
				{
					log.Warn("Received radius data for an unexpected terrain operation. Using vanilla settings.");
					__0.SetPos(pos);
					return;
				}
				float effectiveRadius = GetEffectiveRadius(__result);
				if (effectiveRadius <= 0f)
				{
					log.Warn("Received terrain operation has no valid radius. Using vanilla settings.");
					__0.SetPos(pos);
					return;
				}
				Settings val = CloneSettings(__result);
				float num6 = num3 / effectiveRadius;
				if (val.m_level)
				{
					val.m_levelRadius *= num6;
				}
				if (val.m_raise)
				{
					val.m_raiseRadius *= num6;
				}
				if (val.m_smooth)
				{
					val.m_smoothRadius *= num6;
				}
				if (val.m_paintCleared)
				{
					val.m_paintRadius *= num6;
				}
				__result = val;
				log.Info($"Applied network terrain radius: Hash={num2}, Radius={num3:0.##}m, Level={val.m_levelRadius:0.##}, Smooth={val.m_smoothRadius:0.##}, Paint={val.m_paintRadius:0.##}.");
			}
		}

		private static readonly LogManager log = new LogManager("Hoe Radius", LogManager.LogLevel.Warning);

		private const float RadiusStep = 1f;

		private const float MinRadius = 1f;

		private const float PathenMinRadius = 2f;

		private const float MaxRadius = 7f;

		private const int RadiusWireMagic = 1297371720;

		private const int RadiusWireVersion = 1;

		private static readonly HashSet<int> SupportedTerrainHashes = new HashSet<int>
		{
			StringExtensionMethods.GetStableHashCode("mud_road_v2"),
			StringExtensionMethods.GetStableHashCode("path_v2"),
			StringExtensionMethods.GetStableHashCode("paved_road_v2"),
			StringExtensionMethods.GetStableHashCode("MarsarahTweaks_Paving"),
			StringExtensionMethods.GetStableHashCode("cultivate_v2"),
			StringExtensionMethods.GetStableHashCode("replant_v2")
		};

		private static TerrainOp activeOperation;

		private static float originalLevel;

		private static float originalRaise;

		private static float originalSmooth;

		private static float originalPaint;

		private static float defaultRadius;

		private static float currentRadius;

		private static Transform previewTransform;

		private static Vector3 originalPreviewScale;

		private static Transform pathenParticleTransform;

		private static Vector3 originalPathenParticleScale;

		private static bool interceptPlacementScroll;

		private static bool suppressCameraZoom;

		private static readonly FieldRef<Player, PieceTable> buildPiecesRef = AccessTools.FieldRefAccess<Player, PieceTable>("m_buildPieces");

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

		private static bool TryGetSupportedOperation(Player player, PieceTable pieceTable, out TerrainOp operation)
		{
			operation = null;
			if ((Object)(object)player != (Object)(object)Player.m_localPlayer || (Object)(object)pieceTable == (Object)null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return false;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Hoe");
			GameObject itemPrefab2 = ObjectDB.instance.GetItemPrefab("Cultivator");
			PieceTable val = ((itemPrefab == null) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_buildPieces);
			PieceTable val2 = ((itemPrefab2 == null) ? null : itemPrefab2.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_buildPieces);
			bool flag = (Object)(object)val != (Object)null && (Object)(object)pieceTable == (Object)(object)val;
			bool flag2 = (Object)(object)val2 != (Object)null && (Object)(object)pieceTable == (Object)(object)val2;
			if (!flag && !flag2)
			{
				return false;
			}
			GameObject selectedPrefab = pieceTable.GetSelectedPrefab();
			if ((Object)(object)selectedPrefab == (Object)null)
			{
				return false;
			}
			string name = ((Object)selectedPrefab).name;
			bool num;
			if (!flag)
			{
				if (name == "cultivate_v2")
				{
					goto IL_0191;
				}
				num = name == "replant_v2";
			}
			else
			{
				switch (name)
				{
				case "mud_road_v2":
				case "path_v2":
				case "paved_road_v2":
					goto IL_0191;
				}
				num = name == "MarsarahTweaks_Paving";
			}
			if (!num)
			{
				return false;
			}
			goto IL_0191;
			IL_0191:
			operation = selectedPrefab.GetComponent<TerrainOp>();
			return (Object)(object)operation != (Object)null && operation.m_settings != null;
		}

		private static void SelectOperation(TerrainOp operation)
		{
			RestoreOriginalSettings();
			activeOperation = operation;
			Settings settings = operation.m_settings;
			originalLevel = settings.m_levelRadius;
			originalRaise = settings.m_raiseRadius;
			originalSmooth = settings.m_smoothRadius;
			originalPaint = settings.m_paintRadius;
			defaultRadius = 0f;
			if (settings.m_level)
			{
				defaultRadius = Mathf.Max(defaultRadius, originalLevel);
			}
			if (settings.m_raise)
			{
				defaultRadius = Mathf.Max(defaultRadius, originalRaise);
			}
			if (settings.m_smooth)
			{
				defaultRadius = Mathf.Max(defaultRadius, originalSmooth);
			}
			if (settings.m_paintCleared)
			{
				defaultRadius = Mathf.Max(defaultRadius, originalPaint);
			}
			if (defaultRadius <= 0f)
			{
				log.Warn("No active terrain radius found for '" + ((Object)operation).name + "'.");
				activeOperation = null;
				return;
			}
			if (savedRadii.TryGetValue(((Object)((Component)operation).gameObject).name, out var value))
			{
				currentRadius = Mathf.Clamp(value, GetMinimumRadius(operation), 7f);
				ApplyRadius(settings, currentRadius / defaultRadius);
			}
			else
			{
				currentRadius = defaultRadius;
			}
			log.Info($"Selected '{((Object)operation).name}' with radius {currentRadius:0.##}m.");
		}

		private static void ApplyRadius(Settings settings, float scale)
		{
			if (settings != null)
			{
				settings.m_levelRadius = (settings.m_level ? (originalLevel * scale) : originalLevel);
				settings.m_raiseRadius = (settings.m_raise ? (originalRaise * scale) : originalRaise);
				settings.m_smoothRadius = (settings.m_smooth ? (originalSmooth * scale) : originalSmooth);
				settings.m_paintRadius = (settings.m_paintCleared ? (originalPaint * scale) : originalPaint);
			}
		}

		private static void UpdatePreview(GameObject ghost)
		{
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Invalid comparison between Unknown and I4
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ghost == (Object)null || (Object)(object)activeOperation == (Object)null || defaultRadius <= 0f)
			{
				return;
			}
			float num = currentRadius / defaultRadius;
			TerrainOp component = ghost.GetComponent<TerrainOp>();
			if ((Object)(object)component != (Object)null)
			{
				ApplyRadius(component.m_settings, num);
			}
			Transform val = ghost.transform.Find("_GhostOnly");
			if ((Object)(object)val == (Object)null)
			{
				val = ghost.transform.Find("GhostOnly");
			}
			if ((Object)(object)val != (Object)(object)previewTransform)
			{
				RestorePreviewScale();
				previewTransform = val;
				if ((Object)(object)previewTransform != (Object)null)
				{
					originalPreviewScale = previewTransform.localScale;
					if (((Object)activeOperation).name == "path_v2")
					{
						ParticleSystem componentInChildren = ((Component)previewTransform).GetComponentInChildren<ParticleSystem>(true);
						if ((Object)(object)componentInChildren != (Object)null && (Object)(object)((Component)componentInChildren).transform != (Object)(object)previewTransform)
						{
							MainModule main = componentInChildren.main;
							if ((int)((MainModule)(ref main)).scalingMode == 1)
							{
								pathenParticleTransform = ((Component)componentInChildren).transform;
								originalPathenParticleScale = pathenParticleTransform.localScale;
								log.Info("Detected Pathen's local-scaled ghost particle.");
								goto IL_017f;
							}
						}
						log.Warn("Could not find Pathen's expected local-scaled ghost particle.");
					}
				}
			}
			goto IL_017f;
			IL_017f:
			if ((Object)(object)previewTransform != (Object)null)
			{
				previewTransform.localScale = originalPreviewScale * num;
			}
			if ((Object)(object)pathenParticleTransform != (Object)null)
			{
				pathenParticleTransform.localScale = originalPathenParticleScale * num;
			}
		}

		private static void RestorePreviewScale()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)pathenParticleTransform != (Object)null)
			{
				pathenParticleTransform.localScale = originalPathenParticleScale;
			}
			pathenParticleTransform = null;
			if ((Object)(object)previewTransform != (Object)null)
			{
				previewTransform.localScale = originalPreviewScale;
			}
			previewTransform = null;
		}

		private static void RestoreOriginalSettings()
		{
			if ((Object)(object)activeOperation != (Object)null)
			{
				Settings settings = activeOperation.m_settings;
				settings.m_levelRadius = originalLevel;
				settings.m_raiseRadius = originalRaise;
				settings.m_smoothRadius = originalSmooth;
				settings.m_paintRadius = originalPaint;
			}
			RestorePreviewScale();
			activeOperation = null;
			defaultRadius = 0f;
			currentRadius = 0f;
		}

		private static float GetMinimumRadius(TerrainOp operation)
		{
			return ((Object)(object)operation != (Object)null && ((Object)operation).name == "path_v2") ? 2f : 1f;
		}

		private static float GetEffectiveRadius(Settings settings)
		{
			float num = 0f;
			if (settings.m_level)
			{
				num = Mathf.Max(num, settings.m_levelRadius);
			}
			if (settings.m_raise)
			{
				num = Mathf.Max(num, settings.m_raiseRadius);
			}
			if (settings.m_smooth)
			{
				num = Mathf.Max(num, settings.m_smoothRadius);
			}
			if (settings.m_paintCleared)
			{
				num = Mathf.Max(num, settings.m_paintRadius);
			}
			return num;
		}

		private static Settings CloneSettings(Settings source)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: 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_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Expected O, but got Unknown
			return new Settings
			{
				m_levelOffset = source.m_levelOffset,
				m_level = source.m_level,
				m_levelRadius = source.m_levelRadius,
				m_square = source.m_square,
				m_raise = source.m_raise,
				m_raiseRadius = source.m_raiseRadius,
				m_raisePower = source.m_raisePower,
				m_raiseDelta = source.m_raiseDelta,
				m_smooth = source.m_smooth,
				m_smoothRadius = source.m_smoothRadius,
				m_smoothPower = source.m_smoothPower,
				m_paintCleared = source.m_paintCleared,
				m_paintHeightCheck = source.m_paintHeightCheck,
				m_paintType = source.m_paintType,
				m_paintRadius = source.m_paintRadius,
				m_paintStrength = source.m_paintStrength,
				m_paintExp = source.m_paintExp,
				m_paintCurve = source.m_paintCurve,
				m_rotation = source.m_rotation,
				m_sides = source.m_sides,
				m_addMedianMax = source.m_addMedianMax,
				m_centerMultiplicationFactor = source.m_centerMultiplicationFactor,
				m_pointMultiplicationFactor = source.m_pointMultiplicationFactor,
				m_halfOffset = source.m_halfOffset
			};
		}
	}
	internal static class MoreUsableFuel
	{
		[HarmonyPatch(typeof(Smelter), "Awake")]
		public static class AddAncientBarkToKiln_Patch
		{
			private static void Postfix(Smelter __instance)
			{
				UpdateKiln(__instance);
			}
		}

		[HarmonyPatch(typeof(ShieldGenerator), "Start")]
		public static class AddWitheredBonesToShieldGenerator_Patch
		{
			private static void Postfix(ShieldGenerator __instance)
			{
				UpdateShieldGenerator(__instance);
			}
		}

		private static readonly LogManager log = new LogManager("More Usable Fuel", LogManager.LogLevel.Warning);

		public static void UpdateMoreUsableFuel()
		{
			UpdateAllKilns();
			UpdateAllShieldGenerators();
		}

		private static void UpdateAllKilns()
		{
			Smelter[] array = Object.FindObjectsByType<Smelter>((FindObjectsSortMode)0);
			foreach (Smelter kiln in array)
			{
				UpdateKiln(kiln);
			}
		}

		private static void UpdateKiln(Smelter kiln)
		{
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Expected O, but got Unknown
			if (!kiln.m_conversion.Exists((ItemConversion conv) => (Object)(object)conv.m_to != (Object)null && ((Object)conv.m_to).name == "Coal"))
			{
				return;
			}
			ObjectDB instance = ObjectDB.instance;
			GameObject val = ((instance != null) ? instance.GetItemPrefab("ElderBark") : null);
			ObjectDB instance2 = ObjectDB.instance;
			GameObject val2 = ((instance2 != null) ? instance2.GetItemPrefab("Coal") : null);
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2))
			{
				log.Warn("Missing prefab: AncientBark or Coal.");
				return;
			}
			ItemDrop barkDrop = val.GetComponent<ItemDrop>();
			ItemDrop coalDrop = val2.GetComponent<ItemDrop>();
			ItemConversion val3 = ((IEnumerable<ItemConversion>)kiln.m_conversion).FirstOrDefault((Func<ItemConversion, bool>)((ItemConversion conv) => (Object)(object)conv.m_from == (Object)(object)barkDrop && (Object)(object)conv.m_to == (Object)(object)coalDrop));
			if (ConfigManager.MoreUsableFuelEnabled.Value)
			{
				if (val3 == null)
				{
					ItemConversion item = new ItemConversion
					{
						m_from = barkDrop,
						m_to = coalDrop
					};
					kiln.m_conversion.Add(item);
					log.Info("Added Ancient Bark as fuel for Kiln.");
				}
			}
			else if (val3 != null)
			{
				kiln.m_conversion.Remove(val3);
				log.Info("Removed Ancient Bark as fuel from Kiln.");
			}
		}

		private static void UpdateAllShieldGenerators()
		{
			ShieldGenerator[] array = Object.FindObjectsByType<ShieldGenerator>((FindObjectsSortMode)0);
			foreach (ShieldGenerator sg in array)
			{
				UpdateShieldGenerator(sg);
			}
		}

		private static void UpdateShieldGenerator(ShieldGenerator sg)
		{
			ObjectDB instance = ObjectDB.instance;
			GameObject val = ((instance != null) ? instance.GetItemPrefab("WitheredBone") : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				log.Warn("WitheredBone prefab not found.");
				return;
			}
			ItemDrop component = val.GetComponent<ItemDrop>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				log.Warn("WitheredBone does not have ItemDrop component.");
			}
			else if (ConfigManager.MoreUsableFuelEnabled.Value)
			{
				if (!sg.m_fuelItems.Contains(component))
				{
					sg.m_fuelItems.Add(component);
					log.Info("Added WitheredBone as fuel for Shield Generator.");
				}
			}
			else if (sg.m_fuelItems.Contains(component))
			{
				sg.m_fuelItems.Remove(component);
				log.Info("Removed WitheredBone as fuel from Shield Generator.");
			}
		}
	}
	internal class BoatRadiusChanges
	{
		[HarmonyPatch(typeof(Minimap), "UpdateExplore")]
		private class LargerBoatExploreRadius_Patch
		{
			private static float originalExploreRadius = -1f;

			private static void Prefix(ref float ___m_exploreRadius)
			{
				if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsDedicated())
				{
					return;
				}
				if (ConfigManager.LargerBoatExploreRadiusEnabled.Value)
				{
					if (Object.op_Implicit((Object)(object)Ship.GetLocalShip()) && Ship.GetLocalShip().HasPlayerOnboard())
					{
						if (originalExploreRadius == -1f)
						{
							log.Info($"Backing up explore radius: {___m_exploreRadius}");
							originalExploreRadius = ___m_exploreRadius;
						}
						if (___m_exploreRadius != 100f)
						{
							log.Info("Applying new explore radius: 100");
							___m_exploreRadius = 100f;
						}
					}
					else if (originalExploreRadius != -1f && ___m_exploreRadius != originalExploreRadius)
					{
						log.Info($"Restoring original explore radius: {originalExploreRadius}");
						___m_exploreRadius = originalExploreRadius;
					}
				}
				else if (originalExploreRadius != -1f && ___m_exploreRadius != originalExploreRadius)
				{
					log.Info($"Restoring original explore radius: {originalExploreRadius} due to config OFF");
					___m_exploreRadius = originalExploreRadius;
				}
			}
		}

		private static readonly LogManager log = new LogManager("Boat Radius", LogManager.LogLevel.Warning);
	}
	internal class FasterEquipChanges
	{
		[HarmonyPatch(typeof(Player), "QueueEquipAction")]
		private static class EquipActionSpeed_Patch
		{
			private static void Prefix(ItemData item)
			{
				//IL_0084: Unknown result type (might be due to invalid IL or missing references)
				if (((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsDedicated()) || !ConfigManager.FasterEquipEnabled.Value)
				{
					return;
				}
				if (item.IsWeapon())
				{
					if (item.m_shared.m_equipDuration > 0f)
					{
						item.m_shared.m_equipDuration = 0f;
					}
					log.Info($"Weapon {item.m_shared.m_name} - anim state: {item.m_shared.m_animationState}");
				}
				if (item.IsEquipable() && !item.IsWeapon() && item.m_shared.m_equipDuration > 1f)
				{
					item.m_shared.m_equipDuration = 1f;
				}
			}
		}

		[HarmonyPatch(typeof(Player), "QueueUnequipAction")]
		private static class UnequipActionSpeed_Patch
		{
			private static void Prefix(ItemData item)
			{
				if ((!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsDedicated()) && ConfigManager.FasterEquipEnabled.Value)
				{
					if (item.IsWeapon() && item.m_shared.m_equipDuration > 0f)
					{
						item.m_shared.m_equipDuration = 0f;
					}
					if (item.IsEquipable() && !item.IsWeapon() && item.m_shared.m_equipDuration > 1f)
					{
						item.m_shared.m_equipDuration = 1f;
					}
				}
			}
		}

		[HarmonyPatch(typeof(ZSyncAnimation), "SetTrigger")]
		private class RemoveEquipAndEatAnimation
		{
			private static bool Prefix(ZSyncAnimation __instance, string name)
			{
				if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsDedicated())
				{
					return true;
				}
				if (ConfigManager.FasterEquipEnabled.Value && name == "equip_hip")
				{
					return false;
				}
				return true;
			}
		}

		private static readonly LogManager log = new LogManager("Faster Equip", LogManager.LogLevel.Warning);
	}
	internal class FasterResourceDrops
	{
		[HarmonyPatch(typeof(Ragdoll), "Awake")]
		private class FasterResourceDrops_Patch
		{
			public static void Prefix(Ragdoll __instance, ref float ___m_ttl)
			{
				if (!((Object)(object)__instance == (Object)null) && ConfigManager.FasterResourceDropsEnabled.Value)
				{
					if (___m_ttl > 5f)
					{
						___m_ttl = 5f;
						log.Info("Large monster ttl set to 5s");
					}
					else if (___m_ttl > 0.5f)
					{
						___m_ttl = 0.5f;
						log.Info("Small monster ttl set to 0.5s");
					}
				}
			}
		}

		private static readonly LogManager log = new LogManager("Faster Resource Drops", LogManager.LogLevel.Warning);
	}
	internal class FriendlyBallistas
	{
		[HarmonyPatch(typeof(Turret), "UpdateTarget")]
		private class FriendlyBallistas_Patch
		{
			private static bool originalTargetsFriendly = true;

			private static readonly bool newTargetsFriendly = false;

			private static void Postfix([NotNull] ref bool ___m_targetPlayers, [NotNull] ref bool ___m_targetTamed)
			{
				if (ConfigManager.FriendlyBallistasEnabled.Value)
				{
					if (___m_targetPlayers != newTargetsFriendly)
					{
						log.Info($"Applying new player targeting: {newTargetsFriendly}");
						___m_targetPlayers = newTargetsFriendly;
					}
					if (___m_targetTamed != newTargetsFriendly)
					{
						log.Info($"Applying new tamed targeting: {newTargetsFriendly}");
						___m_targetTamed = newTargetsFriendly;
					}
				}
				else
				{
					if (___m_targetPlayers != originalTargetsFriendly)
					{
						log.Info($"Restoring player targeting: {originalTargetsFriendly}");
						___m_targetPlayers = originalTargetsFriendly;
					}
					if (___m_targetTamed != originalTargetsFriendly)
					{
						log.Info($"Restoring tamed targeting: {originalTargetsFriendly}");
						___m_targetTamed = originalTargetsFriendly;
					}
				}
			}
		}

		private static readonly LogManager log = new LogManager("Friendly Ballistas", LogManager.LogLevel.Warning);
	}
	internal class LargerPickupAreaChanges
	{
		[HarmonyPatch(typeof(Player), "Awake")]
		private class LargerPickupArea_Patch
		{
			private static void Prefix(Player __instance)
			{
				if (!((Object)(object)__instance == (Object)null) && (!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsDedicated()))
				{
					UpdatePickupArea(__instance, wasChanged: false);
				}
			}
		}

		private static readonly LogManager log = new LogManager("Larger Pickup Area", LogManager.LogLevel.Warning);

		private static float originalPickupArea = -1f;

		public static void UpdatePickupArea(Player player, bool wasChanged)
		{
			if (ConfigManager.LargerPickupAreaEnabled.Value)
			{
				if (originalPickupArea == -1f)
				{
					log.Info($"Backing up pickup area ({player.m_autoPickupRange})");
					originalPickupArea = player.m_autoPickupRange;
				}
				log.Info($"Assigning new pickup area (3) - from {player.m_autoPickupRange}");
				player.m_autoPickupRange = 3f;
			}
			else if (wasChanged && originalPickupArea != -1f)
			{
				log.Info($"Restoring pickup area: {originalPickupArea} - from {player.m_autoPickupRange}");
				player.m_autoPickupRange = originalPickupArea;
			}
		}
	}
	internal class LessFallDamage
	{
		[HarmonyPatch(typeof(SEMan), "ModifyFallDamage")]
		private class FallDamage_Patch
		{
			private static void Prefix(ref float damage)
			{
				if ((!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsDedicated()) && ConfigManager.LessFallDamageEnabled.Value)
				{
					log.Info("Reducing fall damage by 40%");
					damage *= 0.6f;
				}
			}
		}

		private static readonly LogManager log = new LogManager("Less Fall Damage", LogManager.LogLevel.Warning);
	}
	internal class LighterMetalWeight
	{
		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		private class OthersSection_Patch
		{
			private static void Postfix(ref ObjectDB __instance)
			{
				if (!((Object)(object)__instance == (Object)null) && (!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsDedicated()))
				{
					UpdateLighterMetalWeight(__instance, wasChanged: false);
				}
			}
		}

		private static readonly LogManager log = new LogManager("Lighter Metal Weight", LogManager.LogLevel.Warning);

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

		private static readonly Dictionary<string, float> metalWeightChanges = new Dictionary<string, float>
		{
			{ "TinOre", 8f },
			{ "Tin", 8f },
			{ "CopperOre", 8f },
			{ "Copper", 8f },
			{ "Bronze", 8f },
			{ "IronOre", 8f },
			{ "IronScrap", 8f },
			{ "Iron", 8f },
			{ "SilverOre", 8f },
			{ "Silver", 8f },
			{ "BlackMetalScrap", 8f },
			{ "BlackMetal", 8f },
			{ "CopperScrap", 8f },
			{ "BronzeScrap", 8f },
			{ "Flametal", 8f },
			{ "FlametalNew", 8f },
			{ "FlametalOre", 8f },
			{ "FlametalOreNew", 8f }
		};

		public static void UpdateLighterMetalWeight(ObjectDB objDB, bool wasChanged)
		{
			if (ConfigManager.LighterMetalWeightEnabled.Value)
			{
				foreach (string itemName in metalWeightChanges.Keys)
				{
					GameObject val = objDB.m_items.Find((GameObject i) => ((Object)i).name == itemName);
					if (!((Object)(object)val == (Object)null))
					{
						ItemDrop component = val.GetComponent<ItemDrop>();
						if (!((Object)(object)component == (Object)null))
						{
							if (!metalWeightOriginals.ContainsKey(((Object)val).name))
							{
								metalWeightOriginals[((Object)val).name] = component.m_itemData.m_shared.m_weight;
							}
							if (metalWeightChanges.TryGetValue(((Object)val).name, out var value))
							{
								log.Info($"Applying new weight for {((Object)val).name} from {component.m_itemData.m_shared.m_weight} to {value}");
								component.m_itemData.m_shared.m_weight = value;
							}
						}
					}
				}
				return;
			}
			if (!wasChanged)
			{
				return;
			}
			foreach (string itemName2 in metalWeightOriginals.Keys)
			{
				GameObject val2 = objDB.m_items.Find((GameObject i) => ((Object)i).name == itemName2);
				if (!((Object)(object)val2 == (Object)null))
				{
					ItemDrop component2 = val2.GetComponent<ItemDrop>();
					if (!((Object)(object)component2 == (Object)null) && metalWeightOriginals.TryGetValue(((Object)val2).name, out var value2))
					{
						log.Info($"Restoring original value for {((Object)val2).name} from {component2.m_itemData.m_shared.m_weight} to {value2}");
						component2.m_itemData.m_shared.m_weight = value2;
					}
				}
			}
			metalWeightOriginals.Clear();
		}
	}
	internal class NoSkillLossChanges
	{
		[HarmonyPatch(typeof(Skills), "Awake")]
		private class NoSkillLowerOnDeath_Patch
		{
			private static void Prefix(ref float ___m_DeathLowerFactor)
			{
				if ((!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsDedicated()) && ConfigManager.NoSkillLowerOnDeathEnabled.Value)
				{
					log.Info("Updating death lower factor");
					___m_DeathLowerFactor = 0f;
				}
			}
		}

		private static readonly LogManager log = new LogManager("No Skill Loss", LogManager.LogLevel.Warning);
	}
	internal class PavingChanges
	{
		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		private static class PavingPrefab_Patch
		{
			private static void Postfix(ZNetScene __instance)
			{
				if (!((Object)(object)__instance == (Object)null))
				{
					RegisterPavingPrefab(__instance);
					UpdatePavingAvailability(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "UpdateRegisters")]
		private static class PavingTerrainOpRegistry_Patch
		{
			private static void Postfix(ObjectDB __instance)
			{
				RegisterPavingTerrainOp(__instance);
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "OnDestroy")]
		private static class PavingCleanup_Patch
		{
			private static void Prefix(ZNetScene __instance)
			{
				if (pavingPrefab == null)
				{
					return;
				}
				GameObject prefab = __instance.GetPrefab("Hoe");
				PieceTable val = ((prefab == null) ? null : prefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_buildPieces);
				if ((Object)(object)val != (Object)null)
				{
					int num = val.m_pieces.RemoveAll((GameObject val2) => val2 == pavingPrefab);
					if (num > 0)
					{
						log.Info($"Removed {num} Paving prefab reference(s) from the Hoe PieceTable during world shutdown.");
					}
				}
				else
				{
					log.Warn("Could not access the Hoe PieceTable during Paving cleanup.");
				}
				pavingPrefab = null;
			}
		}

		private static readonly LogManager log = new LogManager("Paving", LogManager.LogLevel.Warning);

		private const string SourcePrefabName = "paved_road_v2";

		private const string PavingPrefabName = "MarsarahTweaks_Paving";

		private const string HoePrefabName = "Hoe";

		private static readonly FieldRef<ZNetScene, Dictionary<int, GameObject>> namedPrefabsRef = AccessTools.FieldRefAccess<ZNetScene, Dictionary<int, GameObject>>("m_namedPrefabs");

		private static GameObject pavingPrefab;

		private static void RegisterPavingPrefab(ZNetScene znScene)
		{
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Expected O, but got Unknown
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<int, GameObject> dictionary = namedPrefabsRef.Invoke(znScene);
			int stableHashCode = StringExtensionMethods.GetStableHashCode("MarsarahTweaks_Paving");
			if (dictionary.TryGetValue(stableHashCode, out var value))
			{
				if (((Object)value).name == "MarsarahTweaks_Paving")
				{
					pavingPrefab = value;
					RegisterPavingTerrainOp(ObjectDB.instance);
				}
				else
				{
					log.Error("Prefab hash collision for 'MarsarahTweaks_Paving'.");
				}
				return;
			}
			GameObject prefab = znScene.GetPrefab("Hoe");
			PieceTable val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<ItemDrop>() : null)?.m_itemData?.m_shared?.m_buildPieces;
			if ((Object)(object)val == (Object)null)
			{
				log.Error("Could not find the Hoe PieceTable.");
				return;
			}
			GameObject val2 = val.m_pieces.Find((GameObject val5) => (Object)(object)val5 != (Object)null && ((Object)val5).name == "paved_road_v2");
			if ((Object)(object)val2 == (Object)null)
			{
				log.Error("Could not find 'paved_road_v2' in the Hoe PieceTable.");
				{
					foreach (GameObject piece in val.m_pieces)
					{
						if ((Object)(object)piece != (Object)null && ((Object)piece).name.Contains("paved"))
						{
							log.Info($"Available paved-road candidate: '{((Object)piece).name}', TerrainOp={(Object)(object)piece.GetComponent<TerrainOp>() != (Object)null}.");
						}
					}
					return;
				}
			}
			log.Info("Found active Hoe prefab '" + ((Object)val2).name + "'.");
			GameObject val3 = new GameObject("MarsarahTweaks_Paving_CloneContainer");
			val3.transform.SetParent(((Component)znScene).transform, false);
			val3.SetActive(false);
			GameObject val4 = Object.Instantiate<GameObject>(val2, val3.transform);
			((Object)val4).name = "MarsarahTweaks_Paving";
			val4.SetActive(true);
			log.Info(string.Format("Created Paving prefab from '{0}'. ActiveSelf={1}, ActiveInHierarchy={2}.", "paved_road_v2", val4.activeSelf, val4.activeInHierarchy));
			Piece component = val4.GetComponent<Piece>();
			TerrainOp component2 = val4.GetComponent<TerrainOp>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null)
			{
				log.Error("Could not create 'MarsarahTweaks_Paving': source prefab is missing Piece or TerrainOp.");
				Object.Destroy((Object)(object)val3);
				return;
			}
			if (component2.m_settings.m_paintRadius <= 0f)
			{
				log.Error("Could not create 'MarsarahTweaks_Paving': source prefab has no valid paint radius.");
				Object.Destroy((Object)(object)val3);
				return;
			}
			component.m_name = "Paving Without Leveling";
			component.m_description = "Pave the ground without leveling it.";
			component2.m_settings.m_level = false;
			component2.m_settings.m_raise = false;
			component2.m_settings.m_smooth = false;
			component2.m_settings.m_paintCleared = true;
			log.Info($"Paving terrain operation: Level={component2.m_settings.m_level}, Raise={component2.m_settings.m_raise}, Smooth={component2.m_settings.m_smooth}, Paint={component2.m_settings.m_paintCleared}, PaintType={component2.m_settings.m_paintType}, PaintRadius={component2.m_settings.m_paintRadius}.");
			if ((Object)(object)val4.GetComponent<ZNetView>() != (Object)null)
			{
				znScene.m_prefabs.Add(val4);
			}
			else
			{
				znScene.m_nonNetViewPrefabs.Add(val4);
			}
			dictionary.Add(stableHashCode, val4);
			pavingPrefab = val4;
			RegisterPavingTerrainOp(ObjectDB.instance);
			log.Info($"Paving registered successfully. ActiveSelf={val4.activeSelf}, ActiveInHierarchy={val4.activeInHierarchy}, TerrainOp={(Object)(object)component2 != (Object)null}.");
		}

		public static void UpdatePavingAvailability(ZNetScene znScene)
		{
			if ((Object)(object)znScene == (Object)null || (Object)(object)pavingPrefab == (Object)null)
			{
				return;
			}
			GameObject prefab = znScene.GetPrefab("Hoe");
			if ((Object)(object)prefab == (Object)null)
			{
				log.Error("Could not find Hoe prefab.");
				return;
			}
			PieceTable val = prefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_buildPieces;
			if ((Object)(object)val == (Object)null)
			{
				log.Error("Could not find Hoe PieceTable.");
				return;
			}
			bool flag = val.m_pieces.Contains(pavingPrefab);
			if (ConfigManager.PavingEnabled.Value && !flag)
			{
				int num = val.m_pieces.FindIndex((GameObject val2) => (Object)(object)val2 != (Object)null && ((Object)val2).name == "paved_road_v2");
				if (num >= 0)
				{
					val.m_pieces.Insert(num + 1, pavingPrefab);
				}
				else
				{
					val.m_pieces.Add(pavingPrefab);
				}
				log.Info("Added Paving to the Hoe build menu.");
			}
			else if (!ConfigManager.PavingEnabled.Value && flag)
			{
				val.m_pieces.Remove(pavingPrefab);
				log.Info("Removed Paving from the Hoe build menu.");
			}
		}

		private static void RegisterPavingTerrainOp(ObjectDB objectDB)
		{
			if ((Object)(object)objectDB == (Object)null || (Object)(object)pavingPrefab == (Object)null)
			{
				return;
			}
			TerrainOp component = pavingPrefab.GetComponent<TerrainOp>();
			if ((Object)(object)component == (Object)null)
			{
				log.Error("Cannot register Paving TerrainOp: component is missing.");
				return;
			}
			int prefabHash = objectDB.GetPrefabHash(pavingPrefab);
			if (objectDB.m_terrainOpsByHash.TryGetValue(prefabHash, out var value))
			{
				if ((Object)(object)value != (Object)(object)component)
				{
					log.Error(string.Format("TerrainOp hash collision for '{0}' ({1}).", "MarsarahTweaks_Paving", prefabHash));
					return;
				}
			}
			else
			{
				objectDB.m_terrainOpsByHash.Add(prefabHash, component);
				log.Info($"Registered Paving TerrainOp with hash {prefabHash}.");
			}
			if (!objectDB.m_terrainOps.Contains(component))
			{
				objectDB.m_terrainOps.Add(component);
			}
		}
	}
	internal class PermanentLightsChanges
	{
		[HarmonyPatch(typeof(Fireplace), "UpdateFireplace")]
		private static class Fireplace_UpdateFireplace_Patch
		{
			private static void Postfix(Fireplace __instance, ZNetView ___m_nview)
			{
				string prefabName = Utils.GetPrefabName(((Component)__instance).gameObject);
				bool flag = IsFire(__instance, prefabName);
				if (prefabName == "fire_pit")
				{
					__instance.m_maxFuel = (CoversFires ? 5f : 10f);
				}
				else if (prefabName == "hearth")
				{
					__instance.m_maxFuel = (CoversFires ? 10f : 20f);
				}
				if (CoversFireplaces && (!flag || CoversFires))
				{
					Refill(___m_nview, __instance.m_maxFuel);
				}
			}
		}

		[HarmonyPatch(typeof(CookingStation), "UpdateCooking")]
		private static class CookingStation_UpdateCooking_Patch
		{
			private static void Postfix(CookingStation __instance, ZNetView ___m_nview)
			{
				if (CoversUtilities && __instance.m_useFuel && !(Utils.GetPrefabName(((Component)__instance).gameObject) != "piece_oven"))
				{
					Refill(___m_nview, __instance.m_maxFuel);
				}
			}
		}

		[HarmonyPatch(typeof(Smelter), "UpdateSmelter")]
		private static class Smelter_UpdateSmelter_Patch
		{
			private static void Postfix(Smelter __instance, ZNetView ___m_nview)
			{
				if (CoversUtilities && !(Utils.GetPrefabName(((Component)__instance).gameObject) != "piece_bathtub"))
				{
					Refill(___m_nview, __instance.m_maxFuel);
				}
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		private static class PermanentLightsBuildPieces_Patch
		{
			private static void Postfix(ZNetScene __instance)
			{
				if (!((Object)(object)__instance == (Object)null) && (!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsDedicated()))
				{
					UpdateLightBuildPiecesAmounts(__instance, wasChanged: false);
				}
			}
		}

		private static readonly LogManager log = new LogManager("Permanent Lights", LogManager.LogLevel.Warning);

		private const int CampfirePermanentFuel = 5;

		private const int HearthPermanentFuel = 10;

		private static readonly Dictionary<string, Requirement[]> originalLightPieceCosts = new Dictionary<string, Requirement[]>();

		public static readonly Dictionary<string, Dictionary<string, int>> lightPieceCostChanges = new Dictionary<string, Dictionary<string, int>>
		{
			{
				"$piece_firepit",
				new Dictionary<string, int> { { "Wood", 5 } }
			},
			{
				"$piece_hearth",
				new Dictionary<string, int> { { "Wood", 10 } }
			},
			{
				"$piece_sconce",
				new Dictionary<string, int> { { "Resin", 6 } }
			},
			{
				"$piece_groundtorch",
				new Dictionary<string, int> { { "Resin", 6 } }
			},
			{
				"$piece_groundtorchwood",
				new Dictionary<string, int> { { "Resin", 4 } }
			},
			{
				"$piece_groundtorchgreen",
				new Dictionary<string, int> { { "Guck", 6 } }
			},
			{
				"$piece_groundtorchblue",
				new Dictionary<string, int> { { "GreydwarfEye", 6 } }
			},
			{
				"$piece_brazierfloor01",
				new Dictionary<string, int> { { "Coal", 5 } }
			},
			{
				"$piece_brazierfloor02",
				new Dictionary<string, int> { { "GreydwarfEye", 5 } }
			},
			{
				"$piece_brazierceiling01",
				new Dictionary<string, int> { { "Coal", 5 } }
			}
		};

		private static bool CoversFireplaces => ConfigManager.PermanentLightsMode.Value != "Off";

		private static bool CoversFires => ConfigManager.PermanentLightsMode.Value == "Lights & Fires" || ConfigManager.PermanentLightsMode.Value == "Lights, Fires, Stoves & Hot Tubs";

		private static bool CoversUtilities => ConfigManager.PermanentLightsMode.Value == "Lights, Fires, Stoves & Hot Tubs";

		private static bool IsFire(Fireplace fireplace, string prefabName)
		{
			string text = ((Component)fireplace).GetComponent<Piece>()?.m_name;
			switch (text)
			{
			default:
				if (!(text == "$piece_bonfire"))
				{
					return prefabName.IndexOf("fire_pit", StringComparison.OrdinalIgnoreCase) >= 0 || prefabName.IndexOf("firepit", StringComparison.OrdinalIgnoreCase) >= 0 || prefabName.IndexOf("hearth", StringComparison.OrdinalIgnoreCase) >= 0 || prefabName.IndexOf("bonfire", StringComparison.OrdinalIgnoreCase) >= 0;
				}
				goto case "$piece_firepit";
			case "$piece_firepit":
			case "$piece_firepit_iron":
			case "$piece_hearth":
				return true;
			}
		}

		private static void Refill(ZNetView nview, float maxFuel)
		{
			if (!((Object)(object)nview == (Object)null) && nview.IsOwner() && !(maxFuel <= 0f))
			{
				ZDO zDO = nview.GetZDO();
				if (zDO != null && !(zDO.GetFloat("fuel", 0f) >= maxFuel))
				{
					zDO.Set("fuel", maxFuel);
				}
			}
		}

		private static Requirement CopyRequirement(Requirement req)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			return new Requirement
			{
				m_resItem = req.m_resItem,
				m_amount = req.m_amount,
				m_amountPerLevel = req.m_amountPerLevel,
				m_recover = req.m_recover
			};
		}

		private static GameObject FindPiecePrefab(ZNetScene scene, string pieceName)
		{
			if (pieceName == "$piece_firepit")
			{
				return scene.m_prefabs.Find((GameObject p) => ((Object)p).name == "fire_pit" && p.GetComponent<Piece>()?.m_name == pieceName);
			}
			return scene.m_prefabs.Find((GameObject p) => p.GetComponent<Piece>()?.m_name == pieceName);
		}

		public static void UpdateLightBuildPiecesAmounts(ZNetScene znScene, bool wasChanged)
		{
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Expected O, but got Unknown
			if ((Object)(object)znScene == (Object)null)
			{
				return;
			}
			foreach (KeyValuePair<string, Dictionary<string, int>> lightPieceCostChange in lightPieceCostChanges)
			{
				string key = lightPieceCostChange.Key;
				bool flag = ((key == "$piece_firepit" || key == "$piece_hearth") ? CoversFires : CoversFireplaces);
				Requirement[] value;
				bool flag2 = originalLightPieceCosts.TryGetValue(key, out value);
				if (!flag && !flag2)
				{
					continue;
				}
				GameObject val = FindPiecePrefab(znScene, key);
				Piece val2 = ((val != null) ? val.GetComponent<Piece>() : null);
				if ((Object)(object)val2 == (Object)null)
				{
					if (flag)
					{
						log.Warn(key + " prefab not found in ZNetScene.");
					}
					continue;
				}
				if (!flag)
				{
					val2.m_resources = value.Select(CopyRequirement).ToArray();
					originalLightPieceCosts.Remove(key);
					log.Info("Restored build costs for " + key + ".");
					continue;
				}
				if (!flag2)
				{
					originalLightPieceCosts[key] = val2.m_resources.Select(CopyRequirement).ToArray();
				}
				Requirement[] resources = val2.m_resources;
				foreach (Requirement val3 in resources)
				{
					if ((Object)(object)val3.m_resItem != (Object)null && lightPieceCostChange.Value.TryGetValue(((Object)val3.m_resItem).name, out var value2))
					{
						val3.m_amount = value2;
						if (((Object)val3.m_resItem).name == "Wood")
						{
							val3.m_recover = true;
						}
					}
				}
				if (key == "$piece_hearth" && !val2.m_resources.Any((Requirement req) => (Object)(object)req.m_resItem != (Object)null && ((Object)req.m_resItem).name == "Wood"))
				{
					GameObject prefab = znScene.GetPrefab("Wood");
					ItemDrop val4 = ((prefab != null) ? prefab.GetComponent<ItemDrop>() : null);
					if ((Object)(object)val4 != (Object)null)
					{
						val2.m_resources = val2.m_resources.Append(new Requirement
						{
							m_amount = 10,
							m_amountPerLevel = 0,
							m_resItem = val4,
							m_recover = true
						}).ToArray();
						log.Info("Added the Hearth's wood build requirement.");
					}
					else
					{
						log.Warn("Could not find Wood prefab for the Hearth build requirement.");
					}
				}
			}
		}
	}
	internal static class PlayerLogoutAnnounce
	{
		[HarmonyPatch(typeof(ZNet), "Update")]
		private static class ZNetUpdatePatch
		{
			private static void Postfix()
			{
				if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
				{
					return;
				}
				List<ZNetPeer> connectedPeers = ZNet.instance.GetConnectedPeers();
				HashSet<string> hashSet = new HashSet<string>();
				foreach (ZNetPeer item in connectedPeers)
				{
					if (!string.IsNullOrEmpty(item.m_playerName))
					{
						hashSet.Add(item.m_playerName);
					}
				}
				if (ConfigManager.AnnouncePlayerLogout.Value)
				{
					foreach (string previousPeer in previousPeers)
					{
						if (!hashSet.Contains(previousPeer))
						{
							log.Info(previousPeer + " logged out.");
							ZRoutedRpc instance = ZRoutedRpc.instance;
							if (instance != null)
							{
								instance.InvokeRoutedRPC(0L, "MarsarahTweaks_LogoutAnnounce", new object[1] { previousPeer });
							}
						}
					}
				}
				previousPeers = hashSet;
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		private static class ZNetSceneAwakePatch
		{
			private static void Postfix()
			{
				TryRegisterRPC();
			}
		}

		private static readonly LogManager log = new LogManager("Player Logout Announce", LogManager.LogLevel.Warning);

		private const string LogoutRPC = "MarsarahTweaks_LogoutAnnounce";

		private static HashSet<string> previousPeers = new HashSet<string>();

		private static ZRoutedRpc registeredRpc;

		private static void TryRegisterRPC()
		{
			if (ZRoutedRpc.instance != null && registeredRpc != ZRoutedRpc.instance)
			{
				ZRoutedRpc.instance.Register<string>("MarsarahTweaks_LogoutAnnounce", (Action<long, string>)OnPlayerLogoutRPC);
				registeredRpc = ZRoutedRpc.instance;
				previousPeers.Clear();
				log.Info("Registered Player Logout Announce RPC.");
			}
		}

		private static void OnPlayerLogoutRPC(long sender, string playerName)
		{
			if (ConfigManager.AnnouncePlayerLogout.Value)
			{
				MessageHud instance = MessageHud.instance;
				if (instance != null)
				{
					instance.ShowMessage((MessageType)1, playerName + " logged out.", 0, (Sprite)null, false, true);
				}
				Chat instance2 = Chat.instance;
				if (instance2 != null)
				{
					((Terminal)instance2).AddString("[Server]", playerName + " logged out.", (Type)2, false);
				}
			}
		}
	}
	internal class RestedDelay
	{
		[HarmonyPatch(typeof(SE_Cozy), "Setup")]
		private class RestedDelay_Patch
		{
			private static float originalRestedDelay = -1f;

			private static readonly float newRestedDelay = 10f;

			private static void Postfix(SE_Cozy __instance)
			{
				if (originalRestedDelay == -1f)
				{
					originalRestedDelay = __instance.m_delay;
					log.Info($"Original rested delay saved: {originalRestedDelay}");
				}
				if (ConfigManager.ShorterRestedDelayEnabled.Value)
				{
					if (__instance.m_delay != newRestedDelay)
					{
						__instance.m_delay = 10f;
						log.Info($"Rested delay set to {__instance.m_delay}");
					}
				}
				else if (__instance.m_delay != originalRestedDelay)
				{
					__instance.m_delay = originalRestedDelay;
					log.Info($"Rested delay reverted to {__instance.m_delay}");
				}
				else
				{
					log.Info($"Rested delay is at {__instance.m_delay}");
				}
			}
		}

		private static readonly LogManager log = new LogManager("Rested Delay", LogManager.LogLevel.Warning);
	}
	internal class SailingCameraChanges
	{
		[HarmonyPatch(typeof(GameCamera), "GetCameraPosition")]
		private class GameCamera_Patch
		{
			private static void Postfix(GameCamera __instance, ref float dt, ref Vector3 pos, ref Quaternion rot)
			{
				//IL_0024: 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)
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					UpdateShipControlledState();
					float num = UpdateCameraOffset(dt);
					pos += Vector3.up * num;
				}
			}
		}

		private static readonly LogManager log = new LogManager("Sailing Camera", LogManager.LogLevel.Warning);

		private static readonly Dictionary<string, float> shipOffsets = new Dictionary<string, float>
		{
			{ "Raft", 2f },
			{ "Karve", 3f },
			{ "VikingShip", 4f },
			{ "VikingShip_Ashlands", 5f }
		};

		private static bool moveCameraUp = false;

		private static float currentOffset = 0f;

		private static float targetOffset = 0f;

		private const float smoothSpeed = 2f;

		private static void UpdateShipControlledState()
		{
			if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsDedicated())
			{
				return;
			}
			if (!ConfigManager.CameraUpWhenSailingEnabled.Value)
			{
				moveCameraUp = false;
				targetOffset = 0f;
				return;
			}
			Ship controlledShip = Player.m_localPlayer.GetControlledShip();
			if (!Object.op_Implicit((Object)(object)controlledShip))
			{
				moveCameraUp = false;
				targetOffset = 0f;
				return;
			}
			string text = ((Object)((Component)controlledShip).gameObject).name.Replace("(Clone)", "").Trim();
			if (!shipOffsets.TryGetValue(text, out var value))
			{
				value = 0f;
			}
			if (!moveCameraUp || !Mathf.Approximately(targetOffset, value))
			{
				log.Info($"Controlling {text}, offset set to {value:F1}");
			}
			moveCameraUp = true;
			targetOffset = value;
		}

		private static float UpdateCameraOffset(float dt)
		{
			if (ConfigManager.CameraUpWhenSailingEnabled.Value)
			{
				currentOffset = Mathf.Lerp(currentOffset, targetOffset, dt * 2f);
			}
			else
			{
				currentOffset = Mathf.Lerp(currentOffset, 0f, dt * 2f);
			}
			return currentOffset;
		}
	}
	internal class WispRadiusChanges
	{
		[HarmonyPatch(typeof(Demister), "OnEnable")]
		private class BiggerWispRadius_Patch
		{
			private static void Postfix([NotNull] ref Demister __instance)
			{
				if ((!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsDedicated()) && ConfigManager.BiggerWispRadiusEnabled.Value)
				{
					log.Info("Wisplight end range set to 30");
					__instance.m_forceField.endRange = 30f;
				}
			}
		}

		private static readonly LogManager log = new LogManager("Wisp Radius", LogManager.LogLevel.Warning);
	}
}
namespace MarsarahTweaks.Patches.Grind
{
	internal class FoodDurationChanges
	{
		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		private class FoodDurationChanges_Patch
		{
			private static void Postfix(ObjectDB __instance)
			{
				if (!((Object)(object)__instance == (Object)null) && !((Object)(object)ZNet.instance == (Object)null))
				{
					UpdateFoodDurations(__instance, wasModified: false);
				}
			}
		}

		private static readonly LogManager log = new LogManager("Food Durations", LogManager.LogLevel.Warning);

		private static readonly Dictionary<string, int> foodDurations = new Dictionary<string, int>
		{
			{ "Raspberry", 15 },
			{ "Blueberries", 15 },
			{ "MushroomYellow", 15 },
			{ "QueensJam", 30 },
			{ "DeerStew", 30 },
			{ "MinceMeatSauce", 30 },
			{ "CarrotSoup", 30 },
			{ "BlackSoup", 30 },
			{ "ShocklateSmoothie", 30 },
			{ "Sausages", 30 },
			{ "TurnipStew", 30 },
			{ "OnionSoup", 30 },
			{ "WolfMeatSkewer", 30 },
			{ "Eyescream", 30 },
			{ "FishWraps", 30 },
			{ "Bread", 30 },
			{ "MisthareSupreme", 30 },
			{ "MushroomOmelette", 30 },
			{ "Salad", 30 },
			{ "YggdrasilPorridge", 30 },
			{ "MagicallyStuffedShroom", 30 },
			{ "CookedAsksvinMeat", 25 },
			{ "CookedVoltureMeat", 25 },
			{ "FierySvinstew", 30 },
			{ "MashedMeat", 30 },
			{ "SpicyMarmalade", 30 },
			{ "ScorchingMedley", 30 },
			{ "SizzlingBerryBroth", 30 },
			{ "SparklingShroomshake", 30 }
		};

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

		public static void UpdateFoodDurations(ObjectDB objDB, bool wasModified)
		{
			if ((Object)(object)objDB == (Object)null || objDB.m_items == null)
			{
				return;
			}
			bool value = ConfigManager.StandardizedFoodDurationsEnabled.Value;
			if (!value && (!wasModified || originalFoodDurations.Count == 0))
			{
				return;
			}
			foreach (KeyValuePair<string, int> foodDuration in foodDurations)
			{
				string prefabName = foodDuration.Key;
				GameObject val = objDB.m_items.Find((GameObject item) => (Object)(object)item != (Object)null && ((Object)item).name == prefabName);
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				ItemDrop component = val.GetComponent<ItemDrop>();
				if ((Object)(object)component == (Object)null || component.m_itemData == null)
				{
					continue;
				}
				SharedData shared = component.m_itemData.m_shared;
				float value2;
				if (value)
				{
					if (!originalFoodDurations.ContainsKey(prefabName))
					{
						originalFoodDurations[prefabName] = shared.m_foodBurnTime;
					}
					float num = (float)foodDuration.Value * 60f;
					if (shared.m_foodBurnTime < num)
					{
						log.Info($"Setting {prefabName} duration from {shared.m_foodBurnTime}s to {num}s");
						shared.m_foodBurnTime = num;
					}
				}
				else if (originalFoodDurations.TryGetValue(prefabName, out value2) && shared.m_foodBurnTime != value2)
				{
					log.Info($"Restoring {prefabName} duration to {value2}s");
					shared.m_foodBurnTime = value2;
				}
			}
			if (!value)
			{
				originalFoodDurations.Clear();
			}
		}
	}
	internal class BuildPieceChanges
	{
		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		private class BuildPiecesModifications_Patch
		{
			private static void Postfix(ref ZNetScene __instance)
			{
				if (!((Object)(object)__instance == (Object)null) && (!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsDedicated()) && (ConfigManager.BuildPieceAmountsEnabled.Value || ConfigManager.BuildPieceMaterialsEnabled.Value))
				{
					UpdateBuildPieces(__instance, amountsWasChanged: false, materialsWasChanged: false);
				}
			}
		}

		private static readonly LogManager log = new LogManager("Build Piece Changes", LogManager.LogLevel.Warning);

		private static readonly Dictionary<string, Dictionary<string, (string originalResItem, string newResItem, int amount)>> defaultBuildPieceRequirements = new Dictionary<string, Dictionary<string, (string, string, int)>>();

		private static Dictionary<string, Dictionary<string, int>> newPieceAmounts = new Dictionary<string, Dictionary<string, int>>
		{
			{
				"$piece_rock_01",
				new Dictionary<string, int> { { "Stone", 8 } }
			},
			{
				"$piece_rock_02",
				new Dictionary<string, int> { { "Stone", 5 } }
			},
			{
				"$piece_woodfencegate",
				new Dictionary<string, int> { { "Wood", 2 } }
			},
			{
				"$piece_stonefence",
				new Dictionary<string, int> { { "Stone", 3 } }
			},
			{
				"$piece_birdnest",
				new Dictionary<string, int> { { "Acorn", 1 } }
			},
			{
				"$piece_preptable",
				new Dictionary<string, int>
				{
					{ "FineWood", 10 },
					{ "LeatherScraps", 10 }
				}
			},
			{
				"$piece_cookingstation_iron",
				new Dictionary<string, int>
				{
					{ "Iron", 2 },
					{ "Chain", 2 }
				}
			},
			{
				"$piece_itemstand",
				new Dictionary<string, int> { { "FineWood", 2 } }
			},
			{
				"$piece_blastfurnace",
				new Dictionary<string, int> { { "Iron", 5 } }
			},
			{
				"$piece_oven",
				new Dictionary<string, int> { { "Iron", 5 } }
			},
			{
				"$piece_forge_ext3",
				new Dictionary<string, int> { { "Wood", 15 } }
			},
			{
				"$piece_forge_ext4",
				new Dictionary<string, int> { { "Iron", 7 } }
			},
			{
				"$piece_forge_ext5",
				new Dictionary<string, int> { { "FineWood", 10 } }
			},
			{
				"$piece_forge_ext6",
				new Dictionary<string, int> { { "Iron", 5 } }
			},
			{
				"$piece_woodwindowshutter",
				new Dictionary<string, int> { { "Wood", 2 } }
			},
			{
				"$piece_darkwoodgate",
				new Dictionary<string, int> { { "Iron", 3 } }
			},
			{
				"$piece_irongate",
				new Dictionary<string, int> { { "Iron", 3 } }
			},
			{
				"$piece_chest",
				new Dictionary<string, int> { { "Iron", 1 } }
			},
			{
				"$piece_chestprivate",
				new Dictionary<string, int> { { "Iron", 4 } }
			},
			{
				"$piece_chestblackmetal",
				new Dictionary<string, int> { { "BlackMetal", 4 } }
			},
			{
				"$piece_brazierceiling01",
				new Dictionary<string, int> { { "Bronze", 3 } }
			},
			{
				"$piece_sconce",
				new Dictionary<string, int> { { "Copper", 1 } }
			},
			{
				"$piece_groundtorchwood",
				new Dictionary<string, int> { { "Wood", 1 } }
			},
			{
				"$piece_groundtorch",
				new Dictionary<string, int> { { "Iron", 1 } }
			},
			{
				"$piece_groundtorchgreen",
				new Dictionary<string, int> { { "Iron", 1 } }
			},
			{
				"$piece_groundtorchblue",
				new Dictionary<string, int> { { "Iron", 1 } }
			},
			{
				"$piece_portal",
				new Dictionary<string, int> { { "FineWood", 10 } }
			},
			{
				"$piece_portal_stone",
				new Dictionary<string, int> { { "Grausten", 10 } }
			},
			{
				"$piece_rug_lox",
				new Dictionary<string, int> { { "LoxPelt", 3 } }
			},
			{
				"$piece_rug_wolf",
				new Dictionary<string, int> { { "WolfPelt", 3 } }
			},
			{
				"$piece_rug_deer",
				new Dictionary<string, int> { { "DeerHide", 3 } }
			},
			{
				"$piece_banner01",
				new Dictionary<string, int> { { "LeatherScraps", 5 } }
			},
			{
				"$piece_banner02",
				new Dictionary<string, int> { { "LeatherScraps", 5 } }
			},
			{
				"$piece_banner03",
				new Dictionary<string, int> { { "LeatherScraps", 5 } }
			},
			{
				"$piece_banner04",
				new Dictionary<string, int> { { "LeatherScraps", 5 } }
			},
			{
				"$piece_banner05",
				new Dictionary<string, int> { { "LeatherScraps", 5 } }
			},
			{
				"$piece_banner06",
				new Dictionary<string, int> { { "LeatherScraps", 5 } }
			},
			{
				"$piece_banner07",
				new Dictionary<string, int> { { "LeatherScraps", 5 } }
			},
			{
				"$piece_banner08",
				new Dictionary<string, int> { { "LeatherScraps", 5 } }
			},
			{
				"$piece_banner09",
				new Dictionary<string, int> { { "LeatherScraps", 5 } }
			},
			{
				"$piece_banner10",
				new Dictionary<string, int> { { "LeatherScraps", 5 } }
			},
			{
				"$piece_banner11",
				new Dictionary<string, int> { { "LeatherScraps", 5 } }
			},
			{
				"$piece_banner12",
				new Dictionary<string, int> { { "LeatherScraps", 5 } }
			},
			{
				"$piece_banner13",
				new Dictionary<string, int> { { "LeatherScraps", 5 } }
			},
			{
				"$piece_banner14",
				new Dictionary<string, int> { { "LeatherScraps", 5 } }
			},
			{
				"$piece_fermenter",
				new Dictionary<string, int> { { "FineWood", 15 } }
			},
			{
				"$piece_bathtub",
				new Dictionary<string, int> { { "Iron", 5 } }
			},
			{
				"$piece_crystalwall1x1",
				new Dictionary<string, int> { { "Crystal", 1 } }
			},
			{
				"$piece_incinerator",
				new Dictionary<string, int> { { "Iron", 5 } }
			},
			{
				"$piece_stonewall1x1",
				new Dictionary<string, int> { { "Stone", 2 } }
			},
			{
				"$piece_stonewall2x1",
				new Dictionary<string, int> { { "Stone", 3 } }
			},
			{
				"$piece_stonepillar",
				new Dictionary<string, int> { { "Stone", 3 } }
			},
			{
				"$piece_stonearch",
				new Dictionary<string, int> { { "Stone", 3 } }
			},
			{
				"$piece_stonefloor2x2",
				new Dictionary<string, int> { { "Stone", 4 } }
			},
			{
				"$piece_stonestair",
				new Dictionary<string, int> { { "Stone", 3 } }
			},
			{
				"$piece_darkwoodraven",
				new Dictionary<string, int> { { "FineWood", 6 } }
			},
			{
				"$piece_darkwoodwolf",
				new Dictionary<string, int> { { "FineWood", 6 } }
			},
			{
				"$piece_blackmarble_throne",
				new Dictionary<string, int> { { "Copper", 4 } }
			},
			{
				"$piece_blackmarble2x1x1",
				new Dictionary<string, int> { { "BlackMarble", 3 } }
			},
			{
				"$piece_blackmarble_stair",
				new Dictionary<string, int> { { "BlackMarble", 3 } }
			},
			{
				"$piece_blackmarble_base1",
				new Dictionary<string, int> { { "BlackMarble", 4 } }
			},
			{
				"$piece_blackmarble_basecorner",
				new Dictionary<string, int> { { "BlackMarble", 5 } }
			},
			{
				"$piece_blackmarble_out1",
				new Dictionary<string, int> { { "BlackMarble", 4 } }
			},
			{
				"$piece_blackmarble_outcorner",
				new Dictionary<string, int> { { "BlackMarble", 5 } }
			},
			{
				"$piece_blackmarble_arch",
				new Dictionary<string, int> { { "BlackMarble", 4 } }
			},
			{
				"$piece_dvergr_stake_wall",
				new Dictionary<string, int>
				{
					{ "YggdrasilWood", 4 },
					{ "Iron", 2 }
				}
			},
			{
				"$piece_sharpstakes",
				new Dictionary<string, int>
				{
					{ "Wood", 4 },
					{ "RoundLog", 2 }
				}
			},
			{
				"$piece_dvergr_sharpstakes",
				new Dictionary<string, int>
				{
					{ "YggdrasilWood", 4 },
					{ "Iron", 1 }
				}
			},
			{
				"$piece_trap",
				new Dictionary<string, int>
				{
					{ "BlackMetal", 3 },
					{ "BronzeNails", 5 }
				}
			},
			{
				"$piece_turret",
				new Dictionary<string, int>
				{
					{ "BlackMetal", 7 },
					{ "YggdrasilWood", 7 },
					{ "MechanicalSpring", 2 }
				}
			},
			{
				"$piece_eitrrefinery",
				new Dictionary<string, int> { { "BlackMarble", 10 } }
			},
			{
				"$piece_blackforge_ext2",
				new Dictionary<string, int> { { "Copper", 5 } }
			},
			{
				"$piece_sapcollector",
				new Dictionary<string, int>
				{
					{ "YggdrasilWood", 5 },
					{ "BlackMetal", 3 }
				}
			},
			{
				"$piece_magetable",
				new Dictionary<string, int>
				{
					{ "YggdrasilWood", 10 },
					{ "BlackMetal", 5 }
				}
			},
			{
				"$piece_magetable_ext",
				new Dictionary<string, int>
				{
					{ "BlackMarble", 5 },
					{ "Eitr", 5 }
				}
			},
			{
				"$piece_magetable_ext2",
				new Dictionary<string, int>
				{
					{ "BlackMarble", 5 },
					{ "Eitr", 5 }
				}
			},
			{
				"$piece_magetable_ext3",
				new Dictionary<string, int> { { "Eitr", 5 } }
			},
			{
				"$piece_hexagonalgate",
				new Dictionary<string, int> { { "Copper", 4 } }
			},
			{
				"$piece_dvergr_spiralstair",
				new Dictionary<string, int>
				{
					{ "YggdrasilWood", 3 },
					{ "Copper", 1 }
				}
			},
			{
				"$piece_dvergr_spiralstair_right",
				new Dictionary<string, int>
				{
					{ "YggdrasilWood", 3 },
					{ "Copper", 1 }
				}
			},
			{
				"$piece_blackmarble_bench",
				new Dictionary<string, int>
				{
					{ "BlackMarble", 5 },
					{ "Copper", 2 }
				}
			},
			{
				"$piece_table_round",
				new Dictionary<string, int> { { "IronNails", 10 } }
			},
			{
				"$piece_blackmarble_table",
				new Dictionary<string, int>
				{
					{ "BlackMarble", 5 },
					{ "Copper", 2 }
				}
			},
			{
				"$piece_brazierfloor01",
				new Dictionary<string, int> { { "Bronze", 3 } }
			},
			{
				"$piece_brazierfloor02",
				new Dictionary<string, int>
				{
					{ "Bronze", 3 },
					{ "GreydwarfEye", 2 }
				}
			},
			{
				"$piece_jute_carpet",
				new Dictionary<string, int> { { "JuteRed", 3 } }
			},
			{
				"$piece_juteblue_carpet",
				new Dictionary<string, int> { { "JuteBlue", 3 } }
			},
			{
				"$piece_rug_hare",
				new Dictionary<string, int> { { "ScaleHide", 2 } }
			},
			{
				"$piece_dvergr_lantern",
				new Dictionary<string, int> { { "Copper", 1 } }
			},
			{
				"$piece_dvergr_lantern_pole",
				new Dictionary<string, int> { { "Copper", 2 } }
			},
			{
				"$piece_clothdoor",
				new Dictionary<string, int> { { "JuteRed", 3 } }
			},
			{
				"$piece_hanging_cloth_blue1",
				new Dictionary<string, int> { { "JuteBlue", 3 } }
			},
			{
				"$piece_hanging_cloth_blue2",
				new Dictionary<string, int> { { "JuteBlue", 3 } }
			},
			{
				"$piece_ashwood_archedwall",
				new Dictionary<string, int> { { "Blackwood", 1 } }
			},
			{
				"$piece_ashwood_floor_deco",
				new Dictionary<string, int> { { "Blackwood", 2 } }
			},
			{
				"$piece_ashwoodstair",
				new Dictionary<string, int> { { "Blackwood", 1 } }
			},
			{
				"$piece_ashwood_decowall",
				new Dictionary<string, int> { { "Blackwood", 2 } }
			},
			{
				"$piece_ashwood_decowall_divider",
				new Dictionary<string, int> { { "Blackwood", 1 } }
			},
			{
				"$piece_ashwood_decowall_tree",
				new Dictionary<string, int> { { "Blackwood", 1 } }
			},
			{
				"$piece_grausten_stoneladder",
				new Dictionary<string, int> { { "Grausten", 3 } }
			},
			{
				"$piece_grausten_stair",
				new Dictionary<string, int> { { "Grausten", 3 } }
			},
			{
				"$piece_grausten_floor1x1",
				new Dictionary<string, int> { { "Grausten", 1 } }
			},
			{
				"$piece_grausten_pillarmedium",
				new Dictionary<string, int> { { "Grausten", 2 } }
			},
			{
				"$piece_grausten_pillartapered",
				new Dictionary<string, int> { { "Grausten", 4 } }
			},
			{
				"$piece_grausten_pillartaperedinverted",
				new Dictionary<string, int> { { "Grausten", 4 } }
			},
			{
				"$piece_grausten_beammedium",
				new Dictionary<string, int> { { "Grausten", 2 } }
			},
			{
				"$piece_grausten_wall1x2",
				new Dictionary<string, int> { { "Grausten", 2 } }
			},
			{
				"$piece_grausten_wall2x2",
				new Dictionary<string, int> { { "Grausten", 4 } }
			},
			{
				"$piece_grausten_wall4x2",
				new Dictionary<string, int> { { "Grausten", 8 } }
			},
			{
				"$piece_grausten_window4x2",
				new Dictionary<string, int> { { "Grausten", 8 } }
			},
			{
				"$piece_grausten_roof45_corner",
				new Dictionary<string, int> { { "Grausten", 4 } }
			},
			{
				"$piece_grausten_roof45_corner2",
				new Dictionary<string, int> { { "Grausten", 4 } }
			},
			{
				"$piece_grausten_roof45_archcorner",
				new Dictionary<string, int> { { "Grausten", 4 } }
			},
			{
				"$piece_grausten_roof45_archcorner2",
				new Dictionary<string, int> { { "Grausten", 4 } }
			},
			{
				"$piece_flametalgate",
				new Dictionary<string, int> { { "FlametalNew", 8 } }
			},
			{
				"$piece_rug_asksvin",
				new Dictionary<string, int> { { "AskHide", 3 } }
			}
		};

		private static Dictionary<string, Dictionary<string, string>> newPieceMaterials = new Dictionary<string, Dictionary<string, string>>
		{
			{
				"$piece_workbench_ext4",
				new Dictionary<string, string> { { "Obsidian", "Coal" } }
			},
			{
				"$piece_darkwoodgate",
				new Dictionary<string, string> { { "Iron", "BlackMetal" } }
			},
			{
				"$piece_bathtub",
				new Dictionary<string, string> { { "Iron", "BlackMetal" } }
			}
		};

		public static void UpdateBuildPieces(ZNetScene znScene, bool amountsWasChanged, bool materialsWasChanged)
		{
			foreach (GameObject prefab in znScene.m_prefabs)
			{
				Piece component = prefab.GetComponent<Piece>();
				if ((Object)(object)component == (Object)null)
				{
					continue;
				}
				Requirement[] resources = component.m_resources;
				string name = component.m_name;
				bool flag = ConfigManager.BuildPieceAmountsEnabled.Value && newPieceAmounts.ContainsKey(name);
				bool flag2 = ConfigManager.BuildPieceMaterialsEnabled.Value && newPieceMaterials.ContainsKey(name);
				Requirement[] array = resources;
				foreach (Requirement val in array)
				{
					if (flag && newPieceAmounts[name].TryGetValue(((Object)val.m_resItem).name, out var value))
					{
						CreateBackup(name, val, null);
						log.Info($"(Piece Amounts) Applying amounts for Piece {name} - Resource {((Object)val.m_resItem).name}: {val.m_amount} -> {value}");
						ApplyChanges(val, (newResItem: null, amount: value));
					}
					if (flag2 && newPieceMaterials[name].TryGetValue(((Object)val.m_resItem).name, out var value2))
					{
						CreateBackup(name, val, value2);
						log.Info("(Piece Materials) Applying material for Piece " + name + " - Resource " + ((Object)val.m_resItem).name + " -> " + value2);
						ApplyChanges(val, (newResItem: value2, amount: null), modifyResItem: true);
					}
					if (!ConfigManager.BuildPieceAmountsEnabled.Value && newPieceAmounts.ContainsKey(name) && amountsWasChanged)
					{
						log.Info($"(Gear Amounts) Was changed: {amountsWasChanged}");
						if (RestoreBackup(name, val, restoreMaterials: false) && (!flag2 || !newPieceMaterials[name].ContainsKey(((Object)val.m_resItem).name)))
						{
							log.Info("(Piece Amounts) Removing backup for: " + name + " - " + ((Object)val.m_resItem).name);
							defaultBuildPieceRequirements[name].Remove(((Object)val.m_resItem).name);
						}
					}
					if (!(!ConfigManager.BuildPieceMaterialsEnabled.Value && newPieceMaterials.ContainsKey(name) && materialsWasChanged))
					{
						continue;
					}
					log.Info($"(Gear Materials) Was changed: {materialsWasChanged}");
					if (!RestoreBackup(name, val, restoreMaterials: true))
					{
						continue;
					}
					if (flag && newPieceAmounts[name].ContainsKey(((Object)val.m_resItem).name))
					{
						if (newPieceAmounts[name].TryGetValue(((Object)val.m_resItem).name, out var value3))
						{
							log.Info("(Piece Materials - Amounts) Re-applying changes for: " + name + " - " + ((Object)val.m_resItem).name);
							ApplyChanges(val, (newResItem: null, amount: value3));
						}
					}
					else if (!flag || !newPieceAmounts[name].ContainsKey(((Object)val.m_resItem).name))
					{
						log.Info("(Piece Materials) Removing backup for: " + name + " - " + ((Object)val.m_resItem).name);
						defaultBuildPieceRequirements[name].Remove(((Object)val.m_resItem).name);
					}
				}
				if (defaultBuildPieceRequirements.ContainsKey(name) && defaultBuildPieceRequirements[name].Count == 0)
				{
					log.Info("(Cleanup) Removing backup for: " + name);
					defaultBuildPieceRequirements.Remove(name);
				}
			}
		}

		private static void ApplyChanges(Requirement req, (string newResItem, int? amount) values, bool modifyResItem = false)
		{
			if (values.amount.HasValue && req.m_amount != values.amount.Value)
			{
				log.Info($"Applying amounts for Resource {((Object)req.m_resItem).name}: {req.m_amount} -> {values.amount.Value}");
				req.m_amount = values.amount.Value;
			}
			if (modifyResItem && !string.IsNullOrEmpty(values.newResItem) && ((Object)req.m_resItem).name != values.newResItem)
			{
				log.Info("Applying material for Resource " + ((Object)req.m_resItem).name + " -> " + values.newResItem);
				req.m_resItem = ZNetScene.instance.GetPrefab(values.newResItem).GetComponent<ItemDrop>();
			}
		}

		private static void CreateBackup(string pieceName, Requirement req, string newResItem)
		{
			if (!defaultBuildPieceRequirements.TryGetValue(pieceName, out Dictionary<string, (string, string, int)> value))
			{
				value = new Dictionary<string, (string, string, int)>();
				defaultBuildPieceRequirements[pieceName] = value;
			}
			string name = ((Object)req.m_resItem).name;
			if (value.TryGetValue(name, out var value2))
			{
				if (newResItem != null && value2.Item2 == null)
				{
					log.Info("Updating backup for " + pieceName + " - oldResItem: " + name + " with newResItem: " + newResItem);
					value[name] = (value2.Item1, newResItem, value2.Item3);
				}
			}
			else
			{
				log.Info("Creating new backup for " + pieceName + " - " + name);
				value[name] = (name, newResItem, req.m_amount);
			}
		}

		private static bool RestoreBackup(string pieceName, Requirement req, bool restoreMaterials)
		{
			if (!defaultBuildPieceRequirements.TryGetValue(pieceName, out Dictionary<string, (string, string, int)> value))
			{
				log.Info("Restore backup first check.");
				return false;
			}
			log.Info("Restore backup - Recipe name: " + pieceName + ", Given requirement: " + ((Object)req.m_resItem).name);
			foreach (KeyValuePair<string, (string, string, int)> item in value)
			{
				var (text, text2, num) = item.Value;
				log.Info($"Restore backup - values: {text}, {text2}, {restoreMaterials}");
				if (((Object)req.m_resItem).name == text2 && restoreMaterials)
				{
					log.Info("Restoring original material for " + pieceName + " from " + ((Object)req.m_resItem).name + " to " + text);
					req.m_resItem = ZNetScene.instance.GetPrefab(text).GetComponent<ItemDrop>();
					break;
				}
			}
			if (value.TryGetValue(((Object)req.m_resItem).name, out var value2))
			{
				log.Info("Restoring backup for: " + pieceName + " - " + ((Object)req.m_resItem).name);
				req.m_amount = value2.Item3;
				return true;
			}
			log.Info("Restore backup - we got to the end.");
			return false;
		}

		public static void LogBuildPieces(ZNetScene znScene)
		{
			if ((Object)(object)znScene == (Object)null)
			{
				log.Warn("ZNetScene is null. Cannot log build pieces.");
				return;
			}
			log.Info("=== Logging All Build Pieces ===");
			foreach (GameObject prefab in znScene.m_prefabs)
			{
				Piece component = prefab.GetComponent<Piece>();
				if ((Object)(object)component == (Object)null)
				{
					continue;
				}
				log.Info("[Piece] Name: " + component.m_name + ", Prefab: " + ((Object)prefab).name);
				if (component.m_resources != null && component.m_resources.Length != 0)
				{
					Requirement[] resources = component.m_resources;
					foreach (Requirement val in resources)
					{
						if (!((Object)(object)val?.m_resItem == (Object)null))
						{
							log.Info($"   - Resource: {((Object)val.m_resItem).name}, Amount: {val.m_amount}");
						}
					}
				}
				else
				{
					log.Info("   (No build requirements)");
				}
			}
			log.Info("=== Finished Logging Build Pieces ===");
		}

		public static void LogBuildPiecesExtra(ZNetScene znScene)
		{
			if ((Object)(object)znScene == (Object)null)
			{
				log.Warn("ZNetScene is null. Cannot log build pieces.");
				return;
			}
			log.Info("=== Build Piece Costs ===");
			foreach (GameObject prefab in znScene.m_prefabs)
			{
				Piece component = prefab.GetComponent<Piece>();
				if ((Object)(object)component == (Object)null || component.m_resources == null || component.m_resources.Length == 0)
				{
					continue;
				}
				Dictionary<string, int> value;
				bool flag = newPieceAmounts.TryGetValue(component.m_name, out value);
				log.Info("[Piece] " + component.m_name + " | Prefab: " + ((Object)prefab).name);
				Requirement[] resources = component.m_resources;
				foreach (Requirement val in resources)
				{
					if (!((Object)(object)val?.m_resItem == (Object)null))
					{
						int amount = val.m_amount;
						if (flag && value.TryGetValue(((Object)val.m_resItem).name, out var value2) && value2 != amount)
						{
							log.Info($"   - {((Object)val.m_resItem).name}: Vanilla {amount} -> Modified {value2}");
						}
						else
						{
							log.Info($"   - {((Object)val.m_resItem).name}: Vanilla {amount}");
						}
					}
				}
			}
			log.Info("=== End Build Piece Costs ===");
		}

		private static void LogPrefabs(ZNetScene znScene)
		{
			if ((Object)(object)znScene == (Object)null)
			{
				log.Warn("ZNetScene is null, cannot log prefabs.");
				return;
			}
			log.Info("=== Listing all Prefabs in ZNetScene ===");
			foreach (GameObject prefab in znScene.m_prefabs)
			{
				if (!((Object)(object)prefab == (Object)null))
				{
					string name = ((Object)prefab).name;
					Piece component = prefab.GetComponent<Piece>();
					ItemDrop component2 = prefab.GetComponent<ItemDrop>();
					Character component3 = prefab.GetComponent<Character>();
					string text = "Generic GameObject";
					if ((Object)(object)component != (Object)null)
					{
						text = "Build Piece";
					}
					else if ((Object)(object)component2 != (Object)null)
					{
						text = "Item";
					}
					else if ((Object)(object)component3 != (Object)null)
					{
						text = "Character";
					}
					log.Info("Prefab: " + name + " (" + text + ")");
				}
			}
			log.Info("=== End of Prefabs List ===");
		}
	}
	internal class DoubleBronzeCrafting
	{
		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		private class OthersSection_Patch
		{
			private static void Postfix(ref ObjectDB __instance)
			{
				if (!((Object)(object)__instance == (Object)null) && (!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsDedicated()))
				{
					UpdateDoubleBronzeCrafting(__instance, wasChanged: false);
				}
			}
		}

		private static readonly LogManager log = new LogManager("Double Bronze", LogManager.LogLevel.Warning);

		private static readonly Dictionary<string, int> doubleBronzeOriginals = new Dictionary<string, int>();

		private static readonly Dictionary<string, int> doubleBronzeChanges = new Dictionary<string, int>
		{
			{ "Recipe_Bronze", 2 },
			{ "Recipe_Bronze5", 10 }
		};

		public static void UpdateDoubleBronzeCrafting(ObjectDB objDB, bool wasChanged)
		{
			if (ConfigManager.DoubleBronzeEnabled.Value)
			{
				foreach (string recipeName in doubleBronzeChanges.Keys)
				{
					Recipe val = objDB.m_recipes.Find((Recipe r) => ((Object)r).name == recipeName);
					if (!((Object)(object)val == (Object)null))
					{
						if (!doubleBronzeOriginals.ContainsKey(((Object)val).name))
						{
							doubleBronzeOriginals[((Object)val).name] = val.m_amount;
							log.Info("Backed up " + ((Object)val).name);
						}
						val.m_amount = doubleBronzeChanges[((Object)val).name];
						log.Info("Applied new values for " + ((Object)val).name);
					}
				}
				return;
			}
			if (!wasChanged)
			{
				return;
			}
			foreach (string recipeName2 in doubleBronzeOriginals.Keys)
			{
				Recipe val2 = objDB.m_recipes.Find((Recipe r) => ((Object)r).name == recipeName2);
				if (!((Object)(object)val2 == (Object)null))
				{
					val2.m_amount = doubleBronzeOriginals[((Object)val2).name];
					log.Info("Restored " + ((Object)val2).name);
				}
			}
			doubleBronzeOriginals.Clear();
		}
	}
	internal class FoodAndMeadChanges
	{
		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		private class FoodAndMeadChanges_Patch
		{
			private static void Postfix(ref ObjectDB __instance)
			{
				if (!((Object)(object)__instance == (Object)null))
				{
					UpdateFoodAndMead(__instance, wasModified: false);
				}
			}
		}

		private class RecipeModification
		{
			public Dictionary<string, int> ResourceChanges { get; set; } = new Dictionary<string, int>();

			public Dictionary<string, string> ResourceReplacements { get; set; } = new Dictionary<string, string>();

			public Dictionary<string, (string originalResItem, string newResItem)> OriginalResourceReplacements { get; set; } = new Dictionary<string, (string, string)>();

			public int? RecipeAmount { get; set; }
		}

		private class FoodStatModification
		{
			public float? Health { get; set; }

			public float? Stamina { get; set; }

			public float? Eitr { get; set; }

			public float? Regen { get; set; }
		}

		private static readonly LogManager log = new LogManager("Food And Mead", LogManager.LogLevel.Warning);

		private static Dictionary<string, RecipeModification> foodRecipeModifications = new Dictionary<string, RecipeModification>
		{
			{
				"Recipe_QueensJam",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "Raspberry", 5 },
						{ "Blueberries", 5 }
					}
				}
			},
			{
				"Recipe_TurnipStew",
				new RecipeModification
				{
					RecipeAmount = 2
				}
			},
			{
				"Recipe_Blacksoup",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "Bloodbag", 2 },
						{ "Honey", 2 },
						{ "Turnip", 2 }
					},
					RecipeAmount = 2
				}
			},
			{
				"Recipe_CarrotSoup",
				new RecipeModification
				{
					RecipeAmount = 2
				}
			},
			{
				"Recipe_DeerStew",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "CookedDeerMeat", 2 },
						{ "Blueberries", 2 },
						{ "Carrot", 2 }
					},
					RecipeAmount = 2
				}
			},
			{
				"Recipe_ShocklateSmoothie",
				new RecipeModification
				{
					RecipeAmount = 2
				}
			},
			{
				"Recipe_MinceMeatSauce",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "RawMeat", 2 },
						{ "NeckTail", 2 },
						{ "Carrot", 2 }
					},
					RecipeAmount = 2
				}
			},
			{
				"Recipe_Eyescream",
				new RecipeModification
				{
					RecipeAmount = 2
				}
			},
			{
				"Recipe_PulledBear",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "CookedBjornMeat", 2 },
						{ "Blueberries", 2 }
					},
					RecipeAmount = 2
				}
			},
			{
				"Recipe_Onionsoup",
				new RecipeModification
				{
					RecipeAmount = 2
				}
			},
			{
				"Recipe_WolfSkewer",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "WolfMeat", 2 },
						{ "Onion", 2 }
					},
					RecipeAmount = 2
				}
			},
			{
				"Recipe_SerpentStew",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "Mushroom", 2 },
						{ "SerpentMeatCooked", 2 }
					},
					RecipeAmount = 2
				}
			},
			{
				"Recipe_BloodPudding",
				new RecipeModification
				{
					RecipeAmount = 2
				}
			},
			{
				"Recipe_FishWraps",
				new RecipeModification
				{
					RecipeAmount = 2
				}
			},
			{
				"Recipe_FishAndBread",
				new RecipeModification
				{
					RecipeAmount = 2
				}
			},
			{
				"Recipe_LoxPie",
				new RecipeModification
				{
					RecipeAmount = 2
				}
			},
			{
				"Recipe_Bread",
				new RecipeModification
				{
					ResourceChanges = { { "BarleyFlour", 6 } }
				}
			},
			{
				"Recipe_HoneyGlazedChicken",
				new RecipeModification
				{
					ResourceChanges = { { "ChickenMeat", 2 } },
					RecipeAmount = 2
				}
			},
			{
				"Recipe_MagicallyStuffedShroom",
				new RecipeModification
				{
					ResourceChanges = { { "GiantBloodSack", 2 } },
					RecipeAmount = 2
				}
			},
			{
				"Recipe_MeatPlatter",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "BugMeat", 2 },
						{ "LoxMeat", 2 },
						{ "HareMeat", 2 }
					},
					RecipeAmount = 2
				}
			},
			{
				"Recipe_MisthareSupreme",
				new RecipeModification
				{
					ResourceChanges = { { "HareMeat", 2 } },
					RecipeAmount = 2
				}
			},
			{
				"Recipe_MushroomOmelette",
				new RecipeModification
				{
					ResourceChanges = { { "ChickenEgg", 2 } },
					RecipeAmount = 2
				}
			},
			{
				"Recipe_Salad",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "MushroomJotunPuffs", 4 },
						{ "Onion", 4 },
						{ "Cloudberry", 4 }
					},
					RecipeAmount = 4
				}
			},
			{
				"Recipe_YggdrasilPorridge",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "Sap", 2 },
						{ "Barley", 2 }
					},
					RecipeAmount = 2
				}
			},
			{
				"Recipe_FierySvinstew",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "AsksvinMeat", 2 },
						{ "MushroomSmokePuff", 2 }
					},
					RecipeAmount = 2
				}
			},
			{
				"Recipe_MarinatedGreens",
				new RecipeModification
				{
					ResourceChanges = { { "Sap", 2 } },
					RecipeAmount = 2
				}
			},
			{
				"Recipe_SizzlingBerryBroth",
				new RecipeModification
				{
					ResourceChanges = { { "Sap", 2 } },
					RecipeAmount = 2
				}
			},
			{
				"Recipe_SparklingShroomshake",
				new RecipeModification
				{
					ResourceChanges = { { "Sap", 2 } },
					RecipeAmount = 2
				}
			},
			{
				"Recipe_MashedMeat",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "AsksvinMeat", 2 },
						{ "VoltureMeat", 2 },
						{ "Fiddleheadfern", 2 }
					},
					RecipeAmount = 2
				}
			},
			{
				"Recipe_ScorchingMedley",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "MushroomJotunPuffs", 4 },
						{ "Onion", 4 },
						{ "Fiddleheadfern", 4 }
					},
					RecipeAmount = 4
				}
			},
			{
				"Recipe_SpiceInducedMarmalade",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "Vineberry", 2 },
						{ "Honey", 2 },
						{ "Fiddleheadfern", 2 }
					},
					RecipeAmount = 2
				}
			},
			{
				"Recipe_RoastedCrustPie",
				new RecipeModification
				{
					ResourceChanges = { { "VoltureEgg", 2 } },
					RecipeAmount = 2
				}
			},
			{
				"Recipe_PiquantPie",
				new RecipeModification
				{
					RecipeAmount = 2
				}
			}
		};

		private static Dictionary<string, RecipeModification> meadAndWineModifications = new Dictionary<string, RecipeModification>
		{
			{
				"Recipe_MeadBaseEitrLingering",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "Sap", 5 },
						{ "Vineberry", 5 },
						{ "MushroomMagecap", 5 }
					}
				}
			},
			{
				"Recipe_MeadBaseHealthLingering",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "Sap", 5 },
						{ "Vineberry", 5 },
						{ "MushroomSmokePuff", 5 }
					}
				}
			},
			{
				"Recipe_BarleyWineBase",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "Barley", 5 },
						{ "Cloudberry", 5 }
					}
				}
			},
			{
				"Recipe_MeadBaseEitrMinor",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "Honey", 5 },
						{ "Sap", 3 },
						{ "MushroomMagecap", 3 }
					}
				}
			},
			{
				"Recipe_MeadBaseFrostResist",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "Honey", 5 },
						{ "Thistle", 3 }
					}
				}
			},
			{
				"Recipe_MeadBaseHealthMajor",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "Honey", 5 },
						{ "GiantBloodSack", 2 },
						{ "RoyalJelly", 3 }
					},
					ResourceReplacements = { { "RoyalJelly", "MushroomJotunPuffs" } }
				}
			},
			{
				"Recipe_MeadBaseHealthMedium",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "Honey", 5 },
						{ "Bloodbag", 3 },
						{ "Raspberry", 5 }
					}
				}
			},
			{
				"Recipe_MeadBaseHealthMinor",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "Honey", 5 },
						{ "Raspberry", 5 }
					}
				}
			},
			{
				"Recipe_MeadBasePoisonResist",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "Honey", 5 },
						{ "Thistle", 3 },
						{ "Coal", 5 }
					}
				}
			},
			{
				"Recipe_MeadBaseStaminaLingering",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "Sap", 5 },
						{ "Cloudberry", 5 },
						{ "MushroomJotunPuffs", 5 }
					}
				}
			},
			{
				"Recipe_MeadBaseStaminaMedium",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "Honey", 5 },
						{ "Cloudberry", 5 }
					}
				}
			},
			{
				"Recipe_MeadBaseStaminaMinor",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "Honey", 5 },
						{ "Raspberry", 5 }
					}
				}
			},
			{
				"Recipe_MeadBaseTasty",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "Honey", 5 },
						{ "Raspberry", 5 }
					}
				}
			},
			{
				"Recipe_MeadBaseHasty",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "Honey", 5 },
						{ "Blueberries", 5 }
					}
				}
			},
			{
				"Recipe_MeadBaseStrength",
				new RecipeModification
				{
					ResourceChanges = { { "Honey", 5 } }
				}
			},
			{
				"Recipe_MeadBaseSwimmer",
				new RecipeModification
				{
					ResourceChanges = { { "Dandelion", 7 } }
				}
			},
			{
				"Recipe_MeadBaseTamer",
				new RecipeModification
				{
					ResourceChanges = { { "Carrot", 5 } }
				}
			},
			{
				"Recipe_MeadBaseBzerker",
				new RecipeModification
				{
					ResourceChanges = 
					{
						{ "Mushroom", 5 },
						{ "MushroomYellow", 5 }
					}
				}
			}
		};

		private static Dictionary<string, int> foodStacksModifications = new Dictionary<string, int>
		{
			{ "QueensJam", 20 },
			{ "CarrotSoup", 20 },
			{ "DeerStew", 20 },
			{ "TurnipStew", 20 },
			{ "PulledBear", 20 },
			{ "BlackSoup", 20 },
			{ "Eyescream", 20 },
			{ "ShocklateSmoothie", 20 },
			{ "MinceMeatSauce", 20 },
			{ "OnionSoup", 20 },
			{ "SerpentStew", 20 },
			{ "BloodPudding", 20 },
			{ "FishWraps", 20 },
			{ "FishAndBread", 20 },
			{ "LoxPie", 20 },
			{ "MushroomOmelette", 20 },
			{ "YggdrasilPorridge", 20 },
			{ "CookedEgg", 20 },
			{ "Salad", 20 },
			{ "SeekerAspic", 20 },
			{ "HoneyGlazedChicken", 20 },
			{ "MagicallyStuffedShroom", 20 },
			{ "MeatPlatter", 20 },
			{ "MisthareSupreme", 20 },
			{ "FierySvinstew", 20 },
			{ "MarinatedGreens", 20 },
			{ "MashedMeat", 20 },
			{ "ScorchingMedley", 20 },
			{ "SizzlingBerryBroth", 20 },
			{ "SpicyMarmalade", 20 },
			{ "SparklingShroomshake", 20 },
			{ "RoastedCrustPie", 20 },
			{ "PiquantPie", 20 },
			{ "FishAndBreadUncooked", 20 },
			{ "LoxPieUncooked", 20 },
			{ "HoneyGlazedChickenUncooked", 20 },
			{ "MagicallyStuffedShroomUncooked", 20 },
			{ "MeatPlatterUncooked", 20 },
			{ "MisthareSupremeUncooked", 20 },
			{ "RoastedCrustPieUncooked", 20 },
			{ "PiquantPieUncooked", 20 }
		};

		private static readonly Dictionary<string, FoodStatModification> foodStatModifications = new Dictionary<string, FoodStatModification> { 
		{
			"PulledBear",
			new FoodStatModification
			{
				Health = 45f
			}
		} };

		private static Dictionary<string, RecipeModification> recipeModifications;

		private static Dictionary<string, RecipeModification> originalRecipeValues = new Dictionary<string, RecipeModification>();

		private static Dictionary<string, int> originalFoodStacks = new Dictionary<string, int>();

		private static readonly Dictionary<string, FoodStatModification> originalFoodStats = new Dictionary<string, FoodStatModification>();

		private static Dictionary<string, RecipeModification> GetRecipeModifications()
		{
			if (recipeModifications == null)
			{
				recipeModifications = foodRecipeModifications;
				foreach (KeyValuePair<string, RecipeModification> meadAndWineModification in meadAndWineModifications)
				{
					recipeModifications[meadAndWineModification.Key] = meadAndWineModification.Value;
				}
			}
			return recipeModifications;
		}

		public static void UpdateFoodAndMead(ObjectDB objDB, bool wasModified)
		{
			Dictionary<string, RecipeModification> dictionary = GetRecipeModifications();
			if (ConfigManager.FoodAndMeadModificationsEnabled.Value)
			{
				foreach (KeyValuePair<string, RecipeModification> item in dictionary)
				{
					string recipeName = item.Key;
					RecipeModification value = item.Value;
					Recipe val = ((IEnumerable<Recipe>)objDB.m_recipes).FirstOrDefault((Func<Recipe, bool>)((Recipe r) => (