Decompiled source of HerdBell v1.0.3

plugins/HerdBell.dll

Decompiled 20 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace HerdBellMod;

internal static class BellVisuals
{
	private static AudioClip s_clip;

	private static AudioMixerGroup s_mixer;

	private static bool s_mixerSearched;

	internal static AudioClip BellClip
	{
		get
		{
			if ((Object)(object)s_clip != (Object)null)
			{
				return s_clip;
			}
			float num = 2.4f;
			int num2 = (int)(44100f * num);
			float[] array = new float[num2];
			float[] array2 = new float[3] { 0f, 0.42f, 0.86f };
			float[] array3 = new float[3] { 1f, 0.8f, 0.9f };
			float[] array4 = new float[6] { 1f, 2.03f, 2.74f, 3.92f, 5.41f, 6.8f };
			float[] array5 = new float[6] { 1f, 0.55f, 0.42f, 0.28f, 0.17f, 0.1f };
			float[] array6 = new float[6] { 1.1f, 0.65f, 0.45f, 0.32f, 0.22f, 0.15f };
			Random random = new Random(7);
			for (int i = 0; i < array2.Length; i++)
			{
				int num3 = (int)(array2[i] * 44100f);
				for (int j = num3; j < num2; j++)
				{
					float num4 = (float)(j - num3) / 44100f;
					float num5 = 0f;
					for (int k = 0; k < array4.Length; k++)
					{
						num5 += array5[k] * Mathf.Exp((0f - num4) / array6[k]) * Mathf.Sin((float)Math.PI * 1280f * array4[k] * num4 + (float)k);
					}
					if (num4 < 0.004f)
					{
						num5 += (float)(random.NextDouble() * 2.0 - 1.0) * (1f - num4 / 0.004f) * 0.6f;
					}
					array[j] += num5 * array3[i];
				}
			}
			float num6 = 0.0001f;
			for (int l = 0; l < num2; l++)
			{
				num6 = Mathf.Max(num6, Mathf.Abs(array[l]));
			}
			float num7 = 0.85f / num6;
			int num8 = 4410;
			for (int m = 0; m < num2; m++)
			{
				array[m] *= num7;
				if (m > num2 - num8)
				{
					array[m] *= (float)(num2 - m) / (float)num8;
				}
			}
			s_clip = AudioClip.Create("anwo_herd_bell", num2, 1, 44100, false);
			s_clip.SetData(array, 0);
			return s_clip;
		}
	}

