Decompiled source of Sail a dex v2.0.0

Sail-a-dex/Assets/SailadexREBridge.dll

Decompiled 6 days ago
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using RandomEncounters;
using RandomEncounters.API;
using sailadex;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("RandomEncountersBridge")]
[assembly: AssemblyDescription("https://github.com/bryon82/SailwindSail-a-dex")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("raddude")]
[assembly: AssemblyProduct("RandomEncountersBridge")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("8a27e40a-f47b-4e3f-8d0a-5677ecc26bb9")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace RandomEncountersBridge;

public static class EncounterTracker
{
	private static readonly Dictionary<string, string> _encounterNames = new Dictionary<string, string>
	{
		{ "Flotsam", "FlotsamEncounters" },
		{ "Dense Fog", "DenseFogEncounters" },
		{ "Whales", "SeaLifeEncounters" },
		{ "Fishing Bonanza", "FishingBonanzaEncounters" },
		{ "Intense Storm", "IntenseStormEncounters" }
	};

	public static void TrackEncounters()
	{
		SAD_Plugin.LogInfo("Tracking encounters from RandomEncounters mod.");
		EncounterEvents.EncounterTriggered += delegate(Encounter enc)
		{
			SAD_Plugin.LogDebug("Encounter triggered: " + enc.Name);
		};
		EncounterEvents.EncounterCompleted += delegate(Encounter enc)
		{
			EncounterCompleted(enc.Name);
		};
	}

	private static void EncounterCompleted(string encounterName)
	{
		SAD_Plugin.LogInfo("Encounter completed: " + encounterName);
		if (_encounterNames.TryGetValue(encounterName, out var value))
		{
			StatsUI.Instance.IncrementIntStat(value);
		}
	}
}

Sail-a-dex/Sail-a-dex.dll

Decompiled 6 days 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.InteropServices;
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 HarmonyLib;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using cakeslice;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Sail-a-dex")]
[assembly: AssemblyDescription("https://github.com/bryon82/SailwindSail-a-dex")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("raddude")]
[assembly: AssemblyProduct("Sail-a-dex")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("165a01b3-48da-400d-a25f-d6d01b2b3120")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.0.0.0")]
[module: UnverifiableCode]
namespace sailadex;

internal class PassageDude
{
	public class FerryTravelPatches
	{
		[HarmonyPostfix]
		public static void TeleportPlayerPatch()
		{
			if (Configs.statsUIEnabled.Value)
			{
				StatsUI.Instance.PlayerTeleported();
			}
		}
	}

	public static void PatchMod()
	{
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Expected O, but got Unknown
		Type type = AccessTools.TypeByName("FerryTravel");
		MethodInfo methodInfo = AccessTools.Method(type, "TeleportPlayer", (Type[])null, (Type[])null);
		MethodInfo methodInfo2 = AccessTools.Method(typeof(FerryTravelPatches), "TeleportPlayerPatch", (Type[])null, (Type[])null);
		SAD_Plugin.HarmonyInstance.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
	}
}
internal class REConfigs
{
	internal static bool IsSeaLifeModEnabled => Get("IsSeaLifeModEnabled");

	internal static bool IsFlotsamEnabled => Get("IsFlotsamEnabled");

	internal static bool IsDenseFogEnabled => Get("IsDenseFogEnabled");

	internal static bool IsFishingBonanzaEnabled => Get("IsFishingBonanzaEnabled");

	internal static bool IsIntenseStormEnabled => Get("IsIntenseStormEnabled");

	private static bool Get([CallerMemberName] string property = "")
	{
		return SAD_Plugin.RE_PluginInstance.GetStaticProperty<bool>(property);
	}
}
internal class EventPatches
{
	[HarmonyPatch(typeof(FishingRodFish))]
	private class FishingRodFishPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch("CollectFish")]
		public static void CollectFishPatch(GameObject ___currentFish)
		{
			if (Configs.fishCaughtUIEnabled.Value)
			{
				FishCaughtUI.Instance.RegisterCatch(___currentFish);
			}
		}
	}

	[HarmonyPatch(typeof(IslandMarketWarehouseArea))]
	private class IslandMarketWarehouseAreaPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("OnTriggerEnter")]
		public static void OnTriggerEnterPatch(IslandMarket ___market, Collider other)
		{
			if (Configs.portsVisitedUIEnabled.Value && ((Component)other).CompareTag("Player"))
			{
				PortsVisitedUI.Instance.RegisterVisit(___market.GetPortName());
			}
			if (Configs.statsUIEnabled.Value && ((Component)other).CompareTag("Player"))
			{
				StatsUI.Instance.IncrementPortVisited(___market.GetPortName());
			}
		}
	}

	[HarmonyPatch(typeof(ShipItem))]
	private class ShipItemPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("EnterBoat")]
		public static void EnterBoatPatch()
		{
			if (Configs.statsUIEnabled.Value && GameState.playing)
			{
				StatsUI.Instance.RegisterCurrentMass();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("ExitBoat")]
		public static void ExitBoatPatch()
		{
			if (Configs.statsUIEnabled.Value && GameState.playing)
			{
				StatsUI.Instance.RegisterCurrentMass();
			}
		}
	}

	[HarmonyPatch(typeof(PickupableBoatMooringRope))]
	private class PickupableBoatMooringRopePatches
	{
		[HarmonyPrefix]
		[HarmonyPatch("OnPickup")]
		public static void OnPickupPrePatch(Rigidbody ___boatRigidbody, out string __state)
		{
			__state = (from r in ((Component)___boatRigidbody).gameObject.GetComponent<BoatMooringRopes>().ropes
				where (Object)(object)r.GetPrivateField<SpringJoint>("mooredToSpring") != (Object)null
				select ((Object)((Component)r.GetPrivateField<SpringJoint>("mooredToSpring")).transform.parent).name).FirstOrDefault();
		}

		[HarmonyPostfix]
		[HarmonyPatch("OnPickup")]
		public static void OnPickupPatch(Rigidbody ___boatRigidbody, string __state)
		{
			if (Configs.statsUIEnabled.Value && !GameState.currentlyLoading && GameState.playing && !((Component)___boatRigidbody).gameObject.GetComponent<BoatMooringRopes>().AnyRopeMoored())
			{
				SAD_Plugin.LogDebug($"Unmoor from {__state} Day: {GameState.day} Time: {Sun.sun.globalTime}");
				StatsUI.Instance.RegisterUnderway(__state);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("MoorTo")]
		public static void MoorToPatch(Rigidbody ___boatRigidbody)
		{
			if (!Configs.statsUIEnabled.Value || GameState.currentlyLoading || !GameState.playing)
			{
				return;
			}
			if (!((Object)(object)((Component)___boatRigidbody).transform == (Object)(object)GameState.lastBoat))
			{
				Transform transform = ((Component)___boatRigidbody).transform;
				Transform currentBoat = GameState.currentBoat;
				if (!((Object)(object)transform == (Object)(object)((currentBoat != null) ? currentBoat.parent : null)))
				{
					return;
				}
			}
			if (((Component)___boatRigidbody).gameObject.GetComponent<BoatMooringRopes>().AnyRopeMoored())
			{
				string text = (from r in ((Component)___boatRigidbody).gameObject.GetComponent<BoatMooringRopes>().ropes
					where (Object)(object)r.GetPrivateField<SpringJoint>("mooredToSpring") != (Object)null
					select ((Object)((Component)r.GetPrivateField<SpringJoint>("mooredToSpring")).transform.parent).name).FirstOrDefault();
				SAD_Plugin.LogDebug($"Moored at: {text} Day: {GameState.day} Time: {Sun.sun.globalTime} ");
				StatsUI.Instance.RegisterMoored(text);
				StatsUI.Instance.UpdateMilesText();
			}
		}
	}

	[HarmonyPatch(typeof(ShipItemBottle))]
	private class ShipItemBottlePatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("Drink")]
		public static void DrinkPatch(float ___health)
		{
			if (Configs.statsUIEnabled.Value && ___health > 0f)
			{
				StatsUI.Instance.IncrementIntStat("DrinksTaken");
			}
		}
	}

	[HarmonyPatch(typeof(ShipItemFood))]
	private class ShipItemFoodPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch("EatFood")]
		public static void EatFoodPatch()
		{
			if (Configs.statsUIEnabled.Value && !(PlayerNeeds.instance.eatCooldown > 0f))
			{
				StatsUI.Instance.IncrementIntStat("FoodsEaten");
			}
		}
	}

	[HarmonyPatch(typeof(ShipItemPipe))]
	private class ShipItemPipePatches
	{
		[HarmonyPrefix]
		[HarmonyPatch("StopSmoking")]
		public static void StopSmokingPatch(float ___currentInhaleDuration)
		{
			if (Configs.statsUIEnabled.Value && ___currentInhaleDuration > 0f)
			{
				StatsUI.Instance.IncrementIntStat("TimesSmoked");
			}
		}
	}

	[HarmonyPatch(typeof(Sleep))]
	private class SleepPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("EnterBed")]
		public static void EnterBedPatch()
		{
			if (Configs.statsUIEnabled.Value)
			{
				StatsUI.Instance.IncrementIntStat("TimesSlept");
				if (Configs.updateMilesSailed.Value == "sleep")
				{
					StatsUI.Instance.UpdateMilesText();
				}
			}
		}
	}

	[HarmonyPatch(typeof(PlayerMissions))]
	private class PlayerMissionsPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("CompleteMission")]
		public static void CompleteMissionPatch()
		{
			if (Configs.statsUIEnabled.Value)
			{
				StatsUI.Instance.IncrementIntStat("MissionsCompleted");
			}
		}
	}

	[HarmonyPatch(typeof(Port))]
	private class PortPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("Update")]
		public static void UpdatePatch(bool ___teleportPlayer)
		{
			if (Configs.statsUIEnabled.Value && ___teleportPlayer)
			{
				StatsUI.Instance.PlayerTeleported();
			}
		}
	}

	[HarmonyPatch(typeof(BoatMass))]
	private class BoatMassPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("Update")]
		public static void UpdatePatch()
		{
			if (Configs.statsUIEnabled.Value && (Object)(object)GameState.currentBoat != (Object)null)
			{
				StatsUI.Instance.TrackDistance();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("UpdateMass")]
		public static void UpdateMassPatch(Rigidbody ___body)
		{
			if (Configs.statsUIEnabled.Value && (Object)(object)GameState.currentBoat != (Object)null)
			{
				StatsUI.Instance.RegisterTotalMass(___body.mass);
			}
		}
	}

	[HarmonyPatch(typeof(WeatherStorms))]
	private class WeatherStormPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("GetNormalizedDistance")]
		public static void GetNormalizedDistancePatch(float __result)
		{
			if (GameState.playing)
			{
				if (Configs.statsUIEnabled.Value && (Object)(object)GameState.currentBoat != (Object)null && StatsUI.Instance.IsUnderway && __result <= 0.33f)
				{
					StatsUI.Instance.IncrementStormsWeathered();
				}
				if (__result > 0.66f)
				{
					StatsUI.Instance.ClearLastStorm();
				}
			}
		}
	}
}
internal class ModDataPatches
{
	[HarmonyPatch(typeof(SaveLoadManager))]
	private class SaveLoadManagerPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch("SaveModData")]
		public static void SaveModData()
		{
			FishCaughtUI.Instance.SaveFishCaughtUI();
			PortsVisitedUI.Instance.SavePortsVisitedUI();
			StatsUI.Instance.SaveStatsUI();
		}

		[HarmonyPrefix]
		[HarmonyPatch("LoadModData")]
		public static void LoadModData()
		{
			FishCaughtUI.Instance.LoadFishCaughtUI();
			PortsVisitedUI.Instance.LoadPortsVisitedUI();
			StatsUI.Instance.LoadStatsUI();
		}
	}
}
public class FishCaughtUI : MonoBehaviour
{
	public TextMesh[] _fishNameTMs;

	public TextMesh[] _caughtCountTMs;

	public Dictionary<string, GameObject> _fishBadgeGOs;

	public Dictionary<string, int> _caughtFish;

	public Dictionary<string, bool> _fishBadges;

	private static readonly int[] FISH_BADGE_AMOUNTS = new int[3] { 25, 50, 100 };

	private static readonly int[] TOTAL_FISH_BADGE_AMOUNTS = new int[3] { 50, 250, 500 };

