Decompiled source of Quads Bird Trap v1.2.3

plugins/BirdTrap.dll

Decompiled 6 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using DHack.Shared;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json.Linq;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyMetadata("AI_Assisted_Creation", "This assembly was partially or fully created with the assistance of Generative AI (Claude Code).")]
[assembly: AssemblyMetadata("AI_Model_Vendor", "Anthropic")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BirdTrap
{
	internal static class Look
	{
		private static readonly Dictionary<string, Material> Materials = new Dictionary<string, Material>();

		private static readonly Dictionary<string, Color> Plain = new Dictionary<string, Color>
		{
			{
				"StoneDark",
				new Color(0.36f, 0.36f, 0.38f)
			},
			{
				"Coal",
				new Color(0.15f, 0.15f, 0.17f)
			},
			{
				"Parchment",
				new Color(0.9f, 0.82f, 0.63f)
			},
			{
				"Ink",
				new Color(0.16f, 0.11f, 0.08f)
			},
			{
				"Bone",
				new Color(0.92f, 0.89f, 0.8f)
			},
			{
				"Red",
				new Color(0.66f, 0.1f, 0.08f)
			},
			{
				"Gold",
				new Color(0.93f, 0.72f, 0.2f)
			},
			{
				"Leather",
				new Color(0.42f, 0.26f, 0.13f)
			},
			{
				"Glow",
				new Color(1f, 0.72f, 0.28f)
			},
			{
				"Cream",
				new Color(0.95f, 0.92f, 0.84f)
			},
			{
				"Black",
				new Color(0.06f, 0.06f, 0.07f)
			},
			{
				"Green",
				new Color(0.18f, 0.5f, 0.25f)
			},
			{
				"Blue",
				new Color(0.2f, 0.35f, 0.7f)
			},
			{
				"Teal",
				new Color(0.25f, 0.75f, 0.8f)
			},
			{
				"RedDark",
				new Color(0.38f, 0.05f, 0.05f)
			},
			{
				"Chrome",
				new Color(0.78f, 0.8f, 0.84f)
			},
			{
				"Wicker",
				new Color(0.68f, 0.52f, 0.31f)
			},
			{
				"Grey",
				new Color(0.64f, 0.66f, 0.7f)
			}
		};

		private static readonly Dictionary<string, float> Glows = new Dictionary<string, float>
		{
			{ "Glow", 1.1f },
			{ "Gold", 0.18f }
		};

		private static Material Find(ZNetScene scene, string prefab, string material)
		{
			GameObject prefab2 = scene.GetPrefab(prefab);
			if ((Object)(object)prefab2 == (Object)null)
			{
				return null;
			}
			Renderer[] componentsInChildren = prefab2.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				Material[] sharedMaterials = val.sharedMaterials;
				foreach (Material val2 in sharedMaterials)
				{
					if ((Object)(object)val2 != (Object)null && ((Object)val2).name == material)
					{
						return val2;
					}
				}
			}
			return null;
		}

		internal static void Harvest(ZNetScene scene, Material fallbackBase)
		{
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Expected O, but got Unknown
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Expected O, but got Unknown
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			Materials.Clear();
			Materials["Stone"] = Find(scene, "stone_wall_1x1", "stone_mat");
			Materials["Planks"] = Find(scene, "wood_floor", "woodwall");
			Materials["Dark"] = Find(scene, "darkwood_pole", "DarkWood_mat");
			Materials["Iron"] = Find(scene, "iron_grate", "metalwall");
			Material val = Find(scene, "piece_cauldron", "cauldron_chain");
			Material val2 = (((Object)(object)val != (Object)null) ? val : fallbackBase);
			foreach (KeyValuePair<string, Color> item in Plain)
			{
				Material val3 = new Material(val2)
				{
					color = item.Value
				};
				if (val3.HasProperty("_MainTex"))
				{
					val3.mainTexture = null;
				}
				if (Glows.TryGetValue(item.Key, out var value) && val3.HasProperty("_EmissionColor"))
				{
					val3.EnableKeyword("_EMISSION");
					val3.SetColor("_EmissionColor", item.Value * value);
				}
				Materials[item.Key] = val3;
			}
			string[] array = new string[4] { "Stone", "Planks", "Dark", "Iron" };
			foreach (string text in array)
			{
				if ((Object)(object)Materials[text] == (Object)null)
				{
					Materials[text] = new Material(val2)
					{
						color = (Color)(text switch
						{
							"Dark" => new Color(0.25f, 0.17f, 0.11f), 
							"Planks" => new Color(0.5f, 0.34f, 0.2f), 
							"Stone" => new Color(0.5f, 0.5f, 0.52f), 
							_ => new Color(0.38f, 0.38f, 0.42f), 
						})
					};
				}
			}
			Debug.Log((object)("[BirdTrap] materials: " + string.Join(", ", Materials.Select((KeyValuePair<string, Material> kv) => kv.Key + "=" + ((Object)kv.Value).name).ToArray())));
		}

		internal static Material Of(string name)
		{
			if (!Materials.TryGetValue(name, out var value))
			{
				return Materials.Values.FirstOrDefault();
			}
			return value;
		}

		internal static void Clear()
		{
			Materials.Clear();
		}
	}
	internal static class ModelBuilder
	{
		internal static GameObject Build(Transform parent, object[][] parts, int layer)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Expected O, but got Unknown
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Model")
			{
				layer = layer
			};
			val.transform.SetParent(parent, false);
			Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>();
			Vector3 localPosition = default(Vector3);
			Vector3 localScale = default(Vector3);
			Vector3 val2 = default(Vector3);
			Transform val3;
			GameObject val4;
			for (int i = 0; i < parts.Length; val4.transform.SetParent(val3, false), val4.transform.localPosition = localPosition, val4.transform.localRotation = Quaternion.Euler(val2), i++)
			{
				object[] array = parts[i];
				string text = (string)array[0];
				string text2 = (string)array[1];
				string text3 = (string)array[2];
				((Vector3)(ref localPosition))..ctor((float)array[3], (float)array[4], (float)array[5]);
				((Vector3)(ref localScale))..ctor((float)array[6], (float)array[7], (float)array[8]);
				((Vector3)(ref val2))..ctor((float)array[9], (float)array[10], (float)array[11]);
				val3 = ((text3.Length > 0 && dictionary.TryGetValue(text3, out var value)) ? value : val.transform);
				int num;
				switch (text2)
				{
				case "Group":
					val4 = new GameObject(text)
					{
						layer = layer
					};
					dictionary[text] = val4.transform;
					continue;
				default:
					num = 0;
					break;
				case "Cylinder":
					num = 2;
					break;
				case "Cube":
					num = 3;
					break;
				}
				val4 = GameObject.CreatePrimitive((PrimitiveType)num);
				((Object)val4).name = text;
				Object.DestroyImmediate((Object)(object)val4.GetComponent<Collider>());
				val4.layer = layer;
				val4.GetComponent<Renderer>().sharedMaterial = Look.Of((string)array[12]);
				val4.transform.localScale = localScale;
			}
			return val;
		}
	}
	internal static class ModelData
	{
		internal const float Scale = 1f;

		internal static readonly object[][] Parts = new object[120][]
		{
			new object[13]
			{
				"runner", "Cylinder", "", 0f, 0.03f, -0.22f, 0.06f, 0.46f, 0.06f, 0f,
				0f, 90f, "Dark"
			},
			new object[13]
			{
				"runner", "Cylinder", "", 0f, 0.03f, 0.22f, 0.06f, 0.46f, 0.06f, 0f,
				0f, 90f, "Dark"
			},
			new object[13]
			{
				"basePlank", "Cube", "", -0.336f, 0.052f, 0f, 0.16f, 0.036f, 0.62f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"basePlank", "Cube", "", -0.168f, 0.052f, 0f, 0.16f, 0.036f, 0.62f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"basePlank", "Cube", "", 0f, 0.052f, 0f, 0.16f, 0.036f, 0.62f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"basePlank", "Cube", "", 0.168f, 0.052f, 0f, 0.16f, 0.036f, 0.62f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"basePlank", "Cube", "", 0.336f, 0.052f, 0f, 0.16f, 0.036f, 0.62f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"baseBatten", "Cube", "", 0f, 0.074f, -0.26f, 0.82f, 0.012f, 0.035f, 0f,
				0f, 0f, "Dark"
			},
			new object[13]
			{
				"baseBatten", "Cube", "", 0f, 0.074f, 0.26f, 0.82f, 0.012f, 0.035f, 0f,
				0f, 0f, "Dark"
			},
			new object[13]
			{
				"post", "Cube", "", -0.4f, 0.28f, -0.27f, 0.045f, 0.42f, 0.045f, 0f,
				0f, 0f, "Dark"
			},
			new object[13]
			{
				"post", "Cube", "", -0.4f, 0.28f, 0.27f, 0.045f, 0.42f, 0.045f, 0f,
				0f, 0f, "Dark"
			},
			new object[13]
			{
				"post", "Cube", "", 0.4f, 0.28f, -0.27f, 0.045f, 0.42f, 0.045f, 0f,
				0f, 0f, "Dark"
			},
			new object[13]
			{
				"post", "Cube", "", 0.4f, 0.28f, 0.27f, 0.045f, 0.42f, 0.045f, 0f,
				0f, 0f, "Dark"
			},
			new object[13]
			{
				"frameX", "Cube", "", 0f, 0.49f, -0.27f, 0.84f, 0.04f, 0.045f, 0f,
				0f, 0f, "Dark"
			},
			new object[13]
			{
				"frameX", "Cube", "", 0f, 0.49f, 0.27f, 0.84f, 0.04f, 0.045f, 0f,
				0f, 0f, "Dark"
			},
			new object[13]
			{
				"frameZ", "Cube", "", -0.4f, 0.49f, 0f, 0.045f, 0.04f, 0.58f, 0f,
				0f, 0f, "Dark"
			},
			new object[13]
			{
				"frameZ", "Cube", "", 0.4f, 0.49f, 0f, 0.045f, 0.04f, 0.58f, 0f,
				0f, 0f, "Dark"
			},
			new object[13]
			{
				"midZ", "Cube", "", -0.4f, 0.28f, 0f, 0.03f, 0.028f, 0.54f, 0f,
				0f, 0f, "Dark"
			},
			new object[13]
			{
				"midZ", "Cube", "", 0.4f, 0.28f, 0f, 0.03f, 0.028f, 0.54f, 0f,
				0f, 0f, "Dark"
			},
			new object[13]
			{
				"midBack", "Cube", "", 0f, 0.28f, 0.27f, 0.8f, 0.028f, 0.03f, 0f,
				0f, 0f, "Dark"
			},
			new object[13]
			{
				"slatSide", "Cube", "", -0.4f, 0.28f, -0.215f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"slatSide", "Cube", "", 0.4f, 0.28f, -0.215f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"slatSide", "Cube", "", -0.4f, 0.28f, -0.1433f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Wicker"
			},
			new object[13]
			{
				"slatSide", "Cube", "", 0.4f, 0.28f, -0.1433f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Wicker"
			},
			new object[13]
			{
				"slatSide", "Cube", "", -0.4f, 0.28f, -0.0717f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"slatSide", "Cube", "", 0.4f, 0.28f, -0.0717f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"slatSide", "Cube", "", -0.4f, 0.28f, 0f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Wicker"
			},
			new object[13]
			{
				"slatSide", "Cube", "", 0.4f, 0.28f, 0f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Wicker"
			},
			new object[13]
			{
				"slatSide", "Cube", "", -0.4f, 0.28f, 0.0717f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"slatSide", "Cube", "", 0.4f, 0.28f, 0.0717f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"slatSide", "Cube", "", -0.4f, 0.28f, 0.1433f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Wicker"
			},
			new object[13]
			{
				"slatSide", "Cube", "", 0.4f, 0.28f, 0.1433f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Wicker"
			},
			new object[13]
			{
				"slatSide", "Cube", "", -0.4f, 0.28f, 0.215f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"slatSide", "Cube", "", 0.4f, 0.28f, 0.215f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"slatBack", "Cube", "", -0.345f, 0.28f, 0.27f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"slatBack", "Cube", "", -0.2683f, 0.28f, 0.27f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Wicker"
			},
			new object[13]
			{
				"slatBack", "Cube", "", -0.1917f, 0.28f, 0.27f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"slatBack", "Cube", "", -0.115f, 0.28f, 0.27f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Wicker"
			},
			new object[13]
			{
				"slatBack", "Cube", "", -0.0383f, 0.28f, 0.27f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"slatBack", "Cube", "", 0.0383f, 0.28f, 0.27f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Wicker"
			},
			new object[13]
			{
				"slatBack", "Cube", "", 0.115f, 0.28f, 0.27f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"slatBack", "Cube", "", 0.1917f, 0.28f, 0.27f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Wicker"
			},
			new object[13]
			{
				"slatBack", "Cube", "", 0.2683f, 0.28f, 0.27f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"slatBack", "Cube", "", 0.345f, 0.28f, 0.27f, 0.022f, 0.4f, 0.022f, 0f,
				0f, 0f, "Wicker"
			},
			new object[13]
			{
				"slatTop", "Cube", "", -0.345f, 0.502f, 0f, 0.022f, 0.022f, 0.55f, 0f,
				0f, 0f, "Wicker"
			},
			new object[13]
			{
				"slatTop", "Cube", "", -0.2683f, 0.502f, 0f, 0.022f, 0.022f, 0.55f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"slatTop", "Cube", "", -0.1917f, 0.502f, 0f, 0.022f, 0.022f, 0.55f, 0f,
				0f, 0f, "Wicker"
			},
			new object[13]
			{
				"slatTop", "Cube", "", -0.115f, 0.502f, 0f, 0.022f, 0.022f, 0.55f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"slatTop", "Cube", "", -0.0383f, 0.502f, 0f, 0.022f, 0.022f, 0.55f, 0f,
				0f, 0f, "Wicker"
			},
			new object[13]
			{
				"slatTop", "Cube", "", 0.0383f, 0.502f, 0f, 0.022f, 0.022f, 0.55f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"slatTop", "Cube", "", 0.115f, 0.502f, 0f, 0.022f, 0.022f, 0.55f, 0f,
				0f, 0f, "Wicker"
			},
			new object[13]
			{
				"slatTop", "Cube", "", 0.1917f, 0.502f, 0f, 0.022f, 0.022f, 0.55f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"slatTop", "Cube", "", 0.2683f, 0.502f, 0f, 0.022f, 0.022f, 0.55f, 0f,
				0f, 0f, "Wicker"
			},
			new object[13]
			{
				"slatTop", "Cube", "", 0.345f, 0.502f, 0f, 0.022f, 0.022f, 0.55f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"cornerLash", "Cube", "", -0.4f, 0.48f, -0.27f, 0.06f, 0.05f, 0.06f, 0f,
				0f, 0f, "Leather"
			},
			new object[13]
			{
				"cornerLash", "Cube", "", -0.4f, 0.48f, 0.27f, 0.06f, 0.05f, 0.06f, 0f,
				0f, 0f, "Leather"
			},
			new object[13]
			{
				"cornerLash", "Cube", "", 0.4f, 0.48f, -0.27f, 0.06f, 0.05f, 0.06f, 0f,
				0f, 0f, "Leather"
			},
			new object[13]
			{
				"cornerLash", "Cube", "", 0.4f, 0.48f, 0.27f, 0.06f, 0.05f, 0.06f, 0f,
				0f, 0f, "Leather"
			},
			new object[13]
			{
				"lash", "Cube", "", -0.4f, 0.28f, -0.215f, 0.04f, 0.04f, 0.03f, 0f,
				0f, 0f, "Leather"
			},
			new object[13]
			{
				"lash", "Cube", "", 0.4f, 0.28f, -0.215f, 0.04f, 0.04f, 0.03f, 0f,
				0f, 0f, "Leather"
			},
			new object[13]
			{
				"lash", "Cube", "", -0.4f, 0.28f, 0.215f, 0.04f, 0.04f, 0.03f, 0f,
				0f, 0f, "Leather"
			},
			new object[13]
			{
				"lash", "Cube", "", 0.4f, 0.28f, 0.215f, 0.04f, 0.04f, 0.03f, 0f,
				0f, 0f, "Leather"
			},
			new object[13]
			{
				"guide", "Cube", "", -0.4f, 0.45f, -0.295f, 0.05f, 0.76f, 0.035f, 0f,
				0f, 0f, "Dark"
			},
			new object[13]
			{
				"guideKnob", "Sphere", "", -0.4f, 0.85f, -0.295f, 0.07f, 0.06f, 0.07f, 0f,
				0f, 0f, "Dark"
			},
			new object[13]
			{
				"guide", "Cube", "", 0.4f, 0.45f, -0.295f, 0.05f, 0.76f, 0.035f, 0f,
				0f, 0f, "Dark"
			},
			new object[13]
			{
				"guideKnob", "Sphere", "", 0.4f, 0.85f, -0.295f, 0.07f, 0.06f, 0.07f, 0f,
				0f, 0f, "Dark"
			},
			new object[13]
			{
				"guideTop", "Cube", "", 0f, 0.83f, -0.295f, 0.86f, 0.04f, 0.05f, 0f,
				0f, 0f, "Dark"
			},
			new object[13]
			{
				"door", "Group", "", 0f, 0.37f, -0.32f, 1f, 1f, 1f, 0f,
				0f, 0f, ""
			},
			new object[13]
			{
				"doorSlat", "Cube", "door", -0.335f, 0.195f, 0f, 0.026f, 0.38f, 0.022f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"doorSlat", "Cube", "door", -0.2512f, 0.195f, 0f, 0.026f, 0.38f, 0.022f, 0f,
				0f, 0f, "Wicker"
			},
			new object[13]
			{
				"doorSlat", "Cube", "door", -0.1675f, 0.195f, 0f, 0.026f, 0.38f, 0.022f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"doorSlat", "Cube", "door", -0.0837f, 0.195f, 0f, 0.026f, 0.38f, 0.022f, 0f,
				0f, 0f, "Wicker"
			},
			new object[13]
			{
				"doorSlat", "Cube", "door", 0f, 0.195f, 0f, 0.026f, 0.38f, 0.022f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"doorSlat", "Cube", "door", 0.0837f, 0.195f, 0f, 0.026f, 0.38f, 0.022f, 0f,
				0f, 0f, "Wicker"
			},
			new object[13]
			{
				"doorSlat", "Cube", "door", 0.1675f, 0.195f, 0f, 0.026f, 0.38f, 0.022f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"doorSlat", "Cube", "door", 0.2512f, 0.195f, 0f, 0.026f, 0.38f, 0.022f, 0f,
				0f, 0f, "Wicker"
			},
			new object[13]
			{
				"doorSlat", "Cube", "door", 0.335f, 0.195f, 0f, 0.026f, 0.38f, 0.022f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"doorBar", "Cube", "door", 0f, 0.025f, -0.006f, 0.76f, 0.04f, 0.03f, 0f,
				0f, 0f, "Dark"
			},
			new object[13]
			{
				"doorBar", "Cube", "door", 0f, 0.365f, -0.006f, 0.76f, 0.04f, 0.03f, 0f,
				0f, 0f, "Dark"
			},
			new object[13]
			{
				"doorBrace", "Cube", "door", -0.17f, 0.195f, -0.01f, 0.025f, 0.351f, 0.02f, 0f,
				0f, -52f, "Dark"
			},
			new object[13]
			{
				"doorBrace", "Cube", "door", 0.17f, 0.195f, -0.01f, 0.025f, 0.351f, 0.02f, 0f,
				0f, 52f, "Dark"
			},
			new object[13]
			{
				"doorRing", "Cylinder", "door", 0f, 0.395f, -0.012f, 0.05f, 0.006f, 0.05f, 90f,
				0f, 0f, "Iron"
			},
			new object[13]
			{
				"prop", "Group", "", 0f, 0.07f, -0.36f, 1f, 1f, 1f, 0f,
				0f, 0f, ""
			},
			new object[13]
			{
				"propStick", "Cylinder", "prop", 0f, 0.14f, 0f, 0.026f, 0.14f, 0.026f, -6f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"propFork", "Cylinder", "prop", -0.018f, 0.29f, -0.005f, 0.016f, 0.035f, 0.016f, 0f,
				0f, 30f, "Planks"
			},
			new object[13]
			{
				"propFork", "Cylinder", "prop", 0.018f, 0.29f, -0.005f, 0.016f, 0.035f, 0.016f, 0f,
				0f, -30f, "Planks"
			},
			new object[13]
			{
				"cord", "Cylinder", "prop", 0f, 0.16f, 0.12f, 0.008f, 0.2f, 0.008f, 58f,
				0f, 0f, "Leather"
			},
			new object[13]
			{
				"pedal", "Cube", "", 0f, 0.082f, 0.03f, 0.18f, 0.016f, 0.12f, 0f,
				0f, 0f, "Planks"
			},
			new object[13]
			{
				"pedalPin", "Cylinder", "", 0f, 0.095f, 0.09f, 0.02f, 0.012f, 0.02f, 0f,
				0f, 0f, "Dark"
			},
			new object[13]
			{
				"bait", "Group", "", 0f, 0.092f, 0.03f, 1f, 1f, 1f, 0f,
				0f, 0f, ""
			},
			new object[13]
			{
				"leaf", "Sphere", "bait", 0f, 0f, 0f, 0.16f, 0.012f, 0.1f, 0f,
				0f, 0f, "Green"
			},
			new object[13]
			{
				"berry", "Sphere", "bait", -0.03f, 0.018f, 0.01f, 0.03f, 0.03f, 0.03f, 0f,
				0f, 0f, "Red"
			},
			new object[13]
			{
				"berry", "Sphere", "bait", 0.02f, 0.018f, -0.015f, 0.03f, 0.03f, 0.03f, 0f,
				0f, 0f, "Red"
			},
			new object[13]
			{
				"berry", "Sphere", "bait", 0.035f, 0.018f, 0.02f, 0.03f, 0.03f, 0.03f, 0f,
				0f, 0f, "Red"
			},
			new object[13]
			{
				"berry", "Sphere", "bait", -0.01f, 0.018f, -0.03f, 0.03f, 0.03f, 0.03f, 0f,
				0f, 0f, "Red"
			},
			new object[13]
			{
				"berry", "Sphere", "bait", 0f, 0.018f, 0.025f, 0.03f, 0.03f, 0.03f, 0f,
				0f, 0f, "Red"
			},
			new object[13]
			{
				"seed", "Sphere", "bait", -0.05f, 0.01f, -0.01f, 0.018f, 0.012f, 0.026f, 0f,
				0f, 0f, "Leather"
			},
			new object[13]
			{
				"seed", "Sphere", "bait", 0.055f, 0.01f, -0.02f, 0.018f, 0.012f, 0.026f, 0f,
				0f, 0f, "Leather"
			},
			new object[13]
			{
				"seed", "Sphere", "bait", -0.045f, 0.01f, 0.03f, 0.018f, 0.012f, 0.026f, 0f,
				0f, 0f, "Leather"
			},
			new object[13]
			{
				"seed", "Sphere", "bait", 0.06f, 0.01f, 0.03f, 0.018f, 0.012f, 0.026f, 0f,
				0f, 0f, "Leather"
			},
			new object[13]
			{
				"bird", "Group", "", 0.02f, 0.074f, -0.02f, 1f, 1f, 1f, 0f,
				160f, 0f, ""
			},
			new object[13]
			{
				"birdBody", "Group", "bird", 0f, 0f, 0f, 1f, 1f, 1f, 0f,
				0f, 0f, ""
			},
			new object[13]
			{
				"body", "Sphere", "birdBody", 0f, 0.1105f, 0.0065f, 0.156f, 0.13f, 0.26f, -12f,
				0f, 0f, "Cream"
			},
			new object[13]
			{
				"back", "Sphere", "birdBody", 0f, 0.1365f, 0.039f, 0.1495f, 0.078f, 0.208f, -12f,
				0f, 0f, "Grey"
			},
			new object[13]
			{
				"head", "Sphere", "birdBody", 0f, 0.208f, -0.0975f, 0.0975f, 0.0936f, 0.104f, 0f,
				0f, 0f, "Cream"
			},
			new object[13]
			{
				"beak", "Cube", "birdBody", 0f, 0.1989f, -0.1586f, 0.0234f, 0.0234f, 0.0585f, 6f,
				0f, 0f, "Gold"
			},
			new object[13]
			{
				"beakTip", "Cube", "birdBody", 0f, 0.1937f, -0.1846f, 0.0182f, 0.0208f, 0.013f, 0f,
				0f, 0f, "RedDark"
			},
			new object[13]
			{
				"eye", "Sphere", "birdBody", -0.039f, 0.221f, -0.1274f, 0.0182f, 0.0182f, 0.0182f, 0f,
				0f, 0f, "Black"
			},
			new object[13]
			{
				"wing", "Sphere", "birdBody", -0.0715f, 0.13f, 0.039f, 0.039f, 0.091f, 0.221f, -14f,
				0f, 0f, "Grey"
			},
			new object[13]
			{
				"wingTip", "Sphere", "birdBody", -0.0585f, 0.1456f, 0.1495f, 0.0286f, 0.039f, 0.104f, -20f,
				0f, 0f, "Black"
			},
			new object[13]
			{
				"eye", "Sphere", "birdBody", 0.039f, 0.221f, -0.1274f, 0.0182f, 0.0182f, 0.0182f, 0f,
				0f, 0f, "Black"
			},
			new object[13]
			{
				"wing", "Sphere", "birdBody", 0.0715f, 0.13f, 0.039f, 0.039f, 0.091f, 0.221f, -14f,
				0f, 0f, "Grey"
			},
			new object[13]
			{
				"wingTip", "Sphere", "birdBody", 0.0585f, 0.1456f, 0.1495f, 0.0286f, 0.039f, 0.104f, -20f,
				0f, 0f, "Black"
			},
			new object[13]
			{
				"tail", "Cube", "birdBody", 0f, 0.1365f, 0.1495f, 0.078f, 0.0182f, 0.078f, -16f,
				0f, 0f, "Black"
			},
			new object[13]
			{
				"leg", "Cylinder", "bird", -0.0286f, 0.026f, 0f, 0.0143f, 0.0312f, 0.0143f, 0f,
				0f, 0f, "Gold"
			},
			new object[13]
			{
				"foot", "Cube", "bird", -0.0286f, 0.0039f, -0.0156f, 0.039f, 0.0078f, 0.0455f, 0f,
				0f, 0f, "Gold"
			},
			new object[13]
			{
				"leg", "Cylinder", "bird", 0.0286f, 0.026f, 0f, 0.0143f, 0.0312f, 0.0143f, 0f,
				0f, 0f, "Gold"
			},
			new object[13]
			{
				"foot", "Cube", "bird", 0.0286f, 0.0039f, -0.0156f, 0.039f, 0.0078f, 0.0455f, 0f,
				0f, 0f, "Gold"
			},
			new object[13]
			{
				"weightStone", "Sphere", "", 0.1f, 0.535f, 0.1f, 0.22f, 0.075f, 0.16f, 0f,
				20f, 0f, "Stone"
			},
			new object[13]
			{
				"weightStone2", "Sphere", "", 0.2f, 0.53f, 0.16f, 0.12f, 0.05f, 0.1f, 0f,
				-30f, 0f, "StoneDark"
			}
		};
	}
	[BepInPlugin("com.quad.birdtrap", "BirdTrap", "1.2.3")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "com.quad.birdtrap";

		public const string OldGuid = "com.dhack.birdtrap";

		public const string Name = "BirdTrap";

		public const string Version = "1.2.3";

		public const string PiecePrefab = "piece_birdtrap";

		internal static ConfigEntry<float> MinMinutes;

		internal static ConfigEntry<float> MaxMinutes;

		internal static ConfigEntry<int> MinFeathers;

		internal static ConfigEntry<int> MaxFeathers;

		internal static ConfigEntry<int> MaxBait;

		internal static ConfigEntry<bool> NeedsSky;

		internal static ConfigEntry<bool> RestsAtNight;

		private static GameObject _holder;

		private static GameObject _prefab;

		private static PieceTable _table;

		internal static EffectList DoorShut;

		internal static EffectList DoorOpen;

		internal static ServerSettings Synced;

		internal static ConfigEntry<string> Cost;

		internal static ManualLogSource Log;

		private static bool _tellNoServer;

		internal const string DefaultCost = "Wood:8, LeatherScraps:2";

		private Harmony _harmony;

		private BaseUnityPlugin _claudeTools;

		private float _nextClaudeCheck;

		private void Awake()
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Expected O, but got Unknown
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Expected O, but got Unknown
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Expected O, but got Unknown
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Expected O, but got Unknown
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Expected O, but got Unknown
			Migration.FromOldGuid((BaseUnityPlugin)(object)this, "com.dhack.birdtrap");
			Translations.Load((BaseUnityPlugin)(object)this);
			Log = ((BaseUnityPlugin)this).Logger;
			Synced = new ServerSettings("com.quad.birdtrap", ((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			MinMinutes = Synced.Add<float>(((BaseUnityPlugin)this).Config.Bind<float>("Catching", "MinutesMin", 8f, new ConfigDescription("Shortest wait (real minutes, in game time) from baiting to a bird. In multiplayer the server's value applies.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 120f), Array.Empty<object>())));
			MaxMinutes = Synced.Add<float>(((BaseUnityPlugin)this).Config.Bind<float>("Catching", "MinutesMax", 14f, new ConfigDescription("Longest wait (real minutes, in game time) from baiting to a bird. In multiplayer the server's value applies.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 240f), Array.Empty<object>())));
			MaxBait = Synced.Add<int>(((BaseUnityPlugin)this).Config.Bind<int>("Catching", "BaitHeld", 5, new ConfigDescription("How many pieces of bait a trap holds (each bird eats one). In multiplayer the server's value applies.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>())));
			NeedsSky = Synced.Add<bool>(((BaseUnityPlugin)this).Config.Bind<bool>("Catching", "NeedsOpenSky", true, "Birds only come to a trap with open sky above it (not under a roof). In multiplayer the server's value applies."));
			RestsAtNight = Synced.Add<bool>(((BaseUnityPlugin)this).Config.Bind<bool>("Catching", "BirdsRoostAtNight", true, "No birds come at night: one due then comes in the morning. In multiplayer the server's value applies."));
			MinFeathers = Synced.Add<int>(((BaseUnityPlugin)this).Config.Bind<int>("Plucking", "FeathersMin", 2, new ConfigDescription("Fewest feathers a bird gives. In multiplayer the server's value applies.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>())));
			MaxFeathers = Synced.Add<int>(((BaseUnityPlugin)this).Config.Bind<int>("Plucking", "FeathersMax", 3, new ConfigDescription("Most feathers a bird gives. In multiplayer the server's value applies.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>())));
			Cost = Synced.Bind("Building", "Cost", "Wood:8, LeatherScraps:2", "What a bird trap costs to build with the hammer (at a workbench). Item prefab names and amounts, separated by commas, like FineWood:12, BronzeNails:30 (Claude Tools' `prefabs <text>` shows exact names). A cost with a mistake in it keeps the last good one.", null);
			Cost.SettingChanged += delegate
			{
				ApplyCost();
			};
			Synced.ServerChanged += delegate
			{
				_tellNoServer = Synced.Server == ServerSettings.ServerMod.Missing;
			};
			_harmony = new Harmony("com.quad.birdtrap");
			_harmony.PatchAll();
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				Register(ZNetScene.instance);
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"BirdTrap 1.2.3 loaded");
		}

		private void Update()
		{
			Synced?.Update();
			if (_tellNoServer && (Object)(object)Player.m_localPlayer != (Object)null)
			{
				_tellNoServer = false;
				((Character)Player.m_localPlayer).Message((MessageType)2, "$birdtrap_server_missing", 0, (Sprite)null, false);
			}
			if (Time.unscaledTime < _nextClaudeCheck)
			{
				return;
			}
			_nextClaudeCheck = Time.unscaledTime + 5f;
			PluginInfo value;
			BaseUnityPlugin val = (Chainloader.PluginInfos.TryGetValue("com.quad.claudetools", out value) ? value.Instance : null);
			if ((Object)(object)val == (Object)(object)_claudeTools)
			{
				return;
			}
			_claudeTools = val;
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			try
			{
				MethodInfo method = ((object)val).GetType().GetMethod("RegisterCommand", BindingFlags.Static | BindingFlags.Public);
				Func<string[], Action<JObject>, Action<string>, IEnumerator> func = delegate(string[] a, Action<JObject> output, Action<string> error)
				{
					//IL_0025: Unknown result type (might be due to invalid IL or missing references)
					//IL_0014: Unknown result type (might be due to invalid IL or missing references)
					//IL_002a: 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_0035: Expected O, but got Unknown
					//IL_007c: Unknown result type (might be due to invalid IL or missing references)
					//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
					//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
					//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
					//IL_00db: Unknown result type (might be due to invalid IL or missing references)
					//IL_0105: Expected O, but got Unknown
					Vector3 me = (((Object)(object)Player.m_localPlayer != (Object)null) ? ((Component)Player.m_localPlayer).transform.position : Vector3.zero);
					JArray val2 = new JArray();
					foreach (TrapPiece item in TrapPiece.All.OrderBy((TrapPiece x) => Vector3.Distance(((Component)x).transform.position, me)))
					{
						if ((Object)(object)item != (Object)null)
						{
							val2.Add((JToken)(object)item.Report(me));
						}
					}
					output(new JObject
					{
						["traps"] = (JToken)(object)val2,
						["day"] = JToken.op_Implicit(((Object)(object)EnvMan.instance != (Object)null) ? EnvMan.instance.GetDay() : 0),
						["night"] = JToken.op_Implicit((Object)(object)EnvMan.instance != (Object)null && EnvMan.IsNight())
					});
					return (IEnumerator)null;
				};
				method?.Invoke(null, new object[4] { "BirdTrap", "traps", "traps: every bird trap loaded: bait, bird, minutes to the next bird, open sky, owner", func });
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not add the traps command to Claude Tools: " + ex.Message));
			}
		}

		private void OnDestroy()
		{
			try
			{
				((object)_claudeTools)?.GetType().GetMethod("UnregisterAll", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, new object[1] { "BirdTrap" });
			}
			catch
			{
			}
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Unregister();
			Synced?.Dispose();
			Translations.Unload();
		}

		internal static void Register(ZNetScene scene)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			GameObject prefab = scene.GetPrefab("piece_chest_wood");
			GameObject prefab2 = scene.GetPrefab("Hammer");
			GameObject prefab3 = scene.GetPrefab("piece_workbench");
			if ((Object)(object)prefab == (Object)null || (Object)(object)prefab2 == (Object)null)
			{
				Debug.LogWarning((object)"BirdTrap: chest or hammer prefab not found");
				return;
			}
			if ((Object)(object)_prefab == (Object)null)
			{
				_holder = new GameObject("BirdTrapPrefabs");
				_holder.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)_holder);
				try
				{
					Look.Harvest(scene, prefab.GetComponentInChildren<Renderer>(true).sharedMaterial);
				}
				catch (Exception ex)
				{
					Debug.LogWarning((object)("BirdTrap: could not take the game's materials, the trap looks plain: " + ex.Message));
				}
				Container component = prefab.GetComponent<Container>();
				DoorShut = (((Object)(object)component != (Object)null) ? component.m_closeEffects : null);
				DoorOpen = (((Object)(object)component != (Object)null) ? component.m_openEffects : null);
				_prefab = Make(prefab, ((Object)(object)prefab3 != (Object)null) ? prefab3.GetComponent<CraftingStation>() : null);
			}
			Dictionary<int, GameObject> dictionary = (Dictionary<int, GameObject>)AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs").GetValue(scene);
			PieceTable buildPieces = prefab2.GetComponent<ItemDrop>().m_itemData.m_shared.m_buildPieces;
			if (!scene.m_prefabs.Contains(_prefab))
			{
				scene.m_prefabs.Add(_prefab);
			}
			dictionary[StringExtensionMethods.GetStableHashCode(((Object)_prefab).name)] = _prefab;
			buildPieces.m_pieces.RemoveAll((GameObject p) => (Object)(object)p == (Object)null);
			if (!buildPieces.m_pieces.Contains(_prefab))
			{
				buildPieces.m_pieces.Add(_prefab);
			}
			_table = buildPieces;
			Synced.NeedsServer(_prefab);
			RefreshPlaced();
		}

		private static void RefreshPlaced()
		{
			int num = 0;
			ZNetView[] array = Object.FindObjectsByType<ZNetView>((FindObjectsSortMode)0);
			foreach (ZNetView val in array)
			{
				if ((Object)(object)val == (Object)null || val.GetZDO() == null || !((Object)((Component)val).gameObject).name.StartsWith("piece_birdtrap"))
				{
					continue;
				}
				MonoBehaviour[] components = ((Component)val).GetComponents<MonoBehaviour>();
				foreach (MonoBehaviour val2 in components)
				{
					if ((Object)(object)val2 != (Object)null && ((object)val2).GetType().Name == "TrapPiece" && ((object)val2).GetType() != typeof(TrapPiece))
					{
						Object.DestroyImmediate((Object)(object)val2);
					}
				}
				if ((Object)(object)((Component)val).GetComponent<TrapPiece>() == (Object)null)
				{
					((Component)val).gameObject.AddComponent<TrapPiece>();
					num++;
				}
			}
			if (num > 0)
			{
				Debug.Log((object)string.Format("[{0}] refreshed {1} trap(s) already built", "BirdTrap", num));
			}
		}

		internal static void ApplyCost()
		{
			Piece val = (((Object)(object)_prefab != (Object)null) ? _prefab.GetComponent<Piece>() : null);
			if ((Object)(object)val != (Object)null)
			{
				Costs.Apply(val, Cost.Value, Log);
			}
		}

		private static GameObject Make(GameObject source, CraftingStation workbench)
		{
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(source, _holder.transform);
			((Object)val).name = "piece_birdtrap";
			Container component = val.GetComponent<Container>();
			if ((Object)(object)component != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component);
			}
			int num = LayerMask.NameToLayer("piece");
			if (num < 0)
			{
				num = val.layer;
			}
			Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				val2.enabled = false;
			}
			Collider[] componentsInChildren2 = val.GetComponentsInChildren<Collider>(true);
			foreach (Collider val3 in componentsInChildren2)
			{
				Object.DestroyImmediate((Object)(object)val3);
			}
			GameObject val4 = new GameObject("Hitbox")
			{
				layer = num
			};
			val4.transform.SetParent(val.transform, false);
			BoxCollider val5 = val4.AddComponent<BoxCollider>();
			val5.center = new Vector3(0f, 0.42f, 0f);
			val5.size = new Vector3(0.92f, 0.84f, 0.66f);
			try
			{
				ModelBuilder.Build(val.transform, ModelData.Parts, val.layer);
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("BirdTrap: could not build the trap's model: " + ex.Message));
			}
			Piece component2 = val.GetComponent<Piece>();
			component2.m_name = "$birdtrap_piece";
			component2.m_description = "$birdtrap_piece_desc";
			component2.m_category = (PieceCategory)0;
			component2.m_usage = (UsageTagFlags)1;
			component2.m_craftingStation = workbench;
			if (!Costs.Apply(component2, Cost.Value, Log) && !Costs.Apply(component2, "Wood:8, LeatherScraps:2", Log))
			{
				component2.m_resources = source.GetComponent<Piece>().m_resources;
			}
			try
			{
				component2.m_icon = Icon.Make(val, (Vector3?)new Vector3(0.55f, 0.42f, -1f), (Action<GameObject>)delegate(GameObject copy)
				{
					//IL_0023: Unknown result type (might be due to invalid IL or missing references)
					//IL_003d: Unknown result type (might be due to invalid IL or missing references)
					Transform[] componentsInChildren3 = copy.GetComponentsInChildren<Transform>(true);
					foreach (Transform val6 in componentsInChildren3)
					{
						if (((Object)val6).name == "bird")
						{
							val6.localPosition = TrapPiece.PerchPos;
							val6.localRotation = Quaternion.Euler(0f, 205f, 0f);
						}
					}
				}, "icon.png");
			}
			catch (Exception ex2)
			{
				Debug.LogWarning((object)("BirdTrap: could not draw the build-menu picture: " + ex2.Message));
			}
			val.AddComponent<TrapPiece>();
			return val;
		}

		internal static void Unregister()
		{
			if ((Object)(object)_prefab == (Object)null)
			{
				return;
			}
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				ZNetScene.instance.m_prefabs.Remove(_prefab);
				Dictionary<int, GameObject> dictionary = (Dictionary<int, GameObject>)AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs").GetValue(ZNetScene.instance);
				int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)_prefab).name);
				if (dictionary.TryGetValue(stableHashCode, out var value) && (Object)(object)value == (Object)(object)_prefab)
				{
					dictionary.Remove(stableHashCode);
				}
			}
			GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab("Hammer") : null);
			(_table ?? (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>().m_itemData.m_shared.m_buildPieces : null))?.m_pieces.RemoveAll((GameObject p) => (Object)(object)p == (Object)null || (Object)(object)p == (Object)(object)_prefab);
			_table = null;
			_prefab = null;
			Object.Destroy((Object)(object)_holder);
			_holder = null;
			Look.Clear();
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	internal static class ZNetScene_Awake
	{
		private static void Postfix(ZNetScene __instance)
		{
			Plugin.Register(__instance);
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	internal static class ObjectDB_Awake
	{
		private static void Postfix()
		{
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				Plugin.Register(ZNetScene.instance);
			}
		}
	}
	public class TrapPiece : MonoBehaviour, Interactable, Hoverable
	{
		private class BaitAsk
		{
			public long To;

			public string[] Items;

			public float At;

			public bool Back;
		}

		private const string KeyBait = "bt_bait";

		private const string KeyKinds = "bt_kinds";

		private const string KeyNext = "bt_next";

		private const string KeyBird = "bt_bird";

		private const string KeyWhy = "bt_why";

		private const string KeyFrom = "bt_from";

		private const float Lift = 0.3f;

		internal static readonly Vector3 PerchPos = new Vector3(0.16f, 0.85f, -0.295f);

		internal const float PerchYaw = 205f;

		private static readonly string[] Baits = new string[9] { "Raspberry", "Blueberries", "Cloudberry", "BeechSeeds", "BirchSeeds", "Barley", "CarrotSeeds", "TurnipSeeds", "OnionSeeds" };

		internal static readonly HashSet<TrapPiece> All = new HashSet<TrapPiece>();

		private ZNetView _nview;

		private Transform _door;

		private Transform _prop;

		private Transform _bait;

		private Transform _bird;

		private Transform _birdBody;

		private Vector3 _doorUp;

		private Vector3 _birdHome;

		private Quaternion _birdTurn;

		private float _doorAt = 1f;

		private bool _hadBird;

		private bool _seen;

		private float _nextThink;

		private float _pluckAskedAt = -9f;

		private WearNTear _wnt;

		private readonly List<BaitAsk> _asks = new List<BaitAsk>();

		private const float AnswerWait = 5f;

		private const string RpcBait = "bt_Bait";

		private const string RpcBaitTaken = "bt_BaitTaken";

		private const string RpcPluck = "bt_Pluck";

		private const string RpcPlucked = "bt_Plucked";

		private static readonly string[] Rpcs = new string[4] { "bt_Bait", "bt_BaitTaken", "bt_Pluck", "bt_Plucked" };

		private ZDO Zdo
		{
			get
			{
				if (!((Object)(object)_nview != (Object)null) || !_nview.IsValid())
				{
					return null;
				}
				return _nview.GetZDO();
			}
		}

		private int Bait
		{
			get
			{
				ZDO zdo = Zdo;
				if (zdo == null)
				{
					return 0;
				}
				return zdo.GetInt("bt_bait", 0);
			}
		}

		private bool HasBird
		{
			get
			{
				ZDO zdo = Zdo;
				if (zdo == null)
				{
					return false;
				}
				return zdo.GetBool("bt_bird", false);
			}
		}

		private static double Now
		{
			get
			{
				if (!((Object)(object)ZNet.instance != (Object)null))
				{
					return 0.0;
				}
				return ZNet.instance.GetTimeSeconds();
			}
		}

		private void OnDestroy()
		{
			All.Remove(this);
			if ((Object)(object)_nview != (Object)null)
			{
				string[] rpcs = Rpcs;
				foreach (string text in rpcs)
				{
					_nview.Unregister(text);
				}
			}
			if ((Object)(object)_wnt != (Object)null)
			{
				WearNTear wnt = _wnt;
				wnt.m_onDestroyed = (Action)Delegate.Remove(wnt.m_onDestroyed, new Action(OnPieceDestroyed));
			}
			foreach (BaitAsk ask in _asks)
			{
				if (!ask.Back)
				{
					GiveBack(ask, 0);
				}
			}
			_asks.Clear();
		}

		private void Awake()
		{
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			_nview = ((Component)this).GetComponent<ZNetView>();
			if ((Object)(object)_nview != (Object)null && _nview.GetZDO() != null)
			{
				All.Add(this);
				string[] rpcs = Rpcs;
				foreach (string text in rpcs)
				{
					_nview.Unregister(text);
				}
				_nview.Register<string>("bt_Bait", (Action<long, string>)RPC_Bait);
				_nview.Register<int>("bt_BaitTaken", (Action<long, int>)RPC_BaitTaken);
				_nview.Register("bt_Pluck", (Action<long>)RPC_Pluck);
				_nview.Register<int>("bt_Plucked", (Action<long, int>)RPC_Plucked);
				_wnt = ((Component)this).GetComponent<WearNTear>();
				if ((Object)(object)_wnt != (Object)null)
				{
					WearNTear wnt = _wnt;
					wnt.m_onDestroyed = (Action)Delegate.Combine(wnt.m_onDestroyed, new Action(OnPieceDestroyed));
				}
			}
			Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				switch (((Object)val).name)
				{
				case "door":
					_door = val;
					break;
				case "prop":
					_prop = val;
					break;
				case "bait":
					_bait = val;
					break;
				case "bird":
					_bird = val;
					break;
				case "birdBody":
					_birdBody = val;
					break;
				}
			}
			if ((Object)(object)_door != (Object)null)
			{
				_doorUp = _door.localPosition;
			}
			if ((Object)(object)_bird != (Object)null)
			{
				_birdHome = _bird.localPosition;
				_birdTurn = _bird.localRotation;
			}
		}

		private void Update()
		{
			ZDO zdo = Zdo;
			if (zdo != null)
			{
				if (_asks.Count > 0)
				{
					CheckAsks();
				}
				if (zdo.IsOwner() && Time.time >= _nextThink)
				{
					_nextThink = Time.time + 1f;
					Think(zdo);
				}
				Show(zdo);
			}
		}

		private void Think(ZDO zdo)
		{
			if (zdo.GetBool("bt_bird", false))
			{
				return;
			}
			int num = zdo.GetInt("bt_bait", 0);
			double num2 = zdo.GetLong("bt_next", 0L);
			if (num <= 0)
			{
				if (num2 != 0.0)
				{
					zdo.Set("bt_next", 0L);
				}
				return;
			}
			if (num2 == 0.0)
			{
				zdo.Set("bt_next", (long)(Now + Wait()));
				zdo.Set("bt_from", (long)Now);
				return;
			}
			bool flag = (Object)(object)EnvMan.instance != (Object)null && !EnvMan.IsNight() && EnvMan.instance.GetDay(Now) > EnvMan.instance.GetDay((double)zdo.GetLong("bt_from", 0L));
			if (Now < num2 && !flag)
			{
				return;
			}
			string text = null;
			if (Plugin.NeedsSky.Value && !OpenSky())
			{
				text = "roof";
			}
			else if (Plugin.RestsAtNight.Value && (Object)(object)EnvMan.instance != (Object)null && EnvMan.IsNight())
			{
				text = "night";
			}
			if (text != null)
			{
				zdo.Set("bt_next", (long)(Now + 60.0));
				if (zdo.GetString("bt_why", "") != text)
				{
					zdo.Set("bt_why", text);
				}
				return;
			}
			zdo.Set("bt_why", "");
			zdo.Set("bt_bait", num - 1);
			List<string> list = Kinds(zdo);
			if (list.Count >= num && list.Count > 0)
			{
				list.RemoveAt(0);
				zdo.Set("bt_kinds", string.Join(",", list.ToArray()));
			}
			zdo.Set("bt_next", 0L);
			zdo.Set("bt_bird", true);
		}

		internal JObject Report(Vector3 from)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			//IL_0023: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			ZDO zdo = Zdo;
			JObject val = new JObject();
			val["position"] = (JToken)new JArray(new object[3]
			{
				Math.Round(((Component)this).transform.position.x, 1),
				Math.Round(((Component)this).transform.position.y, 1),
				Math.Round(((Component)this).transform.position.z, 1)
			});
			val["distance"] = JToken.op_Implicit(Math.Round(Vector3.Distance(((Component)this).transform.position, from), 1));
			val["openSky"] = JToken.op_Implicit(OpenSky());
			JObject val2 = val;
			if (zdo == null)
			{
				return val2;
			}
			val2["owner"] = JToken.op_Implicit(zdo.IsOwner() ? "this game" : zdo.GetOwner().ToString());
			val2["bait"] = JToken.op_Implicit(zdo.GetInt("bt_bait", 0));
			val2["bird"] = JToken.op_Implicit(zdo.GetBool("bt_bird", false));
			long num = zdo.GetLong("bt_next", 0L);
			long num2 = zdo.GetLong("bt_from", 0L);
			val2["nextInMinutes"] = ((num == 0L) ? null : JToken.op_Implicit(Math.Round(((double)num - Now) / 60.0, 1)));
			val2["setOnDay"] = ((num2 == 0L || (Object)(object)EnvMan.instance == (Object)null) ? null : JToken.op_Implicit(EnvMan.instance.GetDay((double)num2)));
			val2["why"] = JToken.op_Implicit(zdo.GetString("bt_why", ""));
			return val2;
		}

		private static double Wait()
		{
			float num = Mathf.Min(Plugin.MinMinutes.Value, Plugin.MaxMinutes.Value);
			float num2 = Mathf.Max(Plugin.MinMinutes.Value, Plugin.MaxMinutes.Value);
			return (double)Random.Range(num, num2) * 60.0;
		}

		private bool OpenSky()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			int mask = LayerMask.GetMask(new string[2] { "piece", "piece_nonsolid" });
			RaycastHit[] array = Physics.RaycastAll(((Component)this).transform.position + Vector3.up * 1f, Vector3.up, 40f, mask);
			for (int i = 0; i < array.Length; i++)
			{
				RaycastHit val = array[i];
				if ((Object)(object)((RaycastHit)(ref val)).collider != (Object)null && !((Component)((RaycastHit)(ref val)).collider).transform.IsChildOf(((Component)this).transform))
				{
					return false;
				}
			}
			return true;
		}

		private void Show(ZDO zdo)
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			bool flag = zdo.GetBool("bt_bird", false);
			int num = zdo.GetInt("bt_bait", 0);
			if (!_seen)
			{
				_seen = true;
				_hadBird = flag;
				_doorAt = (flag ? 0f : 1f);
			}
			if (flag != _hadBird)
			{
				_hadBird = flag;
				Effect(flag ? Plugin.DoorShut : Plugin.DoorOpen);
			}
			_doorAt = (flag ? Mathf.MoveTowards(_doorAt, 0f, Time.deltaTime / 0.12f) : Mathf.MoveTowards(_doorAt, 1f, Time.deltaTime / 0.7f));
			if ((Object)(object)_door != (Object)null)
			{
				_door.localPosition = _doorUp - new Vector3(0f, 0.3f * (1f - _doorAt), 0f);
			}
			if ((Object)(object)_prop != (Object)null && ((Component)_prop).gameObject.activeSelf != (!flag && _doorAt > 0.99f))
			{
				((Component)_prop).gameObject.SetActive(!flag && _doorAt > 0.99f);
			}
			if ((Object)(object)_bait != (Object)null && ((Component)_bait).gameObject.activeSelf != num > 0)
			{
				((Component)_bait).gameObject.SetActive(num > 0);
			}
			if ((Object)(object)_bird != (Object)null)
			{
				if (((Component)_bird).gameObject.activeSelf != flag)
				{
					((Component)_bird).gameObject.SetActive(flag);
				}
				if (flag && (Object)(object)_birdBody != (Object)null)
				{
					float num2 = Time.time + (float)((Object)this).GetInstanceID() * 0.37f;
					float num3 = Mathf.Max(0f, Mathf.Sin(num2 * 2.3f)) * Mathf.Max(0f, Mathf.Sin(num2 * 0.7f)) * 0.025f;
					_birdBody.localPosition = new Vector3(0f, num3, 0f);
					_bird.localRotation = _birdTurn * Quaternion.Euler(0f, Mathf.Sin(num2 * 0.9f) * 25f, 0f);
					_birdBody.localRotation = Quaternion.Euler(Mathf.Max(0f, Mathf.Sin(num2 * 3.1f + 1f)) * 18f, 0f, 0f);
				}
			}
		}

		private void Effect(EffectList fx)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (fx != null)
				{
					fx.Create(((Component)this).transform.position + Vector3.up * 0.4f, ((Component)this).transform.rotation, (Transform)null, 1f, -1, default(ZDOID));
				}
			}
			catch
			{
			}
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if (!hold)
			{
				Player val = (Player)(object)((user is Player) ? user : null);
				if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer))
				{
					if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
					{
						return true;
					}
					ZDO zdo = Zdo;
					if (zdo == null)
					{
						return false;
					}
					if (zdo.GetBool("bt_bird", false))
					{
						if (Time.time - _pluckAskedAt > 1f)
						{
							_pluckAskedAt = Time.time;
							_nview.InvokeRPC("bt_Pluck", Array.Empty<object>());
						}
						return true;
					}
					int num = zdo.GetInt("bt_bait", 0);
					int value = Plugin.MaxBait.Value;
					if (num >= value)
					{
						((Character)val).Message((MessageType)2, Translations.T("birdtrap_full"), 0, (Sprite)null, false);
						return true;
					}
					if (_asks.Exists((BaitAsk a) => !a.Back))
					{
						return true;
					}
					Inventory inventory = ((Humanoid)val).GetInventory();
					List<string> list = new List<string>();
					while (num + list.Count < value)
					{
						ItemData val2 = ((IEnumerable<ItemData>)inventory.GetAllItems()).FirstOrDefault((Func<ItemData, bool>)IsBait);
						if (val2 == null)
						{
							break;
						}
						list.Add(((Object)val2.m_dropPrefab).name);
						inventory.RemoveItem(val2, 1);
						if (!alt)
						{
							break;
						}
					}
					if (list.Count == 0)
					{
						((Character)val).Message((MessageType)2, Translations.T("birdtrap_need_bait"), 0, (Sprite)null, false);
						return true;
					}
					_asks.Add(new BaitAsk
					{
						To = zdo.GetOwner(),
						Items = list.ToArray(),
						At = Time.time
					});
					_nview.InvokeRPC("bt_Bait", new object[1] { string.Join(",", list.ToArray()) });
					return true;
				}
			}
			return false;
		}

		private void CheckAsks()
		{
			foreach (BaitAsk ask in _asks)
			{
				if (!ask.Back && Time.time - ask.At > 5f)
				{
					GiveBack(ask, 0);
					ask.Back = true;
				}
			}
			_asks.RemoveAll((BaitAsk a) => a.Back && Time.time - a.At > 120f);
		}

		private static void GiveBack(BaitAsk ask, int taken)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			for (int i = taken; i < ask.Items.Length; i++)
			{
				GameObject prefab = ZNetScene.instance.GetPrefab(ask.Items[i]);
				if (!((Object)(object)prefab == (Object)null))
				{
					if (((Humanoid)localPlayer).GetInventory().CanAddItem(prefab, 1))
					{
						((Humanoid)localPlayer).GetInventory().AddItem(prefab, 1);
					}
					else
					{
						Object.Instantiate<GameObject>(prefab, ((Component)localPlayer).transform.position + Vector3.up, Quaternion.identity);
					}
				}
			}
		}

		private static void TakeAgain(Player player, BaitAsk ask, int taken)
		{
			Inventory inventory = ((Humanoid)player).GetInventory();
			for (int i = 0; i < taken; i++)
			{
				string kind = ask.Items[i];
				ItemData val = ((IEnumerable<ItemData>)inventory.GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData x) => (Object)(object)x.m_dropPrefab != (Object)null && ((Object)x.m_dropPrefab).name == kind)) ?? ((IEnumerable<ItemData>)inventory.GetAllItems()).FirstOrDefault((Func<ItemData, bool>)IsBait);
				if (val != null)
				{
					inventory.RemoveItem(val, 1);
					continue;
				}
				break;
			}
		}

		private static List<string> Kinds(ZDO zdo)
		{
			return zdo.GetString("bt_kinds", "").Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
		}

		private void OnPieceDestroyed()
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			ZDO zdo = Zdo;
			if (zdo == null || !_nview.IsOwner() || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			int num = zdo.GetInt("bt_bait", 0);
			List<string> list = Kinds(zdo);
			foreach (string item in list.Skip(Mathf.Max(0, list.Count - num)))
			{
				GameObject prefab = ZNetScene.instance.GetPrefab(item);
				if (!((Object)(object)prefab == (Object)null))
				{
					ItemDrop.OnCreateNew(Object.Instantiate<GameObject>(prefab, ((Component)this).transform.position + Vector3.up * 0.5f + Random.insideUnitSphere * 0.3f, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f)), false);
				}
			}
			zdo.Set("bt_bait", 0);
			zdo.Set("bt_kinds", "");
		}

		private void RPC_Bait(long sender, string items)
		{
			ZDO zdo = Zdo;
			if (zdo == null || !_nview.IsOwner())
			{
				_nview.InvokeRPC(sender, "bt_BaitTaken", new object[1] { 0 });
				return;
			}
			string[] array = (items ?? "").Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries).TakeWhile((string n) => Baits.Contains(n)).ToArray();
			int num = zdo.GetInt("bt_bait", 0);
			int num2 = Mathf.Clamp(Plugin.MaxBait.Value - num, 0, array.Length);
			if (zdo.GetBool("bt_bird", false))
			{
				num2 = 0;
			}
			if (num2 > 0)
			{
				zdo.Set("bt_bait", num + num2);
				zdo.Set("bt_kinds", string.Join(",", Kinds(zdo).Concat(array.Take(num2)).ToArray()));
			}
			_nview.InvokeRPC(sender, "bt_BaitTaken", new object[1] { num2 });
		}

		private void RPC_BaitTaken(long sender, int taken)
		{
			Player localPlayer = Player.m_localPlayer;
			BaitAsk baitAsk = _asks.Find((BaitAsk a) => a.To == sender) ?? ((_asks.Count > 0) ? _asks[0] : null);
			if ((Object)(object)localPlayer == (Object)null || baitAsk == null)
			{
				return;
			}
			_asks.Remove(baitAsk);
			taken = Mathf.Clamp(taken, 0, baitAsk.Items.Length);
			if (baitAsk.Back)
			{
				if (taken == 0)
				{
					return;
				}
				TakeAgain(localPlayer, baitAsk, taken);
			}
			else
			{
				GiveBack(baitAsk, taken);
			}
			string text = baitAsk.Items[0];
			ZDO zdo = Zdo;
			int num = ((zdo != null) ? zdo.GetInt("bt_bait", 0) : taken);
			int value = Plugin.MaxBait.Value;
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(text) : null);
			string text2 = (((Object)(object)val != (Object)null) ? Localization.instance.Localize(val.GetComponent<ItemDrop>().m_itemData.m_shared.m_name) : text);
			((Character)localPlayer).Message((MessageType)2, (taken > 0) ? Translations.T("birdtrap_baited", text2, Mathf.Max(num, taken), value) : Translations.T("birdtrap_full"), 0, (Sprite)null, false);
		}

		private void RPC_Pluck(long sender)
		{
			ZDO zdo = Zdo;
			if (zdo == null || !_nview.IsOwner() || !zdo.GetBool("bt_bird", false))
			{
				_nview.InvokeRPC(sender, "bt_Plucked", new object[1] { 0 });
				return;
			}
			zdo.Set("bt_bird", false);
			int num = Random.Range(Mathf.Min(Plugin.MinFeathers.Value, Plugin.MaxFeathers.Value), Mathf.Max(Plugin.MinFeathers.Value, Plugin.MaxFeathers.Value) + 1);
			_nview.InvokeRPC(sender, "bt_Plucked", new object[1] { Mathf.Max(1, num) });
		}

		private void RPC_Plucked(long sender, int n)
		{
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				if (n <= 0)
				{
					((Character)localPlayer).Message((MessageType)2, Translations.T("birdtrap_gone"), 0, (Sprite)null, false);
				}
				else
				{
					Pluck(localPlayer, n);
				}
			}
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			if (IsBait(item))
			{
				Player val = (Player)(object)((user is Player) ? user : null);
				if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer) && !HasBird)
				{
					return Interact(user, hold: false, alt: false);
				}
			}
			return false;
		}

		public string GetHoverName()
		{
			return Translations.T("birdtrap_piece");
		}

		public float GetHoverOffset()
		{
			return 0f;
		}

		public string GetHoverText()
		{
			ZDO zdo = Zdo;
			if (zdo == null)
			{
				return Translations.T("birdtrap_piece");
			}
			int num = zdo.GetInt("bt_bait", 0);
			int value = Plugin.MaxBait.Value;
			string text = Translations.T("birdtrap_piece");
			if (zdo.GetBool("bt_bird", false))
			{
				text = text + "\n<color=#9BE37A>" + Translations.T("birdtrap_caught") + "</color>\n[<color=yellow><b>$KEY_Use</b></color>] " + Translations.T("birdtrap_hover_pluck");
			}
			else
			{
				string text2;
				if (num <= 0)
				{
					text2 = Translations.T("birdtrap_no_bait");
				}
				else
				{
					string text3 = zdo.GetString("bt_why", "");
					double num2 = (double)zdo.GetLong("bt_next", 0L) - (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : 0.0);
					text2 = ((text3 == "roof") ? ("<color=#E8B04B>" + Translations.T("birdtrap_roof") + "</color>") : ((text3 == "night") ? Translations.T("birdtrap_night") : ((num2 > 60.0) ? Translations.T("birdtrap_soon", Mathf.CeilToInt((float)(num2 / 60.0))) : Translations.T("birdtrap_any_moment"))));
				}
				text = text + "\n" + Translations.T("birdtrap_bait_state", num, value, text2);
				if (num < value)
				{
					text = text + "\n[<color=yellow><b>$KEY_Use</b></color>] " + Translations.T("birdtrap_hover_add") + "\n[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] " + Translations.T("birdtrap_hover_fill");
				}
			}
			return Localization.instance.Localize(text);
		}

		private static bool IsBait(ItemData i)
		{
			if ((Object)(object)i?.m_dropPrefab != (Object)null)
			{
				return Baits.Contains(((Object)i.m_dropPrefab).name);
			}
			return false;
		}

		private void Pluck(Player player, int n)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("Feathers") : null);
			if ((Object)(object)val != (Object)null)
			{
				Inventory inventory = ((Humanoid)player).GetInventory();
				if (inventory.CanAddItem(val, n))
				{
					inventory.AddItem(val, n);
				}
				else
				{
					Object.Instantiate<GameObject>(val, ((Component)this).transform.position + Vector3.up * 0.9f, Quaternion.identity).GetComponent<ItemDrop>().SetStack(n);
				}
			}
			((Character)player).Message((MessageType)2, Translations.T("birdtrap_plucked", n), 0, (Sprite)null, false);
			FlyAway();
		}

		private void FlyAway()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_bird == (Object)null))
			{
				GameObject val = Object.Instantiate<GameObject>(((Component)_bird).gameObject, _bird.parent);
				val.SetActive(true);
				val.transform.localPosition = _birdHome + Vector3.up * 0.5f;
				val.AddComponent<Flutter>();
			}
		}
	}
	internal class Flutter : MonoBehaviour
	{
		private float _t;

		private Vector3 _dir;

		private Transform _wingL;

		private Transform _wingR;

		private void Start()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			_dir = (((Object)(object)((Component)this).transform.parent != (Object)null) ? ((Component)this).transform.parent.rotation : Quaternion.identity) * new Vector3(Random.Range(-0.4f, 0.4f), 0f, -1f);
			Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>();
			foreach (Transform val in componentsInChildren)
			{
				if (((Object)val).name == "wing")
				{
					if ((Object)(object)_wingL == (Object)null)
					{
						_wingL = val;
					}
					else
					{
						_wingR = val;
					}
				}
			}
			((Component)this).transform.SetParent((Transform)null, true);
		}

		private void Update()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			_t += Time.deltaTime;
			Transform transform = ((Component)this).transform;
			transform.position += (((Vector3)(ref _dir)).normalized * 3.5f + Vector3.up * (2.5f + _t * 2f)) * Time.deltaTime;
			((Component)this).transform.rotation = Quaternion.LookRotation(-((Vector3)(ref _dir)).normalized, Vector3.up) * Quaternion.Euler(15f, 0f, 0f);
			float num = Mathf.Sin(_t * 40f) * 60f;
			if ((Object)(object)_wingL != (Object)null)
			{
				_wingL.localRotation = Quaternion.Euler(-14f, 0f, num);
			}
			if ((Object)(object)_wingR != (Object)null)
			{
				_wingR.localRotation = Quaternion.Euler(-14f, 0f, 0f - num);
			}
			if (_t > 2.5f)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}
	}
}
namespace DHack.Shared
{
	internal static class Migration
	{
		private sealed class Notice : MonoBehaviour
		{
			public string Text;

			private float _next;

			private void Update()
			{
				if (!(Time.unscaledTime < _next) && !((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)MessageHud.instance == (Object)null))
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, Text, 0, (Sprite)null, false);
					_next = Time.unscaledTime + 60f;
				}
			}
		}

		public static void FromOldGuid(BaseUnityPlugin plugin, string oldGuid)
		{
			BepInPlugin metadata = MetadataHelper.GetMetadata((object)plugin);
			string text = ((metadata != null) ? metadata.GUID : null);
			if (string.IsNullOrEmpty(oldGuid) || string.IsNullOrEmpty(text) || oldGuid == text)
			{
				return;
			}
			ManualLogSource val = Logger.CreateLogSource(text);
			try
			{
				bool flag = false;
				if (Directory.Exists(Paths.ConfigPath))
				{
					string[] files = Directory.GetFiles(Paths.ConfigPath, oldGuid + ".*");
					foreach (string text2 in files)
					{
						string fileName = Path.GetFileName(text2);
						if (!fileName.EndsWith(".cfg") && !fileName.EndsWith(".json") && !fileName.EndsWith(".txt"))
						{
							continue;
						}
						string text3 = Path.Combine(Paths.ConfigPath, text + fileName.Substring(oldGuid.Length));
						if (!File.Exists(text3))
						{
							File.Copy(text2, text3);
							val.LogInfo((object)("Settings moved over from " + fileName + " (the mod's id is now " + text + "; the old file is kept as a backup)"));
							if (fileName == oldGuid + ".cfg")
							{
								flag = true;
							}
						}
					}
				}
				if (flag)
				{
					plugin.Config.Reload();
				}
			}
			catch (Exception ex)
			{
				val.LogWarning((object)("Couldn't move the settings over from " + oldGuid + ".cfg: " + ex.Message));
			}
			finally
			{
				Logger.Sources.Remove((ILogSource)(object)val);
			}
			((MonoBehaviour)plugin).StartCoroutine(StandDownIfTwin(plugin, oldGuid));
		}

		private static IEnumerator StandDownIfTwin(BaseUnityPlugin plugin, string oldGuid)
		{
			yield return null;
			yield return null;
			if (!((Object)(object)plugin == (Object)null) && Chainloader.PluginInfos.TryGetValue(oldGuid, out var value) && !((Object)(object)value.Instance == (Object)null) && !((Object)(object)value.Instance == (Object)(object)plugin))
			{
				BepInPlugin metadata = MetadataHelper.GetMetadata((object)plugin);
				string text = ((metadata != null) ? metadata.Name : null) ?? oldGuid;
				string text2 = (string.IsNullOrEmpty(value.Location) ? "an older copy" : value.Location);
				string text3 = text + ": two copies are installed, an old one (" + text2 + ") and this one. Both would run and do everything twice, so this one stands down. Delete the old copy, then restart the game.";
				Debug.LogError((object)("[" + text + "] " + text3));
				Object.Destroy((Object)(object)plugin);
				GameObject val = new GameObject("Migration_TwoCopies_" + text);
				Object.DontDestroyOnLoad((Object)(object)val);
				val.AddComponent<Notice>().Text = text3;
			}
		}
	}
	internal static class Translations
	{
		private sealed class Blank
		{
			public string Tag;

			public Func<string> Value;

			public Action Unhook;
		}

		public static readonly string[] Shipped = new string[9] { "English", "Russian", "German", "Chinese", "Portuguese_Brazilian", "Spanish", "French", "Polish", "Turkish" };

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

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

		private static string _overrideDir;

		private static bool _hooked;

		private static readonly MethodInfo AddWord = AccessTools.Method(typeof(Localization), "AddWord", (Type[])null, (Type[])null);

		private static readonly FieldInfo Cache = AccessTools.Field(typeof(Localization), "m_cache");

		private static readonly FieldInfo GameWords = AccessTools.Field(typeof(Localization), "m_translations");

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

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

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

		private static readonly HashSet<string> _runtimeGiven = new HashSet<string>();

		private static readonly Dictionary<string, List<Blank>> Fills = new Dictionary<string, List<Blank>>();

		public static void Load(BaseUnityPlugin plugin)
		{
			Languages.Clear();
			Assembly assembly = ((object)plugin).GetType().Assembly;
			foreach (string item in from n in assembly.GetManifestResourceNames()
				where n.StartsWith("translations/") && n.EndsWith(".json")
				select n)
			{
				using StreamReader streamReader = new StreamReader(assembly.GetManifestResourceStream(item));
				Languages[Path.GetFileNameWithoutExtension(item.Substring("translations/".Length))] = Parse(streamReader.ReadToEnd());
			}
			_english = (Languages.TryGetValue("English", out var value) ? value : new Dictionary<string, string>());
			_overrideDir = Path.Combine(Paths.ConfigPath, "translations", plugin.Info.Metadata.GUID);
			if (!_hooked)
			{
				Localization.OnLanguageChange = (Action)Delegate.Combine(Localization.OnLanguageChange, new Action(Apply));
				_hooked = true;
			}
			Apply();
		}

		public static void Unload()
		{
			if (_hooked)
			{
				Localization.OnLanguageChange = (Action)Delegate.Remove(Localization.OnLanguageChange, new Action(Apply));
				_hooked = false;
			}
			foreach (List<Blank> value2 in Fills.Values)
			{
				foreach (Blank item in value2)
				{
					item.Unhook?.Invoke();
				}
			}
			Fills.Clear();
			Runtime.Clear();
			Localization val = ((_runtimeGiven.Count > 0) ? Localization.instance : null);
			if (val != null && AddWord != null)
			{
				Dictionary<string, string> dictionary = GameWords?.GetValue(val) as Dictionary<string, string>;
				foreach (string item2 in _runtimeGiven)
				{
					if (_files.TryGetValue(item2, out var value))
					{
						AddWord.Invoke(val, new object[2] { item2, value });
					}
					else
					{
						dictionary?.Remove(item2);
					}
				}
				EvictCache(val);
			}
			_runtimeGiven.Clear();
		}

		public static string T(string key, params object[] args)
		{
			string text = ((Localization.instance != null) ? Localization.instance.Localize("$" + key) : null);
			if (string.IsNullOrEmpty(text) || text == "[" + key + "]")
			{
				text = (_english.TryGetValue(key, out var value) ? FillIn(key, value) : key);
			}
			if (args == null || args.Length == 0)
			{
				return text;
			}
			try
			{
				return string.Format(text, args);
			}
			catch (FormatException)
			{
				string value2;
				return _english.TryGetValue(key, out value2) ? SafeFormat(FillIn(key, value2), args) : text;
			}
		}

		private static string SafeFormat(string text, object[] args)
		{
			try
			{
				return string.Format(text, args);
			}
			catch (FormatException)
			{
				return text;
			}
		}

		public static void Fill<TValue>(string key, string placeholder, ConfigEntry<TValue> setting, Func<TValue, string> format = null)
		{
			if (setting != null)
			{
				Fill(key, placeholder, () => (format == null) ? Text(setting.Value) : format(setting.Value), (ConfigEntryBase)setting);
			}
		}

		public static void Fill(string key, string placeholder, Func<string> value, params ConfigEntryBase[] settings)
		{
			if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(placeholder) || value == null)
			{
				return;
			}
			key = key.TrimStart(new char[1] { '$' });
			string tag = (placeholder.StartsWith("{") ? placeholder : ("{" + placeholder + "}"));
			if (!Fills.TryGetValue(key, out var value2))
			{
				value2 = (Fills[key] = new List<Blank>());
			}
			int num = value2.FindIndex((Blank b) => b.Tag == tag);
			if (num >= 0)
			{
				value2[num].Unhook?.Invoke();
				value2.RemoveAt(num);
			}
			Blank blank = new Blank
			{
				Tag = tag,
				Value = value
			};
			if (settings != null)
			{
				EventHandler changed = delegate
				{
					Show(key);
				};
				foreach (ConfigEntryBase setting in settings.Where((ConfigEntryBase s) => s != null).Distinct())
				{
					EventInfo ev = ((object)setting).GetType().GetEvent("SettingChanged");
					if (!(ev == null))
					{
						ev.AddEventHandler(setting, changed);
						blank.Unhook = (Action)Delegate.Combine(blank.Unhook, (Action)delegate
						{
							ev.RemoveEventHandler(setting, changed);
						});
					}
				}
			}
			value2.Add(blank);
			Show(key);
		}

		public static void Refresh()
		{
			Localization instance = Localization.instance;
			if (instance == null || AddWord == null)
			{
				return;
			}
			foreach (string key in Fills.Keys)
			{
				if (_given.TryGetValue(key, out var value))
				{
					AddWord.Invoke(instance, new object[2]
					{
						key,
						FillIn(key, value)
					});
				}
			}
			EvictCache(instance);
		}

		private static void Show(string key)
		{
			Localization instance = Localization.instance;
			if (instance != null && !(AddWord == null) && _given.TryGetValue(key, out var value))
			{
				AddWord.Invoke(instance, new object[2]
				{
					key,
					FillIn(key, value)
				});
				EvictCache(instance);
			}
		}

		private static string FillIn(string key, string text)
		{
			if (text == null || !Fills.TryGetValue(key, out var value))
			{
				return text;
			}
			foreach (Blank item in value)
			{
				if (text.IndexOf(item.Tag, StringComparison.Ordinal) >= 0)
				{
					try
					{
						text = text.Replace(item.Tag, item.Value() ?? "");
					}
					catch (Exception ex)
					{
						Debug.LogWarning((object)("Translations: filling " + item.Tag + " in " + key + ": " + ex.Message));
					}
				}
			}
			return text;
		}

		private static string Text(object value)
		{
			object obj;
			if (!(value is IFormattable formattable))
			{
				obj = value?.ToString();
				if (obj == null)
				{
					return "";
				}
			}
			else
			{
				obj = formattable.ToString(null, CultureInfo.InvariantCulture);
			}
			return (string)obj;
		}

		public static void AddWords(string group, string language, IDictionary<string, string> words)
		{
			if (!string.IsNullOrEmpty(group) && !string.IsNullOrEmpty(language))
			{
				SetWords(group, language, words);
				Apply();
			}
		}

		public static void AddWords(string group, IDictionary<string, Dictionary<string, string>> languages)
		{
			if (string.IsNullOrEmpty(group))
			{
				return;
			}
			Runtime.Remove(group);
			if (languages != null)
			{
				foreach (KeyValuePair<string, Dictionary<string, string>> language in languages)
				{
					if (!string.IsNullOrEmpty(language.Key))
					{
						SetWords(group, language.Key, language.Value);
					}
				}
			}
			Apply();
		}

		public static void RemoveWords(string group)
		{
			if (group != null && Runtime.Remove(group))
			{
				Apply();
			}
		}

		public static Dictionary<string, string> ParseJson(string json)
		{
			if (!string.IsNullOrEmpty(json))
			{
				return Parse(json);
			}
			return new Dictionary<string, string>();
		}

		private static void SetWords(string group, string language, IDictionary<string, string> words)
		{
			if (!Runtime.TryGetValue(group, out var value))
			{
				value = (Runtime[group] = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase));
			}
			if (words == null || words.Count == 0)
			{
				value.Remove(language);
				return;
			}
			Dictionary<string, string> dictionary2 = new Dictionary<string, string>();
			foreach (KeyValuePair<string, string> word in words)
			{
				if (!string.IsNullOrEmpty(word.Key) && word.Value != null)
				{
					dictionary2[word.Key.TrimStart(new char[1] { '$' })] = word.Value;
				}
			}
			value[language] = dictionary2;
		}

		private static void AddRuntime(Dictionary<string, string> words, string language)
		{
			foreach (Dictionary<string, Dictionary<string, string>> value2 in Runtime.Values)
			{
				if (!value2.TryGetValue(language, out var value))
				{
					continue;
				}
				foreach (KeyValuePair<string, string> item in value)
				{
					words[item.Key] = item.Value;
				}
			}
		}

		private static void Apply()
		{
			Localization instance = Localization.instance;
			if (instance == null || AddWord == null)
			{
				return;
			}
			string selectedLanguage = instance.GetSelectedLanguage();
			Dictionary<string, string> dictionary = new Dictionary<string, string>(_english);
			Dictionary<string, string> dictionary2 = new Dictionary<string, string>(_english);
			AddRuntime(dictionary, "English");
			if (!string.Equals(selectedLanguage, "English", StringComparison.OrdinalIgnoreCase))
			{
				if (Languages.TryGetValue(selectedLanguage, out var value))
				{
					foreach (KeyValuePair<string, string> item in value)
					{
						dictionary[item.Key] = item.Value;
						dictionary2[item.Key] = item.Value;
					}
				}
				AddRuntime(dictionary, selectedLanguage);
			}
			try
			{
				string path = Path.Combine(_overrideDir ?? "", selectedLanguage + ".json");
				if (_overrideDir != null && File.Exists(path))
				{
					foreach (KeyValuePair<string, string> item2 in Parse(File.ReadAllText(path)))
					{
						dictionary[item2.Key] = item2.Value;
						dictionary2[item2.Key] = item2.Value;
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("Translations: couldn't read the player's " + selectedLanguage + " file: " + ex.Message));
			}
			Dictionary<string, string> dictionary3 = GameWords?.GetValue(instance) as Dictionary<string, string>;
			foreach (string item3 in _runtimeGiven)
			{
				if (!dictionary.ContainsKey(item3))
				{
					dictionary3?.Remove(item3);
				}
			}
			_runtimeGiven.Clear();
			foreach (Dictionary<string, Dictionary<string, string>> value2 in Runtime.Values)
			{
				foreach (Dictionary<string, string> value3 in value2.Values)
				{
					foreach (string key in value3.Keys)
					{
						_runtimeGiven.Add(key);
					}
				}
			}
			_given = dictionary;
			_files = dictionary2;
			foreach (KeyValuePair<string, string> item4 in dictionary)
			{
				AddWord.Invoke(instance, new object[2]
				{
					item4.Key,
					FillIn(item4.Key, item4.Value)
				});
			}
			EvictCache(instance);
		}

		private static void EvictCache(Localization loc)
		{
			object obj = Cache?.GetValue(loc);
			obj?.GetType().GetMethod("EvictAll")?.Invoke(obj, null);
		}

		private static Dictionary<string, string> Parse(string json)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			foreach (Match item in Regex.Matches(json, "\"((?:[^\"\\\\]|\\\\.)*)\"\\s*:\\s*\"((?:[^\"\\\\]|\\\\.)*)\""))
			{
				dictionary[Unescape(item.Groups[1].Value)] = Unescape(item.Groups[2].Value);
			}
			return dictionary;
		}

		private static string Unescape(string s)
		{
			return Regex.Replace(s, "\\\\(u[0-9a-fA-F]{4}|.)", delegate(Match m)
			{
				string value = m.Groups[1].Value;
				return value[0] switch
				{
					'n' => "\n", 
					't' => "\t", 
					'u' => ((char)Convert.ToInt32(value.Substring(1), 16)).ToString(), 
					_ => value, 
				};
			});
		}
	}
	internal sealed class ServerSettings : IDisposable
	{
		public enum ServerMod
		{
			NotConnected,
			Checking,
			Installed,
			Missing
		}

		private sealed class ConfigurationManagerAttributes
		{
			public bool? ReadOnly;
		}

		private sealed class SyncedText
		{
			public string Key;

			public Func<string> Own;

			public Action<string> Use;

			public string Given;

			public bool FromServer;

			public bool Pending;

			public byte[] Packed;

			public bool TooBig;

			public MemoryStream Incoming;

			public int NextPart;
		}

		private sealed class Sending
		{
			public ZRpc Rpc;

			public string Key;

			public byte[] Data;

			public int Next;

			public int Parts;
		}

		private const int Protocol = 2;

		private const float ChangeSendGap = 0.5f;

		private const float AnswerWait = 20f;

		private const float FileWait = 1f;

		private const int PartSize = 65536;

		private const int CompressFrom = 1024;

		private const int WarnBytes = 262144;

		private const int MaxBytes = 8388608;

		private const int PaceBelow = 10240;

		private readonly string _send;

		private readonly string _ask;

		private readonly string _dAsk;

		private readonly string _dHello;

		private readonly string _dSend;

		private readonly string _edit;

		private readonly string _dTextAsk;

		private readonly string _dText;

		private readonly string _dAgain;

		private readonly ConfigFile _config;

		private readonly ManualLogSource _log;

		private readonly string _name;

		private readonly List<ConfigEntryBase> _entries = new List<ConfigEntryBase>();

		private readonly Dictionary<ConfigEntryBase, object> _own = new Dictionary<ConfigEntryBase, object>();

		private readonly Dictionary<ConfigEntryBase, object> _server = new Dictionary<ConfigEntryBase, object>();

		private readonly List<GameObject> _guardedPieces = new List<GameObject>();

		private readonly List<Recipe> _guardedRecipes = new List<Recipe>();

		private ZRoutedRpc _registeredOn;

		private bool _applying;

		private bool _reloading;

		private bool _changePending;

		private float _nextChangeSend;

		private float _askedAt = -1f;

		private int _serverProtocol;

		private bool _directSeen;

		private readonly HashSet<ZRpc> _directPeers = new HashSet<ZRpc>();

		private readonly List<SyncedText> _texts = new List<SyncedText>();

		private readonly Dictionary<ZRpc, HashSet<string>> _textPeers = new Dictionary<ZRpc, HashSet<string>>();

		private bool _textPending;

		private float _nextTextSend;

		private bool _readOnlyShown;

		private float _nextAdminCheck;

		private FileSystemWatcher _watcher;

		private volatile bool _fileTouched;

		private float _reloadAt = -1f;

		private string _fileText;

		private readonly List<Sending> _outbox = new List<Sending>();

		private static readonly MethodInfo UpdateAvailablePieces = AccessTools.Method(typeof(Player), "UpdateAvailablePiecesList", (Type[])null, (Type[])null);

		private static readonly List<ServerSettings> Live = new List<ServerSettings>();

		private static Harmony _saveHarmony;

		public string Version { get; }

		public bool FromServer => _server.Count > 0;

		public ServerMod Server { get; private set; }

		public string ServerVersion { get; private set; }

		public bool CanEditServer
		{
			get
			{
				if (!IsServer)
				{
					if (Server == ServerMod.Installed && _serverProtocol >= 1 && (Object)(object)ZNet.instance != (Object)null)
					{
						return ZNet.instance.LocalPlayerIsAdminOrHost();
					}
					return false;
				}
				return true;
			}
		}

		private static bool IsServer
		{
			get
			{
				if ((Object)(object)ZNet.instance != (Object)null)
				{
					return ZNet.instance.IsServer();
				}
				return false;
			}
		}

		public event Action ServerChanged;

		public ServerSettings(string guid, ConfigFile config, ManualLogSource log)
		{
			_send = guid + ".settings";
			_ask = guid + ".settings.ask";
			_dAsk = guid + ".settings.d.ask";
			_dHello = guid + ".settings.d.hello";
			_dSend = guid + ".settings.d.values";
			_edit = guid + ".settings.d.edit";
			_dTextAsk = guid + ".settings.d.textask";
			_dAgain = guid + ".settings.d.again";
			_dText = guid + ".settings.d.text";
			_config = config;
			_log = log;
			BepInPlugin val = PluginOf(guid);
			_name = ((val != null) ? val.Name : null) ?? guid;
			Version = ((val == null) ? null : val.Version?.ToString()) ?? "";
			Live.Add(this);
			if (Live.Count == 1)
			{
				PatchSave();
			}
			WatchFile();
		}

		public ConfigEntry<T> Add<T>(ConfigEntry<T> entry)
		{
			if (entry == null || _entries.Contains((ConfigEntryBase)(object)entry))
			{
				return entry;
			}
			_entries.Add((ConfigEntryBase)(object)entry);
			entry.SettingChanged += OnChanged;
			GiveManagerAttributes((ConfigEntryBase)(object)entry);
			return entry;
		}

		private static void GiveManagerAttributes(ConfigEntryBase entry)
		{
			ConfigDescription description = entry.Description;
			if (description == null || description == ConfigDescription.Empty || (description.Tags ?? new object[0]).Any(IsManagerAttributes))
			{
				return;
			}
			try
			{
				object[] value = new object[1]
				{
					new ConfigurationManagerAttributes()
				}.Concat(description.Tags ?? new object[0]).ToArray();
				AccessTools.Field(typeof(ConfigDescription), "<Tags>k__BackingField")?.SetValue(description, value);
			}
			catch (Exception)
			{
			}
		}

		public ConfigEntry<T> Bind<T>(string section, string key, T value, string description, AcceptableValueBase range = null, params object[] tags)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			if (!description.Contains("[Synced with Server]"))
			{
				description += " [Synced with Server]";
			}
			return Add<T>(_config.Bind<T>(section, key, value, new ConfigDescription(description, range, tags ?? new object[0])));
		}

		public void NeedsServer(GameObject piecePrefab)
		{
			if (!((Object)(object)piecePrefab == (Object)null))
			{
				_guardedPieces.RemoveAll((GameObject p) => (Object)(object)p == (Object)null || ((Object)p).name == ((Object)piecePrefab).name);
				_guardedPieces.Add(piecePrefab);
				Guard();
			}
		}

		public void NeedsServer(Recipe recipe)
		{
			if (!((Object)(object)recipe == (Object)null))
			{
				_guardedRecipes.RemoveAll((Recipe r) => (Object)(object)r == (Object)null || (Object)(object)r == (Object)(object)recipe || (!string.IsNullOrEmpty(((Object)recipe).name) && ((Object)r).name == ((Object)recipe).name));
				_guardedRecipes.Add(recipe);
				Guard();
			}
		}

		public void AddText(string key, Func<string> own, Action<string> use)
		{
			if (string.IsNullOrEmpty(key) || own == null || use == null)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogError((object)"AddText needs a key, own and use");
				}
				return;
			}
			_texts.RemoveAll((SyncedText x) => x.Key == key);
			SyncedText syncedText = new SyncedText
			{
				Key = key,
				Own = own,
				Use = use
			};
			_texts.Add(syncedText);
			Give(syncedText, OwnText(syncedText));
			ZRpc val = ((!((Object)(object)ZNet.instance != (Object)null) || IsServer) ? null : ZNet.instance.GetServerPeer()?.m_rpc);
			if (_registeredOn != null && val != null)
			{
				val.Register<ZPackage>(_dText, (Action<ZRpc, ZPackage>)OnText);
				AskTexts(val);
			}
		}

		public void TextChanged(string key)
		{
			SyncedText syncedText = _texts.FirstOrDefault((SyncedText x) => x.Key == key);
			if (syncedText != null)
			{
				syncedText.Packed = null;
				if (!syncedText.FromServer)
				{
					Give(syncedText, OwnText(syncedText));
				}
				if (IsServer)
				{
					syncedText.Pending = true;
					_textPending = true;
				}
			}
		}

		public bool TextFromServer(string key)
		{
			return _texts.Any((SyncedText x) => x.Key == key && x.FromServer);
		}

		public void Update()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != _registeredOn)
			{
				Unregister();
				Restore();
				RestoreTexts(give: true);
				_changePending = false;
				_textPending = false;
				SetServer(ServerMod.NotConnected, null, 0);
				if (instance != null)
				{
					Register(instance);
				}
			}
			float unscaledTime = Time.unscaledTime;
			if (_changePending && unscaledTime >= _nextChangeSend)
			{
				SendChange();
			}
			if (_textPending && unscaledTime >= _nextTextSend)
			{
				SendTexts();
			}
			if (_outbox.Count > 0)
			{
				Pump();
			}
			if (Server == ServerMod.Checking && _askedAt >= 0f && unscaledTime - _askedAt > 20f)
			{
				if (_guardedPieces.Count + _guardedRecipes.Count > 0)
				{
					ManualLogSource log = _log;
					if (log != null)
					{
						log.LogWarning((object)("The server didn't answer: " + _name + " isn't installed there (or its copy is older than 2026-10-11), so its pieces and items can't be made on this server."));
					}
				}
				else
				{
					ManualLogSource log2 = _log;
					if (log2 != null)
					{
						log2.LogInfo((object)("The server didn't answer: " + _name + " isn't installed there, or its copy is older" + (FromServer ? " (its settings apply)." : " (your own settings apply).")));
					}
				}
				SetServer(ServerMod.Missing, null, 0);
			}
			if (_fileTouched)
			{
				_fileTouched = false;
				_reloadAt = unscaledTime + 1f;
			}
			if (_reloadAt >= 0f && unscaledTime >= _reloadAt)
			{
				_reloadAt = -1f;
				ReloadFile();
			}
			if (FromServer && unscaledTime >= _nextAdminCheck)
			{
				_nextAdminCheck = unscaledTime + 1f;
				ShowReadOnly();
			}
		}

		public void Dispose()
		{
			Unregister();
			Restore();
			RestoreTexts(give: false);
			SetServer(ServerMod.NotConnected, null, 0);
			foreach (ConfigEntryBase entry in _entries)
			{
				Unsubscribe(entry);
			}
			_entries.Clear();
			_texts.Clear();
			try
			{
				_watcher?.Dispose();
			}
			catch (Exception)
			{
			}
			_watcher = null;
			Live.Remove(this);
			if (Live.Count == 0)
			{
				UnpatchSave();
			}
		}

		private void Register(ZRoutedRpc rpc)
		{
			Forget(rpc, _send);
			Forget(rpc, _ask);
			rpc.Register<ZPackage>(_send, (Action<long, ZPackage>)OnRoutedValues);
			rpc.Register(_ask, (Action<long>)OnRoutedAsk);
			rpc.m_onNewPeer = (Action<long>)Delegate.Combine(rpc.m_onNewPeer, new Action<long>(OnNewPeer));
			_registeredOn = rpc;
			if (IsServer)
			{
				foreach (ZNetPeer peer in ZNet.instance.GetPeers())
				{
					ListenTo(peer);
					if (peer != null)
					{
						ZRpc rpc2 = peer.m_rpc;
						if (rpc2 != null)
						{
							rpc2.Invoke(_dAgain, Array.Empty<object>());
						}
					}
				}
				return;
			}
			if ((Object)(object)ZNet.instance != (Object)null)
			{
				SetServer(ServerMod.Checking, null, 0);
				if (ZNet.instance.GetServerPeer() != null)
				{
					AskServer();
				}
			}
		}

		private void Unregister()
		{
			if (_registeredOn == null)
			{
				return;
			}
			ZRoutedRpc registeredOn = _registeredOn;
			registeredOn.m_onNewPeer = (Action<long>)Delegate.Remove(registeredOn.m_onNewPeer, new Action<long>(OnNewPeer));
			Forget(_registeredOn, _send);
			Forget(_registeredOn, _ask);
			if ((Object)(object)ZNet.instance != (Object)null)
			{
				foreach (ZNetPeer peer in ZNet.instance.GetPeers())
				{
					if (peer?.m_rpc != null)
					{
						string[] array = new string[7] { _dAsk, _dHello, _dSend, _edit, _dTextAsk, _dText, _dAgain };
						foreach (string name in array)
						{
							ForgetDirect(peer.m_rpc, name);
						}
					}
				}
			}
			_directPeers.Clear();
			_textPeers.Clear();
			_outbox.Clear();
			_directSeen = false;
			_registeredOn = null;
		}

		private static void Forget(ZRoutedRpc rpc, string name)
		{
			if (AccessTools.Field(typeof(ZRoutedRpc), "m_functions")?.GetValue(rpc) is IDictionary dictionary)
			{
				dictionary.Remove(StringExtensionMethods.GetStableHashCode(name));
			}
		}

		private static void ForgetDirect(ZRpc rpc, string name)
		{
			if (AccessTools.Field(typeof(ZRpc), "m_functions")?.GetValue(rpc) is IDictionary dictionary)
			{
				dictionary.Remove(StringExtensionMethods.GetStableHashCode(name));
			}
		}

		private void OnNewPeer(long uid)
		{
			if (IsServer)
			{
				ZNetPeer peer = ZNet.instance.GetPeer(uid);
				ListenTo(peer);
				if (peer?.m_rpc != null)
				{
					SendDirect(peer.m_rpc);
				}
				SendRouted(uid);
			}
			else if ((Object)(object)ZNet.instance != (Object)null)
			{
				ZNetPeer serverPeer = ZNet.instance.GetServerPeer();
				if (serverPeer != null && serverPeer.m_uid == uid)
				{
					AskServer();
				}
			}
		}

		private void ListenTo(ZNetPeer peer)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			if (peer?.m_rpc != null)
			{
				peer.m_rpc.Register(_dAsk, new Method(OnDirectAsk));
				peer.m_rpc.Register<ZPackage>(_edit, (Action<ZRpc, ZPackage>)OnEdit);
				peer.m_rpc.Register<ZPackage>(_dTextAsk, (Action<ZRpc, ZPackage>)OnTextAsk);
			}
		}

		private void OnDirectAsk(ZRpc rpc)
		{
			if (IsServer)
			{
				_directPeers.Add(rpc);
				SendDirect(rpc);
			}
		}

		private void OnRoutedAsk(long sender)
		{
			if (IsServer)
			{
				SendRouted(sender);
			}
		}

		private void SendDirect(ZRpc rpc)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(2);
			val.Write(Version);
			rpc.Invoke(_dHello, new object[1] { val });
			if (_entries.Count > 0)
			{
				rpc.Invoke(_dSend, new object[1] { Values() });
			}
		}

		private void SendRouted(long target)
		{
			if (ZRoutedRpc.instance != null && _entries.Count > 0)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(target, _send, new object[1] { Values() });
			}
		}

		private ZPackage Values()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(_entries.Count);
			foreach (ConfigEntryBase entry in _entries)
			{
				val.Write(entry.Definition.Section);
				val.Write(entry.Definition.Key);
				val.Write(TomlTypeConverter.ConvertToString(entry.BoxedValue, entry.SettingType));
			}
			return val;
		}

		private void AskServer()
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			ZNetPeer val = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetServerPeer() : null);
			if (val?.m_rpc == null)
			{
				return;
			}
			_askedAt = Time.unscaledTime;
			val.m_rpc.Register<ZPackage>(_dHello, (Action<ZRpc, ZPackage>)OnDirectHello);
			val.m_rpc.Register<ZPackage>(_dSend, (Action<ZRpc, ZPackage>)OnDirectValues);
			val.m_rpc.Register<ZPackage>(_dText, (Action<ZRpc, ZPackage>)OnText);
			val.m_rpc.Register(_dAgain, new Method(OnAskAgain));
			val.m_rpc.Invoke(_dAsk, Array.Empty<object>());
			AskTexts(val.m_rpc);
			try
			{
				ZRoutedRpc instance = ZRoutedRpc.instance;
				if (instance != null)
				{
					instance.InvokeRoutedRPC(val.m_uid, _ask, Array.Empty<object>());
				}
			}
			catch (Exception)
			{
			}
		}

		private static bool IsServerConnection(ZRpc rpc)
		{
			if (!IsServer)
			{
				ZNet instance = ZNet.instance;
				return ((instance == null) ? null : instance.GetServerPeer()?.m_rpc) == rpc;
			}
			return false;
		}

		private void OnAskAgain(ZRpc rpc)
		{
			if (IsServerConnection(rpc))
			{
				rpc.Invoke(_dAsk, Array.Empty<object>());
				AskTexts(rpc);
			}
		}

		private void OnDirectHello(ZRpc rpc, ZPackage pkg)
		{
			if (!IsServerConnection(rpc))
			{
				return;
			}
			try
			{
				int protocol = pkg.ReadInt();
				string text = pkg.ReadString();
				if (text != Version && text != ServerVersion)
				{
					ManualLogSource log = _log;
					if (log != null)
					{
						log.LogWarning((object)("The server has " + _name + " " + text + ", you have " + Version + ": some things may not match. Use the same version as the server."));
					}
				}
				_directSeen = true;
				SetServer(ServerMod.Installed, text, protocol);
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = _log;
				if (log2 != null)
				{
					log2.LogWarning((object)("Could not read the server's hello: " + ex.Message));
				}
			}
		}

		private void OnDirectValues(ZRpc rpc, ZPackage pkg)
		{
			if (IsServerConnection(rpc))
			{
				TakeValues(pkg);
			}
		}

		private void OnRoutedValues(long sender, ZPackage pkg)
		{
			if (!_directSeen && !IsServer)
			{
				ZNetPeer val = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetServerPeer() : null);
				if (val != null && val.m_uid == sender)
				{
					TakeValues(pkg);
				}
			}
		}

		private void TakeValues(ZPackage pkg)
		{
			try
			{
				int num = pkg.ReadInt();
				List<string> list = new List<string>();
				for (int i = 0; i < num; i++)
				{
					string section = pkg.ReadString();
					string key = pkg.ReadString();
					string text = pkg.ReadString();
					ConfigEntryBase val = ((IEnumerable<ConfigEntryBase>)_entries).FirstOrDefault((Func<ConfigEntryBase, bool>)((ConfigEntryBase x) => x.Definition.Section == section && x.Definition.Key == key));
					if (val != null)
					{
						object obj;
						try
						{
							obj = TomlTypeConverter.ConvertToValue(text, val.SettingType);
						}
						catch (Exception)
						{
							continue;
						}
						if (!_own.ContainsKey(val))
						{
							_own[val] = val.BoxedValue;
						}
						_server[val] = obj;
						if (!object.Equals(val.BoxedValue, obj))
						{
							Apply(val, obj);
							list.Add(section + "/" + key + " = " + text);
						}
					}
				}
				ManualLogSource