using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using CommonAPI;
using CommonAPI.Systems;
using CommonAPI.Systems.ModLocalization;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("DSP-StockExchange")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.1.0")]
[assembly: AssemblyInformationalVersion("0.1.1")]
[assembly: AssemblyProduct("DSP-StockExchange")]
[assembly: AssemblyTitle("DSP-StockExchange")]
[assembly: AssemblyVersion("0.1.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace StockExchange
{
internal enum TradeMode
{
SellSails,
BuySails,
BuyPhotons
}
internal static class ExchangeLogic
{
private const int MaxPendingInput = 20000;
private const int MaxOutputBuffer = 200;
private const int MaxConvertPerTick = 4;
internal static long TicksSeen;
private static long lastTickedGameTick = long.MinValue;
internal static int GetMode(in FractionatorComponent frac)
{
int num = (int)(frac.seed - 1);
if (num < 0 || num > 2)
{
return 1;
}
return num;
}
private static int ModeInputItem(int mode)
{
if (mode != 1)
{
return 6008;
}
return 1501;
}
private static int ModeOutputItem(int mode)
{
return mode switch
{
1 => 6008,
0 => 1501,
_ => 1208,
};
}
internal static string ModeName(int mode)
{
return mode switch
{
0 => L10N.T("卖出能量币(币 → 太阳帆)", "Sell coins (coins -> sails)"),
2 => L10N.T("兑换光子(币 → 光子)", "Buy photons (coins -> photons)"),
_ => L10N.T("买入能量币(太阳帆 → 币)", "Buy coins (sails -> coins)"),
};
}
internal static bool TryGetExchange(FactorySystem fs, int fracId, out FractionatorComponent frac)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
frac = default(FractionatorComponent);
if (fs == null || fs.factory == null || fs.fractionatorPool == null)
{
return false;
}
if (fracId <= 0 || fracId >= fs.fractionatorPool.Length)
{
return false;
}
ref FractionatorComponent reference = ref fs.fractionatorPool[fracId];
if (reference.id != fracId || reference.entityId <= 0)
{
return false;
}
EntityData[] entityPool = fs.factory.entityPool;
if (reference.entityId >= entityPool.Length || entityPool[reference.entityId].protoId != 6009)
{
return false;
}
frac = reference;
return true;
}
internal static void SetMode(FactorySystem fs, int fracId, TradeMode mode, Player player)
{
if (TryGetExchange(fs, fracId, out var frac) && GetMode(in frac) != (int)mode)
{
ref FractionatorComponent reference = ref fs.fractionatorPool[fracId];
RefundPending(ref reference, player);
reference.seed = (uint)(mode + 1);
Plugin.LogInfo($"[exchange] mode -> {mode} (frac {fracId})");
}
}
internal static void TickAll()
{
if (!Plugin.Registered)
{
return;
}
GameData data = GameMain.data;
if (data == null || data.factories == null)
{
return;
}
long gameTick = GameMain.gameTick;
if (gameTick == lastTickedGameTick)
{
return;
}
lastTickedGameTick = gameTick;
int num = data.factoryCount;
if (num > data.factories.Length)
{
num = data.factories.Length;
}
for (int i = 0; i < num; i++)
{
PlanetFactory val = data.factories[i];
if (val != null && val.factorySystem != null)
{
try
{
TickFactory(val.factorySystem);
}
catch (Exception e)
{
Plugin.LogError("TickAll factory failed", e);
}
}
}
}
internal static void TickFactory(FactorySystem fs)
{
if (!Plugin.Registered || fs == null)
{
return;
}
TicksSeen++;
if (GameMain.data == null || GameMain.history == null)
{
return;
}
EnsureRecipeUnlocked();
PlanetFactory factory = fs.factory;
if (factory == null)
{
return;
}
CargoTraffic cargoTraffic = factory.cargoTraffic;
if (cargoTraffic == null)
{
return;
}
FractionatorComponent[] fractionatorPool = fs.fractionatorPool;
if (fractionatorPool == null)
{
return;
}
int num = fs.fractionatorCursor;
if (num > fractionatorPool.Length)
{
num = fractionatorPool.Length;
}
EntityData[] entityPool = factory.entityPool;
for (int i = 1; i < num; i++)
{
ref FractionatorComponent reference = ref fractionatorPool[i];
if (reference.id != i)
{
continue;
}
int entityId = reference.entityId;
if (entityId > 0 && entityId < entityPool.Length && entityPool[entityId].protoId == 6009)
{
try
{
Process(ref reference, fs, cargoTraffic);
}
catch (Exception e)
{
Plugin.LogError("trade tick failed (fracId=" + i + ")", e);
}
}
}
}
internal static void EnsureRecipeUnlocked()
{
GameHistoryData history = GameMain.history;
if (history == null)
{
return;
}
int value = Plugin.UnlockTechId.Value;
if (value <= 0)
{
if (!history.RecipeUnlocked(6010))
{
history.UnlockRecipe(6010);
}
}
else if (!history.RecipeUnlocked(6010) && history.TechUnlocked(value))
{
history.UnlockRecipe(6010);
}
}
private static void Process(ref FractionatorComponent frac, FactorySystem fs, CargoTraffic traffic)
{
frac.fluidInputMax = 0;
frac.productOutputMax = 0;
frac.fluidOutputMax = 0;
StarData val = ((fs.planet != null) ? fs.planet.star : null);
if (val == null)
{
return;
}
int mode = GetMode(in frac);
if (frac.seed != (uint)(mode + 1))
{
frac.seed = (uint)(mode + 1);
}
double price = PriceService.GetPrice(val);
double tax = Mathf.Clamp((float)Plugin.TaxRate.Value, 0f, 0.5f);
int itemId = ModeInputItem(mode);
if (!frac.isOutput1 && frac.belt1 > 0)
{
IntakeFromBelt(ref frac, traffic, frac.belt1, itemId);
}
if (!frac.isOutput2 && frac.belt2 > 0)
{
IntakeFromBelt(ref frac, traffic, frac.belt2, itemId);
}
float powerRatio = GetPowerRatio(fs, in frac);
bool flag = Plugin.RequirePower == null || !Plugin.RequirePower.Value || powerRatio > 0.1f;
if (flag)
{
switch (mode)
{
case 1:
ConvertBuySails(ref frac, price, tax);
break;
case 0:
ConvertSellSails(ref frac, price, tax);
break;
default:
ConvertBuyPhotons(ref frac);
break;
}
OutputToBelt(ref frac, traffic, ModeOutputItem(mode));
}
frac.isWorking = flag && (frac.fluidInputCount > 0 || frac.productOutputCount > 0 || frac.fluidInputInc > 0 || frac.fluidOutputCount > 0 || frac.progress > 0);
}
internal static float GetPowerRatio(FactorySystem fs, in FractionatorComponent frac)
{
try
{
PowerSystem val = fs.factory?.powerSystem;
if (val == null || frac.pcId <= 0 || frac.pcId >= val.consumerPool.Length)
{
return 0f;
}
int networkId = val.consumerPool[frac.pcId].networkId;
if (networkId <= 0 || val.netPool == null || networkId >= val.netPool.Length)
{
return 0f;
}
PowerNetwork val2 = val.netPool[networkId];
return (val2 != null) ? ((float)val2.consumerRatio) : 0f;
}
catch
{
return 0f;
}
}
private static void IntakeFromBelt(ref FractionatorComponent frac, CargoTraffic traffic, int beltId, int itemId)
{
byte b = default(byte);
byte b2 = default(byte);
if (frac.fluidInputCount < 20000 && traffic.GetItemIdAtRear(beltId) == itemId && traffic.TryPickItemAtRear(beltId, itemId, (int[])null, ref b, ref b2) > 0 && b > 0)
{
frac.fluidInputCount += b;
frac.fluidInputCargoCount = (int)b;
Plugin.LogInfo($"in : +{b} #{itemId} (pending {frac.fluidInputCount})");
}
}
private static void ConvertBuySails(ref FractionatorComponent frac, double price, double tax)
{
int num = Math.Max(1, (int)Math.Ceiling(price * (1.0 + tax)));
int num2 = 0;
while (frac.fluidInputCount >= num && frac.productOutputCount < 200 && num2++ < 4)
{
frac.fluidInputCount -= num;
frac.productOutputCount++;
Plugin.LogInfo($"buy: -{num} sail -> +1 coin (out buffer {frac.productOutputCount})");
}
}
private static void ConvertSellSails(ref FractionatorComponent frac, double price, double tax)
{
double num = price * (1.0 - tax);
int num2 = (int)Math.Floor(num * 1000.0);
if (num2 <= 0 && num > 0.0)
{
num2 = 1;
}
int num3 = 0;
while (frac.fluidInputCount > 0 && frac.progress < 100000 && num3++ < 4)
{
frac.fluidInputCount--;
frac.progress += num2;
}
while (frac.progress >= 1000 && frac.productOutputCount < 200)
{
frac.progress -= 1000;
frac.productOutputCount++;
Plugin.LogInfo($"sell: +1 sail (out buffer {frac.productOutputCount}, milli left {frac.progress})");
}
}
private static void ConvertBuyPhotons(ref FractionatorComponent frac)
{
int num = Math.Max(1, Plugin.PhotonCoinCost.Value);
int num2 = 0;
while (frac.fluidInputCount >= num && frac.productOutputCount < 200 && num2++ < 4)
{
frac.fluidInputCount -= num;
frac.productOutputCount++;
Plugin.LogInfo($"photon: -{num} coin -> +1 photon (out buffer {frac.productOutputCount})");
}
}
private static void OutputToBelt(ref FractionatorComponent frac, CargoTraffic traffic, int outputItem)
{
int belt = frac.belt0;
if (belt > 0 && frac.productOutputCount > 0 && traffic.TryInsertItemAtHead(belt, outputItem, (byte)1, (byte)0))
{
frac.productOutputCount--;
}
}
internal static void RefundPending(ref FractionatorComponent frac, Player player)
{
int mode = GetMode(in frac);
int fluidInputCount = frac.fluidInputCount;
int productOutputCount = frac.productOutputCount;
int num = ((mode == 0) ? (frac.progress / 1000) : 0);
int fluidInputInc = frac.fluidInputInc;
int fluidOutputCount = frac.fluidOutputCount;
Plugin.LogInfo($"[refund] frac entity={frac.entityId} mode={mode} in={fluidInputCount} out={productOutputCount} prog={frac.progress} oldCoin={fluidInputInc} oldSail={fluidOutputCount} player={player != null}");
if (player != null)
{
int num2 = ModeInputItem(mode);
int num3 = ModeOutputItem(mode);
if (fluidInputCount > 0)
{
player.TryAddItemToPackage(num2, fluidInputCount, 0, true, 0, false);
}
if (productOutputCount > 0)
{
player.TryAddItemToPackage(num3, productOutputCount, 0, true, 0, false);
}
if (num > 0)
{
player.TryAddItemToPackage(1501, num, 0, true, 0, false);
}
if (fluidInputInc > 0)
{
player.TryAddItemToPackage(6008, fluidInputInc, 0, true, 0, false);
}
if (fluidOutputCount > 0)
{
player.TryAddItemToPackage(1501, fluidOutputCount, 0, true, 0, false);
}
}
frac.fluidInputCount = 0;
frac.fluidInputInc = 0;
frac.fluidOutputCount = 0;
frac.fluidOutputInc = 0;
frac.productOutputCount = 0;
frac.progress = 0;
}
}
public static class PriceService
{
public static long GetEpoch()
{
int num = Math.Max(1, Plugin.PricePeriodMinutes.Value);
long num2 = (long)(60.0 * 60.0 * (double)num);
if (num2 > 0)
{
return GameMain.gameTick / num2;
}
return 0L;
}
public static double GetPrice(StarData star)
{
return GetPriceAt(star, GetEpoch());
}
public static double GetPriceAt(StarData star, long epoch)
{
return GetPriceAtContinuous(star, epoch);
}
public static double GetPriceAtContinuous(StarData star, double epoch)
{
if (star == null)
{
return Math.Max(0.1, Plugin.BasePrice.Value);
}
double value = Plugin.BasePrice.Value;
double value2 = Plugin.RegionSpread.Value;
double value3 = Plugin.Volatility.Value;
double num = Hash01(star.seed, star.index * 31 + 7);
double num2 = 1.0 + value2 * (num * 2.0 - 1.0);
double num3 = Hash01(star.seed * 17 + 3, star.index * 131 + 11) * Math.PI * 2.0;
double num4 = 0.65 * Math.Sin(epoch * 0.9 + num3) + 0.35 * Math.Sin(epoch * 0.37 + num3 * 2.1);
double num5 = value * num2 * (1.0 + value3 * num4);
if (num5 < 0.2)
{
num5 = 0.2;
}
else if (num5 > 5.0)
{
num5 = 5.0;
}
return num5;
}
public static void GetQuotes(double price, out int sailsPerCoin, out double sailsPerCoinSold)
{
double num = Math.Max(0.0, Math.Min(0.5, Plugin.TaxRate.Value));
sailsPerCoin = Math.Max(1, (int)Math.Ceiling(price * (1.0 + num)));
sailsPerCoinSold = Math.Max(0.0, price * (1.0 - num));
}
private static double Hash01(int a, int b)
{
ulong num = (((0x14650FB0739D0383uL ^ (ulong)(uint)a) * 1099511628211L) ^ (uint)b) * 1099511628211L;
long num2 = (long)(num ^ (num >> 33)) * -49064778989728563L;
long num3 = (num2 ^ (num2 >>> 33)) * -4265267296055464877L;
return (double)((ulong)(num3 ^ (num3 >>> 33)) % 1000000uL) / 1000000.0;
}
}
internal static class L10N
{
private static int cachedLcid = int.MinValue;
private static bool cachedIsChinese;
public static bool IsChinese
{
get
{
try
{
int currentLanguageLCID = Localization.CurrentLanguageLCID;
if (currentLanguageLCID != cachedLcid)
{
cachedLcid = currentLanguageLCID;
cachedIsChinese = currentLanguageLCID == 2052 || currentLanguageLCID == 1028;
}
return cachedIsChinese;
}
catch
{
return false;
}
}
}
public static string T(string cn, string en)
{
if (!IsChinese)
{
return en;
}
return cn;
}
}
internal class MarketOverlay : MonoBehaviour
{
private static bool marketVisible;
private static bool chartVisible;
private static bool stylesReady;
private static Font cjkFont;
private static GUIStyle panelStyle;
private static GUIStyle titleStyle;
private static GUIStyle textStyle;
private static GUIStyle hintStyle;
private static GUIStyle buttonStyle;
private static GUIStyle goldStyle;
private static GUIStyle closeStyle;
private static GUIStyle closeLabelStyle;
private static Texture2D closeTex;
private static GUIStyle rowStyle;
private static readonly List<StarData> cheapest = new List<StarData>();
private static readonly List<StarData> dearest = new List<StarData>();
private static readonly List<double> cheapestPrice = new List<double>();
private static readonly List<double> dearestPrice = new List<double>();
private static readonly List<Rect> exchangeButtonRects = new List<Rect>();
private static readonly List<TradeMode> exchangeButtonModes = new List<TradeMode>();
private static readonly List<Rect> marketStarRects = new List<Rect>();
private static readonly List<StarData> marketStarTargets = new List<StarData>();
private static long cachedEpoch = long.MinValue;
private static Rect marketCloseRect;
private static Rect chartCloseRect;
private static Rect exchangeCloseRect;
private static bool hasMarketClose;
private static bool hasChartClose;
private static bool hasExchangeClose;
private static Texture2D whiteTex;
private void Update()
{
try
{
if (GameMain.data != null)
{
ExchangeLogic.TickAll();
}
HandleClicks();
if (Plugin.ToggleMarketKey != null && Plugin.ToggleMarketKey.keyValue)
{
marketVisible = !marketVisible;
if (marketVisible)
{
chartVisible = false;
}
}
if (Plugin.ToggleChartKey != null && Plugin.ToggleChartKey.keyValue)
{
chartVisible = !chartVisible;
if (chartVisible)
{
marketVisible = false;
}
}
if (marketVisible && Input.GetKeyDown((KeyCode)27))
{
marketVisible = false;
}
if (chartVisible && Input.GetKeyDown((KeyCode)27))
{
chartVisible = false;
}
}
catch (Exception e)
{
Plugin.LogError("overlay input failed", e);
}
}
private void OnGUI()
{
try
{
EnsureStyles();
hasMarketClose = false;
hasChartClose = false;
hasExchangeClose = false;
exchangeButtonRects.Clear();
exchangeButtonModes.Clear();
marketStarRects.Clear();
marketStarTargets.Clear();
if (marketVisible)
{
DrawMarketPanel();
}
if (chartVisible)
{
DrawChartPanel();
}
DrawOpenExchangePanel();
}
catch (Exception e)
{
Plugin.LogError("overlay gui failed", e);
}
}
private static void HandleClicks()
{
//IL_000b: 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_0037: 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_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_0156: Unknown result type (might be due to invalid IL or missing references)
//IL_015b: 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)
if (!Input.GetMouseButtonDown(0))
{
return;
}
Vector2 val = default(Vector2);
((Vector2)(ref val))..ctor(Input.mousePosition.x, (float)Screen.height - Input.mousePosition.y);
if (hasMarketClose && ((Rect)(ref marketCloseRect)).Contains(val))
{
marketVisible = false;
return;
}
if (hasChartClose && ((Rect)(ref chartCloseRect)).Contains(val))
{
chartVisible = false;
return;
}
if (hasExchangeClose && ((Rect)(ref exchangeCloseRect)).Contains(val))
{
UIGame val2 = (((Object)(object)UIRoot.instance != (Object)null) ? UIRoot.instance.uiGame : null);
if ((Object)(object)val2 != (Object)null)
{
val2.ShutFractionatorWindow();
}
return;
}
Rect val3;
for (int i = 0; i < exchangeButtonRects.Count; i++)
{
val3 = exchangeButtonRects[i];
if (((Rect)(ref val3)).Contains(val))
{
UIFractionatorWindow openFractionatorWindow = GetOpenFractionatorWindow();
if (!((Object)(object)openFractionatorWindow == (Object)null) && ExchangeLogic.TryGetExchange(openFractionatorWindow.factorySystem, openFractionatorWindow.fractionatorId, out var _))
{
Plugin.LogInfo("[ui] click mode button " + exchangeButtonModes[i]);
ExchangeLogic.SetMode(openFractionatorWindow.factorySystem, openFractionatorWindow.fractionatorId, exchangeButtonModes[i], GameMain.mainPlayer);
}
return;
}
}
if (!marketVisible)
{
return;
}
for (int j = 0; j < marketStarRects.Count && j < marketStarTargets.Count; j++)
{
val3 = marketStarRects[j];
if (((Rect)(ref val3)).Contains(val))
{
ToggleNavigation(marketStarTargets[j]);
break;
}
}
}
private static void ToggleNavigation(StarData star)
{
try
{
Player mainPlayer = GameMain.mainPlayer;
if (mainPlayer != null && mainPlayer.navigation != null && star != null)
{
int astroId = star.astroId;
if (astroId > 0)
{
mainPlayer.navigation.indicatorAstroId = ((mainPlayer.navigation.indicatorAstroId != astroId) ? astroId : 0);
Plugin.LogInfo("navigate star " + star.displayName + " -> " + astroId);
}
}
}
catch (Exception e)
{
Plugin.LogError("toggle navigation failed", e);
}
}
private void DrawMarketPanel()
{
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_0138: Unknown result type (might be due to invalid IL or missing references)
//IL_0183: Unknown result type (might be due to invalid IL or missing references)
//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
//IL_0208: Unknown result type (might be due to invalid IL or missing references)
//IL_026d: Unknown result type (might be due to invalid IL or missing references)
//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
//IL_0322: Unknown result type (might be due to invalid IL or missing references)
RefreshMarketCache();
StarData localStar = GameMain.localStar;
if (localStar != null)
{
double num = PriceService.GetEpoch();
double priceAt = PriceService.GetPriceAt(localStar, (long)num);
double priceAt2 = PriceService.GetPriceAt(localStar, (long)num - 1);
double num2 = ((priceAt2 > 0.0001) ? ((priceAt - priceAt2) / priceAt2 * 100.0) : 0.0);
double value = Plugin.TaxRate.Value;
PriceService.GetQuotes(priceAt, out var sailsPerCoin, out var sailsPerCoinSold);
GUI.Box(new Rect(16f, 16f, 560f, 382f), GUIContent.none, panelStyle);
GUI.Label(new Rect(32f, 24f, 500f, 24f), L10N.T("光子证券交易所 · 行情", "Photon Stock Exchange · Market"), titleStyle);
DrawCloseButton(546f, 26f, out marketCloseRect, out hasMarketClose);
float num3 = 54f;
GUI.Label(new Rect(32f, num3, 528f, 20f), string.Format(L10N.T("当前星系:{0}", "Current system: {0}"), ShortName(localStar)), textStyle);
num3 += 21f;
GUI.Label(new Rect(32f, num3, 528f, 20f), string.Format(L10N.T("基准价 1 币 = {0:0.00} 帆 ({1:+0.0;-0.0;0.0}%)", "Base price 1 coin = {0:0.00} sails ({1:+0.0;-0.0;0.0}%)"), priceAt, num2), textStyle);
num3 += 21f;
GUI.Label(new Rect(32f, num3, 528f, 20f), string.Format(L10N.T("税后 买币 {0} 帆 = 1 币 | 卖币 1 币 = {1:0.000} 帆", "After tax buy {0} sails = 1 coin | sell 1 coin = {1:0.000} sails"), sailsPerCoin, sailsPerCoinSold), goldStyle);
num3 += 21f;
GUI.Label(new Rect(32f, num3, 528f, 20f), L10N.T("兑换光子 1 币 = 1 光子(不计税)", "Photon exchange: 1 coin = 1 photon (tax free)"), goldStyle);
num3 += 22f;
GUI.Label(new Rect(32f, num3, 528f, 18f), string.Format(L10N.T("第 {0} 期 | 每 {1} 分钟刷新 | 税率 {2:0.0}%", "Epoch {0} | refresh every {1} min | tax {2:0.0}%"), (long)num, Plugin.PricePeriodMinutes.Value, value * 100.0), hintStyle);
num3 += 26f;
GUI.Label(new Rect(32f, num3, 528f, 18f), L10N.T("最便宜星系(适合买入能量币,然后运到贵星系卖出)", "Cheapest systems (buy coins here, sell elsewhere)"), hintStyle);
num3 += 22f;
DrawRanking(16f, num3, 560f, cheapest, cheapestPrice);
num3 += 78f;
GUI.Label(new Rect(32f, num3, 528f, 18f), L10N.T("最贵星系(适合卖出能量币)", "Dearest systems (sell coins here)"), hintStyle);
num3 += 22f;
DrawRanking(16f, num3, 560f, dearest, dearestPrice);
GUI.Label(new Rect(32f, 372f, 528f, 18f), L10N.T("点击星系名称可在星图上添加/取消导航线", "Click a system name to toggle its navigation marker"), hintStyle);
}
}
private static void DrawRanking(float x, float ty, float w, List<StarData> stars, List<double> prices)
{
//IL_0047: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
float num = (w - 40f) * 0.5f;
for (int i = 0; i < stars.Count && i < 6; i++)
{
int num2 = i / 3;
int num3 = i % 3;
float num4 = x + 18f + (float)num2 * num;
float num5 = ty + (float)num3 * 22f;
GUI.Label(new Rect(num4, num5, num - 8f, 22f), $"{i + 1}. {ShortName(stars[i])}", rowStyle);
GUI.Label(new Rect(num4 + num - 92f, num5, 60f, 22f), prices[i].ToString("0.00"), textStyle);
marketStarRects.Add(new Rect(num4, num5, num - 8f, 22f));
marketStarTargets.Add(stars[i]);
}
}
private void DrawChartPanel()
{
//IL_002d: 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_0242: Unknown result type (might be due to invalid IL or missing references)
//IL_0247: Unknown result type (might be due to invalid IL or missing references)
//IL_027f: Unknown result type (might be due to invalid IL or missing references)
//IL_040b: 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_0444: Unknown result type (might be due to invalid IL or missing references)
//IL_0313: Unknown result type (might be due to invalid IL or missing references)
//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0318: Unknown result type (might be due to invalid IL or missing references)
//IL_0365: Unknown result type (might be due to invalid IL or missing references)
//IL_036a: Unknown result type (might be due to invalid IL or missing references)
//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
//IL_03d4: Unknown result type (might be due to invalid IL or missing references)
StarData localStar = GameMain.localStar;
if (localStar == null)
{
return;
}
float num = (float)Screen.width - 372f - 16f;
GUI.Box(new Rect(num, 16f, 372f, 236f), GUIContent.none, panelStyle);
GUI.Label(new Rect(num + 14f, 24f, 312f, 22f), L10N.T("光子证券交易所 · K 线 · ", "Photon Exchange · Chart · ") + ShortName(localStar), titleStyle);
DrawCloseButton(num + 372f - 30f, 25f, out chartCloseRect, out hasChartClose);
long epoch = PriceService.GetEpoch();
double priceAtContinuous = PriceService.GetPriceAtContinuous(localStar, epoch);
double[] array = new double[36];
double[] array2 = new double[36];
double[] array3 = new double[36];
double[] array4 = new double[36];
double num2 = double.MaxValue;
double num3 = double.MinValue;
for (int i = 0; i < 36; i++)
{
double num4 = epoch - (35 - i);
array[i] = PriceService.GetPriceAtContinuous(localStar, num4);
array2[i] = PriceService.GetPriceAtContinuous(localStar, num4 + 0.999);
array3[i] = Math.Max(array[i], array2[i]);
array4[i] = Math.Min(array[i], array2[i]);
for (int j = 1; j < 8; j++)
{
double priceAtContinuous2 = PriceService.GetPriceAtContinuous(localStar, num4 + (double)j / 8.0);
if (priceAtContinuous2 > array3[i])
{
array3[i] = priceAtContinuous2;
}
if (priceAtContinuous2 < array4[i])
{
array4[i] = priceAtContinuous2;
}
}
if (array4[i] < num2)
{
num2 = array4[i];
}
if (array3[i] > num3)
{
num3 = array3[i];
}
}
double num5 = Math.Max(0.02, (num3 - num2) * 0.08);
num2 -= num5;
num3 += num5;
float num6 = num + 40f;
float num7 = 72f;
Color color = default(Color);
((Color)(ref color))..ctor(1f, 1f, 1f, 0.08f);
for (int k = 0; k <= 3; k++)
{
float num8 = num7 + 144f * (float)k / 3f;
DrawRect(new Rect(num6, num8, 316f, 1f), color);
double num9 = num3 - (num3 - num2) * (double)k / 3.0;
GUI.Label(new Rect(num + 4f, num8 - 8f, 34f, 16f), num9.ToString("0.00"), hintStyle);
}
float num10 = 8.777778f;
float num11 = Math.Max(3f, num10 * 0.55f);
for (int l = 0; l < 36; l++)
{
float num12 = num6 + (float)l * num10 + num10 * 0.5f;
Color color2 = ((array2[l] >= array[l]) ? new Color(0.95f, 0.3f, 0.28f) : new Color(0.3f, 0.85f, 0.45f));
float num13 = PriceToY(array3[l], num2, num3, num7, 144f);
float num14 = PriceToY(array4[l], num2, num3, num7, 144f);
DrawRect(new Rect(num12 - 0.5f, num13, 1.5f, Math.Max(1f, num14 - num13)), color2);
float num15 = PriceToY(array[l], num2, num3, num7, 144f);
float num16 = PriceToY(array2[l], num2, num3, num7, 144f);
float num17 = Math.Min(num15, num16);
float num18 = Math.Max(1.5f, Math.Abs(num16 - num15));
DrawRect(new Rect(num12 - num11 * 0.5f, num17, num11, num18), color2);
}
float num19 = PriceToY(priceAtContinuous, num2, num3, num7, 144f);
DrawRect(new Rect(num6, num19, 316f, 1f), new Color(1f, 0.85f, 0.3f, 0.55f));
GUI.Label(new Rect(num + 14f, 226f, 344f, 18f), string.Format(L10N.T("现价 {0:0.00} | 每格 {1} 分钟 | 红涨绿跌 | 共 {2} 格", "Now {0:0.00} | {1} min/bar | red up, green down | {2} bars"), priceAtContinuous, Math.Max(1, Plugin.PricePeriodMinutes.Value), 36), hintStyle);
}
private static float PriceToY(double price, double min, double max, float py, float plotH)
{
if (max - min < 1E-09)
{
return py + plotH * 0.5f;
}
double num = (price - min) / (max - min);
return (float)((double)py + (double)plotH * (1.0 - num));
}
private void DrawOpenExchangePanel()
{
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_0104: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
//IL_022a: Unknown result type (might be due to invalid IL or missing references)
//IL_026c: Unknown result type (might be due to invalid IL or missing references)
//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
//IL_0339: Unknown result type (might be due to invalid IL or missing references)
//IL_036f: Unknown result type (might be due to invalid IL or missing references)
//IL_039f: Unknown result type (might be due to invalid IL or missing references)
//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
//IL_0403: Unknown result type (might be due to invalid IL or missing references)
UIFractionatorWindow openFractionatorWindow = GetOpenFractionatorWindow();
if (!((Object)(object)openFractionatorWindow == (Object)null) && ExchangeLogic.TryGetExchange(openFractionatorWindow.factorySystem, openFractionatorWindow.fractionatorId, out var frac))
{
FactorySystem factorySystem = openFractionatorWindow.factorySystem;
StarData val = ((factorySystem.planet != null) ? factorySystem.planet.star : null);
if (val != null)
{
int fractionatorId = openFractionatorWindow.fractionatorId;
int mode = ExchangeLogic.GetMode(in frac);
double price = PriceService.GetPrice(val);
PriceService.GetQuotes(price, out var sailsPerCoin, out var sailsPerCoinSold);
int num = Math.Max(1, Plugin.PhotonCoinCost.Value);
int fluidInputCount = frac.fluidInputCount;
int productOutputCount = frac.productOutputCount;
float powerRatio = ExchangeLogic.GetPowerRatio(factorySystem, in frac);
string arg = ((powerRatio <= 0.1f) ? L10N.T("未供电", "No power") : ((powerRatio < 0.99f) ? L10N.T("电力不足", "Low power") : L10N.T("已通电", "Powered")));
float num2 = (marketVisible ? 404f : 16f);
GUI.Box(new Rect(16f, num2, 620f, 344f), GUIContent.none, panelStyle);
float num3 = 16f + 14f;
float num4 = num2 + 8f;
GUI.Label(new Rect(num3, num4, 556f, 24f), string.Format(L10N.T("光子证券交易所 #{0} · {1}", "Photon Stock Exchange #{0} · {1}"), fractionatorId, ShortName(val)), titleStyle);
DrawCloseButton(16f + 620f - 34f, num2 + 8f, out exchangeCloseRect, out hasExchangeClose);
num4 += 30f;
GUI.Label(new Rect(num3, num4, 590f, 24f), string.Format(L10N.T("状态:{0} 模式:{1}", "Status: {0} Mode: {1}"), arg, ExchangeLogic.ModeName(mode)), goldStyle);
num4 += 27f;
GUI.Label(new Rect(num3, num4, 590f, 22f), string.Format(L10N.T("基准价:1 能量币 = {0:0.00} 太阳帆", "Base price: 1 coin = {0:0.00} sails"), price), textStyle);
num4 += 26f;
GUI.Label(new Rect(num3, num4, 590f, 22f), string.Format(L10N.T("税后:买币 {0} 帆 = 1 币", "After tax: buy {0} sails = 1 coin"), sailsPerCoin), textStyle);
num4 += 26f;
GUI.Label(new Rect(num3, num4, 590f, 22f), string.Format(L10N.T("税后:卖币 1 币 = {0:0.000} 帆", "After tax: sell 1 coin = {0:0.000} sails"), sailsPerCoinSold), textStyle);
num4 += 26f;
GUI.Label(new Rect(num3, num4, 590f, 22f), string.Format(L10N.T("兑换光子:{0} 能量币 = 1 光子(不计税)", "Photons: {0} coins = 1 photon (tax free)"), num), textStyle);
num4 += 26f;
GUI.Label(new Rect(num3, num4, 590f, 22f), string.Format(L10N.T("仓内:输入 {0} 件 | 产出 {1} 件", "Buffered: input {0} | output {1}"), fluidInputCount, productOutputCount), hintStyle);
num4 += 30f;
GUI.Label(new Rect(num3, num4, 590f, 22f), L10N.T("切换模式(仓内物品会退还给你):", "Switch mode (buffered items are refunded to you):"), hintStyle);
num4 += 26f;
DrawModeButton(new Rect(num3, num4, 168f, 28f), L10N.T("卖出币(币→帆)", "Sell coins (coins->sails)"), TradeMode.SellSails, mode);
DrawModeButton(new Rect(num3 + 176f, num4, 168f, 28f), L10N.T("买入币(帆→币)", "Buy coins (sails->coins)"), TradeMode.BuySails, mode);
DrawModeButton(new Rect(num3 + 352f, num4, 196f, 28f), L10N.T("兑换光子(币→光子)", "Buy photons (coins->photons)"), TradeMode.BuyPhotons, mode);
num4 += 34f;
GUI.Label(new Rect(num3, num4, 590f, 22f), L10N.T("两侧传送带进货,中间传送带出货(无延迟)。", "Side belts = input, middle belt = output (no delay)."), hintStyle);
}
}
}
private static void DrawModeButton(Rect rect, string label, TradeMode target, int currentMode)
{
//IL_001a: 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)
string text = ((target == (TradeMode)currentMode) ? ("> " + label + " <") : label);
GUI.Button(rect, text, buttonStyle);
exchangeButtonRects.Add(rect);
exchangeButtonModes.Add(target);
}
private static UIFractionatorWindow GetOpenFractionatorWindow()
{
try
{
UIGame val = (((Object)(object)UIRoot.instance != (Object)null) ? UIRoot.instance.uiGame : null);
if ((Object)(object)val == (Object)null)
{
return null;
}
UIFractionatorWindow fractionatorWindow = val.fractionatorWindow;
if ((Object)(object)fractionatorWindow == (Object)null || !((ManualBehaviour)fractionatorWindow).active || fractionatorWindow.fractionatorId <= 0 || fractionatorWindow.factorySystem == null)
{
return null;
}
return fractionatorWindow;
}
catch
{
return null;
}
}
private static string ShortName(StarData star)
{
if (star == null)
{
return "?";
}
string text = star.displayName;
if (string.IsNullOrEmpty(text))
{
text = star.name;
}
if (string.IsNullOrEmpty(text))
{
return "#" + star.index;
}
if (text.Length > 6)
{
return text.Substring(0, 6);
}
return text;
}
private static void RefreshMarketCache()
{
long epoch = PriceService.GetEpoch();
if (epoch == cachedEpoch && cheapest.Count > 0)
{
return;
}
cachedEpoch = epoch;
cheapest.Clear();
dearest.Clear();
cheapestPrice.Clear();
dearestPrice.Clear();
GalaxyData galaxy = GameMain.galaxy;
if (galaxy == null || galaxy.stars == null)
{
return;
}
int starCount = galaxy.starCount;
for (int i = 0; i < starCount; i++)
{
StarData val = galaxy.stars[i];
if (val != null)
{
double priceAt = PriceService.GetPriceAt(val, epoch);
InsertSorted(val, priceAt, cheapest, cheapestPrice, ascending: true);
InsertSorted(val, priceAt, dearest, dearestPrice, ascending: false);
}
}
}
private static void InsertSorted(StarData star, double price, List<StarData> stars, List<double> prices, bool ascending)
{
int num = prices.Count;
int num2 = 6;
for (int i = 0; i < prices.Count; i++)
{
if (ascending ? (price < prices[i]) : (price > prices[i]))
{
num = i;
break;
}
}
if (num < num2)
{
prices.Insert(num, price);
stars.Insert(num, star);
if (prices.Count > num2)
{
prices.RemoveAt(prices.Count - 1);
stars.RemoveAt(stars.Count - 1);
}
}
}
private static void DrawCloseButton(float x, float y, out Rect rect, out bool has)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: 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_0068: Unknown result type (might be due to invalid IL or missing references)
rect = new Rect(x, y, 22f, 22f);
has = true;
GUI.Box(rect, GUIContent.none, closeStyle);
if ((Object)(object)closeTex == (Object)null)
{
closeTex = MakeCloseTexture();
}
GUI.DrawTexture(new Rect(((Rect)(ref rect)).x + 5f, ((Rect)(ref rect)).y + 5f, 12f, 12f), (Texture)(object)closeTex);
}
private static Texture2D MakeCloseTexture()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
Texture2D val = new Texture2D(12, 12, (TextureFormat)4, false);
Color val2 = default(Color);
((Color)(ref val2))..ctor(1f, 1f, 1f, 0f);
Color val3 = default(Color);
((Color)(ref val3))..ctor(1f, 0.38f, 0.33f, 1f);
for (int i = 0; i < 12; i++)
{
for (int j = 0; j < 12; j++)
{
bool flag = Mathf.Abs(j - i) <= 1;
bool flag2 = Mathf.Abs(j - (11 - i)) <= 1;
bool flag3 = (j < 2 && i < 2) || (j < 2 && i > 9) || (j > 9 && i < 2) || (j > 9 && i > 9);
val.SetPixel(j, i, ((flag || flag2) && !flag3) ? val3 : val2);
}
}
val.Apply();
return val;
}
private static void DrawRect(Rect rect, Color color)
{
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: 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_001b: Expected O, but got Unknown
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)whiteTex == (Object)null)
{
whiteTex = new Texture2D(1, 1, (TextureFormat)4, false);
whiteTex.SetPixel(0, 0, Color.white);
whiteTex.Apply();
}
Color color2 = GUI.color;
GUI.color = color;
GUI.DrawTexture(rect, (Texture)(object)whiteTex);
GUI.color = color2;
}
private static Texture2D MakeTex(Color color)
{
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Expected O, but got Unknown
Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false);
val.SetPixel(0, 0, color);
val.Apply();
return val;
}
private static void EnsureStyles()
{
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Expected O, but got Unknown
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_0134: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
//IL_0141: Unknown result type (might be due to invalid IL or missing references)
//IL_0148: Unknown result type (might be due to invalid IL or missing references)
//IL_0154: Expected O, but got Unknown
//IL_017a: Unknown result type (might be due to invalid IL or missing references)
//IL_017f: Unknown result type (might be due to invalid IL or missing references)
//IL_0187: Unknown result type (might be due to invalid IL or missing references)
//IL_018e: Unknown result type (might be due to invalid IL or missing references)
//IL_0195: Unknown result type (might be due to invalid IL or missing references)
//IL_019a: Unknown result type (might be due to invalid IL or missing references)
//IL_01a4: Expected O, but got Unknown
//IL_01a4: 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_01b3: Expected O, but got Unknown
//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
//IL_0206: Unknown result type (might be due to invalid IL or missing references)
//IL_0215: Expected O, but got Unknown
//IL_023b: Unknown result type (might be due to invalid IL or missing references)
//IL_0240: Unknown result type (might be due to invalid IL or missing references)
//IL_0248: Unknown result type (might be due to invalid IL or missing references)
//IL_024f: Unknown result type (might be due to invalid IL or missing references)
//IL_0256: Unknown result type (might be due to invalid IL or missing references)
//IL_025b: Unknown result type (might be due to invalid IL or missing references)
//IL_0265: Expected O, but got Unknown
//IL_0265: Unknown result type (might be due to invalid IL or missing references)
//IL_0271: Expected O, but got Unknown
//IL_028a: Unknown result type (might be due to invalid IL or missing references)
if (!stylesReady)
{
stylesReady = true;
try
{
cjkFont = Font.CreateDynamicFontFromOSFont(new string[5] { "Microsoft YaHei", "Microsoft YaHei UI", "SimHei", "Noto Sans CJK SC", "Arial Unicode MS" }, 14);
}
catch
{
cjkFont = null;
}
panelStyle = new GUIStyle(GUI.skin.box);
panelStyle.normal.background = MakeTex(new Color(0.04f, 0.05f, 0.07f, 0.9f));
titleStyle = MakeLabel(15, (FontStyle)1, new Color(1f, 0.85f, 0.3f));
goldStyle = MakeLabel(13, (FontStyle)1, new Color(1f, 0.78f, 0.25f));
textStyle = MakeLabel(12, (FontStyle)0, Color.white);
hintStyle = MakeLabel(11, (FontStyle)0, new Color(0.72f, 0.78f, 0.84f));
rowStyle = MakeLabel(12, (FontStyle)0, new Color(0.95f, 0.92f, 0.85f));
buttonStyle = new GUIStyle(GUI.skin.button)
{
fontSize = 12,
alignment = (TextAnchor)4,
wordWrap = false
};
if ((Object)(object)cjkFont != (Object)null)
{
buttonStyle.font = cjkFont;
}
GUIStyle val = new GUIStyle(GUI.skin.button)
{
fontSize = 15,
fontStyle = (FontStyle)1,
alignment = (TextAnchor)4,
padding = new RectOffset(0, 0, 0, 0),
border = new RectOffset(0, 0, 0, 0)
};
val.normal.textColor = new Color(1f, 0.42f, 0.38f);
val.hover.textColor = new Color(1f, 0.25f, 0.2f);
val.active.textColor = new Color(1f, 0.2f, 0.15f);
closeStyle = val;
if ((Object)(object)cjkFont != (Object)null)
{
closeStyle.font = cjkFont;
}
closeLabelStyle = new GUIStyle(GUI.skin.label)
{
fontSize = 16,
fontStyle = (FontStyle)1,
alignment = (TextAnchor)4,
padding = new RectOffset(0, 0, 0, 0),
wordWrap = false
};
closeLabelStyle.normal.textColor = new Color(1f, 0.42f, 0.38f);
if ((Object)(object)cjkFont != (Object)null)
{
closeLabelStyle.font = cjkFont;
}
}
}
private static GUIStyle MakeLabel(int size, FontStyle style, Color color)
{
//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_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Expected O, but got Unknown
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
GUIStyle val = new GUIStyle(GUI.skin.label)
{
fontSize = size,
fontStyle = style,
wordWrap = false
};
val.normal.textColor = color;
if ((Object)(object)cjkFont != (Object)null)
{
val.font = cjkFont;
}
return val;
}
}
internal static class Patches
{
[HarmonyPatch(typeof(FactorySystem), "GameTick")]
internal static class FactorySystemGameTickPostfix
{
[HarmonyPostfix]
internal static void Postfix(FactorySystem __instance)
{
try
{
ExchangeLogic.TickFactory(__instance);
}
catch (Exception e)
{
Plugin.LogError("GameTick postfix failed", e);
}
}
}
[HarmonyPatch(typeof(GameHistoryData), "UnlockTech")]
internal static class UnlockTechPostfix
{
[HarmonyPostfix]
internal static void Postfix(GameHistoryData __instance, int techId)
{
try
{
if (techId == Plugin.UnlockTechId.Value)
{
ExchangeLogic.EnsureRecipeUnlocked();
}
}
catch (Exception e)
{
Plugin.LogError("UnlockTech postfix failed", e);
}
}
}
[HarmonyPatch(typeof(FactorySystem), "TakeBackItems_Fractionator")]
internal static class TakeBackItemsFractionatorPrefix
{
[HarmonyPrefix]
internal static void Prefix(FactorySystem __instance, Player player, int fracId)
{
try
{
if (TryGetExchange(__instance, fracId, out var _))
{
ref FractionatorComponent frac2 = ref __instance.fractionatorPool[fracId];
Plugin.LogInfo($"[refund] TakeBackItems_Fractionator path, fracId={fracId}");
ExchangeLogic.RefundPending(ref frac2, player);
}
}
catch (Exception e)
{
Plugin.LogError("TakeBackItems prefix failed", e);
}
}
}
[HarmonyPatch(typeof(PlanetFactory), "ClearItemsInEntity")]
internal static class ClearItemsInEntityPrefix
{
[HarmonyPrefix]
internal static void Prefix(PlanetFactory __instance, int entityId)
{
try
{
if (__instance == null || __instance.entityPool == null || entityId <= 0 || entityId >= __instance.entityPool.Length || __instance.entityPool[entityId].protoId != 6009)
{
return;
}
FactorySystem factorySystem = __instance.factorySystem;
if (factorySystem != null && factorySystem.fractionatorPool != null)
{
int fractionatorId = __instance.entityPool[entityId].fractionatorId;
if (TryGetExchange(factorySystem, fractionatorId, out var _))
{
ref FractionatorComponent frac2 = ref factorySystem.fractionatorPool[fractionatorId];
Plugin.LogInfo($"[refund] ClearItemsInEntity path, entityId={entityId} fracId={fractionatorId}");
ExchangeLogic.RefundPending(ref frac2, GameMain.mainPlayer);
}
}
}
catch (Exception e)
{
Plugin.LogError("ClearItemsInEntity prefix failed", e);
}
}
}
[HarmonyPatch(typeof(UIFractionatorWindow), "_OnUpdate")]
internal static class FractionatorWindowUpdatePostfix
{
[HarmonyPostfix]
internal static void Postfix(UIFractionatorWindow __instance)
{
//IL_00bb: 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)
try
{
if ((Object)(object)__instance == (Object)null || __instance.fractionatorId <= 0 || __instance.factorySystem == null || !ExchangeLogic.TryGetExchange(__instance.factorySystem, __instance.fractionatorId, out var frac))
{
return;
}
FactorySystem factorySystem = __instance.factorySystem;
StarData val = ((factorySystem.planet != null) ? factorySystem.planet.star : null);
if (val != null)
{
int mode = ExchangeLogic.GetMode(in frac);
PriceService.GetQuotes(PriceService.GetPrice(val), out var sailsPerCoin, out var sailsPerCoinSold);
float powerRatio = ExchangeLogic.GetPowerRatio(factorySystem, in frac);
string text = ((powerRatio <= 0.1f) ? L10N.T("未供电", "No power") : ((powerRatio < 0.99f) ? L10N.T("电力不足", "Low power") : ((frac.fluidInputCount <= 0 && frac.productOutputCount <= 0) ? L10N.T("待机(等待原料)", "Idle (waiting for input)") : L10N.T("运转中", "Running"))));
if ((Object)(object)__instance.titleText != (Object)null)
{
__instance.titleText.text = L10N.T("光子证券交易所", "Photon Stock Exchange");
}
HideProductWidgets(__instance);
Text remindText = __instance.remindText;
if ((Object)(object)__instance.stateText != (Object)null)
{
__instance.stateText.text = ((powerRatio < 0.99f) ? text : string.Empty);
ApplyPlainStyle(__instance.stateText, remindText);
__instance.stateText.fontSize = 14;
}
if ((Object)(object)__instance.remindText != (Object)null)
{
((Behaviour)__instance.remindText).enabled = false;
__instance.remindText.text = string.Empty;
}
if ((Object)(object)__instance.historyText != (Object)null)
{
((Behaviour)__instance.historyText).enabled = true;
ApplyPlainStyle(__instance.historyText, remindText);
__instance.historyText.fontSize = 13;
__instance.historyText.alignment = (TextAnchor)0;
__instance.historyText.lineSpacing = 1.25f;
__instance.historyText.horizontalOverflow = (HorizontalWrapMode)0;
__instance.historyText.verticalOverflow = (VerticalWrapMode)1;
__instance.historyText.text = string.Format(L10N.T("当前模式:{0}", "Mode: {0}"), ExchangeLogic.ModeName(mode)) + "\r\n" + string.Format(L10N.T("税后:买币 {0} 帆 = 1 币", "After tax: buy {0} sails = 1 coin"), sailsPerCoin) + "\r\n" + string.Format(L10N.T("税后:卖币 1 币 = {0:0.000} 帆", "After tax: sell 1 coin = {0:0.000} sails"), sailsPerCoinSold) + "\r\n" + L10N.T("两侧传送带进货,中间传送带出货(无延迟)。", "Side belts = input, middle belt = output (no delay).");
AlignTextLeftToTitle(__instance);
}
}
}
catch (Exception e)
{
Plugin.LogError("FractionatorWindow postfix failed", e);
}
}
}
internal static void AlignTextLeftToTitle(UIFractionatorWindow window)
{
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
//IL_0174: 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_0185: Unknown result type (might be due to invalid IL or missing references)
//IL_018a: Unknown result type (might be due to invalid IL or missing references)
//IL_015b: Unknown result type (might be due to invalid IL or missing references)
//IL_0160: Unknown result type (might be due to invalid IL or missing references)
//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
//IL_01f6: 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_0209: Unknown result type (might be due to invalid IL or missing references)
//IL_020e: Unknown result type (might be due to invalid IL or missing references)
try
{
Transform transform = ((Component)window).transform;
RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
RectTransform val2 = (((Object)(object)window.titleText != (Object)null) ? ((Graphic)window.titleText).rectTransform : null);
RectTransform val3 = (((Object)(object)window.historyText != (Object)null) ? ((Graphic)window.historyText).rectTransform : null);
if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null) && !((Object)(object)val3 == (Object)null))
{
Rect rect = val.rect;
float num = ((Rect)(ref rect)).width;
if (num < 80f)
{
num = 420f;
}
float num2 = Mathf.Max(140f, num - 56f);
val3.SetSizeWithCurrentAnchors((Axis)0, num2);
Vector3 val4 = ((Transform)val).InverseTransformPoint(((Transform)val2).position);
Vector3 val5 = ((Transform)val).InverseTransformPoint(((Transform)val3).position);
float x = val4.x;
rect = val2.rect;
float num3 = x - ((Rect)(ref rect)).width * val2.pivot.x;
float num4 = val5.x - num2 * val3.pivot.x;
float num5 = num3 - num4;
float num6 = Mathf.Max(12f, (float)window.historyText.fontSize * Mathf.Max(1f, window.historyText.lineSpacing) + 3f) * 4f;
RectTransform val6 = (((Object)(object)window.powerText != (Object)null) ? ((Graphic)window.powerText).rectTransform : null);
float num7;
if (!((Object)(object)val6 != (Object)null))
{
rect = val.rect;
num7 = ((Rect)(ref rect)).yMax - 90f;
}
else
{
float y = ((Transform)val).InverseTransformPoint(((Transform)val6).position).y;
rect = val6.rect;
num7 = y - ((Rect)(ref rect)).height * 0.5f - 6f;
}
float num8 = num7;
rect = val.rect;
float num9 = ((Rect)(ref rect)).yMin + 14f;
if (num9 > num8 - num6)
{
num9 = num8 - num6;
}
float num10 = (num8 + num9) * 0.5f + (val3.pivot.y - 0.5f) * num6;
val3.SetSizeWithCurrentAnchors((Axis)1, num6);
((Transform)val3).position = ((Transform)val).TransformPoint(new Vector3(val5.x + num5, num10, val5.z));
}
}
catch (Exception e)
{
Plugin.LogError("align text failed", e);
}
}
internal static void HideProductWidgets(UIFractionatorWindow window)
{
try
{
if ((Object)(object)window.productBox != (Object)null)
{
window.productBox.SetActive(false);
}
if ((Object)(object)window.oriProductBox != (Object)null)
{
window.oriProductBox.SetActive(false);
}
if ((Object)(object)window.productButton != (Object)null)
{
((Component)window.productButton).gameObject.SetActive(false);
}
if ((Object)(object)window.oriProductButton != (Object)null)
{
((Component)window.oriProductButton).gameObject.SetActive(false);
}
if ((Object)(object)window.needIcon != (Object)null)
{
((Behaviour)window.needIcon).enabled = false;
}
if ((Object)(object)window.productIcon != (Object)null)
{
((Behaviour)window.productIcon).enabled = false;
}
if ((Object)(object)window.oriProductIcon != (Object)null)
{
((Behaviour)window.oriProductIcon).enabled = false;
}
if (window.needIncs != null)
{
for (int i = 0; i < window.needIncs.Length; i++)
{
if ((Object)(object)window.needIncs[i] != (Object)null)
{
((Behaviour)window.needIncs[i]).enabled = false;
}
}
}
if (window.oriProductIncs != null)
{
for (int j = 0; j < window.oriProductIncs.Length; j++)
{
if ((Object)(object)window.oriProductIncs[j] != (Object)null)
{
((Behaviour)window.oriProductIncs[j]).enabled = false;
}
}
}
if (window.speedArrows == null)
{
return;
}
for (int k = 0; k < window.speedArrows.Length; k++)
{
if ((Object)(object)window.speedArrows[k] != (Object)null)
{
((Behaviour)window.speedArrows[k]).enabled = false;
}
}
}
catch (Exception e)
{
Plugin.LogError("hide product widgets failed", e);
}
}
internal static void ApplyPlainStyle(Text target, Text styleSource)
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)target == (Object)null) && !((Object)(object)styleSource == (Object)null))
{
target.font = styleSource.font;
((Graphic)target).material = ((Graphic)styleSource).material;
((Graphic)target).color = ((Graphic)styleSource).color;
target.fontSize = styleSource.fontSize;
target.lineSpacing = 1.1f;
target.supportRichText = false;
}
}
internal static bool TryGetExchange(FactorySystem fs, int fracId, out FractionatorComponent frac)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
frac = default(FractionatorComponent);
if (fs == null || fs.factory == null || fs.fractionatorPool == null)
{
return false;
}
if (fracId <= 0 || fracId >= fs.fractionatorPool.Length)
{
return false;
}
ref FractionatorComponent reference = ref fs.fractionatorPool[fracId];
if (reference.id != fracId || reference.entityId <= 0)
{
return false;
}
EntityData[] entityPool = fs.factory.entityPool;
if (reference.entityId >= entityPool.Length || entityPool[reference.entityId].protoId != 6009)
{
return false;
}
frac = reference;
return true;
}
}
[BepInPlugin("com.xcm.dsp.stockexchange", "Photon Stock Exchange", "0.1.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[CommonAPISubmoduleDependency(new string[] { "ProtoRegistry", "LocalizationModule", "CustomKeyBindSystem" })]
public class Plugin : BaseUnityPlugin
{
public const string GUID = "com.xcm.dsp.stockexchange";
public const string NAME = "Photon Stock Exchange";
public const string VERSION = "0.1.1";
public const int ItemCoin = 6008;
public const int ItemExchange = 6009;
public const int RecipeExchange = 6010;
public const int ModelExchange = 667;
public const int BuildIndexExchange = 410;
public const int VanillaItemFractionator = 2314;
public const int VanillaModelFractionator = 119;
public const int ItemSunSail = 1501;
public const int ItemSmallRocket = 1503;
public const int ItemCriticalPhoton = 1208;
private static readonly int[] ExchangeRecipeInputs = new int[4] { 1103, 1108, 1110, 1303 };
private static readonly int[] ExchangeRecipeCounts = new int[4] { 8, 4, 4, 1 };
internal static ItemProto CoinItem;
internal static ItemProto ExchangeItem;
internal static RecipeProto ExchangeRecipe;
internal static ModelProto ExchangeModel;
public static PressKeyBind ToggleMarketKey;
public static PressKeyBind ToggleChartKey;
public static ConfigEntry<double> TaxRate;
public static ConfigEntry<double> BasePrice;
public static ConfigEntry<double> RegionSpread;
public static ConfigEntry<double> Volatility;
public static ConfigEntry<int> PricePeriodMinutes;
public static ConfigEntry<int> PhotonCoinCost;
public static ConfigEntry<int> UnlockTechId;
public static ConfigEntry<bool> EnableTint;
public static ConfigEntry<bool> VerboseLog;
public static ConfigEntry<bool> RequirePower;
private static int errorLogged;
private const string CoinIconResource = "StockExchange.coin.png";
private static Sprite goldExchangeIconSprite;
private static Sprite coinIconSprite;
public static Plugin Instance { get; private set; }
public static bool Registered { get; private set; }
private void Awake()
{
Instance = this;
RegisterLocalizedStrings();
TaxRate = ((BaseUnityPlugin)this).Config.Bind<double>("Economy", "TaxRate", 0.02, "买卖印花税比例(0~0.2)。买入需要多付、卖出会少得。");
BasePrice = ((BaseUnityPlugin)this).Config.Bind<double>("Economy", "BasePrice", 1.0, "全局基准价:1 能量币 值多少太阳帆(未计地区与涨跌)。");
RegionSpread = ((BaseUnityPlugin)this).Config.Bind<double>("Economy", "RegionSpread", 0.3, "星系间地区价差幅度:0.3 表示各星系价格在 0.7~1.3 倍之间浮动。");
Volatility = ((BaseUnityPlugin)this).Config.Bind<double>("Economy", "Volatility", 0.15, "时间涨跌幅度:0.15 表示价格每 5 分钟在 ±15% 内波动。");
PricePeriodMinutes = ((BaseUnityPlugin)this).Config.Bind<int>("Economy", "PricePeriodMinutes", 10, "价格刷新周期(分钟)。默认 10 分钟。");
PhotonCoinCost = ((BaseUnityPlugin)this).Config.Bind<int>("Economy", "PhotonCoinCost", 1, "买入 1 枚临界光子需要多少能量币。默认 1 币 = 1 光子(暂定)。");
UnlockTechId = ((BaseUnityPlugin)this).Config.Bind<int>("Unlock", "UnlockTechId", 1508, "解锁本建筑配方的科技 ID。1508 = 任务完成!(通关科技);填 0 表示开局即可用。");
EnableTint = ((BaseUnityPlugin)this).Config.Bind<bool>("Visual", "EnableTint", true, "把交易所建筑染成金色,便于与木色分馏塔区分。");
VerboseLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "VerboseLog", false, "输出交易明细日志。");
RequirePower = ((BaseUnityPlugin)this).Config.Bind<bool>("Economy", "RequirePower", true, "交易所是否必须通电才工作(与原版建筑一致)。开发期可临时关掉。");
try
{
RegisterProtos();
}
catch (Exception e)
{
LogError("RegisterProtos failed", e);
}
try
{
Harmony.CreateAndPatchAll(typeof(Plugin).Assembly, "com.xcm.dsp.stockexchange");
}
catch (Exception e2)
{
LogError("Harmony patch failed", e2);
}
try
{
RegisterKeyBind();
}
catch (Exception e3)
{
LogError("keybind register failed", e3);
}
try
{
((Component)this).gameObject.AddComponent<MarketOverlay>();
}
catch (Exception e4)
{
LogError("MarketOverlay attach failed", e4);
}
((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} v{1} loaded (ids: coin={2}, building={3})", "Photon Stock Exchange", "0.1.1", 6008, 6009));
}
private static void RegisterKeyBind()
{
//IL_0002: 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_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
ToggleMarketKey = CustomKeyBindSystem.RegisterKeyBindWithReturn<PressKeyBind>(new BuiltinKey
{
name = "OpenEnergyCoinMarket",
key = new CombineKey(51, (byte)4, (ECombineKeyAction)0, false),
canOverride = true,
conflictGroup = 2821
});
ToggleChartKey = CustomKeyBindSystem.RegisterKeyBindWithReturn<PressKeyBind>(new BuiltinKey
{
name = "OpenEnergyCoinChart",
key = new CombineKey(52, (byte)4, (ECombineKeyAction)0, false),
canOverride = true,
conflictGroup = 2821
});
try
{
LocalizationModule.RegisterTranslation("OpenEnergyCoinMarket", "Exchange Market", "交易所行情", "Marché");
LocalizationModule.RegisterTranslation("KEYOpenEnergyCoinMarket", "Exchange Market", "交易所行情", "Marché");
LocalizationModule.RegisterTranslation("OpenEnergyCoinChart", "Exchange Chart", "交易所K线", "Graphique");
LocalizationModule.RegisterTranslation("KEYOpenEnergyCoinChart", "Exchange Chart", "交易所K线", "Graphique");
}
catch (Exception ex)
{
LogInfo("keybind string register skipped: " + ex.Message);
}
}
private static void RegisterLocalizedStrings()
{
try
{
LocalizationModule.RegisterTranslation("光子证券交易所", "Photon Stock Exchange", "光子证券交易所", "Bourse photonique");
LocalizationModule.RegisterTranslation("能量币", "Energy Coin", "能量币", "Pièce d'énergie");
LocalizationModule.RegisterTranslation("传送带式证券交易所:两侧进料、中间出料。价格随所在星系不同,并定时刷新。", "Belt-fed stock exchange: the side belts feed in, the middle belt outputs. Prices differ per star system and refresh periodically.", "传送带式证券交易所:两侧进料、中间出料。价格随所在星系不同,并定时刷新。", "Bourse à convoyeurs : entrées latérales, sortie centrale, prix variables selon le système.");
LocalizationModule.RegisterTranslation("建造一座光子证券交易所。", "Build a Photon Stock Exchange.", "建造一座光子证券交易所。", "Construire une Bourse photonique.");
}
catch (Exception ex)
{
LogInfo("localized strings register skipped: " + ex.Message);
}
}
private static void RegisterProtos()
{
//IL_003e: 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_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
using (ProtoRegistry.StartModLoad("com.xcm.dsp.stockexchange"))
{
CoinItem = ProtoRegistry.RegisterItem(6008, "能量币", "星际股票交易所的通用货币。可在不同星系之间低买高卖。", "Icons/ItemRecipe/assembler-4", ProtoRegistry.GetGridIndex(4, 11, 10), 500, (EItemType)2, ProtoRegistry.GetDefaultIconDesc(new Color(1f, 0.85f, 0.2f), new Color(0.95f, 0.62f, 0.1f)));
CoinItem.UnlockKey = -1;
CoinItem.IconTag = "coin";
ExchangeItem = ProtoRegistry.RegisterItem(6009, "光子证券交易所", "传送带式证券交易所:两侧进料、中间出料。价格随所在星系不同,并定时刷新。", "Icons/ItemRecipe/fractionator", ProtoRegistry.GetGridIndex(4, 10, 3), 20, (EItemType)6, ProtoRegistry.GetDefaultIconDesc(new Color(1f, 0.78f, 0.25f), new Color(0.42f, 0.3f, 0.1f)));
ExchangeItem.IconTag = "exchange";
ExchangeRecipe = ProtoRegistry.RegisterRecipe(6010, (ERecipeType)4, 180, ExchangeRecipeInputs, ExchangeRecipeCounts, new int[1] { 6009 }, new int[1] { 1 }, "建造一座光子证券交易所。", UnlockTechId.Value, 0, "光子证券交易所", "");
ExchangeRecipe.Handcraft = false;
ExchangeModel = ProtoRegistry.RegisterModel(667, ExchangeItem, "Entities/Prefabs/fractionator", (Material[])null, new int[5] { 53, 11, 12, 1, 40 }, 0);
ExchangeItem.BuildIndex = 410;
ExchangeItem.UnlockKey = 0;
ProtoRegistry.onLoadingFinished += OnLoadingFinished;
}
Registered = true;
}
private static void OnLoadingFinished()
{
//IL_0102: Unknown result type (might be due to invalid IL or missing references)
//IL_0107: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: Unknown result type (might be due to invalid IL or missing references)
//IL_0123: 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)
try
{
ModelProto val = ExchangeModel ?? ((ProtoSet<ModelProto>)(object)LDB.models).Select(667);
ModelProto val2 = ((ProtoSet<ModelProto>)(object)LDB.models).Select(119);
if (val != null && val.prefabDesc != null && val2 != null && val2.prefabDesc != null)
{
val.HpMax = val2.HpMax;
val.prefabDesc.workEnergyPerTick = val2.prefabDesc.workEnergyPerTick;
val.prefabDesc.idleEnergyPerTick = val2.prefabDesc.idleEnergyPerTick;
val.prefabDesc.fracFluidInputMax = 0;
val.prefabDesc.fracProductOutputMax = 0;
val.prefabDesc.fracFluidOutputMax = 0;
if (EnableTint != null && EnableTint.Value)
{
TintModel(val, new Color(1f, 0.78f, 0.25f));
}
}
TryApplyGoldFractionatorIcon();
try
{
Sprite val3 = LoadEmbeddedSprite("StockExchange.coin.png");
if ((Object)(object)val3 != (Object)null && CoinItem != null)
{
SetItemIconSprite(CoinItem, val3);
Rect rect = val3.rect;
string text = ((Rect)(ref rect)).width.ToString();
rect = val3.rect;
LogInfo("coin icon replaced: " + text + "x" + ((Rect)(ref rect)).height);
}
}
catch (Exception e)
{
LogError("coin icon load failed", e);
}
Plugin instance = Instance;
if (instance != null)
{
((BaseUnityPlugin)instance).Logger.LogInfo((object)"protos ready: energy-coin exchange registered");
}
}
catch (Exception e2)
{
LogError("OnLoadingFinished failed", e2);
}
}
private static void TintModel(ModelProto model, Color color)
{
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Expected O, but got Unknown
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Expected O, but got Unknown
PrefabDesc prefabDesc = model.prefabDesc;
if (prefabDesc == null)
{
return;
}
if (prefabDesc.lodMaterials != null)
{
for (int i = 0; i < prefabDesc.lodMaterials.Length; i++)
{
Material[] array = prefabDesc.lodMaterials[i];
if (array == null)
{
continue;
}
for (int j = 0; j < array.Length; j++)
{
if (j == 0 && !((Object)(object)array[j] == (Object)null))
{
Material val = new Material(array[j])
{
color = color
};
prefabDesc.lodMaterials[i][j] = val;
}
}
}
}
if (prefabDesc.materials != null && prefabDesc.materials.Length != 0 && (Object)(object)prefabDesc.materials[0] != (Object)null)
{
prefabDesc.materials[0] = new Material(prefabDesc.materials[0])
{
color = color
};
}
}
private static void TryApplyGoldFractionatorIcon()
{
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_0136: Unknown result type (might be due to invalid IL or missing references)
//IL_013b: Unknown result type (might be due to invalid IL or missing references)
//IL_013d: Unknown result type (might be due to invalid IL or missing references)
//IL_0144: Unknown result type (might be due to invalid IL or missing references)
//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
//IL_020f: Unknown result type (might be due to invalid IL or missing references)
//IL_021e: Unknown result type (might be due to invalid IL or missing references)
//IL_022d: Expected O, but got Unknown
//IL_016f: Unknown result type (might be due to invalid IL or missing references)
//IL_0176: Unknown result type (might be due to invalid IL or missing references)
//IL_014d: Unknown result type (might be due to invalid IL or missing references)
//IL_0154: Unknown result type (might be due to invalid IL or missing references)
//IL_0188: Unknown result type (might be due to invalid IL or missing references)
//IL_017f: Unknown result type (might be due to invalid IL or missing references)
//IL_0166: Unknown result type (might be due to invalid IL or missing references)
//IL_015d: Unknown result type (might be due to invalid IL or missing references)
//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
try
{
ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items).Select(2314);
Sprite val2 = ((val != null) ? val.iconSprite : null);
if ((Object)(object)val2 == (Object)null)
{
LogInfo("[icon] vanilla fractionator sprite missing");
return;
}
Texture2D texture = val2.texture;
LogInfo(string.Format("[icon] frac sprite tex={0} readable={1} size={2}x{3} rect={4}", ((Object)(object)texture != (Object)null) ? ((Object)texture).name : "null", (Object)(object)texture != (Object)null && ((Texture)texture).isReadable, ((Object)(object)texture != (Object)null) ? ((Texture)texture).width : 0, ((Object)(object)texture != (Object)null) ? ((Texture)texture).height : 0, val2.rect));
if (!((Object)(object)texture == (Object)null) && ((Texture)texture).isReadable)
{
Rect rect = val2.rect;
int num = (int)((Rect)(ref rect)).width;
rect = val2.rect;
int num2 = (int)((Rect)(ref rect)).height;
rect = val2.rect;
int num3 = (int)((Rect)(ref rect)).x;
rect = val2.rect;
Color[] pixels = texture.GetPixels(num3, (int)((Rect)(ref rect)).y, num, num2);
for (int i = 0; i < pixels.Length; i++)
{
Color val3 = pixels[i];
float num4 = ((val3.r > val3.g) ? ((val3.r > val3.b) ? val3.r : val3.b) : ((val3.g > val3.b) ? val3.g : val3.b));
num4 = (val3.r = Math.Min(1f, num4 * 1.12f));
val3.g = num4 * 0.78f;
val3.b = num4 * 0.24f;
pixels[i] = val3;
}
Texture2D val4 = new Texture2D(num, num2, (TextureFormat)4, false);
val4.SetPixels(pixels);
val4.Apply();
goldExchangeIconSprite = Sprite.Create(val4, new Rect(0f, 0f, (float)num, (float)num2), new Vector2(0.5f, 0.5f), 100f);
if (ExchangeItem != null)
{
SetItemIconSprite(ExchangeItem, goldExchangeIconSprite);
}
LogInfo("[icon] gold fractionator icon applied: " + num + "x" + num2);
}
}
catch (Exception e)
{
LogError("fractionator icon tint failed", e);
}
}
private static void SetItemIconSprite(ItemProto item, Sprite sprite)
{
FieldInfo field = typeof(ItemProto).GetField("_iconSprite", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (field != null)
{
field.SetValue(item, sprite);
}
}
private static Sprite LoadEmbeddedSprite(string resourceName)
{
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Expected O, but got Unknown
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)coinIconSprite != (Object)null)
{
return coinIconSprite;
}
using Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream(resourceName);
if (stream == null || stream.Length == 0L)
{
return null;
}
byte[] array = new byte[stream.Length];
int num;
for (int i = 0; i < array.Length; i += num)
{
num = stream.Read(array, i, array.Length - i);
if (num <= 0)
{
break;
}
}
Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
if (!ImageConversion.LoadImage(val, array))
{
return null;
}
((Texture)val).filterMode = (FilterMode)1;
((Texture)val).wrapMode = (TextureWrapMode)1;
coinIconSprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
return coinIconSprite;
}
internal static void LogError(string what, Exception e)
{
if (errorLogged++ <= 20)
{
Plugin instance = Instance;
if (instance != null)
{
((BaseUnityPlugin)instance).Logger.LogError((object)(what + ": " + e.GetType().Name + ": " + e.Message + "\n" + e.StackTrace));
}
}
}
internal static void LogInfo(string msg)
{
if (VerboseLog != null && VerboseLog.Value)
{
Plugin instance = Instance;
if (instance != null)
{
((BaseUnityPlugin)instance).Logger.LogInfo((object)msg);
}
}
}
internal static void LogAlways(string msg)
{
Plugin instance = Instance;
if (instance != null)
{
((BaseUnityPlugin)instance).Logger.LogInfo((object)msg);
}
}
}
}