Skip to content

Instantly share code, notes, and snippets.

@ChuckSavage
Created November 10, 2018 11:30
Show Gist options
  • Save ChuckSavage/fd5777417b802bf59a07a60688f84a94 to your computer and use it in GitHub Desktop.
Save ChuckSavage/fd5777417b802bf59a07a60688f84a94 to your computer and use it in GitHub Desktop.
Space Engineers - Stone Duster mod, script to control stone amounts
// Written by steam handle "Dune__" aka Chuck Savage
// - Gist link: https://gist.github.com/ChuckSavage/fd5777417b802bf59a07a60688f84a94
// Feel free to use and modify. It'd be great if you list any
// changes here on this gist page so I can keep this up to date if they are important changes.
// Todo: handle multiple stone dusters. I'm not sure how to go about finding the type "Stone Duster" that
// the mod has listed for itself.
// Some code borrowed from the Space Engineers Visual Script Builder - http://dco.pe/vsb/
// Set name of Stone Duster to this name, or change this name to your stone duster's name
const string StoneDusterName = "StoneDuster";
public Program()
{
Runtime.UpdateFrequency = UpdateFrequency.Update100;
}
public class InventoryItem
{
private readonly IMyInventoryItem _this;
public InventoryItem(IMyInventoryItem item)
{
_this = item;
}
public float Amount { get { return (float)_this.Amount; } }
public bool IsIngot { get { return (bool)(_IsIngot ?? (_IsIngot = TypeId.EndsWith("Ingot"))); } }
bool? _IsIngot;
public bool IsOre { get { return (bool)(_IsOre ?? (_IsOre = TypeId.EndsWith("Ore"))); } }
bool? _IsOre;
public string ItemType { get { return _ItemType ?? (_ItemType = _this.Content.SubtypeId.ToString()); } }
string _ItemType;
public string TypeId { get { return _TypeId ?? (_TypeId = _this.Content.TypeId.ToString()); } }
string _TypeId;
public IMyInventoryItem This { get { return _this; } }
}
public class Inventory
{
private readonly IMyInventory _this;
public Inventory(IMyInventory inventory)
{
_this = inventory;
}
public float CurrentMass { get { return (float)_this.CurrentMass; } }
/// <summary>
/// Multiplied by 1000 to get the value you see in game
/// </summary>
public float CurrentVolume { get { return ((float)_this.CurrentVolume) * 1000f; } }
public List<InventoryItem> Items() { return _this.GetItems().Select(item => new InventoryItem(item)).ToList(); }
public float MaxVolume { get { return ((float)_this.MaxVolume); } }
public IMyInventory This { get { return _this; } }
}
public class CargoContainer
{
private readonly IMyTerminalBlock _this;
public CargoContainer(IMyTerminalBlock cargoBlock)
{
_this = cargoBlock;
}
public Inventory Inventory { get { return _Inventory ?? (_Inventory = new Inventory((_this as IMyEntity).GetInventory(0))); } }
Inventory _Inventory;
//Refineries and Assemblers have In and Out inventories, have yet to figure out which is which and if they
//are different to each other (refineries to assemblers).
//public Inventory InventoryIN { get { return _InventoryIN ?? (_InventoryIN = new Inventory((_this as IMyEntity).GetInventory(0))); } }
//Inventory _InventoryIN;
//public Inventory InventoryOUT { get { return _InventoryOUT ?? (_InventoryOUT = new Inventory((_this as IMyEntity).GetInventory(1))); } }
//Inventory _InventoryOUT;
public bool IsDrill { get { return IsType<IMyShipDrill>(); } }
public bool IsType<T>() where T : IMyTerminalBlock
{
try
{
var t = (T)_this;
return true;
}
catch { return false; }
//return null != _this as T;
}
public string Name { get { return _this.CustomName; } }
public IMyTerminalBlock This { get { return _this; } }
/// <summary>
/// Is the block a cargo container?
/// </summary>
/// <param name="block"></param>
/// <returns></returns>
public static bool IsCargoContainer(IMyTerminalBlock block)
{
return (block as IMyEntity)?.HasInventory ?? false;
/* simplified version of
IMyEntity entity = block as IMyEntity;
if (null == entity)
return false;
return entity.HasInventory;
*/
}
}
void Main(string argument)
{
StringBuilder sb = new StringBuilder();
List<IMyTerminalBlock> blocks = new List<IMyTerminalBlock>();
GridTerminalSystem.GetBlocksOfType<IMyTerminalBlock>(blocks, filterThis);
List<CargoContainer> cargos = blocks
.Where(block => CargoContainer.IsCargoContainer(block))
.Select(block => new CargoContainer(block))
.ToList();
if (cargos.Count == 0)
sb.AppendLine("No Cargo Containers found.");
//List<MyRefinery> stoneDusters = new List<MyRefinery>();
//GridTerminalSystem.GetBlocksOfType<IMyRefinery>(stoneDusters, filterThis);
IMyRefinery stoneduster = (IMyRefinery)GridTerminalSystem.GetBlockWithName(StoneDusterName);
//Echo(stoneduster.GetType().ToString()); //Sandbox.Game.Entities.Cube.MyRefinery
//Echo(stoneduster.GetType().FullName); //Sandbox.Game.Entities.Cube.MyRefinery
if (null == stoneduster)
sb.AppendLine("No Stone Duster by name '" + StoneDusterName + "' found.");
string customData = stoneduster?.CustomData ?? "0"; // if stoneduster is null don't bomb here
int stoneLimit = 100000;
if (string.IsNullOrWhiteSpace(customData))
sb.AppendLine("No CustomData found for " + StoneDusterName + ", use a number.");
else if (!int.TryParse(customData, out stoneLimit))
sb.AppendLine("Invalid stone limit. Set " + StoneDusterName + "'s CustomData to a whole number only.");
if (stoneLimit < 0)
stoneLimit = 0;
if (sb.Length > 0)
{
Echo("Script Errors:\n" + sb.ToString() + "(make sure block ownership is set correctly)");
return;
}
Echo("Stone Limit: " + stoneLimit.ToString());
var stone = cargos.SelectMany(c => c.Inventory.Items())
.Where(item => item.ItemType == "Stone");
float oreAmount = stone.Where(item => item.IsOre)
.Sum(item => item.Amount);
float gravelAmount = stone.Where(item => item.IsIngot)
.Sum(item => item.Amount);
float totalStone = oreAmount + gravelAmount;
//List<InventoryItem> items = cargos.SelectMany(c => c.Inventory.Items()).ToList();
//items
// .Where(item => item.ItemType.ToLower().Contains("stone"))
// .ToList()
// .ForEach(item => Echo(item.TypeId + " : " + item.ItemType));
//List<InventoryItem> ores = cargos.SelectMany(c => c.Inventory.Items())
// .Where(item => item.IsOre)
// .ToList();
//Echo("Ore Count: " + ores.Count.ToString());
Echo("Stone: " + oreAmount.ToString());
Echo("Gravel: " + gravelAmount.ToString());
Echo("Total: " + totalStone.ToString());
// since duster doesn't differentiate between gravel and stone(ore), we use total
if (totalStone > stoneLimit)
stoneduster.ApplyAction("OnOff_On");
else
stoneduster.ApplyAction("OnOff_Off");
}
bool filterThis(IMyTerminalBlock block)
{
return block.CubeGrid == Me.CubeGrid;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment