public override void CheckBeacons()
        {
            m_remoteTargets.Clear();

            // Find beacons in range
            foreach (var beaconBlock in (NaniteConstructionManager.BeaconList.ToList()).Where(x => (x.Value is NaniteBeaconConstruct || x.Value is NaniteBeaconProjection)))
            {
                var item = beaconBlock.Value.BeaconBlock;

                if (item == null || !item.Enabled || !item.IsFunctional ||
                    !MyRelationsBetweenPlayerAndBlockExtensions.IsFriendly(item.GetUserRelationToOwner(m_constructionBlock.ConstructionBlock.OwnerId)) ||
                    !IsInRange(item.GetPosition(), m_maxDistance))
                {
                    continue;
                }

                GetBeaconBlocks((IMyCubeGrid)item.CubeGrid);
                GetBeaconBlocksRetryCounter = 0;

                foreach (var block in beaconBlocks)
                {
                    m_constructionBlock.ScanBlocksCache.Add(new BlockTarget(block, true));
                }
            }
        }
        private bool AddPotentialBlock(IMySlimBlock block, bool remote = false, NaniteAreaBeacon beacon = null)
        {
            if (PotentialTargetList.Contains(block))
            {
                return(false);
            }

            if (!remote && block.FatBlock != null && block.FatBlock is IMyTerminalBlock && block.FatBlock.OwnerId != 0 &&
                !MyRelationsBetweenPlayerAndBlockExtensions.IsFriendly(block.FatBlock.GetUserRelationToOwner(m_constructionBlock.ConstructionBlock.OwnerId)))
            {
                return(false);
            }

            if (!block.IsFullIntegrity || block.HasDeformation)
            {
                if (beacon != null)
                {
                    if (!m_areaTargetBlocks.ContainsKey(block))
                    {
                        m_areaTargetBlocks.Add(block, beacon);
                    }
                    else
                    {
                        m_areaTargetBlocks[block] = beacon;
                    }
                }

                PotentialTargetList.Add(block);
                return(true);
            }

            return(false);
        }
Exemplo n.º 3
0
        internal bool IsAreaBeaconValid(IMyCubeBlock cubeBlock)
        {
            if (cubeBlock == null || !((IMyFunctionalBlock)cubeBlock).Enabled || !((IMyFunctionalBlock)cubeBlock).IsFunctional ||
                !MyRelationsBetweenPlayerAndBlockExtensions.IsFriendly(cubeBlock.GetUserRelationToOwner(m_constructionBlock.ConstructionBlock.OwnerId)))
            {
                return(false);
            }

            float range = NaniteConstructionManager.Settings != null ? NaniteConstructionManager.Settings.AreaBeaconMaxDistanceFromNaniteFacility : 300f;

            foreach (var factory in m_constructionBlock.FactoryGroup)
            {
                if (IsEnabled(factory))
                {
                    if (Vector3D.Distance(cubeBlock.GetPosition(), factory.ConstructionBlock.GetPosition()) < range)
                    {
                        return(true);
                    }

                    foreach (var grid in factory.GridGroup.ToList())
                    {
                        if (cubeBlock.CubeGrid == grid)
                        {
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
Exemplo n.º 4
0
        public override void CheckBeacons()
        {
            foreach (var beaconBlock in NaniteConstructionManager.BeaconList.Where(x => x.Value is NaniteBeaconProjection))
            {
                IMyCubeBlock item = (IMyCubeBlock)beaconBlock.Value.BeaconBlock;

                if (item == null || !((IMyFunctionalBlock)item).Enabled || !((IMyFunctionalBlock)item).IsFunctional ||
                    !MyRelationsBetweenPlayerAndBlockExtensions.IsFriendly(item.GetUserRelationToOwner(m_constructionBlock.ConstructionBlock.OwnerId)) || !IsInRange(item.GetPosition(), m_maxDistance))
                {
                    continue;
                }

                List <IMySlimBlock> beaconBlocks = new List <IMySlimBlock>();

                foreach (var grid in MyAPIGateway.GridGroups.GetGroup((IMyCubeGrid)item.CubeGrid, GridLinkTypeEnum.Physical))
                {
                    grid.GetBlocks(beaconBlocks);
                }

                foreach (var block in beaconBlocks)
                {
                    m_constructionBlock.ScanBlocksCache.Add(new BlockTarget(block));
                }
            }
        }
        public static bool IsValidGasConnection(MyCubeBlock factoryBlock, IMySlimBlock gasTankBlock, out IMyGasTank gasTank)
        {
            gasTank = null;

            try
            {
                if (gasTankBlock.FatBlock == null || gasTankBlock.FatBlock as IMyGasTank == null)
                {
                    return(false);
                }

                gasTank = gasTankBlock.FatBlock as IMyGasTank;

                if (gasTank.GetInventory() == null ||
                    !((IMyInventory)factoryBlock.GetInventory()).IsConnectedTo(gasTank.GetInventory()) ||
                    !MyRelationsBetweenPlayerAndBlockExtensions.IsFriendly(factoryBlock.GetUserRelationToOwner(gasTank.OwnerId)))
                {
                    return(false);
                }

                return(true);
            }
            catch (Exception e)
            {
                Logging.Instance.WriteLine($"IsValidGasConnection exception:\n{e}.");
                return(false);
            }
        }
        public static bool IsValidInventoryConnection(object FactoryBlockInv, object TargetBlockInv, out IMyInventory inv)
        {
            inv = null;
            try
            {
                MyInventory FactoryInv = (MyInventory)FactoryBlockInv;
                MyEntity    TargetInv  = null;

                if (TargetBlockInv is IMySlimBlock && ((IMySlimBlock)TargetBlockInv).FatBlock != null)
                {
                    TargetInv = (MyEntity)((IMyEntity)(((IMySlimBlock)TargetBlockInv).FatBlock));
                }

                else if (TargetBlockInv is MyInventory || TargetBlockInv is IMyInventory)
                {
                    TargetInv = ((MyInventory)TargetBlockInv).Owner;
                }

                MyCubeBlock FactoryInvBlock = (MyCubeBlock)FactoryInv.Owner;
                if (TargetInv == null || FactoryInv == null || FactoryInvBlock == null || !TargetInv.HasInventory)
                {
                    return(false);
                }

                MyCubeBlock InvBlock = TargetInv as MyCubeBlock;
                if (InvBlock == null)
                {
                    return(false);
                }

                IMyProductionBlock prodblock = TargetInv as IMyProductionBlock; //assembler
                inv = (prodblock != null && prodblock.OutputInventory != null) ? prodblock.OutputInventory : ((IMyEntity)TargetInv).GetInventory();

                if (inv == null || !InvBlock.IsFunctional || NaniteConstructionManager.NaniteBlocks.ContainsKey(TargetInv.EntityId) ||
                    TargetInv is Sandbox.ModAPI.Ingame.IMyReactor || !inv.IsConnectedTo((IMyInventory)FactoryInv) ||
                    !MyRelationsBetweenPlayerAndBlockExtensions.IsFriendly(FactoryInvBlock.GetUserRelationToOwner(InvBlock.OwnerId)))
                {
                    return(false);
                }

                return(true);
            }
            catch (Exception e)
            {
                Logging.Instance.WriteLine($"IsValidInventoryConnection exception:\n{e}.");
                return(false);
            }
        }
        public override void ParallelUpdate(List <IMyCubeGrid> gridList, List <BlockTarget> gridBlocks)
        {
            try
            {
                DateTime start = DateTime.Now;

                if (!IsEnabled(m_constructionBlock))
                {
                    m_potentialMiningTargets.Clear();
                    return;
                }

                List <string> allowedMats = new List <string>();

                float range = NaniteConstructionManager.Settings != null ? NaniteConstructionManager.Settings.OreDetectorToNaniteFactoryCommunicationDistance : 300f;

                foreach (var oreDetector in NaniteConstructionManager.OreDetectors)
                {
                    if (oreDetector.Value.Block == null || m_constructionBlock.ConstructionBlock == null ||
                        !IsInRange(oreDetector.Value.Block.GetPosition(), range) || oreDetector.Value.DetectorState == NaniteOreDetector.DetectorStates.Disabled)
                    {
                        continue;
                    }

                    if (m_potentialMiningTargets.Count > 0)
                    { // Do not attempt to add more potential targets unless we're done with the current list. This will enhance performance.
                        if (oreDetector.Value.HasFilterUpgrade)
                        {
                            foreach (string mat in oreDetector.Value.OreListSelected)
                            {
                                if (!allowedMats.Contains(mat))
                                {
                                    allowedMats.Add(mat);
                                }
                            }
                        }
                        else if (!allowedMats.Contains("all"))
                        {
                            allowedMats.Add("all");
                        }

                        break;
                    }

                    IMyCubeBlock item = oreDetector.Value.Block;

                    if (!MyRelationsBetweenPlayerAndBlockExtensions.IsFriendly(item.GetUserRelationToOwner(m_constructionBlock.ConstructionBlock.OwnerId)))
                    {
                        continue;
                    }

                    var materialList = oreDetector.Value.DepositGroup.SelectMany((x) => x.Value.Materials.MiningMaterials());
                    if (materialList.Count() == 0 && oreDetector.Value.minedPositions.Count > 0)
                    {
                        Logging.Instance.WriteLine("[Mining] Clearing deposit groups due to no new minable targets.");
                        oreDetector.Value.ClearMinedPositions();
                        oreDetector.Value.DepositGroup.Clear();
                        continue;
                    }

                    foreach (var material in materialList.ToList())
                    {
                        try
                        {
                            int             minimumAmount   = NaniteConstructionManager.Settings != null ? NaniteConstructionManager.Settings.MiningTargetsScannedPerSecond : 100;
                            int             amountToProcess = Math.Min(material.WorldPosition.Count, minimumAmount * 5);
                            List <Vector3D> removeList      = new List <Vector3D>();
                            for (int i = 0; i < amountToProcess; i++)
                            {
                                try
                                { // material iterations
                                    bool     alreadyMined = false;
                                    Vector3D removePos    = Vector3D.Zero;
                                    foreach (var minedPos in m_globalPositionList.ToList())
                                    {
                                        if (material.WorldPosition[i] == minedPos)
                                        {
                                            alreadyMined = true;
                                            removeList.Add(material.WorldPosition[i]);
                                            removePos = minedPos;
                                            Logging.Instance.WriteLine($"[Mining] Found an already mined position {minedPos}", 2);
                                            break;
                                        }
                                    }

                                    if (alreadyMined)
                                    {
                                        MyAPIGateway.Utilities.InvokeOnGameThread(() =>
                                                                                  { m_globalPositionList.Remove(removePos); });
                                        continue;
                                    }

                                    NaniteMiningItem target = new NaniteMiningItem();
                                    target.Position      = material.WorldPosition[i];
                                    target.VoxelPosition = material.VoxelPosition[i];
                                    target.Definition    = material.Definition;
                                    target.VoxelMaterial = material.Material;
                                    target.VoxelId       = material.EntityId;
                                    target.Amount        = 1f;
                                    target.OreDetectorId = ((MyEntity)item).EntityId;

                                    if (voxelEntities.ContainsKey(material.EntityId))
                                    {
                                        PrepareTarget(voxelEntities[material.EntityId], target);
                                        MyAPIGateway.Parallel.Sleep(1);
                                    }
                                    else
                                    {
                                        MyAPIGateway.Utilities.InvokeOnGameThread(() =>
                                                                                  { TryAddNewVoxelEntity(material.EntityId, oreDetector.Value); });

                                        break;
                                    }
                                }
                                catch (ArgumentException e) when(e.ToString().ToLower().Contains("destination array is not long enough"))
                                {
                                    Logging.Instance.WriteLine("NaniteMiningTargets.ParallelUpdate: An ArgumentException "
                                                               + "('Destination array is not long enough') was caught. This is probably harmless and can be ignored.", 1);
                                    Logging.Instance.WriteLine($"{e}", 2);
                                    continue;
                                }
                                catch (Exception e)
                                {
                                    Logging.Instance.WriteLine($"Exception during NaniteMiningTargets.ParallelUpdate material iterations:\n{e}");
                                    continue;
                                }
                            }

                            foreach (Vector3D pos in removeList)
                            {
                                material.WorldPosition.Remove(pos);
                            }
                        }
                        catch (Exception e) when(e.ToString().Contains("ArgumentOutOfRangeException"))
                        { // because Keen thinks we shouldn't have access to this exception^ ...
                            Logging.Instance.WriteLine("Caught an ArgumentOutOfRangeException while processing mining targets. This is probably harmless and can be ignored.");
                        }
                    }

                    if (m_oldMinedPositionsCount == m_minedPositionsCount && m_minedPositionsCount > 0)
                    {
                        if (m_scannertimeout++ > 20)
                        {
                            m_scannertimeout = 0;
                            oreDetector.Value.DepositGroup.Clear(); //we've mined all the scanned stuff. Try a rescan.
                            Logging.Instance.WriteLine("[Mining] Clearing deposit groups due to mining target timeout.", 1);
                            m_minedPositionsCount = 0;
                        }
                    }
                    else
                    {
                        m_oldMinedPositionsCount = m_minedPositionsCount;
                        m_scannertimeout         = 0;
                    }
                }

                if (allowedMats.Count > 0 && !allowedMats.Contains("all"))
                {
                    List <NaniteMiningItem> removeList = new List <NaniteMiningItem>();
                    foreach (var target in m_potentialMiningTargets)
                    {
                        if (allowedMats.Where(x => x.ToLower() == target.Definition.MinedOre.ToLower()).FirstOrDefault() == null)
                        {
                            removeList.Add(target);
                        }

                        MyAPIGateway.Parallel.Sleep(1);
                    }

                    foreach (var target in removeList)
                    {
                        m_potentialMiningTargets.Remove(target);
                    }
                }

                while (finalAddList.Count > 0)
                {
                    NaniteMiningItem miningTarget;
                    if (finalAddList.TryTake(out miningTarget))
                    {
                        m_potentialMiningTargets.Add(miningTarget);
                    }
                }

                MyAPIGateway.Utilities.InvokeOnGameThread(() =>
                                                          { PotentialTargetListCount = m_potentialMiningTargets.Count; });
            }
            catch (ArgumentException e)
            {
                Logging.Instance.WriteLine("NaniteMiningTargets.ParallelUpdate: An ArgumentException "
                                           + "('Destination array is not long enough') was caught. This is probably harmless and can be ignored.");
                Logging.Instance.WriteLine($"{e}", 2);
            }
            catch (Exception e)
            { Logging.Instance.WriteLine($"{e}"); }
        }
        /// <summary>
        /// Damage Handler: Register friendly damage
        /// </summary>
        public void AfterDamageHandlerNoDamageByBuildAndRepairSystem(object target, MyDamageInformation info)
        {
            try
            {
                if (info.Type == MyDamageType.Grind && info.Amount > 0)
                {
                    var targetBlock = target as IMySlimBlock;
                    if (targetBlock != null)
                    {
                        IMyEntity attackerEntity;
                        MyAPIGateway.Entities.TryGetEntityById(info.AttackerId, out attackerEntity);

                        var attackerId = 0L;

                        var shipGrinder = attackerEntity as IMyShipGrinder;
                        if (shipGrinder != null)
                        {
                            attackerId = shipGrinder.OwnerId;
                        }
                        else
                        {
                            var characterGrinder = attackerEntity as IMyEngineerToolBase;
                            if (characterGrinder != null)
                            {
                                attackerId = characterGrinder.OwnerIdentityId;
                            }
                        }
                        if (Mod.Log.ShouldLog(Logging.Level.Info))
                        {
                            Mod.Log.Write(Logging.Level.Info, "BuildAndRepairSystemMod: AfterDamaged1 {0} from {1} attackerId={2} Amount={3}", Logging.BlockName(target), Logging.BlockName(attackerEntity), attackerId, info.Amount);
                        }

                        if (attackerId != 0)
                        {
                            if (Mod.Log.ShouldLog(Logging.Level.Info))
                            {
                                Mod.Log.Write(Logging.Level.Info, "BuildAndRepairSystemMod: Damaged {0} from attackerId={1} Amount={2}", Logging.BlockName(target), attackerId, info.Amount);
                            }
                            foreach (var entry in BuildAndRepairSystems)
                            {
                                var relation = entry.Value.Welder.GetUserRelationToOwner(attackerId);
                                if (Mod.Log.ShouldLog(Logging.Level.Info))
                                {
                                    Mod.Log.Write(Logging.Level.Info, "BuildAndRepairSystemMod: {0} Damaged Check Add FriendlyDamage {1} relation {2}", Logging.BlockName(entry.Value.Welder), Logging.BlockName(targetBlock), relation);
                                }
                                if (MyRelationsBetweenPlayerAndBlockExtensions.IsFriendly(relation))
                                {
                                    //A 'friendly' damage from grinder -> do not repair (for a while)
                                    entry.Value.FriendlyDamage[targetBlock] = MyAPIGateway.Session.ElapsedPlayTime + Settings.FriendlyDamageTimeout;
                                    if (Mod.Log.ShouldLog(Logging.Level.Info))
                                    {
                                        Mod.Log.Write(Logging.Level.Info, "BuildAndRepairSystemMod: {0} Damaged Add FriendlyDamage {0} Timeout {1}", Logging.BlockName(entry.Value.Welder), Logging.BlockName(targetBlock), entry.Value.FriendlyDamage[targetBlock]);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Mod.Log.Error("BuildAndRepairSystemMod: Exception in BeforeDamageHandlerNoDamageByBuildAndRepairSystem: Source={0}, Message={1}", e.Source, e.Message);
            }
        }
        public override void ParallelUpdate(List <IMyCubeGrid> NaniteGridGroup, List <BlockTarget> gridBlocks)
        {
            try
            {
                // Add
                foreach (var beaconBlock in NaniteConstructionManager.BeaconList.Where(x => x.Value is NaniteBeaconDeconstruct))
                {
                    IMyCubeBlock item = (IMyCubeBlock)beaconBlock.Value.BeaconBlock;

                    if (item == null ||
                        item.CubeGrid == null ||
                        !((IMyFunctionalBlock)item).Enabled ||
                        !((IMyFunctionalBlock)item).IsFunctional ||
                        NaniteGridGroup.Contains(item.CubeGrid) ||
                        !MyRelationsBetweenPlayerAndBlockExtensions.IsFriendly(item.GetUserRelationToOwner(m_constructionBlock.ConstructionBlock.OwnerId)) ||
                        m_validBeaconedGrids.FirstOrDefault(x => x.GridsProcessed.Contains(item.CubeGrid)) != null ||
                        !IsInRange(item.GetPosition(), m_maxDistance)
                        )
                    {
                        continue;
                    }

                    NaniteDeconstructionGrid deconstruct = new NaniteDeconstructionGrid(item.CubeGrid);

                    CreateGridStack(NaniteGridGroup, deconstruct, (MyCubeGrid)item.CubeGrid, (MyCubeBlock)item);
                    m_validBeaconedGrids.Add(deconstruct);

                    Logging.Instance.WriteLine($"[Deconstruction] Grid {item.CubeGrid.CustomName} queued for deconstruction", 1);

                    foreach (var slimBlock in deconstruct.RemoveList)
                    {
                        if (slimBlock != null)
                        {
                            PotentialTargetList.Add(slimBlock);
                        }
                    }

                    deconstruct.RemoveList.Clear();
                }

                CheckAreaBeacons(NaniteGridGroup);

                if (PotentialTargetList.Count > 0)
                {
                    foreach (IMySlimBlock item in PotentialTargetList.ToList())
                    {
                        if (item == null || item.CubeGrid == null || item.CubeGrid.Closed || item.IsDestroyed || item.IsFullyDismounted ||
                            (item.FatBlock != null && item.FatBlock.Closed) ||
                            EntityHelper.GetDistanceBetweenBlockAndSlimblock((IMyCubeBlock)m_constructionBlock.ConstructionBlock, item) > m_maxDistance)
                        {
                            PotentialTargetList.Remove(item);
                        }
                    }
                }
                else if (TargetList.Count == 0 && PotentialTargetList.Count == 0)
                {
                    m_validBeaconedGrids.Clear();
                }
            }
            catch (Exception e)
            { Logging.Instance.WriteLine($"Exception in NaniteDeconstructionTargets.ParallelUpdate:\n{e}"); }
        }