	internal static AudioMixerGroup SfxMixer
	{
		get
		{
			if (s_mixerSearched)
			{
				return s_mixer;
			}
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return null;
			}
			s_mixerSearched = true;
			try
			{
				foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
				{
					if (!((Object)(object)prefab == (Object)null) && ((Object)prefab).name.StartsWith("sfx_", StringComparison.Ordinal))
					{
						AudioSource componentInChildren = prefab.GetComponentInChildren<AudioSource>(true);
						if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.outputAudioMixerGroup != (Object)null)
						{
							s_mixer = componentInChildren.outputAudioMixerGroup;
							break;
						}
					}
				}
				if ((Object)(object)s_mixer == (Object)null && (Object)(object)AudioMan.instance != (Object)null)
				{
					s_mixer = AudioMan.instance.m_ambientMixer;
				}
			}
			catch (Exception ex)
			{
				HerdBellPlugin.Log.LogDebug((object)("Looking up the sound mixer failed: " + ex.Message));
			}
			return s_mixer;
		}
	}

	internal static Transform Decorate(GameObject post)
	{
		//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_0009: 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_0080: Expected O, but got Unknown
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: 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_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_019c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d6: 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_00f3: 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)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_020a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0224: Unknown result type (might be due to invalid IL or missing references)
		//IL_0229: Unknown result type (might be due to invalid IL or missing references)
		//IL_0238: Unknown result type (might be due to invalid IL or missing references)
		//IL_023d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0249: Unknown result type (might be due to invalid IL or missing references)
		//IL_025c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0271: Unknown result type (might be due to invalid IL or missing references)
		//IL_027b: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b1: Expected O, but got Unknown
		//IL_02b1: 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_02db: Expected O, but got Unknown
		//IL_02db: Unknown result type (might be due to invalid IL or missing references)
		//IL_0302: Unknown result type (might be due to invalid IL or missing references)
		//IL_0307: Unknown result type (might be due to invalid IL or missing references)
		//IL_0311: Expected O, but got Unknown
		//IL_0311: Unknown result type (might be due to invalid IL or missing references)
		//IL_0338: Unknown result type (might be due to invalid IL or missing references)
		//IL_033d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0347: Expected O, but got Unknown
		//IL_0347: Unknown result type (might be due to invalid IL or missing references)
		//IL_035c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0377: Unknown result type (might be due to invalid IL or missing references)
		//IL_037c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0386: Expected O, but got Unknown
		//IL_039d: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b6: Unknown result type (might be due to invalid IL or missing references)
		Bounds val = LocalBounds(post);
		float y = ((Bounds)(ref val)).max.y;
		Material val2 = FirstMaterial(post);
		Material val3 = ItemMaterial("Bronze", "Copper", "Tin");
		Material val4 = ItemMaterial("LeatherScraps", "DeerHide");
		if ((Object)(object)val3 == (Object)null)
		{
			val3 = val2;
		}
		if ((Object)(object)val4 == (Object)null)
		{
			val4 = val2;
		}
		GameObject val5 = new GameObject("anwo_bell_gear");
		val5.layer = post.layer;
		val5.transform.SetParent(post.transform, false);
		val5.transform.localPosition = new Vector3(((Bounds)(ref val)).center.x, y, ((Bounds)(ref val)).center.z);
		if (PostMesh(post, out var mesh, out var materials))
		{
			AddMeshPart(val5, "beam", mesh, materials, new Vector3(1f, 0.12f, 0.12f), new Vector3(0.42f, -0.06f, 0f), Quaternion.identity);
			AddMeshPart(val5, "brace", mesh, materials, new Vector3(0.55f, 0.08f, 0.08f), new Vector3(0.2f, -0.32f, 0f), Quaternion.Euler(0f, 0f, 45f));
		}
		else
		{
			AddPart(val5, "beam", Box(new Vector3(1f, 0.12f, 0.12f)), val2, new Vector3(0.42f, -0.06f, 0f), Quaternion.identity);
			AddPart(val5, "brace", Box(new Vector3(0.55f, 0.08f, 0.08f)), val2, new Vector3(0.2f, -0.32f, 0f), Quaternion.Euler(0f, 0f, 45f));
		}
		AddPart(val5, "cap", Box(new Vector3(0.2f, 0.04f, 0.2f)), val3, new Vector3(0f, 0.02f, 0f), Quaternion.identity);
		GameObject val6 = new GameObject("anwo_bell_swing")
		{
			layer = post.layer
		};
		val6.transform.SetParent(val5.transform, false);
		val6.transform.localPosition = new Vector3(0.82f, -0.12f, 0f);
		AddPart(val6, "hanger", Cylinder(0.018f, 0.1f, 10), val3, new Vector3(0f, -0.05f, 0f), Quaternion.identity);
		AddPart(val6, "bell", BellMesh(), val3, new Vector3(0f, -0.42f, 0f), Quaternion.identity);
		AddPart(val6, "clapper", Cylinder(0.035f, 0.07f, 12), val3, new Vector3(0f, -0.43f, 0f), Quaternion.identity);
		AddPart(val6, "pull_rope", Cylinder(0.012f, 0.75f, 8), val4, new Vector3(0f, -0.83f, 0f), Quaternion.identity);
		AddPart(val6, "pull_knot", Box(new Vector3(0.05f, 0.08f, 0.05f)), val4, new Vector3(0f, -1.22f, 0f), Quaternion.identity);
		BoxCollider obj = val5.AddComponent<BoxCollider>();
		obj.center = new Vector3(0.82f, -0.38f, 0f);
		obj.size = new Vector3(0.42f, 0.44f, 0.42f);
		return val6.transform;
	}

	private static Mesh BellMesh()
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: 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_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: 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_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_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: 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_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: 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_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: 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)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: 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_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_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		//IL_016f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_0185: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Expected O, but got Unknown
		//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)
		Vector2[] profile = (Vector2[])(object)new Vector2[8]
		{
			new Vector2(0f, 0.33f),
			new Vector2(0.05f, 0.33f),
			new Vector2(0.09f, 0.31f),
			new Vector2(0.11f, 0.27f),
			new Vector2(0.115f, 0.2f),
			new Vector2(0.125f, 0.12f),
			new Vector2(0.15f, 0.05f),
			new Vector2(0.185f, 0f)
		};
		Vector2[] profile2 = (Vector2[])(object)new Vector2[2]
		{
			new Vector2(0.185f, 0f),
			new Vector2(0.16f, 0f)
		};
		Vector2[] profile3 = new Vector2[7]
		{
			new Vector2(0.16f, 0f),
			new Vector2(0.13f, 0.05f),
			new Vector2(0.105f, 0.12f),
			new Vector2(0.095f, 0.2f),
			new Vector2(0.09f, 0.26f),
			new Vector2(0.06f, 0.295f),
			new Vector2(0f, 0.3f)
		};
		List<Vector3> list = new List<Vector3>();
		List<Vector2> list2 = new List<Vector2>();
		List<int> list3 = new List<int>();
		Revolve(profile, 28, list, list2, list3);
		Revolve(profile2, 28, list, list2, list3);
		Revolve((Vector2[])(object)profile3, 28, list, list2, list3);
		Mesh val = new Mesh();
		((Object)val).name = "anwo_bell";
		val.SetVertices(list);
		val.SetUVs(0, list2);
		Color[] array = (Color[])(object)new Color[list.Count];
		for (int i = 0; i < array.Length; i++)
		{
			array[i] = Color.white;
		}
		val.colors = array;
		val.SetTriangles(list3, 0);
		val.RecalculateNormals();
		val.RecalculateBounds();
		val.RecalculateTangents();
		return val;
	}

	private static void Revolve(Vector2[] profile, int segments, List<Vector3> v, List<Vector2> uv, List<int> t)
	{
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		int count = v.Count;
		int num = segments + 1;
		for (int i = 0; i < profile.Length; i++)
		{
			for (int j = 0; j <= segments; j++)
			{
				float num2 = (float)j / (float)segments * (float)Math.PI * 2f;
				v.Add(new Vector3(profile[i].x * Mathf.Cos(num2), profile[i].y, profile[i].x * Mathf.Sin(num2)));
				uv.Add(new Vector2((float)j / (float)segments, (float)i / (float)Mathf.Max(1, profile.Length - 1)));
			}
		}
		for (int k = 0; k < profile.Length - 1; k++)
		{
			for (int l = 0; l < segments; l++)
			{
				int num3 = count + k * num + l;
				int num4 = count + (k + 1) * num + l;
				int item = num4 + 1;
				int item2 = num3 + 1;
				t.Add(num3);
				t.Add(item);
				t.Add(num4);
				t.Add(num3);
				t.Add(item2);
				t.Add(item);
			}
		}
	}

	private static Bounds LocalBounds(GameObject root)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: 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_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: 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_0136: 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_012c: 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_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: 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_00df: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
		Matrix4x4 worldToLocalMatrix = root.transform.worldToLocalMatrix;
		bool flag = false;
		Bounds result = default(Bounds);
		MeshFilter[] componentsInChildren = root.GetComponentsInChildren<MeshFilter>(true);
		foreach (MeshFilter val in componentsInChildren)
		{
			if ((Object)(object)val.sharedMesh == (Object)null)
			{
				continue;
			}
			Matrix4x4 val2 = worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix;
			Bounds bounds = val.sharedMesh.bounds;
			for (int j = 0; j < 8; j++)
			{
				Vector3 val3 = ((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3(((j & 1) == 0) ? (-1f) : 1f, ((j & 2) == 0) ? (-1f) : 1f, ((j & 4) == 0) ? (-1f) : 1f));
				Vector3 val4 = ((Matrix4x4)(ref val2)).MultiplyPoint3x4(val3);
				if (!flag)
				{
					((Bounds)(ref result))..ctor(val4, Vector3.zero);
					flag = true;
				}
				else
				{
					((Bounds)(ref result)).Encapsulate(val4);
				}
			}
		}
		if (!flag)
		{
			((Bounds)(ref result))..ctor(new Vector3(0f, 1f, 0f), new Vector3(0.2f, 2f, 0.2f));
		}
		return result;
	}

	private static Material FirstMaterial(GameObject root)
	{
		MeshRenderer[] componentsInChildren = root.GetComponentsInChildren<MeshRenderer>(true);
		foreach (MeshRenderer val in componentsInChildren)
		{
			if ((Object)(object)((Renderer)val).sharedMaterial != (Object)null)
			{
				return ((Renderer)val).sharedMaterial;
			}
		}
		return null;
	}

	private static Material ItemMaterial(params string[] names)
	{
		foreach (string text in names)
		{
			GameObject val = null;
			try
			{
				val = PrefabManager.Instance.GetPrefab(text);
			}
			catch
			{
			}
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			MeshRenderer[] componentsInChildren = val.GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val2 in componentsInChildren)
			{
				if ((Object)(object)((Renderer)val2).sharedMaterial != (Object)null)
				{
					return ((Renderer)val2).sharedMaterial;
				}
			}
		}
		return null;
	}

	private static bool PostMesh(GameObject post, out Mesh mesh, out Material[] materials)
	{
		mesh = null;
		materials = null;
		MeshRenderer[] componentsInChildren = post.GetComponentsInChildren<MeshRenderer>(true);
		foreach (MeshRenderer val in componentsInChildren)
		{
			MeshFilter component = ((Component)val).GetComponent<MeshFilter>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.sharedMesh == (Object)null || (Object)(object)((Renderer)val).sharedMaterial == (Object)null)
			{
				continue;
			}
			string text = PathOf(((Component)val).transform, post.transform).ToLowerInvariant();
			if (!text.Contains("worn") && !text.Contains("broken") && !text.Contains("anwo_") && !text.Contains("lod1") && !text.Contains("lod2"))
			{
				bool flag = text.Contains("new");
				if ((Object)(object)mesh == (Object)null || flag)
				{
					mesh = component.sharedMesh;
					materials = ((Renderer)val).sharedMaterials;
				}
				if (flag)
				{
					break;
				}
			}
		}
		return (Object)(object)mesh != (Object)null;
	}

	private static string PathOf(Transform t, Transform root)
	{
		string text = ((Object)t).name;
		Transform parent = t.parent;
		while ((Object)(object)parent != (Object)null && (Object)(object)parent != (Object)(object)root)
		{
			text = ((Object)parent).name + "/" + text;
			parent = parent.parent;
		}
		return text;
	}

	private static void AddMeshPart(GameObject parent, string name, Mesh mesh, Material[] materials, Vector3 size, Vector3 position, Quaternion rotation)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected O, but got Unknown
		//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)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: 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_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_016f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0175: Unknown result type (might be due to invalid IL or missing references)
		//IL_017c: 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_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject(name);
		val.layer = parent.layer;
		val.transform.SetParent(parent.transform, false);
		val.transform.localPosition = position;
		val.transform.localRotation = rotation;
		Bounds bounds = mesh.bounds;
		float num = Mathf.Max(((Bounds)(ref bounds)).size.x, 0.001f);
		float num2 = Mathf.Max(((Bounds)(ref bounds)).size.y, 0.001f);
		float num3 = Mathf.Max(((Bounds)(ref bounds)).size.z, 0.001f);
		Quaternion val2;
		Vector3 val3 = default(Vector3);
		if (num >= num2 && num >= num3)
		{
			val2 = Quaternion.identity;
			((Vector3)(ref val3))..ctor(size.x / num, size.y / num2, size.z / num3);
		}
		else if (num2 >= num3)
		{
			val2 = Quaternion.Euler(0f, 0f, -90f);
			((Vector3)(ref val3))..ctor(size.y / num, size.x / num2, size.z / num3);
		}
		else
		{
			val2 = Quaternion.Euler(0f, 90f, 0f);
			((Vector3)(ref val3))..ctor(size.z / num, size.y / num2, size.x / num3);
		}
		GameObject val4 = new GameObject("mesh")
		{
			layer = parent.layer
		};
		val4.transform.SetParent(val.transform, false);
		val4.transform.localRotation = val2;
		val4.transform.localScale = val3;
		val4.transform.localPosition = -(val2 * Vector3.Scale(((Bounds)(ref bounds)).center, val3));
		val4.AddComponent<MeshFilter>().sharedMesh = mesh;
		MeshRenderer obj = val4.AddComponent<MeshRenderer>();
		((Renderer)obj).sharedMaterials = materials;
		((Renderer)obj).shadowCastingMode = (ShadowCastingMode)1;
		((Renderer)obj).receiveShadows = true;
	}

	private static void AddPart(GameObject parent, string name, Mesh mesh, Material material, Vector3 position, Quaternion rotation)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: 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_0031: 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_003e: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject(name)
		{
			layer = parent.layer
		};
		val.transform.SetParent(parent.transform, false);
		val.transform.localPosition = position;
		val.transform.localRotation = rotation;
		val.AddComponent<MeshFilter>().sharedMesh = mesh;
		MeshRenderer obj = val.AddComponent<MeshRenderer>();
		((Renderer)obj).sharedMaterial = material;
		((Renderer)obj).shadowCastingMode = (ShadowCastingMode)1;
		((Renderer)obj).receiveShadows = true;
	}

	private static Mesh Finish(string name, List<Vector3> v, List<Vector3> n, List<Vector2> uv, List<int> tris)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		Mesh val = new Mesh();
		((Object)val).name = name;
		val.SetVertices(v);
		val.SetNormals(n);
		val.SetUVs(0, uv);
		Color[] array = (Color[])(object)new Color[v.Count];
		for (int i = 0; i < array.Length; i++)
		{
			array[i] = Color.white;
		}
		val.colors = array;
		val.SetTriangles(tris, 0);
		val.RecalculateBounds();
		val.RecalculateTangents();
		return val;
	}

	internal static Mesh Cylinder(float radius, float height, int segments)
	{
		//IL_0058: 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_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_014a: 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_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0169: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0206: Unknown result type (might be due to invalid IL or missing references)
		List<Vector3> list = new List<Vector3>();
		List<Vector3> list2 = new List<Vector3>();
		List<Vector2> list3 = new List<Vector2>();
		List<int> list4 = new List<int>();
		float num = height * 0.5f;
		Vector3 val = default(Vector3);
		for (int i = 0; i <= segments; i++)
		{
			float num2 = (float)i / (float)segments * (float)Math.PI * 2f;
			((Vector3)(ref val))..ctor(Mathf.Cos(num2), 0f, Mathf.Sin(num2));
			list.Add(val * radius + Vector3.down * num);
			list2.Add(val);
			list3.Add(new Vector2((float)i / (float)segments, 0f));
			list.Add(val * radius + Vector3.up * num);
			list2.Add(val);
			list3.Add(new Vector2((float)i / (float)segments, 1f));
		}
		for (int j = 0; j < segments; j++)
		{
			int num3 = j * 2;
			int item = num3 + 1;
			int item2 = num3 + 3;
			int item3 = num3 + 2;
			list4.Add(num3);
			list4.Add(item);
			list4.Add(item3);
			list4.Add(item3);
			list4.Add(item);
			list4.Add(item2);
		}
		Vector3 val3 = default(Vector3);
		for (int k = 0; k < 2; k++)
		{
			Vector3 val2 = ((k == 0) ? Vector3.down : Vector3.up);
			int count = list.Count;
			list.Add(val2 * num);
			list2.Add(val2);
			list3.Add(new Vector2(0.5f, 0.5f));
			for (int l = 0; l <= segments; l++)
			{
				float num4 = (float)l / (float)segments * (float)Math.PI * 2f;
				((Vector3)(ref val3))..ctor(Mathf.Cos(num4), 0f, Mathf.Sin(num4));
				list.Add(val3 * radius + val2 * num);
				list2.Add(val2);
				list3.Add(new Vector2(0.5f + val3.x * 0.5f, 0.5f + val3.z * 0.5f));
			}
			for (int m = 0; m < segments; m++)
			{
				if (k == 0)
				{
					list4.Add(count);
					list4.Add(count + 1 + m);
					list4.Add(count + 2 + m);
				}
				else
				{
					list4.Add(count);
					list4.Add(count + 2 + m);
					list4.Add(count + 1 + m);
				}
			}
		}
		return Finish("anwo_cylinder", list, list2, list3, list4);
	}

	internal static Mesh Box(Vector3 size)
	{
		//IL_0018: 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_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: 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_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: 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_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: 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_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//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_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: 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_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: 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_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_0179: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		List<Vector3> list = new List<Vector3>();
		List<Vector3> list2 = new List<Vector3>();
		List<Vector2> list3 = new List<Vector2>();
		List<int> list4 = new List<int>();
		Vector3 val = size * 0.5f;
		Vector3[] array = (Vector3[])(object)new Vector3[6]
		{
			Vector3.right,
			Vector3.left,
			Vector3.up,
			Vector3.down,
			Vector3.forward,
			Vector3.back
		};
		foreach (Vector3 val2 in array)
		{
			Vector3 val3 = ((val2.y != 0f) ? Vector3.forward : Vector3.up);
			Vector3 val4 = Vector3.Cross(val2, val3);
			int count = list.Count;
			Vector3 val5 = Vector3.Scale(val2, val);
			Vector3 val6 = Vector3.Scale(val3, val);
			Vector3 val7 = Vector3.Scale(val4, val);
			list.Add(val5 - val6 - val7);
			list.Add(val5 - val6 + val7);
			list.Add(val5 + val6 + val7);
			list.Add(val5 + val6 - val7);
			for (int j = 0; j < 4; j++)
			{
				list2.Add(val2);
			}
			list3.Add(new Vector2(0f, 0f));
			list3.Add(new Vector2(1f, 0f));
			list3.Add(new Vector2(1f, 1f));
			list3.Add(new Vector2(0f, 1f));
			list4.Add(count);
			list4.Add(count + 2);
			list4.Add(count + 1);
			list4.Add(count);
			list4.Add(count + 3);
			list4.Add(count + 2);
		}
		return Finish("anwo_box", list, list2, list3, list4);
	}
}
internal static class CreatureYields
{
	internal delegate ConfigEntry<string> Binder(string section, string key, string value, string description);