	public static readonly string[] FishNames = new string[12]
	{
		"templefish", "sunspot fish", "tuna", "blue shimmertail", "salmon", "eel", "blackfin hunter", "trout", "north fish", "swamp snapper",
		"blue bubbler", "fire fish"
	};

	public static readonly string[] TotalFishBadgeNames = new string[4] { "caught50", "caught250", "caught500", "caughtAll" };

	public static FishCaughtUI Instance { get; private set; }

	private void Awake()
	{
		if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
			return;
		}
		Instance = this;
		_caughtFish = new Dictionary<string, int>();
		_fishBadges = new Dictionary<string, bool>();
		_fishBadgeGOs = new Dictionary<string, GameObject>();
		string[] fishNames = FishNames;
		foreach (string text in fishNames)
		{
			_caughtFish.Add(text, 0);
			int[] fISH_BADGE_AMOUNTS = FISH_BADGE_AMOUNTS;
			foreach (int num in fISH_BADGE_AMOUNTS)
			{
				_fishBadges.Add($"{text}{num}", value: false);
			}
		}
		string[] totalFishBadgeNames = TotalFishBadgeNames;
		foreach (string key in totalFishBadgeNames)
		{
			_fishBadges.Add(key, value: false);
		}
	}

	public void RegisterCatch(GameObject fish)
	{
		string name = ((ShipItem)fish.GetComponent<ShipItemFood>()).name;
		if (!_caughtFish.ContainsKey(name))
		{
			SAD_Plugin.LogWarning("Fish caught " + name + " is not in fish caught log");
			return;
		}
		_caughtFish[name]++;
		CheckBadges(name);
		SAD_Plugin.LogDebug("Caught: " + name);
	}

	public void UpdatePage()
	{
		UpdateTexts();
		UpdateBadges();
	}

	private void UpdateTexts()
	{
		int num = 0;
		int num2 = 0;
		foreach (KeyValuePair<string, int> item in _caughtFish)
		{
			if (Configs.fishNamesHidden.Value)
			{
				_fishNameTMs[num].text = ((item.Value > 0) ? item.Key : "???");
			}
			else
			{
				_fishNameTMs[num].text = item.Key;
			}
			_caughtCountTMs[num].text = item.Value.ToString();
			num2 += item.Value;
			num++;
		}
		_fishNameTMs[_fishNameTMs.Length - 1].text = "Total";
		_caughtCountTMs[_caughtCountTMs.Length - 1].text = $"{num2}";
	}

	public void CheckBadges(string fishName)
	{
		CheckIndividualFishBadges(fishName);
		CheckAllFishBadges();
	}

	public void CheckIndividualFishBadges(string fishName)
	{
		int[] fISH_BADGE_AMOUNTS = FISH_BADGE_AMOUNTS;
		foreach (int num in fISH_BADGE_AMOUNTS)
		{
			if (!_fishBadges[$"{fishName}{num}"] && _caughtFish[fishName] >= num)
			{
				if (Configs.notificationsEnabled.Value)
				{
					NotificationUiQueue.Instance.QueueNotification($"Caught {num} {fishName}");
				}
				_fishBadges[$"{fishName}{num}"] = true;
			}
		}
	}

	public void CheckAllFishBadges()
	{
		int num = _caughtFish.Values.Sum();
		for (int i = 0; i < TOTAL_FISH_BADGE_AMOUNTS.Length; i++)
		{
			if (!_fishBadges[TotalFishBadgeNames[i]] && num >= TOTAL_FISH_BADGE_AMOUNTS[i])
			{
				if (Configs.notificationsEnabled.Value)
				{
					NotificationUiQueue.Instance.QueueNotification($"Caught {TOTAL_FISH_BADGE_AMOUNTS[i]} fish");
				}
				_fishBadges[TotalFishBadgeNames[i]] = true;
			}
		}
		if (!_fishBadges[TotalFishBadgeNames[3]] && !_caughtFish.Values.Any((int v) => v.Equals(0)))
		{
			if (Configs.notificationsEnabled.Value)
			{
				NotificationUiQueue.Instance.QueueNotification("Caught all fish");
			}
			_fishBadges[TotalFishBadgeNames[3]] = true;
		}
	}

	private void UpdateBadges()
	{
		foreach (KeyValuePair<string, bool> fishBadge in _fishBadges)
		{
			_fishBadgeGOs[fishBadge.Key].SetActive(fishBadge.Value);
		}
	}

	public void SetUIElems(TextMesh[] fishNameTMs, TextMesh[] caughtCountTMs, Dictionary<string, GameObject> fishBadgeGOs)
	{
		_fishNameTMs = fishNameTMs;
		_caughtCountTMs = caughtCountTMs;
		_fishBadgeGOs = fishBadgeGOs;
	}

	public void LoadFishCaughtUI()
	{
		ModData.GetDictEntry("Sail-a-dex.CaughtFish", _caughtFish);
		ModData.GetDictEntry("Sail-a-dex.FishBadges", _fishBadges);
	}

	public void SaveFishCaughtUI()
	{
		ModData.AddDictEntry("Sail-a-dex.CaughtFish", _caughtFish);
		ModData.AddDictEntry("Sail-a-dex.FishBadges", _fishBadges);
	}
}
internal class LogUIPatches
{
	[HarmonyPatch(typeof(MissionListUI))]
	private class MissionListUIPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch("ToggleMenu")]
		public static void TogglePatch()
		{
			//IL_004d: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			bookmarks[0].SetActive(false);
			bookmarks[1].SetActive(false);
			bookmarks[2].SetActive(false);
			Stack<Vector3> stack = new Stack<Vector3>();
			stack.Push(new Vector3(-0.515f, -0.0035f, -0.4566f));
			stack.Push(new Vector3(-0.387f, 0.0028f, -0.4566f));
			stack.Push(new Vector3(-0.26f, 0.0032f, -0.4566f));
			Stack<Vector3> stack2 = new Stack<Vector3>();
			stack2.Push(new Vector3(-0.515f, 0.0082f, -0.4516f));
			stack2.Push(new Vector3(-0.387f, 0.0138f, -0.4516f));
			stack2.Push(new Vector3(-0.26f, 0.0137f, -0.4516f));
			if (Configs.fishCaughtUIEnabled.Value)
			{
				logModeButtons[5].SetPrivateField("inactiveLocalPos", stack.Pop());
				logModeButtons[5].SetPrivateField("activeLocalPos", stack2.Pop());
				bookmarks[0].SetActive(true);
			}
			if (Configs.portsVisitedUIEnabled.Value)
			{
				logModeButtons[6].SetPrivateField("inactiveLocalPos", stack.Pop());
				logModeButtons[6].SetPrivateField("activeLocalPos", stack2.Pop());
				bookmarks[1].SetActive(true);
			}
			if (Configs.statsUIEnabled.Value)
			{
				logModeButtons[7].SetPrivateField("inactiveLocalPos", stack.Pop());
				logModeButtons[7].SetPrivateField("activeLocalPos", stack2.Pop());
				bookmarks[2].SetActive(true);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("HideUI")]
		public static void HideUIPatches()
		{
			fishCaughtUI.SetActive(false);
			portsVisitedUI.SetActive(false);
			statsUI.SetActive(false);
		}

		[HarmonyPostfix]
		[HarmonyPatch("SwitchMode")]
		public static void SwitchModePatches(MissionListMode mode)
		{
			//IL_0025: 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_0027: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected I4, but got Unknown
			fishCaughtUI.SetActive(false);
			portsVisitedUI.SetActive(false);
			statsUI.SetActive(false);
			switch (mode - 5)
			{
			case 0:
				fishCaughtUI.SetActive(true);
				FishCaughtUI.Instance.UpdatePage();
				break;
			case 1:
				portsVisitedUI.SetActive(true);
				PortsVisitedUI.Instance.UpdatePage();
				break;
			case 2:
				statsUI.SetActive(true);
				StatsUI.Instance.UpdatePage();
				break;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("Start")]
		public static void StartPatch(GameObject ___modeButtons, ref GPButtonLogMode[] ___logModeButtons, GameObject ___reputationUI)
		{
			List<GPButtonLogMode> existingLogModeButtons = new List<GPButtonLogMode>(___logModeButtons);
			(List<GameObject>, GPButtonLogMode[]) tuple = UIBuilder.MakeBookmarks(___modeButtons, existingLogModeButtons);
			bookmarks = tuple.Item1;
			logModeButtons = tuple.Item2;
			statsUI = UIBuilder.MakeStatsUI(___reputationUI);
			portsVisitedUI = UIBuilder.MakePortsVisitedUI(___reputationUI);
			fishCaughtUI = UIBuilder.MakeFishCaughtUI(___reputationUI);
			___logModeButtons = logModeButtons;
		}
	}

	[HarmonyPatch(typeof(NotificationUi))]
	private class NotificationUiPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		public static void StartPatch(NotificationUi ___instance)
		{
			if (Configs.notificationsEnabled.Value)
			{
				((Component)___instance).gameObject.AddComponent<NotificationUiQueue>();
			}
		}
	}

	private static GameObject fishCaughtUI;

	private static GameObject portsVisitedUI;

	private static GameObject statsUI;

	private static List<GameObject> bookmarks;

	private static GPButtonLogMode[] logModeButtons;
}
internal sealed class Region
{
	private readonly int _index;

	private readonly string _name;

	private readonly string _badgeName;

	private readonly string _code;

	private readonly List<string> _ports;

	private readonly List<string> _islands;

	public static readonly Region AlAnkh;

	public static readonly Region EmeraldArchipelago;

	public static readonly Region Aestrin;

	public static readonly Region FireFishLagoon;

	public static readonly IReadOnlyList<Region> AllRegions;

	public static readonly IReadOnlyList<string> AllBadgeNames;

	public int Index => _index;

	public string Name => _name;

	public string BadgeName => _badgeName;

	public string Code => _code;

	public IReadOnlyList<string> Ports => _ports.AsReadOnly();

	public IReadOnlyList<string> Islands => _islands.AsReadOnly();

	public static IReadOnlyList<string> AllPorts { get; private set; }

	public static IReadOnlyList<string> TransitCodes { get; private set; }

	private Region(int index, string name, string badgeName, string code, List<string> ports, List<string> islands)
	{
		_index = index;
		_name = name;
		_badgeName = badgeName;
		_code = code;
		_ports = ports;
		_islands = islands;
	}

	public override string ToString()
	{
		return Name ?? "";
	}

	static Region()
	{
		AlAnkh = new Region(0, "Al'Ankh", "alankhBadge", "Aa", new List<string> { "Gold Rock City", "Al'Nilem", "Neverdin", "Albacore Town", "Alchemist's Island", "Al'Ankh Academy", "Oasis", "Old Ankh Town", "Mirage Mountain", "Saffron Island" }, new List<string>
		{
			"island 1 A (gold rock)", "island 2 A (AlNilem)", "island 3 A (Neverdin)", "island 4 A (fish island)", "island 5 A (clear mind)", "island 6 A (lion fang)", "island 7 A (alchemist's island)", "island 8 A (academy)", "island 20 A (Oasis)", "island 40 (coffee)",
			"island 41 (mirage mountain)", "island 42 ()"
		});
		EmeraldArchipelago = new Region(1, "Emerald Archipelago", "emeraldBadge", "Ea", new List<string> { "Dragon Cliffs", "Sanctuary", "Crab Beach", "New Port", "Sage Hills", "Serpent Isle", "Dead Cove", "Turtle Island" }, new List<string> { "island 9 E (dragon cliffs)", "island 10 E (sanctuary)", "island 11 E (crab beach)", "island 12 E (New Port)", "island 13 E (Sage Hills)", "island 22 E (serpent isle)", "island 37 E (swamp)", "island 38 E (jungle)", "island 39 E (onsen)" });
		Aestrin = new Region(2, "Aestrin", "mediBadge", "Ae", new List<string> { "Fort Aestrin", "Sunspire", "Mount Malefic", "Siren Song", "Eastwind", "Firefly Grotto", "Aestra Abbey", "Fey Valley", "Happy Bay", "Chronos" }, new List<string>
		{
			"island 15 M (Fort)", "island 16 M (Sunspire)", "island 17 M (Mount Malefic)", "island 19 M (Eastwind)", "island 21 M (Siren Song)", "island 33 M cave church", "island 34 M monastery", "island 35 M valley", "island 23 M oracle", "island 18 M (Oasis)",
			"island 25 (chronos)"
		});
		FireFishLagoon = new Region(3, "Fire Fish Lagoon", "lagoonBadge", "Ffl", new List<string> { "Kicia Bay", "Fire Fish Town", "On'na", "Sen'na" }, new List<string> { "island 26 Lagoon Temple", "island 27 Lagoon Shipyard", "island 28 Lagoon Senna", "island 29 Lagoon Onna", "island 31 Lagoon Fisherman" });
		AllRegions = new List<Region> { AlAnkh, EmeraldArchipelago, Aestrin, FireFishLagoon }.AsReadOnly();
		AllBadgeNames = new List<string> { AlAnkh.BadgeName, EmeraldArchipelago.BadgeName, Aestrin.BadgeName, FireFishLagoon.BadgeName, "allPortsBadge" }.AsReadOnly();
		List<string> list = new List<string>();
		foreach (Region allRegion in AllRegions)
		{
			list.AddRange(allRegion.Ports);
		}
		AllPorts = list.AsReadOnly();
		List<string> list2 = new List<string>();
		foreach (Region allRegion2 in AllRegions)
		{
			foreach (Region allRegion3 in AllRegions)
			{
				if (allRegion2.Index != allRegion3.Index)
				{
					list2.Add(allRegion2.Code + allRegion3.Code);
				}
			}
		}
		TransitCodes = list2.AsReadOnly();
	}
}
internal class ModData
{
	public static void AddEntry<T>(string dataName, T data)
	{
		string value = ((data == null) ? string.Empty : data.ToString());
		if (GameState.modData.ContainsKey(dataName))
		{
			GameState.modData[dataName] = value;
		}
		else
		{
			GameState.modData.Add(dataName, value);
		}
	}

	public static T GetEntry<T>(string dataName)
	{
		if (!GameState.modData.ContainsKey(dataName))
		{
			SAD_Plugin.LogWarning("GetEntry: " + dataName + " not found in modData");
			return default(T);
		}
		string value = GameState.modData[dataName];
		return (T)Convert.ChangeType(value, typeof(T));
	}

	public static void AddDictEntry<K, T>(string dataName, Dictionary<K, T> data)
	{
		StringBuilder stringBuilder = new StringBuilder();
		if (typeof(T) == typeof(bool[]))
		{
			foreach (KeyValuePair<K, T> datum in data)
			{
				stringBuilder.AppendLine(string.Format("{0}|{1}", datum.Key, string.Join(",", (bool[])(object)datum.Value)));
			}
		}
		else if (typeof(T) == typeof(float))
		{
			foreach (KeyValuePair<K, T> datum2 in data)
			{
				stringBuilder.AppendLine($"{datum2.Key}|{((float)(object)datum2.Value).ToString(CultureInfo.InvariantCulture)}");
			}
		}
		else
		{
			foreach (KeyValuePair<K, T> datum3 in data)
			{
				stringBuilder.AppendLine($"{datum3.Key}|{datum3.Value}");
			}
		}
		string value = stringBuilder.ToString();
		if (GameState.modData.ContainsKey(dataName))
		{
			GameState.modData[dataName] = value;
		}
		else
		{
			GameState.modData.Add(dataName, value);
		}
	}

	public static void GetDictEntry<K, T>(string dataName, Dictionary<K, T> gameDict)
	{
		if (!GameState.modData.ContainsKey(dataName))
		{
			SAD_Plugin.LogWarning("LoadDictFromModData: " + dataName + " not found in modData");
			return;
		}
		string text = GameState.modData[dataName];
		string[] array = text.Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
		string[] array2 = array;
		foreach (string text2 in array2)
		{
			string[] array3 = text2.Trim().Split(new char[1] { '|' });
			if (array3.Length >= 2)
			{
				K val = (K)Convert.ChangeType(array3[0], typeof(K));
				if (!gameDict.ContainsKey(val))
				{
					SAD_Plugin.LogWarning($"LoadDictFromModData: {val} not found in game");
				}
				else
				{
					gameDict[val] = ParseValue<T>(array3[1]);
				}
			}
		}
	}

	private static T ParseValue<T>(string raw)
	{
		if (typeof(T) == typeof(bool[]))
		{
			bool[] array = Array.ConvertAll(raw.Split(new char[1] { ',' }), bool.Parse);
			return (T)(object)array;
		}
		if (typeof(T) == typeof(float))
		{
			return (T)(object)float.Parse(raw, CultureInfo.InvariantCulture);
		}
		return (T)Convert.ChangeType(raw, typeof(T));
	}
}
internal class UIBuilder
{
	internal const MissionListMode FISH_CAUGHT = (MissionListMode)5;

	internal const MissionListMode PORTS_VISITED = (MissionListMode)6;

	internal const MissionListMode STATS = (MissionListMode)7;

	private const int FISH_CAUGHT_FONT_SIZE = 50;

	private const int STAT_HEADER_FONT_SIZE = 45;

	private const int STAT_FONT_SIZE = 40;

	internal static (List<GameObject>, GPButtonLogMode[]) MakeBookmarks(GameObject modeButtons, List<GPButtonLogMode> existingLogModeButtons)
	{
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: 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)
		List<GameObject> list = new List<GameObject>();
		GameObject gameObject = ((Component)modeButtons.transform.GetChild(9)).gameObject;
		GameObject val = Object.Instantiate<GameObject>(gameObject);
		val.transform.parent = modeButtons.transform;
		val.transform.localRotation = gameObject.transform.localRotation;
		val.transform.localScale = gameObject.transform.localScale;
		((Object)val).name = "bookmark fish caught";
		((Component)val.transform.GetChild(0)).gameObject.GetComponent<TextMesh>().text = "fish caught";
		GPButtonLogMode component = val.GetComponent<GPButtonLogMode>();
		Traverse.Create((object)component).Field("mode").SetValue((object)(MissionListMode)5);
		Object.Destroy((Object)(object)val.GetComponent<Outline>());
		list.Add(val);
		existingLogModeButtons.Add(component);
		GameObject val2 = Object.Instantiate<GameObject>(gameObject);
		val2.transform.parent = modeButtons.transform;
		val2.transform.localRotation = gameObject.transform.localRotation;
		val2.transform.localScale = gameObject.transform.localScale;
		((Object)val2).name = "bookmark ports visited";
		((Component)val2.transform.GetChild(0)).gameObject.GetComponent<TextMesh>().text = "ports visited";
		GPButtonLogMode component2 = val2.GetComponent<GPButtonLogMode>();
		Traverse.Create((object)component2).Field("mode").SetValue((object)(MissionListMode)6);
		Object.Destroy((Object)(object)val2.GetComponent<Outline>());
		list.Add(val2);
		existingLogModeButtons.Add(component2);
		GameObject val3 = Object.Instantiate<GameObject>(gameObject);
		val3.transform.parent = modeButtons.transform;
		val3.transform.localRotation = gameObject.transform.localRotation;
		val3.transform.localScale = gameObject.transform.localScale;
		((Object)val3).name = "bookmark stats";
		((Component)val3.transform.GetChild(0)).gameObject.GetComponent<TextMesh>().text = "stats & transit";
		GPButtonLogMode component3 = val3.GetComponent<GPButtonLogMode>();
		Traverse.Create((object)component3).Field("mode").SetValue((object)(MissionListMode)7);
		Object.Destroy((Object)(object)val3.GetComponent<Outline>());
		list.Add(val3);
		existingLogModeButtons.Add(component3);
		return (list, existingLogModeButtons.ToArray());
	}

	internal static GameObject MakeFishCaughtUI(GameObject repUI)
	{
		//IL_0037: 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_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0308: Unknown result type (might be due to invalid IL or missing references)
		//IL_0320: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_04cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_056f: Unknown result type (might be due to invalid IL or missing references)
		//IL_058d: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = Object.Instantiate<GameObject>(repUI);
		Object.Destroy((Object)(object)val.GetComponent<ReputationUI>());
		val.transform.parent = repUI.transform.parent;
		val.transform.localPosition = repUI.transform.localPosition;
		val.transform.localRotation = repUI.transform.localRotation;
		val.transform.localScale = repUI.transform.localScale;
		((Object)val).name = "fish caught ui";
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(7)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(6)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(5)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(4)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(3)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(2)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(0)).gameObject);
		val.AddComponent<FishCaughtUI>();
		GameObject gameObject = ((Component)val.transform.GetChild(1)).gameObject;
		gameObject.SetActive(true);
		gameObject.GetComponent<TextMesh>().font = ((Component)gameObject.transform.GetChild(1)).GetComponent<TextMesh>().font;
		((Renderer)gameObject.GetComponent<MeshRenderer>()).material = ((Renderer)((Component)gameObject.transform.GetChild(1)).GetComponent<MeshRenderer>()).material;
		((Object)((Component)gameObject.transform.GetChild(1)).gameObject).name = "caught count";
		Transform child = gameObject.transform.GetChild(1);
		Vector3 localPosition = gameObject.transform.GetChild(1).localPosition;
		child.localPosition = new Vector3(55f, 0f, ((Vector3)(ref localPosition))[2]);
		((Component)gameObject.transform.GetChild(1)).GetComponent<TextMesh>().fontSize = 50;
		TextMesh[] array = (TextMesh[])(object)new TextMesh[FishCaughtUI.FishNames.Length + 1];
		TextMesh[] array2 = (TextMesh[])(object)new TextMesh[FishCaughtUI.FishNames.Length + 1];
		Dictionary<string, GameObject> dictionary = new Dictionary<string, GameObject>();
		for (int i = 0; i < FishCaughtUI.FishNames.Length; i++)
		{
			GameObject val2 = Object.Instantiate<GameObject>(gameObject);
			Object.Destroy((Object)(object)((Component)val2.transform.GetChild(4)).gameObject);
			Object.Destroy((Object)(object)((Component)val2.transform.GetChild(3)).gameObject);
			Object.Destroy((Object)(object)((Component)val2.transform.GetChild(2)).gameObject);
			Object.Destroy((Object)(object)((Component)val2.transform.GetChild(0)).gameObject);
			val2.GetComponent<TextMesh>().fontSize = 50;
			((Object)val2).name = FishCaughtUI.FishNames[i];
			val2.transform.parent = gameObject.transform.parent;
			Transform transform = val2.transform;
			float num = 0.24f - 0.0375f * (float)i;
			localPosition = gameObject.transform.localPosition;
			transform.localPosition = new Vector3(0.8f, num, ((Vector3)(ref localPosition))[2]);
			val2.transform.localRotation = gameObject.transform.localRotation;
			val2.transform.localScale = gameObject.transform.localScale;
			array2[i] = val2.GetComponent<TextMesh>();
			array[i] = ((Component)val2.transform.GetChild(1)).GetComponent<TextMesh>();
			string[] array3 = new string[3] { "25", "50", "100" };
			for (int j = 0; j < array3.Length; j++)
			{
				string name = ((Object)val2).name + array3[j];
				((MonoBehaviour)SAD_Plugin.Instance).StartCoroutine(CreateBadgeObject(dictionary, name, val2.transform, new Vector3(12f, 12f, 1f), new Vector3(75f + (float)j * 13f, 0f, 0f)));
			}
		}
		GameObject val3 = Object.Instantiate<GameObject>(gameObject);
		Object.Destroy((Object)(object)((Component)val3.transform.GetChild(4)).gameObject);
		Object.Destroy((Object)(object)((Component)val3.transform.GetChild(3)).gameObject);
		Object.Destroy((Object)(object)((Component)val3.transform.GetChild(2)).gameObject);
		Object.Destroy((Object)(object)((Component)val3.transform.GetChild(0)).gameObject);
		((Object)val3).name = "totalCaught";
		val3.transform.parent = gameObject.transform.parent;
		Transform transform2 = val3.transform;
		localPosition = gameObject.transform.localPosition;
		transform2.localPosition = new Vector3(0.8f, -0.21f, ((Vector3)(ref localPosition))[2]);
		val3.transform.localRotation = gameObject.transform.localRotation;
		val3.transform.localScale = gameObject.transform.localScale;
		array2[FishCaughtUI.FishNames.Length] = val3.GetComponent<TextMesh>();
		array[FishCaughtUI.FishNames.Length] = ((Component)val3.transform.GetChild(1)).GetComponent<TextMesh>();
		string[] array4 = new string[4] { "caught50", "caught250", "caught500", "caughtAll" };
		for (int k = 0; k < array4.Length; k++)
		{
			string name2 = array4[k];
			((MonoBehaviour)SAD_Plugin.Instance).StartCoroutine(CreateBadgeObject(dictionary, name2, val3.transform, new Vector3(15f, 15f, 1f), new Vector3(15f + (float)k * 20f, -13f, 0f)));
		}
		Object.Destroy((Object)(object)gameObject);
		FishCaughtUI.Instance.SetUIElems(array2, array, dictionary);
		SAD_Plugin.LogDebug("Loaded fish caught UI");
		return val;
	}

	internal static GameObject MakePortsVisitedUI(GameObject repUI)
	{
		//IL_0037: 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_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: 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_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_019f: Unknown result type (might be due to invalid IL or missing references)
		//IL_021f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0224: Unknown result type (might be due to invalid IL or missing references)
		//IL_022e: 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_0268: Unknown result type (might be due to invalid IL or missing references)
		//IL_0744: Unknown result type (might be due to invalid IL or missing references)
		//IL_0758: Unknown result type (might be due to invalid IL or missing references)
		//IL_0433: Unknown result type (might be due to invalid IL or missing references)
		//IL_048c: Unknown result type (might be due to invalid IL or missing references)
		//IL_03dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0517: Unknown result type (might be due to invalid IL or missing references)
		//IL_051c: Unknown result type (might be due to invalid IL or missing references)
		//IL_052d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0532: Unknown result type (might be due to invalid IL or missing references)
		//IL_054d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0552: Unknown result type (might be due to invalid IL or missing references)
		//IL_055c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0575: Unknown result type (might be due to invalid IL or missing references)
		//IL_058e: Unknown result type (might be due to invalid IL or missing references)
		//IL_05e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_05ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_05fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0603: Unknown result type (might be due to invalid IL or missing references)
		//IL_061e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0623: Unknown result type (might be due to invalid IL or missing references)
		//IL_062d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0646: Unknown result type (might be due to invalid IL or missing references)
		//IL_065f: Unknown result type (might be due to invalid IL or missing references)
		//IL_06e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_06fb: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = Object.Instantiate<GameObject>(repUI);
		Object.Destroy((Object)(object)val.GetComponent<ReputationUI>());
		val.transform.parent = repUI.transform.parent;
		val.transform.localPosition = repUI.transform.localPosition;
		val.transform.localRotation = repUI.transform.localRotation;
		val.transform.localScale = repUI.transform.localScale;
		((Object)val).name = "ports visited ui";
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(7)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(6)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(5)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(4)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(3)).gameObject);
		val.AddComponent<PortsVisitedUI>();
		Transform child = val.transform.GetChild(0);
		Vector3 localPosition = val.transform.GetChild(0).localPosition;
		child.localPosition = new Vector3(0.75f, 0.245f, ((Vector3)(ref localPosition))[2]);
		Transform child2 = val.transform.GetChild(1);
		localPosition = val.transform.GetChild(1).localPosition;
		child2.localPosition = new Vector3(0.75f, -0.05f, ((Vector3)(ref localPosition))[2]);
		Transform child3 = val.transform.GetChild(2);
		localPosition = val.transform.GetChild(2).localPosition;
		child3.localPosition = new Vector3(0.02f, 0.245f, ((Vector3)(ref localPosition))[2]);
		((Component)val.transform.GetChild(1)).gameObject.SetActive(true);
		((Component)val.transform.GetChild(2)).gameObject.SetActive(true);
		GameObject val2 = Object.Instantiate<GameObject>(((Component)val.transform.GetChild(1)).gameObject);
		val2.transform.parent = val.transform;
		Transform transform = val2.transform;
		localPosition = val.transform.GetChild(1).localPosition;
		transform.localPosition = new Vector3(0.02f, -0.05f, ((Vector3)(ref localPosition))[2]);
		val2.transform.localRotation = val.transform.GetChild(1).localRotation;
		val2.transform.localScale = val.transform.GetChild(1).localScale;
		((Object)val2).name = "lagoon";
		val2.GetComponent<TextMesh>().text = "Fire Fish Lagoon";
		TextMesh[] array = (TextMesh[])(object)new TextMesh[Region.AllPorts.Count];
		TextMesh[] array2 = (TextMesh[])(object)new TextMesh[Region.AllPorts.Count];
		Dictionary<string, GameObject> dictionary = new Dictionary<string, GameObject>();
		int num = 0;
		int[] array3 = new int[4]
		{
			Region.AlAnkh.Ports.Count,
			Region.EmeraldArchipelago.Ports.Count,
			Region.Aestrin.Ports.Count,
			Region.FireFishLagoon.Ports.Count
		};
		for (int i = 0; i < array3.Length; i++)
		{
			Transform child4 = val.transform.GetChild(i);
			if (i == 3)
			{
				child4 = val.transform.GetChild(8);
			}
			Object.Destroy((Object)(object)((Component)child4.GetChild(1)).gameObject);
			Object.Destroy((Object)(object)((Component)child4.GetChild(2)).gameObject);
			Object.Destroy((Object)(object)((Component)child4.GetChild(4)).gameObject);
			if (i == 0)
			{
				Object.Destroy((Object)(object)((Component)child4.GetChild(5)).gameObject);
				((Component)child4.GetChild(6)).GetComponent<TextMesh>().alignment = (TextAlignment)0;
				((Component)child4.GetChild(6)).GetComponent<TextMesh>().anchor = (TextAnchor)3;
				((Component)child4.GetChild(6)).GetComponent<TextMesh>().fontSize = 60;
				((Component)child4.GetChild(6)).transform.localPosition = Vector3.zero;
			}
			GameObject gameObject = ((Component)child4.GetChild(0)).gameObject;
			GameObject gameObject2 = ((Component)child4.GetChild(3)).gameObject;
			gameObject2.SetActive(true);
			((Object)gameObject).name = "port1";
			gameObject.transform.localPosition = new Vector3(5f, -8f, -0.1f);
			gameObject.GetComponent<TextMesh>().alignment = (TextAlignment)0;
			gameObject.GetComponent<TextMesh>().anchor = (TextAnchor)3;
			gameObject.GetComponent<TextMesh>().fontSize = 50;
			((Object)gameObject2).name = "visited port1";
			gameObject2.transform.localPosition = new Vector3(70f, -9f, 0f);
			gameObject2.GetComponent<TextMesh>().alignment = (TextAlignment)2;
			gameObject2.GetComponent<TextMesh>().anchor = (TextAnchor)5;
			gameObject2.GetComponent<TextMesh>().fontSize = 50;
			array[num] = gameObject.GetComponent<TextMesh>();
			array2[num] = gameObject2.GetComponent<TextMesh>();
			num++;
			for (int j = 1; j < array3[i]; j++)
			{
				GameObject val3 = Object.Instantiate<GameObject>(gameObject);
				val3.transform.parent = gameObject.transform.parent;
				Transform transform2 = val3.transform;
				localPosition = gameObject.transform.localPosition;
				float num2 = ((Vector3)(ref localPosition))[0];
				localPosition = gameObject.transform.localPosition;
				float num3 = ((Vector3)(ref localPosition))[1] - 7.5f * (float)j;
				localPosition = gameObject.transform.localPosition;
				transform2.localPosition = new Vector3(num2, num3, ((Vector3)(ref localPosition))[2]);
				val3.transform.localRotation = gameObject.transform.localRotation;
				val3.transform.localScale = gameObject.transform.localScale;
				((Object)val3).name = "port" + (j + 1);
				GameObject val4 = Object.Instantiate<GameObject>(gameObject2);
				val4.transform.parent = gameObject2.transform.parent;
				Transform transform3 = val4.transform;
				localPosition = gameObject2.transform.localPosition;
				float num4 = ((Vector3)(ref localPosition))[0];
				localPosition = gameObject2.transform.localPosition;
				float num5 = ((Vector3)(ref localPosition))[1] - 7.5f * (float)j;
				localPosition = gameObject2.transform.localPosition;
				transform3.localPosition = new Vector3(num4, num5, ((Vector3)(ref localPosition))[2]);
				val4.transform.localRotation = gameObject2.transform.localRotation;
				val4.transform.localScale = gameObject2.transform.localScale;
				((Object)val4).name = $"visited port{j + 1}";
				array[num] = val3.GetComponent<TextMesh>();
				array2[num] = val4.GetComponent<TextMesh>();
				num++;
			}
			string name = ((Object)child4).name + "Badge";
			((MonoBehaviour)SAD_Plugin.Instance).StartCoroutine(CreateBadgeObject(dictionary, name, child4, new Vector3(15f, 15f, 1f), new Vector3(-8f, -2f, 0f)));
		}
		((MonoBehaviour)SAD_Plugin.Instance).StartCoroutine(CreateBadgeObject(dictionary, "allPortsBadge", val.transform, new Vector3(0.1f, 0.0675f, 1f), new Vector3(-0.15f, -0.23f, -0.007f)));
		PortsVisitedUI.Instance.SetUIElems(array, array2, dictionary);
		SAD_Plugin.LogDebug("Loaded ports visited UI");
		return val;
	}

	internal static GameObject MakeStatsUI(GameObject repUI)
	{
		//IL_0037: 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_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_05a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0670: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = Object.Instantiate<GameObject>(repUI);
		Object.Destroy((Object)(object)val.GetComponent<ReputationUI>());
		val.transform.parent = repUI.transform.parent;
		val.transform.localPosition = repUI.transform.localPosition;
		val.transform.localRotation = repUI.transform.localRotation;
		val.transform.localScale = repUI.transform.localScale;
		((Object)val).name = "stats ui";
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(7)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(6)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(5)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(4)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(3)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(2)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(0)).gameObject);
		val.AddComponent<StatsUI>();
		GameObject gameObject = ((Component)val.transform.GetChild(1)).gameObject;
		gameObject.SetActive(true);
		gameObject.GetComponent<TextMesh>().font = ((Component)gameObject.transform.GetChild(1)).GetComponent<TextMesh>().font;
		gameObject.GetComponent<TextMesh>().fontSize = 40;
		gameObject.GetComponent<TextMesh>().characterSize = 1f;
		((Renderer)gameObject.GetComponent<MeshRenderer>()).material = ((Renderer)((Component)gameObject.transform.GetChild(1)).GetComponent<MeshRenderer>()).material;
		((Object)((Component)gameObject.transform.GetChild(0)).gameObject).name = "current value";
		gameObject.transform.GetChild(0).localPosition = new Vector3(38f, 0f, 0f);
		((Component)gameObject.transform.GetChild(0)).GetComponent<TextMesh>().font = ((Component)gameObject.transform.GetChild(1)).GetComponent<TextMesh>().font;
		((Component)gameObject.transform.GetChild(0)).GetComponent<TextMesh>().fontSize = 40;
		((Component)gameObject.transform.GetChild(0)).GetComponent<TextMesh>().anchor = (TextAnchor)3;
		((Component)gameObject.transform.GetChild(0)).GetComponent<TextMesh>().fontStyle = (FontStyle)0;
		((Component)gameObject.transform.GetChild(0)).GetComponent<TextMesh>().characterSize = 1f;
		((Component)gameObject.transform.GetChild(0)).GetComponent<TextMesh>().lineSpacing = 1f;
		((Renderer)((Component)gameObject.transform.GetChild(0)).GetComponent<MeshRenderer>()).material = ((Renderer)((Component)gameObject.transform.GetChild(1)).GetComponent<MeshRenderer>()).material;
		((Object)((Component)gameObject.transform.GetChild(1)).gameObject).name = "record value";
		gameObject.transform.GetChild(1).localPosition = new Vector3(80f, 0f, 0f);
		((Component)gameObject.transform.GetChild(1)).GetComponent<TextMesh>().fontSize = 40;
		((Component)gameObject.transform.GetChild(1)).GetComponent<TextMesh>().anchor = (TextAnchor)3;
		((Component)gameObject.transform.GetChild(1)).GetComponent<TextMesh>().fontStyle = (FontStyle)0;
		Dictionary<string, TextMesh> dictionary = new Dictionary<string, TextMesh>();
		AddTrackedStat(gameObject, "CargoMass", 0.215f, dictionary);
		AddTrackedStat(gameObject, "TotalMass", 0.19f, dictionary);
		AddTrackedStat(gameObject, "UnderwayTime", 0.165f, dictionary);
		AddTrackedStat(gameObject, "MilesSailed", 0.09f, dictionary, ltime: true);
		List<float> list = new List<float>();
		int num = 0;
		string[] intStatNames = StatsUI.IntStatNames;
		foreach (string text in intStatNames)
		{
			if (!(text == "UnderwayDay"))
			{
				if (StatsUI.RandomEncounterStats.ContainsKey(text))
				{
					list.Add(0.065f - 0.025f * (float)num);
				}
				AddTrackedStat(gameObject, text, 0.065f - 0.025f * (float)num, dictionary, ltime: true);
				num++;
			}
		}
		StatsUI.RandomEncounterStatYPos = list;
		int num2 = 0;
		foreach (string transitCode in Region.TransitCodes)
		{
			AddTrackedStat(gameObject, transitCode, 0.215f - 0.025f * (float)num2, dictionary, ltime: false, transit: true);
			num2++;
		}
		StatsUI.Instance.SetUIElems(dictionary);
		((Object)gameObject).name = "stats header";
		gameObject.GetComponent<TextMesh>().text = "Stat                           Current                         Record";
		gameObject.transform.localPosition = new Vector3(0.82f, 0.24f, -0.007f);
		gameObject.GetComponent<TextMesh>().fontSize = 45;
		gameObject.GetComponent<TextMesh>().fontStyle = (FontStyle)1;
		Object.Destroy((Object)(object)((Component)gameObject.transform.GetChild(4)).gameObject);
		Object.Destroy((Object)(object)((Component)gameObject.transform.GetChild(3)).gameObject);
		Object.Destroy((Object)(object)((Component)gameObject.transform.GetChild(2)).gameObject);
		Object.Destroy((Object)(object)((Component)gameObject.transform.GetChild(1)).gameObject);
		Object.Destroy((Object)(object)((Component)gameObject.transform.GetChild(0)).gameObject);
		GameObject val2 = Object.Instantiate<GameObject>(gameObject, gameObject.transform.parent);
		((Object)val2).name = "lifetime stats header";
		val2.GetComponent<TextMesh>().text = "Lifetime Stats";
		val2.transform.localPosition = new Vector3(0.82f, 0.115f, -0.007f);
		Object.Destroy((Object)(object)((Component)val2.transform.GetChild(4)).gameObject);
		Object.Destroy((Object)(object)((Component)val2.transform.GetChild(3)).gameObject);
		Object.Destroy((Object)(object)((Component)val2.transform.GetChild(2)).gameObject);
		Object.Destroy((Object)(object)((Component)val2.transform.GetChild(1)).gameObject);
		Object.Destroy((Object)(object)((Component)val2.transform.GetChild(0)).gameObject);
		GameObject val3 = Object.Instantiate<GameObject>(gameObject, gameObject.transform.parent);
		((Object)val3).name = "transit times header";
		val3.GetComponent<TextMesh>().text = "Transit Times             Last                               Record";
		val3.transform.localPosition = new Vector3(0.14f, 0.24f, -0.007f);
		Object.Destroy((Object)(object)((Component)val3.transform.GetChild(4)).gameObject);
		Object.Destroy((Object)(object)((Component)val3.transform.GetChild(3)).gameObject);
		Object.Destroy((Object)(object)((Component)val3.transform.GetChild(2)).gameObject);
		Object.Destroy((Object)(object)((Component)val3.transform.GetChild(1)).gameObject);
		Object.Destroy((Object)(object)((Component)val3.transform.GetChild(0)).gameObject);
		SAD_Plugin.LogDebug("Loaded stats & transit UI");
		return val;
	}

	private static void AddTrackedStat(GameObject templateGO, string name, float yPos, Dictionary<string, TextMesh> statTMs, bool ltime = false, bool transit = false)
	{
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		float num = (transit ? 0.14f : 0.82f);
		string text = (transit ? "last" : "current");
		GameObject val = Object.Instantiate<GameObject>(templateGO);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(4)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(3)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(2)).gameObject);
		if (ltime)
		{
			Object.Destroy((Object)(object)((Component)val.transform.GetChild(1)).gameObject);
			val.transform.GetChild(0).localPosition = new Vector3(41f, 0f, 0f);
		}
		((Object)val).name = name;
		val.transform.parent = templateGO.transform.parent;
		Transform transform = val.transform;
		Vector3 localPosition = templateGO.transform.localPosition;
		transform.localPosition = new Vector3(num, yPos, ((Vector3)(ref localPosition))[2]);
		val.transform.localRotation = templateGO.transform.localRotation;
		val.transform.localScale = templateGO.transform.localScale;
		statTMs[name] = val.GetComponent<TextMesh>();
		statTMs[text + name] = ((Component)val.transform.GetChild(0)).GetComponent<TextMesh>();
		if (!ltime)
		{
			statTMs["record" + name] = ((Component)val.transform.GetChild(1)).GetComponent<TextMesh>();
		}
		AddLine(((Component)val.transform.GetChild(1)).gameObject);
	}

	private static void AddLine(GameObject templateGO)
	{
		//IL_0040: 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_006e: 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_008f: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = Object.Instantiate<GameObject>(templateGO);
		((Object)val).name = "line";
		val.transform.parent = templateGO.transform.parent;
		val.transform.localPosition = new Vector3(-1.2f, -1.75f, 0f);
		val.transform.localRotation = templateGO.transform.localRotation;
		val.transform.localScale = templateGO.transform.localScale;
		TextMesh component = val.GetComponent<TextMesh>();
		component.color = Color32.op_Implicit(new Color32((byte)2, (byte)2, (byte)10, (byte)133));
		component.text = "--------------------------------------------------------";
	}

	private static IEnumerator CreateBadgeObject(Dictionary<string, GameObject> badgeGOs, string name, Transform parent, Vector3 scale, Vector3 position)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		yield return (object)new WaitUntil((Func<bool>)(() => AssetsLoader.BadgesLoaded));
		GameObject badge = GameObject.CreatePrimitive((PrimitiveType)5);
		badge.layer = 5;
		badge.transform.SetParent(parent, false);
		badge.transform.localScale = scale;
		badge.transform.localPosition = position;
		((Object)badge).name = name;
		if (name.Equals("allPortsBadge"))
		{
			badge.transform.localEulerAngles = new Vector3(0f, 180f, 0f);
		}
		MeshRenderer meshRenderer = badge.GetComponent<MeshRenderer>();
		((Renderer)meshRenderer).shadowCastingMode = (ShadowCastingMode)0;
		((Renderer)meshRenderer).material = AssetsLoader.Materials[name];
		Object.Destroy((Object)(object)badge.GetComponent<MeshCollider>());
		badgeGOs.Add(name, badge);
	}
}
internal class AssetsLoader
{
	private static Dictionary<string, Texture2D> _textures;

