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 ShipSmokeDispenser v0.2.7
ShipSmokeDispenser/shipsmokedispenser.dll
Decompiled 14 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Collections; using Unity.Netcode; using UnityEngine; [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("ShipSmokeDispenser")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.2.6.0")] [assembly: AssemblyInformationalVersion("0.2.6")] [assembly: AssemblyProduct("ShipSmokeDispenser")] [assembly: AssemblyTitle("ShipSmokeDispenser")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.2.6.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 ShipSmokeDispenser { internal sealed class DispenserModel : IDisposable { internal readonly GameObject Root; private readonly InteractTrigger trigger; private readonly List<Material> materials = new List<Material>(); private Texture2D? labelTexture; internal Vector3 OutletPosition => Root.transform.TransformPoint(new Vector3(0f, -0.28f, -0.39f)); internal DispenserModel(Terminal terminal, Transform furniture) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0043: 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_007b: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0106: 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_013a: 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_016e: 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) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: 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_01f7: 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_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_0311: Unknown result type (might be due to invalid IL or missing references) //IL_031b: Expected O, but got Unknown //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Expected O, but got Unknown //IL_0331: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Expected O, but got Unknown //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Expected O, but got Unknown //IL_0351: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Expected O, but got Unknown //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Expected O, but got Unknown Root = new GameObject("ShipSmokeDispenser"); try { Root.transform.SetParent(furniture, false); Material material = Material(new Color(0.075f, 0.11f, 0.13f), terminal); Material material2 = Material(new Color(0.72f, 0.73f, 0.65f), terminal); Material material3 = Material(new Color(0.015f, 0.025f, 0.025f), terminal); Material material4 = Material(new Color(0.1f, 0.65f, 0.28f), terminal); Material material5 = Material(new Color(0.92f, 0.91f, 0.84f), terminal); Material material6 = Material(new Color(0.7f, 0.36f, 0.12f), terminal); Part("Steel casing", new Vector3(0f, 0f, 0f), new Vector3(0.55f, 0.77f, 0.32f), material); Part("Front panel", new Vector3(0f, 0f, -0.171f), new Vector3(0.5f, 0.71f, 0.025f), material2); Part("Label panel", new Vector3(0f, 0.2f, -0.19f), new Vector3(0.44f, 0.27f, 0.018f), material3); Part("Dispense button", new Vector3(0.17f, -0.085f, -0.205f), new Vector3(0.08f, 0.08f, 0.04f), material4); Part("Cigarette icon", new Vector3(-0.055f, -0.075f, -0.193f), new Vector3(0.18f, 0.025f, 0.018f), material5); Part("Filter icon", new Vector3(0.055f, -0.075f, -0.194f), new Vector3(0.05f, 0.025f, 0.018f), material6); Part("Outlet slot", new Vector3(0f, -0.23f, -0.193f), new Vector3(0.39f, 0.1f, 0.02f), material3); Part("Collection lip", new Vector3(0f, -0.3f, -0.23f), new Vector3(0.44f, 0.025f, 0.17f), material); PrintedLabel(terminal); trigger = ((Component)furniture).GetComponentInChildren<InteractTrigger>(true); trigger.interactable = false; trigger.hoverTip = "Dispense cigarette : [E]"; trigger.disabledHoverTip = "Cigarettes loading..."; trigger.oneHandedItemAllowed = true; trigger.twoHandedItemAllowed = true; trigger.holdInteraction = false; trigger.interactCooldown = true; trigger.cooldownTime = 0.35f; trigger.triggerOnce = false; trigger.onInteract = new InteractEvent(); trigger.onInteractEarly = new InteractEvent(); trigger.onInteractEarlyOtherClients = new InteractEvent(); trigger.onStopInteract = new InteractEvent(); trigger.onCancelAnimation = new InteractEvent(); trigger.holdingInteractEvent = new InteractEventFloat(); InteractTrigger[] componentsInChildren = ((Component)terminal).GetComponentsInChildren<InteractTrigger>(true); foreach (InteractTrigger val in componentsInChildren) { if ((Object)(object)val != (Object)(object)trigger && Object.op_Implicit((Object)(object)val.hoverIcon)) { trigger.hoverIcon = val.hoverIcon; trigger.disabledHoverIcon = val.hoverIcon; break; } } } catch { Dispose(); throw; } } internal void SetReady(bool ready) { trigger.interactable = ready; } private Material Material(Color color, Terminal terminal) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0071: 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) Shader val = Shader.Find("HDRP/Lit") ?? Shader.Find("HDRP/Unlit"); Material val2; if (Object.op_Implicit((Object)(object)val)) { val2 = new Material(val); } else { MeshRenderer componentInChildren = ((Component)terminal).GetComponentInChildren<MeshRenderer>(true); if (!Object.op_Implicit((Object)(object)componentInChildren) || !Object.op_Implicit((Object)(object)((Renderer)componentInChildren).sharedMaterial)) { throw new InvalidOperationException("Cannot find a suitable machine shader."); } val2 = new Material(((Renderer)componentInChildren).sharedMaterial); } if (val2.HasProperty("_BaseColor")) { val2.SetColor("_BaseColor", color); } if (val2.HasProperty("_Color")) { val2.SetColor("_Color", color); } if (val2.HasProperty("_Metallic")) { val2.SetFloat("_Metallic", 0.25f); } materials.Add(val2); return val2; } private void Part(string name, Vector3 position, Vector3 scale, Material material) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) GameObject obj = GameObject.CreatePrimitive((PrimitiveType)3); ((Object)obj).name = name; obj.transform.SetParent(Root.transform, false); obj.transform.localPosition = position; obj.transform.localScale = scale; Collider component = obj.GetComponent<Collider>(); component.enabled = false; Object.Destroy((Object)(object)component); ((Renderer)obj.GetComponent<MeshRenderer>()).sharedMaterial = material; } private void PrintedLabel(Terminal terminal) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0073: 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_014c: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("ShipSmokeDispenser.Label.png") ?? throw new InvalidOperationException("Missing dispenser label texture."); using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); labelTexture = new Texture2D(2, 2, (TextureFormat)3, true); if (!ImageConversion.LoadImage(labelTexture, memoryStream.ToArray(), true)) { throw new InvalidOperationException("Cannot load dispenser label texture."); } ((Texture)labelTexture).wrapMode = (TextureWrapMode)1; ((Texture)labelTexture).anisoLevel = 4; Material val = Material(Color.white, terminal); if (val.HasProperty("_BaseColorMap")) { val.SetTexture("_BaseColorMap", (Texture)(object)labelTexture); } else { if (!val.HasProperty("_UnlitColorMap")) { throw new InvalidOperationException("Machine shader cannot display the printed label."); } val.SetTexture("_UnlitColorMap", (Texture)(object)labelTexture); } if (val.HasProperty("_UnlitColor")) { val.SetColor("_UnlitColor", Color.white); } if (val.HasProperty("_Metallic")) { val.SetFloat("_Metallic", 0f); } val.renderQueue = 2000; GameObject obj = GameObject.CreatePrimitive((PrimitiveType)5); ((Object)obj).name = "Printed front panel"; obj.transform.SetParent(Root.transform, false); obj.transform.localPosition = new Vector3(0f, 0.2f, -0.1992f); obj.transform.localScale = new Vector3(0.44f, 0.27f, 1f); Collider component = obj.GetComponent<Collider>(); component.enabled = false; Object.Destroy((Object)(object)component); ((Renderer)obj.GetComponent<MeshRenderer>()).sharedMaterial = val; } public void Dispose() { if (Object.op_Implicit((Object)(object)trigger)) { trigger.interactable = false; } if (Object.op_Implicit((Object)(object)Root)) { Object.Destroy((Object)(object)Root); } foreach (Material material in materials) { if (Object.op_Implicit((Object)(object)material)) { Object.Destroy((Object)(object)material); } } materials.Clear(); if (Object.op_Implicit((Object)(object)labelTexture)) { Object.Destroy((Object)(object)labelTexture); } } } internal sealed class DispenserSnapshot { internal const int Protocol = 3; internal const int Size = 38; internal bool Enabled; internal bool Available; internal ulong NetworkId; internal float X; internal float Y; internal float Z; internal float Pitch; internal float Yaw; internal float Roll; internal static bool HasPayload(int bufferLength, int position) { if (position >= 0 && bufferLength >= position) { return bufferLength - position == 38; } return false; } internal byte[] Encode() { using MemoryStream memoryStream = new MemoryStream(38); using BinaryWriter binaryWriter = new BinaryWriter(memoryStream); binaryWriter.Write(3); binaryWriter.Write(Enabled); binaryWriter.Write(Available); binaryWriter.Write(NetworkId); binaryWriter.Write(X); binaryWriter.Write(Y); binaryWriter.Write(Z); binaryWriter.Write(Pitch); binaryWriter.Write(Yaw); binaryWriter.Write(Roll); return memoryStream.ToArray(); } internal static bool TryDecode(byte[] data, out DispenserSnapshot snapshot) { snapshot = null; if (data == null || data.Length != 38 || data[4] > 1 || data[5] > 1) { return false; } using MemoryStream input = new MemoryStream(data, writable: false); using BinaryReader binaryReader = new BinaryReader(input); if (binaryReader.ReadInt32() != 3) { return false; } DispenserSnapshot dispenserSnapshot = new DispenserSnapshot { Enabled = binaryReader.ReadBoolean(), Available = binaryReader.ReadBoolean(), NetworkId = binaryReader.ReadUInt64(), X = binaryReader.ReadSingle(), Y = binaryReader.ReadSingle(), Z = binaryReader.ReadSingle(), Pitch = binaryReader.ReadSingle(), Yaw = binaryReader.ReadSingle(), Roll = binaryReader.ReadSingle() }; float[] array = new float[6] { dispenserSnapshot.X, dispenserSnapshot.Y, dispenserSnapshot.Z, dispenserSnapshot.Pitch, dispenserSnapshot.Yaw, dispenserSnapshot.Roll }; foreach (float f in array) { if (float.IsNaN(f) || float.IsInfinity(f)) { return false; } } snapshot = dispenserSnapshot; return true; } } internal static class Furniture { internal const string UnlockableName = "Cigarette dispenser"; internal static uint PrefabHash; internal static UnlockableItem Item; internal static GameObject Prefab; internal static void Register() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_0142: 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_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Expected O, but got Unknown //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Expected O, but got Unknown //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02ed: Expected O, but got Unknown //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Expected O, but got Unknown //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Expected O, but got Unknown //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Expected O, but got Unknown //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) //IL_0336: 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_0344: Unknown result type (might be due to invalid IL or missing references) //IL_034b: 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_035e: Expected O, but got Unknown Assembly assembly = ((object)Chainloader.PluginInfos["evaisa.lethallib"].Instance).GetType().Assembly; Prefab = (GameObject)assembly.GetType("LethalLib.Modules.NetworkPrefabs").GetMethod("CreateNetworkPrefab", new Type[1] { typeof(string) }).Invoke(null, new object[1] { "achachala.shipsmokedispenser.Furniture.v2" }); PrefabHash = StablePrefabHash("achachala.shipsmokedispenser.Furniture.v2"); typeof(NetworkObject).GetField("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).SetValue(Prefab.GetComponent<NetworkObject>(), PrefabHash); int num = LayerMask.NameToLayer("PlaceableShipObjects"); if (num < 0) { throw new InvalidOperationException("Missing native PlaceableShipObjects layer."); } Prefab.layer = num; Prefab.tag = "PlaceableObject"; AudioSource obj = Prefab.AddComponent<AudioSource>(); obj.playOnAwake = false; obj.spatialBlend = 1f; obj.rolloffMode = (AudioRolloffMode)1; obj.minDistance = 1f; obj.maxDistance = 12f; AutoParentToShip parentObject = Prefab.AddComponent<AutoParentToShip>(); PlaceableShipObject val = Prefab.AddComponent<PlaceableShipObject>(); BoxCollider val2 = Prefab.AddComponent<BoxCollider>(); val2.size = new Vector3(0.56f, 0.78f, 0.34f); GameObject val3 = GameObject.CreatePrimitive((PrimitiveType)3); Mesh val4 = Object.Instantiate<Mesh>(val3.GetComponent<MeshFilter>().sharedMesh); Vector3[] vertices = val4.vertices; for (int i = 0; i < vertices.Length; i++) { vertices[i] = Vector3.Scale(vertices[i], new Vector3(0.55f, 0.77f, 0.32f)); } val4.vertices = vertices; val4.RecalculateBounds(); MeshFilter val5 = Prefab.AddComponent<MeshFilter>(); val5.sharedMesh = val4; MeshRenderer obj2 = Prefab.AddComponent<MeshRenderer>(); ((Renderer)obj2).sharedMaterial = ((Renderer)val3.GetComponent<MeshRenderer>()).sharedMaterial; Object.Destroy((Object)(object)val3); ((Renderer)obj2).enabled = false; val.parentObject = parentObject; val.mainMesh = val5; val.mainTransform = Prefab.transform; val.placeObjectCollider = (Collider)(object)val2; val.yOffset = 0.39f; val.AllowPlacementOnCounters = true; val.AllowPlacementOnWalls = true; val.overrideWallOffset = true; val.wallOffset = 0.18f; Prefab.AddComponent<FurnitureMarker>(); GameObject val6 = new GameObject("Dispense interaction"); val6.transform.SetParent(Prefab.transform, false); int num2 = LayerMask.NameToLayer("InteractableObject"); val6.layer = ((num2 >= 0) ? num2 : 9); val6.tag = "InteractTrigger"; val6.AddComponent<DispenserMarker>(); val6.AddComponent<BoxCollider>().size = new Vector3(0.54f, 0.76f, 0.3f); InteractTrigger obj3 = val6.AddComponent<InteractTrigger>(); obj3.onInteract = new InteractEvent(); obj3.onInteractEarly = new InteractEvent(); obj3.onInteractEarlyOtherClients = new InteractEvent(); obj3.onStopInteract = new InteractEvent(); obj3.onCancelAnimation = new InteractEvent(); obj3.holdingInteractEvent = new InteractEventFloat(); obj3.interactable = false; Item = new UnlockableItem { unlockableName = "Cigarette dispenser", prefabObject = Prefab, unlockableType = 1, IsPlaceable = true, canBeStored = true, maxNumber = 1, alreadyUnlocked = true, spawnPrefab = true }; MethodInfo methodInfo = assembly.GetType("LethalLib.Modules.Unlockables").GetMethods(BindingFlags.Static | BindingFlags.Public).Single((MethodInfo m) => m.Name == "RegisterUnlockable" && m.GetParameters().Length == 3 && m.GetParameters()[0].ParameterType == typeof(UnlockableItem) && m.GetParameters()[1].ParameterType == typeof(int)); Type parameterType = methodInfo.GetParameters()[2].ParameterType; methodInfo.Invoke(null, new object[3] { Item, -1, Enum.ToObject(parameterType, 0) }); } internal static void Configure() { //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_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) StartOfRound instance = StartOfRound.Instance; if (!Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)Prefab)) { return; } int num = ResolveItem(); if (num < 0) { return; } PlaceableShipObject component = Prefab.GetComponent<PlaceableShipObject>(); AutoParentToShip component2 = Prefab.GetComponent<AutoParentToShip>(); component.unlockableID = (component2.unlockableID = num); PlaceableShipObject[] array = Object.FindObjectsOfType<PlaceableShipObject>(); foreach (PlaceableShipObject val in array) { if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.placeObjectSFX) && !Object.op_Implicit((Object)(object)((Component)val).GetComponent<FurnitureMarker>())) { component.placeObjectSFX = val.placeObjectSFX; break; } } component2.overrideOffset = true; component2.positionOffset = instance.elevatorTransform.InverseTransformPoint(DefaultPosition()); component2.rotationOffset = instance.elevatorTransform.eulerAngles; } internal static Vector3 DefaultPosition() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_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_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: 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) Bounds bounds = StartOfRound.Instance.shipInnerRoomBounds.bounds; Vector3 center = ((Bounds)(ref bounds)).center; RaycastHit val = default(RaycastHit); if (Physics.Raycast(center, Vector3.down, ref val, ((Bounds)(ref bounds)).size.y + 5f, LayerMask.GetMask(new string[2] { "Room", "Colliders" }), (QueryTriggerInteraction)1)) { return ((RaycastHit)(ref val)).point + Vector3.up * 0.4f; } return new Vector3(center.x, ((Bounds)(ref bounds)).min.y + 0.4f, center.z); } internal static uint StablePrefabHash(string name) { uint num = 2166136261u; foreach (char c in name) { num = (num ^ c) * 16777619; } return num; } internal static int ResolveItem() { StartOfRound instance = StartOfRound.Instance; if (!Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)instance.unlockablesList)) { return -1; } int num = instance.unlockablesList.unlockables.FindIndex((UnlockableItem item) => item != null && string.Equals(item.unlockableName, "Cigarette dispenser", StringComparison.Ordinal)); if (num >= 0) { Item = instance.unlockablesList.unlockables[num]; } return num; } internal static bool BindReplica(FurnitureMarker marker, bool register = true) { int num = ResolveItem(); if (num < 0) { return false; } PlaceableShipObject component = ((Component)marker).GetComponent<PlaceableShipObject>(); AutoParentToShip component2 = ((Component)marker).GetComponent<AutoParentToShip>(); component.unlockableID = (component2.unlockableID = num); component.parentObject = component2; StartOfRound instance = StartOfRound.Instance; if (register && instance.SpawnedShipUnlockables != null) { instance.SpawnedShipUnlockables[num] = ((Component)marker).gameObject; } return true; } internal static FurnitureMarker? Find(ulong? networkId = null) { NetworkManager singleton = NetworkManager.Singleton; if (!Object.op_Implicit((Object)(object)singleton) || singleton.SpawnManager == null || ResolveItem() < 0) { return null; } if (networkId.HasValue) { if (!singleton.SpawnManager.SpawnedObjects.TryGetValue(networkId.Value, out var value)) { return null; } FurnitureMarker component = ((Component)value).GetComponent<FurnitureMarker>(); if (!Object.op_Implicit((Object)(object)component) || !BindReplica(component)) { return null; } return component; } foreach (NetworkObject value2 in singleton.SpawnManager.SpawnedObjects.Values) { if (Object.op_Implicit((Object)(object)value2) && value2.IsSpawned) { FurnitureMarker component2 = ((Component)value2).GetComponent<FurnitureMarker>(); if (Object.op_Implicit((Object)(object)component2) && BindReplica(component2)) { return component2; } } } return null; } } public sealed class FurnitureMarker : MonoBehaviour { } [HarmonyPatch(typeof(AutoParentToShip), "Awake")] internal static class FurnitureAwakePatch { [HarmonyPrefix] private static void Prefix(AutoParentToShip __instance) { FurnitureMarker component = ((Component)__instance).GetComponent<FurnitureMarker>(); if (Object.op_Implicit((Object)(object)component)) { Furniture.BindReplica(component, register: false); } } } [BepInPlugin("achachala.shipsmokedispenser", "Ship Smoke Dispenser", "0.2.6")] [BepInDependency("com.roandegraaf.lethalsmokes", "1.0.0")] [BepInDependency("evaisa.lethallib", "1.2.0")] public sealed class Plugin : BaseUnityPlugin { public const string Id = "achachala.shipsmokedispenser"; public const string Version = "0.2.6"; public const string SmokesId = "com.roandegraaf.lethalsmokes"; private const string Hello = "achachala.shipsmokedispenser.hello.v3"; private const string Settings = "achachala.shipsmokedispenser.settings.v3"; private const string Dispense = "achachala.shipsmokedispenser.dispense.v1"; internal static Plugin Instance; private ConfigEntry<bool> enabledConfig; private ConfigEntry<float> cooldownConfig; private ConfigEntry<int> valueConfig; private readonly RequestGate requests = new RequestGate(); private readonly HashSet<ulong> handshakePeers = new HashSet<ulong>(); private NetworkManager? network; private Terminal? terminal; private DispenserModel? model; private FurnitureMarker? furniture; private FurnitureMarker? positionedFurniture; private Item? cigarette; private PropertyInfo? cigaretteProperty; private Harmony harmony; private bool attached; private bool haveSettings; private bool activeEnabled; private float nextUpdate; private float nextHello; private bool? collidersEnabled; private bool hostHasFurniture; private ulong hostFurnitureId; private Vector3 hostPositionOffset; private Vector3 hostRotationOffset; private bool applyHostPlacement; private float nextDiagnostic; private string lastWaitReason = ""; private uint localSequence; private bool missingItemLogged; private float nextModelAttempt; private void Awake() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Expected O, but got Unknown Instance = this; enabledConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Dispenser", "Enabled", true, "Host: create the unlimited dispenser in the ship."); cooldownConfig = ((BaseUnityPlugin)this).Config.Bind<float>("Dispenser", "SecondsBetweenUses", 0.35f, new ConfigDescription("Host: per-player debounce; supply is unlimited. Prevents duplicate clicks.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>())); valueConfig = ((BaseUnityPlugin)this).Config.Bind<int>("Dispenser", "DispensedScrapValue", 0, new ConfigDescription("Host: resale value of dispenser cigarettes. Zero gives free cigarettes without generating credits. Does not change found cigarettes.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1000), Array.Empty<object>())); RemoveOldPlacementConfig(); Assembly assembly = ((object)Chainloader.PluginInfos["com.roandegraaf.lethalsmokes"].Instance).GetType().Assembly; cigaretteProperty = assembly.GetType("LethalSmokes.CigarettePrefab")?.GetProperty("Item", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (cigaretteProperty == null) { throw new InvalidOperationException("This LethalSmokes version does not expose CigarettePrefab.Item. Dispenser cannot load safely."); } Furniture.Register(); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Registered dispenser network prefab hash={Furniture.PrefabHash}."); harmony = new Harmony("achachala.shipsmokedispenser"); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Ship Smoke Dispenser 0.2.6 loaded. Install on host AND all clients, alongside LethalSmokes."); } private unsafe void Update() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Expected O, but got Unknown //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0184: 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_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_05f4: Unknown result type (might be due to invalid IL or missing references) //IL_05f9: Unknown result type (might be due to invalid IL or missing references) //IL_0605: Unknown result type (might be due to invalid IL or missing references) //IL_060a: Unknown result type (might be due to invalid IL or missing references) //IL_061e: Unknown result type (might be due to invalid IL or missing references) //IL_0620: Unknown result type (might be due to invalid IL or missing references) //IL_062f: Unknown result type (might be due to invalid IL or missing references) //IL_0631: Unknown result type (might be due to invalid IL or missing references) //IL_0635: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)(object)network || (attached && (!Object.op_Implicit((Object)(object)singleton) || !singleton.IsListening))) { Detach(); } if (!Object.op_Implicit((Object)(object)singleton) || !singleton.IsListening || singleton.CustomMessagingManager == null) { return; } if (!attached) { network = singleton; singleton.CustomMessagingManager.RegisterNamedMessageHandler("achachala.shipsmokedispenser.hello.v3", new HandleNamedMessageDelegate(ReceiveHello)); singleton.CustomMessagingManager.RegisterNamedMessageHandler("achachala.shipsmokedispenser.settings.v3", new HandleNamedMessageDelegate(ReceiveSettings)); singleton.CustomMessagingManager.RegisterNamedMessageHandler("achachala.shipsmokedispenser.dispense.v1", new HandleNamedMessageDelegate(ReceiveDispense)); singleton.OnClientDisconnectCallback += Disconnected; singleton.OnClientConnectedCallback += Connected; attached = true; nextHello = (nextUpdate = 0f); } if (Time.unscaledTime < nextUpdate) { return; } nextUpdate = Time.unscaledTime + 0.25f; if (singleton.IsServer) { activeEnabled = enabledConfig.Value; haveSettings = true; } else if (singleton.IsConnectedClient && Time.unscaledTime >= nextHello) { nextHello = Time.unscaledTime + 2f; FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1); try { int num = 3; ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives)); singleton.CustomMessagingManager.SendNamedMessage("achachala.shipsmokedispenser.hello.v3", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } if (!Object.op_Implicit((Object)(object)terminal)) { terminal = Object.FindObjectOfType<Terminal>(); } FurnitureMarker furnitureMarker = (singleton.IsServer ? Furniture.Find() : ((haveSettings && hostHasFurniture) ? Furniture.Find(hostFurnitureId) : null)); if ((Object)(object)furnitureMarker != (Object)(object)furniture) { DestroyModel(); furniture = furnitureMarker; collidersEnabled = null; } if (!Object.op_Implicit((Object)(object)cigarette)) { ref Item? reference = ref cigarette; object? obj = cigaretteProperty?.GetValue(null); reference = (Item?)((obj is Item) ? obj : null); } if (!singleton.IsServer && Object.op_Implicit((Object)(object)furnitureMarker) && applyHostPlacement && Furniture.BindReplica(furnitureMarker)) { PlaceableShipObject component = ((Component)furnitureMarker).GetComponent<PlaceableShipObject>(); ShipBuildModeManager instance = ShipBuildModeManager.Instance; if (!Object.op_Implicit((Object)(object)instance) || !instance.InBuildMode || AccessTools.Field(typeof(ShipBuildModeManager), "placingObject").GetValue(instance) != component) { AutoParentToShip component2 = ((Component)furnitureMarker).GetComponent<AutoParentToShip>(); component2.overrideOffset = true; component2.disableObject = false; component2.positionOffset = hostPositionOffset; component2.rotationOffset = hostRotationOffset; component2.MoveToOffset(); if (!((Component)furnitureMarker).gameObject.activeSelf) { ((Component)furnitureMarker).gameObject.SetActive(true); } Furniture.Item.inStorage = false; applyHostPlacement = false; } } if (!singleton.IsServer && (!haveSettings || !hostHasFurniture || !Object.op_Implicit((Object)(object)furniture))) { string text = ((!haveSettings) ? "waiting for host handshake (confirm every player uses 0.2.6)" : ((!hostHasFurniture) ? "host reports no deployed dispenser" : $"waiting for network object {hostFurnitureId}; check matching mods/dependencies and prefab registration")); if (Time.unscaledTime >= nextDiagnostic || text != lastWaitReason) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Dispenser client: " + text)); nextDiagnostic = Time.unscaledTime + 20f; lastWaitReason = text; } } if (!singleton.IsServer && Object.op_Implicit((Object)(object)furnitureMarker) && hostHasFurniture) { Furniture.Item.inStorage = false; } bool flag = haveSettings && activeEnabled && (singleton.IsServer ? (!Furniture.Item.inStorage) : hostHasFurniture); if (Object.op_Implicit((Object)(object)furniture) && collidersEnabled != flag) { Collider[] componentsInChildren = ((Component)furniture).GetComponentsInChildren<Collider>(true); for (int num = 0; num < componentsInChildren.Length; num++) { componentsInChildren[num].enabled = flag; } collidersEnabled = flag; } if (!flag || !Object.op_Implicit((Object)(object)terminal) || !Object.op_Implicit((Object)(object)furniture)) { DestroyModel(); return; } if (model == null || !Object.op_Implicit((Object)(object)model.Root)) { if (Time.unscaledTime < nextModelAttempt) { return; } try { model = new DispenserModel(terminal, ((Component)furniture).transform); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("Created movable ship cigarette dispenser on {0}, object={1}, unlockable={2}.", singleton.IsServer ? "host" : "client", ((Component)furniture).GetComponent<NetworkObject>().NetworkObjectId, Furniture.ResolveItem())); } catch (Exception ex) { nextModelAttempt = Time.unscaledTime + 10f; ((BaseUnityPlugin)this).Logger.LogError((object)("Could not build dispenser; will retry in 10 seconds: " + ex)); return; } } if (singleton.IsServer && (Object)(object)positionedFurniture != (Object)(object)furniture && Object.op_Implicit((Object)(object)ShipBuildModeManager.Instance) && Object.op_Implicit((Object)(object)GameNetworkManager.Instance) && Object.op_Implicit((Object)(object)GameNetworkManager.Instance.localPlayerController)) { string currentSaveFileName = GameNetworkManager.Instance.currentSaveFileName; if (!ES3.Load<bool>("ShipSmokeDispenser.CenteredPlacementV1", currentSaveFileName, false) || !Furniture.Item.hasBeenMoved) { NetworkObject component3 = ((Component)furniture).GetComponent<NetworkObject>(); Vector3 val2 = Furniture.DefaultPosition(); Vector3 eulerAngles = StartOfRound.Instance.elevatorTransform.eulerAngles; PlaceableShipObject component4 = ((Component)furniture).GetComponent<PlaceableShipObject>(); ShipBuildModeManager.Instance.PlaceShipObject(val2, eulerAngles, component4, false); ShipBuildModeManager.Instance.PlaceShipObjectServerRpc(val2, eulerAngles, new NetworkObjectReference(component3), (int)GameNetworkManager.Instance.localPlayerController.playerClientId); ES3.Save<bool>("ShipSmokeDispenser.CenteredPlacementV1", true, currentSaveFileName); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Placed cigarette dispenser in the centre of the ship; subsequent furniture moves are preserved."); } positionedFurniture = furniture; } model.SetReady(Object.op_Implicit((Object)(object)cigarette) && Object.op_Implicit((Object)(object)cigarette.spawnPrefab)); } internal void ConfigureFurniture() { Furniture.Configure(); } private void RemoveOldPlacementConfig() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown if (AccessTools.Property(typeof(ConfigFile), "OrphanedEntries")?.GetValue(((BaseUnityPlugin)this).Config) is IDictionary<ConfigDefinition, string> dictionary) { dictionary.Remove(new ConfigDefinition("Placement", "TerminalLocalPosition")); dictionary.Remove(new ConfigDefinition("Placement", "TerminalLocalYaw")); } ((BaseUnityPlugin)this).Config.Save(); } private void Connected(ulong client) { if (Object.op_Implicit((Object)(object)network) && network.IsServer && client != network.LocalClientId) { SendState(client); } } private unsafe void SendState(ulong client) { //IL_0074: 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_0079: 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_0082: 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_00c7: 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_00df: 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_00f8: 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_0142: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)network) || !network.IsServer || !network.ConnectedClients.ContainsKey(client)) { return; } FurnitureMarker furnitureMarker = Furniture.Find(); bool flag = Object.op_Implicit((Object)(object)furnitureMarker) && !Furniture.Item.inStorage; AutoParentToShip val = (flag ? ((Component)furnitureMarker).GetComponent<AutoParentToShip>() : null); Vector3 val2 = (Object.op_Implicit((Object)(object)val) ? val.positionOffset : Vector3.zero); Vector3 val3 = (Object.op_Implicit((Object)(object)val) ? val.rotationOffset : Vector3.zero); byte[] array = new DispenserSnapshot { Enabled = enabledConfig.Value, Available = flag, NetworkId = (flag ? ((Component)furnitureMarker).GetComponent<NetworkObject>().NetworkObjectId : 0), X = val2.x, Y = val2.y, Z = val2.z, Pitch = val3.x, Yaw = val3.y, Roll = val3.z }.Encode(); FastBufferWriter val4 = default(FastBufferWriter); ((FastBufferWriter)(ref val4))..ctor(38, (Allocator)2, -1); try { ((FastBufferWriter)(ref val4)).WriteBytesSafe(array, array.Length, 0); network.CustomMessagingManager.SendNamedMessage("achachala.shipsmokedispenser.settings.v3", client, val4, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val4))/*cast due to .constrained prefix*/).Dispose(); } } private void ReceiveHello(ulong sender, FastBufferReader reader) { //IL_003e: 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) if (!Object.op_Implicit((Object)(object)network) || !network.IsServer || !network.ConnectedClients.ContainsKey(sender) || !((FastBufferReader)(ref reader)).TryBeginRead(4)) { return; } int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives)); if (num == 3) { if (handshakePeers.Add(sender)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Client {sender} acknowledged dispenser protocol {num}."); } SendState(sender); } } private void ReceiveSettings(ulong sender, FastBufferReader reader) { //IL_0157: 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_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_011d: 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_012c: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)network) || network.IsServer || sender != 0L || !DispenserSnapshot.HasPayload(((FastBufferReader)(ref reader)).Length, ((FastBufferReader)(ref reader)).Position) || !((FastBufferReader)(ref reader)).TryBeginRead(38)) { return; } int length = ((FastBufferReader)(ref reader)).Length; int position = ((FastBufferReader)(ref reader)).Position; byte[] array = new byte[38]; ((FastBufferReader)(ref reader)).ReadBytesSafe(ref array, array.Length, 0); if (DispenserSnapshot.TryDecode(array, out DispenserSnapshot snapshot)) { bool enabled = snapshot.Enabled; bool available = snapshot.Available; ulong networkId = snapshot.NetworkId; Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(snapshot.X, snapshot.Y, snapshot.Z); Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(snapshot.Pitch, snapshot.Yaw, snapshot.Roll); if (!haveSettings) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Received dispenser host handshake: available={available}, object={networkId}, frame={length}, payloadOffset={position}."); } bool flag = !haveSettings || available != hostHasFurniture || networkId != hostFurnitureId || val != hostPositionOffset || val2 != hostRotationOffset; activeEnabled = enabled; hostHasFurniture = available; hostFurnitureId = networkId; hostPositionOffset = val; hostRotationOffset = val2; applyHostPlacement |= flag; haveSettings = true; } } internal unsafe void Interact(PlayerControllerB player) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)network) || !attached || !haveSettings || !activeEnabled || !Object.op_Implicit((Object)(object)player) || !((NetworkBehaviour)player).IsOwner) { return; } uint sequence = ++localSequence; if (network.IsServer) { ExecuteDispense(network.LocalClientId, sequence); } else if (network.IsConnectedClient) { FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe<uint>(ref sequence, default(ForPrimitives)); network.CustomMessagingManager.SendNamedMessage("achachala.shipsmokedispenser.dispense.v1", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } } private void ReceiveDispense(ulong sender, FastBufferReader reader) { //IL_002b: 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) if (Object.op_Implicit((Object)(object)network) && network.IsServer && ((FastBufferReader)(ref reader)).TryBeginRead(4)) { uint sequence = default(uint); ((FastBufferReader)(ref reader)).ReadValueSafe<uint>(ref sequence, default(ForPrimitives)); ExecuteDispense(sender, sequence); } } private void ExecuteDispense(ulong sender, uint sequence) { //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: 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_0196: 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) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)network) || !network.IsServer || !enabledConfig.Value || !network.ConnectedClients.ContainsKey(sender) || !Object.op_Implicit((Object)(object)StartOfRound.Instance) || model == null || !Object.op_Implicit((Object)(object)model.Root) || !Object.op_Implicit((Object)(object)furniture) || Furniture.Item.inStorage || ((Component)furniture).GetComponent<PlaceableShipObject>().inUse) { return; } PlayerControllerB val = null; PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val2 in allPlayerScripts) { if (Object.op_Implicit((Object)(object)val2) && val2.actualClientId == sender && val2.isPlayerControlled) { val = val2; break; } } if (!Object.op_Implicit((Object)(object)val) || val.isPlayerDead || !val.isInHangarShipRoom) { return; } Vector3 val3 = ((Component)val).transform.position - model.Root.transform.position; if (((Vector3)(ref val3)).sqrMagnitude > 9f) { return; } if (!Object.op_Implicit((Object)(object)cigarette) || !Object.op_Implicit((Object)(object)cigarette.spawnPrefab)) { if (!missingItemLogged) { missingItemLogged = true; ((BaseUnityPlugin)this).Logger.LogWarning((object)"LethalSmokes cigarette prefab is not ready; dispensing skipped."); } } else { if (!requests.TryAccept(sender, sequence, Time.unscaledTime, cooldownConfig.Value)) { return; } GameObject val4 = null; try { StartOfRound instance = StartOfRound.Instance; val4 = Object.Instantiate<GameObject>(cigarette.spawnPrefab, model.OutletPosition, Quaternion.Euler(cigarette.restingRotation), instance.elevatorTransform); GrabbableObject component = val4.GetComponent<GrabbableObject>(); NetworkObject component2 = val4.GetComponent<NetworkObject>(); if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component2)) { throw new InvalidOperationException("LethalSmokes cigarette prefab lacks required components."); } component.fallTime = 0f; component.isInElevator = true; component.isInShipRoom = true; component.SetScrapValue(valueConfig.Value); component2.Spawn(false); ((MonoBehaviour)this).StartCoroutine(SyncValue(new NetworkObjectReference(component2), valueConfig.Value)); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Dispensed one cigarette for client {sender}."); } catch (Exception ex) { if (Object.op_Implicit((Object)(object)val4)) { NetworkObject component3 = val4.GetComponent<NetworkObject>(); if (Object.op_Implicit((Object)(object)component3) && component3.IsSpawned) { component3.Despawn(true); } else { Object.Destroy((Object)(object)val4); } } ((BaseUnityPlugin)this).Logger.LogError((object)("Could not dispense cigarette: " + ex)); } } } private IEnumerator SyncValue(NetworkObjectReference reference, int value) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) yield return (object)new WaitForSeconds(1f); NetworkObject val = default(NetworkObject); if (Object.op_Implicit((Object)(object)network) && network.IsServer && Object.op_Implicit((Object)(object)RoundManager.Instance) && ((NetworkObjectReference)(ref reference)).TryGet(ref val, (NetworkManager)null) && val.IsSpawned) { RoundManager.Instance.SyncScrapValuesClientRpc((NetworkObjectReference[])(object)new NetworkObjectReference[1] { reference }, new int[1] { value }); } } private void Disconnected(ulong client) { requests.Remove(client); handshakePeers.Remove(client); if (Object.op_Implicit((Object)(object)network) && client == network.LocalClientId) { Detach(); } } private void DestroyModel() { model?.Dispose(); model = null; } private void Detach() { //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0114: 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_011a: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)network)) { network.OnClientDisconnectCallback -= Disconnected; network.OnClientConnectedCallback -= Connected; if (network.CustomMessagingManager != null) { network.CustomMessagingManager.UnregisterNamedMessageHandler("achachala.shipsmokedispenser.hello.v3"); network.CustomMessagingManager.UnregisterNamedMessageHandler("achachala.shipsmokedispenser.settings.v3"); network.CustomMessagingManager.UnregisterNamedMessageHandler("achachala.shipsmokedispenser.dispense.v1"); } } DestroyModel(); furniture = (positionedFurniture = null); collidersEnabled = null; network = null; terminal = null; attached = (haveSettings = (activeEnabled = false)); requests.Clear(); handshakePeers.Clear(); localSequence = 0u; ((MonoBehaviour)this).StopAllCoroutines(); hostHasFurniture = (applyHostPlacement = false); hostFurnitureId = 0uL; hostPositionOffset = (hostRotationOffset = Vector3.zero); nextDiagnostic = 0f; lastWaitReason = ""; } private void OnDestroy() { Detach(); Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } } public sealed class DispenserMarker : MonoBehaviour { } [HarmonyPatch(typeof(InteractTrigger), "Interact")] internal static class InteractionPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(InteractTrigger __instance, Transform __0) { if (!Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<DispenserMarker>())) { return true; } if (__instance.interactable && Object.op_Implicit((Object)(object)__0) && Object.op_Implicit((Object)(object)Plugin.Instance)) { Plugin.Instance.Interact(((Component)__0).GetComponent<PlayerControllerB>()); } return false; } } [HarmonyPatch(typeof(Terminal), "Awake")] internal static class TerminalFurniturePatch { [HarmonyPostfix] private static void Postfix(Terminal __instance) { Plugin.Instance.ConfigureFurniture(); } } internal sealed class RequestGate { private readonly Dictionary<ulong, (uint sequence, double time)> accepted = new Dictionary<ulong, (uint, double)>(); internal bool TryAccept(ulong client, uint sequence, double now, double cooldown) { if (sequence == 0 || double.IsNaN(now) || double.IsInfinity(now)) { return false; } if (accepted.TryGetValue(client, out (uint, double) value) && (sequence <= value.Item1 || now - value.Item2 < cooldown)) { return false; } accepted[client] = (sequence, now); return true; } internal void Remove(ulong client) { accepted.Remove(client); } internal void Clear() { accepted.Clear(); } } }