Decompiled source of ShipSmokeDispenser v0.2.7

ShipSmokeDispenser/shipsmokedispenser.dll

Decompiled 14 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using 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();
		}
	}
}