	private static Dictionary<string, Texture2D> _fishTextures;

	private static Dictionary<int, Texture2D> _badgeRings;

	private static bool _fishBadgesLoaded;

	private static bool _portBadgesLoaded;

	private const string LIB_FILE = "SailadexREBridge.dll";

	private const string ASSETS_DIR = "Assets";

	private const string BELLS_AUDIO_FILE = "twoBells.wav";

	private static readonly List<string> assetPaths = new List<string>
	{
		Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)SAD_Plugin.Instance).Info.Location), "Assets"),
		Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)SAD_Plugin.Instance).Info.Location))
	};

	public static bool BadgesLoaded => _fishBadgesLoaded && _portBadgesLoaded;

	public static AudioClip NotificationSound { get; private set; }

	public static Dictionary<string, Material> Materials { get; private set; }

	public static string FindAssetPath(string fileName)
	{
		foreach (string assetPath in assetPaths)
		{
			string text = Path.Combine(assetPath, fileName);
			if (File.Exists(text))
			{
				return text;
			}
		}
		return null;
	}

	public static void Start()
	{
		Materials = new Dictionary<string, Material>();
		_textures = new Dictionary<string, Texture2D>();
		_fishTextures = new Dictionary<string, Texture2D>();
		_badgeRings = new Dictionary<int, Texture2D>();
		((MonoBehaviour)SAD_Plugin.Instance).StartCoroutine(LoadAssetsAsync());
	}

	internal static void LoadBridge()
	{
		try
		{
			string text = FindAssetPath("SailadexREBridge.dll");
			if (text == null)
			{
				SAD_Plugin.LogError("Assembly file not found: SailadexREBridge.dll");
				return;
			}
			SAD_Plugin.REBridge_Assembly = Assembly.LoadFrom(text);
			SAD_Plugin.LogDebug("Loaded assembly: " + SAD_Plugin.REBridge_Assembly.FullName);
		}
		catch (Exception ex)
		{
			SAD_Plugin.LogError("Failed to load assembly: " + ex.Message);
		}
	}

	private static IEnumerator LoadAssetsAsync()
	{
		Coroutine audioCoroutine = ((MonoBehaviour)SAD_Plugin.Instance).StartCoroutine(LoadAudio());
		Coroutine fishBadgeCoroutine = ((MonoBehaviour)SAD_Plugin.Instance).StartCoroutine(LoadFishBadges());
		Coroutine portBadgeCoroutine = ((MonoBehaviour)SAD_Plugin.Instance).StartCoroutine(LoadPortBadges());
		yield return audioCoroutine;
		yield return fishBadgeCoroutine;
		yield return portBadgeCoroutine;
		SAD_Plugin.LogInfo("Assets loaded");
	}

	private static IEnumerator LoadAudio()
	{
		string clipPath = FindAssetPath("twoBells.wav");
		UnityWebRequest webRequest = UnityWebRequestMultimedia.GetAudioClip("file://" + clipPath, (AudioType)20);
		try
		{
			yield return webRequest.SendWebRequest();
			if (webRequest.isNetworkError || webRequest.isHttpError)
			{
				SAD_Plugin.LogError(webRequest.error);
				yield break;
			}
			AudioClip clip = DownloadHandlerAudioClip.GetContent(webRequest);
			((Object)clip).name = "twoBells";
			NotificationSound = clip;
			SAD_Plugin.LogDebug("Audio loaded.");
		}
		finally
		{
			((IDisposable)webRequest)?.Dispose();
		}
	}

	private static IEnumerator LoadFishBadges()
	{
		yield return ((MonoBehaviour)SAD_Plugin.Instance).StartCoroutine(LoadBadgeRings());
		yield return ((MonoBehaviour)SAD_Plugin.Instance).StartCoroutine(LoadFishTextures());
		yield return ((MonoBehaviour)SAD_Plugin.Instance).StartCoroutine(GenerateFishBadges());
		_fishBadgesLoaded = true;
		SAD_Plugin.LogDebug("Fish badges loaded.");
	}

	private static IEnumerator LoadBadgeRings()
	{
		int[] amountNums = new int[3] { 25, 50, 100 };
		List<Coroutine> ringCoroutines = new List<Coroutine>();
		int[] array = amountNums;
		for (int i = 0; i < array.Length; i++)
		{
			int amount = array[i];
			string ringName = amount + "Fish";
			string path = FindAssetPath(ringName + ".png");
			ringCoroutines.Add(((MonoBehaviour)SAD_Plugin.Instance).StartCoroutine(LoadBadgeRing(path, amount)));
		}
		foreach (Coroutine item in ringCoroutines)
		{
			yield return item;
		}
	}

	private static IEnumerator LoadBadgeRing(string path, int amount)
	{
		if (!File.Exists(path))
		{
			SAD_Plugin.LogError("Badge ring file not found: " + path);
			yield break;
		}
		Texture2D texture2D = new Texture2D(1, 1);
		byte[] fileData = null;
		yield return ((MonoBehaviour)SAD_Plugin.Instance).StartCoroutine(LoadFile(path, delegate(byte[] result)
		{
			fileData = result;
		}));
		if (fileData != null && fileData.Length != 0)
		{
			if (!ImageConversion.LoadImage(texture2D, fileData))
			{
				SAD_Plugin.LogError("Failed to load badge ring from bytes: " + path);
			}
			else
			{
				_badgeRings[amount] = texture2D;
			}
		}
	}

	private static IEnumerator LoadFishTextures()
	{
		List<Coroutine> fishCoroutines = new List<Coroutine>();
		string[] fishNames = FishCaughtUI.FishNames;
		foreach (string fishName in fishNames)
		{
			string path = FindAssetPath(fishName + ".png");
			fishCoroutines.Add(((MonoBehaviour)SAD_Plugin.Instance).StartCoroutine(LoadFishTexture(path, fishName)));
		}
		foreach (Coroutine item in fishCoroutines)
		{
			yield return item;
		}
	}

	private static IEnumerator LoadFishTexture(string path, string fishName)
	{
		if (!File.Exists(path))
		{
			SAD_Plugin.LogError("Fish texture file not found: " + path);
			yield break;
		}
		Texture2D texture2D = new Texture2D(1, 1);
		byte[] fileData = null;
		yield return ((MonoBehaviour)SAD_Plugin.Instance).StartCoroutine(LoadFile(path, delegate(byte[] result)
		{
			fileData = result;
		}));
		if (fileData != null && fileData.Length != 0)
		{
			if (!ImageConversion.LoadImage(texture2D, fileData))
			{
				SAD_Plugin.LogError("Failed to load fish texture from bytes: " + path);
			}
			else
			{
				_fishTextures[fishName] = texture2D;
			}
		}
	}

	private static IEnumerator GenerateFishBadges()
	{
		int[] amountNums = new int[3] { 25, 50, 100 };
		string[] fishNames = FishCaughtUI.FishNames;
		foreach (string fishName in fishNames)
		{
			if (!_fishTextures.ContainsKey(fishName))
			{
				SAD_Plugin.LogError("Fish texture not found for: " + fishName);
				continue;
			}
			Texture2D fishTexture = _fishTextures[fishName];
			Dictionary<string, Texture2D> scaledFishTextures = new Dictionary<string, Texture2D>();
			for (int j = 0; j < amountNums.Length; j++)
			{
				int amount = amountNums[j];
				if (!_badgeRings.ContainsKey(amount))
				{
					SAD_Plugin.LogError($"Badge ring not found for amount: {amount}");
					continue;
				}
				Texture2D ringTexture = _badgeRings[amount];
				string badgeName = fishName + amount;
				string sizeKey = $"{((Texture)ringTexture).width}x{((Texture)ringTexture).height}";
				if (!scaledFishTextures.TryGetValue(sizeKey, out var scaledFishTexture))
				{
					scaledFishTexture = ScaleTexture(fishTexture, ((Texture)ringTexture).width, ((Texture)ringTexture).height);
					scaledFishTextures.Add(sizeKey, scaledFishTexture);
				}
				Texture2D combinedTexture = CombineTextures(scaledFishTexture, ringTexture);
				((Object)combinedTexture).name = badgeName;
				_textures[badgeName] = combinedTexture;
				Materials[badgeName] = CreateMaterial(combinedTexture);
				scaledFishTexture = null;
			}
			foreach (Texture2D scaledTexture in scaledFishTextures.Values)
			{
				Object.DestroyImmediate((Object)(object)scaledTexture);
			}
			yield return null;
		}
		string[] totalFishBadgeNames = FishCaughtUI.TotalFishBadgeNames;
		foreach (string caughtBadge in totalFishBadgeNames)
		{
			string path = FindAssetPath(caughtBadge + ".png");
			yield return ((MonoBehaviour)SAD_Plugin.Instance).StartCoroutine(LoadTexture(path, caughtBadge));
		}
	}

	private static Texture2D CombineTextures(Texture2D scaledFishTexture, Texture2D ringTexture)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Expected O, but got Unknown
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: 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_0049: 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_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: 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_0073: Unknown result type (might be due to invalid IL or missing references)
		int width = ((Texture)ringTexture).width;
		int height = ((Texture)ringTexture).height;
		Texture2D val = new Texture2D(width, height, (TextureFormat)4, false);
		Color[] pixels = ringTexture.GetPixels();
		val.SetPixels(pixels);
		Color[] pixels2 = scaledFishTexture.GetPixels();
		for (int i = 0; i < pixels.Length; i++)
		{
			Color val2 = pixels2[i];
			Color val3 = pixels[i];
			if (val2.a > 0f)
			{
				pixels[i] = Color.Lerp(val3, val2, val2.a);
			}
		}
		val.SetPixels(pixels);
		val.Apply();
		return val;
	}

	private static Texture2D ScaleTexture(Texture2D source, int targetWidth, int targetHeight)
	{
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Expected O, but got Unknown
		//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_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		float num = (float)((Texture)source).width / (float)((Texture)source).height;
		float num2 = (float)targetWidth / (float)targetHeight;
		int num3;
		int num4;
		if (num > num2)
		{
			num3 = targetWidth;
			num4 = Mathf.RoundToInt((float)targetWidth / num);
		}
		else
		{
			num4 = targetHeight;
			num3 = Mathf.RoundToInt((float)targetHeight * num);
		}
		Texture2D val = new Texture2D(targetWidth, targetHeight, source.format, false);
		Color[] array = (Color[])(object)new Color[targetWidth * targetHeight];
		for (int i = 0; i < array.Length; i++)
		{
			array[i] = Color.clear;
		}
		int num5 = (targetWidth - num3) / 2;
		int num6 = (targetHeight - num4) / 2;
		Color[] pixels = source.GetPixels();
		for (int j = 0; j < num4; j++)
		{
			for (int k = 0; k < num3; k++)
			{
				float num7 = (float)k / (float)num3 * (float)((Texture)source).width;
				float num8 = (float)j / (float)num4 * (float)((Texture)source).height;
				int num9 = Mathf.FloorToInt(num7);
				int num10 = Mathf.FloorToInt(num8);
				num9 = Mathf.Clamp(num9, 0, ((Texture)source).width - 1);
				num10 = Mathf.Clamp(num10, 0, ((Texture)source).height - 1);
				int num11 = num10 * ((Texture)source).width + num9;
				int num12 = (j + num6) * targetWidth + (k + num5);
				if (num12 >= 0 && num12 < array.Length)
				{
					array[num12] = pixels[num11];
				}
			}
		}
		val.SetPixels(array);
		val.Apply();
		return val;
	}

	private static IEnumerator LoadPortBadges()
	{
		List<Coroutine> textureCoroutines = new List<Coroutine>();
		foreach (string pbName in Region.AllBadgeNames)
		{
			string path = FindAssetPath(pbName + ".png");
			textureCoroutines.Add(((MonoBehaviour)SAD_Plugin.Instance).StartCoroutine(LoadTexture(path, pbName)));
		}
		foreach (Coroutine item in textureCoroutines)
		{
			yield return item;
		}
		_portBadgesLoaded = true;
		SAD_Plugin.LogDebug("Port badges loaded.");
	}

	private static IEnumerator LoadTexture(string path, string textureName)
	{
		if (!File.Exists(path))
		{
			SAD_Plugin.LogError("File not found: " + path);
			yield break;
		}
		Texture2D texture2D = new Texture2D(1, 1);
		byte[] fileData = null;
		yield return ((MonoBehaviour)SAD_Plugin.Instance).StartCoroutine(LoadFile(path, delegate(byte[] result)
		{
			fileData = result;
		}));
		if (fileData != null && fileData.Length != 0)
		{
			if (!ImageConversion.LoadImage(texture2D, fileData))
			{
				SAD_Plugin.LogError("Failed to load texture from bytes: " + path);
				yield break;
			}
			_textures[textureName] = texture2D;
			Materials[textureName] = CreateMaterial(texture2D);
		}
	}

	private static IEnumerator LoadFile(string path, Action<byte[]> onComplete)
	{
		byte[] result = null;
		yield return null;
		UnityWebRequest www = UnityWebRequest.Get("file://" + path);
		try
		{
			yield return www.SendWebRequest();
			if (www.isNetworkError || www.isHttpError)
			{
				SAD_Plugin.LogError(www.error);
				yield break;
			}
			result = www.downloadHandler.data;
		}
		finally
		{
			((IDisposable)www)?.Dispose();
		}
		onComplete(result);
	}

	private static Material CreateMaterial(Texture2D tex)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Expected O, but got Unknown
		Material val = new Material(Shader.Find("Standard"))
		{
			renderQueue = 2001,
			mainTexture = (Texture)(object)tex
		};
		val.EnableKeyword("_ALPHATEST_ON");
		val.SetShaderPassEnabled("ShadowCaster", false);
		return val;
	}
}
internal class Configs
{
	internal static ConfigEntry<bool> fishNamesHidden;

