Пример #1
0
        /// <summary>
        /// Performs a binary search for intersection using spheres.
        /// </summary>
        /// <param name="pointOfObstruction">a point on the capsule's line close to obstruction</param>
        public static bool Intersects(this Capsule capsule, IMyVoxelMap asteroid, out Vector3?pointOfObstruction, float capsuleLength = -1)
        {
            if (capsuleLength < 0)
            {
                capsuleLength = capsule.get_length();
            }
            float   halfLength = capsuleLength / 2;
            Vector3 middle     = capsule.get_Middle();

            BoundingSphereD containingSphere = new BoundingSphereD(middle, halfLength + capsule.Radius);

            if (!asteroid.GetIntersectionWithSphere(ref containingSphere))
            {
                pointOfObstruction = null;
                return(false);
            }

            if (capsuleLength < 1f)
            {
                pointOfObstruction = containingSphere.Center;
                return(true);
            }

            return(Intersects(new Capsule(capsule.P0, middle, capsule.Radius), asteroid, out pointOfObstruction, halfLength) ||
                   Intersects(new Capsule(capsule.P1, middle, capsule.Radius), asteroid, out pointOfObstruction, halfLength));
        }
Пример #2
0
        /// <summary>
        /// Tests for path intersection with voxel.
        /// </summary>
        /// <returns>True iff path is clear; voxel does not intersect path.</returns>
        private bool TestVoxel(MyVoxelBase voxel, Capsule path, out Vector3?pointOfObstruction)
        {
            if (m_ignoreAsteroid)
            {
                m_logger.debugLog("Ignoring asteroid: " + voxel.getBestName());
                pointOfObstruction = null;
                return(true);
            }

            Vector3[] intersection = new Vector3[2];
            if (!path.IntersectsAABB(voxel, out intersection[0]))
            {
                m_logger.debugLog("path does not intersect AABB. " + voxel.getBestName(), Logger.severity.TRACE);
                pointOfObstruction = null;
                return(true);
            }

            if (!path.get_Reverse().IntersectsAABB(voxel, out intersection[1]))
            {
                m_logger.debugLog("Reversed path does not intersect AABB, perhaps it moved? " + voxel.getBestName(), Logger.severity.WARNING);
                pointOfObstruction = null;
                return(true);
            }

            Capsule     testSection = new Capsule(intersection[0], intersection[1], path.Radius);
            IMyVoxelMap asteroid    = voxel as IMyVoxelMap;

            if (asteroid != null)
            {
                if (testSection.Intersects(asteroid, out pointOfObstruction))
                {
                    return(false);
                }
            }
            // planet test is done by PlanetChecker

            m_logger.debugLog("Does not intersect path: " + voxel.getBestName(), Logger.severity.TRACE);
            pointOfObstruction = null;
            return(true);
        }
Пример #3
0
        protected void RefreshCache( )
        {
            IMyVoxelMap voxelMap = (IMyVoxelMap)BackingObject;

            m_cache = new MyStorageDataCache( );
            Vector3I size = voxelMap.Storage.Size;

            m_cache.Resize(size);

            //			SandboxGameAssemblyWrapper.Instance.GameAction(() =>
            //			{
            voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, 0, Vector3I.Zero, size - 1);
            //voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, Vector3I.Zero, size - 1);
            //			});

            foreach (byte materialIndex in m_cache.Data)
            {
                try
                {
                    MyVoxelMaterialDefinition material = MyDefinitionManager.Static.GetVoxelMaterialDefinition(materialIndex);
                    if (material == null)
                    {
                        continue;
                    }

                    if (!m_materialTotals.ContainsKey(material))
                    {
                        m_materialTotals.Add(material, 1);
                    }
                    else
                    {
                        m_materialTotals[material]++;
                    }
                }
                catch (Exception ex)
                {
                    ApplicationLog.BaseLog.Error(ex);
                }
            }
        }
