Decompiled source of Interactive Store v1.0.0

BepInEx/plugins/InteractiveStore/InteractiveStore.dll

Decompiled 7 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using InteractiveStore.Configuration;
using InteractiveStore.NetcodePatcher;
using InteractiveStore.UI.Application;
using InteractiveStore.UI.Cursor;
using InteractiveTerminalAPI.Compat;
using InteractiveTerminalAPI.UI;
using InteractiveTerminalAPI.UI.Application;
using InteractiveTerminalAPI.UI.Cursor;
using InteractiveTerminalAPI.UI.Page;
using InteractiveTerminalAPI.UI.Screen;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
internal class <Module>
{
	static <Module>()
	{
	}
}
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 WeatherProbe.Misc
{
	internal static class Metadata
	{
		public const string GUID = "com.github.WhiteSpike.InteractiveStore";

		public const string NAME = "Interactive Store";

		public const string VERSION = "1.0.0";
	}
}
namespace InteractiveStore
{
	[BepInPlugin("com.github.WhiteSpike.InteractiveStore", "Interactive Store", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static readonly Harmony harmony = new Harmony("com.github.WhiteSpike.InteractiveStore");

		internal static ManualLogSource mls;

		internal static ModConfiguration config;

		private void Awake()
		{
			config = new ModConfiguration(((BaseUnityPlugin)this).Config);
			InteractiveTerminalManager.RegisterApplication<StoreApplication>(config.ItemStoreCommandList.Value, config.ItemStoreCommandCaseSensitive.Value);
			InteractiveTerminalManager.RegisterApplication<UnlockableStoreApplication>(config.DecorationStoreCommandList.Value, config.DecorationStoreCommandCaseSensitive.Value);
			mls = ((BaseUnityPlugin)this).Logger;
			mls.LogInfo((object)"Interactive Store 1.0.0 has been loaded successfully.");
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "InteractiveStore";

		public const string PLUGIN_NAME = "ExtendDeadline";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace InteractiveStore.UI.Cursor
{
	public class ItemCursorElement : CursorOutputElement<int>
	{
		private const int NAME_LENGTH = 30;

		private const char WHITE_SPACE = ' ';

		public Item item;

		private float salePercentage;

		private Terminal terminal;

		public ItemCursorElement(Item item, float salePercentage, Action pressAction, Terminal terminal)
		{
			this.item = item;
			this.salePercentage = salePercentage;
			((CursorElement)this).Action = pressAction;
			this.terminal = terminal;
			((CursorCounterElement)this).Counter = 0;
			base.Func = (int x) => x * Mathf.CeilToInt((float)item.creditsWorth * salePercentage);
			this.terminal = terminal;
		}

		public override string GetText(int availableLength)
		{
			StringBuilder stringBuilder = new StringBuilder();
			int groupCredits = terminal.groupCredits;
			if (!((CursorElement)this).Active((CursorElement)(object)this))
			{
				stringBuilder.Append("<color=#66666666>");
			}
			string value = ((item.itemName.Length > 30) ? item.itemName.Substring(0, 30) : (item.itemName + new string(' ', Mathf.Max(0, 30 - item.itemName.Length))));
			stringBuilder.Append(value);
			int num = Mathf.CeilToInt((float)item.creditsWorth * salePercentage);
			if (num > groupCredits)
			{
				stringBuilder.Append(string.Format("<color={0}>", "#8B0000"));
				stringBuilder.Append($"{num}$");
				stringBuilder.Append("</color>");
			}
			else
			{
				stringBuilder.Append($"{num}$");
			}
			if (salePercentage < 1f)
			{
				stringBuilder.Append(' ');
				stringBuilder.Append($"({(1f - salePercentage) * 100f:F0}% OFF)");
			}
			stringBuilder.Append(' ');
			stringBuilder.Append($"⇐{((CursorCounterElement)this).Counter}⇒");
			if (!((CursorElement)this).Active((CursorElement)(object)this))
			{
				stringBuilder.Append("</color>");
			}
			return stringBuilder.ToString();
		}
	}
	public class UnlockableCursorElement : CursorElement
	{
		private const int NAME_LENGTH = 30;

		private const char WHITE_SPACE = ' ';

		public TerminalNode node;

		public UnlockableItem unlockable;

		private Terminal terminal;

		public UnlockableCursorElement(TerminalNode node, Terminal terminal)
		{
			this.node = node;
			this.terminal = terminal;
			unlockable = StartOfRound.Instance.unlockablesList.unlockables[node.shipUnlockableID];
			((CursorElement)this).Active = (CursorElement x) => IsAvailableForPurchase(x);
		}

		private bool IsAvailableForPurchase(CursorElement x)
		{
			//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)
			int itemCost = node.itemCost;
			int result;
			if (terminal.groupCredits >= itemCost && (StartOfRound.Instance.inShipPhase || StartOfRound.Instance.shipHasLanded))
			{
				AnimatorStateInfo currentAnimatorStateInfo = StartOfRound.Instance.shipAnimator.GetCurrentAnimatorStateInfo(0);
				if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).tagHash == Animator.StringToHash("ShipIdle") && (terminal.ShipDecorSelection.Contains(node) || unlockable.alwaysInStock || (node.buyUnlockable && !((Object)(object)unlockable.shopSelectionNode == (Object)null))))
				{
					result = ((!unlockable.hasBeenUnlockedByPlayer && !unlockable.alreadyUnlocked) ? 1 : 0);
					goto IL_00c3;
				}
			}
			result = 0;
			goto IL_00c3;
			IL_00c3:
			return (byte)result != 0;
		}

		public override string GetText(int availableLength)
		{
			StringBuilder stringBuilder = new StringBuilder();
			int groupCredits = terminal.groupCredits;
			if (!((CursorElement)this).Active((CursorElement)(object)this))
			{
				if (unlockable.hasBeenUnlockedByPlayer || unlockable.alreadyUnlocked)
				{
					stringBuilder.Append("<color=#026440>");
				}
				else
				{
					stringBuilder.Append("<color=#66666666>");
				}
			}
			string value = ((node.creatureName.Length > 30) ? node.creatureName.Substring(0, 30) : (node.creatureName + new string(' ', Mathf.Max(0, 30 - node.creatureName.Length))));
			stringBuilder.Append(value);
			int num = Mathf.CeilToInt((float)node.itemCost);
			if (num > groupCredits)
			{
				stringBuilder.Append(string.Format("<color={0}>", "#8B0000"));
				stringBuilder.Append($"{num}$");
				stringBuilder.Append("</color>");
			}
			else
			{
				stringBuilder.Append($"{num}$");
			}
			if (!((CursorElement)this).Active((CursorElement)(object)this))
			{
				stringBuilder.Append("</color>");
			}
			return stringBuilder.ToString();
		}
	}
}
namespace InteractiveStore.UI.Application
{
	internal class StoreApplication : CounterPageApplication<CursorOutputElement<int>>
	{
		private const string SCREEN_TITLE = "The Company Store";

		private const string INITIAL_SCREEN_DESCRIPTION = "Select the amount of items you wish to purchase from each entry.";

		private const string COLORED_OUTPUT_ITEM_SCREEN_FORMAT = "<color={0}>{1}/{2}</color>";

		private const string OUTPUT_SCREEN_ITEM_FORMAT = "{0}/{1}";

		private const string OUTPUT_SCREEN_CREDIT_FORMAT = "{0}$";

		private const string COLORED_OUTPUT_SCREEN_CREDIT_FORMAT = "<color={0}>{1}$</color>";

		private const string CONFIRM_PURCHASE_FORMAT = "Do you wish to purchase the selected {0} items for {1}$ ? \n {2}";

		private const string PURCHASE_LISTING_FORMAT = "{0}x {1} ({2}$)\n";

		private const string NO_ITEMS_SELECTED_ERROR = "No items were selected for purchasing...";

		private const string NOT_ENOUGH_CREDITS_ERROR = "You do not have enough Company Credits to purchase the selected items...";

		private const string MAXIMUM_CAPACITY_ERROR = "The amount of items selected and already purchased surpasses the maximum capacity of the item dropship...";

		private Item[] buyableItems = null;

		private int[] salePercentages = null;

		private CursorOutputElement<int>[] itemCursorElements = null;

		private const int PURCHASE_AUDIO_SYNCED_INDEX = 0;

		protected override int GetEntriesPerPage<K>(K[] entries)
		{
			return 10;
		}

		public override void Initialization()
		{
			buyableItems = ((TerminalApplication)this).terminal.buyableItemsList;
			salePercentages = ((TerminalApplication)this).terminal.itemSalesPercentages;
			itemCursorElements = new CursorOutputElement<int>[buyableItems.Length];
			int num = 0;
			(Item[][], BaseCursorMenu<CursorOutputElement<int>>[], IScreen[]) pageEntries = ((PageApplication<CursorOutputElement<int>>)(object)this).GetPageEntries<Item>(buyableItems);
			Item[][] item = pageEntries.Item1;
			BaseCursorMenu<CursorOutputElement<int>>[] cursorMenus = pageEntries.Item2;
			IScreen[] screens = pageEntries.Item3;
			for (int i = 0; i < item.Length; i++)
			{
				Item[] array = item[i];
				CursorOutputElement<int>[] array2 = new CursorOutputElement<int>[array.Length];
				cursorMenus[i] = (BaseCursorMenu<CursorOutputElement<int>>)(object)CursorMenu<CursorOutputElement<int>>.Create(0, '>', array2, new Func<CursorOutputElement<int>, CursorOutputElement<int>, int>[3] { CompareName, CompareDescendingPrice, CompareAscendingPrice });
				cursorMenus[i].sortingIndex = -1;
				BaseCursorMenu<CursorOutputElement<int>> val = cursorMenus[i];
				ITextElement[] elements = (ITextElement[])(object)new ITextElement[3]
				{
					(ITextElement)TextElement.Create("Select the amount of items you wish to purchase from each entry."),
					(ITextElement)TextElement.Create(" "),
					(ITextElement)val
				};
				screens[i] = (IScreen)(object)new BoxedOutputScreen<int, string>
				{
					Title = "The Company Store",
					elements = elements,
					Input = () => ApplyInputFunction(),
					Output = (int x) => ApplyOutputFunction(x)
				};
				for (int j = 0; j < array.Length; j++)
				{
					Item val2 = array[j];
					if ((Object)(object)val2 == (Object)null)
					{
						continue;
					}
					int num2 = j + i * array.Length;
					int pageIndex = i;
					array2[j] = new ItemCursorElement(buyableItems[num2], (float)salePercentages[num2] / 100f, delegate
					{
						TryBuySelectedItems(delegate
						{
							((BaseInteractiveApplication<CursorOutputElement<int>>)(object)this).SwitchScreen(screens[pageIndex], cursorMenus[pageIndex], true);
						});
					}, ((TerminalApplication)this).terminal);
					itemCursorElements[num++] = array2[j];
				}
			}
			((PageApplication<CursorOutputElement<int>>)(object)this).currentPage = ((PageApplication<CursorOutputElement<int>>)(object)this).initialPage;
			((BaseInteractiveApplication<CursorOutputElement<int>>)(object)this).currentCursorMenu = ((PageApplication<CursorOutputElement<int>>)(object)this).initialPage.GetCurrentCursorMenu();
			((TerminalApplication)this).currentScreen = ((PageElement)((PageApplication<CursorOutputElement<int>>)(object)this).initialPage).GetCurrentScreen();
		}

		private int CompareName(CursorElement cursor1, CursorElement cursor2)
		{
			if (cursor1 == null)
			{
				return 1;
			}
			if (cursor2 == null)
			{
				return -1;
			}
			ItemCursorElement itemCursorElement = cursor1 as ItemCursorElement;
			ItemCursorElement itemCursorElement2 = cursor2 as ItemCursorElement;
			string itemName = itemCursorElement.item.itemName;
			string itemName2 = itemCursorElement2.item.itemName;
			return itemName.CompareTo(itemName2);
		}

		private int CompareDescendingPrice(CursorElement cursor1, CursorElement cursor2)
		{
			if (cursor1 == null)
			{
				return 1;
			}
			if (cursor2 == null)
			{
				return -1;
			}
			ItemCursorElement itemCursorElement = cursor1 as ItemCursorElement;
			ItemCursorElement itemCursorElement2 = cursor2 as ItemCursorElement;
			int creditsWorth = itemCursorElement.item.creditsWorth;
			int creditsWorth2 = itemCursorElement2.item.creditsWorth;
			return creditsWorth.CompareTo(creditsWorth2);
		}

		private int CompareAscendingPrice(CursorElement cursor1, CursorElement cursor2)
		{
			if (cursor1 == null)
			{
				return 1;
			}
			if (cursor2 == null)
			{
				return -1;
			}
			ItemCursorElement itemCursorElement = cursor1 as ItemCursorElement;
			ItemCursorElement itemCursorElement2 = cursor2 as ItemCursorElement;
			int creditsWorth = itemCursorElement.item.creditsWorth;
			int creditsWorth2 = itemCursorElement2.item.creditsWorth;
			return creditsWorth2.CompareTo(creditsWorth);
		}

		private string ApplyOutputFunction(int x)
		{
			StringBuilder stringBuilder = new StringBuilder();
			int num = 0;
			for (int i = 0; i < itemCursorElements.Length; i++)
			{
				ItemCursorElement itemCursorElement = itemCursorElements[i] as ItemCursorElement;
				int counter = ((CursorCounterElement)itemCursorElement).Counter;
				if (counter != 0)
				{
					num += counter;
				}
			}
			if (num + ((TerminalApplication)this).terminal.numberOfItemsInDropship == 12)
			{
				stringBuilder.Append(string.Format("<color={0}>{1}/{2}</color>", "#FFFF00", num + ((TerminalApplication)this).terminal.numberOfItemsInDropship, 12));
			}
			else if (num + ((TerminalApplication)this).terminal.numberOfItemsInDropship > 12)
			{
				stringBuilder.Append(string.Format("<color={0}>{1}/{2}</color>", "#8B0000", num + ((TerminalApplication)this).terminal.numberOfItemsInDropship, 12));
			}
			else
			{
				stringBuilder.Append($"{num + ((TerminalApplication)this).terminal.numberOfItemsInDropship}/{12}");
			}
			stringBuilder.Append(' ');
			if (((TerminalApplication)this).terminal.groupCredits < x)
			{
				stringBuilder.Append(string.Format("<color={0}>{1}$</color>", "#8B0000", x));
			}
			else
			{
				stringBuilder.Append($"{x}$");
			}
			int sortingIndex = ((BaseInteractiveApplication<CursorOutputElement<int>>)(object)this).currentCursorMenu.sortingIndex;
			if (1 == 0)
			{
			}
			string text = sortingIndex switch
			{
				0 => "Sort: Alphabetical [" + InputActionRebindingExtensions.GetBindingDisplayString(InputUtils_Compat.ChangeApplicationSortingKey, (DisplayStringOptions)0, (string)null) + "]", 
				1 => "Sort: Price (Des.) [" + InputActionRebindingExtensions.GetBindingDisplayString(InputUtils_Compat.ChangeApplicationSortingKey, (DisplayStringOptions)0, (string)null) + "]", 
				2 => "Sort: Price (Asc.) [" + InputActionRebindingExtensions.GetBindingDisplayString(InputUtils_Compat.ChangeApplicationSortingKey, (DisplayStringOptions)0, (string)null) + "]", 
				_ => "Sort: None [" + InputActionRebindingExtensions.GetBindingDisplayString(InputUtils_Compat.ChangeApplicationSortingKey, (DisplayStringOptions)0, (string)null) + "]", 
			};
			if (1 == 0)
			{
			}
			string text2 = text;
			return text2 + "|" + stringBuilder.ToString();
		}

		private void TryBuySelectedItems(Action backAction)
		{
			int totalItems = 0;
			int totalCost = 0;
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < itemCursorElements.Length; i++)
			{
				ItemCursorElement itemCursorElement = itemCursorElements[i] as ItemCursorElement;
				int counter = ((CursorCounterElement)itemCursorElement).Counter;
				if (counter != 0)
				{
					totalItems += counter;
					totalCost += ((CursorOutputElement<int>)itemCursorElement).ApplyFunction();
					stringBuilder.Append($"{((CursorCounterElement)itemCursorElement).Counter}x {itemCursorElement.item.itemName} ({((CursorOutputElement<int>)itemCursorElement).ApplyFunction()}$)\n");
				}
			}
			if (totalItems <= 0)
			{
				ErrorMessage("The Company Store", "No items were selected for purchasing...", backAction, "");
				return;
			}
			if (((TerminalApplication)this).terminal.groupCredits < totalCost)
			{
				ErrorMessage("The Company Store", "You do not have enough Company Credits to purchase the selected items...", backAction, "");
				return;
			}
			if (((TerminalApplication)this).terminal.numberOfItemsInDropship + totalItems > 12)
			{
				ErrorMessage("The Company Store", "The amount of items selected and already purchased surpasses the maximum capacity of the item dropship...", backAction, "");
				return;
			}
			Confirm("The Company Store", $"Do you wish to purchase the selected {totalItems} items for {totalCost}$ ? \n {stringBuilder.ToString()}", delegate
			{
				PurchaseSelectedItems(totalItems, totalCost, backAction);
			}, backAction);
		}

		private void PurchaseSelectedItems(int totalItems, int totalCost, Action backAction)
		{
			((TerminalApplication)this).terminal.groupCredits = Mathf.Clamp(((TerminalApplication)this).terminal.groupCredits - totalCost, 0, 10000000);
			while (totalItems > 0)
			{
				for (int i = 0; i < itemCursorElements.Length; i++)
				{
					if (totalItems <= 0)
					{
						break;
					}
					if (!(itemCursorElements[i] is ItemCursorElement itemCursorElement))
					{
						continue;
					}
					int num = ((CursorCounterElement)itemCursorElement).Counter;
					if (num != 0)
					{
						while (num > 0)
						{
							((TerminalApplication)this).terminal.orderedItemsFromTerminal.Add(i);
							Terminal terminal = ((TerminalApplication)this).terminal;
							terminal.numberOfItemsInDropship++;
							num--;
							totalItems--;
						}
						((CursorCounterElement)itemCursorElement).Counter = 0;
					}
				}
			}
			((TerminalApplication)this).terminal.PlayTerminalAudioServerRpc(0);
			if (!((NetworkBehaviour)((TerminalApplication)this).terminal).IsServer)
			{
				((TerminalApplication)this).terminal.SyncBoughtItemsWithServer(((TerminalApplication)this).terminal.orderedItemsFromTerminal.ToArray(), ((TerminalApplication)this).terminal.numberOfItemsInDropship);
			}
			else
			{
				((TerminalApplication)this).terminal.SyncGroupCreditsClientRpc(((TerminalApplication)this).terminal.groupCredits, ((TerminalApplication)this).terminal.numberOfItemsInDropship);
			}
			backAction();
		}

		private int ApplyInputFunction()
		{
			int num = 0;
			for (int i = 0; i < itemCursorElements.Length; i++)
			{
				num += itemCursorElements[i].ApplyFunction();
			}
			return num;
		}

		protected void Confirm(string title, string description, Action confirmAction, Action declineAction, string additionalMessage = "")
		{
			CursorOutputElement<int>[] array = new CursorOutputElement<int>[2]
			{
				CursorOutputElement<int>.Create("Confirm", "", confirmAction, 0, (Func<int, int>)null, (Func<CursorElement, bool>)null, true, false),
				CursorOutputElement<int>.Create("Cancel", "", declineAction, 0, (Func<int, int>)null, (Func<CursorElement, bool>)null, true, false)
			};
			CursorMenu<CursorOutputElement<int>> val = CursorMenu<CursorOutputElement<int>>.Create(0, '>', array, (Func<CursorOutputElement<int>, CursorOutputElement<int>, int>[])null);
			ITextElement[] array2 = (ITextElement[])(object)new ITextElement[4]
			{
				(ITextElement)TextElement.Create(description),
				(ITextElement)TextElement.Create(" "),
				(ITextElement)TextElement.Create(additionalMessage),
				(ITextElement)val
			};
			IScreen val2 = (IScreen)(object)BoxedScreen.Create(title, array2);
			((BaseInteractiveApplication<CursorOutputElement<int>>)(object)this).SwitchScreen(val2, (BaseCursorMenu<CursorOutputElement<int>>)(object)val, false);
		}

		protected void ErrorMessage(string title, string description, Action backAction, string error)
		{
			CursorOutputElement<int>[] array = new CursorOutputElement<int>[1] { CursorOutputElement<int>.Create("Back", "", backAction, 0, (Func<int, int>)null, (Func<CursorElement, bool>)null, true, false) };
			CursorMenu<CursorOutputElement<int>> val = CursorMenu<CursorOutputElement<int>>.Create(0, '>', array, (Func<CursorOutputElement<int>, CursorOutputElement<int>, int>[])null);
			ITextElement[] array2 = (ITextElement[])(object)new ITextElement[5]
			{
				(ITextElement)TextElement.Create(description),
				(ITextElement)TextElement.Create(" "),
				(ITextElement)TextElement.Create(error),
				(ITextElement)TextElement.Create(" "),
				(ITextElement)val
			};
			IScreen val2 = (IScreen)(object)BoxedScreen.Create(title, array2);
			((BaseInteractiveApplication<CursorOutputElement<int>>)(object)this).SwitchScreen(val2, (BaseCursorMenu<CursorOutputElement<int>>)(object)val, false);
		}
	}
	internal class UnlockableStoreApplication : PageApplication<CursorElement>
	{
		private const string SCREEN_TITLE = "The Company Store";

		private const string INITIAL_SCREEN_DESCRIPTION = "Select the items you wish to purchase.";

		private const string CONFIRM_PURCHASE_FORMAT = "Do you wish to purchase the selected item for {0}$ ? \n{1}";

		private const string NOT_ENOUGH_CREDITS_ERROR = "You do not have enough Company Credits to purchase the selected items...";

		private const string NO_PURCHASE_DURING_FLIGHT = "You cannot purchase furniture items while landing/departing...";

		private const string UNLOCKABLE_NOT_AVAILABLE = "This item is currently not available for purchase...";

		private const string UNLOCKABLE_ALREADY_PURCHASED = "This item was already purchased for your assigned ship...";

		private const int PURCHASE_AUDIO_SYNCED_INDEX = 0;

		protected override int GetEntriesPerPage<K>(K[] entries)
		{
			return 10;
		}

		public override void Initialization()
		{
			List<TerminalNode> list = new List<TerminalNode>(((TerminalApplication)this).terminal.ShipDecorSelection);
			UnlockableItem val = null;
			TerminalKeyword[] allKeywords = ((TerminalApplication)this).terminal.terminalNodes.allKeywords;
			foreach (TerminalKeyword val2 in allKeywords)
			{
				if (val2.compatibleNouns != null)
				{
					CompatibleNoun[] compatibleNouns = val2.compatibleNouns;
					foreach (CompatibleNoun val3 in compatibleNouns)
					{
						TerminalNode result = val3.result;
						if (!((Object)(object)result == (Object)null) && result.shipUnlockableID >= 0)
						{
							val = StartOfRound.Instance.unlockablesList.unlockables[result.shipUnlockableID];
							if (val.alwaysInStock && !list.Contains(result))
							{
								list.Add(result);
							}
						}
					}
				}
				TerminalNode specialKeywordResult = val2.specialKeywordResult;
				if (!((Object)(object)specialKeywordResult == (Object)null) && specialKeywordResult.shipUnlockableID >= 0)
				{
					val = StartOfRound.Instance.unlockablesList.unlockables[specialKeywordResult.shipUnlockableID];
					if (val.alwaysInStock && !list.Contains(specialKeywordResult))
					{
						list.Add(specialKeywordResult);
					}
				}
			}
			TerminalNode[] array = list.ToArray();
			(TerminalNode[][], BaseCursorMenu<CursorElement>[], IScreen[]) pageEntries = base.GetPageEntries<TerminalNode>(array);
			TerminalNode[][] item = pageEntries.Item1;
			BaseCursorMenu<CursorElement>[] cursorMenus = pageEntries.Item2;
			IScreen[] screens = pageEntries.Item3;
			for (int k = 0; k < item.Length; k++)
			{
				TerminalNode[] array2 = item[k];
				CursorElement[] array3 = (CursorElement[])(object)new CursorElement[array2.Length];
				cursorMenus[k] = (BaseCursorMenu<CursorElement>)(object)CursorMenu<CursorElement>.Create(0, '>', array3, new Func<CursorElement, CursorElement, int>[3] { CompareName, CompareDescendingPrice, CompareAscendingPrice });
				cursorMenus[k].sortingIndex = -1;
				BaseCursorMenu<CursorElement> val4 = cursorMenus[k];
				ITextElement[] elements = (ITextElement[])(object)new ITextElement[3]
				{
					(ITextElement)TextElement.Create("Select the items you wish to purchase."),
					(ITextElement)TextElement.Create(" "),
					(ITextElement)val4
				};
				screens[k] = (IScreen)(object)new BoxedOutputScreen<int, string>
				{
					Title = "The Company Store",
					elements = elements,
					Input = () => ApplyInputFunction(),
					Output = (int x) => ApplyOutputFunction(x)
				};
				for (int l = 0; l < array2.Length; l++)
				{
					TerminalNode val5 = array2[l];
					if ((Object)(object)val5 == (Object)null)
					{
						continue;
					}
					int num = l + k * array2.Length;
					int pageIndex = k;
					int num2 = l;
					UnlockableCursorElement cursor = new UnlockableCursorElement(array[num], ((TerminalApplication)this).terminal);
					((CursorElement)cursor).Action = delegate
					{
						TryBuySelectedItem((CursorElement)(object)cursor, delegate
						{
							((BaseInteractiveApplication<CursorElement>)(object)this).SwitchScreen(screens[pageIndex], cursorMenus[pageIndex], true);
						});
					};
					array3[l] = (CursorElement)(object)cursor;
				}
			}
			base.currentPage = base.initialPage;
			((BaseInteractiveApplication<CursorElement>)(object)this).currentCursorMenu = base.initialPage.GetCurrentCursorMenu();
			((TerminalApplication)this).currentScreen = ((PageElement)base.initialPage).GetCurrentScreen();
		}

		private int CompareName(CursorElement cursor1, CursorElement cursor2)
		{
			if (cursor1 == null)
			{
				return 1;
			}
			if (cursor2 == null)
			{
				return -1;
			}
			UnlockableCursorElement unlockableCursorElement = cursor1 as UnlockableCursorElement;
			UnlockableCursorElement unlockableCursorElement2 = cursor2 as UnlockableCursorElement;
			string creatureName = unlockableCursorElement.node.creatureName;
			string creatureName2 = unlockableCursorElement2.node.creatureName;
			return creatureName.CompareTo(creatureName2);
		}

		private int CompareDescendingPrice(CursorElement cursor1, CursorElement cursor2)
		{
			if (cursor1 == null)
			{
				return 1;
			}
			if (cursor2 == null)
			{
				return -1;
			}
			UnlockableCursorElement unlockableCursorElement = cursor1 as UnlockableCursorElement;
			UnlockableCursorElement unlockableCursorElement2 = cursor2 as UnlockableCursorElement;
			int itemCost = unlockableCursorElement.node.itemCost;
			int itemCost2 = unlockableCursorElement2.node.itemCost;
			return itemCost.CompareTo(itemCost2);
		}

		private int CompareAscendingPrice(CursorElement cursor1, CursorElement cursor2)
		{
			if (cursor1 == null)
			{
				return 1;
			}
			if (cursor2 == null)
			{
				return -1;
			}
			UnlockableCursorElement unlockableCursorElement = cursor1 as UnlockableCursorElement;
			UnlockableCursorElement unlockableCursorElement2 = cursor2 as UnlockableCursorElement;
			int itemCost = unlockableCursorElement.node.itemCost;
			int itemCost2 = unlockableCursorElement2.node.itemCost;
			return itemCost2.CompareTo(itemCost);
		}

		private string ApplyOutputFunction(int x)
		{
			StringBuilder stringBuilder = new StringBuilder();
			int sortingIndex = ((BaseInteractiveApplication<CursorElement>)(object)this).currentCursorMenu.sortingIndex;
			if (1 == 0)
			{
			}
			string text = sortingIndex switch
			{
				0 => "Sort: Alphabetical [" + InputActionRebindingExtensions.GetBindingDisplayString(InputUtils_Compat.ChangeApplicationSortingKey, (DisplayStringOptions)0, (string)null) + "]", 
				1 => "Sort: Price (Des.) [" + InputActionRebindingExtensions.GetBindingDisplayString(InputUtils_Compat.ChangeApplicationSortingKey, (DisplayStringOptions)0, (string)null) + "]", 
				2 => "Sort: Price (Asc.) [" + InputActionRebindingExtensions.GetBindingDisplayString(InputUtils_Compat.ChangeApplicationSortingKey, (DisplayStringOptions)0, (string)null) + "]", 
				_ => "Sort: None [" + InputActionRebindingExtensions.GetBindingDisplayString(InputUtils_Compat.ChangeApplicationSortingKey, (DisplayStringOptions)0, (string)null) + "]", 
			};
			if (1 == 0)
			{
			}
			string text2 = text;
			return text2 ?? "";
		}

		private void TryBuySelectedItem(CursorElement node, Action backAction)
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder stringBuilder = new StringBuilder();
			UnlockableCursorElement cursor = node as UnlockableCursorElement;
			int totalCost = cursor.node.itemCost;
			if (((TerminalApplication)this).terminal.groupCredits < totalCost)
			{
				((InteractiveTerminalApplication<CursorElement>)(object)this).ErrorMessage("The Company Store", "You do not have enough Company Credits to purchase the selected items...", backAction, "");
				return;
			}
			if (StartOfRound.Instance.inShipPhase || StartOfRound.Instance.shipHasLanded)
			{
				AnimatorStateInfo currentAnimatorStateInfo = StartOfRound.Instance.shipAnimator.GetCurrentAnimatorStateInfo(0);
				if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).tagHash == Animator.StringToHash("ShipIdle"))
				{
					UnlockableItem unlockable = cursor.unlockable;
					if (!((TerminalApplication)this).terminal.ShipDecorSelection.Contains(cursor.node) && !unlockable.alwaysInStock && (!cursor.node.buyUnlockable || (Object)(object)unlockable.shopSelectionNode == (Object)null))
					{
						((InteractiveTerminalApplication<CursorElement>)(object)this).ErrorMessage("The Company Store", "This item is currently not available for purchase...", backAction, "");
						return;
					}
					if (unlockable.hasBeenUnlockedByPlayer || unlockable.alreadyUnlocked)
					{
						((InteractiveTerminalApplication<CursorElement>)(object)this).ErrorMessage("The Company Store", "This item was already purchased for your assigned ship...", backAction, "");
						return;
					}
					((InteractiveTerminalApplication<CursorElement>)(object)this).Confirm("The Company Store", $"Do you wish to purchase the selected item for {totalCost}$ ? \n{stringBuilder.ToString()}", (Action)delegate
					{
						PurchaseSelectedItems(cursor.node, totalCost, backAction);
					}, backAction, "");
					return;
				}
			}
			((InteractiveTerminalApplication<CursorElement>)(object)this).ErrorMessage("The Company Store", "You cannot purchase furniture items while landing/departing...", backAction, "");
		}

		private void PurchaseSelectedItems(TerminalNode node, int totalCost, Action backAction)
		{
			((TerminalApplication)this).terminal.groupCredits = Mathf.Clamp(((TerminalApplication)this).terminal.groupCredits - totalCost, 0, 10000000);
			((TerminalApplication)this).terminal.PlayTerminalAudioServerRpc(0);
			StartOfRound.Instance.BuyShipUnlockableServerRpc(node.shipUnlockableID, ((TerminalApplication)this).terminal.groupCredits);
			backAction();
		}

		private int ApplyInputFunction()
		{
			return 0;
		}
	}
}
namespace InteractiveStore.Configuration
{
	public class ModConfiguration
	{
		public ConfigEntry<string> ItemStoreCommandList { get; set; }

