Decompiled source of DiscoverySync v1.0.2

plugins/DiscoverySync.Core.dll

Decompiled a week ago
using System;
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 DiscoverySync.Core.Discovery;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("DiscoverySync.Core")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+069f8eaba8817f3f6f02fac9124e88bf15e3802c")]
[assembly: AssemblyProduct("DiscoverySync.Core")]
[assembly: AssemblyTitle("DiscoverySync.Core")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace DiscoverySync.Core.Persistence
{
	public sealed class WorldDiscoveryData
	{
		[JsonProperty(Order = 1)]
		public int Version { get; set; } = 5;

		[JsonProperty(Order = 2)]
		public List<CharacterConsentRecord> Characters { get; set; } = new List<CharacterConsentRecord>();

		[JsonProperty(Order = 3)]
		[JsonConverter(typeof(DiscoveryMapConverter))]
		public Dictionary<string, int> Discoveries { get; set; } = new Dictionary<string, int>(StringComparer.Ordinal);

		public List<string>? ManualDiscoveriesOnlyCharacters { get; set; }

		public List<string>? AcceptedDiscoveryUpdateCharacters { get; set; }

		public List<string>? PendingDiscoveryConsentCharacters { get; set; }

		public bool ShouldSerializeManualDiscoveriesOnlyCharacters()
		{
			return false;
		}

		public bool ShouldSerializeAcceptedDiscoveryUpdateCharacters()
		{
			return false;
		}

		public bool ShouldSerializePendingDiscoveryConsentCharacters()
		{
			return false;
		}
	}
	public sealed class CharacterConsentRecord
	{
		[JsonProperty(Order = 1)]
		public int Id { get; set; }

		[JsonProperty(Order = 2)]
		public string CharacterName { get; set; } = string.Empty;

		[JsonProperty(Order = 3)]
		public string PlatformId { get; set; } = string.Empty;

		[JsonProperty(Order = 4)]
		[JsonConverter(typeof(StringEnumConverter))]
		public CharacterConsentStatus Status { get; set; }

		[JsonIgnore]
		public string Key => CharacterKey.Create(PlatformId, CharacterName);
	}
	public enum CharacterConsentStatus
	{
		Pending,
		Accepted,
		ManualOnly
	}
	public static class CharacterKey
	{
		public const int MaxPartLength = 128;

		public static string Create(string platformId, string characterName)
		{
			return platformId.Trim() + ":" + characterName.Trim().ToLowerInvariant();
		}

		public static bool IsValidPart(string? value)
		{
			if (value != null && value.Trim().Length > 0)
			{
				return value.Length <= 128;
			}
			return false;
		}
	}
	internal sealed class DiscoveryMapConverter : JsonConverter
	{
		public override bool CanConvert(Type objectType)
		{
			return objectType == typeof(Dictionary<string, int>);
		}

		public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
		{
			//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_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Invalid comparison between Unknown and I4
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Invalid comparison between Unknown and I4
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Invalid comparison between Unknown and I4
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Invalid comparison between Unknown and I4
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Invalid comparison between Unknown and I4
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Invalid comparison between Unknown and I4
			Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.Ordinal);
			JsonToken tokenType = reader.TokenType;
			if ((int)tokenType != 1)
			{
				if ((int)tokenType != 2)
				{
					if ((int)tokenType == 11)
					{
						return null;
					}
					throw new JsonSerializationException($"Unexpected Discoveries value: {reader.TokenType}.");
				}
				while (reader.Read() && (int)reader.TokenType != 14)
				{
					if ((int)reader.TokenType == 9 && reader.Value is string key)
					{
						dictionary[key] = 0;
					}
					else
					{
						reader.Skip();
					}
				}
				return dictionary;
			}
			while (reader.Read() && (int)reader.TokenType == 4)
			{
				string key2 = (string)reader.Value;
				reader.Read();
				long num = (((int)reader.TokenType == 7) ? Convert.ToInt64(reader.Value) : 0);
				dictionary[key2] = (int)((num > 0 && num <= int.MaxValue) ? num : 0);
				if ((int)reader.TokenType == 1 || (int)reader.TokenType == 2)
				{
					reader.Skip();
				}
			}
			return dictionary;
		}

		public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
		{
			writer.WriteStartObject();
			if (value is Dictionary<string, int> dictionary)
			{
				foreach (KeyValuePair<string, int> item in dictionary)
				{
					writer.WritePropertyName(item.Key);
					writer.WriteValue(item.Value);
				}
			}
			writer.WriteEndObject();
		}
	}
	public sealed class WorldDiscoveryStore
	{
		public const int CurrentVersion = 5;

		private readonly string _worldsDirectory;

		private readonly Action<string> _info;

		private readonly Action<string> _warning;

		public WorldDiscoveryStore(string worldsDirectory, Action<string>? info = null, Action<string>? warning = null)
		{
			_worldsDirectory = worldsDirectory ?? throw new ArgumentNullException("worldsDirectory");
			_info = info ?? ((Action<string>)delegate
			{
			});
			_warning = warning ?? ((Action<string>)delegate
			{
			});
		}

		public IReadOnlyList<string> Load(string worldId)
		{
			return LoadState(worldId).Discoveries.Keys.ToList();
		}

		public WorldDiscoveryData LoadState(string worldId)
		{
			//IL_00eb: Expected O, but got Unknown
			string path = GetPath(worldId);
			try
			{
				if (!File.Exists(path))
				{
					_info("No Discovery Sync state exists yet for world '" + worldId + "'.");
					return new WorldDiscoveryData();
				}
				string text = File.ReadAllText(path);
				if (string.IsNullOrWhiteSpace(text))
				{
					_warning("Discovery Sync state for world '" + worldId + "' is empty; starting with no discoveries.");
					return new WorldDiscoveryData();
				}
				WorldDiscoveryData worldDiscoveryData = JsonConvert.DeserializeObject<WorldDiscoveryData>(text);
				if (worldDiscoveryData?.Discoveries == null)
				{
					_warning("Discovery Sync state for world '" + worldId + "' did not contain discoveries; starting empty.");
					return new WorldDiscoveryData();
				}
				worldDiscoveryData.Discoveries = CleanDiscoveries(worldDiscoveryData.Discoveries);
				worldDiscoveryData.Characters = CleanCharacters(worldDiscoveryData.Characters, worldDiscoveryData.Discoveries.Values);
				ReportLegacyCharacters(worldId, worldDiscoveryData);
				worldDiscoveryData.Version = 5;
				return worldDiscoveryData;
			}
			catch (JsonException ex)
			{
				JsonException ex2 = ex;
				_warning("Could not parse Discovery Sync state for world '" + worldId + "': " + ((Exception)(object)ex2).Message);
				return new WorldDiscoveryData();
			}
			catch (IOException ex3)
			{
				_warning("Could not read Discovery Sync state for world '" + worldId + "': " + ex3.Message);
				return new WorldDiscoveryData();
			}
			catch (UnauthorizedAccessException ex4)
			{
				_warning("Could not access Discovery Sync state for world '" + worldId + "': " + ex4.Message);
				return new WorldDiscoveryData();
			}
		}

		public bool Save(string worldId, IEnumerable<string> discoveries)
		{
			WorldDiscoveryData worldDiscoveryData = LoadState(worldId);
			return Save(worldId, WithDiscoverers(discoveries, worldDiscoveryData.Discoveries), worldDiscoveryData.Characters);
		}

		public bool Save(string worldId, IEnumerable<string> discoveries, IEnumerable<CharacterConsentRecord> characters)
		{
			return Save(worldId, WithDiscoverers(discoveries, null), characters);
		}

		public bool Save(string worldId, IReadOnlyDictionary<string, int> discoveries, IEnumerable<CharacterConsentRecord> characters)
		{
			string path = GetPath(worldId);
			try
			{
				Directory.CreateDirectory(_worldsDirectory);
				Dictionary<string, int> dictionary = CleanDiscoveries(discoveries);
				string contents = JsonConvert.SerializeObject((object)new WorldDiscoveryData
				{
					Version = 5,
					Discoveries = dictionary,
					Characters = CleanCharacters(characters, dictionary.Values)
				}, (Formatting)1);
				string text = path + ".tmp";
				File.WriteAllText(text, contents);
				if (File.Exists(path))
				{
					File.Delete(path);
				}
				File.Move(text, path);
				return true;
			}
			catch (IOException ex)
			{
				_warning("Could not save Discovery Sync state for world '" + worldId + "': " + ex.Message);
				return false;
			}
			catch (UnauthorizedAccessException ex2)
			{
				_warning("Could not access Discovery Sync state for world '" + worldId + "': " + ex2.Message);
				return false;
			}
		}

		private static Dictionary<string, int> WithDiscoverers(IEnumerable<string> discoveries, IReadOnlyDictionary<string, int>? known)
		{
			Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.Ordinal);
			foreach (string item in discoveries ?? Enumerable.Empty<string>())
			{
				if (item != null)
				{
					dictionary[item] = ((known != null && known.TryGetValue(item, out var value)) ? value : 0);
				}
			}
			return dictionary;
		}

		private static Dictionary<string, int> CleanDiscoveries(IEnumerable<KeyValuePair<string, int>> discoveries)
		{
			Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.Ordinal);
			foreach (KeyValuePair<string, int> item in discoveries.Where<KeyValuePair<string, int>>((KeyValuePair<string, int> pair) => DiscoveryValidator.IsValidItemId(pair.Key)).OrderBy<KeyValuePair<string, int>, string>((KeyValuePair<string, int> pair) => pair.Key, StringComparer.Ordinal))
			{
				if (!dictionary.ContainsKey(item.Key))
				{
					dictionary[item.Key] = ((item.Value > 0) ? item.Value : 0);
				}
			}
			return dictionary;
		}

		private static List<CharacterConsentRecord> CleanCharacters(IEnumerable<CharacterConsentRecord?>? characters, IEnumerable<int> discovererIds)
		{
			Dictionary<string, CharacterConsentRecord> dictionary = new Dictionary<string, CharacterConsentRecord>(StringComparer.Ordinal);
			foreach (CharacterConsentRecord item in characters ?? Enumerable.Empty<CharacterConsentRecord>())
			{
				if (item != null && CharacterKey.IsValidPart(item.CharacterName) && CharacterKey.IsValidPart(item.PlatformId) && Enum.IsDefined(typeof(CharacterConsentStatus), item.Status))
				{
					int id = item.Id;
					if (id <= 0 && dictionary.TryGetValue(item.Key, out var value))
					{
						id = value.Id;
					}
					dictionary[item.Key] = new CharacterConsentRecord
					{
						Id = id,
						CharacterName = item.CharacterName.Trim(),
						PlatformId = item.PlatformId.Trim(),
						Status = item.Status
					};
				}
			}
			List<CharacterConsentRecord> list = dictionary.Values.OrderBy<CharacterConsentRecord, string>((CharacterConsentRecord record) => record.CharacterName, StringComparer.OrdinalIgnoreCase).ThenBy<CharacterConsentRecord, string>((CharacterConsentRecord record) => record.PlatformId, StringComparer.Ordinal).ToList();
			int num = 1 + Math.Max(list.Select((CharacterConsentRecord record) => record.Id).DefaultIfEmpty(0).Max(), (discovererIds ?? Enumerable.Empty<int>()).DefaultIfEmpty(0).Max());
			HashSet<int> hashSet = new HashSet<int>();
			foreach (CharacterConsentRecord item2 in list.OrderBy((CharacterConsentRecord record) => (record.Id > 0) ? record.Id : int.MaxValue))
			{
				if (item2.Id <= 0 || !hashSet.Add(item2.Id))
				{
					item2.Id = num++;
					hashSet.Add(item2.Id);
				}
			}
			return list;
		}

		private void ReportLegacyCharacters(string worldId, WorldDiscoveryData data)
		{
			int num = (data.ManualDiscoveriesOnlyCharacters?.Count ?? 0) + (data.AcceptedDiscoveryUpdateCharacters?.Count ?? 0);
			data.ManualDiscoveriesOnlyCharacters = null;
			data.AcceptedDiscoveryUpdateCharacters = null;
			data.PendingDiscoveryConsentCharacters = null;
			if (num > 0)
			{
				_info($"World '{worldId}' had {num} character choice(s) saved by an older version that cannot be matched to characters. Those players will be asked again.");
			}
		}

		private string GetPath(string worldId)
		{
			string text = (DiscoveryValidator.IsValidItemId(worldId) ? worldId : "unknown-world");
			return Path.Combine(_worldsDirectory, text + ".json");
		}
	}
}
namespace DiscoverySync.Core.Network
{
	public static class DiscoveryBatch
	{
		public const int MaxItems = 4096;

