/// <summary>
        ///
        /// SERVER ONLY FUNCTION
        ///
        /// Server will periodically determine which contacts are near a grid
        /// with radar and send them out in a message.  This is a workaround
        /// for the fact that not all entities within radar range may be
        /// streamed to the client.
        /// </summary>
        private void DoAcquisitionSweep()
        {
            //_logger.debugLog("Running acquisition sweep", "DoAcquisitionSweep");

            Vector3D pos = _grid.WorldAABB.Center;

            VRageMath.BoundingSphereD sphere
                = new VRageMath.BoundingSphereD(pos, _settings.range);
            List <IMyEntity> ents
                = MyAPIGateway.Entities.GetEntitiesInSphere(ref sphere);

            List <RemoteContact> contacts = new List <RemoteContact>();

            foreach (IMyEntity e in ents)
            {
                if (e == _grid)
                {
                    continue;
                }

                if (e is IMyCubeGrid)
                {
                    Vector3D vecTo = e.WorldAABB.Center - pos;

                    contacts.Add(new RemoteContact()
                    {
                        entId = e.EntityId,
                        pos   = e.WorldAABB.Center,
                        xsec  = EWMath.DetermineXSection(e as IMyCubeGrid, vecTo)
                    });
                }
            }

            // Send the contact list, even if it is blank.  This is how the
            // client will know when distant contacts have gone out of range
            // or disappeared.
            //_logger.debugLog($"List<RemoteContact> -> Clients with {contacts.Count} entities", "DoAcquisitionSweep");
            Message <BlockAddress, List <RemoteContact> > msg
                = new Message <BlockAddress, List <RemoteContact> >(
                      new BlockAddress(this.GridID, this.BlockID),
                      contacts);

            MyAPIGateway.Multiplayer.SendMessageToOthers(
                Constants.MIDAcquisitionSweep,
                msg.ToXML());
        }
        /// <summary>
        /// Goes through all tracks in the list and determines whether or not
        /// they can currently be seen.  This function does not add or remove
        /// contacts from the list.  That can only be done in ProcessAcquiredContacts.
        /// </summary>
        private void DoTrackingSweep()
        {
            //_logger.debugLog("Beginning sweep", "DoTrackingSweep");

            Vector3D myPos = _grid.WorldAABB.Center;

            // Go through all current tracks and update their makers
            foreach (Track track in _allTracks.Values)
            {
                //_logger.debugLog($"For Track {track.trackId}", "DoTrackingSweep");

                // If the entity is null, this track is only available on the
                // server so use the stored value.  Otherwise get the most
                // up to date value
                if (track.ent != null)
                {
                    //_logger.debugLog("Entity is not null", "DoTrackingSweep");
                    track.position = track.ent.WorldAABB.Center;
                }

                // Transform the coordinates into grid space so we
                // can compare it against our radar coverage
                VRageMath.Vector3D relative
                    = VRageMath.Vector3D.Transform(
                          track.position, _grid.WorldMatrixNormalizedInv);

                //Check that the sector is covered by our radars
                Sector sec = SectorExtensions.ClassifyVector(relative);
                if (IsSectorBlind(sec))
                {
                    //_logger.debugLog("Sector is blind", "DoTrackingSweep");
                    // If a contact is not trackable, clear its GPS marker
                    ClearTrackMarker(track);
                    continue;
                }

                // Vector to target
                Vector3D vecTo = track.position - myPos;

                // If the entity is available, calculate the cross-section
                // Otherwise we will use the stored value from the server
                if (track.ent != null)
                {
                    track.xsec
                        = EWMath.DetermineXSection(track.ent as IMyCubeGrid, vecTo);
                }

                double range = vecTo.Length();
                double minxsec
                    = EWMath.MinimumXSection(
                          Constants.radarBeamWidths[(int)_assignedType], range);
                if (track.xsec < minxsec)
                {
                    //_logger.debugLog("Cross-section not large enough", "DoTrackingSweep");
                    ClearTrackMarker(track);
                    continue;
                }

                // TODO: raycast

                // If all of the previous checks passed, this contact should
                // be visible with a marker
                AddUpdateTrackMarker(track);
            }
        }