private int GetMissingComponentCount(NaniteConstructionInventory inventoryManager, IMySlimBlock block)
        {
            Dictionary <string, int> missing = new Dictionary <string, int>();

            block.GetMissingComponents(missing);
            if (missing.Count == 0)
            {
                return(0);
            }

            Dictionary <string, int> available = new Dictionary <string, int>();

            inventoryManager.GetAvailableComponents(ref available);
            for (int r = missing.Count - 1; r >= 0; r--)
            {
                var item = missing.ElementAt(r);
                if (available.ContainsKey(item.Key))
                {
                    int amount = Math.Min(item.Value, available[item.Key]);
                    available[item.Key] -= amount;
                    missing[item.Key]   -= amount;
                }
            }

            return(missing.Sum(x => x.Value));
        }
        public override void FindTargets(ref Dictionary <string, int> available)
        {
            ComponentsRequired.Clear();

            if (!IsEnabled())
            {
                return;
            }

            if (TargetList.Count >= GetMaximumTargets())
            {
                if (PotentialTargetList.Count > 0)
                {
                    m_lastInvalidTargetReason = "Maximum targets reached.  Add more upgrades!";
                }

                return;
            }

            NaniteConstructionInventory inventoryManager = m_constructionBlock.InventoryManager;
            Vector3D sourcePosition          = m_constructionBlock.ConstructionBlock.GetPosition();
            Dictionary <string, int> missing = new Dictionary <string, int>();

            using (m_lock.AcquireExclusiveUsing())
            {
                foreach (var item in PotentialTargetList.OrderBy(x => Vector3D.Distance(sourcePosition, EntityHelper.GetBlockPosition((IMySlimBlock)x))))
                {
                    if (m_constructionBlock.IsUserDefinedLimitReached())
                    {
                        m_lastInvalidTargetReason = "User defined maximum nanite limit reached";
                        return;
                    }

                    if (TargetList.Contains(item))
                    {
                        continue;
                    }

                    missing = inventoryManager.GetProjectionComponents((IMySlimBlock)item);
                    bool haveComponents = inventoryManager.CheckComponentsAvailable(ref missing, ref available);
                    if (haveComponents && NaniteConstructionPower.HasRequiredPowerForNewTarget((IMyFunctionalBlock)m_constructionBlock.ConstructionBlock, this))
                    {
                        if (((IMySlimBlock)item).CubeGrid.GetPosition() == Vector3D.Zero)
                        {
                            m_lastInvalidTargetReason = "Target blocks grid is in an invalid position (Vector3D.Zero, this shouldn't happen!)";
                            continue;
                        }

                        var  blockList = NaniteConstructionManager.GetConstructionBlocks((IMyCubeGrid)m_constructionBlock.ConstructionBlock.CubeGrid);
                        bool found     = false;
                        foreach (var block in blockList)
                        {
                            if (block.GetTarget <NaniteProjectionTargets>().TargetList.Contains(item))
                            {
                                found = true;
                                break;
                            }
                        }

                        if (found)
                        {
                            m_lastInvalidTargetReason = "Another factory has this block as a target";
                            continue;
                        }

                        TargetList.Add(item);
                        IMySlimBlock slimBlock = (IMySlimBlock)item;
                        var          def       = slimBlock.BlockDefinition as MyCubeBlockDefinition;
                        Logging.Instance.WriteLine(string.Format("ADDING Projection Target: conid={0} subtypeid={1} entityID={2} position={3}", m_constructionBlock.ConstructionBlock.EntityId, def.Id.SubtypeId, slimBlock.FatBlock != null ? slimBlock.FatBlock.EntityId : 0, slimBlock.Position));
                        if (TargetList.Count >= GetMaximumTargets())
                        {
                            break;
                        }
                    }
                    else if (!haveComponents)
                    {
                        m_lastInvalidTargetReason = "Missing components to start projected block";
                    }
                    else if (!NaniteConstructionPower.HasRequiredPowerForNewTarget((IMyFunctionalBlock)m_constructionBlock.ConstructionBlock, this))
                    {
                        m_lastInvalidTargetReason = "Insufficient power for another target.";
                    }
                }
            }
        }
Example #3
0
        public override void FindTargets(ref Dictionary <string, int> available, List <NaniteConstructionBlock> blockList)
        {
            MyAPIGateway.Utilities.InvokeOnGameThread(() =>
            {
                m_lastInvalidTargetReason = "";
                ComponentsRequired.Clear();
            });

            var maxTargets = GetMaximumTargets();

            if (TargetList.Count >= maxTargets)
            {
                if (PotentialTargetList.Count > 0)
                {
                    InvalidTargetReason("Maximum targets reached. Add more upgrades!");
                }

                return;
            }

            NaniteConstructionInventory inventoryManager = m_constructionBlock.InventoryManager;
            Vector3D sourcePosition          = m_constructionBlock.ConstructionBlock.GetPosition();
            Dictionary <string, int> missing = new Dictionary <string, int>();
            string LastInvalidTargetReason   = "";

            int TargetListCount = TargetList.Count;

            foreach (var item in PotentialTargetList.OrderBy(x => Vector3D.Distance(sourcePosition, EntityHelper.GetBlockPosition((IMySlimBlock)x))).ToList())
            {
                if (item == null || TargetList.Contains(item))
                {
                    continue;
                }

                missing = inventoryManager.GetProjectionComponents((IMySlimBlock)item);
                bool haveComponents = inventoryManager.CheckComponentsAvailable(ref missing, ref available);
                if ((MyAPIGateway.Session.CreativeMode || haveComponents) && m_constructionBlock.HasRequiredPowerForNewTarget(this) &&
                    ((IMySlimBlock)item).CubeGrid.GetPosition() != Vector3D.Zero)
                {
                    bool found = false;
                    foreach (var block in blockList.ToList())
                    {
                        if (block != null && block.GetTarget <NaniteProjectionTargets>().TargetList.Contains(item))
                        {
                            found = true;
                            LastInvalidTargetReason = "Another factory has this block as a target";
                            break;
                        }
                    }

                    if (found)
                    {
                        continue;
                    }

                    AddTarget(item);

                    IMySlimBlock slimBlock = (IMySlimBlock)item;
                    var          def       = slimBlock.BlockDefinition as MyCubeBlockDefinition;
                    Logging.Instance.WriteLine(string.Format("[Projection] Adding Projection Target: conid={0} subtypeid={1} entityID={2} position={3}",
                                                             m_constructionBlock.ConstructionBlock.EntityId, def.Id.SubtypeId, slimBlock.FatBlock != null ? slimBlock.FatBlock.EntityId : 0, slimBlock.Position), 1);

                    if (++TargetListCount >= maxTargets)
                    {
                        break;
                    }
                }
                else if (!haveComponents)
                {
                    LastInvalidTargetReason = "Missing components to start projected block";
                }

                else if (!m_constructionBlock.HasRequiredPowerForNewTarget(this))
                {
                    LastInvalidTargetReason = "Insufficient power for another target.";
                    break;
                }
            }
            if (LastInvalidTargetReason != "")
            {
                InvalidTargetReason(LastInvalidTargetReason);
            }
        }
        public override void FindTargets(ref Dictionary <string, int> available)
        {
            if (!IsEnabled())
            {
                return;
            }

            ComponentsRequired.Clear();
            if (m_targetList.Count >= GetMaximumTargets())
            {
                if (PotentialTargetList.Count > 0)
                {
                    m_lastInvalidTargetReason = "Maximum targets reached.  Add more upgrades!";
                }

                return;
            }

            NaniteConstructionInventory inventoryManager = m_constructionBlock.InventoryManager;
            Vector3D sourcePosition = m_constructionBlock.ConstructionBlock.GetPosition();

            Dictionary <string, int> missing = new Dictionary <string, int>();

            using (Lock.AcquireExclusiveUsing())
            {
                var potentialList = m_potentialTargetList.OrderByDescending(x => GetMissingComponentCount(inventoryManager, (IMySlimBlock)x)).ToList();
                for (int r = potentialList.Count - 1; r >= 0; r--)
                {
                    if (m_constructionBlock.IsUserDefinedLimitReached())
                    {
                        m_lastInvalidTargetReason = "User defined maximum nanite limit reached";
                        return;
                    }

                    var item = (IMySlimBlock)potentialList[r];
                    if (TargetList.Contains(item))
                    {
                        continue;
                    }

                    missing.Clear();
                    item.GetMissingComponents(missing);
                    bool foundMissingComponents = true;

                    if (MyAPIGateway.Session.CreativeMode)
                    {
                        foundMissingComponents = true;
                    }
                    else if (missing.Count > 0)
                    {
                        foundMissingComponents = inventoryManager.CheckComponentsAvailable(ref missing, ref available);
                    }

                    if (foundMissingComponents && NaniteConstructionPower.HasRequiredPowerForNewTarget((IMyFunctionalBlock)m_constructionBlock.ConstructionBlock, this))
                    {
                        // Check to see if another block targetting this for construction
                        var  blockList = NaniteConstructionManager.GetConstructionBlocks((IMyCubeGrid)m_constructionBlock.ConstructionBlock.CubeGrid);
                        bool found     = false;
                        foreach (var block in blockList)
                        {
                            if (block.Targets.First(y => y is NaniteConstructionTargets).TargetList.Contains(item as IMySlimBlock))
                            {
                                found = true;
                                break;
                            }
                        }

                        if (found)
                        {
                            m_lastInvalidTargetReason = "Another factory has this block as a target";
                            continue;
                        }

                        m_potentialTargetList.RemoveAt(r);
                        m_targetList.Add(item);
                        var def = item.BlockDefinition as MyCubeBlockDefinition;
                        Logging.Instance.WriteLine(string.Format("ADDING Construction/Repair Target: conid={0} subtype={1} entityID={2} position={3}", m_constructionBlock.ConstructionBlock.EntityId, def.Id.SubtypeId, item.FatBlock != null ? item.FatBlock.EntityId : 0, item.Position));
                        if (m_targetList.Count >= GetMaximumTargets())
                        {
                            break;
                        }
                    }
                    else if (!foundMissingComponents)
                    {
                        foreach (var component in missing)
                        {
                            if (!ComponentsRequired.ContainsKey(component.Key))
                            {
                                ComponentsRequired.Add(component.Key, component.Value);
                            }
                            else
                            {
                                ComponentsRequired[component.Key] += component.Value;
                            }
                        }

                        m_lastInvalidTargetReason = "Missing components";
                    }
                    else if (!NaniteConstructionPower.HasRequiredPowerForNewTarget((IMyFunctionalBlock)m_constructionBlock.ConstructionBlock, this))
                    {
                        m_lastInvalidTargetReason = "Insufficient power for another target.";
                    }
                }
            }
        }