	internal const string Section = "4 - Creature yields";

	internal const string NoneWord = "none";

	private static readonly string[][] Table = new string[77][]
	{
		new string[3] { "Boar", null, "LeatherScraps 1-2" },
		new string[3] { "Deer", null, "DeerHide 1-2" },
		new string[3] { "Greyling", null, "Resin 1-2" },
		new string[3] { "Hen", null, "Feathers 1-2" },
		new string[3] { "Neck", null, "NeckTail 1" },
		new string[3] { "Eikthyr", null, "DeerHide 2-3, HardAntler 1 25%" },
		new string[3] { "Greydwarf", null, "Wood 1-2, Resin 1, GreydwarfEye 1 25%" },
		new string[3] { "Greydwarf_Elite", "Greydwarf brute", "Wood 2-4, GreydwarfEye 1 50%, AncientSeed 1 10%" },
		new string[3] { "Greydwarf_Shaman", "Greydwarf shaman", "Resin 1-2, GreydwarfEye 1 50%" },
		new string[3] { "Skeleton", null, "BoneFragments 1-2" },
		new string[3] { "Ghost", null, "Ectoplasm 1-2" },
		new string[3] { "Troll", null, "TrollHide 1-2" },
		new string[3] { "Bjorn", "Bear", "BjornHide 1-2" },
		new string[3] { "gd_king", "The Elder", "ElderBark 2-4, AncientSeed 1 25%" },
		new string[3] { "Blob", null, "Ooze 1-2" },
		new string[3] { "BlobElite", "Oozer", "Ooze 2-3, IronScrap 1 25%" },
		new string[3] { "Draugr", null, "Entrails 1-2" },
		new string[3] { "Draugr_Elite", "Draugr elite", "Entrails 2-3" },
		new string[3] { "Leech", null, "Bloodbag 1" },
		new string[3] { "Skeleton_Poison", "Rancid remains", "BoneFragments 2-3" },
		new string[3] { "Surtling", null, "Coal 2-3, SurtlingCore 1 25%" },
		new string[3] { "Wraith", null, "Chain 1" },
		new string[3] { "Abomination", null, "Root 1-2, Guck 1-2" },
		new string[3] { "Unbjorn", "Vile", "UndeadBjornRibcage 1-2, BjornHide 1 50%" },
		new string[3] { "BogWitchKvastur", "Kvastur", "Wood 1-2, Resin 1-2" },
		new string[3] { "Bonemass", null, "Guck 2-4, BoneFragments 2-4" },
		new string[3] { "Wolf", null, "WolfPelt 1, WolfFang 1 25%" },
		new string[3] { "Ulv", null, "WolfFang 1" },
		new string[3] { "Bat", null, "LeatherScraps 1" },
		new string[3] { "Hatchling", "Drake", "FreezeGland 1-2" },
		new string[3] { "StoneGolem", "Stone golem", "Crystal 2-4" },
		new string[3] { "Fenring", null, "WolfFang 1-2" },
		new string[3] { "Fenring_Cultist", "Cultist", "JuteRed 1-2" },
		new string[3] { "TrollFrost", null, "TrollHide 1-2" },
		new string[3] { "Dragon", "Moder", "FreezeGland 2-3, Crystal 2-4, DragonEgg 1 10%" },
		new string[3] { "Lox", null, "LoxPelt 1" },
		new string[3] { "Deathsquito", null, "Needle 1" },
		new string[3] { "Goblin", "Fuling", "BlackMetalScrap 1-2" },
		new string[3] { "GoblinBrute", "Fuling berserker", "BlackMetalScrap 2-3, GoblinTotem 1 5%" },
		new string[3] { "GoblinShaman", "Fuling shaman", "BlackMetalScrap 1-2" },
		new string[3] { "BlobTar", "Growth", "Tar 1-2" },
		new string[3] { "GoblinKing", "Yagluth", "BlackMetalScrap 3-5, GoblinTotem 1 10%" },
		new string[3] { "Seeker", null, "Carapace 1-2" },
		new string[3] { "SeekerBrute", "Seeker soldier", "Carapace 2-3, Mandible 1 25%" },
		new string[3] { "Tick", null, "GiantBloodSack 1" },
		new string[3] { "Gjall", null, "Bilebag 1" },
		new string[3] { "Hare", null, "ScaleHide 1-2" },
		new string[3] { "Dverger", "Dvergr", "BlackMarble 1-2, Softtissue 1 25%" },
		new string[3] { "SeekerQueen", "The Queen", "Carapace 3-5, RoyalJelly 1-2" },
		new string[3] { "Asksvin", null, "AskHide 1-2, AskBladder 1 25%" },
		new string[3] { "Charred_Melee", "Charred warrior", "CharredBone 1-2" },
		new string[3] { "Charred_Archer", "Charred marksman", "CharredBone 1-2" },
		new string[3] { "Charred_Mage", "Charred warlock", "CharredBone 1-2" },
		new string[3] { "Charred_Twitcher", "Charred twitcher", "CharredBone 1" },
		new string[3] { "Morgen", null, "MorgenSinew 1-2" },
		new string[3] { "Volture", null, "Feathers 1-2, VoltureEgg 1 25%" },
		new string[3] { "BlobLava", "Lava blob", "SulfurStone 1-2, ProustitePowder 1 50%" },
		new string[3] { "BonemawSerpent", "Bonemaw", "BonemawSerpentTooth 2-4" },
		new string[3] { "FallenValkyrie", "Fallen Valkyrie", "CelestialFeather 1-2" },
		new string[3] { "Charred_Melee_Dyrnwyn", "Lord Reto", "CharredBone 2-3" },
		new string[3] { "Fader", null, "SulfurStone 2-4, ProustitePowder 1-2" },
		new string[3] { "Serpent", null, "SerpentScale 2-4" },
		new string[3] { "Moose", null, "MooseHide 1-2, MooseSinew 1 50%" },
		new string[3] { "Seal", null, "SealHide 1-2, SealBlubber 1 25%" },
		new string[3] { "GoblinDeepNorth", null, "Lingonberry 1-3" },
		new string[3] { "Elaking", null, "ElakingHairBundle 1-2" },
		new string[3] { "ElakingMole", null, "MoleClaws 1" },
		new string[3] { "BlobMorkMini", null, "OozeMork 1" },
		new string[3] { "BlobMork", null, "OozeMork 1-2" },
		new string[3] { "BlobFrost", null, "Crystal 1-2" },
		new string[3] { "Frysling", null, "FrostCore 1" },
		new string[3] { "Writhan", null, "WrithanRoots 1-2" },
		new string[3] { "Barka", null, "BarkaBranch 1" },
		new string[3] { "JotunWitch", null, "NornThread 1-2" },
		new string[3] { "JotunWarriorDualWield", null, "Leatherstraps 1-2" },
		new string[3] { "rae_OdinHorse", "Odin horse (OdinHorse)", "rae_HorseHide 1" },
		new string[3] { "BestestDog", "Dog (GoodestBoy)", "BoneFragments 1-2" }
	};

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

