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.ObjectBuilders; using VRageMath; namespace IngameScript { partial class Program : MyGridProgram { const int NUMBER_OF_MISSILES = 52; // The quantity of components will be created to build this quantity of missiles. const int NUMBER_OF_CANNON_SHELL = 160; const int NUMBER_OF_ARTILLERY_SHELL = 40; const int CONSOLE_NB_LINES = 14; const string GRID_PREFIX = "[PML]"; const float EPSILON = 0.05f; readonly IMyCubeGrid grid; readonly Output output; readonly Output topPanel; readonly Output bottomPanel; readonly IMyAssembler assembler; readonly List missileComponents = new List{ new ComponentQuantity(MyItemType.MakeComponent("SteelPlate"), MyDefinitionId.Parse("MyObjectBuilder_BlueprintDefinition/SteelPlate"), 256), new ComponentQuantity(MyItemType.MakeComponent("Construction"), MyDefinitionId.Parse("MyObjectBuilder_BlueprintDefinition/ConstructionComponent"), 166), new ComponentQuantity(MyItemType.MakeComponent("Motor"), MyDefinitionId.Parse("MyObjectBuilder_BlueprintDefinition/MotorComponent"), 18), new ComponentQuantity(MyItemType.MakeComponent("InteriorPlate"), MyDefinitionId.Parse("MyObjectBuilder_BlueprintDefinition/InteriorPlate"), 40), new ComponentQuantity(MyItemType.MakeComponent("Computer"), MyDefinitionId.Parse("MyObjectBuilder_BlueprintDefinition/ComputerComponent"), 48), new ComponentQuantity(MyItemType.MakeComponent("PowerCell"), MyDefinitionId.Parse("MyObjectBuilder_BlueprintDefinition/PowerCell"), 2), new ComponentQuantity(MyItemType.MakeComponent("Display"), MyDefinitionId.Parse("MyObjectBuilder_BlueprintDefinition/Display"), 1), new ComponentQuantity(MyItemType.MakeComponent("SmallTube"), MyDefinitionId.Parse("MyObjectBuilder_BlueprintDefinition/SmallTube"), 29), new ComponentQuantity(MyItemType.MakeComponent("MetalGrid"), MyDefinitionId.Parse("MyObjectBuilder_BlueprintDefinition/MetalGrid"), 48), new ComponentQuantity(MyItemType.MakeComponent("LargeTube"), MyDefinitionId.Parse("MyObjectBuilder_BlueprintDefinition/LargeTube"), 16), new ComponentQuantity(MyItemType.MakeComponent("Detector"), MyDefinitionId.Parse("MyObjectBuilder_BlueprintDefinition/DetectorComponent"), 8), new ComponentQuantity(MyItemType.MakeComponent("Girder"), MyDefinitionId.Parse("MyObjectBuilder_BlueprintDefinition/GirderComponent"), 12), new ComponentQuantity(MyItemType.MakeComponent("Explosives"), MyDefinitionId.Parse("MyObjectBuilder_BlueprintDefinition/ExplosivesComponent"), 24), }; public Program() { this.grid = this.Me.CubeGrid; var output = this.Me.GetSurface(0); this.output = new Output(output, CONSOLE_NB_LINES); this.output.Print("PML system starting..."); this.topPanel = new Output(this.GridTerminalSystem.GetBlock("LCD Panel - Main 02", this.grid)); this.assembler = this.GridTerminalSystem.GetBlock("Assembler Main", this.grid); 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 "COMMAND": this.output.Print("BLA..."); break; case "START_MINING": default: this.output.Print($"Uknown command: {argument}"); break; } } } void UpdateState() { this.BuildComponentForMissiles(); this.BuildAmmo(); this.DisplayStatus(); } void BuildComponentForMissiles() { var existingAmounts = this.GetCurrentItemQuantity(missileComponents.Select(quantity => quantity.ItemType)); int i = 0; foreach (var missileComponent in this.missileComponents) { var existing = existingAmounts[i]; var queue = new List(); this.assembler.GetQueue(queue); foreach (var item in queue) { if (item.BlueprintId == missileComponent.blueprintId) existing += item.Amount; } var desired = missileComponent.Quantity * NUMBER_OF_MISSILES; if (existing < desired) { var toBuild = desired - existing; this.output.Print($"Requesting {toBuild} of {missileComponent.blueprintId.SubtypeName}"); this.assembler.AddQueueItem(missileComponent.blueprintId, toBuild); } i += 1; } } void BuildAmmo() { //var ammoDefinitionIds = new List //{ // MyDefinitionId.Parse("MyObjectBuilder_AmmoMagazine/Missile200mm"), // MyDefinitionId.Parse("MyObjectBuilder_AmmoMagazine/Missile400mm"), // MyDefinitionId.Parse("MyObjectBuilder_AmmoMagazine/Missile800mm"), // MyDefinitionId.Parse("MyObjectBuilder_AmmoMagazine/Missile1200mm"), // MyDefinitionId.Parse("MyObjectBuilder_AmmoMagazine/Projectile200mm"), // MyDefinitionId.Parse("MyObjectBuilder_AmmoMagazine/Projectile400mm"), // MyDefinitionId.Parse("MyObjectBuilder_AmmoMagazine/Projectile800mm"), // MyDefinitionId.Parse("MyObjectBuilder_AmmoMagazine/Projectile1200mm"), // MyDefinitionId.Parse("MyObjectBuilder_AmmoMagazine/ArtilleryShell"), //}; //var existingAmounts = this.GetCurrentItemQuantity(ammoDefinitionIds); //var desiredAmounts = new List //{ // (MyFixedPoint)(NUMBER_OF_MISSILES * 4), // Missile200mm // (MyFixedPoint)(NUMBER_OF_MISSILES * 4), // Missile400mm // (MyFixedPoint)(NUMBER_OF_MISSILES * 2), // Missile800mm // (MyFixedPoint)(NUMBER_OF_MISSILES * 2), // Missile1200mm // (MyFixedPoint)(NUMBER_OF_CANNON_SHELL / 4), // Projectile200mm // (MyFixedPoint)(NUMBER_OF_CANNON_SHELL / 4), // Projectile400mm // (MyFixedPoint)(NUMBER_OF_CANNON_SHELL / 4), // Projectile800mm // (MyFixedPoint)(NUMBER_OF_CANNON_SHELL / 4), // Projectile1200mm // (MyFixedPoint)(NUMBER_OF_ARTILLERY_SHELL), // ArtilleryShell //}; //foreach (var tuple in ammoDefinitionIds.Zip(existingAmounts, desiredAmounts, (id, existing, desired) => (id, existing, desired))) //{ // if (tuple.existing < tuple.desired - EPSILON) // { // var toBuild = tuple.desired - tuple.existing; // this.assembler.AddQueueItem(tuple.id, toBuild); // this.output.Print($"Requesting {toBuild} of {tuple.id.SubtypeName}"); // } //} } void DisplayStatus() { var cargoSpace = this.GetCargoSpace(); var energyState = this.GetEnergyState(); var hydrogenVolume = this.GetHydrogenVolume(); var oxygenVolume = this.GetOxygenVolume(); this.topPanel.Display( $@" {cargoSpace.ToString("Cargo volume", "kL")} {energyState.ToString("Energy", "MWh")} {hydrogenVolume.ToString("Hydrogen", "L")} {oxygenVolume.ToString("Oxygen", "L")}" ); } List GetCurrentItemQuantity(IEnumerable itemTypes) { var total = new List(new MyFixedPoint[itemTypes.Count()]); foreach (var container in this.GridTerminalSystem.GetBlocks(null, this.grid)) { //this.output.Print($"Container: {container.CustomName}"); int i = 0; foreach (var itemType in itemTypes) { var items = container.GetInventory().FindItem(itemType); //this.output.Print($"{itemType}: {items}"); if (items.HasValue) total[i] += items.Value.Amount; i += 1; } } foreach (var assembler in this.GridTerminalSystem.GetBlocks(null, this.grid)) { int i = 0; foreach (var itemType in itemTypes) { var items = assembler.OutputInventory.FindItem(itemType); if (items.HasValue) total[i] += items.Value.Amount; i += 1; } } foreach (var sorter in this.GridTerminalSystem.GetBlocks(null, this.grid)) { int i = 0; foreach (var itemType in itemTypes) { var items = sorter.GetInventory().FindItem(itemType); if (items.HasValue) total[i] += items.Value.Amount; i += 1; } } foreach (var welder in this.GridTerminalSystem.GetBlocks(null, this.grid)) { int i = 0; foreach (var itemType in itemTypes) { var items = welder.GetInventory().FindItem(itemType); if (items.HasValue) total[i] += items.Value.Amount; i += 1; } } foreach (var turret in this.GridTerminalSystem.GetBlocks(null, this.grid)) { int i = 0; foreach (var itemType in itemTypes) { var items = turret.GetInventory().FindItem(itemType); if (items.HasValue) total[i] += items.Value.Amount; i += 1; } } return total; } class ComponentQuantity { public ComponentQuantity(MyItemType itemType, MyDefinitionId blueprintId, MyFixedPoint quantity) { this.ItemType = itemType; this.blueprintId = blueprintId; //if (!MyDefinitionId.TryParse("MyObjectBuilder_BlueprintDefinition", this.ItemType.SubtypeId, out this.Id)) // throw new ArgumentException($"Cannot parse {this.ItemType} into a MyDefinitionId"); this.Quantity = quantity; } public readonly MyItemType ItemType; public readonly MyDefinitionId blueprintId; public readonly MyFixedPoint Quantity; } 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 firstLineLength = 50; var secondLineLength = 50; var firstLine = new StringBuilder(); firstLine.Append(name).Append(": "); var values = $"{this.Current:N1} {unit} / {this.Total:N1} {unit}"; firstLine.Append(values.PadLeft(firstLineLength - 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 = secondLineLength - 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(null, 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(null, 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(null, this.grid, tank => tank.CustomName.Contains("Hydrogen")); //var tanks = new List(); //GridTerminalSystem.GetBlocksOfType(tanks, // (IMyGasTank tank) => // { // return tank.CustomName.Contains("Mammouth") && tank.CustomName.Contains("hydro"); // } //); 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(null, this.grid, tank => tank.CustomName.Contains("Oxygen")); //var tanks = new List(); //GridTerminalSystem.GetBlocksOfType(tanks, // (IMyGasTank tank) => // { // return tank.CustomName.Contains("Mammouth") && tank.CustomName.Contains("oxygène"); // } //); foreach (var tank in tanks) { currentVolume += (double)tank.Capacity * (double)tank.FilledRatio; totalVolume += (double)tank.Capacity; } return new Quantity(currentVolume, totalVolume); } } }