Decompiled source of Quads Quiver v0.2.3

plugins/Quiver.dll

Decompiled 15 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using DHack.Shared;
using HarmonyLib;
using Microsoft.CodeAnalysis;
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 Quiver
{
	[BepInPlugin("com.quad.quiver", "Quiver", "0.2.3")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "com.quad.quiver";

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

		public const string Name = "Quiver";

		public const string Version = "0.2.3";

		internal static ManualLogSource Log;

		internal static ServerSettings Synced;

		internal static ConfigEntry<bool> Recover;

		internal static ConfigEntry<bool> Bolts;

		internal static ConfigEntry<bool> FireBurns;

		internal static ConfigEntry<bool> ShowQuiver;

		internal static ConfigEntry<bool> Debug;

		internal static ConfigEntry<float> GroundChance;

		internal static ConfigEntry<float> CreatureChance;

		internal static ConfigEntry<float> Back;

		internal static ConfigEntry<float> Side;

		internal static ConfigEntry<float> Height;

		internal static ConfigEntry<float> TiltSide;

		internal static ConfigEntry<float> TiltBack;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Expected O, but got Unknown
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Expected O, but got Unknown
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Expected O, but got Unknown
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Expected O, but got Unknown
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Expected O, but got Unknown
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Expected O, but got Unknown
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Expected O, but got Unknown
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Expected O, but got Unknown
			Migration.FromOldGuid((BaseUnityPlugin)(object)this, "com.dhack.quiver");
			Log = ((BaseUnityPlugin)this).Logger;
			Synced = new ServerSettings("com.quad.quiver", ((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			Recover = Synced.Add<bool>(((BaseUnityPlugin)this).Config.Bind<bool>("Arrows", "PickUpArrows", true, "Arrows you shoot that hit something land on the ground as arrows you can pick up again. In multiplayer the server's value applies."));
			GroundChance = Synced.Add<float>(((BaseUnityPlugin)this).Config.Bind<float>("Arrows", "ChanceOnGround", 1f, new ConfigDescription("The chance an arrow that hit the ground, a tree, a wall or the like is kept. 1 keeps every one. In multiplayer the server's value applies.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())));
			CreatureChance = Synced.Add<float>(((BaseUnityPlugin)this).Config.Bind<float>("Arrows", "ChanceOnCreature", 0.75f, new ConfigDescription("The chance an arrow that hit a creature is kept: it drops with that creature's loot when it dies. 0.75 keeps three in four. In multiplayer the server's value applies.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())));
			Bolts = Synced.Add<bool>(((BaseUnityPlugin)this).Config.Bind<bool>("Arrows", "IncludeBolts", true, "Crossbow bolts can be picked up too. In multiplayer the server's value applies."));
			FireBurns = Synced.Add<bool>(((BaseUnityPlugin)this).Config.Bind<bool>("Arrows", "FireArrowsBurnUp", true, "Fire arrows are always used up. In multiplayer the server's value applies."));
			Debug = ((BaseUnityPlugin)this).Config.Bind<bool>("Arrows", "LogHits", false, "Write what each arrow hit did (kept, broke, why not) to the BepInEx log. For finding out why an arrow did not come back.");
			ShowQuiver = ((BaseUnityPlugin)this).Config.Bind<bool>("Quiver", "Show", true, "A quiver on your back while you have arrows (or bolts) equipped.");
			Back = ((BaseUnityPlugin)this).Config.Bind<float>("Quiver", "Back", 0.2f, new ConfigDescription("How far behind your spine the quiver hangs (metres).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 0.4f), Array.Empty<object>()));
			Side = ((BaseUnityPlugin)this).Config.Bind<float>("Quiver", "Side", 0.1f, new ConfigDescription("How far to your right it hangs (negative: left).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.3f, 0.3f), Array.Empty<object>()));
			Height = ((BaseUnityPlugin)this).Config.Bind<float>("Quiver", "Height", -0.03f, new ConfigDescription("How far up it hangs (negative: lower).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.4f, 0.4f), Array.Empty<object>()));
			TiltSide = ((BaseUnityPlugin)this).Config.Bind<float>("Quiver", "TiltSide", 22f, new ConfigDescription("How far the top leans to your right (degrees).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-45f, 45f), Array.Empty<object>()));
			TiltBack = ((BaseUnityPlugin)this).Config.Bind<float>("Quiver", "TiltBack", 8f, new ConfigDescription("How far the top leans backwards (degrees).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-45f, 45f), Array.Empty<object>()));
			_harmony = new Harmony("com.quad.quiver");
			_harmony.PatchAll(typeof(Plugin).Assembly);
		}

		private void Update()
		{
			Synced?.Update();
			Stuck.Tick();
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null && !BetterArchery.QuiverOn && (Object)(object)((Component)localPlayer).GetComponent<QuiverView>() == (Object)null)
			{
				((Component)localPlayer).gameObject.AddComponent<QuiverView>();
			}
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Stuck.Clear();
			QuiverView[] array = Object.FindObjectsOfType<QuiverView>();
			foreach (QuiverView quiverView in array)
			{
				quiverView.Clear();
				Object.Destroy((Object)(object)quiverView);
			}
			Synced?.Dispose();
		}
	}
	internal static class BetterArchery
	{
		private static bool _checked;

		private static bool _arrows;

		private static bool _quiver;

		public static bool ArrowsOn
		{
			get
			{
				Check();
				return _arrows;
			}
		}

		public static bool QuiverOn
		{
			get
			{
				Check();
				return _quiver;
			}
		}

		private static void Check()
		{
			if (_checked || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			_checked = true;
			if (Chainloader.PluginInfos.TryGetValue("ishid4.mods.betterarchery", out var value))
			{
				_arrows = Setting(value, "Retrievable Arrows", "Enable Retrievable Arrows");
				_quiver = Setting(value, "Quiver", "Enable Quiver");
				if (_arrows)
				{
					Plugin.Log.LogInfo((object)"BetterArchery's retrievable arrows are on: arrows are picked up its way, and this mod's arrow recovery is off");
				}
				if (_quiver)
				{
					Plugin.Log.LogInfo((object)"BetterArchery's quiver is on: this mod's quiver is not drawn");
				}
			}
		}

		private static bool Setting(PluginInfo info, string section, string key)
		{
			ConfigEntry<bool> val = null;
			if (!((Object)(object)info.Instance == (Object)null) && info.Instance.Config.TryGetEntry<bool>(section, key, ref val))
			{
				return val.Value;
			}
			return true;
		}
	}
	internal class QuiverView : MonoBehaviour
	{
		private static readonly FieldRef<Humanoid, ItemData> AmmoRef = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_ammoItem");

		private Humanoid _body;

		private GameObject _root;

		private string _shown = "";

		private float _next;

		private static Material _leather;

		private static Material _dark;

		private const float TubeHalf = 0.25f;

		private const float TubeRadius = 0.06f;

		private const float Sticks = 0.17f;

		private const float MaxArrow = 0.6f;

		private void Awake()
		{
			_body = ((Component)this).GetComponent<Humanoid>();
		}

		private void Update()
		{
			if (!(Time.time < _next))
			{
				_next = Time.time + 0.3f;
				Refresh();
			}
		}

		public void Clear()
		{
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
			}
			_root = null;
			_shown = "";
		}

		private void Refresh()
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Invalid comparison between Unknown and I4
			ItemData val = ((Plugin.ShowQuiver.Value && (Object)(object)_body != (Object)null && !((Character)_body).IsDead()) ? AmmoRef.Invoke(_body) : null);
			if (val == null || (int)val.m_shared.m_itemType != 9 || (Object)(object)val.m_dropPrefab == (Object)null)
			{
				Clear();
				return;
			}
			int num = _body.GetInventory().CountItems(val.m_shared.m_name, -1, true);
			int num2 = Mathf.Clamp(1 + num / 15, 1, 7);
			string text = $"{((Object)val.m_dropPrefab).name}|{num2}|{Plugin.Back.Value}|{Plugin.Side.Value}|{Plugin.Height.Value}|{Plugin.TiltSide.Value}|{Plugin.TiltBack.Value}";
			if (!(text == _shown) || !((Object)(object)_root != (Object)null))
			{
				Clear();
				_shown = text;
				Build(val, num2);
			}
		}

		private void Build(ItemData ammo, int arrows)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: 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_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: 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_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			Transform val = FindBone(((Component)this).transform, "Spine2") ?? FindBone(((Component)this).transform, "Spine1") ?? FindBone(((Component)this).transform, "Spine");
			if (!((Object)(object)val == (Object)null))
			{
				MakeMaterials();
				_root = new GameObject("Quiver");
				Vector3 up = ((Component)this).transform.up;
				Vector3 right = ((Component)this).transform.right;
				Vector3 val2 = -((Component)this).transform.forward;
				Vector3 val3 = up + right * Mathf.Tan(Plugin.TiltSide.Value * ((float)Math.PI / 180f)) + val2 * Mathf.Tan(Plugin.TiltBack.Value * ((float)Math.PI / 180f));
				Vector3 normalized = ((Vector3)(ref val3)).normalized;
				_root.transform.position = val.position + val2 * Plugin.Back.Value + right * Plugin.Side.Value + up * Plugin.Height.Value;
				_root.transform.rotation = Quaternion.FromToRotation(Vector3.up, normalized) * Quaternion.LookRotation(Vector3.forward, Vector3.up);
				_root.transform.localScale = Vector3.one;
				Part((PrimitiveType)2, "Tube", new Vector3(0.12f, 0.25f, 0.12f), Vector3.zero, _leather);
				Part((PrimitiveType)2, "Rim", new Vector3(0.13499999f, 0.012f, 0.13499999f), Vector3.up * 0.25f, _dark);
				Part((PrimitiveType)2, "Base", new Vector3(0.102f, 0.02f, 0.102f), Vector3.down * 0.25f, _dark);
				Part((PrimitiveType)2, "Band", new Vector3(0.12900001f, 0.014f, 0.12900001f), Vector3.up * 0.1125f, _dark);
				Random random = new Random(((Object)ammo.m_dropPrefab).name.GetHashCode());
				Vector3 at = default(Vector3);
				for (int i = 0; i < arrows; i++)
				{
					float num = ((i == 0) ? 0f : 0.032f);
					float num2 = (float)i * 137.5f * ((float)Math.PI / 180f);
					((Vector3)(ref at))..ctor(Mathf.Cos(num2) * num, 0f, Mathf.Sin(num2) * num);
					Quaternion lean = Quaternion.Euler((float)(random.NextDouble() * 10.0 - 5.0), 0f, (float)(random.NextDouble() * 10.0 - 5.0));
					Arrow(ammo.m_dropPrefab, at, lean);
				}
				_root.transform.SetParent(val, true);
				Collider[] componentsInChildren = _root.GetComponentsInChildren<Collider>();
				foreach (Collider val4 in componentsInChildren)
				{
					Object.Destroy((Object)(object)val4);
				}
			}
		}

		private void Part(PrimitiveType shape, string name, Vector3 scale, Vector3 at, Material material)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.CreatePrimitive(shape);
			((Object)val).name = name;
			val.transform.SetParent(_root.transform, false);
			val.transform.localPosition = at;
			val.transform.localScale = scale;
			val.GetComponent<Renderer>().sharedMaterial = material;
		}

		private void Arrow(GameObject prefab, Vector3 at, Quaternion lean)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Expected O, but got Unknown
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: 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_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Arrow");
			val.transform.SetParent(_root.transform, false);
			float num = float.MaxValue;
			float num2 = float.MinValue;
			LODGroup componentInChildren = prefab.GetComponentInChildren<LODGroup>();
			Renderer[] array = ((componentInChildren != null && componentInChildren.GetLODs().Length != 0) ? componentInChildren.GetLODs()[0].renderers : prefab.GetComponentsInChildren<Renderer>());
			Renderer[] array2 = array;
			foreach (Renderer val2 in array2)
			{
				MeshFilter val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<MeshFilter>() : null);
				if ((Object)(object)val3 == (Object)null || (Object)(object)val3.sharedMesh == (Object)null)
				{
					continue;
				}
				MeshRenderer val4 = (MeshRenderer)(object)((val2 is MeshRenderer) ? val2 : null);
				if (val4 == null)
				{
					continue;
				}
				Matrix4x4 val5 = prefab.transform.worldToLocalMatrix * ((Component)val3).transform.localToWorldMatrix;
				GameObject val6 = new GameObject(((Object)val3).name);
				val6.transform.SetParent(val.transform, false);
				val6.transform.localPosition = Vector4.op_Implicit(((Matrix4x4)(ref val5)).GetColumn(3));
				val6.transform.localRotation = ((Matrix4x4)(ref val5)).rotation;
				val6.transform.localScale = ((Matrix4x4)(ref val5)).lossyScale;
				val6.AddComponent<MeshFilter>().sharedMesh = val3.sharedMesh;
				((Renderer)val6.AddComponent<MeshRenderer>()).sharedMaterials = ((Renderer)val4).sharedMaterials;
				Bounds bounds = val3.sharedMesh.bounds;
				float[] array3 = new float[2]
				{
					((Bounds)(ref bounds)).min.x,
					((Bounds)(ref bounds)).max.x
				};
				foreach (float num3 in array3)
				{
					float[] array4 = new float[2]
					{
						((Bounds)(ref bounds)).min.y,
						((Bounds)(ref bounds)).max.y
					};
					foreach (float num4 in array4)
					{
						float[] array5 = new float[2]
						{
							((Bounds)(ref bounds)).min.z,
							((Bounds)(ref bounds)).max.z
						};
						foreach (float num5 in array5)
						{
							float z = ((Matrix4x4)(ref val5)).MultiplyPoint3x4(new Vector3(num3, num4, num5)).z;
							num = Mathf.Min(num, z);
							num2 = Mathf.Max(num2, z);
						}
					}
				}
			}
			if (num == float.MaxValue || num2 - num < 0.01f)
			{
				Object.Destroy((Object)(object)val);
				return;
			}
			float num6 = Mathf.Min(1f, 0.6f / (num2 - num));
			val.transform.localScale = Vector3.one * num6;
			val.transform.localRotation = lean * Quaternion.Euler(90f, 0f, 0f);
			val.transform.localPosition = at + Vector3.up * (0.42000002f + num * num6);
		}

		private static Transform FindBone(Transform root, string name)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			if (((Object)root).name == name)
			{
				return root;
			}
			foreach (Transform item in root)
			{
				Transform root2 = item;
				Transform val = FindBone(root2, name);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private static void MakeMaterials()
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_leather != (Object)null && (Object)(object)_dark != (Object)null)
			{
				return;
			}
			Material val = null;
			GameObject val2 = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("Wood") : null);
			if ((Object)(object)val2 != (Object)null)
			{
				Renderer[] componentsInChildren = val2.GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val3 in componentsInChildren)
				{
					val = val ?? ((IEnumerable<Material>)val3.sharedMaterials).FirstOrDefault((Func<Material, bool>)((Material m) => (Object)(object)m != (Object)null && ((Object)m).name == "wood_item"));
				}
			}
			val = (Material)(((object)val) ?? ((object)new Material(Shader.Find("Standard") ?? Shader.Find("Sprites/Default"))));
			_leather = Plain(val, new Color(0.4f, 0.24f, 0.12f));
			_dark = Plain(val, new Color(0.17f, 0.1f, 0.06f));
		}

		private static Material Plain(Material basis, Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			Material val = new Material(basis)
			{
				color = color
			};
			if (val.HasProperty("_MainTex"))
			{
				val.mainTexture = null;
			}
			if (val.HasProperty("_Glossiness"))
			{
				val.SetFloat("_Glossiness", 0.1f);
			}
			if (val.HasProperty("_Metallic"))
			{
				val.SetFloat("_Metallic", 0f);
			}
			return val;
		}
	}
	[HarmonyPatch(typeof(Projectile), "OnHit")]
	internal static class Projectile_OnHit_Recover
	{
		private static readonly FieldRef<Projectile, ItemData> Ammo = AccessTools.FieldRefAccess<Projectile, ItemData>("m_ammo");

		private static readonly FieldRef<Projectile, Character> Owner = AccessTools.FieldRefAccess<Projectile, Character>("m_owner");

		private static readonly FieldRef<Projectile, ZNetView> View = AccessTools.FieldRefAccess<Projectile, ZNetView>("m_nview");

		private static readonly FieldRef<Projectile, ItemData> SpawnItem = AccessTools.FieldRefAccess<Projectile, ItemData>("m_spawnItem");

		private static readonly FieldRef<Projectile, ItemData> Weapon = AccessTools.FieldRefAccess<Projectile, ItemData>("m_weapon");

		private static readonly HashSet<int> Done = new HashSet<int>();

		private static void Postfix(Projectile __instance, Collider collider, Vector3 hitPoint, bool water, Vector3 normal)
		{
			//IL_041e: Unknown result type (might be due to invalid IL or missing references)
			//IL_041f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0426: Unknown result type (might be due to invalid IL or missing references)
			//IL_042b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0430: Unknown result type (might be due to invalid IL or missing references)
			//IL_043a: Unknown result type (might be due to invalid IL or missing references)
			//IL_043f: Unknown result type (might be due to invalid IL or missing references)
			//IL_045d: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.Debug.Value)
			{
				ZNetView val = View.Invoke(__instance);
				ManualLogSource log = Plugin.Log;
				object[] obj = new object[6]
				{
					((Object)__instance).name,
					null,
					null,
					null,
					null,
					null
				};
				Character obj2 = Owner.Invoke(__instance);
				obj[1] = ((obj2 != null) ? ((Object)obj2).name : null) ?? "none";
				obj[2] = ((object)Owner.Invoke(__instance))?.GetType().Name;
				obj[3] = (((Object)(object)val == (Object)null) ? "none" : ((!val.IsValid()) ? "invalid" : (val.IsOwner() ? "owned here" : "owned elsewhere")));
				obj[4] = water;
				obj[5] = ((collider != null) ? ((Object)collider).name : null) ?? "nothing";
				log.LogInfo((object)string.Format("OnHit {0}: owner {1} ({2}), view {3}, water {4}, on {5}", obj));
			}
			if (!Plugin.Recover.Value || water)
			{
				return;
			}
			Character obj3 = Owner.Invoke(__instance);
			Player val2 = (Player)(object)((obj3 is Player) ? obj3 : null);
			if (val2 == null || (Object)(object)val2 != (Object)(object)Player.m_localPlayer || BetterArchery.ArrowsOn)
			{
				return;
			}
			ItemData val3 = Ammo.Invoke(__instance) ?? SpawnItem.Invoke(__instance);
			if (Plugin.Debug.Value)
			{
				ManualLogSource log2 = Plugin.Log;
				string[] obj4 = new string[13]
				{
					"Hit by ",
					((Object)__instance).name,
					": ammo ",
					Ammo.Invoke(__instance)?.m_shared.m_name ?? "none",
					", spawnItem ",
					SpawnItem.Invoke(__instance)?.m_shared.m_name ?? "none",
					", weapon ",
					Weapon.Invoke(__instance)?.m_shared.m_name ?? "none",
					", on ",
					((collider != null) ? ((Object)collider).name : null) ?? "nothing",
					" (",
					null,
					null
				};
				object obj5;
				if (collider == null)
				{
					obj5 = null;
				}
				else
				{
					Character componentInParent = ((Component)collider).GetComponentInParent<Character>();
					obj5 = ((componentInParent != null) ? ((Object)componentInParent).name : null);
				}
				if (obj5 == null)
				{
					obj5 = "no creature";
				}
				obj4[11] = (string)obj5;
				obj4[12] = ")";
				log2.LogInfo((object)string.Concat(obj4));
			}
			if (val3 == null || (Object)(object)val3.m_dropPrefab == (Object)null || !Recoverable(val3))
			{
				if (Plugin.Debug.Value)
				{
					Plugin.Log.LogInfo((object)("  not kept: " + ((val3 == null) ? "no ammo item on the projectile" : (((Object)(object)val3.m_dropPrefab == (Object)null) ? "ammo has no drop prefab" : "not an arrow or bolt it keeps"))));
				}
			}
			else
			{
				if (!Done.Add(((Object)__instance).GetInstanceID()))
				{
					return;
				}
				if (Done.Count > 300)
				{
					Done.Clear();
				}
				Character val4 = (((Object)(object)collider != (Object)null) ? ((Component)collider).GetComponentInParent<Character>() : null);
				if ((Object)(object)val4 != (Object)null && !val4.IsPlayer() && !val4.IsTamed() && !val4.IsDead())
				{
					bool flag = Random.value <= Plugin.CreatureChance.Value;
					if (Plugin.Debug.Value)
					{
						Plugin.Log.LogInfo((object)("  creature " + ((Object)val4).name + ": arrow " + ((Object)val3.m_dropPrefab).name + " " + (flag ? "kept for when it dies" : "broke")));
					}
					if (flag)
					{
						Stuck.Add(val4, val3);
					}
					return;
				}
				if (!(Random.value > Plugin.GroundChance.Value))
				{
					if (Plugin.Debug.Value)
					{
						Plugin.Log.LogInfo((object)("  " + ((Object)val3.m_dropPrefab).name + " dropped where it hit"));
					}
					ItemData val5 = val3.Clone();
					val5.m_stack = 1;
					val5.m_equipped = false;
					ItemDrop.DropItem(val5, 1, hitPoint + normal * 0.08f + Vector3.up * 0.05f, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f));
					try
					{
						__instance.SetStayTTL(0.05f);
						return;
					}
					catch (Exception)
					{
						return;
					}
				}
				if (Plugin.Debug.Value)
				{
					Plugin.Log.LogInfo((object)"  broke on what it hit");
				}
			}
		}

		private static bool Recoverable(ItemData ammo)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			if ((int)ammo.m_shared.m_itemType != 9)
			{
				return false;
			}
			string text = (ammo.m_shared.m_ammoType ?? "").ToLowerInvariant();
			if (text.Contains("bolt") && !Plugin.Bolts.Value)
			{
				return false;
			}
			if (!text.Contains("arrow") && !text.Contains("bolt"))
			{
				return false;
			}
			if (Plugin.FireBurns.Value)
			{
				return !((Object)ammo.m_dropPrefab).name.ToLowerInvariant().Contains("fire");
			}
			return true;
		}
	}
	internal static class Stuck
	{
		private class Entry
		{
			public Character Target;

			public string Name;

			public Vector3 Last;

			public float LastHit;

			public float Seen;

			public bool Died;

			public HashSet<string> Ragdolls;

			public readonly Dictionary<string, KeyValuePair<ItemData, int>> Arrows = new Dictionary<string, KeyValuePair<ItemData, int>>();
		}

		private struct Body
		{
			public string Name;

			public Vector3 At;

			public float Time;
		}

		private const float Patience = 300f;

		private const int MaxKept = 200;

		private const float Wait = 3f;

		private const float BodyRange = 8f;

		private static readonly Dictionary<int, Entry> Hit = new Dictionary<int, Entry>();

		private static readonly List<Body> Bodies = new List<Body>();

		private static float _next;

		public static void Add(Character target, ItemData arrow)
		{
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			int instanceID = ((Object)target).GetInstanceID();
			if (!Hit.TryGetValue(instanceID, out var value))
			{
				if (Hit.Count >= 200)
				{
					Hit.Remove(Hit.OrderBy((KeyValuePair<int, Entry> kv) => kv.Value.LastHit).First().Key);
				}
				value = (Hit[instanceID] = new Entry
				{
					Target = target,
					Name = ((Object)target).name,
					Seen = Time.time,
					Ragdolls = RagdollNames(target)
				});
			}
			value.LastHit = Time.time;
			string name = ((Object)arrow.m_dropPrefab).name;
			value.Arrows[name] = new KeyValuePair<ItemData, int>(value.Arrows.TryGetValue(name, out var value2) ? value2.Key : arrow, (value.Arrows.TryGetValue(name, out var value3) ? value3.Value : 0) + 1);
			value.Last = ((Component)target).transform.position;
			if (Plugin.Debug.Value)
			{
				Plugin.Log.LogInfo((object)("  " + ((Object)target).name + " has " + string.Join(", ", value.Arrows.Select((KeyValuePair<string, KeyValuePair<ItemData, int>> kv) => kv.Value.Value + " " + kv.Key)) + " stuck in it"));
			}
		}

		public static void OnDeath(Character target)
		{
			//IL_0038: 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)
			if (Hit.Count != 0 && !((Object)(object)target == (Object)null) && Hit.TryGetValue(((Object)target).GetInstanceID(), out var value))
			{
				value.Died = true;
				value.Last = ((Component)target).transform.position;
			}
		}

		public static void OnRagdoll(Ragdoll ragdoll)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			if (Hit.Count != 0 && !((Object)(object)ragdoll == (Object)null))
			{
				Bodies.Add(new Body
				{
					Name = Utils.GetPrefabName(((Component)ragdoll).gameObject),
					At = ((Component)ragdoll).transform.position,
					Time = Time.time
				});
			}
		}

		public static void Tick()
		{
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			if (Hit.Count == 0)
			{
				Bodies.Clear();
			}
			else
			{
				if (Time.time < _next)
				{
					return;
				}
				_next = Time.time + 0.25f;
				Bodies.RemoveAll((Body b) => Time.time - b.Time > 5f);
				foreach (int item in Hit.Keys.ToList())
				{
					Entry entry = Hit[item];
					bool flag = (Object)(object)entry.Target == (Object)null;
					if (!flag)
					{
						entry.Last = ((Component)entry.Target).transform.position;
						entry.Seen = Time.time;
						if (entry.Target.IsDead() || entry.Target.GetHealth() <= 0f)
						{
							entry.Died = true;
						}
					}
					if (!entry.Died && flag && FoundBody(entry))
					{
						entry.Died = true;
					}
					if (entry.Died)
					{
						Drop(entry);
						Hit.Remove(item);
					}
					else if (flag && Time.time - entry.Seen > 3f)
					{
						if (Plugin.Debug.Value)
						{
							Plugin.Log.LogInfo((object)("  " + entry.Name + " with arrows in it went away without dying: they stay with it"));
						}
						Hit.Remove(item);
					}
					else if (!flag && Time.time - entry.LastHit > 300f)
					{
						Hit.Remove(item);
					}
				}
			}
		}

		private static bool FoundBody(Entry e)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			if (e.Ragdolls == null || e.Ragdolls.Count == 0)
			{
				return false;
			}
			foreach (Body body in Bodies)
			{
				if (body.Time >= e.Seen - 1f && e.Ragdolls.Contains(body.Name) && Vector3.Distance(body.At, e.Last) < 8f)
				{
					return true;
				}
			}
			return false;
		}

		private static HashSet<string> RagdollNames(Character target)
		{
			HashSet<string> hashSet = new HashSet<string>();
			if (target.m_deathEffects?.m_effectPrefabs == null)
			{
				return hashSet;
			}
			EffectData[] effectPrefabs = target.m_deathEffects.m_effectPrefabs;
			foreach (EffectData val in effectPrefabs)
			{
				if (val != null && val.m_enabled && (Object)(object)val.m_prefab != (Object)null && (Object)(object)val.m_prefab.GetComponent<Ragdoll>() != (Object)null)
				{
					hashSet.Add(((Object)val.m_prefab).name);
				}
			}
			return hashSet;
		}

		private static void Drop(Entry e)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = e.Last + Vector3.up * 0.4f;
			foreach (KeyValuePair<ItemData, int> value in e.Arrows.Values)
			{
				ItemData val2 = value.Key.Clone();
				val2.m_stack = value.Value;
				val2.m_equipped = false;
				ItemDrop.DropItem(val2, value.Value, val + Random.insideUnitSphere * 0.3f, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f));
				if (Plugin.Debug.Value)
				{
					Plugin.Log.LogInfo((object)$"  {e.Name} died: {value.Value} {((Object)value.Key.m_dropPrefab).name} dropped with its loot");
				}
			}
		}

		public static void Clear()
		{
			Hit.Clear();
			Bodies.Clear();
		}
	}
	[HarmonyPatch(typeof(Character), "OnDeath")]
	internal static class Character_OnDeath_Stuck
	{
		private static void Prefix(Character __instance)
		{
			Stuck.OnDeath(__instance);
		}
	}
	[HarmonyPatch(typeof(Ragdoll), "Awake")]
	internal static class Ragdoll_Awake_Stuck
	{
		private static void Postfix(Ragdoll __instance)
		{
			Stuck.OnRagdoll(__instance);
		}
	}
}
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 sealed class ServerSettings : IDisposable
	{
		private readonly string _send;

		private readonly string _ask;

		private readonly ConfigFile _config;

		private readonly ManualLogSource _log;

		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 ZRoutedRpc _registeredOn;

		private bool _applying;

		private bool _changePending;

		private float _nextChangeSend;

		private const float ChangeSendGap = 0.5f;

		public bool FromServer => _server.Count > 0;

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

		public ServerSettings(string guid, ConfigFile config, ManualLogSource log)
		{
			_send = guid + ".settings";
			_ask = guid + ".settings.ask";
			_config = config;
			_log = log;
		}

		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;
			return entry;
		}

		public void Update()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != _registeredOn)
			{
				Unregister();
				Restore();
				_changePending = false;
				if (instance != null)
				{
					Register(instance);
				}
			}
			if (_changePending && Time.unscaledTime >= _nextChangeSend)
			{
				SendChange();
			}
		}

		public void Dispose()
		{
			Unregister();
			Restore();
			foreach (ConfigEntryBase entry in _entries)
			{
				Unsubscribe(entry);
			}
			_entries.Clear();
		}

		private void Register(ZRoutedRpc rpc)
		{
			Forget(rpc, _send);
			Forget(rpc, _ask);
			rpc.Register<ZPackage>(_send, (Action<long, ZPackage>)OnValues);
			rpc.Register(_ask, (Action<long>)OnAsk);
			rpc.m_onNewPeer = (Action<long>)Delegate.Combine(rpc.m_onNewPeer, new Action<long>(OnNewPeer));
			_registeredOn = rpc;
		}

		private void Unregister()
		{
			if (_registeredOn != null)
			{
				ZRoutedRpc registeredOn = _registeredOn;
				registeredOn.m_onNewPeer = (Action<long>)Delegate.Remove(registeredOn.m_onNewPeer, new Action<long>(OnNewPeer));
				Forget(_registeredOn, _send);
				Forget(_registeredOn, _ask);
				_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 void OnNewPeer(long peer)
		{
			if (IsServer)
			{
				Send(peer);
			}
			else if ((Object)(object)ZNet.instance != (Object)null)
			{
				ZNetPeer serverPeer = ZNet.instance.GetServerPeer();
				if (serverPeer != null && serverPeer.m_uid == peer)
				{
					Ask();
				}
			}
		}

		private void OnAsk(long sender)
		{
			if (IsServer)
			{
				Send(sender);
			}
		}

		private void Ask()
		{
			try
			{
				ZRoutedRpc instance = ZRoutedRpc.instance;
				if (instance != null)
				{
					instance.InvokeRoutedRPC(ZNet.instance.GetServerPeer().m_uid, _ask, Array.Empty<object>());
				}
			}
			catch (Exception)
			{
			}
		}

		private void Send(long target)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			if (ZRoutedRpc.instance == null || _entries.Count == 0)
			{
				return;
			}
			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));
			}
			ZRoutedRpc.instance.InvokeRoutedRPC(target, _send, new object[1] { val });
		}

		private void OnValues(long sender, ZPackage pkg)
		{
			if (IsServer)
			{
				return;
			}
			ZNetPeer val = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetServerPeer() : null);
			if (val == null || val.m_uid != sender)
			{
				return;
			}
			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 val2 = ((IEnumerable<ConfigEntryBase>)_entries).FirstOrDefault((Func<ConfigEntryBase, bool>)((ConfigEntryBase x) => x.Definition.Section == section && x.Definition.Key == key));
					if (val2 != null)
					{
						object obj;
						try
						{
							obj = TomlTypeConverter.ConvertToValue(text, val2.SettingType);
						}
						catch (Exception)
						{
							continue;
						}
						if (!_own.ContainsKey(val2))
						{
							_own[val2] = val2.BoxedValue;
						}
						_server[val2] = obj;
						if (!object.Equals(val2.BoxedValue, obj))
						{
							Apply(val2, obj);
							list.Add(section + "/" + key + " = " + text);
						}
					}
				}
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogInfo((object)($"Settings from the server apply while you play here ({_server.Count})" + ((list.Count > 0) ? (": " + string.Join(", ", list.ToArray())) : "")));
				}
			}
			catch (Exception ex2)
			{
				ManualLogSource log2 = _log;
				if (log2 != null)
				{
					log2.LogWarning((object)("Could not read the server's settings: " + ex2.Message));
				}
			}
		}

		private void Apply(ConfigEntryBase e, object value)
		{
			bool saveOnConfigSet = _config.SaveOnConfigSet;
			_applying = true;
			try
			{
				_config.SaveOnConfigSet = false;
				e.BoxedValue = value;
			}
			finally
			{
				_config.SaveOnConfigSet = saveOnConfigSet;
				_applying = false;
			}
		}

		private void Restore()
		{
			if (_server.Count == 0)
			{
				return;
			}
			foreach (KeyValuePair<ConfigEntryBase, object> item in _own)
			{
				Apply(item.Key, item.Value);
			}
			_own.Clear();
			_server.Clear();
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogInfo((object)"Your own settings apply again");
			}
		}

		private void OnChanged(object sender, EventArgs args)
		{
			if (_applying)
			{
				return;
			}
			ConfigEntryBase val = (ConfigEntryBase)((sender is ConfigEntryBase) ? sender : null);
			if (val == null)
			{
				return;
			}
			if (_server.TryGetValue(val, out var value))
			{
				_own[val] = val.BoxedValue;
				Apply(val, value);
			}
			else if (IsServer)
			{
				_changePending = true;
				if (Time.unscaledTime >= _nextChangeSend)
				{
					SendChange();
				}
			}
		}

		private void SendChange()
		{
			_changePending = false;
			_nextChangeSend = Time.unscaledTime + 0.5f;
			if (IsServer && ZNet.instance.GetPeers().Count > 0)
			{
				Send(0L);
			}
		}

		private void Unsubscribe(ConfigEntryBase e)
		{
			((object)e).GetType().GetEvent("SettingChanged")?.RemoveEventHandler(e, new EventHandler(OnChanged));
		}
	}
}