Decompiled source of Lantern Mod v0.1.11

BepInEx/plugins/LanternMod/LanternMod.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using FishNet;
using FishNet.Broadcast;
using FishNet.Connection;
using FishNet.Managing;
using FishNet.Managing.Object;
using FishNet.Object;
using FishNet.Serializing;
using FishNet.Transporting;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace LanternMod
{
	public static class Rules
	{
		public const byte SmallId = 245;

		public const byte BigId = 246;

		public const ushort SmallCollection = 42424;

		public const ushort BigCollection = 42425;

		public const int SmallPrice = 250;

		public const int BigPrice = 500;

		public const float UseRange = 6f;

		public const float DeployRange = 8f;

		public const float HoldSeconds = 1f;

		public const float VendorRange = 5f;

		public const float VendorLookDot = 0.72f;

		public static int Price(byte kind)
		{
			if (kind != 246)
			{
				return 250;
			}
			return 500;
		}

		public static string TypeName(byte kind)
		{
			if (kind != 246)
			{
				return "Camping Lantern";
			}
			return "Tiki Torch";
		}

		public static bool IsKind(byte kind)
		{
			if (kind != 245)
			{
				return kind == 246;
			}
			return true;
		}

		public static bool Finite(float value)
		{
			if (!float.IsNaN(value))
			{
				return !float.IsInfinity(value);
			}
			return false;
		}

		public static bool SurfaceAllowed(float y)
		{
			if (Finite(y))
			{
				return y >= 0.02f;
			}
			return false;
		}

		public static float Intensity(float value)
		{
			return Mathf.Clamp(value, 0.1f, 2f);
		}

		public static float Temperature(float value)
		{
			return Mathf.Clamp(value, 2000f, 6500f);
		}

		public static float ColorChannel(float value)
		{
			return Mathf.Clamp01(value);
		}

		public static float Frequency(float value)
		{
			return Mathf.Clamp(value, 0.25f, 8f);
		}

		public static int EffectMode(int value)
		{
			return Mathf.Clamp(value, 0, 2);
		}

		public static Vector3 DefaultBody(byte kind)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(0.62f, 0.035f, 0.025f);
		}

		public static Vector3 DefaultStand()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(0.3f, 0.13f, 0.045f);
		}

		public static bool CanUseVendor(float distance, float lookDot)
		{
			if (Finite(distance) && Finite(lookDot) && distance <= 5.35f)
			{
				return lookDot >= 0.72f;
			}
			return false;
		}

		public static string CleanName(string value, string fallback)
		{
			if (string.IsNullOrWhiteSpace(value))
			{
				return fallback;
			}
			value = value.Trim();
			if (value.Length <= 28)
			{
				return value;
			}
			return value.Substring(0, 28);
		}
	}
	[Serializable]
	public sealed class LanternData
	{
		public int serial;

		public byte kind;

		public ulong owner;

		public string ownerName;

		public string name;

		public bool deployed;

		public bool available = true;

		public float intensity = 1f;

		public float temperature = 3200f;

		public float frequency = 1f;

		public float yaw;

		public bool lightOn = true;

		public bool useTemperature = true;

		public int effectMode;

		public Vector3 bodyColor = new Vector3(-1f, -1f, -1f);

		public Vector3 standColor = new Vector3(-1f, -1f, -1f);

		public Vector3 lightColor = new Vector3(1f, 0.62f, 0.2f);

		public Vector3 position;

		public Vector3 surfaceNormal = Vector3.up;

		public Quaternion Rotation => Quaternion.FromToRotation(Vector3.up, (((Vector3)(ref surfaceNormal)).sqrMagnitude > 0.01f) ? surfaceNormal : Vector3.up) * Quaternion.Euler(0f, yaw, 0f);
	}
	[Serializable]
	public sealed class WorldData
	{
		public string name;

		public List<LanternData> lanterns = new List<LanternData>();
	}
	[Serializable]
	public sealed class SaveData
	{
		public int version = 1;

		public int nextSerial = 1;

		public List<WorldData> worlds = new List<WorldData>();
	}
	[Serializable]
	public sealed class Command
	{
		public int protocol = 1;

		public int sequence;

		public int serial;

		public int argument;

		public string action;

		public string text;

		public float value;

		public Vector3 position;

		public Vector3 normal;
	}
	[Serializable]
	public sealed class Snapshot
	{
		public int protocol = 1;

		public string world;

		public List<LanternData> lanterns = new List<LanternData>();
	}
	[Serializable]
	public sealed class Reply
	{
		public int sequence;

		public int serial;

		public string message;
	}
	public struct RequestMessage : IBroadcast
	{
		public string json;
	}
	public struct StateMessage : IBroadcast
	{
		public string json;
	}
	public struct ReplyMessage : IBroadcast
	{
		public string json;
	}
	public static class Codec
	{
		private sealed class Fields : DefaultContractResolver
		{
			protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization mode)
			{
				return (from f in type.GetFields(BindingFlags.Instance | BindingFlags.Public)
					where !f.IsNotSerialized
					select ((DefaultContractResolver)this).CreateProperty((MemberInfo)f, (MemberSerialization)2)).ToList();
			}
		}

		private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
		{
			ContractResolver = (IContractResolver)(object)new Fields(),
			TypeNameHandling = (TypeNameHandling)0,
			ObjectCreationHandling = (ObjectCreationHandling)2,
			MaxDepth = 24
		};

		public static string ToJson(object value, bool pretty = false)
		{
			return JsonConvert.SerializeObject(value, (Formatting)(pretty ? 1 : 0), Settings);
		}

		public static T FromJson<T>(string json)
		{
			return JsonConvert.DeserializeObject<T>(json, Settings);
		}
	}
	public sealed class LanternTintTarget : MonoBehaviour
	{
		public bool stand;
	}
	public static class LanternItem
	{
		public static Item SmallPrefab;

		public static Item BigPrefab;

		private static GameObject storage;

		public static bool Is(Item item)
		{
			if ((Object)(object)item != (Object)null && Rules.IsKind(item.ID))
			{
				return (Object)(object)((Component)item).GetComponent<LanternVisual>() != (Object)null;
			}
			return false;
		}

		public static int Serial(Item item)
		{
			if (!Is(item))
			{
				return 0;
			}
			return Mathf.RoundToInt(item.BettingMultiplier);
		}

		public static Item Prefab(byte kind)
		{
			if (kind != 246)
			{
				return SmallPrefab;
			}
			return BigPrefab;
		}

		public static void Register()
		{
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Expected O, but got Unknown
			if ((Object)(object)SmallPrefab != (Object)null || (Object)(object)InstanceFinder.NetworkManager == (Object)null)
			{
				return;
			}
			Dictionary<byte, Item> dictionary = (Dictionary<byte, Item>)AccessTools.Field(typeof(GameInfo), "_idToSpawnable").GetValue(null);
			if (dictionary.Count != 0)
			{
				if (dictionary.ContainsKey(245) || dictionary.ContainsKey(246))
				{
					throw new Exception("Lantern Mod item IDs 245 or 246 are already occupied.");
				}
				Item? obj = (from i in dictionary.Values
					where (Object)(object)i != (Object)null && ((object)i).GetType() == typeof(Item) && (Object)(object)((Component)i).GetComponent<NetworkObject>() != (Object)null
					orderby i.ID
					select i).FirstOrDefault();
				if ((Object)(object)obj == (Object)null)
				{
					throw new Exception("No compatible base item prefab was found.");
				}
				storage = new GameObject("Lantern Mod prefab storage");
				storage.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)storage);
				SmallPrefab = Build(obj, 245, 42424, pole: false);
				BigPrefab = Build(obj, 246, 42425, pole: true);
				Plugin.Log("Registered Camping Lantern and Tiki Torch network items.");
			}
		}

		private static Item Build(Item source, byte kind, ushort collectionId, bool pole)
		{
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: 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_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: Expected O, but got Unknown
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			//IL_030d: Unknown result type (might be due to invalid IL or missing references)
			//IL_042b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0415: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_045e: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<byte, Item> dictionary = (Dictionary<byte, Item>)AccessTools.Field(typeof(GameInfo), "_idToSpawnable").GetValue(null);
			Item val = Object.Instantiate<Item>(source, storage.transform);
			((Object)val).name = Rules.TypeName(kind);
			AccessTools.Field(typeof(Item), "_id").SetValue(val, kind);
			AccessTools.Field(typeof(Item), "_cost").SetValue(val, Rules.Price(kind));
			AccessTools.Field(typeof(Item), "_worth").SetValue(val, Rules.Price(kind) / 2);
			AccessTools.Field(typeof(Item), "_ignoredBySeagulls").SetValue(val, true);
			AccessTools.Field(typeof(Item), "_ignoredByMoneyNPC").SetValue(val, false);
			AccessTools.Field(typeof(Item), "_ignoredByCloseDots").SetValue(val, false);
			AccessTools.Field(typeof(Item), "_heldPos").SetValue(val, (object)(pole ? new Vector3(0.35f, -0.85f, 0.65f) : new Vector3(0.23f, -0.52f, 0.72f)));
			AccessTools.Field(typeof(Item), "_heldRot").SetValue(val, (object)(pole ? new Vector3(4f, 8f, -8f) : new Vector3(5f, 12f, 0f)));
			Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].enabled = false;
			}
			Collider[] componentsInChildren2 = ((Component)val).GetComponentsInChildren<Collider>(true);
			foreach (Collider val2 in componentsInChildren2)
			{
				if (!val2.isTrigger)
				{
					val2.enabled = false;
				}
			}
			Light[] componentsInChildren3 = ((Component)val).GetComponentsInChildren<Light>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				((Behaviour)componentsInChildren3[i]).enabled = false;
			}
			GameObject val3 = new GameObject("LanternBodyCollider");
			val3.transform.SetParent(((Component)val).transform, false);
			BoxCollider val4 = val3.AddComponent<BoxCollider>();
			val4.center = (pole ? new Vector3(0f, 0.88f, 0f) : new Vector3(0f, 0.26f, 0f));
			val4.size = (pole ? new Vector3(0.52f, 1.76f, 0.44f) : new Vector3(0.39f, 0.51f, 0.33f));
			AccessTools.Field(typeof(Item), "_worldColliders").SetValue(val, new Collider[1] { (Collider)val4 });
			Collider val5 = (Collider)AccessTools.Field(typeof(Item), "_pickUpCollider").GetValue(val);
			if ((Object)(object)val5 != (Object)null)
			{
				val5.isTrigger = true;
			}
			if (val5 is SphereCollider)
			{
				SphereCollider val6 = (SphereCollider)val5;
				val6.radius = (pole ? 0.92f : 0.36f);
				val6.center = (pole ? new Vector3(0f, 0.8f, 0f) : new Vector3(0f, 0.26f, 0f));
			}
			AccessTools.Field(typeof(Item), "_outOfHandHolder").SetValue(val, null);
			AccessTools.Field(typeof(Item), "_inHandHolder").SetValue(val, null);
			LanternVisual lanternVisual = ((Component)val).gameObject.AddComponent<LanternVisual>();
			lanternVisual.Build(pole);
			AccessTools.Field(typeof(Item), "_mesh").SetValue(val, lanternVisual.InventoryMesh);
			AccessTools.Field(typeof(Item), "_inventoryMeshScale").SetValue(val, pole ? 0.35f : 0.52f);
			AccessTools.Field(typeof(Item), "_inventoryMeshPos").SetValue(val, (object)(pole ? new Vector3(0f, -0.55f, 0f) : new Vector3(0f, -0.2f, 0f)));
			AccessTools.Field(typeof(Item), "_inventoryMeshRot").SetValue(val, (object)new Vector3(15f, 30f, 0f));
			AccessTools.Field(typeof(Item), "_renderers").SetValue(val, (from r in ((Component)lanternVisual).GetComponentsInChildren<Renderer>(true)
				where r.enabled
				select r).ToList());
			NetworkObject component = ((Component)val).GetComponent<NetworkObject>();
			component.SetIsSpawnable(true);
			PrefabObjects prefabObjects = InstanceFinder.NetworkManager.GetPrefabObjects<SinglePrefabObjects>(collectionId, true);
			if (prefabObjects.GetObjectCount() != 0)
			{
				throw new Exception("Lantern Mod network collection " + collectionId + " is occupied.");
			}
			prefabObjects.AddObject(component, false, true);
			dictionary.Add(kind, val);
			((Dictionary<byte, Item>)AccessTools.Field(typeof(GameInfo), "_allItems").GetValue(null)).Add(kind, val);
			((Dictionary<string, Item>)AccessTools.Field(typeof(GameInfo), "_nameToSpawnable").GetValue(null)).Add((kind == 246) ? "lanternmodpole" : "lanternmodcamping", val);
			return val;
		}
	}
	public sealed class LanternVisual : MonoBehaviour
	{
		private static Material red;

		private static Material dark;

		private static Material wood;

		private static Material rope;

		private static Material glass;

		private static Material glow;

		private Light lamp;

		private Renderer glowRenderer;

		private List<Renderer> bodyRenderers = new List<Renderer>();

		private List<Renderer> standRenderers = new List<Renderer>();

		private HashSet<Renderer> privateMaterials = new HashSet<Renderer>();

		private bool pole;

		private Vector3 lastBody = new Vector3(-9f, -9f, -9f);

		private Vector3 lastStand = new Vector3(-9f, -9f, -9f);

		private int lastStaticSignature = int.MinValue;

		public Mesh InventoryMesh { get; private set; }

		private bool IsPole
		{
			get
			{
				Item component = ((Component)this).GetComponent<Item>();
				if (!((Object)(object)component != (Object)null))
				{
					return pole;
				}
				return component.ID == 246;
			}
		}

		private static Material Mat(Color c, float metallic = 0f)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			Material val = new Material(Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard"))
			{
				color = c
			};
			if (val.HasProperty("_Metallic"))
			{
				val.SetFloat("_Metallic", metallic);
			}
			if (val.HasProperty("_Smoothness"))
			{
				val.SetFloat("_Smoothness", metallic * 0.55f);
			}
			return val;
		}

		public void Build(bool isPole)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: 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_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: 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)
			pole = isPole;
			if ((Object)(object)red == (Object)null)
			{
				red = Mat(new Color(0.62f, 0.035f, 0.025f), 0.65f);
				dark = Mat(new Color(0.045f, 0.05f, 0.06f), 0.8f);
				wood = Mat(new Color(0.3f, 0.13f, 0.045f));
				rope = Mat(new Color(0.55f, 0.32f, 0.1f));
				glass = Mat(new Color(1f, 0.62f, 0.18f));
				glow = Mat(new Color(1f, 0.43f, 0.04f));
				if (glow.HasProperty("_EmissionColor"))
				{
					glow.EnableKeyword("_EMISSION");
					glow.SetColor("_EmissionColor", new Color(1f, 0.24f, 0.01f) * 3f);
				}
			}
			Transform transform = new GameObject(isPole ? "ElevatedLanternModel" : "CampingLanternModel").transform;
			transform.SetParent(((Component)this).transform, false);
			transform.localScale = (isPole ? (Vector3.one * 0.8f) : (Vector3.one * 0.54f));
			if (isPole)
			{
				BuildTiki(transform);
			}
			else
			{
				BuildCamping(transform);
			}
		}

		private Transform Part(string name, Transform parent, PrimitiveType primitive, Vector3 pos, Vector3 scale, Material material, Quaternion rotation)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.CreatePrimitive(primitive);
			((Object)val).name = name;
			val.transform.SetParent(parent, false);
			val.transform.localPosition = pos;
			val.transform.localRotation = rotation;
			val.transform.localScale = scale;
			Object.DestroyImmediate((Object)(object)val.GetComponent<Collider>());
			val.GetComponent<Renderer>().sharedMaterial = material;
			if ((Object)(object)InventoryMesh == (Object)null)
			{
				InventoryMesh = val.GetComponent<MeshFilter>().sharedMesh;
			}
			return val.transform;
		}

		private void Bar(Transform root, string name, Vector3 a, Vector3 b, float width, Material material)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = b - a;
			Part(name, root, (PrimitiveType)2, (a + b) * 0.5f, new Vector3(width, ((Vector3)(ref val)).magnitude * 0.5f, width), material, Quaternion.FromToRotation(Vector3.up, ((Vector3)(ref val)).normalized));
		}

		private void AddLamp(Transform root, Vector3 center, float scale)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_0085: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: 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_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Expected O, but got Unknown
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			Part("LampBottom", root, (PrimitiveType)2, center + Vector3.down * 0.28f * scale, new Vector3(0.24f * scale, 0.055f * scale, 0.24f * scale), dark, Quaternion.identity);
			Part("LampTop", root, (PrimitiveType)2, center + Vector3.up * 0.29f * scale, new Vector3(0.25f * scale, 0.065f * scale, 0.25f * scale), dark, Quaternion.identity);
			Transform val = Part("WarmGlow", root, (PrimitiveType)0, center, new Vector3(0.25f, 0.42f, 0.25f) * scale, glow, Quaternion.identity);
			glowRenderer = ((Component)val).GetComponent<Renderer>();
			for (int i = 0; i < 4; i++)
			{
				float num = (float)i * (float)Math.PI * 0.5f;
				Bar(root, "Cage", center + new Vector3(Mathf.Cos(num) * 0.22f, -0.27f, Mathf.Sin(num) * 0.22f) * scale, center + new Vector3(Mathf.Cos(num) * 0.22f, 0.28f, Mathf.Sin(num) * 0.22f) * scale, 0.018f * scale, dark);
			}
			GameObject val2 = new GameObject("Lantern Light");
			val2.layer = 0;
			val2.transform.SetParent(root, false);
			val2.transform.localPosition = center;
			lamp = val2.AddComponent<Light>();
			lamp.type = (LightType)2;
			lamp.shadows = (LightShadows)0;
			lamp.renderMode = (LightRenderMode)1;
			lamp.cullingMask = -1;
			lamp.bounceIntensity = 1.35f;
			((Behaviour)lamp).enabled = false;
		}

		private void BuildCamping(Transform root)
		{
			BuildLanternHead(root, 0f, 1f);
		}

		private void BuildLanternHead(Transform root, float baseY, float scale)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Expected O, but got Unknown
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			Body(Part("FlatBase", root, (PrimitiveType)2, new Vector3(0f, baseY + 0.07f * scale, 0f), new Vector3(0.37f, 0.07f, 0.37f) * scale, red, Quaternion.identity));
			Body(Part("FuelTank", root, (PrimitiveType)2, new Vector3(0f, baseY + 0.2f * scale, 0f), new Vector3(0.34f, 0.12f, 0.34f) * scale, red, Quaternion.identity));
			Body(Part("BaseShoulder", root, (PrimitiveType)2, new Vector3(0f, baseY + 0.34f * scale, 0f), new Vector3(0.39f, 0.07f, 0.39f) * scale, red, Quaternion.identity));
			Transform val = FacetedBulb(root, new Vector3(0f, baseY + 0.69f * scale, 0f), 0.92f * scale);
			glowRenderer = ((Component)val).GetComponent<Renderer>();
			Body(Part("UpperShoulder", root, (PrimitiveType)2, new Vector3(0f, baseY + 1f * scale, 0f), new Vector3(0.38f, 0.07f, 0.38f) * scale, red, Quaternion.identity));
			Body(Part("TopCap", root, (PrimitiveType)2, new Vector3(0f, baseY + 1.11f * scale, 0f), new Vector3(0.25f, 0.08f, 0.25f) * scale, red, Quaternion.identity));
			Body(Part("TopButton", root, (PrimitiveType)2, new Vector3(0f, baseY + 1.21f * scale, 0f), new Vector3(0.14f, 0.055f, 0.14f) * scale, red, Quaternion.identity));
			GameObject val2 = new GameObject("Lantern Light");
			val2.layer = 0;
			val2.transform.SetParent(root, false);
			val2.transform.localPosition = new Vector3(0f, baseY + 0.69f * scale, 0f);
			lamp = val2.AddComponent<Light>();
			lamp.type = (LightType)2;
			lamp.shadows = (LightShadows)0;
			lamp.renderMode = (LightRenderMode)1;
			lamp.cullingMask = -1;
			lamp.bounceIntensity = 1.35f;
			((Behaviour)lamp).enabled = false;
		}

		private Transform FacetedBulb(Transform root, Vector3 center, float scale)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Expected O, but got Unknown
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			float[] array = new float[5] { -0.36f, -0.25f, 0.08f, 0.28f, 0.36f };
			float[] array2 = new float[5] { 0.15f, 0.25f, 0.25f, 0.15f, 0.13f };
			List<Vector3> list = new List<Vector3>();
			List<int> list2 = new List<int>();
			List<Vector2> list3 = new List<Vector2>();
			for (int i = 0; i < array.Length; i++)
			{
				for (int j = 0; j < 8; j++)
				{
					float num = (float)j * (float)Math.PI * 2f / 8f;
					list.Add(center + new Vector3(Mathf.Cos(num) * array2[i], array[i], Mathf.Sin(num) * array2[i]) * scale);
					list3.Add(new Vector2((float)j / 8f, (float)i / (float)(array.Length - 1)));
				}
			}
			for (int k = 0; k < array.Length - 1; k++)
			{
				for (int l = 0; l < 8; l++)
				{
					int num2 = (l + 1) % 8;
					int item = k * 8 + l;
					int item2 = k * 8 + num2;
					int item3 = (k + 1) * 8 + l;
					int item4 = (k + 1) * 8 + num2;
					list2.Add(item);
					list2.Add(item3);
					list2.Add(item2);
					list2.Add(item2);
					list2.Add(item3);
					list2.Add(item4);
				}
			}
			GameObject val = new GameObject("FacetedGlass");
			val.transform.SetParent(root, false);
			Mesh val2 = new Mesh
			{
				name = "Camping Lantern Faceted Glass"
			};
			val2.SetVertices(list);
			val2.SetTriangles(list2, 0);
			val2.SetUVs(0, list3);
			val2.RecalculateNormals();
			val2.RecalculateBounds();
			val.AddComponent<MeshFilter>().sharedMesh = val2;
			((Renderer)val.AddComponent<MeshRenderer>()).sharedMaterial = glow;
			return val.transform;
		}

		private void BuildTiki(Transform root)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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)
			//IL_005d: 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_007b: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			Stand(Part("WoodenFoot", root, (PrimitiveType)2, new Vector3(0f, 0.07f, 0f), new Vector3(0.34f, 0.07f, 0.34f), wood, Quaternion.identity));
			Stand(Part("WoodenStand", root, (PrimitiveType)2, new Vector3(0f, 0.72f, 0f), new Vector3(0.12f, 0.65f, 0.12f), wood, Quaternion.identity));
			for (int i = 0; i < 3; i++)
			{
				Stand(Part("StandNode" + i, root, (PrimitiveType)2, new Vector3(0f, 0.28f + (float)i * 0.43f, 0f), new Vector3(0.145f, 0.035f, 0.145f), rope, Quaternion.identity));
			}
			BuildLanternHead(root, 1.31f, 0.68f);
		}

		private void Body(Transform value)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			Renderer val = (((Object)(object)value == (Object)null) ? null : ((Component)value).GetComponent<Renderer>());
			if ((Object)(object)val != (Object)null)
			{
				(((Component)val).GetComponent<LanternTintTarget>() ?? ((Component)val).gameObject.AddComponent<LanternTintTarget>()).stand = false;
				val.sharedMaterial = new Material(val.sharedMaterial);
				bodyRenderers.Add(val);
			}
		}

		private void BodyBar(Transform root, string name, Vector3 a, Vector3 b, float width, Material material)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			int childCount = root.childCount;
			Bar(root, name, a, b, width, material);
			if (root.childCount > childCount)
			{
				Body(root.GetChild(root.childCount - 1));
			}
		}

		private void Stand(Transform value)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			Renderer val = (((Object)(object)value == (Object)null) ? null : ((Component)value).GetComponent<Renderer>());
			if ((Object)(object)val != (Object)null)
			{
				(((Component)val).GetComponent<LanternTintTarget>() ?? ((Component)val).gameObject.AddComponent<LanternTintTarget>()).stand = true;
				val.sharedMaterial = new Material(val.sharedMaterial);
				standRenderers.Add(val);
			}
		}

		private void EnsureColorTargets()
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Expected O, but got Unknown
			if (bodyRenderers == null)
			{
				bodyRenderers = new List<Renderer>();
			}
			if (standRenderers == null)
			{
				standRenderers = new List<Renderer>();
			}
			if (privateMaterials == null)
			{
				privateMaterials = new HashSet<Renderer>();
			}
			bodyRenderers.Clear();
			standRenderers.Clear();
			LanternTintTarget[] componentsInChildren = ((Component)this).GetComponentsInChildren<LanternTintTarget>(true);
			foreach (LanternTintTarget lanternTintTarget in componentsInChildren)
			{
				if ((Object)(object)lanternTintTarget == (Object)null)
				{
					continue;
				}
				Renderer component = ((Component)lanternTintTarget).GetComponent<Renderer>();
				if (!((Object)(object)component == (Object)null))
				{
					if (!privateMaterials.Contains(component) && (Object)(object)component.sharedMaterial != (Object)null)
					{
						component.sharedMaterial = new Material(component.sharedMaterial)
						{
							name = ((Object)component.sharedMaterial).name + " (Lantern Instance)"
						};
						privateMaterials.Add(component);
					}
					if (lanternTintTarget.stand)
					{
						standRenderers.Add(component);
					}
					else
					{
						bodyRenderers.Add(component);
					}
				}
			}
			if ((Object)(object)glowRenderer == (Object)null)
			{
				Transform val = ((IEnumerable<Transform>)((Component)this).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "FacetedGlass" || ((Object)t).name == "WarmGlow"));
				if ((Object)(object)val != (Object)null)
				{
					glowRenderer = ((Component)val).GetComponent<Renderer>();
				}
			}
		}

		public void ApplyBody(Vector3 value)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Expected O, but got Unknown
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			EnsureColorTargets();
			bool isPole = IsPole;
			if (value.x < 0f)
			{
				value = Rules.DefaultBody((byte)(isPole ? 246 : 245));
			}
			((Vector3)(ref value))..ctor(Rules.ColorChannel(value.x), Rules.ColorChannel(value.y), Rules.ColorChannel(value.z));
			lastBody = value;
			Color val = default(Color);
			((Color)(ref val))..ctor(value.x, value.y, value.z, 1f);
			foreach (Renderer bodyRenderer in bodyRenderers)
			{
				if ((Object)(object)bodyRenderer == (Object)null)
				{
					continue;
				}
				Material sharedMaterial = bodyRenderer.sharedMaterial;
				if ((Object)(object)sharedMaterial != (Object)null)
				{
					sharedMaterial.color = val;
					if (sharedMaterial.HasProperty("_BaseColor"))
					{
						sharedMaterial.SetColor("_BaseColor", val);
					}
					if (sharedMaterial.HasProperty("_Color"))
					{
						sharedMaterial.SetColor("_Color", val);
					}
				}
				MaterialPropertyBlock val2 = new MaterialPropertyBlock();
				bodyRenderer.GetPropertyBlock(val2);
				val2.SetColor("_BaseColor", val);
				val2.SetColor("_Color", val);
				bodyRenderer.SetPropertyBlock(val2);
			}
		}

		public void ApplyStand(Vector3 value)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Expected O, but got Unknown
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: 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)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			EnsureColorTargets();
			if (!IsPole)
			{
				return;
			}
			if (value.x < 0f)
			{
				value = Rules.DefaultStand();
			}
			((Vector3)(ref value))..ctor(Rules.ColorChannel(value.x), Rules.ColorChannel(value.y), Rules.ColorChannel(value.z));
			lastStand = value;
			Color val = default(Color);
			((Color)(ref val))..ctor(value.x, value.y, value.z, 1f);
			foreach (Renderer standRenderer in standRenderers)
			{
				if ((Object)(object)standRenderer == (Object)null)
				{
					continue;
				}
				Material sharedMaterial = standRenderer.sharedMaterial;
				if ((Object)(object)sharedMaterial != (Object)null)
				{
					sharedMaterial.color = val;
					if (sharedMaterial.HasProperty("_BaseColor"))
					{
						sharedMaterial.SetColor("_BaseColor", val);
					}
					if (sharedMaterial.HasProperty("_Color"))
					{
						sharedMaterial.SetColor("_Color", val);
					}
				}
				MaterialPropertyBlock val2 = new MaterialPropertyBlock();
				standRenderer.GetPropertyBlock(val2);
				val2.SetColor("_BaseColor", val);
				val2.SetColor("_Color", val);
				standRenderer.SetPropertyBlock(val2);
			}
		}

		public void ResetStaticLight(LanternData data)
		{
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: 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_0267: Expected O, but got Unknown
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			if (data == null || data.effectMode != 0)
			{
				return;
			}
			EnsureColorTargets();
			if ((Object)(object)lamp == (Object)null)
			{
				lamp = ((Component)this).GetComponentInChildren<Light>(true);
			}
			Item component = ((Component)this).GetComponent<Item>();
			Plugin instance = Plugin.Instance;
			bool flag = data.deployed && (Object)(object)component != (Object)null && (Object)(object)component.SyncedHolder == (Object)null && ((Object)(object)instance == (Object)null || instance.CanRenderLight(data.serial));
			int num = 17;
			num = num * 31 + (flag ? 1 : 0);
			num = num * 31 + (data.lightOn ? 1 : 0);
			num = num * 31 + (data.useTemperature ? 1 : 0);
			num = num * 31 + Mathf.RoundToInt(data.intensity * 1000f);
			num = num * 31 + Mathf.RoundToInt(data.temperature);
			num = num * 31 + Mathf.RoundToInt(data.lightColor.x * 255f);
			num = num * 31 + Mathf.RoundToInt(data.lightColor.y * 255f);
			num = num * 31 + Mathf.RoundToInt(data.lightColor.z * 255f);
			if (num == lastStaticSignature)
			{
				return;
			}
			lastStaticSignature = num;
			if ((Object)(object)lamp != (Object)null)
			{
				bool isPole = IsPole;
				float num2 = Rules.Intensity(data.intensity);
				float num3 = 1f + (float)(Math.Abs(data.serial) % 97) * 0.0001f;
				Color val = (Color)(data.useTemperature ? Mathf.CorrelatedColorTemperatureToRGB(Rules.Temperature(data.temperature)) : new Color(Rules.ColorChannel(data.lightColor.x), Rules.ColorChannel(data.lightColor.y), Rules.ColorChannel(data.lightColor.z)));
				lamp.color = val;
				lamp.intensity = (isPole ? 12f : 7f) * num2 * num3;
				lamp.range = (isPole ? 18f : 12f) * Mathf.Lerp(0.75f, 1.25f, (num2 - 0.1f) / 1.9f);
				bool flag2 = flag && data.lightOn;
				if (((Behaviour)lamp).enabled != flag2)
				{
					((Behaviour)lamp).enabled = flag2;
				}
				if ((Object)(object)glowRenderer != (Object)null)
				{
					MaterialPropertyBlock val2 = new MaterialPropertyBlock();
					glowRenderer.GetPropertyBlock(val2);
					val2.SetColor("_BaseColor", val);
					val2.SetColor("_Color", val);
					val2.SetColor("_EmissionColor", val * 4f);
					glowRenderer.SetPropertyBlock(val2);
				}
			}
		}

		private void LateUpdate()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Expected O, but got Unknown
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			Item component = ((Component)this).GetComponent<Item>();
			Plugin instance = Plugin.Instance;
			LanternData lanternData = (((Object)(object)instance == (Object)null) ? null : instance.Find(LanternItem.Serial(component)));
			EnsureColorTargets();
			if ((Object)(object)lamp == (Object)null)
			{
				lamp = ((Component)this).GetComponentInChildren<Light>(true);
			}
			if (lanternData != null)
			{
				ApplyBody(lanternData.bodyColor);
				ApplyStand(lanternData.standColor);
			}
			bool flag = lanternData != null && lanternData.deployed && (Object)(object)component != (Object)null && (Object)(object)component.SyncedHolder == (Object)null && ((Object)(object)instance == (Object)null || instance.CanRenderLight(lanternData.serial));
			if (flag)
			{
				((Component)this).transform.SetPositionAndRotation(lanternData.position, lanternData.Rotation);
			}
			if ((Object)(object)lamp == (Object)null)
			{
				return;
			}
			if (lanternData == null)
			{
				if (((Behaviour)lamp).enabled)
				{
					((Behaviour)lamp).enabled = false;
				}
				return;
			}
			if (lanternData.effectMode == 0)
			{
				ResetStaticLight(lanternData);
				return;
			}
			lastStaticSignature = int.MinValue;
			float num = 1f;
			if (flag && lanternData.lightOn)
			{
				float num2 = Rules.Frequency(lanternData.frequency);
				num = ((lanternData.effectMode != 1) ? (0.15f + 0.85f * (Mathf.Sin(Time.time * num2 * (float)Math.PI * 2f) * 0.5f + 0.5f)) : ((Mathf.Repeat(Time.time * num2, 1f) < 0.5f) ? 1f : 0f));
			}
			bool flag2 = flag && lanternData.lightOn && num > 0.01f;
			if (((Behaviour)lamp).enabled != flag2)
			{
				((Behaviour)lamp).enabled = flag2;
			}
			if (flag)
			{
				bool isPole = IsPole;
				float num3 = Rules.Intensity(lanternData.intensity);
				float num4 = 1f + (float)(Math.Abs(lanternData.serial) % 97) * 0.0001f;
				Color val = (Color)(lanternData.useTemperature ? Mathf.CorrelatedColorTemperatureToRGB(Rules.Temperature(lanternData.temperature)) : new Color(Rules.ColorChannel(lanternData.lightColor.x), Rules.ColorChannel(lanternData.lightColor.y), Rules.ColorChannel(lanternData.lightColor.z)));
				lamp.color = val;
				lamp.intensity = (isPole ? 12f : 7f) * num3 * num4 * num;
				lamp.range = (isPole ? 18f : 12f) * Mathf.Lerp(0.75f, 1.25f, (num3 - 0.1f) / 1.9f);
				if ((Object)(object)glowRenderer != (Object)null)
				{
					MaterialPropertyBlock val2 = new MaterialPropertyBlock();
					glowRenderer.GetPropertyBlock(val2);
					val2.SetColor("_BaseColor", val * num);
					val2.SetColor("_Color", val * num);
					val2.SetColor("_EmissionColor", val * (4f * num));
					glowRenderer.SetPropertyBlock(val2);
				}
			}
		}
	}
	[BepInPlugin("ponyfisher.howtofish.lanternmod", "Lantern Mod", "0.1.10")]
	[DefaultExecutionOrder(29400)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "ponyfisher.howtofish.lanternmod";

		public static Plugin Instance;

		public List<LanternData> Current = new List<LanternData>();

		public int Selected;

		public bool Open;

		public bool EditorOpen;

		public int EditorTab;

		public string Status = "Buy lights from money vendors, then interact with a deployed lantern to configure it.";

		private SaveData save = new SaveData();

		private WorldData world;

		private NetworkManager manager;

		private Harmony harmony;

		private string savePath;

		private bool persistenceReady = true;

		private bool registrationFailed;

		private bool nearMoneyVendor;

		private Component hoveredInteractable;

		private float nextTick;

		private float nextSave;

		private float nextState;

		private float nextIconRefresh;

		private float nextHello;

		private float nextVendorScan;

		private float nextLightBudget;

		private float statusUntil;

		private int sequence;

		private ConfigEntry<int> maximumRenderedLights;

		private ConfigEntry<bool> unlimitedRenderedLights;

		private readonly HashSet<int> renderAllowed = new HashSet<int>();

		private readonly Dictionary<int, int> lastSequence = new Dictionary<int, int>();

		private readonly Dictionary<int, float> rateLimit = new Dictionary<int, float>();

		private readonly Dictionary<int, Item> items = new Dictionary<int, Item>();

		private float useStarted;

		private Item activeTarget;

		private bool holdFired;

		private GUIStyle hintStyle;

		private GUIStyle titleStyle;

		private GUIStyle headerStyle;

		private GUIStyle labelStyle;

		private GUIStyle statusStyle;

		private GUIStyle buttonStyle;

		private GUIStyle toggleStyle;

		private Vector2 listScroll;

		private string renameDraft = "";

		private string maxLightsDraft = "16";

		private int draftSerial;

		private int editorDraftSerial;

		private int bodyPartTab;

		private float intensityDraft = 1f;

		private float tempDraft = 3200f;

		private float frequencyDraft = 1f;

		private Vector3 bodyDraft;

		private Vector3 standDraft;

		private Vector3 lightColorDraft;

		private bool lightBudgetLoaded;

		private bool unlimitedDraft;

		public int MaximumRenderedLights
		{
			get
			{
				if (maximumRenderedLights != null)
				{
					return Mathf.Clamp(maximumRenderedLights.Value, 1, 256);
				}
				return 16;
			}
		}

		public bool UnlimitedRenderedLights
		{
			get
			{
				if (unlimitedRenderedLights != null)
				{
					return unlimitedRenderedLights.Value;
				}
				return true;
			}
		}

		public static void Log(string value)
		{
			if ((Object)(object)Instance != (Object)null)
			{
				((BaseUnityPlugin)Instance).Logger.LogInfo((object)value);
			}
		}

		private void Awake()
		{
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Expected O, but got Unknown
			Instance = this;
			maximumRenderedLights = ((BaseUnityPlugin)this).Config.Bind<int>("Rendering", "MaximumRenderedLights", 16, "Maximum number of nearest deployed lantern lights rendered for this player when Unlimited is off.");
			unlimitedRenderedLights = ((BaseUnityPlugin)this).Config.Bind<bool>("Rendering", "UnlimitedRenderedLights", true, "Render every deployed Lantern Mod light and raise the URP additional-light budget to its supported maximum.");
			savePath = Path.Combine(Paths.ConfigPath, "LanternMod-worlds.json");
			try
			{
				if (File.Exists(savePath))
				{
					save = Codec.FromJson<SaveData>(File.ReadAllText(savePath));
					if (save == null || save.version != 1 || save.worlds == null)
					{
						throw new Exception("Unrecognized save format");
					}
				}
			}
			catch (Exception ex)
			{
				persistenceReady = false;
				Status = "Lantern save data could not be read; actions are paused.";
				((BaseUnityPlugin)this).Logger.LogError((object)ex);
			}
			GenericWriter<RequestMessage>.SetWrite((Action<Writer, RequestMessage>)delegate(Writer w, RequestMessage v)
			{
				w.WriteString(v.json);
			});
			GenericReader<RequestMessage>.SetRead((Func<Reader, RequestMessage>)((Reader r) => new RequestMessage
			{
				json = r.ReadStringAllocated()
			}));
			GenericWriter<StateMessage>.SetWrite((Action<Writer, StateMessage>)delegate(Writer w, StateMessage v)
			{
				w.WriteString(v.json);
			});
			GenericReader<StateMessage>.SetRead((Func<Reader, StateMessage>)((Reader r) => new StateMessage
			{
				json = r.ReadStringAllocated()
			}));
			GenericWriter<ReplyMessage>.SetWrite((Action<Writer, ReplyMessage>)delegate(Writer w, ReplyMessage v)
			{
				w.WriteString(v.json);
			});
			GenericReader<ReplyMessage>.SetRead((Func<Reader, ReplyMessage>)((Reader r) => new ReplyMessage
			{
				json = r.ReadStringAllocated()
			}));
			harmony = new Harmony("ponyfisher.howtofish.lanternmod");
			harmony.PatchAll(typeof(Plugin).Assembly);
			Log("Lantern Mod 0.1.10 loaded. Interact with a lantern to open its controls.");
		}

		private void Update()
		{
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: 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_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: 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)
			Keyboard current = Keyboard.current;
			UpdateInteraction();
			if ((Object)(object)manager != (Object)(object)InstanceFinder.NetworkManager)
			{
				RegisterNetwork();
			}
			if (!registrationFailed && (Object)(object)LanternItem.SmallPrefab == (Object)null)
			{
				try
				{
					LanternItem.Register();
				}
				catch (Exception ex)
				{
					registrationFailed = true;
					Status = "Lantern item registration failed; see the BepInEx log.";
					((BaseUnityPlugin)this).Logger.LogError((object)ex);
				}
			}
			if ((Object)(object)LanternItem.SmallPrefab != (Object)null && Time.unscaledTime >= nextVendorScan)
			{
				nextVendorScan = Time.unscaledTime + 0.15f;
				nearMoneyVendor = (Object)(object)FocusedMoneyVendor(Player.LocalPlayer, 5f) != (Object)null;
			}
			if (!Open && nearMoneyVendor && current != null)
			{
				if (((ButtonControl)current.digit0Key).wasPressedThisFrame)
				{
					Send("buy", 245);
				}
				else if (((ButtonControl)current.minusKey).wasPressedThisFrame)
				{
					Send("buy", 246);
				}
			}
			if ((Object)(object)LanternItem.SmallPrefab != (Object)null && Time.unscaledTime >= nextIconRefresh)
			{
				nextIconRefresh = Time.unscaledTime + 0.15f;
				LanternInventoryIcon.RefreshAll();
			}
			if (Time.unscaledTime >= nextLightBudget)
			{
				nextLightBudget = Time.unscaledTime + 0.35f;
				RefreshLightBudget();
			}
			if (InstanceFinder.IsServerStarted && SaveManager.CurServerSave != null)
			{
				string name = SaveManager.CurServerSave.Name;
				if (world == null || world.name != name)
				{
					world = save.worlds.FirstOrDefault((WorldData w) => w.name == name);
					if (world == null)
					{
						world = new WorldData
						{
							name = name
						};
						save.worlds.Add(world);
					}
					Current = world.lanterns;
					items.Clear();
					lastSequence.Clear();
					rateLimit.Clear();
				}
				if (Time.unscaledTime >= nextTick)
				{
					nextTick = Time.unscaledTime + 0.2f;
					AuditWorld();
				}
				if (Time.unscaledTime >= nextState)
				{
					nextState = Time.unscaledTime + 0.35f;
					Broadcast();
				}
				if (Time.unscaledTime >= nextSave)
				{
					nextSave = Time.unscaledTime + 8f;
					Persist();
				}
			}
			else if (!InstanceFinder.IsClientStarted)
			{
				world = null;
				Current = new List<LanternData>();
				items.Clear();
			}
			if (InstanceFinder.IsClientStarted && !InstanceFinder.IsServerStarted && Time.unscaledTime >= nextHello)
			{
				nextHello = Time.unscaledTime + 3f;
				Send("hello");
			}
		}

		private void LateUpdate()
		{
			if (Open)
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
		}

		public void Toggle(bool value)
		{
			Open = value;
			if (!Open)
			{
				EditorOpen = false;
				Cursor.lockState = (CursorLockMode)1;
				Cursor.visible = false;
			}
			else
			{
				SelectUsable();
			}
		}

		private void RegisterNetwork()
		{
			if ((Object)(object)manager != (Object)null)
			{
				manager.ServerManager.UnregisterBroadcast<RequestMessage>((Action<NetworkConnection, RequestMessage, Channel>)Receive);
				manager.ClientManager.UnregisterBroadcast<StateMessage>((Action<StateMessage, Channel>)ReceiveState);
				manager.ClientManager.UnregisterBroadcast<ReplyMessage>((Action<ReplyMessage, Channel>)ReceiveReply);
			}
			manager = InstanceFinder.NetworkManager;
			if (!((Object)(object)manager == (Object)null))
			{
				manager.ServerManager.RegisterBroadcast<RequestMessage>((Action<NetworkConnection, RequestMessage, Channel>)Receive, true);
				manager.ClientManager.RegisterBroadcast<StateMessage>((Action<StateMessage, Channel>)ReceiveState);
				manager.ClientManager.RegisterBroadcast<ReplyMessage>((Action<ReplyMessage, Channel>)ReceiveReply);
			}
		}

		public LanternData Find(int serial)
		{
			return Current.FirstOrDefault((LanternData x) => x.serial == serial);
		}

		public void SelectUsable()
		{
			Player p = Player.LocalPlayer;
			if ((Object)(object)p == (Object)null)
			{
				return;
			}
			Item heldItem = p.Holding.HeldItem;
			if (LanternItem.Is(heldItem))
			{
				Selected = LanternItem.Serial(heldItem);
			}
			else if (Find(Selected) == null || Find(Selected).owner != p.SteamID)
			{
				Selected = Current.FirstOrDefault((LanternData x) => x.available && x.owner == p.SteamID)?.serial ?? 0;
			}
		}

		public void Persist()
		{
			if (!persistenceReady || !InstanceFinder.IsServerStarted || world == null)
			{
				return;
			}
			try
			{
				string text = savePath + ".tmp";
				File.WriteAllText(text, Codec.ToJson(save, pretty: true));
				if (File.Exists(savePath))
				{
					File.Replace(text, savePath, savePath + ".bak");
				}
				else
				{
					File.Move(text, savePath);
				}
			}
			catch (Exception ex)
			{
				persistenceReady = false;
				Status = "Lantern Mod could not save; actions are paused.";
				((BaseUnityPlugin)this).Logger.LogError((object)ex);
			}
		}

		public void Send(string action, int argument = 0, float value = 0f, string text = null, Vector3 position = default(Vector3), Vector3 normal = default(Vector3), int serial = 0)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.LocalPlayer == (Object)null)
			{
				SetStatus("Load into a game first.");
				return;
			}
			Command command = new Command
			{
				action = action,
				serial = ((serial > 0) ? serial : Selected),
				argument = argument,
				value = value,
				text = text,
				position = position,
				normal = normal,
				sequence = ++sequence
			};
			if (InstanceFinder.IsServerStarted)
			{
				Execute(Player.LocalPlayer, command, null);
			}
			else if ((Object)(object)manager != (Object)null && InstanceFinder.IsClientStarted)
			{
				manager.ClientManager.Broadcast<RequestMessage>(new RequestMessage
				{
					json = Codec.ToJson(command)
				}, (Channel)0);
				if (action != "hello")
				{
					SetStatus("Waiting for the host...");
				}
			}
		}

		private void Receive(NetworkConnection connection, RequestMessage message, Channel channel)
		{
			if (!InstanceFinder.IsServerStarted || message.json == null || message.json.Length > 4096)
			{
				return;
			}
			try
			{
				Command command = Codec.FromJson<Command>(message.json);
				if (command != null && command.protocol == 1 && command.sequence > 0 && (!lastSequence.TryGetValue(connection.ClientId, out var value) || command.sequence > value) && (!rateLimit.TryGetValue(connection.ClientId, out var value2) || !(Time.unscaledTime - value2 < 0.08f)))
				{
					lastSequence[connection.ClientId] = command.sequence;
					rateLimit[connection.ClientId] = Time.unscaledTime;
					Player val = ((IEnumerable<Player>)Object.FindObjectsByType<Player>()).FirstOrDefault((Func<Player, bool>)((Player x) => ((NetworkBehaviour)x).Owner == connection));
					if ((Object)(object)val != (Object)null)
					{
						Execute(val, command, connection);
					}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Rejected Lantern Mod request: " + ex.Message));
			}
		}

		private void SetStatus(string value)
		{
			Status = value;
			statusUntil = Time.unscaledTime + 4f;
		}

		private void Respond(Command cmd, NetworkConnection connection, string message, int selected = 0)
		{
			Reply value = new Reply
			{
				sequence = cmd.sequence,
				serial = selected,
				message = message
			};
			if (connection == (NetworkConnection)null || connection.IsLocalClient)
			{
				SetStatus(message);
				if (selected > 0)
				{
					Selected = selected;
				}
			}
			else
			{
				manager.ServerManager.Broadcast<ReplyMessage>(connection, new ReplyMessage
				{
					json = Codec.ToJson(value)
				}, true, (Channel)0);
			}
		}

		private void ReceiveReply(ReplyMessage message, Channel channel)
		{
			Reply reply = Codec.FromJson<Reply>(message.json);
			if (reply != null)
			{
				SetStatus(reply.message);
				if (reply.serial > 0)
				{
					Selected = reply.serial;
				}
			}
		}

		private void ReceiveState(StateMessage message, Channel channel)
		{
			if (InstanceFinder.IsServerStarted || message.json == null || message.json.Length > 250000)
			{
				return;
			}
			Snapshot snapshot = Codec.FromJson<Snapshot>(message.json);
			if (snapshot == null || snapshot.protocol != 1 || snapshot.lanterns == null)
			{
				return;
			}
			Current = snapshot.lanterns;
			foreach (LanternData item in Current)
			{
				ApplyBodyNow(item);
				if (item.effectMode == 0)
				{
					ResetStaticNow(item);
				}
			}
		}

		private void Broadcast()
		{
			if ((Object)(object)manager != (Object)null && world != null)
			{
				manager.ServerManager.Broadcast<StateMessage>(new StateMessage
				{
					json = Codec.ToJson(new Snapshot
					{
						world = world.name,
						lanterns = Current
					})
				}, true, (Channel)0);
			}
		}

		private void Scan()
		{
			items.Clear();
			Item[] array = Object.FindObjectsByType<Item>((FindObjectsInactive)1);
			foreach (Item val in array)
			{
				if (LanternItem.Is(val) && ((NetworkBehaviour)val).IsSpawned && !((NetworkBehaviour)val).IsDeinitializing)
				{
					int num = LanternItem.Serial(val);
					if (num > 0 && !items.ContainsKey(num))
					{
						items.Add(num, val);
					}
				}
			}
		}

		public Item FindItem(int serial)
		{
			if (items.TryGetValue(serial, out var value) && (Object)(object)value != (Object)null && ((NetworkBehaviour)value).IsSpawned && !((NetworkBehaviour)value).IsDeinitializing)
			{
				return value;
			}
			value = ((IEnumerable<Item>)Object.FindObjectsByType<Item>((FindObjectsInactive)1)).FirstOrDefault((Func<Item, bool>)((Item x) => LanternItem.Is(x) && ((NetworkBehaviour)x).IsSpawned && !((NetworkBehaviour)x).IsDeinitializing && LanternItem.Serial(x) == serial));
			if ((Object)(object)value != (Object)null)
			{
				items[serial] = value;
			}
			return value;
		}

		public void ApplyBodyNow(LanternData data)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if (data == null)
			{
				return;
			}
			LanternVisual[] array = Object.FindObjectsByType<LanternVisual>((FindObjectsInactive)1);
			foreach (LanternVisual lanternVisual in array)
			{
				if (!((Object)(object)lanternVisual == (Object)null))
				{
					Item component = ((Component)lanternVisual).GetComponent<Item>();
					if ((Object)(object)component != (Object)null && LanternItem.Serial(component) == data.serial)
					{
						lanternVisual.ApplyBody(data.bodyColor);
						lanternVisual.ApplyStand(data.standColor);
					}
				}
			}
		}

		public void ResetStaticNow(LanternData data)
		{
			if (data == null)
			{
				return;
			}
			LanternVisual[] array = Object.FindObjectsByType<LanternVisual>((FindObjectsInactive)1);
			foreach (LanternVisual lanternVisual in array)
			{
				if (!((Object)(object)lanternVisual == (Object)null))
				{
					Item component = ((Component)lanternVisual).GetComponent<Item>();
					if ((Object)(object)component != (Object)null && LanternItem.Serial(component) == data.serial)
					{
						lanternVisual.ResetStaticLight(data);
					}
				}
			}
		}

		public bool CanRenderLight(int serial)
		{
			if (!UnlimitedRenderedLights)
			{
				return renderAllowed.Contains(serial);
			}
			return true;
		}

		public void SetLightBudget(bool unlimited, int maximum)
		{
			if (unlimitedRenderedLights != null)
			{
				unlimitedRenderedLights.Value = unlimited;
			}
			if (maximumRenderedLights != null)
			{
				maximumRenderedLights.Value = Mathf.Clamp(maximum, 1, 256);
			}
			((BaseUnityPlugin)this).Config.Save();
			RefreshLightBudget();
			SetStatus(unlimited ? "All Lantern Mod lights will render." : ("Rendering the nearest " + MaximumRenderedLights + " Lantern Mod lights."));
		}

		private void RefreshLightBudget()
		{
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			renderAllowed.Clear();
			List<LanternData> list = Current.Where((LanternData d) => d != null && d.available && d.deployed).ToList();
			if (UnlimitedRenderedLights)
			{
				foreach (LanternData item in list)
				{
					renderAllowed.Add(item.serial);
				}
			}
			else
			{
				Vector3 origin = (((Object)(object)Player.LocalPlayer != (Object)null && (Object)(object)Player.LocalPlayer.CamObject != (Object)null) ? Player.LocalPlayer.CamObject.position : Vector3.zero);
				foreach (LanternData item2 in list.OrderBy(delegate(LanternData d)
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_000c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Unknown result type (might be due to invalid IL or missing references)
					Vector3 val = d.position - origin;
					return ((Vector3)(ref val)).sqrMagnitude;
				}).Take(MaximumRenderedLights))
				{
					renderAllowed.Add(item2.serial);
				}
			}
			ApplyPipelineLightBudget(UnlimitedRenderedLights ? 256 : MaximumRenderedLights);
			foreach (LanternData item3 in list)
			{
				if (item3.effectMode == 0)
				{
					ResetStaticNow(item3);
				}
			}
		}

		private void ApplyPipelineLightBudget(int requested)
		{
			try
			{
				RenderPipelineAsset currentRenderPipeline = GraphicsSettings.currentRenderPipeline;
				if (!((Object)(object)currentRenderPipeline == (Object)null))
				{
					Type type = ((object)currentRenderPipeline).GetType();
					int num = Mathf.Clamp(requested, 1, 256);
					BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
					PropertyInfo property = type.GetProperty("maxAdditionalLightsCount", bindingAttr);
					if (property != null && property.CanWrite)
					{
						property.SetValue(currentRenderPipeline, num, null);
					}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not raise the render-pipeline light budget: " + ex.Message));
			}
		}

		private void AuditWorld()
		{
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			Scan();
			foreach (KeyValuePair<int, Item> item in items)
			{
				Item value = item.Value;
				LanternData lanternData = Find(item.Key);
				if (lanternData == null)
				{
					Player syncedHolder = value.SyncedHolder;
					lanternData = new LanternData
					{
						serial = item.Key,
						kind = value.ID,
						owner = (((Object)(object)syncedHolder == (Object)null) ? 0 : syncedHolder.SteamID),
						ownerName = (((Object)(object)syncedHolder == (Object)null) ? null : syncedHolder.SteamName),
						name = Rules.TypeName(value.ID),
						bodyColor = Rules.DefaultBody(value.ID),
						standColor = Rules.DefaultStand()
					};
					Current.Add(lanternData);
					save.nextSerial = Math.Max(save.nextSerial, item.Key + 1);
				}
				lanternData.available = true;
				lanternData.kind = value.ID;
				if (lanternData.kind == 246 && lanternData.name == "Pole Light")
				{
					lanternData.name = Rules.TypeName(lanternData.kind);
				}
				if (lanternData.bodyColor.x < 0f)
				{
					lanternData.bodyColor = Rules.DefaultBody(lanternData.kind);
				}
				if (lanternData.standColor.x < 0f)
				{
					lanternData.standColor = Rules.DefaultStand();
				}
				if (lanternData.frequency <= 0f)
				{
					lanternData.frequency = 1f;
				}
				if ((Object)(object)value.SyncedHolder != (Object)null)
				{
					lanternData.deployed = false;
				}
				else if (lanternData.deployed)
				{
					value.RigidbodySync.SetKinematic(true);
					if (Vector3.Distance(((Component)value).transform.position, lanternData.position) > 0.05f)
					{
						value.RigidbodySync.TeleportToPosRot(lanternData.position, lanternData.Rotation, (float[])null, (Quaternion[])null);
					}
				}
			}
			foreach (LanternData item2 in Current)
			{
				item2.available = items.ContainsKey(item2.serial);
			}
		}

		private int OpenSlot(Player p)
		{
			int num = (int)AccessTools.Method(typeof(PlayerInventory), "GetTotalSlots", (Type[])null, (Type[])null).Invoke(p.Inventory, null);
			Item val = default(Item);
			for (byte b = 0; b < num; b++)
			{
				if (!p.Inventory._items.TryGetValue(b, ref val) || (Object)(object)val == (Object)null)
				{
					return b;
				}
			}
			return -1;
		}

		private Item Spawn(Player player, int slot, int serial, byte kind)
		{
			//IL_000d: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			Item val = Object.Instantiate<Item>(LanternItem.Prefab(kind), ((Component)player).transform.position + Vector3.up, Quaternion.identity, Server.Instance.DynamicObjectsHolder);
			val.LoadFromSave(new SavedItem
			{
				Exists = true,
				ItemID = kind,
				BettingMultiplier = serial,
				Weight = 1f,
				KillScoreMultiplier = 1f
			});
			InstanceFinder.ServerManager.Spawn(((Component)val).gameObject, (NetworkConnection)null, default(Scene));
			val.SetSyncedHolder(player, true);
			player.Inventory.AddItem((byte)slot, val);
			if (!player.Inventory.HasItemInInventory(val))
			{
				InstanceFinder.ServerManager.Despawn(((Component)val).gameObject, (DespawnType?)null);
				throw new Exception("Inventory did not accept the lantern.");
			}
			return val;
		}

		private bool Ground(Player p, Command cmd, Item item, out RaycastHit hit)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: 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_00d5: 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_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			hit = default(RaycastHit);
			if (!Rules.Finite(cmd.position.x) || !Rules.Finite(cmd.position.y) || !Rules.Finite(cmd.position.z) || !Rules.SurfaceAllowed(cmd.normal.y) || Vector3.Distance(cmd.position, p.CamObject.position) > 8.35f)
			{
				return false;
			}
			Vector3 normalized = ((Vector3)(ref cmd.normal)).normalized;
			foreach (RaycastHit item2 in from x in Physics.RaycastAll(cmd.position + normalized * 0.35f, -normalized, 0.8f, -1, (QueryTriggerInteraction)1)
				orderby ((RaycastHit)(ref x)).distance
				select x)
			{
				RaycastHit current = item2;
				if (((Component)((RaycastHit)(ref current)).collider).gameObject.layer != LayerMask.NameToLayer("Water") && !((Object)(object)((Component)((RaycastHit)(ref current)).collider).GetComponentInParent<Player>() != (Object)null) && !((Object)(object)((Component)((RaycastHit)(ref current)).collider).GetComponentInParent<Item>() != (Object)null) && Rules.SurfaceAllowed(((RaycastHit)(ref current)).normal.y) && !(Vector3.Dot(((RaycastHit)(ref current)).normal, normalized) < 0.5f))
				{
					hit = current;
					return true;
				}
			}
			return false;
		}

		private float Distance(Player p, Item item)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			return Mathf.Min(Vector3.Distance(((Component)p).transform.position, ((Component)item).transform.position), ((Object)(object)p.CamObject == (Object)null) ? float.MaxValue : Vector3.Distance(p.CamObject.position, ((Component)item).transform.position));
		}

		private void PutInInventory(Player p, Item item, LanternData data, Command cmd, NetworkConnection connection, string message)
		{
			int num = OpenSlot(p);
			bool flag = (Object)(object)p.Holding.HeldItem == (Object)null && (Object)(object)p.Holding.UninitializedHeldItem == (Object)null && (Object)(object)p.Inventory.SyncedCurItem == (Object)null;
			if (num < 0 && !flag)
			{
				Respond(cmd, connection, "Free an inventory slot or empty your hands first.");
				return;
			}
			data.deployed = false;
			item.RigidbodySync.SetKinematic(false);
			int value = p.Inventory._syncedCurSlot.Value;
			item.SetSyncedHolder(p, true);
			if (num >= 0)
			{
				p.Inventory.AddItem((byte)num, item);
			}
			item.ReconcileLocalHolderWithSyncedHolder();
			if (num >= 0)
			{
				p.Inventory.ServerSetSyncedCurSlot(value);
			}
			Respond(cmd, connection, message, data.serial);
			Persist();
			Broadcast();
		}

		private void Execute(Player p, Command cmd, NetworkConnection connection)
		{
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_035a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0361: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0370: Unknown result type (might be due to invalid IL or missing references)
			//IL_0375: Unknown result type (might be due to invalid IL or missing references)
			//IL_037d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0382: Unknown result type (might be due to invalid IL or missing references)
			//IL_0389: Unknown result type (might be due to invalid IL or missing references)
			//IL_038e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0392: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_067c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0681: Unknown result type (might be due to invalid IL or missing references)
			if (cmd.action == "hello")
			{
				Broadcast();
				return;
			}
			if (!persistenceReady || world == null || (Object)(object)LanternItem.SmallPrefab == (Object)null || p.Dying.IsDead)
			{
				Respond(cmd, connection, "Lantern Mod is not ready on the host.");
				return;
			}
			Scan();
			try
			{
				if (cmd.action == "buy")
				{
					byte kind = (byte)cmd.argument;
					if (!Rules.IsKind(kind))
					{
						Respond(cmd, connection, "Unknown lantern type.");
						return;
					}
					if ((Object)(object)FocusedMoneyVendor(p, 5f) == (Object)null)
					{
						Respond(cmd, connection, "Move close to and look at a money vendor to buy a light.");
						return;
					}
					int num = OpenSlot(p);
					if (num < 0)
					{
						Respond(cmd, connection, "Free an inventory slot first.");
						return;
					}
					int value = Rules.Price(kind);
					if (!Wallet.Charge(p, value))
					{
						Respond(cmd, connection, "You need $" + value.ToString("N0") + ".");
						return;
					}
					int num2 = save.nextSerial++;
					try
					{
						Spawn(p, num, num2, kind);
					}
					catch
					{
						Wallet.Credit(p, value);
						throw;
					}
					LanternData lanternData = new LanternData
					{
						serial = num2,
						kind = kind,
						owner = p.SteamID,
						ownerName = p.SteamName,
						name = Rules.TypeName(kind),
						bodyColor = Rules.DefaultBody(kind)
					};
					Current.Add(lanternData);
					Persist();
					Broadcast();
					Respond(cmd, connection, lanternData.name + " purchased for $" + value.ToString("N0") + ".", num2);
					return;
				}
				LanternData lanternData2 = Find(cmd.serial);
				Item val = FindItem(cmd.serial);
				if (lanternData2 == null || (Object)(object)val == (Object)null)
				{
					Respond(cmd, connection, "That lantern is unavailable.");
					return;
				}
				if (lanternData2.owner != p.SteamID)
				{
					Respond(cmd, connection, "That lantern belongs to " + (string.IsNullOrEmpty(lanternData2.ownerName) ? "another player" : lanternData2.ownerName) + ".");
					return;
				}
				bool flag = (Object)(object)val.SyncedHolder == (Object)(object)p;
				if (cmd.action == "deploy")
				{
					if (!flag || lanternData2.deployed)
					{
						Respond(cmd, connection, "Hold that lantern before deploying it.");
						return;
					}
					if (!Ground(p, cmd, val, out var hit))
					{
						Respond(cmd, connection, "Look at an upward-facing surface within 8 metres.");
						return;
					}
					val.SpawnFromInventory();
					p.Inventory.RemoveItem(val);
					if ((Object)(object)val.Holder != (Object)null)
					{
						val.Drop(false, default(Vector3), default(Vector3));
					}
					val.SetSyncedHolder((Player)null, true);
					val.ReconcileLocalHolderWithSyncedHolder();
					if ((Object)(object)p.Holding.HeldItem == (Object)(object)val)
					{
						p.Hands.DropItem(false, val);
						p.Holding.DropItem(false, val);
						p.Holding.SetHeldItem((Item)null);
					}
					if ((Object)(object)p.Holding.UninitializedHeldItem == (Object)(object)val)
					{
						p.Holding.SetUninitializedHeldItem((Item)null);
					}
					lanternData2.position = ((RaycastHit)(ref hit)).point + ((RaycastHit)(ref hit)).normal * 0.012f;
					lanternData2.surfaceNormal = ((RaycastHit)(ref hit)).normal;
					Quaternion curPlayerRot = p.CurPlayerRot;
					lanternData2.yaw = ((Quaternion)(ref curPlayerRot)).eulerAngles.y;
					lanternData2.deployed = true;
					val.RigidbodySync.ServerSetSyncedSimulator(((NetworkBehaviour)Server.Instance).Owner);
					val.RigidbodySync.TeleportToPosRot(lanternData2.position, lanternData2.Rotation, (float[])null, (Quaternion[])null);
					val.RigidbodySync.SetKinematic(true);
					Respond(cmd, connection, lanternData2.name + " deployed.", lanternData2.serial);
				}
				else
				{
					if (cmd.action == "pickup")
					{
						if (flag)
						{
							Respond(cmd, connection, "That lantern is already in your inventory.");
						}
						else if (Distance(p, val) > 6.35f)
						{
							Respond(cmd, connection, "Move within 6 metres of the lantern.");
						}
						else
						{
							PutInInventory(p, val, lanternData2, cmd, connection, lanternData2.name + " picked up.");
						}
						return;
					}
					if (cmd.action == "recall")
					{
						if (flag)
						{
							Respond(cmd, connection, "That lantern is already in your inventory.", lanternData2.serial);
						}
						else
						{
							PutInInventory(p, val, lanternData2, cmd, connection, lanternData2.name + " recalled to your inventory.");
						}
						return;
					}
					if (cmd.action == "rename")
					{
						lanternData2.name = Rules.CleanName(cmd.text, Rules.TypeName(lanternData2.kind));
						Respond(cmd, connection, "Lantern renamed to " + lanternData2.name + ".", lanternData2.serial);
					}
					else if (cmd.action == "intensity")
					{
						lanternData2.intensity = Rules.Intensity(cmd.value);
						if (lanternData2.effectMode == 0)
						{
							ResetStaticNow(lanternData2);
						}
						Respond(cmd, connection, "Light intensity updated.", lanternData2.serial);
					}
					else if (cmd.action == "temperature")
					{
						lanternData2.temperature = Rules.Temperature(cmd.value);
						lanternData2.useTemperature = true;
						if (lanternData2.effectMode == 0)
						{
							ResetStaticNow(lanternData2);
						}
						Respond(cmd, connection, "Color temperature updated.", lanternData2.serial);
					}
					else if (cmd.action == "bodycolor")
					{
						lanternData2.bodyColor = new Vector3(Rules.ColorChannel(cmd.position.x), Rules.ColorChannel(cmd.position.y), Rules.ColorChannel(cmd.position.z));
						ApplyBodyNow(lanternData2);
						Respond(cmd, connection, "Lantern body color saved.", lanternData2.serial);
					}
					else if (cmd.action == "standcolor")
					{
						if (lanternData2.kind != 246)
						{
							Respond(cmd, connection, "That lantern has no stand.");
							return;
						}
						lanternData2.standColor = new Vector3(Rules.ColorChannel(cmd.position.x), Rules.ColorChannel(cmd.position.y), Rules.ColorChannel(cmd.position.z));
						ApplyBodyNow(lanternData2);
						Respond(cmd, connection, "Lantern stand color saved.", lanternData2.serial);
					}
					else if (cmd.action == "lightcolor")
					{
						lanternData2.lightColor = new Vector3(Rules.ColorChannel(cmd.position.x), Rules.ColorChannel(cmd.position.y), Rules.ColorChannel(cmd.position.z));
						lanternData2.useTemperature = false;
						if (lanternData2.effectMode == 0)
						{
							ResetStaticNow(lanternData2);
						}
						Respond(cmd, connection, "Light color saved.", lanternData2.serial);
					}
					else if (cmd.action == "colormode")
					{
						lanternData2.useTemperature = cmd.argument != 0;
						if (lanternData2.effectMode == 0)
						{
							ResetStaticNow(lanternData2);
						}
						Respond(cmd, connection, lanternData2.useTemperature ? "Color temperature mode enabled." : "Direct light color mode enabled.", lanternData2.serial);
					}
					else if (cmd.action == "lighttoggle")
					{
						lanternData2.lightOn = cmd.argument != 0;
						if (lanternData2.effectMode == 0)
						{
							ResetStaticNow(lanternData2);
						}
						Respond(cmd, connection, lanternData2.lightOn ? "Light switched on." : "Light switched off.", lanternData2.serial);
					}
					else if (cmd.action == "effect")
					{
						lanternData2.effectMode = Rules.EffectMode(cmd.argument);
						if (lanternData2.effectMode == 0)
						{
							ResetStaticNow(lanternData2);
						}
						Respond(cmd, connection, "Light mode set to " + ((lanternData2.effectMode == 1) ? "strobe" : ((lanternData2.effectMode == 2) ? "pulse" : "static")) + ".", lanternData2.serial);
					}
					else
					{
						if (!(cmd.action == "frequency"))
						{
							if (!(cmd.action == "sell"))
							{
								return;
							}
							int value2 = Rules.Price(lanternData2.kind) / 2;
							if (flag)
							{
								p.Inventory.RemoveItem(val);
								if ((Object)(object)p.Holding.HeldItem == (Object)(object)val)
								{
									p.Hands.DropItem(false, val);
									p.Holding.DropItem(false, val);
									p.Holding.SetHeldItem((Item)null);
								}
							}
							lanternData2.deployed = false;
							Wallet.Credit(p, value2);
							Current.Remove(lanternData2);
							items.Remove(lanternData2.serial);
							InstanceFinder.ServerManager.Despawn(((Component)val).gameObject, (DespawnType?)null);
							Selected = 0;
							Persist();
							Broadcast();
							Respond(cmd, connection, "Lantern sold back for $" + value2.ToString("N0") + ".");
							return;
						}
						lanternData2.frequency = Rules.Frequency(cmd.value);
						Respond(cmd, connection, "Effect frequency updated.", lanternData2.serial);
					}
				}
				Persist();
				Broadcast();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)ex);
				Respond(cmd, connection, "Lantern Mod could not complete that action. Check the BepInEx log.");
			}
		}

		public void CompleteVanillaSale(Item item)
		{
			if (!InstanceFinder.IsServerStarted || (Object)(object)item == (Object)null)
			{
				return;
			}
			LanternData lanternData = Find(LanternItem.Serial(item));
			if (lanternData != null)
			{
				Current.Remove(lanternData);
				items.Remove(lanternData.serial);
				if (Selected == lanternData.serial)
				{
					Selected = 0;
				}
				Persist();
				Broadcast();
			}
		}

		public static bool IsMoneyVendor(NPC npc)
		{
			if ((Object)(object)npc == (Object)null)
			{
				return false;
			}
			FieldInfo fieldInfo = AccessTools.Field(typeof(NPC), "_quests");
			return ((fieldInfo == null) ? null : (fieldInfo.GetValue(npc) as IEnumerable<NPCQuest>))?.Any((NPCQuest q) => (Object)(object)q != (Object)null && (int)q.Type == 1) ?? false;
		}

		public void SetHoveredInteractable(Component value, bool active)
		{
			if (active)
			{
				hoveredInteractable = value;
			}
			else if ((Object)(object)hoveredInteractable == (Object)(object)value)
			{
				hoveredInteractable = null;
			}
		}

		private static NPC VendorFrom(Component component)
		{
			if ((Object)(object)component == (Object)null)
			{
				return null;
			}
			NPC componentInParent = component.GetComponentInParent<NPC>();
			if (!((Object)(object)componentInParent != (Object)null))
			{
				return component.GetComponentInChildren<NPC>(true);
			}
			return componentInParent;
		}

		public NPC FocusedMoneyVendor(Player player, float range)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: 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_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || (Object)(object)player.CamObject == (Object)null)
			{
				return null;
			}
			if ((Object)(object)player == (Object)(object)Player.LocalPlayer && (Object)(object)hoveredInteractable != (Object)null)
			{
				NPC val = VendorFrom(hoveredInteractable);
				if (IsMoneyVendor(val) && Vector3.Distance(((Component)player).transform.position, ((Component)val).transform.position) <= range + 0.35f)
				{
					return val;
				}
			}
			foreach (RaycastHit item in from h in Physics.RaycastAll(player.CamObject.position, player.CamObject.forward, range, -1, (QueryTriggerInteraction)2)
				orderby ((RaycastHit)(ref h)).distance
				select h)
			{
				RaycastHit current = item;
				if (!((Object)(object)((Component)((RaycastHit)(ref current)).collider).GetComponentInParent<Player>() == (Object)(object)player))
				{
					NPC componentInParent = ((Component)((RaycastHit)(ref current)).collider).GetComponentInParent<NPC>();
					if (IsMoneyVendor(componentInParent))
					{
						return componentInParent;
					}
					if (!((RaycastHit)(ref current)).collider.isTrigger)
					{
						break;
					}
				}
			}
			NPC result = null;
			float num = 0.72f;
			RaycastHit val3 = default(RaycastHit);
			foreach (NPC item2 in Object.FindObjectsByType<NPC>().Where(IsMoneyVendor))
			{
				Vector3 val2 = (((Object)(object)item2.MouthPosForItems != (Object)null) ? item2.MouthPosForItems.position : (((Component)item2).transform.position + Vector3.up)) - player.CamObject.position;
				float magnitude = ((Vector3)(ref val2)).magnitude;
				if (!(magnitude <= 0.01f))
				{
					float num2 = Vector3.Dot(player.CamObject.forward, val2 / magnitude);
					if (Rules.CanUseVendor(magnitude, num2) && !(num2 < num) && Physics.Raycast(player.CamObject.position, val2 / magnitude, ref val3, magnitude + 0.5f, -1, (QueryTriggerInteraction)2) && !((Object)(object)((Component)((RaycastHit)(ref val3)).collider).GetComponentInParent<NPC>() != (Object)(object)item2))
					{
						result = item2;
						num = num2;
					}
				}
			}
			return result;
		}

		private void OnDestroy()
		{
			Persist();
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Instance = null;
		}

		public static bool IsDeployed(Item item)
		{
			if ((Object)(object)Instance != (Object)null && LanternItem.Is(item) && (Object)(object)item.SyncedHolder == (Object)null)
			{
				return Instance.Find(LanternItem.Serial(item))?.deployed ?? false;
			}
			return false;
		}

		private Item RayLantern(float range)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.LocalPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)localPlayer.CamObject == (Object)null)
			{
				return null;
			}
			foreach (RaycastHit item in from x in Physics.RaycastAll(localPlayer.CamObject.position, localPlayer.CamObject.forward, range, -1, (QueryTriggerInteraction)2)
				orderby ((RaycastHit)(ref x)).distance
				select x)
			{
				RaycastHit current = item;
				if ((Object)(object)((Component)((RaycastHit)(ref current)).collider).GetComponentInParent<Player>() == (Object)(object)localPlayer)
				{
					continue;
				}
				Item componentInParent = ((Component)((RaycastHit)(ref current)).collider).GetComponentInParent<Item>();
				if (!((Object)(object)componentInParent != (Object)null) || !((Object)(object)componentInParent.SyncedHolder == (Object)(object)localPlayer))
				{
					if (LanternItem.Is(componentInParent) && IsDeployed(componentInParent))
					{
						return componentInParent;
					}
					if (!((RaycastHit)(ref current)).collider.isTrigger)
					{
						return null;
					}
				}
			}
			return null;
		}

		private Item InteractionTarget()
		{
			Player localPlayer = Player.LocalPlayer;
			if ((Object)(object)localPlayer == (Object)null || Open || localPlayer.BlockInputs || localPlayer.Dying.IsDead)
			{
				return null;
			}
			Item heldItem = localPlayer.Holding.HeldItem;
			if (LanternItem.Is(heldItem))
			{
				return heldItem;
			}
			return RayLantern(6f);
		}

		public bool CapturesInteract()
		{
			if (!((Object)(object)InteractionTarget() != (Object)null))
			{
				return (Object)(object)activeTarget != (Object)null;
			}
			return true;
		}

		private bool CrosshairSurface(Item held, out RaycastHit surface)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			surface = default(RaycastHit);
			Player localPlayer = Player.LocalPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)localPlayer.CamObject == (Object)null)
			{
				return false;
			}
			foreach (RaycastHit item in from x in Physics.RaycastAll(localPlayer.CamObject.position, localPlayer.CamObject.forward, 8f, -1, (QueryTriggerInteraction)1)
				orderby ((RaycastHit)(ref x)).distance
				select x)
			{
				RaycastHit current = item;
				if (!((Object)(object)((Component)((RaycastHit)(ref current)).collider).GetComponentInParent<Player>() == (Object)(object)localPlayer) && !((Object)(object)((Component)((RaycastHit)(ref current)).collider).GetComponentInParent<Item>() == (Object)(object)held))
				{
					if (((Component)((RaycastHit)(ref current)).collider).gameObject.layer == LayerMask.NameToLayer("Water") || !Rules.SurfaceAllowed(((RaycastHit)(ref current)).normal.y))
					{
						return false;
					}
					surface = current;
					return true;
				}
			}
			return false;
		}

		private void FireHeldAction(Item target)
		{
			//IL_0066: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			Selected = LanternItem.Serial(target);
			if ((Object)(object)target.SyncedHolder == (Object)(object)Player.LocalPlayer)
			{
				if (!CrosshairSurface(target, out var surface))
				{
					SetStatus("Look at an upward-facing surface within 8 metres.");
				}
				else
				{
					Send("deploy", 0, 0f, null, ((RaycastHit)(ref surface)).point, ((RaycastHit)(ref surface)).normal);
				}
			}
			else
			{
				Send("pickup");
			}
		}

		private void UpdateInteraction()
		{
			Keyboard current = Keyboard.current;
			if (current == null)
			{
				return;
			}
			if (((ButtonControl)current.eKey).wasPressedThisFrame)
			{
				activeTarget = InteractionTarget();
				useStarted = Time.unscaledTime;
				holdFired = false;
			}
			if ((Object)(object)activeTarget != (Object)null && ((ButtonControl)current.eKey).isPressed && !holdFired && Time.unscaledTime - useStarted >= 1f)
			{
				holdFired = true;
				FireHeldAction(activeTarget);
			}
			if (((ButtonControl)current.eKey).wasReleasedThisFrame)
			{
				Item val = activeTarget;
				if ((Object)(object)val != (Object)null && !holdFired && (Object)(object)val.SyncedHolder != (Object)(object)Player.LocalPlayer)
				{
					OpenLanternEditor(LanternItem.Serial(val));
				}
				activeTarget = null;
				holdFired = false;
			}
		}

		private void DrawInteractionHint()
		{
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Expected O, but got Unknown
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Expected O, but got Unknown
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			Item val = activeTarget ?? InteractionTarget();
			if (!((Object)(object)val == (Object)null))
			{
				LanternData lanternData = Find(LanternItem.Serial(val));
				bool num = (Object)(object)val.SyncedHolder == (Object)(object)Player.LocalPlayer;
				string text = ((lanternData == null) ? Rules.TypeName(val.ID) : lanternData.name);
				string text2 = (num ? ("Hold E to deploy " + text) : "Tap E to edit  •  Hold E to pick up");
				if ((Object)(object)activeTarget != (Object)null && Keyboard.current != null && ((ButtonControl)Keyboard.current.eKey).isPressed)
				{
					text2 = text2 + "   " + Mathf.Clamp01((Time.unscaledTime - u