Decompiled source of Cogling v1.0.0

plugins/Cogling.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using HeaveHo.Shared;
using Microsoft.CodeAnalysis;
using Nick.Shared;
using Splatform;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Audio;
using UnityEngine.Playables;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyMetadata("AI_Assisted_Creation", "This assembly was partially or fully created with the assistance of Generative AI.")]
[assembly: AssemblyMetadata("AI_Model_Vendor", "Anthropic")]
[assembly: AssemblyMetadata("ClaudeTools.Reload", "world")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[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 HeaveHo.Shared
{
	internal sealed class ServerSettings : IDisposable
	{
		public enum ServerMod
		{
			NotConnected,
			Checking,
			Installed,
			Missing
		}

		private sealed class ConfigurationManagerAttributes
		{
			public bool? ReadOnly;
		}

		private sealed class SyncedText
		{
			public string Key;

			public Func<string> Own;

			public Action<string> Use;

			public string Given;

			public bool FromServer;

			public bool Pending;

			public byte[] Packed;

			public bool TooBig;

			public MemoryStream Incoming;

			public int NextPart;
		}

		private sealed class Sending
		{
			public ZRpc Rpc;

			public string Key;

			public byte[] Data;

			public int Next;

			public int Parts;
		}

		private const int Protocol = 2;

		private const float ChangeSendGap = 0.5f;

		private const float AnswerWait = 20f;

		private const float FileWait = 1f;

		private const int PartSize = 65536;

		private const int CompressFrom = 1024;

		private const int WarnBytes = 262144;

		private const int MaxBytes = 8388608;

		private const int PaceBelow = 10240;

		private readonly string _send;

		private readonly string _ask;

		private readonly string _dAsk;

		private readonly string _dHello;

		private readonly string _dSend;

		private readonly string _edit;

		private readonly string _dTextAsk;

		private readonly string _dText;

		private readonly string _dAgain;

		private readonly ConfigFile _config;

		private readonly ManualLogSource _log;

		private readonly string _name;

		private readonly List<ConfigEntryBase> _entries = new List<ConfigEntryBase>();

		private readonly Dictionary<ConfigEntryBase, object> _own = new Dictionary<ConfigEntryBase, object>();

		private readonly Dictionary<ConfigEntryBase, object> _server = new Dictionary<ConfigEntryBase, object>();

		private readonly List<GameObject> _guardedPieces = new List<GameObject>();

		private readonly List<Recipe> _guardedRecipes = new List<Recipe>();

		private ZRoutedRpc _registeredOn;

		private bool _applying;

		private bool _reloading;

		private bool _changePending;

		private float _nextChangeSend;

		private float _askedAt = -1f;

		private int _serverProtocol;

		private bool _directSeen;

		private readonly HashSet<ZRpc> _directPeers = new HashSet<ZRpc>();

		private readonly List<SyncedText> _texts = new List<SyncedText>();

		private readonly Dictionary<ZRpc, HashSet<string>> _textPeers = new Dictionary<ZRpc, HashSet<string>>();

		private bool _textPending;

		private float _nextTextSend;

		private bool _readOnlyShown;

		private float _nextAdminCheck;

		private FileSystemWatcher _watcher;

		private volatile bool _fileTouched;

		private float _reloadAt = -1f;

		private string _fileText;

		private readonly List<Sending> _outbox = new List<Sending>();

		private static readonly MethodInfo UpdateAvailablePieces = AccessTools.Method(typeof(Player), "UpdateAvailablePiecesList", (Type[])null, (Type[])null);

		private static readonly List<ServerSettings> Live = new List<ServerSettings>();

		private static Harmony _saveHarmony;

		public string Version { get; }

		public bool FromServer => _server.Count > 0;

		public ServerMod Server { get; private set; }

		public string ServerVersion { get; private set; }

		public bool CanEditServer
		{
			get
			{
				if (!IsServer)
				{
					if (Server == ServerMod.Installed && _serverProtocol >= 1 && (Object)(object)ZNet.instance != (Object)null)
					{
						return ZNet.instance.LocalPlayerIsAdminOrHost();
					}
					return false;
				}
				return true;
			}
		}

		private static bool IsServer
		{
			get
			{
				if ((Object)(object)ZNet.instance != (Object)null)
				{
					return ZNet.instance.IsServer();
				}
				return false;
			}
		}

		public event Action ServerChanged;

		public ServerSettings(string guid, ConfigFile config, ManualLogSource log)
		{
			_send = guid + ".settings";
			_ask = guid + ".settings.ask";
			_dAsk = guid + ".settings.d.ask";
			_dHello = guid + ".settings.d.hello";
			_dSend = guid + ".settings.d.values";
			_edit = guid + ".settings.d.edit";
			_dTextAsk = guid + ".settings.d.textask";
			_dAgain = guid + ".settings.d.again";
			_dText = guid + ".settings.d.text";
			_config = config;
			_log = log;
			BepInPlugin val = PluginOf(guid);
			_name = ((val != null) ? val.Name : null) ?? guid;
			Version = ((val == null) ? null : val.Version?.ToString()) ?? "";
			Live.Add(this);
			if (Live.Count == 1)
			{
				PatchSave();
			}
			WatchFile();
		}

		public ConfigEntry<T> Add<T>(ConfigEntry<T> entry)
		{
			if (entry == null || _entries.Contains((ConfigEntryBase)(object)entry))
			{
				return entry;
			}
			_entries.Add((ConfigEntryBase)(object)entry);
			entry.SettingChanged += OnChanged;
			GiveManagerAttributes((ConfigEntryBase)(object)entry);
			return entry;
		}

		private static void GiveManagerAttributes(ConfigEntryBase entry)
		{
			ConfigDescription description = entry.Description;
			if (description == null || description == ConfigDescription.Empty || (description.Tags ?? new object[0]).Any(IsManagerAttributes))
			{
				return;
			}
			try
			{
				object[] value = new object[1]
				{
					new ConfigurationManagerAttributes()
				}.Concat(description.Tags ?? new object[0]).ToArray();
				AccessTools.Field(typeof(ConfigDescription), "<Tags>k__BackingField")?.SetValue(description, value);
			}
			catch (Exception)
			{
			}
		}

		public ConfigEntry<T> Bind<T>(string section, string key, T value, string description, AcceptableValueBase range = null, params object[] tags)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			if (!description.Contains("[Synced with Server]"))
			{
				description += " [Synced with Server]";
			}
			return Add<T>(_config.Bind<T>(section, key, value, new ConfigDescription(description, range, tags ?? new object[0])));
		}

		public void NeedsServer(GameObject piecePrefab)
		{
			if (!((Object)(object)piecePrefab == (Object)null))
			{
				_guardedPieces.RemoveAll((GameObject p) => (Object)(object)p == (Object)null || ((Object)p).name == ((Object)piecePrefab).name);
				_guardedPieces.Add(piecePrefab);
				Guard();
			}
		}

		public void NeedsServer(Recipe recipe)
		{
			if (!((Object)(object)recipe == (Object)null))
			{
				_guardedRecipes.RemoveAll((Recipe r) => (Object)(object)r == (Object)null || (Object)(object)r == (Object)(object)recipe || (!string.IsNullOrEmpty(((Object)recipe).name) && ((Object)r).name == ((Object)recipe).name));
				_guardedRecipes.Add(recipe);
				Guard();
			}
		}

		public void AddText(string key, Func<string> own, Action<string> use)
		{
			if (string.IsNullOrEmpty(key) || own == null || use == null)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogError((object)"AddText needs a key, own and use");
				}
				return;
			}
			_texts.RemoveAll((SyncedText x) => x.Key == key);
			SyncedText syncedText = new SyncedText
			{
				Key = key,
				Own = own,
				Use = use
			};
			_texts.Add(syncedText);
			Give(syncedText, OwnText(syncedText));
			ZRpc val = ((!((Object)(object)ZNet.instance != (Object)null) || IsServer) ? null : ZNet.instance.GetServerPeer()?.m_rpc);
			if (_registeredOn != null && val != null)
			{
				val.Register<ZPackage>(_dText, (Action<ZRpc, ZPackage>)OnText);
				AskTexts(val);
			}
		}

		public void TextChanged(string key)
		{
			SyncedText syncedText = _texts.FirstOrDefault((SyncedText x) => x.Key == key);
			if (syncedText != null)
			{
				syncedText.Packed = null;
				if (!syncedText.FromServer)
				{
					Give(syncedText, OwnText(syncedText));
				}
				if (IsServer)
				{
					syncedText.Pending = true;
					_textPending = true;
				}
			}
		}

		public bool TextFromServer(string key)
		{
			return _texts.Any((SyncedText x) => x.Key == key && x.FromServer);
		}

		public void Update()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != _registeredOn)
			{
				Unregister();
				Restore();
				RestoreTexts(give: true);
				_changePending = false;
				_textPending = false;
				SetServer(ServerMod.NotConnected, null, 0);
				if (instance != null)
				{
					Register(instance);
				}
			}
			float unscaledTime = Time.unscaledTime;
			if (_changePending && unscaledTime >= _nextChangeSend)
			{
				SendChange();
			}
			if (_textPending && unscaledTime >= _nextTextSend)
			{
				SendTexts();
			}
			if (_outbox.Count > 0)
			{
				Pump();
			}
			if (Server == ServerMod.Checking && _askedAt >= 0f && unscaledTime - _askedAt > 20f)
			{
				if (_guardedPieces.Count + _guardedRecipes.Count > 0)
				{
					ManualLogSource log = _log;
					if (log != null)
					{
						log.LogWarning((object)("The server didn't answer: " + _name + " isn't installed there (or its copy is older than 2026-10-11), so its pieces and items can't be made on this server."));
					}
				}
				else
				{
					ManualLogSource log2 = _log;
					if (log2 != null)
					{
						log2.LogInfo((object)("The server didn't answer: " + _name + " isn't installed there, or its copy is older" + (FromServer ? " (its settings apply)." : " (your own settings apply).")));
					}
				}
				SetServer(ServerMod.Missing, null, 0);
			}
			if (_fileTouched)
			{
				_fileTouched = false;
				_reloadAt = unscaledTime + 1f;
			}
			if (_reloadAt >= 0f && unscaledTime >= _reloadAt)
			{
				_reloadAt = -1f;
				ReloadFile();
			}
			if (FromServer && unscaledTime >= _nextAdminCheck)
			{
				_nextAdminCheck = unscaledTime + 1f;
				ShowReadOnly();
			}
		}

		public void Dispose()
		{
			Unregister();
			Restore();
			RestoreTexts(give: false);
			SetServer(ServerMod.NotConnected, null, 0);
			foreach (ConfigEntryBase entry in _entries)
			{
				Unsubscribe(entry);
			}
			_entries.Clear();
			_texts.Clear();
			try
			{
				_watcher?.Dispose();
			}
			catch (Exception)
			{
			}
			_watcher = null;
			Live.Remove(this);
			if (Live.Count == 0)
			{
				UnpatchSave();
			}
		}

		private void Register(ZRoutedRpc rpc)
		{
			Forget(rpc, _send);
			Forget(rpc, _ask);
			rpc.Register<ZPackage>(_send, (Action<long, ZPackage>)OnRoutedValues);
			rpc.Register(_ask, (Action<long>)OnRoutedAsk);
			rpc.m_onNewPeer = (Action<long>)Delegate.Combine(rpc.m_onNewPeer, new Action<long>(OnNewPeer));
			_registeredOn = rpc;
			if (IsServer)
			{
				foreach (ZNetPeer peer in ZNet.instance.GetPeers())
				{
					ListenTo(peer);
					if (peer != null)
					{
						ZRpc rpc2 = peer.m_rpc;
						if (rpc2 != null)
						{
							rpc2.Invoke(_dAgain, Array.Empty<object>());
						}
					}
				}
				return;
			}
			if ((Object)(object)ZNet.instance != (Object)null)
			{
				SetServer(ServerMod.Checking, null, 0);
				if (ZNet.instance.GetServerPeer() != null)
				{
					AskServer();
				}
			}
		}

		private void Unregister()
		{
			if (_registeredOn == null)
			{
				return;
			}
			ZRoutedRpc registeredOn = _registeredOn;
			registeredOn.m_onNewPeer = (Action<long>)Delegate.Remove(registeredOn.m_onNewPeer, new Action<long>(OnNewPeer));
			Forget(_registeredOn, _send);
			Forget(_registeredOn, _ask);
			if ((Object)(object)ZNet.instance != (Object)null)
			{
				foreach (ZNetPeer peer in ZNet.instance.GetPeers())
				{
					if (peer?.m_rpc != null)
					{
						string[] array = new string[7] { _dAsk, _dHello, _dSend, _edit, _dTextAsk, _dText, _dAgain };
						foreach (string name in array)
						{
							ForgetDirect(peer.m_rpc, name);
						}
					}
				}
			}
			_directPeers.Clear();
			_textPeers.Clear();
			_outbox.Clear();
			_directSeen = false;
			_registeredOn = null;
		}

		private static void Forget(ZRoutedRpc rpc, string name)
		{
			if (AccessTools.Field(typeof(ZRoutedRpc), "m_functions")?.GetValue(rpc) is IDictionary dictionary)
			{
				dictionary.Remove(StringExtensionMethods.GetStableHashCode(name));
			}
		}

		private static void ForgetDirect(ZRpc rpc, string name)
		{
			if (AccessTools.Field(typeof(ZRpc), "m_functions")?.GetValue(rpc) is IDictionary dictionary)
			{
				dictionary.Remove(StringExtensionMethods.GetStableHashCode(name));
			}
		}

		private void OnNewPeer(long uid)
		{
			if (IsServer)
			{
				ZNetPeer peer = ZNet.instance.GetPeer(uid);
				ListenTo(peer);
				if (peer?.m_rpc != null)
				{
					SendDirect(peer.m_rpc);
				}
				SendRouted(uid);
			}
			else if ((Object)(object)ZNet.instance != (Object)null)
			{
				ZNetPeer serverPeer = ZNet.instance.GetServerPeer();
				if (serverPeer != null && serverPeer.m_uid == uid)
				{
					AskServer();
				}
			}
		}

		private void ListenTo(ZNetPeer peer)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			if (peer?.m_rpc != null)
			{
				peer.m_rpc.Register(_dAsk, new Method(OnDirectAsk));
				peer.m_rpc.Register<ZPackage>(_edit, (Action<ZRpc, ZPackage>)OnEdit);
				peer.m_rpc.Register<ZPackage>(_dTextAsk, (Action<ZRpc, ZPackage>)OnTextAsk);
			}
		}

		private void OnDirectAsk(ZRpc rpc)
		{
			if (IsServer)
			{
				_directPeers.Add(rpc);
				SendDirect(rpc);
			}
		}

		private void OnRoutedAsk(long sender)
		{
			if (IsServer)
			{
				SendRouted(sender);
			}
		}

		private void SendDirect(ZRpc rpc)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(2);
			val.Write(Version);
			rpc.Invoke(_dHello, new object[1] { val });
			if (_entries.Count > 0)
			{
				rpc.Invoke(_dSend, new object[1] { Values() });
			}
		}

		private void SendRouted(long target)
		{
			if (ZRoutedRpc.instance != null && _entries.Count > 0)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(target, _send, new object[1] { Values() });
			}
		}

		private ZPackage Values()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(_entries.Count);
			foreach (ConfigEntryBase entry in _entries)
			{
				val.Write(entry.Definition.Section);
				val.Write(entry.Definition.Key);
				val.Write(TomlTypeConverter.ConvertToString(entry.BoxedValue, entry.SettingType));
			}
			return val;
		}

		private void AskServer()
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			ZNetPeer val = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetServerPeer() : null);
			if (val?.m_rpc == null)
			{
				return;
			}
			_askedAt = Time.unscaledTime;
			val.m_rpc.Register<ZPackage>(_dHello, (Action<ZRpc, ZPackage>)OnDirectHello);
			val.m_rpc.Register<ZPackage>(_dSend, (Action<ZRpc, ZPackage>)OnDirectValues);
			val.m_rpc.Register<ZPackage>(_dText, (Action<ZRpc, ZPackage>)OnText);
			val.m_rpc.Register(_dAgain, new Method(OnAskAgain));
			val.m_rpc.Invoke(_dAsk, Array.Empty<object>());
			AskTexts(val.m_rpc);
			try
			{
				ZRoutedRpc instance = ZRoutedRpc.instance;
				if (instance != null)
				{
					instance.InvokeRoutedRPC(val.m_uid, _ask, Array.Empty<object>());
				}
			}
			catch (Exception)
			{
			}
		}

		private static bool IsServerConnection(ZRpc rpc)
		{
			if (!IsServer)
			{
				ZNet instance = ZNet.instance;
				return ((instance == null) ? null : instance.GetServerPeer()?.m_rpc) == rpc;
			}
			return false;
		}

		private void OnAskAgain(ZRpc rpc)
		{
			if (IsServerConnection(rpc))
			{
				rpc.Invoke(_dAsk, Array.Empty<object>());
				AskTexts(rpc);
			}
		}

		private void OnDirectHello(ZRpc rpc, ZPackage pkg)
		{
			if (!IsServerConnection(rpc))
			{
				return;
			}
			try
			{
				int protocol = pkg.ReadInt();
				string text = pkg.ReadString();
				if (text != Version && text != ServerVersion)
				{
					ManualLogSource log = _log;
					if (log != null)
					{
						log.LogWarning((object)("The server has " + _name + " " + text + ", you have " + Version + ": some things may not match. Use the same version as the server."));
					}
				}
				_directSeen = true;
				SetServer(ServerMod.Installed, text, protocol);
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = _log;
				if (log2 != null)
				{
					log2.LogWarning((object)("Could not read the server's hello: " + ex.Message));
				}
			}
		}

		private void OnDirectValues(ZRpc rpc, ZPackage pkg)
		{
			if (IsServerConnection(rpc))
			{
				TakeValues(pkg);
			}
		}

		private void OnRoutedValues(long sender, ZPackage pkg)
		{
			if (!_directSeen && !IsServer)
			{
				ZNetPeer val = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetServerPeer() : null);
				if (val != null && val.m_uid == sender)
				{
					TakeValues(pkg);
				}
			}
		}

		private void TakeValues(ZPackage pkg)
		{
			try
			{
				int num = pkg.ReadInt();
				List<string> list = new List<string>();
				for (int i = 0; i < num; i++)
				{
					string section = pkg.ReadString();
					string key = pkg.ReadString();
					string text = pkg.ReadString();
					ConfigEntryBase val = ((IEnumerable<ConfigEntryBase>)_entries).FirstOrDefault((Func<ConfigEntryBase, bool>)((ConfigEntryBase x) => x.Definition.Section == section && x.Definition.Key == key));
					if (val != null)
					{
						object obj;
						try
						{
							obj = TomlTypeConverter.ConvertToValue(text, val.SettingType);
						}
						catch (Exception)
						{
							continue;
						}
						if (!_own.ContainsKey(val))
						{
							_own[val] = val.BoxedValue;
						}
						_server[val] = obj;
						if (!object.Equals(val.BoxedValue, obj))
						{
							Apply(val, obj);
							list.Add(section + "/" + key + " = " + text);
						}
					}
				}
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogInfo((object)($"Settings from the server apply while you play here ({_server.Count})" + ((list.Count > 0) ? (": " + string.Join(", ", list.ToArray())) : "")));
				}
				ShowReadOnly();
			}
			catch (Exception ex2)
			{
				ManualLogSource log2 = _log;
				if (log2 != null)
				{
					log2.LogWarning((object)("Could not read the server's settings: " + ex2.Message));
				}
			}
		}

		private void Apply(ConfigEntryBase e, object value)
		{
			bool saveOnConfigSet = _config.SaveOnConfigSet;
			_applying = true;
			try
			{
				_config.SaveOnConfigSet = false;
				e.BoxedValue = value;
			}
			finally
			{
				_config.SaveOnConfigSet = saveOnConfigSet;
				_applying = false;
			}
		}

		private void Restore()
		{
			if (_server.Count == 0)
			{
				return;
			}
			foreach (KeyValuePair<ConfigEntryBase, object> item in _own)
			{
				Apply(item.Key, item.Value);
			}
			_own.Clear();
			_server.Clear();
			ShowReadOnly();
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogInfo((object)"Your own settings apply again");
			}
		}

		private void OnChanged(object sender, EventArgs args)
		{
			if (_applying)
			{
				return;
			}
			ConfigEntryBase val = (ConfigEntryBase)((sender is ConfigEntryBase) ? sender : null);
			if (val == null)
			{
				return;
			}
			if (_server.TryGetValue(val, out var value))
			{
				if (!_reloading && CanEditServer)
				{
					SendEdit(val);
				}
				else
				{
					_own[val] = val.BoxedValue;
				}
				Apply(val, value);
			}
			else if (IsServer)
			{
				_changePending = true;
				if (Time.unscaledTime >= _nextChangeSend)
				{
					SendChange();
				}
			}
		}

		private void SendChange()
		{
			_changePending = false;
			_nextChangeSend = Time.unscaledTime + 0.5f;
			if (!IsServer)
			{
				return;
			}
			foreach (ZNetPeer peer in ZNet.instance.GetPeers())
			{
				if (peer?.m_rpc == null)
				{
					continue;
				}
				if (_directPeers.Contains(peer.m_rpc))
				{
					if (_entries.Count > 0)
					{
						peer.m_rpc.Invoke(_dSend, new object[1] { Values() });
					}
				}
				else
				{
					SendRouted(peer.m_uid);
				}
			}
		}

		private void SendEdit(ConfigEntryBase e)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			ZNet instance = ZNet.instance;
			ZNetPeer val = ((instance != null) ? instance.GetServerPeer() : null);
			if (val?.m_rpc != null)
			{
				ZPackage val2 = new ZPackage();
				val2.Write(e.Definition.Section);
				val2.Write(e.Definition.Key);
				val2.Write(TomlTypeConverter.ConvertToString(e.BoxedValue, e.SettingType));
				val.m_rpc.Invoke(_edit, new object[1] { val2 });
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogInfo((object)("Asked the server to set " + e.Definition.Section + "/" + e.Definition.Key));
				}
			}
		}

		private void OnEdit(ZRpc rpc, ZPackage pkg)
		{
			try
			{
				if (!IsServer)
				{
					return;
				}
				ISocket socket = rpc.GetSocket();
				string text = ((socket != null) ? socket.GetHostName() : null) ?? "";
				ZNetPeer val = ((IEnumerable<ZNetPeer>)ZNet.instance.GetPeers()).FirstOrDefault((Func<ZNetPeer, bool>)((ZNetPeer p) => p.m_rpc == rpc));
				string section = pkg.ReadString();
				string key = pkg.ReadString();
				string text2 = pkg.ReadString();
				if (!ZNet.instance.IsAdmin(text))
				{
					ManualLogSource log = _log;
					if (log != null)
					{
						log.LogWarning((object)((val?.m_playerName ?? text) + " tried to change " + section + "/" + key + " but isn't on the admin list"));
					}
					if (_entries.Count > 0)
					{
						rpc.Invoke(_dSend, new object[1] { Values() });
					}
					return;
				}
				ConfigEntryBase val2 = ((IEnumerable<ConfigEntryBase>)_entries).FirstOrDefault((Func<ConfigEntryBase, bool>)((ConfigEntryBase x) => x.Definition.Section == section && x.Definition.Key == key));
				if (val2 != null)
				{
					val2.BoxedValue = TomlTypeConverter.ConvertToValue(text2, val2.SettingType);
					ManualLogSource log2 = _log;
					if (log2 != null)
					{
						log2.LogInfo((object)("Admin " + (val?.m_playerName ?? text) + " set " + section + "/" + key + " = " + text2));
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log3 = _log;
				if (log3 != null)
				{
					log3.LogWarning((object)("Could not take an admin's change: " + ex.Message));
				}
			}
		}

		private void ShowReadOnly()
		{
			bool flag = FromServer && !CanEditServer;
			if (flag == _readOnlyShown)
			{
				return;
			}
			_readOnlyShown = flag;
			foreach (ConfigEntryBase entry in _entries)
			{
				ConfigDescription description = entry.Description;
				object[] array = ((description != null) ? description.Tags : null) ?? new object[0];
				foreach (object obj in array)
				{
					if (IsManagerAttributes(obj))
					{
						try
						{
							AccessTools.Field(obj.GetType(), "ReadOnly")?.SetValue(obj, flag ? ((object)true) : null);
						}
						catch (Exception)
						{
						}
					}
				}
			}
		}

		private static bool IsManagerAttributes(object tag)
		{
			if (tag != null)
			{
				return tag.GetType().Name == "ConfigurationManagerAttributes";
			}
			return false;
		}

		private string OwnText(SyncedText t)
		{
			try
			{
				return t.Own() ?? "";
			}
			catch (Exception ex)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogWarning((object)("Could not read " + t.Key + ": " + ex.Message));
				}
				return t.Given ?? "";
			}
		}

		private void Give(SyncedText t, string text)
		{
			if (t.Given != null && t.Given == text)
			{
				return;
			}
			t.Given = text;
			try
			{
				t.Use(text);
			}
			catch (Exception ex)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogWarning((object)("Could not use " + t.Key + ": " + ex));
				}
			}
		}

		private void RestoreTexts(bool give)
		{
			foreach (SyncedText text in _texts)
			{
				text.Incoming = null;
				if (!text.FromServer)
				{
					continue;
				}
				text.FromServer = false;
				if (give)
				{
					Give(text, OwnText(text));
					ManualLogSource log = _log;
					if (log != null)
					{
						log.LogInfo((object)("Your own " + text.Key + " applies again"));
					}
				}
			}
		}

		private void AskTexts(ZRpc server)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			if (_texts.Count == 0 || server == null)
			{
				return;
			}
			ZPackage val = new ZPackage();
			val.Write(_texts.Count);
			foreach (SyncedText text in _texts)
			{
				val.Write(text.Key);
			}
			server.Invoke(_dTextAsk, new object[1] { val });
		}

		private void OnTextAsk(ZRpc rpc, ZPackage pkg)
		{
			try
			{
				if (!IsServer)
				{
					return;
				}
				int num = pkg.ReadInt();
				HashSet<string> hashSet = new HashSet<string>();
				for (int i = 0; i < num && i < 1000; i++)
				{
					string key = pkg.ReadString();
					if (_texts.Any((SyncedText x) => x.Key == key))
					{
						hashSet.Add(key);
					}
				}
				if (_textPeers.TryGetValue(rpc, out var value))
				{
					hashSet.UnionWith(value);
				}
				foreach (ZRpc item in _textPeers.Keys.Where((ZRpc r) => !r.IsConnected()).ToList())
				{
					_textPeers.Remove(item);
				}
				_textPeers[rpc] = hashSet;
				foreach (SyncedText text in _texts)
				{
					if (hashSet.Contains(text.Key))
					{
						SendText(rpc, text);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogWarning((object)("Could not answer a player's ask for server data: " + ex.Message));
				}
			}
		}

		private void SendTexts()
		{
			_textPending = false;
			_nextTextSend = Time.unscaledTime + 0.5f;
			if (!IsServer)
			{
				return;
			}
			foreach (SyncedText text in _texts)
			{
				if (!text.Pending)
				{
					continue;
				}
				text.Pending = false;
				foreach (ZNetPeer peer in ZNet.instance.GetPeers())
				{
					if (peer?.m_rpc != null && _textPeers.TryGetValue(peer.m_rpc, out var value) && value.Contains(text.Key))
					{
						SendText(peer.m_rpc, text);
					}
				}
			}
		}

		private void SendText(ZRpc rpc, SyncedText t)
		{
			byte[] array = Packed(t);
			if (array != null)
			{
				_outbox.RemoveAll((Sending s) => s.Rpc == rpc && s.Key == t.Key);
				_outbox.Add(new Sending
				{
					Rpc = rpc,
					Key = t.Key,
					Data = array,
					Parts = Math.Max(1, (array.Length + 65536 - 1) / 65536)
				});
				Pump();
			}
		}

		private void Pump()
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			for (int num = _outbox.Count - 1; num >= 0; num--)
			{
				Sending sending = _outbox[num];
				try
				{
					while (sending.Next < sending.Parts && sending.Rpc.IsConnected() && sending.Rpc.GetSocket().GetSendQueueSize() < 10240)
					{
						int num2 = sending.Next * 65536;
						int num3 = Math.Min(65536, sending.Data.Length - num2);
						byte[] array = new byte[num3];
						Buffer.BlockCopy(sending.Data, num2, array, 0, num3);
						ZPackage val = new ZPackage();
						val.Write(sending.Key);
						val.Write(sending.Next);
						val.Write(sending.Parts);
						val.Write(array);
						sending.Rpc.Invoke(_dText, new object[1] { val });
						sending.Next++;
					}
					if (sending.Next >= sending.Parts || !sending.Rpc.IsConnected())
					{
						_outbox.RemoveAt(num);
					}
				}
				catch (Exception ex)
				{
					_outbox.RemoveAt(num);
					ManualLogSource log = _log;
					if (log != null)
					{
						log.LogWarning((object)("Could not send " + sending.Key + " to a player: " + ex.Message));
					}
				}
			}
		}

		private byte[] Packed(SyncedText t)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			if (t.Packed == null)
			{
				string text = OwnText(t);
				ZPackage val = new ZPackage();
				val.Write(text);
				ZPackage val2 = new ZPackage();
				bool flag = text.Length > 1024;
				val2.Write(flag);
				if (flag)
				{
					val2.WriteCompressed(val);
				}
				else
				{
					val2.Write(val);
				}
				t.Packed = val2.GetArray();
				t.TooBig = t.Packed.Length > 8388608;
				string arg = $"{t.Packed.Length / 1024} KB" + (flag ? $" gzipped ({text.Length / 1024} KB of text)" : "");
				if (t.TooBig)
				{
					ManualLogSource log = _log;
					if (log != null)
					{
						log.LogError((object)$"{t.Key} is too big to send to players ({arg}, at most {8} MB): they keep their own.");
					}
				}
				else if (t.Packed.Length > 262144)
				{
					ManualLogSource log2 = _log;
					if (log2 != null)
					{
						log2.LogWarning((object)$"{t.Key} is big to send to every player who joins ({arg}): it takes about {(float)t.Packed.Length / 153600f:0} s of their connection, and their world loads slower meanwhile.");
					}
				}
			}
			if (!t.TooBig)
			{
				return t.Packed;
			}
			return null;
		}

		private void OnText(ZRpc rpc, ZPackage pkg)
		{
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Expected O, but got Unknown
			if (!IsServerConnection(rpc))
			{
				return;
			}
			SyncedText syncedText = null;
			try
			{
				string key = pkg.ReadString();
				int num = pkg.ReadInt();
				int num2 = pkg.ReadInt();
				byte[] array = pkg.ReadByteArray();
				syncedText = _texts.FirstOrDefault((SyncedText x) => x.Key == key);
				if (syncedText == null)
				{
					return;
				}
				if (num2 < 1 || num2 > 129 || num < 0 || num >= num2)
				{
					throw new InvalidDataException($"part {num} of {num2}");
				}
				if (num == 0)
				{
					syncedText.Incoming = new MemoryStream();
					syncedText.NextPart = 0;
				}
				if (syncedText.Incoming == null || num != syncedText.NextPart)
				{
					throw new InvalidDataException($"part {num} came out of order");
				}
				syncedText.Incoming.Write(array, 0, array.Length);
				syncedText.NextPart = num + 1;
				if (num >= num2 - 1)
				{
					ZPackage val = new ZPackage(syncedText.Incoming.ToArray());
					syncedText.Incoming = null;
					ZPackage val2 = (val.ReadBool() ? val.ReadCompressedPackage() : val.ReadPackage());
					string text = val2.ReadString();
					syncedText.FromServer = true;
					Give(syncedText, text);
					ManualLogSource log = _log;
					if (log != null)
					{
						log.LogInfo((object)$"The server's {key} applies while you play here ({text.Length / 1024} KB)");
					}
				}
			}
			catch (Exception ex)
			{
				if (syncedText != null)
				{
					syncedText.Incoming = null;
				}
				ManualLogSource log2 = _log;
				if (log2 != null)
				{
					log2.LogWarning((object)("Could not read the server's data" + ((syncedText != null) ? (" for " + syncedText.Key) : "") + ": " + ex.Message));
				}
			}
		}

		private void SetServer(ServerMod state, string version, int protocol)
		{
			if (state != ServerMod.Checking)
			{
				_askedAt = -1f;
			}
			bool flag = state != Server || version != ServerVersion;
			Server = state;
			ServerVersion = version;
			_serverProtocol = protocol;
			if (!flag)
			{
				return;
			}
			Guard();
			try
			{
				this.ServerChanged?.Invoke();
			}
			catch (Exception ex)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogWarning((object)("ServerChanged: " + ex));
				}
			}
		}

		private void Guard()
		{
			bool flag = Server == ServerMod.NotConnected || Server == ServerMod.Installed;
			bool flag2 = false;
			foreach (GameObject guardedPiece in _guardedPieces)
			{
				Piece val = (((Object)(object)guardedPiece != (Object)null) ? guardedPiece.GetComponent<Piece>() : null);
				if ((Object)(object)val != (Object)null && val.m_enabled != flag)
				{
					val.m_enabled = flag;
					flag2 = true;
				}
			}
			foreach (Recipe guardedRecipe in _guardedRecipes)
			{
				if ((Object)(object)guardedRecipe != (Object)null && guardedRecipe.m_enabled != flag)
				{
					guardedRecipe.m_enabled = flag;
					flag2 = true;
				}
			}
			if (flag2 && (Object)(object)Player.m_localPlayer != (Object)null)
			{
				try
				{
					UpdateAvailablePieces?.Invoke(Player.m_localPlayer, null);
				}
				catch (Exception)
				{
				}
			}
		}

		private void WatchFile()
		{
			try
			{
				string configFilePath = _config.ConfigFilePath;
				_watcher = new FileSystemWatcher(Path.GetDirectoryName(configFilePath), Path.GetFileName(configFilePath))
				{
					NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite)
				};
				FileSystemEventHandler value = delegate
				{
					_fileTouched = true;
				};
				_watcher.Changed += value;
				_watcher.Created += value;
				_watcher.Renamed += delegate
				{
					_fileTouched = true;
				};
				_watcher.EnableRaisingEvents = true;
			}
			catch (Exception ex)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogWarning((object)("Edits to the config file apply after a restart (can't watch it: " + ex.Message + ")"));
				}
			}
		}

		private void ReloadFile()
		{
			string text = ReadFile(_config.ConfigFilePath);
			if (text == null)
			{
				if (File.Exists(_config.ConfigFilePath))
				{
					_reloadAt = Time.unscaledTime + 1f;
				}
			}
			else
			{
				if (text == _fileText)
				{
					return;
				}
				_fileText = text;
				bool saveOnConfigSet = _config.SaveOnConfigSet;
				_reloading = true;
				try
				{
					_config.SaveOnConfigSet = false;
					_config.Reload();
				}
				catch (Exception ex)
				{
					ManualLogSource log = _log;
					if (log != null)
					{
						log.LogWarning((object)("Could not read the edited config file (check the line you changed): " + ex.Message));
					}
				}
				finally
				{
					_config.SaveOnConfigSet = saveOnConfigSet;
					_reloading = false;
				}
			}
		}

		private void PatchSave()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_0045: 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_0067: Expected O, but got Unknown
			//IL_0067: Expected O, but got Unknown
			try
			{
				_saveHarmony = new Harmony(_send + ".save");
				_saveHarmony.Patch((MethodBase)AccessTools.Method(typeof(ConfigFile), "Save", (Type[])null, (Type[])null), new HarmonyMethod(typeof(ServerSettings), "BeforeSave", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(ServerSettings), "AfterSave", (Type[])null), (HarmonyMethod)null);
			}
			catch (Exception ex)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogWarning((object)("Could not keep the server's values out of your config file: " + ex.Message));
				}
			}
		}

		private static void UnpatchSave()
		{
			try
			{
				Harmony saveHarmony = _saveHarmony;
				if (saveHarmony != null)
				{
					saveHarmony.UnpatchSelf();
				}
			}
			catch (Exception)
			{
			}
			_saveHarmony = null;
		}

		private static void BeforeSave(ConfigFile __instance)
		{
			foreach (ServerSettings item in Live)
			{
				if (item._config != __instance)
				{
					continue;
				}
				foreach (KeyValuePair<ConfigEntryBase, object> item2 in item._own)
				{
					SetQuietly(item2.Key, item2.Value);
				}
			}
		}

		private static Exception AfterSave(ConfigFile __instance, Exception __exception)
		{
			foreach (ServerSettings item in Live)
			{
				if (item._config != __instance)
				{
					continue;
				}
				foreach (KeyValuePair<ConfigEntryBase, object> item2 in item._server)
				{
					SetQuietly(item2.Key, item2.Value);
				}
				item._fileText = ReadFile(__instance.ConfigFilePath);
			}
			return __exception;
		}

		private static string ReadFile(string path)
		{
			try
			{
				return File.Exists(path) ? File.ReadAllText(path) : null;
			}
			catch (Exception)
			{
				return null;
			}
		}

		private static void SetQuietly(ConfigEntryBase e, object value)
		{
			AccessTools.Field(((object)e).GetType(), "_typedValue")?.SetValue(e, value);
		}

		private static BepInPlugin PluginOf(string guid)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			Type[] array;
			try
			{
				array = typeof(ServerSettings).Assembly.GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				array = ex.Types.Where((Type t) => t != null).ToArray();
			}
			Type[] array2 = array;
			foreach (Type type in array2)
			{
				object[] customAttributes = type.GetCustomAttributes(typeof(BepInPlugin), inherit: false);
				for (int num2 = 0; num2 < customAttributes.Length; num2++)
				{
					BepInPlugin val = (BepInPlugin)customAttributes[num2];
					if (val.GUID == guid || guid.StartsWith(val.GUID + "."))
					{
						return val;
					}
				}
			}
			return null;
		}

		private void Unsubscribe(ConfigEntryBase e)
		{
			((object)e).GetType().GetEvent("SettingChanged")?.RemoveEventHandler(e, new EventHandler(OnChanged));
		}
	}
}
namespace Cogling
{
	internal sealed class Antenna : MonoBehaviour, Hoverable, Interactable
	{
		internal const string Name = "cogling_antenna";