	internal static ConfigEntry<bool> portNamesHidden;

	internal static ConfigEntry<bool> fishCaughtUIEnabled;

	internal static ConfigEntry<bool> portsVisitedUIEnabled;

	internal static ConfigEntry<bool> statsUIEnabled;

	internal static ConfigEntry<bool> notificationsEnabled;

	internal static ConfigEntry<float> notificationSoundVolume;

	internal static ConfigEntry<string> updateMilesSailed;

	internal static void InitializeConfigs()
	{
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Expected O, but got Unknown
		ConfigFile config = ((BaseUnityPlugin)SAD_Plugin.Instance).Config;
		fishCaughtUIEnabled = config.Bind<bool>("Enable/Disable UI", "Fish Caught UI", true, (ConfigDescription)null);
		portsVisitedUIEnabled = config.Bind<bool>("Enable/Disable UI", "Ports Visited UI", true, (ConfigDescription)null);
		statsUIEnabled = config.Bind<bool>("Enable/Disable UI", "Stats UI", true, (ConfigDescription)null);
		fishNamesHidden = config.Bind<bool>("Gameplay Settings", "Hide Fish Names Before Caught", true, (ConfigDescription)null);
		portNamesHidden = config.Bind<bool>("Gameplay Settings", "Hide Port Names Before Visited", false, (ConfigDescription)null);
		updateMilesSailed = config.Bind<string>("Gameplay Settings", "Miles Sailed Updates", "moored", new ConfigDescription("Miles sailed text will be updated once moored, going to sleeping or moored, or in real time.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[3] { "moored", "sleep", "realtime" }), Array.Empty<object>()));
		notificationsEnabled = config.Bind<bool>("Notification Settings", "Notification on badge earned", true, (ConfigDescription)null);
		notificationSoundVolume = config.Bind<float>("Notification Settings", "Notification Volume", 0.2f, "Above 1f is loud and not recommended. Set to 0f to disable.");
	}
}
internal static class Extensions
{
	public static T GetPrivateField<T>(this object obj, string field)
	{
		return (T)Traverse.Create(obj).Field(field).GetValue();
	}

	public static void SetPrivateField(this object obj, string field, object value)
	{
		Traverse.Create(obj).Field(field).SetValue(value);
	}

	public static T GetPrivateProperty<T>(this object obj, string property)
	{
		return (T)Traverse.Create(obj).Property(property, (object[])null).GetValue();
	}

	public static T GetStaticProperty<T>(this object obj, string property)
	{
		return (T)Traverse.Create(obj.GetType()).Property(property, (object[])null).GetValue();
	}

	public static object InvokePrivateMethod(this object obj, string method, params object[] parameters)
	{
		return AccessTools.Method(obj.GetType(), method, (Type[])null, (Type[])null).Invoke(obj, parameters);
	}
}
public class NotificationUiQueue : MonoBehaviour
{
	private Coroutine _queueCoroutine;

	private Queue<string> _queue;

	private AudioSource _audioSource;

	private const float TIMER_DURATION = 3f;

	public static NotificationUiQueue Instance { get; private set; }

	public void Start()
	{
		if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
			return;
		}
		Instance = this;
		_queue = new Queue<string>();
		_queueCoroutine = null;
		_audioSource = ((Component)this).gameObject.AddComponent<AudioSource>();
		_audioSource.volume = Configs.notificationSoundVolume.Value;
		_audioSource.spatialBlend = 1f;
		_audioSource.minDistance = 10f;
		_audioSource.maxDistance = 20f;
	}

	private IEnumerator ProcessQueue()
	{
		while (_queue.Count > 0)
		{
			NotificationUi.instance.ShowNotification(_queue.Dequeue());
			if (Configs.notificationSoundVolume.Value > 0f)
			{
				_audioSource.PlayOneShot(AssetsLoader.NotificationSound);
			}
			yield return (object)new WaitForSeconds(3f);
		}
		_queueCoroutine = null;
	}

	public void QueueNotification(string message)
	{
		_queue.Enqueue(message);
		if (_queueCoroutine == null)
		{
			_queueCoroutine = ((MonoBehaviour)this).StartCoroutine(ProcessQueue());
		}
	}
}
[BepInPlugin("com.raddude.sailadex", "Sail-a-dex", "2.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class SAD_Plugin : BaseUnityPlugin
{
	public const string PLUGIN_GUID = "com.raddude.sailadex";

	public const string PLUGIN_NAME = "Sail-a-dex";

	public const string PLUGIN_VERSION = "2.0.0";

	public const string PASSAGEDUDE_GUID = "pr0skynesis.passagedude";

	public const string RANDOMENCOUNTERS_GUID = "com.raddude.randomencounters";

	internal static ManualLogSource _logger;

	internal static BaseUnityPlugin RE_PluginInstance { get; private set; }

	internal static Assembly REBridge_Assembly { get; set; }

	internal static SAD_Plugin Instance { get; private set; }

	internal static Harmony HarmonyInstance { get; private set; }

	public static void LogDebug(string message)
	{
		_logger.LogDebug((object)message);
	}

	public static void LogInfo(string message)
	{
		_logger.LogInfo((object)message);
	}

	public static void LogWarning(string message)
	{
		_logger.LogWarning((object)message);
	}

	public static void LogError(string message)
	{
		_logger.LogError((object)message);
	}

	private void Awake()
	{
		if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
			return;
		}
		Instance = this;
		_logger = ((BaseUnityPlugin)this).Logger;
		Configs.InitializeConfigs();
		AssetsLoader.Start();
		HarmonyInstance = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "com.raddude.sailadex");
		bool flag = false;
		foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
		{
			BepInPlugin metadata = pluginInfo.Value.Metadata;
			if (metadata.GUID.Equals("pr0skynesis.passagedude"))
			{
				LogInfo("PassageDude mod found");
				flag = true;
				PassageDude.PatchMod();
			}
			if (metadata.GUID.Equals("com.raddude.randomencounters") && metadata.Version >= new Version(2, 0, 0))
			{
				LogInfo("RandomEncounters mod found");
				RE_PluginInstance = pluginInfo.Value.Instance;
				AssetsLoader.LoadBridge();
				Type type = AccessTools.TypeByName("EncounterTracker");
				AccessTools.Method(type, "TrackEncounters", (Type[])null, (Type[])null).Invoke(null, null);
			}
			if (flag && (Object)(object)RE_PluginInstance != (Object)null)
			{
				break;
			}
		}
	}
}
public class PortsVisitedUI : MonoBehaviour
{
	private TextMesh[] _portNameTMs;

