Created
April 7, 2019 00:05
-
-
Save senevoldsen/f95913aea28090e294fdc7af3086e8ca to your computer and use it in GitHub Desktop.
Space Engineer - Full Haul Detection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*** | |
(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