Example #1
0
        /// <summary>
        /// Finds a block that is attached to Controller
        /// </summary>
        /// <remarks>
        /// Search is performed immediately.
        /// For a navigating block, always use AttachedGrid.AttachmentKind.None.
        /// </remarks>
        protected bool GetLocalBlock(IMyCubeBlock autopilot, string searchFor, out IMyCubeBlock localBlock, out string message, AttachedGrid.AttachmentKind allowedAttachments = AttachedGrid.AttachmentKind.None)
        {
            searchFor = searchFor.RemoveWhitespace();
            IMyCubeBlock foundBlock     = null;
            int          bestNameLength = int.MaxValue;

            foreach (IMyCubeBlock block in AttachedGrid.AttachedCubeBlocks(autopilot.CubeGrid, allowedAttachments, true))
            {
                if (autopilot.canControlBlock(block))
                {
                    string blockName = block.DisplayNameText.RemoveWhitespace();
                    if (blockName.Length < bestNameLength && blockName.Contains(searchFor, StringComparison.InvariantCultureIgnoreCase))
                    {
                        foundBlock     = block;
                        bestNameLength = blockName.Length;
                        if (searchFor.Length == bestNameLength)
                        {
                            break;
                        }
                    }
                }
            }

            if (foundBlock == null)
            {
                message    = "Not found: " + searchFor;
                localBlock = null;
                return(false);
            }

            message    = null;
            localBlock = foundBlock;
            return(true);
        }
Example #2
0
        protected void SetPropertyOfBlock(Pathfinder pathfinder, string blockName, string propName, T propValue)
        {
            blockName = blockName.LowerRemoveWhitespace();
            propName  = propName.Trim();            // leave spaces in propName

            foreach (IMyCubeBlock fatblock in AttachedGrid.AttachedCubeBlocks(pathfinder.Mover.Block.CubeGrid, AttachedGrid.AttachmentKind.Permanent, true))
            {
                if (!(fatblock is IMyTerminalBlock))
                {
                    continue;
                }

                if (!pathfinder.Mover.Block.Controller.canControlBlock(fatblock))
                {
                    continue;
                }

                if (!fatblock.DisplayNameText.LowerRemoveWhitespace().Contains(blockName))
                {
                    continue;
                }

                IMyTerminalBlock      terminalBlock = fatblock as IMyTerminalBlock;
                ITerminalProperty <T> property      = terminalBlock.GetProperty(propName) as ITerminalProperty <T>;
                if (property != null)
                {
                    property.SetValue(fatblock, propValue);
                }
            }
        }
Example #3
0
		private static void RunActionOnBlock(Pathfinder pathfinder, string blockName, string actionString, List<Ingame.TerminalActionParameter> termParams)
		{
			blockName = blockName.Trim();
			actionString = actionString.Trim(); // leave spaces in actionString

			foreach (IMyCubeBlock fatblock in AttachedGrid.AttachedCubeBlocks(pathfinder.Mover.Block.CubeGrid, AttachedGrid.AttachmentKind.Permanent, true))
			{
				if (!(fatblock is IMyTerminalBlock))
					continue;

				if (!pathfinder.Mover.Block.Controller.canControlBlock(fatblock))
					continue;

				if (!fatblock.DisplayNameText.Contains(blockName, StringComparison.InvariantCultureIgnoreCase))
					continue;

				IMyTerminalBlock terminalBlock = fatblock as IMyTerminalBlock;
				Sandbox.ModAPI.Interfaces.ITerminalAction actionToRun = terminalBlock.GetActionWithName(actionString); // get actionToRun on every iteration so invalid blocks can be ignored
				if (actionToRun != null)
				{
					if (termParams != null)
						actionToRun.Apply(fatblock, termParams);
					else
						actionToRun.Apply(fatblock);
				}
			}
		}
Example #4
0
        /// <summary>
        /// Tests whether a connection is possible between this and another NetworkNode.
        /// </summary>
        /// <param name="other">Node to test connection to this.</param>
        private CommunicationType TestConnection(RelayNode other)
        {
            if (!this.m_ownerId().canConsiderFriendly(other.m_ownerId()))
            {
                if (this.m_comp_radio != null && other.m_comp_radio != null && this.m_comp_radio.CanBroadcastPositionTo(other.m_comp_radio) && other.Storage != null)
                {
                    if (s_sendPositionTo.Add(other.Storage))
                    {
                        Log.TraceLog("Hostile receiver in range: " + other.DebugName + ", new storage: " + other.Storage.PrimaryNode.DebugName);
                    }
                    else
                    {
                        Log.TraceLog("Hostile receiver in range: " + other.DebugName + ", existing storage: " + other.Storage.PrimaryNode.DebugName);
                    }
                }
                return(CommunicationType.None);
            }

            // test block connection
            // skip is working test so that storage doesn't split if ship powers off
            if (this.m_comp_blockAttach != null && other.m_comp_blockAttach != null &&
                AttachedGrid.IsGridAttached(this.m_comp_blockAttach.CubeGrid, other.m_comp_blockAttach.CubeGrid, AttachedGrid.AttachmentKind.Terminal))
            {
                return(CommunicationType.TwoWay);
            }

            // test laser
            if (this.m_comp_laser != null && other.m_comp_laser != null && m_comp_laser.Other == other.m_comp_laser && other.m_comp_laser.Other == m_comp_laser)
            {
                return(CommunicationType.TwoWay);
            }

            // test radio
            if (this.m_comp_radio != null && other.m_comp_radio != null)
            {
                // check radio antenna to radio antenna
                CommunicationType radioResult;
                radioResult = this.m_comp_radio.TestConnection(other.m_comp_radio);
                if (radioResult != CommunicationType.None)
                {
                    Log.TraceLog("radio connection to " + other.DebugName + " is " + radioResult);
                    return(radioResult);
                }

                // check beacon to radio antenna
                if (this.m_comp_radio.CanBroadcastPositionTo(other.m_comp_radio) && other.Storage != null)
                {
                    if (s_sendPositionTo.Add(other.Storage))
                    {
                        Log.TraceLog("Friendly receiver in range: " + other.DebugName + ", new storage: " + other.Storage.PrimaryNode.DebugName);
                    }
                    else
                    {
                        Log.TraceLog("Friendly receiver in range: " + other.DebugName + ", existing storage: " + other.Storage.PrimaryNode.DebugName);
                    }
                }
            }

            return(CommunicationType.None);
        }