	private TextMesh[] _portVisitedTMs;

	private Dictionary<string, GameObject> _portBadgeGOs;

	private Dictionary<string, bool> _visitedPorts;

	private Dictionary<string, bool> _portBadges;

	public static PortsVisitedUI Instance { get; private set; }

	private void Awake()
	{
		if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
			return;
		}
		Instance = this;
		_visitedPorts = new Dictionary<string, bool>();
		foreach (string allPort in Region.AllPorts)
		{
			_visitedPorts[allPort] = false;
		}
		_portBadges = new Dictionary<string, bool>();
		foreach (string allBadgeName in Region.AllBadgeNames)
		{
			_portBadges[allBadgeName] = false;
		}
	}

	public void RegisterVisit(string portName)
	{
		if (!_visitedPorts.ContainsKey(portName))
		{
			SAD_Plugin.LogWarning("Attempted to register visit to unknown port: " + portName);
			return;
		}
		if (!_visitedPorts[portName])
		{
			_visitedPorts[portName] = true;
			CheckBadges();
		}
		SAD_Plugin.LogDebug("Visited: " + portName);
	}

	public void UpdatePage()
	{
		UpdateTexts();
		UpdateBadges();
	}

	private void UpdateTexts()
	{
		int num = 0;
		foreach (KeyValuePair<string, bool> visitedPort in _visitedPorts)
		{
			if (num >= _portNameTMs.Length || num >= _portVisitedTMs.Length)
			{
				SAD_Plugin.LogWarning("Not enough TextMesh objects to display all ports");
				break;
			}
			_portNameTMs[num].text = GetPortDisplayName(visitedPort.Key, visitedPort.Value);
			_portVisitedTMs[num].text = (visitedPort.Value ? "✓" : "✗");
			num++;
		}
	}

	private string GetPortDisplayName(string portName, bool visited)
	{
		return (Configs.portNamesHidden.Value && !visited) ? "???" : portName;
	}

	public void CheckBadges()
	{
		foreach (Region allRegion in Region.AllRegions)
		{
			if (!_portBadges[allRegion.BadgeName] && allRegion.Ports.All((string p) => _visitedPorts[p]))
			{
				_portBadges[allRegion.BadgeName] = true;
				ShowBadgeNotification(allRegion.Name);
			}
		}
		if (!_portBadges["allPortsBadge"] && Region.AllPorts.All((string p) => _visitedPorts[p]))
		{
			_portBadges["allPortsBadge"] = true;
			ShowBadgeNotification("all");
		}
	}

	private void ShowBadgeNotification(string region)
	{
		if (Configs.notificationsEnabled.Value)
		{
			string message = ((region != "all") ? ("Visited all\n" + region + " ports") : "Visited all ports");
			NotificationUiQueue.Instance.QueueNotification(message);
		}
	}

	public void UpdateBadges()
	{
		foreach (KeyValuePair<string, bool> portBadge in _portBadges)
		{
			if (!_portBadgeGOs.ContainsKey(portBadge.Key))
			{
				SAD_Plugin.LogWarning("Missing GameObject for badge: " + portBadge.Key);
			}
			else
			{
				_portBadgeGOs[portBadge.Key].SetActive(portBadge.Value);
			}
		}
	}

	public void SetUIElems(TextMesh[] portNameTMs, TextMesh[] portVisitedTMs, Dictionary<string, GameObject> portBadgeGOs)
	{
		_portNameTMs = portNameTMs;
		_portVisitedTMs = portVisitedTMs;
		_portBadgeGOs = portBadgeGOs;
	}

	public void LoadPortsVisitedUI()
	{
		ModData.GetDictEntry("Sail-a-dex.VisitedPorts", _visitedPorts);
		ModData.GetDictEntry("Sail-a-dex.PortBadges", _portBadges);
	}

	public void SavePortsVisitedUI()
	{
		ModData.AddDictEntry("Sail-a-dex.VisitedPorts", _visitedPorts);
		ModData.AddDictEntry("Sail-a-dex.PortBadges", _portBadges);
	}
}
public class StatsUI : MonoBehaviour
{
	private Dictionary<string, TextMesh> _statTMs;

	private Dictionary<string, float> _floatStats;

	private Dictionary<string, int> _intStats;

	private Dictionary<string, bool[]> _boolArrayStats;

	private Vector3 lastPosition;

	internal string lastPortVisited;

	private int trackerTimer;

	internal string lastStorm;

	private const int TRACKER_TIMER_VALUE = 1000;

	private const float MILES_CONVERSION_FACTOR = 137.487f;

	public static readonly string[] FloatStatNames = new string[4] { "CargoMass", "TotalMass", "UnderwayTime", "MilesSailed" };

	public static readonly string[] IntStatNames = new string[13]
	{
		"UnderwayDay", "PortsVisited", "MissionsCompleted", "DrinksTaken", "FoodsEaten", "TimesSmoked", "TimesSlept", "StormsWeathered", "FlotsamEncounters", "DenseFogEncounters",
		"SeaLifeEncounters", "FishingBonanzaEncounters", "IntenseStormEncounters"
	};

	private static readonly Dictionary<string, Func<bool>> _randomEncounterStats = new Dictionary<string, Func<bool>>
	{
		{
			"FlotsamEncounters",
			() => REConfigs.IsFlotsamEnabled
		},
		{
			"DenseFogEncounters",
			() => REConfigs.IsDenseFogEnabled
		},
		{
			"SeaLifeEncounters",
			() => REConfigs.IsSeaLifeModEnabled
		},
		{
			"FishingBonanzaEncounters",
			() => REConfigs.IsFishingBonanzaEnabled
		},
		{
			"IntenseStormEncounters",
			() => REConfigs.IsIntenseStormEnabled
		}
	};

	public static StatsUI Instance { get; private set; }

	public bool IsUnderway { get; internal set; }

	public static IReadOnlyDictionary<string, Func<bool>> RandomEncounterStats => _randomEncounterStats;

	public static List<float> RandomEncounterStatYPos { get; set; }