		private float _nextRing;

		private static readonly List<Antenna> All = new List<Antenna>();

		private ZNetView _view;

		private GameObject _marker;

		private float _nextRebuildCheck;

		private static readonly int GhostLayer = LayerMask.NameToLayer("ghost");

		internal static GameObject Prefab;

		private static GameObject _holder;

		private static PieceTable _table;

		private const float DishFrom = 1.16f;

		private const float CutAt = 1.06f;

		private const float PostWidth = 0.3f;

		private static Mesh _post;

		private static Mesh _dish;

		private static Vector3 _pivot;

		private static Material _bulbMaterial;

		private static Vector3? _lampCentre;

		private static Mesh _cylinder;

		internal static float Radius => Plugin.AntennaRadius.Value;

		public string GetHoverName()
		{
			return Localization.instance.Localize("$cogling_antenna");
		}

		public float GetHoverOffset()
		{
			return 0f;
		}

		public string GetHoverText()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			List<Antenna> network = NetworkAt(((Component)this).transform.position);
			if (network.Count == 0)
			{
				network = new List<Antenna> { this };
			}
			int num = CoglingsIn(network);
			int num2 = network.Count * Plugin.CoglingsPerAntenna.Value;
			List<string> list = Character.GetAllCharacters().Where(delegate(Character c)
			{
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				if (CoglingStance.IsCogling(c) && !c.IsDead())
				{
					ZNetView component = ((Component)c).GetComponent<ZNetView>();
					if (((component != null) ? component.GetZDO() : null) != null)
					{
						return InArea(network, ((Component)c).transform.position);
					}
				}
				return false;
			}).Select(CoglingTag.NameOf)
				.ToList();
			long now = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTime().Ticks : 0);
			List<float> list2 = (from r in network.SelectMany((Antenna a) => Rebuilds.Pending(a))
				select Mathf.Max(0f, (float)new TimeSpan(r.due - now).TotalMinutes) into m
				orderby m
				select m).ToList();
			List<string> list3 = new List<string>();
			list3.Add(Translations.T((network.Count > 1) ? "cogling_antenna_powers_linked" : "cogling_antenna_powers", num, num2, network.Count));
			List<string> list4 = list3;
			if (list.Count > 0)
			{
				list4.Add(string.Join(", ", list));
			}
			foreach (float item in list2)
			{
				list4.Add(Translations.T("cogling_antenna_rebuilding", Mathf.CeilToInt(item)));
			}
			list4.Add(Translations.T("cogling_antenna_range", Radius.ToString("0")));
			return GetHoverName() + "\n<color=#bdb7a9>" + string.Join("\n", list4) + "</color>" + Localization.instance.Localize("\n[<color=yellow><b>$KEY_Use</b></color>] $cogling_antenna_bell");
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: 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)
			if (hold || alt || Time.time < _nextRing || (Object)(object)_view == (Object)null || !_view.IsValid() || !(user is Player))
			{
				return false;
			}
			_nextRing = Time.time + 3f;
			List<Antenna> network = NetworkAt(((Component)this).transform.position);
			if (network.Count == 0)
			{
				network = new List<Antenna> { this };
			}
			List<Character> list = (from c in Character.GetAllCharacters().Where(delegate(Character c)
				{
					//IL_0030: Unknown result type (might be due to invalid IL or missing references)
					if (CoglingStance.IsCogling(c) && !c.IsDead())
					{
						ZNetView component = ((Component)c).GetComponent<ZNetView>();
						if (((component != null) ? component.GetZDO() : null) != null)
						{
							return InArea(network, ((Component)c).transform.position);
						}
					}
					return false;
				})
				orderby Vector3.SignedAngle(((Component)user).transform.position - ((Component)this).transform.position, ((Component)c).transform.position - ((Component)this).transform.position, Vector3.up)
				select c).ToList();
			for (int num = 0; num < list.Count; num++)
			{
				((Component)list[num]).GetComponent<ZNetView>().InvokeRPC("cogling_called", new object[3]
				{
					((Component)this).transform.position,
					((Component)user).transform.position,
					num * 100 + Mathf.Min(99, list.Count)
				});
			}
			return true;
		}

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

		private void Awake()
		{
			_view = ((Component)this).GetComponent<ZNetView>();
			Transform obj = ((Component)this).transform.Find("AreaMarker");
			_marker = ((obj != null) ? ((Component)obj).gameObject : null);
			if ((Object)(object)_marker != (Object)null)
			{
				CircleProjector component = _marker.GetComponent<CircleProjector>();
				if (component != null)
				{
					component.m_radius = Radius;
				}
			}
			if ((Object)(object)_view != (Object)null && _view.GetZDO() != null)
			{
				All.Add(this);
				_view.Unregister("cogling_rebuild_add");
				_view.Register<long, long>("cogling_rebuild_add", (Action<long, long, long>)delegate(long sender, long due, long creator)
				{
					Rebuilds.RPC_Add(this, due, creator);
				});
			}
			Shape(((Component)this).gameObject);
			if (!((Component)this).GetComponents<MonoBehaviour>().Any((MonoBehaviour m) => (Object)(object)m != (Object)null && ((object)m).GetType().Name == "AntennaLife"))
			{
				((Component)this).gameObject.AddComponent<AntennaLife>();
			}
		}

		private void OnDestroy()
		{
			All.Remove(this);
			if ((Object)(object)_view != (Object)null && _view.IsValid())
			{
				_view.Unregister("cogling_rebuild_add");
			}
		}

		internal static void ApplySize()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			Vector3 localScale = Vector3.one * Plugin.AntennaSize.Value;
			if ((Object)(object)Prefab != (Object)null)
			{
				Prefab.transform.localScale = localScale;
			}
			foreach (Antenna item in All)
			{
				if ((Object)(object)item != (Object)null)
				{
					((Component)item).transform.localScale = localScale;
				}
			}
		}

		private void Update()
		{
			if (Time.time > _nextRebuildCheck)
			{
				_nextRebuildCheck = Time.time + 5f;
				Rebuilds.Tick(this);
			}
			bool flag = (((Object)(object)_view != (Object)null && _view.GetZDO() != null) || ((Component)this).gameObject.layer == GhostLayer) && ShowAreas();
			if (!((Object)(object)_marker != (Object)null) || _marker.activeSelf == flag)
			{
				return;
			}
			_marker.SetActive(flag);
			if (flag)
			{
				CircleProjector component = _marker.GetComponent<CircleProjector>();
				if (component != null)
				{
					component.m_radius = Radius;
				}
			}
		}

		private static bool ShowAreas()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || !((Character)localPlayer).InPlaceMode())
			{
				return false;
			}
			Piece selectedPiece = localPlayer.GetSelectedPiece();
			if ((Object)(object)selectedPiece == (Object)null)
			{
				return false;
			}
			string name = ((Object)((Component)selectedPiece).gameObject).name;
			if (!(name == "cogling_antenna"))
			{
				return name == "cogling";
			}
			return true;
		}

		internal static Antenna Nearest(Vector3 at, float within)
		{
			//IL_0007: 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)
			return (from a in All
				where (Object)(object)a != (Object)null && Vector3.Distance(((Component)a).transform.position, at) <= within
				orderby Vector3.Distance(((Component)a).transform.position, at)
				select a).FirstOrDefault();
		}

		internal static bool Covers(Vector3 at)
		{
			//IL_0007: 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)
			return All.Any((Antenna a) => (Object)(object)a != (Object)null && Utils.DistanceXZ(((Component)a).transform.position, at) <= Radius);
		}

		internal static List<Antenna> NetworkAt(Vector3 at)
		{
			//IL_0007: 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_005e: 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)
			List<Antenna> list = All.Where((Antenna a) => (Object)(object)a != (Object)null && Utils.DistanceXZ(((Component)a).transform.position, at) <= Radius).ToList();
			for (int num = 0; num < list.Count; num++)
			{
				foreach (Antenna item in All)
				{
					if ((Object)(object)item != (Object)null && !list.Contains(item) && Utils.DistanceXZ(((Component)item).transform.position, ((Component)list[num]).transform.position) <= 2f * Radius)
					{
						list.Add(item);
					}
				}
			}
			return list;
		}

		internal static int CoglingsIn(List<Antenna> network)
		{
			return Character.GetAllCharacters().Count(delegate(Character c)
			{
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				if (CoglingStance.IsCogling(c) && !c.IsDead())
				{
					ZNetView component = ((Component)c).GetComponent<ZNetView>();
					if (((component != null) ? component.GetZDO() : null) != null)
					{
						return InArea(network, ((Component)c).transform.position);
					}
				}
				return false;
			}) + network.Sum((Antenna a) => ((Object)(object)a != (Object)null) ? Rebuilds.Pending(a).Count : 0);
		}

		internal static bool InArea(List<Antenna> network, Vector3 at)
		{
			//IL_0007: 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)
			return network.Any((Antenna a) => (Object)(object)a != (Object)null && Utils.DistanceXZ(((Component)a).transform.position, at) <= Radius);
		}

		internal static void Register(ZNetScene scene)
		{
			if ((Object)(object)scene == (Object)null)
			{
				return;
			}
			if ((Object)(object)Prefab == (Object)null)
			{
				Prefab = Build(scene);
			}
			if (!((Object)(object)Prefab == (Object)null))
			{
				GameObject prefab = scene.GetPrefab("Hammer");
				PieceTable val = ((!((Object)(object)prefab != (Object)null)) ? null : prefab.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_buildPieces);
				if ((Object)(object)val != (Object)null)
				{
					_table = val;
				}
				PieceReload.ReplacePrefab(scene, Prefab, ((Object)(object)val != (Object)null) ? val : _table);
				int num = PieceReload.Reattach(scene, Prefab);
				if (num > 0)
				{
					Plugin.Log.LogInfo((object)$"Gave {num} standing antenna(s) this copy's code");
				}
				ApplyCost();
				if (Prefab.GetComponent<Piece>().m_resources.Length == 0 && (Object)(object)_table != (Object)null)
				{
					_table.m_pieces.Remove(Prefab);
					Plugin.Log.LogWarning((object)"The Cogling antenna has no cost (see its Cost setting): it isn't in the build menu");
				}
				Plugin.Synced.NeedsServer(Prefab);
			}
		}

		internal static void ApplyCost()
		{
			Piece val = (((Object)(object)Prefab != (Object)null) ? Prefab.GetComponent<Piece>() : null);
			if (!((Object)(object)val == (Object)null))
			{
				Costs.Apply(val, Plugin.AntennaCost.Value, Plugin.Log);
				Costs.ApplyStation(val, Plugin.AntennaStation.Value, Plugin.Log);
			}
		}

		internal static void Unregister()
		{
			PieceReload.UnloadPiece(Prefab, _table);
			_holder = (Prefab = null);
			_table = null;
			All.Clear();
			_post = (_dish = null);
		}

		private static GameObject Build(ZNetScene scene)
		{
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: 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_009c: Expected O, but got Unknown
			//IL_0163: 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)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = scene.GetPrefab("dverger_demister");
			GameObject prefab2 = scene.GetPrefab("piece_dvergr_lantern_pole");
			Piece val = ((prefab2 != null) ? prefab2.GetComponent<Piece>() : null);
			GameObject prefab3 = scene.GetPrefab("wood_beam");
			object obj;
			if (prefab3 == null)
			{
				obj = null;
			}
			else
			{
				Transform obj2 = prefab3.transform.Find("new");
				if (obj2 == null)
				{
					obj = null;
				}
				else
				{
					MeshRenderer component = ((Component)obj2).GetComponent<MeshRenderer>();
					obj = ((component != null) ? ((Renderer)component).sharedMaterial : null);
				}
			}
			Material val2 = (Material)obj;
			GameObject prefab4 = scene.GetPrefab("guard_stone");
			if ((Object)(object)prefab == (Object)null || (Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"The game has no Dvergr wisp light or lantern post to copy: no Cogling antenna this session");
				return null;
			}
			_holder = new GameObject("cogling_prefabs_antenna");
			_holder.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)_holder);
			GameObject val3 = Object.Instantiate<GameObject>(prefab, _holder.transform);
			((Object)val3).name = "cogling_antenna";
			val3.layer = ((Component)val).gameObject.layer;
			ZNetView component2 = val3.GetComponent<ZNetView>();
			if (component2 != null)
			{
				component2.m_persistent = true;
			}
			Piece val4 = val3.GetComponent<Piece>() ?? val3.AddComponent<Piece>();
			FieldInfo[] fields = typeof(Piece).GetFields(BindingFlags.Instance | BindingFlags.Public);
			foreach (FieldInfo fieldInfo in fields)
			{
				fieldInfo.SetValue(val4, fieldInfo.GetValue(val));
			}
			val4.m_name = "$cogling_antenna";
			val4.m_description = "$cogling_antenna_desc";
			val4.m_category = (PieceCategory)0;
			val4.m_usage = (UsageTagFlags)1;
			val4.m_icon = val.m_icon;
			val4.m_resources = (Requirement[])(object)new Requirement[0];
			try
			{
				Renderer[] componentsInChildren = val3.GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val5 in componentsInChildren)
				{
					Material[] sharedMaterials = val5.sharedMaterials;
					for (int k = 0; k < sharedMaterials.Length; k++)
					{
						if ((Object)(object)sharedMaterials[k] != (Object)null && ((Object)sharedMaterials[k]).name.StartsWith("torch") && (Object)(object)val2 != (Object)null)
						{
							sharedMaterials[k] = val2;
						}
					}
					val5.sharedMaterials = sharedMaterials;
				}
				Shape(val3);
				Transform val6 = (((Object)(object)prefab4 != (Object)null) ? prefab4.transform.Find("AreaMarker") : null);
				if ((Object)(object)val6 != (Object)null)
				{
					GameObject val7 = Object.Instantiate<GameObject>(((Component)val6).gameObject, val3.transform);
					((Object)val7).name = "AreaMarker";
					val7.transform.localPosition = Vector3.zero;
					val7.SetActive(false);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Cogling antenna look: " + ex.Message));
			}
			val3.transform.localScale = Vector3.one * Plugin.AntennaSize.Value;
			val3.AddComponent<Antenna>();
			try
			{
				val4.m_icon = Icon.Make(val3, null, null, null) ?? val4.m_icon;
			}
			catch (Exception ex2)
			{
				Plugin.Log.LogWarning((object)("Cogling antenna icon: " + ex2.Message));
			}
			return val3;
		}

		private static void Shape(GameObject antenna)
		{
			//IL_0027: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: 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_01bf: 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_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			Transform val = antenna.transform.Find("_enabled");
			if ((Object)(object)val != (Object)null)
			{
				((Component)val).gameObject.SetActive(false);
				Scene scene = antenna.scene;
				if (((Scene)(ref scene)).IsValid())
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
				else
				{
					Object.DestroyImmediate((Object)(object)((Component)val).gameObject, true);
				}
			}
			Transform val2 = antenna.transform.Find("New");
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			Transform val3 = val2.Find("cogling_turn");
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = new GameObject("cogling_turn")
				{
					layer = ((Component)val2).gameObject.layer
				}.transform;
				val3.SetParent(val2, false);
			}
			string[] array = new string[2] { "cogling_dish", "cogling_hinge" };
			foreach (string text in array)
			{
				Transform val4 = val2.Find(text);
				if (val4 != null)
				{
					val4.SetParent(val3, false);
				}
			}
			Transform val5 = val3.Find("cogling_dish");
			if ((Object)(object)val5 == (Object)null)
			{
				MeshFilter component = ((Component)val2).GetComponent<MeshFilter>();
				if ((Object)(object)component == (Object)null || (Object)(object)component.sharedMesh == (Object)null || !Split(component.sharedMesh, val2.localScale))
				{
					return;
				}
				BoxCollider component2 = ((Component)val2).GetComponent<BoxCollider>();
				if (component2 != null)
				{
					component2.center = Vector3.Scale(component2.center, val2.localScale);
					component2.size = Vector3.Scale(component2.size, val2.localScale);
				}
				val2.localScale = Vector3.one;
				component.sharedMesh = _post;
				val5 = new GameObject("cogling_dish")
				{
					layer = ((Component)val2).gameObject.layer
				}.transform;
				val5.SetParent(val3, false);
				val5.localPosition = _pivot;
				((Component)val5).gameObject.AddComponent<MeshFilter>().sharedMesh = _dish;
				((Renderer)((Component)val5).gameObject.AddComponent<MeshRenderer>()).sharedMaterials = ((Renderer)((Component)val2).GetComponent<MeshRenderer>()).sharedMaterials;
			}
			else if ((Object)(object)_post != (Object)null && (Object)(object)_dish != (Object)null)
			{
				MeshFilter component3 = ((Component)val2).GetComponent<MeshFilter>();
				if (component3 != null)
				{
					component3.sharedMesh = _post;
				}
				MeshFilter component4 = ((Component)val5).GetComponent<MeshFilter>();
				if (component4 != null)
				{
					component4.sharedMesh = _dish;
				}
			}
			BoxCollider component5 = ((Component)val2).GetComponent<BoxCollider>();
			if (component5 != null)
			{
				component5.size = new Vector3(0.3f, component5.size.y, 0.3f);
			}
			val5.localRotation = Quaternion.Euler(Plugin.DishTilt.Value, 0f, 0f);
			Transform val6 = val3.Find("cogling_hinge");
			if ((Object)(object)val6 != (Object)null && val6.childCount != 4)
			{
				((Component)val6).gameObject.SetActive(false);
				Object.Destroy((Object)(object)((Component)val6).gameObject);
				val6 = null;
			}
			if ((Object)(object)val6 == (Object)null)
			{
				Hinge(val3, ((Renderer)((Component)val2).GetComponent<MeshRenderer>()).sharedMaterials);
			}
			Transform val7 = val5.Find("cogling_lamp");
			if (val7 != null)
			{
				val7.localPosition = LampAt(val5);
				Transform val8 = val7.Find("bulb");
				if (val8 != null)
				{
					CentreBulb(val8);
				}
			}
			else
			{
				Lamp(val5);
			}
			antenna.GetComponent<AntennaLife>()?.Find();
		}

		private static void Lamp(Transform dish)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: 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_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Expected O, but got Unknown
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Expected O, but got Unknown
			ZNetScene instance = ZNetScene.instance;
			GameObject val = ((instance != null) ? instance.GetPrefab("dverger_demister") : null);
			Transform val2 = (((Object)(object)val != (Object)null) ? val.transform.Find("New") : null);
			Transform val3 = (((Object)(object)val != (Object)null) ? val.transform.Find("_enabled/demister_ball (1)") : null);
			if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val3 == (Object)null))
			{
				GameObject val4 = new GameObject("cogling_lamp")
				{
					layer = ((Component)dish).gameObject.layer
				};
				val4.transform.SetParent(dish, false);
				val4.transform.localPosition = LampAt(dish);
				val4.transform.localScale = Vector3.one * Plugin.AntennaLightSize.Value;
				Light val5 = val4.AddComponent<Light>();
				val5.type = (LightType)2;
				val5.shadows = (LightShadows)0;
				val5.range = Plugin.AntennaLightRange.Value;
				val5.intensity = Plugin.AntennaLightBrightness.Value;
				val5.color = Plugin.EyeColor.Value;
				GameObject val6 = new GameObject("bulb")
				{
					layer = ((Component)dish).gameObject.layer
				};
				val6.transform.SetParent(val4.transform, false);
				val6.transform.localScale = val3.lossyScale;
				val6.AddComponent<MeshFilter>().sharedMesh = ((Component)val3).GetComponent<MeshFilter>().sharedMesh;
				CentreBulb(val6.transform);
				MeshRenderer val7 = val6.AddComponent<MeshRenderer>();
				if ((Object)(object)_bulbMaterial == (Object)null)
				{
					_bulbMaterial = new Material(((Renderer)((Component)val3).GetComponent<MeshRenderer>()).sharedMaterial)
					{
						name = "cogling_bulb"
					};
					_bulbMaterial.EnableKeyword("_EMISSION");
				}
				((Renderer)val7).sharedMaterial = _bulbMaterial;
				((Renderer)val7).shadowCastingMode = (ShadowCastingMode)0;
			}
		}

		private static Vector3 LampAt(Transform dish)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (!_lampCentre.HasValue)
			{
				MeshFilter component = ((Component)dish).GetComponent<MeshFilter>();
				_lampCentre = BowlCentre((component != null) ? component.sharedMesh : null);
			}
			return _lampCentre.Value + new Vector3(Plugin.AntennaLightSide.Value, Plugin.AntennaLightHeight.Value, Plugin.AntennaLightForward.Value);
		}

		private static void CentreBulb(Transform bulb)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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)
			MeshFilter component = ((Component)bulb).GetComponent<MeshFilter>();
			Mesh val = ((component != null) ? component.sharedMesh : null);
			if (!((Object)(object)val == (Object)null))
			{
				Bounds bounds = val.bounds;
				bulb.localPosition = -Vector3.Scale(((Bounds)(ref bounds)).center, bulb.localScale);
			}
		}

		private static Vector3 BowlCentre(Mesh bowl)
		{
			//IL_0017: 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)
			if ((Object)(object)bowl == (Object)null || !bowl.isReadable)
			{
				return Vector3.zero;
			}
			Vector3[] vertices = bowl.vertices;
			float top = vertices.Max((Vector3 p) => p.y);
			float bottom = vertices.Min((Vector3 p) => p.y);
			List<Vector3> source = vertices.Where((Vector3 p) => p.y > top - (top - bottom) * 0.1f).ToList();
			float x = source.Average((Vector3 p) => p.x);
			float z = source.Average((Vector3 p) => p.z);
			float width = source.Max((Vector3 p) => Mathf.Sqrt((p.x - x) * (p.x - x) + (p.z - z) * (p.z - z)));
			x = 0.005f;
			z = 0.025f;
			List<Vector3> list = vertices.Where((Vector3 p) => Mathf.Sqrt((p.x - x) * (p.x - x) + (p.z - z) * (p.z - z)) < width * 0.15f).ToList();
			float num = ((list.Count > 0) ? list.Max((Vector3 p) => p.y) : ((top + bottom) / 2f));
			float num2 = 0.03f;
			Vector3 result = default(Vector3);
			((Vector3)(ref result))..ctor(x, num + num2, z);
			return result;
		}

		internal static void ApplyLamp()
		{
			foreach (Transform item in from t in (from a in All
					where (Object)(object)a != (Object)null
					select ((Component)a).transform).Concat((IEnumerable<Transform>)(object)((!((Object)(object)Prefab != (Object)null)) ? new Transform[0] : new Transform[1] { Prefab.transform }))
				select t.Find("New/cogling_turn/cogling_dish") into d
				where (Object)(object)d != (Object)null
				select d)
			{
				Transform val = item.Find("cogling_lamp");
				if (!((Object)(object)val == (Object)null))
				{
					((Component)val).gameObject.SetActive(false);
					Object.Destroy((Object)(object)((Component)val).gameObject);
					((Object)val).name = "cogling_lamp_old";
					Lamp(item);
					((Component)item).GetComponentInParent<AntennaLife>()?.Find();
				}
			}
		}

		private static void Hinge(Transform stand, Material[] wood)
		{
			//IL_0041: 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_00a1: 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_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: 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_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_cylinder == (Object)null)
			{
				GameObject val = GameObject.CreatePrimitive((PrimitiveType)2);
				_cylinder = val.GetComponent<MeshFilter>().sharedMesh;
				Object.DestroyImmediate((Object)(object)val);
			}
			Transform hinge = new GameObject("cogling_hinge")
			{
				layer = ((Component)stand).gameObject.layer
			}.transform;
			hinge.SetParent(stand, false);
			float num = 0.49f;
			float y = _pivot.y;
			Part("neck", new Vector3(0f, (num + y) / 2f, 0f), new Vector3(0.13f, y - num + 0.05f, 0.13f), Quaternion.identity);
			Part("pin", new Vector3(0f, y, 0f), new Vector3(0.08f, 0.34f, 0.08f), Quaternion.Euler(0f, 0f, 90f));
			Part("knob_l", new Vector3(-0.17f, y, 0f), new Vector3(0.11f, 0.04f, 0.11f), Quaternion.Euler(0f, 0f, 90f));
			Part("knob_r", new Vector3(0.17f, y, 0f), new Vector3(0.11f, 0.04f, 0.11f), Quaternion.Euler(0f, 0f, 90f));
			void Part(string name, Vector3 at, Vector3 size, Quaternion turn)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Expected O, but got Unknown
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_004f: 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_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)
				GameObject val2 = new GameObject(name)
				{
					layer = ((Component)stand).gameObject.layer
				};
				val2.transform.SetParent(hinge, false);
				val2.transform.localPosition = at;
				val2.transform.localRotation = turn;
				val2.transform.localScale = new Vector3(size.x, size.y / 2f, size.z);
				val2.AddComponent<MeshFilter>().sharedMesh = _cylinder;
				((Renderer)val2.AddComponent<MeshRenderer>()).sharedMaterials = wood;
			}
		}

		private static bool Split(Mesh source, Vector3 scale)
		{
			//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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_post != (Object)null)
			{
				return true;
			}
			if (!source.isReadable)
			{
				Plugin.Log.LogWarning((object)"The wisp light's mesh can't be read: its dish stays upright");
				return false;
			}
			Vector3[] v = source.vertices;
			Vector3[] n = source.normals;
			Vector2[] uv = source.uv;
			int[] triangles = source.triangles;
			_pivot = Vector3.Scale(new Vector3(0f, 1.16f, 0f), scale);
			List<int> list = new List<int>();
			List<int> list2 = new List<int>();
			int num = 0;
			for (int i = 0; i < triangles.Length; i += 3)
			{
				float num2 = (v[triangles[i]].y + v[triangles[i + 1]].y + v[triangles[i + 2]].y) / 3f;
				if (num2 > 1.06f && num2 <= 1.16f)
				{
					num++;
				}
				((num2 > 1.06f) ? list2 : list).AddRange(new int[3]
				{
					triangles[i],
					triangles[i + 1],
					triangles[i + 2]
				});
			}
			Plugin.Log.LogInfo((object)$"Antenna: {num} triangle(s) of the dish's hub now turn with the dish (they stayed on the post before)");
			_post = Part(list, Vector3.zero, "cogling_antenna_post");
			_dish = Part(list2, _pivot, "cogling_antenna_dish");
			return true;
			Mesh Part(List<int> part, Vector3 origin, string name)
			{
				//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_0072: Unknown result type (might be due to invalid IL or missing references)
				//IL_0077: Unknown result type (might be due to invalid IL or missing references)
				//IL_0078: Unknown result type (might be due to invalid IL or missing references)
				//IL_0143: 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_0151: Expected O, but got Unknown
				//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
				//IL_011d: Unknown result type (might be due to invalid IL or missing references)
				Dictionary<int, int> map = new Dictionary<int, int>();
				List<Vector3> list3 = new List<Vector3>();
				List<Vector3> list4 = new List<Vector3>();
				List<Vector2> list5 = new List<Vector2>();
				foreach (int item in part)
				{
					if (!map.ContainsKey(item))
					{
						map[item] = list3.Count;
						list3.Add(Vector3.Scale(v[item], scale) - origin);
						if (n.Length == v.Length)
						{
							Vector3 val = new Vector3(n[item].x / scale.x, n[item].y / scale.y, n[item].z / scale.z);
							list4.Add(((Vector3)(ref val)).normalized);
						}
						if (uv.Length == v.Length)
						{
							list5.Add(uv[item]);
						}
					}
				}
				Mesh val2 = new Mesh
				{
					name = name
				};
				val2.SetVertices(list3);
				if (list4.Count == list3.Count)
				{
					val2.SetNormals(list4);
				}
				if (list5.Count == list3.Count)
				{
					val2.SetUVs(0, list5);
				}
				val2.SetTriangles(part.Select((int key) => map[key]).ToList(), 0);
				if (list4.Count != list3.Count)
				{
					val2.RecalculateNormals();
				}
				val2.RecalculateBounds();
				((Object)val2).hideFlags = (HideFlags)32;
				return val2;
			}
		}

		internal static void ApplyTilt()
		{
			if ((Object)(object)Prefab != (Object)null)
			{
				Shape(Prefab);
			}
			foreach (Antenna item in All)
			{
				if ((Object)(object)item != (Object)null)
				{
					Shape(((Component)item).gameObject);
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class AntennaRule
	{
		private static readonly FieldRef<Player, GameObject> Ghost = AccessTools.FieldRefAccess<Player, GameObject>("m_placementGhost");

		private static readonly FieldRef<Player, PlacementStatus> Status = AccessTools.FieldRefAccess<Player, PlacementStatus>("m_placementStatus");

		private static string Problem(Player player, out GameObject ghost)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			ghost = Ghost.Invoke(player);
			if ((Object)(object)ghost == (Object)null || !ghost.activeSelf || Utils.GetPrefabName(ghost) != "cogling")
			{
				return null;
			}
			List<Antenna> list = Antenna.NetworkAt(ghost.transform.position);
			if (list.Count == 0)
			{
				return "$cogling_needs_antenna";
			}
			int num = Antenna.CoglingsIn(list);
			int num2 = list.Count * Plugin.CoglingsPerAntenna.Value;
			if (num < num2)
			{
				return null;
			}
			return Translations.T("cogling_network_full", num, num2);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
		private static void Ghost_Postfix(Player __instance)
		{
			if ((int)Status.Invoke(__instance) == 0 && Problem(__instance, out var ghost) != null)
			{
				Status.Invoke(__instance) = (PlacementStatus)1;
				Piece component = ghost.GetComponent<Piece>();
				if (component != null)
				{
					component.SetInvalidPlacementHeightlight(true);
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Player), "TryPlacePiece")]
		private static bool TryPlace_Prefix(Player __instance, Piece piece, ref bool __result)
		{
			if ((Object)(object)piece == (Object)null || ((Object)((Component)piece).gameObject).name != "cogling")
			{
				return true;
			}
			GameObject ghost;
			string text = Problem(__instance, out ghost);
			if (text == null)
			{
				return true;
			}
			((Character)__instance).Message((MessageType)2, text, 0, (Sprite)null, false);
			__result = false;
			return false;
		}
	}
	internal sealed class AntennaLife : MonoBehaviour
	{
		private ZNetView _view;

		private Transform _turn;

		private Transform _dish;

		private Light _light;

		private Renderer _bulb;

		private MaterialPropertyBlock _block;

		private AudioSource _sound;

		private long _soundSlot = long.MinValue;

		private float _level = 1f;

		private float _nextLook;

		private Color _colour;

		private bool _near;

		private static AudioClip[] _creaks;

		private static AudioMixerGroup _mixer;

		private float _nextTwitch;

		private float _twitchYaw;

		private float _twitchTip;

		private float _toYaw;

		private float _toTip;

		private float _target = 1f;

		private void Start()
		{
			//IL_003b: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Invalid comparison between Unknown and I4
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			_view = ((Component)this).GetComponent<ZNetView>();
			if ((Object)(object)_view == (Object)null || _view.GetZDO() == null)
			{
				((Behaviour)this).enabled = false;
				return;
			}
			Find();
			_colour = Plugin.EyeColor.Value;
			if ((int)SystemInfo.graphicsDeviceType != 4)
			{
				Creaks();
				GameObject val = new GameObject("cogling_antenna_sound");
				val.transform.SetParent(((Object)(object)_dish != (Object)null) ? _dish : ((Component)this).transform, false);
				_sound = val.AddComponent<AudioSource>();
				_sound.outputAudioMixerGroup = _mixer;
				_sound.spatialBlend = 1f;
				_sound.rolloffMode = (AudioRolloffMode)1;
				_sound.minDistance = 1.5f;
				_sound.maxDistance = 18f;
				_sound.playOnAwake = false;
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)_sound != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_sound).gameObject);
			}
		}

		internal void Find()
		{
			_turn = ((Component)this).transform.Find("New/cogling_turn");
			_dish = (((Object)(object)_turn != (Object)null) ? _turn.Find("cogling_dish") : null);
			Transform val = (((Object)(object)_dish != (Object)null) ? _dish.Find("cogling_lamp") : null);
			_light = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<Light>() : null);
			_bulb = (Renderer)(object)(((Object)(object)val != (Object)null) ? ((Component)val).GetComponentInChildren<MeshRenderer>(true) : null);
		}

		private static void Creaks()
		{
			if (_creaks != null)
			{
				return;
			}
			_creaks = (AudioClip[])(object)new AudioClip[0];
			string[] array = new string[2] { "ashwood_door", "wood_door" };
			foreach (string text in array)
			{
				ZNetScene instance = ZNetScene.instance;
				object obj;
				if (instance == null)
				{
					obj = null;
				}
				else
				{
					GameObject prefab = instance.GetPrefab(text);
					obj = ((prefab != null) ? prefab.GetComponent<Door>() : null);
				}
				Door val = (Door)obj;
				if (val?.m_openEffects?.m_effectPrefabs == null)
				{
					continue;
				}
				EffectData[] effectPrefabs = val.m_openEffects.m_effectPrefabs;
				foreach (EffectData val2 in effectPrefabs)
				{
					ZSFX val3 = (((Object)(object)val2?.m_prefab != (Object)null) ? val2.m_prefab.GetComponent<ZSFX>() : null);
					if (!((Object)(object)val3 == (Object)null) && val3.m_audioClips != null && val3.m_audioClips.Length != 0)
					{
						_creaks = val3.m_audioClips;
						AudioSource component = ((Component)val3).GetComponent<AudioSource>();
						_mixer = ((component != null) ? component.outputAudioMixerGroup : null);
						return;
					}
				}
			}
			Plugin.Log.LogWarning((object)"No door sound to borrow: the antenna moves quietly");
		}

		private void Update()
		{
			if ((Object)(object)_turn == (Object)null || (Object)(object)_dish == (Object)null)
			{
				Find();
				if ((Object)(object)_turn == (Object)null || (Object)(object)_dish == (Object)null)
				{
					return;
				}
			}
			Move();
			Twitch();
			Lamp();
		}

		private void Slot(long k, float every, out double start, out float yaw, out float tip)
		{
			//IL_000b: 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)
			ZDOID uid = _view.GetZDO().m_uid;
			Random random = new Random((int)(((long)((ZDOID)(ref uid)).ID * 73856093L) ^ (((ZDOID)(ref uid)).UserID * 83492791) ^ (k * 19349663)));
			start = (double)k * (double)every + random.NextDouble() * (double)every * 0.6;
			float value = Plugin.AntennaTurn.Value;
			yaw = (float)(random.NextDouble() * 2.0 - 1.0) * value;
			tip = (float)(random.NextDouble() * 2.0 - 1.0) * Plugin.AntennaTip.Value;
		}

		private float MoveSeconds()
		{
			float num = Mathf.Max(0.3f, Plugin.AntennaSoundPitch.Value);
			float num2 = ((_creaks != null && _creaks.Length != 0) ? (_creaks[0].length / num) : 0.9f);
			return Mathf.Clamp(num2, 0.4f, 1.6f);
		}

		private void Move()
		{
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			float num2 = 0f;
			if (Plugin.AntennaMoves.Value && (Object)(object)ZNet.instance != (Object)null && _view.IsValid())
			{
				float num3 = Mathf.Max(3f, Plugin.AntennaMoveEvery.Value);
				double timeSeconds = ZNet.instance.GetTimeSeconds();
				long num4 = (long)Math.Floor(timeSeconds / (double)num3);
				Slot(num4, num3, out var start, out var yaw, out var tip);
				Slot(num4 - 1, num3, out var _, out var yaw2, out var tip2);
				float num5 = (float)((timeSeconds - start) / (double)MoveSeconds());
				if (num5 >= 0f && num5 < 1f && _soundSlot != num4)
				{
					_soundSlot = num4;
					Creak();
				}
				float num6 = Ease(Mathf.Clamp01(num5 * 1.4f));
				float num7 = Ease(Mathf.Clamp01(num5 * 1.6f - 0.6f));
				num = Mathf.LerpAngle(yaw2, yaw, num6);
				num2 = Mathf.Lerp(tip2, tip, num7);
			}
			_turn.localRotation = Quaternion.Euler(0f, num, 0f);
			_dish.localRotation = Quaternion.Euler(Plugin.DishTilt.Value + num2, 0f, 0f);
		}

		private void Twitch()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: 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_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			if (Time.time >= _nextTwitch)
			{
				_nextTwitch = Time.time + Random.Range(0.5f, 0.9f);
				bool flag = CoglingBody.FiddlingNear(((Component)this).transform.position, 2.2f);
				_toYaw = (flag ? Random.Range(-6f, 6f) : 0f);
				_toTip = (flag ? Random.Range(-4f, 4f) : 0f);
				if (flag && Random.value < 0.3f)
				{
					Creak();
				}
			}
			_twitchYaw = Mathf.MoveTowards(_twitchYaw, _toYaw, Time.deltaTime * 60f);
			_twitchTip = Mathf.MoveTowards(_twitchTip, _toTip, Time.deltaTime * 40f);
			if (_twitchYaw != 0f || _twitchTip != 0f)
			{
				Transform turn = _turn;
				turn.localRotation *= Quaternion.Euler(0f, _twitchYaw, 0f);
				Transform dish = _dish;
				dish.localRotation *= Quaternion.Euler(_twitchTip, 0f, 0f);
			}
		}

		private static float Ease(float x)
		{
			if (!(x < 0.5f))
			{
				return 1f - Mathf.Pow(-2f * x + 2f, 3f) / 2f;
			}
			return 4f * x * x * x;
		}

		private void Creak()
		{
			if (!((Object)(object)_sound == (Object)null) && _creaks != null && _creaks.Length != 0 && !(Plugin.AntennaSoundVolume.Value <= 0f))
			{
				_sound.pitch = Plugin.AntennaSoundPitch.Value;
				_sound.volume = Plugin.AntennaSoundVolume.Value;
				_sound.PlayOneShot(_creaks[Random.Range(0, _creaks.Length)]);
			}
		}

		private void Lamp()
		{
			//IL_0087: 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_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: 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_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Expected O, but got Unknown
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			bool value = Plugin.AntennaLight.Value;
			if ((Object)(object)_light == (Object)null || (Object)(object)_bulb == (Object)null)
			{
				return;
			}
			if (((Component)_light).gameObject.activeSelf != value)
			{
				((Component)_light).gameObject.SetActive(value);
			}
			if (!value)
			{
				return;
			}
			if (Time.time >= _nextLook)
			{
				_nextLook = Time.time + 0.5f;
				Camera mainCamera = Utils.GetMainCamera();
				_near = (Object)(object)mainCamera != (Object)null && Vector3.Distance(((Component)mainCamera).transform.position, ((Component)this).transform.position) < 45f;
				if (CoglingBody.EyesNear(((Component)this).transform.position, Antenna.Radius, out var colour, out var level))
				{
					_colour = colour;
					_target = Mathf.Max(0.2f, level);
				}
				else
				{
					_colour = Plugin.EyeColor.Value;
					_target = 1f;
				}
			}
			_level = Mathf.MoveTowards(_level, _target, Time.deltaTime * 1.5f);
			((Behaviour)_light).enabled = _near && Plugin.AntennaLightBrightness.Value > 0f;
			_light.color = _colour;
			_light.intensity = Plugin.AntennaLightBrightness.Value * _level;
			_light.range = Plugin.AntennaLightRange.Value;
			((Component)_light).transform.localScale = Vector3.one * Plugin.AntennaLightSize.Value;
			if (_block == null)
			{
				_block = new MaterialPropertyBlock();
			}
			_bulb.GetPropertyBlock(_block);
			_block.SetColor("_Color", _colour);
			_block.SetColor("_EmissionColor", _colour * Mathf.Max(0.5f, Plugin.EyeGlow.Value) * _level);
			_bulb.SetPropertyBlock(_block);
		}
	}
	[HarmonyPatch(typeof(Piece), "SetCreator")]
	internal static class BuiltHook
	{
		private static void Postfix(Piece __instance)
		{
			CoglingSlack.Built(__instance);
		}
	}
	[HarmonyPatch(typeof(Container), "Awake")]
	internal static class Chests
	{
		private static readonly List<Container> All = new List<Container>();

		private static void Postfix(Container __instance)
		{
			All.Add(__instance);
		}

		internal static void FindLoaded()
		{
			All.Clear();
			All.AddRange(Object.FindObjectsByType<Container>((FindObjectsSortMode)0));
		}

		internal static void Forget()
		{
			All.Clear();
		}

		internal static List<Container> Stored(List<Antenna> network)
		{
			All.RemoveAll((Container c) => (Object)(object)c == (Object)null);
			return All.Where((Container c) => Antenna.InArea(network, ((Component)c).transform.position) && ContainerAccess.IsStorage(c)).ToList();
		}

		internal static List<Container> Usable(List<Antenna> network)
		{
			All.RemoveAll((Container c) => (Object)(object)c == (Object)null);
			return All.Where((Container c) => Antenna.InArea(network, ((Component)c).transform.position) && ContainerAccess.IsStorage(c) && !ContainerAccess.InUse(c) && ContainerAccess.MayUse(c)).ToList();
		}
	}
	internal static class FloorItems
	{
		private static readonly FieldRef<List<ItemDrop>> Instances = AccessTools.StaticFieldRefAccess<List<ItemDrop>>(AccessTools.Field(typeof(ItemDrop), "s_instances"));

		private static readonly MethodInfo EggCanGrow = AccessTools.Method(typeof(EggGrow), "CanGrow", (Type[])null, (Type[])null);

		private static readonly Dictionary<ZDOID, float> FirstSeen = new Dictionary<ZDOID, float>();

		private static readonly Dictionary<ZDOID, float> ColdSince = new Dictionary<ZDOID, float>();

		private static readonly Dictionary<ZDOID, float> NoHomeUntil = new Dictionary<ZDOID, float>();

		internal static readonly HashSet<ZDOID> Claimed = new HashSet<ZDOID>();

		private static readonly int Below = LayerMask.GetMask(new string[5] { "piece", "Default", "static_solid", "Default_small", "terrain" });

		private static readonly Dictionary<ZDOID, int> NoWayCount = new Dictionary<ZDOID, int>();

		private static List<Character> Enemies()
		{
			Character me = (Character)(object)Player.m_localPlayer;
			return (from c in Character.GetAllCharacters()
				where (Object)(object)c != (Object)null && !c.IsDead() && !c.IsPlayer() && (int)c.GetFaction() != 1 && !CoglingStance.IsCogling(c) && !CoglingDanger.Built(c) && ((!((Object)(object)me != (Object)null)) ? ((int)c.GetFaction() > 0) : BaseAI.IsEnemy(me, c))
				select c).ToList();
		}

		private static string FightNear(ItemDrop d, List<Character> enemies)
		{
			return ((IEnumerable<Character>)enemies).FirstOrDefault((Func<Character, bool>)delegate(Character e)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				float num = Vector3.Distance(((Component)e).transform.position, ((Component)d).transform.position);
				return num < 8f || (num < 20f && (Object)(object)e.GetBaseAI() != (Object)null && e.GetBaseAI().IsAlerted());
			})?.m_name;
		}

		private static float Age(ItemDrop d, ZDOID id)
		{
			//IL_005e: 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)
			ZNetView component = ((Component)d).GetComponent<ZNetView>();
			ZDO val = ((component != null) ? component.GetZDO() : null);
			long num = ((val != null) ? val.GetLong(ZDOVars.s_spawnTime, 0L) : 0);
			if (num > 0 && (Object)(object)ZNet.instance != (Object)null)
			{
				return (float)(ZNet.instance.GetTime() - new DateTime(num)).TotalSeconds;
			}
			if (!FirstSeen.TryGetValue(id, out var value))
			{
				value = (FirstSeen[id] = Time.time);
			}
			return Time.time - value;
		}

		internal static int Load(ItemData item)
		{
			float weight = item.m_shared.m_weight;
			if (weight <= 0.0001f)
			{
				return item.m_stack;
			}
			return Mathf.Clamp(Mathf.FloorToInt(Plugin.MaxCarryWeight.Value / weight), 1, item.m_stack);
		}

		internal static ZDOID Id(ItemDrop d)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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)
			ZNetView component = ((Component)d).GetComponent<ZNetView>();
			return (ZDOID)(((??)((component == null) ? ((ZDOID?)null) : component.GetZDO()?.m_uid)) ?? ZDOID.None);
		}

		internal static void NoHome(ItemDrop d, float seconds = 90f)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			NoHomeUntil[Id(d)] = Time.time + seconds;
		}

		internal static float NoWay(ItemDrop d)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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)
			ZDOID key = Id(d);
			NoWayCount.TryGetValue(key, out var value);
			float num = (NoWayCount[key] = value + 1) switch
			{
				2 => 30f, 
				1 => 10f, 
				_ => 120f, 
			};
			NoHome(d, num);
			return num;
		}

		internal static List<ItemDrop> Candidates(List<Antenna> network, Vector3 from)
		{
			//IL_0007: 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_004e: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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_0081: 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)
			float time = Time.time;
			List<ItemDrop> list = new List<ItemDrop>();
			List<Character> enemies = Enemies();
			foreach (ItemDrop item in Instances.Invoke())
			{
				if (!((Object)(object)item == (Object)null) && Antenna.InArea(network, ((Component)item).transform.position))
				{
					ZDOID val = Id(item);
					if (!(val == ZDOID.None) && !Claimed.Contains(val) && Allowed(item, val, Age(item, val)) && FightNear(item, enemies) == null)
					{
						list.Add(item);
					}
				}
			}
			if (FirstSeen.Count > 2000)
			{
				Prune();
			}
			return list.OrderBy((ItemDrop d) => Vector3.Distance(((Component)d).transform.position, from)).ToList();
		}

		private static bool Allowed(ItemDrop d, ZDOID id, float age)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return WhyNot(d, id, age) == null;
		}

		private static string WhyNot(ItemDrop d, ZDOID id, float age)
		{
			//IL_000b: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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_0147: Unknown result type (might be due to invalid IL or missing references)
			if (NoHomeUntil.TryGetValue(id, out var value) && Time.time < value)
			{
				return $"no chest for it or out of reach (tries again in {value - Time.time:F0} s)";
			}
			if (age < Plugin.DropWait.Value)
			{
				return $"freshly dropped ({Plugin.DropWait.Value - age:F0} s to wait)";
			}
			if (d.IsPiece())
			{
				return "placed with the build menu";
			}
			ItemData itemData = d.m_itemData;
			if (itemData == null || itemData.m_shared.m_weight > Plugin.MaxCarryWeight.Value)
			{
				return $"too heavy (one weighs {itemData?.m_shared.m_weight:F0}: the dragon egg)";
			}
			Vector3 at = ((Component)d).transform.position;
			if (Floating.GetLiquidLevel(at, 1f, (LiquidType)0) > at.y + 0.05f)
			{
				return "in water";
			}
			if (Player.GetAllPlayers().Any((Player p) => Vector3.Distance(((Component)p).transform.position, at) < 2f))
			{
				return "a player is next to it";
			}
			if (!PrivateArea.CheckAccess(at, 0f, false, false))
			{
				return "inside a ward you can't use";
			}
			if (OnFurniture(d))
			{
				return "on furniture (a decoration)";
			}
			EggGrow component = ((Component)d).GetComponent<EggGrow>();
			if (component != null && !ColdEggReady(component, id))
			{
				return "an egg: warm, or not cold for long enough yet";
			}
			return null;
		}

		internal static List<ItemDrop> Near(Vector3 at, float within, ItemData like)
		{
			//IL_0041: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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_009d: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			List<ItemDrop> list = new List<ItemDrop>();
			foreach (ItemDrop item in Instances.Invoke())
			{
				if (!((Object)(object)item == (Object)null) && item.m_itemData != null && !(Vector3.Distance(((Component)item).transform.position, at) > within) && !(item.m_itemData.m_shared.m_name != like.m_shared.m_name) && item.m_itemData.m_quality == like.m_quality)
				{
					ZDOID val = Id(item);
					if (!(val == ZDOID.None) && !Claimed.Contains(val) && WhyNot(item, val, Age(item, val)) == null)
					{
						list.Add(item);
					}
				}
			}
			return list;
		}

		private static bool OnFurniture(ItemDrop d)
		{
			//IL_0006: 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)
			//IL_0015: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Invalid comparison between Unknown and I4
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Invalid comparison between Unknown and I4
			RaycastHit val = default(RaycastHit);
			if (!Physics.Raycast(((Component)d).transform.position + Vector3.up * 0.2f, Vector3.down, ref val, 1.5f, Below))
			{
				return false;
			}
			Piece componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Piece>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				if ((int)componentInParent.m_category != 4)
				{
					return (componentInParent.m_usage & 0x80) > 0;
				}
				return true;
			}
			return false;
		}

		private static bool ColdEggReady(EggGrow egg, ZDOID id)
		{
			//IL_0036: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			if ((EggCanGrow != null && (bool)EggCanGrow.Invoke(egg, null)) || !Plugin.CollectColdEggs.Value)
			{
				ColdSince.Remove(id);
				return false;
			}
			if (!ColdSince.TryGetValue(id, out var value))
			{
				ColdSince[id] = Time.time;
				return false;
			}
			return Time.time - value >= Plugin.ColdEggWait.Value * 60f;
		}

		private static void Prune()
		{
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			HashSet<ZDOID> live = new HashSet<ZDOID>((from d in Instances.Invoke()
				where (Object)(object)d != (Object)null
				select d).Select(Id));
			Dictionary<ZDOID, float>[] array = new Dictionary<ZDOID, float>[3] { FirstSeen, ColdSince, NoHomeUntil };
			foreach (Dictionary<ZDOID, float> dictionary in array)
			{
				foreach (ZDOID item in dictionary.Keys.Where((ZDOID k) => !live.Contains(k)).ToList())
				{
					dictionary.Remove(item);
				}
			}
		}

		internal static void Forget()
		{
			FirstSeen.Clear();
			ColdSince.Clear();
			NoHomeUntil.Clear();
			NoWayCount.Clear();
			Claimed.Clear();
		}
	}
	internal sealed class CoglingAI : BaseAI
	{
		private enum Mode
		{
			Resting,
			Strolling,
			GoingHome,
			Working,
			Returning,
			Slacking
		}

		private float _nextReturnPlan;

		private CoglingNavigator _nav;

		private CoglingJob _job;

		private CoglingDanger _danger;

		private CoglingSlack _slack;

		internal bool Running;

		internal float WalkScale = 1f;

		internal float RunScale = 1f;

		private float _nextJobLook;

		private float _nextTidy;

		private Mode _mode = Mode.GoingHome;

		private float _nextStroll;

		private Vector3 _home;

		private bool _haveHome;

		private static readonly string[] Rpcs = new string[5] { "Alert", "OnNearProjectileHit", "SetAggravated", "RPC_Wakeup", "RPC_Sleep" };

		private static readonly MethodInfo BaseOnDestroy = AccessTools.Method(typeof(BaseAI), "OnDestroy", (Type[])null, (Type[])null);

		private static readonly FieldRef<Character, BaseAI> CharacterAI = AccessTools.FieldRefAccess<Character, BaseAI>("m_baseAI");

		private bool _duplicate;

		private float _nextHomeCheck;

		private float _nextNetwork;

		private List<Antenna> _network = new List<Antenna>();

		private float _lastUpdate;

		private float _deadSince = -1f;

		private readonly Dictionary<CoglingVoice.Line, float> _saidAt = new Dictionary<CoglingVoice.Line, float>();

		private float _holdUntil;

		private float _lastSaid;

		private float _nextPlayerLook;

		private float _waveAt = -1f;

		private float _faceWaverUntil;

		private float _waveGiveUp;

		private Vector3 _waver;

		private float _calledUntil;

		private Vector3 _callSpot;

		private Vector3 _caller;

		private bool _gathered;

		private const string SeenKey = "cogling_seen";

		private bool _welcomeAfterBoot;

		private float _nextSeenWrite;

		private float _restingSince;

		private float _bootUntil;

		internal Character Going;

		private bool _homeAfterFright;

		private float _greetUntil;

		priva