Example #5
0
        private bool GetTextPanel(string name, out IMyTextPanel panel)
        {
            IMyCubeBlock foundBlock     = null;
            int          bestNameLength = int.MaxValue;

            foreach (IMyCubeBlock Fatblock in AttachedGrid.AttachedCubeBlocks(Grid, AttachedGrid.AttachmentKind.Permanent, true))
            {
                if (Block.canControlBlock(Fatblock))
                {
                    string blockName = Fatblock.DisplayNameText.LowerRemoveWhitespace();

                    if (blockName.Length < bestNameLength && blockName.Contains(name))
                    {
                        foundBlock     = Fatblock;
                        bestNameLength = blockName.Length;
                        if (name.Length == bestNameLength)
                        {
                            break;
                        }
                    }
                }
            }

            panel = foundBlock as IMyTextPanel;
            return(panel != null);
        }
Example #6
0
        /// <returns>true iff the entity should be kept</returns>
        public static bool collect_Entity(IMyCubeGrid myGrid, MyEntity entity)
        {
            if (!(entity is IMyCubeGrid) && !(entity is IMyVoxelMap) && !(entity is IMyFloatingObject))
            {
                return(false);
            }

            IMyCubeGrid asGrid = entity as IMyCubeGrid;

            if (asGrid != null)
            {
                if (asGrid == myGrid)
                {
                    return(false);
                }

                if (!asGrid.Save)
                {
                    return(false);
                }

                if (AttachedGrid.IsGridAttached(myGrid, asGrid, AttachedGrid.AttachmentKind.Physics))
                {
                    return(false);
                }
            }

            if (entity.Physics != null && entity.Physics.Mass > 0 && entity.Physics.Mass < 1000)
            {
                return(false);
            }

            return(true);
        }
Example #7
0
        public void UpdateTarget(AntennaRelay.LastSeen enemy)
        {
            if (enemy == null)
            {
                return;
            }

            foreach (IMyCubeGrid grid in AttachedGrid.AttachedGrids(m_block.CubeGrid, AttachedGrid.AttachmentKind.Terminal, true))
            {
                CubeGridCache cache = CubeGridCache.GetFor(grid);
                if (cache == null)
                {
                    continue;
                }
                foreach (IMyCubeBlock warhead in cache.BlocksOfType(typeof(MyObjectBuilder_Warhead)))
                {
                    if (m_block.canControlBlock(warhead))
                    {
                        Log.DebugLog("Starting countdown for " + warhead.getBestName(), Logger.severity.DEBUG);
                        warhead.ApplyAction("StartCountdown");
                    }
                }
            }
            m_countingDown = true;
        }
Example #8
0
        private void AllLastSeen(RelayStorage store)
        {
            Vector3D myPos = m_block.GetPosition();

            store.ForEachLastSeen((LastSeen seen) => {
                IMyCubeGrid grid = seen.Entity as IMyCubeGrid;
                if (grid != null && AttachedGrid.IsGridAttached(m_block.CubeGrid, grid, AttachedGrid.AttachmentKind.Physics))
                {
                    return;
                }

                ExtensionsRelations.Relations relations = m_block.getRelationsTo(seen.Entity, ExtensionsRelations.Relations.Enemy).highestPriority();
                m_sortableList.Add(new sortableLastSeen(myPos, seen, relations, m_options));
                //Log.DebugLog("item: " + seen.Entity.getBestName() + ", relations: " + relations, "Display()");
            });
        }
Example #9
0
 private bool BatteriesCharged(IMyCubeGrid startGrid)
 {
     foreach (IMyCubeGrid attachedGrid in AttachedGrid.AttachedGrids(startGrid, AttachedGrid.AttachmentKind.Permanent, true))
     {
         CubeGridCache cache = CubeGridCache.GetFor(attachedGrid);
         if (cache == null)
         {
             return(false);
         }
         foreach (IMyBatteryBlock battery in cache.BlocksOfType(typeof(MyObjectBuilder_BatteryBlock)))
         {
             if (battery.IsCharging)
             {
                 return(false);
             }
         }
     }
     Logger.DebugLog("All batteries are recharged", Logger.severity.DEBUG);
     return(true);
 }
Example #10
0
		private static bool CheckParams(VRage.Game.ModAPI.IMyCubeBlock autopilot, string blockName, string actionName, string[] parameters, out string message, out List<Ingame.TerminalActionParameter> termParams)
		{
			int needParams = -1;
			message = actionName + " not found";

			foreach (IMyCubeBlock block in AttachedGrid.AttachedCubeBlocks((IMyCubeGrid)autopilot.CubeGrid, AttachedGrid.AttachmentKind.Permanent, true))
			{
				if (!block.DisplayNameText.Contains(blockName, StringComparison.InvariantCultureIgnoreCase))
					continue;
				IMyTerminalBlock term = block as IMyTerminalBlock;
				if (term == null)
					continue;
				ITerminalAction terminalAction = (ITerminalAction)term.GetActionWithName(actionName);
				if (terminalAction != null)
				{
					int paramCount = terminalAction.GetParameterDefinitions().Count;
					if (Math.Abs(parameters.Length - paramCount) > (Math.Abs(parameters.Length - needParams)))
						continue;

					needParams = paramCount;
					if (parameters.Length == needParams && CheckParams(terminalAction, out message, out termParams, parameters))
						return true;
				}
			}

			if (needParams < 0)
			{
				message = actionName + " has no parameters";
				termParams = null;
				return false;
			}
			if (parameters.Length != needParams)
			{
				message = actionName + " requires " + needParams + " parameters, got " + parameters.Length;
				termParams = null;
				return false;
			}

			termParams = null;
			return false;
		}
Example #11
0
		private void ListContent(IMyTerminalBlock autopilot, List<MyTerminalControlListBoxItem> items, List<MyTerminalControlListBoxItem> selected)
		{
			string blockName = m_targetBlock.ToString().Trim();
			if (string.IsNullOrWhiteSpace(blockName))
				return;

			HashSet<ITerminalAction> termActs = new HashSet<ITerminalAction>();
			foreach (IMyCubeBlock block in AttachedGrid.AttachedCubeBlocks((IMyCubeGrid)autopilot.CubeGrid, AttachedGrid.AttachmentKind.Permanent, true))
			{
				if (!block.DisplayNameText.Contains(blockName, StringComparison.InvariantCultureIgnoreCase))
					continue;
				IMyTerminalBlock term = block as IMyTerminalBlock;
				if (term == null)
					continue;
				term.GetActions(null, action => {
					if (termActs.Add((ITerminalAction)action))
						items.Add(new MyTerminalControlListBoxItem(MyStringId.GetOrCompute(action.Id), MyStringId.NullOrEmpty, action));
					return false;
				});
			}
		}
Example #12
0
        private void CalculateInertiaMoment()
        {
            Log.DebugLog("recalculating inertia moment", Logger.severity.INFO);

            m_calcInertiaMoment = Vector3.Zero;
            foreach (IMySlimBlock slim in (AttachedGrid.AttachedSlimBlocks(myGrid, AttachedGrid.AttachmentKind.Physics, true)))
            {
                AddToInertiaMoment(slim);
            }

            using (m_lock.AcquireExclusiveUsing())
            {
                m_inertiaMoment         = m_calcInertiaMoment;
                m_invertedInertiaMoment = 1f / m_inertiaMoment;
            }

            Log.DebugLog("Inertia moment: " + m_inertiaMoment, Logger.severity.DEBUG);
            Log.DebugLog("Inverted inertia moment: " + m_invertedInertiaMoment, Logger.severity.DEBUG);

            m_updating = false;
        }
Example #13
0
        /// <summary>
        /// Find a block that matches m_targetBlockName.
        /// </summary>
        private void BlockSearch()
        {
            Log.DebugLog("Grid == null", Logger.severity.FATAL, condition: Grid == null);
            Log.DebugLog("m_targetBlockName == null", Logger.severity.FATAL, condition: m_targetBlockName == null);

            NextSearch_Block = Globals.UpdateCount + SearchInterval_Block;
            Block            = null;

            int         bestNameLength = int.MaxValue;
            IMyCubeGrid asGrid         = Grid.Entity as IMyCubeGrid;

            Log.DebugLog("asGrid == null", Logger.severity.FATAL, condition: asGrid == null);

            foreach (IMyCubeBlock Fatblock in AttachedGrid.AttachedCubeBlocks(asGrid, m_allowedAttachment, true))
            {
                if (!m_controlBlock.CubeBlock.canControlBlock(Fatblock))
                {
                    continue;
                }

                string blockName = Fatblock.DisplayNameText.LowerRemoveWhitespace();

                if (BlockCondition != null && !BlockCondition(Fatblock))
                {
                    continue;
                }

                //Log.DebugLog("checking block name: \"" + blockName + "\" contains \"" + m_targetBlockName + "\"", "BlockSearch()");
                if (blockName.Length < bestNameLength && blockName.Contains(m_targetBlockName))
                {
                    Log.DebugLog("block name matches: " + Fatblock.DisplayNameText);
                    Block          = Fatblock;
                    bestNameLength = blockName.Length;
                    if (m_targetBlockName.Length == bestNameLength)
                    {
                        return;
                    }
                }
            }
        }
Example #14
0
        /// <summary>
        /// Tests if autopilot's ship would endanger a grid with a ship tool.
        /// </summary>
        /// <param name="grid">The grid that is potentially endangered.</param>
        /// <param name="input"><see cref="TestInput"/></param>
        /// <param name="result"><see cref="GridTestResult"/></param>
        /// True if the ship would endanger grid.
        private bool EndangerGrid(MyCubeGrid grid, ref TestInput input, ref GridTestResult result)
        {
            Vector3D currentPosition = AutopilotGrid.GetCentre();
            Vector3D obstructPositon = grid.GetCentre();
            Vector3D rejectD         = input.Direction;

            Vector3D gridPosition = grid.GetCentre() - input.Offset;
            float    gridRadius   = grid.PositionComp.LocalVolume.Radius;

            Vector3  rejectDispF; Vector3.Multiply(ref input.Direction, input.Length, out rejectDispF);
            Vector3D rejectDisp = rejectDispF;

            IEnumerable <CubeGridCache> myCaches = AttachedGrid.AttachedGrids(AutopilotGrid, AttachedGrid.AttachmentKind.Terminal, true).Select(CubeGridCache.GetFor);

            foreach (CubeGridCache cache in myCaches)
            {
                if (cache == null)
                {
                    Logger.DebugLog("Missing a cache", Logger.severity.DEBUG);
                    return(true);
                }
                foreach (MyShipDrill drill in cache.BlocksOfType(typeof(MyObjectBuilder_Drill)))
                {
                    if (drill.IsShooting && ToolObstructed(drill, ref gridPosition, gridRadius, ref rejectDisp, ref result) && IsRejectionTowards(ref obstructPositon, ref currentPosition, ref rejectD))
                    {
                        return(true);
                    }
                }
                foreach (MyShipGrinder grinder in cache.BlocksOfType(typeof(MyObjectBuilder_ShipGrinder)))
                {
                    if (grinder.IsShooting && ToolObstructed(grinder, ref gridPosition, gridRadius, ref rejectDisp, ref result) && IsRejectionTowards(ref obstructPositon, ref currentPosition, ref rejectD))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Example #15
0
        private void ListContent(IMyTerminalBlock autopilot, List <MyTerminalControlListBoxItem> items, List <MyTerminalControlListBoxItem> selected)
        {
            string blockName = m_targetBlock.ToString().Trim();

            if (string.IsNullOrWhiteSpace(blockName))
            {
                return;
            }

            HashSet <ITerminalProperty <T> > termProps = new HashSet <ITerminalProperty <T> >();

            foreach (IMyCubeBlock block in AttachedGrid.AttachedCubeBlocks((IMyCubeGrid)autopilot.CubeGrid, AttachedGrid.AttachmentKind.Permanent, true))
            {
                if (!block.DisplayNameText.Contains(blockName, StringComparison.InvariantCultureIgnoreCase))
                {
                    continue;
                }
                IMyTerminalBlock term = block as IMyTerminalBlock;
                if (term == null)
                {
                    continue;
                }
                term.GetProperties(null, property => {
                    ITerminalProperty <T> propT = property as ITerminalProperty <T>;
                    if (propT == null)
                    {
                        return(false);
                    }
                    if (termProps.Add(propT))
                    {
                        items.Add(new MyTerminalControlListBoxItem(MyStringId.GetOrCompute(propT.Id), MyStringId.NullOrEmpty, propT));
                    }
                    return(false);
                });
            }
        }
Example #16
0
 private bool IsConnected(RelayNode node)
 {
     return(!node.Block.Closed && node.Block.IsWorking && m_block.canConsiderFriendly(node.Block) && AttachedGrid.IsGridAttached(m_block.CubeGrid, node.Block.CubeGrid, AttachedGrid.AttachmentKind.Terminal));
 }
Example #17
0
        public void Update10()
        {
            if (Globals.ElapsedTime < m_nextHack)
            {
                return;
            }
            if (!m_hackBlock.IsWorking)
            {
                m_strengthLeft = 0f;
                return;
            }
            IMyCubeGrid attached = m_hackBlock.GetAttachedEntity() as IMyCubeGrid;

            if (attached == null)
            {
                m_strengthLeft = 0f;
                return;
            }

            // break force might be removed from game entirely
            //if (m_hackBlock.BreakForce > allowedBreakForce)
            //{
            //	Log.DebugLog("break force too high: " + m_hackBlock.BreakForce);
            //	ITerminalProperty<float> prop = m_hackBlock.GetProperty("BreakForce") as ITerminalProperty<float>;
            //	if (prop == null)
            //	{
            //		Log.DebugLog("break force is disabled in SE", Logger.severity.INFO);
            //		allowedBreakForce = float.PositiveInfinity;
            //	}
            //	else
            //		prop.SetValue(m_hackBlock, allowedBreakForce);
            //}
            //if (allowedBreakForce == float.PositiveInfinity)

            // landing gear is unbreakable, disconnect / fail if not otherwise attached
            if (!AttachedGrid.IsGridAttached(m_hackBlock.CubeGrid as IMyCubeGrid, attached, AttachedGrid.AttachmentKind.Physics))
            {
                Log.DebugLog("no other connection to attached, hacker must disconnect", Logger.severity.DEBUG);
                ITerminalProperty <bool> autolock = m_hackBlock.GetProperty("Autolock") as ITerminalProperty <bool>;
                if (autolock.GetValue(m_hackBlock))
                {
                    autolock.SetValue(m_hackBlock, false);
                }
                m_hackBlock.GetActionWithName("Unlock").Apply(m_hackBlock);
                return;
            }

            m_nextHack = Globals.ElapsedTime + s_hackFrequency;

            m_strengthLeft += s_hackStrength;

            foreach (int i in Enumerable.Range(0, 8).OrderBy(x => Globals.Random.Next()))
            {
                Disruption disrupt;
                switch (i)
                {
                case 0:
                    disrupt = new AirVentDepressurize();
                    break;

                case 1:
                    disrupt = new DoorLock();
                    break;

                case 2:
                    disrupt = new GravityReverse();
                    break;

                case 3:
                    disrupt = new DisableTurret();
                    break;

                case 4:
                    disrupt = new TraitorTurret();
                    break;

                case 5:
                    disrupt = new CryoChamberMurder();
                    break;

                case 6:
                    disrupt = new JumpDriveDrain();
                    break;

                case 7:
                    disrupt = new MedicalRoom();
                    break;

                default:
                    Log.AlwaysLog("Case not implemented: " + i, Logger.severity.FATAL);
                    continue;
                }
                foreach (IMyCubeGrid grid in AttachedGrid.AttachedGrids(attached, AttachedGrid.AttachmentKind.Terminal, true))
                {
                    disrupt.Start(grid, s_hackLength, ref m_strengthLeft, m_hackBlock.OwnerId);
                }
            }
        }
Example #18
0
        /// <summary>
        /// Test if it is safe for the grid to rotate.
        /// </summary>
        /// <param name="axis">Normalized axis of rotation in world space.</param>
        /// <returns>True iff the path is clear.</returns>
        private bool in_TestRotate(Vector3 axis)
        {
            IMyCubeGrid myGrid       = m_block.CubeGrid;
            Vector3     centreOfMass = myGrid.Physics.CenterOfMassWorld;
            float       longestDim   = myGrid.GetLongestDim();

            // calculate height
            Matrix  toMyLocal     = myGrid.WorldMatrixNormalizedInv;
            Vector3 myLocalCoM    = Vector3.Transform(centreOfMass, toMyLocal);
            Vector3 myLocalAxis   = Vector3.Transform(axis, toMyLocal.GetOrientation());
            Vector3 myLocalCentre = myGrid.LocalAABB.Center;             // CoM may not be on ship (it now considers mass from attached grids)
            Ray     upper         = new Ray(myLocalCentre + myLocalAxis * longestDim * 2f, -myLocalAxis);
            float?  upperBound    = myGrid.LocalAABB.Intersects(upper);

            if (!upperBound.HasValue)
            {
                Log.AlwaysLog("Math fail, upperBound does not have a value", Logger.severity.FATAL);
            }
            Ray   lower      = new Ray(myLocalCentre - myLocalAxis * longestDim * 2f, myLocalAxis);
            float?lowerBound = myGrid.LocalAABB.Intersects(lower);

            if (!lowerBound.HasValue)
            {
                Log.AlwaysLog("Math fail, lowerBound does not have a value", Logger.severity.FATAL);
            }
            //Log.DebugLog("LocalAABB: " + myGrid.LocalAABB + ", centre: " + myLocalCentre + ", axis: " + myLocalAxis + ", longest dimension: " + longestDim + ", upper ray: " + upper + ", lower ray: " + lower);
            float height = longestDim * 4f - upperBound.Value - lowerBound.Value;

            float furthest = 0f;

            foreach (IMyCubeGrid grid in AttachedGrid.AttachedGrids(myGrid, Attached.AttachedGrid.AttachmentKind.Physics, true))
            {
                CubeGridCache cache = CubeGridCache.GetFor(grid);
                if (cache == null)
                {
                    return(false);
                }
                foreach (Vector3I cell in cache.OccupiedCells())
                {
                    Vector3 rejection       = Vector3.Reject(cell * myGrid.GridSize, myLocalAxis);
                    float   cellDistSquared = Vector3.DistanceSquared(myLocalCoM, rejection);
                    if (cellDistSquared > furthest)
                    {
                        furthest = cellDistSquared;
                    }
                }
            }
            float length = (float)Math.Sqrt(furthest) + myGrid.GridSize;

            //Log.DebugLog("height: " + height + ", length: " + length);

            BoundingSphereD surroundingSphere = new BoundingSphereD(centreOfMass, Math.Max(length, height) * MathHelper.Sqrt2);

            m_obstructions.Clear();
            MyGamePruningStructure.GetAllTopMostEntitiesInSphere(ref surroundingSphere, m_obstructions);

            LineSegment axisSegment = new LineSegment();

            m_closestPlanet = null;

            foreach (MyEntity entity in m_collector.Invoke(m_obstructions))
            {
                if (entity is IMyVoxelBase)
                {
                    IMyVoxelMap voxel = entity as IMyVoxelMap;
                    if (voxel != null)
                    {
                        if (voxel.GetIntersectionWithSphere(ref surroundingSphere))
                        {
                            Log.DebugLog("Too close to " + voxel.getBestName() + ", CoM: " + centreOfMass.ToGpsTag("Centre of Mass") + ", required distance: " + surroundingSphere.Radius);
                            ObstructingEntity = voxel;
                            return(false);
                        }
                        continue;
                    }

                    if (m_closestPlanet == null)
                    {
                        MyPlanet planet = entity as MyPlanet;
                        if (planet == null)
                        {
                            continue;
                        }

                        double distToPlanetSq = Vector3D.DistanceSquared(centreOfMass, planet.PositionComp.GetPosition());
                        if (distToPlanetSq < planet.MaximumRadius * planet.MaximumRadius)
                        {
                            m_closestPlanet = planet;

                            if (m_planetObstruction)
                            {
                                Log.DebugLog("planet blocking");
                                ObstructingEntity = m_closestPlanet;
                                return(false);
                            }
                        }
                    }
                    continue;
                }

                IMyCubeGrid grid = entity as IMyCubeGrid;
                if (grid != null)
                {
                    Matrix  toLocal     = grid.WorldMatrixNormalizedInv;
                    Vector3 localAxis   = Vector3.Transform(axis, toLocal.GetOrientation());
                    Vector3 localCentre = Vector3.Transform(centreOfMass, toLocal);
                    axisSegment.From = localCentre - localAxis * height;
                    axisSegment.To   = localCentre + localAxis * height;

                    CubeGridCache cache = CubeGridCache.GetFor(grid);
                    if (cache == null)
                    {
                        return(false);
                    }
                    foreach (Vector3I cell in cache.OccupiedCells())
                    {
                        if (axisSegment.PointInCylinder(length, cell * grid.GridSize))
                        {
                            Log.DebugLog("axis segment: " + axisSegment.From + " to " + axisSegment.To + ", radius: " + length + ", hit " + grid.nameWithId() + " at " + cell);
                            ObstructingEntity = grid;
                            return(false);
                        }
                    }

                    continue;
                }

                Log.DebugLog("No tests for object: " + entity.getBestName(), Logger.severity.INFO);
                ObstructingEntity = entity;
                return(false);
            }

            MyAPIGateway.Utilities.TryInvokeOnGameThread(TestPlanet);
            ObstructingEntity = null;
            return(true);
        }
Example #19
0
        /// <summary>
        /// Updates direct connections between this node and other nodes.
        /// When debug is set, checks connection to primary storage node.
        /// </summary>
        public void Update100()
        {
            s_sendPositionTo.Clear();

            bool checkPrimary = false;

            Registrar.ForEach((RelayNode node) => {
                if (node == this)
                {
                    return;
                }

                CommunicationType connToNode = TestConnection(node);

                if (connToNode == CommunicationType.TwoWay)
                {
                    if (m_directConnect.Add(node))
                    {
                        Log.TraceLog("Now connected to " + node.DebugName, Logger.severity.DEBUG);

                        if (this.Storage == null)
                        {
                            if (node.Storage != null)
                            {
                                Log.TraceLog("Using storage from other node: " + node.DebugName
                                             + ", primary: " + node.Storage.PrimaryNode.DebugName, Logger.severity.DEBUG);
                                this.Storage = node.Storage;
                            }
                        }
                        else if (node.Storage != null && this.Storage != node.Storage)
                        {
                            // should prefer blocks since they are less likely to be removed from world while offline
                            if (this.Block != null && node.Block == null)
                            {
                                Log.TraceLog("Nodes have different storages, copying to this node's storage because this node is a block", Logger.severity.DEBUG);
                                node.Storage.CopyTo(this.Storage);
                                node.Storage = this.Storage;
                            }
                            else if (this.Block == null && node.Block != null)
                            {
                                Log.TraceLog("Nodes have different storages, copying to other node's storage beacause other node is a block", Logger.severity.DEBUG);
                                this.Storage.CopyTo(node.Storage);
                                this.Storage = node.Storage;
                            }
                            else if (this.Storage.Size < node.Storage.Size)
                            {
                                Log.TraceLog("Nodes have different storages, copying to other node's storage", Logger.severity.DEBUG);
                                this.Storage.CopyTo(node.Storage);
                                this.Storage = node.Storage;
                            }
                            else
                            {
                                Log.TraceLog("Nodes have different storages, copying to this node's storage", Logger.severity.DEBUG);
                                node.Storage.CopyTo(this.Storage);
                                node.Storage = this.Storage;
                            }
                        }
                    }
                }
                else
                {
                    if (m_directConnect.Remove(node))
                    {
                        Log.TraceLog("No longer connected to " + node.DebugName, Logger.severity.DEBUG);
                        checkPrimary = true;
                    }
                }

                if (Storage != null)
                {
                    if (connToNode == CommunicationType.OneWay)
                    {
                        if (m_oneWayConnect.Add(node))
                        {
                            Log.TraceLog("New one-way connection to " + node.DebugName, Logger.severity.DEBUG);
                            Storage.AddPushTo(node);
                        }
                    }
                    else
                    {
                        if (m_oneWayConnect.Remove(node))
                        {
                            Log.TraceLog("Lost one-way connection to " + node.DebugName, Logger.severity.DEBUG);
                            Storage.RemovePushTo(node);
                        }
                    }
                }
            });

            if (Storage == null)
            {
                Log.DebugLog("No storage, creating a new one", Logger.severity.INFO);
                Storage = new RelayStorage(this);
            }
            else if (checkPrimary && !IsConnectedTo(Storage.PrimaryNode))
            {
                Log.DebugLog("Lost connection to primary, cloning storage", Logger.severity.INFO);
                Storage = Storage.Clone(this);
            }

            // connections don't update immediately, so don't worry about a single message (per block)
            Log.TraceLog("Not connected to primary node", Logger.severity.INFO, condition: !IsConnectedTo(Storage.PrimaryNode));

            IMyEntity topEntity = m_entity.GetTopMostParent();

            Log.TraceLog("Sending self to " + s_sendPositionTo.Count + " neutral/hostile storages", Logger.severity.TRACE);
            RelayStorage.Receive(s_sendPositionTo, new LastSeen(topEntity, LastSeen.DetectedBy.Broadcasting));

            if (Storage.VeryRecentRadarInfo(topEntity.EntityId))
            {
                return;
            }

            if (Block == null)
            {
                Storage.Receive(new LastSeen(topEntity, LastSeen.DetectedBy.Broadcasting, new LastSeen.RadarInfo(topEntity)));
            }
            else
            {
                foreach (IMyCubeGrid grid in AttachedGrid.AttachedGrids(Block.CubeGrid, AttachedGrid.AttachmentKind.Terminal, true))
                {
                    Storage.Receive(new LastSeen(grid, LastSeen.DetectedBy.Broadcasting, new LastSeen.RadarInfo(grid)));
                }
            }
        }
Example #20
0
        /// <summary>
        /// Tests if the ship is obstructed by any voxel.
        /// </summary>
        /// <param name="input"><see cref="TestInput"/></param>
        /// <param name="result"><see cref="VoxelTestResult"/></param>
        /// <returns>True iff a voxel is obstructing the ship.</returns>
        public bool RayCastIntersectsVoxel(ref TestInput input, out VoxelTestResult result)
        {
            Profiler.StartProfileBlock();

            Logger.DebugLog("direction vector is invalid: " + input.Direction, Logger.severity.FATAL, condition: !input.Direction.IsValid() || Math.Abs(1f - input.Direction.LengthSquared()) > 0.01f);
            Logger.TraceLog(input.ToString());

            if (input.Length < 1f)
            {
                // need to skip as Proximity doesn't work with short capsules
                // should be safe, as the ship got here somehow
                Logger.TraceLog("Input length is small, no voxel test necessary");
                result           = VoxelTestResult.Default;
                result.Distance  = input.Length;
                result.Proximity = 1f;
                return(false);
            }

            Vector3D currentPosition = AutopilotGrid.GetCentre();
            Vector3  startOffset; Vector3.Multiply(ref input.Direction, StartRayCast, out startOffset);
            Vector3D startOffsetD = startOffset;
            Vector3D totalOffset; Vector3D.Add(ref input.Offset, ref startOffsetD, out totalOffset);

            CapsuleD capsule;

            Vector3D.Add(ref currentPosition, ref totalOffset, out capsule.P0);
            Vector3D capsuleDisp;

            {
                capsuleDisp.X = input.Direction.X * input.Length;
                capsuleDisp.Y = input.Direction.Y * input.Length;
                capsuleDisp.Z = input.Direction.Z * input.Length;
            }
            Vector3D.Add(ref capsule.P0, ref capsuleDisp, out capsule.P1);
            capsule.Radius = AutopilotGrid.PositionComp.LocalVolume.Radius;
            //Logger.DebugLog("current position: " + currentPosition + ", offset: " + offset + ", line: " + rayDirectionLength + ", start: " + capsule.P0 + ", end: " + capsule.P1);

            result = VoxelTestResult.Default;
            Vector3D hitPosition;
            float    proximity = (float)CapsuleDExtensions.ProximityToVoxel(ref capsule, out result.ObstructingVoxel, out hitPosition, true, input.Length);

            result.Proximity = 10f * proximity;             // lie because we have not done a proper test but could have a very nice result
            if (proximity > 1f)
            {
                Logger.TraceLog("Large capsule DOES NOT intersect voxel: " + capsule.String() + ", proximity: " + proximity + "/" + result.Proximity);
                result.Distance = input.Length;
                Profiler.EndProfileBlock();
                return(false);
            }
            Logger.TraceLog("Large capsule DOES intersect voxel: " + capsule.String() + ", proximity: " + proximity + "/" + result.Proximity);

            IEnumerable <CubeGridCache> myCaches = AttachedGrid.AttachedGrids(AutopilotGrid, AttachedGrid.AttachmentKind.Physics, true).Select(CubeGridCache.GetFor);

            Vector3 v; input.Direction.CalculatePerpendicularVector(out v);
            Vector3 w; Vector3.Cross(ref input.Direction, ref v, out w);
            Matrix  to3D = new Matrix(v.X, v.Y, v.Z, 0f,
                                      w.X, w.Y, w.Z, 0f,
                                      input.Direction.X, input.Direction.Y, input.Direction.Z, 0f,
                                      0f, 0f, 0f, 1f);
            Matrix to2D; Matrix.Invert(ref to3D, out to2D);

            Vector2IMatrix <Vector3D> apShipRejections;

            ResourcePool.Get(out apShipRejections);

            MatrixD worldMatrix = AutopilotGrid.WorldMatrix;
            float   gridSize    = AutopilotGrid.GridSize;

            foreach (CubeGridCache cache in myCaches)
            {
                if (cache == null)
                {
                    Logger.DebugLog("Missing a cache", Logger.severity.DEBUG);
                    Profiler.EndProfileBlock();
                    return(false);
                }
                foreach (Vector3I cell in cache.OccupiedCells())
                {
                    Vector3  local = cell * gridSize;
                    Vector3D world; Vector3D.Transform(ref local, ref worldMatrix, out world);
                    Vector3D offsetWorld; Vector3D.Add(ref world, ref totalOffset, out offsetWorld);
                    Vector3D relative; Vector3D.Subtract(ref offsetWorld, ref currentPosition, out relative);
                    Vector3  relativeF = relative;
                    Vector3  rejection; Vector3.Reject(ref relativeF, ref input.Direction, out rejection);
                    Vector3  planarComponents; Vector3.Transform(ref rejection, ref to2D, out planarComponents);
                    Logger.DebugLog("Math fail: rejection: " + rejection + ", planar components: " + planarComponents + "\nto3D: " + to3D, Logger.severity.FATAL, condition: planarComponents.Z > 0.001f || planarComponents.Z < -0.001f);
                    Vector2 pc2 = new Vector2(planarComponents.X, planarComponents.Y);
                    apShipRejections.Add(ToCell(pc2, gridSize), offsetWorld);
                }
            }

            Vector2IMatrix <bool> testedRejections;

            ResourcePool.Get(out testedRejections);

            const int allowedEmpty = 2;

            foreach (KeyValuePair <Vector2I, Vector3D> cell in apShipRejections.MiddleOut())
            {
                //Logger.DebugLog("Cell was not set: " + cell, Logger.severity.FATAL, condition: cell.Value == Vector3D.Zero);

                if (!testedRejections.Add(cell.Key, true))
                {
                    continue;
                }

                int ringIndex = 0;
                m_insideRing.Clear();

                int biggestRingSq = 0;
                while (true)
                {
                    int consecutiveEmpty     = 0;
                    ExpandingRings.Ring ring = ExpandingRings.GetRing(ringIndex++);
                    foreach (Vector2I ringOffset in ring.Squares)
                    {
                        if (apShipRejections.Contains(ringOffset + cell.Key))
                        {
                            consecutiveEmpty = 0;
                        }
                        else
                        {
                            consecutiveEmpty++;
                            if (consecutiveEmpty > allowedEmpty)
                            {
                                goto GotRing;
                            }
                        }
                    }
                    m_insideRing.AddArray(ring.Squares);
                    biggestRingSq = ring.DistanceSquared;
                }

GotRing:
                foreach (Vector2I ringOffset in m_insideRing)
                {
                    testedRejections.Add(ringOffset + cell.Key, true);
                }

                capsule.P0 = cell.Value;
                Vector3D.Add(ref capsule.P0, ref capsuleDisp, out capsule.P1);
                capsule.Radius   = (1f + (float)Math.Sqrt(biggestRingSq)) * gridSize;
                result.Proximity = (float)CapsuleDExtensions.ProximityToVoxel(ref capsule, out result.ObstructingVoxel, out hitPosition, true, input.Length);
                if (result.Proximity <= 1f)
                {
                    Logger.TraceLog("Block capsule does hit voxel: " + capsule.String() + ", proxmity: " + result.Proximity);
                    double distance;  Vector3D.Distance(ref capsule.P0, ref hitPosition, out distance);
                    result.Distance = (float)distance;
                    apShipRejections.Clear();
                    testedRejections.Clear();
                    ResourcePool.Return(apShipRejections);
                    ResourcePool.Return(testedRejections);
                    Profiler.EndProfileBlock();
                    return(true);
                }
            }

            Logger.TraceLog("Ship's path is clear from voxels, proximity: " + result.Proximity);
            apShipRejections.Clear();
            testedRejections.Clear();
            ResourcePool.Return(apShipRejections);
            ResourcePool.Return(testedRejections);
            Profiler.EndProfileBlock();
            return(false);
        }
Example #21
0
        /// <summary>
        /// Tests a grid for obstructing the ship via vector rejection.
        /// </summary>
        /// <param name="oGrid">The grid that may obstruct this one.</param>
        /// <param name="ignoreBlock">Block to ignore, or null</param>
        /// <param name="input"><see cref="TestInput"/></param>
        /// <param name="result"><see cref="GridTestResult"/></param>
        /// <returns>True if oGrid is blocking the ship.</returns>
        private bool RejectionIntersects(MyCubeGrid oGrid, MyCubeBlock ignoreBlock, ref TestInput input, ref GridTestResult result)
        {
            //Logger.DebugLog("Rejection vector is not normalized, length squared: " + rejectionVector.LengthSquared(), Logger.severity.FATAL, condition: Math.Abs(rejectionVector.LengthSquared() - 1f) > 0.001f);
            //Logger.DebugLog("Testing for rejection intersection: " + oGrid.nameWithId() + ", starting from: " + (AutopilotGrid.GetCentre() + offset) + ", rejection vector: " + rejectionVector + ", distance: " + rejectionDistance +
            //	", final: " + (AutopilotGrid.GetCentre() + offset + rejectionVector * rejectionDistance));
            //Logger.DebugLog("rejction distance < 0: " + rejectionDistance, Logger.severity.ERROR, condition: rejectionDistance < 0f);

            IEnumerable <CubeGridCache> myCaches = AttachedGrid.AttachedGrids(AutopilotGrid, AttachedGrid.AttachmentKind.Physics, true).Select(CubeGridCache.GetFor);
            Vector3D currentPosition             = AutopilotGrid.GetCentre();

            CubeGridCache oCache = CubeGridCache.GetFor(oGrid);

            if (oCache == null)
            {
                Logger.DebugLog("Failed to get cache for other grid", Logger.severity.DEBUG);
                return(false);
            }

            bool checkBlock = ignoreBlock != null && oGrid == ignoreBlock.CubeGrid;

            Vector3 v; input.Direction.CalculatePerpendicularVector(out v);
            Vector3 w; Vector3.Cross(ref input.Direction, ref v, out w);
            Matrix  to3D = new Matrix(v.X, v.Y, v.Z, 0f,
                                      w.X, w.Y, w.Z, 0f,
                                      input.Direction.X, input.Direction.Y, input.Direction.Z, 0f,
                                      0f, 0f, 0f, 1f);
            Matrix to2D; Matrix.Invert(ref to3D, out to2D);

            float roundTo;
            int   minDistanceSquared;

            if (AutopilotGrid.GridSizeEnum == oGrid.GridSizeEnum)
            {
                roundTo            = AutopilotGrid.GridSize;
                minDistanceSquared = 1;
            }
            else
            {
                roundTo             = Math.Min(AutopilotGrid.GridSize, oGrid.GridSize);
                minDistanceSquared  = (int)Math.Ceiling(Math.Max(AutopilotGrid.GridSize, oGrid.GridSize) / roundTo);
                minDistanceSquared *= minDistanceSquared;
            }
            int maxDistanceSquared = minDistanceSquared * 100;

            Profiler.StartProfileBlock("RejectionIntersects:Build ship");

            Vector2IMatrix <bool> apShipRejections;

            ResourcePool.Get(out apShipRejections);

            MatrixD worldMatrix = AutopilotGrid.WorldMatrix;
            float   gridSize = AutopilotGrid.GridSize;
            float   minProjection = float.MaxValue, maxProjection = float.MinValue;           // the permitted range when rejecting the other grids cells

            foreach (CubeGridCache cache in myCaches)
            {
                if (cache == null)
                {
                    Logger.DebugLog("Missing a cache", Logger.severity.DEBUG);
                    Profiler.EndProfileBlock();
                    return(false);
                }
                foreach (Vector3I cell in cache.OccupiedCells())
                {
                    Vector3 local = cell * gridSize;

                    MyCubeBlock block = (MyCubeBlock)cache.CubeGrid.GetCubeBlock(cell)?.FatBlock;
                    if (block != null && block.Subparts != null && block.Subparts.Count != 0 && !CellOccupiedByBlock(cell, block))
                    {
                        continue;
                    }

                    Vector3D world; Vector3D.Transform(ref local, ref worldMatrix, out world);
                    Vector3D relative; Vector3D.Subtract(ref world, ref currentPosition, out relative);
                    Vector3  relativeF = relative;

                    float projectionDistance; Vector3 rejection;
                    VectorExtensions.RejectNormalized(ref relativeF, ref input.Direction, out projectionDistance, out rejection);
                    if (projectionDistance < minProjection)
                    {
                        minProjection = projectionDistance;
                    }
                    else if (projectionDistance > maxProjection)
                    {
                        maxProjection = projectionDistance;
                    }

                    Vector3 planarComponents; Vector3.Transform(ref rejection, ref to2D, out planarComponents);
                    //Logger.DebugLog("Math fail: rejection: " + rejection + ", planar components: " + planarComponents + "\nto3D: " + to3D, Logger.severity.WARNING, condition: planarComponents.Z > 0.001f || planarComponents.Z < -0.001f);
                    Vector2 pc2 = new Vector2(planarComponents.X, planarComponents.Y);
                    apShipRejections[ToCell(pc2, roundTo)] = true;
                    //Logger.DebugLog("My rejection: " + rejection + ", planar: " + ToCell(pc2, roundTo));
                }
            }
            Profiler.EndProfileBlock();

            minProjection += StartRayCast;             // allow autopilot to move away from a touching object

            //Logger.DebugLog("projection min: " + minProjection + ", max: " + maxProjection + ", max for other: " + (maxProjection + rejectionDistance));
            maxProjection += input.Length;

            //Logger.DebugLog("checking other grid cells");

            Profiler.StartProfileBlock("RejectionIntersects:other grid");

            Vector2IMatrix <bool> otherGridRejections;

            ResourcePool.Get(out otherGridRejections);

            worldMatrix = oGrid.WorldMatrix;
            gridSize    = oGrid.GridSize;
            foreach (Vector3I cell in oCache.OccupiedCells())
            {
                //Logger.DebugLog("cell: " + cell);

                Vector3  local = cell * gridSize;
                Vector3D world; Vector3D.Transform(ref local, ref worldMatrix, out world);
                Vector3D offsetWorld; Vector3D.Subtract(ref world, ref input.Offset, out offsetWorld);
                Vector3D relative; Vector3D.Subtract(ref offsetWorld, ref currentPosition, out relative);
                Vector3  relativeF = relative;

                Vector3 rejection;
                VectorExtensions.RejectNormalized(ref relativeF, ref input.Direction, out result.Distance, out rejection);
                if (result.Distance < minProjection || result.Distance > maxProjection)
                {
                    continue;
                }

                Vector3 planarComponents; Vector3.Transform(ref rejection, ref to2D, out planarComponents);
                //Logger.DebugLog("Math fail: rejection: " + rejection + ", planar components: " + planarComponents + "\nto3D: " + to3D, Logger.severity.WARNING, condition: planarComponents.Z > 0.001f || planarComponents.Z < -0.001f);
                Vector2  pc2    = new Vector2(planarComponents.X, planarComponents.Y);
                Vector2I cell2D = ToCell(pc2, roundTo);

                if (!otherGridRejections.Add(cell2D, true))
                {
                    //Logger.DebugLog("Already tested: " + cell2D);
                    continue;
                }

                //Logger.DebugLog("Rejection: " + rejection + ", planar: " + cell2D);
                //Logger.DebugLog("testing range. x: " + (cell2D.X - steps) + " - " + (cell2D.X + steps));

                ExpandingRings.Ring ring = default(ExpandingRings.Ring);
                for (int ringIndex = 0; ring.DistanceSquared <= maxDistanceSquared; ringIndex++)
                {
                    ring = ExpandingRings.GetRing(ringIndex);
                    for (int squareIndex = 0; squareIndex < ring.Squares.Length; squareIndex++)
                    {
                        if (apShipRejections.Contains(cell2D + ring.Squares[squareIndex]))
                        {
                            if (ring.DistanceSquared <= minDistanceSquared)
                            {
                                IMySlimBlock slim = oGrid.GetCubeBlock(cell);
                                if (slim != null)
                                {
                                    if (checkBlock && slim.FatBlock == ignoreBlock)
                                    {
                                        continue;
                                    }

                                    MyCubeBlock fat = (MyCubeBlock)slim.FatBlock;
                                    if (fat != null && fat.Subparts != null && fat.Subparts.Count != 0 && !CellOccupiedByBlock(cell, fat))
                                    {
                                        continue;
                                    }

                                    result.ObstructingBlock = fat;
                                }
                                else
                                {
                                    result.ObstructingBlock = null;
                                }

                                result.Proximity = 0f;
                                Logger.DebugLog("Hit, projectionDistance: " + result.Distance + ", min: " + minProjection + ", max: " + maxProjection + ", ring: " + ringIndex + ", ring dist sq: " + ring.DistanceSquared + ", min dist sq: " + minDistanceSquared + ", max dist sq: " + maxDistanceSquared);
                                Profiler.EndProfileBlock();
                                apShipRejections.Clear();
                                otherGridRejections.Clear();
                                ResourcePool.Return(apShipRejections);
                                ResourcePool.Return(otherGridRejections);
                                return(true);
                            }
                            else
                            {
                                maxDistanceSquared = ring.DistanceSquared;
                                goto NextCell;
                            }
                        }
                    }
                }

                NextCell :;
            }
            Profiler.EndProfileBlock();

            apShipRejections.Clear();
            otherGridRejections.Clear();
            ResourcePool.Return(apShipRejections);
            ResourcePool.Return(otherGridRejections);
            result.Proximity = (float)Math.Sqrt(maxDistanceSquared);
            return(false);
        }