Decompiled source of PokeMoons v1.0.2

Pokemoons.dll

Decompiled 2 weeks 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 System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalLib.Modules;
using LethalQuantities;
using LethalQuantities.Json;
using LethalQuantities.Objects;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Pokemoons;
using Pokemoons.NetcodePatcher;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Pokemoons")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Pokemoons Mod")]
[assembly: AssemblyFileVersion("0.0.1.0")]
[assembly: AssemblyInformationalVersion("0.0.1+c6a7c7490f8f6b1fc2f43008cf1bf645c7acc66b")]
[assembly: AssemblyProduct("Pokemoons")]
[assembly: AssemblyTitle("Pokemoons")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
internal class <Module>
{
	static <Module>()
	{
	}
}
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
[HarmonyPatch(typeof(RoundManager), "DespawnPropsAtEndOfRound")]
internal static class DexReleasePatch
{
	internal class TrackedPokemon
	{
		public NetworkObject networkObject;

		public KeyValuePair<int, bool> pokemon;
	}

	[HarmonyPrefix]
	private static void BeforeDespawn(out List<TrackedPokemon> __state)
	{
		__state = null;
		if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer)
		{
			return;
		}
		__state = new List<TrackedPokemon>();
		PokemonProp[] array = Object.FindObjectsOfType<PokemonProp>();
		foreach (PokemonProp pokemonProp in array)
		{
			if (((GrabbableObject)pokemonProp).isInShipRoom && (Object)(object)((NetworkBehaviour)pokemonProp).NetworkObject != (Object)null && ((NetworkBehaviour)pokemonProp).NetworkObject.IsSpawned && DexData.TryGetDexNumber((GrabbableObject)(object)pokemonProp, out var dexNumber))
			{
				__state.Add(new TrackedPokemon
				{
					networkObject = ((NetworkBehaviour)pokemonProp).NetworkObject,
					pokemon = new KeyValuePair<int, bool>(dexNumber, pokemonProp.IsShiny)
				});
			}
		}
	}

	[HarmonyPostfix]
	private static void AfterDespawn(List<TrackedPokemon> __state)
	{
		if (__state == null)
		{
			return;
		}
		List<KeyValuePair<int, bool>> list = new List<KeyValuePair<int, bool>>();
		foreach (TrackedPokemon item in __state)
		{
			if ((Object)(object)item.networkObject == (Object)null || !item.networkObject.IsSpawned)
			{
				list.Add(item.pokemon);
			}
		}
		DexData.AddReleased(list);
	}
}
[HarmonyPatch(typeof(GameNetworkManager))]
internal static class DexSavePatch
{
	[HarmonyPatch("SaveItemsInShip")]
	[HarmonyPostfix]
	private static void AfterSaveItems()
	{
		Commit();
	}

	[HarmonyPatch("ResetSavedGameValues")]
	[HarmonyPostfix]
	private static void AfterReset()
	{
		Commit();
	}

	private static void Commit()
	{
		if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsServer)
		{
			DexData.Commit();
		}
	}
}
[HarmonyPatch(typeof(ES3), "DeleteFile", new Type[] { typeof(string) })]
internal static class DexDeletePatch
{
	[HarmonyPostfix]
	private static void AfterDelete(string filePath)
	{
		if (!string.IsNullOrEmpty(filePath) && filePath.StartsWith("LCSaveFile") && !filePath.EndsWith("_Pokemoons.es3") && ES3.FileExists(filePath + "_Pokemoons.es3"))
		{
			ES3.DeleteFile(filePath + "_Pokemoons.es3");
		}
	}
}
[HarmonyPatch(typeof(DepositItemsDesk), "SellItemsOnServer")]
internal static class DexSellPatch
{
	private static readonly List<KeyValuePair<int, bool>> _pending = new List<KeyValuePair<int, bool>>();

	[HarmonyPrefix]
	private static void BeforeSell(DepositItemsDesk __instance)
	{
		_pending.Clear();
		if (!((NetworkBehaviour)__instance).IsServer || __instance.itemsOnCounter == null)
		{
			return;
		}
		foreach (GrabbableObject item in __instance.itemsOnCounter)
		{
			if (DexData.TryGetDexNumber(item, out var dexNumber))
			{
				_pending.Add(new KeyValuePair<int, bool>(dexNumber, ((PokemonProp)(object)item).IsShiny));
			}
		}
	}

	[HarmonyPostfix]
	private static void AfterSell()
	{
		DexData.AddSold(_pending);
		_pending.Clear();
	}
}
[HarmonyPatch(typeof(RoundManager))]
internal static class RoundManagerPatches
{
	[HarmonyPatch("Start")]
	[HarmonyPostfix]
	[HarmonyPriority(200)]
	public static void AfterStart()
	{
		DexData.Initialise();
		DexSync.Register();
		if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsServer)
		{
			DexData.EnsureLoaded();
		}
		else
		{
			DexSync.RequestFromHost();
		}
		DexSpawnTables.EstimateAll();
	}
}
internal static class DexSpawnTables
{
	public static void EstimateAll()
	{
		SelectableLevel[] array = StartOfRound.Instance?.levels;
		if (array == null)
		{
			return;
		}
		int num = 0;
		SelectableLevel[] array2 = array;
		foreach (SelectableLevel val in array2)
		{
			if ((Object)(object)val == (Object)null || val.spawnableScrap == null)
			{
				continue;
			}
			try
			{
				List<SpawnableItemWithRarity> list = val.spawnableScrap;
				if (LQCompat.Enabled)
				{
					list = LQCompat.TryApplyPreset(val, list) ?? list;
				}
				DexData.RecordMoon(val.PlanetName, SpawnWeights.Preview(val, list), observed: false);
				num++;
			}
			catch (Exception)
			{
				Plugin.logger.LogWarning((object)("Dex: invalid loot table for '" + val.PlanetName + "'"));
			}
		}
		Plugin.logger.LogInfo((object)$"Dex: estimated loot tables for {num} moons.");
	}
}
internal static class LQCompat
{
	private static bool _failed;

	public static bool Enabled
	{
		get
		{
			if (!_failed)
			{
				return Chainloader.PluginInfos.ContainsKey("LethalQuantities");
			}
			return false;
		}
	}

	public static List<SpawnableItemWithRarity> TryApplyPreset(SelectableLevel level, List<SpawnableItemWithRarity> table)
	{
		try
		{
			return ApplyPreset(level, table);
		}
		catch (Exception)
		{
			_failed = true;
			Plugin.logger.LogWarning((object)"Dex: couldn't read LethalQuantities presets. Using game tables.");
			return null;
		}
	}

	[MethodImpl(MethodImplOptions.NoInlining)]
	private static List<SpawnableItemWithRarity> ApplyPreset(SelectableLevel level, List<SpawnableItemWithRarity> table)
	{
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0134: Expected O, but got Unknown
		if (!(AccessTools.Field(typeof(Plugin), "presets")?.GetValue(Plugin.INSTANCE) as Dictionary<Guid, LevelPreset>).TryGetValue(SelectableLevelCache.getGuid(level), out var value) || !value.scrap.set)
		{
			return null;
		}
		Dictionary<Item, int> dictionary = new Dictionary<Item, int>();
		foreach (SpawnableItemWithRarity item in table)
		{
			if (item != null && !((Object)(object)item.spawnableItem == (Object)null))
			{
				dictionary.TryGetValue(item.spawnableItem, out var value2);
				dictionary[item.spawnableItem] = value2 + item.rarity;
			}
		}
		List<SpawnableItemWithRarity> list = new List<SpawnableItemWithRarity>();
		foreach (KeyValuePair<Item, LevelPresetItem> item2 in value.scrap.value)
		{
			if (!((Object)(object)item2.Key == (Object)null))
			{
				dictionary.TryGetValue(item2.Key, out var value3);
				if (item2.Value.rarity.set)
				{
					value3 = item2.Value.rarity.value;
				}
				if (value3 > 0)
				{
					list.Add(new SpawnableItemWithRarity(item2.Key, value3));
				}
			}
		}
		if (list.Count <= 0)
		{
			return null;
		}
		return list;
	}
}
namespace Pokemoons
{
	public class DexEntry
	{
		public string Name { get; set; }

		public int DexNumber { get; set; }

		public Dictionary<string, int> SpawnWeight { get; set; } = new Dictionary<string, int>();

		public Dictionary<string, float> SpawnChance { get; set; } = new Dictionary<string, float>();
	}
	public static class DexData
	{
		private static bool _initialised = false;

		private static string _savedFilePath;

		public const string FileSuffix = "_Pokemoons.es3";

		public static readonly HashSet<string> ObservedMoons = new HashSet<string>();

		public static int[] Sold = new int[PokemonList.Gen1PokemonNames.Count];

		public static int[] SoldShiny = new int[PokemonList.Gen1PokemonNames.Count];

		public static int[] Released = new int[PokemonList.Gen1PokemonNames.Count];

		public static int[] ReleasedShiny = new int[PokemonList.Gen1PokemonNames.Count];

		private static string _loadedPath;

		private static bool _unsaved;

		private const string SoldKey = "DexSold";

		private const string SoldShinyKey = "DexSoldShiny";

		private const string ReleasedKey = "DexReleased";

		private const string ReleasedShinyKey = "DexReleasedShiny";

		public static Dictionary<string, DexEntry> DexEntries { get; set; } = new Dictionary<string, DexEntry>();

		public static void Initialise()
		{
			_savedFilePath = GameNetworkManager.Instance.currentSaveFileName + "_Pokemoons.es3";
			ObservedMoons.Clear();
			_loadedPath = null;
			SetCounts(null, null, null, null);
			NewEntryPopup.Reset();
			if (!_initialised)
			{
				for (int i = 0; i < PokemonList.Gen1PokemonNames.Count; i++)
				{
					DexEntries[PokemonList.Gen1PokemonNames[i]] = new DexEntry
					{
						Name = PokemonList.Gen1PokemonNames[i],
						DexNumber = i + 1
					};
				}
				_initialised = true;
			}
		}

