public void Main(string argument, UpdateType updateSource) { UpdateInv(); if (ComputerCount < compAmount) { Assembler.AddQueueItem(MyDefinitionId.Parse("MyObjectBuilder_BlueprintDefinition/ComputerComponent"), compAmount - ComputerCount); } if (ConstructionCount < constructAmount) { Assembler.AddQueueItem(MyDefinitionId.Parse("MyObjectBuilder_BlueprintDefinition/ConstructionComponent"), constructAmount - ConstructionCount); } if (SteelPlateCount < steelAmount) { Assembler.AddQueueItem(MyDefinitionId.Parse("MyObjectBuilder_BlueprintDefinition/SteelPlate"), steelAmount - SteelPlateCount); } if (MotorCount < motorAmount) { Assembler.AddQueueItem(MyDefinitionId.Parse("MyObjectBuilder_BlueprintDefinition/MotorComponent"), motorAmount - MotorCount); } if (Assembler.GetInventory(1).IsItemAt(0)) { Assembler.GetInventory(1).TransferItemTo(CompContainer.GetInventory(0), Assembler.GetInventory(1).GetItemAt(0).Value); } }
private void OrderItemType(Dictionary <MyItemType, MyFixedPoint> resourcesOnFactory, MyItemType item, int maxCount) { int orderCount = maxCount; if (resourcesOnFactory.ContainsKey(item)) { orderCount = maxCount - resourcesOnFactory[item].ToIntSafe(); } if (orderCount > 0) { var blueprintDef = GetDefId(GetBlueprintName(item)); Echo("BlueprintDef = " + blueprintDef.SubtypeId.ToString()); var canUse = m_MainAssembler.CanUseBlueprint(blueprintDef); var queueEmpty = true; foreach (var assembler in m_Assemblers) { if (!assembler.IsQueueEmpty) { queueEmpty = false; } } Echo(canUse.ToString()); if (canUse && queueEmpty) { m_LastOrder = string.Format("{0}: {1}/{2} at{3}", blueprintDef.SubtypeId.ToString(), orderCount, maxCount, DateTime.Now); Echo("AddToQueue " + blueprintDef.SubtypeId.ToString()); m_MainAssembler.AddQueueItem(blueprintDef, (decimal)(m_Assemblers.Count * 10)); } } }
private void BuildComponent(string componentName, double buildAmount, double batchAmount) { //Echo($"Build {buildAmount} {componentName}"); componentName = CorrectComponent(componentName); MyDefinitionId blueprint = MyDefinitionId.Parse($"MyObjectBuilder_BlueprintDefinition/{componentName}"); //Echo(blueprint.ToString()); List <IMyAssembler> assemblerList = new List <IMyAssembler>(); GridTerminalSystem.GetBlocksOfType <IMyAssembler>(assemblerList, assembler => assembler.CubeGrid == Me.CubeGrid); double thisOrder; while (buildAmount > 0) { thisOrder = Math.Min(buildAmount, batchAmount); buildAmount -= thisOrder; string assemblerName = ""; double minAmount = 1000000, thisAmount; foreach (IMyAssembler assembler in assemblerList) { thisAmount = 0; Echo($"{assembler.DisplayNameText}\n{assembler.GetType()}\n"); if (assembler.DisplayNameText == "[Base] Survival kit") { Echo("Survival Kits are gay"); } else { List <MyProductionItem> productionList = new List <MyProductionItem>(); assembler.GetQueue(productionList); foreach (MyProductionItem item in productionList) { thisAmount += (double)item.Amount; } //Echo($"ThisAmount={thisAmount}"); if (thisAmount < minAmount) { minAmount = thisAmount; assemblerName = assembler.DisplayNameText; //Echo($"Min {assemblerName}={minAmount}"); } } } IMyAssembler minAssembler = (IMyAssembler)GridTerminalSystem.GetBlockWithName(assemblerName); bool canUseBlueprint = minAssembler.CanUseBlueprint(blueprint); //Echo($"Does it assemble? {canUseBlueprint}"); if (canUseBlueprint) { minAssembler.AddQueueItem(blueprint, thisOrder); } } }
void ProcessProjection(IMyAssembler assembler, IMyProjector projector, bool allBlocks) { var queueDictionary = GetBlocksForQueue(projector, allBlocks); if (allBlocks == false) { var existingParts = GetExistingParts(assembler); foreach (var component in existingParts.Keys.Where(component => queueDictionary.ContainsKey(component))) { if (existingParts[component] >= queueDictionary[component]) { queueDictionary[component] = 0; } else { queueDictionary[component] -= existingParts[component]; } } } foreach (var component in queueDictionary.Keys.Where(component => blueprintDictionary.ContainsKey(component))) { var blueprint = new MyDefinitionId(); var definition = $"MyObjectBuilder_BlueprintDefinition/{blueprintDictionary[component]}"; if (MyDefinitionId.TryParse(definition, out blueprint) && assembler.CanUseBlueprint(blueprint)) { assembler.AddQueueItem(blueprint, (MyFixedPoint)queueDictionary[component]); } } }
private void QueueAssemblyLine(InventoryComponent targetInventory, InventoryComponent actualInventory, IEnumerable <IMyAssembler> assemblers) { if (assemblers == null || assemblers.Count() == 0) { return; } IMyAssembler assembler = FindMasterAssembler(assemblers); if (assembler == null) { assembler = FindRandomAssembler(assemblers); } IEnumerable <ComponentType> componentTypes = actualInventory.GetKeys(); foreach (ComponentType componentType in componentTypes) { var difference = targetInventory.GetValue(componentType) - actualInventory.GetValue(componentType); if (difference > 0) { assembler.AddQueueItem(MyDefinitionId.Parse("MyObjectBuilder_BlueprintDefinition/" + componentType.ToString()), difference); } } }
public void AddToAssemblerQueue(string itemName, int amount) { MyDefinitionId blueprint = GetMyDefinitionIdByName(itemName); Assembler.AddQueueItem(blueprint, (double)amount); }
public void Main(string argument) { string projectorName = "Projector", assemblerName = "Assembler"; int staggeringFactor = 10; // set 1 to not stagger bool fewFirst = true; lightArmor = true; bool onlyRemaining = false; if (!String.IsNullOrEmpty(argument)) { try { var spl = argument.Split(';'); if (spl[0] != "") { projectorName = spl[0]; } if (spl.Length > 1) { if (spl[1] != "") { assemblerName = spl[1]; } } if (spl.Length > 2) { if (spl[2] != "") { lightArmor = bool.Parse(spl[2]); } } if (spl.Length > 3) { if (spl[3] != "") { staggeringFactor = int.Parse(spl[3]); } } if (spl.Length > 4) { if (spl[4] != "") { fewFirst = bool.Parse(spl[4]); } } if (spl.Length > 5) { if (spl[5] != "") { onlyRemaining = bool.Parse(spl[5]); } } } catch (Exception) { Echo("Wrong argument(s). Format: [ProjectorName];[AssemblerName];[lightArmor];[staggeringFactor];[fewFirst];[onlyRemaining]. See Readme for more info."); return; } } if (staggeringFactor <= 0) { Echo("Invalid staggeringFactor: must be an integer greater than 0."); return; } IMyProjector projector = GridTerminalSystem.GetBlockWithName(projectorName) as IMyProjector; if (projector == null) { Echo("The specified projector name is not valid. No projector found."); return; } var compList = GetTotalComponents(projector); if (onlyRemaining) { compList = SubtractPresentComponents(compList); } string output = ""; foreach (var component in compList) { output += component.Key.Replace("MyObjectBuilder_BlueprintDefinition/", "") + " " + component.Value.ToString() + "\n"; } Me.CustomData = output; IMyAssembler assembler = GridTerminalSystem.GetBlockWithName(assemblerName) as IMyAssembler; if (assembler == null) { Echo("The specified assembler name is not valid. No assembler found."); return; } //var compList = totalComponents.ToList(); if (fewFirst) { compList.Sort((pair1, pair2) => pair1.Value.CompareTo(pair2.Value)); } for (int i = 0; i < staggeringFactor; i++) { foreach (var x in compList) { if (x.Key.Contains("ZoneChip")) { continue; // Zone Chips cannot be assembled } int amount = x.Value / staggeringFactor; // if the total amount of the component is not divisible by staggeringFactor, we add the remainder to the first batch // so that if we have < staggeringFactor (or few, in general) units we get them right at the start if (i == 0) { amount += x.Value % staggeringFactor; } if (amount > 0) { assembler.AddQueueItem(MyDefinitionId.Parse(x.Key), (decimal)amount); } } } }
public void Main(string argument, UpdateType updateSource) { // Gets assembler assembler = GridTerminalSystem.GetBlockWithName(assemblerName) as IMyAssembler; // Gets every block in same grid with an inventory and stores it in blocksWithInventory blocksWithInventory = new List <IMyTerminalBlock>(); GridTerminalSystem.GetBlocksOfType(blocksWithInventory, x => x.HasInventory && x.IsSameConstructAs(Me)); // Only runs every 10 seconds (60 ticks per second, 600 per ten, called every 100, loops for six then runs) if (counter != 5) { counter++; return; } counter = 0; // For each required component foreach (string component in minComponents.Keys) { // If none specified if (minComponents[component] == 0) { continue; } int amountInv = 0; int amountQueued = 0; // For each block in list of blocks foreach (IMyTerminalBlock blockWithInventory in blocksWithInventory) { // If blockWithInventory is an assembler if (blockWithInventory is IMyAssembler) { // Get queue of assembler List <MyProductionItem> assemblerQueue = new List <MyProductionItem>(); assembler.GetQueue(assemblerQueue); // For each item in queue foreach (MyProductionItem productionItem in assemblerQueue) { // If item is component (tacking on "Component" keyword to some components because Space Engineers is nothing if not inconsistent) if (productionItem.BlueprintId == MyDefinitionId.Parse("MyObjectBuilder_BlueprintDefinition/" + component + (assemblerComponents.Contains(component) ? "Component" : ""))) { // Add amount of component amountQueued += (int)productionItem.Amount; } } } // Add amount of component in inventory amountInv += (int)blockWithInventory.GetInventory(0).GetItemAmount(new MyItemType("MyObjectBuilder_Component", component)); } Echo(component + ": " + amountInv + " + " + amountQueued + " / " + minComponents[component]); // If less of component than minimum if (amountInv + amountQueued < minComponents[component]) { // Queue enough of item to meet minimum assembler.AddQueueItem( MyDefinitionId.Parse("MyObjectBuilder_BlueprintDefinition/" + component), (double)minComponents[component] - (amountInv + amountQueued) ); } } }
public void AddToProduction(string componentType, int amount) { MyDefinitionId definition = MyDefinitionId.Parse($"MyObjectBuilder_BlueprintDefinition/{ComponentUtils.GetComponentSubType(componentType)}"); assembler.AddQueueItem(definition, (double)amount); }
public void Main(string argument, UpdateType updateSource) { //Normal update if (updateSource == UpdateType.Update100) { //Update on screen if main assembler is in production ClearScreen(); //Move all item out of main assembler var output = new List <MyInventoryItem>(); MainAssembler.OutputInventory.GetItems(output); foreach (var item in output) { if (AnyCargo != null) { MainAssembler.OutputInventory.TransferItemTo(AnyCargo.GetInventory(), item); } } //Max characters: 53 Dictionary <string, int> itemsAndAmount = new Dictionary <string, int>(); Dictionary <string, int> itemsAndQueue = new Dictionary <string, int>(); if (RequestedAndAmountCustom == null) { RequestedAndAmountCustom = new Dictionary <string, int>(); } //Check sorter for requests var requests = new List <MyInventoryItemFilter>(); SorterOfRequested.GetFilterList(requests); Report($"Request: {requests.Count} | {(allDone ? "(All done)" : "(Working)")}"); foreach (var item in requests) { itemsAndAmount.Add(item.ItemType.SubtypeId, 0); itemsAndQueue.Add(item.ItemType.SubtypeId, 0); } //Check main assembly for queues var queue = new List <MyProductionItem>(); MainAssembler.GetQueue(queue); Report($"Queue: {queue.Count} | {(MainAssembler.IsProducing ? "ACTIVE" : "INACTIVE")}"); //Check if assembler is in disassembling moded if (MainAssembler.Mode == MyAssemblerMode.Disassembly) { MainAssembler.Mode = MyAssemblerMode.Assembly; } foreach (var item in queue) { if (!itemsAndQueue.ContainsKey(item.BlueprintId.SubtypeName)) { itemsAndQueue.Add(item.BlueprintId.SubtypeName, item.Amount.ToIntSafe()); } else { itemsAndQueue[item.BlueprintId.SubtypeName] += item.Amount.ToIntSafe(); } } //Checking items List <IMyTerminalBlock> allBlocks = new List <IMyTerminalBlock>(); GridTerminalSystem.GetBlocks(allBlocks); foreach (var block in allBlocks) { if (block == SorterOfRequested) { continue; } else if (block == Me) { continue; } if (AnyCargo == null) { if (block is IMyCargoContainer && !block.GetInventory().IsFull) { AnyCargo = block as IMyCargoContainer; } } else { if (AnyCargo.GetInventory().IsFull) { AnyCargo = null; } } if (block.InventoryCount > 0) { for (int i = 0; i < block.InventoryCount; i++) { var allItems = block.GetInventory(i); if (allItems != null && allItems.ItemCount > 0) { var actualAllItems = new List <MyInventoryItem>(); allItems.GetItems(actualAllItems); foreach (var item2 in actualAllItems) { if (itemsAndAmount.ContainsKey(item2.Type.SubtypeId)) { itemsAndAmount[item2.Type.SubtypeId] += item2.Amount.ToIntSafe(); } else { itemsAndAmount.Add(item2.Type.SubtypeId, item2.Amount.ToIntSafe()); } } } } } } Report($"AM=Amount | AS=Assembling | REQ=Required"); Report($"{"Name",-22} | {"AM",-6} | {"AS",-6} | {"REQ",-6} |\r\n" + $"-----------------------------------------------------"); foreach (var pair in itemsAndAmount) { if (!itemsAndQueue.ContainsKey(pair.Key)) { continue; } if (RequestedAndAmountCustom.ContainsKey(pair.Key)) { Report($"{pair.Key,-22} | {pair.Value,-6} | {itemsAndQueue[pair.Key],-6} | {RequestedAndAmountCustom[pair.Key],-6} |\r\n"); } else { Report($"{pair.Key,-22} | {pair.Value,-6} | {itemsAndQueue[pair.Key],-6} | {MinimumAmount,-6} |\r\n"); } if ((RequestedAndAmountCustom.ContainsKey(pair.Key) && pair.Value < RequestedAndAmountCustom[pair.Key]) || (!RequestedAndAmountCustom.ContainsKey(pair.Key) && pair.Value < MinimumAmount)) { allDone = false; } } if (!MainAssembler.IsProducing && MainAssembler.IsQueueEmpty && !allDone) { Runtime.UpdateFrequency = UpdateFrequency.None; Main("CheckAndRequest", UpdateType.Script); } ReportAllItemsInfo(); } else if (argument == "CheckAndRequest" && updateSource == UpdateType.Script) { ClearScreen(); Report("Begin checking items"); //Get sorter //Find item list on Conveyer sorter filter list RequestedItems = new List <MyInventoryItemFilter>(); SorterOfRequested.GetFilterList(RequestedItems); Report("Gathered list of items from sorter of request"); Report($"Found {RequestedItems.Count} items"); RequestedAndAmount = new Dictionary <string, int>(); RequestedAndAmountCustom = new Dictionary <string, int>(); //Read all custom amounts if (!string.IsNullOrEmpty(Me.CustomData)) { var linesOfCustom = Me.CustomData.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); foreach (var line in linesOfCustom) { var info = line.Split('='); RequestedAndAmountCustom.Add(info[0], int.Parse(info[1])); } } //Load requested amount from custom data or write into it if empty string input = ""; foreach (var item in RequestedItems) { RequestedAndAmount.Add(item.ItemType.SubtypeId, 0); Report($"Add {item.ItemType.SubtypeId} into requested list"); if (RequestedAndAmountCustom.ContainsKey(item.ItemType.SubtypeId)) { input += $"{item.ItemType.SubtypeId}={RequestedAndAmountCustom[item.ItemType.SubtypeId]}\r\n"; } else { input += $"{item.ItemType.SubtypeId}={MinimumAmount}\r\n"; RequestedAndAmountCustom.Add(item.ItemType.SubtypeId, MinimumAmount); } } Me.CustomData = input; //Check all inventories Report("Began checking inventories"); List <IMyTerminalBlock> allBlocks = new List <IMyTerminalBlock>(); GridTerminalSystem.GetBlocks(allBlocks); Report($"Began checking {allBlocks.Count} blocks"); foreach (var item in allBlocks) { Report($"Checking {item.CustomName}"); if (item == SorterOfRequested) { continue; } else if (item == Me) { continue; } if (item.InventoryCount > 0) { for (int i = 0; i < item.InventoryCount; i++) { Report($"Found inventory on {item.CustomName} {i + 1}/{item.InventoryCount}"); var allItems = item.GetInventory(i); Report($"{item.CustomName}'s inventory {(allItems == null ? "is null" : "has an item")} {allItems.ItemCount}"); if (allItems != null && allItems.ItemCount > 0) { var actualAllItems = new List <MyInventoryItem>(); allItems.GetItems(actualAllItems); Report($"Found {actualAllItems.Count} item on inventory"); foreach (var req in RequestedItems) { foreach (var actual in actualAllItems) { Report($"{req.ItemType.SubtypeId} vs {actual.Type.SubtypeId}"); if (req.ItemType.SubtypeId == actual.Type.SubtypeId) { Report($"Add {req.ItemType.SubtypeId} into list"); Report($"Add {actual.Amount.ToIntSafe()} into dictionary"); if (!RequestedAndAmount.ContainsKey(req.ItemType.SubtypeId)) { RequestedAndAmount.Add(req.ItemType.SubtypeId, 0); } RequestedAndAmount[req.ItemType.SubtypeId] += actual.Amount.ToIntSafe(); } } } } } } } ClearScreen(); Report("Began requesting assembler"); var queue = new List <MyProductionItem>(); MainAssembler.GetQueue(queue); //If it has less than MinimumAmount then send request to assembly //TODO: Take all slaves assembly into account bool unfinished = false; foreach (var pair in RequestedAndAmount) { //Check if it's already in queue or not foreach (var item in queue) { if (item.BlueprintId.SubtypeName == pair.Key) { continue; } } if (RequestedAndAmountCustom.ContainsKey(pair.Key)) { Report($"{pair.Key}: R={RequestedAndAmountCustom[pair.Key]} Now={pair.Value}"); if (pair.Value <= RequestedAndAmountCustom[pair.Key]) { Report($"Parsing item id: {pair.Key}"); MyDefinitionId itemID = MyDefinitionId.Parse($"MyObjectBuilder_BlueprintDefinition/{pair.Key}"); Report($"Item ID parsing: {(itemID == null ? "ItemID parse failed" : "ItemID parse complete")}"); Report($"Requested item \"{itemID.SubtypeName}\" still missing about {RequestedAndAmountCustom[pair.Key] - pair.Value}"); try { MainAssembler.AddQueueItem(itemID, Convert.ToDecimal(RequestedAndAmountCustom[itemID.SubtypeName] - pair.Value)); } catch (Exception e) { Report($"ERROR: {e.Message}"); } unfinished = true; } } else { Report($"{pair.Key}: R={MinimumAmount} Now={pair.Value}"); if (pair.Value <= MinimumAmount) { Report($"Parsing item id: {pair.Key}"); MyDefinitionId itemID = MyDefinitionId.Parse($"MyObjectBuilder_BlueprintDefinition/{pair.Key}"); Report($"Item ID parsing: {(itemID == null ? "ItemID parse failed" : "ItemID parse complete")}"); Report($"Requested item \"{itemID.SubtypeName}\" still missing about {(MinimumAmount - pair.Value)}"); MainAssembler.AddQueueItem(itemID, Convert.ToDecimal(MinimumAmount - pair.Value)); unfinished = true; } } } if (unfinished) { //Set back updater Runtime.UpdateFrequency = UpdateFrequency.Update100; } else { allDone = true; Runtime.UpdateFrequency = UpdateFrequency.Update100; } } }
public void Main(string arguments, UpdateType updateSource) { if (arguments == "i") { GridProgram = new GridProgramRef(GridTerminalSystem, null, Echo, Me); GridProgram.Utils = new UtilsClass(GridProgram); BlueprintDefinitions.Initialize(GridProgram); Echo("Initialized blueprint definitions."); Echo($"{BlueprintDefinitions.blueprints.Count} definitions loaded."); projectionController = new ProjectionController(GridProgram, "Projector", ProjectorState.Unpowered); projectionController.SetProjectorState(ProjectorState.Powered); if (!projectionController.Projector.IsProjecting) { Echo("Projector wasn't projecting."); return; } Dictionary <string, int> components = projectionController.GetRequiredComponents(); foreach (KeyValuePair <string, int> kvp in components) { Echo($"{kvp.Key}: {kvp.Value}"); } } if (arguments == "a") { List <IMyAssembler> assemblers = new List <IMyAssembler>(); GridTerminalSystem.GetBlocksOfType(assemblers); IMyAssembler assembler = assemblers[0]; IMyTextPanel textpanel = GridTerminalSystem.GetBlockWithName("TXTPNL") as IMyTextPanel; MyDefinitionId id = MyDefinitionId.Parse("MyObjectBuilder_BlueprintDefinition/BulletproofGlass"); assembler.AddQueueItem(id, 1.0); return; } if (arguments == "p") { IMyTextPanel textpanel = GridTerminalSystem.GetBlockWithName("TXTPNL") as IMyTextPanel; textpanel.WriteText(projectionController.Projector.DetailedInfo); return; } if (arguments == "m") { return; } switch (internal_state) { case 0: // config try { GridProgram = new GridProgramRef(GridTerminalSystem, null, Echo, Me); GridProgram.Utils = new UtilsClass(GridProgram); platformMotor = new PlatformMotor(GridProgram, "Pistons", new MotorConfig(0.05f, 10f, 0.05f, MotorExtendType.POSITIVE)); platformTracker = new PlatformTracker(new TrackerConfig(GridProgram, "Camera X1", "Camera X2", "Camera Y1", "Camera Y2", 370), GridProgram); welderController = new WelderController(GridProgram, new WelderConfig("Welders", WelderState.Unpowered)); cargoController = new CargoController(GridProgram, true); projectionController = new ProjectionController(GridProgram, "Projector", ProjectorState.Unpowered); platformTracker.EnableRaycast(); internal_state = 1; } catch (Exception ex) { Echo($"Execution halted, safeguard violation raised in {ex.TargetSite}: {ex.Message}"); } break; case 1: try { platformMotor.SetMotorState(MotorState.Extend); internal_state = 2; } catch (Exception ex) { Echo($"Execution halted, safeguard violation raised in {ex.TargetSite}: {ex.Message}"); } break; case 2: try { TrackedPlatform tp = platformTracker.Track(); platformTracker.IsPlatformSafe(tp); } catch (Exception ex) { Echo($"Execution halted, safeguard violation raised in {ex.TargetSite}: {ex.Message}"); } break; } }
public void DoSort() { // Echo("dbg: DoSort()"); neededItemCounts.Clear(); // pull into each container foreach (var dest in sortedContainers) { //Echo($"dbg: sorting {dest.CustomName}"); var inv = dest.GetInventory(); if (inv == null) { Echo($"Warning: Destination '{dest.CustomName}' doesn't have an inventory."); continue; } // figure out what items we should be storing (by parsing the name) var nameWords = dest.CustomName.Split().Skip(1 /*"store"*/); //Echo($"dbg: nameWords: {String.Join(" ", nameWords)}"); itemNames.Clear(); itemDesiredCount.Clear(); foreach (var word in nameWords) { if (word.Length == 0) { continue; } var parts = word.Split('-'); var name = parts[0]; var count = 0; if (parts.Length == 2) { int.TryParse(parts[1], out count); } //Echo($"dbg: item name {name}-{count}"); itemNames.Add(name); itemDesiredCount.Add(count); } if (itemNames.Count() == 0) { continue; } // for each item... for (var i = 0; i < itemNames.Count(); i++) { var name = itemNames[i]; var desiredCount = itemDesiredCount[i]; var specifiesDesiredCount = desiredCount > 0; // Echo($"dbg: we want {name}-{desiredCount}"); // figure out how many we already have var iType = LookupItemType(name); if (!iType.HasValue) { Echo($"Warning: '{dest.CustomName}' wants invalid item '{name}'. All known names: {String.Join(",", namesToKnownItems.Keys)}"); continue; } var currentCount = inv.GetItemAmount(iType.Value); // Echo($"dbg: we have {currentCount}"); int currentGlobalCount = 0; allItemCounts.TryGetValue(iType.Value, out currentGlobalCount); var producingCount = 0; allAssemblerWork.TryGetValue(iType.Value, out producingCount); var neededCount = desiredCount - currentCount; // TODO: Actually, take all we can get always // if (neededCount <= 0) // continue; if (neededCount > 0) { Echo($"We want {desiredCount} {name} and we have {currentCount} locally and {currentGlobalCount - currentCount} more globally and we are making {producingCount}."); // Echo($"'{dest.CustomName}' wants {(specifiesDesiredCount ? neededCount.ToString() : "inf.")} more {iType.Value.SubtypeId}"); } else /* taking all anyway */ } { // search the grid foreach (var src in sourceContainers) { // for each inventory for (var invIdx = 0; invIdx < src.InventoryCount; invIdx++) { var srcInv = src.GetInventory(invIdx); if (srcInv == null) { continue; } // see how many we have var srcCount = srcInv.GetItemAmount(iType.Value); if (srcCount <= 0) { continue; } // Echo($"dbg: {src.CustomName} has {srcCount}"); // transfer each occurrance tempItems.Clear(); srcInv.GetItems(tempItems, item => item.Type.SubtypeId == iType.Value.SubtypeId); foreach (var invI in tempItems) { var trasnferSuccess = srcInv.TransferItemTo(inv, invI, invI.Amount); if (trasnferSuccess) { Echo($"Transferred {invI.Amount} {name} from '{src.CustomName}'"); neededCount -= invI.Amount; } else { Echo($"dbg: Transferring {invI.Amount} {name} from '{src.CustomName}' to '{dest.CustomName} failed."); break; // TODO: log transfer success / fail ? Probably too noisy. } } } } // update the counts of what we need if (neededCount > 0) { //Echo($"dbg: we didn't get enough {name}; we need {neededCount} more"); int prevNeededCount; if (neededItemCounts.TryGetValue(iType.Value, out prevNeededCount)) { neededItemCounts[iType.Value] += (int)neededCount; } else { neededItemCounts[iType.Value] = (int)neededCount; } } } } // put items we still need into production // UpdateAllAssemblerWork(); // see how many we are already producing if (leadAssembler != null) { foreach (var typeAndCount in neededItemCounts) { var iType = typeAndCount.Key; var wantedCount = typeAndCount.Value; if (wantedCount <= 0) { continue; } // Echo($"dbg: We want {wantedCount} more {iType.SubtypeId}"); // compare to what we are producing currently var producingCount = 0; allAssemblerWork.TryGetValue(iType, out producingCount); var neededCount = wantedCount - producingCount; // Echo($"dbg: We need {neededCount} more {iType.SubtypeId}"); if (neededCount <= 0) { // Echo($"We are already trying to produce {producingCount}."); continue; } else { // Echo($"dbg: We are producing any."); } // enqueue MyDefinitionId?blueprintOpt = FindBlueprint(iType); if (!blueprintOpt.HasValue) { Echo($"Warning: Failed to find definition for {iType.SubtypeId}"); continue; } MyDefinitionId blueprint = blueprintOpt.Value; try { leadAssembler.AddQueueItem(blueprint, (MyFixedPoint)neededCount); if (allAssemblerWork.ContainsKey(iType)) { allAssemblerWork[iType] += neededCount; } else { allAssemblerWork[iType] = neededCount; } Echo($"Enqueued {wantedCount} more {blueprint.SubtypeName}"); } catch (Exception e) { Echo($"Warning: Lead assembler failed to produce {blueprint.TypeId}/{blueprint.SubtypeName}"); } } } }
public void Main(string argument, UpdateType updateSource) { // for each item: // find total in inventory // find total queued // find missing based on limits // prioritize based on %missing // enqueue work unit if total < total desired and < max work units // check setup... bool exit = false; IMyBlockGroup assemblerGroup = GridTerminalSystem.GetBlockGroupWithName(assemblerGroupName); if (assemblerGroup == null) { exit = true; Echo($"Assembler Group {assemblerGroupName} not found."); } IMyBlockGroup containerGroup = GridTerminalSystem.GetBlockGroupWithName(partsContainersGroupName); if (containerGroup == null) { exit = true; Echo($"Container Group {partsContainersGroupName} not found."); } List <IMyAssembler> assemblers = new List <IMyAssembler>(); List <IMyEntity> containers = new List <IMyEntity>(); List <IMyAssembler> primaries = new List <IMyAssembler>(); assemblerGroup.GetBlocksOfType(assemblers); assemblerGroup.GetBlocksOfType(primaries, a => !a.CooperativeMode && a.Enabled && a.Mode == MyAssemblerMode.Assembly); if (primaries.Count == 0) { exit = true; Echo($"No primary assembler found"); } if (exit) { return; } // we at least have an assembler that can queue and a container to count. containerGroup.GetBlocksOfType(containers); // assemblers are also containers so add them in. Use a HashSet for deduping HashSet <IMyEntity> allContainers = new HashSet <IMyEntity>(); allContainers.UnionWith(containers); allContainers.UnionWith(assemblers); // sum it all up! Dictionary <MyDefinitionId, MyFixedPoint> allQueued = SumQueued(assemblers); Dictionary <MyItemType, MyFixedPoint> allStored = SumStored(allContainers); // used for round robin balancing of work int queueStep = 0; // queue up work for every component we want built. foreach (KeyValuePair <MyItemType, MyFixedPoint> kv in AllComponents) { Echo($"Checking queue for {kv.Key.ToString()}"); MyFixedPoint queued; MyFixedPoint stored; allQueued.TryGetValue(ToBlueprintDefinition(kv.Key), out queued); allStored.TryGetValue(kv.Key, out stored); MyFixedPoint total = queued + stored; MyFixedPoint gap = kv.Value - total; Echo($"Found total {total}, queued {queued}, requested {kv.Value}"); while (gap >= workUnit && queued <= workUnit * (maxWorkUnits - 1)) { ++queueStep; MyDefinitionId blueprint = ToBlueprintDefinition(kv.Key); // load balance between all assemblers that can build the blueprint List <IMyAssembler> buildable = primaries.FindAll(a => a.CanUseBlueprint(blueprint)); if (buildable.Count() == 0) { Echo($"Warning no Assembler found for {blueprint.ToString()}"); break; } IMyAssembler assembler = buildable[queueStep % buildable.Count()]; Echo($"Queuing {workUnit} of {kv.Key.ToString()} to {assembler.CustomName} as {blueprint.ToString()}"); assembler.AddQueueItem(ToBlueprintDefinition(kv.Key), workUnit); gap += workUnit; queued += workUnit; } } }