Skip to content

Instantly share code, notes, and snippets.

@senevoldsen
Created April 7, 2019 00:05
Show Gist options
  • Save senevoldsen/f95913aea28090e294fdc7af3086e8ca to your computer and use it in GitHub Desktop.
Save senevoldsen/f95913aea28090e294fdc7af3086e8ca to your computer and use it in GitHub Desktop.
Space Engineer - Full Haul Detection
/***
(Mining) Capacity Exceeded Indicator.
When the percentage of used volume becomes too high for selected
cargo containers it will toggle indicators, for example a light.
======================================
Put the following texts in "Custom Data" to configure the
system.
1. To mark a Cargo Container as included in the calculation,
add to its custom data:
[miner-inventory-status]
Drills are automatically included.
2. To mark an indicator (e.g. a light), the indicator will
simply be turned on/off, put this in its data:
[miner-inventory-status]
indicator = true
3. You can change the treshold from the default 95% full by
adding a value to the programmable block. For example to
change the treshold to 60% do this:
[miner-inventory-status]
treshold = 60
4. If you simply want to use all cargo containers on the ship
you can just add to the programmable block:
containers = all
======================================
***/
// We need TerminalBlocks because Drills have internal storage.
const string INI_SECTION = "miner-inventory-status";
List<IMyTerminalBlock> _containers = new List<IMyTerminalBlock>();
List<IMyFunctionalBlock> _indicators = new List<IMyFunctionalBlock>();
MyIni _ini = new MyIni();
int _treshold = 95; // Percent
bool _useAllCargoContainers = false;
ChangeTrigger<bool> _indicatorsActive = new ChangeTrigger<bool>(false);
private bool IsMinerContainer(IMyTerminalBlock block)
{
if (block.InventoryCount == 0) return false;
if (block is IMyShipDrill) return true;
if (!(block is IMyCargoContainer)) return false;
// Don't include bases you are docked with for example.
if (!Me.IsSameConstructAs(block)) return false;
if (_useAllCargoContainers) return true;
// Check if explicitly enabled.
MyIniParseResult result;
if (!_ini.TryParse(block.CustomData, out result)) return false;
return _ini.ContainsSection(INI_SECTION);
}
// Assumes IMyTerminalBlock satisfies IsMinerContainer
private MyTuple<MyFixedPoint, MyFixedPoint> GetVolumeUsedAndTotal(IMyTerminalBlock block)
{
MyFixedPoint total = 0;
MyFixedPoint used = 0;
for (int i = 0; i < block.InventoryCount; ++i)
{
var inventory = block.GetInventory(i);
total += inventory.MaxVolume;
used += inventory.CurrentVolume;
}
return MyTuple.Create(used, total);
}
private float GetPercentUsage()
{
var summed = _containers.Select(GetVolumeUsedAndTotal).Aggregate((a, b) => MyTuple.Create(a.Item1 + b.Item1, a.Item2 + b.Item2));
return (float)summed.Item1 / (float)summed.Item2 * 100.0f;
}
private void UpdateContainerList()
{
GridTerminalSystem.GetBlocksOfType<IMyTerminalBlock>(_containers, IsMinerContainer);
}
private void UpdateIndicatorList()
{
GridTerminalSystem.GetBlocksOfType<IMyFunctionalBlock>(_indicators, b =>
{
if (_ini.TryParse(b.CustomData, INI_SECTION))
{
return _ini.Get(INI_SECTION, "indicator").ToBoolean(false);
}
return false;
});
}
private void Configure()
{
if (_ini.TryParse(Me.CustomData, INI_SECTION))
{
_treshold = _ini.Get(INI_SECTION, "treshold").ToInt32(95);
_useAllCargoContainers = _ini.Get(INI_SECTION, "containers").ToString().ToLower() == "all";
}
UpdateContainerList();
UpdateIndicatorList();
// Set initial indicator status.
_indicatorsActive = new ChangeTrigger<bool>(false, newEnabled =>
{
_indicators.ForEach(b => b.Enabled = newEnabled);
}, triggerNow: true);
}
public Program()
{
Configure();
Runtime.UpdateFrequency = UpdateFrequency.Update100;
}
//public void Save()
//{
//}
public void Main(string argument, UpdateType updateSource)
{
if (updateSource.HasFlag(UpdateType.Terminal))
{
Configure();
}
var usage = GetPercentUsage();
var aboveTreshold = Math.Round(usage) >= _treshold;
Echo(
$@"Found {_containers.Count} valid containers
Found {_indicators.Count} indicators
Treshold is set to {_treshold}%
Containers are at {usage:F1}% usage
");
_indicatorsActive.Value = aboveTreshold;
}
public class ChangeTrigger<T>
{
public ChangeTrigger(T initialValue, Action<T> onChange = null, bool triggerNow = false)
{
_value = initialValue;
this.OnChange = onChange;
if (triggerNow)
{
ForceTrigger();
}
}
void Reset(T newValue)
{
_value = newValue;
}
void Update(T currentValue)
{
this.Value = currentValue;
}
void ForceTrigger()
{
OnChange?.Invoke(_value);
}
public static implicit operator T(ChangeTrigger<T> ct)
{
return ct._value;
}
public Action<T> OnChange { get; set; }
public T Value
{
get
{
return _value;
}
set
{
bool change = !(_value.Equals(value));
_value = value;
if (change)
{
ForceTrigger();
}
}
}
private T _value;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment