Decompiled source of Good Tidings v1.0.0

plugins/GoodTidings.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using HeaveHo.Shared;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json.Linq;
using Nick.Shared;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Audio;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.Playables;
using UnityEngine.Rendering;
using UnityEngine.UI;

[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", "menu")]
[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;
		}
	}
}
internal sealed class ConfigurationManagerAttributes
{
	public bool? IsAdvanced;

	public int? Order;

	public Action<ConfigEntryBase> CustomDrawer;

	public bool? HideDefaultButton;

	public bool? HideSettingName;

	public bool? ReadOnly;

	public bool? Browsable;

	public string Category;

	public string DispName;

	public string Description;
}
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 GoodTidings
{
	internal sealed class BountifulSeason : Visit
	{
		internal const float Radius = 96f;

		private const float Rescan = 5f;

		private const float EffectSpacing = 3f;

		private const float ParticleSpeed = 0.35f;

		private static bool _running;

		private static bool _stop;

		private static readonly Color Wisp = new Color(0.45f, 1f, 0.5f);

		public override string Id => "bountiful";

		public override bool Enabled => Plugin.BountifulEnabled.Value;

		internal static bool Running => _running;

		public override bool Start(Vector3 basePoint)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			if (_running)
			{
				return false;
			}
			ZPackage val = new ZPackage();
			val.Write(basePoint);
			val.Write(Plugin.BountifulMinutes.Value * 60f);
			val.Write(Plugin.BountifulSpeed.Value);
			val.Write(Plugin.BountifulHeadStart.Value * 60f);
			val.Write(Plugin.BountifulGrowSpeed.Value);
			ZRoutedRpc.instance.InvokeRoutedRPC(0L, "GoodTidings_Bountiful", new object[1] { val });
			Plugin.Log.LogInfo((object)$"Bountiful season at {basePoint} for {Plugin.BountifulMinutes.Value} minutes at {Plugin.BountifulSpeed.Value}x");
			return true;
		}

		internal static void OnRpc(long sender, ZPackage pkg)
		{
			//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_004f: Unknown result type (might be due to invalid IL or missing references)
			Vector3 center = pkg.ReadVector3();
			float seconds = pkg.ReadSingle();
			float num = pkg.ReadSingle();
			float headStart = ((pkg.GetPos() < pkg.Size()) ? pkg.ReadSingle() : 0f);
			float growSpeed = ((pkg.GetPos() < pkg.Size()) ? pkg.ReadSingle() : num);
			((MonoBehaviour)Plugin.Instance).StartCoroutine(Run(center, seconds, num, headStart, growSpeed));
		}

		internal static void Stop()
		{
			_stop = true;
		}

		private static IEnumerator Run(Vector3 center, float seconds, float speed, float headStart, float growSpeed)
		{
			//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)
			_running = true;
			_stop = false;
			Dictionary<Component, GameObject> effects = new Dictionary<Component, GameObject>();
			List<Vector3> spots = new List<Vector3>();
			bool near = (Object)(object)Player.m_localPlayer != (Object)null && Utils.DistanceXZ(((Component)Player.m_localPlayer).transform.position, center) < 176f;
			if (near)
			{
				MessageHud.instance.ShowMessage((MessageType)2, Lines.Pick("goodtidings_bountiful"), 0, (Sprite)null, false, true);
				Effect("sfx_staff_elder_grow", center);
			}
			MapPins pins = new MapPins();
			float end = Time.time + seconds;
			float nextScan = 0f;
			float last = Time.time;
			List<Component> targets = new List<Component>();
			HashSet<Component> started = new HashSet<Component>();
			while (Time.time < end && !_stop)
			{
				if (Time.time >= nextScan)
				{
					nextScan = Time.time + 5f;
					targets = Find(center);
					if (near)
					{
						foreach (Component item in targets)
						{
							if (Object.op_Implicit((Object)(object)item) && !effects.ContainsKey(item))
							{
								Vector3 at = item.transform.position;
								bool flag = spots.Any((Vector3 s) => Vector3.Distance(s, at) < 3f);
								effects[item] = (flag ? null : Glow(at, end - Time.time));
								if (!flag)
								{
									spots.Add(at);
								}
							}
						}
					}
				}
				float num = Time.time - last;
				last = Time.time;
				float num2 = num * (speed - 1f);
				float num3 = num * (growSpeed - 1f);
				foreach (Component item2 in targets)
				{
					if (!((Object)(object)item2 == (Object)null))
					{
						bool flag2 = item2 is Plant || item2 is Beehive;
						float num4 = ((flag2 && started.Add(item2)) ? headStart : 0f);
						try
						{
							Boost(item2, (flag2 ? num3 : num2) + num4);
						}
						catch (Exception ex)
						{
							Plugin.Debug("Bountiful season on " + ((Object)item2).name + ": " + ex.Message);
						}
					}
				}
				pins.Update(center, center, "", withIcon: false);
				yield return (object)new WaitForSeconds(1f);
			}
			pins.Remove();
			foreach (GameObject value in effects.Values)
			{
				if (Object.op_Implicit((Object)(object)value))
				{
					Fade(value);
				}
			}
			if (near && !_stop)
			{
				MessageHud.instance.ShowMessage((MessageType)1, "$goodtidings_bountiful_end", 0, (Sprite)null, false, true);
			}
			_running = false;
		}

		private static List<Component> Find(Vector3 center)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			HashSet<Component> hashSet = new HashSet<Component>();
			Collider[] array = Physics.OverlapSphere(center, 96f, -1, (QueryTriggerInteraction)2);
			foreach (Collider val in array)
			{
				Component val2 = (Component)(((Component)val).GetComponentInParent<Plant>() ?? ((Component)val).GetComponentInParent<Beehive>() ?? ((Component)val).GetComponentInParent<Fermenter>() ?? ((object)((Component)val).GetComponentInParent<Smelter>()) ?? ((object)((Component)val).GetComponentInParent<CookingStation>()));
				if ((Object)(object)val2 != (Object)null)
				{
					hashSet.Add(val2);
				}
			}
			return hashSet.ToList();
		}

		private static void Boost(Component t, float extra)
		{
			ZNetView componentInParent = t.GetComponentInParent<ZNetView>();
			if ((Object)(object)componentInParent == (Object)null || !componentInParent.IsValid() || !componentInParent.IsOwner())
			{
				return;
			}
			ZDO zDO = componentInParent.GetZDO();
			long ticks = TimeSpan.FromSeconds(extra).Ticks;
			long ticks2 = ZNet.instance.GetTime().Ticks;
			if (!(t is Plant))
			{
				if (!(t is Beehive))
				{
					if (!(t is Fermenter))
					{
						if (!(t is Smelter))
						{
							CookingStation val = (CookingStation)(object)((t is CookingStation) ? t : null);
							if (val == null)
							{
								return;
							}
							for (int i = 0; i < val.m_slots.Length; i++)
							{
								string item = zDO.GetString("slot" + i, "");
								ItemConversion val2 = ((item == "") ? null : ((IEnumerable<ItemConversion>)val.m_conversion).FirstOrDefault((Func<ItemConversion, bool>)((ItemConversion x) => Object.op_Implicit((Object)(object)x.m_from) && ((Object)x.m_from).name == item)));
								if (val2 != null)
								{
									float num = zDO.GetFloat("slot" + i, 0f);
									if (num < val2.m_cookTime - 0.05f)
									{
										zDO.Set("slot" + i, Mathf.Min(num + extra, val2.m_cookTime - 0.05f));
									}
								}
							}
						}
						else
						{
							zDO.Set(ZDOVars.s_startTime, zDO.GetLong(ZDOVars.s_startTime, ticks2) - ticks);
						}
					}
					else
					{
						long num2 = zDO.GetLong(ZDOVars.s_startTime, 0L);
						if (num2 != 0L)
						{
							zDO.Set(ZDOVars.s_startTime, num2 - ticks);
						}
					}
				}
				else
				{
					zDO.Set(ZDOVars.s_lastTime, zDO.GetLong(ZDOVars.s_lastTime, ticks2) - ticks);
				}
			}
			else
			{
				zDO.Set(ZDOVars.s_plantTime, zDO.GetLong(ZDOVars.s_plantTime, ticks2) - ticks);
			}
		}

		private static GameObject Glow(Vector3 at, float seconds)
		{
			//IL_0005: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = LocalFx.Spawn("vfx_prespawn", at, Quaternion.identity, null, 0f);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			ParticleSystem[] componentsInChildren = val.GetComponentsInChildren<ParticleSystem>();
			foreach (ParticleSystem val2 in componentsInChildren)
			{
				MainModule main = val2.main;
				((MainModule)(ref main)).simulationSpeed = 0.35f;
				((MainModule)(ref main)).loop = true;
				((MainModule)(ref main)).startColor = Blue(((MainModule)(ref main)).startColor);
				ColorOverLifetimeModule colorOverLifetime = val2.colorOverLifetime;
				if (((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled)
				{
					((ColorOverLifetimeModule)(ref colorOverLifetime)).color = Blue(((ColorOverLifetimeModule)(ref colorOverLifetime)).color);
				}
			}
			Light[] componentsInChildren2 = val.GetComponentsInChildren<Light>();
			foreach (Light val3 in componentsInChildren2)
			{
				val3.color = Wisp;
			}
			AudioSource[] componentsInChildren3 = val.GetComponentsInChildren<AudioSource>();
			foreach (AudioSource val4 in componentsInChildren3)
			{
				((Behaviour)val4).enabled = false;
			}
			Object.Destroy((Object)(object)val, seconds + 10f);
			return val;
		}

		private static MinMaxGradient Blue(MinMaxGradient g)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected I4, but got Unknown
			//IL_0022: 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_002c: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			ParticleSystemGradientMode mode = ((MinMaxGradient)(ref g)).mode;
			return (MinMaxGradient)((int)mode switch
			{
				0 => new MinMaxGradient(Blue(((MinMaxGradient)(ref g)).color)), 
				2 => new MinMaxGradient(Blue(((MinMaxGradient)(ref g)).colorMin), Blue(((MinMaxGradient)(ref g)).colorMax)), 
				1 => new MinMaxGradient(Blue(((MinMaxGradient)(ref g)).gradient)), 
				3 => new MinMaxGradient(Blue(((MinMaxGradient)(ref g)).gradientMin), Blue(((MinMaxGradient)(ref g)).gradientMax)), 
				_ => g, 
			});
		}

		private static Gradient Blue(Gradient g)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			if (g == null)
			{
				return null;
			}
			GradientColorKey[] array = ((IEnumerable<GradientColorKey>)g.colorKeys).Select((Func<GradientColorKey, GradientColorKey>)((GradientColorKey k) => new GradientColorKey(Blue(k.color), k.time))).ToArray();
			Gradient val = new Gradient();
			val.SetKeys(array, g.alphaKeys);
			return val;
		}

		private static Color Blue(Color c)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Max(new float[3] { c.r, c.g, c.b });
			return new Color(Wisp.r * num, Wisp.g * num, Wisp.b * num, c.a);
		}

		private static void Fade(GameObject g)
		{
			ParticleSystem[] componentsInChildren = g.GetComponentsInChildren<ParticleSystem>();
			foreach (ParticleSystem val in componentsInChildren)
			{
				val.Stop(true, (ParticleSystemStopBehavior)1);
			}
			Object.Destroy((Object)(object)g, 6f);
		}

		private static void Effect(string prefab, Vector3 at)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab2 = ZNetScene.instance.GetPrefab(prefab);
			if (Object.op_Implicit((Object)(object)prefab2))
			{
				Object.Instantiate<GameObject>(prefab2, at, Quaternion.identity);
			}
		}
	}
	internal static class Commands
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ConsoleEvent <>9__3_0;

			public static Func<Visit, string> <>9__5_1;

			internal void <Register>b__3_0(ConsoleEventArgs args)
			{
				Run(args.Context, args.Args);
			}

			internal string <Run>b__5_1(Visit v)
			{
				return v.Id;
			}
		}

		private const string Command = "goodtidings";

		private const string Usage = "goodtidings visit [trader|bountiful|muninn|dverger|skald] | goodtidings found";

		private static readonly FieldRef<Dictionary<string, ConsoleCommand>> TerminalCommands = AccessTools.StaticFieldRefAccess<Dictionary<string, ConsoleCommand>>(AccessTools.Field(typeof(Terminal), "commands"));

		internal static void Register()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			object obj = <>c.<>9__3_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate(ConsoleEventArgs args)
				{
					Run(args.Context, args.Args);
				};
				<>c.<>9__3_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("goodtidings", "Good Tidings: goodtidings visit [trader|bountiful|muninn|dverger|skald] | goodtidings found", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}

		internal static void Unregister()
		{
			TerminalCommands.Invoke().Remove("goodtidings");
		}

		private static void Run(Terminal t, string[] a)
		{
			string text = ((a.Length > 1) ? a[1].ToLowerInvariant() : "");
			Player localPlayer = Player.m_localPlayer;
			if (!(text == "visit"))
			{
				if (text == "found")
				{
					Stock.Rebuild();
					List<StockDiscovery.Found> list = Stock.FoundNow();
					t.AddString("Stock file: " + StockFile.FilePath + (Plugin.Synced.TextFromServer("Stock") ? " (the server's applies)" : "") + "; " + string.Format("{0} added, {1} removed, finding other mods' items {2}.", StockFile.Adds.Count, StockFile.Removed.Count, StockFile.FindOtherMods ? "on" : "off"));
					t.AddString("Always: " + string.Join(", ", Stock.AlwaysNames()));
					t.AddString((list.Count == 0) ? "No other mods' items found." : $"{list.Count} other mods' items found:");
					{
						foreach (StockDiscovery.Found item in list)
						{
							string[] obj = new string[6] { "  ", item.Item, " (", null, null, null };
							Localization instance = Localization.instance;
							GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item.Item);
							obj[3] = instance.Localize(((itemPrefab == null) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_name) ?? "?");
							obj[4] = "): ";
							obj[5] = $"{item.Slot} of the {Stock.LandNames[item.Land]}, {item.Stack} for {item.Price}, {item.From}";
							t.AddString(string.Concat(obj));
						}
						return;
					}
				}
				t.AddString("goodtidings visit [trader|bountiful|muninn|dverger|skald] | goodtidings found");
				return;
			}
			if ((Object)(object)ZNet.instance == (Object)null || (!ZNet.instance.IsServer() && !((Terminal)Console.instance).IsCheatsEnabled()))
			{
				t.AddString("Host or devcommands only.");
				return;
			}
			string only = ((a.Length > 2) ? a[2].ToLowerInvariant() : null);
			if (only != null && !Visits.All.Any((Visit v) => v.Id == only))
			{
				t.AddString("No visit called " + only + ": " + string.Join(", ", Visits.All.Select((Visit v) => v.Id)) + ".");
			}
			else if (Visits.TryStart(only))
			{
				t.AddString("Visit started.");
			}
			else if ((Object)(object)localPlayer != (Object)null && localPlayer.GetBaseValue() < 3)
			{
				t.AddString($"Not at a base here (base value {localPlayer.GetBaseValue()}, visits need 3): go home first.");
			}
			else if (TraderVisitor.Count > 0 && (only == null || only == "trader"))
			{
				t.AddString("Dagny is still here: one at a time.");
			}
			else if (MuninnVisitor.Count > 0 && (only == null || only == "muninn"))
			{
				t.AddString("Muninn is still here (he leaves a few seconds after an answer): try again in a moment.");
			}
			else if (SkaldVisitor.Count > 0 && (only == null || only == "skald"))
			{
				t.AddString("The skald is still playing here.");
			}
			else if (DvergerVisitor.Count > 0 && (only == null || only == "dverger"))
			{
				t.AddString("The wounded Dvergr is still here.");
			}
			else if (BountifulSeason.Running && (only == null || only == "bountiful"))
			{
				t.AddString("A bountiful season is already going on.");
			}
			else if (only != null && !Visits.All.First((Visit v) => v.Id == only).Enabled)
			{
				t.AddString(only + " is switched off in the settings.");
			}
			else
			{
				t.AddString("No visit could start here (no open ground near the base?).");
			}
		}
	}
	internal static class Cuts
	{
		internal sealed class Tint
		{
			public float Hue;

			public float Saturation;

			public float Value = 1f;

			public bool Grey;

			public List<RectInt> Keep = new List<RectInt>();

			public List<RectInt> Black = new List<RectInt>();

			public List<RectInt> Cut = new List<RectInt>();

			public override string ToString()
			{
				return string.Format("{0:0.00},{1:0.00},{2:0.00},{3},{4},{5},{6}", Hue, Saturation, Value, Grey, string.Join("/", Keep), string.Join("/", Black), string.Join("/", Cut));
			}
		}

		internal static readonly Dictionary<string, List<RectInt>> BySuit = new Dictionary<string, List<RectInt>>();

		internal static int Grid;

		private static readonly Dictionary<string, Material> Made = new Dictionary<string, Material>();

		internal static readonly Color[] GridColours = (Color[])(object)new Color[16]
		{
			Color.red,
			Color.green,
			Color.blue,
			Color.yellow,
			Color.cyan,
			Color.magenta,
			Color.white,
			Color.black,
			new Color(1f, 0.5f, 0f),
			new Color(0.5f, 0f, 1f),
			new Color(1f, 0.6f, 0.8f),
			new Color(0.45f, 0.25f, 0.1f),
			Color.grey,
			new Color(0.6f, 1f, 0.2f),
			new Color(0f, 0f, 0.4f),
			new Color(0f, 0.5f, 0.5f)
		};

		internal static Material MaterialFor(Material source, string suit, Tint tint = null)
		{
			//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03da: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f8: Expected O, but got Unknown
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			BySuit.TryGetValue(suit, out var value);
			if (Grid == 0 && (value == null || value.Count == 0) && tint == null)
			{
				return source;
			}
			string key = suit + "|" + Grid + "|" + string.Join(";", value ?? new List<RectInt>()) + "|" + tint;
			if (Made.TryGetValue(key, out var value2) && Object.op_Implicit((Object)(object)value2))
			{
				return value2;
			}
			Texture2D val = Readable(source.mainTexture);
			if ((Object)(object)val == (Object)null)
			{
				return source;
			}
			Color32[] pixels = val.GetPixels32();
			int width = ((Texture)val).width;
			int height = ((Texture)val).height;
			if (tint != null)
			{
				float num = default(float);
				float num2 = default(float);
				float num3 = default(float);
				for (int i = 0; i < height; i++)
				{
					for (int j = 0; j < width; j++)
					{
						Vector2Int at = new Vector2Int(j, i);
						Color32 val2 = pixels[i * width + j];
						if (tint.Cut.Exists((RectInt r) => ((RectInt)(ref r)).Contains(at)))
						{
							pixels[i * width + j].a = 0;
						}
						else if (!tint.Keep.Exists((RectInt r) => ((RectInt)(ref r)).Contains(at)))
						{
							Color.RGBToHSV(Color32.op_Implicit(val2), ref num, ref num2, ref num3);
							Color val3 = (tint.Black.Exists((RectInt r) => ((RectInt)(ref r)).Contains(at)) ? Color.HSVToRGB(0f, 0f, num3 * 0.3f) : (tint.Grey ? Color.HSVToRGB(0f, 0f, Mathf.Clamp01(num3 * tint.Value)) : Color.HSVToRGB(tint.Hue, Mathf.Max(num2, tint.Saturation), Mathf.Clamp01(num3 * tint.Value))));
							pixels[i * width + j] = new Color32((byte)(val3.r * 255f), (byte)(val3.g * 255f), (byte)(val3.b * 255f), val2.a);
						}
					}
				}
			}
			if (Grid > 0)
			{
				for (int num4 = 0; num4 < height; num4++)
				{
					for (int num5 = 0; num5 < width; num5++)
					{
						int num6 = num4 * Grid / height * Grid + num5 * Grid / width;
						Color val4 = Color.Lerp(Color32.op_Implicit(pixels[num4 * width + num5]), GridColours[num6 % GridColours.Length], 0.75f);
						pixels[num4 * width + num5] = new Color32((byte)(val4.r * 255f), (byte)(val4.g * 255f), (byte)(val4.b * 255f), pixels[num4 * width + num5].a);
					}
				}
			}
			if (value != null)
			{
				foreach (RectInt item in value)
				{
					RectInt current = item;
					for (int num7 = Mathf.Max(0, ((RectInt)(ref current)).yMin); num7 < Mathf.Min(height, ((RectInt)(ref current)).yMax); num7++)
					{
						for (int num8 = Mathf.Max(0, ((RectInt)(ref current)).xMin); num8 < Mathf.Min(width, ((RectInt)(ref current)).xMax); num8++)
						{
							pixels[num7 * width + num8].a = 0;
						}
					}
				}
			}
			val.SetPixels32(pixels);
			val.Apply();
			value2 = new Material(source)
			{
				name = ((Object)source).name + "_goodtidings",
				mainTexture = (Texture)(object)val
			};
			return Made[key] = value2;
		}

		internal static void Clear()
		{
			foreach (Material value in Made.Values)
			{
				if (Object.op_Implicit((Object)(object)value))
				{
					Object.Destroy((Object)(object)value.mainTexture);
					Object.Destroy((Object)(object)value);
				}
			}
			Made.Clear();
		}

		internal static Texture2D Readable(Texture source)
		{
			//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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)source == (Object)null)
			{
				return null;
			}
			RenderTexture temporary = RenderTexture.GetTemporary(source.width, source.height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2);
			Graphics.Blit(source, temporary);
			RenderTexture active = RenderTexture.active;
			RenderTexture.active = temporary;
			Texture2D val = new Texture2D(source.width, source.height, (TextureFormat)4, false)
			{
				filterMode = source.filterMode,
				wrapMode = source.wrapMode
			};
			val.ReadPixels(new Rect(0f, 0f, (float)source.width, (float)source.height), 0, 0);
			val.Apply();
			RenderTexture.active = active;
			RenderTexture.ReleaseTemporary(temporary);
			return val;
		}
	}
	internal sealed class DvergerVisit : Visit
	{
		private static int _blockMask;

		public override string Id => "dverger";

		public override bool Enabled => Plugin.DvergerEnabled.Value;

		public override bool Start(Vector3 basePoint)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			if (DvergerVisitor.Count > 0)
			{
				Plugin.Debug("A wounded Dvergr is already here");
				return false;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab("goodtidings_dverger");
			if ((Object)(object)prefab == (Object)null || !FindGround(basePoint, 10f, 18f, out var at) || !FindGround(basePoint, 35f, 45f, out var at2))
			{
				return false;
			}
			Vector3 val = at - at2;
			val.y = 0f;
			GameObject val2 = Object.Instantiate<GameObject>(prefab, at2, (((Vector3)(ref val)).sqrMagnitude > 0.01f) ? Quaternion.LookRotation(val) : Quaternion.identity);
			ZDO zDO = val2.GetComponent<ZNetView>().GetZDO();
			zDO.Set("GoodTidings.LeaveAt", ZNet.instance.GetTime().Ticks + TimeSpan.FromMinutes(Plugin.DvergerMinutes.Value).Ticks);
			zDO.Set("GoodTidings.KneelAt", at);
			val2.GetComponent<DvergerAI>().SetHome(basePoint);
			Net.MessageAll((MessageType)2, "$goodtidings_dverger_arrives");
			Plugin.Log.LogInfo((object)$"A wounded Dvergr staggers in from {at2} to {at}, by the base at {basePoint}");
			return true;
		}

		private static bool FindGround(Vector3 home, float min, float max, out Vector3 at)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			if (_blockMask == 0)
			{
				_blockMask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "vehicle", "character" });
			}
			float num = default(float);
			for (int i = 0; i < 60; i++)
			{
				Vector2 insideUnitCircle = Random.insideUnitCircle;
				Vector2 val = ((Vector2)(ref insideUnitCircle)).normalized * Random.Range(min, max);
				Vector3 val2 = home + new Vector3(val.x, 0f, val.y);
				if (ZoneSystem.instance.GetSolidHeight(val2, ref num, 1000) && !(num < ZoneSystem.instance.m_waterLevel + 0.3f) && !(Mathf.Abs(num - ZoneSystem.instance.GetGroundHeight(val2)) > 0.3f))
				{
					val2.y = num;
					if (!Physics.CheckSphere(val2 + Vector3.up * 1.2f, 1f, _blockMask, (QueryTriggerInteraction)1))
					{
						at = val2 + Vector3.up * 0.2f;
						return true;
					}
				}
			}
			at = Vector3.zero;
			return false;
		}
	}
	internal static class DvergerPrefab
	{
		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		private static class ZNetScene_Awake
		{
			private static void Postfix(ZNetScene __instance)
			{
				Register(__instance);
			}
		}

		internal const string Name = "goodtidings_dverger";

		private static GameObject _holder;

		private static GameObject _prefab;

		private static readonly FieldRef<ZNetScene, Dictionary<int, GameObject>> NamedPrefabs = AccessTools.FieldRefAccess<ZNetScene, Dictionary<int, GameObject>>("m_namedPrefabs");

		internal static void Register(ZNetScene scene)
		{
			if ((Object)(object)scene == (Object)null)
			{
				return;
			}
			if ((Object)(object)_prefab == (Object)null)
			{
				Build(scene);
			}
			if (!((Object)(object)_prefab == (Object)null))
			{
				scene.m_prefabs.RemoveAll((GameObject p) => (Object)(object)p == (Object)null || (((Object)p).name == "goodtidings_dverger" && (Object)(object)p != (Object)(object)_prefab));
				if (!scene.m_prefabs.Contains(_prefab))
				{
					scene.m_prefabs.Add(_prefab);
				}
				NamedPrefabs.Invoke(scene)[StringExtensionMethods.GetStableHashCode("goodtidings_dverger")] = _prefab;
			}
		}

		internal static void Unregister()
		{
			ZNetScene instance = ZNetScene.instance;
			if ((Object)(object)instance != (Object)null && (Object)(object)_prefab != (Object)null)
			{
				instance.m_prefabs.Remove(_prefab);
				Dictionary<int, GameObject> dictionary = NamedPrefabs.Invoke(instance);
				if (dictionary.TryGetValue(StringExtensionMethods.GetStableHashCode("goodtidings_dverger"), out var value) && (Object)(object)value == (Object)(object)_prefab)
				{
					dictionary.Remove(StringExtensionMethods.GetStableHashCode("goodtidings_dverger"));
				}
			}
			if (Object.op_Implicit((Object)(object)_holder))
			{
				Object.Destroy((Object)(object)_holder);
			}
			_holder = (_prefab = null);
		}

		private static void Build(ZNetScene scene)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			GameObject prefab = scene.GetPrefab("Dverger");
			if ((Object)(object)prefab == (Object)null)
			{
				Plugin.Log.LogError((object)"No Dverger prefab: the wounded Dvergr can't be made");
				return;
			}
			_holder = new GameObject("goodtidings_prefabs_dverger");
			_holder.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)_holder);
			GameObject val = Object.Instantiate<GameObject>(prefab, _holder.transform, false);
			((Object)val).name = "goodtidings_dverger";
			MonsterAI component = val.GetComponent<MonsterAI>();
			DvergerAI dvergerAI = val.AddComponent<DvergerAI>();
			FieldInfo[] fields = typeof(BaseAI).GetFields(BindingFlags.Instance | BindingFlags.Public);
			foreach (FieldInfo fieldInfo in fields)
			{
				fieldInfo.SetValue(dvergerAI, fieldInfo.GetValue(component));
			}
			((BaseAI)dvergerAI).m_aggravatable = false;
			((BaseAI)dvergerAI).m_randomMoveRange = 12f;
			((BaseAI)dvergerAI).m_randomMoveInterval = 6f;
			((BaseAI)dvergerAI).m_spawnMessage = "";
			Object.DestroyImmediate((Object)(object)component);
			Type[] array = new Type[2]
			{
				typeof(CharacterDrop),
				typeof(NpcTalk)
			};
			foreach (Type type in array)
			{
				Component component2 = val.GetComponent(type);
				if (component2 != null)
				{
					Object.DestroyImmediate((Object)(object)component2);
				}
			}
			Humanoid component3 = val.GetComponent<Humanoid>();
			((Character)component3).m_name = "$goodtidings_dverger";
			component3.m_defaultItems = (GameObject[])(object)new GameObject[0];
			component3.m_randomWeapon = (GameObject[])(object)new GameObject[0];
			component3.m_randomShield = ((IEnumerable<GameObject>)(object)new GameObject[1] { Item("DvergerHairMale_Redbeard") }).Where((GameObject x) => Object.op_Implicit((Object)(object)x)).ToArray();
			component3.m_randomSets = (ItemSet[])(object)new ItemSet[0];
			((Character)component3).m_walkSpeed = 1.1f;
			((Character)component3).m_speed = 1.1f;
			((Character)component3).m_runSpeed = 1.4f;
			val.AddComponent<DvergerVisitor>();
			_prefab = val;
			GameObject Item(string name)
			{
				return scene.GetPrefab(name);
			}
		}
	}
	internal sealed class DvergerAI : BaseAI
	{
		internal const string HomeKey = "GoodTidings.Home";

		internal const string LeaveAtKey = "GoodTidings.LeaveAt";

		internal const string StageKey = "GoodTidings.Stage";

		internal const string SpotKey = "GoodTidings.Spot";

		internal const string SpotRotKey = "GoodTidings.SpotRot";

		internal const string ApproachKey = "GoodTidings.Approach";

		internal const string PoseKey = "GoodTidings.Pose";

		internal const string NoFireKey = "GoodTidings.NoFire";

		internal const string MealsKey = "GoodTidings.Meals";

		internal const string StageAtKey = "GoodTidings.StageAt";

		internal const string BandAtKey = "GoodTidings.BandAt";

		internal const string BandSentKey = "GoodTidings.BandSent";

		internal const string KneelAtKey = "GoodTidings.KneelAt";

		internal const string TargetKey = "GoodTidings.Target";

		internal const string RetriedKey = "GoodTidings.Retried";

		internal const int Arriving = 0;

		internal const int Slumped = 1;

		internal const int Walking = 2;

		internal const int Resting = 3;

		internal const int Healing = 4;

		internal const int Tempering = 5;

		internal const int Crafting = 6;

		internal const int Thankful = 7;

		internal const int Neglected = 8;

		internal const string GroundPose = "Sitting idle";

		internal const string BedPose = "Laying Sleeping";

		private static readonly long LeaveGrace = TimeSpan.FromSeconds(150.0).Ticks;

		private static readonly long WalkGiveUp = TimeSpan.FromSeconds(60.0).Ticks;

		private static readonly long ArriveGiveUp = TimeSpan.FromSeconds(90.0).Ticks;

		private static readonly long TemperWalk = TimeSpan.FromSeconds(25.0).Ticks;

		private static readonly long CraftTime = TimeSpan.FromSeconds(4.5).Ticks;

		private static readonly long HealTime = TimeSpan.FromSeconds(8.0).Ticks;

		private static readonly long BandDelay = TimeSpan.FromSeconds(45.0).Ticks;

		private float _fireSearch;

		private float _progressTimer;

		private float _lastDistance = float.MaxValue;

		private long Now => ZNet.instance.GetTime().Ticks;

		internal void SetHome(Vector3 point)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			base.m_spawnPoint = point;
			ZDO zDO = base.m_nview.GetZDO();
			zDO.Set("GoodTidings.Home", point);
			zDO.Set(ZDOVars.s_spawnPoint, point);
		}

		private void SetStage(ZDO zdo, int stage)
		{
			zdo.Set("GoodTidings.Stage", stage);
			zdo.Set("GoodTidings.StageAt", Now);
		}

		public override bool UpdateAI(float dt)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0454: Unknown result type (might be due to invalid IL or missing references)
			//IL_0459: Unknown result type (might be due to invalid IL or missing references)
			//IL_045e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_043e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0443: Unknown result type (might be due to invalid IL or missing references)
			//IL_047f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0484: Unknown result type (might be due to invalid IL or missing references)
			if (!((BaseAI)this).UpdateAI(dt))
			{
				return false;
			}
			ZDO zDO = base.m_nview.GetZDO();
			long now = Now;
			base.m_spawnPoint = zDO.GetVec3(ZDOVars.s_spawnPoint, base.m_spawnPoint);
			long num = zDO.GetLong("GoodTidings.LeaveAt", 0L);
			if (num == 0L)
			{
				num = now + TimeSpan.FromMinutes(Plugin.DvergerMinutes.Value).Ticks;
				zDO.Set("GoodTidings.LeaveAt", num);
			}
			int num2 = zDO.GetInt("GoodTidings.Stage", 0);
			if (num2 <= 3 && now >= num)
			{
				StandUp(zDO);
				SetStage(zDO, 8);
				zDO.Set("GoodTidings.BandAt", now + BandDelay);
				HeadAway(zDO);
				Plugin.Log.LogInfo((object)"The wounded Dvergr was left: he limps off, and his kin will come");
				return true;
			}
			switch (num2)
			{
			case 0:
			{
				if (zDO.GetLong("GoodTidings.StageAt", 0L) == 0L)
				{
					zDO.Set("GoodTidings.StageAt", now);
				}
				Vector3 vec2 = zDO.GetVec3("GoodTidings.KneelAt", ((Component)this).transform.position);
				if (((BaseAI)this).MoveTo(dt, vec2, 0.8f, false) || now - zDO.GetLong("GoodTidings.StageAt", now) > ArriveGiveUp)
				{
					((BaseAI)this).StopMoving();
					SetStage(zDO, 1);
				}
				else
				{
					Unstick(dt, vec2);
				}
				return true;
			}
			case 1:
				((BaseAI)this).StopMoving();
				return true;
			case 2:
			{
				Vector3 vec = zDO.GetVec3("GoodTidings.Approach", ((Component)this).transform.position);
				if (((BaseAI)this).MoveTo(dt, vec, 0.7f, false))
				{
					SetStage(zDO, 3);
					return true;
				}
				if (now - zDO.GetLong("GoodTidings.StageAt", now) > WalkGiveUp)
				{
					if (Vector3.Distance(((Component)this).transform.position, vec) < 1.5f)
					{
						SetStage(zDO, 3);
						return true;
					}
					if (!zDO.GetBool("GoodTidings.Retried", false))
					{
						zDO.Set("GoodTidings.Retried", true);
						Rest.Find(((Component)this).transform.position, ((Component)this).transform.rotation, base.m_pathAgentType, out var place, furniture: false);
						GoTo(zDO, place);
						Plugin.Log.LogInfo((object)$"The wounded Dvergr can't get there: he goes to {place.What} at {place.Spot}");
						return true;
					}
					zDO.Set("GoodTidings.Spot", ((Component)this).transform.position);
					zDO.Set("GoodTidings.SpotRot", ((Component)this).transform.rotation);
					zDO.Set("GoodTidings.Approach", ((Component)this).transform.position);
					zDO.Set("GoodTidings.Pose", "Sitting idle");
					SetStage(zDO, 3);
					return true;
				}
				Unstick(dt, vec);
				return true;
			}
			case 3:
			case 4:
				((BaseAI)this).StopMoving();
				Hold(zDO);
				if (num2 == 3 && zDO.GetBool("GoodTidings.NoFire", false))
				{
					LookForFire(zDO, dt);
				}
				if (num2 == 4 && now - zDO.GetLong("GoodTidings.StageAt", now) > HealTime)
				{
					StandUp(zDO);
					Player closestPlayer = Player.GetClosestPlayer(((Component)this).transform.position, 30f);
					if ((Object)(object)closestPlayer == (Object)null)
					{
						Finish(zDO);
						return true;
					}
					zDO.Set("GoodTidings.Target", closestPlayer.GetPlayerID());
					SetStage(zDO, 5);
					Plugin.Log.LogInfo((object)("The wounded Dvergr is healed: he goes over to " + closestPlayer.GetPlayerName()));
				}
				return true;
			case 5:
			{
				Player val = Target(zDO);
				if ((Object)(object)val == (Object)null)
				{
					Finish(zDO);
					return true;
				}
				if (((BaseAI)this).MoveTo(dt, ((Component)val).transform.position, 1.6f, false) || now - zDO.GetLong("GoodTidings.StageAt", now) > TemperWalk)
				{
					((BaseAI)this).StopMoving();
					SetStage(zDO, 6);
				}
				else
				{
					Unstick(dt, ((Component)val).transform.position);
				}
				return true;
			}
			case 6:
			{
				((BaseAI)this).StopMoving();
				Player val2 = Target(zDO);
				if (Object.op_Implicit((Object)(object)val2))
				{
					((BaseAI)this).LookAt(((Component)val2).transform.position);
				}
				if (now - zDO.GetLong("GoodTidings.StageAt", now) > CraftTime)
				{
					Finish(zDO);
				}
				return true;
			}
			case 8:
				if (!zDO.GetBool("GoodTidings.BandSent", false) && now >= zDO.GetLong("GoodTidings.BandAt", now))
				{
					zDO.Set("GoodTidings.BandSent", true);
					DvergerBand.Call(zDO.GetVec3("GoodTidings.Home", ((Component)this).transform.position));
				}
				break;
			}
			Vector3 vec3 = zDO.GetVec3("GoodTidings.Home", base.m_spawnPoint);
			if ((num2 != 8 || zDO.GetBool("GoodTidings.BandSent", false)) && (Utils.DistanceXZ(((Component)this).transform.position, vec3) > 60f || now > zDO.GetLong("GoodTidings.StageAt", now) + LeaveGrace))
			{
				ZNetScene.instance.Destroy(((Component)this).gameObject);
				return true;
			}
			((BaseAI)this).IdleMovement(dt);
			return true;
		}

		private Player Target(ZDO zdo)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			long id = zdo.GetLong("GoodTidings.Target", 0L);
			Player val = ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)((Player x) => Object.op_Implicit((Object)(object)x) && x.GetPlayerID() == id));
			if (!Object.op_Implicit((Object)(object)val) || !(Vector3.Distance(((Component)val).transform.position, ((Component)this).transform.position) < 40f))
			{
				return null;
			}
			return val;
		}

		private void Finish(ZDO zdo)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			SetStage(zdo, 7);
			Tempered.SendTemper(((Component)this).transform.position);
			HeadAway(zdo);
			Plugin.Log.LogInfo((object)"The wounded Dvergr has tempered the gear of those near: he goes");
		}

		private void Unstick(float dt, Vector3 target)
		{
			//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)
			_progressTimer += dt;
			if (!(_progressTimer < 2f))
			{
				_progressTimer = 0f;
				float num = Vector3.Distance(((Component)this).transform.position, target);
				if (_lastDistance - num < 0.3f)
				{
					OpenDoors();
				}
				_lastDistance = num;
			}
		}

		private void OpenDoors()
		{
			//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_0010: 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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: 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)
			Vector3 val = ((Component)this).transform.position + Vector3.up;
			foreach (Door item in (from c in Physics.OverlapSphere(val, 3f, -1, (QueryTriggerInteraction)2)
				select ((Component)c).GetComponentInParent<Door>() into x
				where (Object)(object)x != (Object)null
				select x).Distinct())
			{
				ZNetView component = ((Component)item).GetComponent<ZNetView>();
				if (!((Object)(object)component == (Object)null) && component.IsValid() && !((Object)(object)item.m_keyItem != (Object)null) && component.GetZDO().GetInt(ZDOVars.s_state, 0) == 0)
				{
					Vector3 forward = ((Component)item).transform.forward;
					Vector3 val2 = ((Component)this).transform.position - ((Component)item).transform.position;
					bool flag = Vector3.Dot(forward, ((Vector3)(ref val2)).normalized) < 0f;
					component.InvokeRPC("UseDoor", new object[1] { flag });
					Plugin.Debug("The wounded Dvergr opens " + ((Object)item).name);
				}
			}
		}

		private void LookForFire(ZDO zdo, float dt)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			_fireSearch -= dt;
			if (!(_fireSearch > 0f))
			{
				_fireSearch = 4f;
				Rest.Find(((Component)this).transform.position, ((Component)this).transform.rotation, base.m_pathAgentType, out var place);
				if (place.ByFire)
				{
					StandUp(zdo);
					GoTo(zdo, place);
					Plugin.Log.LogInfo((object)$"The wounded Dvergr sees a fire: he goes to {place.What} at {place.Spot}");
				}
			}
		}

		private void GoTo(ZDO zdo, Rest.Place place)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			zdo.Set("GoodTidings.Spot", place.Spot);
			zdo.Set("GoodTidings.SpotRot", place.Rotation);
			zdo.Set("GoodTidings.Approach", place.Approach);
			zdo.Set("GoodTidings.Pose", place.Pose);
			zdo.Set("GoodTidings.NoFire", !place.ByFire);
			SetStage(zdo, 2);
		}

		private void Hold(ZDO zdo)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
			Vector3 vec = zdo.GetVec3("GoodTidings.Spot", ((Component)this).transform.position);
			Quaternion quaternion = zdo.GetQuaternion("GoodTidings.SpotRot", ((Component)this).transform.rotation);
			Vector3 val = Vector3.ProjectOnPlane(quaternion * Vector3.forward, Vector3.up);
			if (((Vector3)(ref val)).sqrMagnitude > 0.01f)
			{
				base.m_character.SetLookDir(val, 0f);
			}
			Vector3 val2 = ((Component)this).transform.position - vec;
			if (((Vector3)(ref val2)).sqrMagnitude > 0.0004f || Quaternion.Angle(((Component)this).transform.rotation, quaternion) > 1f)
			{
				Rigidbody component = ((Component)base.m_character).GetComponent<Rigidbody>();
				((Component)this).transform.SetPositionAndRotation(vec, quaternion);
				if (Object.op_Implicit((Object)(object)component))
				{
					component.position = vec;
					component.rotation = quaternion;
					component.velocity = Vector3.zero;
				}
			}
		}

		private void StandUp(ZDO zdo)
		{
			//IL_0022: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			int num = zdo.GetInt("GoodTidings.Stage", 0);
			if (num == 3 || num == 4)
			{
				Vector3 position = zdo.GetVec3("GoodTidings.Approach", ((Component)this).transform.position) + Vector3.up * 0.1f;
				((Component)this).transform.position = position;
				Rigidbody component = ((Component)base.m_character).GetComponent<Rigidbody>();
				if (Object.op_Implicit((Object)(object)component))
				{
					component.position = position;
					component.velocity = Vector3.zero;
				}
			}
		}

		private void HeadAway(ZDO zdo)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			Vector3 vec = zdo.GetVec3("GoodTidings.Home", ((Component)this).transform.position);
			Vector3 val = ((Component)this).transform.position - vec;
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < 1f)
			{
				val = ((Component)this).transform.forward;
			}
			base.m_spawnPoint = vec + ((Vector3)(ref val)).normalized * 90f;
			zdo.Set(ZDOVars.s_spawnPoint, base.m_spawnPoint);
		}

		internal void Help()
		{
			//IL_0022: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			ZDO zDO = base.m_nview.GetZDO();
			if (zDO.GetInt("GoodTidings.Stage", 0) == 1)
			{
				Rest.Find(((Component)this).transform.position, ((Component)this).transform.rotation, base.m_pathAgentType, out var place);
				GoTo(zDO, place);
				Plugin.Log.LogInfo((object)$"The wounded Dvergr was helped up: he goes to {place.What} at {place.Spot}");
			}
		}

		internal void Fed()
		{
			ZDO zDO = base.m_nview.GetZDO();
			if (zDO.GetInt("GoodTidings.Stage", 0) == 3 && !zDO.GetBool("GoodTidings.NoFire", false))
			{
				int num = zDO.GetInt("GoodTidings.Meals", 0) + 1;
				zDO.Set("GoodTidings.Meals", num);
				if (num >= Plugin.DvergerMeals.Value)
				{
					SetStage(zDO, 4);
				}
			}
		}
	}
	internal static class Rest
	{
		internal struct Place
		{
			public Vector3 Spot;

			public Vector3 Approach;

			public Quaternion Rotation;

			public string Pose;

			public string What;

			public bool ByFire;
		}

		internal const float FireSearch = 60f;

		internal const float NearFire = 6f;

		private static readonly FieldInfo AllAreasField = AccessTools.Field(typeof(EffectArea), "s_allAreas");

		private static int _solidMask;

		private static readonly List<Vector3> Path = new List<Vector3>();

		private static int SolidMask
		{
			get
			{
				if (_solidMask == 0)
				{
					return _solidMask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "terrain", "vehicle" });
				}
				return _solidMask;
			}
		}

		private static List<EffectArea> AllAreas()
		{
			return AllAreasField?.GetValue(null) as List<EffectArea>;
		}

		internal static IEnumerable<Fireplace> Fires(Vector3 near, float range)
		{
			//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 e in AllAreas() ?? new List<EffectArea>()
				where Object.op_Implicit((Object)(object)e) && ((Behaviour)e).isActiveAndEnabled && (e.m_type & 1) > 0
				select ((Component)e).GetComponentInParent<Fireplace>() into f
				where (Object)(object)f != (Object)null && f.IsBurning() && Vector3.Distance(((Component)f).transform.position, near) < range
				select f).Distinct();
		}

		internal static void Find(Vector3 from, Quaternion facing, AgentType agent, out Place place, bool furniture = true)
		{
			//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_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_038e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0394: Unknown result type (might be due to invalid IL or missing references)
			//IL_0399: Unknown result type (might be due to invalid IL or missing references)
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03db: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0485: Unknown result type (might be due to invalid IL or missing references)
			//IL_0486: Unknown result type (might be due to invalid IL or missing references)
			//IL_048d: Unknown result type (might be due to invalid IL or missing references)
			//IL_048e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0495: Unknown result type (might be due to invalid IL or missing references)
			//IL_0497: Unknown result type (might be due to invalid IL or missing references)
			//IL_049c: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0414: Unknown result type (might be due to invalid IL or missing references)
			//IL_041b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0420: Unknown result type (might be due to invalid IL or missing references)
			//IL_0425: Unknown result type (might be due to invalid IL or missing references)
			//IL_0428: Unknown result type (might be due to invalid IL or missing references)
			//IL_042d: U