Пример #4
0
        /// <summary>
        /// Gets a point outside of an asteroid.
        /// </summary>
        /// <param name="startPoint">Where to start the search from, must be inside WorldAABB, can be inside or outside asteroid.</param>
        /// <param name="direction">Direction from outside asteroid towards inside asteroid</param>
        /// <param name="buffer">Minimum distance between the voxel and exterior point</param>
        private Vector3D GetExteriorPoint_Asteroid(Vector3D startPoint, Vector3 direction, float buffer)
        {
            IMyVoxelMap voxel = m_targetVoxel as IMyVoxelMap;

            if (voxel == null)
            {
                m_logger.alwaysLog("m_targetVoxel is not IMyVoxelMap: " + m_targetVoxel.getBestName(), Logger.severity.FATAL);
                throw new InvalidOperationException("m_targetVoxel is not IMyVoxelMap");
            }

            Vector3 v             = direction * m_targetVoxel.LocalAABB.GetLongestDim();
            Capsule surfaceFinder = new Capsule(startPoint - v, startPoint + v, buffer);
            Vector3?obstruction;

            if (surfaceFinder.Intersects(voxel, out obstruction))
            {
                return(obstruction.Value);
            }
            else
            {
                m_logger.debugLog("Failed to intersect asteroid, using surfaceFinder.P0", Logger.severity.WARNING);
                return(surfaceFinder.P0);
            }
        }
        private void ProcessAsteroid(string displayType, string displayName, IMyVoxelMap voxelMap, double distance, BoundingBoxD aabb)
        {
            Vector3I min = Vector3I.MaxValue;
            Vector3I max = Vector3I.MinValue;
            Vector3I block;
            Dictionary <byte, long> assetCount = new Dictionary <byte, long>();

            // read the asteroid in chunks of 64 to avoid the Arithmetic overflow issue.
            for (block.Z = 0; block.Z < voxelMap.Storage.Size.Z; block.Z += 64)
            {
                for (block.Y = 0; block.Y < voxelMap.Storage.Size.Y; block.Y += 64)
                {
                    for (block.X = 0; block.X < voxelMap.Storage.Size.X; block.X += 64)
                    {
                        var cacheSize = new Vector3I(64);
                        var oldCache  = new MyStorageData();
                        oldCache.Resize(cacheSize);
                        // LOD1 is not detailed enough for content information on asteroids.
                        voxelMap.Storage.ReadRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, 0, block, block + cacheSize - 1);

                        Vector3I p;
                        for (p.Z = 0; p.Z < cacheSize.Z; ++p.Z)
                        {
                            for (p.Y = 0; p.Y < cacheSize.Y; ++p.Y)
                            {
                                for (p.X = 0; p.X < cacheSize.X; ++p.X)
                                {
                                    var content = oldCache.Content(ref p);
                                    if (content > 0)
                                    {
                                        min = Vector3I.Min(min, p + block);
                                        max = Vector3I.Max(max, p + block + 1);

                                        var material = oldCache.Material(ref p);
                                        if (assetCount.ContainsKey(material))
                                        {
                                            assetCount[material] += content;
                                        }
                                        else
                                        {
                                            assetCount.Add(material, content);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            var assetNameCount = new Dictionary <string, long>();

            foreach (var kvp in assetCount)
            {
                var name = MyDefinitionManager.Static.GetVoxelMaterialDefinition(kvp.Key).Id.SubtypeName;
                if (assetNameCount.ContainsKey(name))
                {
                    assetNameCount[name] += kvp.Value;
                }
                else
                {
                    assetNameCount.Add(name, kvp.Value);
                }
            }
            assetNameCount = assetNameCount.OrderByDescending(e => e.Value).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

            var sum  = assetNameCount.Values.Sum();
            var ores = new StringBuilder();

            foreach (var kvp in assetNameCount)
            {
                ores.AppendFormat("{0}  {1:N}  {2:P}\r\n", kvp.Key, (double)kvp.Value / 255, (double)kvp.Value / (double)sum);
            }

            var contentBox  = new BoundingBoxD(voxelMap.PositionLeftBottomCorner + min, voxelMap.PositionLeftBottomCorner + max);
            var description = string.Format("Distance: {0:N}\r\nSize: {1}\r\nBoundingBox Center: [X:{2:N} Y:{3:N} Z:{4:N}]\r\n\r\nContent Size:{5}\r\nLOD0 Content Center: [X:{6:N} Y:{7:N} Z:{8:N}]\r\n\r\nMaterial  Mass  Percent\r\n{9}",
                                            distance, voxelMap.Storage.Size,
                                            aabb.Center.X, aabb.Center.Y, aabb.Center.Z,
                                            max - min,
                                            contentBox.Center.X, contentBox.Center.Y, contentBox.Center.Z,
                                            ores);

            MyAPIGateway.Utilities.ShowMissionScreen(string.Format("ID {0}:", displayType), string.Format("'{0}'", displayName), " ", description, null, "OK");
        }
Пример #6
0
        private static Dictionary <long, long> ProcessAsteroidOwnership()
        {
            Dictionary <long, long> result   = new Dictionary <long, long>();
            HashSet <IMyEntity>     entities = new HashSet <IMyEntity>();

            MyAPIGateway.Entities.GetEntities(entities);

            foreach (IMyEntity entity in entities)
            {
                if (!(entity is IMyVoxelMap))
                {
                    continue;
                }

                if (!entity.Save)
                {
                    continue;
                }
                IMyVoxelMap            voxel         = (IMyVoxelMap)entity;
                BoundingSphereD        sphere        = new BoundingSphereD(entity.GetPosition(), 500);   // Size of sphere around Roid
                List <IMyEntity>       blocks        = MyAPIGateway.Entities.GetEntitiesInSphere(ref sphere);
                Dictionary <long, int> asteroidScore = new Dictionary <long, int>();

                foreach (IMyEntity block in blocks)
                {
                    if (block is IMyCubeBlock)
                    {
                        IMyCubeBlock cube = (IMyCubeBlock)block;

                        if (!(cube.GetTopMostParent() is IMyCubeGrid))
                        {
                            continue;
                        }

                        IMyCubeGrid parent = (IMyCubeGrid)cube.GetTopMostParent();
                        if (!parent.IsStatic)
                        {
                            continue;
                        }
                        if (cube.OwnerId != 0 && TestBeacon(cube))                         // Test Valid Beacon.
                        {
                            if (!asteroidScore.ContainsKey(cube.OwnerId))
                            {
                                asteroidScore.Add(cube.OwnerId, 0);
                            }

                            asteroidScore[cube.OwnerId] = asteroidScore[cube.OwnerId] + 1;
                        }
                    }
                }

                long asteroidOwner = asteroidScore.OrderBy(x => x.Value).Where(x => x.Value > 0).Select(x => x.Key).FirstOrDefault();
                if (asteroidOwner != 0)
                {
                    MyObjectBuilder_Checkpoint.PlayerItem item = PlayerMap.Instance.GetPlayerItemFromPlayerId(asteroidOwner);
                    //Console.WriteLine(string.Format("Owner of asteroid at: {0} is {1}", General.Vector3DToString(entity.GetPosition()), item.Name));
                    result.Add(entity.EntityId, asteroidOwner);
                }
            }

            return(result);
        }
Пример #7
0
            public VoxelData(Ingame.IMyOreDetector oreDetector, IMyVoxelMap voxel, float maxRange)
            {
                this.m_logger = new Logger(GetType().Name, () => oreDetector.CubeGrid.DisplayName, () => oreDetector.DisplayNameText, () => voxel.ToString());
                this.m_oreDetector = oreDetector;
                this.m_voxel = voxel;
                this.m_storage.Resize(new Vector3I(QUERY_STEP, QUERY_STEP, QUERY_STEP));
                this.m_maxRange = maxRange;

                m_logger.debugLog("Created for voxel at " + voxel.PositionLeftBottomCorner, "VoxelData()");
            }
Пример #8
0
        /// <summary>
        /// Find the closest ore to position that matches one of the oreType
        /// </summary>
        /// <param name="position">The position to search near</param>
        /// <param name="oreType">The types of ore to search for</param>
        /// <param name="orePosition">The postion of the ore that was found</param>
        /// <param name="voxel">The voxel map that contains the ore that was found</param>
        /// <param name="oreName">The name of the ore that was found</param>
        /// <returns>True iff an ore was found</returns>
        public bool FindClosestOre(Vector3D position, byte[] oreType, out Vector3D orePosition, out IMyVoxelMap voxel, out string oreName)
        {
            IOrderedEnumerable<IMyVoxelMap> sortedByDistance;
            using (l_voxelDate.AcquireExclusiveUsing())
                sortedByDistance = m_voxelData.Keys.OrderBy(map => Vector3.DistanceSquared(position, map.GetPosition()));

            foreach (IMyVoxelMap map in sortedByDistance)
            {
                VoxelData data;
                using (l_voxelDate.AcquireSharedUsing())
                    data = m_voxelData[map];

                //Vector3I myVoxelCoord; MyVoxelCoordSystems.WorldPositionToVoxelCoord(map.PositionLeftBottomCorner, ref position, out myVoxelCoord);
                m_logger.debugLog("PositionLeftBottomCorner: " + map.PositionLeftBottomCorner + ", pos: " + position, "FindClosestOre()");
                //Vector3D closest;
                byte foundOreType;
                if (data.GetClosest(oreType, ref position, out orePosition, out foundOreType))
                {
                    oreName = MyDefinitionManager.Static.GetVoxelMaterialDefinition(foundOreType).MinedOre;
                    //MyVoxelCoordSystems.VoxelCoordToWorldPosition(map.PositionLeftBottomCorner, ref closest, out orePosition);
                    m_logger.debugLog("PositionLeftBottomCorner: " + map.PositionLeftBottomCorner + ", worldPosition: " + orePosition, "FindClosestOre()");
                    voxel = map;
                    return true;
                }
            }

            orePosition = Vector3D.Zero;
            voxel = null;
            oreName = null;
            return false;
        }
Пример #9
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);
        }
        private void ProcessAsteroid(string displayType, string displayName, IMyVoxelMap voxelMap, double distance, BoundingBoxD aabb)
        {
            Vector3I min = Vector3I.MaxValue;
            Vector3I max = Vector3I.MinValue;
            Vector3I block;
            Dictionary<byte, long> assetCount = new Dictionary<byte, long>();

            // read the asteroid in chunks of 64 to avoid the Arithmetic overflow issue.
            for (block.Z = 0; block.Z < voxelMap.Storage.Size.Z; block.Z += 64)
                for (block.Y = 0; block.Y < voxelMap.Storage.Size.Y; block.Y += 64)
                    for (block.X = 0; block.X < voxelMap.Storage.Size.X; block.X += 64)
                    {
                        var cacheSize = new Vector3I(64);
                        var oldCache = new MyStorageDataCache();
                        oldCache.Resize(cacheSize);
                        // LOD1 is not detailed enough for content information on asteroids.
                        voxelMap.Storage.ReadRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, 0, block, block + cacheSize - 1);

                        Vector3I p;
                        for (p.Z = 0; p.Z < cacheSize.Z; ++p.Z)
                            for (p.Y = 0; p.Y < cacheSize.Y; ++p.Y)
                                for (p.X = 0; p.X < cacheSize.X; ++p.X)
                                {
                                    var content = oldCache.Content(ref p);
                                    if (content > 0)
                                    {
                                        min = Vector3I.Min(min, p + block);
                                        max = Vector3I.Max(max, p + block + 1);

                                        var material = oldCache.Material(ref p);
                                        if (assetCount.ContainsKey(material))
                                            assetCount[material] += content;
                                        else
                                            assetCount.Add(material, content);
                                    }
                                }
                    }

            var assetNameCount = new Dictionary<string, long>();

            foreach (var kvp in assetCount)
            {
                var name = MyDefinitionManager.Static.GetVoxelMaterialDefinition(kvp.Key).Id.SubtypeName;

                if (assetNameCount.ContainsKey(name))
                {
                    assetNameCount[name] += kvp.Value;
                }
                else
                {
                    assetNameCount.Add(name, kvp.Value);
                }
            }

            var sum = assetNameCount.Values.Sum();

            var ores = new StringBuilder();
            foreach (var kvp in assetNameCount)
                ores.AppendFormat("{0}  {1:N}  {2:P}\r\n", kvp.Key, (double)kvp.Value / 255, (double)kvp.Value / (double)sum);

            var contentBox = new BoundingBoxD(voxelMap.PositionLeftBottomCorner + min, voxelMap.PositionLeftBottomCorner + max);
            var description = string.Format("Distance: {0:N}\r\nSize: {1}\r\nBoundingBox Center: [X:{2:N} Y:{3:N} Z:{4:N}]\r\n\r\nContent Size:{5}\r\nLOD0 Content Center: [X:{6:N} Y:{7:N} Z:{8:N}]\r\n\r\nMaterial  Mass  Percent\r\n{9}",
                distance, voxelMap.Storage.Size,
                aabb.Center.X, aabb.Center.Y, aabb.Center.Z,
                max - min,
                contentBox.Center.X, contentBox.Center.Y, contentBox.Center.Z,
                ores);

            MyAPIGateway.Utilities.ShowMissionScreen(string.Format("ID {0}:", displayType), string.Format("'{0}'", displayName), " ", description, null, "OK");
        }
Пример #11
0
		/// <summary>
		/// Performs a binary search for intersection using spheres.
		/// </summary>
		/// <param name="pointOfObstruction">a point on the capsule's line close to obstruction</param>
		public static bool Intersects(this Capsule capsule, IMyVoxelMap asteroid, out Vector3? pointOfObstruction, float capsuleLength = -1)
		{
			if (capsuleLength < 0)
				capsuleLength = capsule.get_length();
			float halfLength = capsuleLength / 2;
			Vector3 middle = capsule.get_Middle();

			BoundingSphereD containingSphere = new BoundingSphereD(middle, halfLength + capsule.Radius);
			if (!asteroid.GetIntersectionWithSphere(ref containingSphere))
			{
				pointOfObstruction = null;
				return false;
			}

			if (capsuleLength < 1f)
			{
				pointOfObstruction = containingSphere.Center;
				return true;
			}

			return Intersects(new Capsule(capsule.P0, middle, capsule.Radius), asteroid, out pointOfObstruction, halfLength)
				|| Intersects(new Capsule(capsule.P1, middle, capsule.Radius), asteroid, out pointOfObstruction, halfLength);
		}
Пример #12
0
        public static void CheckAndSendVoxels( )
        {
            if (m_voxelCheck)
            {
                return;
            }

            m_voxelCheck = true;

            try
            {
                DateTime            start    = DateTime.Now;
                HashSet <IMyEntity> entities = new HashSet <IMyEntity>( );
                List <IMyPlayer>    players  = new List <IMyPlayer>( );
                try
                {
                    MyAPIGateway.Entities.GetEntities(entities);
                    MyAPIGateway.Players.GetPlayers(players);
                }
                catch
                {
                    Essentials.Log.Info("Entity list busy, skipping check");
                    return;
                }

                HashSet <Tuple <ulong, IMyEntity> > voxelsToSend = new HashSet <Tuple <ulong, IMyEntity> >( );
                foreach (IMyEntity entity in entities)
                {
                    if (!(entity is IMyVoxelMap))
                    {
                        continue;
                    }

                    IMyVoxelMap voxel = (IMyVoxelMap)entity;

                    foreach (IMyPlayer player in players)
                    {
                        double distance = 0d;
                        if (Entity.GetDistanceBetweenPointAndPlayer(entity.GetPosition( ), player, out distance))
                        {
                            if (!m_userVoxels.ContainsKey(player.SteamUserId))
                            {
                                m_userVoxels.Add(player.SteamUserId, new HashSet <long>( ));
                            }

                            HashSet <long> voxels = m_userVoxels[player.SteamUserId];

                            if (distance < PluginSettings.Instance.DynamicVoxelDistance && !voxels.Contains(entity.EntityId))
                            {
                                voxelsToSend.Add(new Tuple <ulong, IMyEntity>(player.SteamUserId, entity));
                            }
                        }
                    }
                }

                if (voxelsToSend.Count > 0)
                {
                    Wrapper.GameAction(() =>
                    {
                        foreach (Tuple <ulong, IMyEntity> p in voxelsToSend)
                        {
                            SendVoxel(p.Item1, p.Item2);
                        }
                    });
                }

                if ((DateTime.Now - start).TotalSeconds > 1)
                {
                    Essentials.Log.Debug("CheckAndSendVoxels(): {0}ms", (DateTime.Now - start).TotalMilliseconds);
                }
            }
            catch (Exception ex)
            {
                Essentials.Log.Error(ex, "Check and send voxels");
            }
            finally
            {
                m_voxelCheck = false;
            }
        }
Пример #13
0
        private static void SendVoxelData(ulong steamId, IMyEntity voxel)
        {
            try
            {
                IMyVoxelMap voxelMap = (IMyVoxelMap)voxel;

                byte[] voxelData;
                voxelMap.Storage.Save(out voxelData);

                VoxelHeaderData header = new VoxelHeaderData( );
                header.EntityId   = voxel.EntityId;
                header.HalfExtent = voxelMap.Storage.Size / 2;
                header.Position   = voxel.GetPosition( );
                header.Name       = voxelMap.StorageName;
                header.DataLength = voxelData.Length;

                string headerString = MyAPIGateway.Utilities.SerializeToXML <VoxelHeaderData>(header);
                ushort length       = (ushort)headerString.Length;

                byte[] headerData = new byte[2 + headerString.Length];

                headerData[0] = (byte)length;
                headerData[1] = (byte)(length >> 8);

                for (int r = 0; r < headerString.Length; r++)
                {
                    headerData[r + 2] = (byte)headerString[r];
                }
                Essentials.Log.Debug("Sending Voxel Header Data: {0} / {1} - {2} ({3})", voxelData.Length, headerData.Length, steamId, voxel.GetPosition( ));
                Communication.SendDataMessage(steamId, Communication.DataMessageType.VoxelHeader, headerData);

                int blockSize = 4096;
                for (ushort r = 0; r < (voxelData.Length / blockSize) + 1; r++)
                {
                    int partLength = voxelData.Length - (r * blockSize);

                    if (partLength > blockSize)
                    {
                        partLength = blockSize;
                    }

                    byte[] outData = new byte[partLength + 12];

                    for (int s = 0; s < 8; s++)
                    {
                        outData[s] = (byte)(header.EntityId >> (s * 8));
                    }

                    for (int s = 0; s < 2; s++)
                    {
                        outData[s + 8] = (byte)(partLength >> (s * 8));
                    }

                    for (int s = 0; s < 2; s++)
                    {
                        outData[s + 10] = (byte)(r >> (s * 8));
                    }

                    Buffer.BlockCopy(voxelData, r * blockSize, outData, 12, partLength);
                    Communication.SendDataMessage(steamId, Communication.DataMessageType.VoxelPart, outData);
                }
            }
            catch (Exception ex)
            {
                Essentials.Log.Error(ex, "Send voxel data");
            }
        }
        public override void UpdateAfterSimulation10()
        {
            try
            {
                var antenna     = (Sandbox.ModAPI.Ingame.IMyTerminalBlock)Entity;
                var entityBlock = (IMyCubeBlock)Entity;

                // called multiple times for ships, to be kept up to date.
                if (antenna.CustomName != null && antenna.CustomName.StartsWith(CustomNameKeyPos, StringComparison.InvariantCultureIgnoreCase))
                {
                    var pos = antenna.CubeGrid.GridIntegerToWorld(antenna.Position);
                    //dont really care about the decimal places so cast as int.
                    antenna.SetCustomName(string.Format("{0} [X:{1:N0}  Y:{2:N0}  Z:{3:N0}]", CustomNameKeyPos, (int)(pos.X), (int)(pos.Y), (int)(pos.Z)));
                }
                else if (antenna.CustomName != null && antenna.CustomName.StartsWith(CustomNameKeyDir, StringComparison.InvariantCultureIgnoreCase))
                {
                    var orientation = antenna.WorldMatrix.Up;
                    //care about the decimal places as being off a few degrees can be very significant. vector3.tostring is already localized.
                    antenna.SetCustomName(string.Format("{0} [X:{1:N5}  Y:{2:N5} Z:{3:N5}]", CustomNameKeyDir, orientation.X, orientation.Y, orientation.Z));
                }
                else if (antenna.CustomName != null && antenna.CustomName.StartsWith(CustomNameKeyProbe, StringComparison.InvariantCultureIgnoreCase))
                {
                    antenna.SetCustomName(CustomNameKeyProbe);
                    var pos = antenna.CubeGrid.GridIntegerToWorld(antenna.Position);

                    Vector3     closestpos  = Vector3.Zero;
                    float       closestdist = float.MaxValue;
                    int         i           = 0;
                    IMyVoxelMap map         = null;
                    for (i = 0; (map = MyAPIGateway.Session.VoxelMaps.GetVoxelMap(i)) != null; i++)
                    {
                        var mappos = map.PositionLeftBottomCorner + map.SizeInMetresHalf;
                        if (Vector3.Distance(mappos, pos) < closestdist)
                        {
                            closestpos  = mappos;
                            closestdist = Vector3.Distance(mappos, pos);
                        }
                    }
                    if (closestpos != Vector3.Zero)
                    {
                        var direction = closestpos - pos;
                        direction = Vector3.Normalize(direction);

                        var obj = (MyObjectBuilder_RadioAntenna)entityBlock.GetObjectBuilderCubeBlock();
                        if (closestdist < 1000 && obj.BroadcastRadius > closestdist)
                        {
                            antenna.SetCustomName(string.Format("{0} Asteroid too close. Distance: {1:N}", CustomNameKeyProbe, closestdist));
                        }
                        else if (obj.BroadcastRadius > closestdist)
                        {
                            antenna.SetCustomName(string.Format("{0} [X:{1:N5}  Y:{2:N5} Z:{3:N5}]", CustomNameKeyProbe, direction.X, direction.Y, direction.Z));
                        }
                        else
                        {
                            antenna.SetCustomName(string.Format("{0} {1} Broadcast Range: {2:N}", CustomNameKeyProbe, "No asteroids in range. ", obj.BroadcastRadius));
                        }
                    }
                    else
                    {
                        antenna.SetCustomName(string.Format("{0} {1}", CustomNameKeyProbe, "No asteroids detected."));
                    }
                }
            }
            catch (Exception)
            {
                var antenna = (Sandbox.ModAPI.Ingame.IMyTerminalBlock)Entity;
                antenna.SetCustomName(string.Format("{0} Error.", CustomNameKeyProbe));
            }
        }
Пример #15
0
        public void Update()
        {
            if (_targetHit)
            {
                Kill();
                return;
            }

            // Update velocity due to gravity
            Vector3D totalGravity      = MyParticlesManager.CalculateGravityInPoint(_position); // Does this get affected by artificial grav? If so... cooooool
            Vector3D naturalGravity    = RailgunCore.GetNaturalGravityAtPoint(_position);
            Vector3D artificialGravity = totalGravity - naturalGravity;

            _velocity += (naturalGravity * RailgunCore.MyConfig.NaturalGravityMultiplier + artificialGravity * RailgunCore.MyConfig.ArtificialGravityMultiplier) * _tick;

            // Update direction if velocity has changed
            if (!_velocity.Equals(_lastVelocity, 1e-3))
            {
                _direction = Vector3D.Normalize(_velocity);
            }

            _lastVelocity = _velocity;

            // Update position
            _position += _velocity * _tick;
            var _toOrigin = _position - _origin;

            //draw tracer line
            if (_drawTrail && _currentTracerFadeTicks < _maxTracerFadeTicks)
            {
                _lineColor *= _trailColorDecayRatio;
                _currentTracerFadeTicks++;
            }

            if (_toOrigin.LengthSquared() > _maxTrajectory * _maxTrajectory)
            {
                MyLog.Default.WriteLine(">> Max range hit");

                _targetHit   = true;
                _hitPosition = _position;
                Kill();
                if (_shouldExplode)
                {
                    CreateExplosion(_position, _direction, _explosionRadius, _explosionDamage);
                }
                return;
            }

            _checkIntersectionIndex = ++_checkIntersectionIndex % 5;
            if (_checkIntersectionIndex != 0 && _positionChecked)
            {
                return;
            }

            // Add current position to trajectory list
            _trajectoryPoints.Add(_position);

            var to   = _position; //_position + 5.0 * _velocity * _tick;
            var from = _lastPositionChecked;

            _positionChecked     = true;
            _lastPositionChecked = _position;

            IHitInfo hitInfo;
            bool     hit = false;

            if (Vector3D.DistanceSquared(to, from) > 50 * 50)
            {
                // Use faster raycast if ray is long enough
                hit = MyAPIGateway.Physics.CastLongRay(from, to, out hitInfo, true);
            }
            else
            {
                hit = MyAPIGateway.Physics.CastRay(from, to, out hitInfo, 0);
            }

            if (hit)
            {
                MyLog.Default.WriteLine(">> Raycast hit");
                _hitPosition = hitInfo.Position + -0.5 * _direction;
                if ((_hitPosition - _origin).LengthSquared() > _minimumArmDistance * _minimumArmDistance) //only explode if beyond arm distance
                {
                    if (_shouldExplode)
                    {
                        CreateExplosion(_hitPosition, _direction, _explosionRadius, _explosionDamage);
                    }

                    if (_shouldPenetrate)
                    {
                        GetObjectsToPenetrate(_hitPosition, _hitPosition + _direction * _penetrationRange);
                    }

                    _targetHit = true;
                    Kill();
                }
                else
                {
                    _targetHit   = true;
                    _hitPosition = _position;
                    Kill();
                }
                return;
            }

            // implied else
            var line = new LineD(from, to);

            MyGamePruningStructure.GetVoxelMapsOverlappingRay(ref line, _voxelOverlap);
            foreach (var result in _voxelOverlap)
            {
                MatrixD matrix;
                MatrixD matrixInv;
                Vector3 sizeInMetersHalf;

                MyPlanet    planet   = result.Element as MyPlanet;
                IMyVoxelMap voxelMap = result.Element as IMyVoxelMap;
                if (planet == null && voxelMap == null)
                {
                    continue;
                }

                if (planet != null)
                {
                    matrix           = planet.WorldMatrix;
                    matrixInv        = planet.PositionComp.WorldMatrixInvScaled;
                    sizeInMetersHalf = planet.SizeInMetresHalf;
                }
                else
                {
                    matrix           = voxelMap.WorldMatrix;
                    matrixInv        = voxelMap.PositionComp.WorldMatrixInvScaled;
                    sizeInMetersHalf = new Vector3(voxelMap.Storage.Size) * 0.5f;
                }

                Vector3 localTo;
                Vector3 localFrom;
                MyVoxelCoordSystems.WorldPositionToLocalPosition(from, matrix, matrixInv, sizeInMetersHalf, out localFrom);
                MyVoxelCoordSystems.WorldPositionToLocalPosition(to, matrix, matrixInv, sizeInMetersHalf, out localTo);
                var localLine = new LineD(localFrom, localTo);

                if (planet != null && ((IMyStorage)(planet.Storage)).Intersect(ref localLine))
                {
                    MyLog.Default.WriteLine(">> Railgun projectile hit planet");
                    _hitPosition = _position;
                    _targetHit   = true;
                    Kill();
                    return;
                }

                // This is very broken
                //if (voxelMap != null && ((IMyStorage)(voxelMap.Storage)).Intersect(ref localLine))
                //{
                //    MyLog.Default.WriteLine(">> Railgun projectile hit voxel");
                //    _hitPosition = _position;
                //    _targetHit = true;
                //    Kill();
                //    return;
                //}
            }
        }
Пример #16
0
        /// <summary>
        /// Test if it is safe for the grid to rotate.
        /// </summary>
        /// <param name="axis">Normalized axis of rotation in world space.</param>
        /// <param name="ignoreAsteroids"></param>
        /// <returns>True iff the path is clear.</returns>
        public bool TestRotate(Vector3 axis, bool ignoreAsteroids, out IMyEntity obstruction)
        {
            Vector3 centreOfMass = m_grid.Physics.CenterOfMassWorld;
            float   longestDim   = m_grid.GetLongestDim();

            // calculate height
            Matrix  toMyLocal     = m_grid.WorldMatrixNormalizedInv;
            Vector3 myLocalCoM    = Vector3.Transform(centreOfMass, toMyLocal);
            Vector3 myLocalAxis   = Vector3.Transform(axis, toMyLocal.GetOrientation());
            Vector3 myLocalCentre = m_grid.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    = m_grid.LocalAABB.Intersects(upper);

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

            if (!lowerBound.HasValue)
            {
                m_logger.alwaysLog("Math fail, lowerBound does not have a value", Logger.severity.FATAL);
            }
            m_logger.debugLog("LocalAABB: " + m_grid.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;

            m_cells.ForEach(cell => {
                Vector3 rejection     = Vector3.Reject(cell * m_grid.GridSize, myLocalAxis);
                float cellDistSquared = Vector3.DistanceSquared(myLocalCoM, rejection);
                if (cellDistSquared > furthest)
                {
                    furthest = cellDistSquared;
                }
            });
            float length = (float)Math.Sqrt(furthest) + m_grid.GridSize * 0.5f;

            m_logger.debugLog("height: " + height + ", length: " + length);

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

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

            LineSegment axisSegment = new LineSegment();

            ClosestPlanet = MyPlanetExtensions.GetClosestPlanet(centreOfMass);
            MyAPIGateway.Utilities.TryInvokeOnGameThread(TestPlanet);

            foreach (MyEntity entity in m_obstructions)
            {
                if (PathChecker.collect_Entity(m_grid, entity))
                {
                    if (entity is IMyVoxelBase)
                    {
                        if (ignoreAsteroids)
                        {
                            continue;
                        }

                        IMyVoxelMap voxel = entity as IMyVoxelMap;
                        if (voxel != null)
                        {
                            if (voxel.GetIntersectionWithSphere(ref surroundingSphere))
                            {
                                m_logger.debugLog("Too close to " + voxel.getBestName() + ", CoM: " + centreOfMass.ToGpsTag("Centre of Mass") + ", required distance: " + surroundingSphere.Radius);
                                obstruction = voxel;
                                return(false);
                            }
                            continue;
                        }

                        if (PlanetState != Pathfinder.PathState.No_Obstruction)
                        {
                            m_logger.debugLog("planet blocking");
                            obstruction = 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;

                        bool found = false;
                        GridCellCache.GetCellCache(grid).ForEach(cell => {
                            if (axisSegment.PointInCylinder(length, cell * grid.GridSize))
                            {
                                found = true;
                                return(true);
                            }
                            return(false);
                        });

                        if (found)
                        {
                            obstruction = grid;
                            return(false);
                        }
                        continue;
                    }

                    m_logger.debugLog("No tests for object: " + entity.getBestName(), Logger.severity.INFO);
                    obstruction = entity;
                    return(false);
                }
            }

            obstruction = null;
            return(true);
        }