	internal static int Count => Table.Length;

	internal static void Bind(Binder bind, Action changed)
	{
		string[][] table = Table;
		foreach (string[] array in table)
		{
			string text = array[0];
			string text2 = ((array[1] != null) ? (array[1] + " (" + text + ")") : text);
			string description = "What a tamed " + text2 + " yields: Item min-max chance%, separated by commas. Empty: its own drops minus the excluded items. none: nothing.";
			ConfigEntry<string> val = bind("4 - Creature yields", text, array[2], description);
			val.SettingChanged += delegate
			{
				changed();
			};
			s_entries[text] = val;
		}
	}

	internal static void AddTo(Dictionary<string, List<string[]>> map)
	{
		foreach (KeyValuePair<string, ConfigEntry<string>> s_entry in s_entries)
		{
			string text = ((s_entry.Value.Value != null) ? s_entry.Value.Value.Trim() : "");
			string key = s_entry.Key.ToLowerInvariant();
			if (text.Length != 0 || !map.ContainsKey(key))
			{
				map[key] = YieldTable.ParseItems(text);
			}
		}
	}

	internal static IEnumerable<string[]> Defaults()
	{
		return Table;
	}
}
public class HerdBell : MonoBehaviour, Hoverable, Interactable
{
	private sealed class Group
	{
		public string Name;

		public int Count;

		public int Ready;

		public int Hungry;

		public int Young;

		public string Yields;
	}

	internal static readonly List<HerdBell> All = new List<HerdBell>();

	private const string RpcRing = "anwo_hb_ring";

	public Transform m_swing;

	private ZNetView m_nview;

	private bool m_registered;

	private AudioSource m_audio;

	private Quaternion m_swingRest = Quaternion.identity;

	private float m_ringStart = -100f;

	private float m_lastLocalRing = -100f;

	private bool m_swinging;

	private static readonly StringBuilder s_text = new StringBuilder();

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

	private static readonly List<Group> s_sorted = new List<Group>();

	private string m_cachedText;

	private float m_cachedAt = -100f;

	internal bool IsValid
	{
		get
		{
			if (m_registered && (Object)(object)m_nview != (Object)null)
			{
				return m_nview.IsValid();
			}
			return false;
		}
	}

