Decompiled source of PowerMeter v0.1.0

PowerMeter.Core.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("endo5501")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("ゲーム非依存の電力集計・整形ロジック(ユニットテスト対象)")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("PowerMeter.Core")]
[assembly: AssemblyTitle("PowerMeter.Core")]
[assembly: AssemblyVersion("0.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[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 PowerMeter.Core
{
	public readonly struct NetworkSample
	{
		public int PlanetId { get; }

		public int StarId { get; }

		public long EnergyCapacity { get; }

		public long EnergyRequired { get; }

		public long EnergyServed { get; }

		public long EnergyCharge { get; }

		public long EnergyDischarge { get; }

		public long EnergyStored { get; }

		public NetworkSample(int planetId, int starId, long energyCapacity, long energyRequired, long energyServed, long energyCharge = 0L, long energyDischarge = 0L, long energyStored = 0L)
		{
			PlanetId = planetId;
			StarId = starId;
			EnergyCapacity = energyCapacity;
			EnergyRequired = energyRequired;
			EnergyServed = energyServed;
			EnergyCharge = energyCharge;
			EnergyDischarge = energyDischarge;
			EnergyStored = energyStored;
		}
	}
	public static class PowerAggregator
	{
		public static PowerSnapshot Aggregate(IEnumerable<NetworkSample> samples, PowerScope scope, int planetId, int starId, int tickPerSecond)
		{
			if (samples == null)
			{
				return PowerSnapshot.Invalid;
			}
			int num = 0;
			long num2 = 0L;
			long num3 = 0L;
			long num4 = 0L;
			long num5 = 0L;
			long num6 = 0L;
			long num7 = 0L;
			foreach (NetworkSample sample in samples)
			{
				if (IsInScope(sample, scope, planetId, starId))
				{
					num++;
					num2 += sample.EnergyCapacity;
					num3 += sample.EnergyRequired;
					num4 += sample.EnergyServed;
					num5 += sample.EnergyCharge;
					num6 += sample.EnergyDischarge;
					num7 += sample.EnergyStored;
				}
			}
			if (num == 0)
			{
				return PowerSnapshot.Invalid;
			}
			double num8 = num4 + num5 - num6;
			if (num8 < 0.0)
			{
				num8 = 0.0;
			}
			double satisfactionRatio = ((num3 > 0) ? ((double)num4 / (double)num3) : 1.0);
			double utilizationRatio = ((num2 > 0) ? (num8 / (double)num2) : 0.0);
			return new PowerSnapshot(isValid: true, num, (double)num2 * (double)tickPerSecond, num8 * (double)tickPerSecond, (double)num3 * (double)tickPerSecond, (double)num4 * (double)tickPerSecond, (double)num5 * (double)tickPerSecond, (double)num6 * (double)tickPerSecond, satisfactionRatio, utilizationRatio, num7);
		}

		private static bool IsInScope(NetworkSample sample, PowerScope scope, int planetId, int starId)
		{
			return scope switch
			{
				PowerScope.Planet => sample.PlanetId == planetId, 
				PowerScope.Star => sample.StarId == starId, 
				_ => true, 
			};
		}
	}
	public static class PowerFormatter
	{
		private static readonly string[] WattUnits = new string[7] { "W", "kW", "MW", "GW", "TW", "PW", "EW" };

		private static readonly string[] JouleUnits = new string[7] { "J", "kJ", "MJ", "GJ", "TJ", "PJ", "EJ" };

		public static string FormatWatt(double watt)
		{
			return Format(watt, WattUnits, alwaysSigned: false);
		}

		public static string FormatSignedWatt(double watt)
		{
			return Format(watt, WattUnits, alwaysSigned: true);
		}

		public static string FormatJoule(double joule)
		{
			return Format(joule, JouleUnits, alwaysSigned: false);
		}

		public static string FormatPercent(double ratio)
		{
			if (double.IsNaN(ratio) || ratio <= 0.0)
			{
				return "0%";
			}
			if (ratio >= 1.0)
			{
				return "100%";
			}
			int num = (int)Math.Floor(ratio * 100.0);
			if (num > 99)
			{
				num = 99;
			}
			return num.ToString(CultureInfo.InvariantCulture) + "%";
		}

		private static string Format(double value, string[] units, bool alwaysSigned)
		{
			if (double.IsNaN(value) || double.IsInfinity(value))
			{
				return "- " + units[0];
			}
			bool flag = value < 0.0;
			double num = Math.Abs(value);
			if (num < 1.0)
			{
				return "0 " + units[0];
			}
			int num2 = 0;
			while (num >= 1000.0 && num2 < units.Length - 1)
			{
				num /= 1000.0;
				num2++;
			}
			int digits = DecimalsFor(num);
			double num3 = Math.Round(num, digits, MidpointRounding.AwayFromZero);
			if (num3 >= 1000.0 && num2 < units.Length - 1)
			{
				num2++;
				num3 /= 1000.0;
				digits = DecimalsFor(num3);
				num3 = Math.Round(num3, digits, MidpointRounding.AwayFromZero);
			}
			string text = ((!flag) ? (alwaysSigned ? "+" : string.Empty) : "-");
			return text + num3.ToString("F" + digits.ToString(CultureInfo.InvariantCulture), CultureInfo.InvariantCulture) + " " + units[num2];
		}

		private static int DecimalsFor(double mantissa)
		{
			if (mantissa >= 100.0)
			{
				return 0;
			}
			if (!(mantissa >= 10.0))
			{
				return 2;
			}
			return 1;
		}
	}
	public enum PowerScope
	{
		Planet,
		Star,
		Global
	}
	public readonly struct PowerSnapshot
	{
		public bool IsValid { get; }

		public int NetworkCount { get; }

		public double CapacityWatt { get; }

		public double GenerationWatt { get; }

		public double ConsumptionWatt { get; }

		public double ServedWatt { get; }

		public double ChargeWatt { get; }

		public double DischargeWatt { get; }

		public double NetChargeWatt => ChargeWatt - DischargeWatt;

		public double SatisfactionRatio { get; }

		public double UtilizationRatio { get; }

		public double StoredJoule { get; }

		public static PowerSnapshot Invalid => default(PowerSnapshot);

		public PowerSnapshot(bool isValid, int networkCount, double capacityWatt, double generationWatt, double consumptionWatt, double servedWatt, double chargeWatt, double dischargeWatt, double satisfactionRatio, double utilizationRatio, double storedJoule)
		{
			IsValid = isValid;
			NetworkCount = networkCount;
			CapacityWatt = capacityWatt;
			GenerationWatt = generationWatt;
			ConsumptionWatt = consumptionWatt;
			ServedWatt = servedWatt;
			ChargeWatt = chargeWatt;
			DischargeWatt = dischargeWatt;
			SatisfactionRatio = satisfactionRatio;
			UtilizationRatio = utilizationRatio;
			StoredJoule = storedJoule;
		}
	}
}

PowerMeter.Plugin.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using Microsoft.CodeAnalysis;
using PowerMeter.Core;
using PowerMeter.Plugin.UI;
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("endo5501")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("PowerMeter.Plugin")]
[assembly: AssemblyTitle("PowerMeter.Plugin")]
[assembly: AssemblyVersion("0.1.0.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 PowerMeter.Plugin
{
	public static class GamePowerSampler
	{
		public static int TickPerSecond
		{
			get
			{
				int num = 60;
				if (num <= 0)
				{
					return 60;
				}
				return num;
			}
		}

		public static bool TryCollect(List<NetworkSample> buffer, out int localPlanetId, out int localStarId)
		{
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			buffer.Clear();
			localPlanetId = 0;
			localStarId = 0;
			if ((Object)(object)GameMain.instance == (Object)null || GameMain.instance.isMenuDemo || !GameMain.isRunning)
			{
				return false;
			}
			GameData data = GameMain.data;
			if (data == null || data.factories == null)
			{
				return false;
			}
			PlanetData localPlanet = GameMain.localPlanet;
			if (localPlanet != null)
			{
				localPlanetId = localPlanet.id;
			}
			StarData localStar = GameMain.localStar;
			if (localStar != null)
			{
				localStarId = localStar.id;
			}
			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)
				{
					continue;
				}
				PlanetData planet = val.planet;
				PowerSystem powerSystem = val.powerSystem;
				if (planet == null || powerSystem == null || powerSystem.netPool == null)
				{
					continue;
				}
				int id = planet.id;
				int num2 = ((planet.star != null) ? planet.star.id : 0);
				int num3 = powerSystem.netCursor;
				if (num3 > powerSystem.netPool.Length)
				{
					num3 = powerSystem.netPool.Length;
				}
				for (int j = 1; j < num3; j++)
				{
					PowerNetwork val2 = powerSystem.netPool[j];
					if (val2 != null && val2.id == j)
					{
						buffer.Add(new NetworkSample(id, num2, val2.energyCapacity, val2.energyRequired, val2.energyServed, val2.energyCharge, val2.energyDischarge, val2.energyStored));
					}
				}
			}
			return true;
		}
	}
	public enum WidgetCorner
	{
		TopLeft,
		TopRight,
		BottomLeft,
		BottomRight
	}
	public enum WidgetLanguage
	{
		Auto,
		Japanese,
		English
	}
	public enum ChargeColumnMode
	{
		Off,
		Net,
		Split
	}
	public class PowerMeterConfig
	{
		public ConfigFile File { get; }

		public ConfigEntry<bool> Enabled { get; }

		public ConfigEntry<KeyboardShortcut> ToggleHotkey { get; }

		public ConfigEntry<float> UpdateIntervalSeconds { get; }

		public ConfigEntry<WidgetLanguage> Language { get; }

		public ConfigEntry<WidgetCorner> Corner { get; }

		public ConfigEntry<float> OffsetX { get; }

		public ConfigEntry<float> OffsetY { get; }

		public ConfigEntry<int> FontSize { get; }

		public ConfigEntry<float> BackgroundOpacity { get; }

		public ConfigEntry<bool> ShowCapacity { get; }

		public ConfigEntry<bool> ShowUtilization { get; }

		public ConfigEntry<bool> ShowSatisfaction { get; }

		public ConfigEntry<ChargeColumnMode> ChargeColumn { get; }

		public ConfigEntry<bool> ShowAccumulated { get; }

		public ConfigEntry<int> UtilizationWarningPercent { get; }

		public ConfigEntry<int> SatisfactionWarningPercent { get; }

		public ConfigEntry<bool> DiagnosticLogging { get; }

		public ConfigEntry<float> DiagnosticLogIntervalSeconds { get; }

		public bool UseJapanese => Language.Value switch
		{
			WidgetLanguage.Japanese => true, 
			WidgetLanguage.English => false, 
			_ => IsGameJapanese(), 
		};

		public PowerMeterConfig(ConfigFile file)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Expected O, but got Unknown
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Expected O, but got Unknown
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Expected O, but got Unknown
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Expected O, but got Unknown
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Expected O, but got Unknown
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Expected O, but got Unknown
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Expected O, but got Unknown
			File = file;
			Enabled = file.Bind<bool>("General", "Enabled", true, "PowerMeter を有効にする。");
			ToggleHotkey = file.Bind<KeyboardShortcut>("General", "ToggleHotkey", new KeyboardShortcut((KeyCode)112, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "ウィジットの表示を切り替えるキー。");
			UpdateIntervalSeconds = file.Bind<float>("General", "UpdateIntervalSeconds", 0.5f, new ConfigDescription("電力値を再集計する間隔(秒)。短くすると追従は良くなるが負荷が上がる。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()));
			Language = file.Bind<WidgetLanguage>("General", "Language", WidgetLanguage.Auto, "ウィジットのラベル言語。Auto はゲームの言語設定に従う。");
			Corner = file.Bind<WidgetCorner>("Layout", "Corner", WidgetCorner.TopRight, "ウィジットを表示する画面の隅。");
			OffsetX = file.Bind<float>("Layout", "OffsetX", 16f, new ConfigDescription("指定した隅からの横方向のオフセット。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2000f), Array.Empty<object>()));
			OffsetY = file.Bind<float>("Layout", "OffsetY", 16f, new ConfigDescription("指定した隅からの縦方向のオフセット。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2000f), Array.Empty<object>()));
			FontSize = file.Bind<int>("Layout", "FontSize", 14, new ConfigDescription("文字サイズ。ウィジット全体の寸法もこれに追従する。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(8, 32), Array.Empty<object>()));
			BackgroundOpacity = file.Bind<float>("Layout", "BackgroundOpacity", 0.55f, new ConfigDescription("背景パネルの不透明度。0 で背景なし。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			ShowCapacity = file.Bind<bool>("Columns", "ShowCapacity", true, "発電容量(最大発電能力)の列を表示する。ゲーム内の「発電性能」に対応する。");
			ShowUtilization = file.Bind<bool>("Columns", "ShowUtilization", true, "使用率(実発電量 / 発電容量)の列を表示する。発電設備の余力を見るための指標。");
			ShowSatisfaction = file.Bind<bool>("Columns", "ShowSatisfaction", false, "充足率(供給 / 需要)の列を表示する。電力不足のときだけ 100% を下回る。");
			ChargeColumn = file.Bind<ChargeColumnMode>("Columns", "ChargeColumn", ChargeColumnMode.Split, "充放電の列の出し方。Split はゲーム内パネルと同じく充電と放電を分けて表示し、Net は差し引きを 1 列にまとめる。");
			ShowAccumulated = file.Bind<bool>("Columns", "ShowAccumulated", false, "蓄電量(蓄電池に貯まっているエネルギー)の列を表示する。");
			UtilizationWarningPercent = file.Bind<int>("Columns", "UtilizationWarningPercent", 90, new ConfigDescription("使用率がこの値以上になったら警告色で表示する。発電設備の増設時期の目安。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			SatisfactionWarningPercent = file.Bind<int>("Columns", "SatisfactionWarningPercent", 95, new ConfigDescription("充足率がこの値を下回ったら警告色で表示する。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			DiagnosticLogging = file.Bind<bool>("Diagnostics", "DiagnosticLogging", false, "集計結果を BepInEx のログへ定期出力する。ゲーム内統計ウィンドウとの突き合わせ用。通常は不要だが、表示値がおかしいときに有効にすると生の W / J 値も出る。");
			DiagnosticLogIntervalSeconds = file.Bind<float>("Diagnostics", "DiagnosticLogIntervalSeconds", 5f, new ConfigDescription("診断ログを出力する間隔(秒)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 60f), Array.Empty<object>()));
		}

		private static bool IsGameJapanese()
		{
			try
			{
				return Localization.isJAJA;
			}
			catch (Exception)
			{
				return false;
			}
		}
	}
	[BepInPlugin("com.endo5501.dsp.PowerMeter", "PowerMeter", "0.1.0")]
	public class PowerMeterPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.endo5501.dsp.PowerMeter";

		public const string PluginName = "PowerMeter";

		public const string PluginVersion = "0.1.0";

		private readonly List<NetworkSample> _samples = new List<NetworkSample>(256);

		private readonly PowerMeterWidget _widget = new PowerMeterWidget();

		private PowerMeterConfig _config;

		private float _sinceRefresh;

		private float _sinceDiagnosticLog;

		private bool _disabledByError;

		private bool _configDirty;

		private bool _userVisible = true;

		public PowerSnapshot Planet { get; private set; }

		public PowerSnapshot Star { get; private set; }

		public PowerSnapshot Global { get; private set; }

		private void Awake()
		{
			_config = new PowerMeterConfig(((BaseUnityPlugin)this).Config);
			((BaseUnityPlugin)this).Config.SettingChanged += delegate
			{
				_configDirty = true;
			};
			((BaseUnityPlugin)this).Logger.LogInfo((object)"PowerMeter 0.1.0 loaded.");
		}

		private void OnDestroy()
		{
			_widget.Destroy();
		}

		private void Update()
		{
			if (_disabledByError || _config == null)
			{
				return;
			}
			try
			{
				Tick();
			}
			catch (Exception arg)
			{
				_disabledByError = true;
				_widget.Destroy();
				((BaseUnityPlugin)this).Logger.LogError((object)string.Format("{0} を無効化しました(更新中に例外が発生): {1}", "PowerMeter", arg));
			}
		}

		private void Tick()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			KeyboardShortcut value = _config.ToggleHotkey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				_userVisible = !_userVisible;
				PowerMeterWidget widget = _widget;
				int visible;
				if (_userVisible)
				{
					PowerSnapshot global = Global;
					visible = (((PowerSnapshot)(ref global)).IsValid ? 1 : 0);
				}
				else
				{
					visible = 0;
				}
				widget.SetVisible((byte)visible != 0);
			}
			if (!_config.Enabled.Value)
			{
				_widget.SetVisible(visible: false);
				return;
			}
			float unscaledDeltaTime = Time.unscaledDeltaTime;
			_sinceRefresh += unscaledDeltaTime;
			_sinceDiagnosticLog += unscaledDeltaTime;
			if (!(_sinceRefresh < _config.UpdateIntervalSeconds.Value))
			{
				_sinceRefresh = 0f;
				Refresh();
			}
		}

		private void Refresh()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!GamePowerSampler.TryCollect(_samples, out var localPlanetId, out var localStarId))
			{
				Planet = PowerSnapshot.Invalid;
				Star = PowerSnapshot.Invalid;
				Global = PowerSnapshot.Invalid;
				_widget.SetVisible(visible: false);
				return;
			}
			int tickPerSecond = GamePowerSampler.TickPerSecond;
			Planet = PowerAggregator.Aggregate((IEnumerable<NetworkSample>)_samples, (PowerScope)0, localPlanetId, localStarId, tickPerSecond);
			Star = PowerAggregator.Aggregate((IEnumerable<NetworkSample>)_samples, (PowerScope)1, localPlanetId, localStarId, tickPerSecond);
			Global = PowerAggregator.Aggregate((IEnumerable<NetworkSample>)_samples, (PowerScope)2, localPlanetId, localStarId, tickPerSecond);
			UpdateWidget();
			if (_config.DiagnosticLogging.Value && _sinceDiagnosticLog >= _config.DiagnosticLogIntervalSeconds.Value)
			{
				_sinceDiagnosticLog = 0f;
				LogDiagnostics(localPlanetId, localStarId, tickPerSecond);
			}
		}

		private void UpdateWidget()
		{
			//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_0047: Unknown result type (might be due to invalid IL or missing references)
			if (_widget.TryCreate(_config))
			{
				if (_configDirty)
				{
					_configDirty = false;
					_widget.ApplyConfig(_config);
				}
				_widget.UpdateValues(Planet, Star, Global, _config);
				_widget.SetVisible(_userVisible);
			}
		}

		private void LogDiagnostics(int planetId, int starId, int tickPerSecond)
		{
			//IL_0055: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"[diag] tps={tickPerSecond} planetId={planetId} starId={starId} networks={_samples.Count}");
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[diag] 惑星   " + Describe(Planet)));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[diag] 星系   " + Describe(Star)));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[diag] 全星系 " + Describe(Global)));
			LogRaw("惑星", Planet);
			LogRaw("全星系", Global);
		}

		private void LogRaw(string scope, PowerSnapshot s)
		{
			if (((PowerSnapshot)(ref s)).IsValid)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[diag] " + scope + "raw" + $" capacityW={((PowerSnapshot)(ref s)).CapacityWatt:F0}" + $" requiredW={((PowerSnapshot)(ref s)).ConsumptionWatt:F0}" + $" servedW={((PowerSnapshot)(ref s)).ServedWatt:F0}" + $" generationW={((PowerSnapshot)(ref s)).GenerationWatt:F0}" + $" chargeW={((PowerSnapshot)(ref s)).ChargeWatt:F0}" + $" dischargeW={((PowerSnapshot)(ref s)).DischargeWatt:F0}" + $" storedJ={((PowerSnapshot)(ref s)).StoredJoule:F0}"));
			}
		}

		private static string Describe(PowerSnapshot s)
		{
			if (!((PowerSnapshot)(ref s)).IsValid)
			{
				return "(対象なし)";
			}
			return "発電 " + PowerFormatter.FormatWatt(((PowerSnapshot)(ref s)).GenerationWatt) + " / 需要 " + PowerFormatter.FormatWatt(((PowerSnapshot)(ref s)).ConsumptionWatt) + " / 供給 " + PowerFormatter.FormatWatt(((PowerSnapshot)(ref s)).ServedWatt) + " / 容量 " + PowerFormatter.FormatWatt(((PowerSnapshot)(ref s)).CapacityWatt) + " / 使用率 " + PowerFormatter.FormatPercent(((PowerSnapshot)(ref s)).UtilizationRatio) + " / 充足 " + PowerFormatter.FormatPercent(((PowerSnapshot)(ref s)).SatisfactionRatio) + " / 充電 " + PowerFormatter.FormatWatt(((PowerSnapshot)(ref s)).ChargeWatt) + " / 放電 " + PowerFormatter.FormatWatt(((PowerSnapshot)(ref s)).DischargeWatt) + " / 蓄電 " + PowerFormatter.FormatJoule(((PowerSnapshot)(ref s)).StoredJoule) + $" / 網数 {((PowerSnapshot)(ref s)).NetworkCount}";
		}
	}
}
namespace PowerMeter.Plugin.UI
{
	public class PowerMeterWidget
	{
		private const int RowCount = 4;

		private const int ColumnCount = 10;

		private const int ColLabel = 0;

		private const int ColGen = 1;

		private const int ColSep = 2;

		private const int ColCon = 3;

		private const int ColCap = 4;

		private const int ColUtil = 5;

		private const int ColSat = 6;

		private const int ColCharge = 7;

		private const int ColDischarge = 8;

		private const int ColStored = 9;

		private const int RowHeader = 0;

		private const int RowPlanet = 1;

		private const int RowStar = 2;

		private const int RowGlobal = 3;

		private static readonly Color BackgroundColor = new Color(0.04f, 0.08f, 0.12f, 1f);

		private static readonly Color HeaderColor = new Color(0.55f, 0.72f, 0.85f, 1f);

		private static readonly Color LabelColor = new Color(0.72f, 0.82f, 0.9f, 1f);

		private static readonly Color ValueColor = new Color(0.94f, 0.96f, 0.98f, 1f);

		private static readonly Color WarningColor = new Color(1f, 0.48f, 0.36f, 1f);

		private static readonly Color ChargeColor = new Color(1f, 0.72f, 0.35f, 1f);

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

		private GameObject _root;

		private RectTransform _rootRect;

		private Image _background;

		private Text[,] _cells;

		private WidgetLabels _labels;

		public bool Exists => (Object)(object)_root != (Object)null;

		public bool TryCreate(PowerMeterConfig config)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_root != (Object)null)
			{
				return true;
			}
			Transform val = FindParent();
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			_root = new GameObject("PowerMeterWidget", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			_rootRect = _root.GetComponent<RectTransform>();
			((Transform)_rootRect).SetParent(val, false);
			((Transform)_rootRect).localScale = Vector3.one;
			_background = _root.GetComponent<Image>();
			((Graphic)_background).raycastTarget = false;
			Font font = FindGameFont(val);
			_cells = new Text[4, 10];
			for (int i = 0; i < 4; i++)
			{
				for (int j = 0; j < 10; j++)
				{
					_cells[i, j] = CreateText(_rootRect, "R" + i + "C" + j, font);
				}
			}
			ApplyConfig(config);
			return true;
		}

		public void ApplyConfig(PowerMeterConfig config)
		{
			//IL_01bf: 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_01d5: 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)
			if (!((Object)(object)_root == (Object)null))
			{
				_labels = WidgetLabels.For(config.UseJapanese);
				int value = config.FontSize.Value;
				ChargeColumnMode value2 = config.ChargeColumn.Value;
				float num = Mathf.Round((float)value * 0.6f);
				float num2 = Mathf.Round((float)value * 0.5f);
				float num3 = Mathf.Round((float)value * 1.55f);
				float num4 = Mathf.Round((float)value * 4.6f);
				float num5 = Mathf.Round((float)value * 5.4f);
				float num6 = Mathf.Round((float)value * 0.9f);
				float width = Mathf.Round((float)value * 3.4f);
				float num7 = num;
				PlaceColumn(0, num7, num4, num3, num, value, (TextAnchor)3, visible: true);
				num7 += num4 + num2;
				PlaceColumn(1, num7, num5, num3, num, value, (TextAnchor)5, visible: true);
				num7 += num5;
				PlaceColumn(2, num7, num6, num3, num, value, (TextAnchor)4, visible: true);
				num7 += num6;
				PlaceColumn(3, num7, num5, num3, num, value, (TextAnchor)5, visible: true);
				num7 += num5;
				num7 = PlaceOptionalColumn(4, num7, num5, num3, num, num2, value, config.ShowCapacity.Value);
				num7 = PlaceOptionalColumn(5, num7, width, num3, num, num2, value, config.ShowUtilization.Value);
				num7 = PlaceOptionalColumn(6, num7, width, num3, num, num2, value, config.ShowSatisfaction.Value);
				num7 = PlaceOptionalColumn(7, num7, num5, num3, num, num2, value, value2 != ChargeColumnMode.Off);
				num7 = PlaceOptionalColumn(8, num7, num5, num3, num, num2, value, value2 == ChargeColumnMode.Split);
				num7 = PlaceOptionalColumn(9, num7, num5, num3, num, num2, value, config.ShowAccumulated.Value);
				_rootRect.sizeDelta = new Vector2(num7 + num, num * 2f + num3 * 4f);
				ApplyCorner(config);
				Color backgroundColor = BackgroundColor;
				backgroundColor.a = config.BackgroundOpacity.Value;
				((Graphic)_background).color = backgroundColor;
				((Behaviour)_background).enabled = config.BackgroundOpacity.Value > 0.001f;
				ApplyHeaderTexts(value2);
			}
		}

		public void UpdateValues(PowerSnapshot planet, PowerSnapshot star, PowerSnapshot global, PowerMeterConfig config)
		{
			//IL_001c: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_root == (Object)null))
			{
				SetRow(1, _labels.Planet, planet, config);
				SetRow(2, _labels.Star, star, config);
				SetRow(3, _labels.Global, global, config);
			}
		}

		public void SetVisible(bool visible)
		{
			if ((Object)(object)_root != (Object)null && _root.activeSelf != visible)
			{
				_root.SetActive(visible);
			}
		}

		public void Destroy()
		{
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
			}
			_root = null;
			_rootRect = null;
			_background = null;
			_cells = null;
		}

		private void SetRow(int row, string label, PowerSnapshot snapshot, PowerMeterConfig config)
		{
			//IL_0144: 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_01a0: 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_0065: 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_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			_cells[row, 0].text = label;
			_cells[row, 2].text = "/";
			if (!((PowerSnapshot)(ref snapshot)).IsValid)
			{
				for (int i = 1; i < 10; i++)
				{
					if (i != 2)
					{
						_cells[row, i].text = _labels.NoData;
						((Graphic)_cells[row, i]).color = ValueColor;
					}
				}
				return;
			}
			_cells[row, 1].text = PowerFormatter.FormatWatt(((PowerSnapshot)(ref snapshot)).GenerationWatt);
			_cells[row, 3].text = PowerFormatter.FormatWatt(((PowerSnapshot)(ref snapshot)).ConsumptionWatt);
			_cells[row, 4].text = PowerFormatter.FormatWatt(((PowerSnapshot)(ref snapshot)).CapacityWatt);
			_cells[row, 9].text = PowerFormatter.FormatJoule(((PowerSnapshot)(ref snapshot)).StoredJoule);
			_cells[row, 5].text = PowerFormatter.FormatPercent(((PowerSnapshot)(ref snapshot)).UtilizationRatio);
			((Graphic)_cells[row, 5]).color = ((((PowerSnapshot)(ref snapshot)).UtilizationRatio >= (double)config.UtilizationWarningPercent.Value / 100.0) ? WarningColor : ValueColor);
			_cells[row, 6].text = PowerFormatter.FormatPercent(((PowerSnapshot)(ref snapshot)).SatisfactionRatio);
			((Graphic)_cells[row, 6]).color = ((((PowerSnapshot)(ref snapshot)).SatisfactionRatio < (double)config.SatisfactionWarningPercent.Value / 100.0) ? WarningColor : ValueColor);
			if (config.ChargeColumn.Value == ChargeColumnMode.Split)
			{
				_cells[row, 7].text = PowerFormatter.FormatWatt(((PowerSnapshot)(ref snapshot)).ChargeWatt);
				((Graphic)_cells[row, 7]).color = ChargeColor;
				_cells[row, 8].text = PowerFormatter.FormatWatt(((PowerSnapshot)(ref snapshot)).DischargeWatt);
				((Graphic)_cells[row, 8]).color = DischargeColor;
			}
			else
			{
				double netChargeWatt = ((PowerSnapshot)(ref snapshot)).NetChargeWatt;
				_cells[row, 7].text = PowerFormatter.FormatSignedWatt(netChargeWatt);
				((Graphic)_cells[row, 7]).color = ((netChargeWatt < 0.0) ? DischargeColor : ChargeColor);
			}
		}

		private void ApplyHeaderTexts(ChargeColumnMode chargeMode)
		{
			//IL_013f: 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_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			_cells[0, 0].text = _labels.Title;
			_cells[0, 1].text = _labels.Generation;
			_cells[0, 2].text = string.Empty;
			_cells[0, 3].text = _labels.Demand;
			_cells[0, 4].text = _labels.Capacity;
			_cells[0, 5].text = _labels.Utilization;
			_cells[0, 6].text = _labels.Satisfaction;
			_cells[0, 7].text = ((chargeMode == ChargeColumnMode.Split) ? _labels.Charge : _labels.NetCharge);
			_cells[0, 8].text = _labels.Discharge;
			_cells[0, 9].text = _labels.Stored;
			for (int i = 0; i < 10; i++)
			{
				((Graphic)_cells[0, i]).color = HeaderColor;
			}
			for (int j = 1; j <= 3; j++)
			{
				((Graphic)_cells[j, 0]).color = LabelColor;
				((Graphic)_cells[j, 2]).color = LabelColor;
				((Graphic)_cells[j, 1]).color = ValueColor;
				((Graphic)_cells[j, 3]).color = ValueColor;
				((Graphic)_cells[j, 4]).color = ValueColor;
				((Graphic)_cells[j, 9]).color = ValueColor;
			}
		}

		private float PlaceOptionalColumn(int col, float x, float width, float rowHeight, float pad, float gap, int fontSize, bool visible)
		{
			if (!visible)
			{
				PlaceColumn(col, x, width, rowHeight, pad, fontSize, (TextAnchor)5, visible: false);
				return x;
			}
			PlaceColumn(col, x + gap, width, rowHeight, pad, fontSize, (TextAnchor)5, visible: true);
			return x + gap + width;
		}

		private void PlaceColumn(int col, float x, float width, float rowHeight, float pad, int fontSize, TextAnchor alignment, bool visible)
		{
			//IL_002a: 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_0056: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < 4; i++)
			{
				Text obj = _cells[i, col];
				((Component)obj).gameObject.SetActive(visible);
				obj.fontSize = fontSize;
				obj.alignment = alignment;
				RectTransform rectTransform = ((Graphic)obj).rectTransform;
				rectTransform.anchorMin = new Vector2(0f, 1f);
				rectTransform.anchorMax = new Vector2(0f, 1f);
				rectTransform.pivot = new Vector2(0f, 1f);
				rectTransform.sizeDelta = new Vector2(width, rowHeight);
				rectTransform.anchoredPosition = new Vector2(x, 0f - (pad + rowHeight * (float)i));
			}
		}

		private void ApplyCorner(PowerMeterConfig config)
		{
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: 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_00da: Unknown result type (might be due to invalid IL or missing references)
			float value = config.OffsetX.Value;
			float value2 = config.OffsetY.Value;
			Vector2 val = default(Vector2);
			Vector2 anchoredPosition = default(Vector2);
			switch (config.Corner.Value)
			{
			case WidgetCorner.TopLeft:
				((Vector2)(ref val))..ctor(0f, 1f);
				((Vector2)(ref anchoredPosition))..ctor(value, 0f - value2);
				break;
			case WidgetCorner.BottomLeft:
				((Vector2)(ref val))..ctor(0f, 0f);
				((Vector2)(ref anchoredPosition))..ctor(value, value2);
				break;
			case WidgetCorner.BottomRight:
				((Vector2)(ref val))..ctor(1f, 0f);
				((Vector2)(ref anchoredPosition))..ctor(0f - value, value2);
				break;
			default:
				((Vector2)(ref val))..ctor(1f, 1f);
				((Vector2)(ref anchoredPosition))..ctor(0f - value, 0f - value2);
				break;
			}
			_rootRect.anchorMin = val;
			_rootRect.anchorMax = val;
			_rootRect.pivot = val;
			_rootRect.anchoredPosition = anchoredPosition;
		}

		private static Text CreateText(RectTransform parent, string name, Font font)
		{
			//IL_0021: 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)
			Text component = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(Text)
			}).GetComponent<Text>();
			((Transform)((Graphic)component).rectTransform).SetParent((Transform)(object)parent, false);
			((Graphic)component).raycastTarget = false;
			component.horizontalOverflow = (HorizontalWrapMode)1;
			component.verticalOverflow = (VerticalWrapMode)1;
			component.supportRichText = false;
			((Graphic)component).color = ValueColor;
			if ((Object)(object)font != (Object)null)
			{
				component.font = font;
			}
			return component;
		}

		private static Transform FindParent()
		{
			UIRoot instance = UIRoot.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			UIGame uiGame = instance.uiGame;
			if ((Object)(object)uiGame != (Object)null)
			{
				if ((Object)(object)uiGame.lowGroup != (Object)null)
				{
					return (Transform)(object)uiGame.lowGroup;
				}
				if ((Object)(object)((Component)uiGame).transform != (Object)null)
				{
					return ((Component)uiGame).transform;
				}
			}
			if (!((Object)(object)instance.overlayCanvas != (Object)null))
			{
				return null;
			}
			return ((Component)instance.overlayCanvas).transform;
		}

		private static Font FindGameFont(Transform parent)
		{
			try
			{
				Text componentInChildren = ((Component)parent).GetComponentInChildren<Text>(true);
				if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.font != (Object)null)
				{
					return componentInChildren.font;
				}
			}
			catch (Exception)
			{
			}
			return LoadBuiltinFont("LegacyRuntime.ttf") ?? LoadBuiltinFont("Arial.ttf");
		}

		private static Font LoadBuiltinFont(string name)
		{
			try
			{
				return Resources.GetBuiltinResource<Font>(name);
			}
			catch (Exception)
			{
				return null;
			}
		}
	}
	public class WidgetLabels
	{
		public static readonly WidgetLabels Japanese = new WidgetLabels("電力", "発電", "需要", "容量", "使用率", "充足", "充電", "放電", "充放電", "蓄電", "惑星", "星系", "全星系", "—");

		public static readonly WidgetLabels English = new WidgetLabels("Power", "Gen", "Demand", "Cap", "Load", "Sat", "Charge", "Discharge", "Net", "Stored", "Planet", "System", "All", "—");

		public string Title { get; }

		public string Generation { get; }

		public string Demand { get; }

		public string Capacity { get; }

		public string Utilization { get; }

		public string Satisfaction { get; }

		public string Charge { get; }

		public string Discharge { get; }

		public string NetCharge { get; }

		public string Stored { get; }

		public string Planet { get; }

		public string Star { get; }

		public string Global { get; }

		public string NoData { get; }

		private WidgetLabels(string title, string generation, string demand, string capacity, string utilization, string satisfaction, string charge, string discharge, string netCharge, string stored, string planet, string star, string global, string noData)
		{
			Title = title;
			Generation = generation;
			Demand = demand;
			Capacity = capacity;
			Utilization = utilization;
			Satisfaction = satisfaction;
			Charge = charge;
			Discharge = discharge;
			NetCharge = netCharge;
			Stored = stored;
			Planet = planet;
			Star = star;
			Global = global;
			NoData = noData;
		}

		public static WidgetLabels For(bool japanese)
		{
			if (!japanese)
			{
				return English;
			}
			return Japanese;
		}
	}
}