using Sandbox.Game; using Sandbox.Game.EntityComponents; using Sandbox.ModAPI.Ingame; using Sandbox.ModAPI.Interfaces; using SpaceEngineers.Game.ModAPI.Ingame; using System; using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; using System.ComponentModel; using System.Linq; using System.Text; using VRage; using VRage.Collections; using VRage.Game; using VRage.Game.Components; using VRage.Game.GUI.TextPanel; using VRage.Game.ModAPI.Ingame; using VRage.Game.ModAPI.Ingame.Utilities; using VRage.Game.ObjectBuilders.Definitions; using VRage.Game.VisualScripting; using VRage.GameServices; using VRage.ObjectBuilders; using VRageMath; namespace IngameScript { partial class Program : MyGridProgram { enum State { IDLE, BUILD_COMPONENTS_MISSILES, } State currentState = State.IDLE; readonly IMyCubeGrid grid; readonly Output output; readonly Output leftPanel; readonly Output rightPanel; readonly List assemblers = new List(); // First one is the main assembler. readonly MissileManager missileManager; readonly AmmoManager ammoManager; public Program() { this.grid = this.Me.CubeGrid; var cockpitPilot = this.GridTerminalSystem.GetBlock("[Mimine] Control Seat Main"); var cockpitCopilot = this.GridTerminalSystem.GetBlock("[Mimine] Control Seat Copilot"); var output = this.Me.GetSurface(0); this.output = new Output(output, Constants.CONSOLE_NB_LINES); this.output.Print("Mimine system starting..."); this.leftPanel = new Output(new List { this.GridTerminalSystem.GetBlock("[Mimine] LCD Panel 01", this.grid), cockpitCopilot.GetSurface(1), cockpitPilot.GetSurface(1) }); this.rightPanel = new Output(new List { this.GridTerminalSystem.GetBlock("[Mimine] LCD Panel 02", this.grid), cockpitCopilot.GetSurface(0), cockpitPilot.GetSurface(0) }); foreach (var assembler in this.GridTerminalSystem.GetBlocks(grid: this.grid)) { if (assembler.BlockDefinition.SubtypeName == "LargeAssembler") { if (assembler.CooperativeMode) this.assemblers.Add(assembler); else this.assemblers.Insert(0, assembler); } else { // Not very useful to inform about ignored assemblers -> commented out. //this.output.Print($"Assembler Ignored, not a large assembler:"); //this.output.Print($" {assembler.CustomName}"); } } if (this.assemblers.Count == 0) this.output.PrintError("No assembler found"); else this.output.Print($"Main assembler: {this.assemblers[0].CustomName}"); this.missileManager = new MissileManager(this.GridTerminalSystem, this.grid, this.output, this.assemblers); this.ammoManager = new AmmoManager(this.GridTerminalSystem, this.grid, this.output, this.assemblers); Runtime.UpdateFrequency = UpdateFrequency.Update100; } public void Save() { } public void Main(string argument, UpdateType updateSource) { if ((updateSource & UpdateType.Update100) != 0) { this.UpdateState(); } else if ((updateSource & (UpdateType.Terminal | UpdateType.Trigger)) != 0) { switch (argument) { case "BUILD": this.currentState = State.BUILD_COMPONENTS_MISSILES; break; case "STOP": this.currentState = State.IDLE; break; default: this.output.Print($"Uknown command: {argument}"); break; } } } void UpdateState() { var ammoStatus = this.ammoManager.GetAmmoStatus(); if (this.currentState == State.BUILD_COMPONENTS_MISSILES) { this.missileManager.BuildComponentForMissiles(); this.ammoManager.BuildAmmo(ammoStatus); } this.DisplayStatus(); StringBuilder sb = new StringBuilder(); this.missileManager.DisplayIngotsStatus(sb); sb.AppendLine(new string('-', Constants.CONSOLE_LINE_LENGTH)); this.ammoManager.DisplayAmmoStatus(sb, ammoStatus); this.rightPanel.Display(sb.ToString()); } void DisplayStatus() { var cargoSpace = this.GetCargoSpace(); var energyState = this.GetEnergyState(); var hydrogenVolume = this.GetHydrogenVolume(); var oxygenVolume = this.GetOxygenVolume(); this.leftPanel.Display( $@" {cargoSpace.ToString("Cargo volume", "kL")} {energyState.ToString("Energy", "MWh")} {hydrogenVolume.ToString("Hydrogen", "L")} {oxygenVolume.ToString("Oxygen", "L")}" ); } struct Quantity { public Quantity(double current, double total) { this.Current = current; this.Total = total; } public readonly double Current; public readonly double Total; public string ToString(string name, string unit) { var firstLine = new StringBuilder(); firstLine.Append(name).Append(": "); var values = $"{this.Current:N1} {unit} / {this.Total:N1} {unit}"; firstLine.Append(values.PadLeft(Constants.CONSOLE_LINE_LENGTH - firstLine.Length)); var secondLine = new StringBuilder(); secondLine.Append("["); var ratio = this.Current / this.Total; var percentStr = $"{ratio * 100.0,8:N1}%"; // "-2" because of the starting and ending characters: '[', ']'. var gaugeSize = Constants.CONSOLE_LINE_LENGTH - percentStr.Length - 2; var n = (int)((double)gaugeSize * ratio); secondLine.Append(new string('|', n)); secondLine.Append(new string(' ', gaugeSize - n)).Append("]"); secondLine.Append(percentStr); return $"{firstLine}\n{secondLine}"; } } Quantity GetCargoSpace() { var containers = this.GridTerminalSystem.GetBlocks(grid: this.grid); double currentVolume = 0; double totalVolume = 0; foreach (var container in containers) { var inventory = container.GetInventory(); currentVolume += (double)inventory.CurrentVolume; totalVolume += (double)inventory.MaxVolume; } return new Quantity(currentVolume, totalVolume); } Quantity GetEnergyState() { double currentkWh = 0; double maxkWh = 0; var batteries = this.GridTerminalSystem.GetBlocks(grid: this.grid); foreach (var battery in batteries) { currentkWh += (double)battery.CurrentStoredPower; maxkWh += (double)battery.MaxStoredPower; } return new Quantity(currentkWh, maxkWh); } Quantity GetHydrogenVolume() { double currentVolume = 0; double totalVolume = 0; var tanks = this.GridTerminalSystem.GetBlocks(grid: this.grid, filter: tank => tank.CustomName.Contains("Hydrogen")); foreach (var tank in tanks) { currentVolume += (double)tank.Capacity * (double)tank.FilledRatio; totalVolume += (double)tank.Capacity; } return new Quantity(currentVolume, totalVolume); } Quantity GetOxygenVolume() { double currentVolume = 0; double totalVolume = 0; var tanks = this.GridTerminalSystem.GetBlocks(grid: this.grid, filter: tank => tank.CustomName.Contains("Oxygen")); foreach (var tank in tanks) { currentVolume += (double)tank.Capacity * (double)tank.FilledRatio; totalVolume += (double)tank.Capacity; } return new Quantity(currentVolume, totalVolume); } } }