	private void Start()
	{
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		m_nview = ((Component)this).GetComponent<ZNetView>();
		if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid())
		{
			All.Add(this);
			m_registered = true;
			m_nview.Register("anwo_hb_ring", (Action<long>)RPC_Ring);
			if ((Object)(object)m_swing != (Object)null)
			{
				m_swingRest = m_swing.localRotation;
			}
			m_audio = ((Component)this).gameObject.AddComponent<AudioSource>();
			m_audio.playOnAwake = false;
			m_audio.spatialBlend = 1f;
			m_audio.rolloffMode = (AudioRolloffMode)1;
			m_audio.minDistance = 4f;
			m_audio.maxDistance = 70f;
			m_audio.dopplerLevel = 0f;
		}
	}

	private void OnDestroy()
	{
		if (m_registered)
		{
			All.Remove(this);
		}
	}

	internal bool Reaches(Vector3 point)
	{
		//IL_0000: 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_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = point - ((Component)this).transform.position;
		if (Mathf.Abs(val.y) > 20f)
		{
			return false;
		}
		val.y = 0f;
		float value = HerdBellPlugin.BellRadius.Value;
		return ((Vector3)(ref val)).sqrMagnitude <= value * value;
	}

	internal static bool InReach(Vector3 point)
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < All.Count; i++)
		{
			HerdBell herdBell = All[i];
			if ((Object)(object)herdBell != (Object)null && herdBell.IsValid && herdBell.Reaches(point))
			{
				return true;
			}
		}
		return false;
	}

	public string GetHoverName()
	{
		return "Herd bell";
	}

	public float GetHoverOffset()
	{
		return 0.5f;
	}

	public string GetHoverText()
	{
		try
		{
			if (!IsValid)
			{
				return "Herd bell";
			}
			if (m_cachedText != null && Time.time - m_cachedAt < 0.5f)
			{
				return m_cachedText;
			}
			m_cachedText = BuildText();
			m_cachedAt = Time.time;
			return m_cachedText;
		}
		catch (Exception ex)
		{
			HerdBellPlugin.Log.LogDebug((object)("Herd bell hover failed: " + ex.Message));
			return "Herd bell";
		}
	}

	private string BuildText()
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		s_groups.Clear();
		int num = 0;
		int num2 = 0;
		foreach (HerdYield item in HerdYield.All)
		{
			if ((Object)(object)item == (Object)null || !item.IsValid || !item.IsTamed || !Reaches(((Component)item).transform.position) || item.Products.Count == 0)
			{
				continue;
			}
			string text = ((Localization.instance != null) ? Localization.instance.Localize(item.Character.m_name) : item.Character.m_name);
			if (!s_groups.TryGetValue(text, out var value))
			{
				value = new Group();
				value.Name = text;
				value.Yields = YieldTable.Describe(item.Products);
				s_groups[text] = value;
			}
			value.Count++;
			num++;
			if (!item.IsGrown)
			{
				value.Young++;
				continue;
			}
			int stored = item.Stored;
			value.Ready += stored;
			num2 += stored;
			if (HerdBellPlugin.RequireFed.Value && item.IsHungry)
			{
				value.Hungry++;
			}
		}
		s_text.Length = 0;
		s_text.Append("Herd bell");
		s_text.Append("\n[<color=yellow><b>$KEY_Use</b></color>] Ring the bell");
		s_text.Append((num2 > 0) ? (" - " + num2 + ((num2 == 1) ? " yield" : " yields") + " ready") : " - nothing ready yet");
		if (num == 0)
		{
			s_text.Append("\n<color=#c0c0c0>No tamed animals within " + HerdBellPlugin.BellRadius.Value.ToString("0") + " m</color>");
		}
		else
		{
			s_sorted.Clear();
			s_sorted.AddRange(s_groups.Values);
			s_sorted.Sort((Group a, Group b) => b.Count.CompareTo(a.Count));
			int num3 = 0;
			foreach (Group item2 in s_sorted)
			{
				if (num3 == 6)
				{
					int num4 = s_sorted.Count - num3;
					s_text.Append("\n<color=#c0c0c0>… and " + num4 + ((num4 == 1) ? " more kind" : " more kinds") + "</color>");
					break;
				}
				s_text.Append("\n").Append(item2.Name).Append(" x")
					.Append(item2.Count)
					.Append(": ");
				List<string> list = new List<string>();
				if (item2.Ready > 0)
				{
					list.Add(item2.Ready + " ready");
				}
				if (item2.Hungry > 0)
				{
					list.Add("<color=#ff9a7a>" + item2.Hungry + " hungry</color>");
				}
				if (item2.Young > 0)
				{
					list.Add(item2.Young + " young");
				}
				if (list.Count == 0)
				{
					list.Add("working");
				}
				s_text.Append(string.Join(", ", list.ToArray()));
				s_text.Append(" <color=#c0c0c0>(").Append(item2.Yields).Append(")</color>");
				num3++;
			}
		}
		if (Localization.instance == null)
		{
			return s_text.ToString();
		}
		return Localization.instance.Localize(s_text.ToString());
	}

	public bool Interact(Humanoid user, bool hold, bool alt)
	{
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		//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_010e: 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_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: 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_01aa: Unknown result type (might be due to invalid IL or missing references)
		if (hold)
		{
			return false;
		}
		Player val = (Player)(object)((user is Player) ? user : null);
		if ((Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)Player.m_localPlayer || !IsValid)
		{
			return false;
		}
		try
		{
			if (Time.time - m_lastLocalRing < 2.5f)
			{
				return false;
			}
			if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
			{
				return false;
			}
			m_lastLocalRing = Time.time;
			m_cachedText = null;
			m_nview.InvokeRPC(ZNetView.Everybody, "anwo_hb_ring", Array.Empty<object>());
			Vector3 val2 = ((Component)val).transform.position - ((Component)this).transform.position;
			val2.y = 0f;
			if (((Vector3)(ref val2)).sqrMagnitude < 0.01f)
			{
				val2 = ((Component)this).transform.forward;
			}
			Vector3 val3 = ((Component)this).transform.position + ((Vector3)(ref val2)).normalized * Mathf.Min(1.5f, ((Vector3)(ref val2)).magnitude) + Vector3.up * 0.6f;
			float num = default(float);
			if (Heightmap.GetHeight(val3, ref num) && val3.y < num + 0.5f)
			{
				val3.y = num + 0.5f;
			}
			int num2 = 0;
			int num3 = 0;
			foreach (HerdYield item in HerdYield.All)
			{
				if (!((Object)(object)item == (Object)null) && item.IsValid && item.IsTamed && Reaches(((Component)item).transform.position))
				{
					int stored = item.Stored;
					if (stored > 0)
					{
						num2 += stored;
						num3++;
						item.RequestCollect(val3);
					}
				}
			}
			if (num2 > 0)
			{
				((Character)val).Message((MessageType)2, "The herd brings in " + num2 + ((num2 == 1) ? " yield" : " yields") + " from " + num3 + ((num3 == 1) ? " animal" : " animals"), 0, (Sprite)null, false);
			}
			else
			{
				((Character)val).Message((MessageType)2, HerdBellPlugin.RequireFed.Value ? "Nothing ready yet. Keep the herd fed." : "Nothing ready yet", 0, (Sprite)null, false);
			}
			return true;
		}
		catch (Exception ex)
		{
			HerdBellPlugin.Log.LogWarning((object)("Ringing the Herd bell failed: " + ex));
			return false;
		}
	}

	public bool UseItem(Humanoid user, ItemData item)
	{
		return false;
	}

	private void RPC_Ring(long sender)
	{
		m_ringStart = Time.time;
		m_swinging = true;
		try
		{
			if ((Object)(object)m_audio != (Object)null)
			{
				if ((Object)(object)m_audio.outputAudioMixerGroup == (Object)null)
				{
					m_audio.outputAudioMixerGroup = BellVisuals.SfxMixer;
				}
				m_audio.pitch = Random.Range(0.96f, 1.04f);
				m_audio.PlayOneShot(BellVisuals.BellClip, HerdBellPlugin.BellVolume.Value);
			}
		}
		catch (Exception ex)
		{
			HerdBellPlugin.Log.LogDebug((object)("Bell sound failed: " + ex.Message));
		}
	}

	private void Update()
	{
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: 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)
		if (m_swinging && !((Object)(object)m_swing == (Object)null))
		{
			float num = Time.time - m_ringStart;
			if (num > 3f)
			{
				m_swing.localRotation = m_swingRest;
				m_swinging = false;
			}
			else
			{
				float num2 = 30f * Mathf.Sin(num * (float)Math.PI * 2f * 1.4f) * Mathf.Exp((0f - num) / 0.9f);
				m_swing.localRotation = m_swingRest * Quaternion.Euler(0f, 0f, num2);
			}
		}
	}
}
public class HerdYield : MonoBehaviour
{
	internal static readonly List<HerdYield> All = new List<HerdYield>();

	internal const string KeyLast = "anwo_hb_last";

	internal const string KeyProgress = "anwo_hb_progress";

	internal const string KeyStored = "anwo_hb_stored";

	internal const string RpcCollect = "anwo_hb_collect";

	private const double TicksPerSecond = 10000000.0;

	private const float TickSeconds = 20f;

	private ZNetView m_nview;

	private Character m_character;

	private Tameable m_tameable;

	private bool m_registered;

	private float m_nextTick;

	private static readonly Dictionary<GameObject, int> s_roll = new Dictionary<GameObject, int>();

	internal Character Character => m_character;

	internal bool IsValid
	{
		get
		{
			if (m_registered && (Object)(object)m_nview != (Object)null && m_nview.IsValid() && (Object)(object)m_character != (Object)null)
			{
				return !m_character.IsDead();
			}
			return false;
		}
	}

	internal bool IsTamed
	{
		get
		{
			if ((Object)(object)m_character != (Object)null)
			{
				return m_character.IsTamed();
			}
			return false;
		}
	}

	internal bool IsGrown => (Object)(object)((Component)this).GetComponent<Growup>() == (Object)null;

	internal List<Product> Products => YieldTable.For(m_character);

	internal int Stored
	{
		get
		{
			if (!IsValid)
			{
				return 0;
			}
			return m_nview.GetZDO().GetInt("anwo_hb_stored", 0);
		}
	}

	internal float Progress
	{
		get
		{
			if (!IsValid)
			{
				return 0f;
			}
			return m_nview.GetZDO().GetFloat("anwo_hb_progress", 0f);
		}
	}

	internal bool IsHungry
	{
		get
		{
			if ((Object)(object)m_tameable != (Object)null)
			{
				return m_tameable.IsHungry();
			}
			return false;
		}
	}

	internal float SecondsPerYield
	{
		get
		{
			float num = HerdBellPlugin.YieldMinutes.Value * 60f;
			if (HerdBellPlugin.SlowerForBigCreatures.Value && (Object)(object)m_character != (Object)null)
			{
				float num2 = Mathf.Max(1f, m_character.m_health);
				num *= Mathf.Clamp(1f + Mathf.Log10(Mathf.Max(1f, num2 / 100f)), 1f, 3f);
			}
			return Mathf.Max(30f, num);
		}
	}