		public const int SendChunkSize = 512;

		public static bool IsValidCount(int count)
		{
			if (count >= 0)
			{
				return count <= 4096;
			}
			return false;
		}

		public static IReadOnlyList<IReadOnlyList<string>> Split(IReadOnlyList<string> itemIds, int chunkSize = 512)
		{
			if (chunkSize <= 0 || chunkSize > 4096)
			{
				throw new ArgumentOutOfRangeException("chunkSize");
			}
			List<IReadOnlyList<string>> list = new List<IReadOnlyList<string>>();
			if (itemIds == null)
			{
				return list;
			}
			for (int i = 0; i < itemIds.Count; i += chunkSize)
			{
				int num = Math.Min(chunkSize, itemIds.Count - i);
				string[] array = new string[num];
				for (int j = 0; j < num; j++)
				{
					array[j] = itemIds[i + j];
				}
				list.Add(array);
			}
			return list;
		}
	}
	public sealed class DiscoverySnapshot
	{
		public IReadOnlyList<string> ItemIds { get; }

		public DiscoverySnapshot(IEnumerable<string> itemIds)
		{
			ItemIds = (itemIds ?? Enumerable.Empty<string>()).Where(DiscoveryValidator.IsValidItemId).Distinct().OrderBy<string, string>((string value) => value, StringComparer.Ordinal)
				.ToArray();
		}
	}
}
namespace DiscoverySync.Core.Discovery
{
	public static class DiscoveryOriginPolicy
	{
		public static bool ShouldApplyToHost(long sender, bool isNewDiscovery)
		{
			return sender != 0 && isNewDiscovery;
		}
	}
	public sealed class DiscoveryRegistry
	{
		private readonly HashSet<string> _discoveries;

		public int Count => _discoveries.Count;

		public DiscoveryRegistry()
		{
			_discoveries = new HashSet<string>(StringComparer.Ordinal);
		}

		public bool Add(string itemId)
		{
			if (!DiscoveryValidator.IsValidItemId(itemId))
			{
				return false;
			}
			return _discoveries.Add(itemId);
		}

		public IReadOnlyList<string> AddRange(IEnumerable<string> itemIds)
		{
			List<string> list = new List<string>();
			foreach (string item in itemIds ?? Enumerable.Empty<string>())
			{
				if (Add(item))
				{
					list.Add(item);
				}
			}
			return list;
		}

		public bool Contains(string itemId)
		{
			if (DiscoveryValidator.IsValidItemId(itemId))
			{
				return _discoveries.Contains(itemId);
			}
			return false;
		}

		public void ReplaceWith(IEnumerable<string> itemIds)
		{
			_discoveries.Clear();
			foreach (string item in itemIds ?? Enumerable.Empty<string>())
			{
				Add(item);
			}
		}

		public void Clear()
		{
			_discoveries.Clear();
		}

		public IReadOnlyList<string> Snapshot()
		{
			return _discoveries.OrderBy<string, string>((string value) => value, StringComparer.Ordinal).ToArray();
		}
	}
	public static class DiscoveryValidator
	{
		public const int MaxItemIdLength = 128;

		public static bool IsValidItemId(string? itemId)
		{
			if (itemId == null || itemId.Trim().Length == 0)
			{
				return false;
			}
			if (itemId.Length > 128)
			{
				return false;
			}
			foreach (char c in itemId)
			{
				if (!char.IsLetterOrDigit(c) && c != '_' && c != '-' && c != '.')
				{
					return false;
				}
			}
			return true;
		}
	}
}

plugins/DiscoverySync.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DiscoverySync.Core.Discovery;
using DiscoverySync.Core.Network;
using DiscoverySync.Core.Persistence;
using DiscoverySync.Discovery;
using DiscoverySync.Network;
using DiscoverySync.Persistence;
using DiscoverySync.UI;
using HarmonyLib;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("Truncated")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2+069f8eaba8817f3f6f02fac9124e88bf15e3802c")]
[assembly: AssemblyProduct("DiscoverySync")]
[assembly: AssemblyTitle("DiscoverySync")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace DiscoverySync
{
	internal static class ModConfig
	{
		private const string OverallSection = "1 - Overall";

		private const string AdministrationSection = "2 - Administration";

		private const string ServerSettingsSection = "3 - Server Settings";

		private const string ClientSection = "4 - Client";

		private static ConfigFileWatcher? _watcher;

		internal static ConfigEntry<bool> Enabled { get; private set; }

		internal static ConfigEntry<bool> AllowShareKnownItems { get; private set; }

		internal static ConfigEntry<bool> ListKnownEnabled { get; private set; }

		internal static ConfigEntry<bool> ShareKnownItemsAdminOnly { get; private set; }

		internal static ConfigEntry<bool> SharedListAdminOnly { get; private set; }

		internal static ConfigEntry<bool> ServerSetsDebugLogging { get; private set; }

		internal static ConfigEntry<bool> ServerSetsSharedListHotkey { get; private set; }

		internal static ConfigEntry<bool> ServerDebugLogging { get; private set; }

		internal static ConfigEntry<KeyCode> ServerSharedListHotkey { get; private set; }

		internal static ConfigEntry<int> CatchUpSummaryThreshold { get; private set; }

		internal static ConfigEntry<bool> GroupRecipeUnlocks { get; private set; }

		internal static ConfigEntry<KeyCode> SharedListHotkey { get; private set; }

		internal static ConfigEntry<bool> DebugLogging { get; private set; }

		internal static bool EffectiveDebugLogging
		{
			get
			{
				if (((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) || Application.isBatchMode)
				{
					return ServerDebugLogging.Value;
				}
				if (!ServerSetsDebugLogging.Value)
				{
					return DebugLogging.Value;
				}
				return ServerDebugLogging.Value;
			}
		}

		internal static KeyCode EffectiveSharedListHotkey
		{
			get
			{
				//IL_001c: 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)
				if (!ServerSetsSharedListHotkey.Value)
				{
					return SharedListHotkey.Value;
				}
				return ServerSharedListHotkey.Value;
			}
		}

		internal static void Bind(ConfigFile config)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			bool saveOnConfigSet = config.SaveOnConfigSet;
			config.SaveOnConfigSet = false;
			try
			{
				BindEntries(config);
			}
			finally
			{
				config.Save();
				config.SaveOnConfigSet = saveOnConfigSet;
			}
			_watcher = new ConfigFileWatcher(config, 1000L);
			_watcher.OnConfigFileReloaded += delegate
			{
				Plugin.Log.LogInfo((object)"Discovery Sync settings reloaded from the config file.");
			};
		}

		private static void BindEntries(ConfigFile config)
		{
			int num = 100;
			Enabled = config.Bind<bool>("1 - Overall", "Mod Enabled", true, Synced("Turns the whole mod on or off. When on, item discoveries are shared between everyone in the current world. Synced from the server.", num--));
			AllowShareKnownItems = config.Bind<bool>("1 - Overall", "Share Known Items Command Enabled", true, Synced("Allows the 'ds_sharealliknow' command, which adds everything a character already knows to this world's shared discoveries. Synced from the server.", num--));
			ListKnownEnabled = config.Bind<bool>("1 - Overall", "List Known Command Enabled", true, Synced("Allows the 'ds_listknown' command and the List Known Hotkey, which open the List Known window showing everything this world shares. When off, nobody can open it, admins included. Synced from the server.", num--));
			ShareKnownItemsAdminOnly = config.Bind<bool>("2 - Administration", "Restrict Share Known Items Command to Admins", true, Synced("Only players in the server's adminlist.txt (and the host of a local game) can run the 'ds_sharealliknow' command. Synced from the server.", num--));
			SharedListAdminOnly = config.Bind<bool>("2 - Administration", "Restrict List Known Command to Admins", true, Synced("Only players in the server's adminlist.txt (and the host of a local game) can run the 'ds_listknown' command or use the List Known Hotkey. Synced from the server.", num--));
			ServerSetsDebugLogging = config.Bind<bool>("2 - Administration", "Server Sets Debug Logging", false, Synced("When on, every client uses the server's Enable Server Debug Logging value instead of its own Debug Logging setting. While both are on, clients also send this mod's log lines to the server. Synced from the server.", num--));
			ServerSetsSharedListHotkey = config.Bind<bool>("2 - Administration", "Server Sets List Known Hotkey", false, Synced("When on, every client uses the server's Server List Known Hotkey instead of its own List Known Hotkey setting. Synced from the server.", num--));
			ServerDebugLogging = config.Bind<bool>("3 - Server Settings", "Enable Server Debug Logging", false, Synced("Writes detailed Discovery Sync logs to BepInEx\\LogOutput.log on the server. While Server Sets Debug Logging is on, it also turns debug logging on or off for every client. Synced from the server.", num--));
			ServerSharedListHotkey = config.Bind<KeyCode>("3 - Server Settings", "Server List Known Hotkey", (KeyCode)289, Synced("Hotkey that opens or closes the List Known window on every client, only while Server Sets List Known Hotkey is on; ignored otherwise. Set to None to disable it for everyone. Synced from the server.", num--));
			CatchUpSummaryThreshold = config.Bind<int>("4 - Client", "Catch Up Summary Threshold", 20, Local("When more than this many shared discoveries arrive at once (for example when you join a world), skip the individual unlock pop-ups and show one summary instead. Set to 0 to always show every pop-up. Client-only.", num--));
			GroupRecipeUnlocks = config.Bind<bool>("4 - Client", "Group Recipe Unlocks", true, Local("Show one pop-up per crafting station or build tool (for example 'Forge: 23 new recipes') instead of one per recipe or piece. Recipes and pieces learned from a catch-up are announced when you next use that station or equip that tool. Client-only.", num--));
			SharedListHotkey = config.Bind<KeyCode>("4 - Client", "List Known Hotkey", (KeyCode)289, Local("Hotkey to open or close the List Known window. Set to None to disable. The server's List Known settings still decide who can open it. Ignored while the server's Server Sets List Known Hotkey is on. Client-only.", num--));
			DebugLogging = config.Bind<bool>("4 - Client", "Debug Logging", false, Local("Writes detailed Discovery Sync logs to BepInEx\\LogOutput.log on this client only. The server uses Enable Server Debug Logging instead. Ignored while the server's Server Sets Debug Logging is on. Client-only.", num--));
		}

		private static ConfigDescription Synced(string description, int order)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			return new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true,
				Order = order
			} });
		}

		private static ConfigDescription Local(string description, int order)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			return new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				Order = order
			} });
		}
	}
	[BepInPlugin("Truncated.DiscoverySync", "DiscoverySync", "1.0.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	internal sealed class Plugin : BaseUnityPlugin
	{
		private readonly Harmony _harmony = new Harmony("Truncated.DiscoverySync");

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		internal static DiscoveryService Discovery { get; private set; }

		internal static VanillaDiscoveryService VanillaDiscovery { get; private set; }

		internal static DiscoveryNetwork Network { get; private set; }

		internal static DiscoverySessionState Session { get; private set; }

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ModConfig.Bind(((BaseUnityPlugin)this).Config);
			ModLocalization.Initialize();
			WorldDiscoveryStoreAdapter store = new WorldDiscoveryStoreAdapter();
			Session = new DiscoverySessionState();
			Discovery = new DiscoveryService(store);
			VanillaDiscovery = new VanillaDiscoveryService();
			Network = new DiscoveryNetwork(Discovery, VanillaDiscovery);
			((Component)this).gameObject.AddComponent<SharedListWindow>();
			((Component)this).gameObject.AddComponent<DiscoveryConsentPrompt>();
			((Component)this).gameObject.AddComponent<MuninConsentRaven>();
			((Component)this).gameObject.AddComponent<ClientLogRelay>();
			_harmony.PatchAll(typeof(Plugin).Assembly);
			Network.TryRegister();
			Log.LogInfo((object)"DiscoverySync 1.0.2 loaded.");
		}

		private void OnDestroy()
		{
			_harmony.UnpatchSelf();
			ResetSessionState(save: true);
			Log.LogInfo((object)"DiscoverySync unloaded.");
		}

		internal static void ResetSessionState(bool save)
		{
			if (save)
			{
				Discovery.SaveCurrentWorld();
			}
			Session.Reset();
			SharedListWindow.Close();
			DiscoveryConsentPrompt.Close();
			MuninConsentRaven.Reset();
			Discovery.Clear();
			VanillaDiscovery.ClearPending();
			UnlockAnnouncer.Reset();
			Network.ResetSession();
			ClientLogRelay.ResetServerState();
		}

		internal static void DebugLog(string message)
		{
			if (ModConfig.EffectiveDebugLogging)
			{
				Log.LogInfo((object)message);
			}
		}
	}
	internal static class PluginInfo
	{
		public const string Guid = "Truncated.DiscoverySync";

		public const string Name = "DiscoverySync";

		public const string Version = "1.0.2";

		public const string FullVersion = "1.0.2";
	}
}
namespace DiscoverySync.UI
{
	internal sealed class DiscoveryConsentPrompt : MonoBehaviour
	{
		private readonly struct ChoiceButton
		{
			public RectTransform Rect { get; }

			public float RequiredHeight { get; }

			public ChoiceButton(RectTransform rect, float requiredHeight)
			{
				Rect = rect;
				RequiredHeight = requiredHeight;
			}
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static UnityAction <>9__40_0;

			public static UnityAction <>9__40_1;

			internal void <CreatePrompt>b__40_0()
			{
				MuninConsentRaven.SubmitChoice(manualOnly: false);
			}

			internal void <CreatePrompt>b__40_1()
			{
				MuninConsentRaven.SubmitChoice(manualOnly: true);
			}
		}

		private const float PromptWidth = 620f;

		private const float PromptHeight = 380f;

		private const float MinPromptHeight = 240f;

		private const float PanelTopPadding = 24f;

		private const float PanelBottomPadding = 28f;

		private const float TextSideMargin = 40f;

		private const float TitleSideMargin = 24f;

		private const float SectionGap = 14f;

		private const float ButtonsTopExtraGap = 8f;

		private const float TitleHeight = 44f;

		private const int TitleFontSize = 30;

		private const int BodyFontSize = 20;

		private const int FootnoteFontSize = 16;

		private const float OverlayOpacity = 0.62f;

		private const float ButtonWidth = 200f;

		private const float ButtonMinHeight = 46f;

		private const float ButtonGap = 20f;

		private const float ButtonLabelPadding = 5f;

		private const int ButtonFontSize = 18;

		private static readonly Color ButtonTextColor = new Color(1f, 93f / 145f, 0f, 1f);

		private const string ButtonSprite = "button";

		private const string ButtonHighlightSprite = "button_highlight";

		private const string ButtonPressedSprite = "button_pressed";

		private const string ButtonDisabledSprite = "button_disabled";

		private const string ButtonClickSound = "sfx_gui_button";

		private const string ButtonClickVibration = "sfx_gui_button_vibrateonly_medium";

		private static DiscoveryConsentPrompt? _instance;

		private bool _visible;

		private bool _cursorStateCaptured;

		private bool _inputBlocked;

		private bool _previousCursorVisible;

		private CursorLockMode _previousCursorLockState;

		private Transform? _guiParent;

		private GameObject? _promptRoot;

		private static GameObject? _clickSound;

		private static GameObject? _clickVibration;

		public static void Show()
		{
			//IL_002e: 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)
			if (!((Object)(object)_instance == (Object)null))
			{
				if (!_instance._visible)
				{
					_instance._previousCursorVisible = Cursor.visible;
					_instance._previousCursorLockState = Cursor.lockState;
					_instance._cursorStateCaptured = true;
				}
				_instance._visible = true;
				_instance.EnableCursor();
				_instance.EnsurePrompt();
				_instance.SetPromptActive(active: true);
			}
		}

		public static void Close()
		{
			if (!((Object)(object)_instance == (Object)null))
			{
				_instance._visible = false;
				_instance.SetPromptActive(active: false);
				_instance.SetInputBlocked(blocked: false);
				_instance.RestoreCursor();
			}
		}

		private void Awake()
		{
			_instance = this;
		}

		private void OnDestroy()
		{
			SetInputBlocked(blocked: false);
			RestoreCursor();
			if ((Object)(object)_promptRoot != (Object)null)
			{
				Object.Destroy((Object)(object)_promptRoot);
				_promptRoot = null;
			}
			if ((Object)(object)_instance == (Object)(object)this)
			{
				_instance = null;
			}
		}

		private void LateUpdate()
		{
			if (_visible)
			{
				EnableCursor();
				EnsurePrompt();
				SetPromptActive(active: true);
			}
		}

		private void EnsurePrompt()
		{
			Transform val = (((Object)(object)GUIManager.CustomGUIFront != (Object)null) ? GUIManager.CustomGUIFront.transform : null);
			if (!((Object)(object)val == (Object)null) && (!((Object)(object)_promptRoot != (Object)null) || !((Object)(object)_guiParent == (Object)(object)val)))
			{
				if ((Object)(object)_promptRoot != (Object)null)
				{
					Object.Destroy((Object)(object)_promptRoot);
				}
				_guiParent = val;
				_promptRoot = CreatePrompt(val);
				_promptRoot.SetActive(_visible);
			}
		}

		private static GameObject CreatePrompt(Transform parent)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//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_0044: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: 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_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: 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)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Expected O, but got Unknown
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Expected O, but got Unknown
			GameObject val = new GameObject("DiscoverySyncConsentPrompt", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent(parent, false);
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchorMin = Vector2.zero;
			val2.anchorMax = Vector2.one;
			val2.offsetMin = Vector2.zero;
			val2.offsetMax = Vector2.zero;
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = new Color(0f, 0f, 0f, 0.62f);
			((Graphic)component).raycastTarget = true;
			GUIManager instance = GUIManager.Instance;
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			GameObject val4 = instance.CreateWoodpanel(val.transform, val3, val3, Vector2.zero, 620f, 380f, false);
			RectTransform val5 = (RectTransform)val4.transform;
			float width = 540f;
			float num = 572f;
			Text component2 = instance.CreateText(ModLocalization.Get("consent_title"), val4.transform, Vector2.zero, Vector2.zero, Vector2.zero, instance.AveriaSerifBold, 30, instance.ValheimOrange, true, Color.black, num, 44f, false).GetComponent<Text>();
			component2.alignment = (TextAnchor)4;
			component2.horizontalOverflow = (HorizontalWrapMode)1;
			Text val6 = CreateWrappedText(instance, ModLocalization.Get("consent_body"), val4.transform, 20, width);
			Text val7 = CreateWrappedText(instance, ModLocalization.Get("consent_footnote"), val4.transform, 16, width);
			string label = ModLocalization.Get("consent_yes");
			Transform transform = val4.transform;
			object obj = <>c.<>9__40_0;
			if (obj == null)
			{
				UnityAction val8 = delegate
				{
					MuninConsentRaven.SubmitChoice(manualOnly: false);
				};
				<>c.<>9__40_0 = val8;
				obj = (object)val8;
			}
			ChoiceButton choiceButton = CreateChoiceButton(instance, label, transform, (UnityAction)obj);
			string label2 = ModLocalization.Get("consent_no");
			Transform transform2 = val4.transform;
			object obj2 = <>c.<>9__40_1;
			if (obj2 == null)
			{
				UnityAction val9 = delegate
				{
					MuninConsentRaven.SubmitChoice(manualOnly: true);
				};
				<>c.<>9__40_1 = val9;
				obj2 = (object)val9;
			}
			ChoiceButton choiceButton2 = CreateChoiceButton(instance, label2, transform2, (UnityAction)obj2);
			float num2 = Mathf.Max(choiceButton.RequiredHeight, choiceButton2.RequiredHeight);
			float num3 = 110f;
			float num4 = 24f;
			PlaceAtTop(((Graphic)component2).rectTransform, 0f, num4, num, 44f);
			num4 += 58f;
			float num5 = PreferredHeight(val6, width);
			PlaceAtTop(((Graphic)val6).rectTransform, 0f, num4, width, num5);
			num4 += num5 + 14f + 8f;
			PlaceAtTop(choiceButton.Rect, 0f - num3, num4, 200f, num2);
			PlaceAtTop(choiceButton2.Rect, num3, num4, 200f, num2);
			num4 += num2 + 14f;
			float num6 = PreferredHeight(val7, width);
			PlaceAtTop(((Graphic)val7).rectTransform, 0f, num4, width, num6);
			num4 += num6 + 28f;
			val5.SetSizeWithCurrentAnchors((Axis)1, Mathf.Max(num4, 240f));
			return val;
		}

		private static Text CreateWrappedText(GUIManager gui, string value, Transform parent, int fontSize, float width)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			Text component = gui.CreateText(value, parent, Vector2.zero, Vector2.zero, Vector2.zero, gui.AveriaSerif, fontSize, gui.ValheimBeige, true, Color.black, width, (float)fontSize * 2f, false).GetComponent<Text>();
			component.alignment = (TextAnchor)4;
			component.horizontalOverflow = (HorizontalWrapMode)0;
			component.verticalOverflow = (VerticalWrapMode)1;
			return component;
		}

		private static float PreferredHeight(Text text, float width)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			TextGenerationSettings generationSettings = text.GetGenerationSettings(new Vector2(width, 0f));
			return Mathf.Ceil(text.cachedTextGeneratorForLayout.GetPreferredHeight(text.text, generationSettings) / text.pixelsPerUnit);
		}

		private static void PlaceAtTop(RectTransform rect, float x, float top, float width, float height)
		{
			//IL_0012: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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)
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0.5f, 1f);
			rect.anchorMin = val;
			rect.anchorMax = val;
			rect.pivot = val;
			rect.sizeDelta = new Vector2(width, height);
			rect.anchoredPosition = new Vector2(x, 0f - top);
		}

		private static ChoiceButton CreateChoiceButton(GUIManager gui, string label, Transform parent, UnityAction onClick)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Expected O, but got Unknown
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: 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_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = gui.CreateButton(label, parent, Vector2.zero, Vector2.zero, Vector2.zero, 200f, 46f);
			((Object)obj).name = "DiscoverySyncChoiceButton";
			Image component = obj.GetComponent<Image>();
			SetSprite(gui, component, "button");
			component.type = (Type)1;
			component.pixelsPerUnitMultiplier = 1f;
			((Graphic)component).color = Color.white;
			Button component2 = obj.GetComponent<Button>();
			((Selectable)component2).transition = (Transition)2;
			SpriteState spriteState = ((Selectable)component2).spriteState;
			((SpriteState)(ref spriteState)).highlightedSprite = SpriteOr(gui, "button_highlight", ((SpriteState)(ref spriteState)).highlightedSprite);
			((SpriteState)(ref spriteState)).selectedSprite = ((SpriteState)(ref spriteState)).highlightedSprite;
			((SpriteState)(ref spriteState)).pressedSprite = SpriteOr(gui, "button_pressed", ((SpriteState)(ref spriteState)).pressedSprite);
			((SpriteState)(ref spriteState)).disabledSprite = SpriteOr(gui, "button_disabled", ((SpriteState)(ref spriteState)).disabledSprite);
			((Selectable)component2).spriteState = spriteState;
			((UnityEvent)component2.onClick).AddListener(onClick);
			AddClickSound(obj);
			Text componentInChildren = obj.GetComponentInChildren<Text>(true);
			float width = 190f;
			float num = 46f;
			if ((Object)(object)componentInChildren != (Object)null)
			{
				gui.ApplyTextStyle(componentInChildren, gui.AveriaSerifBold, ButtonTextColor, 18, true);
				componentInChildren.alignment = (TextAnchor)4;
				componentInChildren.resizeTextForBestFit = false;
				componentInChildren.horizontalOverflow = (HorizontalWrapMode)0;
				componentInChildren.verticalOverflow = (VerticalWrapMode)1;
				RectTransform rectTransform = ((Graphic)componentInChildren).rectTransform;
				rectTransform.anchorMin = Vector2.zero;
				rectTransform.anchorMax = Vector2.one;
				rectTransform.pivot = new Vector2(0.5f, 0.5f);
				rectTransform.offsetMin = new Vector2(5f, 5f);
				rectTransform.offsetMax = new Vector2(-5f, -5f);
				num = Mathf.Max(num, PreferredHeight(componentInChildren, width) + 10f);
			}
			return new ChoiceButton((RectTransform)obj.transform, num);
		}

		private static void SetSprite(GUIManager gui, Image image, string spriteName)
		{
			Sprite sprite = gui.GetSprite(spriteName);
			if ((Object)(object)sprite != (Object)null)
			{
				image.sprite = sprite;
			}
		}

		private static Sprite SpriteOr(GUIManager gui, string spriteName, Sprite fallback)
		{
			Sprite sprite = gui.GetSprite(spriteName);
			if (!((Object)(object)sprite != (Object)null))
			{
				return fallback;
			}
			return sprite;
		}

		private static void AddClickSound(GameObject buttonObject)
		{
			if ((Object)(object)_clickSound == (Object)null)
			{
				ButtonSfx[] array = Resources.FindObjectsOfTypeAll<ButtonSfx>();
				foreach (ButtonSfx val in array)
				{
					if ((Object)(object)val.m_sfxPrefab != (Object)null && ((Object)val.m_sfxPrefab).name == "sfx_gui_button")
					{
						_clickSound = val.m_sfxPrefab;
						if ((Object)(object)val.m_sfxPrefabVibrationOnly != (Object)null && ((Object)val.m_sfxPrefabVibrationOnly).name == "sfx_gui_button_vibrateonly_medium")
						{
							_clickVibration = val.m_sfxPrefabVibrationOnly;
						}
						break;
					}
				}
			}
			if (!((Object)(object)_clickSound == (Object)null))
			{
				ButtonSfx val2 = buttonObject.GetComponent<ButtonSfx>();
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = buttonObject.AddComponent<ButtonSfx>();
				}
				val2.m_sfxPrefab = _clickSound;
				val2.m_sfxPrefabVibrationOnly = _clickVibration;
			}
		}

		private void SetPromptActive(bool active)
		{
			if ((Object)(object)_promptRoot != (Object)null && _promptRoot.activeSelf != active)
			{
				_promptRoot.SetActive(active);
			}
			SetInputBlocked(active && (Object)(object)_promptRoot != (Object)null);
		}

		private void SetInputBlocked(bool blocked)
		{
			if (_inputBlocked != blocked)
			{
				GUIManager.BlockInput(blocked);
				_inputBlocked = blocked;
			}
		}

		private void EnableCursor()
		{
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
		}

		private void RestoreCursor()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (_cursorStateCaptured)
			{
				Cursor.lockState = _previousCursorLockState;
				Cursor.visible = _previousCursorVisible;
				_cursorStateCaptured = false;
			}
		}
	}
	internal static class ModLocalization
	{
		private const string TokenPrefix = "$ds_";

		private const string FilePrefix = "DiscoverySync-";

		private const string EnglishLanguage = "English";

		private static readonly Dictionary<string, string> LanguageCodes = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
		{
			{ "English", "en" },
			{ "French", "fr" },
			{ "German", "de" },
			{ "Italian", "it" },
			{ "Spanish", "es" },
			{ "Russian", "ru" },
			{ "Turkish", "tr" },
			{ "Polish", "pl" },
			{ "Ukrainian", "uk" },
			{ "Japanese", "ja" },
			{ "Korean", "ko" },
			{ "Portuguese_Brazilian", "pt-BR" },
			{ "Chinese", "zh-Hans" },
			{ "Chinese_Trad", "zh-Hant" }
		};

		private static readonly HashSet<string> Loaded = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private static string? _translationsDirectory;

		public static void Initialize()
		{
			if (Application.isBatchMode)
			{
				Plugin.Log.LogInfo((object)"Dedicated server: Discovery Sync translations are not loaded.");
				return;
			}
			_translationsDirectory = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? throw new InvalidOperationException("Could not locate the Discovery Sync plugin directory."), "Translations");
			if (!EnsureLanguage("English"))
			{
				Plugin.Log.LogError((object)("Discovery Sync English localization file was not found: " + FilePath("en")));
			}
			EnsureLanguage(PlayerPrefs.GetString("language", "English"));
		}

		internal static bool EnsureLanguage(string? language)
		{
			if (_translationsDirectory == null || string.IsNullOrEmpty(language))
			{
				return false;
			}
			if (Loaded.Contains(language))
			{
				return true;
			}
			if (!LanguageCodes.TryGetValue(language, out string value))
			{
				Plugin.DebugLog("No Discovery Sync translation for '" + language + "'; English is used.");
				return false;
			}
			string text = FilePath(value);
			if (!File.Exists(text))
			{
				Plugin.Log.LogWarning((object)("Discovery Sync translation file is missing, English is used: " + text));
				return false;
			}
			try
			{
				LocalizationManager.Instance.GetLocalization().AddJsonFile(language, File.ReadAllText(text));
				Loaded.Add(language);
				Plugin.Log.LogInfo((object)("Loaded Discovery Sync translation '" + Path.GetFileName(text) + "' for " + language + "."));
				return true;
			}
			catch (IOException ex)
			{
				Plugin.Log.LogError((object)("Could not read Discovery Sync localization file '" + text + "': " + ex.Message));
			}
			catch (UnauthorizedAccessException ex2)
			{
				Plugin.Log.LogError((object)("Could not access Discovery Sync localization file '" + text + "': " + ex2.Message));
			}
			return false;
		}

		public static string Get(string key)
		{
			return LocalizationManager.Instance.GetLocalization().TryTranslate("$ds_" + key);
		}

		public static string Format(string key, params object[] values)
		{
			return string.Format(CultureInfo.CurrentCulture, Get(key), values);
		}

		private static string FilePath(string code)
		{
			return Path.Combine(_translationsDirectory, "DiscoverySync-" + code + ".json");
		}
	}
	internal sealed class MuninConsentRaven : MonoBehaviour
	{
		private const float FarewellSeconds = 2.5f;

		private static MuninConsentRaven? _instance;

		private RavenText? _welcomeText;

		private Raven? _raven;

		private Raven? _traceRaven;

		private string? _worldId;

		private Vector3 _departurePosition;

		private string? _lastTraceName;

		private RavenText? _lastTraceText;

		private bool _originalMuninState;

		private string? _originalRavenName;

		private bool _ravenIdentityCaptured;

		private bool _promptOpen;

		private bool _awaitingChoice;

		private bool _farewellShowing;

		private bool _changingMind;

		private bool _departureInProgress;

		private bool _suppressRavenTextUntilPlayerLeaves;

		private bool _ravenSuppressionLogged;

		private bool _hasTraceState;

		private bool _hasCanHideTrace;

		private bool _lastCanHideAllowed;

		private bool _lastTraceIsMunin;

		private bool _lastTraceSpawned;

		private bool _lastTraceFlying;

		private bool _lastTraceAway;

		private bool _lastTraceHasTalked;

		private bool _lastTraceDialogVisible;

		private float _farewellClearAt;

		private bool _missingPrefabWarningShown;

		private string GreetingKey
		{
			get
			{
				if (!_changingMind)
				{
					return "munin_welcome";
				}
				return "munin_changemind_welcome";
			}
		}

		public static void QueueWelcome(string worldId)
		{
			if ((Object)(object)_instance == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Could not queue Munin's discovery welcome: its controller is unavailable.");
			}
			else
			{
				_instance.BeginWelcome(worldId, changingMind: false);
			}
		}

		public static void QueueChangeMind(string worldId)
		{
			if ((Object)(object)_instance == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Could not call Munin to change the discovery choice: his controller is unavailable.");
			}
			else if (!_instance._promptOpen && !_instance._awaitingChoice && (_instance._welcomeText == null || _instance._changingMind || !(_instance._worldId == worldId)))
			{
				_instance.BeginWelcome(worldId, changingMind: true);
			}
		}

		public static void TraceRavenUpdate(Raven raven, RavenText? currentText, bool hasTalked, Animator? animator)
		{
			if ((Object)(object)_instance == (Object)null || (Object)(object)_instance._traceRaven != (Object)(object)raven)
			{
				return;
			}
			bool isMunin = raven.m_isMunin;
			bool flag = IsInAnimatorState(animator, "visible");
			bool flag2 = IsInAnimatorState(animator, "flying");
			bool flag3 = IsInAnimatorState(animator, "away");
			bool flag4 = (Object)(object)Chat.instance != (Object)null && Chat.instance.IsDialogVisible(((Component)raven).gameObject);
			string name = raven.m_name;
			bool flag5 = _instance._lastTraceSpawned || _instance._lastTraceFlying;
			if (!_instance._hasTraceState || _instance._lastTraceIsMunin != isMunin || _instance._lastTraceSpawned != flag || _instance._lastTraceFlying != flag2 || _instance._lastTraceAway != flag3 || _instance._lastTraceHasTalked != hasTalked || _instance._lastTraceDialogVisible != flag4 || _instance._lastTraceText != currentText || _instance._lastTraceName != name)
			{
				string text = ((currentText == null) ? "<none>" : currentText.m_key);
				bool flag6 = currentText?.m_munin ?? false;
				Plugin.DebugLog($"Munin Raven trace: name='{name}', munin={isMunin}, spawned={flag}, flying={flag2}, away={flag3}, animatorReady={(Object)(object)animator != (Object)null && animator.isInitialized}, hasTalked={hasTalked}, dialogVisible={flag4}, textKey='{text}', textMunin={flag6}, promptOpen={_instance._promptOpen}, farewellShowing={_instance._farewellShowing}.");
				_instance._hasTraceState = true;
				_instance._lastTraceIsMunin = isMunin;
				_instance._lastTraceSpawned = flag;
				_instance._lastTraceFlying = flag2;
				_instance._lastTraceAway = flag3;
				_instance._lastTraceHasTalked = hasTalked;
				_instance._lastTraceDialogVisible = flag4;
				_instance._lastTraceText = currentText;
				_instance._lastTraceName = name;
			}
			if (flag3 && flag5)
			{
				if (_instance._departureInProgress)
				{
					_instance.CompleteConsentDeparture(raven);
					return;
				}
				_instance._traceRaven = null;
				_instance._hasTraceState = false;
			}
		}

		public static void TraceCanHide(Raven raven, bool allowed)
		{
			if (!((Object)(object)_instance == (Object)null) && !((Object)(object)_instance._traceRaven != (Object)(object)raven) && (!_instance._hasCanHideTrace || _instance._lastCanHideAllowed != allowed))
			{
				Plugin.DebugLog($"Munin Raven CanHide result changed: allowed={allowed}, promptOpen={_instance._promptOpen}, farewellVisible={_instance.IsFarewellVisible(raven)}, farewellShowing={_instance._farewellShowing}.");
				_instance._hasCanHideTrace = true;
				_instance._lastCanHideAllowed = allowed;
			}
		}

		public static bool TryGetWelcomeText(Raven raven, ref RavenText result)
		{
			if ((Object)(object)_instance == (Object)null)
			{
				return false;
			}
			if (_instance.ShouldSuppressRavenText(raven))
			{
				result = null;
				return true;
			}
			if (_instance._welcomeText == null)
			{
				return false;
			}
			if ((Object)(object)_instance._raven != (Object)null && (Object)(object)_instance._raven != (Object)(object)raven)
			{
				result = null;
				return true;
			}
			_instance.PrepareRaven(raven);
			result = _instance._welcomeText;
			return true;
		}

		public static bool HandleWelcomeTalk(Raven raven, RavenText? currentText)
		{
			if ((Object)(object)_instance == (Object)null || _instance._welcomeText == null || _instance._welcomeText != currentText)
			{
				return false;
			}
			if (_instance._promptOpen)
			{
				Plugin.DebugLog("Munin consent interaction received while the consent prompt is already open.");
				return true;
			}
			_instance.PrepareRaven(raven);
			_instance._promptOpen = true;
			Plugin.DebugLog("Munin consent interaction opened the discovery consent prompt.");
			_instance.Say(raven, ModLocalization.Get(_instance.GreetingKey));
			DiscoveryConsentPrompt.Show();
			return true;
		}

		public static bool ShouldKeepRavenAvailable(Raven raven)
		{
			if ((Object)(object)_instance != (Object)null && (Object)(object)_instance._raven == (Object)(object)raven)
			{
				if (!_instance._promptOpen)
				{
					return _instance.IsFarewellVisible(raven);
				}
				return true;
			}
			return false;
		}

		public static bool AllowFlyAway(Raven raven)
		{
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_instance == (Object)null || (Object)(object)_instance._raven != (Object)(object)raven)
			{
				return true;
			}
			if (_instance._promptOpen || _instance.IsFarewellVisible(raven))
			{
				Plugin.DebugLog($"Blocked Raven FlyAway: promptOpen={_instance._promptOpen}, farewellVisible={_instance.IsFarewellVisible(raven)}, welcomePending={_instance._welcomeText != null}.");
				return false;
			}
			if (_instance._welcomeText != null)
			{
				Plugin.DebugLog("Allowed Raven FlyAway while consent welcome text is pending.");
				return true;
			}
			if (_instance._departureInProgress)
			{
				return true;
			}
			if (_instance._farewellShowing)
			{
				_instance._departureInProgress = true;
				_instance._departurePosition = ((Component)raven).transform.position;
				_instance._ravenSuppressionLogged = false;
				Plugin.DebugLog($"Starting Munin departure while preserving his identity through flight at {_instance._departurePosition}.");
				return true;
			}
			Plugin.DebugLog($"Allowed Raven FlyAway outside the consent farewell: dialogVisible={(Object)(object)Chat.instance != (Object)null && Chat.instance.IsDialogVisible(((Component)raven).gameObject)}, name='{raven.m_name}', munin={raven.m_isMunin}.");
			_instance.RestoreRavenIdentity();
			_instance._raven = null;
			_instance._farewellShowing = false;
			return true;
		}

		public static void SubmitChoice(bool manualOnly)
		{
			if (!((Object)(object)_instance == (Object)null) && _instance._promptOpen && !_instance._awaitingChoice)
			{
				_instance._awaitingChoice = true;
				Plugin.DebugLog($"Munin consent choice submitted: manualOnly={manualOnly}.");
				if (!Plugin.Network.SetManualDiscoveriesOnly(manualOnly))
				{
					_instance._awaitingChoice = false;
					Plugin.Log.LogWarning((object)"Could not send the discovery consent choice because the network is unavailable.");
				}
			}
		}

		public static void ReceiveConsentStatus(bool accepted)
		{
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: 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_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Expected O, but got Unknown
			if ((Object)(object)_instance == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Received a Munin consent result, but the Raven controller is unavailable.");
				return;
			}
			Plugin.DebugLog($"Munin consent result received: accepted={accepted}, awaitingChoice={_instance._awaitingChoice}, ravenAvailable={(Object)(object)_instance._raven != (Object)null}.");
			if (!_instance._awaitingChoice)
			{
				_instance.ClearWelcome();
				return;
			}
			_instance._awaitingChoice = false;
			_instance._promptOpen = false;
			DiscoveryConsentPrompt.Close();
			if ((Object)(object)_instance._raven == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Could not show Munin's farewell because the raven is no longer available.");
				_instance.ClearWelcome();
				return;
			}
			Raven raven = _instance._raven;
			if ((Object)(object)Chat.instance != (Object)null)
			{
				Chat.instance.ClearNpcText(((Component)raven).gameObject);
			}
			_instance._welcomeText = null;
			_instance._farewellShowing = true;
			Plugin.DebugLog($"Showing Munin consent farewell: accepted={accepted}, name='{raven.m_name}', munin={raven.m_isMunin}.");
			string key = ((!_instance._changingMind) ? (accepted ? "munin_accept" : "munin_decline") : (accepted ? "munin_changemind_accept" : "munin_changemind_decline"));
			_instance._changingMind = false;
			RavenText value = new RavenText
			{
				m_key = string.Empty,
				m_topic = string.Empty,
				m_text = ModLocalization.Get(key),
				m_label = string.Empty,
				m_static = false,
				m_isTutorial = true,
				m_munin = true,
				m_priority = int.MaxValue,
				m_alwaysSpawn = false
			};
			FieldInfo fieldInfo = AccessTools.Field(typeof(Raven), "m_currentText");
			MethodInfo methodInfo = AccessTools.Method(typeof(Raven), "Talk", (Type[])null, (Type[])null);
			if (fieldInfo == null || methodInfo == null)
			{
				Plugin.Log.LogWarning((object)"Could not display Munin's farewell because Raven's dialogue members were not found.");
				_instance.ClearWelcome();
				return;
			}
			fieldInfo.SetValue(raven, value);
			float num = Mathf.Min(raven.m_dialogVisibleTime, 2.5f);
			float longDialogVisibleTime = raven.m_longDialogVisibleTime;
			try
			{
				raven.m_longDialogVisibleTime = num;
				methodInfo.Invoke(raven, null);
			}
			finally
			{
				raven.m_longDialogVisibleTime = longDialogVisibleTime;
			}
			_instance._farewellClearAt = Time.unscaledTime + num;
			Plugin.DebugLog($"Munin farewell displayed: dialogVisible={(Object)(object)Chat.instance != (Object)null && Chat.instance.IsDialogVisible(((Component)raven).gameObject)}, duration={num:0.##}s.");
		}

		public static void ReceiveConsentFailure()
		{
			if (!((Object)(object)_instance == (Object)null) && _instance._awaitingChoice)
			{
				_instance._awaitingChoice = false;
				Plugin.Log.LogWarning((object)"The server could not save the discovery consent choice. The prompt remains open so you can retry.");
			}
		}

		public static void Reset()
		{
			if ((Object)(object)_instance != (Object)null)
			{
				_instance.ClearWelcome();
			}
		}

		private void Awake()
		{
			_instance = this;
		}

		private void OnDestroy()
		{
			ClearWelcome();
			if ((Object)(object)_instance == (Object)(object)this)
			{
				_instance = null;
			}
		}

		private void LateUpdate()
		{
			if (_welcomeText != null)
			{
				EnsureRavenExists();
			}
			if (_farewellShowing && (Object)(object)_raven != (Object)null && _farewellClearAt > 0f && Time.unscaledTime >= _farewellClearAt)
			{
				_farewellClearAt = 0f;
				if ((Object)(object)Chat.instance == (Object)null)
				{
					Plugin.Log.LogWarning((object)"Could not finish Munin's farewell because the chat system is unavailable.");
					return;
				}
				Plugin.DebugLog($"Munin consent farewell timer elapsed: dialogVisible={Chat.instance.IsDialogVisible(((Component)_raven).gameObject)}, hasTalked={GetHasTalked(_raven)}. Clearing dialogue for Valheim's normal Raven departure.");
				Chat.instance.ClearNpcText(((Component)_raven).gameObject);
			}
		}

		private void BeginWelcome(string worldId, bool changingMind)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Expected O, but got Unknown
			if (_welcomeText == null || !(_worldId == worldId) || _changingMind != changingMind)
			{
				ClearWelcome();
				_worldId = worldId;
				_changingMind = changingMind;
				Plugin.DebugLog(changingMind ? ("Queued Munin change-of-mind visit for world UID " + worldId + ".") : ("Queued Munin discovery welcome for world UID " + worldId + "."));
				_welcomeText = new RavenText
				{
					m_key = (changingMind ? ("DiscoverySync_ChangeMind_" + worldId) : ("DiscoverySync_Consent_" + worldId)),
					m_topic = string.Empty,
					m_text = ModLocalization.Get(GreetingKey),
					m_label = string.Empty,
					m_static = false,
					m_isTutorial = false,
					m_munin = true,
					m_priority = int.MaxValue,
					m_alwaysSpawn = false
				};
				EnsureRavenExists();
			}
		}

		private void EnsureRavenExists()
		{
			//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)
			if (_welcomeText == null || Raven.IsInstantiated())
			{
				return;
			}
			Tutorial instance = Tutorial.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_ravenPrefab == (Object)null)
			{
				if (!_missingPrefabWarningShown)
				{
					Plugin.Log.LogWarning((object)"Munin's discovery welcome is waiting for Valheim's raven prefab.");
					_missingPrefabWarningShown = true;
				}
			}
			else
			{
				Object.Instantiate<GameObject>(instance.m_ravenPrefab, Vector3.zero, Quaternion.identity);
			}
		}

		private void PrepareRaven(Raven raven)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_raven == (Object)null)
			{
				_raven = raven;
				_traceRaven = raven;
				_hasTraceState = false;
				_hasCanHideTrace = false;
				_originalMuninState = raven.m_isMunin;
				_originalRavenName = raven.m_name;
				_ravenIdentityCaptured = true;
				Plugin.DebugLog($"Assigned Raven for Munin consent: originalName='{_originalRavenName}', originalMunin={_originalMuninState}, position={((Component)raven).transform.position}.");
			}
			raven.m_isMunin = true;
			raven.m_name = "$npc_munin";
		}

		private bool ShouldSuppressRavenText(Raven raven)
		{
			//IL_003f: 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)
			if ((Object)(object)_raven != (Object)(object)raven || (!_departureInProgress && !_suppressRavenTextUntilPlayerLeaves))
			{
				return false;
			}
			if (_suppressRavenTextUntilPlayerLeaves && (Object)(object)Player.m_localPlayer != (Object)null && Vector3.Distance(((Component)Player.m_localPlayer).transform.position, _departurePosition) > raven.m_despawnDistance)
			{
				Plugin.DebugLog("Player left Munin's departure area; restoring the Raven's normal text selection.");
				_suppressRavenTextUntilPlayerLeaves = false;
				_ravenSuppressionLogged = false;
				_raven = null;
				_traceRaven = null;
				_hasTraceState = false;
				_hasCanHideTrace = false;
				return false;
			}
			if (!_ravenSuppressionLogged)
			{
				Plugin.DebugLog($"Suppressing Raven text while Munin departs; departureInProgress={_departureInProgress}, waitingForPlayerToLeave={_suppressRavenTextUntilPlayerLeaves}.");
				_ravenSuppressionLogged = true;
			}
			return true;
		}

		private void CompleteConsentDeparture(Raven raven)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			Plugin.DebugLog($"Munin completed his departure: name='{raven.m_name}', munin={raven.m_isMunin}, position={((Component)raven).transform.position}. Keeping Raven text suppressed until the player leaves the departure area.");
			RestoreRavenIdentity();
			_departureInProgress = false;
			_suppressRavenTextUntilPlayerLeaves = true;
			_farewellShowing = false;
			_traceRaven = null;
			_hasTraceState = false;
		}

		private static bool GetHasTalked(Raven raven)
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(Raven), "m_hasTalked");
			if (fieldInfo == null)
			{
				Plugin.Log.LogWarning((object)"Could not trace Raven.m_hasTalked because the game field was not found.");
				return false;
			}
			return (bool)fieldInfo.GetValue(raven);
		}

		private static bool IsInAnimatorState(Animator? animator, string tag)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if ((Object)(object)animator == (Object)null || !animator.isInitialized)
			{
				return false;
			}
			AnimatorStateInfo val = animator.GetCurrentAnimatorStateInfo(0);
			if (!((AnimatorStateInfo)(ref val)).IsTag(tag))
			{
				val = animator.GetNextAnimatorStateInfo(0);
				return ((AnimatorStateInfo)(ref val)).IsTag(tag);
			}
			return true;
		}

		private bool IsFarewellVisible(Raven raven)
		{
			if (_farewellShowing && (Object)(object)Chat.instance != (Object)null)
			{
				return Chat.instance.IsDialogVisible(((Component)raven).gameObject);
			}
			return false;
		}

		private void Say(Raven raven, string message)
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(Raven), "Say", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				Plugin.Log.LogWarning((object)"Could not display Munin's greeting because Raven.Say was not found.");
				return;
			}
			methodInfo.Invoke(raven, new object[5]
			{
				string.Empty,
				message,
				false,
				true,
				true
			});
		}

		private void RestoreRavenIdentity()
		{
			if (_ravenIdentityCaptured && !((Object)(object)_raven == (Object)null))
			{
				_raven.m_isMunin = _originalMuninState;
				_raven.m_name = _originalRavenName ?? string.Empty;
				_ravenIdentityCaptured = false;
			}
		}

		private void ClearWelcome()
		{
			DiscoveryConsentPrompt.Close();
			RestoreRavenIdentity();
			_welcomeText = null;
			_raven = null;
			_traceRaven = null;
			_worldId = null;
			_promptOpen = false;
			_awaitingChoice = false;
			_farewellShowing = false;
			_changingMind = false;
			_departureInProgress = false;
			_suppressRavenTextUntilPlayerLeaves = false;
			_ravenSuppressionLogged = false;
			_hasTraceState = false;
			_hasCanHideTrace = false;
			_lastTraceName = null;
			_lastTraceText = null;
			_farewellClearAt = 0f;
		}
	}
	internal sealed class SharedListEntry
	{
		public string Name { get; }

		public string Detail { get; }

		public bool Known { get; }

		public string Note { get; }

		public string SearchText { get; }

		public SharedListEntry(string name, string detail, bool known, string note = "")
		{
			Name = name;
			Detail = detail;
			Known = known;
			Note = note;
			SearchText = (name + " " + detail + " " + note).ToLowerInvariant();
		}
	}
	internal sealed class SharedListGroup
	{
		public string Title { get; }

		public List<SharedListEntry> Entries { get; }

		public SharedListGroup(string title, List<SharedListEntry> entries)
		{
			Title = title;
			Entries = entries;
		}
	}
	internal sealed class SharedListModel
	{
		private sealed class NamedItem
		{
			public SharedData Shared { get; }

			public List<string> Ids { get; } = new List<string>();

			public NamedItem(SharedData shared)
			{
				Shared = shared;
			}
		}

		private static readonly string[] ItemGroupOrder = new string[13]
		{
			"category_materials", "category_food", "category_meads_potions", "category_weapons", "category_ammo", "category_shields", "category_armor", "category_utility_trinkets", "category_tools", "category_fish",
			"category_trophies", "category_other", "category_not_installed"
		};

		public int SharedIdCount { get; private set; }

		public int ItemCount { get; private set; }

		public int RecipeCount { get; private set; }

		public int PieceCount { get; private set; }

		public List<SharedListGroup> Items { get; private set; } = new List<SharedListGroup>();

		public List<SharedListGroup> Recipes { get; private set; } = new List<SharedListGroup>();

		public List<SharedListGroup> Pieces { get; private set; } = new List<SharedListGroup>();

		public static SharedListModel Build(IReadOnlyList<string> itemIds, IReadOnlyDictionary<string, string> discoverers)
		{
			Player localPlayer = Player.m_localPlayer;
			SharedListModel sharedListModel = new SharedListModel
			{
				SharedIdCount = itemIds.Count
			};
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			Dictionary<string, NamedItem> dictionary = new Dictionary<string, NamedItem>(StringComparer.Ordinal);
			List<string> list = new List<string>();
			foreach (string itemId in itemIds)
			{
				GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(itemId) : null);
				ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null);
				SharedData val3 = ((!((Object)(object)val2 != (Object)null)) ? null : val2.m_itemData?.m_shared);
				if (val3 == null)
				{
					list.Add(itemId);
					continue;
				}
				hashSet.Add(val3.m_name);
				if (!dictionary.TryGetValue(val3.m_name, out var value))
				{
					value = new NamedItem(val3);
					dictionary[val3.m_name] = value;
				}
				value.Ids.Add(itemId);
			}
			Dictionary<string, List<SharedListEntry>> groups = new Dictionary<string, List<SharedListEntry>>();
			foreach (NamedItem value4 in dictionary.Values)
			{
				string value3;
				string note = string.Join(", ", (from id in value4.Ids
					select (!discoverers.TryGetValue(id, out value3)) ? string.Empty : value3 into name
					where name.Length > 0
					select name).Distinct<string>(StringComparer.OrdinalIgnoreCase));
				bool known = (Object)(object)localPlayer == (Object)null || localPlayer.IsMaterialKnown(value4.Shared.m_name);
				AddTo(groups, ItemGroup(value4.Shared), new SharedListEntry(Localize(value4.Shared.m_name), string.Join(", ", value4.Ids), known, note));
			}
			foreach (string item in list)
			{
				string value2;
				string note2 = (discoverers.TryGetValue(item, out value2) ? value2 : string.Empty);
				AddTo(groups, "category_not_installed", new SharedListEntry(item, ModLocalization.Get("missing_mod_item"), known: false, note2));
			}
			sharedListModel.ItemCount = dictionary.Count;
			sharedListModel.Items = Sorted(groups, ItemGroupOrder);
			sharedListModel.Recipes = BuildRecipes(hashSet, localPlayer, out var count);
			sharedListModel.RecipeCount = count;
			sharedListModel.Pieces = BuildPieces(hashSet, localPlayer, out var count2);
			sharedListModel.PieceCount = count2;
			return sharedListModel;
		}

		private static List<SharedListGroup> BuildRecipes(HashSet<string> knownNames, Player? player, out int count)
		{
			Dictionary<string, List<SharedListEntry>> groups = new Dictionary<string, List<SharedListEntry>>();
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			count = 0;
			if ((Object)(object)ObjectDB.instance == (Object)null)
			{
				return new List<SharedListGroup>();
			}
			foreach (Recipe recipe in ObjectDB.instance.m_recipes)
			{
				if (!((Object)(object)recipe == (Object)null) && recipe.m_enabled && !((Object)(object)recipe.m_item == (Object)null) && recipe.m_item.m_itemData?.m_shared != null && AllKnown(recipe.m_resources, knownNames) && hashSet.Add(((Object)recipe).name))
				{
					string text = (((Object)(object)recipe.m_craftingStation != (Object)null) ? Localize(recipe.m_craftingStation.m_name) : ModLocalization.Get("crafted_by_hand"));
					string name = Localize(recipe.m_item.m_itemData.m_shared.m_name) + ((recipe.m_amount > 1) ? $" x{recipe.m_amount}" : string.Empty);
					string detail = ((recipe.m_minStationLevel > 1) ? ModLocalization.Format("station_level_required", text, recipe.m_minStationLevel) : string.Empty);
					bool known = (Object)(object)player == (Object)null || player.IsRecipeKnown(recipe.m_item.m_itemData.m_shared.m_name);
					AddTo(groups, text, new SharedListEntry(name, detail, known));
					count++;
				}
			}
			return Sorted(groups, null);
		}

		private static List<SharedListGroup> BuildPieces(HashSet<string> knownNames, Player? player, out int count)
		{
			Dictionary<string, List<SharedListEntry>> groups = new Dictionary<string, List<SharedListEntry>>();
			count = 0;
			if ((Object)(object)ObjectDB.instance == (Object)null)
			{
				return new List<SharedListGroup>();
			}
			HashSet<PieceTable> hashSet = new HashSet<PieceTable>();
			foreach (GameObject item in ObjectDB.instance.m_items)
			{
				ItemDrop val = (((Object)(object)item != (Object)null) ? item.GetComponent<ItemDrop>() : null);
				PieceTable val2 = ((!((Object)(object)val != (Object)null)) ? null : val.m_itemData?.m_shared?.m_buildPieces);
				if ((Object)(object)val2 == (Object)null || !hashSet.Add(val2))
				{
					continue;
				}
				string title = Localize(val.m_itemData.m_shared.m_name);
				HashSet<string> hashSet2 = new HashSet<string>(StringComparer.Ordinal);
				foreach (GameObject piece in val2.m_pieces)
				{
					Piece val3 = (((Object)(object)piece != (Object)null) ? piece.GetComponent<Piece>() : null);
					if (!((Object)(object)val3 == (Object)null) && val3.m_enabled && AllKnown(val3.m_resources, knownNames) && hashSet2.Add(val3.m_name))
					{
						bool known = (Object)(object)player == (Object)null || player.IsRecipeKnown(val3.m_name);
						AddTo(groups, title, new SharedListEntry(Localize(val3.m_name), string.Empty, known));
						count++;
					}
				}
			}
			return Sorted(groups, null);
		}

		private static bool AllKnown(Requirement[] requirements, HashSet<string> knownNames)
		{
			bool result = false;
			Requirement[] array = requirements ?? Array.Empty<Requirement>();
			foreach (Requirement val in array)
			{
				if (!((Object)(object)val?.m_resItem == (Object)null))
				{
					result = true;
					if (!knownNames.Contains(val.m_resItem.m_itemData.m_shared.m_name))
					{
						return false;
					}
				}
			}
			return result;
		}

		private static string ItemGroup(SharedData shared)
		{
			//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_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected I4, but got Unknown
			ItemType itemType = shared.m_itemType;
			switch (itemType - 1)
			{
			case 0:
				return "category_materials";
			case 1:
				if (!(shared.m_food > 0f))
				{
					return "category_meads_potions";
				}
				return "category_food";
			case 2:
			case 3:
			case 13:
			case 14:
			case 19:
			case 21:
				return "category_weapons";
			case 8:
			case 22:
				return "category_ammo";
			case 4:
				return "category_shields";
			case 5:
			case 6:
			case 10:
			case 11:
			case 16:
				return "category_armor";
			case 17:
			case 23:
				return "category_utility_trinkets";
			case 18:
				return "category_tools";
			case 20:
				return "category_fish";
			case 12:
				return "category_trophies";
			default:
				return "category_other";
			}
		}

		private static void AddTo(Dictionary<string, List<SharedListEntry>> groups, string title, SharedListEntry entry)
		{
			if (!groups.TryGetValue(title, out List<SharedListEntry> value))
			{
				value = (groups[title] = new List<SharedListEntry>());
			}
			value.Add(entry);
		}

		private static List<SharedListGroup> Sorted(Dictionary<string, List<SharedListEntry>> groups, string[]? order)
		{
			IEnumerable<string> source;
			if (order == null)
			{
				IEnumerable<string> enumerable = groups.Keys.OrderBy<string, string>((string k) => k, StringComparer.CurrentCultureIgnoreCase);
				source = enumerable;
			}
			else
			{
				source = order.Where(groups.ContainsKey).Concat(from k in groups.Keys
					where !order.Contains(k)
					orderby k
					select k);
			}
			return source.Select((string t) => new SharedListGroup(t, groups[t].OrderBy<SharedListEntry, string>((SharedListEntry e) => e.Name, StringComparer.CurrentCultureIgnoreCase).ToList())).ToList();
		}

		private static string Localize(string token)
		{
			if (Localization.instance == null)
			{
				return token;
			}
			return Localization.instance.Localize(token);
		}
	}
	internal sealed class SharedListWindow : MonoBehaviour
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__Close;
		}

		private const float WindowWidth = 700f;

		private const float WindowHeight = 690f;

		private static readonly string[] Tabs = new string[3] { "tab_recipes", "tab_build_pieces", "tab_items" };

		private const int ItemsTab = 2;

		private const float RowLeft = 24f;

		private const float RowWidth = 600f;

		private const float NoteColumnWidth = 190f;

		private const float ColumnGap = 12f;

		private const float MinRowHeight = 28f;

		private const float RowSpacing = 1f;

		private const int RowFontSize = 16;

		private const int NoteFontSize = 14;

		private static readonly Color NoteTextColor = new Color(0.95f, 0.92f, 0.84f, 0.8f);

		private static readonly Color UnknownTextColor = new Color(0.56f, 0.56f, 0.56f, 0.6f);

		private const int TooltipFontSize = 15;

		private const float TooltipPadding = 8f;

		private static readonly Vector2 TooltipOffset = new Vector2(18f, -22f);

		private static readonly Color TooltipBackgroundColor = new Color(0.12f, 0.1f, 0.08f, 0.95f);

		private static SharedListWindow? _instance;

		private readonly HashSet<string> _collapsedGroups = new HashSet<string>(StringComparer.Ordinal);

		private readonly Button[] _tabButtons = (Button[])(object)new Button[3];

		private SharedListModel? _model;

		private bool _visible;

		private bool _inputBlocked;

		private bool _cursorStateCaptured;

		private bool _previousCursorVisible;

		private CursorLockMode _previousCursorLockState;

		private int _tab;

		private string _search = string.Empty;

		private Transform? _guiParent;

		private GameObject? _windowRoot;

		private Text? _summaryText;

		private InputField? _searchInput;

		private ScrollRect? _scrollRect;

		private RectTransform? _listContent;

		private RectTransform? _tooltip;

		private Text? _tooltipText;

		private SharedListRowTooltip? _tooltipOwner;

		public static bool IsOpen
		{
			get
			{
				if ((Object)(object)_instance != (Object)null)
				{
					return _instance._visible;
				}
				return false;
			}
		}

		public static void Show(SharedListModel model)
		{
			//IL_002e: 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)
			if (!((Object)(object)_instance == (Object)null))
			{
				if (!_instance._visible)
				{
					_instance._previousCursorVisible = Cursor.visible;
					_instance._previousCursorLockState = Cursor.lockState;
					_instance._cursorStateCaptured = true;
				}
				_instance._model = model;
				_instance._visible = true;
				_instance._tab = 0;
				_instance._search = string.Empty;
				_instance._collapsedGroups.Clear();
				_instance.EnableCursor();
				_instance.EnsureWindow();
				_instance.RefreshWindow();
				_instance.SetWindowActive(active: true);
			}
		}

		public static void Close()
		{
			if (!((Object)(object)_instance == (Object)null))
			{
				_instance._visible = false;
				_instance._model = null;
				_instance.SetWindowActive(active: false);
				_instance.SetInputBlocked(blocked: false);
				_instance.RestoreCursor();
			}
		}

		private void Awake()
		{
			_instance = this;
		}

		private void OnDestroy()
		{
			SetInputBlocked(blocked: false);
			RestoreCursor();
			DestroyWindow();
			if ((Object)(object)_instance == (Object)(object)this)
			{
				_instance = null;
			}
		}

		private void Update()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				if (_visible)
				{
					Close();
				}
				return;
			}
			KeyCode effectiveSharedListHotkey = ModConfig.EffectiveSharedListHotkey;
			if ((int)effectiveSharedListHotkey != 0 && Input.GetKeyDown(effectiveSharedListHotkey))
			{
				if (_visible)
				{
					Close();
				}
				else if (!((Object)(object)ZNet.instance == (Object)null) && Plugin.Session.IsLocalPlayerReady && !Plugin.Network.RequestSharedList())
				{
					ShareKnownItemsFeedback.Show(ModLocalization.Get("network_unavailable"));
				}
			}
			else if (_visible && Input.GetKeyDown((KeyCode)27))
			{
				Close();
			}
		}

		private void LateUpdate()
		{
			if (_visible)
			{
				if (EnsureWindow())
				{
					RefreshWindow();
				}
				EnableCursor();
				SetWindowActive(active: true);
				UpdateTooltipPosition();
			}
		}

		private bool EnsureWindow()
		{
			GameObject customGUIFront = GUIManager.CustomGUIFront;
			if ((Object)(object)customGUIFront == (Object)null)
			{
				return false;
			}
			Transform transform = customGUIFront.transform;
			if ((Object)(object)_windowRoot != (Object)null && (Object)(object)_guiParent == (Object)(object)transform)
			{
				return false;
			}
			DestroyWindow();
			_guiParent = transform;
			CreateWindow(transform);
			return true;
		}

		private void CreateWindow(Transform parent)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0053: 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_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: 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_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: 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_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: 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_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: 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_01d7: 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_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Expected O, but got Unknown
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: 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_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b5: 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_03ea: Expected O, but got Unknown
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0409: Unknown result type (might be due to invalid IL or missing references)
			//IL_0434: Unknown result type (might be due to invalid IL or missing references)
			//IL_043e: Expected O, but got Unknown
			//IL_0445: Unknown result type (might be due to invalid IL or missing references)
			//IL_046e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0470: Unknown result type (might be due to invalid IL or missing references)
			//IL_047c: Unknown result type (might be due to invalid IL or missing references)
			//IL_04aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_04af: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b5: Expected O, but got Unknown
			GUIManager instance = GUIManager.Instance;
			_windowRoot = new GameObject("DiscoverySyncSharedListWindow", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			_windowRoot.transform.SetParent(parent, false);
			RectTransform val = (RectTransform)_windowRoot.transform;
			val.anchorMin = Vector2.zero;
			val.anchorMax = Vector2.one;
			val.offsetMin = Vector2.zero;
			val.offsetMax = Vector2.zero;
			Image component = _windowRoot.GetComponent<Image>();
			((Graphic)component).color = new Color(0f, 0f, 0f, 0.62f);
			((Graphic)component).raycastTarget = true;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			GameObject val3 = instance.CreateWoodpanel(_windowRoot.transform, val2, val2, Vector2.zero, 700f, 690f, true);
			Vector2 val4 = default(Vector2);
			((Vector2)(ref val4))..ctor(0.5f, 1f);
			instance.CreateText(ModLocalization.Get("list_title"), val3.transform, val4, val4, new Vector2(0f, -32f), instance.AveriaSerifBold, 28, instance.ValheimOrange, true, Color.black, 652f, 42f, false).GetComponent<Text>().alignment = (TextAnchor)4;
			_summaryText = instance.CreateText(string.Empty, val3.transform, val4, val4, new Vector2(0f, -78f), instance.AveriaSerif, 17, instance.ValheimBeige, true, Color.black, 644f, 56f, false).GetComponent<Text>();
			_summaryText.alignment = (TextAnchor)4;
			_summaryText.horizontalOverflow = (HorizontalWrapMode)0;
			_summaryText.verticalOverflow = (VerticalWrapMode)1;
			instance.CreateText(ModLocalization.Get("list_detail"), val3.transform, val4, val4, new Vector2(0f, -132f), instance.AveriaSerif, 15, instance.ValheimBeige, true, Color.black, 644f, 26f, false).GetComponent<Text>().alignment = (TextAnchor)4;
			Vector2 val5 = default(Vector2);
			((Vector2)(ref val5))..ctor(0f, 1f);
			for (int i = 0; i < Tabs.Length; i++)
			{
				int tabIndex = i;
				GameObject val6 = instance.CreateButton(Tabs[i], val3.transform, val5, val5, new Vector2(22f + (float)i * 218f, -159f), 210f, 38f);
				SetTopLeftPivot(val6);
				_tabButtons[i] = val6.GetComponent<Button>();
				((UnityEvent)_tabButtons[i].onClick).AddListener((UnityAction)delegate
				{
					SelectTab(tabIndex);
				});
			}
			GameObject obj = instance.CreateText(ModLocalization.Get("search_label"), val3.transform, val5, val5, new Vector2(24f, -207f), instance.AveriaSerifBold, 16, instance.ValheimBeige, true, Color.black, 78f, 34f, false);
			SetTopLeftPivot(obj);
			obj.GetComponent<Text>().alignment = (TextAnchor)3;
			GameObject val7 = instance.CreateInputField(val3.transform, val5, val5, new Vector2(98f, -207f), (ContentType)0, ModLocalization.Get("search_placeholder"), 16, 250f, 34f);
			SetTopLeftPivot(val7);
			_searchInput = val7.GetComponent<InputField>();
			_searchInput.text = _search;
			((UnityEvent<string>)(object)_searchInput.onValueChanged).AddListener((UnityAction<string>)OnSearchChanged);
			GameObject obj2 = instance.CreateButton(ModLocalization.Get("expand_all"), val3.transform, val5, val5, new Vector2(372f, -207f), 132f, 34f);
			SetTopLeftPivot(obj2);
			((UnityEvent)obj2.GetComponent<Button>().onClick).AddListener(new UnityAction(ExpandAll));
			GameObject obj3 = instance.CreateButton(ModLocalization.Get("collapse_all"), val3.transform, val5, val5, new Vector2(516f, -207f), 158f, 34f);
			SetTopLeftPivot(obj3);
			((UnityEvent)obj3.GetComponent<Button>().onClick).AddListener(new UnityAction(CollapseAll));
			CreateListScrollView(val3.transform, val5);
			Vector2 val8 = default(Vector2);
			((Vector2)(ref val8))..ctor(0.5f, 0f);
			ButtonClickedEvent onClick = instance.CreateButton(ModLocalization.Get("close_esc"), val3.transform, val8, val8, new Vector2(0f, 41f), 656f, 38f).GetComponent<Button>().onClick;
			object obj4 = <>O.<0>__Close;
			if (obj4 == null)
			{
				UnityAction val9 = Close;
				<>O.<0>__Close = val9;
				obj4 = (object)val9;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj4);
			CreateTooltip(instance);
			_windowRoot.SetActive(_visible);
		}

		private void CreateTooltip(GUIManager gui)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: 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_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("DiscoverySyncTooltip", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent(_windowRoot.transform, false);
			_tooltip = (RectTransform)val.transform;
			_tooltip.anchorMin = new Vector2(0.5f, 0.5f);
			_tooltip.anchorMax = new Vector2(0.5f, 0.5f);
			_tooltip.pivot = new Vector2(0f, 1f);
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = TooltipBackgroundColor;
			((Graphic)component).raycastTarget = false;
			GameObject val2 = gui.CreateText(string.Empty, val.transform, Vector2.zero, Vector2.one, Vector2.zero, gui.AveriaSerif, 15, gui.ValheimBeige, true, Color.black, 0f, 0f, false);
			_tooltipText = val2.GetComponent<Text>();
			RectTransform rectTransform = ((Graphic)_tooltipText).rectTransform;
			rectTransform.anchorMin = Vector2.zero;
			rectTransform.anchorMax = Vector2.one;
			rectTransform.offsetMin = new Vector2(8f, 8f);
			rectTransform.offsetMax = new Vector2(-8f, -8f);
			_tooltipText.alignment = (TextAnchor)4;
			_tooltipText.horizontalOverflow = (HorizontalWrapMode)1;
			_tooltipText.verticalOverflow = (VerticalWrapMode)1;
			((Graphic)_tooltipText).raycastTarget = false;
			val.SetActive(false);
		}

		internal static void ShowTooltip(SharedListRowTooltip owner, string text)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			SharedListWindow instance = _instance;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance._tooltip == (Object)null) && !((Object)(object)instance._tooltipText == (Object)null))
			{
				instance._tooltipOwner = owner;
				instance._tooltipText.text = text;
				instance._tooltip.sizeDelta = new Vector2(Mathf.Ceil(instance._tooltipText.preferredWidth) + 16f, Mathf.Ceil(instance._tooltipText.preferredHeight) + 16f);
				((Component)instance._tooltip).gameObject.SetActive(true);
				((Transform)instance._tooltip).SetAsLastSibling();
				instance.UpdateTooltipPosition();
			}
		}

		internal static void HideTooltip(SharedListRowTooltip owner)
		{
			SharedListWindow instance = _instance;
			if ((Object)(object)instance != (Object)null && (Object)(object)instance._tooltipOwner == (Object)(object)owner)
			{
				instance.HideTooltip();
			}
		}

		private void HideTooltip()
		{
			_tooltipOwner = null;
			if ((Object)(object)_tooltip != (Object)null)
			{
				((Component)_tooltip).gameObject.SetActive(false);
			}
		}

		private void UpdateTooltipPosition()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_0051: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_tooltip == (Object)null || (Object)(object)_windowRoot == (Object)null || !((Component)_tooltip).gameObject.activeSelf)
			{
				return;
			}
			RectTransform val = (RectTransform)_windowRoot.transform;
			Canvas componentInParent = ((Component)val).GetComponentInParent<Canvas>();
			Camera val2 = (((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode != 0) ? componentInParent.worldCamera : null);
			Vector2 val3 = default(Vector2);
			if (RectTransformUtility.ScreenPointToLocalPointInRectangle(val, Vector2.op_Implicit(Input.mousePosition), val2, ref val3))
			{
				Vector2 val4 = val3 + TooltipOffset;
				Vector2 sizeDelta = _tooltip.sizeDelta;
				Rect rect = val.rect;
				if (val4.x + sizeDelta.x > ((Rect)(ref rect)).xMax)
				{
					val4.x = val3.x - TooltipOffset.x - sizeDelta.x;
				}
				if (val4.y - sizeDelta.y < ((Rect)(ref rect)).yMin)
				{
					val4.y = val3.y - TooltipOffset.y + sizeDelta.y;
				}
				_tooltip.anchoredPosition = val4;
			}
		}

		private void CreateListScrollView(Transform panel, Vector2 topLeft)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0052: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: 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_0110: Expected O, but got Unknown
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Expected O, but got Unknown
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Expected O, but got Unknown
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("DiscoverySyncSharedListScrollView", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(ScrollRect)
			});
			val.transform.SetParent(panel, false);
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchorMin = topLeft;
			val2.anchorMax = topLeft;
			val2.pivot = topLeft;
			val2.anchoredPosition = new Vector2(22f, -248f);
			val2.sizeDelta = new Vector2(656f, 362f);
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = new Color(0.12f, 0.1f, 0.08f, 0.45f);
			((Graphic)component).raycastTarget = true;
			GameObject val3 = new GameObject("Viewport", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(RectMask2D)
			});
			val3.transform.SetParent(val.transform, false);
			RectTransform val4 = (RectTransform)val3.transform;
			val4.anchorMin = Vector2.zero;
			val4.anchorMax = Vector2.one;
			val4.offsetMin = new Vector2(8f, 8f);
			val4.offsetMax = new Vector2(-26f, -8f);
			Image component2 = val3.GetComponent<Image>();
			((Graphic)component2).color = new Color(1f, 1f, 1f, 0.01f);
			((Graphic)component2).raycastTarget = true;
			GameObject val5 = new GameObject("Content", new Type[1] { typeof(RectTransform) });
			val5.transform.SetParent((Transform)(object)val4, false);
			_listContent = (RectTransform)val5.transform;
			_listContent.anchorMin = new Vector2(0f, 1f);
			_listContent.anchorMax = new Vector2(1f, 1f);
			_listContent.pivot = new Vector2(0.5f, 1f);
			_listContent.sizeDelta = Vector2.zero;
			_scrollRect = val.GetComponent<ScrollRect>();
			_scrollRect.viewport = val4;
			_scrollRect.content = _listContent;
			_scrollRect.horizontal = false;
			_scrollRect.vertical = true;
			_scrollRect.movementType = (MovementType)2;
			_scrollRect.scrollSensitivity = 3000f;
			_scrollRect.inertia = false;
			_scrollRect.decelerationRate = 0.135f;
			CreateVerticalScrollbar(val2);
		}

		private void CreateVerticalScrollbar(RectTransform scrollRect)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_005c: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_0117: Expected O, but got Unknown
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("VerticalScrollbar", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Scrollbar)
			});
			val.transform.SetParent((Transform)(object)scrollRect, false);
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchorMin = new Vector2(1f, 0f);
			val2.anchorMax = Vector2.one;
			val2.pivot = new Vector2(1f, 0.5f);
			val2.anchoredPosition = new Vector2(-3f, 0f);
			val2.sizeDelta = new Vector2(14f, -12f);
			((Graphic)val.GetComponent<Image>()).color = new Color(0.12f, 0.1f, 0.08f, 0.85f);
			GameObject val3 = new GameObject("Handle", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val3.transform.SetParent((Transform)(object)val2, false);
			RectTransform val4 = (RectTransform)val3.transform;
			val4.anchorMin = Vector2.zero;
			val4.anchorMax = Vector2.one;
			val4.offsetMin = new Vector2(2f, 2f);
			val4.offsetMax = new Vector2(-2f, -2f);
			Image component = val3.GetComponent<Image>();
			component.sprite = GUIManager.Instance.GetSprite("UISprite");
			component.type = (Type)1;
			((Graphic)component).raycastTarget = true;
			Scrollbar component2 = val.GetComponent<Scrollbar>();
			component2.handleRect = val4;
			((Selectable)component2).targetGraphic = (Graphic)(object)component;
			component2.direction = (Direction)2;
			((Selectable)component2).colors = GUIManager.Instance.ValheimScrollbarHandleColorBlock;
			component2.size = 0.2f;
			((Selectable)component2).interactable = true;
			_scrollRect.verticalScrollbar = component2;
			_scrollRect.verticalScrollbarVisibility = (ScrollbarVisibility)0;
			_scrollRect.verticalScrollbarSpacing = -3f;
		}

		private void RefreshWindow()
		{
			if (_model != null && !((Object)(object)_summaryText == (Object)null))
			{
				_summaryText.text = ModLocalization.Format("list_summary", _model.RecipeCount, _model.PieceCount, _model.ItemCount, _model.SharedIdCount);
				UpdateTabButtonLabels();
				RenderGroups();
			}
		}

		private void SelectTab(int tab)
		{
			if (_tab != tab)
			{
				_tab = tab;
				if ((Object)(object)_scrollRect != (Object)null)
				{
					_scrollRect.verticalNormalizedPosition = 1f;
				}
				UpdateTabButtonLabels();
				RenderGroups();
			}
		}

		private void UpdateTabButtonLabels()
		{
			for (int i = 0; i < _tabButtons.Length; i++)
			{
				Text val = (((Object)(object)_tabButtons[i] != (Object)null) ? ((Component)_tabButtons[i]).GetComponentInChildren<Text>() : null);
				if ((Object)(object)val != (Object)null)
				{
					string text = ModLocalization.Get(Tabs[i]);
					val.text = ((i == _tab) ? ("[" + text + "]") : text);
				}
			}
		}

		private void OnSearchChanged(string value)
		{
			_search = value ?? string.Empty;
			if ((Object)(object)_scrollRect != (Object)null)
			{
				_scrollRect.verticalNormalizedPosition = 1f;
			}
			RenderGroups();
		}

		private void ExpandAll()
		{
			foreach (SharedListGroup currentGroup in GetCurrentGroups())
			{
				_collapsedGroups.Remove(GetGroupKey(currentGroup));
			}
			RenderGroups();
		}

		private void CollapseAll()
		{
			foreach (SharedListGroup currentGroup in GetCurrentGroups())
			{
				_collapsedGroups.Add(GetGroupKey(currentGroup));
			}
			RenderGroups();
		}

		private void RenderGroups()
		{
			//IL_03fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Expected O, but got Unknown
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			if (_model == null || (Object)(object)_listContent == (Object)null)
			{
				return;
			}
			HideTooltip();
			ClearListContent();
			string text = ModLocalization.Get("unknown_to_you");
			List<SharedListGroup> currentGroups = GetCurrentGroups();
			string filter = (_search ?? string.Empty).Trim().ToLowerInvariant();
			float num = 8f;
			int num2 = 0;
			GUIManager instance = GUIManager.Instance;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0f, 1f);
			foreach (SharedListGroup group in currentGroups)
			{
				List<SharedListEntry> list = ((filter.Length == 0) ? group.Entries : group.Entries.FindAll((SharedListEntry entry) => entry.SearchText.Contains(filter) || GetGroupTitle(group.Title).ToLowerInvariant().Contains(filter)));
				if (list.Count == 0)
				{
					continue;
				}
				num2++;
				string groupKey = GetGroupKey(group);
				bool flag = _collapsedGroups.Contains(groupKey);
				GameObject obj = instance.CreateButton(string.Format("{0}{1} ({2})", flag ? "[+] " : "[-] ", GetGroupTitle(group.Title), list.Count), (Transform)(object)_listContent, val, val, new Vector2(8f, 0f - num), 624f, 34f);
				SetTopLeftPivot(obj);
				((UnityEvent)obj.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
				{
					ToggleGroup(groupKey);
				});
				num += 38f;
				if (flag)
				{
					continue;
				}
				bool flag2 = _tab == 2;
				float num3 = (flag2 ? 398f : 600f);
				foreach (SharedListEntry item in list)
				{
					string value = ((item.Detail.Length == 0) ? item.Name : (item.Name + "  -  " + item.Detail));
					Color color = (item.Known ? instance.ValheimBeige : UnknownTextColor);
					Text text2 = CreateRowText(instance, value, 24f, num, num3, 16, color, item.Known);
					float num4 = Mathf.Max(28f, PreferredHeight(text2, num3));
					if (flag2 && item.Note.Length > 0)
					{
						Color color2 = (item.Known ? NoteTextColor : UnknownTextColor);
						Text val2 = CreateRowText(instance, item.Note, 24f + num3 + 12f, num, 190f, 14, color2, item.Known);
						val2.fontStyle = (FontStyle)2;
						num4 = Mathf.Max(num4, PreferredHeight(val2, 190f));
						SetRowHeight(val2, num4);
					}
					SetRowHeight(text2, num4);
					if (!item.Known)
					{
						AddRowTooltip(num, num4, text);
					}
					num += num4 + 1f;
				}
				num += 5f;
			}
			if (num2 == 0)
			{
				GameObject obj2 = instance.CreateText(ModLocalization.Get((filter.Length == 0) ? "list_empty" : "list_no_matches"), (Transform)(object)_listContent, val, val, new Vector2(16f, -16f), instance.AveriaSerif, 18, instance.ValheimBeige, true, Color.black, 600f, 32f, false);
				SetTopLeftPivot(obj2);
				obj2.GetComponent<Text>().alignment = (TextAnchor)4;
				num = 56f;
			}
			_listContent.sizeDelta = new Vector2(0f, num);
			LayoutRebuilder.ForceRebuildLayoutImmediate(_listContent);
			Canvas.ForceUpdateCanvases();
		}

		private Text CreateRowText(GUIManager gui, string value, float x, float y, float width, int fontSize, Color color, bool outline)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = gui.CreateText(value, (Transform)(object)_listContent, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(x, 0f - y), gui.AveriaSerif, fontSize, color, outline, Color.black, width, 28f, false);
			SetTopLeftPivot(obj);
			Text component = obj.GetComponent<Text>();
			component.alignment = (TextAnchor)3;
			component.horizontalOverflow = (HorizontalWrapMode)0;
			component.verticalOverflow = (VerticalWrapMode)1;
			return component;
		}

		private void AddRowTooltip(float y, float height, string text)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_007e: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("RowTooltip", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(SharedListRowTooltip)
			});
			val.transform.SetParent((Transform)(object)_listContent, false);
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchorMin = new Vector2(0f, 1f);