Skip to content

Instantly share code, notes, and snippets.

@ChuckSavage
Created November 3, 2018 08:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ChuckSavage/e5e26a0b3764c679a100481bf74c97ad to your computer and use it in GitHub Desktop.
Save ChuckSavage/e5e26a0b3764c679a100481bf74c97ad to your computer and use it in GitHub Desktop.
Space Engineers Game - Battery Charge and Drill (miner) load level and balancer
// dco.pe/vsb
const float MinValueToActivateRedLights = 5000f;
const float VolumeOfDrills = 33750f; // small ship drill (large is 234375f)
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 IsOre { get { return (bool)(_IsOre ?? (_IsOre = _this.Content.TypeId.ToString().EndsWith("Ore"))); } }
bool? _IsOre;
public string ItemType { get { return _ItemType ?? (_ItemType = _this.Content.SubtypeId.ToString()); } }
string _ItemType;
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 List<VRage.Game.Entity.MyPhysicalInventoryItem> Items2() { return _this.GetItems(); }
public float MaxVolume { get { return ((float)_this.MaxVolume); } }
public IMyInventory This { get { return _this; } }
}
public class CargoContainers
{
private readonly IMyTerminalBlock _this;
public CargoContainers(IMyTerminalBlock cargoBlock)
{
_this = cargoBlock;
}
//IMyInventory inventoryB = (containerB as IMyInventoryOwner).GetInventory(0)
public Inventory Inventory { get { return _Inventory ?? (_Inventory = new Inventory((_this as IMyInventoryOwner).GetInventory(0))); } }
Inventory _Inventory;
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; } }
}
void Main(string argument)
{
// block declarations
string ERR_TXT = "";
List<IMyTerminalBlock> v0 = new List<IMyTerminalBlock>();
GridTerminalSystem.GetBlocksOfType<IMyBatteryBlock>(v0, filterThis);
if (v0.Count == 0)
{
ERR_TXT += "no Battery blocks found\n";
}
List<IMyTerminalBlock> v1 = new List<IMyTerminalBlock>();
GridTerminalSystem.GetBlocksOfType<IMyInteriorLight>(v1, filterThis);
if (v1.Count == 0)
{
ERR_TXT += "no Interior Light blocks found\n";
}
List<IMyTerminalBlock> v2 = new List<IMyTerminalBlock>();
GridTerminalSystem.GetBlocksOfType<IMyShipDrill>(v2, filterThis);
if (v2.Count == 0)
{
ERR_TXT += "no Drill blocks found\n";
}
// display errors
if (ERR_TXT != "")
{
Echo("Script Errors:\n" + ERR_TXT + "(make sure block ownership is set correctly)");
if (ERR_TXT.Contains("Drill"))
return;
}
if (v0.Count > 0)
{
// battery logic
bool result0v0 = true;
for (int i = 0; i < v0.Count; i++)
{
if (!(getExtraFieldFloat(v0[i], "Max Stored Power:.*Stored power: (\\d+\\.?\\d*) (\\w?)Wh") >= 1050000 && v0[i].GetValueBool("Recharge") == true))
{
//Echo("break power loop");
result0v0 = false;
break;
}
}
if (result0v0)
SetInteriorLightsColor(v1, 0, 255, 0); // set green
else
SetInteriorLightsColor(v1, 255, 255, 255); // set white
}
else
SetInteriorLightsColor(v1, 255, 255, 255); // set white
// Balance the drills inventories
//List<IMyTerminalBlock> blocks = new List<IMyTerminalBlock>();
//GridTerminalSystem.GetBlocksOfType<IMyCargoContainer>(blocks); // get all cargo container type blocks
List<CargoContainers> drills = v2.Select(block => new CargoContainers(block)).ToList();
//Echo("CargoContainers : " + cargos.Count.ToString());
//cargos.ForEach(cargo => Echo("Container : " + cargo.Name));
//var drills = cargos.Where(cargo => cargo.IsDrill).ToList();
//Echo("Drills : " + drills.Count.ToString());
//var d = drills.First();
//var firstItem = d.Inventory.GetItems().FirstOrDefault();
//Echo(firstItem.GetType().FullName);
// Balance the drills if there are more than one drill
if (drills.Count > 1)
{
drills = drills.OrderBy(drill => drill.Inventory.CurrentMass).ToList();
var maxDrill = drills.Last();
// balance if volume would trigger red lights if not balanced
if (maxDrill.Inventory.CurrentVolume >= MinValueToActivateRedLights)
{
var minDrill = drills.First(); // was already sorted getting the maxDrill
float diff = maxDrill.Inventory.CurrentMass - minDrill.Inventory.CurrentMass;
diff /= 2; // diff = diff / 2;
Echo("MaxDrill:" + maxDrill.Inventory.CurrentMass.ToString());
Echo("MinDrill:" + minDrill.Inventory.CurrentMass.ToString());
Echo("Half Diff:" + diff.ToString());
if (diff >= 1f)
{
float max = 0;
int maxIndex = 0;
var maxItems = maxDrill.Inventory.Items();
InventoryItem maxItem = null;
for (int i = 0; i < maxItems.Count; i++)
{
maxItem = maxItems[i];
if (maxItem.Amount > max)
{
max = maxItem.Amount;
maxIndex = i;
}
}
//Echo("MaxItemAmount:" + max.ToString());
//Echo("MaxItemIndex:" + maxIndex.ToString());
// amount = lesser of item.Amount and diff
var amount = (VRage.MyFixedPoint)Math.Min(diff, maxItem.Amount);
// parameters for this are: TransferItemTo(IMyInventory destination, int itemIndex, Nullable&lt;int> targetItemIndex, Nullable&lt;bool> tryToStack, Nullable&lt;MyFixedPoint> amount);
maxDrill.Inventory.This.TransferItemTo(minDrill.Inventory.This, maxIndex, null, true, amount);
}
}
//var firstItem = maxDrill.Inventory.This.GetItems().FirstOrDefault();
//Echo(firstItem?.Content.SubtypeId.ToString() ?? "No Items");
//Echo(firstItem.GetType().FullName);
}
//float maxDrillVolume = v2
// .Select(d => (IMyShipDrill)d)
// .Select(I => I.GetInventory(0))
// .Select(inv => ((float)inv.CurrentVolume) * 1000)
// .Max();
float maxDrillVolume = v2.Max(drill => (float)((IMyShipDrill)drill).GetInventory(0).CurrentVolume * 1000);
//Echo(fs(maxDrillVolume));
if (maxDrillVolume >= MinValueToActivateRedLights)
{
float percentInDrill = maxDrillVolume / VolumeOfDrills;
float sumDrillVolume = 255 * percentInDrill; // to get percent value of 255 not 100
//Echo("sumDrillVolume : "+ fs(sumDrillVolume));
float nonRed = sumDrillVolume % 255; // 0 to 255 color
nonRed = 255 - nonRed; // flip the value to be 255 to 0
//Echo(fs(nonRed));
SetInteriorLightsColor(v1, 255, (int)nonRed, (int)nonRed); // set steadily increasing red color
}
else
Echo("Drills empty");
// This used to sum the value in the drills.
// Not as effective, since drills don't share their volumes. One could fill up, and you'd
// then be wasting that ore it continued to mine.
//bool result2v2 = false;
//float drillVolume, sumDrillVolume;
//sumDrillVolume = 0;
// for (int i = 0; i < v2.Count; i++) {
//drillVolume = (float)((IMyShipDrill)v2[i]).GetInventory(0).CurrentVolume;
// // maxDrillVolume = Math.Max(maxDrillVolume, )
// drillVolume *= 1000;
////Echo("Drill "+v2[i].CustomName +" : "+ fs(drillVolume));
////drillVolume = 5001; // 1/6th full
////drillVolume = 11250; // 1/3rd full
////drillVolume = 16875; // 1/2 full
////drillVolume = 25312; // 3/4th full
//sumDrillVolume += drillVolume;
////Echo("sumDrillVolume : "+ fs(sumDrillVolume));
//if(!result2v2 && (drillVolume > 5000f))
// result2v2 = true;
// }
// if(result2v2) {
////Echo("Drills : "+ v2.Count.ToString());
////Echo("sumDrillVolume : "+ fs(sumDrillVolume));
//float totalVolume = 33750f * v2.Count;
////Echo("totalVolume : "+fs(totalVolume));
//sumDrillVolume /= totalVolume;
//sumDrillVolume *= 255; // to get percent value of 255 not 100
////Echo("sumDrillVolume : "+ fs(sumDrillVolume));
//float nonRed = sumDrillVolume % 255; // 0 to 255 color
//nonRed = 255 - nonRed; // flip the value to be 255 to 0
////Echo(fs(nonRed));
//for(int i = 0; i < v1.Count; i++) {
// v1[i].SetValueColor("Color", new Color(255, (int)nonRed, (int)nonRed));
//}
// }
// else
//Echo("Drills empty");
}
void SetInteriorLightsColor(List<IMyTerminalBlock> list, int red, int green, int blue)
{
list.ForEach(light => light.SetValueColor("Color", new Color(red, green, blue)));
}
string fs(float f)
{
int i = (int)f;
return i.ToString();
}
const string MULTIPLIERS = ".kMGTPEZY";
bool filterThis(IMyTerminalBlock block)
{
return block.CubeGrid == Me.CubeGrid;
}
float getExtraFieldFloat(IMyTerminalBlock block, string regexString)
{
System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(regexString, System.Text.RegularExpressions.RegexOptions.Singleline);
float result = 0.0f;
double parsedDouble;
System.Text.RegularExpressions.Match match = regex.Match(block.DetailedInfo);
if (match.Success)
{
if (Double.TryParse(match.Groups[1].Value, out parsedDouble))
{
result = (float)parsedDouble;
}
if (MULTIPLIERS.IndexOf(match.Groups[2].Value) > -1)
{
result = result * (float)Math.Pow(1000.0, MULTIPLIERS.IndexOf(match.Groups[2].Value));
}
}
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment