/// <summary>
        /// Search every possible ore detector for materials.
        /// </summary>
        /// <param name="requester">Must be able to control OreDetector and have same NetworkStorage</param>
        /// <param name="oreType">Voxel materials to search for</param>
        public static void SearchForMaterial(ShipControllerBlock requester, byte[] oreType, OreSearchComplete onComplete)
        {
            Vector3D     position = requester.CubeBlock.GetPosition();
            RelayStorage storage  = requester.NetworkStorage;

            Static.m_thread.EnqueueAction(() => {
                List <OreDetector> oreDetectors = ResourcePool <List <OreDetector> > .Get();
                Registrar.ForEach((OreDetector detector) => {
                    if (detector.Block.IsWorking && requester.CubeBlock.canControlBlock(detector.Block) && detector.m_netClient.GetStorage() == storage)
                    {
                        oreDetectors.Add(detector);
                    }
                });

                IOrderedEnumerable <OreDetector> sorted = oreDetectors.OrderBy(detector => Vector3D.DistanceSquared(position, detector.Block.GetPosition()));

                foreach (OreDetector detector in sorted)
                {
                    if (detector.GetOreLocations(position, oreType, onComplete))
                    {
                        return;
                    }
                }

                oreDetectors.Clear();
                ResourcePool <List <OreDetector> > .Return(oreDetectors);

                onComplete(false, null, null, null);
            });
        }
Exemple #2
0
        /// <summary>
        /// Add the spheres that prevent autopilot from getting stuck between objects.
        /// </summary>
        /// <remarks>
        /// For every cluster, adds a sphere that includes the centre of every sphere in the cluster.
        /// </remarks>
        public void AddMiddleSpheres()
        {
            for (int indexO = Clusters.Count - 1; indexO >= 0; indexO--)
            {
                List <RepulseSphere> cluster = Clusters[indexO];
                if (cluster.Count < 2)
                {
                    continue;
                }
                Vector3D[] points = new Vector3D[cluster.Count];
                for (int indexI = cluster.Count - 1; indexI >= 0; indexI--)
                {
                    points[indexI] = cluster[indexI].Centre;
                }

                BoundingSphereD sphere  = BoundingSphereD.CreateFromPoints(points);
                RepulseSphere   repulse = new RepulseSphere()
                {
                    Centre = sphere.Center, FixedRadius = sphere.Radius
                };

#if DEBUG
                List <IMyEntity> entities; ResourcePool.Get(out entities);
                foreach (RepulseSphere rs in cluster)
                {
                    entities.AddArray(rs.Entities);
                }
                repulse.Entities = entities.ToArray();
                entities.Clear();
                ResourcePool.Return(entities);
#endif

                cluster.Add(repulse);
            }
        }
Exemple #3
0
        private void DisplyAutopilotStatus()
        {
            //Log.DebugLog("Building autopilot list", "DisplyAutopilotStatus()", Logger.severity.TRACE);

            RelayStorage store = m_networkClient.GetStorage();

            if (store == null)
            {
                m_textPanel.WritePublicText("No network connection");
                return;
            }

            List <SortableAutopilot> autopilots = ResourcePool <List <SortableAutopilot> > .Get();

            Vector3D mypos = m_block.GetPosition();

            Registrar.ForEach <AutopilotTerminal>(ap => {
                IRelayPart relayPart;
                if (RelayClient.TryGetRelayPart((IMyCubeBlock)ap.m_block, out relayPart) && relayPart.GetStorage() == store && m_block.canControlBlock(ap.m_block))
                {
                    autopilots.Add(new SortableAutopilot(ap, mypos));
                }
            });

            autopilots.Sort();

            StringBuilder displayText = new StringBuilder();

            displayText.Append(timeString);
            displayText.Append(DateTime.Now.ToLongTimeString());
            displayText.AppendLine();
            int count = 0;

            foreach (SortableAutopilot ap in autopilots)
            {
                displayText.Append(tab);
                displayText.Append(ap.Autopilot.m_block.CubeGrid.DisplayName);
                displayText.Append(tab);
                displayText.Append(PrettySI.makePretty(ap.Distance));
                displayText.AppendLine("m");

                ap.Autopilot.AppendingCustomInfo(displayText);

                displayText.AppendLine();

                count++;
                if (count >= 5)
                {
                    break;
                }
            }

            autopilots.Clear();
            ResourcePool <List <SortableAutopilot> > .Return(autopilots);

            string displayString = displayText.ToString();

            //Log.DebugLog("Writing to panel: " + m_textPanel.DisplayNameText + ":\n\t" + displayString, "DisplyAutopilotStatus()", Logger.severity.TRACE);
            m_textPanel.WritePublicText(displayText.ToString());
        }
Exemple #4
0
        /// <summary>
        /// <para>For each LastSeen add to this storage or updates an existing LastSeen. LastSeen will be pushed to connected storages.</para>
        /// </summary>
        /// <param name="seen">Collection of LastSeen entitites.</param>
        public void Receive(ICollection <LastSeen> seen)
        {
            HashSet <RelayStorage> sendToSet = ResourcePool <HashSet <RelayStorage> > .Get();

            try
            {
                AddStorage(sendToSet, this);

                foreach (RelayStorage sto in sendToSet)
                {
                    using (sto.lock_lastSeen.AcquireExclusiveUsing())
                        foreach (LastSeen s in seen)
                        {
                            sto.in_Receive(s);
                        }
                    if (sto.m_nextClean_lastSeen <= Globals.UpdateCount)
                    {
                        Log.DebugLog("Running cleanup on last seen", Logger.severity.INFO);
                        sto.ForEachLastSeen(s => { });
                    }
                }
            }
            finally
            {
                sendToSet.Clear();
                ResourcePool <HashSet <RelayStorage> > .Return(sendToSet);
            }
        }
Exemple #5
0
        /// <summary>
        /// <para>Add a Message to this storage. Message will be pushed to connected storages.</para>
        /// <para>Not optimized for use within a loop.</para>
        /// </summary>
        /// <param name="msg">Message to receive.</param>
        public void Receive(Message msg)
        {
            HashSet <RelayStorage> sendToSet = ResourcePool <HashSet <RelayStorage> > .Get();

            try
            {
                AddStorage(sendToSet, this);

                foreach (RelayStorage sto in sendToSet)
                {
                    using (sto.lock_messages.AcquireExclusiveUsing())
                        sto.in_Receive(msg);
                    if (sto.m_nextClean_message <= Globals.UpdateCount)
                    {
                        Log.DebugLog("Running cleanup on message", Logger.severity.INFO);
                        sto.ForEachMessage(s => { });
                    }
                }
            }
            finally
            {
                sendToSet.Clear();
                ResourcePool <HashSet <RelayStorage> > .Return(sendToSet);
            }
        }
Exemple #6
0
        /// <summary>
        /// Send _outgoing immediately.
        /// </summary>
        private void SendOutgoing()
        {
            const int maxSize = 4088;

            List <byte> bytes; ResourcePool.Get(out bytes);

            AddIdAndValue(bytes);

            int initCount = bytes.Count;

            if (initCount > maxSize)
            {
                alwaysLog("Cannot send message, value is too large. byte count: " + initCount + ", value: " + _outgoing.Value);
                _outgoing = null;
                return;
            }

            for (int entityIdIndex = _outgoing.EntityId.Count - 1; entityIdIndex >= 0; --entityIdIndex)
            {
                ByteConverter.AppendBytes(bytes, _outgoing.EntityId[entityIdIndex]);
                if (bytes.Count > maxSize)
                {
                    traceLog("Over max size, splitting message");
                    SendOutgoing(bytes);
                    AddIdAndValue(bytes);
                }
            }

            SendOutgoing(bytes);
            _outgoing = null;
            bytes.Clear();
            ResourcePool.Return(bytes);
        }
        protected override FrameworkElement CreateMarkerCore(object dataItem)
        {
            if (template == null)
            {
                throw new InvalidOperationException(Strings.Exceptions.TemplateShouldNotBeNull);
            }

            FrameworkElement marker = pool.Get();

            if (marker == null)
            {
                marker = (FrameworkElement)template.LoadContent();
            }

            return(marker);
        }
Exemple #8
0
        private void OnOreSearchComplete(bool success, IMyVoxelBase foundVoxel, string oreName, IEnumerable <Vector3D> positions)
        {
            Log.DebugLog("success: " + success + ", foundVoxel: " + foundVoxel + ", oreName: " + oreName, Logger.severity.DEBUG);

            if (!success)
            {
                Log.DebugLog("No ore target found", Logger.severity.INFO);
                m_navSet.OnTaskComplete_NavRot();
                m_navSet.Settings_Commands.Complaint = InfoString.StringId.NoOreFound;
                return;
            }

            m_targetVoxel = foundVoxel;
            m_oreName     = oreName;

            if (m_approachFinders != null)
            {
                m_approachFinders.Clear();
            }
            else
            {
                ResourcePool.Get(out m_approachFinders);
            }

            Vector3D centre   = TargetVoxel.GetCentre();
            double   minSpace = 4d * m_grid.LocalVolume.Radius;

            foreach (Vector3D pos in positions)
            {
                Vector3D deposit = pos;

                if (deposit == centre)
                {
                    deposit += 1;
                }

                m_approachFinders.Add(new DepositFreeSpace(TargetVoxel, ref deposit, minSpace));

                if (m_approachFinders.Count == MaxDeposits)
                {
                    break;
                }
            }

            Log.DebugLog("Created " + m_approachFinders.Count + " finders for " + oreName);
            m_stage = Stage.GetApproach;
        }
Exemple #9
0
        private void ProcessPoolResources(ResourcePool <Course> pool)
        {
            Parallel.For(1, 100, (i, loopState) =>
            {
                var course = pool.Get();
                try
                {
                    Console.WriteLine($"Student Name: {course.GetStudentById(i)}");
                }
                finally
                {
                    pool.Return(course);
                }

                if (_cancellationTokenSource.Token.IsCancellationRequested)
                {
                    loopState.Stop();
                }
            });
        }
Exemple #10
0
        /// <summary>
        /// Send a LastSeen to one or more NetworkStorage. Faster than looping through the collection and invoking Receive() for each one.
        /// </summary>
        public static void Receive(ICollection <RelayStorage> storage, LastSeen seen)
        {
            HashSet <RelayStorage> sendToSet = ResourcePool <HashSet <RelayStorage> > .Get();

            try
            {
                foreach (RelayStorage sto in storage)
                {
                    AddStorage(sendToSet, sto);
                }

                foreach (RelayStorage sto in sendToSet)
                {
                    using (sto.lock_lastSeen.AcquireExclusiveUsing())
                        sto.in_Receive(seen);
                }
            }
            finally
            {
                sendToSet.Clear();
                ResourcePool <HashSet <RelayStorage> > .Return(sendToSet);
            }
        }
Exemple #11
0
        private static void RequestValues()
        {
            if (MyAPIGateway.Multiplayer.IsServer)
            {
                throw new Exception("Cannot request values, this is the server");
            }

            List <byte> bytes; ResourcePool.Get(out bytes);

            bytes.Clear();

            ByteConverter.AppendBytes(bytes, MessageHandler.SubMod.SyncRequest);
            ByteConverter.AppendBytes(bytes, MyAPIGateway.Multiplayer.MyId);

            Logger.DebugLog("requesting values from server");

            if (!MyAPIGateway.Multiplayer.SendMessageToServer(MessageHandler.ModId, bytes.ToArray()))
            {
                Logger.AlwaysLog("Failed to send message, length: " + bytes.Count, Logger.severity.ERROR);
            }

            bytes.Clear();
            ResourcePool.Return(bytes);
        }
Exemple #12
0
 public Manager(MathboxRenderer mathboxRenderer)
 {
     MathboxRenderer = mathboxRenderer;
     Pool            = new ResourcePool(mathboxRenderer);
     WIP             = Pool.Get();
 }
Exemple #13
0
        /// <summary>
        /// Check opts, load/unload
        /// </summary>
        public void Update100()
        {
            if (m_holoEntities.Count != 0 && DateTime.UtcNow >= m_clearAllAt)
            {
                Log.DebugLog("clearing all holo entities");
                foreach (SeenHolo sh in m_holoEntities.Values)
                {
                    Log.DebugLog("removing " + sh.Seen.Entity.EntityId + "from m_holoEntities (clear all)");
                    OnRemove(sh);
                }
                m_holoEntities.Clear();
            }

            if (!Enabled)
            {
                return;
            }

            Vector3D playerPos = MyAPIGateway.Session.Player.GetPosition(), holoCentre = m_offset.ToWorld(m_block);
            double   distSquared = Vector3D.DistanceSquared(playerPos, holoCentre);

            m_playerCanSee = distSquared <= 1e4d;
            if (m_playerCanSee && distSquared > 100d)
            {
                List <MyLineSegmentOverlapResult <MyEntity> > entitiesInRay = ResourcePool <List <MyLineSegmentOverlapResult <MyEntity> > > .Get();

                m_playerCanSee = false;
                MyEntity[] ignore = new MyEntity[] { (MyEntity)MyAPIGateway.Session.Player.Controller.ControlledEntity };
                foreach (Vector3 vector in Static.Directions)
                {
                    LineD ray = new LineD(playerPos, holoCentre + vector * m_radiusHolo);
                    MyGamePruningStructure.GetTopmostEntitiesOverlappingRay(ref ray, entitiesInRay);
                    if (!RayCast.Obstructed(ray, entitiesInRay.Select(overlap => overlap.Element), ignore))
                    {
                        m_playerCanSee = true;
                        entitiesInRay.Clear();
                        break;
                    }
                    entitiesInRay.Clear();
                }

                ResourcePool <List <MyLineSegmentOverlapResult <MyEntity> > > .Return(entitiesInRay);
            }

            if (!m_playerCanSee)
            {
                return;
            }

            RelayStorage storage = m_netClient.GetStorage();

            if (storage == null)
            {
                ((IMyTerminalBlock)m_block).AppendCustomInfo("No network connection");
                return;
            }

            m_clearAllAt = DateTime.UtcNow + Static.keepInCache;

            storage.ForEachLastSeen(CreateHolo);

            foreach (SeenHolo sh in m_holoEntities.Values)
            {
                if (CanDisplay(sh.Seen))
                {
                    if (!sh.Holo.Render.Visible)
                    {
                        Log.DebugLog("showing holo: " + sh.Seen.Entity.getBestName());
                        SetupProjection(sh.Holo);
                        SetVisible(sh.Holo, true);
                    }
                    if (sh.Seen.Entity is MyCubeGrid && sh.ColouredByIntegrity != ((m_options & Option.IntegrityColours) != 0))
                    {
                        if (sh.ColouredByIntegrity)
                        {
                            RestoreColour(sh);
                        }
                        else
                        {
                            ColourByIntegrity(sh);
                        }
                    }
                }
                else if (sh.Holo.Render.Visible)
                {
                    Log.DebugLog("hiding holo: " + sh.Seen.Entity.getBestName());
                    SetVisible(sh.Holo, false);
                }
            }

            if (m_holoEntitiesRemove.Count != 0)
            {
                foreach (long entityId in m_holoEntitiesRemove)
                {
                    Log.DebugLog("removing " + entityId + "from m_holoEntities");
                    SeenHolo sh;
                    if (!m_holoEntities.TryGetValue(entityId, out sh))
                    {
                        // this may be normal
                        Log.DebugLog("not in m_holoEntities: " + entityId, Logger.severity.WARNING);
                        continue;
                    }
                    OnRemove(sh);
                    m_holoEntities.Remove(entityId);
                }
                m_holoEntitiesRemove.Clear();
            }
        }
Exemple #14
0
 /// <summary>
 /// Commits the assembled display list for rendering and initializes a new batch for assembly
 /// </summary>
 /// <param name="erase">indicates whether the target buffer should be erased before redering this display list</param>
 public void CommitDisplayList(bool erase)
 {
     WIP.Commit(erase);
     RenderQueue.Enqueue(WIP);
     WIP = Pool.Get();
 }
Exemple #15
0
        private void Display(List <long> entityIds = null)
        {
            if (entityIds != null)
            {
                UpdateInstructions();
            }

            //Log.DebugLog("Building display list", "Display()", Logger.severity.TRACE);

            RelayStorage store = m_networkClient.GetStorage();

            if (store == null)
            {
                //m_textPanel.WritePublicText("No network connection");
                m_textSurface.WriteText("No network connection");
                return;
            }

            m_sortableList = ResourcePool <List <sortableLastSeen> > .Get();

            if (entityIds == null)
            {
                AllLastSeen(store);
            }
            else
            {
                SelectLastSeen(store, entityIds);
            }

            if (m_sortableList.Count == 0)
            {
                //m_textPanel.WritePublicText("No entities detected");
                m_textSurface.WriteText("No entities detected");
                m_sortableList.Clear();
                ResourcePool <List <sortableLastSeen> > .Return(m_sortableList);

                return;
            }

            m_lastDisplay = Globals.ElapsedTime;
            m_sortableList.Sort();

            StringBuilder displayText = new StringBuilder();

            displayText.Append(timeString);
            displayText.Append(DateTime.Now.ToLongTimeString());
            displayText.AppendLine();
            int count = 0;

            foreach (sortableLastSeen sortable in m_sortableList)
            {
                sortable.TextForPlayer(displayText, count++);
                if (count >= 20)
                {
                    break;
                }
            }

            m_sortableList.Clear();
            ResourcePool <List <sortableLastSeen> > .Return(m_sortableList);

            string displayString = displayText.ToString();

            //Log.DebugLog("Writing to panel: " + m_textPanel.DisplayNameText + ":\n\t" + displayString, "Display()", Logger.severity.TRACE);
            //m_textPanel.WritePublicText(displayText.ToString());
            m_textPanel.WriteText(displayText.ToString());
        }
Exemple #16
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);
        }
Exemple #17
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);
        }
 protected UIElement GetResourceFromPool()
 {
     return(pool.Get());
 }