using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
[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("LaplaceLogistics")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("LaplaceLogistics")]
[assembly: AssemblyTitle("LaplaceLogistics")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace LaplaceLogistics;
internal sealed class ConsoleTheme
{
internal readonly GUIStyle Window;
internal readonly GUIStyle Title;
internal readonly GUIStyle Nav;
internal readonly GUIStyle NavActive;
internal readonly GUIStyle Header;
internal readonly GUIStyle SubHeader;
internal readonly GUIStyle Label;
internal readonly GUIStyle Positive;
internal readonly GUIStyle Negative;
internal readonly GUIStyle Muted;
internal readonly GUIStyle Empty;
internal readonly GUIStyle Help;
internal readonly GUIStyle BarBackground;
internal readonly Texture2D Cyan;
internal readonly Texture2D Panel;
internal readonly Texture2D Amber;
internal readonly Texture2D Red;
internal ConsoleTheme()
{
//IL_0049: 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_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
//IL_010e: Unknown result type (might be due to invalid IL or missing references)
//IL_0132: Unknown result type (might be due to invalid IL or missing references)
//IL_014c: Unknown result type (might be due to invalid IL or missing references)
//IL_0151: Unknown result type (might be due to invalid IL or missing references)
//IL_0162: Unknown result type (might be due to invalid IL or missing references)
//IL_0177: Unknown result type (might be due to invalid IL or missing references)
//IL_0181: Unknown result type (might be due to invalid IL or missing references)
//IL_0189: Unknown result type (might be due to invalid IL or missing references)
//IL_0190: 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_01a3: Expected O, but got Unknown
//IL_01a8: Expected O, but got Unknown
//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
//IL_01df: Unknown result type (might be due to invalid IL or missing references)
//IL_01e6: 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_01f3: Unknown result type (might be due to invalid IL or missing references)
//IL_01fd: Expected O, but got Unknown
//IL_0202: Expected O, but got Unknown
//IL_020d: Unknown result type (might be due to invalid IL or missing references)
//IL_0212: 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_0233: Unknown result type (might be due to invalid IL or missing references)
//IL_023d: Unknown result type (might be due to invalid IL or missing references)
//IL_0249: 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_0259: Unknown result type (might be due to invalid IL or missing references)
//IL_0261: 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_0271: Unknown result type (might be due to invalid IL or missing references)
//IL_027b: Expected O, but got Unknown
//IL_027b: Unknown result type (might be due to invalid IL or missing references)
//IL_0287: Expected O, but got Unknown
//IL_028e: Unknown result type (might be due to invalid IL or missing references)
//IL_0293: Unknown result type (might be due to invalid IL or missing references)
//IL_029f: Unknown result type (might be due to invalid IL or missing references)
//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
//IL_02af: Unknown result type (might be due to invalid IL or missing references)
//IL_02bb: Expected O, but got Unknown
//IL_02c6: 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_02e0: Unknown result type (might be due to invalid IL or missing references)
//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
//IL_0300: Unknown result type (might be due to invalid IL or missing references)
//IL_0305: Unknown result type (might be due to invalid IL or missing references)
//IL_030f: Expected O, but got Unknown
//IL_0314: Expected O, but got Unknown
//IL_031f: Unknown result type (might be due to invalid IL or missing references)
//IL_0324: 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_0343: Unknown result type (might be due to invalid IL or missing references)
//IL_034a: Unknown result type (might be due to invalid IL or missing references)
//IL_0357: Expected O, but got Unknown
//IL_0362: Unknown result type (might be due to invalid IL or missing references)
//IL_0367: Unknown result type (might be due to invalid IL or missing references)
//IL_037c: Unknown result type (might be due to invalid IL or missing references)
//IL_0386: Unknown result type (might be due to invalid IL or missing references)
//IL_038d: Unknown result type (might be due to invalid IL or missing references)
//IL_0395: Unknown result type (might be due to invalid IL or missing references)
//IL_039a: Unknown result type (might be due to invalid IL or missing references)
//IL_03a4: Expected O, but got Unknown
//IL_03a9: Expected O, but got Unknown
//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
//IL_03b5: Unknown result type (might be due to invalid IL or missing references)
//IL_03ca: 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)
//IL_03e0: Expected O, but got Unknown
//IL_03e7: Unknown result type (might be due to invalid IL or missing references)
//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
//IL_0401: 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_0417: Expected O, but got Unknown
//IL_041e: Unknown result type (might be due to invalid IL or missing references)
//IL_0423: Unknown result type (might be due to invalid IL or missing references)
//IL_0438: Unknown result type (might be due to invalid IL or missing references)
//IL_0447: Expected O, but got Unknown
//IL_044e: Unknown result type (might be due to invalid IL or missing references)
//IL_0453: Unknown result type (might be due to invalid IL or missing references)
//IL_045f: Unknown result type (might be due to invalid IL or missing references)
//IL_0474: Unknown result type (might be due to invalid IL or missing references)
//IL_047e: Unknown result type (might be due to invalid IL or missing references)
//IL_0485: Unknown result type (might be due to invalid IL or missing references)
//IL_048c: Unknown result type (might be due to invalid IL or missing references)
//IL_0494: Unknown result type (might be due to invalid IL or missing references)
//IL_049d: Unknown result type (might be due to invalid IL or missing references)
//IL_04a7: Expected O, but got Unknown
//IL_04ac: Expected O, but got Unknown
//IL_04b3: Unknown result type (might be due to invalid IL or missing references)
//IL_04b8: Unknown result type (might be due to invalid IL or missing references)
//IL_04c4: Unknown result type (might be due to invalid IL or missing references)
//IL_04d9: Unknown result type (might be due to invalid IL or missing references)
//IL_04e3: Unknown result type (might be due to invalid IL or missing references)
//IL_04ea: Unknown result type (might be due to invalid IL or missing references)
//IL_04f2: Unknown result type (might be due to invalid IL or missing references)
//IL_04f9: Unknown result type (might be due to invalid IL or missing references)
//IL_0503: Expected O, but got Unknown
//IL_0503: Unknown result type (might be due to invalid IL or missing references)
//IL_0508: Unknown result type (might be due to invalid IL or missing references)
//IL_0512: Expected O, but got Unknown
//IL_0517: Expected O, but got Unknown
//IL_0522: Unknown result type (might be due to invalid IL or missing references)
//IL_0527: Unknown result type (might be due to invalid IL or missing references)
//IL_0534: Unknown result type (might be due to invalid IL or missing references)
//IL_0539: Unknown result type (might be due to invalid IL or missing references)
//IL_0543: Expected O, but got Unknown
//IL_0548: Expected O, but got Unknown
Font font = Font.CreateDynamicFontFromOSFont(new string[4] { "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Courier New" }, 13);
Panel = Texture(new Color(0.018f, 0.035f, 0.052f, 1f));
Texture2D background = Texture(new Color(0.07f, 0.13f, 0.18f, 1f));
Texture2D background2 = Texture(new Color(0.04f, 0.36f, 0.46f, 1f));
Texture2D background3 = Texture(new Color(0.035f, 0.075f, 0.105f, 1f));
Texture2D background4 = Texture(new Color(0.08f, 0.15f, 0.19f, 1f));
Cyan = Texture(new Color(0.1f, 0.78f, 0.88f, 1f));
Amber = Texture(new Color(1f, 0.68f, 0.12f, 1f));
Red = Texture(new Color(0.95f, 0.2f, 0.18f, 1f));
GUIStyle val = new GUIStyle(GUI.skin.window);
val.normal.background = Panel;
val.normal.textColor = new Color(0.72f, 0.94f, 1f);
val.fontSize = 13;
val.fontStyle = (FontStyle)1;
val.padding = new RectOffset(16, 16, 34, 16);
Window = val;
GUIStyle val2 = new GUIStyle(GUI.skin.label);
val2.normal.textColor = new Color(0.72f, 0.94f, 1f);
val2.fontSize = 13;
val2.fontStyle = (FontStyle)1;
val2.alignment = (TextAnchor)3;
val2.padding = new RectOffset(16, 8, 0, 0);
Title = val2;
GUIStyle val3 = new GUIStyle(GUI.skin.button);
val3.normal.background = background;
val3.normal.textColor = new Color(0.62f, 0.76f, 0.82f);
val3.hover.background = background2;
val3.hover.textColor = Color.white;
val3.fontSize = 11;
val3.fixedHeight = 27f;
val3.margin = new RectOffset(2, 2, 2, 2);
val3.alignment = (TextAnchor)4;
Nav = val3;
GUIStyle val4 = new GUIStyle(Nav);
val4.normal.background = background2;
val4.normal.textColor = Color.white;
val4.fontStyle = (FontStyle)1;
NavActive = val4;
GUIStyle val5 = new GUIStyle(GUI.skin.label);
val5.normal.textColor = new Color(0.2f, 0.86f, 0.94f);
val5.font = font;
val5.fontSize = 15;
val5.fontStyle = (FontStyle)1;
val5.margin = new RectOffset(2, 2, 8, 4);
Header = val5;
GUIStyle val6 = new GUIStyle(GUI.skin.label);
val6.normal.textColor = new Color(0.48f, 0.65f, 0.72f);
val6.font = font;
val6.fontSize = 10;
SubHeader = val6;
GUIStyle val7 = new GUIStyle(GUI.skin.label);
val7.normal.textColor = new Color(0.84f, 0.91f, 0.94f);
val7.font = font;
val7.fontSize = 12;
val7.padding = new RectOffset(3, 3, 2, 2);
Label = val7;
GUIStyle val8 = new GUIStyle(Label);
val8.normal.textColor = new Color(0.22f, 0.9f, 0.72f);
val8.fontStyle = (FontStyle)1;
Positive = val8;
GUIStyle val9 = new GUIStyle(Label);
val9.normal.textColor = new Color(1f, 0.36f, 0.31f);
val9.fontStyle = (FontStyle)1;
Negative = val9;
GUIStyle val10 = new GUIStyle(Label);
val10.normal.textColor = new Color(0.48f, 0.6f, 0.66f);
Muted = val10;
GUIStyle val11 = new GUIStyle(Label);
val11.normal.background = background3;
val11.normal.textColor = new Color(0.56f, 0.76f, 0.82f);
val11.alignment = (TextAnchor)4;
val11.wordWrap = true;
val11.fontSize = 14;
val11.padding = new RectOffset(30, 30, 30, 30);
Empty = val11;
GUIStyle val12 = new GUIStyle(Label);
val12.normal.background = background3;
val12.normal.textColor = new Color(0.7f, 0.88f, 0.92f);
val12.wordWrap = true;
val12.fontSize = 11;
val12.padding = new RectOffset(10, 10, 7, 7);
val12.margin = new RectOffset(2, 2, 2, 5);
Help = val12;
GUIStyle val13 = new GUIStyle(GUI.skin.box);
val13.normal.background = background4;
val13.padding = new RectOffset(0, 0, 0, 0);
BarBackground = val13;
}
private static Texture2D Texture(Color color)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: 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_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Expected O, but got Unknown
Texture2D val = new Texture2D(1, 1)
{
hideFlags = (HideFlags)61
};
val.SetPixel(0, 0, color);
val.Apply();
return val;
}
}
internal sealed class FlowAnalyzer
{
private sealed class PreviousSample
{
internal long Produced;
internal long Consumed;
internal double ProducedPerMinute;
internal double ConsumedPerMinute;
}
private readonly Dictionary<int, PreviousSample> previous = new Dictionary<int, PreviousSample>();
private float previousTime = -1f;
internal void CalculateRates(IList<FlowRow> rows, float now)
{
double num = ((previousTime < 0f) ? 0.0 : ((double)(now - previousTime) / 60.0));
foreach (FlowRow row in rows)
{
if (!previous.TryGetValue(row.ItemId, out var value))
{
value = new PreviousSample();
previous.Add(row.ItemId, value);
}
if (num > 0.0)
{
double num2 = (double)Math.Max(0L, row.Produced - value.Produced) / num;
double num3 = (double)Math.Max(0L, row.Consumed - value.Consumed) / num;
value.ProducedPerMinute = ((value.ProducedPerMinute == 0.0) ? num2 : (value.ProducedPerMinute * 0.65 + num2 * 0.35));
value.ConsumedPerMinute = ((value.ConsumedPerMinute == 0.0) ? num3 : (value.ConsumedPerMinute * 0.65 + num3 * 0.35));
}
value.Produced = row.Produced;
value.Consumed = row.Consumed;
row.ProducedPerMinute = value.ProducedPerMinute;
row.ConsumedPerMinute = value.ConsumedPerMinute;
}
previousTime = now;
}
}
internal sealed class FlowRow
{
internal int ItemId;
internal string Name;
internal long Stored;
internal long Produced;
internal long Consumed;
internal double ProducedPerMinute;
internal double ConsumedPerMinute;
internal double NetPerMinute => ProducedPerMinute - ConsumedPerMinute;
}
internal static class FlowSnapshot
{
internal static List<FlowRow> Capture()
{
Dictionary<int, FlowRow> dictionary = new Dictionary<int, FlowRow>();
FactoryProductionStat[] array = (GameMain.data?.statistics?.production)?.factoryStatPool;
if (array == null)
{
return new List<FlowRow>();
}
FactoryProductionStat[] array2 = array;
foreach (FactoryProductionStat val in array2)
{
if (val?.productPool == null)
{
continue;
}
int num = Math.Min(val.productCursor, val.productPool.Length);
for (int j = 1; j < num; j++)
{
ProductStat val2 = val.productPool[j];
if (val2 != null && val2.itemId > 0)
{
if (!dictionary.TryGetValue(val2.itemId, out var value))
{
ItemProto val3 = ((ProtoSet<ItemProto>)(object)LDB.items).Select(val2.itemId);
value = new FlowRow
{
ItemId = val2.itemId,
Name = ((val3 == null) ? $"Item {val2.itemId}" : ((Proto)val3).name)
};
dictionary.Add(val2.itemId, value);
}
value.Stored += val2.storageCount;
}
}
}
foreach (FlowRow value2 in dictionary.Values)
{
value2.Produced = FlowTelemetry.ProducedTotal(value2.ItemId);
value2.Consumed = FlowTelemetry.ConsumedTotal(value2.ItemId);
}
return (from row in dictionary.Values
where row.Produced != 0L || row.Consumed != 0L || row.Stored != 0
orderby row.NetPerMinute, row.Name
select row).ToList();
}
}
internal static class FlowTelemetry
{
private static readonly ConcurrentDictionary<int, long> Produced = new ConcurrentDictionary<int, long>();
private static readonly ConcurrentDictionary<int, long> Consumed = new ConcurrentDictionary<int, long>();
internal static void RecordProduced(int itemId, int count)
{
if (itemId > 0 && count > 0)
{
Produced.AddOrUpdate(itemId, count, (int _, long current) => current + count);
}
}
internal static void RecordConsumed(int itemId, int count)
{
if (itemId > 0 && count > 0)
{
Consumed.AddOrUpdate(itemId, count, (int _, long current) => current + count);
}
}
internal static long ProducedTotal(int itemId)
{
if (!Produced.TryGetValue(itemId, out var value))
{
return 0L;
}
return value;
}
internal static long ConsumedTotal(int itemId)
{
if (!Consumed.TryGetValue(itemId, out var value))
{
return 0L;
}
return value;
}
}
[HarmonyPatch(typeof(FactoryProductionStat), "AddProductionToTotalArray")]
internal static class ObserveProductionPatch
{
private static void Prefix(int itemId, int itemCount)
{
FlowTelemetry.RecordProduced(itemId, itemCount);
}
}
[HarmonyPatch(typeof(FactoryProductionStat), "AddConsumptionToTotalArray")]
internal static class ObserveConsumptionPatch
{
private static void Prefix(int itemId, int itemCount)
{
FlowTelemetry.RecordConsumed(itemId, itemCount);
}
}
internal static class InstrumentVisuals
{
internal static void Draw(int panel, IList<FlowRow> flows, ConsoleTheme theme)
{
GUILayout.Label("LIVE SIGNAL BOARD", theme.Header, Array.Empty<GUILayoutOption>());
switch (panel)
{
case 1:
DrawOrbits(theme);
break;
case 2:
DrawAlignment(theme);
break;
case 3:
DrawRoutes(theme);
break;
case 4:
DrawEnvironment(theme);
break;
case 5:
DrawPower(theme);
break;
case 7:
DrawResources(theme);
break;
case 8:
DrawHome(theme);
break;
case 9:
DrawDyson(theme);
break;
case 10:
DrawFleet(theme);
break;
case 11:
DrawDeficits(flows, theme);
break;
case 12:
DrawRisk(flows, theme);
break;
default:
GUILayout.Label("No visual signal is available for this instrument.", theme.Empty, Array.Empty<GUILayoutOption>());
break;
}
}
private static void DrawOrbits(ConsoleTheme theme)
{
PlanetData[] array = GameMain.localStar?.planets;
if (array == null)
{
Empty("NO ORBITAL SIGNAL", theme);
return;
}
foreach (PlanetData item in array.Take(8))
{
Gauge(Short(item.displayName), Normalize(item.runtimeOrbitPhase) / 360.0, $"{Normalize(item.runtimeOrbitPhase):N0}° phase", theme, theme.Cyan);
}
}
private static void DrawAlignment(ConsoleTheme theme)
{
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
PlanetData origin = GameMain.localPlanet;
PlanetData[] array = GameMain.localStar?.planets;
if (origin == null || array == null)
{
Empty("LAND ON A PLANET TO COMPARE ALIGNMENT", theme);
return;
}
foreach (PlanetData item in array.Where((PlanetData value) => value != origin).Take(8))
{
double num = Angle(origin.runtimePosition, item.runtimePosition);
Gauge(Short(item.displayName), num / 180.0, $"{num:N0}° separation", theme, (num < 30.0) ? theme.Cyan : ((num < 90.0) ? theme.Amber : theme.Red));
}
}
private static void DrawRoutes(ConsoleTheme theme)
{
PlanetData origin = GameMain.localPlanet;
PlanetData[] array = GameMain.localStar?.planets;
if (origin == null || array == null)
{
Empty("NO ROUTING ORIGIN", theme);
return;
}
var list = (from target in array
where target != origin
select new
{
Planet = target,
Distance = Distance(origin.uPosition, target.uPosition) / 40000.0
}).ToList();
double num = Math.Max(0.001, (list.Count == 0) ? 1.0 : list.Max(value => value.Distance));
foreach (var item in list.Take(8))
{
Gauge(Short(item.Planet.displayName), item.Distance / num, $"{item.Distance:N3} AU", theme, theme.Cyan);
}
}
private static void DrawEnvironment(ConsoleTheme theme)
{
PlanetData localPlanet = GameMain.localPlanet;
if (localPlanet == null)
{
Empty("LAND ON A PLANET TO READ ENVIRONMENT", theme);
return;
}
Gauge("SOLAR POTENTIAL", Math.Min(1.0, (double)localPlanet.luminosity / 2.0), $"{localPlanet.luminosity:P0} reference", theme, theme.Amber);
Gauge("WIND POTENTIAL", Math.Min(1.0, (double)localPlanet.windStrength / 2.0), $"{localPlanet.windStrength:P0} reference", theme, theme.Cyan);
Gauge("AXIAL TILT", Math.Min(1.0, (double)Math.Abs(localPlanet.obliquity) / 90.0), $"{localPlanet.obliquity:N1}°", theme, theme.Cyan);
}
private static void DrawPower(ConsoleTheme theme)
{
PowerSystem val = GameMain.localPlanet?.factory?.powerSystem;
if (val?.netPool == null)
{
Empty("NO POWER NETWORK", theme);
return;
}
long num = 0L;
long num2 = 0L;
long num3 = 0L;
long num4 = 0L;
PowerNetwork[] netPool = val.netPool;
foreach (PowerNetwork val2 in netPool)
{
if (val2 != null && val2.id > 0)
{
num += val2.energyRequired;
num2 += val2.energyServed;
num3 += val2.energyStored;
num4 += val2.energyCapacity;
}
}
double num5 = ((num <= 0) ? 1.0 : ((double)num2 / (double)num));
double num6 = ((num4 <= 0) ? 0.0 : ((double)num3 / (double)num4));
Gauge("DEMAND SERVED", num5, num5.ToString("P1"), theme, (num5 >= 0.999) ? theme.Cyan : ((num5 >= 0.9) ? theme.Amber : theme.Red));
Gauge("ACCUMULATOR RESERVE", num6, num6.ToString("P1"), theme, (num6 > 0.25) ? theme.Cyan : theme.Amber);
}
private static void DrawResources(ConsoleTheme theme)
{
PlanetData localPlanet = GameMain.localPlanet;
VeinGroup[] array = ((localPlanet != null) ? localPlanet.runtimeVeinGroups : null);
if (array == null)
{
Empty("NO RESOURCE SURVEY", theme);
return;
}
var list = (from @group in array
where !((VeinGroup)(ref @group)).isNull
group @group by @group.type into @group
select new
{
Name = ((object)@group.Key/*cast due to .constrained prefix*/).ToString(),
Amount = @group.Sum((VeinGroup value) => value.amount)
} into value
orderby value.Amount
select value).ToList();
double num = Math.Max(1.0, (list.Count == 0) ? 1.0 : list.Max(value => (double)value.Amount));
foreach (var item in list.Take(8))
{
Gauge(item.Name, (double)item.Amount / num, $"{item.Amount:N0} remaining", theme, (item == list.First()) ? theme.Amber : theme.Cyan);
}
}
private static void DrawHome(ConsoleTheme theme)
{
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
Card("FACTORIES", GameMain.data.factoryCount.ToString("N0"), theme);
StarData localStar = GameMain.localStar;
Card("LOCAL STAR", ((localStar != null) ? localStar.displayName : null) ?? "IN TRANSIT", theme);
PlanetData localPlanet = GameMain.localPlanet;
Card("LOCAL PLANET", ((localPlanet != null) ? localPlanet.displayName : null) ?? "IN SPACE", theme);
GUILayout.EndHorizontal();
}
private static void DrawDyson(ConsoleTheme theme)
{
StarData localStar = GameMain.localStar;
object obj;
if (localStar != null)
{
DysonSphere[] dysonSpheres = GameMain.data.dysonSpheres;
obj = ((dysonSpheres != null) ? dysonSpheres[localStar.index] : null);
}
else
{
obj = null;
}
DysonSphere val = (DysonSphere)obj;
if (val == null)
{
Empty("NO LOCAL DYSON STRUCTURE", theme);
return;
}
double fraction = ((val.totalStructurePoint <= 0) ? 0.0 : ((double)val.totalConstructedStructurePoint / (double)val.totalStructurePoint));
double fraction2 = ((val.totalCellPoint <= 0) ? 0.0 : ((double)val.totalConstructedCellPoint / (double)val.totalCellPoint));
Gauge("STRUCTURE", fraction, fraction.ToString("P1"), theme, theme.Cyan);
Gauge("SOLAR-SAIL CELLS", fraction2, fraction2.ToString("P1"), theme, theme.Amber);
}
private static void DrawFleet(ConsoleTheme theme)
{
StationComponent[] array = GameMain.data.galacticTransport?.stationPool;
if (array == null)
{
Empty("NO LOGISTICS FLEET", theme);
return;
}
List<StationComponent> source = array.Where((StationComponent station) => station != null && station.id > 0).ToList();
int num = source.Sum((StationComponent station) => station.idleShipCount + station.workShipCount);
int num2 = source.Sum((StationComponent station) => station.workShipCount);
int num3 = source.Sum((StationComponent station) => station.idleDroneCount + station.workDroneCount);
int num4 = source.Sum((StationComponent station) => station.workDroneCount);
Gauge("VESSEL UTILIZATION", (num == 0) ? 0.0 : ((double)num2 / (double)num), $"{num2:N0} / {num:N0} active", theme, theme.Cyan);
Gauge("DRONE UTILIZATION", (num3 == 0) ? 0.0 : ((double)num4 / (double)num3), $"{num4:N0} / {num3:N0} active", theme, theme.Cyan);
}
private static void DrawDeficits(IList<FlowRow> flows, ConsoleTheme theme)
{
List<FlowRow> list = (from flow in flows
where flow.NetPerMinute < -0.01
orderby flow.NetPerMinute
select flow).Take(8).ToList();
if (list.Count == 0)
{
Empty("NO ACTIVE MATERIAL DEFICITS", theme);
return;
}
double num = list.Max((FlowRow flow) => 0.0 - flow.NetPerMinute);
foreach (FlowRow item in list)
{
Gauge(Short(item.Name), (0.0 - item.NetPerMinute) / num, $"losing {0.0 - item.NetPerMinute:N1}/min", theme, theme.Red);
}
}
private static void DrawRisk(IList<FlowRow> flows, ConsoleTheme theme)
{
int num = flows.Count((FlowRow flow) => flow.NetPerMinute < -0.01);
int num2 = flows.Count((FlowRow flow) => flow.NetPerMinute < -0.01 && flow.Stored <= 0);
double num3 = flows.Where((FlowRow flow) => flow.NetPerMinute < 0.0).Sum((FlowRow flow) => 0.0 - flow.NetPerMinute);
double num4 = Math.Min(100.0, (double)num2 * 12.0 + (double)num * 1.5 + Math.Log10(1.0 + num3) * 8.0);
Gauge("CIVILIZATION RISK", num4 / 100.0, $"{num4:N1} / 100", theme, (num4 < 20.0) ? theme.Cyan : ((num4 < 50.0) ? theme.Amber : theme.Red));
Gauge("EMPTY SHORTAGES", Math.Min(1.0, (double)num2 / 10.0), $"{num2:N0} empty and declining", theme, (num2 == 0) ? theme.Cyan : theme.Red);
}
private static void Gauge(string label, double fraction, string value, ConsoleTheme theme, Texture2D color)
{
//IL_0042: 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)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
GUILayout.Label(label, theme.Label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(185f) });
Rect rect = GUILayoutUtility.GetRect(100f, 17f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
GUI.Box(rect, GUIContent.none, theme.BarBackground);
float num = ((Rect)(ref rect)).width * Mathf.Clamp01((float)fraction);
GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, num, ((Rect)(ref rect)).height), (Texture)(object)color);
GUILayout.Label(value, theme.Label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(145f) });
GUILayout.EndHorizontal();
}
private static void Card(string label, string value, ConsoleTheme theme)
{
GUILayout.BeginVertical(theme.Help, (GUILayoutOption[])(object)new GUILayoutOption[2]
{
GUILayout.ExpandWidth(true),
GUILayout.Height(82f)
});
GUILayout.Label(label, theme.SubHeader, Array.Empty<GUILayoutOption>());
GUILayout.Label(value, theme.Header, Array.Empty<GUILayoutOption>());
GUILayout.EndVertical();
}
private static void Empty(string message, ConsoleTheme theme)
{
GUILayout.Label(message, theme.Empty, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(90f) });
}
private static string Short(string value)
{
if (!string.IsNullOrEmpty(value))
{
if (value.Length > 22)
{
return value.Substring(0, 22);
}
return value;
}
return "UNKNOWN";
}
private static double Normalize(double degrees)
{
return (degrees % 360.0 + 360.0) % 360.0;
}
private static double Distance(VectorLF3 a, VectorLF3 b)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: 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_0021: Unknown result type (might be due to invalid IL or missing references)
double num = a.x - b.x;
double num2 = a.y - b.y;
double num3 = a.z - b.z;
return Math.Sqrt(num * num + num2 * num2 + num3 * num3);
}
private static double Angle(VectorLF3 a, VectorLF3 b)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: 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_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: 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_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: 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_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
double num = a.x * b.x + a.y * b.y + a.z * b.z;
double num2 = Math.Sqrt(a.x * a.x + a.y * a.y + a.z * a.z) * Math.Sqrt(b.x * b.x + b.y * b.y + b.z * b.z);
if (!(num2 <= 0.0))
{
return Math.Acos(Math.Max(-1.0, Math.Min(1.0, num / num2))) * 180.0 / Math.PI;
}
return 0.0;
}
}
internal static class OperationsDeck
{
private const double RadiansToDegrees = 180.0 / Math.PI;
internal static string Title(int panel)
{
string[] array = new string[13]
{
"", "EPHEMERIS", "ALIGNMENT SOLVER", "LOGISTICS GEOMETRY", "ILLUMINATION", "POWER STABILITY", "MATERIAL FLOW", "DEPLETION MODEL", "LAPLACE HOME", "DYSON ANALYSIS",
"FLEET MATHEMATICS", "DEPENDENCY FORECAST", "CIVILIZATION RISK"
};
if (panel < 1 || panel > 12)
{
return "LAPLACE HOME";
}
return array[panel];
}
internal static string Help(int panel)
{
string[] array = new string[13]
{
"", "Live orbital reference for every body in the local system. Phase and period come directly from DSP's simulation.", "Compares the current planet with its neighbors. Small star-centered separation angles indicate favorable geometry; this is not a launch autopilot.", "Estimates straight-line vessel travel from current positions. Dispatch, acceleration, and warp transitions are deliberately excluded.", "Reports the local world's solar, rotational, atmospheric, and wind parameters without changing generation or weather.", "Combines all loaded power networks on the local planet. Demand served below 100% means consumers are being throttled.", "Measures production and consumption events observed since this session began. Press V for Numerical, Visual, or Hybrid presentation.", "Surveys remaining vein units and nodes on the current planet, ordered toward scarce resources first.", "Deck status and current simulation context. Select instruments with the buttons or configured F-keys.", "Shows completion and live output for the Dyson structure around the local star. Empty systems remain in standby.",
"Aggregates logistics stations, drones, vessels, energy, warpers, and current utilization across the cluster.", "Ranks measured deficits and estimates time to empty at the present net rate. It is a warning model, not a production planner.", "Summarizes active shortages as a transparent 0–100 operational risk heuristic. It never changes the factory or your save."
};
if (panel < 1 || panel > 12)
{
return array[8];
}
return array[panel];
}
internal static List<string> Build(int panel, IList<FlowRow> flows)
{
List<string> list = new List<string>();
if (GameMain.data == null)
{
list.Add("Awaiting an active factory simulation...");
return list;
}
switch (panel)
{
case 1:
BuildEphemeris(list);
break;
case 2:
BuildAlignment(list);
break;
case 3:
BuildGeometry(list);
break;
case 4:
BuildIllumination(list);
break;
case 5:
BuildPower(list);
break;
case 7:
BuildDepletion(list);
break;
case 8:
BuildHome(list);
break;
case 9:
BuildDyson(list);
break;
case 10:
BuildFleet(list);
break;
case 11:
BuildDependencies(list, flows);
break;
case 12:
BuildRisk(list, flows);
break;
default:
BuildHome(list);
break;
}
return list;
}
internal static List<string> BuildPlain(int panel, IList<FlowRow> flows)
{
List<string> list = new List<string>();
if (GameMain.data == null)
{
list.Add("Start or load a game and Laplace will explain what your factory is doing.");
return list;
}
PlanetData planet = GameMain.localPlanet;
StarData localStar = GameMain.localStar;
switch (panel)
{
case 1:
list.Add("You are in the " + (((localStar != null) ? localStar.displayName : null) ?? "current") + " system.");
list.Add((localStar?.planets == null) ? "No orbit information is available yet." : $"This system has {localStar.planets.Length} planets or moons. Technical mode shows their exact orbit and rotation numbers.");
break;
case 2:
list.Add((planet == null) ? "Land on a planet before comparing travel alignment." : ("Using " + planet.displayName + " as your starting point, FAVORABLE destinations are currently positioned for simpler routes."));
list.Add("MODERATE routes are workable. POOR routes cross a wide angle around the star and are less convenient right now.");
if (planet == null || localStar?.planets == null)
{
break;
}
foreach (PlanetData item in localStar.planets.Where((PlanetData value) => value != planet).Take(6))
{
list.Add("Next estimated best window to " + Trim(item.displayName) + ": " + Duration(NextAlignmentSeconds(planet, item)) + ".");
}
list.Add("These are orbital planning estimates, not guaranteed fastest vessel arrivals.");
break;
case 3:
list.Add((planet == null) ? "Land on a planet before estimating logistics trips." : ("Laplace estimates vessel travel from " + planet.displayName + " using a straight line and normal sailing speed."));
list.Add("Real trips can take longer while ships launch, accelerate, dock, or enter warp.");
break;
case 4:
list.Add((planet == null) ? "Land on a planet to inspect its environment." : $"On {planet.displayName}, solar strength is {planet.luminosity:P0} and wind strength is {planet.windStrength:P0} of the game's reference levels.");
list.Add("Higher values generally mean solar panels or wind turbines perform better here.");
break;
case 5:
BuildPlainPower(list);
break;
case 7:
BuildPlainResources(list, planet);
break;
case 8:
list.Add($"Laplace can see {GameMain.data.factoryCount:N0} active planetary factories.");
list.Add("You are " + ((planet == null) ? "travelling in space" : ("on " + planet.displayName)) + ".");
list.Add("Use the numbered buttons to inspect a system. Press U for the raw engineering readout.");
break;
case 9:
BuildPlainDyson(list, localStar);
break;
case 10:
BuildPlainFleet(list);
break;
case 11:
BuildPlainForecast(list, flows);
break;
case 12:
BuildPlainRisk(list, flows);
break;
default:
list.Add("Press U to switch back to the full technical readout.");
break;
}
return list;
}
private static void BuildPlainPower(List<string> lines)
{
PowerSystem val = GameMain.localPlanet?.factory?.powerSystem;
if (val?.netPool == null)
{
lines.Add("No planetary power grid is available here.");
return;
}
long num = 0L;
long num2 = 0L;
long num3 = 0L;
long num4 = 0L;
PowerNetwork[] netPool = val.netPool;
foreach (PowerNetwork val2 in netPool)
{
if (val2 != null && val2.id > 0)
{
num += val2.energyRequired;
num2 += val2.energyServed;
num3 += val2.energyStored;
num4 += val2.energyCapacity;
}
}
double num5 = ((num <= 0) ? 1.0 : ((double)num2 / (double)num));
double num6 = ((num4 <= 0) ? 0.0 : ((double)num3 / (double)num4));
lines.Add((num5 >= 0.999) ? "Your power grid is fully supplying its machines." : $"Your grid is meeting only {num5:P0} of demand. Some machines are slowing down or stopping.");
lines.Add((num4 <= 0) ? "You have no measured accumulator reserve." : $"Your accumulators are {num6:P0} charged.");
}
private static void BuildPlainResources(List<string> lines, PlanetData planet)
{
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
VeinGroup[] array = ((planet != null) ? planet.runtimeVeinGroups : null);
if (array == null)
{
lines.Add("Resource information is not available on the current planet.");
return;
}
var anon = (from @group in array
where !((VeinGroup)(ref @group)).isNull
group @group by @group.type into @group
select new
{
Type = @group.Key,
Amount = @group.Sum((VeinGroup value) => value.amount)
} into value
orderby value.Amount
select value).FirstOrDefault();
lines.Add((anon == null) ? "No mineable vein resources were found." : $"Your scarcest local vein resource is {anon.Type}, with about {anon.Amount:N0} units remaining.");
lines.Add("Technical mode contains the complete resource table.");
}
private static void BuildPlainDyson(List<string> lines, StarData star)
{
object obj;
if (star != null)
{
DysonSphere[] dysonSpheres = GameMain.data.dysonSpheres;
obj = ((dysonSpheres != null) ? dysonSpheres[star.index] : null);
}
else
{
obj = null;
}
DysonSphere val = (DysonSphere)obj;
if (val == null)
{
lines.Add("There is no Dyson structure around the local star yet.");
return;
}
double num = ((val.totalStructurePoint <= 0) ? 0.0 : ((double)val.totalConstructedStructurePoint / (double)val.totalStructurePoint));
double num2 = ((val.totalCellPoint <= 0) ? 0.0 : ((double)val.totalConstructedCellPoint / (double)val.totalCellPoint));
lines.Add($"The local Dyson structure is {num:P0} built and its solar-sail cells are {num2:P0} complete.");
lines.Add($"There are currently {val.rocketCount:N0} rockets flying toward it.");
}
private static void BuildPlainFleet(List<string> lines)
{
StationComponent[] array = GameMain.data.galacticTransport?.stationPool;
if (array == null)
{
lines.Add("No logistics network information is available.");
return;
}
List<StationComponent> list = array.Where((StationComponent station) => station != null && station.id > 0).ToList();
int num = list.Sum((StationComponent station) => station.idleShipCount + station.workShipCount);
int num2 = list.Sum((StationComponent station) => station.workShipCount);
int num3 = list.Sum((StationComponent station) => station.idleDroneCount + station.workDroneCount);
int num4 = list.Sum((StationComponent station) => station.workDroneCount);
lines.Add($"{list.Count:N0} stations manage {num:N0} vessels and {num3:N0} drones.");
lines.Add($"Right now, {num2:N0} vessels and {num4:N0} drones are making deliveries.");
lines.Add((num > 0 && num2 == num) ? "Every vessel is busy; more ships or shorter routes may help." : "Some vessel capacity is still available.");
}
private static void BuildPlainForecast(List<string> lines, IList<FlowRow> flows)
{
List<FlowRow> list = (from flow in flows
where flow.NetPerMinute < -0.01
orderby flow.NetPerMinute
select flow).ToList();
if (list.Count == 0)
{
lines.Add("No measured item is currently being consumed faster than it is produced.");
return;
}
lines.Add($"{list.Count} item types are shrinking. The worst shortage is {list[0].Name} at {Math.Abs(list[0].NetPerMinute):N1} items per minute.");
FlowRow flowRow = (from flow in list
where flow.Stored > 0
orderby (double)flow.Stored / (0.0 - flow.NetPerMinute)
select flow).FirstOrDefault();
if (flowRow != null)
{
lines.Add("At the present rate, " + flowRow.Name + " is the next stocked item expected to run out: roughly " + Duration((double)flowRow.Stored / (0.0 - flowRow.NetPerMinute) * 60.0) + ".");
}
lines.Add("This describes what is happening now; it does not assume demand stays constant forever.");
}
private static void BuildPlainRisk(List<string> lines, IList<FlowRow> flows)
{
int num = flows.Count((FlowRow flow) => flow.NetPerMinute < -0.01);
int num2 = flows.Count((FlowRow flow) => flow.NetPerMinute < -0.01 && flow.Stored <= 0);
if (num == 0)
{
lines.Add("Laplace sees no active material shortages. Your measured supply picture is controlled.");
}
else if (num2 > 0)
{
lines.Add($"Warning: {num2} required item types are already empty and still in deficit. Production chains are likely stalled.");
}
else
{
lines.Add($"{num} item types are declining, but none of the measured shortages are empty yet.");
}
lines.Add("Civilization Risk is an early-warning summary, not a prediction that your entire factory will fail.");
}
private static void BuildEphemeris(List<string> lines)
{
StarData localStar = GameMain.localStar;
if (localStar?.planets == null)
{
lines.Add("No local stellar ephemeris available.");
return;
}
lines.Add($"REFERENCE STAR {localStar.displayName} MASS {localStar.mass:N3} M☉ LUMINOSITY {localStar.luminosity:N3} L☉");
lines.Add("BODY ORBIT/AU PHASE/° PERIOD ROTATION TILT/°");
PlanetData[] planets = localStar.planets;
foreach (PlanetData val in planets)
{
lines.Add($"{Trim(val.displayName),-28} {val.orbitRadius,9:N3} {Normalize(val.runtimeOrbitPhase),13:N2} {Duration(val.orbitalPeriod),13} {Duration(Math.Abs(val.rotationPeriod)),13} {val.obliquity,10:N2}");
}
}
private static void BuildAlignment(List<string> lines)
{
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
PlanetData origin = GameMain.localPlanet;
StarData localStar = GameMain.localStar;
if (origin == null || localStar?.planets == null)
{
lines.Add("Land on a planet to establish an alignment origin.");
return;
}
lines.Add("ORIGIN " + origin.displayName);
lines.Add("TARGET SEPARATION/° DISTANCE/AU NEXT BEST WINDOW* ALIGNMENT");
foreach (PlanetData item in localStar.planets.Where((PlanetData p) => p != origin))
{
double num = Angle(origin.runtimePosition, item.runtimePosition);
double num2 = Distance(origin.uPosition, item.uPosition) / 40000.0;
string text = ((num < 30.0) ? "FAVORABLE" : ((num < 90.0) ? "MODERATE" : "POOR"));
double seconds = NextAlignmentSeconds(origin, item);
lines.Add($"{Trim(item.displayName),-25} {num,10:N2} {num2,13:N4} {Duration(seconds),20} {text}");
}
lines.Add("");
lines.Add("*Approximate next minimum-separation window from live phase and relative angular speed; moons and eccentric motion reduce accuracy.");
}
private static void BuildGeometry(List<string> lines)
{
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
PlanetData origin = GameMain.localPlanet;
StarData localStar = GameMain.localStar;
GameHistoryData history = GameMain.history;
if (origin == null || localStar?.planets == null)
{
lines.Add("No local routing origin available.");
return;
}
double num = Math.Max(1.0, history.logisticShipSailSpeedModified);
lines.Add($"VESSEL SAIL SPEED {num:N0} m/s CARGO CAPACITY {history.logisticShipCarries:N0}");
lines.Add("TARGET DISTANCE/AU ONE-WAY ETA* CARGO-DISTANCE");
foreach (PlanetData item in localStar.planets.Where((PlanetData p) => p != origin))
{
double num2 = Distance(origin.uPosition, item.uPosition);
double num3 = num2 / 40000.0;
lines.Add($"{Trim(item.displayName),-30} {num3,10:N4} {Duration(num2 / num),15} {(double)history.logisticShipCarries * num3,17:N1} item·AU");
}
lines.Add("*Straight-line game-model estimate; dispatch, acceleration and warping are excluded.");
}
private static void BuildIllumination(List<string> lines)
{
PlanetData localPlanet = GameMain.localPlanet;
if (localPlanet == null)
{
lines.Add("Land on a planet to initialize the illumination model.");
return;
}
lines.Add("BODY " + localPlanet.displayName);
lines.Add($"STELLAR DISTANCE {localPlanet.sunDistance:N4} AU");
lines.Add("ROTATION PERIOD " + Duration(Math.Abs(localPlanet.rotationPeriod)));
lines.Add($"AXIAL TILT {localPlanet.obliquity:N3}°");
lines.Add($"ORBITAL INCLINATION {localPlanet.orbitInclination:N3}°");
lines.Add($"ATMOSPHERE HEIGHT {localPlanet.atmosphereHeight:N1} m (game scale)");
lines.Add($"WIND RESOURCE FACTOR {localPlanet.windStrength:N3}");
lines.Add($"LOCAL SOLAR LUMINOSITY {localPlanet.luminosity:N3}");
}
private static void BuildPower(List<string> lines)
{
PowerSystem val = GameMain.localPlanet?.factory?.powerSystem;
if (val?.netPool == null)
{
lines.Add("No loaded planetary power networks available.");
return;
}
long num = 0L;
long num2 = 0L;
long num3 = 0L;
long num4 = 0L;
int num5 = 0;
PowerNetwork[] netPool = val.netPool;
foreach (PowerNetwork val2 in netPool)
{
if (val2 != null && val2.id > 0)
{
num5++;
num += val2.energyRequired;
num2 += val2.energyServed;
num3 += val2.energyStored;
num4 += val2.energyCapacity;
}
}
double num6 = ((num <= 0) ? 1.0 : ((double)num2 / (double)num));
double num7 = ((num4 <= 0) ? 0.0 : ((double)num3 / (double)num4));
lines.Add($"POWER NETWORKS {num5:N0}");
lines.Add($"DEMAND SERVED {num6:P3}");
lines.Add($"ACCUMULATOR CHARGE {num7:P3}");
lines.Add($"CONSUMERS {val.consumerCount:N0}");
lines.Add($"POWER NODES {val.nodeCount:N0}");
lines.Add("STABILITY CLASS " + ((num6 >= 0.999) ? "NOMINAL" : ((num6 >= 0.9) ? "DEGRADED" : "CRITICAL")));
}
private static void BuildDepletion(List<string> lines)
{
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
PlanetData localPlanet = GameMain.localPlanet;
VeinGroup[] array = ((localPlanet != null) ? localPlanet.runtimeVeinGroups : null);
if (array == null)
{
lines.Add("Vein survey unavailable or planet not scanned.");
return;
}
var orderedEnumerable = from g in array
where !((VeinGroup)(ref g)).isNull
group g by g.type into g
select new
{
Type = g.Key,
Amount = g.Sum((VeinGroup x) => x.amount),
Nodes = g.Sum((VeinGroup x) => x.count)
} into x
orderby x.Amount
select x;
lines.Add("SURVEY BODY " + localPlanet.displayName);
lines.Add("RESOURCE TYPE REMAINING UNITS NODES");
foreach (var item in orderedEnumerable)
{
lines.Add($"{item.Type,-30} {item.Amount,15:N0} {item.Nodes,14:N0}");
}
}
private static void BuildHome(List<string> lines)
{
GalaxyData galaxy = GameMain.galaxy;
lines.Add("LAPLACE SCIENTIFIC OPERATIONS DECK");
lines.Add($"GALAXY SEED {galaxy.seed}");
lines.Add($"STELLAR SYSTEMS {galaxy.starCount:N0}");
lines.Add($"ACTIVE FACTORIES {GameMain.data.factoryCount:N0}");
StarData localStar = GameMain.localStar;
lines.Add("LOCAL STAR " + (((localStar != null) ? localStar.displayName : null) ?? "IN TRANSIT"));
PlanetData localPlanet = GameMain.localPlanet;
lines.Add("LOCAL PLANET " + (((localPlanet != null) ? localPlanet.displayName : null) ?? "IN SPACE"));
lines.Add("");
lines.Add("Use the named tabs to select live instruments. Ctrl+L opens or closes the deck.");
}
private static void BuildDyson(List<string> lines)
{
StarData localStar = GameMain.localStar;
object obj;
if (localStar != null)
{
DysonSphere[] dysonSpheres = GameMain.data.dysonSpheres;
obj = ((dysonSpheres != null) ? dysonSpheres[localStar.index] : null);
}
else
{
obj = null;
}
DysonSphere val = (DysonSphere)obj;
if (val == null)
{
lines.Add("No Dyson structure exists around the local star.");
return;
}
double num = ((val.totalCellPoint <= 0) ? 0.0 : ((double)val.totalConstructedCellPoint / (double)val.totalCellPoint));
double num2 = ((val.totalStructurePoint <= 0) ? 0.0 : ((double)val.totalConstructedStructurePoint / (double)val.totalStructurePoint));
lines.Add("HOST STAR " + localStar.displayName);
lines.Add($"POWER OUTPUT {(double)val.energyGenCurrentTick / 1000000.0:N3} MW (game tick field)");
lines.Add($"STRUCTURE COMPLETION {num2:P3}");
lines.Add($"CELL COMPLETION {num:P3}");
lines.Add($"NODES {val.totalConstructedNodeCount:N0} / {val.totalNodeCount:N0}");
lines.Add($"FRAMES {val.totalConstructedFrameCount:N0} / {val.totalFrameCount:N0}");
lines.Add($"ROCKETS IN FLIGHT {val.rocketCount:N0}");
}
private static void BuildFleet(List<string> lines)
{
GalacticTransport galacticTransport = GameMain.data.galacticTransport;
StationComponent[] array = galacticTransport?.stationPool;
if (array == null)
{
lines.Add("Interstellar fleet telemetry unavailable.");
return;
}
int num = 0;
int num2 = 0;
int num3 = 0;
int num4 = 0;
int num5 = 0;
int num6 = 0;
long num7 = 0L;
long num8 = 0L;
StationComponent[] array2 = array;
foreach (StationComponent val in array2)
{
if (val != null && val.id > 0)
{
num++;
num2 += val.idleShipCount + val.workShipCount;
num3 += val.workShipCount;
num4 += val.idleDroneCount + val.workDroneCount;
num5 += val.workDroneCount;
num6 += val.warperCount;
num7 += val.energy;
num8 += val.energyMax;
}
}
lines.Add($"LOGISTICS STATIONS {num:N0}");
lines.Add($"VESSELS {num2:N0} total / {num3:N0} active");
lines.Add($"DRONES {num4:N0} total / {num5:N0} active");
lines.Add($"VESSEL UTILIZATION {((num2 == 0) ? 0.0 : ((double)num3 / (double)num2)):P2}");
lines.Add($"DRONE UTILIZATION {((num4 == 0) ? 0.0 : ((double)num5 / (double)num4)):P2}");
lines.Add($"STATION ENERGY {((num8 == 0L) ? 0.0 : ((double)num7 / (double)num8)):P2}");
lines.Add($"WARPER RESERVE {num6:N0}");
lines.Add($"ACTIVE REMOTE PAIRS {galacticTransport.remotePairCount:N0}");
}
private static void BuildDependencies(List<string> lines, IList<FlowRow> flows)
{
List<FlowRow> list = (from f in flows
where f.NetPerMinute < -0.01
orderby f.NetPerMinute
select f).Take(20).ToList();
lines.Add($"ACTIVE MATERIAL DEFICITS {flows.Count((FlowRow f) => f.NetPerMinute < -0.01):N0}");
lines.Add("MATERIAL NET/MIN STORED EXHAUSTION*");
foreach (FlowRow item in list)
{
double num = ((item.Stored <= 0) ? 0.0 : ((double)item.Stored / (0.0 - item.NetPerMinute)));
lines.Add($"{Trim(item.Name),-30} {item.NetPerMinute,10:N1} {item.Stored,15:N0} {Duration(num * 60.0),15}");
}
lines.Add("*Linear forecast at the measured net rate; recipe propagation arrives in the next model revision.");
}
private static void BuildRisk(List<string> lines, IList<FlowRow> flows)
{
int num = flows.Count((FlowRow f) => f.NetPerMinute < -0.01);
int num2 = flows.Count((FlowRow f) => f.NetPerMinute < -0.01 && f.Stored <= 0);
int num3 = (GameMain.data.galacticTransport?.stationPool)?.Where((StationComponent s) => s != null).Sum((StationComponent s) => s.workShipCount) ?? 0;
double num4 = flows.Where((FlowRow f) => f.NetPerMinute < 0.0).Sum((FlowRow f) => 0.0 - f.NetPerMinute);
double num5 = Math.Min(100.0, (double)num2 * 12.0 + (double)num * 1.5 + Math.Log10(1.0 + num4) * 8.0);
lines.Add($"CIVILIZATION RISK INDEX {num5:N1} / 100.0");
lines.Add($"DEFICIT MATERIALS {num:N0}");
lines.Add($"EMPTY + DECLINING {num2:N0}");
lines.Add($"TOTAL NEGATIVE FLOW {num4:N1} items/min");
lines.Add($"VESSELS CURRENTLY ACTIVE {num3:N0}");
lines.Add("ASSESSMENT " + ((num5 < 20.0) ? "CONTROLLED" : ((num5 < 50.0) ? "UNSTABLE" : ((num5 < 80.0) ? "SEVERE" : "ADMINISTRATIVE APOCALYPSE"))));
lines.Add("");
lines.Add("Index is a transparent operational heuristic, not a physical constant.");
}
private static double Normalize(double degrees)
{
return (degrees % 360.0 + 360.0) % 360.0;
}
private static double NextAlignmentSeconds(PlanetData origin, PlanetData target)
{
double num = Math.Abs(origin.orbitalPeriod);
double num2 = Math.Abs(target.orbitalPeriod);
if (num <= 0.0 || num2 <= 0.0)
{
return double.NaN;
}
double num3 = Normalize(target.runtimeOrbitPhase - origin.runtimeOrbitPhase);
double num4 = 360.0 / num2 - 360.0 / num;
if (Math.Abs(num4) < 1E-12)
{
return double.PositiveInfinity;
}
if (!(num4 > 0.0))
{
return num3 / (0.0 - num4);
}
return (360.0 - num3) / num4;
}
private static string Trim(string value)
{
if (!string.IsNullOrEmpty(value))
{
if (value.Length > 28)
{
return value.Substring(0, 28);
}
return value;
}
return "UNKNOWN";
}
private static string Duration(double seconds)
{
if (double.IsNaN(seconds) || double.IsInfinity(seconds))
{
return "—";
}
TimeSpan timeSpan = TimeSpan.FromSeconds(Math.Max(0.0, seconds));
if (!(timeSpan.TotalDays >= 1.0))
{
if (!(timeSpan.TotalHours >= 1.0))
{
return $"{timeSpan.Minutes:00}:{timeSpan.Seconds:00}";
}
return $"{(int)timeSpan.TotalHours:00}:{timeSpan.Minutes:00}:{timeSpan.Seconds:00}";
}
return $"{timeSpan.TotalDays:N1} d";
}
private static double Distance(VectorLF3 a, VectorLF3 b)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: 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_0021: Unknown result type (might be due to invalid IL or missing references)
double num = a.x - b.x;
double num2 = a.y - b.y;
double num3 = a.z - b.z;
return Math.Sqrt(num * num + num2 * num2 + num3 * num3);
}
private static double Angle(VectorLF3 a, VectorLF3 b)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: 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_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: 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_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: 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_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
double num = a.x * b.x + a.y * b.y + a.z * b.z;
double num2 = Math.Sqrt(a.x * a.x + a.y * a.y + a.z * a.z) * Math.Sqrt(b.x * b.x + b.y * b.y + b.z * b.z);
if (!(num2 <= 0.0))
{
return Math.Acos(Math.Max(-1.0, Math.Min(1.0, num / num2))) * (180.0 / Math.PI);
}
return 0.0;
}
}
[BepInPlugin("dev.h3llgoose.dsp.laplace-logistics", "Laplace Logistics Engine", "0.3.0")]
public sealed class Plugin : BaseUnityPlugin
{
public const string Guid = "dev.h3llgoose.dsp.laplace-logistics";
public const string Name = "Laplace Logistics Engine";
public const string Version = "0.3.0";
public const string SupportedGameVersion = "0.10.34.28529";
private ConfigEntry<KeyboardShortcut> toggleShortcut;
private ConfigEntry<KeyboardShortcut> modeShortcut;
private ConfigEntry<KeyboardShortcut> riskShortcut;
private ConfigEntry<KeyboardShortcut> helpShortcut;
private ConfigEntry<KeyboardShortcut> resetHelpShortcut;
private ConfigEntry<KeyboardShortcut> languageShortcut;
private ConfigEntry<string> tutorialsSeen;
private readonly List<FlowRow> rows = new List<FlowRow>();
private readonly FlowAnalyzer analyzer = new FlowAnalyzer();
private Rect windowRect = new Rect(72f, 72f, 900f, 680f);
private Vector2 scroll;
private bool visible;
private float nextRefresh;
private int activePanel = 8;
private int displayMode = 2;
private ConsoleTheme theme;
private bool showHelp = true;
private bool plainLanguage;
private readonly HashSet<int> seenPanels = new HashSet<int>();
private void Awake()
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_010f: Unknown result type (might be due to invalid IL or missing references)
//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
toggleShortcut = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Interface", "Toggle console", new KeyboardShortcut((KeyCode)108, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Show or hide the Laplace operations deck.");
modeShortcut = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Interface", "Cycle display mode", new KeyboardShortcut((KeyCode)118, Array.Empty<KeyCode>()), "Cycle Numerical, Visual, and Hybrid display modes while Laplace is visible.");
riskShortcut = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Interface", "Crisis mode alternate", new KeyboardShortcut((KeyCode)114, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Open Civilization Risk when the operating system reserves F12.");
helpShortcut = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Interface", "Contextual help", new KeyboardShortcut((KeyCode)104, Array.Empty<KeyCode>()), "Show or hide help for the active instrument.");
resetHelpShortcut = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Interface", "Reset tutorials", new KeyboardShortcut((KeyCode)104, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Clear first-use tutorial completion and show help again.");
languageShortcut = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Interface", "Plain language mode", new KeyboardShortcut((KeyCode)117, Array.Empty<KeyCode>()), "Toggle between technical telemetry and plain-language explanations.");
tutorialsSeen = ((BaseUnityPlugin)this).Config.Bind<string>("Interface", "Tutorials seen", string.Empty, "Comma-separated instrument numbers whose first-use help has been seen.");
string[] array = tutorialsSeen.Value.Split(new char[1] { ',' });
for (int i = 0; i < array.Length; i++)
{
if (int.TryParse(array[i], out var result) && result >= 1 && result <= 12)
{
seenPanels.Add(result);
}
}
Harmony.CreateAndPatchAll(typeof(Plugin).Assembly, "dev.h3llgoose.dsp.laplace-logistics");
if (!SupportedVersion(Application.version))
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("DSP " + Application.version + " differs from tested version 0.10.34.28529. Laplace will remain read-only, but displayed fields may have changed."));
}
((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} {1} initialized. Press {2} to open the deck.", "Laplace Logistics Engine", "0.3.0", toggleShortcut.Value));
}
private static bool SupportedVersion(string version)
{
if (!(version == "0.10.34.28529"))
{
if (!string.IsNullOrEmpty(version))
{
return "0.10.34.28529".StartsWith(version + ".");
}
return false;
}
return true;
}
private void Update()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: 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_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: 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)
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
KeyboardShortcut value = toggleShortcut.Value;
if (((KeyboardShortcut)(ref value)).IsDown())
{
visible = !visible;
nextRefresh = 0f;
}
if (visible)
{
value = modeShortcut.Value;
if (((KeyboardShortcut)(ref value)).IsDown())
{
displayMode = (displayMode + 1) % 3;
}
value = riskShortcut.Value;
if (((KeyboardShortcut)(ref value)).IsDown())
{
SelectPanel(12);
}
value = resetHelpShortcut.Value;
if (((KeyboardShortcut)(ref value)).IsDown())
{
ResetTutorials();
}
else
{
value = helpShortcut.Value;
if (((KeyboardShortcut)(ref value)).IsDown())
{
showHelp = !showHelp;
}
}
value = languageShortcut.Value;
if (((KeyboardShortcut)(ref value)).IsDown())
{
plainLanguage = !plainLanguage;
}
}
if (visible && Time.unscaledTime >= nextRefresh)
{
rows.Clear();
rows.AddRange(FlowSnapshot.Capture());
analyzer.CalculateRates(rows, Time.unscaledTime);
rows.Sort((FlowRow left, FlowRow right) => left.NetPerMinute.CompareTo(right.NetPerMinute));
nextRefresh = Time.unscaledTime + 2f;
}
}
private void OnGUI()
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Expected O, but got Unknown
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
if (visible)
{
if (theme == null)
{
theme = new ConsoleTheme();
}
ClampWindowToScreen();
windowRect = GUI.Window(907601, windowRect, new WindowFunction(DrawWindow), string.Empty, theme.Window);
}
}
private void DrawWindow(int id)
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_0165: Unknown result type (might be due to invalid IL or missing references)
//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
//IL_0259: 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_0193: Unknown result type (might be due to invalid IL or missing references)
GUI.DrawTexture(new Rect(0f, 0f, ((Rect)(ref windowRect)).width, ((Rect)(ref windowRect)).height), (Texture)(object)theme.Panel);
GUI.DrawTexture(new Rect(0f, 22f, ((Rect)(ref windowRect)).width, 3f), (Texture)(object)theme.Cyan);
GUI.Label(new Rect(0f, 0f, ((Rect)(ref windowRect)).width, 22f), "LAPLACE LOGISTICS // " + OperationsDeck.Title(activePanel) + " // " + ModeName() + " // " + (plainLanguage ? "PLAIN" : "TECHNICAL"), theme.Title);
DrawInstrumentButtons(1, 6);
DrawInstrumentButtons(7, 12);
GUILayout.Label("SCIENTIFIC OPERATIONS DECK • LIVE READ-ONLY TELEMETRY", theme.SubHeader, Array.Empty<GUILayoutOption>());
GUILayout.Space(7f);
if (showHelp)
{
GUILayout.Label(OperationsDeck.Help(activePanel), theme.Help, Array.Empty<GUILayoutOption>());
GUILayout.Space(5f);
}
if (activePanel != 6)
{
if (displayMode != 1)
{
scroll = GUILayout.BeginScrollView(scroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { (displayMode == 2) ? GUILayout.Height(230f) : GUILayout.ExpandHeight(true) });
foreach (string item in plainLanguage ? OperationsDeck.BuildPlain(activePanel, rows) : OperationsDeck.Build(activePanel, rows))
{
GUILayout.Label(item, theme.Label, Array.Empty<GUILayoutOption>());
}
GUILayout.EndScrollView();
}
if (displayMode != 0)
{
InstrumentVisuals.Draw(activePanel, rows, theme);
}
GUILayout.Label("U: plain/technical • H: help • V: display • Alt+R: crisis • Ctrl+L: close", theme.Muted, Array.Empty<GUILayoutOption>());
GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref windowRect)).width, 24f));
}
else
{
if (displayMode != 1)
{
DrawFlowTable();
}
if (displayMode != 0)
{
DrawFlowVisual();
}
GUILayout.Label("U: plain/technical • H: help • V: display • rates settle after samples • Ctrl+L: close", theme.Muted, Array.Empty<GUILayoutOption>());
GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref windowRect)).width, 24f));
}
}
private void DrawFlowTable()
{
//IL_0124: Unknown result type (might be due to invalid IL or missing references)
//IL_012e: Unknown result type (might be due to invalid IL or missing references)
//IL_0133: Unknown result type (might be due to invalid IL or missing references)
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
GUILayout.Label(plainLanguage ? "ITEM" : "MATERIAL", theme.Header, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(260f) });
GUILayout.Label(plainLanguage ? "ON HAND" : "STORED", theme.Header, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(105f) });
GUILayout.Label(plainLanguage ? "MADE/MIN" : "PROD/MIN", theme.Header, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(105f) });
GUILayout.Label(plainLanguage ? "USED/MIN" : "CONS/MIN", theme.Header, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(105f) });
GUILayout.Label(plainLanguage ? "GAIN/LOSS" : "NET", theme.Header, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(105f) });
GUILayout.EndHorizontal();
scroll = GUILayout.BeginScrollView(scroll, Array.Empty<GUILayoutOption>());
if (GameMain.data == null)
{
GUILayout.Label("AWAITING ACTIVE FACTORY SIMULATION", theme.Empty, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(130f) });
}
else if (rows.Count == 0)
{
GUILayout.Label("NO MATERIAL FLOW DETECTED\n\nBuild and power a production machine, then allow several seconds for telemetry sampling.", theme.Empty, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(150f) });
}
else
{
if (plainLanguage)
{
int num = rows.Count((FlowRow row) => row.NetPerMinute < -0.01);
GUILayout.Label((num == 0) ? "Your measured production is keeping up with consumption." : $"{num} item types are being used faster than they are made. Red numbers need attention.", (num == 0) ? theme.Positive : theme.Negative, Array.Empty<GUILayoutOption>());
}
foreach (FlowRow row in rows)
{
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
GUILayout.Label(row.Name, theme.Label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(260f) });
GUILayout.Label(row.Stored.ToString("N0"), theme.Label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(105f) });
GUILayout.Label(row.ProducedPerMinute.ToString("N1"), theme.Label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(105f) });
GUILayout.Label(row.ConsumedPerMinute.ToString("N1"), theme.Label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(105f) });
GUIStyle val = ((row.NetPerMinute < -0.01) ? theme.Negative : ((row.NetPerMinute > 0.01) ? theme.Positive : theme.Label));
GUILayout.Label(FormatSigned(row.NetPerMinute), val, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(105f) });
GUILayout.EndHorizontal();
}
}
GUILayout.EndScrollView();
}
private void DrawFlowVisual()
{
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
//IL_0170: Unknown result type (might be due to invalid IL or missing references)
GUILayout.Label("FLOW MAGNITUDE // TOP 12 ACTIVE MATERIALS", theme.Header, Array.Empty<GUILayoutOption>());
if (rows.Count == 0)
{
GUILayout.Label("VISUALIZATION STANDBY — NO FLOW SIGNAL", theme.Empty, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(100f) });
return;
}
double num = 1.0;
foreach (FlowRow row in rows)
{
num = Math.Max(num, Math.Max(row.ProducedPerMinute, row.ConsumedPerMinute));
}
int num2 = 0;
foreach (FlowRow row2 in rows)
{
if (num2++ >= 12)
{
break;
}
GUILayout.Label(row2.Name + " " + FormatSigned(row2.NetPerMinute) + "/min", theme.Label, Array.Empty<GUILayoutOption>());
Rect rect = GUILayoutUtility.GetRect(100f, 12f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
GUI.Box(rect, GUIContent.none, theme.BarBackground);
float num3 = (float)(Math.Max(row2.ProducedPerMinute, row2.ConsumedPerMinute) / num);
GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width * num3, ((Rect)(ref rect)).height), (Texture)(object)((row2.NetPerMinute < 0.0) ? theme.Red : theme.Cyan));
}
}
private void DrawInstrumentButtons(int first, int last)
{
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
float num = Mathf.Max(78f, (((Rect)(ref windowRect)).width - 38f) / 6f);
for (int i = first; i <= last; i++)
{
string text = ShortTitle(i);
GUIStyle val = ((activePanel == i) ? theme.NavActive : theme.Nav);
if (GUILayout.Button(text, val, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(num) }))
{
SelectPanel(i);
}
}
GUILayout.EndHorizontal();
}
private void SelectPanel(int panel)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
activePanel = panel;
scroll = Vector2.zero;
if (!seenPanels.Contains(panel))
{
seenPanels.Add(panel);
tutorialsSeen.Value = string.Join(",", seenPanels.OrderBy((int value) => value));
showHelp = true;
}
((BaseUnityPlugin)this).Logger.LogDebug((object)$"Selected F{panel} {OperationsDeck.Title(panel)}.");
}
private void ResetTutorials()
{
seenPanels.Clear();
tutorialsSeen.Value = string.Empty;
showHelp = true;
((BaseUnityPlugin)this).Logger.LogInfo((object)"Laplace first-use tutorials reset.");
}
private void ClampWindowToScreen()
{
float num = Mathf.Max(500f, (float)Screen.width - 24f);
float num2 = Mathf.Max(400f, (float)Screen.height - 24f);
((Rect)(ref windowRect)).width = Mathf.Min(900f, num);
((Rect)(ref windowRect)).height = Mathf.Min(680f, num2);
((Rect)(ref windowRect)).x = Mathf.Clamp(((Rect)(ref windowRect)).x, 0f, Mathf.Max(0f, (float)Screen.width - ((Rect)(ref windowRect)).width));
((Rect)(ref windowRect)).y = Mathf.Clamp(((Rect)(ref windowRect)).y, 0f, Mathf.Max(0f, (float)Screen.height - ((Rect)(ref windowRect)).height));
}
private static string ShortTitle(int panel)
{
return (new string[13]
{
"", "ORBITS", "ALIGN", "ROUTES", "LIGHT", "POWER", "FLOW", "VEINS", "HOME", "DYSON",
"FLEET", "FORECAST", "RISK"
})[panel];
}
private static string FormatSigned(double value)
{
if (!(value > 0.0))
{
return value.ToString("N1");
}
return $"+{value:N1}";
}
private string ModeName()
{
if (displayMode != 0)
{
if (displayMode != 1)
{
return "HYBRID";
}
return "VISUAL";
}
return "NUMERICAL";
}
}