Decompiled source of Rod Locker v1.0.1

BepInEx/plugins/RodLockerBepInEx.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Localization;
using UnityEngine.Localization.Components;
using UnityEngine.Localization.Tables;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("RodLockerBepInEx")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("RodLockerBepInEx")]
[assembly: AssemblyTitle("RodLockerBepInEx")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RodLockerBepInEx
{
	[BepInPlugin("legoless.RodLocker", "Rod Locker", "1.0.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "legoless.RodLocker";

		public const string PluginName = "Rod Locker";

		public const string PluginVersion = "1.0.0";

		private Harmony harmony;

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			RodLockerRuntime.PluginAssembly = Assembly.GetExecutingAssembly();
			harmony = new Harmony("legoless.RodLocker");
			harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Rod Locker BepInEx Edition loaded. No game files are modified by this plugin DLL.");
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}
	}
	internal static class RodLockerRuntime
	{
		private sealed class RodDefinition
		{
			public string Id { get; }

			public Sprite Sprite { get; }

			public RodDefinition(string id, Sprite sprite)
			{
				Id = id;
				Sprite = sprite;
			}
		}

		private const string BlackstoneDockId = "dock.outcast-isle";

		private const string RodLockerDestinationId = "destination.rod-locker";

		private const string RodLockerTitleKey = "destination.rod-locker";

		private const GridKey RodLockerGridKey = 459001;

		private static readonly FieldInfo DestinationButtonPrefabField = AccessTools.Field(typeof(DockUI), "destinationButtonPrefab");

		private static readonly FieldInfo DestinationButtonContainerField = AccessTools.Field(typeof(DockUI), "destinationButtonContainer");

		private static readonly FieldInfo DestinationButtonObjectsField = AccessTools.Field(typeof(DockUI), "destinationButtonObjects");

		private static readonly FieldInfo DestinationButtonsField = AccessTools.Field(typeof(DockUI), "destinationButtons");

		private static readonly FieldInfo DockDestinationsField = AccessTools.Field(typeof(Dock), "destinations");

		private static readonly FieldInfo BaseDestinationIdField = AccessTools.Field(typeof(BaseDestination), "id");

		private static readonly FieldInfo BaseDestinationTitleKeyField = AccessTools.Field(typeof(BaseDestination), "titleKey");

		private static readonly FieldInfo BaseDestinationSpeakerRootNodeOverrideField = AccessTools.Field(typeof(BaseDestination), "speakerRootNodeOverride");

		private static readonly FieldInfo BaseDestinationAlwaysShowField = AccessTools.Field(typeof(BaseDestination), "alwaysShow");

		private static readonly FieldInfo BaseDestinationIsIndoorsField = AccessTools.Field(typeof(BaseDestination), "isIndoors");

		private static readonly FieldInfo BaseDestinationIconField = AccessTools.Field(typeof(BaseDestination), "icon");

		private static readonly FieldInfo BaseDestinationLoopSfxField = AccessTools.Field(typeof(BaseDestination), "loopSFX");

		private static readonly FieldInfo BaseDestinationVisitSfxField = AccessTools.Field(typeof(BaseDestination), "visitSFX");

		private static readonly FieldInfo BaseDestinationVCamField = AccessTools.Field(typeof(BaseDestination), "vCam");

		private static readonly FieldInfo BaseDestinationHighlightConditionsField = AccessTools.Field(typeof(BaseDestination), "highlightConditions");

		private static readonly FieldInfo BaseDestinationPlayerInventoryTabIndexesField = AccessTools.Field(typeof(BaseDestination), "playerInventoryTabIndexesToShow");

		private static readonly FieldInfo MarketDestinationItemTypesBoughtField = AccessTools.Field(typeof(MarketDestination), "itemTypesBought");

		private static readonly FieldInfo MarketDestinationItemSubtypesBoughtField = AccessTools.Field(typeof(MarketDestination), "itemSubtypesBought");

		private static readonly FieldInfo MarketDestinationBulkItemTypesBoughtField = AccessTools.Field(typeof(MarketDestination), "bulkItemTypesBought");

		private static readonly FieldInfo MarketDestinationBulkItemSubtypesBoughtField = AccessTools.Field(typeof(MarketDestination), "bulkItemSubtypesBought");

		private static readonly FieldInfo MarketDestinationSpecificItemsBoughtField = AccessTools.Field(typeof(MarketDestination), "specificItemsBought");

		private static readonly FieldInfo MarketDestinationSellValueModifierField = AccessTools.Field(typeof(MarketDestination), "sellValueModifier");

		private static readonly FieldInfo MarketDestinationAllowSellIfGridFullField = AccessTools.Field(typeof(MarketDestination), "allowSellIfGridFull");

		private static readonly FieldInfo MarketDestinationAllowStorageAccessField = AccessTools.Field(typeof(MarketDestination), "allowStorageAccess");

		private static readonly FieldInfo MarketDestinationAllowRepairsField = AccessTools.Field(typeof(MarketDestination), "allowRepairs");

		private static readonly FieldInfo MarketDestinationAllowBulkSellField = AccessTools.Field(typeof(MarketDestination), "allowBulkSell");

		private static readonly FieldInfo MarketDestinationBulkSellPromptStringField = AccessTools.Field(typeof(MarketDestination), "bulkSellPromptString");

		private static readonly FieldInfo MarketDestinationBulkSellNotificationStringField = AccessTools.Field(typeof(MarketDestination), "bulkSellNotificationString");

		private static readonly FieldInfo DestinationButtonTextField = AccessTools.Field(typeof(DestinationButton), "textField");

		private static readonly FieldInfo MarketTitleStringField = AccessTools.Field(typeof(MarketDestinationUI), "localizedTitleString");

		private static readonly FieldInfo BaseDestinationUIDestinationField = AccessTools.Field(typeof(BaseDestinationUI), "destination");

		private static readonly FieldInfo ItemManagerAllItemsField = AccessTools.Field(typeof(ItemManager), "allItems");

		private static readonly FieldInfo PlatformSpriteOverridesField = AccessTools.Field(typeof(SpatialItemData), "platformSpecificSpriteOverrides");

		private static readonly FieldInfo ItemOwnPrerequisitesField = AccessTools.Field(typeof(SpatialItemData), "itemOwnPrerequisites");

		private static readonly FieldInfo ResearchPrerequisitesField = AccessTools.Field(typeof(SpatialItemData), "researchPrerequisites");

		private static readonly FieldInfo ResearchPointsRequiredField = AccessTools.Field(typeof(SpatialItemData), "researchPointsRequired");

		private static readonly FieldInfo BuyableWithoutResearchField = AccessTools.Field(typeof(SpatialItemData), "buyableWithoutResearch");

		private static readonly FieldInfo ResearchIsForRecipeField = AccessTools.Field(typeof(SpatialItemData), "researchIsForRecipe");

		private static readonly FieldInfo GridMainItemTypeField = AccessTools.Field(typeof(GridConfiguration), "mainItemType");

		private static readonly FieldInfo GridMainItemSubtypeField = AccessTools.Field(typeof(GridConfiguration), "mainItemSubtype");

		private static readonly FieldInfo GridItemsBelongToPlayerField = AccessTools.Field(typeof(GridConfiguration), "itemsInThisBelongToPlayer");

		private static readonly FieldInfo GridCanAddItemsInQuestModeField = AccessTools.Field(typeof(GridConfiguration), "canAddItemsInQuestMode");

		private static readonly FieldInfo GridHasUnderlayField = AccessTools.Field(typeof(GridConfiguration), "hasUnderlay");

		private static readonly string[] RodItemIds = new string[7] { "legoless.rodlocker.playstation", "legoless.rodlocker.xbox", "legoless.rodlocker.switch", "legoless.rodlocker.steam", "legoless.rodlocker.gog", "legoless.rodlocker.ios", "legoless.rodlocker.android" };

		private static readonly Dictionary<string, string> RodSpriteResourceNames = new Dictionary<string, string>(StringComparer.Ordinal)
		{
			{ "legoless.rodlocker.playstation", "RodLockerBepInEx.Assets.legoless.rodlocker.playstation.png" },
			{ "legoless.rodlocker.xbox", "RodLockerBepInEx.Assets.legoless.rodlocker.xbox.png" },
			{ "legoless.rodlocker.switch", "RodLockerBepInEx.Assets.legoless.rodlocker.switch.png" },
			{ "legoless.rodlocker.steam", "RodLockerBepInEx.Assets.legoless.rodlocker.steam.png" },
			{ "legoless.rodlocker.gog", "RodLockerBepInEx.Assets.legoless.rodlocker.gog.png" },
			{ "legoless.rodlocker.ios", "RodLockerBepInEx.Assets.legoless.rodlocker.ios.png" },
			{ "legoless.rodlocker.android", "RodLockerBepInEx.Assets.legoless.rodlocker.android.png" }
		};

		private static readonly Dictionary<string, string> TitleTranslations = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
		{
			{ "en", "Rod Locker" },
			{ "fr", "Casier à cannes" },
			{ "de", "Angelrutenschrank" },
			{ "it", "Armadietto portacanne" },
			{ "es", "Taquilla de cañas" },
			{ "pl", "Szafka na wędki" },
			{ "ru", "Шкафчик для удочек" },
			{ "pt-BR", "Armário de varas" },
			{ "ja-JP", "ロッドロッカー" },
			{ "ko-KR", "낙싯대 보관함" },
			{ "zh-Hans", "鱼竿柜" },
			{ "zh-Hant", "釣竿櫃" }
		};

		private static bool loggedInjection;

		private static bool registeredItems;

		private static bool loadedEmbeddedSprites;

		private static MarketDestination rodLockerDestination;

		private static GridConfiguration rodLockerGridConfig;

		private static Sprite rodIconSprite;

		private static readonly Dictionary<string, Sprite> RodSprites = new Dictionary<string, Sprite>(StringComparer.Ordinal);

		internal static Assembly PluginAssembly { get; set; }

		internal static BaseDestination EnsureRodLockerDestination(Dock dock)
		{
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0364: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bc: Expected O, but got Unknown
			if ((Object)(object)dock == (Object)null || (Object)(object)dock.Data == (Object)null || dock.Data.Id != "dock.outcast-isle")
			{
				return null;
			}
			EnsureRuntimeData();
			EnsureRodLockerGrid();
			if ((Object)(object)rodLockerDestination != (Object)null)
			{
				return (BaseDestination)(object)rodLockerDestination;
			}
			try
			{
				BaseDestination val = GetDockDestinations(dock)?.FirstOrDefault((Func<BaseDestination, bool>)((BaseDestination destination) => (Object)(object)destination != (Object)null && (destination.Id == "destination.outcast-yard" || ((Object)((Component)destination).gameObject).name == "Workshop")));
				MarketDestination val2 = (MarketDestination)(object)((val is MarketDestination) ? val : null);
				Transform val3 = (((Object)(object)val != (Object)null) ? ((Component)val).transform.parent : ((Component)dock).transform);
				GameObject val4 = new GameObject("Rod Locker Destination");
				val4.transform.SetParent(val3, false);
				val4.transform.localPosition = (((Object)(object)val != (Object)null) ? (((Component)val).transform.localPosition + new Vector3(0f, 1.25f, 0f)) : Vector3.zero);
				MarketDestination val5 = val4.AddComponent<MarketDestination>();
				BaseDestinationIdField.SetValue(val5, "destination.rod-locker");
				BaseDestinationTitleKeyField.SetValue(val5, CreateLocalizedString("destination.rod-locker"));
				BaseDestinationSpeakerRootNodeOverrideField.SetValue(val5, string.Empty);
				BaseDestinationAlwaysShowField.SetValue(val5, true);
				BaseDestinationIsIndoorsField.SetValue(val5, true);
				BaseDestinationIconField.SetValue(val5, ((Object)(object)rodIconSprite != (Object)null) ? rodIconSprite : (((Object)(object)val != (Object)null) ? val.Icon : null));
				BaseDestinationLoopSfxField.SetValue(val5, ((Object)(object)val2 != (Object)null) ? BaseDestinationLoopSfxField.GetValue(val2) : null);
				BaseDestinationVisitSfxField.SetValue(val5, ((Object)(object)val2 != (Object)null) ? BaseDestinationVisitSfxField.GetValue(val2) : null);
				BaseDestinationVCamField.SetValue(val5, ((Object)(object)val != (Object)null) ? val.VCam : null);
				BaseDestinationHighlightConditionsField.SetValue(val5, new List<HighlightCondition>());
				((BaseDestination)val5).selectOnLeft = new List<BaseDestination>();
				((BaseDestination)val5).selectOnRight = new List<BaseDestination>();
				((BaseDestination)val5).selectOnUp = new List<BaseDestination>();
				((BaseDestination)val5).selectOnDown = (((Object)(object)val != (Object)null) ? new List<BaseDestination> { val } : new List<BaseDestination>());
				List<int> value = (((Object)(object)val2 != (Object)null) ? new List<int>((List<int>)BaseDestinationPlayerInventoryTabIndexesField.GetValue(val2)) : new List<int> { 0, 1, 2 });
				BaseDestinationPlayerInventoryTabIndexesField.SetValue(val5, value);
				MarketDestinationItemTypesBoughtField.SetValue(val5, (object)(ItemType)2);
				MarketDestinationItemSubtypesBoughtField.SetValue(val5, (object)(ItemSubtype)4);
				MarketDestinationBulkItemTypesBoughtField.SetValue(val5, (object)(ItemType)0);
				MarketDestinationBulkItemSubtypesBoughtField.SetValue(val5, (object)(ItemSubtype)0);
				MarketDestinationSpecificItemsBoughtField.SetValue(val5, Array.Empty<SpatialItemData>());
				MarketDestinationSellValueModifierField.SetValue(val5, 0f);
				MarketDestinationAllowSellIfGridFullField.SetValue(val5, false);
				MarketDestinationAllowStorageAccessField.SetValue(val5, true);
				MarketDestinationAllowRepairsField.SetValue(val5, false);
				MarketDestinationAllowBulkSellField.SetValue(val5, false);
				MarketDestinationBulkSellPromptStringField.SetValue(val5, string.Empty);
				MarketDestinationBulkSellNotificationStringField.SetValue(val5, string.Empty);
				val5.marketTabs = new List<MarketTabConfig>
				{
					new MarketTabConfig
					{
						gridKey = (GridKey)459001,
						tabSprite = (((Object)(object)rodIconSprite != (Object)null) ? rodIconSprite : (((Object)(object)val != (Object)null) ? val.Icon : null)),
						titleKey = CreateLocalizedString("destination.rod-locker"),
						isUnlockedBasedOnDialogue = false,
						unlockDialogueNodes = new List<string>()
					}
				};
				rodLockerDestination = val5;
				return (BaseDestination)(object)val5;
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Failed to create Rod Locker destination: {arg}");
				return null;
			}
		}

		internal static void AddRodLockerButton(DockUI dockUi, Dock dock)
		{
			if ((Object)(object)dockUi == (Object)null || (Object)(object)dock == (Object)null || (Object)(object)dock.Data == (Object)null || dock.Data.Id != "dock.outcast-isle")
			{
				return;
			}
			BaseDestination val = EnsureRodLockerDestination(dock);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			try
			{
				List<DestinationButton> list = DestinationButtonsField.GetValue(dockUi) as List<DestinationButton>;
				if (list != null && list.Any((DestinationButton button) => (Object)(object)button != (Object)null && (Object)(object)button.destination != (Object)null && button.destination.Id == "destination.rod-locker"))
				{
					return;
				}
				object? value = DestinationButtonPrefabField.GetValue(dockUi);
				GameObject val2 = (GameObject)((value is GameObject) ? value : null);
				object? value2 = DestinationButtonContainerField.GetValue(dockUi);
				Transform val3 = (Transform)((value2 is Transform) ? value2 : null);
				List<GameObject> list2 = DestinationButtonObjectsField.GetValue(dockUi) as List<GameObject>;
				if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null)
				{
					Plugin.Log.LogError((object)"Rod Locker could not find the vanilla destination button prefab/container.");
					return;
				}
				GameObject val4 = Object.Instantiate<GameObject>(val2, val3);
				DestinationButton component = val4.GetComponent<DestinationButton>();
				if ((Object)(object)component == (Object)null)
				{
					Object.Destroy((Object)(object)val4);
					Plugin.Log.LogError((object)"Rod Locker destination button prefab did not contain DestinationButton.");
					return;
				}
				component.Init(val);
				SetDestinationButtonText(component);
				list?.Add(component);
				list2?.Add(val4);
				if (!loggedInjection)
				{
					Plugin.Log.LogInfo((object)$"Rod Locker UI button added to Blackstone. StoredDestinations={GetDockDestinations(dock)?.Count ?? 0}, BoatActionsReady={(Object)(object)dock.boatActionsDestination != (Object)null}");
					loggedInjection = true;
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Failed to add Rod Locker UI button: {arg}");
			}
		}

		internal static void ResetCachedDestination()
		{
			rodLockerDestination = null;
			loggedInjection = false;
		}

		internal static void EnsureRuntimeData()
		{
			LoadEmbeddedSprites();
			GameManager instance = GameManager.Instance;
			RegisterRodItems((instance != null) ? instance.ItemManager : null);
			EnsureRodLockerGridConfig();
		}

		internal static void RegisterRodItems(ItemManager itemManager)
		{
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			LoadEmbeddedSprites();
			if ((Object)(object)itemManager == (Object)null || !itemManager.HasLoaded())
			{
				return;
			}
			if (!(ItemManagerAllItemsField.GetValue(itemManager) is List<ItemData> list))
			{
				Plugin.Log.LogWarning((object)"Could not access ItemManager item list for Rod Locker registration.");
			}
			else
			{
				if (registeredItems && HasAllRodItems(list))
				{
					return;
				}
				RodItemData itemDataById = itemManager.GetItemDataById<RodItemData>("rod21");
				if ((Object)(object)itemDataById == (Object)null)
				{
					Plugin.Log.LogWarning((object)"Could not find vanilla rod21 Custom Rod data.");
					return;
				}
				rodIconSprite = (((Object)(object)((ItemData)itemDataById).itemTypeIcon != (Object)null) ? ((ItemData)itemDataById).itemTypeIcon : ((SpatialItemData)itemDataById).GetSprite());
				RodDefinition[] array = RodItemIds.Select((string itemId) => new RodDefinition(itemId, GetRodSprite(itemId))).ToArray();
				int num = 0;
				RodDefinition[] array2 = array;
				foreach (RodDefinition definition in array2)
				{
					if ((Object)(object)definition.Sprite == (Object)null)
					{
						Plugin.Log.LogWarning((object)("Skipping " + definition.Id + ": no sprite was available."));
					}
					else if (!list.Any((ItemData item) => (Object)(object)item != (Object)null && item.id == definition.Id))
					{
						RodItemData val = Object.Instantiate<RodItemData>(itemDataById);
						((Object)val).name = definition.Id;
						((ItemData)val).id = definition.Id;
						((SpatialItemData)val).sprite = definition.Sprite;
						((SpatialItemData)val).itemColor = Color32.op_Implicit(new Color32((byte)49, (byte)49, (byte)49, byte.MaxValue));
						((SpatialItemData)val).value = default(decimal);
						((SpatialItemData)val).sellOverrideValue = default(decimal);
						val.fishingSpeedModifier = 0.4f;
						((HarvesterItemData)val).harvestableTypes = (HarvestableType[])(object)new HarvestableType[1] { (HarvestableType)1 };
						((HarvesterItemData)val).aberrationBonus = 0f;
						((ItemData)val).itemType = (ItemType)2;
						((ItemData)val).itemSubtype = (ItemSubtype)4;
						((SpatialItemData)val).damageMode = (DamageMode)2;
						((SpatialItemData)val).moveMode = (MoveMode)1;
						((ItemData)val).entitlementsRequired = new List<Entitlement>();
						PlatformSpriteOverridesField.SetValue(val, new Dictionary<Platform, Sprite>());
						ItemOwnPrerequisitesField.SetValue(val, new List<OwnedItemResearchablePrerequisite>());
						ResearchPrerequisitesField.SetValue(val, new List<ResearchedItemResearchablePrerequisite>());
						ResearchPointsRequiredField.SetValue(val, 0);
						BuyableWithoutResearchField.SetValue(val, false);
						ResearchIsForRecipeField.SetValue(val, false);
						list.Add((ItemData)(object)val);
						num++;
					}
				}
				registeredItems = HasAllRodItems(list);
				Plugin.Log.LogInfo((object)$"Rod Locker registered custom rod item data. Added={num}, Present={CountRodItems(list)}/{RodItemIds.Length}");
			}
		}

		internal static void EnsureRodLockerGrid()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			EnsureRuntimeData();
			GameManager instance = GameManager.Instance;
			SaveData val = ((instance != null) ? instance.SaveData : null);
			if (val != null && !((Object)(object)rodLockerGridConfig == (Object)null))
			{
				if (val.grids == null)
				{
					val.grids = new Dictionary<GridKey, SerializableGrid>();
				}
				if (!val.grids.TryGetValue((GridKey)459001, out var value) || value == null)
				{
					value = new SerializableGrid();
					val.grids[(GridKey)459001] = value;
					value.Init(rodLockerGridConfig, false);
				}
				else if ((Object)(object)value.GridConfiguration == (Object)null)
				{
					value.Init(rodLockerGridConfig, false);
				}
				RemoveAlreadyTakenStock(value);
				AddMissingStock(value);
			}
		}

		internal static bool IsRodLockerDestination(BaseDestination destination)
		{
			if ((Object)(object)destination != (Object)null)
			{
				return destination.Id == "destination.rod-locker";
			}
			return false;
		}

		internal static bool IsRodLockerGrid(GridKey gridKey)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			return (int)gridKey == 459001;
		}

		internal static void SetDestinationButtonText(DestinationButton button)
		{
			if (!((Object)(object)button == (Object)null) && IsRodLockerDestination(button.destination))
			{
				object? value = DestinationButtonTextField.GetValue(button);
				TextMeshProUGUI val = (TextMeshProUGUI)((value is TextMeshProUGUI) ? value : null);
				if ((Object)(object)val != (Object)null)
				{
					((TMP_Text)val).text = GetTranslatedTitle();
				}
			}
		}

		internal static void SetMarketTitle(MarketDestinationUI ui)
		{
			if (!((Object)(object)ui == (Object)null) && IsRodLockerMarketUI(ui))
			{
				object? value = MarketTitleStringField.GetValue(ui);
				LocalizeStringEvent val = (LocalizeStringEvent)((value is LocalizeStringEvent) ? value : null);
				TextMeshProUGUI val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<TextMeshProUGUI>() : null);
				if ((Object)(object)val2 != (Object)null)
				{
					((TMP_Text)val2).text = GetTranslatedTitle();
				}
			}
		}

		internal static bool IsRodLockerMarketUI(MarketDestinationUI ui)
		{
			if ((Object)(object)ui == (Object)null)
			{
				return false;
			}
			object? obj = BaseDestinationUIDestinationField?.GetValue(ui);
			return IsRodLockerDestination((BaseDestination)((obj is BaseDestination) ? obj : null));
		}

		internal static string GetTranslatedTitle()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			string text = "en";
			try
			{
				GameManager instance = GameManager.Instance;
				object obj;
				if (instance == null)
				{
					obj = null;
				}
				else
				{
					LanguageManager languageManager = instance.LanguageManager;
					if (languageManager == null)
					{
						obj = null;
					}
					else
					{
						Locale locale = languageManager.GetLocale();
						if (locale == null)
						{
							obj = null;
						}
						else
						{
							LocaleIdentifier identifier = locale.Identifier;
							obj = ((LocaleIdentifier)(ref identifier)).Code;
						}
					}
				}
				if (obj == null)
				{
					obj = text;
				}
				text = (string)obj;
			}
			catch
			{
			}
			if (TitleTranslations.TryGetValue(text, out var value))
			{
				return value;
			}
			string key = text.Split(new char[1] { '-' })[0];
			if (!TitleTranslations.TryGetValue(key, out value))
			{
				return TitleTranslations["en"];
			}
			return value;
		}

		private static void EnsureRodLockerGridConfig()
		{
			if (!((Object)(object)rodLockerGridConfig != (Object)null))
			{
				GameManager instance = GameManager.Instance;
				GameConfigData val = ((instance != null) ? instance.GameConfigData : null);
				GridConfiguration val2 = (((Object)(object)val != (Object)null) ? val.GetGridConfigForKey((GridKey)21) : null);
				rodLockerGridConfig = (((Object)(object)val2 != (Object)null) ? Object.Instantiate<GridConfiguration>(val2) : ScriptableObject.CreateInstance<GridConfiguration>());
				((Object)rodLockerGridConfig).name = "legoless.rodlocker.grid";
				rodLockerGridConfig.columns = 7;
				rodLockerGridConfig.rows = 2;
				rodLockerGridConfig.cellGroupConfigs = new List<CellGroupConfiguration>();
				GridMainItemTypeField.SetValue(rodLockerGridConfig, (object)(ItemType)2);
				GridMainItemSubtypeField.SetValue(rodLockerGridConfig, (object)(ItemSubtype)4);
				GridItemsBelongToPlayerField.SetValue(rodLockerGridConfig, false);
				GridCanAddItemsInQuestModeField.SetValue(rodLockerGridConfig, false);
				GridHasUnderlayField.SetValue(rodLockerGridConfig, false);
			}
		}

		private static List<BaseDestination> GetDockDestinations(Dock dock)
		{
			if (!((Object)(object)dock != (Object)null))
			{
				return null;
			}
			return DockDestinationsField.GetValue(dock) as List<BaseDestination>;
		}

		private static bool HasAllRodItems(List<ItemData> allItems)
		{
			return CountRodItems(allItems) == RodItemIds.Length;
		}

		private static int CountRodItems(List<ItemData> allItems)
		{
			if (allItems == null)
			{
				return 0;
			}
			return RodItemIds.Count((string itemId) => allItems.Any((ItemData item) => (Object)(object)item != (Object)null && item.id == itemId));
		}

		private static void RemoveAlreadyTakenStock(SerializableGrid grid)
		{
			foreach (SpatialItemInstance item in grid.spatialItems.Where((SpatialItemInstance item) => item != (SpatialItemInstance)null && RodItemIds.Contains(((ItemInstance)item).id) && HasRodLockerItemBeenTaken(((ItemInstance)item).id)).ToList())
			{
				grid.RemoveObjectFromGridData(item, false);
			}
		}

		private static void AddMissingStock(SerializableGrid grid)
		{
			GameManager instance = GameManager.Instance;
			ItemManager val = ((instance != null) ? instance.ItemManager : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			HashSet<string> hashSet = new HashSet<string>(from item in grid.spatialItems
				where item != (SpatialItemInstance)null
				select ((ItemInstance)item).id);
			string[] rodItemIds = RodItemIds;
			foreach (string text in rodItemIds)
			{
				if (!hashSet.Contains(text) && !HasRodLockerItemBeenTaken(text))
				{
					SpatialItemData itemDataById = val.GetItemDataById<SpatialItemData>(text);
					if ((Object)(object)itemDataById == (Object)null)
					{
						Plugin.Log.LogWarning((object)("Could not stock " + text + ": item data is not registered."));
					}
					else if (grid.FindSpaceAndAddObjectToGridData(itemDataById, false, (Action<GridObject>)null))
					{
						hashSet.Add(text);
					}
					else
					{
						Plugin.Log.LogWarning((object)("Could not place " + text + " in the Rod Locker grid."));
					}
				}
			}
		}

		private static bool HasRodLockerItemBeenTaken(string itemId)
		{
			GameManager instance = GameManager.Instance;
			return (((instance != null) ? instance.SaveData : null)?.itemTransactions?.Any((SerializedItemTransaction transaction) => transaction != null && transaction.itemId == itemId && transaction.bought > 0)).GetValueOrDefault();
		}

		private static LocalizedString CreateLocalizedString(string key)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			return new LocalizedString(TableReference.op_Implicit(LanguageManager.STRING_TABLE), TableEntryReference.op_Implicit(key));
		}

		private static Sprite GetRodSprite(string itemId)
		{
			LoadEmbeddedSprites();
			if (!RodSprites.TryGetValue(itemId, out var value))
			{
				return null;
			}
			return value;
		}

		private static void LoadEmbeddedSprites()
		{
			if (loadedEmbeddedSprites)
			{
				return;
			}
			foreach (KeyValuePair<string, string> rodSpriteResourceName in RodSpriteResourceNames)
			{
				Sprite val = LoadEmbeddedSprite(rodSpriteResourceName.Value, rodSpriteResourceName.Key + ".sprite");
				if ((Object)(object)val != (Object)null)
				{
					RodSprites[rodSpriteResourceName.Key] = val;
				}
			}
			loadedEmbeddedSprites = true;
			Plugin.Log.LogInfo((object)$"Rod Locker loaded {RodSprites.Count}/{RodSpriteResourceNames.Count} embedded rod sprites.");
		}

		private static Sprite LoadEmbeddedSprite(string resourceName, string spriteName)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			using Stream stream = PluginAssembly.GetManifestResourceStream(resourceName);
			if (stream == null)
			{
				Plugin.Log.LogError((object)("Missing embedded sprite resource: " + resourceName));
				return null;
			}
			byte[] array = new byte[stream.Length];
			int num;
			for (int i = 0; i < array.Length; i += num)
			{
				num = stream.Read(array, i, array.Length - i);
				if (num <= 0)
				{
					break;
				}
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			((Object)val).name = spriteName.Replace(".sprite", ".texture");
			if (!ImageConversion.LoadImage(val, array))
			{
				Plugin.Log.LogError((object)("Failed to load embedded sprite resource: " + resourceName));
				return null;
			}
			((Texture)val).filterMode = (FilterMode)1;
			Sprite obj = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
			((Object)obj).name = spriteName;
			return obj;
		}
	}
	[HarmonyPatch(typeof(ItemManager), "OnItemDataAddressablesLoaded")]
	internal static class ItemManagerLoadedPatch
	{
		private static void Postfix(ItemManager __instance)
		{
			RodLockerRuntime.RegisterRodItems(__instance);
			RodLockerRuntime.EnsureRodLockerGrid();
		}
	}
	[HarmonyPatch(typeof(GameManager), "BeginGame")]
	internal static class GameManagerBeginGamePatch
	{
		private static void Postfix()
		{
			RodLockerRuntime.ResetCachedDestination();
			RodLockerRuntime.EnsureRuntimeData();
			RodLockerRuntime.EnsureRodLockerGrid();
		}
	}
	[HarmonyPatch(typeof(GameConfigData), "GetGridConfigForKey")]
	internal static class GameConfigDataGetGridConfigPatch
	{
		private static void Postfix(GridKey key, ref GridConfiguration __result)
		{
			//IL_0000: 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)
			if (RodLockerRuntime.IsRodLockerGrid(key))
			{
				RodLockerRuntime.EnsureRuntimeData();
				GameManager instance = GameManager.Instance;
				SaveData val = ((instance != null) ? instance.SaveData : null);
				if (val != null && val.grids.TryGetValue(key, out var value))
				{
					__result = value.GridConfiguration;
				}
			}
		}
	}
	[HarmonyPatch(typeof(DockUI), "ShowUIWithDelay")]
	internal static class DockUIShowUIWithDelayPatch
	{
		private static void Postfix(DockUI __instance, Dock dock, ref IEnumerator __result)
		{
			__result = AddRodLockerButtonAfterVanillaUI(__instance, dock, __result);
		}

		private static IEnumerator AddRodLockerButtonAfterVanillaUI(DockUI dockUi, Dock dock, IEnumerator original)
		{
			while (true)
			{
				object current;
				try
				{
					if (!original.MoveNext())
					{
						break;
					}
					current = original.Current;
					goto IL_004f;
				}
				catch (Exception arg)
				{
					Plugin.Log.LogError((object)$"Vanilla DockUI.ShowUIWithDelay failed before Rod Locker injection: {arg}");
					yield break;
				}
				IL_004f:
				yield return current;
			}
			(original as IDisposable)?.Dispose();
			RodLockerRuntime.AddRodLockerButton(dockUi, dock);
		}
	}
	[HarmonyPatch(typeof(DestinationButton), "Init")]
	internal static class DestinationButtonInitPatch
	{
		private static void Postfix(DestinationButton __instance)
		{
			if ((Object)(object)__instance != (Object)null && RodLockerRuntime.IsRodLockerDestination(__instance.destination))
			{
				RodLockerRuntime.SetDestinationButtonText(__instance);
				((MonoBehaviour)__instance).StartCoroutine(SetTextNextFrame(__instance));
			}
		}

		private static IEnumerator SetTextNextFrame(DestinationButton button)
		{
			yield return null;
			RodLockerRuntime.SetDestinationButtonText(button);
		}
	}
	[HarmonyPatch(typeof(MarketDestinationUI), "ShowMainUI")]
	internal static class MarketDestinationUIShowMainUIPatch
	{
		private static void Prefix(MarketDestinationUI __instance)
		{
			if (RodLockerRuntime.IsRodLockerMarketUI(__instance))
			{
				RodLockerRuntime.EnsureRodLockerGrid();
			}
		}

		private static void Postfix(MarketDestinationUI __instance)
		{
			if (RodLockerRuntime.IsRodLockerMarketUI(__instance))
			{
				RodLockerRuntime.SetMarketTitle(__instance);
				((MonoBehaviour)__instance).StartCoroutine(SetTitleNextFrame(__instance));
			}
		}

		private static IEnumerator SetTitleNextFrame(MarketDestinationUI ui)
		{
			yield return null;
			RodLockerRuntime.SetMarketTitle(ui);
		}
	}
	[HarmonyPatch(typeof(MarketDestinationUI), "OnMarketTabChanged")]
	internal static class MarketDestinationUIOnMarketTabChangedPatch
	{
		private static void Postfix(MarketDestinationUI __instance)
		{
			RodLockerRuntime.SetMarketTitle(__instance);
		}
	}
}