Decompiled source of FXDSP v1.0.0

plugins/FXDSP/FXDSP.dll

Decompiled a day ago
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using ABN;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using FXDSP.Configuration;
using FXDSP.Core;
using FXDSP.Persistence;
using FXDSP.Runtime;
using FXDSP.UI;
using HarmonyLib;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;
using crecheng.DSPModSave;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("FXDSP")]
[assembly: AssemblyProduct("FXDSP")]
[assembly: AssemblyDescription("Item-backed trading, building exchange and logistics delivery for Dyson Sphere Program.")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: ComVisible(false)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace FXDSP
{
	[BepInPlugin("dspfx.mod", "FXDSP", "1.0.0")]
	[BepInDependency("crecheng.DSPModSave", "1.2.2")]
	public sealed class Plugin : BaseUnityPlugin, IModCanSave
	{
		private const string RuntimeOwnerKey = "FXDSP.PluginRuntimeOwner.v1";

		private readonly string _owner = Guid.NewGuid().ToString("N");

		private Harmony _harmony;

		private ModSettings _settings;

		private MarketSession _session;

		private MarketWindow _window;

		private UIMessageBox _achievementPopup;

		private PositionHud _hud;

		private DeliveryService _delivery;

		private bool _useDelivery;

		private bool _registered;

		private bool _saveWarningShown;

		private string _notice = "";

		private int _selectedLeverage = 5;

		private int _selectedItemId = 99000001;

		private int _exchangeItemId = 2001;

		private int _exchangeTier = 1;

		private readonly List<MarketOption> _marketOptions = new List<MarketOption>();

		private readonly Dictionary<int, PositionSettlement> _shownSettlements = new Dictionary<int, PositionSettlement>();

		internal static Plugin Active { get; private set; }

		internal bool BypassAbnormalityChecks
		{
			get
			{
				if (OwnsRuntime && _settings != null)
				{
					return _settings.BypassAbnormalityChecks.Value;
				}
				return false;
			}
		}

		private bool OwnsRuntime => object.Equals(AppDomain.CurrentDomain.GetData("FXDSP.PluginRuntimeOwner.v1"), _owner);

		private void Awake()
		{
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Expected O, but got Unknown
			try
			{
				AppDomain.CurrentDomain.SetData("FXDSP.PluginRuntimeOwner.v1", _owner);
				Active = this;
				ModLocalization.Update();
				_settings = new ModSettings(((BaseUnityPlugin)this).Config);
				_settings.VerboseLogging.SettingChanged += OnVerboseLoggingChanged;
				_session = new MarketSession();
				_delivery = new DeliveryService(_session);
				_window = new MarketWindow(GetSnapshot, GetPortfolio, Execute, _session.AcknowledgeIntroduction, () => _session.Achievements);
				_hud = new PositionHud(GetPortfolio, Execute, _window.ShowAllPositions, _window.ShowExchange, () => _settings.PositionHudMode.Value, delegate(int mode)
				{
					_settings.PositionHudMode.Value = mode;
				});
				_harmony = new Harmony("dspfx.mod.runtime." + Guid.NewGuid().ToString("N"));
				_harmony.PatchAll(typeof(Plugin).Assembly);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Local abnormality bypass: " + BypassAbnormalityChecks + ". Existing records retained; sandbox/account eligibility unchanged."));
				TryRegisterSaveHandler();
				TradeResearchState tradeResearchState = ResearchProgression.Read();
				_session.SetTradingFeeRate(tradeResearchState.TradingFee);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"FXDSP 1.0.0 loaded. F8: copper-margin market; F6: ScriptEngine reload.");
				if (_settings.VerboseLogging.Value)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Harmony owner: " + _harmony.Id));
				}
			}
			catch (Exception ex)
			{
				Cleanup();
				((BaseUnityPlugin)this).Logger.LogError((object)("FXDSP initialization failed: " + ex));
				throw;
			}
		}

		private void Update()
		{
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			if (!OwnsRuntime || _session == null)
			{
				return;
			}
			try
			{
				TryRegisterSaveHandler();
				ModLocalization.Update();
				TradeResearchState tradeResearchState = ResearchProgression.Read();
				_session.SetTradingFeeRate(tradeResearchState.TradingFee);
				if (GameMain.isRunning && GameMain.data != null && (Object)(object)GameMain.instance != (Object)null && !GameMain.instance.isMenuDemo)
				{
					ResourceMarketCatalog.GetOptions();
				}
				_session.Tick();
				_delivery.Tick();
				ShowNewSettlement();
				try
				{
					if (!GameMain.isRunning || GameMain.mainPlayer == null || !((Object)(object)GameMain.instance != (Object)null) || GameMain.instance.isMenuDemo)
					{
						_window.Close();
						_hud.Tick(visible: false);
						return;
					}
					KeyboardShortcut value;
					if (!tradeResearchState.Access)
					{
						value = _settings.WindowKey.Value;
						if (((KeyboardShortcut)(ref value)).IsDown() && !VFInput.inputing)
						{
							UIRealtimeTip.Popup(TextLocalization.Translate("请先研究“交易系统”:10 铁矿、10 铜矿。"), true, 0);
						}
						_window.Close();
						_hud.Tick(visible: false);
						return;
					}
					value = _settings.WindowKey.Value;
					if (((KeyboardShortcut)(ref value)).IsDown() && !VFInput.inputing)
					{
						_window.Toggle();
					}
					_window.Tick();
					_hud.Tick(!_window.HasSettlement);
					ShowAchievements();
				}
				catch (Exception ex)
				{
					_window.Close();
					_hud.Tick(visible: false);
					_notice = "交易窗口暂时无法创建,请查看日志后重试 F8。";
					((BaseUnityPlugin)this).Logger.LogError((object)("FXDSP window failed: " + ex));
				}
			}
			catch (Exception ex2)
			{
				_notice = "更新失败,请查看 BepInEx 日志。";
				((BaseUnityPlugin)this).Logger.LogError((object)("FXDSP update failed: " + ex2));
				((Behaviour)this).enabled = false;
				_window.Close();
				if (_hud != null)
				{
					_hud.Tick(visible: false);
				}
			}
		}

		private void ShowAchievements()
		{
			if (_session.CanAccessDelivery && _session.Achievements.Pending.Count != 0 && (!((Object)(object)_achievementPopup != (Object)null) || !((Component)_achievementPopup).gameObject.activeInHierarchy))
			{
				AchievementDefinition achievementDefinition = AchievementCatalog.Find(_session.Achievements.Pending[0]);
				_achievementPopup = UIMessageBox.Show(TextLocalization.Translate("成就达成 · " + achievementDefinition.Name), TextLocalization.Translate(achievementDefinition.Description), TextLocalization.Translate("知道了"), 0);
				_session.Achievements.AcknowledgeFirst();
				_session.PreserveForReload();
			}
		}

		private void TryRegisterSaveHandler()
		{
			if (!_registered && OwnsRuntime && DSPModSavePlugin.logger != null && Chainloader.PluginInfos.ContainsKey("crecheng.DSPModSave"))
			{
				DSPModSavePlugin.RemoveModSaveManually((BaseUnityPlugin)(object)this);
				DSPModSavePlugin.AddModSaveManually((BaseUnityPlugin)(object)this);
				_registered = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"FXDSP save handler registered.");
			}
		}

		private MarketSnapshot GetSnapshot(int quantity)
		{
			MarketSnapshot marketSnapshot = new MarketSnapshot();
			if (_session == null)
			{
				return marketSnapshot;
			}
			if (MarketCatalog.IsSelectable(_selectedItemId) && !_session.IsMarketEnabled(_selectedItemId))
			{
				MarginMarket marginMarket = _session.Markets.FirstOrDefault((MarginMarket candidate) => MarketCatalog.IsSelectable(candidate.State.ItemId) && MarketCatalog.Category(candidate.State.ItemId) == MarketCatalog.Category(_selectedItemId) && _session.IsMarketEnabled(candidate.State.ItemId));
				if (marginMarket != null)
				{
					_selectedItemId = marginMarket.State.ItemId;
				}
			}
			MarginMarket market = _session.GetMarket(_selectedItemId);
			TradeResearchState tradeResearchState = ResearchProgression.Read();
			marketSnapshot.Ready = ((Behaviour)this).enabled && OwnsRuntime && _registered && _session.CanTrade && !GameMain.isPaused && tradeResearchState.Access;
			marketSnapshot.ResourcesEditable = marketSnapshot.Ready;
			marketSnapshot.MarketEnabled = _session.IsMarketEnabled(_selectedItemId);
			marketSnapshot.Ready &= marketSnapshot.MarketEnabled;
			marketSnapshot.Status = (marketSnapshot.Ready ? _notice : _session.Status);
			if (marketSnapshot.ResourcesEditable && !marketSnapshot.MarketEnabled)
			{
				marketSnapshot.Status = (string.IsNullOrEmpty(_notice) ? "请选择品种" : _notice);
			}
			if (GameMain.isPaused)
			{
				marketSnapshot.Status = "游戏已暂停,交易与行情暂停。";
			}
			marketSnapshot.PersistenceStatus = (marketSnapshot.Ready ? "" : _session.Status);
			if (market == null)
			{
				return marketSnapshot;
			}
			marketSnapshot.ItemId = market.State.ItemId;
			marketSnapshot.ItemName = MarketCatalog.Name(marketSnapshot.ItemId);
			bool flag = marketSnapshot.ItemId == 99000001;
			ItemProto val = (((Object)(object)LDB.items == (Object)null || flag) ? null : ((ProtoSet<ItemProto>)(object)LDB.items).Select(marketSnapshot.ItemId));
			if (val != null)
			{
				marketSnapshot.ItemName = ((Proto)val).name;
				marketSnapshot.ItemIcon = val.iconSprite;
			}
			marketSnapshot.BackpackQuantity = ((!flag && marketSnapshot.MarketEnabled) ? PlayerInventory.Count(marketSnapshot.ItemId) : 0);
			marketSnapshot.CanUseDelivery = marketSnapshot.ItemId != 1099;
			marketSnapshot.UseDelivery = _useDelivery && marketSnapshot.CanUseDelivery;
			marketSnapshot.TransferAvailable = (marketSnapshot.UseDelivery ? _delivery.Available(marketSnapshot.ItemId).Count : ((flag || !marketSnapshot.MarketEnabled) ? ((BigInteger)0) : PlayerInventory.Available(marketSnapshot.ItemId)));
			marketSnapshot.DeliveryName = _delivery.BindingName(marketSnapshot.ItemId);
			marketSnapshot.DeliveryBound = _delivery.BoundPlatform(marketSnapshot.ItemId) != null;
			if (_marketOptions.Count == 0 && (Object)(object)LDB.items != (Object)null)
			{
				foreach (int itemId in MarketCatalog.ItemIds)
				{
					ItemProto val2 = ((itemId == 99000001) ? null : ((ProtoSet<ItemProto>)(object)LDB.items).Select(itemId));
					_marketOptions.Add(new MarketOption
					{
						ItemId = itemId,
						Name = MarketCatalog.Name(itemId),
						Icon = ((val2 == null) ? null : val2.iconSprite)
					});
				}
			}
			marketSnapshot.Markets = _marketOptions;
			marketSnapshot.ResourceOptions = ResourceMarketCatalog.GetOptions();
			foreach (MarketOption resourceOption in marketSnapshot.ResourceOptions)
			{
				resourceOption.Enabled = _session.IsMarketEnabled(resourceOption.ItemId);
				MarginMarket marginMarket2 = _session.FindMarket(resourceOption.ItemId);
				resourceOption.HasPosition = marginMarket2 != null && marginMarket2.Position != null;
			}
			marketSnapshot.BuildingCoinBalance = _session.GetMarket(99000001).State.Balance;
			if (flag)
			{
				marketSnapshot.ExchangeOffers = (from offer in BuildingExchangeCatalog.GetOffers()
					where offer.Tier == _exchangeTier
					select offer).ToArray();
				foreach (ExchangeOffer exchangeOffer in marketSnapshot.ExchangeOffers)
				{
					marketSnapshot.ExchangeInventory[exchangeOffer.ItemId] = PlayerInventory.Count(exchangeOffer.ItemId);
				}
				marketSnapshot.ExchangeTier = _exchangeTier;
				marketSnapshot.ExchangeUnlocked = tradeResearchState.CanExchange(_exchangeTier);
				marketSnapshot.ExchangeFeeRate = tradeResearchState.ExchangeFee;
				marketSnapshot.ExchangeItemId = _exchangeItemId;
				marketSnapshot.ExchangeBackpackQuantity = ((_exchangeItemId > 0) ? PlayerInventory.Count(_exchangeItemId) : 0);
			}
			marketSnapshot.AvailableBalance = market.State.Balance;
			marketSnapshot.Equity = market.Equity;
			marketSnapshot.UsedMargin = market.UsedMargin;
			marketSnapshot.UnrealizedPnL = market.UnrealizedPnL;
			marketSnapshot.RealizedPnL = market.State.RealizedPnL;
			marketSnapshot.NetPnL = market.NetPnL;
			marketSnapshot.SelectedLeverage = _selectedLeverage;
			marketSnapshot.Bid = (marketSnapshot.MarketEnabled ? market.Bid : 0m);
			marketSnapshot.Ask = (marketSnapshot.MarketEnabled ? market.Ask : 0m);
			marketSnapshot.FeeRate = market.FeeRate;
			marketSnapshot.Deposited = market.State.TotalDeposited;
			marketSnapshot.Withdrawn = market.State.TotalWithdrawn;
			marketSnapshot.ReturnRatio = AccountPerformance.ReturnRatio(marketSnapshot.RealizedPnL, marketSnapshot.Deposited, marketSnapshot.Withdrawn);
			if (marketSnapshot.MarketEnabled)
			{
				marketSnapshot.Candles = MarketCandles.Build(market.History);
			}
			marketSnapshot.RecentEvents = market.RecentLogs.Reverse().ToArray();
			MarginPosition position = market.Position;
			marketSnapshot.HasPosition = position != null;
			if (position != null)
			{
				marketSnapshot.PositionDirection = ((position.Side == PositionSide.Long) ? "做多" : "做空");
				marketSnapshot.PositionLeverage = position.Leverage;
				marketSnapshot.EntryPrice = position.EntryPrice;
				marketSnapshot.PositionMargin = position.Margin;
				marketSnapshot.PositionOpenTick = position.OpenTick;
				marketSnapshot.CurrentTick = GameMain.gameTick;
				marketSnapshot.LiquidationPrice = market.LiquidationPrice;
			}
			if (marketSnapshot.MarketEnabled && quantity >= 1 && quantity <= 100)
			{
				marketSnapshot.OrderMargin = market.MarginForAllocation(quantity, _selectedLeverage);
				if (marketSnapshot.OrderMargin > 0m)
				{
					marketSnapshot.OpenCost = market.OpenCost(marketSnapshot.OrderMargin, _selectedLeverage);
					marketSnapshot.OpenFee = market.OpenFee(marketSnapshot.OrderMargin, _selectedLeverage);
				}
			}
			return marketSnapshot;
		}

		private void Execute(MarketCommand command, int quantity)
		{
			switch (command)
			{
			case MarketCommand.UseBackpack:
			case MarketCommand.UseDelivery:
				_useDelivery = command == MarketCommand.UseDelivery;
				_notice = "";
				return;
			case MarketCommand.SelectExchangeTier:
				if (quantity >= 1 && quantity <= 5)
				{
					_exchangeTier = quantity;
					ExchangeOffer[] array = (from offer in BuildingExchangeCatalog.GetOffers()
						where offer.Tier == quantity
						select offer).ToArray();
					if (!array.Any((ExchangeOffer offer) => offer.ItemId == _exchangeItemId))
					{
						_exchangeItemId = ((array.Length != 0) ? array[0].ItemId : 0);
					}
					_notice = "";
				}
				return;
			case MarketCommand.SelectExchangeItem:
				BuildingExchangeCatalog.Find(quantity);
				_exchangeItemId = quantity;
				_notice = "";
				return;
			case MarketCommand.SelectMarket:
				if (MarketCatalog.Contains(quantity))
				{
					_selectedItemId = quantity;
					_notice = "";
					return;
				}
				break;
			}
			if (!OwnsRuntime || !_registered || !_session.CanTrade || GameMain.isPaused || !((Behaviour)this).enabled)
			{
				_notice = "当前不能交易,请先进入存档并检查市场状态。";
				return;
			}
			try
			{
				TradeResearchState tradeResearchState = ResearchProgression.Read();
				tradeResearchState.RequireAccess();
				_session.SetTradingFeeRate(tradeResearchState.TradingFee);
				MarginMarket market = _session.GetMarket(_selectedItemId);
				if ((command == MarketCommand.Deposit || command == MarketCommand.Withdraw || command == MarketCommand.OpenLong || command == MarketCommand.OpenShort) && !_session.IsMarketEnabled(_selectedItemId))
				{
					throw new InvalidOperationException("请先启用该市场。");
				}
				switch (command)
				{
				case MarketCommand.EnableResource:
				case MarketCommand.DisableResource:
					ResourceMarketCatalog.RequireResource(quantity);
					_session.SetResourceEnabled(quantity, command == MarketCommand.EnableResource);
					_notice = "";
					break;
				case MarketCommand.Deposit:
					_notice = ((_useDelivery && _selectedItemId != 1099) ? _delivery.Transfer(market, quantity, deposit: true) : PlayerInventory.Deposit(market, quantity));
					break;
				case MarketCommand.Withdraw:
					_notice = ((_useDelivery && _selectedItemId != 1099) ? _delivery.Transfer(market, quantity, deposit: false) : PlayerInventory.Withdraw(market, quantity));
					break;
				case MarketCommand.OpenLong:
					_notice = market.Open(PositionSide.Long, market.MarginForAllocation(quantity, _selectedLeverage), _selectedLeverage, quantity);
					break;
				case MarketCommand.OpenShort:
					_notice = market.Open(PositionSide.Short, market.MarginForAllocation(quantity, _selectedLeverage), _selectedLeverage, quantity);
					break;
				case MarketCommand.ClosePosition:
					_notice = market.Close();
					break;
				case MarketCommand.CloseMarketPosition:
				case MarketCommand.CloseHudPosition:
					_notice = (_session.ClosePosition(quantity) ? "持仓已平仓。" : "该市场当前空仓。");
					if (command == MarketCommand.CloseHudPosition)
					{
						_shownSettlements[quantity] = _session.GetMarket(quantity).LastSettlement;
					}
					break;
				case MarketCommand.CloseAllPositions:
					_notice = "已平仓 " + _session.CloseAllPositions() + " 项持仓。";
					break;
				case MarketCommand.BuyBuilding:
				case MarketCommand.SellBuilding:
				{
					ExchangeOffer exchangeOffer = BuildingExchangeCatalog.Find(_exchangeItemId);
					tradeResearchState.RequireExchange(exchangeOffer.Tier);
					MarginMarket market2 = _session.GetMarket(99000001);
					_notice = ((command == MarketCommand.BuyBuilding) ? PlayerInventory.BuyBuilding(market2, exchangeOffer.ItemId, quantity, exchangeOffer.UnitValue, tradeResearchState.ExchangeFee) : PlayerInventory.SellBuilding(market2, exchangeOffer.ItemId, quantity, exchangeOffer.UnitValue, tradeResearchState.ExchangeFee));
					break;
				}
				case MarketCommand.ChangeLeverage:
					if (!MarginMarket.IsAllowedLeverage(quantity))
					{
						throw new InvalidOperationException("不支持该杠杆。");
					}
					_selectedLeverage = quantity;
					_notice = "";
					break;
				default:
					throw new InvalidOperationException("未知交易指令。");
				}
				_session.PreserveForReload();
				ShowNewSettlement();
				if (_settings.VerboseLogging.Value)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)_notice);
				}
			}
			catch (InvalidOperationException ex)
			{
				_notice = ex.Message;
			}
			catch (OverflowException)
			{
				_notice = "数量或金额超出安全数值范围,本次操作取消。";
			}
			catch (Exception ex3)
			{
				_notice = "操作异常,交易已停用,请保留日志。";
				((BaseUnityPlugin)this).Logger.LogError((object)("FXDSP command failed: " + ex3));
				((Behaviour)this).enabled = false;
			}
		}

		private PortfolioSnapshot GetPortfolio()
		{
			PortfolioSnapshot portfolioSnapshot = new PortfolioSnapshot();
			if (_session == null)
			{
				return portfolioSnapshot;
			}
			portfolioSnapshot.Ready = ((Behaviour)this).enabled && OwnsRuntime && _registered && _session.CanTrade;
			List<PositionSnapshot> list = new List<PositionSnapshot>();
			foreach (MarginMarket market in _session.Markets)
			{
				MarginPosition position = market.Position;
				if (position != null)
				{
					int itemId = market.State.ItemId;
					ItemProto val = ((itemId == 99000001 || (Object)(object)LDB.items == (Object)null) ? null : ((ProtoSet<ItemProto>)(object)LDB.items).Select(itemId));
					list.Add(new PositionSnapshot
					{
						ItemId = itemId,
						Name = MarketCatalog.Name(itemId),
						Icon = ((val == null) ? null : val.iconSprite),
						Direction = ((position.Side == PositionSide.Long) ? "做多" : "做空"),
						Leverage = position.Leverage,
						Margin = position.Margin,
						EntryPrice = position.EntryPrice,
						CurrentPrice = market.MidPrice,
						LiquidationPrice = market.LiquidationPrice,
						UnrealizedPnL = market.UnrealizedPnL,
						OpenTick = position.OpenTick,
						CurrentTick = GameMain.gameTick
					});
				}
			}
			portfolioSnapshot.Positions = list;
			return portfolioSnapshot;
		}

		private void ShowNewSettlement()
		{
			if (!_session.CanTrade)
			{
				return;
			}
			foreach (MarginMarket market in _session.Markets)
			{
				PositionSettlement lastSettlement = market.LastSettlement;
				if (lastSettlement != null && (!_shownSettlements.TryGetValue(market.State.ItemId, out var value) || lastSettlement != value))
				{
					_shownSettlements[market.State.ItemId] = lastSettlement;
					_notice = "";
					_window.ShowSettlement(lastSettlement);
				}
			}
		}

		internal void ConsumeEscape()
		{
			if (!OwnsRuntime || _window == null)
			{
				return;
			}
			try
			{
				_window.ConsumeEscape();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("FXDSP input failed: " + ex));
			}
		}

		internal bool AllowSave()
		{
			if (!OwnsRuntime || _session == null || GameMain.data == null || (Object)(object)GameMain.instance == (Object)null || GameMain.instance.isMenuDemo)
			{
				return true;
			}
			_session.Tick();
			_delivery.Tick();
			if (_session.CanSave)
			{
				return true;
			}
			if (!_saveWarningShown)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"FXDSP has not received this save's account state. Saving is blocked to preserve its sidecar. Return to the main menu and reload the save with FXDSP loaded.");
				_saveWarningShown = true;
			}
			_notice = "市场尚未接入当前存档,请返回主菜单重新读档后再保存。";
			return false;
		}

		public void Export(BinaryWriter writer)
		{
			_session.Export(writer);
		}

		public void Import(BinaryReader reader)
		{
			_session.Import(reader);
			_shownSettlements.Clear();
			_window.ResetNotifications();
			_notice = "";
			_saveWarningShown = false;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("FXDSP account import: " + _session.Status));
		}

		public void IntoOtherSave()
		{
			_session.IntoOtherSave();
			_shownSettlements.Clear();
			_window.ResetNotifications();
			_notice = "";
			_saveWarningShown = false;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("FXDSP new account: " + _session.Status));
		}

		private void OnVerboseLoggingChanged(object sender, EventArgs args)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("VerboseLogging = " + _settings.VerboseLogging.Value));
		}

		private void OnDestroy()
		{
			Cleanup();
		}

		private void Cleanup()
		{
			if (OwnsRuntime && _delivery != null)
			{
				_delivery.Tick();
			}
			if (_session != null)
			{
				_session.PreserveForReload();
			}
			if (OwnsRuntime && _registered)
			{
				DSPModSavePlugin.RemoveModSaveManually((BaseUnityPlugin)(object)this);
			}
			_registered = false;
			if (_window != null)
			{
				_window.Dispose();
				_window = null;
			}
			if (_hud != null)
			{
				_hud.Dispose();
				_hud = null;
			}
			if (_delivery != null)
			{
				_delivery.Deactivate();
				_delivery = null;
			}
			if (_settings != null)
			{
				_settings.VerboseLogging.SettingChanged -= OnVerboseLoggingChanged;
				_settings = null;
			}
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
				_harmony = null;
			}
			if ((Object)(object)Active == (Object)(object)this)
			{
				Active = null;
			}
		}
	}
	[HarmonyPatch(typeof(VFInput), "OnUpdate")]
	internal static class MarketInputPatch
	{
		private static void Postfix()
		{
			if ((Object)(object)Plugin.Active != (Object)null)
			{
				Plugin.Active.ConsumeEscape();
			}
		}
	}
	[HarmonyPatch(typeof(GameSave), "SaveCurrentGame")]
	internal static class MarketSaveGuardPatch
	{
		private static bool Prefix(ref bool __result)
		{
			if ((Object)(object)Plugin.Active == (Object)null || Plugin.Active.AllowSave())
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	public static class PluginInfo
	{
		public const string Guid = "dspfx.mod";

		public const string Name = "FXDSP";

		public const string Version = "1.0.0";
	}
}
namespace FXDSP.UI
{
	internal sealed class AchievementsView : IDisposable
	{
		private readonly Text _count;

		private readonly Text _pageText;

		private readonly Button _previous;

		private readonly Button _next;

		private readonly Text[] _names = (Text[])(object)new Text[6];

		private readonly Text[] _descriptions = (Text[])(object)new Text[6];

		private readonly Text[] _states = (Text[])(object)new Text[6];

		private readonly Image[] _cards = (Image[])(object)new Image[6];

		private TradingAchievementState _state;

		private int _page;

		internal AchievementsView(NativeUiFactory ui, Transform parent)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Expected O, but got Unknown
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Expected O, but got Unknown
			((Graphic)ui.Image("achievement-background", parent, 20f, 101f, 1100f, 627f, new Color(0.03f, 0.055f, 0.07f, 1f))).raycastTarget = true;
			_count = ui.Text("achievements-title", parent, 42f, 117f, 900f, 40f, "成就", 22, null, (TextAnchor)0);
			for (int i = 0; i < 6; i++)
			{
				float x = 42 + i % 2 * 542;
				float y = 176 + i / 2 * 160;
				Image val = ui.Image("achievement-card-" + i, parent, x, y, 514f, 140f, Color.white);
				_cards[i] = val;
				_names[i] = ui.Text("name", ((Component)val).transform, 20f, 14f, 370f, 32f, "", 20, null, (TextAnchor)0);
				_states[i] = ui.Text("state", ((Component)val).transform, 390f, 18f, 104f, 26f, "", 14, null, (TextAnchor)5);
				_descriptions[i] = ui.Text("description", ((Component)val).transform, 20f, 58f, 474f, 66f, "", 15, null, (TextAnchor)0);
				_descriptions[i].verticalOverflow = (VerticalWrapMode)0;
			}
			_previous = ui.Button("previous", parent, 42f, 680f, 104f, 32f, "上一页", (UnityAction)delegate
			{
				_page--;
				Refresh(_state);
			});
			_next = ui.Button("next", parent, 994f, 680f, 104f, 32f, "下一页", (UnityAction)delegate
			{
				_page++;
				Refresh(_state);
			});
			_pageText = ui.Text("page", parent, 470f, 680f, 200f, 32f, "", 14, null, (TextAnchor)4);
		}

		internal void Refresh(TradingAchievementState state)
		{
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			_state = state;
			int num = (AchievementCatalog.All.Count + 5) / 6;
			_page = Math.Max(0, Math.Min(num - 1, _page));
			_count.text = "成就    " + (state?.CompletedCount ?? 0) + " / " + AchievementCatalog.All.Count;
			_pageText.text = _page + 1 + " / " + num;
			((Selectable)_previous).interactable = _page > 0;
			((Selectable)_next).interactable = _page + 1 < num;
			for (int i = 0; i < 6; i++)
			{
				int num2 = _page * 6 + i;
				((Component)_cards[i]).gameObject.SetActive(num2 < AchievementCatalog.All.Count);
				if (num2 < AchievementCatalog.All.Count)
				{
					AchievementDefinition achievementDefinition = AchievementCatalog.All[num2];
					bool flag = state?.Completed(achievementDefinition.Id) ?? false;
					((Graphic)_cards[i]).color = (flag ? new Color(0.09f, 0.19f, 0.19f, 1f) : new Color(0.055f, 0.095f, 0.12f, 1f));
					_names[i].text = achievementDefinition.Name;
					_descriptions[i].text = achievementDefinition.Description;
					_states[i].text = (flag ? "已达成" : "未达成");
					((Graphic)_states[i]).color = (flag ? new Color(0.4f, 0.82f, 0.75f, 1f) : new Color(0.5f, 0.6f, 0.66f, 1f));
				}
			}
		}

		public void Dispose()
		{
			((UnityEventBase)_previous.onClick).RemoveAllListeners();
			((UnityEventBase)_next.onClick).RemoveAllListeners();
		}
	}
	internal sealed class HoldingActionTarget : MonoBehaviour, IPointerDownHandler, IEventSystemHandler
	{
		internal int ItemId;

		private int _pressedItemId;

		public void OnPointerDown(PointerEventData data)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			if ((int)data.button == 0)
			{
				_pressedItemId = ItemId;
			}
		}

		internal int Consume()
		{
			int result = ((_pressedItemId > 0) ? _pressedItemId : ItemId);
			_pressedItemId = 0;
			return result;
		}
	}
	internal sealed class HoldingsView
	{
		private sealed class Row
		{
			internal int ItemId;

			internal RectTransform Root;

			internal Image Icon;

			internal Text Name;

			internal Text Direction;

			internal Text Margin;

			internal Text Entry;

			internal Text Current;

			internal Text Liquidation;

			internal Text PnL;

			internal Text Return;

			internal Text Held;

			internal Button Close;

			internal Button Details;

			internal HoldingActionTarget CloseTarget;

			internal HoldingActionTarget DetailsTarget;
		}

		private readonly List<Row> _rows = new List<Row>();

		private readonly Text _count;

		private readonly Button _closeAll;

		private readonly Button _previous;

		private readonly Button _next;

		private readonly Text _pageText;

		private PortfolioSnapshot _lastState;

		private int _page;

		internal HoldingsView(NativeUiFactory ui, Transform parent, Action<int> details, Action<int> close, Action closeAll)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Expected O, but got Unknown
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Expected O, but got Unknown
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Expected O, but got Unknown
			//IL_032f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_0729: Unknown result type (might be due to invalid IL or missing references)
			//IL_073d: Expected O, but got Unknown
			//IL_077c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0790: Expected O, but got Unknown
			HoldingsView holdingsView = this;
			((Graphic)ui.Image("holdings-background", parent, 20f, 101f, 1100f, 627f, new Color(0.03f, 0.055f, 0.07f, 1f))).raycastTarget = true;
			_count = ui.Text("holdings-title", parent, 40f, 113f, 600f, 38f, "全部持仓", 21, null, (TextAnchor)0);
			_closeAll = ui.Button("close-all", parent, 916f, 113f, 184f, 36f, "一键全部平仓", (UnityAction)delegate
			{
				closeAll();
			}, (Color?)new Color(0.4f, 0.27f, 0.23f, 1f));
			string[] array = new string[9] { "市场", "方向 / 杠杆", "保证金", "入场价", "最新价", "爆仓价", "浮动盈亏", "收益率", "持有时间" };
			float[] array2 = new float[9] { 40f, 194f, 282f, 385f, 473f, 561f, 649f, 772f, 865f };
			float[] array3 = new float[9] { 144f, 80f, 95f, 80f, 80f, 80f, 115f, 85f, 75f };
			for (int num = 0; num < array.Length; num++)
			{
				ui.Text("column-" + num, parent, array2[num], 157f, array3[num], 38f, array[num], 12, (Color?)new Color(0.6f, 0.72f, 0.78f, 1f), (TextAnchor)3);
			}
			_previous = ui.Button("holdings-prev", parent, 40f, 686f, 90f, 30f, "上一页", (UnityAction)delegate
			{
				holdingsView._page = Math.Max(0, holdingsView._page - 1);
				holdingsView.Refresh(holdingsView._lastState);
			});
			_next = ui.Button("holdings-next", parent, 1010f, 686f, 90f, 30f, "下一页", (UnityAction)delegate
			{
				holdingsView._page++;
				holdingsView.Refresh(holdingsView._lastState);
			});
			_pageText = ui.Text("holdings-page", parent, 470f, 686f, 200f, 30f, "", 13, null, (TextAnchor)4);
			for (int num2 = 0; num2 < 9; num2++)
			{
				Row row = new Row();
				row.Root = ui.Container("holding-" + num2, parent, 34f, 207 + num2 * 52, 1072f, 46f);
				ui.Image("row-fill", (Transform)(object)row.Root, 0f, 0f, 1072f, 46f, new Color(0.065f, 0.11f, 0.135f, 0.9f));
				row.Icon = ui.Image("icon", (Transform)(object)row.Root, 8f, 10f, 28f, 28f, Color.white);
				row.Name = ui.Text("name", (Transform)(object)row.Root, 44f, 0f, 106f, 46f, "", 14, null, (TextAnchor)3);
				row.Direction = ui.Text("direction", (Transform)(object)row.Root, 160f, 0f, 80f, 46f, "", 13, null, (TextAnchor)3);
				row.Direction.supportRichText = true;
				row.Margin = ui.Text("margin", (Transform)(object)row.Root, 248f, 0f, 95f, 46f, "", 13, null, (TextAnchor)3);
				row.Entry = ui.Text("entry", (Transform)(object)row.Root, 351f, 0f, 80f, 46f, "", 13, null, (TextAnchor)3);
				row.Current = ui.Text("current", (Transform)(object)row.Root, 439f, 0f, 80f, 46f, "", 13, null, (TextAnchor)3);
				row.Liquidation = ui.Text("liquidation", (Transform)(object)row.Root, 527f, 0f, 80f, 46f, "", 13, null, (TextAnchor)3);
				row.PnL = ui.Text("pnl", (Transform)(object)row.Root, 615f, 0f, 115f, 46f, "", 14, null, (TextAnchor)3);
				row.PnL.resizeTextForBestFit = true;
				row.PnL.resizeTextMinSize = 10;
				row.PnL.resizeTextMaxSize = 14;
				row.PnL.verticalOverflow = (VerticalWrapMode)0;
				row.Return = ui.Text("unrealized-return", (Transform)(object)row.Root, 738f, 0f, 85f, 46f, "", 12, null, (TextAnchor)3);
				row.Held = ui.Text("held", (Transform)(object)row.Root, 831f, 0f, 75f, 46f, "", 13, null, (TextAnchor)3);
				Text[] array4 = (Text[])(object)new Text[5] { row.Name, row.Direction, row.Margin, row.Return, row.Held };
				foreach (Text obj in array4)
				{
					obj.resizeTextForBestFit = true;
					obj.resizeTextMinSize = 9;
					obj.resizeTextMaxSize = obj.fontSize;
					obj.verticalOverflow = (VerticalWrapMode)0;
				}
				row.Details = ui.Button("details", (Transform)(object)row.Root, 925f, 9f, 60f, 30f, "详情", (UnityAction)delegate
				{
					details(row.DetailsTarget.Consume());
				});
				row.Close = ui.Button("close", (Transform)(object)row.Root, 994f, 9f, 66f, 30f, "平仓", (UnityAction)delegate
				{
					close(row.CloseTarget.Consume());
				});
				row.DetailsTarget = ((Component)row.Details).gameObject.AddComponent<HoldingActionTarget>();
				row.CloseTarget = ((Component)row.Close).gameObject.AddComponent<HoldingActionTarget>();
				_rows.Add(row);
			}
		}

		internal void Refresh(PortfolioSnapshot state)
		{
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_0333: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: 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)
			_lastState = state;
			int num = state?.Positions.Count ?? 0;
			int num2 = Math.Max(1, (num + _rows.Count - 1) / _rows.Count);
			_page = Math.Max(0, Math.Min(num2 - 1, _page));
			_pageText.text = _page + 1 + " / " + num2;
			((Selectable)_previous).interactable = _page > 0;
			((Selectable)_next).interactable = _page + 1 < num2;
			_count.text = ((num == 0) ? "全部持仓 · 当前空仓" : ("全部持仓  " + num));
			((Selectable)_closeAll).interactable = state != null && state.Ready && num > 0;
			for (int i = 0; i < _rows.Count; i++)
			{
				Row row = _rows[i];
				int num3 = _page * _rows.Count + i;
				((Component)row.Root).gameObject.SetActive(num3 < num);
				if (num3 >= num)
				{
					row.ItemId = 0;
					continue;
				}
				PositionSnapshot positionSnapshot = state.Positions[num3];
				row.ItemId = positionSnapshot.ItemId;
				row.DetailsTarget.ItemId = (row.CloseTarget.ItemId = positionSnapshot.ItemId);
				row.Icon.sprite = positionSnapshot.Icon;
				((Behaviour)row.Icon).enabled = (Object)(object)positionSnapshot.Icon != (Object)null;
				row.Name.text = positionSnapshot.Name;
				((RectTransform)((Component)row.Name).transform).anchoredPosition = new Vector2((float)(((Object)(object)positionSnapshot.Icon == (Object)null) ? 10 : 44), 0f);
				row.Direction.text = NativeUiFactory.DirectionText(positionSnapshot.Direction) + " " + positionSnapshot.Leverage + "×";
				row.Margin.text = positionSnapshot.Margin.ToString("#,0.00");
				row.Entry.text = positionSnapshot.EntryPrice.ToString("0.0000");
				row.Current.text = positionSnapshot.CurrentPrice.ToString("0.0000");
				row.Liquidation.text = positionSnapshot.LiquidationPrice.ToString("0.0000");
				row.PnL.text = MoneyDisplay.Signed(positionSnapshot.UnrealizedPnL);
				((Graphic)row.PnL).color = (Color)((positionSnapshot.UnrealizedPnL > 0m) ? MarketCandleGraphic.Rising : ((positionSnapshot.UnrealizedPnL < 0m) ? MarketCandleGraphic.Falling : new Color(0.6f, 0.72f, 0.78f, 1f)));
				row.Return.text = MoneyDisplay.Percent(positionSnapshot.UnrealizedReturnRatio);
				((Graphic)row.Return).color = ((Graphic)row.PnL).color;
				row.Held.text = positionSnapshot.HeldCandles.ToString("N0", CultureInfo.InvariantCulture);
				((Selectable)row.Close).interactable = state.Ready;
			}
		}

		internal void Dispose()
		{
			if ((Object)(object)_closeAll != (Object)null)
			{
				((UnityEventBase)_closeAll.onClick).RemoveAllListeners();
			}
			if ((Object)(object)_previous != (Object)null)
			{
				((UnityEventBase)_previous.onClick).RemoveAllListeners();
			}
			if ((Object)(object)_next != (Object)null)
			{
				((UnityEventBase)_next.onClick).RemoveAllListeners();
			}
			foreach (Row row in _rows)
			{
				if ((Object)(object)row.Close != (Object)null)
				{
					((UnityEventBase)row.Close.onClick).RemoveAllListeners();
				}
				if ((Object)(object)row.Details != (Object)null)
				{
					((UnityEventBase)row.Details.onClick).RemoveAllListeners();
				}
			}
			_rows.Clear();
		}
	}
	internal static class IntroductionCopy
	{
		internal const string Title = "欢迎接入 DSP 交易平台";

		internal const string Body = "伊卡洛斯,老实铺产线很枯燥吧!除了扩大生产,你现在还可以通过交易获取物资。\n\n选择交易品种、存入对应物品,即可使用该物品作为保证金,<color=#D45954>开多</color>(预测<color=#D45954>上涨</color>)或<color=#52BA80>开空</color>(预测<color=#52BA80>下跌</color>)。各品种账户<color=#69CCD6>独立</color>,收益可直接提取为同种物资。\n\n<color=#69CCD6>仓位</color>比例决定投入的保证金,<color=#69CCD6>杠杆</color>放大收益与亏损。判断失误、亏损过大超过爆仓线时,持仓将被强制平仓。\n\n特殊的<color=#D9B76B>建筑币</color>可按固定价格双向兑换各种建筑与运输、战斗单位,如果你足够厉害或幸运,或许可以实现建筑自由。如果不想投机,可能也可以寻找一个性价比高的建筑量产建筑币,并兑换其它建筑作为超市使用。\n\n按 <color=#69CCD6>F8</color> 打开或关闭交易界面,右上角持仓面板可随时查看浮动盈亏、平仓或进入兑换。\n\n解锁科技建造<color=#69CCD6>物流塔交付平台</color>绑定物品,可将交易账户连接到工厂物流网络,让盈利物资直接投入生产。\n\n研究相关<color=#69CCD6>科技升级</color>,可以解锁更高等级的建筑兑换并降低交易和兑换手续费。\n\n你可以选择不同的交易风格,满仓百倍杠杆梭哈短线擒龙,或是在低估泡沫时耐心价值投资等待估值回归。\n\n<color=#D9B76B>FX战士伊卡洛斯</color>,祝你交易顺利,期待在主脑交易龙虎榜上看到你的名字!";
	}
	internal sealed class LocalizedText : Text
	{
		private static readonly HashSet<LocalizedText> ActiveTexts = new HashSet<LocalizedText>();

		private string _source = "";

		public override string text
		{
			get
			{
				return ((Text)this).text;
			}
			set
			{
				_source = value ?? "";
				baseText();
			}
		}

		protected override void OnEnable()
		{
			((Text)this).OnEnable();
			ActiveTexts.Add(this);
			baseText();
		}

		protected override void OnDisable()
		{
			ActiveTexts.Remove(this);
			((Text)this).OnDisable();
		}

		protected override void OnDestroy()
		{
			ActiveTexts.Remove(this);
			((Graphic)this).OnDestroy();
		}

		internal static void RefreshLanguage()
		{
			foreach (LocalizedText activeText in ActiveTexts)
			{
				if ((Object)(object)activeText != (Object)null)
				{
					activeText.baseText();
				}
			}
		}

		private void baseText()
		{
			((Text)this).text = TextLocalization.Translate(_source);
		}
	}
	internal sealed class MarketCandleGraphic : MaskableGraphic
	{
		internal static readonly Color Rising = new Color(0.83f, 0.35f, 0.33f, 1f);

		internal static readonly Color Falling = new Color(0.32f, 0.73f, 0.5f, 1f);

		private readonly List<MarketCandle> _candles = new List<MarketCandle>();

		internal float Minimum { get; private set; }

		internal float Maximum { get; private set; }

		internal float LiquidationPrice { get; private set; }

		internal float LiquidationRatio
		{
			get
			{
				if (!(Maximum <= Minimum))
				{
					return (LiquidationPrice - Minimum) / (Maximum - Minimum);
				}
				return 0f;
			}
		}

		internal void SetCandles(IReadOnlyList<MarketCandle> candles, decimal liquidationPrice)
		{
			int num = ((candles != null) ? Mathf.Min(60, candles.Count) : 0);
			int num2 = ((candles != null) ? (candles.Count - num) : 0);
			bool flag = num != _candles.Count || LiquidationPrice != (float)liquidationPrice;
			if (!flag)
			{
				for (int i = 0; i < num; i++)
				{
					if (candles[num2 + i].StartTick != _candles[i].StartTick || candles[num2 + i].Open != _candles[i].Open || candles[num2 + i].Close != _candles[i].Close || candles[num2 + i].DisplayHigh != _candles[i].DisplayHigh || candles[num2 + i].DisplayLow != _candles[i].DisplayLow)
					{
						flag = true;
						break;
					}
				}
			}
			if (!flag)
			{
				return;
			}
			LiquidationPrice = (float)liquidationPrice;
			_candles.Clear();
			Minimum = float.MaxValue;
			Maximum = float.MinValue;
			if (candles != null)
			{
				for (int j = 0; j < num; j++)
				{
					MarketCandle marketCandle = candles[num2 + j];
					_candles.Add(marketCandle);
					Minimum = Mathf.Min(Minimum, (float)marketCandle.DisplayLow);
					Maximum = Mathf.Max(Maximum, (float)marketCandle.DisplayHigh);
				}
			}
			if (num == 0)
			{
				Minimum = 0f;
				Maximum = 1f;
			}
			float num3 = Mathf.Max((Maximum - Minimum) * 0.08f, Mathf.Abs(Minimum) * 0.001f);
			Minimum -= num3;
			Maximum += num3;
			((Graphic)this).SetVerticesDirty();
		}

		protected override void OnPopulateMesh(VertexHelper mesh)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			mesh.Clear();
			Rect rect = ((Graphic)this).rectTransform.rect;
			Color tint = default(Color);
			((Color)(ref tint))..ctor(0.35f, 0.55f, 0.65f, 0.17f);
			for (int i = 0; i <= 3; i++)
			{
				Box(mesh, ((Rect)(ref rect)).xMin, ((Rect)(ref rect)).yMin + 8f + (((Rect)(ref rect)).height - 16f) * (float)i / 3f, ((Rect)(ref rect)).width, 0.8f, tint);
			}
			for (int j = 0; j <= 6; j++)
			{
				Box(mesh, ((Rect)(ref rect)).xMin + ((Rect)(ref rect)).width * (float)j / 6f, ((Rect)(ref rect)).yMin, 0.8f, ((Rect)(ref rect)).height, tint);
			}
			if (_candles.Count == 0 || Maximum <= Minimum)
			{
				return;
			}
			Rect plot = default(Rect);
			((Rect)(ref plot))..ctor(((Rect)(ref rect)).xMin + 6f, ((Rect)(ref rect)).yMin + 8f, ((Rect)(ref rect)).width - 12f, ((Rect)(ref rect)).height - 16f);
			float num = ((Rect)(ref plot)).width / (float)Mathf.Max(24, _candles.Count);
			float num2 = Mathf.Max(3f, num * 0.62f);
			for (int k = 0; k < _candles.Count; k++)
			{
				MarketCandle marketCandle = _candles[k];
				float num3 = ((Rect)(ref plot)).xMin + num * ((float)k + 0.5f);
				float num4 = Y(marketCandle.Open, plot);
				float num5 = Y(marketCandle.Close, plot);
				float num6 = Y(marketCandle.DisplayLow, plot);
				float num7 = Y(marketCandle.DisplayHigh, plot);
				Color tint2 = (Color)((marketCandle.Close > marketCandle.Open) ? Rising : ((marketCandle.Close < marketCandle.Open) ? Falling : new Color(0.63f, 0.69f, 0.73f, 1f)));
				Box(mesh, num3 - 0.7f, num6, 1.4f, Mathf.Max(1f, num7 - num6), tint2);
				Box(mesh, num3 - num2 / 2f, Mathf.Min(num4, num5) - ((Mathf.Abs(num5 - num4) < 1.5f) ? 0.75f : 0f), num2, Mathf.Max(1.5f, Mathf.Abs(num5 - num4)), tint2);
			}
			if (LiquidationPrice > 0f)
			{
				float y = ((Rect)(ref plot)).yMin + ((Rect)(ref plot)).height * Mathf.Clamp01(LiquidationRatio);
				Color tint3 = default(Color);
				((Color)(ref tint3))..ctor(0.85f, 0.66f, 0.32f, 1f);
				for (float num8 = ((Rect)(ref plot)).xMin; num8 < ((Rect)(ref plot)).xMax; num8 += 12f)
				{
					Box(mesh, num8, y, Mathf.Min(7f, ((Rect)(ref plot)).xMax - num8), 1.3f, tint3);
				}
			}
		}

		private float Y(decimal value, Rect plot)
		{
			return ((Rect)(ref plot)).yMin + ((Rect)(ref plot)).height * ((float)value - Minimum) / (Maximum - Minimum);
		}

		private static void Box(VertexHelper mesh, float x, float y, float width, float height, Color tint)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_0030: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			int currentVertCount = mesh.currentVertCount;
			mesh.AddVert(new Vector3(x, y), Color32.op_Implicit(tint), Vector4.op_Implicit(Vector2.zero));
			mesh.AddVert(new Vector3(x, y + height), Color32.op_Implicit(tint), Vector4.op_Implicit(Vector2.zero));
			mesh.AddVert(new Vector3(x + width, y + height), Color32.op_Implicit(tint), Vector4.op_Implicit(Vector2.zero));
			mesh.AddVert(new Vector3(x + width, y), Color32.op_Implicit(tint), Vector4.op_Implicit(Vector2.zero));
			mesh.AddTriangle(currentVertCount, currentVertCount + 1, currentVertCount + 2);
			mesh.AddTriangle(currentVertCount, currentVertCount + 2, currentVertCount + 3);
		}
	}
	internal sealed class MarketDragHandle : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler
	{
		internal RectTransform Window;

		private Vector2 _startPointer;

		private Vector2 _startWindow;

		public void OnBeginDrag(PointerEventData data)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Window == (Object)null) && (int)data.button == 0)
			{
				Transform parent = ((Transform)Window).parent;
				RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
				if (!((Object)(object)val == (Object)null))
				{
					RectTransformUtility.ScreenPointToLocalPointInRectangle(val, data.position, data.pressEventCamera, ref _startPointer);
					_startWindow = Window.anchoredPosition;
					((Transform)Window).SetAsLastSibling();
				}
			}
		}

		public void OnDrag(PointerEventData data)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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_005c: 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)
			if (!((Object)(object)Window == (Object)null) && (int)data.button == 0)
			{
				Transform parent = ((Transform)Window).parent;
				RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
				Vector2 val2 = default(Vector2);
				if (!((Object)(object)val == (Object)null) && RectTransformUtility.ScreenPointToLocalPointInRectangle(val, data.position, data.pressEventCamera, ref val2))
				{
					Window.anchoredPosition = _startWindow + val2 - _startPointer;
					Clamp(Window);
				}
			}
		}

		internal static void Clamp(RectTransform window)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_004d: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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)
			//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)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			Transform parent = ((Transform)window).parent;
			RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Rect rect = val.rect;
			if (!(((Rect)(ref rect)).width <= 0f))
			{
				rect = val.rect;
				if (!(((Rect)(ref rect)).height <= 0f))
				{
					rect = val.rect;
					float width = ((Rect)(ref rect)).width;
					rect = window.rect;
					float num = Mathf.Max(0f, (width - ((Rect)(ref rect)).width * ((Transform)window).localScale.x) * 0.5f - 8f);
					rect = val.rect;
					float height = ((Rect)(ref rect)).height;
					rect = window.rect;
					float num2 = Mathf.Max(0f, (height - ((Rect)(ref rect)).height * ((Transform)window).localScale.y) * 0.5f - 8f);
					Vector2 anchoredPosition = window.anchoredPosition;
					window.anchoredPosition = new Vector2(Mathf.Clamp(anchoredPosition.x, 0f - num, num), Mathf.Clamp(anchoredPosition.y, 0f - num2, num2));
				}
			}
		}
	}
	internal sealed class MarketWindow : IDisposable
	{
		private sealed class ExchangeCell
		{
			public int ItemId;

			public Button Button;

			public Image Icon;

			public Image Background;

			public Text Name;

			public Text Value;
		}

		private const float Width = 1140f;

		private const float Height = 760f;

		private static readonly Color Muted = new Color(0.6f, 0.72f, 0.78f, 0.9f);

		private static readonly Color Cyan = new Color(0.4f, 0.82f, 0.85f, 1f);

		private static readonly Color Warning = new Color(0.85f, 0.64f, 0.36f, 1f);

		private readonly Func<int, MarketSnapshot> _snapshot;

		private readonly Action<MarketCommand, int> _execute;

		private readonly Func<PortfolioSnapshot> _portfolio;

		private readonly Func<bool> _acknowledgeIntroduction;

		private readonly Func<TradingAchievementState> _achievements;

		private RectTransform _achievementsRoot;

		private AchievementsView _achievementsView;

		private Button _achievementsButton;

		private bool _achievementsMode;

		private readonly TransferSelection _depositSelection = new TransferSelection();

		private readonly TransferSelection _withdrawSelection = new TransferSelection();

		private int _transferContextItem;

		private bool _transferContextDelivery;

		private RectTransform _positionsRoot;

		private RectTransform _sidebarRoot;

		private HoldingsView _holdings;

		private Text _inventoryLabel;

		private Button _sourceBackpack;

		private Button _sourceDelivery;

		private Button _allPositionsButton;

		private bool _positionsMode;

		private bool _resourceSelectionMode;

		private MarketCategory? _categoryOverride;

		private MarketSnapshot _lastState;

		private RectTransform _resourcePickerRoot;

		private Button _chooseResources;

		private ResourceSelectionView _resourcePicker;

		private ResourceSidebarView _resourceSidebar;

		private readonly List<Button> _buttons = new List<Button>();

		private readonly List<Button> _allocationButtons = new List<Button>();

		private readonly Dictionary<int, Button> _marketButtons = new Dictionary<int, Button>();

		private readonly Queue<PositionSettlement> _settlements = new Queue<PositionSettlement>();

		private RectTransform _root;

		private RectTransform _tradeRoot;

		private RectTransform _exchangeRoot;

		private RectTransform _transferRoot;

		private RectTransform _coinFunding;

		private readonly Dictionary<MarketCategory, Button> _categoryButtons = new Dictionary<MarketCategory, Button>();

		private readonly Dictionary<int, Image> _marketIcons = new Dictionary<int, Image>();

		private readonly List<ExchangeCell> _exchangeCells = new List<ExchangeCell>();

		private Button _coinTradeTab;

		private Button _exchangeBuy;

		private Button _exchangeSell;

		private readonly List<Button> _exchangeTierButtons = new List<Button>();

		private readonly Text[] _priceAxis = (Text[])(object)new Text[4];

		private Text _marginPreview;

		private Text _exchangeName;

		private Text _exchangeValue;

		private Text _exchangeBackpack;

		private Text _exchangeWallet;

		private Text _exchangeTotal;

		private Text _exchangePageText;

		private Text _coinBalance;

		private Image _exchangeIcon;

		private InputField _exchangeQuantityInput;

		private Slider _exchangeQuantitySlider;

		private int _exchangeMaximum;

		private string _exchangeQuantityValue = "1";

		private int _exchangePage;

		private bool _exchangeMode;

		private Canvas _canvas;

		private NativeUiFactory _ui;

		private InputField _depositInput;

		private InputField _withdrawInput;

		private Slider _allocationSlider;

		private Slider _leverageSlider;

		private Slider _depositSlider;

		private Slider _withdrawSlider;

		private Text _assets;

		private Text _floating;

		private Text _floatingReturn;

		private Text _realized;

		private Text _returnRate;

		private Text _positionText;

		private Text _quote;

		private Text _preview;

		private Text _backpack;

		private Text _withdrawable;

		private Text _status;

		private Text _events;

		private Text _chartRange;

		private Text _chartTitle;

		private Text _transferTitle;

		private Text _liquidationLabel;

		private Image _liquidationBackground;

		private Text _allocationLabel;

		private Text _leverageLabel;

		private MarketCandleGraphic _chart;

		private Button _long;

		private Button _short;

		private Button _deposit;

		private Button _withdraw;

		private Button _closePosition;

		private GameObject _modal;

		private PositionSettlement _pendingSettlement;

		private string _depositValue = "10";

		private string _withdrawValue = "10";

		private int _allocation = 25;

		private int _selectedLeverage = 5;

		private string _localError = "";

		private float _nextRefresh;

		private bool _dirty = true;

		private bool _clearSelection;

		private bool _disposed;

		private int _escapeFrame = -1;

		private int _inputEndedFrame = -1;

		internal bool IsOpen
		{
			get
			{
				if ((Object)(object)_root != (Object)null)
				{
					return ((Component)_root).gameObject.activeSelf;
				}
				return false;
			}
		}

		internal bool HasSettlement => (Object)(object)_modal != (Object)null;

		internal bool IsInputFocused
		{
			get
			{
				if (IsOpen)
				{
					if ((!((Object)(object)_depositInput != (Object)null) || !_depositInput.isFocused) && (!((Object)(object)_withdrawInput != (Object)null) || !_withdrawInput.isFocused))
					{
						if ((Object)(object)_exchangeQuantityInput != (Object)null)
						{
							return _exchangeQuantityInput.isFocused;
						}
						return false;
					}
					return true;
				}
				return false;
			}
		}

		internal bool BlocksGameInput
		{
			get
			{
				if (IsOpen)
				{
					if (!IsInputFocused && !IsPointerOver)
					{
						return (Object)(object)_modal != (Object)null;
					}
					return true;
				}
				return false;
			}
		}

		internal bool IsPointerOver
		{
			get
			{
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//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)
				if (!IsOpen)
				{
					return false;
				}
				Camera val = (((Object)(object)_canvas == (Object)null || (int)_canvas.renderMode == 0) ? null : _canvas.worldCamera);
				return RectTransformUtility.RectangleContainsScreenPoint(_root, Vector2.op_Implicit(Input.mousePosition), val);
			}
		}

		internal MarketWindow(Func<int, MarketSnapshot> snapshot, Func<PortfolioSnapshot> portfolio, Action<MarketCommand, int> execute, Func<bool> acknowledgeIntroduction, Func<TradingAchievementState> achievements)
		{
			_snapshot = snapshot ?? throw new ArgumentNullException("snapshot");
			_portfolio = portfolio ?? throw new ArgumentNullException("portfolio");
			_execute = execute ?? throw new ArgumentNullException("execute");
			_acknowledgeIntroduction = acknowledgeIntroduction ?? throw new ArgumentNullException("acknowledgeIntroduction");
			_achievements = achievements;
		}

		internal void Toggle()
		{
			if (_disposed)
			{
				return;
			}
			if (IsOpen)
			{
				Close();
			}
			else
			{
				if (!GameMain.isRunning || GameMain.data == null || (Object)(object)UIRoot.instance == (Object)null || (Object)(object)UIRoot.instance.uiGame == (Object)null || (Object)(object)UIRoot.instance.uiGame.inserterWindow == (Object)null)
				{
					return;
				}
				try
				{
					Build();
					bool num = _acknowledgeIntroduction();
					if (num)
					{
						_achievementsMode = false;
						_categoryOverride = MarketCategory.RawMaterials;
						_positionsMode = (_exchangeMode = false);
						_resourceSelectionMode = true;
					}
					_dirty = true;
					_nextRefresh = 0f;
					Tick();
					if (num && (Object)(object)_modal == (Object)null)
					{
						BuildIntroductionPopup();
					}
				}
				catch (Exception ex)
				{
					Close();
					Debug.LogWarning((object)("[FXDSP] Market window is unavailable: " + ex));
				}
			}
		}

		internal void ShowAllPositions()
		{
			_achievementsMode = false;
			if (!_disposed)
			{
				_positionsMode = true;
				_categoryOverride = null;
				_resourceSelectionMode = false;
				_exchangeMode = false;
				ClearInputSelection();
				if (!IsOpen)
				{
					Toggle();
					return;
				}
				_dirty = true;
				Refresh();
			}
		}

		internal void ShowExchange()
		{
			_achievementsMode = false;
			if (!_disposed && !((Object)(object)_modal != (Object)null))
			{
				_positionsMode = (_resourceSelectionMode = false);
				_categoryOverride = null;
				_exchangeMode = true;
				_execute(MarketCommand.SelectMarket, 99000001);
				ClearInputSelection();
				if (!IsOpen)
				{
					Toggle();
					return;
				}
				_dirty = true;
				Refresh();
			}
		}

		internal void ShowSettlement(PositionSettlement settlement)
		{
			if (settlement == null || _disposed)
			{
				return;
			}
			if (_pendingSettlement != null)
			{
				_settlements.Enqueue(settlement);
				if (!IsOpen)
				{
					Toggle();
				}
				return;
			}
			_pendingSettlement = settlement;
			if (!IsOpen)
			{
				Toggle();
			}
			else
			{
				BuildSettlementPopup();
			}
			_dirty = true;
		}

		internal void ResetNotifications()
		{
			_settlements.Clear();
			DismissSettlement();
		}

		internal void Tick()
		{
			if (_disposed || !IsOpen)
			{
				return;
			}
			ConsumeEscape();
			if (IsOpen)
			{
				if (_clearSelection && !IsInputFocused)
				{
					_clearSelection = false;
					ClearInputSelection();
				}
				FitToParent();
				if (_dirty || !(Time.unscaledTime < _nextRefresh))
				{
					_dirty = false;
					_nextRefresh = Time.unscaledTime + 0.2f;
					Refresh();
				}
			}
		}

		internal bool ConsumeEscape()
		{
			if (!Input.GetKeyDown((KeyCode)27))
			{
				return false;
			}
			if (_escapeFrame == Time.frameCount)
			{
				VFInput.UseEscape();
				return true;
			}
			if (!IsOpen)
			{
				return false;
			}
			_escapeFrame = Time.frameCount;
			if ((Object)(object)_modal != (Object)null)
			{
				DismissSettlement();
			}
			else if (IsInputFocused || _inputEndedFrame == Time.frameCount)
			{
				ClearInputSelection();
			}
			else
			{
				Close();
			}
			VFInput.UseEscape();
			return true;
		}

		internal void Close()
		{
			ClearInputSelection();
			if ((Object)(object)_depositInput != (Object)null)
			{
				_depositValue = _depositInput.text;
			}
			if ((Object)(object)_withdrawInput != (Object)null)
			{
				_withdrawValue = _withdrawInput.text;
			}
			if ((Object)(object)_exchangeQuantityInput != (Object)null)
			{
				_exchangeQuantityValue = _exchangeQuantityInput.text;
			}
			InputField[] array = (InputField[])(object)new InputField[3] { _depositInput, _withdrawInput, _exchangeQuantityInput };
			foreach (InputField val in array)
			{
				if ((Object)(object)val != (Object)null)
				{
					((UnityEventBase)val.onValueChanged).RemoveAllListeners();
					((UnityEventBase)val.onEndEdit).RemoveAllListeners();
				}
			}
			if ((Object)(object)_allocationSlider != (Object)null)
			{
				((UnityEventBase)_allocationSlider.onValueChanged).RemoveAllListeners();
			}
			if ((Object)(object)_leverageSlider != (Object)null)
			{
				((UnityEventBase)_leverageSlider.onValueChanged).RemoveAllListeners();
			}
			if ((Object)(object)_depositSlider != (Object)null)
			{
				((UnityEventBase)_depositSlider.onValueChanged).RemoveAllListeners();
			}
			if ((Object)(object)_withdrawSlider != (Object)null)
			{
				((UnityEventBase)_withdrawSlider.onValueChanged).RemoveAllListeners();
			}
			if ((Object)(object)_exchangeQuantitySlider != (Object)null)
			{
				((UnityEventBase)_exchangeQuantitySlider.onValueChanged).RemoveAllListeners();
			}
			foreach (Button button in _buttons)
			{
				if ((Object)(object)button != (Object)null)
				{
					((UnityEventBase)button.onClick).RemoveAllListeners();
				}
			}
			_buttons.Clear();
			_allocationButtons.Clear();
			_marketButtons.Clear();
			_marketIcons.Clear();
			_categoryButtons.Clear();
			_exchangeCells.Clear();
			_exchangeTierButtons.Clear();
			Array.Clear(_priceAxis, 0, _priceAxis.Length);
			if (_holdings != null)
			{
				_holdings.Dispose();
				_holdings = null;
			}
			_achievementsView?.Dispose();
			_achievementsView = null;
			_achievementsRoot = null;
			_achievementsButton = null;
			_inventoryLabel = null;
			_sourceBackpack = (_sourceDelivery = null);
			if (_resourcePicker != null)
			{
				_resourcePicker.Dispose();
				_resourcePicker = null;
			}
			if (_resourceSidebar != null)
			{
				_resourceSidebar.Dispose();
				_resourceSidebar = null;
			}
			_resourcePickerRoot = null;
			_chooseResources = null;
			_positionsRoot = (_sidebarRoot = null);
			_allPositionsButton = null;
			DestroyModal();
			if ((Object)(object)_root != (Object)null)
			{
				((Component)_root).gameObject.SetActive(false);
				Object.Destroy((Object)(object)((Component)_root).gameObject);
			}
			_root = (_tradeRoot = (_exchangeRoot = (_transferRoot = (_coinFunding = null))));
			_canvas = null;
			_ui = null;
			_exchangeQuantityInput = null;
			_exchangeBuy = (_exchangeSell = (_coinTradeTab = null));
			_exchangeQuantitySlider = null;
			_depositInput = (_withdrawInput = null);
			_allocationSlider = (_leverageSlider = null);
			_depositSlider = (_withdrawSlider = null);
			_chart = null;
			_assets = (_floating = (_floatingReturn = (_realized = (_returnRate = (_positionText = (_quote = (_preview = null)))))));
			_backpack = (_withdrawable = (_status = (_events = (_chartRange = null))));
			_chartTitle = (_transferTitle = (_liquidationLabel = null));
			_liquidationBackground = null;
			_allocationLabel = (_leverageLabel = null);
			_long = (_short = (_deposit = (_withdraw = (_closePosition = null))));
			_clearSelection = false;
			_localError = "";
		}

		public void Dispose()
		{
			if (!_disposed)
			{
				Close();
				_pendingSettlement = null;
				_settlements.Clear();
				_disposed = true;
			}
		}

		private void Build()
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Expected O, but got Unknown
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Expected O, but got Unknown
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Expected O, but got Unknown
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Expected O, but got Unknown
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Expected O, but got Unknown
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dd: Expected O, but got Unknown
			//IL_0409: Unknown result type (might be due to invalid IL or missing references)
			//IL_0422: Expected O, but got Unknown
			//IL_04f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0510: Expected O, but got Unknown
			//IL_0716: Unknown result type (might be due to invalid IL or missing references)
			//IL_053c: Unknown result type (might be due to invalid IL or missing references)
			Close();
			_ui = new NativeUiFactory();
			_root = _ui.Root("FXDSP-market-window", 1140f, 760f);
			_canvas = ((Component)_root).GetComponentInParent<Canvas>();
			((Graphic)_ui.Image("window-background", (Transform)(object)_root, 0f, 0f, 1140f, 760f, new Color(0.025f, 0.07f, 0.09f, 1f))).raycastTarget = true;
			Image obj = _ui.Image("title-bar", (Transform)(object)_root, 1f, 1f, 1138f, 51f, new Color(0.14f, 0.23f, 0.28f, 0.92f));
			((Graphic)obj).raycastTarget = true;
			((Component)obj).gameObject.AddComponent<MarketDragHandle>().Window = _root;
			_ui.Text("title", (Transform)(object)_root, 22f, 10f, 640f, 36f, "DSP 交易平台", 22, null, (TextAnchor)3);
			AddButton("introduction", 990f, 10f, 72f, 32f, "说明", new UnityAction(BuildIntroductionPopup));
			AddButton("close", 1081f, 10f, 40f, 32f, "X", new UnityAction(Close));
			string[] array = new string[6] { "原料", "材料", "武器", "消耗品", "矩阵", "建筑币" };
			for (int i = 0; i < array.Length; i++)
			{
				MarketCategory category = (MarketCategory)i;
				_categoryButtons.Add(category, AddButton("category-" + i, 22 + i * 126, 58f, 116f, 28f, array[i], (UnityAction)delegate
				{
					SelectCategory(category);
				}));
			}
			_allPositionsButton = AddButton("all-positions", 800f, 58f, 148f, 28f, "全部持仓", new UnityAction(ShowAllPositions));
			_achievementsButton = AddButton("achievements", 966f, 58f, 138f, 28f, "成就", (UnityAction)delegate
			{
				if (!((Object)(object)_modal != (Object)null))
				{
					_achievementsMode = true;
					ClearInputSelection();
					_dirty = true;
					Refresh();
				}
			});
			_sidebarRoot = _ui.Container("sidebar", (Transform)(object)_root, 0f, 0f, 1140f, 760f);
			Panel("sidebar-fill", 20f, 101f, 168f, 627f, (Transform)(object)_sidebarRoot);
			_ui.Text("markets-label", (Transform)(object)_sidebarRoot, 34f, 111f, 140f, 30f, "交易", 17, Muted, (TextAnchor)4);
			_resourceSidebar = new ResourceSidebarView(_ui, (Transform)(object)_sidebarRoot, SelectMarket, Refresh);
			_chooseResources = AddButton("choose-resources", 30f, 682f, 148f, 34f, "选择资源", (UnityAction)delegate
			{
				_resourceSelectionMode = true;
				_positionsMode = false;
				_exchangeMode = false;
				ClearInputSelection();
				_dirty = true;
				Refresh();
			}, null, (Transform)(object)_sidebarRoot);
			_coinTradeTab = AddButton("coin-trading", 30f, 151f, 148f, 54f, "行情交易", (UnityAction)delegate
			{
				SetExchangeMode(exchange: false);
			}, null, (Transform)(object)_sidebarRoot);
			((Component)_coinTradeTab).GetComponentInChildren<Text>().fontSize = 17;
			string[] array2 = new string[5] { "一级兑换", "二级兑换", "三级兑换", "四级兑换", "五级兑换" };
			string[] array3 = new string[5] { "50A9EA", "E26060", "E8C14A", "AA76D3", "55BC7D" };
			Color color = default(Color);
			for (int num = 0; num < array2.Length; num++)
			{
				int tier = num + 1;
				Button val = AddButton("coin-exchange-" + tier, 30f, 253 + num * 46, 148f, 34f, array2[num], (UnityAction)delegate
				{
					_execute(MarketCommand.SelectExchangeTier, tier);
					_exchangePage = 0;
					SetExchangeMode(exchange: true);
				}, null, (Transform)(object)_sidebarRoot);
				Text componentInChildren = ((Component)val).GetComponentInChildren<Text>();
				componentInChildren.supportRichText = false;
				if (ColorUtility.TryParseHtmlString("#" + array3[num], ref color))
				{
					((Graphic)componentInChildren).color = color;
				}
				_exchangeTierButtons.Add(val);
			}
			_tradeRoot = _ui.Container("trading-view", (Transform)(object)_root, 0f, 0f, 1140f, 760f);
			BuildTrading();
			_exchangeRoot = _ui.Container("exchange-view", (Transform)(object)_root, 0f, 0f, 1140f, 760f);
			BuildExchange();
			_resourcePickerRoot = _ui.Container("resource-selection-view", (Transform)(object)_root, 0f, 0f, 1140f, 760f);
			_resourcePicker = new ResourceSelectionView(_ui, (Transform)(object)_resourcePickerRoot, delegate(int id, bool enabled)
			{
				_execute(enabled ? MarketCommand.EnableResource : MarketCommand.DisableResource, id);
				_dirty = true;
				Refresh();
			}, LeaveResourceSelection, Refresh);
			_positionsRoot = _ui.Container("all-holdings-view", (Transform)(object)_root, 0f, 0f, 1140f, 760f);
			_achievementsRoot = _ui.Container("achievements-view", (Transform)(object)_root, 0f, 0f, 1140f, 760f);
			_achievementsView = new AchievementsView(_ui, (Transform)(object)_achievementsRoot);
			_holdings = new HoldingsView(_ui, (Transform)(object)_positionsRoot, SelectMarket, delegate(int id)
			{
				_execute(MarketCommand.CloseMarketPosition, id);
				_dirty = true;
				Refresh();
			}, delegate
			{
				_execute(MarketCommand.CloseAllPositions, 0);
				_dirty = true;
				Refresh();
			});
			_status = _ui.Text("status", (Transform)(object)_root, 22f, 738f, 1096f, 20f, "", 11, Cyan, (TextAnchor)0);
			FitToParent();
			if (_pendingSettlement != null)
			{
				BuildSettlementPopup();
			}
		}

		private void BuildTrading()
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Expected O, but got Unknown
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Expected O, but got Unknown
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_033c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0351: Expected O, but got Unknown
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_05da: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ce: Expected O, but got Unknown
			//IL_07e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f9: Expected O, but got Unknown
			//IL_0832: Unknown result type (might be due to invalid IL or missing references)
			//IL_086e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0887: Unknown result type (might be due to invalid IL or missing references)
			//IL_0897: Expected O, but got Unknown
			//IL_08c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_08dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_08ec: Expected O, but got Unknown
			//IL_096e: Unknown result type (might be due to invalid IL or missing references)
			//IL_09aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_09c4: Expected O, but got Unknown
			//IL_09f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a0a: Expected O, but got Unknown
			//IL_0a3c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a7d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0abb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c25: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c3f: Expected O, but got Unknown
			//IL_0c6b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c85: Expected O, but got Unknown
			//IL_0d06: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d44: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d7f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d99: Expected O, but got Unknown
			//IL_0de1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e1a: Unknown result type (might be due to invalid IL or missing references)
			RectTransform tradeRoot = _tradeRoot;
			Panel("chart", 204f, 101f, 580f, 455f, (Transform)(object)tradeRoot);
			_chartTitle = _ui.Text("chart-heading", (Transform)(object)tradeRoot, 220f, 110f, 548f, 34f, "", 17, null, (TextAnchor)3);
			_chartRange = _ui.Text("chart-range", (Transform)(object)tradeRoot, 220f, 147f, 548f, 24f, "", 14, Muted, (TextAnchor)0);
			GameObject val = new GameObject("candlestick-chart", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(MarketCandleGraphic)
			});
			NativeUiFactory.Place((RectTransform)val.transform, (Transform)(object)tradeRoot, 222f, 180f, 488f, 215f);
			_chart = val.GetComponent<MarketCandleGraphic>();
			((Graphic)_chart).raycastTarget = false;
			for (int i = 0; i < _priceAxis.Length; i++)
			{
				_priceAxis[i] = _ui.Text("price-axis-" + i, (Transform)(object)tradeRoot, 715f, 178f + (float)(199 * i) / 3f, 55f, 20f, "", 11, Muted, (TextAnchor)3);
			}
			_liquidationBackground = _ui.Image("liquidation-tag", val.transform, 6f, 0f, 204f, 24f, new Color(0.035f, 0.055f, 0.07f, 0.95f));
			_liquidationLabel = _ui.Text("liquidation-price", ((Component)_liquidationBackground).transform, 5f, 0f, 194f, 24f, "", 12, Warning, (TextAnchor)3);
			_liquidationLabel.horizontalOverflow = (HorizontalWrapMode)1;
			_quote = _ui.Text("quote", (Transform)(object)tradeRoot, 220f, 409f, 548f, 30f, "", 15, null, (TextAnchor)0);
			_ui.Text("position-heading", (Transform)(object)tradeRoot, 220f, 449f, 548f, 27f, "当前持仓", 18, Muted, (TextAnchor)0);
			_positionText = _ui.Text("position", (Transform)(object)tradeRoot, 220f, 482f, 414f, 65f, "", 16, null, (TextAnchor)0);
			_positionText.supportRichText = true;
			_positionText.resizeTextForBestFit = true;
			_positionText.resizeTextMinSize = 13;
			_positionText.resizeTextMaxSize = 16;
			_positionText.verticalOverflow = (VerticalWrapMode)0;
			_closePosition = AddButton("close-position", 648f, 510f, 118f, 34f, "平仓", (UnityAction)delegate
			{
				Execute(MarketCommand.ClosePosition);
			}, null, (Transform)(object)tradeRoot);
			Panel("order", 800f, 101f, 320f, 455f, (Transform)(object)tradeRoot);
			_ui.Text("assets-heading", (Transform)(object)tradeRoot, 816f, 112f, 288f, 28f, "账户", 18, Muted, (TextAnchor)3);
			_assets = _ui.Text("assets", (Transform)(object)tradeRoot, 816f, 147f, 288f, 51f, "", 18, null, (TextAnchor)0);
			_assets.resizeTextForBestFit = true;
			_assets.resizeTextMinSize = 12;
			_assets.resizeTextMaxSize = 18;
			_assets.horizontalOverflow = (HorizontalWrapMode)0;
			_assets.verticalOverflow = (VerticalWrapMode)0;
			_floating = _ui.Text("floating-pnl", (Transform)(object)tradeRoot, 816f, 199f, 288f, 23f, "", 16, null, (TextAnchor)3);
			_floatingReturn = _ui.Text("floating-return", (Transform)(object)tradeRoot, 816f, 222f, 288f, 20f, "", 14, null, (TextAnchor)3);
			_realized = _ui.Text("realized-pnl", (Transform)(object)tradeRoot, 816f, 244f, 288f, 23f, "", 16, null, (TextAnchor)3);
			_returnRate = _ui.Text("return-rate", (Transform)(object)tradeRoot, 816f, 268f, 288f, 21f, "", 16, null, (TextAnchor)3);
			Text[] array = (Text[])(object)new Text[3] { _floating, _realized, _returnRate };
			foreach (Text obj in array)
			{
				obj.resizeTextForBestFit = true;
				obj.resizeTextMinSize = 12;
				obj.resizeTextMaxSize = 16;
				obj.verticalOverflow = (VerticalWrapMode)0;
			}
			_allocationLabel = _ui.Text("allocation-heading", (Transform)(object)tradeRoot, 816f, 294f, 288f, 22f, "", 16, null, (TextAnchor)3);
			_marginPreview = _ui.Text("margin-preview", (Transform)(object)tradeRoot, 816f, 319f, 288f, 24f, "", 19, Cyan, (TextAnchor)3);
			_allocationSlider = _ui.Slider("allocation", (Transform)(object)tradeRoot, 818f, 347f, 282f, 20f, 1, 100, _allocation, delegate(float value)
			{
				_allocation = Mathf.RoundToInt(value);
				_localError = "";
				_dirty = true;
			});
			int[] array2 = new int[4] { 25, 50, 75, 100 };
			for (int num2 = 0; num2 < array2.Length; num2++)
			{
				int percent = array2[num2];
				_allocationButtons.Add(AddButton("allocation-" + percent, 816 + num2 * 73, 375f, 65f, 26f, percent + "%", (UnityAction)delegate
				{
					_allocationSlider.value = percent;
					ClearInputSelection();
					_dirty = true;
				}, null, (Transform)(object)tradeRoot));
			}
			_leverageLabel = _ui.Text("leverage-label", (Transform)(object)tradeRoot, 816f, 407f, 288f, 24f, "", 16, null, (TextAnchor)3);
			_leverageSlider = _ui.Slider("leverage", (Transform)(object)tradeRoot, 818f, 438f, 282f, 24f, 1, 100, _selectedLeverage, delegate(float value)
			{
				_selectedLeverage = Mathf.RoundToInt(value);
				_execute(MarketCommand.ChangeLeverage, _selectedLeverage);
				_localError = "";
				_dirty = true;
			});
			int[] array3 = new int[4] { 2, 5, 10, 50 };
			for (int num3 = 0; num3 < array3.Length; num3++)
			{
				int leverage = array3[num3];
				AddButton("leverage-" + leverage, 816 + num3 * 73, 470f, 65f, 26f, leverage + "×", (UnityAction)delegate
				{
					_leverageSlider.value = leverage;
					ClearInputSelection();
					_dirty = true;
				}, null, (Transform)(object)tradeRoot);
			}
			_preview = _ui.Text("order-preview", (Transform)(object)tradeRoot, 816f, 500f, 288f, 19f, "", 12, Muted, (TextAnchor)0);
			_long = AddButton("long", 816f, 521f, 136f, 28f, "做多 / 开多", (UnityAction)delegate
			{
				Execute(MarketCommand.OpenLong);
			}, (Color?)new Color(0.45f, 0.22f, 0.22f, 1f), (Transform)(object)tradeRoot);
			_short = AddButton("short", 966f, 521f, 138f, 28f, "做空 / 开空", (UnityAction)delegate
			{
				Execute(MarketCommand.OpenShort);
			}, (Color?)new Color(0.18f, 0.39f, 0.28f, 1f), (Transform)(object)tradeRoot);
			_transferRoot = _ui.Container("item-transfers", (Transform)(object)tradeRoot, 0f, 0f, 1140f, 760f);
			Panel("transfer", 204f, 574f, 580f, 154f, (Transform)(object)_transferRoot);
			_transferTitle = _ui.Text("transfer-heading", (Transform)(object)_transferRoot, 220f, 584f, 270f, 28f, "", 16, Muted, (TextAnchor)0);
			_sourceBackpack = AddButton("source-backpack", 520f, 584f, 114f, 26f, "背包", (UnityAction)delegate
			{
				_execute(MarketCommand.UseBackpack, 0);
				_dirty = true;
				Refresh();
			}, null, (Transform)(object)_transferRoot);
			_sourceDelivery = AddButton("source-delivery", 646f, 584f, 120f, 26f, "交付平台", (UnityAction)delegate
			{
				_execute(MarketCommand.UseDelivery, 0);
				_dirty = true;
				Refresh();
			}, null, (Transform)(object)_transferRoot);
			_inventoryLabel = _ui.Text("inventory-label", (Transform)(object)_transferRoot, 220f, 617f, 280f, 20f, "背包可用", 12, Muted, (TextAnchor)0);
			_ui.Text("withdrawable-label", (Transform)(object)_transferRoot, 510f, 617f, 260f, 20f, "可提取", 12, Muted, (TextAnchor)0);
			_backpack = _ui.Text("backpack-available", (Transform)(object)_transferRoot, 220f, 636f, 260f, 26f, "0", 18, Cyan, (TextAnchor)0);
			_withdrawable = _ui.Text("withdrawable", (Transform)(object)_transferRoot, 510f, 636f, 260f, 26f, "0", 18, null, (TextAnchor)0);
			_depositSlider = _ui.Slider("deposit-amount", (Transform)(object)_transferRoot, 220f, 662f, 256f, 18f, 0, 1000, 0, delegate(float value)
			{
				SetTransferSlider(deposit: true, value);
			});
			_withdrawSlider = _ui.Slider("withdraw-amount", (Transform)(object)_transferRoot, 510f, 662f, 256f, 18f, 0, 1000, 0, delegate(float value)
			{
				SetTransferSlider(deposit: false, value);
			});
			_depositInput = TransferInput((Transform)(object)_transferRoot, 220f, 686f, 118f, _depositValue, delegate(string value)
			{
				SetTransferInput(deposit: true, value);
			});
			_withdrawInput = TransferInput((Transform)(object)_transferRoot, 510f, 686f, 118f, _withdrawValue, delegate(string value)
			{
				SetTransferInput(deposit: false, value);
			});
			_deposit = AddButton("deposit", 350f, 686f, 126f, 34f, "存入", (UnityAction)delegate
			{
				Execute(MarketCommand.Deposit);
			}, null, (Transform)(object)_transferRoot);
			_withdraw = AddButton("withdraw", 640f, 686f, 126f, 34f, "提取", (UnityAction)delegate
			{
				Execute(MarketCommand.Withdraw);
			}, null, (Transform)(object)_transferRoot);
			_coinFunding = _ui.Container("coin-funding", (Transform)(object)tradeRoot, 0f, 0f, 1140f, 760f);
			Panel("coin-balance", 204f, 574f, 580f, 154f, (Transform)(object)_coinFunding);
			_ui.Text("coin-label", (Transform)(object)_coinFunding, 220f, 592f, 300f, 28f, "可用建筑币", 14, Muted, (TextAnchor)0);
			_coinBalance = _ui.Text("coin-balance-value", (Transform)(object)_coinFunding, 220f, 634f, 340f, 46f, "", 24, Cyan, (TextAnchor)0);
			AddButton("open-exchange", 596f, 674f, 170f, 36f, "前往建筑兑换", (UnityAction)delegate
			{
				SetExchangeMode(exchange: true);
			}, null, (Transform)(object)_coinFunding);
			Panel("events", 800f, 574f, 320f, 154f, (Transform)(object)tradeRoot);
			_ui.Text("events-heading", (Transform)(object)tradeRoot, 816f, 584f, 288f, 28f, "操作记录", 16, Muted, (TextAnchor)0);
			_events = _ui.Text("events", (Transform)(object)tradeRoot, 816f, 616f, 288f, 108f, "", 12, Muted, (TextAnchor)0);
			_events.lineSpacing = 0.9f;
			_events.horizontalOverflow = (HorizontalWrapMode)1;
		}

		private void BuildExchange()
		{
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Expected O, but got Unknown
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_031d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0331: Expected O, but got Unknown
			//IL_0358: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Expected O, but got Unknown
			//IL_038e: Unknown result type (might be due to invalid IL or missing references)
			//IL_040d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0486: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b6: Expected O, but got Unknown
			//IL_05e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_060b: Expected O, but got Unknown
			RectTransform exchangeRoot = _exchangeRoot;
			Panel("exchange-list", 204f, 101f, 580f, 627f, (Transform)(object)exchangeRoot);
			Panel("exchange-detail", 800f, 101f, 320f, 627f, (Transform)(object)exchangeRoot);
			_ui.Text("exchange-title", (Transform)(object)exchangeRoot, 220f, 111f, 300f, 32f, "建筑兑换", 18, null, (TextAnchor)3);
			_exchangePageText = _ui.Text("exchange-page", (Transform)(object)exchangeRoot, 590f, 114f, 176f, 28f, "", 13, Muted, (TextAnchor)5);
			for (int i = 0; i < 28; i++)
			{
				ExchangeCell cell = new ExchangeCell();
				float x = 220 + i % 4 * 137;
				float y = 155 + i / 4 * 72;
				cell.Button = AddButton("exchange-item-" + i, x, y, 128f, 64f, "", (UnityAction)delegate
				{
					if (cell.ItemId > 0)
					{
						_execute(MarketCommand.SelectExchangeItem, cell.ItemId);
						_dirty = true;
						Refresh();
					}
				}, null, (Transform)(object)exchangeRoot);
				cell.Background = _ui.Image("inventory-background", ((Component)cell.Button).transform, 3f, 3f, 122f, 58f, new Color(0.035f, 0.055f, 0.075f, 1f));
				((Graphic)cell.Background).raycastTarget = false;
				cell.Icon = _ui.Image("icon", ((Component)cell.Button).transform, 7f, 6f, 30f, 30f, Color.white);
				cell.Name = _ui.Text("name", ((Component)cell.Button).transform, 42f, 3f, 81f, 34f, "", 11, null, (TextAnchor)3);
				cell.Name.resizeTextForBestFit = true;
				cell.Name.resizeTextMinSize = 9;
				cell.Name.resizeTextMaxSize = 11;
				cell.Name.verticalOverflow = (VerticalWrapMode)0;
				cell.Value = _ui.Text("value", ((Component)cell.Button).transform, 7f, 40f, 114f, 20f, "", 11, Muted, (TextAnchor)0);
				_exchangeCells.Add(cell);
			}
			AddButton("exchange-prev", 220f, 680f, 100f, 32f, "上一页", (UnityAction)delegate
			{
				_exchangePage = Math.Max(0, _exchangePage - 1);
				_dirty = true;
				Refresh();
			}, null, (Transform)(object)exchangeRoot);
			AddButton("exchange-next", 666f, 680f, 100f, 32f, "下一页", (UnityAction)delegate
			{
				_exchangePage++;
				_dirty = true;
				Refresh();
			}, null, (Transform)(object)exchangeRoot);
			_exchangeIcon = _ui.Image("selected-building", (Transform)(object)exchangeRoot, 928f, 126f, 64f, 64f, Color.white);
			_exchangeIcon.preserveAspect = true;
			_exchangeName = _ui.Text("building-name", (Transform)(object)exchangeRoot, 816f, 211f, 288f, 46f, "", 19, null, (TextAnchor)4);
			_exchangeValue = _ui.Text("building-value", (Transform)(object)exchangeRoot, 816f, 271f, 288f, 44f, "", 15, Muted, (TextAnchor)0);
			_exchangeBackpack = _ui.Text("building-backpack", (Transform)(object)exchangeRoot, 816f, 329f, 288f, 32f, "", 16, null, (TextAnchor)0);
			_exchangeWallet = _ui.Text("exchange-wallet", (Transform)(object)exchangeRoot, 816f, 373f, 288f, 44f, "", 17, Cyan, (TextAnchor)0);
			_ui.Text("exchange-quantity-heading", (Transform)(object)exchangeRoot, 816f, 435f, 288f, 26f, "兑换数量", 14, Muted, (TextAnchor)0);
			_exchangeQuantityInput = TransferInput((Transform)(object)exchangeRoot, 816f, 471f, 288f, _exchangeQuantityValue, delegate(string value)
			{
				_exchangeQuantityValue = value;
			});
			_exchangeQuantitySlider = _ui.Slider("exchange-quantity", (Transform)(object)exchangeRoot, 816f, 507f, 288f, 18f, 0, 1000, 0, delegate(float value)
			{
				_exchangeQuantityValue = TransferAmounts.FromSlider(Mathf.RoundToInt(value), _exchangeMaximum).ToString(CultureInfo.InvariantCulture);
				_exchangeQuantityInput.SetTextWithoutNotify(_exchangeQuantityValue);
				_localError = "";
				_dirty = true;
			});
			_exchangeTotal = _ui.Text("exchange-total", (Transform)(object)exchangeRoot, 816f, 527f, 288f, 78f, "", 15, null, (TextAnchor)0);
			_exchangeBuy = AddButton("exchange-buy", 816f, 622f, 288f, 36f, "建筑币 → 物品", (UnityAction)delegate
			{
				Execute(MarketCommand.BuyBuilding);
			}, null, (Transform)(object)exchangeRoot);
			_exchangeSell = AddButton("exchange-sell", 816f, 676f, 288f, 36f, "物品 → 建筑币", (UnityAction)delegate
			{
				Execute(MarketCommand.SellBuilding);
			}, (Color?)new Color(0.24f, 0.36f, 0.33f, 1f), (Transform)(object)exchangeRoot);
		}

		private InputField TransferInput(Transform parent, float x, float y, float width, string initial, Action<string> save)
		{
			InputField obj = _ui.QuantityInput(parent, x, y, width, 34f);
			obj.text = initial;
			((UnityEvent<string>)(object)obj.onValueChanged).AddListener((UnityAction<string>)delegate(string value)
			{
				save(value);
				_localError = "";
				_dirty = true;
			});
			((UnityEvent<string>)(object)obj.onEndEdit).AddListener((UnityAction<string>)OnInputEnded);
			return obj;
		}

		private void Refresh()
		{
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_037f: 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_0424: Unknown result type (might be due to invalid IL or missing references)
			//IL_043f: 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_04c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_056b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0550: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0727: Unknown result type (might be due to invalid IL or missing references)
			//IL_0715: Unknown result type (might be due to invalid IL or missing references)
			//IL_09f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_09d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a3c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a21: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c17: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c1e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0dae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0dfc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e09: Unknown result type (might be due to invalid IL or missing references)
			((Component)_achievementsRoot).gameObject.SetActive(_achievementsMode);
			((Graphic)((Selectable)_achievementsButton).image).color = (_achievementsMode ? new Color(0.25f, 0.43f, 0.51f, 1f) : new Color(0.14f, 0.24f, 0.29f, 1f));
			if (_achievementsMode)
			{
				((Component)_tradeRoot).gameObject.SetActive(false);
				((Component)_exchangeRoot).gameObject.SetActive(false);
				((Component)_resourcePickerRoot).gameObject.SetActive(false);
				((Component)_sidebarRoot).gameObject.SetActive(false);
				((Component)_positionsRoot).gameObject.SetActive(false);
				((Graphic)((Selectable)_allPositionsButton).image).color = new Color(0.14f, 0.24f, 0.29f, 1f);
				_status.text = "";
				_achievementsView.Refresh(_achievements());
				return;
			}
			MarketSnapshot marketSnapshot;
			try
			{
				marketSnapshot = _snapshot(_allocation);
			}
			catch (Exception ex)
			{
				_status.text = "读取失败:" + ex.Message;
				((Graphic)_status).color = Warning;
				SetCommandsEnabled(open: false, deposit: false, withdraw: false);
				((Selectable)_closePosition).interactable = false;
				return;
			}
			if (marketSnapshot == null)
			{
				_status.text = "市场尚未载入";
				SetCommandsEnabled(open: false, deposit: false, withdraw: false);
				((Selectable)_closePosition).interactable = false;
				return;
			}
			_lastState = marketSnapshot;
			string itemName = marketSnapshot.ItemName;
			_chartTitle.text = itemName;
			_transferTitle.text = itemName + "存取";
			MarketCategory marketCategory = _categoryOverride ?? MarketCatalog.Category(marketSnapshot.ItemId);
			bool flag = MarketCatalog.IsSelectableCategory(marketCategory);
			bool flag2 = marketCategory == MarketCategory.BuildingCurrency;
			if (!flag2)
			{
				_exchangeMode = false;
			}
			if (!flag)
			{
				_resourceSelectionMode = false;
			}
			if (flag && (!marketSnapshot.MarketEnabled || MarketCatalog.Category(marketSnapshot.ItemId) != marketCategory) && !_positionsMode)
			{
				_resourceSelectionMode = true;
			}
			((Component)_tradeRoot).gameObject.SetActive(!_exchangeMode && !_positionsMode && !_resourceSelectionMode);
			((Component)_exchangeRoot).gameObject.SetActive(_exchangeMode && !_positionsMode && !_resourceSelectionMode);
			((Component)_resourcePickerRoot).gameObject.SetActive(_resourceSelectionMode && !_positionsMode);
			((Component)_resourceSidebar.Root).gameObject.SetActive(flag);
			((Component)_chooseResources).gameObject.SetActive(flag);
			if (flag)
			{
				((Component)_chooseResources).GetComponentInChildren<Text>().text = "选择" + MarketCatalog.CategoryName(marketCategory);
			}
			if (flag)
			{
				_resourceSidebar.Refresh(marketSnapshot, marketCategory);
			}
			((Component)_sidebarRoot).gameObject.SetActive(!_positionsMode);
			((Component)_positionsRoot).gameObject.SetActive(_positionsMode);
			((Graphic)((Selectable)_allPositionsButton).image).color = (_positionsMode ? new Color(0.25f, 0.43f, 0.51f, 1f) : new Color(0.14f, 0.24f, 0.29f, 1f));
			((Component)_transferRoot).gameObject.SetActive(!flag2);
			((Component)_coinFunding).gameObject.SetActive(flag2);
			_coinBalance.text = Amount(marketSnapshot.BuildingCoinBalance);
			((Component)_coinTradeTab).gameObject.SetActive(flag2);
			for (int i = 0; i < _exchangeTierButtons.Count; i++)
			{
				Button obj = _exchangeTierButtons[i];
				((Component)obj).gameObject.SetActive(flag2);
				((Graphic)((Selectable)obj).image).color = ((_exchangeMode && marketSnapshot.ExchangeTier == i + 1) ? new Color(0.25f, 0.43f, 0.51f, 1f) : new Color(0.14f, 0.24f, 0.29f, 1f));
			}
			foreach (KeyValuePair<MarketCategory, Button> categoryButton in _categoryButtons)
			{
				((Graphic)((Selectable)categoryButton.Value).image).color = ((!_positionsMode && categoryButton.Key == marketCategory) ? new Color(0.25f, 0.43f, 0.51f, 1f) : new Color(0.14f, 0.24f, 0.29f, 1f));
			}
			foreach (KeyValuePair<int, Button> marketButton in _marketButtons)
			{
				((Component)marketButton.Value).gameObject.SetActive(MarketCatalog.Category(marketButton.Key) == marketCategory);
				((Graphic)((Selectable)marketButton.Value).image).color = ((marketButton.Key == marketSnapshot.ItemId) ? new Color(0.25f, 0.43f, 0.51f, 1f) : new Color(0.14f, 0.24f, 0.29f, 1f));
			}
			foreach (MarketOption market in marketSnapshot.Markets)
			{
				if (_marketIcons.TryGetValue(market.ItemId, out var value))
				{
					value.sprite = market.Icon;
					((Behaviour)value).enabled = (Object)(object)market.Icon != (Object)null;
				}
			}
			_assets.text = "可用\u3000\u3000" + Amount(marketSnapshot.AvailableBalance) + "\n总权益\u3000" + Amount(marketSnapshot.Equity);
			_floating.text = "浮动盈亏    " + Signed(marketSnapshot.UnrealizedPnL);
			_floatingReturn.text = "收益率    " + MoneyDisplay.Percent(marketSnapshot.UnrealizedReturnRatio);
			_realized.text = "累计盈亏    " + Signed(marketSnapshot.RealizedPnL);
			_returnRate.text = "收益率    " + MoneyDisplay.Percent(marketSnapshot.ReturnRatio);
			((Graphic)_floating).color = PnLColor(marketSnapshot.UnrealizedPnL);
			((Graphic)_floatingReturn).color = (marketSnapshot.UnrealizedReturnRatio.HasValue ? PnLColor(marketSnapshot.UnrealizedPnL) : Muted);
			((Graphic)_realized).color = PnLColor(marketSnapshot.RealizedPnL);
			((Graphic)_returnRate).color = (marketSnapshot.ReturnRatio.HasValue ? PnLColor(marketSnapshot.ReturnRatio.Value) : Muted);
			_quote.text = "买入 " + Price(marketSnapshot.Ask) + "     卖出 " + Price(marketSnapshot.Bid) + "     费率 " + (marketSnapshot.FeeRate * 100m).ToString("0.00") + "%";
			_allocationLabel.text = "仓位比例   " + _allocation + "%";
			_selectedLeverage = marketSnapshot.SelectedLeverage;
			_leverageLabel.text = "杠杆   " + _selectedLeverage + "×";
			_leverageSlider.SetValueWithoutNotify((float)_selectedLeverage);
			_marginPreview.text = "保证金  " + Amount(marketSnapshot.OrderMargin);
			_preview.text = "开仓费 " + Amount(marketSnapshot.OpenFee);
			_positionText.text = (marketSnapshot.HasPosition ? (NativeUiFactory.DirectionText(marketSnapshot.PositionDirection) + "  " + marketSnapshot.PositionLeverage + "×   入场 " + Price(marketSnapshot.EntryPrice) + "\n保证金 " + Amount(marketSnapshot.PositionMargin) + "    爆仓价 " + Price(marketSnapshot.LiquidationPrice) + "\n持有时间 " + marketSnapshot.HeldCandles.Value.ToString("N0", CultureInfo.InvariantCulture)) : "空仓");
			_backpack.text = marketSnapshot.TransferAvailable.ToString("N0");
			_inventoryLabel.text = ((marketSnapshot.ItemId == 1099) ? "沙土可用" : ((!marketSnapshot.UseDelivery) ? "背包可用" : (marketSnapshot.DeliveryBound ? ("平台可用 · " + marketSnapshot.DeliveryName) : "请在交付塔中设置该物品")));
			((Component)_sourceBackpack).GetComponentInChild

plugins/FXDSP/FXDSP.DeliveryBootstrap.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using FXDSP.Core;
using HarmonyLib;
using UnityEngine;
using UnityEngine.UI.Youthcat;
using xiaoye97;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("FXDSP.DeliveryBootstrap")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+c79acf0c7eb1a3efb6903aff5c793433ad2619ae")]
[assembly: AssemblyProduct("FXDSP.DeliveryBootstrap")]
[assembly: AssemblyTitle("FXDSP.DeliveryBootstrap")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace FXDSP.Core
{
	public sealed class DeliveryRecipeDefinition
	{
		public readonly int ItemId;

		public readonly int BaseItemId;

		public readonly string Name;

		public readonly string Description;

		public int InputCount
		{
			get
			{
				if (ItemId != 11702)
				{
					return 5;
				}
				return 4;
			}
		}

		public int TimeSpend => 3600;

		public bool Handcraft => false;

		public DeliveryRecipeDefinition(int itemId, int baseItemId, string name, string description)
		{
			ItemId = itemId;
			BaseItemId = baseItemId;
			Name = name;
			Description = description;
		}
	}
	public static class DeliveryRecipes
	{
		public static readonly IReadOnlyList<DeliveryRecipeDefinition> Definitions = Array.AsReadOnly(new DeliveryRecipeDefinition[2]
		{
			new DeliveryRecipeDefinition(11702, 2103, "行星级交付平台", "在行星物流塔基础上改造而成的现货交付平台,具备原行星物流塔的全部功能,并拥有深不可测的储存容量以应对大单交割。平台槽位设置物品后即唯一绑定交易系统,可在交易面板中从平台中存入或提取物资,该物品不能再被第二个交付平台选中。"),
			new DeliveryRecipeDefinition(11703, 2104, "星际交付平台", "在星际物流塔基础上改造而成的现货交付平台,具备原星际物流塔的全部功能,并拥有深不可测的储存容量以应对大单交割。平台槽位设置物品后即唯一绑定交易系统,可在交易面板中从平台存入或提取物资,该物品不能再被第二个交付平台选中。")
		});

		public static int AllocateGrid(ISet<int> occupied)
		{
			for (int num = 8; num >= 1; num--)
			{
				for (int i = 1; i <= 14; i++)
				{
					int num2 = 2000 + num * 100 + i;
					if (occupied.Add(num2))
					{
						return num2;
					}
				}
			}
			throw new InvalidOperationException("制作面板的建筑分页已满,无法放置交付平台配方。");
		}
	}
	public sealed class TradeTechnology
	{
		public int Id;

		public int Previous;

		public int Cost;

		public int IconItemId;

		public int Level;

		public int ExchangeTier;

		public string Name;

		public string Description;

		public string Conclusion;

		public string UnlockText;

		public int[] Items;

		public bool Upgrade;

		public string InlineIconTag => "fx" + Id.ToString(CultureInfo.InvariantCulture);

		public string RegistrationName
		{
			get
			{
				if (!Upgrade)
				{
					return Name;
				}
				return Name + " " + Level + " 级";
			}
		}

		public bool ImplicitPrevious
		{
			get
			{
				if (Upgrade)
				{
					return Previous == 1951;
				}
				return false;
			}
		}

		public long HashNeeded => (long)Cost * 36L;

		public int[] ItemPoints => Items.Select((int item) => 100).ToArray();
	}
	public sealed class TradeResearchState
	{
		public bool Access;

		public int FeeLevel;

		public readonly bool[] Exchange = new bool[6];

		public decimal TradingFee => TradeResearch.TradingFee(FeeLevel);

		public decimal ExchangeFee => TradeResearch.ExchangeFee(FeeLevel);

		public bool CanExchange(int tier)
		{
			if (Access && tier >= 1 && tier <= 5)
			{
				return Exchange[tier];
			}
			return false;
		}

		public void RequireAccess()
		{
			if (!Access)
			{
				throw new InvalidOperationException("请先研究“交易系统”。");
			}
		}

		public void RequireExchange(int tier)
		{
			RequireAccess();
			if (!CanExchange(tier))
			{
				throw new InvalidOperationException("请先研究“建筑兑换(" + tier + ")”。");
			}
		}
	}
	public static class TradeResearch
	{
		public const int AccessTech = 1951;

		private static readonly decimal[] TradingRates = new decimal[7] { 0.003m, 0.002m, 0.001m, 0.0005m, 0.0002m, 0.0001m, 0m };

		private static readonly decimal[] ExchangeRates = new decimal[7] { 0.10m, 0.10m, 0.08m, 0.06m, 0.04m, 0.02m, 0m };

		public static IReadOnlyList<TradeTechnology> Definitions { get; } = Build();

		public static int ExchangeTech(int tier)
		{
			return 7700 + tier;
		}

		public static int FeeTech(int level)
		{
			return 7800 + level;
		}

		public static decimal TradingFee(int level)
		{
			return TradingRates[Math.Max(0, Math.Min(6, level))];
		}

		public static decimal ExchangeFee(int level)
		{
			return ExchangeRates[Math.Max(0, Math.Min(6, level))];
		}

		public static TradeResearchState Read(Func<int, bool> unlocked)
		{
			TradeResearchState tradeResearchState = new TradeResearchState
			{
				Access = unlocked(1951)
			};
			for (int i = 1; i <= 5; i++)
			{
				tradeResearchState.Exchange[i] = unlocked(ExchangeTech(i));
			}
			for (int j = 1; j <= 6; j++)
			{
				if (!tradeResearchState.Access)
				{
					break;
				}
				if (!unlocked(FeeTech(j)))
				{
					break;
				}
				tradeResearchState.FeeLevel = j;
			}
			return tradeResearchState;
		}

		public static TradeTechnology Find(int id)
		{
			return Definitions.FirstOrDefault((TradeTechnology definition) => definition.Id == id);
		}

		private static IReadOnlyList<TradeTechnology> Build()
		{
			List<TradeTechnology> list = new List<TradeTechnology>();
			list.Add(new TradeTechnology
			{
				Id = 1951,
				Name = "交易系统",
				UnlockText = "开放DSP交易平台",
				Description = "老实拍工厂很枯燥吧?创建DSP交易账户,接入主脑交易平台,FX战士伊卡洛斯!",
				Conclusion = "开放DSP交易平台",
				Items = new int[2] { 1001, 1002 },
				Cost = 10,
				IconItemId = 1002
			});
			List<TradeTechnology> list2 = list;
			int[] array = new int[5] { 200, 400, 1000, 2000, 4000 };
			for (int i = 1; i <= 5; i++)
			{
				list2.Add(new TradeTechnology
				{
					Id = ExchangeTech(i),
					Previous = ((i == 1) ? 1951 : ExchangeTech(i - 1)),
					Upgrade = true,
					Level = i,
					ExchangeTier = i,
					Name = "建筑兑换",
					Description = "在建筑币市场中自由交易兑换各种建筑,或许也是一种建筑超市。",
					UnlockText = "开放建筑币市场" + i + "级建筑交易",
					Conclusion = "开放建筑币市场" + i + "级建筑交易",
					Items = new int[1] { 6000 + i },
					Cost = array[i - 1],
					IconItemId = 6000 + i
				});
			}
			int[] array2 = new int[6] { 400, 800, 1200, 1600, 2000, 4000 };
			for (int j = 1; j <= 6; j++)
			{
				string text = "交易手续费降低至" + (TradingFee(j) * 100m).ToString("0.##", CultureInfo.InvariantCulture) + "%\n建筑兑换双向手续费降低至" + (ExchangeFee(j) * 100m).ToString("0.##", CultureInfo.InvariantCulture) + "%";
				list2.Add(new TradeTechnology
				{
					Id = FeeTech(j),
					Previous = ((j == 1) ? 1951 : FeeTech(j - 1)),
					Upgrade = true,
					Level = j,
					Name = "交易效率",
					UnlockText = text,
					Conclusion = text,
					Description = ((j == 6) ? "感谢你对主脑作出的贡献,免除交易手续费!" : "为奖励伊卡洛斯上传矩阵提供的算力,降低交易佣金。"),
					Items = ((j == 6) ? new int[1] { 6006 } : Enumerable.Range(6001, j).ToArray()),
					Cost = array2[j - 1],
					IconItemId = ((j == 6) ? 6006 : (6000 + j))
				});
			}
			return list2.AsReadOnly();
		}
	}
	public static class PrototypeOwnership
	{
		private static string Key(string kind, int id)
		{
			return "FXDSP.PrototypeOwner.v1." + kind + "." + id;
		}

		public static void Mark(string kind, int id, object prototype)
		{
			if (prototype == null)
			{
				throw new ArgumentNullException("prototype");
			}
			AppDomain.CurrentDomain.SetData(Key(kind, id), prototype);
		}

		public static bool Owns(string kind, int id, object prototype)
		{
			if (prototype != null)
			{
				return AppDomain.CurrentDomain.GetData(Key(kind, id)) == prototype;
			}
			return false;
		}
	}
	public static class TextLocalization
	{
		private sealed class Node
		{
			internal readonly Dictionary<char, Node> Children = new Dictionary<char, Node>();

			internal string Value;
		}

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

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

		private static readonly Node Root = new Node();

		private static bool _loaded;

		private static bool _english;

		public static bool English
		{
			get
			{
				return _english;
			}
			set
			{
				if (_english != value)
				{
					_english = value;
					Cache.Clear();
				}
			}
		}

		public static int EntryCount
		{
			get
			{
				Load();
				return Entries.Count;
			}
		}

		public static string Translate(string source)
		{
			if (!_english || string.IsNullOrEmpty(source))
			{
				return source ?? "";
			}
			Load();
			if (Entries.TryGetValue(source, out var value) || Cache.TryGetValue(source, out value))
			{
				return value;
			}
			bool flag = false;
			foreach (char c in source)
			{
				if (c >= '一' && c <= '鿿')
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				return source;
			}
			StringBuilder stringBuilder = new StringBuilder();
			int num = 0;
			while (num < source.Length)
			{
				Node value2 = Root;
				string text = null;
				int num2 = num;
				for (int j = num; j < source.Length && value2.Children.TryGetValue(source[j], out value2); j++)
				{
					if (value2.Value != null)
					{
						text = value2.Value;
						num2 = j + 1;
					}
				}
				if (text == null)
				{
					stringBuilder.Append(source[num]);
					num++;
				}
				else
				{
					stringBuilder.Append(text);
					num = num2;
				}
			}
			value = stringBuilder.ToString();
			if (Cache.Count >= 512)
			{
				Cache.Clear();
			}
			Cache[source] = value;
			return value;
		}

		public static void RegisterNativeName(string source, string translation)
		{
			if (string.IsNullOrEmpty(source) || string.IsNullOrEmpty(translation) || source == translation)
			{
				return;
			}
			Load();
			if (Entries.ContainsKey(source))
			{
				Entries[source] = translation;
				Node node = Root;
				foreach (char key in source)
				{
					node = node.Children[key];
				}
				node.Value = translation;
			}
			else
			{
				Add(source, translation);
			}
			Cache.Clear();
		}

		private static void Load()
		{
			if (_loaded)
			{
				return;
			}
			using (Stream stream = typeof(TextLocalization).Assembly.GetManifestResourceStream("FXDSP.Localization.en-US.tsv"))
			{
				if (stream == null)
				{
					throw new InvalidOperationException("English localization resource is missing.");
				}
				using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8);
				string text;
				while ((text = streamReader.ReadLine()) != null)
				{
					if (text.Length != 0 && text[0] != '#')
					{
						int num = text.IndexOf('\t');
						if (num < 1)
						{
							throw new InvalidDataException("Invalid localization entry.");
						}
						Add(Decode(text.Substring(0, num)), Decode(text.Substring(num + 1)));
					}
				}
			}
			_loaded = true;
		}

		private static void Add(string source, string target)
		{
			Entries.Add(source, target);
			Node node = Root;
			foreach (char key in source)
			{
				if (!node.Children.TryGetValue(key, out var value))
				{
					value = (node.Children[key] = new Node());
				}
				node = value;
			}
			node.Value = target;
		}

		private static string Decode(string text)
		{
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < text.Length; i++)
			{
				char c = text[i];
				if (c == '\\' && i + 1 < text.Length)
				{
					char c2 = text[++i];
					switch (c2)
					{
					case 'n':
						stringBuilder.Append('\n');
						break;
					case 'r':
						stringBuilder.Append('\r');
						break;
					case 't':
						stringBuilder.Append('\t');
						break;
					case '\\':
						stringBuilder.Append('\\');
						break;
					default:
						stringBuilder.Append('\\');
						stringBuilder.Append(c2);
						break;
					}
				}
				else
				{
					stringBuilder.Append(c);
				}
			}
			return stringBuilder.ToString();
		}
	}
}
namespace FXDSP.DeliveryBootstrap
{
	[BepInPlugin("dspfx.delivery.prototypes", "FXDSP Delivery Buildings", "1.0.0")]
	[BepInDependency("me.xiaoye97.plugin.Dyson.LDBTool", "3.0.3")]
	public sealed class DeliveryBootstrap : BaseUnityPlugin
	{
		private static readonly int[] Ids = new int[2] { 11702, 11703 };

		private static readonly int[] Bases = new int[2] { 2103, 2104 };

		private Harmony _harmony;

		private bool _registered;

		private int _language = int.MinValue;

		private static readonly MethodInfo CloneMethod = typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic);

		private static T Clone<T>(T source)
		{
			return (T)CloneMethod.Invoke(source, null);
		}

		private void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			_harmony = new Harmony("dspfx.delivery.prototypes.localization");
			_harmony.PatchAll(typeof(DeliveryBootstrap).Assembly);
			LDBTool.PostAddDataAction = (Action)Delegate.Combine(LDBTool.PostAddDataAction, new Action(Register));
			LDBTool.EditDataAction = (Action<Proto>)Delegate.Combine(LDBTool.EditDataAction, new Action<Proto>(FinalizePrototype));
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Delivery prototypes scheduled; reloadable trading logic remains in scripts/FXDSP.dll.");
		}

		private void Register()
		{
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Expected O, but got Unknown
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			int[] ids = Ids;
			for (int i = 0; i < ids.Length; i++)
			{
				int num = ids[i];
				if (((ProtoSet<ItemProto>)(object)LDB.items).Select(num) != null || ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(num) != null)
				{
					throw new InvalidOperationException("FXDSP delivery prototype ID conflict: " + num);
				}
			}
			foreach (TradeTechnology definition in TradeResearch.Definitions)
			{
				if (((ProtoSet<TechProto>)(object)LDB.techs).Select(definition.Id) != null)
				{
					throw new InvalidOperationException("FXDSP technology ID conflict: " + definition.Id);
				}
			}
			try
			{
				TechnologyIcons.Load();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded 12 custom FXDSP technology icons.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Custom technology icons unavailable; using native fallback icons: " + ex));
			}
			TechnologyRegistration.Register();
			HashSet<int> occupied = new HashSet<int>(((ProtoSet<RecipeProto>)(object)LDB.recipes).dataArray.Select((RecipeProto recipe) => recipe.GridIndex).Concat(((ProtoSet<ItemProto>)(object)LDB.items).dataArray.Select((ItemProto item) => item.GridIndex)));
			foreach (DeliveryRecipeDefinition definition2 in DeliveryRecipes.Definitions)
			{
				int itemId = definition2.ItemId;
				if (((ProtoSet<ItemProto>)(object)LDB.items).Select(itemId) != null || ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(itemId) != null)
				{
					throw new InvalidOperationException("FXDSP delivery prototype ID conflict: " + itemId);
				}
				ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items).Select(definition2.BaseItemId);
				val.FindPreTech();
				ItemProto val2 = Clone<ItemProto>(val);
				((Proto)val2).ID = itemId;
				((Proto)val2).Name = definition2.Name;
				((Proto)val2).name = definition2.Name;
				string description = (val2.description = definition2.Description);
				val2.Description = description;
				int gridIndex = (val2.GridIndex = DeliveryRecipes.AllocateGrid(occupied));
				val2.BuildIndex = 0;
				val2.Upgrades = new int[0];
				val2.PreTechOverride = ((val.preTech != null) ? ((Proto)val.preTech).ID : 0);
				val2.prefabDesc = Clone<PrefabDesc>(val.prefabDesc);
				val2.prefabDesc.stationMaxItemCount = 1000000;
				RecipeProto val3 = new RecipeProto();
				((Proto)val3).ID = itemId;
				((Proto)val3).Name = definition2.Name;
				((Proto)val3).name = definition2.Name;
				val3.Description = definition2.Description;
				val3.Type = (ERecipeType)4;
				val3.Handcraft = definition2.Handcraft;
				val3.Explicit = false;
				val3.TimeSpend = definition2.TimeSpend;
				val3.Items = new int[1] { definition2.BaseItemId };
				val3.ItemCounts = new int[1] { definition2.InputCount };
				val3.Results = new int[1] { itemId };
				val3.ResultCounts = new int[1] { 1 };
				val3.GridIndex = gridIndex;
				val3.IconPath = val.IconPath;
				val3.preTech = val.preTech;
				RecipeProto val4 = (val2.maincraft = val3);
				val2.handcraft = null;
				val2.recipes = new List<RecipeProto> { val4 };
				val2.handcrafts = new List<RecipeProto>();
				val2.makes = new List<RecipeProto>();
				val2.rawMats = new List<IDCNTINC>();
				val2.maincraftProductCount = 1;
				val2.handcraftProductCount = 0;
				LDBTool.PostAddProto((Proto)(object)val2);
				LDBTool.PostAddProto((Proto)(object)val4);
				if (val2.GridIndex <= 0)
				{
					val2.GridIndex = gridIndex;
				}
				if (val4.GridIndex <= 0)
				{
					val4.GridIndex = gridIndex;
				}
				if (((Proto)val2).ID != itemId || ((Proto)val4).ID != itemId)
				{
					throw new InvalidOperationException("FXDSP delivery IDs must remain stable in LDBTool configuration.");
				}
				PrototypeOwnership.Mark("item", itemId, val2);
				PrototypeOwnership.Mark("recipe", itemId, val4);
				if (val.preTech != null)
				{
					val.preTech.UnlockRecipes = val.preTech.UnlockRecipes.Concat(new int[1] { itemId }).Distinct().ToArray();
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Registered two assembler-only FXDSP delivery towers.");
			_registered = true;
		}

		private static void FinalizePrototype(Proto proto)
		{
			TechnologyRegistration.Finalize(proto);
			RecipeProto val = (RecipeProto)(object)((proto is RecipeProto) ? proto : null);
			if (val != null && Ids.Contains(((Proto)val).ID) && PrototypeOwnership.Owns("recipe", ((Proto)val).ID, val))
			{
				val.Preload(Array.IndexOf(((ProtoSet<RecipeProto>)(object)LDB.recipes).dataArray, val));
				PrototypeTranslation.Apply((Proto)(object)val);
				return;
			}
			ItemProto val2 = (ItemProto)(object)((proto is ItemProto) ? proto : null);
			if (val2 != null)
			{
				int num = Array.IndexOf(Ids, ((Proto)val2).ID);
				if (num >= 0 && PrototypeOwnership.Owns("item", ((Proto)val2).ID, val2))
				{
					ItemProto val3 = ((ProtoSet<ItemProto>)(object)LDB.items).Select(Bases[num]);
					val2.DescFields = (int[])val3.DescFields.Clone();
					val2.HpMax = val3.HpMax;
					val2.prefabDesc = Clone<PrefabDesc>(val3.prefabDesc);
					val2.prefabDesc.stationMaxItemCount = 1000000;
					PrototypeTranslation.Apply((Proto)(object)val2);
				}
			}
		}

		private void LateUpdate()
		{
			if (_registered && Localization.Loaded && _language != Localization.CurrentLanguageLCID)
			{
				_language = Localization.CurrentLanguageLCID;
				PrototypeTranslation.RefreshAll();
			}
		}

		private void OnDestroy()
		{
			LDBTool.PostAddDataAction = (Action)Delegate.Remove(LDBTool.PostAddDataAction, new Action(Register));
			LDBTool.EditDataAction = (Action<Proto>)Delegate.Remove(LDBTool.EditDataAction, new Action<Proto>(FinalizePrototype));
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
		}
	}
	internal static class PrototypeTranslation
	{
		internal static void Apply(Proto proto)
		{
			if (proto == null)
			{
				return;
			}
			TechProto val = (TechProto)(object)((proto is TechProto) ? proto : null);
			if (val != null && PrototypeOwnership.Owns("tech", ((Proto)val).ID, val))
			{
				TradeTechnology tradeTechnology = TradeResearch.Find(((Proto)val).ID);
				if (tradeTechnology == null)
				{
					return;
				}
				SetLanguage();
				((Proto)val).name = TextLocalization.Translate(tradeTechnology.Name);
				val.description = TextLocalization.Translate(tradeTechnology.Description);
				val.conclusion = TextLocalization.Translate(tradeTechnology.Conclusion);
				TextIconMapping val2 = (((Object)(object)Configs.builtin == (Object)null) ? null : Configs.builtin.generalIconMapping);
				if (!((Object)(object)val2 != (Object)null) || val2.iconMappings == null)
				{
					return;
				}
				IconConfig[] iconMappings = val2.iconMappings;
				foreach (IconConfig val3 in iconMappings)
				{
					if (val3 != null && val3.tag == tradeTechnology.InlineIconTag)
					{
						val3.name = ((Proto)val).name;
					}
				}
				return;
			}
			foreach (DeliveryRecipeDefinition definition in DeliveryRecipes.Definitions)
			{
				if (proto.ID == definition.ItemId)
				{
					ItemProto val4 = (ItemProto)(object)((proto is ItemProto) ? proto : null);
					if (val4 != null && PrototypeOwnership.Owns("item", ((Proto)val4).ID, val4))
					{
						SetLanguage();
						((Proto)val4).name = TextLocalization.Translate(definition.Name);
						val4.description = TextLocalization.Translate(definition.Description);
					}
					RecipeProto val5 = (RecipeProto)(object)((proto is RecipeProto) ? proto : null);
					if (val5 != null && PrototypeOwnership.Owns("recipe", ((Proto)val5).ID, val5))
					{
						SetLanguage();
						((Proto)val5).name = TextLocalization.Translate(definition.Name);
						val5.description = TextLocalization.Translate(definition.Description);
					}
				}
			}
		}

		internal static void RefreshAll()
		{
			if ((Object)(object)LDB.techs != (Object)null)
			{
				foreach (TradeTechnology definition in TradeResearch.Definitions)
				{
					Apply((Proto)(object)((ProtoSet<TechProto>)(object)LDB.techs).Select(definition.Id));
				}
			}
			if ((Object)(object)LDB.items == (Object)null || (Object)(object)LDB.recipes == (Object)null)
			{
				return;
			}
			foreach (DeliveryRecipeDefinition definition2 in DeliveryRecipes.Definitions)
			{
				Apply((Proto)(object)((ProtoSet<ItemProto>)(object)LDB.items).Select(definition2.ItemId));
				Apply((Proto)(object)((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(definition2.ItemId));
			}
		}

		private static void SetLanguage()
		{
			TextLocalization.English = Localization.Loaded && !Localization.isZHCN;
		}
	}
	[HarmonyPatch(typeof(TechProto), "RefreshTranslation")]
	internal static class TechnologyTranslationPatch
	{
		private static void Postfix(TechProto __instance)
		{
			PrototypeTranslation.Apply((Proto)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(ItemProto), "RefreshTranslation")]
	internal static class ItemTranslationPatch
	{
		private static void Postfix(ItemProto __instance)
		{
			PrototypeTranslation.Apply((Proto)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(RecipeProto), "RefreshTranslation")]
	internal static class RecipeTranslationPatch
	{
		private static void Postfix(RecipeProto __instance)
		{
			PrototypeTranslation.Apply((Proto)(object)__instance);
		}
	}
	internal static class TechnologyIcons
	{
		private const int Columns = 4;

		private const int Rows = 3;

		private const int Count = 12;

		private const int NativeIconSize = 80;

		private const string ResourceName = "FXDSP.DeliveryBootstrap.Assets.technology-icons.png";

		private static readonly FieldInfo IconField = typeof(TechProto).GetField("_iconSprite", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static Sprite[] _sprites;

		internal static void Load()
		{
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: 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_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0366: Unknown result type (might be due to invalid IL or missing references)
			//IL_036d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0374: Unknown result type (might be due to invalid IL or missing references)
			//IL_037e: Expected O, but got Unknown
			//IL_03b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
			if (_sprites != null)
			{
				return;
			}
			if (IconField == null)
			{
				throw new MissingFieldException(typeof(TechProto).FullName, "_iconSprite");
			}
			byte[] array;
			using (Stream stream = typeof(TechnologyIcons).Assembly.GetManifestResourceStream("FXDSP.DeliveryBootstrap.Assets.technology-icons.png"))
			{
				if (stream == null)
				{
					throw new InvalidDataException("Embedded technology icon atlas missing.");
				}
				using MemoryStream memoryStream = new MemoryStream();
				stream.CopyTo(memoryStream);
				array = memoryStream.ToArray();
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			Sprite[] array2 = (Sprite[])(object)new Sprite[12];
			Texture2D[] array3 = (Texture2D[])(object)new Texture2D[12];
			try
			{
				if (!ImageConversion.LoadImage(val, array, false) || ((Texture)val).width % 4 != 0 || ((Texture)val).height % 3 != 0)
				{
					throw new InvalidDataException("Technology atlas must have twelve equal cells in a 4 by 3 grid.");
				}
				Color32[] pixels = val.GetPixels32();
				for (int i = 0; i < pixels.Length; i++)
				{
					Color32 val2 = pixels[i];
					int num = Math.Max(val2.r, Math.Max(val2.g, val2.b));
					int num2 = val2.a * ((num >= 224) ? 255 : num) / 255;
					pixels[i] = new Color32((byte)245, (byte)245, (byte)245, (byte)((num2 > 8) ? ((num2 >= 248) ? byte.MaxValue : ((byte)num2)) : 0));
				}
				int num3 = ((Texture)val).width / 4;
				int num4 = ((Texture)val).height / 3;
				for (int j = 0; j < 12; j++)
				{
					int num5 = j % 4 * num3;
					int num6 = ((Texture)val).height - (j / 4 + 1) * num4;
					int num7 = num3;
					int num8 = num4;
					int num9 = -1;
					int num10 = -1;
					for (int k = 0; k < num4; k++)
					{
						for (int l = 0; l < num3; l++)
						{
							if (pixels[(num6 + k) * ((Texture)val).width + num5 + l].a > 32)
							{
								num7 = Math.Min(num7, l);
								num8 = Math.Min(num8, k);
								num9 = Math.Max(num9, l);
								num10 = Math.Max(num10, k);
							}
						}
					}
					if (num9 < num7 || num10 < num8)
					{
						throw new InvalidDataException("Empty technology icon cell " + j);
					}
					num7 = Math.Max(0, num7 - 2);
					num8 = Math.Max(0, num8 - 2);
					num9 = Math.Min(num3 - 1, num9 + 2);
					num10 = Math.Min(num4 - 1, num10 + 2);
					int num11 = num9 - num7 + 1;
					int num12 = num10 - num8 + 1;
					int num13 = Math.Max(num11, num12);
					int num14 = Math.Max(8, (num13 + 11) / 12);
					int num15 = num13 + 2 * num14;
					Color32[] array4 = (Color32[])(object)new Color32[num15 * num15];
					for (int m = 0; m < array4.Length; m++)
					{
						array4[m] = new Color32((byte)245, (byte)245, (byte)245, (byte)0);
					}
					int num16 = (num15 - num11) / 2;
					int num17 = (num15 - num12) / 2;
					for (int n = 0; n < num12; n++)
					{
						Array.Copy(pixels, (num6 + num8 + n) * ((Texture)val).width + num5 + num7, array4, (num17 + n) * num15 + num16, num11);
					}
					Texture2D val3 = new Texture2D(80, 80, (TextureFormat)4, false)
					{
						name = "FXDSP.TechIcon." + j,
						filterMode = (FilterMode)1,
						wrapMode = (TextureWrapMode)1,
						hideFlags = (HideFlags)61
					};
					Texture2D val4 = (array3[j] = val3);
					val4.SetPixels32(ResizeMask(array4, num15));
					val4.Apply(false, false);
					array2[j] = Sprite.Create(val4, new Rect(0f, 0f, 80f, 80f), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0);
					((Object)array2[j]).name = "FXDSP.TechIcon." + j;
					((Object)array2[j]).hideFlags = (HideFlags)61;
				}
				_sprites = array2;
			}
			catch
			{
				Sprite[] array5 = array2;
				foreach (Sprite val5 in array5)
				{
					if ((Object)(object)val5 != (Object)null)
					{
						Object.Destroy((Object)(object)val5);
					}
				}
				Texture2D[] array6 = array3;
				foreach (Texture2D val6 in array6)
				{
					if ((Object)(object)val6 != (Object)null)
					{
						Object.Destroy((Object)(object)val6);
					}
				}
				throw;
			}
			finally
			{
				Object.Destroy((Object)(object)val);
			}
		}

		private static Color32[] ResizeMask(Color32[] source, int side)
		{
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			Color32[] array = (Color32[])(object)new Color32[6400];
			double num = (double)side / 80.0;
			double num2 = num * num;
			for (int i = 0; i < 80; i++)
			{
				double num3 = (double)i * num;
				double num4 = (double)(i + 1) * num;
				int num5 = (int)Math.Floor(num3);
				int num6 = Math.Min(side, (int)Math.Ceiling(num4));
				for (int j = 0; j < 80; j++)
				{
					double num7 = (double)j * num;
					double num8 = (double)(j + 1) * num;
					double num9 = 0.0;
					int num10 = (int)Math.Floor(num7);
					int num11 = Math.Min(side, (int)Math.Ceiling(num8));
					for (int k = num5; k < num6; k++)
					{
						double num12 = Math.Min(num4, k + 1) - Math.Max(num3, k);
						for (int l = num10; l < num11; l++)
						{
							double num13 = Math.Min(num8, l + 1) - Math.Max(num7, l);
							num9 += (double)(int)source[k * side + l].a * num13 * num12;
						}
					}
					array[i * 80 + j] = new Color32((byte)245, (byte)245, (byte)245, (byte)Math.Max(0.0, Math.Min(255.0, Math.Round(num9 / num2))));
				}
			}
			return array;
		}

		internal static void Apply(TechProto tech)
		{
			if (_sprites == null)
			{
				return;
			}
			TradeTechnology tradeTechnology = TradeResearch.Find(((Proto)tech).ID);
			if (tradeTechnology != null)
			{
				int num = (tradeTechnology.Upgrade ? ((tradeTechnology.ExchangeTier > 0) ? tradeTechnology.ExchangeTier : (5 + tradeTechnology.Level)) : 0);
				if (num < 0 || num >= _sprites.Length)
				{
					throw new InvalidDataException("Technology icon rank is out of range.");
				}
				IconField.SetValue(tech, _sprites[num]);
			}
		}
	}
	internal static class TechnologyRegistration
	{
		internal static void Register()
		{
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Expected O, but got Unknown
			//IL_02e5: 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_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			float num = ((ProtoSet<TechProto>)(object)LDB.techs).dataArray.Where((TechProto tech) => ((Proto)tech).ID >= 2000).Min((TechProto tech) => tech.Position.y) - 4f;
			TechProto val = ((ProtoSet<TechProto>)(object)LDB.techs).Select(1826);
			if (val == null)
			{
				throw new InvalidOperationException("Cannot locate battlefield analysis technology.");
			}
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(val.Position.x - 4f, val.Position.y);
			float num2 = 9f;
			int num3 = 0;
			int num4 = 0;
			foreach (TradeTechnology definition in TradeResearch.Definitions)
			{
				if (((ProtoSet<TechProto>)(object)LDB.techs).Select(definition.Id) != null)
				{
					throw new InvalidOperationException("FXDSP technology ID conflict: " + definition.Id);
				}
				ItemProto val3 = ((ProtoSet<ItemProto>)(object)LDB.items).Select(definition.IconItemId);
				TechProto val4 = new TechProto();
				((Proto)val4).ID = definition.Id;
				((Proto)val4).Name = definition.RegistrationName;
				((Proto)val4).name = definition.Name;
				val4.Desc = definition.Description;
				val4.Conclusion = definition.Conclusion;
				val4.Published = true;
				val4.Level = definition.Level;
				val4.MaxLevel = definition.Level;
				val4.IsLabTech = definition.Items.Any((int id) => id >= 6001 && id <= 6006);
				val4.IconPath = val3.IconPath;
				val4.IconTag = definition.InlineIconTag;
				val4.Items = definition.Items;
				val4.ItemPoints = definition.ItemPoints;
				val4.HashNeeded = definition.HashNeeded;
				val4.PreTechs = ((definition.Previous == 0 || definition.ImplicitPrevious) ? Array.Empty<int>() : new int[1] { definition.Previous });
				val4.PreTechsImplicit = ((!definition.ImplicitPrevious) ? Array.Empty<int>() : new int[1] { definition.Previous });
				val4.PreItem = Array.Empty<int>();
				val4.UnlockRecipes = Array.Empty<int>();
				val4.UnlockFunctions = Array.Empty<int>();
				val4.UnlockValues = Array.Empty<double>();
				val4.AddItems = Array.Empty<int>();
				val4.AddItemCounts = Array.Empty<int>();
				val4.PropertyOverrideItems = Array.Empty<int>();
				val4.PropertyItemCounts = Array.Empty<int>();
				val4.Position = (Vector2)((!definition.Upgrade) ? val2 : ((definition.ExchangeTier > 0) ? new Vector2(num2 + (float)(num3++ * 4), num) : new Vector2(num2 + (float)(num4++ * 4), num - 4f)));
				TechProto val5 = val4;
				LDBTool.PostAddProto((Proto)(object)val5);
				if (((Proto)val5).ID != definition.Id)
				{
					throw new InvalidOperationException("FXDSP technology IDs must remain stable.");
				}
				PrototypeOwnership.Mark("tech", ((Proto)val5).ID, val5);
				((Proto)val5).Name = definition.Name;
			}
		}

		internal static void Finalize(Proto proto)
		{
			TechProto val = (TechProto)(object)((proto is TechProto) ? proto : null);
			if (val != null)
			{
				bool num = PrototypeOwnership.Owns("tech", ((Proto)val).ID, val);
				if (num)
				{
					val.Preload();
				}
				bool flag = DeliveryRecipes.Definitions.Any((DeliveryRecipeDefinition definition) => PrototypeOwnership.Owns("recipe", definition.ItemId, ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(definition.ItemId)));
				if (num || (flag && (((Proto)val).ID == 1604 || ((Proto)val).ID == 1605)))
				{
					val.UnlockRecipes = val.UnlockRecipes.Distinct().ToArray();
					val.Preload2();
				}
				if (num)
				{
					TechnologyIcons.Apply(val);
				}
				if (num)
				{
					PrototypeTranslation.Apply((Proto)(object)val);
				}
			}
		}
	}
}