	internal bool NearBell
	{
		get
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (HerdBellPlugin.RequireBell.Value)
			{
				return HerdBell.InReach(((Component)this).transform.position);
			}
			return true;
		}
	}

	private void Awake()
	{
		m_nview = ((Component)this).GetComponent<ZNetView>();
		m_character = ((Component)this).GetComponent<Character>();
		m_tameable = ((Component)this).GetComponent<Tameable>();
		if ((Object)(object)m_nview == (Object)null || m_nview.GetZDO() == null || (Object)(object)m_character == (Object)null || (Object)(object)m_tameable == (Object)null)
		{
			((Behaviour)this).enabled = false;
			return;
		}
		m_nview.Register<Vector3>("anwo_hb_collect", (Action<long, Vector3>)RPC_Collect);
		All.Add(this);
		m_registered = true;
		m_nextTick = Time.time + Random.Range(2f, 20f);
	}

	private void OnDestroy()
	{
		if (m_registered)
		{
			All.Remove(this);
		}
	}

	private void Update()
	{
		if (Time.time < m_nextTick)
		{
			return;
		}
		m_nextTick = Time.time + 20f;
		try
		{
			if (IsValid && m_nview.IsOwner() && (Object)(object)ZNet.instance != (Object)null)
			{
				Tick();
			}
		}
		catch (Exception ex)
		{
			HerdBellPlugin.Log.LogDebug((object)("Herd yield update failed on " + ((Object)this).name + ": " + ex.Message));
		}
	}

	private void Tick()
	{
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_014a: Unknown result type (might be due to invalid IL or missing references)
		if (!IsTamed)
		{
			return;
		}
		ZDO zDO = m_nview.GetZDO();
		long ticks = ZNet.instance.GetTime().Ticks;
		long num = zDO.GetLong("anwo_hb_last", 0L);
		if (num <= 0 || num > ticks)
		{
			zDO.Set("anwo_hb_last", ticks);
			return;
		}
		if (!IsGrown || Products.Count == 0 || !NearBell)
		{
			zDO.Set("anwo_hb_last", ticks);
			return;
		}
		int stored = zDO.GetInt("anwo_hb_stored", 0);
		float progress = zDO.GetFloat("anwo_hb_progress", 0f);
		long fed = zDO.GetLong(ZDOVars.s_tameLastFeeding, 0L);
		bool num2 = Accumulate(num, ticks, fed, m_tameable.m_fedDuration, HerdBellPlugin.RequireFed.Value, SecondsPerYield, HerdBellPlugin.MaxStored.Value, ref stored, ref progress);
		zDO.Set("anwo_hb_last", ticks);
		if (num2)
		{
			zDO.Set("anwo_hb_stored", stored);
			zDO.Set("anwo_hb_progress", progress);
		}
		if (HerdBellPlugin.AutoDrop.Value && stored > 0)
		{
			Vector3 at = ((Component)this).transform.position + ((Component)this).transform.forward * -0.6f + Vector3.up * 0.4f;
			DropStored(at);
		}
	}

	internal static bool Accumulate(long last, long now, long fed, float fedDuration, bool requireFed, float secondsPerYield, int max, ref int stored, ref float progress)
	{
		int num = stored;
		float num2 = progress;
		if (max < 1)
		{
			max = 1;
		}
		if (stored >= max)
		{
			stored = max;
			progress = 0f;
			if (stored == num)
			{
				return progress != num2;
			}
			return true;
		}
		long num3 = last;
		long num4 = now;
		if (requireFed)
		{
			if (fed <= 0)
			{
				return false;
			}
			long val = fed + (long)((double)fedDuration * 10000000.0);
			num3 = Math.Max(last, fed);
			num4 = Math.Min(now, val);
		}
		double num5 = (double)(num4 - num3) / 10000000.0;
		if (num5 <= 0.0 || secondsPerYield <= 0f)
		{
			return false;
		}
		double num6 = (double)progress + num5 / (double)secondsPerYield;
		int num7 = (int)Math.Min(Math.Floor(num6), max - stored);
		stored += num7;
		num6 -= (double)num7;
		progress = ((stored >= max) ? 0f : ((float)Math.Min(num6, 0.9999)));
		if (stored == num)
		{
			return progress != num2;
		}
		return true;
	}

	internal void RequestCollect(Vector3 dropAt)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		if (IsValid)
		{
			m_nview.InvokeRPC("anwo_hb_collect", new object[1] { dropAt });
		}
	}

	private void RPC_Collect(long sender, Vector3 dropAt)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (IsValid && m_nview.IsOwner())
			{
				Tick();
				DropStored(dropAt);
			}
		}
		catch (Exception ex)
		{
			HerdBellPlugin.Log.LogWarning((object)("Collecting from " + ((Object)this).name + " failed: " + ex.Message));
		}
	}

	private void DropStored(Vector3 at)
	{
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		ZDO zDO = m_nview.GetZDO();
		int num = zDO.GetInt("anwo_hb_stored", 0);
		if (num <= 0)
		{
			return;
		}
		List<Product> products = Products;
		zDO.Set("anwo_hb_stored", 0);
		if (products.Count == 0)
		{
			return;
		}
		s_roll.Clear();
		int level = m_character.GetLevel();
		for (int i = 0; i < num; i++)
		{
			YieldTable.Roll(products, level, s_roll);
		}
		foreach (KeyValuePair<GameObject, int> item in s_roll)
		{
			DropStacks(item.Key, item.Value, at);
		}
		s_roll.Clear();
	}

	internal static void DropStacks(GameObject prefab, int amount, Vector3 at)
	{
		//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)
		//IL_0050: 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_006e: 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_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: 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)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		ItemDrop component = prefab.GetComponent<ItemDrop>();
		if ((Object)(object)component == (Object)null || amount <= 0)
		{
			return;
		}
		int num = Mathf.Max(1, component.m_itemData.m_shared.m_maxStackSize);
		while (amount > 0)
		{
			int num2 = Mathf.Min(amount, num);
			amount -= num2;
			Vector3 val = Random.insideUnitSphere * 0.6f;
			val.y = Mathf.Abs(val.y) * 0.3f + 0.2f;
			GameObject obj = Object.Instantiate<GameObject>(prefab, at + val, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f));
			ItemDrop component2 = obj.GetComponent<ItemDrop>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.m_itemData.m_worldLevel = Game.m_worldLevel;
				component2.SetStack(num2);
			}
			Rigidbody component3 = obj.GetComponent<Rigidbody>();
			if ((Object)(object)component3 != (Object)null)
			{
				Vector3 insideUnitSphere = Random.insideUnitSphere;
				insideUnitSphere.y = Mathf.Abs(insideUnitSphere.y) + 0.5f;
				component3.AddForce(insideUnitSphere * 2.5f, (ForceMode)2);
			}
		}
	}
}
[HarmonyPatch]
internal static class Patches
{
	[HarmonyPatch(typeof(Tameable), "Awake")]
	[HarmonyPostfix]
	private static void TameableAwake(Tameable __instance)
	{
		try
		{
			if ((Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).GetComponent<HerdYield>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<HerdYield>();
			}
		}
		catch (Exception ex)
		{
			HerdBellPlugin.Log.LogDebug((object)("Adding the yield tracker failed: " + ex.Message));
		}
	}

	[HarmonyPatch(typeof(Tameable), "GetHoverText")]
	[HarmonyPostfix]
	private static void TameableHover(Tameable __instance, ref string __result)
	{
		try
		{
			if (!HerdBellPlugin.ShowOnCreatures.Value || (Object)(object)__instance == (Object)null)
			{
				return;
			}
			HerdYield component = ((Component)__instance).GetComponent<HerdYield>();
			if (!((Object)(object)component == (Object)null) && component.IsValid && component.IsTamed)
			{
				string text = YieldLine(component);
				if (!string.IsNullOrEmpty(text))
				{
					__result = __result + "\n" + text;
				}
			}
		}
		catch (Exception ex)
		{
			HerdBellPlugin.Log.LogDebug((object)("Yield hover failed: " + ex.Message));
		}
	}

