Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Doorbell v1.0.0
plugins/Doorbell.dll
Decompiled a day agousing 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('$'); } } }