public void Run(ZACommons commons, EventDriver eventDriver) { var groups = commons.GetBlockGroupsWithPrefix(DOOR_AUTO_CLOSER_PREFIX); if (groups.Count > 0) { groups.ForEach(group => { // Determine open duration var parts = group.Name.Split(new char[] { DURATION_DELIMITER }, 2); var duration = DEFAULT_DOOR_OPEN_DURATION; if (parts.Length == 2) { if (!double.TryParse(parts[1], out duration)) { duration = DEFAULT_DOOR_OPEN_DURATION; } } var doors = ZACommons.GetBlocksOfType<IMyDoor>(group.Blocks, block => block.IsFunctional); CloseDoors(commons, eventDriver, doors, duration); }); } else { // Default behavior (all doors except vanilla Airtight Hangar Doors and tagged doors) var doors = ZACommons .GetBlocksOfType<IMyDoor>(commons.Blocks, block => block.IsFunctional && block.CustomName.IndexOf("[Excluded]", ZACommons.IGNORE_CASE) < 0 && block.DefinitionDisplayNameText != "Airtight Hangar Door"); CloseDoors(commons, eventDriver, doors, DEFAULT_DOOR_OPEN_DURATION); } eventDriver.Schedule(RunDelay, Run); }
public void Run(ZACommons commons, EventDriver eventDriver) { var groups = commons.GetBlockGroupsWithPrefix(SIMPLE_AIRLOCK_GROUP_PREFIX); for (var e = groups.GetEnumerator(); e.MoveNext();) { var doors = ZACommons.GetBlocksOfType<IMyDoor>(e.Current.Blocks, door => door.CubeGrid == commons.Me.CubeGrid && door.IsFunctional); var opened = IsAnyDoorOpen(doors); for (var f = doors.GetEnumerator(); f.MoveNext();) { var door = (IMyDoor)f.Current; if (door.OpenRatio == 0.0f && opened) { // This door is not open and some other door in the group is, lock it down if (door.Enabled) door.SetValue<bool>("OnOff", false); } else { if (!door.Enabled) door.SetValue<bool>("OnOff", true); } } } eventDriver.Schedule(RunDelay, Run); }
public void HandleCommand(ZACommons commons, EventDriver eventDriver, string argument) { // Handle commands argument = argument.Trim().ToLower(); if (argument == "pause") { Active = false; SaveActive(commons); var solarGroups = commons.GetBlockGroupsWithPrefix(MAX_POWER_GROUP_PREFIX); solarGroups.ForEach(group => { var rotor = GetRotor(group); if (rotor != null) { rotor.Enabled = false; } }); } else if (argument == "resume") { if (!Active) { Init(commons, eventDriver); } } }
public void Run(ZACommons commons, EventDriver eventDriver) { var groups = commons.GetBlockGroupsWithPrefix(SIMPLE_AIRLOCK_GROUP_PREFIX); for (var e = groups.GetEnumerator(); e.MoveNext();) { var doors = ZACommons.GetBlocksOfType <IMyDoor>(e.Current.Blocks, door => door.CubeGrid == commons.Me.CubeGrid && door.IsFunctional); var opened = IsAnyDoorOpen(doors); for (var f = doors.GetEnumerator(); f.MoveNext();) { var door = (IMyDoor)f.Current; if (door.OpenRatio == 0.0f && opened) { // This door is not open and some other door in the group is, lock it down if (door.Enabled) { door.SetValue <bool>("OnOff", false); } } else { if (!door.Enabled) { door.SetValue <bool>("OnOff", true); } } } } eventDriver.Schedule(RunDelay, Run); }
public void Run(ZACommons commons, EventDriver eventDriver) { var groups = commons.GetBlockGroupsWithPrefix(DOOR_AUTO_CLOSER_PREFIX); if (groups.Count > 0) { groups.ForEach(group => { // Determine open duration var parts = group.Name.Split(new char[] { DURATION_DELIMITER }, 2); var duration = DEFAULT_DOOR_OPEN_DURATION; if (parts.Length == 2) { if (!double.TryParse(parts[1], out duration)) { duration = DEFAULT_DOOR_OPEN_DURATION; } } var doors = ZACommons.GetBlocksOfType <IMyDoor>(group.Blocks, block => block.IsFunctional); CloseDoors(commons, eventDriver, doors, duration); }); } else { // Default behavior (all doors except vanilla Airtight Hangar Doors and tagged doors) var doors = ZACommons .GetBlocksOfType <IMyDoor>(commons.Blocks, block => block.IsFunctional && block.CustomName.IndexOf("[Excluded]", ZACommons.IGNORE_CASE) < 0 && block.DefinitionDisplayNameText != "Airtight Hangar Door"); CloseDoors(commons, eventDriver, doors, DEFAULT_DOOR_OPEN_DURATION); } eventDriver.Schedule(RunDelay, Run); }
public void Run(ZACommons commons, EventDriver eventDriver) { var groups = commons.GetBlockGroupsWithPrefix(SIMPLE_AIRLOCK_GROUP_PREFIX); foreach (var group in groups) { var doors = ZACommons.GetBlocksOfType <IMyDoor>(group.Blocks, door => door.CubeGrid == commons.Me.CubeGrid && door.IsFunctional); var opened = IsAnyDoorOpen(doors); foreach (var door in doors) { if (door.OpenRatio == 0.0f && opened) { // This door is not open and some other door in the group is, lock it down if (door.Enabled) { door.Enabled = false; } } else { if (!door.Enabled) { door.Enabled = true; } } } } eventDriver.Schedule(RunDelay, Run); }
public void Run(ZACommons commons, EventDriver eventDriver) { if (!Active) { return; } TotalPower = 0.0f; var solarGroups = commons.GetBlockGroupsWithPrefix(MAX_POWER_GROUP_PREFIX); foreach (var group in solarGroups) { var rotor = GetRotor(group); if (rotor == null) { commons.Echo(string.Format("Group {0} ignored; needs exactly 1 rotor", group.Name)); continue; } else if (rotor.CubeGrid != commons.Me.CubeGrid) { // Skip if rotor is on a different grid than this programmable block continue; } var solarPanelDetails = new SolarPanelDetails(group); var currentMaxPower = solarPanelDetails.MaxPowerOutput; float maxPower; if (!MaxPowers.TryGetValue(group.Name, out maxPower)) { maxPower = -100.0f; } var minError = solarPanelDetails.DefinedPowerOutput * SOLAR_ROTOR_MIN_ERROR; var delta = currentMaxPower - maxPower; MaxPowers[group.Name] = currentMaxPower; if (delta > minError || currentMaxPower < minError /* failsafe */) { // Keep going rotor.Enabled = true; } else if (delta < -minError) { // Back up rotor.Enabled = true; rotor.ApplyAction("Reverse"); } else { // Hold still for a moment rotor.Enabled = false; } TotalPower += currentMaxPower; } eventDriver.Schedule(RunDelay, Run); }
public void Run(ZACommons commons, EventDriver eventDriver) { if (!Active) return; TotalPower = 0.0f; var solarGroups = commons.GetBlockGroupsWithPrefix(MAX_POWER_GROUP_PREFIX); for (var e = solarGroups.GetEnumerator(); e.MoveNext();) { var group = e.Current; var rotor = GetRotor(group); if (rotor == null) { commons.Echo(string.Format("Group {0} ignored; needs exactly 1 rotor", group.Name)); continue; } else if (rotor.CubeGrid != commons.Me.CubeGrid) { // Skip if rotor is on a different grid than this programmable block continue; } var solarPanelDetails = new SolarPanelDetails(group); var currentMaxPower = solarPanelDetails.MaxPowerOutput; float maxPower; if (!MaxPowers.TryGetValue(group.Name, out maxPower)) maxPower = -100.0f; var minError = solarPanelDetails.DefinedPowerOutput * SOLAR_ROTOR_MIN_ERROR; var delta = currentMaxPower - maxPower; MaxPowers[group.Name] = currentMaxPower; if (delta > minError || currentMaxPower < minError /* failsafe */) { // Keep going rotor.SetValue<bool>("OnOff", true); } else if (delta < -minError) { // Back up rotor.SetValue<bool>("OnOff", true); rotor.ApplyAction("Reverse"); } else { // Hold still for a moment rotor.SetValue<bool>("OnOff", false); } TotalPower += currentMaxPower; } eventDriver.Schedule(RunDelay, Run); }
public void Run(ZACommons commons) { for (var e = commons.GetBlockGroupsWithPrefix(REDUNDANCY_PREFIX).GetEnumerator(); e.MoveNext();) { var group = e.Current; // Figure out how many to maintain var parts = group.Name.Split(new char[] { COUNT_DELIMITER }, 2); var count = 1; if (parts.Length == 2) { if (int.TryParse(parts[1], out count)) { count = Math.Max(count, 1); } else { count = 1; } } var running = 0; var spares = new LinkedList<IMyTerminalBlock>(); for (var f = group.Blocks.GetEnumerator(); f.MoveNext();) { var block = f.Current as IMyFunctionalBlock; if (block != null && block.CubeGrid == commons.Me.CubeGrid && block.IsFunctional) { if (block.IsWorking && block.Enabled) { running++; } else { spares.AddLast(block); } } } while (running < count && spares.First != null) { var block = spares.First.Value; spares.RemoveFirst(); block.SetValue<bool>("OnOff", true); running++; } } }
public void Run(ZACommons commons, EventDriver eventDriver) { for (var e = commons.GetBlockGroupsWithPrefix(DOCKING_ACTION_PREFIX).GetEnumerator(); e.MoveNext();) { var group = e.Current; // Figure out action var parts = group.Name.Split(new char[] { ACTION_DELIMETER }, 2); string action = "on"; if (parts.Length == 2) { action = parts[1]; } // Determine state of first connector (should only have 1) bool connected = false; var connectors = ZACommons.GetBlocksOfType <IMyShipConnector>(group.Blocks); if (connectors.Count > 0) { var connector = (IMyShipConnector)connectors[0]; connected = connector.IsLocked && connector.IsConnected; } if ("on".Equals(action, ZACommons.IGNORE_CASE) || "off".Equals(action, ZACommons.IGNORE_CASE)) { bool enable; if ("on".Equals(action, ZACommons.IGNORE_CASE)) { enable = connected; } else { enable = !connected; } // Set state according to action group.Blocks.ForEach(block => { if (!(block is IMyShipConnector)) // ignore connectors { block.SetValue <bool>("OnOff", enable); } }); } // Ignore anything else for now } eventDriver.Schedule(RunDelay, Run); }
public void Run(ZACommons commons) { for (var e = commons.GetBlockGroupsWithPrefix(REDUNDANCY_PREFIX).GetEnumerator(); e.MoveNext();) { var group = e.Current; // Figure out how many to maintain var parts = group.Name.Split(new char[] { COUNT_DELIMITER }, 2); var count = 1; if (parts.Length == 2) { if (int.TryParse(parts[1], out count)) { count = Math.Max(count, 1); } else { count = 1; } } var running = 0; var spares = new LinkedList <IMyTerminalBlock>(); for (var f = group.Blocks.GetEnumerator(); f.MoveNext();) { var block = f.Current as IMyFunctionalBlock; if (block != null && block.CubeGrid == commons.Me.CubeGrid && block.IsFunctional) { if (block.IsWorking && block.Enabled) { running++; } else { spares.AddLast(block); } } } while (running < count && spares.First != null) { var block = spares.First.Value; spares.RemoveFirst(); block.SetValue <bool>("OnOff", true); running++; } } }
public void Run(ZACommons commons, EventDriver eventDriver) { for (var e = commons.GetBlockGroupsWithPrefix(DOCKING_ACTION_PREFIX).GetEnumerator(); e.MoveNext();) { var group = e.Current; // Figure out action var parts = group.Name.Split(new char[] { ACTION_DELIMETER }, 2); string action = "on"; if (parts.Length == 2) { action = parts[1]; } // Determine state of first connector (should only have 1) bool connected = false; var connectors = ZACommons.GetBlocksOfType<IMyShipConnector>(group.Blocks); if (connectors.Count > 0) { var connector = (IMyShipConnector)connectors[0]; connected = connector.IsLocked && connector.IsConnected; } if ("on".Equals(action, ZACommons.IGNORE_CASE) || "off".Equals(action, ZACommons.IGNORE_CASE)) { bool enable; if ("on".Equals(action, ZACommons.IGNORE_CASE)) { enable = connected; } else { enable = !connected; } // Set state according to action group.Blocks.ForEach(block => { if (!(block is IMyShipConnector)) // ignore connectors { block.SetValue<bool>("OnOff", enable); } }); } // Ignore anything else for now } eventDriver.Schedule(RunDelay, Run); }
public void Run(ZACommons commons, EventDriver eventDriver) { foreach (var group in commons.GetBlockGroupsWithPrefix(DOCKING_ACTION_PREFIX)) { // Figure out action var parts = group.Name.Split(new char[] { ACTION_DELIMETER }, 2); string action = "on"; if (parts.Length == 2) { action = parts[1]; } // Determine state of first connector (should only have 1) bool connected = false; var connectors = ZACommons.GetBlocksOfType <IMyShipConnector>(group.Blocks); if (connectors.Count > 0) { var connector = connectors[0]; connected = connector.Status == MyShipConnectorStatus.Connected; } if ("on".Equals(action, ZACommons.IGNORE_CASE) || "off".Equals(action, ZACommons.IGNORE_CASE)) { bool enable; if ("on".Equals(action, ZACommons.IGNORE_CASE)) { enable = connected; } else { enable = !connected; } // Set state according to action group.Blocks.ForEach(block => { if (!(block is IMyShipConnector) && // ignore connectors block is IMyFunctionalBlock) { ((IMyFunctionalBlock)block).Enabled = enable; } }); } // Ignore anything else for now } eventDriver.Schedule(RunDelay, Run); }
public void Run(ZACommons commons) { foreach (var group in commons.GetBlockGroupsWithPrefix(REDUNDANCY_PREFIX)) { // Figure out how many to maintain var parts = group.Name.Split(new char[] { COUNT_DELIMITER }, 2); var count = 1; if (parts.Length == 2) { if (int.TryParse(parts[1], out count)) { count = Math.Max(count, 1); } else { count = 1; } } var running = 0; var spares = new LinkedList <IMyFunctionalBlock>(); foreach (var block in group.Blocks) { var fblock = block as IMyFunctionalBlock; if (fblock != null && fblock.CubeGrid == commons.Me.CubeGrid && fblock.IsFunctional) { if (fblock.IsWorking && fblock.Enabled) { running++; } else { spares.AddLast(fblock); } } } while (running < count && spares.First != null) { var block = spares.First.Value; spares.RemoveFirst(); block.Enabled = true; running++; } } }
public void Run(ZACommons commons, EventDriver eventDriver) { var groups = commons.GetBlockGroupsWithPrefix(REFINERY_MANAGER_PREFIX); if (groups.Count > 0) { groups.ForEach(group => Balance(commons, group.Blocks)); } else { // Balance all refineries Balance(commons, commons.Blocks); } eventDriver.Schedule(RunDelay, Run); }
private void Init(ZACommons commons) { var groups = commons.GetBlockGroupsWithPrefix("Airlock"); // Classify each group for (var e = groups.GetEnumerator(); e.MoveNext();) { var group = e.Current; if (string.Equals("AirlockDoorInner", group.Name, ZACommons.IGNORE_CASE)) { innerDoors.UnionWith(ToDoors(ZACommons.GetBlocksOfType <IMyDoor>(group.Blocks))); } else if (string.Equals("AirlockDoorSpace", group.Name, ZACommons.IGNORE_CASE)) { spaceDoors.UnionWith(ToDoors(ZACommons.GetBlocksOfType <IMyDoor>(group.Blocks))); } else if (group.Name.StartsWith("AirlockDoor", ZACommons.IGNORE_CASE)) { doorVentGroups.Add(group.Name, group); var vents = ToVents(ZACommons.GetBlocksOfType <IMyAirVent>(group.Blocks)); var doors = ToDoors(ZACommons.GetBlocksOfType <IMyDoor>(group.Blocks)); for (var f = doors.GetEnumerator(); f.MoveNext();) { doorVentMap.Add(f.Current, vents); } } else { rooms.Add(group); roomsMap.Add(group.Name, group); var doors = ToDoors(ZACommons.GetBlocksOfType <IMyDoor>(group.Blocks)); for (var f = doors.GetEnumerator(); f.MoveNext();) { doorVentRooms.Add(f.Current, group); } } } }
private void Init(ZACommons commons) { var groups = commons.GetBlockGroupsWithPrefix("Airlock"); // Classify each group for (var e = groups.GetEnumerator(); e.MoveNext();) { var group = e.Current; if (string.Equals("AirlockDoorInner", group.Name, ZACommons.IGNORE_CASE)) { innerDoors.UnionWith(ToDoors(ZACommons.GetBlocksOfType<IMyDoor>(group.Blocks))); } else if (string.Equals("AirlockDoorSpace", group.Name, ZACommons.IGNORE_CASE)) { spaceDoors.UnionWith(ToDoors(ZACommons.GetBlocksOfType<IMyDoor>(group.Blocks))); } else if (group.Name.StartsWith("AirlockDoor", ZACommons.IGNORE_CASE)) { doorVentGroups.Add(group.Name, group); var vents = ToVents(ZACommons.GetBlocksOfType<IMyAirVent>(group.Blocks)); var doors = ToDoors(ZACommons.GetBlocksOfType<IMyDoor>(group.Blocks)); for (var f = doors.GetEnumerator(); f.MoveNext();) { doorVentMap.Add(f.Current, vents); } } else { rooms.Add(group); roomsMap.Add(group.Name, group); var doors = ToDoors(ZACommons.GetBlocksOfType<IMyDoor>(group.Blocks)); for (var f = doors.GetEnumerator(); f.MoveNext();) { doorVentRooms.Add(f.Current, group); } } } }
private void Init(ZACommons commons) { var groups = commons.GetBlockGroupsWithPrefix("Airlock"); // Classify each group foreach (var group in groups) { if (string.Equals("AirlockDoorInner", group.Name, ZACommons.IGNORE_CASE)) { innerDoors.UnionWith(ZACommons.GetBlocksOfType <IMyDoor>(group.Blocks)); } else if (string.Equals("AirlockDoorSpace", group.Name, ZACommons.IGNORE_CASE)) { spaceDoors.UnionWith(ZACommons.GetBlocksOfType <IMyDoor>(group.Blocks)); } else if (group.Name.StartsWith("AirlockDoor", ZACommons.IGNORE_CASE)) { doorVentGroups.Add(group.Name, group); var vents = ZACommons.GetBlocksOfType <IMyAirVent>(group.Blocks); var doors = ZACommons.GetBlocksOfType <IMyDoor>(group.Blocks); foreach (var door in doors) { doorVentMap.Add(door, vents); } } else { rooms.Add(group); roomsMap.Add(group.Name, group); var doors = ZACommons.GetBlocksOfType <IMyDoor>(group.Blocks); foreach (var door in doors) { doorVentRooms.Add(door, group); } } } }
private static IMyProjector GetProjector(ZACommons commons, string name, out string rest) { var groupPrefix = PROJECTOR_ACTION_PREFIX + name + ACTION_DELIMITER; var groups = commons.GetBlockGroupsWithPrefix(groupPrefix); if (groups.Count > 0) { var blocks = ZACommons.GetBlocksOfType <IMyProjector>(groups[0].Blocks); foreach (var block in blocks) { // Just take first one if (block.IsFunctional) { rest = groups[0].Name.Substring(groupPrefix.Length); return(blocks[0]); } } } rest = default(string); return(null); }
private static IMyProjector GetProjector(ZACommons commons, string name, out string rest) { var groupPrefix = PROJECTOR_ACTION_PREFIX + name + ACTION_DELIMITER; var groups = commons.GetBlockGroupsWithPrefix(groupPrefix); if (groups.Count > 0) { var blocks = ZACommons.GetBlocksOfType<IMyProjector>(groups[0].Blocks); for (var e = blocks.GetEnumerator(); e.MoveNext();) { var block = e.Current; // Just take first one if (block.IsFunctional) { rest = groups[0].Name.Substring(groupPrefix.Length); return (IMyProjector)blocks[0]; } } } rest = default(string); return null; }
private void DoActions(ZACommons commons, EventDriver eventDriver, double currentSpeed) { foreach (var group in commons.GetBlockGroupsWithPrefix(SPEED_ACTION_PREFIX)) { // Break it up and parse each part var parts = group.Name.Split(new char[] { ACTION_DELIMETER }, 3); if (parts.Length < 2) { continue; // Need at least speed } double speed; if (!double.TryParse(parts[1], out speed)) { continue; // And it needs to be parsable } string action = "on"; if (parts.Length == 3) { action = parts[2]; } var rising = false; var falling = false; switch (action[0]) { case '>': rising = true; action = action.Substring(1); break; case '<': falling = true; action = action.Substring(1); break; } var onFlag = "on".Equals(action, ZACommons.IGNORE_CASE); var offFlag = "off".Equals(action, ZACommons.IGNORE_CASE); if (onFlag || offFlag) { if (!rising && !falling) { bool enable; if (onFlag) { enable = currentSpeed >= speed; } else { enable = currentSpeed < speed; } group.Blocks.ForEach(block => block.SetValue <bool>("OnOff", enable)); } else if ((rising && LastSpeed < speed && currentSpeed >= speed) || (falling && LastSpeed >= speed && currentSpeed < speed)) { group.Blocks.ForEach(block => block.SetValue <bool>("OnOff", onFlag)); } } } }
private void TargetUpdated(ZACommons commons, EventDriver eventDriver, MyDetectedEntityInfo info, bool full = false, bool localOnly = false, TimeSpan?updateTime = null, bool newOffset = true) { var position = info.Position; var velocity = new Vector3D(info.Velocity); // Convert to quaternion so it's more compact var orientation = QuaternionD.CreateFromRotationMatrix(info.Orientation); if (updateTime == null) { // Fresh update, use it for gyro lock TargetPosition = position; TargetVelocity = velocity; LastTargetUpdate = eventDriver.TimeSinceStart; } else { // Interpolate position since given update time var delta = (eventDriver.TimeSinceStart - (TimeSpan)updateTime).TotalSeconds; position += velocity * delta; } // Compose message string msg; if (full) { Vector3D localOffset; if (newOffset) { // Be sure to use original position when determining offset var offset = (Vector3D)info.HitPosition - info.Position; var toLocal = MatrixD.Transpose(info.Orientation); localOffset = Vector3D.TransformNormal(offset, toLocal); // Save for future TargetOffset = localOffset; } else { localOffset = TargetOffset; } msg = string.Format("tnew;{0};{1};{2};{3};{4};{5};{6};{7};{8};{9};{10};{11};{12};{13}", info.EntityId, position.X, position.Y, position.Z, velocity.X, velocity.Y, velocity.Z, orientation.X, orientation.Y, orientation.Z, orientation.W, localOffset.X, localOffset.Y, localOffset.Z); } else { msg = string.Format("tupdate;{0};{1};{2};{3};{4};{5};{6};{7};{8};{9};{10}", info.EntityId, position.X, position.Y, position.Z, velocity.X, velocity.Y, velocity.Z, orientation.X, orientation.Y, orientation.Z, orientation.W); } var broadcasted = false; foreach (var group in commons.GetBlockGroupsWithPrefix(TARGET_UPDATE_PREFIX)) { foreach (var block in group.Blocks) { if (block is IMyProgrammableBlock) { ((IMyProgrammableBlock)block).TryRun(msg); } else if (!localOnly && block is IMyLaserAntenna) { ((IMyLaserAntenna)block).TransmitMessage(msg); } else if (!localOnly && !broadcasted && block is IMyRadioAntenna) { // Only if functional and enabled var antenna = (IMyRadioAntenna)block; if (antenna.IsFunctional && antenna.Enabled) { antenna.TransmitMessage(msg, TRACKER_ANTENNA_TARGET); broadcasted = true; } } } } }
public void HandleCommand(ZACommons commons, EventDriver eventDriver, string argument) { // Handle commands argument = argument.Trim().ToLower(); if (argument == "pause") { Active = false; SaveActive(commons); var solarGroups = commons.GetBlockGroupsWithPrefix(MAX_POWER_GROUP_PREFIX); solarGroups.ForEach(group => { var rotor = GetRotor(group); if (rotor != null) rotor.SetValue<bool>("OnOff", false); }); } else if (argument == "resume") { if (!Active) Init(commons, eventDriver); } }
private void _Run(ZACommons commons, EventDriver eventDriver) { // No source, don't bother var stockGroup = commons.GetBlockGroupWithName(STOCKER_SOURCE_NAME); if (stockGroup == null) { return; } var toCheck = new Dictionary <IMyTerminalBlock, Dictionary <string, int> >(); for (var e = commons.GetBlockGroupsWithPrefix(STOCKER_PREFIX).GetEnumerator(); e.MoveNext();) { var group = e.Current; if (group.Name == STOCKER_SOURCE_NAME) { continue; } // Determine count var parts = group.Name.Split(new char[] { COUNT_DELIMITER }, 2); var count = 1; if (parts.Length == 2) { if (int.TryParse(parts[1], out count)) { count = Math.Max(count, 1); } else { count = 1; } } // Determine SubtypeName var subtypeName = parts[0].Substring(STOCKER_PREFIX.Length).Trim(); if (subtypeName.Length == 0) { continue; } // Gather destinations and wanted subtypes/counts group.Blocks.ForEach(block => { if (!block.IsFunctional || block.GetInventoryCount() == 0) { return; } Dictionary <string, int> wantedStocks; if (!toCheck.TryGetValue(block, out wantedStocks)) { wantedStocks = new Dictionary <string, int>(); toCheck.Add(block, wantedStocks); } int wanted; if (wantedStocks.TryGetValue(subtypeName, out wanted)) { // Use biggest request wanted = Math.Max(wanted, count); } else { wanted = count; } wantedStocks[subtypeName] = wanted; }); } // Determine how many are missing from all destinations var missingStocks = new Dictionary <string, LinkedList <MissingStock> >(); for (var e = toCheck.GetEnumerator(); e.MoveNext();) { var block = e.Current.Key; var wantedStocks = e.Current.Value; // Gather current item counts var currents = new Dictionary <string, VRage.MyFixedPoint>(); for (int i = 0; i < block.GetInventoryCount(); i++) { var inventory = block.GetInventory(i); var items = inventory.GetItems(); items.ForEach(item => { // Only care about wanted items for this block var subtypeName = item.Content.SubtypeName; if (wantedStocks.ContainsKey(subtypeName)) { VRage.MyFixedPoint current; if (!currents.TryGetValue(subtypeName, out current)) { current = (VRage.MyFixedPoint) 0.0f; } current += item.Amount; currents[subtypeName] = current; } }); } // Now figure out what's missing for (var f = wantedStocks.GetEnumerator(); f.MoveNext();) { var subtypeName = f.Current.Key; var count = f.Current.Value; VRage.MyFixedPoint current; if (!currents.TryGetValue(subtypeName, out current)) { current = (VRage.MyFixedPoint) 0.0f; } if (current < count) { // Add to dictionary under SubtypeName & keep track // of this block LinkedList <MissingStock> missing; if (!missingStocks.TryGetValue(subtypeName, out missing)) { missing = new LinkedList <MissingStock>(); missingStocks.Add(subtypeName, missing); } // NB Assumes first inventory missing.AddLast(new MissingStock(block.GetInventory(0), (VRage.MyFixedPoint)count - current)); } } } // Nothing missing, nothing to do if (missingStocks.Count == 0) { return; } // Now attempt to fill missing blocks stockGroup.Blocks.ForEach(source => { if (!source.IsFunctional) { return; } for (int i = 0; i < source.GetInventoryCount(); i++) { var inventory = source.GetInventory(i); var items = inventory.GetItems(); for (int j = items.Count - 1; j >= 0; j--) { var item = items[j]; var subtypeName = item.Content.SubtypeName; LinkedList <MissingStock> missing; if (missingStocks.TryGetValue(subtypeName, out missing)) { var sourceAmount = item.Amount; while (missing.First != null && sourceAmount > (VRage.MyFixedPoint) 0.0f) { var dest = missing.First.Value; VRage.MyFixedPoint transferAmount; // Has enough to fully restock? if (sourceAmount >= dest.Amount) { transferAmount = dest.Amount; // Assume it will succeed missing.RemoveFirst(); } else { transferAmount = sourceAmount; dest.Amount -= transferAmount; } // Move some over dest.Inventory.TransferItemFrom(inventory, j, stackIfPossible: true, amount: transferAmount); // FIXME no error checking sourceAmount -= transferAmount; } } } } }); }
private void _Run(ZACommons commons, EventDriver eventDriver) { // No source, don't bother var stockGroup = commons.GetBlockGroupWithName(STOCKER_SOURCE_NAME); if (stockGroup == null) return; var toCheck = new Dictionary<IMyTerminalBlock, Dictionary<string, int>>(); for (var e = commons.GetBlockGroupsWithPrefix(STOCKER_PREFIX).GetEnumerator(); e.MoveNext();) { var group = e.Current; if (group.Name == STOCKER_SOURCE_NAME) continue; // Determine count var parts = group.Name.Split(new char[] { COUNT_DELIMITER }, 2); var count = 1; if (parts.Length == 2) { if (int.TryParse(parts[1], out count)) { count = Math.Max(count, 1); } else { count = 1; } } // Determine SubtypeName var subtypeName = parts[0].Substring(STOCKER_PREFIX.Length).Trim(); if (subtypeName.Length == 0) continue; // Gather destinations and wanted subtypes/counts group.Blocks.ForEach(block => { if (!block.IsFunctional || block.GetInventoryCount() == 0) return; Dictionary<string, int> wantedStocks; if (!toCheck.TryGetValue(block, out wantedStocks)) { wantedStocks = new Dictionary<string, int>(); toCheck.Add(block, wantedStocks); } int wanted; if (wantedStocks.TryGetValue(subtypeName, out wanted)) { // Use biggest request wanted = Math.Max(wanted, count); } else { wanted = count; } wantedStocks[subtypeName] = wanted; }); } // Determine how many are missing from all destinations var missingStocks = new Dictionary<string, LinkedList<MissingStock>>(); for (var e = toCheck.GetEnumerator(); e.MoveNext();) { var block = e.Current.Key; var wantedStocks = e.Current.Value; // Gather current item counts var currents = new Dictionary<string, VRage.MyFixedPoint>(); for (int i = 0; i < block.GetInventoryCount(); i++) { var inventory = block.GetInventory(i); var items = inventory.GetItems(); items.ForEach(item => { // Only care about wanted items for this block var subtypeName = item.Content.SubtypeName; if (wantedStocks.ContainsKey(subtypeName)) { VRage.MyFixedPoint current; if (!currents.TryGetValue(subtypeName, out current)) { current = (VRage.MyFixedPoint)0.0f; } current += item.Amount; currents[subtypeName] = current; } }); } // Now figure out what's missing for (var f = wantedStocks.GetEnumerator(); f.MoveNext();) { var subtypeName = f.Current.Key; var count = f.Current.Value; VRage.MyFixedPoint current; if (!currents.TryGetValue(subtypeName, out current)) { current = (VRage.MyFixedPoint)0.0f; } if (current < count) { // Add to dictionary under SubtypeName & keep track // of this block LinkedList<MissingStock> missing; if (!missingStocks.TryGetValue(subtypeName, out missing)) { missing = new LinkedList<MissingStock>(); missingStocks.Add(subtypeName, missing); } // NB Assumes first inventory missing.AddLast(new MissingStock(block.GetInventory(0), (VRage.MyFixedPoint)count - current)); } } } // Nothing missing, nothing to do if (missingStocks.Count == 0) return; // Now attempt to fill missing blocks stockGroup.Blocks.ForEach(source => { if (!source.IsFunctional) return; for (int i = 0; i < source.GetInventoryCount(); i++) { var inventory = source.GetInventory(i); var items = inventory.GetItems(); for (int j = items.Count - 1; j >= 0; j--) { var item = items[j]; var subtypeName = item.Content.SubtypeName; LinkedList<MissingStock> missing; if (missingStocks.TryGetValue(subtypeName, out missing)) { var sourceAmount = item.Amount; while (missing.First != null && sourceAmount > (VRage.MyFixedPoint)0.0f) { var dest = missing.First.Value; VRage.MyFixedPoint transferAmount; // Has enough to fully restock? if (sourceAmount >= dest.Amount) { transferAmount = dest.Amount; // Assume it will succeed missing.RemoveFirst(); } else { transferAmount = sourceAmount; dest.Amount -= transferAmount; } // Move some over dest.Inventory.TransferItemFrom(inventory, j, stackIfPossible: true, amount: transferAmount); // FIXME no error checking sourceAmount -= transferAmount; } } } } }); }
private void DoActions(ZACommons commons, EventDriver eventDriver, double currentSpeed) { for (var e = commons.GetBlockGroupsWithPrefix(SPEED_ACTION_PREFIX).GetEnumerator(); e.MoveNext();) { var group = e.Current; // Break it up and parse each part var parts = group.Name.Split(new char[] { ACTION_DELIMETER }, 3); if (parts.Length < 2) continue; // Need at least speed double speed; if (!double.TryParse(parts[1], out speed)) continue; // And it needs to be parsable string action = "on"; if (parts.Length == 3) { action = parts[2]; } var rising = false; var falling = false; switch (action[0]) { case '>': rising = true; action = action.Substring(1); break; case '<': falling = true; action = action.Substring(1); break; } var onFlag = "on".Equals(action, ZACommons.IGNORE_CASE); var offFlag = "off".Equals(action, ZACommons.IGNORE_CASE); if (onFlag || offFlag) { if (!rising && !falling) { bool enable; if (onFlag) { enable = currentSpeed >= speed; } else { enable = currentSpeed < speed; } group.Blocks.ForEach(block => block.SetValue<bool>("OnOff", enable)); } else if ((rising && LastSpeed < speed && currentSpeed >= speed) || (falling && LastSpeed >= speed && currentSpeed < speed)) { group.Blocks.ForEach(block => block.SetValue<bool>("OnOff", onFlag)); } } } }