		public static void RecordMoon(string moon, IEnumerable<SpawnableItemWithRarity> table, bool observed)
		{
			if (!_initialised || string.IsNullOrEmpty(moon) || table == null || (!observed && ObservedMoons.Contains(moon)))
			{
				return;
			}
			if (observed)
			{
				ObservedMoons.Add(moon);
			}
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			int num = 0;
			foreach (SpawnableItemWithRarity item in table)
			{
				if (item != null && !((Object)(object)item.spawnableItem == (Object)null) && item.rarity > 0)
				{
					num += item.rarity;
					string name = ((Object)item.spawnableItem).name;
					if (DexEntries.ContainsKey(name))
					{
						dictionary.TryGetValue(name, out var value);
						dictionary[name] = value + item.rarity;
					}
				}
			}
			foreach (DexEntry value3 in DexEntries.Values)
			{
				if (dictionary.TryGetValue(value3.Name, out var value2))
				{
					value3.SpawnWeight[moon] = value2;
					value3.SpawnChance[moon] = (float)value2 / (float)num;
				}
				else
				{
					value3.SpawnWeight.Remove(moon);
					value3.SpawnChance.Remove(moon);
				}
			}
		}

		public static bool TryGetDexNumber(GrabbableObject item, out int dexNumber)
		{
			dexNumber = 0;
			if (!(item is PokemonProp) || (Object)(object)item.itemProperties == (Object)null || !DexEntries.TryGetValue(((Object)item.itemProperties).name, out var value))
			{
				return false;
			}
			dexNumber = value.DexNumber;
			return true;
		}

		public static void GetFound(out int[] found, out int[] foundShiny, out int[] onShip)
		{
			int count = PokemonList.Gen1PokemonNames.Count;
			found = new int[count];
			foundShiny = new int[count];
			onShip = new int[count];
			for (int i = 0; i < count; i++)
			{
				found[i] = Sold[i] + SoldShiny[i] + Released[i] + ReleasedShiny[i];
				foundShiny[i] = SoldShiny[i] + ReleasedShiny[i];
			}
			PokemonProp[] array = Object.FindObjectsOfType<PokemonProp>();
			foreach (PokemonProp pokemonProp in array)
			{
				if (((GrabbableObject)pokemonProp).isInShipRoom && TryGetDexNumber((GrabbableObject)(object)pokemonProp, out var dexNumber))
				{
					found[dexNumber - 1]++;
					onShip[dexNumber - 1]++;
					if (pokemonProp.IsShiny)
					{
						foundShiny[dexNumber - 1]++;
					}
				}
			}
		}

		public static void EnsureLoaded()
		{
			if (!(_loadedPath == _savedFilePath))
			{
				_loadedPath = _savedFilePath;
				_unsaved = false;
				SetCounts(ES3.Load<int[]>("DexSold", _savedFilePath, new int[0]), ES3.Load<int[]>("DexSoldShiny", _savedFilePath, new int[0]), ES3.Load<int[]>("DexReleased", _savedFilePath, new int[0]), ES3.Load<int[]>("DexReleasedShiny", _savedFilePath, new int[0]));
			}
		}

		public static void AddSold(List<KeyValuePair<int, bool>> pokemon)
		{
			EnsureLoaded();
			Add(pokemon, Sold, SoldShiny);
		}

		public static void AddReleased(List<KeyValuePair<int, bool>> pokemon)
		{
			EnsureLoaded();
			Add(pokemon, Released, ReleasedShiny);
		}

		private static void Add(List<KeyValuePair<int, bool>> pokemon, int[] normal, int[] shiny)
		{
			if (pokemon.Count == 0)
			{
				return;
			}
			foreach (KeyValuePair<int, bool> item in pokemon)
			{
				(item.Value ? shiny : normal)[item.Key - 1]++;
			}
			_unsaved = true;
			DexSync.SendToClients();
		}

		public static void Commit()
		{
			if (_unsaved && !(_loadedPath != _savedFilePath))
			{
				ES3.Save<int[]>("DexSold", Sold, _savedFilePath);
				ES3.Save<int[]>("DexSoldShiny", SoldShiny, _savedFilePath);
				ES3.Save<int[]>("DexReleased", Released, _savedFilePath);
				ES3.Save<int[]>("DexReleasedShiny", ReleasedShiny, _savedFilePath);
				_unsaved = false;
			}
		}

		public static void SetCounts(int[] sold, int[] soldShiny, int[] released, int[] releasedShiny)
		{
			Sold = Fit(sold);
			SoldShiny = Fit(soldShiny);
			Released = Fit(released);
			ReleasedShiny = Fit(releasedShiny);
		}

		private static int[] Fit(int[] source)
		{
			int[] array = new int[PokemonList.Gen1PokemonNames.Count];
			if (source != null)
			{
				Array.Copy(source, array, Mathf.Min(array.Length, source.Length));
			}
			return array;
		}
	}
	public static class DexSync
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static HandleNamedMessageDelegate <0>__OnCounts;

			public static HandleNamedMessageDelegate <1>__OnRequest;
		}

		private const string CountsMessage = "Pokemoons.DexCounts";

		private const string RequestMessage = "Pokemoons.DexRequest";

		public static void Register()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			NetworkManager singleton = NetworkManager.Singleton;
			CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null);
			if (val != null)
			{
				object obj = <>O.<0>__OnCounts;
				if (obj == null)
				{
					HandleNamedMessageDelegate val2 = OnCounts;
					<>O.<0>__OnCounts = val2;
					obj = (object)val2;
				}
				val.RegisterNamedMessageHandler("Pokemoons.DexCounts", (HandleNamedMessageDelegate)obj);
				object obj2 = <>O.<1>__OnRequest;
				if (obj2 == null)
				{
					HandleNamedMessageDelegate val3 = OnRequest;
					<>O.<1>__OnRequest = val3;
					obj2 = (object)val3;
				}
				val.RegisterNamedMessageHandler("Pokemoons.DexRequest", (HandleNamedMessageDelegate)obj2);
			}
		}

		public unsafe static void RequestFromHost()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || singleton.IsServer)
			{
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(1, (Allocator)2, -1);
			try
			{
				byte b = 0;
				((FastBufferWriter)(ref val)).WriteValueSafe<byte>(ref b, default(ForPrimitives));
				singleton.CustomMessagingManager.SendNamedMessage("Pokemoons.DexRequest", 0uL, val, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		public static void SendToClients()
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsServer)
			{
				return;
			}
			foreach (ulong connectedClientsId in singleton.ConnectedClientsIds)
			{
				if (connectedClientsId != 0L)
				{
					Send(connectedClientsId);
				}
			}
		}

		private unsafe static void Send(ulong clientId)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null)
			{
				return;
			}
			int num = 32 + 4 * DexData.Sold.Length * 4;
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(num, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(DexData.Sold, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(DexData.SoldShiny, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(DexData.Released, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(DexData.ReleasedShiny, default(ForPrimitives));
				singleton.CustomMessagingManager.SendNamedMessage("Pokemoons.DexCounts", clientId, val, (NetworkDelivery)4);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private static void OnRequest(ulong senderClientId, FastBufferReader reader)
		{
			if (!((Object)(object)NetworkManager.Singleton == (Object)null) && NetworkManager.Singleton.IsServer)
			{
				DexData.EnsureLoaded();
				Send(senderClientId);
			}
		}

		private static void OnCounts(ulong senderClientId, FastBufferReader reader)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)NetworkManager.Singleton == (Object)null) && !NetworkManager.Singleton.IsServer)
			{
				int[] sold = default(int[]);
				((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref sold, default(ForPrimitives));
				int[] soldShiny = default(int[]);
				((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref soldShiny, default(ForPrimitives));
				int[] released = default(int[]);
				((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref released, default(ForPrimitives));
				int[] releasedShiny = default(int[]);
				((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref releasedShiny, default(ForPrimitives));
				DexData.SetCounts(sold, soldShiny, released, releasedShiny);
			}
		}
	}
	internal static class LLLCompat
	{
		private const string Guid = "imabatby.lethallevelloader";

		private static readonly HashSet<string> AlwaysNamed = new HashSet<string> { "artifice", "embrion" };

		private static bool _failed;

		private static PropertyInfo _levels;

		private static PropertyInfo _selectableLevel;

		private static PropertyInfo _locked;

		private static PropertyInfo _hidden;

		public static bool Enabled
		{
			get
			{
				if (!_failed)
				{
					return Chainloader.PluginInfos.ContainsKey("imabatby.lethallevelloader");
				}
				return false;
			}
		}

		public static HashSet<string> LockedMoons()
		{
			HashSet<string> hashSet = new HashSet<string>();
			if (!Enabled)
			{
				return hashSet;
			}
			try
			{
				if (_levels == null)
				{
					Type type = AccessTools.TypeByName("LethalLevelLoader.PatchedContent");
					Type type2 = AccessTools.TypeByName("LethalLevelLoader.ExtendedLevel");
					_levels = AccessTools.Property(type, "ExtendedLevels");
					_selectableLevel = AccessTools.Property(type2, "SelectableLevel");
					_locked = AccessTools.Property(type2, "IsRouteLocked");
					_hidden = AccessTools.Property(type2, "IsRouteHidden");
					if (_levels == null || _selectableLevel == null || _locked == null || _hidden == null)
					{
						throw new MissingMemberException("LethalLevelLoader.ExtendedLevel", "IsRouteLocked / IsRouteHidden");
					}
				}
				if (!(_levels.GetValue(null) is IEnumerable enumerable))
				{
					return hashSet;
				}
				foreach (object item in enumerable)
				{
					if (item != null && ((bool)_locked.GetValue(item) || (bool)_hidden.GetValue(item)))
					{
						object? value = _selectableLevel.GetValue(item);
						SelectableLevel val = (SelectableLevel)((value is SelectableLevel) ? value : null);
						if (val != null && !string.IsNullOrEmpty(val.PlanetName) && !AlwaysNamed.Contains(SpawnWeights.SimplifyMoon(val.PlanetName)))
						{
							hashSet.Add(val.PlanetName);
						}
					}
				}
			}
			catch (Exception ex)
			{
				_failed = true;
				Plugin.logger.LogWarning((object)("Pokedex: couldn't read LethalLevelLoader's locked moons (" + ex.GetType().Name + ": " + ex.Message + "). All moons will be named."));
			}
			return hashSet;
		}
	}
	public static class NewEntryPopup
	{
		public enum PopupPosition
		{
			TopRight,
			Centre
		}

		private struct PopupInfo
		{
			public int DexNumber;

			public bool Shiny;

			public Sprite Icon;

			public int FoundCount;
		}

		public const string SoundPath = "Assets/Pokemons/Sounds/itemgot.ogg";

		private const float FadeTime = 0.3f;

		private const float FlipTime = 1f;

		private const float HoldTime = 2.5f;

		private const float SlideDistance = 0.03f;

		private static readonly Color ShinyColour = new Color(1f, 0.84f, 0f);

		private const float FrameThickness = 0.003f;

		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<float> _volume;

		private static ConfigEntry<PopupPosition> _position;

		private const float BoxScale = 0.8f;

		private static AudioClip _sound;

		private static HashSet<int> _known;

		private static HashSet<int> _knownShiny;

		private static readonly Queue<PopupInfo> _queue = new Queue<PopupInfo>();

		private static bool _running;

		public static void Init(ConfigFile config)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			_enabled = config.Bind<bool>("Pokedex", "NewEntryPopup", true, "Show a pop-up when a Pokemon species (or its shiny) is brought back to the ship for the first time.");
			_volume = config.Bind<float>("Pokedex", "NewEntrySoundVolume", 0.8f, new ConfigDescription("Volume of the pop-up's sound (0 to 1).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			_position = config.Bind<PopupPosition>("Pokedex", "NewEntryPosition", PopupPosition.TopRight, "Where the pop-up appears on screen. Try Centre if another mod (e.g. Brutal Company) also uses the top right.");
		}

		public static void LoadSound(AssetBundle bundle)
		{
			_sound = bundle.LoadAsset<AudioClip>("Assets/Pokemons/Sounds/itemgot.ogg");
		}

		public static void Reset()
		{
			_known = null;
			_knownShiny = null;
			_queue.Clear();
			_running = false;
		}

		public static void OnArriving(GrabbableObject item)
		{
			if (!_enabled.Value || !(item is PokemonProp pokemonProp) || !DexData.TryGetDexNumber(item, out var dexNumber))
			{
				return;
			}
			DexData.GetFound(out var found, out var foundShiny, out var _);
			if (_known == null)
			{
				_known = new HashSet<int>(from n in Enumerable.Range(1, found.Length)
					where found[n - 1] > 0
					select n);
				_knownShiny = new HashSet<int>(from n in Enumerable.Range(1, found.Length)
					where foundShiny[n - 1] > 0
					select n);
			}
			bool flag = found[dexNumber - 1] == 0 && _known.Add(dexNumber);
			bool flag2 = pokemonProp.IsShiny && foundShiny[dexNumber - 1] == 0 && _knownShiny.Add(dexNumber);
			if (flag || flag2)
			{
				_queue.Enqueue(new PopupInfo
				{
					DexNumber = dexNumber,
					Shiny = flag2,
					Icon = item.itemProperties.itemIcon,
					FoundCount = found.Count((int c) => c > 0) + (flag ? 1 : 0)
				});
				if (!_running && (Object)(object)HUDManager.Instance != (Object)null)
				{
					_running = true;
					((MonoBehaviour)HUDManager.Instance).StartCoroutine(RunQueue());
				}
			}
		}

		private static IEnumerator RunQueue()
		{
			while (_queue.Count > 0)
			{
				PopupInfo info = _queue.Dequeue();
				GameObject val = null;
				try
				{
					val = Build(info);
				}
				catch (Exception ex)
				{
					Plugin.logger.LogWarning((object)("Pokedex: new entry pop-up failed to show: " + ex.Message));
				}
				if ((Object)(object)val != (Object)null)
				{
					yield return Animate(val);
				}
			}
			_running = false;
		}

		private static GameObject Build(PopupInfo info)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_00d0: Expected O, but got Unknown
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: 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_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: 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_032c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0376: Unknown result type (might be due to invalid IL or missing references)
			//IL_037b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_038f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0390: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a2: 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_03c0: Unknown result type (might be due to invalid IL or missing references)
			HUDManager instance = HUDManager.Instance;
			TextMeshProUGUI val = ((instance.ScrapItemBoxes != null && instance.ScrapItemBoxes.Length != 0 && instance.ScrapItemBoxes[0] != null) ? instance.ScrapItemBoxes[0].headerText : null);
			if ((Object)(object)val == (Object)null)
			{
				val = instance.tipsPanelHeader;
			}
			if ((Object)(object)((Graphic)val).canvas == (Object)null)
			{
				return null;
			}
			Canvas rootCanvas = ((Graphic)val).canvas.rootCanvas;
			Rect rect = ((RectTransform)((Component)rootCanvas).transform).rect;
			float height = ((Rect)(ref rect)).height;
			float num = height * 0.8f;
			Color colour = (info.Shiny ? ShinyColour : ((Graphic)val).color);
			colour.a = 1f;
			GameObject val2 = new GameObject("PokemoonsNewEntry", new Type[2]
			{
				typeof(RectTransform),
				typeof(CanvasGroup)
			});
			RectTransform val3 = (RectTransform)val2.transform;
			((Transform)val3).SetParent(((Component)rootCanvas).transform, false);
			((Transform)val3).SetAsLastSibling();
			val3.sizeDelta = new Vector2(num * 0.55f, num * 0.42f);
			Vector2 val4 = default(Vector2);
			Vector2 val5;
			if (_position.Value == PopupPosition.TopRight)
			{
				((Vector2)(ref val4))..ctor(1f, 1f);
				val3.pivot = val4;
				val5 = (val3.anchorMin = (val3.anchorMax = val4));
				val3.anchoredPosition = new Vector2((0f - height) * 0.04f, (0f - height) * 0.2f);
			}
			else
			{
				((Vector2)(ref val4))..ctor(0.5f, 1f);
				val3.pivot = val4;
				val5 = (val3.anchorMin = (val3.anchorMax = val4));
				val3.anchoredPosition = new Vector2(0f, (0f - height) * 0.24f);
			}
			val2.GetComponent<CanvasGroup>().blocksRaycasts = false;
			float num2 = num * 0.003f;
			AddBar(val3, colour, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0f, num2));
			AddBar(val3, colour, new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(0f, num2));
			AddBar(val3, colour, new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(num2, 0f));
			AddBar(val3, colour, new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(num2, 0f));
			string arg = PokemonList.Gen1PokemonNames[info.DexNumber - 1].ToUpperInvariant();
			AddText(val2, val, info.Shiny ? "NEW SHINY!" : "NEW POKEMON", colour, num * 0.045f, 0.9f);
			AddText(val2, val, $"#{info.DexNumber:D3}  {arg}", colour, num * 0.04f, 0.2f);
			AddText(val2, val, $"Pokedex {info.FoundCount}/{PokemonList.Gen1PokemonNames.Count}", colour, num * 0.03f, 0.08f);
			if ((Object)(object)info.Icon != (Object)null)
			{
				GameObject val10 = new GameObject("Icon", new Type[2]
				{
					typeof(RectTransform),
					typeof(Image)
				});
				RectTransform val11 = (RectTransform)val10.transform;
				((Transform)val11).SetParent((Transform)(object)val3, false);
				((Vector2)(ref val5))..ctor(0.5f, 0.53f);
				val11.anchorMax = val5;
				val11.anchorMin = val5;
				val11.sizeDelta = new Vector2(num * 0.2f, num * 0.2f);
				Image component = val10.GetComponent<Image>();
				component.sprite = info.Icon;
				component.preserveAspect = true;
				((Graphic)component).raycastTarget = false;
			}
			return val2;
		}

		private static void AddBar(RectTransform parent, Color colour, Vector2 anchorMin, Vector2 anchorMax, Vector2 size)
		{
			//IL_0025: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Frame", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)parent, false);
			val2.anchorMin = anchorMin;
			val2.anchorMax = anchorMax;
			val2.sizeDelta = size;
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = colour;
			((Graphic)component).raycastTarget = false;
		}

		private static void AddText(GameObject box, TextMeshProUGUI template, string text, Color colour, float size, float y)
		{
			//IL_0025: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Text", new Type[2]
			{
				typeof(RectTransform),
				typeof(TextMeshProUGUI)
			});
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent(box.transform, false);
			val2.anchorMin = new Vector2(0f, y);
			val2.anchorMax = new Vector2(1f, y);
			val2.sizeDelta = new Vector2(0f, size * 1.5f);
			TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>();
			((TMP_Text)component).font = ((TMP_Text)template).font;
			((TMP_Text)component).fontSharedMaterial = ((TMP_Text)template).fontSharedMaterial;
			((TMP_Text)component).fontSize = size;
			((Graphic)component).color = colour;
			((TMP_Text)component).alignment = (TextAlignmentOptions)514;
			((TMP_Text)component).enableWordWrapping = false;
			((Graphic)component).raycastTarget = false;
			((TMP_Text)component).text = text;
		}

		private static IEnumerator Animate(GameObject box)
		{
			RectTransform rect = (RectTransform)box.transform;
			CanvasGroup group = box.GetComponent<CanvasGroup>();
			Transform icon = ((Transform)rect).Find("Icon");
			Rect rect2 = ((RectTransform)((Transform)rect).parent).rect;
			float slide = ((Rect)(ref rect2)).height * 0.03f;
			Vector2 rest = rect.anchoredPosition;
			if ((Object)(object)_sound != (Object)null)
			{
				HUDManager.Instance.UIAudio.PlayOneShot(_sound, _volume.Value);
			}
			for (float t = 0f; t < 0.3f; t += Time.deltaTime)
			{
				float num = (group.alpha = t / 0.3f);
				rect.anchoredPosition = rest + new Vector2(0f, slide * (1f - num));
				yield return null;
			}
			group.alpha = 1f;
			rect.anchoredPosition = rest;
			if ((Object)(object)icon != (Object)null)
			{
				for (float t = 0f; t < 1f; t += Time.deltaTime)
				{
					icon.localScale = new Vector3(Mathf.Cos(t / 1f * MathF.PI * 2f), 1f, 1f);
					yield return null;
				}
				icon.localScale = Vector3.one;
			}
			yield return (object)new WaitForSeconds(2.5f);
			for (float t = 0f; t < 0.3f; t += Time.deltaTime)
			{
				group.alpha = 1f - t / 0.3f;
				yield return null;
			}
			Object.Destroy((Object)(object)box);
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB), "SetItemInElevator")]
	internal static class NewEntryPatch
	{
		[HarmonyPrefix]
		private static void Prefix(bool droppedInShipRoom, GrabbableObject gObject)
		{
			if (droppedInShipRoom && (Object)(object)gObject != (Object)null && !gObject.isInShipRoom)
			{
				try
				{
					NewEntryPopup.OnArriving(gObject);
				}
				catch (Exception ex)
				{
					Plugin.logger.LogWarning((object)("Pokedex: new entry check failed: " + ex.Message));
				}
			}
		}
	}
	[BepInPlugin("shronkstones.pokemoons", "PokeMoons", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string modGUID = "shronkstones.pokemoons";

		public const string modName = "PokeMoons";

		public const string modVersion = "1.0.0";

		public static Plugin Instance;

		public static ManualLogSource logger;

		public static ConfigEntry<float> PokemonCryVolume;

		private void Awake()
		{
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Expected O, but got Unknown
			Instance = this;
			logger = ((BaseUnityPlugin)this).Logger;
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			for (int i = 0; i < types.Length; i++)
			{
				MethodInfo[] methods = types[i].GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					if (methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false).Length != 0)
					{
						methodInfo.Invoke(null, null);
					}
				}
			}
			ShinySystem.Init(((BaseUnityPlugin)this).Config);
			PokedexCommand.Init(((BaseUnityPlugin)this).Config);
			NewEntryPopup.Init(((BaseUnityPlugin)this).Config);
			PokemonCryVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Sounds", "PokemonCryVolume", 0.4f, new ConfigDescription("Volume of each Pokemon's cry when picked up.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			SpawnWeights.Init(((BaseUnityPlugin)this).Config, directoryName);
			AssetBundle val = AssetBundle.LoadFromFile(Path.Combine(directoryName, "pokemoons"));
			if ((Object)(object)val == (Object)null)
			{
				logger.LogError((object)"Bundle Not Found");
				return;
			}
			PokemonItemLoader pokemonItemLoader = new PokemonItemLoader(val);
			foreach (string gen1PokemonName in PokemonList.Gen1PokemonNames)
			{
				pokemonItemLoader.LoadPokemon(gen1PokemonName);
			}
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "shronkstones.pokemoons");
			logger.LogInfo((object)"Plugin shronkstones.pokemoons is loaded!");
		}
	}
	public static class PokedexCommand
	{
		public enum HintMoonSet
		{
			Both,
			Vanilla,
			Modded
		}

		private const int PageSize = 15;

		private const int MaxMoons = 8;

		private const int NameWidth = 12;

		private static ConfigEntry<HintMoonSet> _hintMoons;

		private static ConfigEntry<bool> _hideLocked;

		private static readonly HashSet<string> VanillaMoons = new HashSet<string>
		{
			"experimentation", "assurance", "vow", "offense", "march", "adamance", "rend", "dine", "titan", "artifice",
			"embrion"
		};

		private const float CommonCutoff = 0.06f;

		private const float UncommonCutoff = 0.03f;

		public static void Init(ConfigFile config)
		{
			_hintMoons = config.Bind<HintMoonSet>("Pokedex", "HintMoons", HintMoonSet.Both, "Whether to suggest Vanilla or Modded moons as habitats in the Pokedex. Modded is suggested if playing Wesley's moons.");
			_hideLocked = config.Bind<bool>("Pokedex", "HideLockedMoons", true, "Moons show as ??? in the Pokedex until routing to them is unlocked. Recommended true for Wesley's moons).");
		}

		public static bool IsCommand(string word)
		{
			if (!(word == "pokedex"))
			{
				return word == "dex";
			}
			return true;
		}

		public static string Execute(string[] args)
		{
			if (args.Length == 0)
			{
				return ListView(1, missingOnly: false);
			}
			bool flag = args[0] == "missing";
			string[] array = (flag ? args.Skip(1).ToArray() : args);
			if (array.Length == 0)
			{
				return ListView(1, flag);
			}
			if (array.Length == 1 && array[0].Length > 1 && array[0][0] == 'p' && int.TryParse(array[0].Substring(1), out var result))
			{
				return ListView(result, flag);
			}
			if (!flag)
			{
				if (array.Length == 1 && int.TryParse(array[0], out var result2))
				{
					return EntryView(result2);
				}
				string wanted = SpawnWeights.Simplify(string.Join("", array));
				int num = PokemonList.Gen1PokemonNames.FindIndex((string n) => SpawnWeights.Simplify(n) == wanted);
				if (num >= 0)
				{
					return EntryView(num + 1);
				}
			}
			return "Usage:\n  pokedex\n  pokedex p2\n  pokedex missing\n  pokedex 25  or  pokedex pikachu\n";
		}

		private static string ListView(int page, bool missingOnly)
		{
			DexData.GetFound(out var found, out var foundShiny, out var _);
			List<int> list = (from n in Enumerable.Range(1, found.Length)
				where !missingOnly || found[n - 1] == 0
				select n).ToList();
			int num = Math.Max(1, (list.Count + 15 - 1) / 15);
			page = Math.Min(Math.Max(page, 1), num);
			StringBuilder stringBuilder = new StringBuilder();
			if (found.All((int c) => c > 0))
			{
				stringBuilder.AppendLine("CONGRATULATIONS! You're a Pokemon master!\n");
			}
			stringBuilder.AppendLine($"POKEDEX  Found {found.Count((int c) => c > 0)}/{found.Length}  Shiny {foundShiny.Count((int c) => c > 0)}");
			stringBuilder.AppendLine(string.Format("{0} - page {1}/{2}", missingOnly ? "Missing" : "All", page, num));
			stringBuilder.AppendLine(new string('-', 40));
			stringBuilder.AppendLine("No. " + "Name".PadRight(12) + " Found  Shiny");
			if (list.Count == 0)
			{
				stringBuilder.AppendLine("Nothing missing!");
			}
			foreach (int item in list.Skip((page - 1) * 15).Take(15))
			{
				string text = Shorten(PokemonList.Gen1PokemonNames[item - 1]);
				if (found[item - 1] == 0)
				{
					stringBuilder.AppendLine($"{item:D3} {text.PadRight(12)}   ---");
					continue;
				}
				stringBuilder.AppendLine($"{item:D3} {text.PadRight(12)} {found[item - 1],5}  {foundShiny[item - 1],5}");
			}
			stringBuilder.AppendLine();
			string arg = (missingOnly ? "pokedex missing" : "pokedex");
			if (page < num)
			{
				stringBuilder.AppendLine($"Next: {arg} p{page + 1}");
			}
			if (page > 1)
			{
				stringBuilder.AppendLine($"Prev: {arg} p{page - 1}");
			}
			stringBuilder.AppendLine("Details: pokedex 25  or  pokedex pikachu");
			if (!missingOnly)
			{
				stringBuilder.AppendLine("Missing only: pokedex missing");
			}
			return stringBuilder.ToString();
		}

		private static string EntryView(int number)
		{
			if (number < 1 || number > PokemonList.Gen1PokemonNames.Count)
			{
				return $"There is no Pokemon #{number}. The Pokemon covered are between 1 and {PokemonList.Gen1PokemonNames.Count}.";
			}
			DexData.GetFound(out var found, out var foundShiny, out var onShip);
			int num = number - 1;
			string text = PokemonList.Gen1PokemonNames[num];
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine($"#{number:D3} {text.ToUpperInvariant()}");
			stringBuilder.AppendLine(new string('-', 40));
			bool flag = found[num] > 0;
			if (flag)
			{
				stringBuilder.AppendLine($"Found: {found[num]} ({foundShiny[num]} shiny)");
				stringBuilder.AppendLine($"In ship: {onShip[num]}  Sold: {DexData.Sold[num] + DexData.SoldShiny[num]}  Released: {DexData.Released[num] + DexData.ReleasedShiny[num]}");
				PokemonInfo pokemonInfo = PokemonInfoData.Get(text);
				if (pokemonInfo != null)
				{
					stringBuilder.AppendLine();
					stringBuilder.AppendLine("Species: " + pokemonInfo.species);
					if (pokemonInfo.type != null && pokemonInfo.type.Length != 0)
					{
						stringBuilder.AppendLine("Type: " + string.Join("/", pokemonInfo.type));
					}
					if (!string.IsNullOrEmpty(pokemonInfo.description))
					{
						stringBuilder.AppendLine(pokemonInfo.description);
					}
				}
				stringBuilder.AppendLine(new string('-', 40));
			}
			else
			{
				stringBuilder.AppendLine("Not found yet.");
				stringBuilder.AppendLine();
			}
			if (!DexData.DexEntries.TryGetValue(text, out var value) || value.SpawnChance.Count == 0)
			{
				stringBuilder.AppendLine("No sightings reported on any moon.");
				return stringBuilder.ToString();
			}
			HashSet<string> locked = (_hideLocked.Value ? LLLCompat.LockedMoons() : new HashSet<string>());
			List<KeyValuePair<string, float>> list = (from kv in value.SpawnChance
				where kv.Value > 0f && ShowMoon(kv.Key)
				orderby locked.Contains(kv.Key), kv.Value descending
				select kv).Take(8).ToList();
			if (list.Count == 0)
			{
				stringBuilder.AppendLine("No sightings on the moons covered by the Pokedex.");
				stringBuilder.AppendLine("(Pokedex HintMoons in the config is probably set to Modded moons only.)");
				return stringBuilder.ToString();
			}
			stringBuilder.AppendLine(flag ? "Habitats:" : "Reported sightings:");
			foreach (KeyValuePair<string, float> item in list)
			{
				stringBuilder.AppendLine($"  {MoonLabel(item.Key, locked),-22} {RarityWord(item.Key, value)}");
			}
			return stringBuilder.ToString();
		}

		private static bool ShowMoon(string planetName)
		{
			HintMoonSet value = _hintMoons.Value;
			if (value == HintMoonSet.Both)
			{
				return true;
			}
			bool flag = VanillaMoons.Contains(SpawnWeights.SimplifyMoon(planetName));
			if (value != HintMoonSet.Vanilla)
			{
				return !flag;
			}
			return flag;
		}

		private static string MoonLabel(string planetName, HashSet<string> locked)
		{
			if (!locked.Contains(planetName))
			{
				return planetName;
			}
			return "???";
		}

		private static string RarityWord(string moon, DexEntry entry)
		{
			int num = 0;
			foreach (DexEntry value3 in DexData.DexEntries.Values)
			{
				if (value3.SpawnWeight.TryGetValue(moon, out var value) && value > 0)
				{
					num += value;
				}
			}
			if (num <= 0 || !entry.SpawnWeight.TryGetValue(moon, out var value2))
			{
				return "missingno";
			}
			float num2 = (float)value2 / (float)num;
			if (num2 >= 0.06f)
			{
				return "common";
			}
			if (num2 >= 0.03f)
			{
				return "uncommon";
			}
			return "rare";
		}

		private static string Shorten(string name)
		{
			if (name.Length <= 12)
			{
				return name;
			}
			return name.Substring(0, 11) + ".";
		}
	}
	public class PokemonInfo
	{
		public string name;

		public string species;

		public string description;

		public string[] type;
	}
	public static class PokemonInfoData
	{
		private const string DataFileName = "pokemon_151.json";

		private static Dictionary<string, PokemonInfo> _byName;

		public static PokemonInfo Get(string name)
		{
			if (_byName == null)
			{
				Load();
			}
			_byName.TryGetValue(SpawnWeights.Simplify(name), out var value);
			return value;
		}

		private static void Load()
		{
			_byName = new Dictionary<string, PokemonInfo>();
			try
			{
				Assembly executingAssembly = Assembly.GetExecutingAssembly();
				string name = executingAssembly.GetManifestResourceNames().FirstOrDefault((string n) => n.EndsWith("pokemon_151.json", StringComparison.OrdinalIgnoreCase));
				string text;
				using (Stream stream = executingAssembly.GetManifestResourceStream(name))
				{
					using StreamReader streamReader = new StreamReader(stream);
					text = streamReader.ReadToEnd();
				}
				PokemonInfo[] array = JsonConvert.DeserializeObject<PokemonInfo[]>(text.TrimStart('\ufeff'));
				foreach (PokemonInfo pokemonInfo in array)
				{
					if (!string.IsNullOrEmpty(pokemonInfo.name))
					{
						pokemonInfo.species = Plain(pokemonInfo.species);
						pokemonInfo.description = Plain(pokemonInfo.description);
						pokemonInfo.type = pokemonInfo.type?.Select(Plain).ToArray();
						_byName[SpawnWeights.Simplify(pokemonInfo.name.Replace("♀", "F").Replace("♂", "M"))] = pokemonInfo;
					}
				}
				int num2 = PokemonList.Gen1PokemonNames.Count((string n) => !_byName.ContainsKey(SpawnWeights.Simplify(n)));
				Plugin.logger.LogInfo((object)($"Pokedex: loaded entries for {_byName.Count} Pokemon" + ((num2 > 0) ? $" ({num2} Pokemon have no entry)." : ".")));
			}
			catch (Exception arg)
			{
				Plugin.logger.LogError((object)string.Format("Pokedex: failed to read {0}: {1}", "pokemon_151.json", arg));
			}
		}

		private static string Plain(string text)
		{
			if (string.IsNullOrEmpty(text))
			{
				return text;
			}
			return text.Replace("é", "e").Replace("’", "'").Replace("‘", "'")
				.Replace("“", "\"")
				.Replace("”", "\"")
				.Replace("—", " - ")
				.Replace("♀", " F")
				.Replace("♂", " M");
		}
	}
	public class PokemonItemLoader
	{
		private AssetBundle _bundle;

		private const string _baseAssetPath = "Assets/Pokemons/Scrap";

		private static readonly AudioClip SilentClip = AudioClip.Create("PokemoonsSilence", 1, 1, 44100, false);

		private static readonly HashSet<AudioClip> _scaledClips = new HashSet<AudioClip>();

		public PokemonItemLoader(AssetBundle bundle)
		{
			_bundle = bundle;
			ShinySystem.LoadSound(bundle);
			NewEntryPopup.LoadSound(bundle);
		}

		public void LoadPokemon(string name)
		{
			Plugin.logger.LogInfo((object)("Loading Pokemon " + name));
			string text = "Assets/Pokemons/Scrap/" + name + "/" + name + "_Item.asset";
			Item val = _bundle.LoadAsset<Item>(text);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.logger.LogError((object)("Cannot load " + name + ": no item asset at " + text + "."));
				return;
			}
			if ((Object)(object)val.pocketSFX == (Object)null)
			{
				val.pocketSFX = SilentClip;
			}
			((Object)val).name = name;
			val.itemName = name;
			val.isScrap = true;
			GameObject spawnPrefab = val.spawnPrefab;
			if ((Object)(object)spawnPrefab == (Object)null)
			{
				Plugin.logger.LogWarning((object)("Item " + name + " has no spawn prefab assigned. Skipping."));
				return;
			}
			ScaleVolume(val.grabSFX, Plugin.PokemonCryVolume.Value);
			val.saveItemVariable = true;
			if ((Object)(object)spawnPrefab.GetComponent<PokemonProp>() == (Object)null)
			{
				if ((Object)(object)spawnPrefab.GetComponent<GrabbableObject>() == (Object)null)
				{
					PokemonProp pokemonProp = spawnPrefab.AddComponent<PokemonProp>();
					((GrabbableObject)pokemonProp).grabbable = true;
					((GrabbableObject)pokemonProp).grabbableToEnemies = true;
					((GrabbableObject)pokemonProp).itemProperties = val;
				}
				else
				{
					Plugin.logger.LogWarning((object)("GrabbableObject was not null for " + name + ". PokemonProp skipped."));
				}
			}
			NetworkPrefabs.RegisterNetworkPrefab(spawnPrefab);
			Utilities.FixMixerGroups(spawnPrefab);
			Items.RegisterScrap(val, (Dictionary<LevelTypes, int>)null, (Dictionary<string, int>)null);
			SpawnWeights.RegisterItem(name, val);
		}

		private static void ScaleVolume(AudioClip clip, float volume)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Invalid comparison between Unknown and I4
			if ((Object)(object)clip == (Object)null || Mathf.Approximately(volume, 1f) || !_scaledClips.Add(clip))
			{
				return;
			}
			if ((int)clip.loadState != 2)
			{
				clip.LoadAudioData();
			}
			float[] array = new float[clip.samples * clip.channels];
			if (!clip.GetData(array, 0))
			{
				Plugin.logger.LogDebug((object)"Note that the sound being loaded needs 'Decompress On Load' or else its volume can't be changed.");
				return;
			}
			for (int i = 0; i < array.Length; i++)
			{
				array[i] *= volume;
			}
			clip.SetData(array, 0);
		}
	}
	public static class PokemonList
	{
		public static readonly List<string> Gen1PokemonNames = new List<string>
		{
			"Bulbasaur", "Ivysaur", "Venusaur", "Charmander", "Charmeleon", "Charizard", "Squirtle", "Wartortle", "Blastoise", "Caterpie",
			"Metapod", "Butterfree", "Weedle", "Kakuna", "Beedrill", "Pidgey", "Pidgeotto", "Pidgeot", "Rattata", "Raticate",
			"Spearow", "Fearow", "Ekans", "Arbok", "Pikachu", "Raichu", "Sandshrew", "Sandslash", "NidoranF", "Nidorina",
			"Nidoqueen", "NidoranM", "Nidorino", "Nidoking", "Clefairy", "Clefable", "Vulpix", "Ninetales", "Jigglypuff", "Wigglytuff",
			"Zubat", "Golbat", "Oddish", "Gloom", "Vileplume", "Paras", "Parasect", "Venonat", "Venomoth", "Diglett",
			"Dugtrio", "Meowth", "Persian", "Psyduck", "Golduck", "Mankey", "Primeape", "Growlithe", "Arcanine", "Poliwag",
			"Poliwhirl", "Poliwrath", "Abra", "Kadabra", "Alakazam", "Machop", "Machoke", "Machamp", "Bellsprout", "Weepinbell",
			"Victreebel", "Tentacool", "Tentacruel", "Geodude", "Graveler", "Golem", "Ponyta", "Rapidash", "Slowpoke", "Slowbro",
			"Magnemite", "Magneton", "Farfetchd", "Doduo", "Dodrio", "Seel", "Dewgong", "Grimer", "Muk", "Shellder",
			"Cloyster", "Gastly", "Haunter", "Gengar", "Onix", "Drowzee", "Hypno", "Krabby", "Kingler", "Voltorb",
			"Electrode", "Exeggcute", "Exeggutor", "Cubone", "Marowak", "Hitmonlee", "Hitmonchan", "Lickitung", "Koffing", "Weezing",
			"Rhyhorn", "Rhydon", "Chansey", "Tangela", "Kangaskhan", "Horsea", "Seadra", "Goldeen", "Seaking", "Staryu",
			"Starmie", "MrMime", "Scyther", "Jynx", "Electabuzz", "Magmar", "Pinsir", "Tauros", "Magikarp", "Gyarados",
			"Lapras", "Ditto", "Eevee", "Vaporeon", "Jolteon", "Flareon", "Porygon", "Omanyte", "Omastar", "Kabuto",
			"Kabutops", "Aerodactyl", "Snorlax", "Articuno", "Zapdos", "Moltres", "Dratini", "Dragonair", "Dragonite", "Mewtwo",
			"Mew"
		};
	}
	public class PokemonProp : PhysicsProp
	{
		private readonly NetworkVariable<int> shinyState = new NetworkVariable<int>(0, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		private int _loadedState;

		private Transform _shinyModel;

		private string _baseHeader;

		private float _baseSparkleRate = -1f;

		private Transform _sparkle;

		private bool _sparklesShouldShow;

		public bool IsShiny => shinyState.Value == 2;

		public override void OnNetworkSpawn()
		{
			((NetworkBehaviour)this).OnNetworkSpawn();
			NetworkVariable<int> obj = shinyState;
			obj.OnValueChanged = (OnValueChangedDelegate<int>)(object)Delegate.Combine((Delegate?)(object)obj.OnValueChanged, (Delegate?)(object)new OnValueChangedDelegate<int>(OnShinyChanged));
			if (((NetworkBehaviour)this).IsServer && shinyState.Value == 0)
			{
				shinyState.Value = ((_loadedState != 0) ? _loadedState : ((!ShinySystem.RollShiny()) ? 1 : 2));
			}
			ApplyVisuals();
		}

		public override void OnNetworkDespawn()
		{
			NetworkVariable<int> obj = shinyState;
			obj.OnValueChanged = (OnValueChangedDelegate<int>)(object)Delegate.Remove((Delegate?)(object)obj.OnValueChanged, (Delegate?)(object)new OnValueChangedDelegate<int>(OnShinyChanged));
			((NetworkBehaviour)this).OnNetworkDespawn();
		}

		public override int GetItemDataToSave()
		{
			return shinyState.Value;
		}

		public override void LoadItemSaveData(int saveData)
		{
			if (saveData == 1 || saveData == 2)
			{
				_loadedState = saveData;
			}
		}

		public override void EquipItem()
		{
			bool isPocketed = ((GrabbableObject)this).isPocketed;
			((PhysicsProp)this).EquipItem();
			if (!isPocketed && IsShiny)
			{
				PlayShinySound();
			}
		}

		private void PlayShinySound()
		{
			AudioClip shinyClip = ShinySystem.ShinyClip;
			if (!((Object)(object)shinyClip == (Object)null))
			{
				float soundDelay = ShinySystem.SoundDelay;
				if (soundDelay <= 0f)
				{
					PlayClip(shinyClip);
				}
				else
				{
					((MonoBehaviour)this).StartCoroutine(PlayClipAfter(shinyClip, soundDelay));
				}
			}
		}

		private IEnumerator PlayClipAfter(AudioClip clip, float delay)
		{
			yield return (object)new WaitForSeconds(delay);
			PlayClip(clip);
		}

		private void PlayClip(AudioClip clip)
		{
			((Component)this).GetComponent<AudioSource>().PlayOneShot(clip, ShinySystem.SoundVolume);
		}

		private void OnShinyChanged(int previous, int current)
		{
			ApplyVisuals();
		}

		public override void Update()
		{
			((GrabbableObject)this).Update();
			UpdateSparkles();
		}

		private void UpdateSparkles()
		{
			if ((Object)(object)_sparkle == (Object)null)
			{
				return;
			}
			bool flag = _sparklesShouldShow && !((GrabbableObject)this).isPocketed;
			if (((Component)_sparkle).gameObject.activeSelf != flag)
			{
				((Component)_sparkle).gameObject.SetActive(flag);
				ParticleSystem component = ((Component)_sparkle).GetComponent<ParticleSystem>();
				if (flag && (Object)(object)component != (Object)null && !component.isPlaying)
				{
					component.Play();
				}
			}
		}

		private void ApplyVisuals()
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: 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_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_shinyModel == (Object)null)
			{
				_shinyModel = ((Component)this).transform.Find("PokemonShinyModel");
			}
			if ((Object)(object)_shinyModel == (Object)null)
			{
				if (IsShiny)
				{
					Plugin.logger.LogWarning((object)("[Shiny] " + ((Object)this).name + " does not have a shiny model."));
				}
				return;
			}
			foreach (Transform item in ((Component)this).transform)
			{
				Transform val = item;
				if (!((Object)(object)val == (Object)(object)_shinyModel) && !(((Object)val).name == "ScanNode") && (Object)(object)((Component)val).GetComponentInChildren<Renderer>(true) != (Object)null)
				{
					((Component)val).gameObject.SetActive(!IsShiny);
				}
			}
			((Component)_shinyModel).gameObject.SetActive(IsShiny);
			if ((Object)(object)_sparkle == (Object)null)
			{
				_sparkle = _shinyModel.Find("ShinySparkle");
			}
			_sparklesShouldShow = IsShiny && ShinySystem.Sparkles && ShinySystem.SparkleAmount > 0f;
			ParticleSystem val2 = (((Object)(object)_sparkle != (Object)null) ? ((Component)_sparkle).GetComponent<ParticleSystem>() : null);
			if (_sparklesShouldShow && (Object)(object)val2 != (Object)null)
			{
				EmissionModule emission = val2.emission;
				if (_baseSparkleRate < 0f)
				{
					MinMaxCurve rateOverTime = ((EmissionModule)(ref emission)).rateOverTime;
					_baseSparkleRate = ((MinMaxCurve)(ref rateOverTime)).constant;
				}
				((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(_baseSparkleRate * ShinySystem.SparkleAmount);
			}
			UpdateSparkles();
			ScanNodeProperties componentInChildren = ((Component)this).GetComponentInChildren<ScanNodeProperties>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				if (_baseHeader == null)
				{
					_baseHeader = componentInChildren.headerText;
				}
				componentInChildren.headerText = (IsShiny ? ("Shiny " + _baseHeader) : _baseHeader);
			}
		}

		protected override void __initializeVariables()
		{
			if (shinyState == null)
			{
				throw new Exception("PokemonProp.shinyState cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)shinyState).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)shinyState, "shinyState");
			((NetworkBehaviour)this).NetworkVariableFields.Add((NetworkVariableBase)(object)shinyState);
			((PhysicsProp)this).__initializeVariables();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		protected internal override string __getTypeName()
		{
			return "PokemonProp";
		}
	}
	public static class ShinySystem
	{
		public const string ShinyModelName = "PokemonShinyModel";

		private static ConfigEntry<int> _oneIn;

		private static ConfigEntry<bool> _sparkles;

		private static ConfigEntry<float> _sparkleAmount;

		private static ConfigEntry<float> _soundVolume;

		private static ConfigEntry<float> _soundDelay;

		public const string SoundPath = "Assets/Pokemons/Sounds/shiny.ogg";

		public static AudioClip ShinyClip { get; private set; }

		public static bool Sparkles => _sparkles.Value;

		public static float SparkleAmount => _sparkleAmount.Value;

		public static float SoundVolume => _soundVolume.Value;

		public static float SoundDelay => _soundDelay.Value;

		public static void Init(ConfigFile config)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Expected O, but got Unknown
			_oneIn = config.Bind<int>("Shiny", "ShinyChance", 30, new ConfigDescription("1 in this many Pokemon are shiny. 0 disables shinies.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100000), Array.Empty<object>()));
			_sparkles = config.Bind<bool>("Shiny", "SparkleEffectEnabled", true, "Show a sparkle effect on shiny Pokemon.");
			_sparkleAmount = config.Bind<float>("Shiny", "SparkleAmount", 1f, new ConfigDescription("Sparkle rate multiplier (1 = default, 0.5 = half, 2 = double).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 4f), Array.Empty<object>()));
			_soundVolume = config.Bind<float>("Shiny", "ShinySoundVolume", 1f, new ConfigDescription("Volume of the extra sound a shiny plays when picked up (0 to 1).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			_soundDelay = config.Bind<float>("Shiny", "ShinySoundDelay", 0f, new ConfigDescription("Seconds after pick-up until the shiny sound plays. 0 = at the same time as the cry.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
			Plugin.logger.LogInfo((object)$"Shiny system ready (1 in {_oneIn.Value}).");
		}

		public static void LoadSound(AssetBundle bundle)
		{
			ShinyClip = bundle.LoadAsset<AudioClip>("Assets/Pokemons/Sounds/shiny.ogg");
		}

		public static bool RollShiny()
		{
			int value = _oneIn.Value;
			if (value > 0)
			{
				return Random.Range(0, value) == 0;
			}
			return false;
		}
	}
	[Serializable]
	public class MoonWeightsFile
	{
		public float defaultShare;

		public string[] progressionItems;

		public MoonEntry[] moons;
	}
	[Serializable]
	public class MoonEntry
	{
		public string name;

		public string levelKey;

		public string[] match;

		public float share;

		public string[] species;

		public int[] weights;
	}
	public class SpawnSnapshot
	{
		public List<SpawnableItemWithRarity> list;

		public SpawnableItemWithRarity[] entries;

		public int[] rarities;
	}
	public static class SpawnWeights
	{
		public enum WeightsMode
		{
			Automatic,
			Override,
			Off
		}

		private const string DataFileName = "PokeMoonsMoonWeights.json";

		private const int TargetPokemonPoints = 500;

		private const int MaxMultiplier = 100;

		private static MoonWeightsFile _data;

		private static readonly Dictionary<string, MoonEntry> _moonByMatch = new Dictionary<string, MoonEntry>();

		private static readonly Dictionary<string, Item> _itemsByName = new Dictionary<string, Item>();

		private static readonly HashSet<Item> _pokemonItems = new HashSet<Item>();

		private static readonly HashSet<string> _reportedMoons = new HashSet<string>();

		private static ConfigEntry<WeightsMode> _mode;

		private static ConfigEntry<float> _defaultGlobalPokeScrapShare;

		private static ConfigEntry<bool> _protectProgression;

		private static ConfigEntry<string> _extraProgression;

		private static readonly Dictionary<string, ConfigEntry<string>> _moonShare = new Dictionary<string, ConfigEntry<string>>();

		private static readonly Dictionary<string, ConfigEntry<string>> _moonOverrides = new Dictionary<string, ConfigEntry<string>>();

		public static void Init(ConfigFile config, string pluginDir)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			_data = LoadData(pluginDir);
			_mode = config.Bind<WeightsMode>("General", "WeightsMode", WeightsMode.Automatic, "How Pokemon are added to each moon's loot pool. Automatic (recommended): use recommended spawn weights, where Pokemon appear on moons that match their type and difficulty, except on moons where another mod (e.g. LethalQuantities) adds Pokemon itself. Override: always use the recommended weights, replacing any from other mods. Off: Pokemon only spawn where another mod gives them weights.");
			_defaultGlobalPokeScrapShare = config.Bind<float>("General", "PokemonShare", (_data != null) ? _data.defaultShare : 0.5f, new ConfigDescription("Share of each moon's loot that is Pokemon, from 0 to 0.95 (0.5 = half). Applies to every moon except Dine, and moons with a Share set in the moon-specific section later.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.95f), Array.Empty<object>()));
			_protectProgression = config.Bind<bool>("Progression", "ProtectProgressionItems", true, "Raise the weights of progression items (moon-unlocking videotapes and logs) so adding the Pokemon doesn't make them rarer.");
			_extraProgression = config.Bind<string>("Progression", "ExtraProgressionItems", "", "Item names to protect, separated by commas. Names are matched ignoring case and punctuation. NOTE: Wesley's Moons progression as of v81 is already covered.");
			if (_data == null)
			{
				Plugin.logger.LogError((object)"SpawnWeights: couldn't read PokeMoonsMoonWeights.json. Pokemon will not spawn automatically.");
				return;
			}
			MoonEntry[] moons = _data.moons;
			foreach (MoonEntry moonEntry in moons)
			{
				string text = "Moon - " + moonEntry.name;
				_moonShare[moonEntry.name] = config.Bind<string>(text, "Share", "", "Share of this moon's loot that is Pokemon, from 0 to 0.95 (e.g. 0.3). Leave blank for " + (HasOverriddenShare(moonEntry) ? $"this moon's built-in value ({moonEntry.share:0.##})." : "the [General] PokemonShare."));
				_moonOverrides[moonEntry.name] = config.Bind<string>(text, "Overrides", "", "Set Pokemon spawns on this moon, as Name:Weight separated by commas, e.g. Bulbasaur:0, Pikachu:30, Mew:3. Weight 0 removes the Pokemon from this moon; a number above 0 sets it. Weights use the same scale as PokeMoons.DefaultWeights.txt. Leave blank for the built-in table.");
				string[] match = moonEntry.match;
				foreach (string key in match)
				{
					_moonByMatch[key] = moonEntry;
				}
			}
			WriteReferenceFile();
			Plugin.logger.LogInfo((object)$"SpawnWeights: loaded weights for {_data.moons.Length} moons.");
		}

		public static void RegisterItem(string name, Item item)
		{
			_itemsByName[Simplify(name)] = item;
			_pokemonItems.Add(item);
		}

		private static MoonWeightsFile LoadData(string pluginDir)
		{
			try
			{
				string text = null;
				string text2 = Path.Combine(pluginDir, "PokeMoonsMoonWeights.json");
				if (File.Exists(text2))
				{
					text = File.ReadAllText(text2);
					Plugin.logger.LogInfo((object)("SpawnWeights: using " + text2));
				}
				else
				{
					Assembly executingAssembly = Assembly.GetExecutingAssembly();
					string text3 = executingAssembly.GetManifestResourceNames().FirstOrDefault((string n) => n.EndsWith("PokeMoonsMoonWeights.json", StringComparison.OrdinalIgnoreCase));
					if (text3 == null)
					{
						return null;
					}
					using Stream stream = executingAssembly.GetManifestResourceStream(text3);
					using StreamReader streamReader = new StreamReader(stream);
					text = streamReader.ReadToEnd();
				}
				return ParseData(text.TrimStart('\ufeff'));
			}
			catch (Exception arg)
			{
				Plugin.logger.LogError((object)$"SpawnWeights: failed to read the weights file: {arg}");
				return null;
			}
		}

		private static MoonWeightsFile ParseData(string text)
		{
			JObject val = JObject.Parse(text);
			MoonWeightsFile obj = new MoonWeightsFile
			{
				defaultShare = (float)val["defaultShare"]
			};
			JToken obj2 = val["progressionItems"];
			obj.progressionItems = ((obj2 != null) ? obj2.ToObject<string[]>() : null);
			MoonWeightsFile moonWeightsFile = obj;
			List<MoonEntry> list = new List<MoonEntry>();
			JToken obj3 = val["moons"];
			JObject val2 = (JObject)(object)((obj3 is JObject) ? obj3 : null);
			if (val2 != null)
			{
				foreach (JProperty item in val2.Properties())
				{
					JToken value = item.Value;
					JObject val3 = (JObject)(object)((value is JObject) ? value : null);
					if (val3 != null)
					{
						JToken obj4 = val3["weights"];
						List<JProperty> source = ((JObject)((obj4 is JObject) ? obj4 : null)).Properties().ToList();
						MoonEntry obj5 = new MoonEntry
						{
							name = item.Name,
							levelKey = (string)val3["levelKey"]
						};
						JToken obj6 = val3["match"];
						obj5.match = ((obj6 != null) ? obj6.ToObject<string[]>() : null);
						obj5.share = ((float?)val3["share"]).GetValueOrDefault();
						obj5.species = source.Select((JProperty w) => w.Name).ToArray();
						obj5.weights = source.Select((JProperty w) => (int)Math.Round((double)w.Value)).ToArray();
						list.Add(obj5);
					}
				}
			}
			moonWeightsFile.moons = list.ToArray();
			return moonWeightsFile;
		}

		private static void WriteReferenceFile()
		{
			try
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("SPOILERS! PokeMoons default Pokemon weights.");
				stringBuilder.AppendLine("See the Thunderstore readme for info about how to build your own weights.");
				MoonEntry[] moons = _data.moons;
				foreach (MoonEntry moonEntry in moons)
				{
					stringBuilder.AppendLine();
					stringBuilder.AppendLine(HasOverriddenShare(moonEntry) ? $"[{moonEntry.name}]  own share {moonEntry.share:0.##}" : ("[" + moonEntry.name + "]"));
					foreach (var item in from x in moonEntry.species.Zip(moonEntry.weights, (string s, int w) => new { s, w })
						orderby x.w descending, x.s
						select x)
					{
						stringBuilder.AppendLine($"  {item.s}: {item.w}");
					}
				}
				File.WriteAllText(Path.Combine(Paths.ConfigPath, "PokeMoons.DefaultWeights.txt"), stringBuilder.ToString());
			}
			catch (Exception ex)
			{
				Plugin.logger.LogDebug((object)("SpawnWeights: couldn't write the reference file: " + ex.Message));
			}
		}

		public static SpawnSnapshot Apply(SelectableLevel level)
		{
			if (!((Object)(object)level == (Object)null))
			{
				return ApplyTo(level, level.spawnableScrap);
			}
			return null;
		}

		public static List<SpawnableItemWithRarity> Preview(SelectableLevel level, IEnumerable<SpawnableItemWithRarity> table)
		{
			List<SpawnableItemWithRarity> list = table.Where((SpawnableItemWithRarity e) => e != null && (Object)(object)e.spawnableItem != (Object)null).Select((Func<SpawnableItemWithRarity, SpawnableItemWithRarity>)((SpawnableItemWithRarity e) => new SpawnableItemWithRarity(e.spawnableItem, e.rarity))).ToList();
			ApplyTo(level, list);
			return list;
		}

		private static SpawnSnapshot ApplyTo(SelectableLevel level, List<SpawnableItemWithRarity> list)
		{
			//IL_03e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03eb: Expected O, but got Unknown
			if (_data == null || _mode.Value == WeightsMode.Off)
			{
				return null;
			}
			string planetName = level.PlanetName;
			string text = SimplifyMoon(planetName);
			if (!_moonByMatch.TryGetValue(text, out var value))
			{
				Report("nomoon:" + planetName, "SpawnWeights: no weights for the moon '" + planetName + "' (simplified '" + text + "'), so no Pokemon are added there.");
				return null;
			}
			List<SpawnableItemWithRarity> list2 = list.Where((SpawnableItemWithRarity e) => e != null && (Object)(object)e.spawnableItem != (Object)null && !_pokemonItems.Contains(e.spawnableItem)).ToList();
			List<SpawnableItemWithRarity> source = list.Where((SpawnableItemWithRarity e) => e != null && (Object)(object)e.spawnableItem != (Object)null && _pokemonItems.Contains(e.spawnableItem)).ToList();
			if (_mode.Value == WeightsMode.Automatic && source.Any((SpawnableItemWithRarity e) => e.rarity > 0))
			{
				Report("existing:" + planetName, "SpawnWeights: '" + planetName + "' already has Pokemon weights set by another mod, so they are left alone.");
				return null;
			}
			double num = list2.Where((SpawnableItemWithRarity e) => e.rarity > 0).Sum((Func<SpawnableItemWithRarity, double>)((SpawnableItemWithRarity e) => e.rarity));
			if (num <= 0.0)
			{
				return null;
			}
			double num2 = AllPokeScrapShareOnMoon(value);
			if (num2 <= 0.0)
			{
				return null;
			}
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			for (int num3 = 0; num3 < value.species.Length; num3++)
			{
				dictionary[Simplify(value.species[num3])] = value.weights[num3];
			}
			foreach (KeyValuePair<string, int> item in ParsePairs(_moonOverrides[value.name].Value, value.name))
			{
				dictionary[item.Key] = item.Value;
			}
			List<KeyValuePair<string, int>> list3 = dictionary.Where((KeyValuePair<string, int> kv) => kv.Value > 0 && _itemsByName.ContainsKey(kv.Key)).ToList();
			double num4 = ((IEnumerable<KeyValuePair<string, int>>)list3).Sum((Func<KeyValuePair<string, int>, double>)((KeyValuePair<string, int> kv) => kv.Value));
			if (num4 <= 0.0)
			{
				return null;
			}
			SpawnSnapshot result = new SpawnSnapshot
			{
				list = list,
				entries = list.ToArray(),
				rarities = list.Select((SpawnableItemWithRarity e) => e?.rarity ?? 0).ToArray()
			};
			list.RemoveAll((SpawnableItemWithRarity e) => e != null && (Object)(object)e.spawnableItem != (Object)null && _pokemonItems.Contains(e.spawnableItem));
			double num5 = num2 * num / (1.0 - num2);
			int num6 = (int)Math.Max(1.0, Math.Min(100.0, Math.Ceiling(500.0 / num5)));
			foreach (SpawnableItemWithRarity item2 in list2)
			{
				if (item2.rarity > 0)
				{
					item2.rarity *= num6;
				}
			}
			double num7 = num * (double)num6;
			double num8 = 0.0;
			foreach (KeyValuePair<string, int> item3 in list3)
			{
				int num9 = Math.Max(1, (int)Math.Round((double)item3.Value * num5 * (double)num6 / num4));
				list.Add(new SpawnableItemWithRarity(_itemsByName[item3.Key], num9));
				num8 += (double)num9;
			}
			double num10 = 1.0;
			if (_protectProgression.Value)
			{
				HashSet<string> names = ProgressionNames();
				List<SpawnableItemWithRarity> list4 = list2.Where((SpawnableItemWithRarity e) => e.rarity > 0 && names.Contains(Simplify(e.spawnableItem.itemName))).ToList();
				double num11 = ((IEnumerable<SpawnableItemWithRarity>)list4).Sum((Func<SpawnableItemWithRarity, double>)((SpawnableItemWithRarity e) => e.rarity));
				double num12 = num7 - num11;
				if (list4.Count > 0 && num12 > 0.0)
				{
					num10 = (num12 + num8) / num12;
					foreach (SpawnableItemWithRarity item4 in list4)
					{
						item4.rarity = (int)Math.Round((double)item4.rarity * num10);
					}
				}
			}
			return result;
		}

		public static void Restore(SpawnSnapshot snapshot)
		{
			if (snapshot == null)
			{
				return;
			}
			snapshot.list.Clear();
			snapshot.list.AddRange(snapshot.entries);
			for (int i = 0; i < snapshot.entries.Length; i++)
			{
				if (snapshot.entries[i] != null)
				{
					snapshot.entries[i].rarity = snapshot.rarities[i];
				}
			}
		}

		private static bool HasOverriddenShare(MoonEntry moon)
		{
			if (moon.share > 0f)
			{
				return Math.Abs(moon.share - _data.defaultShare) > 0.001f;
			}
			return false;
		}

		private static double AllPokeScrapShareOnMoon(MoonEntry moon)
		{
			double val = (HasOverriddenShare(moon) ? moon.share : _defaultGlobalPokeScrapShare.Value);
			string value = _moonShare[moon.name].Value;
			if (!string.IsNullOrWhiteSpace(value))
			{
				if (double.TryParse(value.Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && result >= 0.0 && result <= 0.95)
				{
					val = result;
				}
				else
				{
					Report("badshare:" + moon.name, "SpawnWeights: the Share '" + value + "' for " + moon.name + " isn't a number from 0 to 0.95; using the default instead.");
				}
			}
			return Math.Min(Math.Max(val, 0.0), 0.95);
		}

		private static HashSet<string> ProgressionNames()
		{
			HashSet<string> hashSet = new HashSet<string>((_data.progressionItems ?? new string[0]).Select(Simplify));
			foreach (string item in SplitList(_extraProgression.Value))
			{
				hashSet.Add(Simplify(item));
			}
			return hashSet;
		}

		private static IEnumerable<KeyValuePair<string, int>> ParsePairs(string text, string moonName)
		{
			foreach (string item in SplitList(text))
			{
				string[] array = item.Split(new char[2] { ':', '=' }, 2);
				if (array.Length != 2 || !int.TryParse(array[1].Trim(), out var result) || result < 0)
				{
					Report("badpair:" + moonName + ":" + item, "SpawnWeights: couldn't read '" + item + "' in the Overrides for " + moonName + " (expected Name:Weight); ignoring it.");
					continue;
				}
				string text2 = Simplify(array[0]);
				if (!_itemsByName.ContainsKey(text2))
				{
					Report("badname:" + moonName + ":" + text2, "SpawnWeights: no Pokemon called '" + array[0].Trim() + "' (Overrides for " + moonName + "); ignoring it.");
				}
				else
				{
					yield return new KeyValuePair<string, int>(text2, result);
				}
			}
		}

		private static IEnumerable<string> SplitList(string text)
		{
			if (string.IsNullOrWhiteSpace(text))
			{
				yield break;
			}
			string[] array = text.Split(new char[4] { ',', ';', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
			foreach (string text2 in array)
			{
				if (!string.IsNullOrWhiteSpace(text2))
				{
					yield return text2.Trim();
				}
			}
		}

		public static string SimplifyMoon(string planetName)
		{
			return Simplify(Regex.Replace(planetName ?? "", "^\\s*\\d+\\s*", ""));
		}

		public static string Simplify(string text)
		{
			if (string.IsNullOrEmpty(text))
			{
				return "";
			}
			StringBuilder stringBuilder = new StringBuilder();
			foreach (char c in text)
			{
				if (char.IsLetterOrDigit(c))
				{
					stringBuilder.Append(char.ToLowerInvariant(c));
				}
			}
			return stringBuilder.ToString();
		}

		private static void Report(string key, string message)
		{
			if (_reportedMoons.Add(key))
			{
				Plugin.logger.LogInfo((object)message);
			}
		}
	}
	[HarmonyPatch(typeof(RoundManager), "SpawnScrapInLevel")]
	public static class SpawnScrapPatch
	{
		[HarmonyPriority(0)]
		public static void Prefix(RoundManager __instance, out SpawnSnapshot __state)
		{
			__state = null;
			try
			{
				__state = SpawnWeights.Apply(__instance.currentLevel);
			}
			catch (Exception arg)
			{
				Plugin.logger.LogError((object)$"SpawnWeights: {arg}");
			}
			try
			{
				DexData.RecordMoon(__instance.currentLevel?.PlanetName, __instance.currentLevel?.spawnableScrap, observed: true);
			}
			catch (Exception ex)
			{
				Plugin.logger.LogWarning((object)("Dex: couldn't record the loot table: " + ex.Message));
			}
		}

		public static void Postfix(SpawnSnapshot __state)
		{
			try
			{
				SpawnWeights.Restore(__state);
			}
			catch (Exception arg)
			{
				Plugin.logger.LogError((object)$"SpawnWeights restore: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(Terminal), "OnSubmit")]
	internal static class TerminalPatch
	{
		[HarmonyPrefix]
		private static bool OnSubmit(Terminal __instance)
		{
			if (!__instance.terminalInUse || __instance.textAdded <= 0 || (Object)(object)__instance.screenText == (Object)null)
			{
				return true;
			}
			if ((Object)(object)__instance.currentNode != (Object)null && __instance.currentNode.acceptAnything)
			{
				return true;
			}
			string text = __instance.screenText.text;
			if (__instance.textAdded > text.Length)
			{
				return true;
			}
			string[] array = text.Substring(text.Length - __instance.textAdded).Trim().ToLowerInvariant()
				.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
			if (array.Length == 0 || !PokedexCommand.IsCommand(array[0]))
			{
				return true;
			}
			string text2;
			try
			{
				text2 = PokedexCommand.Execute(array.Skip(1).ToArray());
			}
			catch (Exception arg)
			{
				Plugin.logger.LogError((object)$"Pokedex: {arg}");
				text2 = "The Pokedex had a problem. MissingNo is investigating.\n\n\n (See the BepInEx log.)";
			}
			__instance.LoadNewNode(CreateTextNode(text2));
			__instance.screenText.ActivateInputField();
			((Selectable)__instance.screenText).Select();
			return false;
		}

		private static TerminalNode CreateTextNode(string text)
		{
			TerminalNode obj = ScriptableObject.CreateInstance<TerminalNode>();
			obj.displayText = text + "\n\n";
			obj.clearPreviousText = true;
			obj.terminalEvent = "";
			return obj;
		}
	}
	[HarmonyPatch(typeof(Terminal), "Start")]
	internal static class TerminalHelpPatch
	{
		private const string HelpEntry = ">POKEDEX\nShows the Pokemon you've caught, and hints for the ones still missing.\n\n";

		[HarmonyPostfix]
		private static void Start(Terminal __instance)
		{
			TerminalNode val = __instance.terminalNodes?.allKeywords?.FirstOrDefault((Func<TerminalKeyword, bool>)((TerminalKeyword k) => (Object)(object)k != (Object)null && k.word == "help"))?.specialKeywordResult;
			if (!((Object)(object)val == (Object)null) && val.displayText != null && !val.displayText.Contains(">POKEDEX"))
			{
				int num = val.displayText.IndexOf("[numberOfItemsOnRoute]", StringComparison.Ordinal);
				val.displayText = ((num >= 0) ? val.displayText.Insert(num, ">POKEDEX\nShows the Pokemon you've caught, and hints for the ones still missing.\n\n") : (val.displayText.TrimEnd('\n') + "\n\n>POKEDEX\nShows the Pokemon you've caught, and hints for the ones still missing.\n\n"));
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "Pokemoons";

		public const string PLUGIN_NAME = "Pokemoons";

		public const string PLUGIN_VERSION = "0.0.1";
	}
}
namespace Pokemoons.NetcodePatcher
{
	[AttributeUsage(AttributeTargets.Module)]
	internal class NetcodePatchedAssemblyAttribute : Attribute
	{
	}
}