		public ConfigEntry<bool> ItemStoreCommandCaseSensitive { get; set; }

		public ConfigEntry<string> DecorationStoreCommandList { get; set; }

		public ConfigEntry<bool> DecorationStoreCommandCaseSensitive { get; set; }

		public ModConfiguration(ConfigFile config)
		{
			string text = "Initialization";
			ItemStoreCommandList = config.Bind<string>(text, "Command Prompts for Item Store", "istore", "List of commands separated by a comma (') to access the interactive item store");
			ItemStoreCommandCaseSensitive = config.Bind<bool>(text, "Item Store Prompt Case Sensitivity", false, "Wether the letter case of the command prompts should be relevant or not to bring up the application");
			DecorationStoreCommandList = config.Bind<string>(text, "Command Prompts for Decoration/Ship Upgrade Store", "idecor", "List of commands separated by a comma (') to access the interactive decoration/upgrade store");
			DecorationStoreCommandCaseSensitive = config.Bind<bool>(text, "Decoration Store Prompt Case Sensitivity", false, "Wether the letter case of the command prompts should be relevant or not to bring up the application");
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace InteractiveStore.NetcodePatcher
{
	[AttributeUsage(AttributeTargets.Module)]
	internal class NetcodePatchedAssemblyAttribute : Attribute
	{
	}
}