Decompiled source of Doorbell v1.0.0

plugins/Doorbell.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Splatform;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Doorbell")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Doorbell")]
[assembly: AssemblyTitle("Doorbell")]
[assembly: AssemblyVersion("1.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 Doorbell
{
	internal sealed class ConfigurationManagerAttributes
	{
		public int? Order;

		public bool? HideDefaultButton;

		public Action<ConfigEntryBase> CustomDrawer;
	}
	internal class DoorbellComponent : MonoBehaviour, Hoverable, Interactable
	{
		private const string RpcRing = "Batera_Doorbell_Ring";

		private const string OwnerNameKey = "batera_doorbell_owner";

		private const float RingCooldown = 5f;

		private const float ReplayGuard = 1.5f;

		private static float s_lastRingTime = -999f;

		private ZNetView _nview;

		private Piece _piece;

		private float _lastPlayed = -999f;

		private void Awake()
		{
			_nview = ((Component)this).GetComponent<ZNetView>();
			_piece = ((Component)this).GetComponent<Piece>();
			if (!((Object)(object)_nview == (Object)null) && _nview.GetZDO() != null)
			{
				_nview.Register<string>("Batera_Doorbell_Ring", (Action<long, string>)RPC_Ring);
			}
		}

		private void Start()
		{
			if (!((Object)(object)_nview == (Object)null) && _nview.IsValid() && _nview.IsOwner() && !((Object)(object)_piece == (Object)null) && _piece.IsCreator())
			{
				ZDO zDO = _nview.GetZDO();
				if (string.IsNullOrEmpty(zDO.GetString("batera_doorbell_owner", "")) && (Object)(object)Player.m_localPlayer != (Object)null)
				{
					zDO.Set("batera_doorbell_owner", Player.m_localPlayer.GetPlayerName());
				}
			}
		}

		public string GetHoverName()
		{
			return Translations.Get("$piece_batera_doorbell");
		}

		public string GetHoverText()
		{
			if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
			{
				return "";
			}
			string text = _nview.GetZDO().GetString("batera_doorbell_owner", "");
			return (string.IsNullOrEmpty(text) ? Translations.Get("$piece_batera_doorbell") : string.Format(Translations.Get("$batera_doorbell_owned_by"), text)) + "\n" + Translations.Get("[<color=yellow><b>$KEY_Use</b></color>] $batera_doorbell_ring");
		}

		public float GetHoverOffset()
		{
			return 0f;
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			if (hold || (Object)(object)_nview == (Object)null || !_nview.IsValid())
			{
				return false;
			}
			if (Time.time - s_lastRingTime < 5f)
			{
				return true;
			}
			s_lastRingTime = Time.time;
			string text = (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerName() : "?");
			_nview.InvokeRPC(ZNetView.Everybody, "Batera_Doorbell_Ring", new object[1] { text });
			if ((Object)(object)_piece != (Object)null)
			{
				RingNetwork.NotifyOwner(_piece.GetCreator(), text, ((Component)this).transform.position);
			}
			return true;
		}

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

		private void RPC_Ring(long sender, string ringer)
		{
			//IL_0035: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			if (Time.time - _lastPlayed < 1.5f)
			{
				return;
			}
			_lastPlayed = Time.time;
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null) && !(Vector3.Distance(((Component)localPlayer).transform.position, ((Component)this).transform.position) > Plugin.HearingDistance.Value))
			{
				SoundPlayer.Instance?.Play3D(((Component)this).transform.position);
				if ((!((Object)(object)ZNet.instance != (Object)null) || sender != ZNet.GetUID()) && (Object)(object)MessageHud.instance != (Object)null)
				{
					MessageHud.instance.ShowMessage((MessageType)1, string.Format(Translations.Get("$batera_doorbell_someone_rang"), ringer), 0, (Sprite)null, false, true);
				}
			}
		}
	}
	internal static class DoorbellModel
	{
		private static readonly Color IronFallback = new Color(0.35f, 0.35f, 0.38f);

		private static readonly Color BronzeFallback = new Color(0.85f, 0.6f, 0.25f);

		private static readonly Color RopeColor = new Color(0.55f, 0.45f, 0.3f);

		public static void Apply(GameObject prefab)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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_007e: Expected O, but got Unknown
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: 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_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: 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)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0352: 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_0389: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0409: Unknown result type (might be due to invalid IL or missing references)
			//IL_0422: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			Material val = FirstMaterial(prefab);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogError((object)"Doorbell: base prefab has no material to reuse.");
				return;
			}
			Material material = ItemMaterial("Iron") ?? Tinted(val, IronFallback);
			Material material2 = ItemMaterial("Bronze") ?? Tinted(val, BronzeFallback);
			Material material3 = Tinted(val, RopeColor);
			RemoveBaseVisuals(prefab);
			int layer = LayerMask.NameToLayer("piece");
			GameObject val2 = new GameObject("doorbell_model");
			val2.transform.SetParent(prefab.transform, false);
			val2.layer = layer;
			Mesh mesh = PrimitiveMesh((PrimitiveType)3);
			Mesh mesh2 = PrimitiveMesh((PrimitiveType)0);
			Mesh mesh3 = PrimitiveMesh((PrimitiveType)2);
			Transform transform = val2.transform;
			Part(transform, "plate", mesh, val, new Vector3(0f, 0.25f, 0.025f), new Vector3(0.32f, 0.5f, 0.05f));
			Part(transform, "band_top", mesh, material, new Vector3(0f, 0.42f, 0.053f), new Vector3(0.34f, 0.03f, 0.012f));
			Part(transform, "band_bottom", mesh, material, new Vector3(0f, 0.08f, 0.053f), new Vector3(0.34f, 0.03f, 0.012f));
			Part(transform, "arm", mesh, material, new Vector3(0f, 0.44f, 0.19f), new Vector3(0.035f, 0.035f, 0.28f));
			Vector3 val3 = default(Vector3);
			((Vector3)(ref val3))..ctor(0f, 0.3f, 0.05f);
			Vector3 val4 = default(Vector3);
			((Vector3)(ref val4))..ctor(0f, 0.44f, 0.24f);
			Vector3 val5 = val4 - val3;
			Part(transform, "brace", mesh, material, (val3 + val4) / 2f, new Vector3(0.025f, 0.025f, ((Vector3)(ref val5)).magnitude), Quaternion.LookRotation(val5));
			Part(transform, "hanger", mesh, material, new Vector3(0f, 0.415f, 0.3f), new Vector3(0.02f, 0.04f, 0.02f));
			((Renderer)Part(transform, "bell", BellMesh(), material2, new Vector3(0f, 0.4f, 0.3f), Vector3.one).GetComponent<MeshRenderer>()).shadowCastingMode = (ShadowCastingMode)2;
			Part(transform, "bell_crown", mesh2, material2, new Vector3(0f, 0.405f, 0.3f), Vector3.one * 0.035f);
			Part(transform, "clapper_rod", mesh3, material, new Vector3(0f, 0.31f, 0.3f), new Vector3(0.008f, 0.08f, 0.008f));
			Part(transform, "clapper", mesh2, material, new Vector3(0f, 0.22500001f, 0.3f), Vector3.one * 0.035f);
			Part(transform, "rope", mesh3, material3, new Vector3(0f, 0.13500002f, 0.3f), new Vector3(0.007f, 0.075f, 0.007f));
			Part(transform, "handle", mesh3, val, new Vector3(0f, 0.03999999f, 0.3f), new Vector3(0.022f, 0.025f, 0.022f));
			BoxCollider obj = val2.AddComponent<BoxCollider>();
			obj.center = new Vector3(0f, 0.25f, 0.17f);
			obj.size = new Vector3(0.34f, 0.52f, 0.34f);
			WearNTear component = prefab.GetComponent<WearNTear>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_new = val2;
				component.m_worn = val2;
				component.m_broken = val2;
				component.m_wet = null;
				component.m_fragmentRoots = null;
			}
		}

		private static void RemoveBaseVisuals(GameObject prefab)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			List<GameObject> list = new List<GameObject>();
			foreach (Transform item in prefab.transform)
			{
				Transform val = item;
				list.Add(((Component)val).gameObject);
			}
			foreach (GameObject item2 in list)
			{
				Object.DestroyImmediate((Object)(object)item2);
			}
			LODGroup[] components = prefab.GetComponents<LODGroup>();
			for (int i = 0; i < components.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)components[i]);
			}
			Renderer[] components2 = prefab.GetComponents<Renderer>();
			for (int i = 0; i < components2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)components2[i]);
			}
			MeshFilter[] components3 = prefab.GetComponents<MeshFilter>();
			for (int i = 0; i < components3.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)components3[i]);
			}
			Collider[] components4 = prefab.GetComponents<Collider>();
			for (int i = 0; i < components4.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)components4[i]);
			}
		}

		private static GameObject Part(Transform parent, string name, Mesh mesh, Material material, Vector3 position, Vector3 scale, Quaternion? rotation = null)
		{
			//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_0017: 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_004c: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			GameObject val = new GameObject(name)
			{
				layer = ((Component)parent).gameObject.layer
			};
			val.transform.SetParent(parent, false);
			val.transform.localPosition = position;
			val.transform.localRotation = (Quaternion)(((??)rotation) ?? Quaternion.identity);
			val.transform.localScale = scale;
			val.AddComponent<MeshFilter>().sharedMesh = mesh;
			((Renderer)val.AddComponent<MeshRenderer>()).sharedMaterial = material;
			return val;
		}

		private static Mesh BellMesh()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//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_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: 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_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: 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_0124: 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_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: 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_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_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: 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_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: 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_02d8: Expected O, but got Unknown
			Vector2[] array = (Vector2[])(object)new Vector2[17]
			{
				new Vector2(0.001f, 0f),
				new Vector2(0.03f, -0.002f),
				new Vector2(0.045f, -0.015f),
				new Vector2(0.05f, -0.05f),
				new Vector2(0.053f, -0.09f),
				new Vector2(0.06f, -0.13f),
				new Vector2(0.075f, -0.165f),
				new Vector2(0.09f, -0.19f),
				new Vector2(0.095f, -0.2f),
				new Vector2(0.087f, -0.2f),
				new Vector2(0.08f, -0.188f),
				new Vector2(0.066f, -0.16f),
				new Vector2(0.052f, -0.125f),
				new Vector2(0.046f, -0.09f),
				new Vector2(0.043f, -0.05f),
				new Vector2(0.036f, -0.02f),
				new Vector2(0.001f, -0.012f)
			};
			List<Vector3> list = new List<Vector3>();
			List<Vector2> list2 = new List<Vector2>();
			for (int i = 0; i <= 28; i++)
			{
				float num = MathF.PI * 2f * (float)i / 28f;
				float num2 = Mathf.Cos(num);
				float num3 = Mathf.Sin(num);
				for (int j = 0; j < array.Length; j++)
				{
					list.Add(new Vector3(array[j].x * num2, array[j].y, array[j].x * num3));
					list2.Add(new Vector2((float)i / 28f, (float)j / (float)(array.Length - 1)));
				}
			}
			List<int> list3 = new List<int>();
			int num4 = array.Length;
			for (int k = 0; k < 28; k++)
			{
				for (int l = 0; l < num4 - 1; l++)
				{
					int num5 = k * num4 + l;
					int num6 = (k + 1) * num4 + l;
					list3.AddRange(new int[6]
					{
						num5,
						num6,
						num5 + 1,
						num6,
						num6 + 1,
						num5 + 1
					});
				}
			}
			Mesh val = new Mesh
			{
				name = "DoorbellBell"
			};
			val.SetVertices(list);
			val.SetUVs(0, list2);
			val.SetTriangles(list3, 0);
			val.RecalculateNormals();
			val.RecalculateBounds();
			return val;
		}

		private static Mesh PrimitiveMesh(PrimitiveType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GameObject.CreatePrimitive(type);
			Mesh sharedMesh = obj.GetComponent<MeshFilter>().sharedMesh;
			Object.DestroyImmediate((Object)(object)obj);
			return sharedMesh;
		}

		private static Material FirstMaterial(GameObject go)
		{
			MeshRenderer[] componentsInChildren = go.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(string itemPrefab)
		{
			GameObject prefab = Cache.GetPrefab<GameObject>(itemPrefab);
			if (!((Object)(object)prefab != (Object)null))
			{
				return null;
			}
			return FirstMaterial(prefab);
		}

		private static Material Tinted(Material source, 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_001d: Expected O, but got Unknown
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			Material val = new Material(source)
			{
				name = ((Object)source).name + "_doorbell"
			};
			if (val.HasProperty("_Color"))
			{
				val.color = color;
			}
			return val;
		}
	}
	internal static class DoorbellPiece
	{
		public const string PrefabName = "piece_batera_doorbell";

		private const string BasePrefab = "itemstand";

		public static void Register()
		{
			PrefabManager.OnVanillaPrefabsAvailable += AddPiece;
		}

		private static void AddPiece()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			PrefabManager.OnVanillaPrefabsAvailable -= AddPiece;
			PieceConfig val = new PieceConfig();
			val.Name = "$piece_batera_doorbell";
			val.Description = "$piece_batera_doorbell_desc";
			val.PieceTable = PieceTables.Hammer;
			val.Category = PieceCategories.Furniture;
			val.CraftingStation = CraftingStations.Workbench;
			val.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
			{
				new RequirementConfig("Wood", 2, 0, true),
				new RequirementConfig("Copper", 1, 0, true)
			};
			PieceConfig val2 = val;
			CustomPiece val3 = new CustomPiece("piece_batera_doorbell", "itemstand", val2);
			if (!val3.IsValid())
			{
				Plugin.Log.LogError((object)"Could not create the doorbell piece from 'itemstand'.");
				return;
			}
			ReplaceBehaviour(val3.PiecePrefab);
			DoorbellModel.Apply(val3.PiecePrefab);
			SetIcon(val3);
			PieceManager.Instance.AddPiece(val3);
		}

		private static void SetIcon(CustomPiece piece)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			Sprite val = RenderManager.Instance.Render(piece.PiecePrefab, Quaternion.Euler(12f, 35f, 0f));
			if ((Object)(object)val != (Object)null)
			{
				piece.Piece.m_icon = val;
			}
			else
			{
				Plugin.Log.LogWarning((object)"Could not render the doorbell icon; using the base piece icon.");
			}
		}

		private static void ReplaceBehaviour(GameObject prefab)
		{
			MonoBehaviour[] componentsInChildren = prefab.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren)
			{
				if (val is Interactable || val is Hoverable || val is TextReceiver)
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
			prefab.AddComponent<DoorbellComponent>();
		}
	}
	internal static class FilePicker
	{
		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
		private class OpenFileName
		{
			public int lStructSize;

			public IntPtr hwndOwner;

			public IntPtr hInstance;

			public string lpstrFilter;

			public string lpstrCustomFilter;

			public int nMaxCustFilter;

			public int nFilterIndex;

			public string lpstrFile;

			public int nMaxFile;

			public string lpstrFileTitle;

			public int nMaxFileTitle;

			public string lpstrInitialDir;

			public string lpstrTitle;

			public int Flags;

			public short nFileOffset;

			public short nFileExtension;

			public string lpstrDefExt;

			public IntPtr lCustData;

			public IntPtr lpfnHook;

			public string lpTemplateName;

			public IntPtr pvReserved;

			public int dwReserved;

			public int FlagsEx;
		}

		private const int OFN_NOCHANGEDIR = 8;

		private const int OFN_PATHMUSTEXIST = 2048;

		private const int OFN_FILEMUSTEXIST = 4096;

		private const int OFN_EXPLORER = 524288;

		private static volatile bool _isOpen;

		private static volatile string _result;

		public static bool IsSupported
		{
			get
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Invalid comparison between Unknown and I4
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Invalid comparison between Unknown and I4
				if ((int)Application.platform != 2)
				{
					return (int)Application.platform == 7;
				}
				return true;
			}
		}

		public static bool IsOpen => _isOpen;

		public static void Open()
		{
			if (!_isOpen && IsSupported)
			{
				_isOpen = true;
				IntPtr owner = GetActiveWindow();
				Thread thread = new Thread((ThreadStart)delegate
				{
					Run(owner);
				});
				thread.IsBackground = true;
				thread.Name = "Doorbell file picker";
				thread.SetApartmentState(ApartmentState.STA);
				thread.Start();
			}
		}

		public static bool TryTakeResult(out string path)
		{
			path = _result;
			if (path == null)
			{
				return false;
			}
			_result = null;
			return true;
		}

		private static void Run(IntPtr owner)
		{
			try
			{
				OpenFileName openFileName = new OpenFileName
				{
					hwndOwner = owner,
					lpstrFilter = "Audio files (*.wav, *.ogg, *.mp3)\0*.wav;*.ogg;*.mp3\0All files (*.*)\0*.*\0\0",
					lpstrFile = new string('\0', 1024),
					lpstrTitle = "Doorbell - choose a sound",
					Flags = 530440
				};
				openFileName.nMaxFile = openFileName.lpstrFile.Length;
				openFileName.lStructSize = Marshal.SizeOf(openFileName);
				if (GetOpenFileNameW(openFileName))
				{
					string text = openFileName.lpstrFile?.TrimEnd('\0');
					if (!string.IsNullOrEmpty(text))
					{
						_result = text;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not open the file dialog: " + ex.Message));
			}
			finally
			{
				_isOpen = false;
			}
		}

		[DllImport("user32.dll")]
		private static extern IntPtr GetActiveWindow();

		[DllImport("comdlg32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
		private static extern bool GetOpenFileNameW([In][Out] OpenFileName ofn);
	}
	internal static class MapPing
	{
		public static void Show(Vector3 position, string label, float seconds)
		{
			//IL_0028: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Minimap.instance == (Object)null) && !(seconds <= 0f) && !((Object)(object)SoundPlayer.Instance == (Object)null))
			{
				PinData pin = Minimap.instance.AddPin(position, (PinType)12, label, false, false, 0L, default(PlatformUserID));
				((MonoBehaviour)SoundPlayer.Instance).StartCoroutine(RemoveLater(pin, seconds));
			}
		}

		private static IEnumerator RemoveLater(PinData pin, float seconds)
		{
			yield return (object)new WaitForSeconds(seconds);
			if ((Object)(object)Minimap.instance != (Object)null)
			{
				Minimap.instance.RemovePin(pin);
			}
		}
	}
	[BepInPlugin("batera.Doorbell", "Doorbell", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "batera.Doorbell";

		public const string PluginName = "Doorbell";

		public const string PluginVersion = "1.0.0";

		internal static Plugin Instance;

		internal static ManualLogSource Log;

		internal static ConfigEntry<SoundPreset> SoundPresetSetting;

		internal static ConfigEntry<string> SoundFile;

		internal static ConfigEntry<float> Volume;

		internal static ConfigEntry<float> HearingDistance;

		internal static ConfigEntry<bool> NotifyAsOwner;

		internal static ConfigEntry<bool> DoNotDisturb;

		internal static ConfigEntry<string> OwnerMessage;

		internal static ConfigEntry<float> MapPingSeconds;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			BindConfig();
			GameObject val = new GameObject("Doorbell");
			Object.DontDestroyOnLoad((Object)val);
			val.AddComponent<SoundPlayer>();
			Translations.Register();
			DoorbellPiece.Register();
			_harmony = new Harmony("batera.Doorbell");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Doorbell 1.0.0 loaded");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void BindConfig()
		{
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Expected O, but got Unknown
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Expected O, but got Unknown
			SoundPresetSetting = ((BaseUnityPlugin)this).Config.Bind<SoundPreset>("1 - Sound", "SoundPreset", SoundPreset.Knock, Desc("Doorbell sound you hear. DingDong is built into the mod; MagicBells, Knock and Forge are game sounds; Custom uses SoundFile.", 6));
			Volume = ((BaseUnityPlugin)this).Config.Bind<float>("1 - Sound", "Volume", 0.7f, Desc("Doorbell volume.", 5, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f)));
			HearingDistance = ((BaseUnityPlugin)this).Config.Bind<float>("1 - Sound", "HearingDistance", 40f, Desc("How far (meters) from a doorbell you can hear it ring.", 4, (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 150f)));
			SoundFile = ((BaseUnityPlugin)this).Config.Bind<string>("1 - Sound", "SoundFile", "", new ConfigDescription("Custom sound file (.wav, .ogg or .mp3), used when SoundPreset = Custom. Click Browse to pick a file, or Reset to clear it.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 3,
					CustomDrawer = DrawSoundFile
				}
			}));
			((BaseUnityPlugin)this).Config.Bind<string>("1 - Sound", "TestSound", "", new ConfigDescription("Plays the doorbell sound with the current settings.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 2,
					HideDefaultButton = true,
					CustomDrawer = DrawTestButton
				}
			}));
			NotifyAsOwner = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Owner", "NotifyWhenAway", true, Desc("When someone rings a doorbell you built, play the sound and show a message wherever you are.", 4));
			DoNotDisturb = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Owner", "DoNotDisturb", false, Desc("Temporarily mute the notification when you are away. You still hear doorbells near you.", 3));
			MapPingSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Owner", "MapPingSeconds", 30f, Desc("How long (seconds) the doorbell that rang stays marked on your map. Only you see it. 0 = off.", 2, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f)));
			OwnerMessage = ((BaseUnityPlugin)this).Config.Bind<string>("2 - Owner", "MessageText", "{player} tocou sua campainha!", Desc("Message shown to the owner. {player} = who rang.", 1));
		}

		private static ConfigDescription Desc(string text, int order, AcceptableValueBase range = null)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			return new ConfigDescription(text, range, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = order
				}
			});
		}

		private static void DrawSoundFile(ConfigEntryBase entry)
		{
			string value = SoundFile.Value;
			GUILayout.Label(string.IsNullOrEmpty(value) ? "(none)" : Path.GetFileName(value), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			if (FilePicker.IsSupported)
			{
				bool enabled = GUI.enabled;
				GUI.enabled = enabled && !FilePicker.IsOpen;
				if (GUILayout.Button(FilePicker.IsOpen ? "Choosing..." : "Browse...", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) }))
				{
					FilePicker.Open();
				}
				GUI.enabled = enabled;
			}
		}

		private static void DrawTestButton(ConfigEntryBase entry)
		{
			if (GUILayout.Button("Test sound", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }))
			{
				SoundPlayer.Instance?.Play2D();
			}
		}
	}
	internal static class RingNetwork
	{
		[HarmonyPatch(typeof(Game), "Start")]
		private static class GameStartPatch
		{
			private static void Postfix()
			{
				ZRoutedRpc instance = ZRoutedRpc.instance;
				if (instance != null)
				{
					instance.Register<long, string, Vector3>("Batera_Doorbell_NotifyOwner", (Action<long, long, string, Vector3>)RPC_NotifyOwner);
				}
			}
		}

		private const string RpcNotify = "Batera_Doorbell_NotifyOwner";

		public static void NotifyOwner(long ownerId, string ringer, Vector3 position)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (ownerId != 0L && ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "Batera_Doorbell_NotifyOwner", new object[3] { ownerId, ringer, position });
			}
		}

		private static void RPC_NotifyOwner(long sender, long ownerId, string ringer, Vector3 position)
		{
			//IL_001f: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || localPlayer.GetPlayerID() != ownerId || Vector3.Distance(((Component)localPlayer).transform.position, position) <= Plugin.HearingDistance.Value || !Plugin.NotifyAsOwner.Value || Plugin.DoNotDisturb.Value)
			{
				return;
			}
			SoundPlayer.Instance?.Play2D();
			if ((Object)(object)MessageHud.instance != (Object)null)
			{
				string text = Plugin.OwnerMessage.Value;
				if (string.IsNullOrWhiteSpace(text))
				{
					text = "{player} tocou sua campainha!";
				}
				MessageHud.instance.ShowMessage((MessageType)2, text.Replace("{player}", ringer), 0, (Sprite)null, false, true);
			}
			MapPing.Show(position, string.Format(Translations.Get("$batera_doorbell_someone_rang"), ringer), Plugin.MapPingSeconds.Value);
		}
	}
	internal class SoundPlayer : MonoBehaviour
	{
		private static readonly Dictionary<SoundPreset, string> GameSounds = new Dictionary<SoundPreset, string>
		{
			{
				SoundPreset.MagicBells,
				"sfx_secretfound"
			},
			{
				SoundPreset.Knock,
				"sfx_gui_craftitem_workbench"
			},
			{
				SoundPreset.Forge,
				"sfx_gui_craftitem_forge_end"
			}
		};

		private readonly Dictionary<SoundPreset, AudioClip> _gameClips = new Dictionary<SoundPreset, AudioClip>();

		private AudioSource _source2D;

		private AudioClip _dingDong;

		private AudioClip _customClip;

		public static SoundPlayer Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			_source2D = ((Component)this).gameObject.AddComponent<AudioSource>();
			_source2D.playOnAwake = false;
			_source2D.spatialBlend = 0f;
			_source2D.ignoreListenerPause = true;
			_dingDong = CreateDingDong();
			LoadCustomClip();
			Plugin.SoundFile.SettingChanged += delegate
			{
				if (!string.IsNullOrWhiteSpace(Plugin.SoundFile.Value))
				{
					Plugin.SoundPresetSetting.Value = SoundPreset.Custom;
				}
				LoadCustomClip();
			};
		}

		private void Update()
		{
			if (FilePicker.TryTakeResult(out var path))
			{
				Plugin.SoundFile.Value = path;
			}
		}

		public void Play2D()
		{
			_source2D.Stop();
			_source2D.PlayOneShot(GetClip(), Plugin.Volume.Value);
		}

		public void Play3D(Vector3 position)
		{
			//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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			AudioClip clip = GetClip();
			GameObject val = new GameObject("DoorbellRing");
			val.transform.position = position;
			AudioSource obj = val.AddComponent<AudioSource>();
			obj.clip = clip;
			obj.volume = Plugin.Volume.Value;
			obj.spatialBlend = 1f;
			obj.rolloffMode = (AudioRolloffMode)1;
			obj.minDistance = 3f;
			obj.maxDistance = Plugin.HearingDistance.Value;
			obj.dopplerLevel = 0f;
			obj.Play();
			Object.Destroy((Object)val, clip.length + 0.2f);
		}

		private AudioClip GetClip()
		{
			SoundPreset value = Plugin.SoundPresetSetting.Value;
			if (value == SoundPreset.Custom)
			{
				if (!((Object)(object)_customClip != (Object)null))
				{
					return _dingDong;
				}
				return _customClip;
			}
			if (GameSounds.TryGetValue(value, out var value2))
			{
				if (!_gameClips.TryGetValue(value, out var value3) || (Object)(object)value3 == (Object)null)
				{
					value3 = FindGameClip(value2);
					if ((Object)(object)value3 != (Object)null)
					{
						_gameClips[value] = value3;
					}
				}
				if ((Object)(object)value3 != (Object)null)
				{
					return value3;
				}
			}
			return _dingDong;
		}

		private static AudioClip FindGameClip(string prefabName)
		{
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return null;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab(prefabName);
			ZSFX val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponentInChildren<ZSFX>(true) : null);
			if ((Object)(object)val == (Object)null || val.m_audioClips == null || val.m_audioClips.Length == 0)
			{
				Plugin.Log.LogWarning((object)("Game sound '" + prefabName + "' not found. Using the built-in ding-dong."));
				return null;
			}
			return val.m_audioClips[0];
		}

		private void LoadCustomClip()
		{
			//IL_008a: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			_customClip = null;
			string text = Plugin.SoundFile.Value?.Trim().Trim('"');
			if (string.IsNullOrEmpty(text))
			{
				return;
			}
			string text2 = ResolveSoundPath(text);
			if (text2 == null)
			{
				Plugin.Log.LogWarning((object)("Sound file not found: '" + text + "'. Using the built-in ding-dong."));
				return;
			}
			AudioType type;
			switch (Path.GetExtension(text2).ToLowerInvariant())
			{
			case ".wav":
				type = (AudioType)20;
				break;
			case ".ogg":
				type = (AudioType)14;
				break;
			case ".mp3":
				type = (AudioType)13;
				break;
			default:
				Plugin.Log.LogWarning((object)("Unsupported sound format '" + text2 + "'. Use .wav, .ogg or .mp3."));
				return;
			}
			((MonoBehaviour)this).StartCoroutine(LoadClip(text2, type));
		}

		private static string ResolveSoundPath(string setting)
		{
			if (Path.IsPathRooted(setting))
			{
				if (!File.Exists(setting))
				{
					return null;
				}
				return setting;
			}
			string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)Plugin.Instance).Info.Location);
			string[] array = new string[3]
			{
				Paths.ConfigPath,
				directoryName,
				Paths.PluginPath
			};
			foreach (string text in array)
			{
				if (!string.IsNullOrEmpty(text))
				{
					string text2 = Path.Combine(text, setting);
					if (File.Exists(text2))
					{
						return text2;
					}
				}
			}
			return null;
		}

		private IEnumerator LoadClip(string path, AudioType type)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(new Uri(path).AbsoluteUri, type);
			try
			{
				yield return request.SendWebRequest();
				if ((int)request.result != 1)
				{
					Plugin.Log.LogWarning((object)("Failed to load sound '" + path + "': " + request.error));
					yield break;
				}
				AudioClip content = DownloadHandlerAudioClip.GetContent(request);
				if ((Object)(object)content == (Object)null || content.length <= 0f)
				{
					Plugin.Log.LogWarning((object)("Sound '" + path + "' is empty or invalid."));
					yield break;
				}
				((Object)content).name = Path.GetFileNameWithoutExtension(path);
				_customClip = content;
				Plugin.Log.LogInfo((object)("Loaded custom doorbell sound: " + path));
			}
			finally
			{
				((IDisposable)request)?.Dispose();
			}
		}

		private static AudioClip CreateDingDong()
		{
			float[] array = new float[2] { 659.25f, 523.25f };
			int num = 85995;
			float[] array2 = new float[num];
			for (int i = 0; i < array.Length; i++)
			{
				float num2 = array[i];
				int num3 = (int)(24255f * (float)i);
				int num4 = 61740;
				for (int j = 0; j < num4 && num3 + j < num; j++)
				{
					float num5 = (float)j / 44100f;
					float num6 = Mathf.Clamp01(num5 / 0.004f);
					float num7 = Mathf.Exp((0f - num5) * 3.2f);
					float num8 = Mathf.Sin(MathF.PI * 2f * num2 * num5) + 0.5f * Mathf.Sin(MathF.PI * 2f * num2 * 2f * num5) * Mathf.Exp((0f - num5) * 5f) + 0.25f * Mathf.Sin(MathF.PI * 2f * num2 * 3.01f * num5) * Mathf.Exp((0f - num5) * 9f);
					array2[num3 + j] += num8 * num6 * num7 * 0.35f;
				}
			}
			AudioClip obj = AudioClip.Create("DoorbellDingDong", array2.Length, 1, 44100, false);
			obj.SetData(array2, 0);
			return obj;
		}
	}
	public enum SoundPreset
	{
		DingDong,
		MagicBells,
		Knock,
		Forge,
		Custom
	}
	internal static class Translations
	{
		public const string PieceName = "$piece_batera_doorbell";

		public const string PieceDescription = "$piece_batera_doorbell_desc";

		public const string Ring = "$batera_doorbell_ring";

		public const string OwnedBy = "$batera_doorbell_owned_by";

		public const string SomeoneRang = "$batera_doorbell_someone_rang";

		public static void Register()
		{
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			string text = "English";
			localization.AddTranslation(ref text, new Dictionary<string, string>
			{
				{
					Key("$piece_batera_doorbell"),
					"Doorbell"
				},
				{
					Key("$piece_batera_doorbell_desc"),
					"Visitors can ring it, even inside your ward. You get notified wherever you are."
				},
				{
					Key("$batera_doorbell_ring"),
					"Ring"
				},
				{
					Key("$batera_doorbell_owned_by"),
					"{0}'s doorbell"
				},
				{
					Key("$batera_doorbell_someone_rang"),
					"{0} rang the doorbell"
				}
			});
			text = "Portuguese_Brazilian";
			localization.AddTranslation(ref text, new Dictionary<string, string>
			{
				{
					Key("$piece_batera_doorbell"),
					"Campainha"
				},
				{
					Key("$piece_batera_doorbell_desc"),
					"Visitantes podem tocar, mesmo dentro do seu ward. Você é avisado onde estiver."
				},
				{
					Key("$batera_doorbell_ring"),
					"Tocar"
				},
				{
					Key("$batera_doorbell_owned_by"),
					"Campainha de {0}"
				},
				{
					Key("$batera_doorbell_someone_rang"),
					"{0} tocou a campainha"
				}
			});
		}

		public static string Get(string text)
		{
			if (Localization.instance == null)
			{
				return text;
			}
			return Localization.instance.Localize(text);
		}

		private static string Key(string token)
		{
			return token.TrimStart('$');
		}
	}
}