	internal static string YieldLine(HerdYield herd)
	{
		if (herd.Products.Count == 0)
		{
			return null;
		}
		string text = YieldTable.Describe(herd.Products);
		string text2 = "<color=#e3c77a>Yields</color> " + text;
		if (!herd.IsGrown)
		{
			return text2 + " <color=#c0c0c0>- when grown</color>";
		}
		int stored = herd.Stored;
		int value = HerdBellPlugin.MaxStored.Value;
		string text3 = ((stored > 0) ? (stored + "/" + value + " ready") : null);
		if (stored >= value)
		{
			return text2 + " - <color=#a5e07a>full (" + stored + "/" + value + "), ring a Herd bell</color>";
		}
		if (!herd.NearBell)
		{
			return text2 + " - <color=#ff9a7a>needs a Herd bell within " + HerdBellPlugin.BellRadius.Value.ToString("0") + " m</color>" + ((text3 != null) ? (" (" + text3 + ")") : "");
		}
		if (HerdBellPlugin.RequireFed.Value && herd.IsHungry)
		{
			return text2 + " - <color=#ff9a7a>hungry, not producing</color>" + ((text3 != null) ? (" (" + text3 + ")") : "");
		}
		float num = Mathf.Max(0f, (1f - Mathf.Clamp01(herd.Progress)) * herd.SecondsPerYield / 60f);
		string text4 = ((num < 1f) ? "next in under a minute" : ("next in " + Mathf.CeilToInt(num) + " min"));
		return text2 + " - " + ((text3 != null) ? (text3 + ", ") : "") + text4;
	}
}
[BepInPlugin("anwo.HerdBell", "HerdBell", "1.0.3")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
public class HerdBellPlugin : BaseUnityPlugin
{
	public const string Guid = "anwo.HerdBell";

	public const string ModName = "HerdBell";

	public const string Version = "1.0.3";

	public const string BellPrefabName = "anwo_herd_bell";

	internal static ManualLogSource Log;

	internal static ConfigEntry<bool> RequireBell;

	internal static ConfigEntry<float> BellRadius;

	internal static ConfigEntry<bool> RequireFed;

	internal static ConfigEntry<float> YieldMinutes;

	internal static ConfigEntry<bool> SlowerForBigCreatures;

	internal static ConfigEntry<int> MaxStored;

	internal static ConfigEntry<float> StarBonus;

	internal static ConfigEntry<bool> AutoDrop;

	internal static ConfigEntry<bool> BossesYield;

	internal static ConfigEntry<string> Overrides;

	internal static ConfigEntry<string> Excluded;

	internal static ConfigEntry<string> BellRecipe;

	internal static ConfigEntry<bool> ShowOnCreatures;

	internal static ConfigEntry<float> BellVolume;

	private Harmony m_harmony;

	private void Awake()
	{
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		BindConfig();
		Overrides.SettingChanged += delegate
		{
			YieldTable.ClearCache();
		};
		Excluded.SettingChanged += delegate
		{
			YieldTable.ClearCache();
		};
		BossesYield.SettingChanged += delegate
		{
			YieldTable.ClearCache();
		};
		m_harmony = new Harmony("anwo.HerdBell");
		m_harmony.PatchAll(typeof(Patches));
		PrefabManager.OnVanillaPrefabsAvailable += RegisterPieces;
		Log.LogInfo((object)"HerdBell 1.0.3 loaded.");
	}

	private void OnDestroy()
	{
		if (m_harmony != null)
		{
			m_harmony.UnpatchSelf();
		}
	}

	private ConfigEntry<T> Synced<T>(string section, string key, T value, string description, AcceptableValueBase range = null)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Expected O, but got Unknown
		ConfigurationManagerAttributes val = new ConfigurationManagerAttributes();
		val.IsAdminOnly = true;
		return ((BaseUnityPlugin)this).Config.Bind<T>(section, key, value, new ConfigDescription(description, range, new object[1] { val }));
	}

	private void BindConfig()
	{
		//IL_0204: Unknown result type (might be due to invalid IL or missing references)
		//IL_020e: Expected O, but got Unknown
		RequireBell = Synced("1 - Ranch", "Needs a herd bell", value: true, "Animals only build up a yield while they are within reach of a Herd bell (like a Palworld ranch). Turn off to let every tamed animal yield anywhere.");
		BellRadius = Synced("1 - Ranch", "Bell reach", 20f, "How far a Herd bell reaches, in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 60f));
		RequireFed = Synced("1 - Ranch", "Only while fed", value: true, "Animals only build up a yield while they are fed, so your crops and meat become feed. Turn off to make yield free.");
		YieldMinutes = Synced("1 - Ranch", "Minutes per yield", 15f, "Minutes a small animal (boar, hen, wolf) must spend fed near a bell for one yield. Counted in world time: real time while the world runs, and sleeping skips ahead.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 240f));
		SlowerForBigCreatures = Synced("1 - Ranch", "Big creatures yield slower", value: true, "Tougher creatures take longer per yield (lox and stone golems about 2x, based on their health).");
		MaxStored = Synced("1 - Ranch", "Max stored yields", 4, "How many yields an animal holds before it stops producing until you ring the bell.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20));
		StarBonus = Synced("1 - Ranch", "Bonus per star", 0.25f, "Extra amount per star, as a share (0.25 = +25% per star, so a 4-star animal gives twice as much).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f));
		AutoDrop = Synced("1 - Ranch", "Drop automatically", value: false, "Animals drop each yield at their feet as soon as it's ready, instead of waiting for the bell (handy with auto-pickup chests).");
		BossesYield = Synced("2 - Products", "Bosses yield", value: false, "Let tamed bosses yield (their entries under 4 - Creature yields). Off by default because bosses are meant to be fought, not farmed.");
		Overrides = Synced("2 - Products", "Product overrides", "", "Yields for creatures that have no entry under 4 - Creature yields (for example creatures from other mods), in one line. Format: Creature = Item min-max chance%, Item2 ...; NextCreature = ... Creature and item names are prefab names. A creature's own entry under 4 - Creature yields wins over this. Creatures listed nowhere yield their own drops, minus the excluded items.");
		Excluded = Synced("2 - Products", "Excluded items", "Meat, Trophy, NeckTail, Fish, Coins, HardAntler, CryptKey, Wishbone, DragonTear, YagluthDrop, QueenDrop, FaderDrop", "Natural drops containing any of these words are never yielded (meat and trophies stay a reward for hunting).");
		CreatureYields.Bind((string section, string key, string value, string description) => Synced(section, key, value, description), YieldTable.ClearCache);
		BellRecipe = Synced("1 - Ranch", "Bell recipe", "Wood:6,Bronze:2,LeatherScraps:2", "Cost of one Herd bell, as Item:Amount pairs separated by commas. Needs a game restart.");
		ShowOnCreatures = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Display", "Show yield on animals", true, "Show what an animal yields and how far along it is when you look at it.");
		BellVolume = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Display", "Bell volume", 0.8f, new ConfigDescription("Volume of the bell.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
	}

	private void RegisterPieces()
	{
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Expected O, but got Unknown
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Expected O, but got Unknown
		try
		{
			string text = null;
			string[] array = new string[3] { "wood_pole2", "wood_pole_log", "wood_pole" };
			foreach (string text2 in array)
			{
				if ((Object)(object)PrefabManager.Instance.GetPrefab(text2) != (Object)null)
				{
					text = text2;
					break;
				}
			}
			if (text == null)
			{
				Log.LogError((object)"No vanilla pole found to build the Herd bell from. The bell is not added.");
				return;
			}
			GameObject val = PrefabManager.Instance.CreateClonedPrefab("anwo_herd_bell", text);
			if ((Object)(object)val == (Object)null)
			{
				Log.LogError((object)("Cloning " + text + " failed. The Herd bell is not added."));
				return;
			}
			Transform swing = BellVisuals.Decorate(val);
			val.AddComponent<HerdBell>().m_swing = swing;
			PieceConfig val2 = new PieceConfig();
			val2.Name = "Herd bell";
			val2.Description = "Tamed animals kept fed within reach of this bell build up a yield of their own materials. Ring it to collect.";
			val2.PieceTable = PieceTables.Hammer;
			val2.Category = PieceCategories.Misc;
			val2.CraftingStation = CraftingStations.Workbench;
			val2.Icon = LoadIcon();
			val2.Requirements = ParseRecipe(BellRecipe.Value);
			PieceManager.Instance.AddPiece(new CustomPiece(val, false, val2));
			Log.LogInfo((object)("Herd bell built from " + text));
		}
		catch (Exception ex)
		{
			Log.LogError((object)("Registering the Herd bell failed: " + ex));
		}
		finally
		{
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterPieces;
		}
	}

	private static RequirementConfig[] ParseRecipe(string recipe)
	{
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Expected O, but got Unknown
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Expected O, but got Unknown
		List<RequirementConfig> list = new List<RequirementConfig>();
		if (!string.IsNullOrEmpty(recipe))
		{
			string[] array = recipe.Split(',');
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(':');
				if (array2.Length == 2 && int.TryParse(array2[1].Trim(), out var result) && result > 0)
				{
					RequirementConfig val = new RequirementConfig();
					val.Item = array2[0].Trim();
					val.Amount = result;
					val.Recover = true;
					list.Add(val);
				}
			}
		}
		if (list.Count == 0)
		{
			RequirementConfig val2 = new RequirementConfig();
			val2.Item = "Wood";
			val2.Amount = 6;
			val2.Recover = true;
			list.Add(val2);
		}
		return list.ToArray();
	}

	private static Sprite LoadIcon()
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Expected O, but got Unknown
		//IL_0081: 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)
		try
		{
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("HerdBell.icon.png");
			if (stream == null)
			{
				return null;
			}
			byte[] array = new byte[stream.Length];
			int num;
			for (int i = 0; i < array.Length; i += num)
			{
				num = stream.Read(array, i, array.Length - i);
				if (num <= 0)
				{
					break;
				}
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			ImageConversion.LoadImage(val, array);
			((Object)val).name = "anwo_herd_bell_icon";
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("Could not load the Herd bell icon: " + ex.Message));
			return null;
		}
	}
}
internal sealed class Product
{
	public GameObject Prefab;

	public string Name;

	public int Min;

	public int Max;

	public float Chance;
}
internal static class YieldTable
{
	private static readonly Dictionary<string, List<Product>> s_cache = new Dictionary<string, List<Product>>();

	private static Dictionary<string, List<string[]>> s_overrides;

	private static string[] s_excluded;

	internal static void ClearCache()
	{
		s_cache.Clear();
		s_overrides = null;
		s_excluded = null;
	}

	internal static List<Product> For(Character character)
	{
		string prefabName = Utils.GetPrefabName(((Component)character).gameObject);
		if (s_cache.TryGetValue(prefabName, out var value))
		{
			return value;
		}
		value = Build(character, prefabName);
		if ((Object)(object)ObjectDB.instance != (Object)null)
		{
			s_cache[prefabName] = value;
		}
		return value;
	}

	private static List<Product> Build(Character character, string key)
	{
		List<Product> list = new List<Product>();
		try
		{
			LoadConfig();
			if (character.IsBoss() && !HerdBellPlugin.BossesYield.Value)
			{
				return list;
			}
			List<string[]> list2 = Find(s_overrides, key);
			if (list2 != null && list2.Count > 0)
			{
				if (IsNone(list2))
				{
					return list;
				}
				foreach (string[] item in list2)
				{
					Product product = ParseItem(item);
					if (product != null)
					{
						list.Add(product);
					}
				}
				if (list.Count > 0)
				{
					return list;
				}
				HerdBellPlugin.Log.LogWarning((object)("None of the items listed for " + key + " exist; using its natural drops instead."));
			}
			CharacterDrop component = ((Component)character).GetComponent<CharacterDrop>();
			if ((Object)(object)component == (Object)null || component.m_drops == null)
			{
				return list;
			}
			foreach (Drop drop in component.m_drops)
			{
				if (drop != null && !((Object)(object)drop.m_prefab == (Object)null) && !(drop.m_chance <= 0f) && IsYieldable(drop.m_prefab))
				{
					Product product2 = new Product();
					product2.Prefab = drop.m_prefab;
					product2.Name = ItemName(drop.m_prefab);
					product2.Min = Mathf.Max(1, drop.m_amountMin);
					product2.Max = Mathf.Max(product2.Min, drop.m_amountMax);
					product2.Chance = Mathf.Clamp01(drop.m_chance);
					list.Add(product2);
				}
			}
		}
		catch (Exception ex)
		{
			HerdBellPlugin.Log.LogWarning((object)("Working out the yield of " + key + " failed: " + ex.Message));
		}
		return list;
	}

	private static bool IsYieldable(GameObject prefab)
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Invalid comparison between Unknown and I4
		ItemDrop component = prefab.GetComponent<ItemDrop>();
		if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null)
		{
			return false;
		}
		SharedData shared = component.m_itemData.m_shared;
		if ((int)shared.m_itemType != 1)
		{
			return false;
		}
		if (shared.m_food > 0f || shared.m_foodStamina > 0f)
		{
			return false;
		}
		string name = ((Object)prefab).name;
		string[] array = s_excluded;
		foreach (string text in array)
		{
			if (text.Length > 0 && name.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return false;
			}
		}
		return true;
	}

	internal static string ItemName(GameObject prefab)
	{
		ItemDrop val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<ItemDrop>() : null);
		if ((Object)(object)val != (Object)null && val.m_itemData != null && val.m_itemData.m_shared != null && Localization.instance != null)
		{
			return Localization.instance.Localize(val.m_itemData.m_shared.m_name);
		}
		if (!((Object)(object)prefab != (Object)null))
		{
			return "?";
		}
		return ((Object)prefab).name;
	}

	private static Product ParseItem(string[] tokens)
	{
		if (tokens.Length == 0 || (Object)(object)ObjectDB.instance == (Object)null)
		{
			return null;
		}
		GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(tokens[0]);
		if ((Object)(object)itemPrefab == (Object)null || (Object)(object)itemPrefab.GetComponent<ItemDrop>() == (Object)null)
		{
			HerdBellPlugin.Log.LogWarning((object)("Product override: no item called " + tokens[0]));
			return null;
		}
		Product product = new Product();
		product.Prefab = itemPrefab;
		product.Name = ItemName(itemPrefab);
		product.Min = 1;
		product.Max = 1;
		product.Chance = 1f;
		for (int i = 1; i < tokens.Length; i++)
		{
			string text = tokens[i];
			if (text.EndsWith("%"))
			{
				if (float.TryParse(text.TrimEnd('%'), NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
				{
					product.Chance = Mathf.Clamp01(result / 100f);
				}
				continue;
			}
			string[] array = text.Split('-');
			if (array.Length >= 1 && int.TryParse(array[0], out var result2))
			{
				product.Min = Mathf.Max(0, result2);
				product.Max = product.Min;
				if (array.Length >= 2 && int.TryParse(array[1], out var result3))
				{
					product.Max = Mathf.Max(product.Min, result3);
				}
			}
		}
		if (product.Max <= 0)
		{
			return null;
		}
		if (product.Min <= 0)
		{
			product.Min = 1;
		}
		return product;
	}

	internal static List<string[]> Find(Dictionary<string, List<string[]>> map, string key)
	{
		if (map == null || string.IsNullOrEmpty(key))
		{
			return null;
		}
		string text = key.ToLowerInvariant();
		if (map.TryGetValue(text, out var value))
		{
			return value;
		}
		string text2 = null;
		foreach (string key2 in map.Keys)
		{
			if (key2.Length != 0 && key2.Length < text.Length && text.StartsWith(key2, StringComparison.Ordinal))
			{
				char c = key[key2.Length];
				if ((c == '_' || char.IsUpper(c)) && (text2 == null || key2.Length > text2.Length))
				{
					text2 = key2;
				}
			}
		}
		if (text2 == null)
		{
			return null;
		}
		return map[text2];
	}

	internal static bool IsNone(List<string[]> items)
	{
		if (items.Count == 1 && items[0].Length == 1)
		{
			if (!string.Equals(items[0][0], "none", StringComparison.OrdinalIgnoreCase))
			{
				return string.Equals(items[0][0], "nothing", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}
		return false;
	}

	private static void LoadConfig()
	{
		if (s_overrides != null && s_excluded != null)
		{
			return;
		}
		Dictionary<string, List<string[]>> map = ParseOverrides(HerdBellPlugin.Overrides.Value);
		CreatureYields.AddTo(map);
		s_overrides = map;
		List<string> list = new List<string>();
		string[] array = (HerdBellPlugin.Excluded.Value ?? "").Split(',');
		for (int i = 0; i < array.Length; i++)
		{
			string text = array[i].Trim();
			if (text.Length > 0)
			{
				list.Add(text);
			}
		}
		s_excluded = list.ToArray();
	}

	internal static Dictionary<string, List<string[]>> ParseOverrides(string text)
	{
		Dictionary<string, List<string[]>> dictionary = new Dictionary<string, List<string[]>>();
		if (string.IsNullOrEmpty(text))
		{
			return dictionary;
		}
		string[] array = text.Split(';');
		foreach (string text2 in array)
		{
			int num = text2.IndexOf('=');
			if (num > 0)
			{
				string text3 = text2.Substring(0, num).Trim().ToLowerInvariant();
				if (text3.Length != 0)
				{
					dictionary[text3] = ParseItems(text2.Substring(num + 1));
				}
			}
		}
		return dictionary;
	}

	internal static List<string[]> ParseItems(string text)
	{
		List<string[]> list = new List<string[]>();
		if (string.IsNullOrEmpty(text))
		{
			return list;
		}
		string[] array = text.Split(',');
		for (int i = 0; i < array.Length; i++)
		{
			string[] array2 = array[i].Split(new char[2] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
			if (array2.Length != 0)
			{
				list.Add(array2);
			}
		}
		return list;
	}

	internal static void Roll(List<Product> products, int level, Dictionary<GameObject, int> into)
	{
		if (products.Count == 0)
		{
			return;
		}
		float multiplier = 1f + HerdBellPlugin.StarBonus.Value * (float)Mathf.Max(0, level - 1);
		bool flag = false;
		foreach (Product product2 in products)
		{
			if (!(Random.value > product2.Chance))
			{
				Add(into, product2.Prefab, Scale(Random.Range(product2.Min, product2.Max + 1), multiplier));
				flag = true;
			}
		}
		if (flag)
		{
			return;
		}
		Product product = products[0];
		foreach (Product product3 in products)
		{
			if (product3.Chance > product.Chance)
			{
				product = product3;
			}
		}
		Add(into, product.Prefab, Scale(product.Min, multiplier));
	}

	private static int Scale(int amount, float multiplier)
	{
		float num = (float)amount * multiplier;
		int num2 = Mathf.FloorToInt(num);
		if (Random.value < num - (float)num2)
		{
			num2++;
		}
		return Mathf.Max(1, num2);
	}

	private static void Add(Dictionary<GameObject, int> into, GameObject prefab, int amount)
	{
		into.TryGetValue(prefab, out var value);
		into[prefab] = value + amount;
	}

	internal static string Describe(List<Product> products)
	{
		if (products.Count == 0)
		{
			return "nothing";
		}
		List<string> list = new List<string>();
		foreach (Product product in products)
		{
			if (!list.Contains(product.Name))
			{
				list.Add(product.Name);
			}
		}
		return string.Join(", ", list.ToArray());
	}
}