	private void Awake()
	{
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
			return;
		}
		Instance = this;
		_floatStats = new Dictionary<string, float>();
		_intStats = new Dictionary<string, int>();
		_boolArrayStats = new Dictionary<string, bool[]>();
		_statTMs = new Dictionary<string, TextMesh>();
		lastPosition = Vector3.zero;
		lastPortVisited = string.Empty;
		trackerTimer = 1000;
		lastStorm = string.Empty;
		IsUnderway = false;
		string[] floatStatNames = FloatStatNames;
		foreach (string text in floatStatNames)
		{
			_floatStats.Add(text, 0f);
			_floatStats.Add("current" + text, 0f);
			_floatStats.Add("record" + text, 0f);
		}
		string[] intStatNames = IntStatNames;
		foreach (string text2 in intStatNames)
		{
			_intStats.Add(text2, 0);
			_intStats.Add("current" + text2, 0);
			_intStats.Add("record" + text2, 0);
		}
		foreach (string transitCode in Region.TransitCodes)
		{
			_floatStats.Add("last" + transitCode + "TransitTime", 0f);
			_intStats.Add("last" + transitCode + "TransitDay", 0);
			_floatStats.Add("record" + transitCode + "TransitTime", 0f);
			_intStats.Add("record" + transitCode + "TransitDay", 0);
		}
		foreach (Region allRegion in Region.AllRegions)
		{
			_floatStats.Add(allRegion.Code + "UnderwayTime", 0f);
			_intStats.Add(allRegion.Code + "UnderwayDay", 0);
			_boolArrayStats.Add(allRegion.Code + "Transit", new bool[4]);
		}
	}

	public void RegisterCurrentMass()
	{
		Transform currentBoat = GameState.currentBoat;
		if (!((Object)(object)((currentBoat != null) ? currentBoat.parent : null) == (Object)null) || !((Object)(object)GameState.lastBoat == (Object)null))
		{
			GameObject val = (((Object)(object)GameState.currentBoat != (Object)null) ? ((Component)GameState.currentBoat.parent).gameObject : ((Component)GameState.lastBoat).gameObject);
			_floatStats["currentCargoMass"] = (from item in val.GetComponent<BoatMass>().GetPrivateField<List<ItemRigidbody>>("itemsOnBoat")
				where IsCargoItem(item)
				select item).Sum((ItemRigidbody item) => item.GetBody().mass);
		}
	}

	private bool IsCargoItem(ItemRigidbody item)
	{
		Good component = ((Component)item.GetShipItem()).GetComponent<Good>();
		if ((Object)(object)component == (Object)null)
		{
			return false;
		}
		string sizeDescription = component.sizeDescription;
		return sizeDescription.Contains("crate") || sizeDescription.Contains("package") || sizeDescription.Contains("barrel") || sizeDescription.Contains("bundle");
	}

	public void RegisterTotalMass(float totalMass)
	{
		_floatStats["currentTotalMass"] = totalMass;
	}

	private void UpdateMassRecords()
	{
		if (_floatStats["recordCargoMass"] < _floatStats["currentCargoMass"])
		{
			_floatStats["recordCargoMass"] = _floatStats["currentCargoMass"];
		}
		if (_floatStats["recordTotalMass"] < _floatStats["currentTotalMass"])
		{
			_floatStats["recordTotalMass"] = _floatStats["currentTotalMass"];
		}
	}

	public void RegisterUnderway(string islandName)
	{
		if (string.IsNullOrEmpty(islandName))
		{
			return;
		}
		IsUnderway = true;
		UpdateMassRecords();
		ResetUnderwayTimers();
		if (islandName == "island 18 M (HappyBay)")
		{
			return;
		}
		foreach (Region allRegion in Region.AllRegions)
		{
			if (allRegion.Islands.Contains(islandName))
			{
				TrackRegionUnderway(allRegion.Code);
				break;
			}
		}
	}

	private void ResetUnderwayTimers()
	{
		_floatStats["UnderwayTime"] = Sun.sun.globalTime;
		_intStats["UnderwayDay"] = GameState.day;
	}

	private void TrackRegionUnderway(string regionCode)
	{
		_floatStats[regionCode + "UnderwayTime"] = Sun.sun.globalTime;
		_intStats[regionCode + "UnderwayDay"] = GameState.day;
		for (int i = 0; i < Region.AllRegions.Count; i++)
		{
			_boolArrayStats[regionCode + "Transit"][i] = false;
		}
	}

	private void UpdateUnderwayRecords()
	{
		if (_intStats["currentUnderwayDay"] > _intStats["recordUnderwayDay"] || (_intStats["currentUnderwayDay"] == _intStats["recordUnderwayDay"] && _floatStats["currentUnderwayTime"] > _floatStats["recordUnderwayTime"]))
		{
			_intStats["recordUnderwayDay"] = _intStats["currentUnderwayDay"];
			_floatStats["recordUnderwayTime"] = _floatStats["currentUnderwayTime"];
		}
		_floatStats["UnderwayTime"] = 0f;
		_intStats["UnderwayDay"] = 0;
	}

	public void RegisterMoored(string islandName)
	{
		if (!Utility.IsNullOrWhiteSpace(islandName))
		{
			IsUnderway = false;
			UpdateStats();
			UpdateUnderwayRecords();
			if (!islandName.Equals("island 18 M (HappyBay)"))
			{
				ProcessRegionalArrival(islandName);
			}
		}
	}

	private void ProcessRegionalArrival(string islandName)
	{
		foreach (Region allRegion in Region.AllRegions)
		{
			if (!allRegion.Islands.Contains(islandName))
			{
				continue;
			}
			{
				foreach (Region allRegion2 in Region.AllRegions)
				{
					if (!(allRegion2.Code == allRegion.Code))
					{
						CheckPossibleTransit(allRegion2.Code, allRegion.Code, allRegion.Index);
					}
				}
				break;
			}
		}
	}

	private void CheckPossibleTransit(string departureRegion, string arrivalRegion, int arrivalIndex)
	{
		string transitCode = departureRegion + arrivalRegion;
		bool flag = _floatStats[departureRegion + "UnderwayTime"] > 0f || _intStats[departureRegion + "UnderwayDay"] > 0;
		bool flag2 = _boolArrayStats[departureRegion + "Transit"][arrivalIndex];
		if (!flag2 && flag)
		{
			CheckTransitTime(departureRegion, transitCode, arrivalIndex);
		}
	}

	public void CheckTransitTime(string underwayKey, string transitCode, int destInt)
	{
		int num = GameState.day - _intStats[underwayKey + "UnderwayDay"];
		float num2 = Sun.sun.globalTime - _floatStats[underwayKey + "UnderwayTime"];
		if (num2 < 0f)
		{
			num2 += 24f;
			num--;
		}
		_intStats["last" + transitCode + "TransitDay"] = num;
		_floatStats["last" + transitCode + "TransitTime"] = num2;
		if ((_intStats["record" + transitCode + "TransitDay"] == 0 && _floatStats["record" + transitCode + "TransitTime"] == 0f) || _intStats["record" + transitCode + "TransitDay"] > num || (_intStats["record" + transitCode + "TransitDay"] == num && _floatStats["record" + transitCode + "TransitTime"] > num2))
		{
			_intStats["record" + transitCode + "TransitDay"] = num;
			_floatStats["record" + transitCode + "TransitTime"] = num2;
			if (Configs.notificationsEnabled.Value)
			{
				NotificationUiQueue.Instance.QueueNotification("Fastest " + FormatTransitName(transitCode) + " time");
			}
		}
		_boolArrayStats[underwayKey + "Transit"][destInt] = true;
	}

	public void PlayerTeleported()
	{
		SAD_Plugin.LogInfo("Player teleported, resetting current transits");
		foreach (Region allRegion in Region.AllRegions)
		{
			int num = 0;
			for (int i = 0; i < Region.AllRegions.Count; i++)
			{
				if (i != num)
				{
					_boolArrayStats[allRegion.Code + "Transit"][i] = true;
				}
				num++;
			}
		}
	}

	public void TrackDistance()
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)GameState.currentBoat == (Object)null) && IsUnderway)
		{
			Vector3 globeCoords = FloatingOriginManager.instance.GetGlobeCoords(GameState.currentBoat);
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(globeCoords.x, 0f, globeCoords.z);
			if (lastPosition == Vector3.zero)
			{
				lastPosition = val;
				return;
			}
			if (trackerTimer > 1)
			{
				trackerTimer--;
				return;
			}
			_floatStats["currentMilesSailed"] += Vector3.Distance(lastPosition, val) * 137.487f;
			lastPosition = val;
			trackerTimer = 1000;
		}
	}

	public void UpdateMilesText()
	{
		_floatStats["MilesSailed"] = _floatStats["currentMilesSailed"];
	}

	public void IncrementIntStat(string statName)
	{
		if (!_intStats.ContainsKey("current" + statName))
		{
			_intStats.Add("current" + statName, 0);
		}
		_intStats["current" + statName]++;
	}

	public void IncrementPortVisited(string port)
	{
		if (!(lastPortVisited == port))
		{
			IncrementIntStat("PortsVisited");
			lastPortVisited = port;
		}
	}

	public void IncrementStormsWeathered()
	{
		string name = ((Object)WeatherStorms.instance.GetCurrentStorm()).name;
		if (!(lastStorm == name))
		{
			SAD_Plugin.LogDebug("Weathering " + name);
			IncrementIntStat("StormsWeathered");
			lastStorm = name;
		}
	}

	public void ClearLastStorm()
	{
		if (!Utility.IsNullOrWhiteSpace(lastStorm))
		{
			SAD_Plugin.LogDebug("Storm cleared");
			lastStorm = string.Empty;
		}
	}

	public void UpdatePage()
	{
		UpdateStats();
		UpdateTexts();
	}

	private void UpdateStats()
	{
		if (_intStats["UnderwayDay"] > 0 || _floatStats["UnderwayTime"] > 0f)
		{
			_intStats["currentUnderwayDay"] = GameState.day - _intStats["UnderwayDay"];
			_floatStats["currentUnderwayTime"] = Sun.sun.globalTime - _floatStats["UnderwayTime"];
		}
		if (_floatStats["currentUnderwayTime"] < 0f)
		{
			_floatStats["currentUnderwayTime"] += 24f;
			_intStats["currentUnderwayDay"]--;
		}
	}

	private void UpdateTexts()
	{
		UpdateFloatTexts();
		UpdateIntTexts();
		UpdateTransitTexts();
	}

	private void UpdateFloatTexts()
	{
		string[] floatStatNames = FloatStatNames;
		foreach (string text in floatStatNames)
		{
			switch (text)
			{
			case "UnderwayTime":
				_statTMs[text].text = FormatStatName(text);
				_statTMs["currentUnderwayTime"].text = FormatUnderwayTime(_intStats["currentUnderwayDay"], _floatStats["currentUnderwayTime"]);
				_statTMs["recordUnderwayTime"].text = FormatUnderwayTime(_intStats["recordUnderwayDay"], _floatStats["recordUnderwayTime"]);
				break;
			case "CargoMass":
				_statTMs[text].text = FormatStatName(text);
				_statTMs["currentCargoMass"].text = ((_floatStats["currentCargoMass"] == 0f) ? "-" : string.Format("{0:#,##0.#} lbs", _floatStats["currentCargoMass"]));
				_statTMs["recordCargoMass"].text = ((_floatStats["recordCargoMass"] == 0f) ? "-" : string.Format("{0:#,##0.#} lbs", _floatStats["recordCargoMass"]));
				break;
			case "TotalMass":
				_statTMs[text].text = FormatStatName(text);
				_statTMs["currentTotalMass"].text = ((_floatStats["currentTotalMass"] == 0f) ? "-" : string.Format("{0:#,##0.#} lbs", _floatStats["currentTotalMass"]));
				_statTMs["recordTotalMass"].text = ((_floatStats["recordTotalMass"] == 0f) ? "-" : string.Format("{0:#,##0.#} lbs", _floatStats["recordTotalMass"]));
				break;
			case "MilesSailed":
				_statTMs[text].text = FormatStatName(text);
				if (Configs.updateMilesSailed.Value == "realtime")
				{
					_statTMs["currentMilesSailed"].text = string.Format("{0:#,##0.#}", _floatStats["currentMilesSailed"]);
				}
				else
				{
					_statTMs["currentMilesSailed"].text = string.Format("{0:#,##0.#}", _floatStats["MilesSailed"]);
				}
				break;
			default:
				_statTMs[text].text = FormatStatName(text);
				_statTMs["current" + text].text = _floatStats["current" + text].ToString();
				_statTMs["record" + text].text = _floatStats["record" + text].ToString();
				break;
			}
		}
	}

	private void UpdateIntTexts()
	{
		Queue<float> posQueue = new Queue<float>(RandomEncounterStatYPos);
		string[] intStatNames = IntStatNames;
		foreach (string text in intStatNames)
		{
			if (!(text == "UnderwayDay"))
			{
				if (_randomEncounterStats.ContainsKey(text))
				{
					PositionRandomEnounterStat(text, posQueue);
				}
				_statTMs[text].text = FormatStatName(text);
				_statTMs["current" + text].text = string.Format("{0:#,##0}", _intStats["current" + text]);
			}
		}
	}

	private void UpdateTransitTexts()
	{
		foreach (string transitCode in Region.TransitCodes)
		{
			_statTMs[transitCode].text = FormatTransitName(transitCode);
			_statTMs["last" + transitCode].text = FormatUnderwayTime(_intStats["last" + transitCode + "TransitDay"], _floatStats["last" + transitCode + "TransitTime"]);
			_statTMs["record" + transitCode].text = FormatUnderwayTime(_intStats["record" + transitCode + "TransitDay"], _floatStats["record" + transitCode + "TransitTime"]);
		}
	}

	private string FormatUnderwayTime(int underwayDay, float underwayTime)
	{
		if (underwayDay == 0 && underwayTime == 0f)
		{
			return "-";
		}
		if (underwayDay > 0)
		{
			string arg = ((underwayDay == 1) ? "Day" : "Days");
			return $"{underwayDay} {arg} {underwayTime:0.0} Hours";
		}
		return $"{underwayTime:0.0} Hours";
	}

	private string FormatStatName(string name)
	{
		if (name.Contains("Encounters"))
		{
			name = name.Replace("Encounters", "Encs");
		}
		return Regex.Replace(name, "([a-z])([A-Z])", "$1 $2");
	}

	private string FormatTransitName(string name)
	{
		string text = FormatStatName(name);
		return text.ToUpper().Insert(text.IndexOf(' '), " to");
	}

	private void PositionRandomEnounterStat(string stat, Queue<float> posQueue)
	{
		//IL_0095: 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_00ac: 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_00be: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)SAD_Plugin.RE_PluginInstance == (Object)null || !_randomEncounterStats[stat]())
		{
			((Component)_statTMs[stat]).gameObject.SetActive(false);
		}
		else if ((Object)(object)SAD_Plugin.RE_PluginInstance != (Object)null && _randomEncounterStats[stat]())
		{
			((Component)_statTMs[stat]).gameObject.SetActive(true);
			Vector3 localPosition = ((Component)_statTMs[stat]).transform.localPosition;
			((Component)_statTMs[stat]).transform.localPosition = new Vector3(localPosition.x, posQueue.Dequeue(), localPosition.z);
		}
	}

	public void SetUIElems(Dictionary<string, TextMesh> statTMs)
	{
		_statTMs = statTMs;
	}

	public void LoadStatsUI()
	{
		ModData.GetDictEntry("Sail-a-dex.IntStats", _intStats);
		ModData.GetDictEntry("Sail-a-dex.FloatStats", _floatStats);
		ModData.GetDictEntry("Sail-a-dex.BoolArrayStats", _boolArrayStats);
		IsUnderway = ModData.GetEntry<bool>("Sail-a-dex.IsUnderway");
		lastPortVisited = ModData.GetEntry<string>("Sail-a-dex.LastPortVisited");
		lastStorm = ModData.GetEntry<string>("Sail-a-dex.LastStorm");
	}

	public void SaveStatsUI()
	{
		ModData.AddDictEntry("Sail-a-dex.IntStats", _intStats);
		ModData.AddDictEntry("Sail-a-dex.FloatStats", _floatStats);
		ModData.AddDictEntry("Sail-a-dex.BoolArrayStats", _boolArrayStats);
		ModData.AddEntry("Sail-a-dex.IsUnderway", IsUnderway);
		ModData.AddEntry("Sail-a-dex.LastPortVisited", lastPortVisited);
		ModData.AddEntry("Sail-a-dex.LastStorm", lastStorm);
	}
}