// Updated by SKO to fix Keen Update issues.
// Version: v1.2 - 30.04.2025 12:30:00
// Fixed: display of grinding/welding items and counters.
static double UpdateInvervalAssemblerQueues = 0.1; //Update every x seconds (0=as fast as possible, 0.5=every 500ms, ..)
static double UpdateInvervalGrinding = 0.1; //Update every x seconds (0=as fast as possible, 0.5=every 500ms, ..)
///
/// Configure the groups with there block names and/or group names.
/// You can access screens from TextSurfaceProvider like Cockpits with there name followed by [screenindex] e.g. "Cockpit[0]"
///
static BuildAndRepairSystemQueuingGroup[] BuildAndRepairSystemQueuingGroups = {
new BuildAndRepairSystemQueuingGroup() {
BuildAndRepairSystemGroupName = "BuildAndRepairGroup1",
AssemblerGroupName = "AssemblerGroup1",
Displays = new [] {
new DisplayDefinition {
DisplayNames = new [] { "BuildAndRepairGroup1StatusPanel", "Cockpit[0]" },
DisplayKinds = new [] { DisplayKind.ShortStatus, DisplayKind.Status, DisplayKind.WeldTargets, DisplayKind.GrindTargets, DisplayKind.CollectTargets, DisplayKind.MissingItems, DisplayKind.BlockWeldPriority, DisplayKind.BlockGrindPriority },
DisplayMaxLines = 19,
DisplaySwitchTime = 4
}
}
}
};
/* Complex Example with multiple groups, displays, ..
static BuildAndRepairSystemQueuingGroup[] BuildAndRepairSystemQueuingGroups = {
new BuildAndRepairSystemQueuingGroup() {
Name = "Hangar BaR Group1",
BuildAndRepairSystemNames = new [] { "Hangar1BaRSystem1", "Hangar1BaRSystem2" },
AssemblerNames = new[] { "Hangar1Assembler1", "Hangar1Assembler2", "Hangar1Assembler3" },
Displays = new[] {
new DisplayDefinition {
DisplayNames = new [] { "BaRStatusPanel" },
DisplayKinds = new [] { DisplayKind.Status, DisplayKind.MissingItems, DisplayKind.WeldTargets, DisplayKind.GrindTargets, DisplayKind.CollectTargets },
DisplayMaxLines = 19,
DisplaySwitchTime = 4
}
}
},
new BuildAndRepairSystemQueuingGroup() {
Name = "Hangar BaR Group2",
BuildAndRepairSystemNames = new[] { "Hangar1BaRSystem1", "Hangar1BaRSystem2" },
AssemblerNames = new[] { "Hangar1Assembler1", "Hangar1Assembler2", "Hangar1Assembler3" },
Displays = new [] {
new DisplayDefinition {
DisplayNames = new [] { "Hangar1BaRSystemStatusPanel1", "Hangar1BaRSystemStatusPanel2" },
DisplayKinds = new [] { DisplayKind.Status },
DisplayMaxLines = 19,
DisplaySwitchTime = 0
},
new DisplayDefinition {
DisplayNames = new [] { "Hangar1BaRSystemStatusPanel3", "Hangar1BaRSystemStatusPanel4" },
DisplayKinds = new [] { DisplayKind.Status, DisplayKind.MissingItems, DisplayKind.WeldTargets, DisplayKind.GrindTargets, DisplayKind.CollectTargets },
DisplayMaxLines = 10,
DisplaySwitchTime = 4
}
}
},
new BuildAndRepairSystemQueuingGroup() {
Name = "Hangar BaR Group3",
BuildAndRepairSystemNames = new[] { "BuildAndRepair1.1", "BuildAndRepair1.2" },
AssemblerNames = new[] { "Assembler1.1", "Assembler1.2", "Assembler1.3" }
},
new BuildAndRepairSystemQueuingGroup() {
Name = "Hangar BaR Group4",
BuildAndRepairSystemGroupName = "BuildAndRepairGroup1",
AssemblerNames = new[] { "Assembler1.1", "Assembler1.2", "Assembler1.3" }
},
new BuildAndRepairSystemQueuingGroup() {
Name = "Hangar BaR Group5",
BuildAndRepairSystemGroupName = "BuildAndRepairGroup1",
AssemblerNames = new[] { "Assembler1.1", "Assembler1.2", "Assembler1.3" }
},
new BuildAndRepairSystemQueuingGroup() {
Name = "Hangar BaR Group6",
BuildAndRepairSystemGroupName = "BuildAndRepairGroup1",
AssemblerGroupName = "AssemblerGroup1"
}
};
*/
///
/// No user changeable settings behind this point
///
///
/// Kind of Display
///
public enum DisplayKind
{
ShortStatus,
Status,
WeldTargets,
GrindTargets,
CollectTargets,
MissingItems,
BlockWeldPriority,
BlockGrindPriority
}
static BuildAndRepairAutoQueuing _AutoQueuing;
public Program()
{
Runtime.UpdateFrequency = UpdateFrequency.Update100;
_AutoQueuing = new BuildAndRepairAutoQueuing(this);
}
void Main(string arg)
{
_AutoQueuing.Handle();
}
///
/// Group configuration.
/// Grouped Systems/Assembler could be defined either by list
/// their Names (BuildAndRepairSystemNames\AssemblerNames) and or by giving
/// a group name (BuildAndRepairSystemGroupName\AssemblerGroupName)
///
public class BuildAndRepairSystemQueuingGroup
{
public string Name { get; set; }
public string[] BuildAndRepairSystemNames { get; set; }
public string BuildAndRepairSystemGroupName { get; set; }
public string[] AssemblerNames { get; set; }
public string AssemblerGroupName { get; set; }
public DisplayDefinition[] Displays { get; set; }
}
///
/// Definition for muliple Displays
///
public class DisplayDefinition
{
///
/// List of Displaynames
///
public string[] DisplayNames { get; set; }
///
/// You can the Display pages you need from enum DisplayKind. THey will be switch every DisplaySwitchTime seconds
///
public DisplayKind[] DisplayKinds { get; set; } = new[] { DisplayKind.Status };
///
/// The maximum of lines that should be displayed in case of list items (Blocks to build, grind, missing, ..)
///
public int DisplayMaxLines { get; set; } = 19;
///
/// Autoswitch time [s]
///
public double DisplaySwitchTime { get; set; } = 5;
}
///
/// Build and repair system automatic queuing of missing components
///
public class BuildAndRepairAutoQueuing
{
private Program _Program;
private bool _IsInit;
private double _ElapsedTime;
private double _ReInit;
private double _NextUpdateAssemblerQueues;
private double _NextUpdateGrinding;
private BuildAndRepairSystemQueuingGroupData[] _GroupData;
public string InitializationResultMessage { get; private set; }
public BuildAndRepairAutoQueuing(Program program)
{
_Program = program;
_ElapsedTime = 0;
}
///
/// Autorepair
///
public void Handle()
{
_ElapsedTime += _Program.Runtime.TimeSinceLastRun.TotalSeconds;
if (!_IsInit)
{
Initialize();
_ReInit = _ElapsedTime + 120; //Refresh every 2 Minutes
_NextUpdateAssemblerQueues = _ElapsedTime - 1; //Next refesh now
_NextUpdateGrinding = _NextUpdateAssemblerQueues;
if (!string.IsNullOrWhiteSpace(InitializationResultMessage))
{
_Program.Echo(InitializationResultMessage);
}
}
if (_IsInit)
{
if (_ElapsedTime > _NextUpdateGrinding)
{
ScriptControlledGrinding();
_NextUpdateGrinding = _ElapsedTime + UpdateInvervalGrinding;
}
if (_ElapsedTime > _NextUpdateAssemblerQueues)
{
CheckAssemblerQueues();
_NextUpdateAssemblerQueues = _ElapsedTime + UpdateInvervalAssemblerQueues;
}
RefreshDisplays();
if (_ElapsedTime > _ReInit)
{
_IsInit = false; //Refresh
}
}
}
///
/// Initialize lists with blocks to manage
///
private void Initialize()
{
_IsInit = false;
InitializationResultMessage = string.Empty;
_GroupData = new BuildAndRepairSystemQueuingGroupData[BuildAndRepairSystemQueuingGroups.Length];
var idx = 0;
foreach (var queuingGroup in BuildAndRepairSystemQueuingGroups)
{
_GroupData[idx] = new BuildAndRepairSystemQueuingGroupData(queuingGroup.Displays.Length);
_GroupData[idx].Settings = queuingGroup;
_GroupData[idx].RepairSystems = InitHandler(queuingGroup);
_GroupData[idx].Assemblers = InitAssemblerList(queuingGroup);
_GroupData[idx].StatusDisplays = new List();
foreach (var displayDef in queuingGroup.Displays)
{
var statusDisplay = new StatusAndLogDisplay(_Program, string.IsNullOrEmpty(queuingGroup.Name) ? "BaR Group " + idx : queuingGroup.Name, displayDef.DisplayNames, null);
_GroupData[idx].StatusDisplays.Add(statusDisplay);
statusDisplay.Clear();
statusDisplay.UpdateDisplay();
}
idx++;
}
_IsInit = true;
return;
}
///
/// Init the group/list of items handler
///
public T InitHandler(BuildAndRepairSystemQueuingGroup queuingGroup) where T : EntityHandler, new()
{
T handler = null;
if (!string.IsNullOrWhiteSpace(queuingGroup.BuildAndRepairSystemGroupName))
{
var group = _Program.GridTerminalSystem.GetBlockGroupWithName(queuingGroup.BuildAndRepairSystemGroupName);
if (group != null)
{
handler = new T();
handler.Init(group);
}
}
if (queuingGroup.BuildAndRepairSystemNames != null)
{
foreach (var name in queuingGroup.BuildAndRepairSystemNames)
{
if (!string.IsNullOrWhiteSpace(name))
{
var entity = _Program.GridTerminalSystem.GetBlockWithName(name);
if (entity != null)
{
if (handler == null) handler = new T();
handler.Init(entity);
}
}
}
}
if (handler == null || handler.Count == 0)
{
InitializationResultMessage += string.Format("\nFatalError: Group Repairsystems group empty/wrong types!");
handler = null;
}
return handler;
}
///
/// Build list of assemblers
///
///
public List InitAssemblerList(BuildAndRepairSystemQueuingGroup queuingGroup)
{
List assemblers = null;
if (!string.IsNullOrWhiteSpace(queuingGroup.AssemblerGroupName))
{
var group = _Program.GridTerminalSystem.GetBlockGroupWithName(queuingGroup.AssemblerGroupName);
if (group != null)
{
assemblers = new List();
var entities = new List();
group.GetBlocksOfType(entities);
foreach (var entity in entities)
{
assemblers.Add(entity.EntityId);
}
}
}
if (queuingGroup.AssemblerNames != null)
{
foreach (var name in queuingGroup.AssemblerNames)
{
if (!string.IsNullOrWhiteSpace(name))
{
var entity = _Program.GridTerminalSystem.GetBlockWithName(name);
if (entity != null && entity is IMyAssembler)
{
if (assemblers == null) assemblers = new List();
assemblers.Add(entity.EntityId);
}
}
}
}
if (assemblers == null || assemblers.Count == 0)
{
InitializationResultMessage += string.Format("Warning: Group Assemblers group empty/wrong types!");
assemblers = null;
}
return assemblers;
}
private void RefreshDisplays()
{
foreach (var groupData in _GroupData)
{
groupData.RefreshDisplay(_ElapsedTime);
}
}
///
/// This the basic algorithm and spread the items over the list of assemblers.
///
private void CheckAssemblerQueues()
{
foreach (var groupData in _GroupData)
{
groupData.CheckAssemblerQueues();
}
}
///
/// Place your code here to handle specialized Grind handling
///
private void ScriptControlledGrinding()
{
//Simple example of Script controlled grind handling
//foreach (var groupData in _GroupData)
//{
// groupData.RepairSystems.ScriptControlled = true;
// var listGrindable = groupData.RepairSystems.PossibleGrindTargets();
// //If nothing to grind or current grinding object no longer in list (allready grinded)
// if (groupData.RepairSystems.CurrentPickedGrindTarget == null || listGrindable.IndexOf(groupData.RepairSystems.CurrentPickedGrindTarget) < 0)
// {
// foreach (var entry in listGrindable)
// {
// var antenna = entry.FatBlock as IMyRadioAntenna;
// if (antenna != null)
// {
// groupData.RepairSystems.CurrentPickedGrindTarget = entry;
// break;
// }
// var reactor = entry.FatBlock as IMyReactor;
// if (reactor != null)
// {
// groupData.RepairSystems.CurrentPickedGrindTarget = entry;
// break;
// }
// var guns = entry.FatBlock as IMyUserControllableGun;
// if (guns != null)
// {
// groupData.RepairSystems.CurrentPickedGrindTarget = entry;
// break;
// }
// }
// }
//}
}
}
///
///
///
public class BuildAndRepairSystemQueuingGroupData
{
public BuildAndRepairSystemQueuingGroup Settings { get; set; }
public RepairSystemHandler RepairSystems { get; set; }
public List Assemblers { get; set; }
public List StatusDisplays { get; set; }
private int[] DisplayKindIdx { get; set; }
private double[] NextSwitchTime { get; set; }
public BuildAndRepairSystemQueuingGroupData(int count)
{
DisplayKindIdx = new int[count];
NextSwitchTime = new double[count];
}
///
///
///
public void CheckAssemblerQueues()
{
if (RepairSystems != null && Assemblers != null)
{
var missingItems = RepairSystems.MissingComponents();
foreach (var item in missingItems)
{
//Test ->
//var blueprintDefinition = TryGetBlueprintDefinitionByResultId(materialId);
//if (blueprintDefinition == null) return 0;
//<- end test
RepairSystems.EnsureQueued(Assemblers, item.Key, item.Value);
}
}
}
///
/// Refresh the status display
///
public void RefreshDisplay(double elapsedTime)
{
for (var idx = 0; idx < StatusDisplays.Count; idx++)
{
var display = StatusDisplays[idx];
var settings = Settings.Displays[idx];
if (display != null && settings != null)
{
display.Clear();
if (settings.DisplayKinds != null && RepairSystems != null)
{
if (elapsedTime >= NextSwitchTime[idx])
{
DisplayKindIdx[idx] = (DisplayKindIdx[idx] + 1) % settings.DisplayKinds.Length;
NextSwitchTime[idx] = elapsedTime + settings.DisplaySwitchTime;
}
switch (settings.DisplayKinds[DisplayKindIdx[idx]])
{
case DisplayKind.Status:
DisplayStatus(settings, display);
break;
case DisplayKind.ShortStatus:
DisplayShortStatus(settings, display);
break;
case DisplayKind.WeldTargets:
DisplayWeldTargets(settings, display);
break;
case DisplayKind.GrindTargets:
DisplayGrindTargets(settings, display);
break;
case DisplayKind.CollectTargets:
DisplayCollectTargets(settings, display);
break;
case DisplayKind.MissingItems:
DisplayMissingItems(settings, display);
break;
case DisplayKind.BlockWeldPriority:
DisplayBlockWeldPriorityList(settings, display);
break;
case DisplayKind.BlockGrindPriority:
DisplayBlockGrindPriorityList(settings, display);
break;
}
display.UpdateDisplay();
}
}
}
}
///
/// Show the short status of the BaR-System
///
private void DisplayShortStatus(DisplayDefinition settings, StatusAndLogDisplay display)
{
display.AddStatus(string.Format("Online : {0}", RepairSystems.CountOfWorking > 0));
display.AddStatus(string.Format("CurrentWelding : {0}", StatusAndLogDisplay.BlockName(RepairSystems.CurrentTarget)));
var listB = RepairSystems.PossibleTargets();
display.AddStatus(string.Format("Blocks to weld : {0}", listB != null ? listB.Count : 0));
display.AddStatus(string.Format("CurrentGrinding : {0}", StatusAndLogDisplay.BlockName(RepairSystems.CurrentGrindTarget)));
listB = RepairSystems.PossibleGrindTargets();
display.AddStatus(string.Format("Blocks to grind : {0}", listB != null ? listB.Count : 0));
var listF = RepairSystems.PossibleCollectTargets();
display.AddStatus(string.Format("Floating items : {0}", listF != null ? listF.Count : 0));
display.AddStatus(string.Format("Missing item kinds: {0}", StatusAndLogDisplay.BlockName(RepairSystems.MissingComponents().Count)));
}
///
/// Show the detailed status of the BaR-System
///
private void DisplayStatus(DisplayDefinition settings, StatusAndLogDisplay display)
{
DisplayShortStatus(settings, display);
display.AddStatus(string.Format("Search mode : {0}", StatusAndLogDisplay.BlockName(RepairSystems.SearchMode)));
display.AddStatus(string.Format("Work mode : {0}", StatusAndLogDisplay.BlockName(RepairSystems.WorkMode)));
display.AddStatus(string.Format("Build projected : {0}", StatusAndLogDisplay.BlockName(RepairSystems.AllowBuild)));
display.AddStatus(string.Format("UseIgnoreColor : {0}", StatusAndLogDisplay.BlockName(RepairSystems.UseIgnoreColor)));
display.AddStatus(string.Format("Script Controlled : {0}", RepairSystems.ScriptControlled));
}
///
/// Show the List of blocks to weld
///
private void DisplayWeldTargets(DisplayDefinition settings, StatusAndLogDisplay display)
{
var list = RepairSystems.PossibleTargets();
display.AddStatus(string.Format("Weld Targets: Count {0}", list != null ? list.Count : 0));
if (list == null) return;
var iI = 2;
foreach (var entry in list)
{
if (iI >= settings.DisplayMaxLines)
{
display.AddStatus(" ..");
break;
}
display.AddStatus(string.Format(" {0}", StatusAndLogDisplay.BlockName(entry)));
iI++;
}
}
///
/// Show the List of blocks to grind
///
private void DisplayGrindTargets(DisplayDefinition settings, StatusAndLogDisplay display)
{
var list = RepairSystems.PossibleGrindTargets();
display.AddStatus(string.Format("Grind Targets: Count {0}", list != null ? list.Count : 0));
if (list == null) return;
var iI = 2;
foreach (var entry in list)
{
if (iI >= settings.DisplayMaxLines)
{
display.AddStatus(" ..");
break;
}
display.AddStatus(string.Format(" {0}", StatusAndLogDisplay.BlockName(entry)));
iI++;
}
}
///
/// Show the List of collectable floating objects
///
private void DisplayCollectTargets(DisplayDefinition settings, StatusAndLogDisplay display)
{
var list = RepairSystems.PossibleCollectTargets();
display.AddStatus(string.Format("Collect Targets: Count {0}", list != null ? list.Count : 0));
if (list == null) return;
var iI = 2;
foreach (var entry in list)
{
if (iI >= settings.DisplayMaxLines)
{
display.AddStatus(" ..");
break;
}
display.AddStatus(string.Format(" {0}", StatusAndLogDisplay.BlockName(entry)));
iI++;
}
}
///
/// Show the List of missing materials
///
private void DisplayMissingItems(DisplayDefinition settings, StatusAndLogDisplay display)
{
var list = RepairSystems.MissingComponents();
display.AddStatus(string.Format("Missing Items: Count {0}", list != null ? list.Count : 0));
if (list == null) return;
var iI = 2;
foreach (var entry in list)
{
if (iI >= settings.DisplayMaxLines)
{
display.AddStatus(" ..");
break;
}
display.AddStatus(string.Format(" {0}: Amount={1}", entry.Key.SubtypeName, entry.Value));
iI++;
}
}
///
/// Show the List of block classes and there enabled state
///
private void DisplayBlockWeldPriorityList(DisplayDefinition settings, StatusAndLogDisplay display)
{
display.AddStatus("Weld Priority:");
var list = RepairSystems.WeldPriorityList();
foreach (var entry in list)
{
display.AddStatus(string.Format(" {0}/{1}", entry.ItemClass, entry.Enabled));
}
}
///
/// Show the List of block classes and there enabled state
///
private void DisplayBlockGrindPriorityList(DisplayDefinition settings, StatusAndLogDisplay display)
{
display.AddStatus("Grind Priority:");
var list = RepairSystems.GrindPriorityList();
foreach (var entry in list)
{
display.AddStatus(string.Format(" {0}/{1}", entry.ItemClass, entry.Enabled));
}
}
///
/// Show the List of component classes and there enabled state
///
private void DisplayComponentClassesList(DisplayDefinition settings, StatusAndLogDisplay display)
{
display.AddStatus("ComponentClassList:");
var list = RepairSystems.ComponentClassList();
foreach (var entry in list)
{
display.AddStatus(string.Format(" {0}/{1}", entry.ItemClass, entry.Enabled));
}
}
}
///
/// Class to handle the RepairSystems
///
public class RepairSystemHandler : EntityHandler
{
private Func, VRage.Game.MyDefinitionId, int, int> _EnsureQueued;
private Func, int> _NeededComponents4Blueprint;
///
/// The block clases the system distinguish
///
public enum BlockClass
{
AutoRepairSystem = 1,
ShipController,
Thruster,
Gyroscope,
CargoContainer,
Conveyor,
ControllableGun,
PowerBlock,
ProgrammableBlock,
Projector,
FunctionalBlock,
ProductionBlock,
Door,
ArmorBlock
}
///
/// The componet classes the system distinguish
///
public enum ComponentClass
{
Material = 1,
Ingot,
Ore,
Stone,
Gravel
}
///
/// The search modes supported by the block
///
public enum SearchModes
{
Grids = 0x0001,
BoundingBox = 0x0002
}
///
/// The work modes supported by the block
///
public enum WorkModes
{
///
/// Grind only if nothing to weld
///
WeldBeforeGrind = 0x0001,
///
/// Weld onyl if nothing to grind
///
GrindBeforeWeld = 0x0002,
///
/// Grind only if nothing to weld or
/// build waiting for missing items
///
GrindIfWeldGetStuck = 0x0004,
///
/// Only welding is allowed
///
WeldOnly = 0x0008,
///
/// Only grinding is allowed
///
GrindOnly = 0x0010
}
///
/// Block/Component class and it's state
///
public class ClassState where T : struct
{
public T ItemClass { get; }
public bool Enabled { get; }
public ClassState(T itemClass, bool enabled)
{
ItemClass = itemClass;
Enabled = enabled;
}
}
///
/// Set the Help Others state
///
public bool HelpOther
{
get
{
return _Entities.Count > 0 ? _Entities[0].HelpOthers : false;
}
set
{
foreach (var entity in _Entities) entity.HelpOthers = value;
}
}
///
/// Set AllowBuild (projected blocks)
///
public bool AllowBuild
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValueBool("BuildAndRepair.AllowBuild") : false;
}
set
{
foreach (var entity in _Entities) entity.SetValueBool("BuildAndRepair.AllowBuild", value);
}
}
///
/// Set the search mode of the block
///
public SearchModes SearchMode
{
get
{
return _Entities.Count > 0 ? (SearchModes)_Entities[0].GetValue("BuildAndRepair.Mode") : SearchModes.Grids;
}
set
{
foreach (var entity in _Entities) entity.SetValue("BuildAndRepair.Mode", (long)value);
}
}
///
/// Set the search mode of the block
///
public WorkModes WorkMode
{
get
{
return _Entities.Count > 0 ? (WorkModes)_Entities[0].GetValue("BuildAndRepair.WorkMode") : WorkModes.WeldBeforeGrind;
}
set
{
foreach (var entity in _Entities) entity.SetValue("BuildAndRepair.WorkMode", (long)value);
}
}
///
/// Enable/Disable the use of the Ignore Color
/// If enabled block's with with color 'IgnoreColor'
/// will be ignored.
/// You could use this do have intentionally unweldet block's
/// and still use autorepair of the rest.
///
public bool UseIgnoreColor
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValueBool("BuildAndRepair.UseIgnoreColor") : false;
}
set
{
foreach (var entity in _Entities) entity.SetValueBool("BuildAndRepair.UseIgnoreColor", value);
}
}
///
/// Set the ignore color
/// X=Hue 0 .. 1 -> * 360 -> Displayed value
/// Y=Saturation -1 .. 1 -> * 100 -> Displayed value
/// Z=Value -1 .. 1 -> * 100 -> Displayed value
///
public Vector3 IgnoreColor
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValue("BuildAndRepair.IgnoreColor") : Vector3.Zero;
}
set
{
foreach (var entity in _Entities) entity.SetValue("BuildAndRepair.IgnoreColor", value);
}
}
///
/// Enable/Disable the use of the Grind Color
/// If enabled block's with with color 'GrindColor'
/// will be grinded.
///
public bool UseGrindColor
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValueBool("BuildAndRepair.UseGrindColor") : false;
}
set
{
foreach (var entity in _Entities) entity.SetValueBool("BuildAndRepair.UseGrindColor", value);
}
}
///
/// Set the grind color
/// X=Hue 0 .. 1 -> * 360 -> Displayed value
/// Y=Saturation -1 .. 1 -> * 100 -> Displayed value
/// Z=Value -1 .. 1 -> * 100 -> Displayed value
///
public Vector3 GrindColor
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValue("BuildAndRepair.GrindColor") : Vector3.Zero;
}
set
{
foreach (var entity in _Entities) entity.SetValue("BuildAndRepair.GrindColor", value);
}
}
///
/// If set autogrind enemy blocks in range
///
public bool GrindJanitorEnemies
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValueBool("BuildAndRepair.GrindJanitorEnemies") : false;
}
set
{
foreach (var entity in _Entities) entity.SetValueBool("BuildAndRepair.GrindJanitorEnemies", value);
}
}
///
/// If set autogrind not owned blocks in range
///
public bool GrindJanitorNotOwned
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValueBool("BuildAndRepair.GrindJanitorNotOwned") : false;
}
set
{
foreach (var entity in _Entities) entity.SetValueBool("BuildAndRepair.GrindJanitorNotOwned", value);
}
}
///
/// If set autogrind blocks owned by neutrals in range
///
public bool GrindJanitorNeutrals
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValueBool("BuildAndRepair.GrindJanitorNeutrals") : false;
}
set
{
foreach (var entity in _Entities) entity.SetValueBool("BuildAndRepair.GrindJanitorNeutrals", value);
}
}
///
/// If set autogrind grinds blocks only down to the 'Out of order' level
///
public bool GrindJanitorOptionDisableOnly
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValueBool("BuildAndRepair.GrindJanitorOptionDisableOnly") : false;
}
set
{
foreach (var entity in _Entities) entity.SetValueBool("BuildAndRepair.GrindJanitorOptionDisableOnly", value);
}
}
///
/// If set autogrind grinds blocks only down to the 'Hack' level
///
public bool GrindJanitorOptionHackOnly
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValueBool("BuildAndRepair.GrindJanitorOptionHackOnly") : false;
}
set
{
foreach (var entity in _Entities) entity.SetValueBool("BuildAndRepair.GrindJanitorOptionHackOnly", value);
}
}
///
/// If set block are only weldet to functional level
///
public bool WeldOptionFunctionalOnly
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValueBool("BuildAndRepair.WeldOptionFunctionalOnly") : false;
}
set
{
foreach (var entity in _Entities) entity.SetValueBool("BuildAndRepair.WeldOptionFunctionalOnly", value);
}
}
///
/// Set the with of the working area
///
public float AreaWidth
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValueFloat("BuildAndRepair.AreaWidth") : 0;
}
set
{
foreach (var entity in _Entities) entity.SetValueFloat("BuildAndRepair.AreaWidth", value);
}
}
///
/// Set the left/right offset of the working area from block center
///
public float AreaOffsetLeftRight
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValueFloat("BuildAndRepair.AreaOffsetLeftRight") : 0;
}
set
{
foreach (var entity in _Entities) entity.SetValueFloat("BuildAndRepair.AreaOffsetLeftRight", value);
}
}
///
/// Set the height of the working area
///
public float AreaHeight
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValueFloat("BuildAndRepair.AreaHeight") : 0;
}
set
{
foreach (var entity in _Entities) entity.SetValueFloat("BuildAndRepair.AreaHeight", value);
}
}
///
/// Set the up/down offset of the working area from block center
///
public float AreaOffsetUpDown
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValueFloat("BuildAndRepair.AreaOffsetUpDown") : 0;
}
set
{
foreach (var entity in _Entities) entity.SetValueFloat("BuildAndRepair.AreaOffsetUpDown", value);
}
}
///
/// Set the depth of the working area
///
public float AreaDepth
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValueFloat("BuildAndRepair.AreaDepth") : 0;
}
set
{
foreach (var entity in _Entities) entity.SetValueFloat("BuildAndRepair.AreaDepth", value);
}
}
///
/// Set the depth of the working area
///
public float AreaOffsetFrontBack
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValueFloat("BuildAndRepair.AreaOffsetFrontBack") : 0;
}
set
{
foreach (var entity in _Entities) entity.SetValueFloat("BuildAndRepair.AreaOffsetFrontBack", value);
}
}
///
/// Get a list with all known block classes and there
/// weld enabled state in descending order of priority.
///
public List> WeldPriorityList()
{
if (_Entities.Count > 0)
{
var list = _Entities[0].GetValue>("BuildAndRepair.WeldPriorityList");
var blockList = new List>();
foreach (var item in list)
{
var values = item.Split(';');
BlockClass blockClass;
bool enabled;
if (Enum.TryParse(values[0], out blockClass) &&
bool.TryParse(values[1], out enabled))
{
blockList.Add(new ClassState(blockClass, enabled));
}
}
return blockList;
}
return null;
}
///
/// Get the weld priority of the given block class
///
public int GetWeldPriority(BlockClass blockClass)
{
if (_Entities.Count > 0)
{
var getPriority = _Entities[0].GetValue>("BuildAndRepair.GetWeldPriority");
return getPriority((int)blockClass);
}
else return int.MaxValue;
}
///
/// Set the weld priority of the given block class
/// (lower number higher priority)
///
public void SetWeldPriority(BlockClass blockClass, int prio)
{
foreach (var entity in _Entities)
{
var setPriority = entity.GetValue>("BuildAndRepair.SetWeldPriority");
setPriority((int)blockClass, prio);
}
}
///
/// Get the weld enabled state of the given block class
/// Enabled=True Block of that class will be repaired/build
/// Enabled=False Block's of that class will be ignored
///
public bool GetWeldEnabled(BlockClass blockClass)
{
if (_Entities.Count > 0)
{
var getEnabled = _Entities[0].GetValue>("BuildAndRepair.GetWeldEnabled");
return getEnabled((int)blockClass);
}
else return false;
}
///
/// Set the weld enabled state of the given block class
/// (see GetEnabled)
///
public void SetWeldEnabled(BlockClass blockClass, bool enabled)
{
foreach (var entity in _Entities)
{
var setEnabled = entity.GetValue>("BuildAndRepair.SetWeldEnabled");
setEnabled((int)blockClass, enabled);
}
}
///
/// Get a list with all known block classes and there
/// grind enabled state in descending order of priority.
///
public List> GrindPriorityList()
{
if (_Entities.Count > 0)
{
var list = _Entities[0].GetValue>("BuildAndRepair.GrindPriorityList");
var blockList = new List>();
foreach (var item in list)
{
var values = item.Split(';');
BlockClass blockClass;
bool enabled;
if (Enum.TryParse(values[0], out blockClass) &&
bool.TryParse(values[1], out enabled))
{
blockList.Add(new ClassState(blockClass, enabled));
}
}
return blockList;
}
return null;
}
///
/// Get the grind priority of the given block class
///
public int GetGrindPriority(BlockClass blockClass)
{
if (_Entities.Count > 0)
{
var getPriority = _Entities[0].GetValue>("BuildAndRepair.GetGrindPriority");
return getPriority((int)blockClass);
}
else return int.MaxValue;
}
///
/// Set the grind priority of the given block class
/// (lower number higher priority)
///
public void SetGrindPriority(BlockClass blockClass, int prio)
{
foreach (var entity in _Entities)
{
var setPriority = entity.GetValue>("BuildAndRepair.SetGrindPriority");
setPriority((int)blockClass, prio);
}
}
///
/// Get the grind enabled state of the given block class
/// Enabled=True Block of that class will be grinded
/// Enabled=False Block's of that class will be ignored
///
public bool GetGrindEnabled(BlockClass blockClass)
{
if (_Entities.Count > 0)
{
var getEnabled = _Entities[0].GetValue>("BuildAndRepair.GetGrindEnabled");
return getEnabled((int)blockClass);
}
else return false;
}
///
/// Set the grind enabled state of the given block class
/// (see GetEnabled)
///
public void SetGrindEnabled(BlockClass blockClass, bool enabled)
{
foreach (var entity in _Entities)
{
var setEnabled = entity.GetValue>("BuildAndRepair.SetGrindEnabled");
setEnabled((int)blockClass, enabled);
}
}
///
/// Get a list with all known component classes and there
/// enabeld state in descending order of priority.
///
public List> ComponentClassList()
{
if (_Entities.Count > 0)
{
var list = _Entities[0].GetValue>("BuildAndRepair.ComponentClassList");
var compList = new List>();
foreach (var item in list)
{
var values = item.Split(';');
ComponentClass compClass;
bool enabled;
if (Enum.TryParse(values[0], out compClass) &&
bool.TryParse(values[1], out enabled))
{
compList.Add(new ClassState(compClass, enabled));
}
}
return compList;
}
return null;
}
///
/// Get the priority of the given component class
///
public int GetCollectPriority(ComponentClass compClass)
{
if (_Entities.Count > 0)
{
var getPriority = _Entities[0].GetValue>("BuildAndRepair.GetCollectPriority");
return getPriority((int)compClass);
}
else return int.MaxValue;
}
///
/// Set the priority of the given component class
/// (lower number higher priority)
///
public void SetCollectPriority(ComponentClass compClass, int prio)
{
foreach (var entity in _Entities)
{
var setPriority = entity.GetValue>("BuildAndRepair.SetCollectPriority");
setPriority((int)compClass, prio);
}
}
///
/// Get the enabled state of the given component class
/// Enabled=True Component of that class will be collected
/// Enabled=False Component's of that class will be ignored
///
public bool GetCollectEnabled(ComponentClass compClass)
{
if (_Entities.Count > 0)
{
var getEnabled = _Entities[0].GetValue>("BuildAndRepair.GetCollectEnabled");
return getEnabled((int)compClass);
}
else return false;
}
///
/// Set the enabled state of the given component class
/// (see GetEnabled)
///
public void SetCollectEnabled(ComponentClass compClass, bool enabled)
{
foreach (var entity in _Entities)
{
var setEnabled = entity.GetValue>("BuildAndRepair.SetCollectEnabled");
setEnabled((int)compClass, enabled);
}
}
///
/// Set if the Block should only collect floating items (ore/ingot/material)
/// if nothing else to do (no welding, no grinding, no material for welding)
///
public bool CollectIfIdle
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValueBool("BuildAndRepair.CollectIfIdle") : false;
}
set
{
foreach (var entity in _Entities) entity.SetValueBool("BuildAndRepair.CollectIfIdle", value);
}
}
///
/// Set if the Block should push all ore/ingot imemediately out of its inventory,
/// else this will happen only if no more room to store the next items to be picked.
///
public bool PushIngotOreImmediately
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValueBool("BuildAndRepair.PushIngotOreImmediately") : false;
}
set
{
foreach (var entity in _Entities) entity.SetValueBool("BuildAndRepair.PushIngotOreImmediately", value);
}
}
///
/// Get the block that is currently being repaired/build.
///
public IMySlimBlock CurrentTarget
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValue("BuildAndRepair.CurrentTarget") : null;
}
}
///
/// Get the block that is currently being grinded.
///
public IMySlimBlock CurrentGrindTarget
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValue("BuildAndRepair.CurrentGrindTarget") : null;
}
}
///
/// Set if the Block if controlled by script.
/// (If controlled by script use PossibleTargets and CurrentPickedTarget
/// to set the block that should be build/repaired)
///
public bool ScriptControlled
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValueBool("BuildAndRepair.ScriptControlled") : false;
}
set
{
foreach (var entity in _Entities) entity.SetValueBool("BuildAndRepair.ScriptControlled", value);
}
}
///
/// Get a list of missing components.
///
public Dictionary MissingComponents()
{
var missingItems = new Dictionary();
foreach (var entity in _Entities)
{
var dict = entity.GetValue>("BuildAndRepair.MissingComponents");
//Merge dictionaries but only first report of an item or higher amount
//(do not add up the missings, as overlapping systems report same missing items)
if (dict != null && dict.Count > 0)
{
int value;
foreach (var newItem in dict)
{
if (missingItems.TryGetValue(newItem.Key, out value))
{
if (newItem.Value > value) missingItems[newItem.Key] = newItem.Value;
}
else
{
missingItems.Add(newItem.Key, newItem.Value);
}
}
}
}
return missingItems;
}
///
/// Get a list of possible repair/build targets.
/// (Contains only damaged/deformed/new block's in range of the system)
///
public MemorySafeList PossibleTargets()
{
if (_Entities.Count > 0)
{
return new MemorySafeList(_Entities[0].GetValue>("BuildAndRepair.PossibleTargets"));
}
return null;
}
///
/// Get the Block that should currently repaired/build.
/// In order to build the given block the property 'ScriptControlled' has to be true and
/// the block has to be in the list of 'PossibleTargets'.
/// If 'ScriptControlled' is true and the block is not in the 'PossibleTargets'
/// the system will do nothing.
///
public IMySlimBlock CurrentPickedTarget
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValue("BuildAndRepair.CurrentPickedTarget") : null;
}
set
{
foreach (var entity in _Entities) entity.SetValue("BuildAndRepair.CurrentPickedTarget", value);
}
}
///
/// Get a list of possible grind targets.
///
public MemorySafeList PossibleGrindTargets()
{
if (_Entities.Count > 0)
{
return new MemorySafeList(_Entities[0].GetValue>("BuildAndRepair.PossibleGrindTargets"));
}
return null;
}
///
/// Get the Block that should currently Grinded.
/// In order to grind the given block the property 'ScriptControlled' has to be true and
/// the block has to be in the list of 'PossibleGrindTargets'.
/// If 'ScriptControlled' is true and the block is not in the 'PossibleGrindTargets'
/// the system will do nothing.
///
public IMySlimBlock CurrentPickedGrindTarget
{
get
{
return _Entities.Count > 0 ? _Entities[0].GetValue("BuildAndRepair.CurrentPickedGrindTarget") : null;
}
set
{
foreach (var entity in _Entities) entity.SetValue("BuildAndRepair.CurrentPickedGrindTarget", value);
}
}
///
/// Get a list of possible grind targets.
///
public MemorySafeList PossibleCollectTargets()
{
if (_Entities.Count > 0)
{
return new MemorySafeList(_Entities[0].GetValue>("BuildAndRepair.PossibleCollectTargets"));
}
return null;
}
///
/// Ensures that the given amount is either in inventory or the production
/// queue of the given production blocks
///
public int EnsureQueued(IEnumerable productionBlockIds, VRage.Game.MyDefinitionId materialId, int amount)
{
if (_Entities.Count > 0)
{
if (_EnsureQueued == null)
{
_EnsureQueued = _Entities[0].GetValue, VRage.Game.MyDefinitionId, int, int>>("BuildAndRepair.ProductionBlock.EnsureQueued");
}
if (_EnsureQueued != null)
{
return _EnsureQueued(productionBlockIds, materialId, amount);
}
return -3;
}
return -2;
}
///
/// Retrieve the total components amount needed to build the projected
/// blueprint
///
///
///
///
public int NeededComponents4Blueprint(IMyProjector projector, Dictionary componentList)
{
if (_Entities.Count > 0)
{
if (_NeededComponents4Blueprint == null)
{
_NeededComponents4Blueprint = _Entities[0].GetValue, int>>("BuildAndRepair.Inventory.NeededComponents4Blueprint");
}
if (_NeededComponents4Blueprint != null)
{
return _NeededComponents4Blueprint(projector, componentList);
}
return -3;
}
return -2;
}
}
///
/// Class to handle Entities
///
public class EntityHandler : EntityHandler where T : class, IMyTerminalBlock
{
protected readonly List _Entities = new List();
protected readonly HashSet _DefinitionIdsInclude = new HashSet();
protected readonly HashSet _DefinitionIdsExclude = new HashSet();
///
///
///
public IEnumerable Entities
{
get
{
return _Entities;
}
}
public HashSet DefinitionIdsInclude
{
get
{
return _DefinitionIdsInclude;
}
}
public HashSet DefinitionIdsExclude
{
get
{
return _DefinitionIdsExclude;
}
}
///
///
///
public bool AreEnabled { get; private set; }
///
/// Count of Working Enties (on and functional)
///
public int CountOfWorking
{
get
{
var res = 0;
foreach (var entity in _Entities) if (entity.IsWorking && entity.IsFunctional) res++;
return res;
}
}
///
/// Get total count
///
protected override int GetCount()
{
return _Entities.Count;
}
///
/// Load entities from group
///
public override void Init(IMyBlockGroup group, bool add = false)
{
if (!add) _Entities.Clear();
var entities = new List();
group.GetBlocksOfType(entities);
foreach (var entity in entities)
{
AddEntity(entity);
}
CheckEnabled();
}
///
/// Load entity by name
///
///
///
public override void Init(VRage.Game.ModAPI.Ingame.IMyEntity newEntity, bool add = false)
{
if (!add) _Entities.Clear();
var entity = newEntity as T;
if (AddEntity(entity))
{
CheckEnabled();
}
}
///
/// Load entity filtered by given collect function
///
///
///
public void Init(IMyGridTerminalSystem gridTerminalSystem, Func collect = null, bool add = false)
{
if (!add) _Entities.Clear();
if (gridTerminalSystem != null)
{
var entities = new List();
gridTerminalSystem.GetBlocksOfType(entities, collect);
foreach (var entity in entities)
{
AddEntity(entity);
}
CheckEnabled();
}
}
///
/// Starten/Stoppen
///
protected virtual bool AddEntity(T entity)
{
if (entity == null || _Entities.IndexOf(entity) >= 0) return false;
var newDefId = entity.BlockDefinition;
var allowed = DefinitionIdsInclude.Count <= 0;
foreach (var defId in DefinitionIdsInclude)
{
if (defId.TypeId == newDefId.TypeId && (string.IsNullOrEmpty(defId.SubtypeName) || defId.SubtypeName.Equals(newDefId.SubtypeName)))
{
allowed = true;
break;
}
}
if (!allowed) return false;
foreach (var defId in DefinitionIdsExclude)
{
if (defId.TypeId == newDefId.TypeId && (string.IsNullOrEmpty(defId.SubtypeName) || defId.SubtypeName.Equals(newDefId.SubtypeName)))
{
return false;
}
}
_Entities.Add(entity);
return true;
}
///
/// Starten/Stoppen
///
public void Enabled(bool enabled)
{
foreach (var entity in _Entities)
{
var funcBlock = entity as IMyFunctionalBlock;
if (funcBlock != null && funcBlock.Enabled != enabled) funcBlock.Enabled = enabled;
}
AreEnabled = enabled;
}
///
///
///
private void CheckEnabled()
{
foreach (var entity in _Entities)
{
if (entity.IsWorking && entity.IsFunctional)
{
AreEnabled = true;
break;
}
}
}
}
///
///
///
public abstract class EntityHandler
{
public int Count { get { return GetCount(); } }
public abstract void Init(IMyBlockGroup group, bool add = false);
public abstract void Init(VRage.Game.ModAPI.Ingame.IMyEntity entity, bool add = false);
protected abstract int GetCount();
///
///
///
public static string GetCustomData(string customData, string startTag, string endTag)
{
var start = customData.IndexOf(startTag);
var end = customData.LastIndexOf(endTag);
if (start < 0 || end < 0 || end < start) return null;
return customData.Substring(start + startTag.Length, end - start - startTag.Length);
}
///
///
///
public static string GetCustomValue(string customData, string name)
{
var tag = "<" + name + "=";
var start = customData.IndexOf(tag);
if (start < 0) return null;
var end = customData.IndexOf("/>", start + tag.Length);
if (end < 0) return null;
return customData.Substring(start + tag.Length, end - start - tag.Length);
}
}
///
/// Status and Log functions
///
public class StatusAndLogDisplay
{
private readonly MyGridProgram _Program;
private readonly List _StatusPanels = new List();
private readonly List _LogPanels = new List();
private readonly string _AIName;
private string _LogText = "";
private string _StatusText = "";
private string _ErrorText = "";
private int _RefreshDelay;
private readonly string[] _LcdStatusPanels;
private readonly string[] _LcdLogPanels;
///
/// Count of Lines in Log Display
///
public int MaxLogLines { get; set; }
public bool ShowHeader { get; set; }
public StatusAndLogDisplay(MyGridProgram caller, string name, string[] lcdStatusPanels, string[] lcdLogPanels)
{
ShowHeader = true;
_Program = caller;
_AIName = name;
_LcdStatusPanels = lcdStatusPanels;
_LcdLogPanels = lcdLogPanels;
MaxLogLines = 20; //Default
ReloadDisplays();
}
///
/// Reload the displayes (after renaming, adding)
///
public string ReloadDisplays()
{
var res = FindPanels(_Program, _LcdStatusPanels, _StatusPanels);
res += FindPanels(_Program, _LcdLogPanels, _LogPanels);
return res;
}
///
/// Cyclic tries to reload the DisplayPanels (so the LCD could be added dynamically)
///
public void CyclicReloadDisplays()
{
_RefreshDelay--;
if (_RefreshDelay > 0) return;
ReloadDisplays();
_RefreshDelay = 20;
}
///
/// Write a Log text
///
public void Log(string msg)
{
var useHadline = !string.IsNullOrEmpty(_AIName);
var maxlines = MaxLogLines + (useHadline ? 0 : 1);
if (!string.IsNullOrEmpty(msg))
{
_LogText += "\n" + msg;
var lines = _LogText.Split('\n');
if (lines.Length >= maxlines)
{
_LogText = "";
for (var a = maxlines; a > 0; a--) _LogText += "\n" + lines[lines.Length - a];
}
}
}
///
/// Clears Status und Error
///
public void Clear()
{
_StatusText = "";
_ErrorText = "";
}
///
///
///
internal void AddStatus(string line)
{
_StatusText += line + "\n";
}
///
///
///
internal void AddError(string line)
{
_ErrorText = line + "\n";
}
///
/// Write Status, Error, Log to the configured panels
///
public void UpdateDisplay()
{
var text = string.Empty;
if (ShowHeader) text = _AIName + " (" + DateTime.Now + "):\n";
if (_ErrorText.Length > 0) text += _ErrorText;
text += _StatusText;
foreach (var panel in _StatusPanels) SetPanelText(panel, text);
_Program.Echo(!string.IsNullOrEmpty(_ErrorText) ? _ErrorText : text);
text = !string.IsNullOrEmpty(_AIName) ? _AIName + _LogText : _LogText;
foreach (var panel in _LogPanels) SetPanelText(panel, text);
}
///
/// Finds TextPanels with the given names
///
private static string FindPanels(MyGridProgram caller, IReadOnlyList names, ICollection list)
{
string res = string.Empty;
if (names != null && names.Count > 0)
{
foreach (var name in names)
{
string blockName;
int index;
GetNameAndIndex(name, out blockName, out index);
var block = caller.GridTerminalSystem.GetBlockWithName(blockName);
if (block == null)
{
res += string.Format("LCD {0} not found\n", blockName);
continue;
}
var textSurface = block as IMyTextSurface;
if (textSurface != null)
{
list.Add(textSurface);
continue;
}
var textSurfaceProvider = block as IMyTextSurfaceProvider;
if (textSurfaceProvider != null)
{
if (textSurfaceProvider.SurfaceCount > index)
{
list.Add(textSurfaceProvider.GetSurface(index));
continue;
}
res += string.Format("LCD {0} index {1} out of range (allowed 0..{2})\n", blockName, index, textSurfaceProvider.SurfaceCount - 1);
continue;
}
res += string.Format("{0} is not an LCD.\n", blockName);
}
}
if (!string.IsNullOrEmpty(res)) caller.Echo(res);
return res;
}
private static void GetNameAndIndex(string name, out string blockName, out int index)
{
index = 0;
var idxStart = name.LastIndexOf('[');
if (idxStart >= 0)
{
var idxEnd = name.LastIndexOf(']');
if (idxEnd >= 0 && idxEnd > idxStart)
{
if (int.TryParse(name.Substring(idxStart + 1, idxEnd - idxStart - 1), out index))
{
blockName = name.Substring(0, idxStart);
}
else blockName = name;
}
else blockName = name;
}
else blockName = name;
}
///
/// Sets panel text if its title is either default or our name.
///
public static void SetPanelText(IMyTextSurface panel, string text)
{
panel.ContentType = ContentType.TEXT_AND_IMAGE;
panel.WriteText(text, false);
}
///
/// Convert displayed values (Terminal) with correct units -> MW
///
public static float PowerUnitMultiple(string unit)
{
if (unit.StartsWith("W")) return 0.000001f;
if (unit.StartsWith("kW")) return 0.001f;
if (unit.StartsWith("MW")) return 1f;
return unit.StartsWith("GW") ? 1000f : 1f;
}
///
///
///
public static string DisplayPowerValueUnit(float value)
{
if (Math.Abs(value) < 0.001) return Math.Round(value * 1000000f) + "W";
if (Math.Abs(value) < 1) return Math.Round(value * 1000f) + "kW";
if (Math.Abs(value) < 1000) return Math.Round(value) + "MW";
return Math.Round(value / 1000f) + "GW";
}
///
///
///
public static string DisplayPowerRate(float current, float max, string ext = "")
{
return string.Format("{0:0.00}% {1}{3}/{2}{3}", max > 0 ? current * 100 / max : 0, DisplayPowerValueUnit(current), DisplayPowerValueUnit(max), ext);
}
///
///
///
///
///
public static double ToDegree(double rad)
{
return rad * 180 / Math.PI;
}
///
/// Get Name of Block
///
///
///
public static string BlockName(object block, bool includeGrid = false)
{
var inventory = block as IMyInventory;
if (inventory != null)
{
block = inventory.Owner;
}
var slimBlock = block as IMySlimBlock;
if (slimBlock != null)
{
if (slimBlock.FatBlock != null) block = slimBlock.FatBlock;
else
{
if (includeGrid) return string.Format("{0}.{1}", slimBlock.CubeGrid != null ? slimBlock.CubeGrid.DisplayName : "Unknown Grid", slimBlock.BlockDefinition.SubtypeName);
return string.Format("{0}", slimBlock.BlockDefinition.SubtypeName);
}
}
var terminalBlock = block as IMyTerminalBlock;
if (terminalBlock != null)
{
if (includeGrid) return string.Format("{0}.{1}", terminalBlock.CubeGrid != null ? terminalBlock.CubeGrid.DisplayName : "Unknown Grid", terminalBlock.CustomName);
return string.Format("{0}", terminalBlock.CustomName);
}
var cubeBlock = block as IMyCubeBlock;
if (cubeBlock != null)
{
if (includeGrid) return string.Format("{0} [{1}/{2}]", cubeBlock.CubeGrid != null ? cubeBlock.CubeGrid.DisplayName : "Unknown Grid", cubeBlock.BlockDefinition.TypeIdString, cubeBlock.BlockDefinition.SubtypeName);
return string.Format("[{0}/{1}]", cubeBlock.BlockDefinition.TypeIdString, cubeBlock.BlockDefinition.SubtypeName);
}
var entity = block as IMyEntity;
if (entity != null)
{
return string.Format("{0} ({1})", entity.DisplayName, entity.EntityId);
}
var cubeGrid = block as IMyCubeGrid;
if (cubeGrid != null) return cubeGrid.DisplayName;
return block != null ? block.ToString() : "NULL";
}
}